コード例 #1
0
        public void TestGetNewRating(int originalRating, double winProbability, Result result, int expectedNewRating)
        {
            var calculator      = new EloCalculator(32);
            var actualNewRating = calculator.GetNewRating(originalRating, winProbability, result);

            Assert.AreEqual(expectedNewRating, actualNewRating);
        }
コード例 #2
0
        public (decimal WinningNewEloScore, decimal LosingNewEloScore) CalculateNewEloScore(decimal winningScore, decimal losingScore, int gameId, int kFactor)
        {
            var newElo = EloCalculator.CalculateElo(winningScore, losingScore, Convert.ToDecimal(EloCalculator.WIN), Convert.ToDecimal(EloCalculator.LOSE),
                                                    kFactor, kFactor);

            return(newElo[0], newElo[1]);
        }
コード例 #3
0
ファイル: CharacterController.cs プロジェクト: abshev/SSBPD
        public ActionResult Stats()
        {
            List <CharacterStats> stats = new List <CharacterStats>();
            var calculator = new EloCalculator();
            var scores     = (from e in db.EloScores
                              select e).ToList();

            foreach (Character character in CharacterUtils.Characters)
            {
                if (Application[character.ToString() + "Stats"] != null)
                {
                    stats.Add((CharacterStats)Application[character.ToString() + "Stats"]);
                    Debug.WriteLine("Hit cache for " + character.ToString());
                }
                else
                {
                    int charId = (int)character;
                    var sets   = from s in db.Sets
                                 where s.WinnerCharacterID == charId || s.LoserCharacterID == charId
                                 select s;
                    var charStats = new CharacterStats(character, sets, scores, calculator);
                    stats.Add(charStats);
                    Application[character.ToString() + "Stats"] = charStats;
                    Debug.WriteLine("Missed cache for " + character.ToString());
                    Application["lastProcessedStats"] = DateTime.Now;
                }
            }
            ViewBag.LastProcessed = Application["lastProcessedStats"];
            return(View(stats));
        }
コード例 #4
0
        public void TestUpdateRating(int playerRating, int opponentRating, Result result, int expectedNewPlayerRating)
        {
            var calculator      = new EloCalculator(32);
            var newRatingHolder = calculator.UpdateRating(new RatingHolder(0, playerRating), new RatingHolder(1, opponentRating), result);

            Assert.AreEqual(newRatingHolder.Rating, expectedNewPlayerRating);
        }
コード例 #5
0
        public void TestGetWinProbability(int playerRating, int opponentRating, double expectedProbabilityToTwoDecimalPlaces)
        {
            var calculator        = new EloCalculator(32);
            var actualProbability = calculator.GetWinProbability(playerRating, opponentRating);
            var actualProbabilityToTwoDecimalPlaces = Math.Round(actualProbability, 2);

            Assert.AreEqual(expectedProbabilityToTwoDecimalPlaces, actualProbabilityToTwoDecimalPlaces);
        }
コード例 #6
0
        public void StrengthPlayerDraw()
        {
            var elo = new EloCalculator(2000, 1000);

            elo.DrawGame();
            decimal newRatingA = (decimal)elo.RatingPlayerA;
            decimal newRatingB = (decimal)elo.RatingPlayerB;

            Assert.AreEqual(2000.157615459, (double)newRatingA, 0.00001);
            Assert.AreEqual(1049.842384540, (double)newRatingB, 0.00001);
        }
コード例 #7
0
        public void StrengthPlayerWinOnWeakPlayer()
        {
            var elo = new EloCalculator(1000, 100);

            elo.WinGamePlayerA();
            decimal newRatingA = (decimal)elo.RatingPlayerA;
            decimal newRatingB = (decimal)elo.RatingPlayerB;

            Assert.AreEqual(1000.5591967308, (double)newRatingA, 0.00001);
            Assert.AreEqual(100, newRatingB);
        }
コード例 #8
0
        public void StrengthPlayerLoss()
        {
            var elo = new EloCalculator(2000, 1000);

            elo.WinGamePlayerB();
            decimal newRatingA = (decimal)elo.RatingPlayerA;
            decimal newRatingB = (decimal)elo.RatingPlayerB;

            Assert.AreEqual(1900.315230918, (double)newRatingA, 0.00001);
            Assert.AreEqual(1099.684769081, (double)newRatingB, 0.00001);
        }
コード例 #9
0
        public void WinBefore500()
        {
            var elo = new EloCalculator(100, 100);

            elo.WinGamePlayerA();
            decimal newRatingA = (decimal)elo.RatingPlayerA;
            decimal newRatingB = (decimal)elo.RatingPlayerB;

            Assert.AreEqual(150, newRatingA);
            Assert.AreEqual(100, newRatingB);
        }
コード例 #10
0
        public void StrengthPlayerLossOnWeakPlayer()
        {
            var elo = new EloCalculator(1000, 100);

            elo.WinGamePlayerB();
            decimal newRatingA = (decimal)elo.RatingPlayerA;
            decimal newRatingB = (decimal)elo.RatingPlayerB;

            Assert.AreEqual(900.55919673088, (double)newRatingA, 0.00001);
            Assert.AreEqual(199.4408032691, (double)newRatingB, 0.00001);
        }
コード例 #11
0
        public void DrawBefore500()
        {
            var elo = new EloCalculator(100, 100);

            elo.DrawGame();
            decimal newRatingA = (decimal)elo.RatingPlayerA;
            decimal newRatingB = (decimal)elo.RatingPlayerB;

            Assert.AreEqual(125, newRatingA);
            Assert.AreEqual(125, newRatingB);
        }
コード例 #12
0
        public void Test()
        {
            int elo;

            elo = EloCalculator.CalculateNewElo(2000, 2000, 0, EloCalculator.VictoryType.Win);
            Assert.AreEqual(elo, 2020);

            elo = EloCalculator.CalculateNewElo(1970, 2320, 35, EloCalculator.VictoryType.Loss);
            Assert.AreEqual(elo, 1968);

            elo = EloCalculator.CalculateNewElo(2480, 2100, 482, EloCalculator.VictoryType.Loss);
            Assert.AreEqual(elo, 2471);
        }
コード例 #13
0
        public void TestUpdateRatings(IReadOnlyCollection <IReadOnlyCollection <KeyValuePair <int, int> > > gameResult, Dictionary <int, int> expectedNewRatings)
        {
            var calculator = new EloCalculator(32);
            var gameResultRatingHolders = gameResult
                                          .Select(rs => rs.Select(r => new RatingHolder(r.Key, r.Value)).ToList())
                                          .ToList();
            var newRatingHolders = calculator.UpdateRatings(gameResultRatingHolders).ToList();

            Assert.AreEqual(newRatingHolders.Count, expectedNewRatings.Count);
            Assert.AreEqual(newRatingHolders.Count, newRatingHolders.Select(rh => rh.Identifier).Distinct().Count());
            foreach (var rh in newRatingHolders)
            {
                Assert.AreEqual(rh.Rating, expectedNewRatings[rh.Identifier]);
            }
        }
コード例 #14
0
    public void OnMatchCreateClicked()
    {
        int winnerID = Winner.value + 1;
        int loserID  = loser.value + 1;

        if (winnerID != loserID)
        {
            EloCalculator.CalculateElo(winnerID, loserID);
            DatabaseController.addMatchPlayed(winnerID);
            DatabaseController.addMatchPlayed(loserID);
        }
        else
        {
            string title   = "Invalid Input";
            string message = "How are they playing themselfs?";
            //EditorUtility.DisplayDialog(title,message,"Ok");
        }
    }
コード例 #15
0
        public void ProvVsProv()
        {
            int v_ActualScore = (int)EloCalculator.CalcProvisionalVsProvisionalRanking(1500, 1, 1500, EloCalculator.ModifierProvisional[EloCalculator.Modifier.Win]);

            Assert.AreEqual(1550, v_ActualScore);
            v_ActualScore = (int)EloCalculator.CalcProvisionalVsProvisionalRanking(1700, 6, 1100, EloCalculator.ModifierProvisional[EloCalculator.Modifier.Win]);
            Assert.AreEqual(1671, v_ActualScore);
            v_ActualScore = (int)EloCalculator.CalcProvisionalVsProvisionalRanking(1158, 12, 1541, EloCalculator.ModifierProvisional[EloCalculator.Modifier.Win]);
            Assert.AreEqual(1180, v_ActualScore);

            v_ActualScore = (int)EloCalculator.CalcProvisionalVsProvisionalRanking(1500, 1, 1500, EloCalculator.ModifierProvisional[EloCalculator.Modifier.Lose]);
            Assert.AreEqual(1450, v_ActualScore);

            v_ActualScore = (int)EloCalculator.CalcProvisionalVsProvisionalRanking(1500, 1, 1500, EloCalculator.ModifierProvisional[EloCalculator.Modifier.Stalemate]);
            Assert.AreEqual(1500, v_ActualScore);

            Assert.Throws <ArgumentException>(() => EloCalculator.CalcProvisionalVsProvisionalRanking(1500, -1, 1500, EloCalculator.ModifierProvisional[EloCalculator.Modifier.Win]));
            Assert.Throws <ArgumentException>(() => EloCalculator.CalcProvisionalVsProvisionalRanking(1500, 21, 1500, EloCalculator.ModifierProvisional[EloCalculator.Modifier.Win]));
        }
コード例 #16
0
        private void calculateElo(Game game, UserStats statsA, UserStats statsB)
        {
            var elo = new EloCalculator(statsA.Elo, statsB.Elo);

            if (game.ScoreA > game.ScoreB)
            {
                elo.WinGamePlayerA();
            }
            else if (game.ScoreA < game.ScoreB)
            {
                elo.WinGamePlayerB();
            }
            else
            {
                elo.DrawGame();
            }

            statsA.Elo = (decimal)elo.RatingPlayerA;
            statsB.Elo = (decimal)elo.RatingPlayerB;
        }
コード例 #17
0
        /// <summary>
        /// Initializes a new instance of the MainViewModel class.
        /// </summary>
        public MainViewModel()
        {
            var path   = Path.Combine(Environment.CurrentDirectory, "DeckMatchups.xlsx");
            var reader = new WorkbookReader(path);

            var matchups = reader.GetAllMatchups();

            var calc = new EloCalculator();

            calc.Calculate(matchups);

            var decklist = new List <Deck>();

            decklist.AddRange(matchups.Select(m => m.DeckA).Distinct());
            decklist.AddRange(matchups.Where(m => !decklist.Contains(m.DeckB)).Select(m => m.DeckB).Distinct());

            _allDecks = decklist;
            Decks     = _allDecks;
            Filter    = new DeckFilter();
            Filter.FilterChangedEvent += OnFilterChanged;
        }
コード例 #18
0
        /// <summary>
        /// Load your modules or register your services here!
        /// </summary>
        /// <param name="kernel">The kernel.</param>
        private static void RegisterServices(IKernel kernel)
        {
            var scoreCalculator = new EloCalculator();
            var scoreQuery      = new ScoreQuery(new WebSignaler(), scoreCalculator);
            var eventBus        = new DomainBus();
            var teamService     = new TeamService();

            eventBus.RegisterHandler(() => new GameHandler(scoreQuery));
            eventBus.RegisterHandler(() => teamService);
            kernel.Bind <IScoreQuery>().ToConstant(scoreQuery);
            kernel.Bind <ITeamService>().ToConstant(teamService);
            var eventStorage   = GetEventStorage(eventBus);
            var sessionFactory = new SessionFactory(eventStorage);

            kernel.Bind <IEventStorage>().ToConstant(eventStorage);
            kernel.Bind <ISessionFactory>().ToConstant(sessionFactory);
            var gameService = new GameService(sessionFactory, eventBus);
            var commandbus  = new DomainBus();

            commandbus.RegisterHandler(() => gameService);
            kernel.Bind <IBus>().ToConstant(commandbus);
        }
コード例 #19
0
        public ActionResult Forecast(ForecastViewModel vm)
        {
            vm.AvailablePlayers = getAvailablePlayersSelectListItems();

            var playerA = _userService.GetUser(vm.PlayerAId);
            var playerB = _userService.GetUser(vm.PlayerBId);

            vm.NamePlayerA = playerA.Name;
            vm.NamePlayerB = playerB.Name;

            vm.CurrentRatingPlayerA = (double)_statsService.GetUserStat(playerA.Id).Elo;
            vm.CurrentRatingPlayerB = (double)_statsService.GetUserStat(playerB.Id).Elo;

            var elo = new EloCalculator(vm.CurrentRatingPlayerA, vm.CurrentRatingPlayerB);

            vm.ChanceToWinPlayerA = elo.GetChanceToWinPlayerA() * 100;
            vm.ChanceToWinPlayerB = 100 - vm.ChanceToWinPlayerA;

            elo.WinGamePlayerA();
            vm.RatingPlayerAWinPlayerA = elo.RatingPlayerA;
            vm.RatingPlayerBWinPlayerA = elo.RatingPlayerB;

            elo = new EloCalculator(vm.CurrentRatingPlayerA, vm.CurrentRatingPlayerB);
            elo.WinGamePlayerB();
            vm.RatingPlayerAWinPlayerB = elo.RatingPlayerA;
            vm.RatingPlayerBWinPlayerB = elo.RatingPlayerB;

            elo = new EloCalculator(vm.CurrentRatingPlayerA, vm.CurrentRatingPlayerB);
            elo.DrawGame();
            vm.RatingPlayerADrawGame = elo.RatingPlayerA;
            vm.RatingPlayerBDrawGame = elo.RatingPlayerB;

            vm.Calculated = true;

            return(View(vm));
        }
コード例 #20
0
        public static void RunDayTwo(List <Player> players)
        {
            var dayTwoPlayers = new List <Player>(players);
            var roundNumber   = 0;

            while (dayTwoPlayers.Count > 1)
            {
                Shuffle(dayTwoPlayers);
                for (var index = 0; index < dayTwoPlayers.Count - 1; index += 2)
                {
                    var playerOne = dayTwoPlayers[index];
                    var playerTwo = dayTwoPlayers[index + 1];

                    var  playerOneGameWinChance  = EloCalculator.PredictResult(playerOne.Elo, playerTwo.Elo)[0];
                    var  playerOneMatchWinChance = playerOneGameWinChance * playerOneGameWinChance * (3 - 2 * playerOneGameWinChance);
                    bool playerOneWins           = playerOneMatchWinChance >= (decimal)rng.NextDouble();
                    if (playerOneWins)
                    {
                        playerOne.DayTwoWins++;
                        playerTwo.DayTwoLosses++;
                    }
                    else
                    {
                        playerTwo.DayTwoWins++;
                        playerOne.DayTwoLosses++;
                    }
                }

                for (var index = dayTwoPlayers.Count - 1; index >= 0; index--)
                {
                    var player = dayTwoPlayers[index];
                    if (player.DayTwoLosses == 2)
                    {
                        var gemsWon = 0;
                        switch (player.DayTwoWins)
                        {
                        case 1:
                        case 2:
                        case 3:
                            gemsWon = player.DayTwoWins * 2000;
                            break;

                        case 4:
                        case 5:
                            gemsWon = (player.DayTwoWins - 3) * 10000;
                            break;

                        case 6:
                            gemsWon = 200000;
                            break;
                        }
                        player.GemsWon += gemsWon;
                        dayTwoPlayers.RemoveAt(index);
                    }
                    else if (player.DayTwoWins == 7) // shouldn't really need the else but if there's a bug it's less bad this way
                    {
                        player.GemsWon += 400000;
                        dayTwoPlayers.RemoveAt(index);
                    }
                }
                roundNumber++;
                Console.WriteLine("After round " + roundNumber + " of Day 2 - " + dayTwoPlayers.Count +
                                  " remaining players.");
            }
        }
コード例 #21
0
        public static List <Player> RunDayOne(List <Player> players, int numReentries)
        {
            var dayOnePlayers = new List <Player>(players);
            var dayTwoPlayers = new List <Player>();
            var roundNumber   = 0;

            // need to avoid getting stuck with an odd player out
            // probably just fail them out
            while (dayOnePlayers.Count > 1)
            {
                // random match making until we know better
                Shuffle(dayOnePlayers);

                for (var index = 0; index < dayOnePlayers.Count - 1; index += 2)
                {
                    var playerOne = dayOnePlayers[index];
                    var playerTwo = dayOnePlayers[index + 1];
                    // yeah yeah yeah decimals aren't doubles blah blah blah
                    bool playerOneWins = EloCalculator.PredictResult(playerOne.Elo, playerTwo.Elo)[0] >= (decimal)rng.NextDouble();
                    if (playerOneWins)
                    {
                        playerOne.CurrentWins++;
                        playerOne.DayOneWins++;
                        playerTwo.CurrentLosses++;
                        playerTwo.DayOneLosses++;
                    }
                    else
                    {
                        playerTwo.CurrentWins++;
                        playerTwo.DayOneWins++;
                        playerOne.CurrentLosses++;
                        playerOne.DayOneLosses++;
                    }
                }

                for (var index = dayOnePlayers.Count - 1; index >= 0; index--)
                {
                    var player = dayOnePlayers[index];
                    if (player.CurrentLosses == 3)
                    {
                        player.GemsWon += Math.Max(0, 400 * (player.CurrentWins - 2));
                        if (player.Run <= numReentries)
                        {
                            // Re-enter the tournament
                            player.Run++;
                            player.CurrentWins   = 0;
                            player.CurrentLosses = 0;
                            player.GemsSpent    += 4000;
                        }
                        else
                        {
                            // you're out!
                            dayOnePlayers.RemoveAt(index);
                        }
                    }
                    else if (player.CurrentWins == 7) // shouldn't really need the else but if there's a bug it's less bad this way
                    {
                        dayTwoPlayers.Add(player);
                        dayOnePlayers.RemoveAt(index);
                    }
                }
                roundNumber++;
                Console.WriteLine("After round " + roundNumber + " of Day 1 - " + dayOnePlayers.Count +
                                  " remaining players, and " + dayTwoPlayers.Count + " day two players.");
            }
            return(dayTwoPlayers);
        }
コード例 #22
0
        // multiplies games weight by e^-(elo_error/EloErrorHalfWeight)
        public static double CalculateGoodnessPrioritizeEval(
            Player sideToMove,
            EnumArray <GameLevel, AggregatedEntry> aggregatedEntries,
            ChessDBCNScore score,
            Options options
            )
        {
            const double eloErrorHalfWeight      = 100;
            const double maxAllowedPlayerEloDiff = 400;
            const double maxCalculatedEloDiff    = 800;

            AggregatedEntry totalEntry = new AggregatedEntry();

            foreach (KeyValuePair <GameLevel, AggregatedEntry> e in aggregatedEntries)
            {
                totalEntry.Combine(e.Value);
            }

            if (score == null && Math.Abs(totalEntry.TotalEloDiff / (double)totalEntry.Count) > maxAllowedPlayerEloDiff)
            {
                return(0.0);
            }

            double evalWeight = options.EvalWeight;

            Tuple <double, double> calculateAdjustedPerf(AggregatedEntry e)
            {
                ulong? lowNThreshold = options.IncreaseErrorBarForLowN ? (ulong?)options.LowN : null;
                ulong  totalWins     = e.WinCount;
                ulong  totalDraws    = e.DrawCount;
                ulong  totalLosses   = e.Count - totalWins - totalDraws;
                double totalEloError = EloCalculator.Clamp(
                    EloCalculator.EloError99pct(totalWins, totalDraws, totalLosses, lowNThreshold),
                    2 * maxCalculatedEloDiff
                    );
                double gw = options.GamesWeight * Math.Exp(-(totalEloError / eloErrorHalfWeight));

                if (e.Count > 0)
                {
                    double totalPerf         = (totalWins + totalDraws * options.DrawScore) / e.Count;
                    double expectedTotalPerf = EloCalculator.GetExpectedPerformance(e.TotalEloDiff / (double)e.Count);
                    if (sideToMove == Player.Black)
                    {
                        totalPerf         = 1.0 - totalPerf;
                        expectedTotalPerf = 1.0 - expectedTotalPerf;
                    }
                    double adjustedPerf = EloCalculator.GetAdjustedPerformance(totalPerf, expectedTotalPerf, maxCalculatedEloDiff);
                    if (score == null)
                    {
                        // If the score is null there's nothing to moderate the bad empirical data.
                        // So we apply the old method to reduce the QI of this move based on elo error.
                        double expectedElo =
                            EloCalculator.Clamp(
                                EloCalculator.Clamp(
                                    EloCalculator.GetEloFromPerformance(adjustedPerf),
                                    maxCalculatedEloDiff
                                    ) - totalEloError,
                                maxCalculatedEloDiff);
                        adjustedPerf = EloCalculator.GetExpectedPerformance(expectedElo);
                    }
                    return(new Tuple <double, double>(gw, adjustedPerf));
                }
                else
                {
                    return(new Tuple <double, double>(0, 0));
                }
            }

            (double gamesWeight, double adjustedGamesPerf) = calculateAdjustedPerf(totalEntry);

            double gamesGoodness = EloCalculator.Clamp(
                EloCalculator.GetEloFromPerformance(adjustedGamesPerf),
                maxCalculatedEloDiff
                ) * gamesWeight;

            // If eval is not present then assume 0.5 but reduce it for moves with low game count.
            // The idea is that we don't want missing eval to penalize common moves.
            double evalGoodness =
                (
                    score != null
                    ? EloCalculator.GetEloFromPerformance(score.Perf)
                    : -EloCalculator.EloError99pct(
                        totalEntry.WinCount,
                        totalEntry.DrawCount,
                        totalEntry.LossCount
                        )
                ) * evalWeight;

            double weightSum = gamesWeight + evalWeight;

            double goodness = EloCalculator.GetExpectedPerformance((gamesGoodness + evalGoodness) / weightSum);

            return(goodness);
        }
コード例 #23
0
        // subtracts totalEloError from expectedElo
        public static double CalculateGoodness(
            Player sideToMove,
            EnumArray <GameLevel, AggregatedEntry> aggregatedEntries,
            ChessDBCNScore score,
            Options options
            )
        {
            const double maxAllowedPlayerEloDiff = 400;
            const double maxCalculatedEloDiff    = 800;

            bool useEval  = options.EvalWeight > 0.0;
            bool useGames = options.GamesWeight > 0.0;

            AggregatedEntry totalEntry = new AggregatedEntry();

            foreach (KeyValuePair <GameLevel, AggregatedEntry> e in aggregatedEntries)
            {
                totalEntry.Combine(e.Value);
            }

            if (useGames && totalEntry.Count == 0)
            {
                return(0.0);
            }

            if (useEval && score == null && Math.Abs(totalEntry.TotalEloDiff / (double)totalEntry.Count) > maxAllowedPlayerEloDiff)
            {
                return(0.0);
            }

            double gamesWeight = options.GamesWeight;
            double evalWeight  = options.EvalWeight;

            double calculateAdjustedPerf(AggregatedEntry e)
            {
                if (e.Count > 0)
                {
                    ulong? lowNThreshold = options.IncreaseErrorBarForLowN ? (ulong?)options.LowN : null;
                    ulong  totalWins     = e.WinCount;
                    ulong  totalDraws    = e.DrawCount;
                    ulong  totalLosses   = e.Count - totalWins - totalDraws;
                    double totalEloError = EloCalculator.Clamp(
                        EloCalculator.EloError99pct(totalWins, totalDraws, totalLosses, lowNThreshold),
                        2 * maxCalculatedEloDiff
                        );
                    double totalPerf         = (totalWins + totalDraws * options.DrawScore) / e.Count;
                    double expectedTotalPerf = EloCalculator.GetExpectedPerformance(e.TotalEloDiff / (double)e.Count);
                    if (sideToMove == Player.Black)
                    {
                        totalPerf         = 1.0 - totalPerf;
                        expectedTotalPerf = 1.0 - expectedTotalPerf;
                    }
                    double adjustedPerf = EloCalculator.GetAdjustedPerformance(totalPerf, expectedTotalPerf, maxCalculatedEloDiff);
                    double expectedElo  =
                        EloCalculator.Clamp(
                            EloCalculator.Clamp(
                                EloCalculator.GetEloFromPerformance(adjustedPerf),
                                maxCalculatedEloDiff
                                ) - totalEloError,
                            maxCalculatedEloDiff);
                    adjustedPerf = EloCalculator.GetExpectedPerformance(expectedElo);
                    return(adjustedPerf);
                }
                else
                {
                    return(0.0);
                }
            }

            double adjustedGamesPerf = calculateAdjustedPerf(totalEntry);

            double gamesGoodness = EloCalculator.Clamp(
                EloCalculator.GetEloFromPerformance(adjustedGamesPerf),
                maxCalculatedEloDiff
                ) * gamesWeight;

            // If eval is not present then assume 0.5 but reduce it for moves with low game count.
            // The idea is that we don't want missing eval to penalize common moves.
            double evalGoodness =
                (
                    score != null
                    ? EloCalculator.GetEloFromPerformance(score.Perf)
                    : -EloCalculator.EloError99pct(
                        totalEntry.WinCount,
                        totalEntry.DrawCount,
                        totalEntry.LossCount
                        )
                ) * evalWeight;

            double weightSum = gamesWeight + evalWeight;

            double goodness = EloCalculator.GetExpectedPerformance((gamesGoodness + evalGoodness) / weightSum);

            return(goodness);
        }
コード例 #24
0
        private void CalculateEloResults(Dictionary <Guid, ResultHelper> a_StartResults, DateTime a_MatchDate, Game.GameType a_GameType)
        {
            // We need to increment the count for all players.
            foreach (KeyValuePair <Guid, ResultHelper> i_Kvp in a_StartResults)
            {
                i_Kvp.Value.AmountGamesPlayed++;
            }

            Dictionary <Guid, KeyValuePair <DateTime, int> > v_TempResults = new Dictionary <Guid, KeyValuePair <DateTime, int> >();

            // We only want to do it ONCE for each entry.
            foreach (KeyValuePair <Guid, ResultHelper> i_Kvp in a_StartResults)
            {
                // Get the standings for given player.
                Dictionary <Modifier, List <Guid> > v_Standings = CalculateStandings(i_Kvp.Key, a_GameType);
                List <double> v_TempEloScores = new List <double>();

                // Iterates over all standings. Standings contains n-1 individual Ids (where n is the amount of players in a match).
                foreach (KeyValuePair <Modifier, List <Guid> > i_KvpInner in v_Standings)
                {
                    double v_ModifierPlayer = EloCalculator.EstablishedStatusToModifier[i_Kvp.Value.IsEstablished][i_KvpInner.Key];

                    foreach (Guid i_OpponentId in i_KvpInner.Value)
                    {
                        /// The +1 is needed because we only increment the amount of played games inside AddResult.
                        /// In the old implementation was actually a defect because the counter for the active player
                        /// was incremented and the calculation used the old value for the opponent.
                        double v_TempEloScore = EloCalculator.CalculateEloRanking(
                            i_Kvp.Value.EloScore,
                            i_Kvp.Value.AmountGamesPlayed,
                            i_Kvp.Value.IsEstablished,
                            a_StartResults[i_OpponentId].EloScore,
                            a_StartResults[i_OpponentId].AmountGamesPlayed,
                            a_StartResults[i_OpponentId].IsEstablished,
                            v_ModifierPlayer
                            );

                        v_TempEloScores.Add(v_TempEloScore);
                    }
                }

                double v_NewEloScore = 0;

                foreach (double i_TempScore in v_TempEloScores)
                {
                    v_NewEloScore += i_TempScore;
                }

                if (v_TempEloScores.Count > 0)
                {
                    v_NewEloScore = v_NewEloScore / v_TempEloScores.Count;
                    // Must NOT be applied immediately! We're putting the reults aside and apply them afterwards.
                    v_TempResults.Add(i_Kvp.Key, new KeyValuePair <DateTime, int>(a_MatchDate, (int)Math.Round(v_NewEloScore, 0)));
                }
            }

            // Now we add the new results.
            foreach (KeyValuePair <Guid, ResultHelper> i_Kvp in a_StartResults)
            {
                i_Kvp.Value.AddResult(v_TempResults[i_Kvp.Key].Key, v_TempResults[i_Kvp.Key].Value);
            }
        }
コード例 #25
0
ファイル: StatsService.cs プロジェクト: rnofenko/FIFA
        private void calculateElo(Game game, UserStats statsA, UserStats statsB)
        {
            var elo = new EloCalculator(statsA.Elo, statsB.Elo);
            if (game.ScoreA > game.ScoreB)
            {
                elo.WinGamePlayerA();
            }
            else if (game.ScoreA < game.ScoreB)
            {
                elo.WinGamePlayerB();
            }
            else
            {
                elo.DrawGame();
            }

            statsA.Elo = (decimal)elo.RatingPlayerA;
            statsB.Elo = (decimal)elo.RatingPlayerB;
        }
コード例 #26
0
 /// <summary>
 /// Changes the rating of the Pokemon based on a game.
 /// </summary>
 /// <param name="opponent">Opponent played.</param>
 /// <param name="victoryType">Whether the Pokemon won.</param>
 public void ChangeRating(Pokemon opponent, EloCalculator.VictoryType victoryType)
 {
     _rating = EloCalculator.CalculateNewElo(Rating, opponent.Rating, GamesPlayed, victoryType);
 }
コード例 #27
0
 public GameService(IRepositoryFactory repositoryFactory, EloCalculator eloCalculator, IGameServiceConfiguration configuration)
 {
     this.repositoryFactory = repositoryFactory;
     this.eloCalculator     = eloCalculator;
     this.configuration     = configuration;
 }
コード例 #28
0
ファイル: GameController.cs プロジェクト: rnofenko/FIFA
        public ActionResult Forecast(ForecastViewModel vm)
        {
            vm.AvailablePlayers = getAvailablePlayersSelectListItems();

            var playerA = _userService.GetUser(vm.PlayerAId);
            var playerB = _userService.GetUser(vm.PlayerBId);

            vm.NamePlayerA = playerA.Name;
            vm.NamePlayerB = playerB.Name;

            vm.CurrentRatingPlayerA = (double)_statsService.GetUserStat(playerA.Id).Elo;
            vm.CurrentRatingPlayerB = (double)_statsService.GetUserStat(playerB.Id).Elo;

            var elo = new EloCalculator(vm.CurrentRatingPlayerA, vm.CurrentRatingPlayerB);
            vm.ChanceToWinPlayerA = elo.GetChanceToWinPlayerA() * 100;
            vm.ChanceToWinPlayerB = 100 - vm.ChanceToWinPlayerA;

            elo.WinGamePlayerA();
            vm.RatingPlayerAWinPlayerA = elo.RatingPlayerA;
            vm.RatingPlayerBWinPlayerA = elo.RatingPlayerB;

            elo = new EloCalculator(vm.CurrentRatingPlayerA, vm.CurrentRatingPlayerB);
            elo.WinGamePlayerB();
            vm.RatingPlayerAWinPlayerB = elo.RatingPlayerA;
            vm.RatingPlayerBWinPlayerB = elo.RatingPlayerB;

            elo = new EloCalculator(vm.CurrentRatingPlayerA, vm.CurrentRatingPlayerB);
            elo.DrawGame();
            vm.RatingPlayerADrawGame = elo.RatingPlayerA;
            vm.RatingPlayerBDrawGame = elo.RatingPlayerB;

            vm.Calculated = true;

            return View(vm);
        }
コード例 #29
0
        static void Run(int numPlayers, int numReentries, double eloDistribution)
        {
            // This doesn't really matter but I picked from the same source as my default distribution
            // https://www.mtgcommunityreview.com/single-post/2018/06/12/Luck-Skill-and-Magic
            double eloMean = 1678.632;
            // I'm not actually going to adjust anyone's elo as they go - I'm using it as a representation of "true" skill
            var playerDistribution = new NormalDistribution(eloMean, eloDistribution);
            var players            = new List <Player>();

            for (var index = 0; index < numPlayers; index++)
            {
                var player = new Player();
                player.Elo       = (decimal)playerDistribution.Generate();
                player.GemsSpent = 4000;
                players.Add(player);
            }

            var dayTwoPlayers = RunDayOne(players, numReentries);

            foreach (var player in dayTwoPlayers)
            {
                player.CurrentWins   = 0;
                player.CurrentLosses = 0;
            }
            RunDayTwo(dayTwoPlayers);

            var dayOneAvgElo     = players.Average(p => p.Elo);
            var dayTwoAvgElo     = dayTwoPlayers.Average(p => p.Elo);
            var dayTwoWinPercent = EloCalculator.PredictResult(dayTwoAvgElo, (decimal)eloMean)[0] * 100;

            Console.WriteLine($"Day one average Elo: {dayOneAvgElo}.");
            Console.WriteLine($"Day two average Elo: {dayTwoAvgElo} ({dayTwoWinPercent,3:0.0}% win percent).");

            var numBuckets = 100;
            var bucketSize = numPlayers / numBuckets;

            if (numPlayers % numBuckets != 0)
            {
                Console.WriteLine("Warning - please use a multiple of " + numBuckets + " for more accurate top end performance");
            }

            var eloSorted = players.OrderBy(p => p.Elo).ToList();
            var skip      = 0;

            while (skip + bucketSize <= eloSorted.Count)
            {
                var nextBucket      = eloSorted.Skip(skip).Take(bucketSize).ToList();
                var minElo          = (int)nextBucket.Min(p => p.Elo);
                var maxElo          = (int)nextBucket.Max(p => p.Elo);
                var avgElo          = (int)nextBucket.Average(p => p.Elo);
                var avgGems         = nextBucket.Average(p => p.GemsWon - p.GemsSpent);
                var avgDayOneWins   = nextBucket.Average(p => p.DayOneWins);
                var avgDayOneLosses = nextBucket.Average(p => p.DayOneLosses);
                var avgDayTwoWins   = nextBucket.Average(p => p.DayTwoWins);
                var avgDayTwoLosses = nextBucket.Average(p => p.DayTwoLosses);
                var winPercentage   = EloCalculator.PredictResult(avgElo, (decimal)eloMean)[0] * 100;
                var bucketNumber    = skip / bucketSize + 1;

                Console.WriteLine($"{avgElo} ({minElo}-{maxElo}) ({winPercentage,3:0.0}% game win%, bucket #{bucketNumber}): {avgGems} gems, " +
                                  $"{avgDayOneWins,3:0.0}-{avgDayOneLosses,3:0.0} on day one, " +
                                  $"{avgDayTwoWins,3:0.0}-{avgDayTwoLosses,3:0.0} on day two.");
                skip += bucketSize;
            }
        }