public void TestFaFaZhu(int gameId, int level, string currencyCode, int numusers, int numItrPerUser, decimal bet, int lines, int mp)
        {
            var sdt = DateTime.Now;

            var serviceProvider = new ServiceCollection()
                                  .AddLogging()
                                  .BuildServiceProvider();
            var logFactory = serviceProvider.GetService <ILoggerFactory>();
            var logger     = logFactory.CreateLogger <FaFaZhuModule>();

            var FaFaZhuModule = new FaFaZhuModule(logger);
            var maxWin        = 0m;

            var summData = new SummaryData();
            var users    = GenerateUsers(gameId, numusers, level);
            var sbs      = GenerateUserBets(users, bet, lines, mp);

            RequestContext <SpinArgs> requestContext = new RequestContext <SpinArgs>("", FaFaZhuConfiguration.GameName, PlatformType.Web);

            RequestContext <BonusArgs> requestBonusContext = new RequestContext <BonusArgs>("", FaFaZhuConfiguration.GameName, PlatformType.Web);

            Parallel.ForEach(users,
                             () => new SummaryData(),
                             (key, state, sdata) =>
            {
                var sb = sbs[key.UserId];
                requestContext.Currency = new Currency()
                {
                    Id = sb.CurrencyId
                };
                requestContext.Parameters = new SpinArgs()
                {
                    LineBet = sb.LineBet, BettingLines = sb.Lines, Multiplier = mp
                };
                requestContext.GameSetting = new GameSetting()
                {
                    GameSettingGroupId = sb.GameSettingGroupId
                };

                for (var i = 0; i < numItrPerUser; ++i)
                {
                    var sr = FaFaZhuModule.ExecuteSpin(level, new UserGameSpinData(), requestContext).Value as FaFaZhuSpinResult;

                    if (sr.Win > maxWin)
                    {
                        maxWin = sr.Win;
                    }

                    UpdateSummaryData(sdata, sr);
                    UpdateFaFaZhuSummaryData(sdata, sr);
                }

                return(sdata);
            },
                             sdata =>
            {
                lock (summData)
                {
                    summData.Sum(sdata);
                }
            });

            DisplayFaFaZhuSummaryData(level, bet, lines, summData, sdt, maxWin, null);
        }
        public void TestFaFaZhuFullCycle(int level, List <int> rows)
        {
            var sdt             = DateTime.Now;
            var serviceProvider = new ServiceCollection()
                                  .AddLogging()
                                  .BuildServiceProvider();
            var logFactory = serviceProvider.GetService <ILoggerFactory>();
            var logger     = logFactory.CreateLogger <FaFaZhuModule>();

            var FaFaZhuModule = new FaFaZhuModule(logger);
            var maxWin        = 0m;
            Dictionary <decimal, int> profile = new Dictionary <decimal, int>();
            List <int> maxIndexPosition       = new List <int>();
            var        summData     = new SummaryData();
            var        reel1Pointer = 0;
            var        reel2Pointer = 0;
            var        reel3Pointer = 0;

            for (var reel0 = 0; reel0 < FaFaZhuConfiguration.VirtualReels[level][0]; reel0++)
            {
                for (var reel1 = 0; reel1 < FaFaZhuConfiguration.VirtualReels[level][1]; reel1++)
                {
                    for (var reel2 = 0; reel2 < FaFaZhuConfiguration.VirtualReels[level][2]; reel2++)
                    {
                        var totalWin = (decimal)0;

                        UserGameKey ugk = new UserGameKey()
                        {
                            UserId = -1,
                            GameId = FaFaZhuConfiguration.GameId,
                            Level  = 1
                        };

                        SpinBet sb = new SpinBet(ugk, PlatformType.None)
                        {
                            LineBet    = 1,
                            Credits    = 0,
                            Lines      = FaFaZhuConfiguration.BettingLines,
                            Multiplier = 1
                        };

                        RequestContext <SpinArgs>  requestContext      = new RequestContext <SpinArgs>("", FaFaZhuConfiguration.GameName, PlatformType.Web);
                        RequestContext <BonusArgs> requestBonusContext = new RequestContext <BonusArgs>("", FaFaZhuConfiguration.GameName, PlatformType.Web);
                        requestContext.Currency = new Currency()
                        {
                            Id = sb.CurrencyId
                        };
                        requestContext.Parameters = new SpinArgs()
                        {
                            LineBet = sb.LineBet, BettingLines = sb.Lines
                        };
                        requestContext.GameSetting = new GameSetting()
                        {
                            GameSettingGroupId = sb.GameSettingGroupId
                        };

                        var wheel = new Wheel(rows);

                        for (int i = 1; i < FaFaZhuConfiguration.Wheels[level].Reels[0].Count - 1; i++)
                        {
                            if (reel0 < FaFaZhuConfiguration.CumulativeWeightReels[level][0][i - 1])
                            {
                                reel1Pointer = i;

                                wheel.Reels[0] = FaFaZhuCommon.GetRange(FaFaZhuConfiguration.Wheels[level].Reels[0], reel1Pointer, wheel.Rows[0]);

                                break;
                            }
                        }

                        for (int j = 1; j < FaFaZhuConfiguration.Wheels[level].Reels[1].Count - 1; j++)
                        {
                            if (reel1 < FaFaZhuConfiguration.CumulativeWeightReels[level][1][j - 1])
                            {
                                reel2Pointer = j;

                                wheel.Reels[1] = FaFaZhuCommon.GetRange(FaFaZhuConfiguration.Wheels[level].Reels[1], reel2Pointer, wheel.Rows[1]);

                                break;
                            }
                        }

                        for (int k = 1; k < FaFaZhuConfiguration.Wheels[level].Reels[2].Count - 1; k++)
                        {
                            if (reel2 < FaFaZhuConfiguration.CumulativeWeightReels[level][2][k - 1])
                            {
                                reel3Pointer = k;

                                wheel.Reels[2] = FaFaZhuCommon.GetRange(FaFaZhuConfiguration.Wheels[level].Reels[2], reel3Pointer, wheel.Rows[2]);

                                break;
                            }
                        }

                        FaFaZhuSpinResult sr = new FaFaZhuSpinResult(ugk)
                        {
                            SpinBet = new SpinBet(ugk, PlatformType.None)
                            {
                                Lines      = FaFaZhuConfiguration.BettingLines,
                                Multiplier = 1,
                                LineBet    = 1m
                            },

                            WheelActual = wheel
                        };

                        sr.WheelActual = wheel;

                        FaFaZhuCommon.CalculateWin(sr);

                        totalWin = sr.Win;

                        UpdateSummaryData(summData, sr);
                        UpdateFaFaZhuSummaryData(summData, sr);

                        if (!profile.ContainsKey(totalWin))
                        {
                            profile.Add(totalWin, 1);
                        }
                        else
                        {
                            profile.TryGetValue(totalWin, out int count);
                            profile.Remove(totalWin);
                            profile.Add(totalWin, count + 1);
                        }
                    }
                }
            }

            DisplayFaFaZhuSummaryData(level, 1, 10, summData, sdt, maxWin, maxIndexPosition);
            if (profile != null)
            {
                foreach (var item in profile.OrderByDescending(p => p.Key))
                {
                    Console.WriteLine($"Win            : {item.Key}; {item.Value}");
                }
            }
        }