public void TwoTeamTrueSkillCalculatorTests() { var calculator = new TwoTeamTrueSkillCalculator(); TrueSkillCalculatorTests.TestAllTwoPlayerScenarios(calculator); TrueSkillCalculatorTests.TestAllTwoTeamScenarios(calculator); }
public void TwoTeamTrueSkillCalculatorTests() { var calculator = new TwoTeamTrueSkillCalculator(); // This calculator supports up to two teams with many players each TrueSkillCalculatorTests.TestAllTwoPlayerScenarios(calculator); TrueSkillCalculatorTests.TestAllTwoTeamScenarios(calculator); }
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); } }
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})"); } } }