Exemplo n.º 1
0
        public async Task <Result <IGameResult, ErrorCode> > Spin(RequestContext <SpinArgs> requestContext)
        {
            using (logger.BeginScope(new Dictionary <string, object>
            {
                ["SessionKey"] = requestContext.UserSession.SessionKey,
                ["UserId"] = requestContext.UserSession.UserId,
                ["GameKey"] = requestContext.GameKey,
                ["Platform"] = requestContext.Platform,
                ["BettingLines"] = requestContext.Parameters.BettingLines,
                ["LineBet"] = requestContext.Parameters.LineBet,
                ["Multiplier"] = requestContext.Parameters.Multiplier
            }))
            {
                var        module      = gameModules.GetModule(requestContext.GameKey);
                var        userSession = requestContext.UserSession;
                SpinResult result      = null;
                var        level       = await userService.GetLevel(requestContext.UserGameKey);

                try
                {
                    var transaction = await transactionService.GenerateGameTransactionId(requestContext.UserGameKey, GameTransactionType.Spin);

                    requestContext.GameTransaction = transaction;

                    var roundId = await transactionService.GenerateAutoNumber(CounterType.RoundId);

                    requestContext.CurrentRound = roundId;

                    var lastSpinData = await userService.GetLastSpinData(userSession, requestContext.Game);

                    var totalBet = module.CalculateTotalBet(lastSpinData, requestContext);

                    logger.LogInformation("User spin on level {Level}, trx id {GameTransactionId}, round {CurrentRoundId}, total bet {TotalBet}", level, transaction.Id, roundId, totalBet);

                    var deductBet = await payoutService.DeductBetFromWallet(requestContext, totalBet);

                    // TODO we should check the wallet result if it's success

                    var spinResult = module.ExecuteSpin(level, lastSpinData, requestContext);
                    if (spinResult.IsError)
                    {
                        return(spinResult.Error);
                    }

                    result               = spinResult.Value;
                    result.Bet           = totalBet;
                    result.RoundId       = roundId;
                    result.TransactionId = transaction.Id;
                    result.UniqueID      = result.TransactionId.ToString();
                    result.DateTimeUtc   = transaction.DateTimeUtc;
                    result.ExchangeRate  = deductBet.ExchangeRate;
                    result.Balance       = Balance.Create(deductBet.Balance);

                    if (result.HasBonus)
                    {
                        logger.LogInformation("User got bonus");
                        var bonusCreated = module.CreateBonus(result);
                        if (bonusCreated.IsError)
                        {
                            logger.LogWarning("Create bonus got error {Error} with {SpinResult}", bonusCreated.Error, JsonHelper.FullString(result));
                            return(ErrorCode.InternalError);
                        }

                        var bonus = bonusCreated.Value;
                        bonus.SpinTransactionId = transaction.Id;
                        bonus.GameResult        = result;
                        var entity = new BonusEntity
                        {
                            UserId       = userSession.UserId,
                            GameId       = requestContext.Game.Id,
                            Guid         = bonus.Guid.ToString("N"),
                            Data         = bonus.ToByteArray(),
                            BonusType    = bonus.GetType().Name,
                            Version      = 3,
                            IsOptional   = bonus.IsOptional,
                            IsStarted    = bonus.IsStarted,
                            RoundId      = roundId,
                            BetReference = deductBet.BetReference
                        };
                        await bonusService.UpdateBonus(userSession, entity);

                        await userService.UpdateGameState(requestContext, UserGameState.ForBonus(roundId));
                    }
                    else
                    {
                        await userService.UpdateGameState(requestContext, UserGameState.ForNormal(roundId));
                    }

                    var paied = await payoutService.PayoutToUser(requestContext, result, new BonusExtraInfo { RoundId = roundId, BetId = deductBet.BetReference }, !result.HasBonus, deductBet.Guid);

                    result.ExchangeRate = deductBet.ExchangeRate;
                    result.Balance      = Balance.Create(paied.Balance);

                    await transactionService.ProfileSpinBet(requestContext);

                    await userService.UpdateLastSpinData(userSession, requestContext.Game, result);

                    if (!userSession.IsFunPlay)
                    {
                        await userService.UpdateUserGameData(new UserGameData
                        {
                            UserId = userSession.UserId,
                            GameId = requestContext.Game.Id,
                            Bet    = requestContext.Parameters.LineBet,
                            Lines  = requestContext.Game.Lines,
                        });
                    }
                }
                catch (InsufficientBalanceException ex)
                {
                    logger.LogInformation(ex, ex.Message);
                    return(ErrorCode.InsufficientCredit);
                }
                catch (Exception ex)
                {
                    logger.LogError(ex, ex.Message);
                    throw;
                }
                finally
                {
                    await TrySaveGameHistory(requestContext, result);
                }
                return(result);
            }
        }