示例#1
0
        /// <inheritdoc/>
        public override IDictionary <TPlayer, Rating> CalculateNewRatings <TPlayer>(GameInfo gameInfo,
                                                                                    IEnumerable
                                                                                    <IDictionary <TPlayer, Rating> >
                                                                                    teams, params int[] teamRanks)
        {
            Guard.ArgumentNotNull(gameInfo, "gameInfo");
            ValidateTeamCountAndPlayersCountPerTeam(teams);

            RankSorter.Sort(ref teams, ref teamRanks);

            IDictionary <TPlayer, Rating> team1 = teams.First();
            IDictionary <TPlayer, Rating> team2 = teams.Last();

            bool wasDraw = (teamRanks[0] == teamRanks[1]);

            var results = new Dictionary <TPlayer, Rating>();

            UpdatePlayerRatings(gameInfo,
                                results,
                                team1,
                                team2,
                                wasDraw ? PairwiseComparison.Draw : PairwiseComparison.Win);

            UpdatePlayerRatings(gameInfo,
                                results,
                                team2,
                                team1,
                                wasDraw ? PairwiseComparison.Draw : PairwiseComparison.Lose);

            return(results);
        }
        public override IDictionary <TPlayer, Rating> CalculateNewRatings <TPlayer>(GameInfo gameInfo, IEnumerable <IDictionary <TPlayer, Rating> > teams, params int[] teamRanks)
        {
            // On page 6 of the TrueSkill paper, the authors write:
            // "When we had to process a team game or a game with more than two teams we used
            //  the so-called *duelling* heuristic: For each player, compute the Δ's in comparison
            //  to all other players based on the team outcome of the player and every other player and
            //  perform an update with the average of the Δ's."
            // This implements that algorithm.

            ValidateTeamCountAndPlayersCountPerTeam(teams);
            RankSorter.Sort(ref teams, ref teamRanks);

            var teamsList = teams.ToList();

            var deltas = new Dictionary <TPlayer, IDictionary <TPlayer, double> >();

            for (int ixCurrentTeam = 0; ixCurrentTeam < teamsList.Count; ixCurrentTeam++)
            {
                for (int ixOtherTeam = 0; ixOtherTeam < teamsList.Count; ixOtherTeam++)
                {
                    if (ixOtherTeam == ixCurrentTeam)
                    {
                        // Shouldn't duel against ourself ;)
                        continue;
                    }

                    var currentTeam = teamsList[ixCurrentTeam];
                    var otherTeam   = teamsList[ixOtherTeam];

                    // Remember that bigger numbers mean worse rank (e.g. other-current is what we want)
                    var comparison = (PairwiseComparison)Math.Sign(teamRanks[ixOtherTeam] - teamRanks[ixCurrentTeam]);

                    foreach (var currentTeamPlayerRatingPair in currentTeam)
                    {
                        foreach (var otherTeamPlayerRatingPair in otherTeam)
                        {
                            UpdateDuels <TPlayer>(gameInfo, deltas,
                                                  currentTeamPlayerRatingPair.Key, currentTeamPlayerRatingPair.Value,
                                                  otherTeamPlayerRatingPair.Key, otherTeamPlayerRatingPair.Value,
                                                  comparison);
                        }
                    }
                }
            }

            var result = new Dictionary <TPlayer, Rating>();

            foreach (var currentTeam in teamsList)
            {
                foreach (var currentTeamPlayerPair in currentTeam)
                {
                    var currentPlayerAverageDuellingDelta = deltas[currentTeamPlayerPair.Key].Values.Average();
                    result[currentTeamPlayerPair.Key] = new EloRating(currentTeamPlayerPair.Value.Mean + currentPlayerAverageDuellingDelta);
                }
            }

            return(result);
        }
示例#3
0
        public void SortUnsortedTest()
        {
            IEnumerable <string> people = new[] { "Five", "Two1", "Two2", "One", "Four" };

            int[] ranks = new[] { 5, 2, 2, 1, 4 };

            RankSorter.Sort(ref people, ref ranks);

            CollectionAssert.AreEqual(new[] { "One", "Two1", "Two2", "Four", "Five" }, people);
            CollectionAssert.AreEqual(new[] { 1, 2, 2, 4, 5 }, ranks);
        }
示例#4
0
        public void SortAlreadySortedTest()
        {
            IEnumerable <string> people = new[] { "One", "Two", "Three" };

            int[] ranks = new[] { 1, 2, 3 };

            RankSorter.Sort(ref people, ref ranks);

            CollectionAssert.AreEqual(new[] { "One", "Two", "Three" }, people);
            CollectionAssert.AreEqual(new[] { 1, 2, 3 }, ranks);
        }
示例#5
0
        public override IDictionary <TPlayer, Rating> CalculateNewRatings <TPlayer>(GameInfo gameInfo,
                                                                                    IEnumerable <IDictionary <TPlayer, Rating> > teams,
                                                                                    params int[] teamRanks)
        {
            Guard.ArgumentNotNull(gameInfo, "gameInfo");
            ValidateTeamCountAndPlayersCountPerTeam(teams);

            RankSorter.Sort(ref teams, ref teamRanks);

            var factorGraph = new TrueSkillFactorGraph <TPlayer>(gameInfo, teams, teamRanks);

            factorGraph.BuildGraph();
            factorGraph.RunSchedule();

            double probabilityOfOutcome = factorGraph.GetProbabilityOfRanking();

            return(factorGraph.GetUpdatedRatings());
        }
示例#6
0
        public override IDictionary<TPlayer, Rating> CalculateNewRatings<TPlayer>(GameInfo gameInfo, IEnumerable<IDictionary<TPlayer, Rating>> teams, params int[] teamRanks)
        {
            ValidateTeamCountAndPlayersCountPerTeam(teams);
            RankSorter.Sort(ref teams, ref teamRanks);

            var result = new Dictionary<TPlayer, Rating>();
            bool isDraw = (teamRanks[0] == teamRanks[1]);

            var player1 = teams.First().First();
            var player2 = teams.Last().First();
            
            var player1Rating = player1.Value.Mean;
            var player2Rating = player2.Value.Mean;

            result[player1.Key] = CalculateNewRating(gameInfo, player1Rating, player2Rating, isDraw ? PairwiseComparison.Draw : PairwiseComparison.Win);
            result[player2.Key] = CalculateNewRating(gameInfo, player2Rating, player1Rating, isDraw ? PairwiseComparison.Draw : PairwiseComparison.Lose);

            return result;
        }
示例#7
0
        /// <inheritdoc/>
        public override IDictionary <TPlayer, Rating> CalculateNewRatings <TPlayer>(GameInfo gameInfo,
                                                                                    IEnumerable
                                                                                    <IDictionary <TPlayer, Rating> >
                                                                                    teams, params int[] teamRanks)
        {
            // Basic argument checking
            Guard.ArgumentNotNull(gameInfo, "gameInfo");
            ValidateTeamCountAndPlayersCountPerTeam(teams);

            // Make sure things are in order
            RankSorter.Sort(ref teams, ref teamRanks);

            // Get the teams as a list to make it easier to index
            List <IDictionary <TPlayer, Rating> > teamList = teams.ToList();

            // Since we verified that each team has one player, we know the player is the first one
            IDictionary <TPlayer, Rating> winningTeam = teamList[0];
            TPlayer winner = winningTeam.Keys.First();
            Rating  winnerPreviousRating = winningTeam[winner];

            IDictionary <TPlayer, Rating> losingTeam = teamList[1];
            TPlayer loser = losingTeam.Keys.First();
            Rating  loserPreviousRating = losingTeam[loser];

            bool wasDraw = (teamRanks[0] == teamRanks[1]);

            var results = new Dictionary <TPlayer, Rating>();

            results[winner] = CalculateNewRating(gameInfo, winnerPreviousRating, loserPreviousRating,
                                                 wasDraw ? PairwiseComparison.Draw : PairwiseComparison.Win);
            results[loser] = CalculateNewRating(gameInfo, loserPreviousRating, winnerPreviousRating,
                                                wasDraw ? PairwiseComparison.Draw : PairwiseComparison.Lose);

            // And we're done!
            return(results);
        }