public void TwoTeamTrueSkillCalculatorTests()
        {
            var calculator = new TwoTeamTrueSkillCalculator();

            TrueSkillCalculatorTests.TestAllTwoPlayerScenarios(calculator);
            TrueSkillCalculatorTests.TestAllTwoTeamScenarios(calculator);
        }
Example #2
0
        public void TwoTeamTrueSkillCalculatorTests()
        {
            var calculator = new TwoTeamTrueSkillCalculator();

            // This calculator supports up to two teams with many players each
            TrueSkillCalculatorTests.TestAllTwoPlayerScenarios(calculator);
            TrueSkillCalculatorTests.TestAllTwoTeamScenarios(calculator);
        }
Example #3
0
        public static void Main(string[] args)
        {
            var calculator = new TwoTeamTrueSkillCalculator();
            var gameInfo   = GameInfo.DefaultGameInfo;

            var ratings = new Dictionary <object, Rating>();
            var lines   = File.ReadLines(args[0]);

            foreach (var line in lines)
            {
                var      newline = line;
                string[] tokens  = line.Split(',');
                for (int i = 1; i <= 22; i++)
                {
                    if (!ratings.ContainsKey(tokens[i]))
                    {
                        ratings[tokens[i]] = gameInfo.DefaultRating;
                    }
                }
                var players = new List <Player>();
                var team1   = new Team();
                for (int i = 1; i <= 11; i++)
                {
                    var player = new Player(tokens[i]);
                    team1.AddPlayer(player, ratings[tokens[i]]);
                    players.Add(player);
                }
                var team2 = new Team();
                for (int i = 12; i <= 22; i++)
                {
                    var player = new Player(tokens[i]);
                    team2.AddPlayer(player, ratings[tokens[i]]);
                    players.Add(player);
                }
                var teams = Teams.Concat(team1, team2);
                var rank1 = 1;
                var rank2 = 1;
                if (tokens[23] == "-1")
                {
                    rank1 = 1;
                    rank2 = 2;
                }
                if (tokens[23] == "1")
                {
                    rank1 = 2;
                    rank2 = 1;
                }
                var newRatings = calculator.CalculateNewRatings(gameInfo, teams, rank1, rank2);
                foreach (var player in players)
                {
                    ratings[player.Id] = newRatings[player];
                    newline            = newline + "," + newRatings [player].Mean;
                }
                Console.WriteLine(newline);
            }
        }
Example #4
0
        static void Main(string[] args)
        {
            var redditText = args.Contains("reddit");
            var debug      = args.Contains("debug");
            var stageNames = args.FirstOrDefault(a => a.StartsWith("stage="))?.Split('=')[1].Split(',');

            var     scheduleText = GetUrl("schedule", "https://api.overwatchleague.com/schedule").Result;
            JObject response     = JObject.Parse(scheduleText);
            var     stages       = response["data"]["stages"].ToObject <StageData[]>();

            var results = from stage in stages
                          where stageNames == null || stageNames.Any(x => x.Equals(stage.Name, StringComparison.OrdinalIgnoreCase))
                          from match in stage.Matches
                          where match.State == "CONCLUDED"
                          orderby match.StartDateTS
                          let matchText = GetUrl("match." + match.Id, $"https://api.overwatchleague.com/match/{match.Id}").Result
                                          let matchResponse                         = JObject.Parse(matchText)
                                                                          let games = matchResponse["games"].ToObject <GameData[]>()
                                                                                      from game in games
                                                                                      where game.State == "CONCLUDED"
                                                                                      select new
            {
                stage,
                match,
                game
            };

            var calculator = new TwoTeamTrueSkillCalculator();

            var initialMean     = 500.0;
            var beta            = initialMean / 6.0;
            var drawProbability = 0.02;
            var dynamicsFactor  = initialMean / 300.0;
            var standardDev     = initialMean / 3.0;

            var gameInfo = new GameInfo(initialMean, standardDev, beta, dynamicsFactor, drawProbability);

            var ratings   = new Dictionary <int, Rating>();
            var playerDb  = new Dictionary <int, PlayerData>();
            var statDb    = new Dictionary <int, PlayerStat>();
            var teamDb    = new Dictionary <int, CompetitorData>();
            var gameCount = 0;
            var drawCount = 0;

            foreach (var r in results)
            {
                gameCount += 1;

                var team1 = new Team();
                var team2 = new Team();

                var team1Id = r.match.Competitors[0].Id;
                var team2Id = r.match.Competitors[1].Id;

                foreach (var team in r.match.Competitors)
                {
                    if (!teamDb.ContainsKey(team.Id))
                    {
                        teamDb[team.Id] = team;
                    }
                }

                foreach (var p in r.game.Players)
                {
                    if (!playerDb.ContainsKey(p.Player.Id))
                    {
                        playerDb[p.Player.Id] = p;
                        statDb[p.Player.Id]   = new PlayerStat();
                    }

                    if (!ratings.TryGetValue(p.Player.Id, out var rating))
                    {
                        ratings[p.Player.Id] = rating = gameInfo.DefaultRating;
                    }

                    var team = p.Team.Id == r.match.Competitors[0].Id
                        ? team1
                        : p.Team.Id == r.match.Competitors[1].Id
                            ? team2
                            : null;

                    if (team != null)
                    {
                        team.AddPlayer(new Player(p.Player.Id), rating);
                    }
                }

                Debug.Assert(team1.AsDictionary().Count == 6);
                Debug.Assert(team2.AsDictionary().Count == 6);

                void Update(Team t, Action <PlayerStat> a)
                {
                    foreach (var k in t.AsDictionary().Keys.Select(k => (int)k.Id))
                    {
                        a(statDb[k]);
                    }
                }

                var team1Points = 1;
                var team2Points = 1;

                var result = "";
                if (r.game.Points[0] < r.game.Points[1])
                {
                    team1Points = 2;
                    result      = $"WINNER {r.match.Competitors[1].Name}";
                    Update(team2, s => s.Win++);
                    Update(team1, s => s.Lose++);
                }
                else if (r.game.Points[1] < r.game.Points[0])
                {
                    team2Points = 2;
                    result      = $"WINNER {r.match.Competitors[0].Name}";
                    Update(team1, s => s.Win++);
                    Update(team2, s => s.Lose++);
                }
                else
                {
                    drawCount += 1;
                    result     = "DRAW";
                    Update(team1, s => s.Draw++);
                    Update(team2, s => s.Draw++);
                }

                var newRatings = calculator.CalculateNewRatings(gameInfo, Teams.Concat(team1, team2), team1Points, team2Points);

                if (debug)
                {
                    Console.WriteLine($"{r.match.Competitors[0].Name} vs {r.match.Competitors[1].Name} [{r.game.Points[0]} to {r.game.Points[1]}] {result}");
                }

                foreach (var rating in newRatings)
                {
                    var pid       = (int)rating.Key.Id;
                    var player    = playerDb[pid];
                    var team      = teamDb[player.Team.Id];
                    var oldRating = ratings[pid];
                    if (debug)
                    {
                        Console.WriteLine($"  {team.Name} {player.Player.Name} : {oldRating.ConservativeRating} to {rating.Value.ConservativeRating}");
                    }

                    ratings[pid] = rating.Value;
                }
            }

            if (debug)
            {
                Console.WriteLine("Finished");
            }

            var rank = 0;

            IEnumerable <KeyValuePair <int, Rating> > ratingsList = ratings;

            var playerResults = from kv in ratingsList
                                let p                                         = playerDb[kv.Key]
                                                        let t                 = teamDb[p.Team.Id]
                                                                        let s = statDb[kv.Key]
                                                                                select new
            {
                Team   = t.Name,
                Player = p.Player.Name,
                Wins   = s.Win,
                Loses  = s.Lose,
                Draws  = s.Draw,
                Rating = kv.Value.ConservativeRating,
                Detail = kv.Value
            };

            if (redditText)
            {
                Console.WriteLine("Rank|Team|Player|Wins|Loses|Draws|Rating|Rating Detail");
                Console.WriteLine(":--|:--|:--|:-:|:-:|:-:|:-:|:--");
            }

            foreach (var r in playerResults.OrderByDescending(x => x.Rating))
            {
                rank += 1;
                if (redditText)
                {
                    Console.WriteLine($"{rank}|{r.Team}|{r.Player}|{r.Wins}|{r.Loses}|{r.Draws}|{r.Rating:f}|{r.Detail}");
                }
                else
                {
                    Console.WriteLine($"{rank,3} {r.Team,22} {r.Player,11} [{r.Wins,2}-{r.Loses,2}-{r.Draws,2}] {r.Rating,7:f} ({r.Detail})");
                }
            }
        }