Example #1
0
        public static Rating GetPartialUpdate(Rating prior, Rating fullPosterior, double updatePercentage)
        {
            var priorGaussian = new GaussianDistribution(prior.Mean, prior.StandardDeviation);
            var posteriorGaussian = new GaussianDistribution(fullPosterior.Mean, fullPosterior.StandardDeviation);

            // From a clarification email from Ralf Herbrich:
            // "the idea is to compute a linear interpolation between the prior and posterior skills of each player 
            //  ... in the canonical space of parameters"

            double precisionDifference = posteriorGaussian.Precision - priorGaussian.Precision;
            double partialPrecisionDifference = updatePercentage*precisionDifference;

            double precisionMeanDifference = posteriorGaussian.PrecisionMean - priorGaussian.PrecisionMean;
            double partialPrecisionMeanDifference = updatePercentage*precisionMeanDifference;

            GaussianDistribution partialPosteriorGaussion = GaussianDistribution.FromPrecisionMean(
                priorGaussian.PrecisionMean + partialPrecisionMeanDifference,
                priorGaussian.Precision + partialPrecisionDifference);

            return new Rating(partialPosteriorGaussion.Mean, partialPosteriorGaussion.StandardDeviation,
                              prior._ConservativeStandardDeviationMultiplier);
        }
Example #2
0
        private void refreshScoreBoxes()
        {
            Person p1 = new Person();
            Person p2 = new Person();
            foreach (Person person in playerList)
            {
                if (person.Name == player1Selector.Text)
                {
                    p1 = person;
                }
                if (person.Name == player2Selector.Text)
                {
                    p2 = person;
                }
            }

            p1MuDisplay.Text = p1.Mu.ToString();
            p1SigmaDisplay.Text = p1.Sigma.ToString();
            p1ScoreDisplay.Text = p1.Score.ToString();
            p2MuDisplay.Text = p2.Mu.ToString();
            p2SigmaDisplay.Text = p2.Sigma.ToString();
            p2ScoreDisplay.Text = p2.Score.ToString();
            p1WLDBox.Text = p1.Wins + " -- " + p1.Losses + " -- " + p1.Draws + " (" + p1.WinPercent + "%)";
            p2WLDBox.Text = p2.Wins + " -- " + p2.Losses + " -- " + p2.Draws + " (" + p2.WinPercent + "%)";

            Player p1s = new Player(1);
            Player p2s = new Player(2);
            Rating p1r = new Rating(p1.Mu, p1.Sigma);
            Rating p2r = new Rating(p2.Mu, p2.Sigma);
            Team t1 = new Team(p1s, p1r);
            Team t2 = new Team(p2s, p2r);

            matchQualBox.Text = (TrueSkillCalculator.CalculateMatchQuality(GameInfo.DefaultGameInfo, Teams.Concat(t1, t2)) * 100).ToString();
            
        }
Example #3
0
        private void updatePlayerMatch(UInt16 winner)
        {
            Person p1 = new Person();
            Person p2 = new Person();
            foreach (Person person in playerList)
            {
                if (person.Name == player1Selector.Text)
                {
                    p1 = person;
                }
                if (person.Name == player2Selector.Text)
                {
                    p2 = person;
                }
            }

            Player p1s = new Player(1);
            Player p2s = new Player(2);
            Rating p1r = new Rating(p1.Mu, p1.Sigma);
            Rating p2r = new Rating(p2.Mu, p2.Sigma);
            Team t1 = new Team(p1s, p1r);
            Team t2 = new Team(p2s, p2r);

            IDictionary<Player, Rating> newRatings = null;

            if(winner == 0)
                newRatings = TrueSkillCalculator.CalculateNewRatings(GameInfo.DefaultGameInfo, Teams.Concat(t1, t2), 1, 1);
            else if(winner == 1)
                newRatings = TrueSkillCalculator.CalculateNewRatings(GameInfo.DefaultGameInfo, Teams.Concat(t1, t2), 1, 2);
            else if(winner == 2)
                newRatings = TrueSkillCalculator.CalculateNewRatings(GameInfo.DefaultGameInfo, Teams.Concat(t1, t2), 2, 1);

            p1.Mu = newRatings[p1s].Mean;
            p1.Sigma = newRatings[p1s].StandardDeviation;
            p2.Mu = newRatings[p2s].Mean;
            p2.Sigma = newRatings[p2s].StandardDeviation;

            foreach (Person person in playerList)
            {
                if (person.Name == player1Selector.Text)
                {
                    person.Mu = p1.Mu;
                    person.Sigma = p1.Sigma;
                    if (winner == 0)
                        person.Draws++;
                    else if (winner == 1)
                        person.Wins++;
                    else if (winner == 2)
                        person.Losses++;
                }
                if (person.Name == player2Selector.Text)
                {
                    person.Mu = p2.Mu;
                    person.Sigma = p2.Sigma;
                    if (winner == 0)
                        person.Draws++;
                    else if (winner == 1)
                        person.Losses++;
                    else if (winner == 2)
                        person.Wins++;
                }
            }

            requireSave = true;

            refreshScoreBoxes();
        }
Example #4
0
 private static void AssertRating(double expected, Rating actual)
 {
     Assert.AreEqual(expected, actual.Mean, ErrorTolerance);
 }
Example #5
0
        /// <summary>
        /// Gets players that are most suited for competition (would provide as close as possible to an even match).  Both @candidates and @target need to have the TSCharacterComponent attached.
        /// </summary>
        /// <param name="candidates">the possible candidates to match against</param>
        /// <param name="target">the player for whom we wish to find matches</param>
        /// <returns>a list of character IDs in order of </returns>
        public static List<SkillMatchInfo> GetTopQualityMatches(IEnumerable<ICharacterInfo> candidates, ICharacterInfo target, int maxResults)
        {
            DateTime start = DateTime.UtcNow;
            List<SkillMatchInfo> matches = new List<SkillMatchInfo>();

            try
            {
                GameInfo gi = GameInfo.DefaultGameInfo;

                Player targetPlayer = new Player(target.ID);
                double targetMu = target.Properties.GetDoubleProperty((int)TSPropertyID.RatingMean).GetValueOrDefault();
                double targetSigma = target.Properties.GetDoubleProperty((int)TSPropertyID.RatingStandardDeviation).GetValueOrDefault();
                Rating targetRating = new Rating(targetMu, targetSigma);
                Team targetTeam = new Team(targetPlayer, targetRating);
                int numCandidates = 0;

                IEnumerator<ICharacterInfo> enu = candidates.GetEnumerator();
                while (enu.MoveNext())
                {
                    numCandidates++;
                    Player player = new Player(enu.Current.ID);
                    double mu = enu.Current.Properties.GetDoubleProperty((int)TSPropertyID.RatingMean).GetValueOrDefault();
                    double sigma = enu.Current.Properties.GetDoubleProperty((int)TSPropertyID.RatingStandardDeviation).GetValueOrDefault();
                    Rating rating = new Rating(mu, sigma);
                    Team team = new Team(player, rating);
                    double quality = TrueSkillCalculator.CalculateMatchQuality(gi, Teams.Concat(targetTeam, team));

                    matches.Add(new SkillMatchInfo(enu.Current.ID, quality));
                }

                // Sort it
                matches.OrderBy(i => i.MatchQuality);

                // trim it, if necessary
                if (maxResults > 0)
                {
                    if (maxResults > matches.Count)
                    {
                        maxResults = matches.Count;
                    }

                    matches = matches.GetRange(0, maxResults - 1);
                }

                DateTime end = DateTime.UtcNow;
                TimeSpan exeTime = end - start;
                int highestQuality = 0;
                if (matches.Count > 0)
                {
                    highestQuality = (int)Math.Floor(matches[0].MatchQuality * 100);
                }

                Log.LogMsg("TrueSkill match maker tested [" + numCandidates + "] candidates for character [" + target.CharacterName + " | " + target.ID + "]. Returned [" + matches.Count + "] possible matches in [" + exeTime.TotalMilliseconds + " ms]. Best match found had a [" + highestQuality + "%] quality rating.");
            }
            catch(Exception e)
            {
                Log.LogMsg("TrueSkill match maker encountered an error when searching for match candidates. " + e.Message);
            }

            return matches;
        }
Example #6
0
        public static void recalcMatches(List<Person> playerList, List<Match> matchList, Double startMu, Double startSigma, Double multiplier, UInt16 decay, UInt32 decayValue, DateTime lastDate, ProgressBar progress)
        {
            lastDate += new TimeSpan(23, 59, 59);

            Dictionary<String, Person> playerMap = new Dictionary<string, Person>();
            DateTime latestMatch = DateTime.MinValue;
            int matchTotal = matchList.Count;
            int counted = 0;
            if (progress != null)
            {
                progress.Value = 0;
                progress.Refresh();
            }

            foreach (Person person in playerList)
            {
                person.Mu = startMu;
                person.Sigma = startSigma;
                person.Wins = 0;
                person.Losses = 0;
                person.Draws = 0;
                person.Multiplier = multiplier;
                person.DecayDays = 0;
                person.DecayMonths = 0;

                playerMap.Add(person.Name, person);
            }

            foreach (Match match in matchList)
            {
                if (progress != null)
                {
                    counted++;
                    progress.Value = (counted * 100) / matchTotal;
                    progress.PerformStep();
                }

                if (match.Timestamp <= lastDate)
                {
                    Person p1 = playerMap[match.Player1];
                    Person p2 = playerMap[match.Player2];

                    if (decay > 0)
                    {
                        uint i = 0;
                        if (decay < 3)
                        {
                            while (p1.LastMatch.AddDays(i).CompareTo(match.Timestamp) < 0)
                            {
                                i++;
                            }
                            p1.DecayDays += i;
                            i = 0;
                            while (p2.LastMatch.AddDays(i).CompareTo(match.Timestamp) < 0)
                            {
                                i++;
                            }
                            p2.DecayDays += i;
                        }
                        else
                        {
                            i = 0;
                            while (p1.LastMatch.AddMonths((int)i).CompareTo(match.Timestamp) < 0)
                            {
                                i++;
                            }
                            p1.DecayMonths += i;
                            i = 0;
                            while (p2.LastMatch.AddMonths((int)i).CompareTo(match.Timestamp) < 0)
                            {
                                i++;
                            }
                            p2.DecayMonths += i;
                        }

                        switch (decay)
                        {
                            case 1:
                                while (p1.DecayDays > decayValue - 1)
                                {
                                    p1.decayScore(startSigma);
                                    p1.DecayDays -= decayValue;
                                }
                                while (p2.DecayDays > decayValue - 1)
                                {
                                    p2.decayScore(startSigma);
                                    p2.DecayDays -= decayValue;
                                }
                                break;
                            case 2:
                                while (p1.DecayDays > (7 * decayValue) - 1)
                                {
                                    p1.decayScore(startSigma);
                                    p1.DecayDays -= 7 * decayValue;
                                }
                                while (p2.DecayDays > (7 * decayValue) - 1)
                                {
                                    p2.decayScore(startSigma);
                                    p2.DecayDays -= 7 * decayValue;
                                }
                                break;
                            case 3:
                                while (p1.DecayMonths > decayValue - 1)
                                {
                                    p1.decayScore(startSigma);
                                    p1.DecayMonths -= decayValue;
                                }
                                while (p2.DecayMonths > decayValue - 1)
                                {
                                    p2.decayScore(startSigma);
                                    p2.DecayMonths -= decayValue;
                                }
                                break;
                            case 4:
                                while (p1.DecayMonths > (12 * decayValue) - 1)
                                {
                                    p1.decayScore(startSigma);
                                    p1.DecayMonths -= 12 * decayValue;
                                }
                                while (p2.DecayMonths > (12 * decayValue) - 1)
                                {
                                    p2.decayScore(startSigma);
                                    p2.DecayMonths -= 12 * decayValue;
                                }
                                break;
                        }
                    }

                    match.P1Score = p1.Score;
                    match.P2Score = p2.Score;

                    Player p1s = new Player(1);
                    Player p2s = new Player(2);
                    Rating p1r = new Rating(p1.Mu, p1.Sigma);
                    Rating p2r = new Rating(p2.Mu, p2.Sigma);
                    Team t1 = new Team(p1s, p1r);
                    Team t2 = new Team(p2s, p2r);

                    IDictionary<Player, Rating> newRatings = null;

                    if (match.Winner == 0)
                        newRatings = TrueSkillCalculator.CalculateNewRatings(GameInfo.DefaultGameInfo, Teams.Concat(t1, t2), 1, 1);
                    else if (match.Winner == 1)
                        newRatings = TrueSkillCalculator.CalculateNewRatings(GameInfo.DefaultGameInfo, Teams.Concat(t1, t2), 1, 2);
                    else if (match.Winner == 2)
                        newRatings = TrueSkillCalculator.CalculateNewRatings(GameInfo.DefaultGameInfo, Teams.Concat(t1, t2), 2, 1);

                    p1.Mu = newRatings[p1s].Mean;
                    p1.Sigma = newRatings[p1s].StandardDeviation;
                    p2.Mu = newRatings[p2s].Mean;
                    p2.Sigma = newRatings[p2s].StandardDeviation;

                    match.P1Score2 = p1.Score;
                    match.P2Score2 = p2.Score;

                    p1.LastMatch = match.Timestamp;
                    p2.LastMatch = match.Timestamp;
                    if (latestMatch < match.Timestamp)
                        latestMatch = match.Timestamp;

                    if (match.Winner == 0)
                    {
                        p1.Draws++;
                        p2.Draws++;
                    }
                    else if (match.Winner == 1)
                    {
                        p1.Wins++;
                        p2.Losses++;
                    }
                    else if (match.Winner == 2)
                    {
                        p1.Losses++;
                        p2.Wins++;
                    }
                }
                else break;
            }

            foreach (Person p in playerList)
            {
                if (decay > 0)
                {
                    uint i = 0;
                    while (p.LastMatch.AddDays(i).CompareTo(latestMatch) < 0)
                    {
                        i++;
                    }
                    p.DecayDays += i;
                    i = 0;
                    while (p.LastMatch.AddMonths((int)i).CompareTo(latestMatch) < 0)
                    {
                        i++;
                    }
                    p.DecayMonths += i;

                    switch (decay)
                    {
                        case 1:
                            while (p.DecayDays > 0)
                            {
                                p.decayScore(startSigma);
                                p.DecayDays--;
                            }
                            break;
                        case 2:
                            while (p.DecayDays > 6)
                            {
                                p.decayScore(startSigma);
                                p.DecayDays -= 7;
                            }
                            break;
                        case 3:
                            while (p.DecayMonths > 0)
                            {
                                p.decayScore(startSigma);
                                p.DecayMonths--;
                            }
                            break;
                        case 4:
                            while (p.DecayMonths > 11)
                            {
                                p.decayScore(startSigma);
                                p.DecayMonths -= 12;
                            }
                            break;
                    }
                }
            }
        }
Example #7
0
 /// <summary>
 /// Adds the <paramref name="player"/> to the team.
 /// </summary>
 /// <param name="player">The player to add.</param>
 /// <param name="rating">The rating of the <paramref name="player"/>.</param>
 /// <returns>The instance of the team (for chaining convenience).</returns>
 public Team <TPlayer> AddPlayer(TPlayer player, Rating rating)
 {
     _PlayerRatings[player] = rating;
     return(this);
 }
Example #8
0
 /// <summary>
 /// Constructs a <see cref="Team"/> and populates it with the specified <paramref name="player"/>.
 /// </summary>
 /// <param name="player">The player to add.</param>
 /// <param name="rating">The rating of the <paramref name="player"/>.</param>
 public Team(TPlayer player, Rating rating)
 {
     AddPlayer(player, rating);
 }
 //------------------------------------------------------------------------------
 // Helpers
 //------------------------------------------------------------------------------        
 
 private static void AssertRating(double expectedMean, double expectedStandardDeviation, Rating actual)
 {
     Assert.AreEqual(expectedMean, actual.Mean, ErrorTolerance);
     Assert.AreEqual(expectedStandardDeviation, actual.StandardDeviation, ErrorTolerance);
 }