/// <summary> /// This creates a best-out-of-three match for the Finale and a solo match for the Bronze Finale. /// </summary> public static void CreateFinaleStructure() { // Finale for (int p = 0; p < 3; p++) { var match = new Match {Phase = Phase.Finale, Priority = p}; Mongo.Matches.Save(match); } // Losers' finale var losers = new Match {Phase = Phase.LoserFinale}; Mongo.Matches.Save(losers); // Bronze finale var bronze = new Match { Phase = Phase.BronzeFinale }; Mongo.Matches.Save(bronze); }
/// <summary> /// This method creates the pool structure and adds it to the database. /// Teams are divided into groups of 4, based on their MMR. /// /// Only works when there are 2^N with N >= 4 teams. /// </summary> public static void CreatePoolStructure() { // Get competing teams var validTeams = Mongo.Teams.FindAll() .OrderByDescending(x => x.AmountOfRuStudents) .ThenBy(x => x.Participants.Sum(y => y.RegisterTime.Ticks)) .Take(32) .OrderByDescending(x => x.MMR).ToList(); // For each pool for (int i = 0; i < validTeams.Count() / 4; i++) { Team[] teams = {validTeams[i], validTeams[validTeams.Count()/2 - i - 1], validTeams[validTeams.Count()/2 + i], validTeams[(int)(validTeams.Count()*0.75) + i]}; List<int>[] availabilityLists = { new List<int> { 0, 1, 2 }, new List<int> { 0, 1, 2 }, new List<int> { 0, 1, 2 }, new List<int> { 0, 1, 2 } }; // For each team for (int j = 0; j < 4; j++) { // Set pool in team objects teams[j].Pool = i; Mongo.Teams.Save(teams[j]); // For each team below team j for (int k = j + 1; k < 4; k++) { // Determine priority var intersect = availabilityLists[j].Intersect(availabilityLists[k]); var p = intersect.Min(); // Remove chosen priority from team availability lists availabilityLists[j].Remove(p); availabilityLists[k].Remove(p); // Determine sides (lowest MMR = blue) var blue = teams[j].MMR < teams[k].MMR ? teams[j].Id : teams[k].Id; var purple = teams[j].MMR >= teams[k].MMR ? teams[j].Id : teams[k].Id; // Create match and add to database var match = new Match { BlueTeamId = blue, PurpleTeamId = purple, Phase = Phase.Pool, Priority = p }; Mongo.Matches.Save(match); } } } }
/// <summary> /// Checks whether the match that was just played has consequences for the structure of the rest of the tournament. If so, push these consequences into the database. /// </summary> /// <param name="finishedMatch">The match that was just finished.</param> private static void NewMatch(Match finishedMatch) { var finishedMatchWinner = finishedMatch.Winner; if (finishedMatch.Phase == Phase.Pool) { var pool = finishedMatch.BlueTeam.Pool; // Check whether the pool is finished if (PoolFinished(pool, Mongo.Matches)) { // Pool is finished // To create brackets, one of the other pools also needs to be finished. // Pools are coupled as follows: 1,2 | 3,4 | etc. int otherPool; // If this is an even pool if (pool%2 == 0) otherPool = pool + 1; else otherPool = pool - 1; // If coupled pool is also finished if (PoolFinished(otherPool, Mongo.Matches)) { // Get ranking for pools var poolARanking = GetPoolRanking(pool, Mongo.Teams); var poolBRanking = GetPoolRanking(otherPool, Mongo.Teams); // We can now create the brackets for these pools // Winner bracket var match = new Match {BlueTeamId = poolARanking[0].Id, PurpleTeamId = poolBRanking[1].Id, Phase = Phase.WinnerBracket, Priority = Math.Min(pool, otherPool)}; var match2 = new Match { BlueTeamId = poolBRanking[0].Id, PurpleTeamId = poolARanking[1].Id, Phase = Phase.WinnerBracket, Priority = Math.Max(pool, otherPool)}; Mongo.Matches.Save(match); Mongo.Matches.Save(match2); // Loser bracket var match3 = new Match { BlueTeamId = poolARanking[2].Id, PurpleTeamId = poolBRanking[3].Id, Phase = Phase.LoserBracket, Priority = Math.Min(pool, otherPool) }; var match4 = new Match { BlueTeamId = poolBRanking[2].Id, PurpleTeamId = poolARanking[3].Id, Phase = Phase.LoserBracket, Priority = Math.Max(pool, otherPool) }; Mongo.Matches.Save(match3); Mongo.Matches.Save(match4); // Set the teams to the correct phase poolARanking[0].Phase = Phase.WinnerBracket; poolARanking[0].OnHold = false; poolARanking[1].Phase = Phase.WinnerBracket; poolARanking[1].OnHold = false; poolARanking[2].Phase = Phase.LoserBracket; poolARanking[2].OnHold = false; poolARanking[3].Phase = Phase.LoserBracket; poolARanking[3].OnHold = false; poolBRanking[0].Phase = Phase.WinnerBracket; poolBRanking[0].OnHold = false; poolBRanking[1].Phase = Phase.WinnerBracket; poolBRanking[1].OnHold = false; poolBRanking[2].Phase = Phase.LoserBracket; poolBRanking[2].OnHold = false; poolBRanking[3].Phase = Phase.LoserBracket; poolBRanking[3].OnHold = false; // Save all to database Mongo.Teams.Save(poolARanking[0]); Mongo.Teams.Save(poolARanking[1]); Mongo.Teams.Save(poolARanking[2]); Mongo.Teams.Save(poolARanking[3]); Mongo.Teams.Save(poolBRanking[0]); Mongo.Teams.Save(poolBRanking[1]); Mongo.Teams.Save(poolBRanking[2]); Mongo.Teams.Save(poolBRanking[3]); } else { // Set all teams in pool to Hold var teams = Mongo.Teams.Find(Query<Team>.Where(x => x.Pool == pool)); foreach (var t in teams) { t.OnHold = true; Mongo.Teams.Save(t); } } } // If this was the final match in the pool for this team else if (finishedMatch.Priority == 2) { // Set match teams on hold since they don't have any matches left Team[] teams = {finishedMatch.BlueTeam, finishedMatch.PurpleTeam}; foreach (var t in teams) { t.OnHold = true; Mongo.Teams.Save(t); } } } else if (finishedMatch.Phase == Phase.WinnerBracket || finishedMatch.Phase == Phase.LoserBracket) { // First phase if (finishedMatch.Priority <= 7) { int[] couples = { 4, 5, 6, 7, 0, 1, 2, 3 }; // Check if other match is also finished var otherPrio = couples[finishedMatch.Priority]; var matchFinished = Mongo.Matches.Find( Query<Match>.Where( x => x.Finished && x.Phase == finishedMatch.Phase && x.Priority == otherPrio)); // It's finished, add new bracket match if (matchFinished.Count() == 1) { var otherTeam = matchFinished.First().Winner; var match = new Match { BlueTeamId = finishedMatch.WinnerId, PurpleTeamId = otherTeam.Id, Phase = finishedMatch.Phase, Priority = Math.Min(finishedMatch.Priority, otherPrio) + 8 }; Mongo.Matches.Save(match); // Set OnHold = false for teams finishedMatchWinner.OnHold = false; otherTeam.OnHold = false; Mongo.Teams.Save(finishedMatch.Winner); Mongo.Teams.Save(otherTeam); } else { // Not finished, put team on hold finishedMatchWinner.OnHold = true; Mongo.Teams.Save(finishedMatchWinner); } } // Second phase else if (finishedMatch.Priority >= 8 && finishedMatch.Priority <= 11) { var couples = new Dictionary<int, int> { {8, 10}, {10, 8}, {9, 11}, {11, 9} }; // Check if other match is also finished var otherPrio = couples[finishedMatch.Priority]; var matchFinished = Mongo.Matches.Find( Query<Match>.Where( x => x.Finished && x.Phase == finishedMatch.Phase && x.Priority == otherPrio)); // It's finished, add new bracket match if (matchFinished.Count() == 1) { var otherTeam = matchFinished.First().Winner; var match = new Match { BlueTeamId = finishedMatch.WinnerId, PurpleTeamId = matchFinished.First().WinnerId, Phase = finishedMatch.Phase, Priority = Math.Min(finishedMatch.Priority, otherPrio) + 4 }; Mongo.Matches.Save(match); // Set OnHold = false for teams finishedMatchWinner.OnHold = false; otherTeam.OnHold = false; Mongo.Teams.Save(finishedMatch.Winner); Mongo.Teams.Save(otherTeam); } else { // Not finished, put team on hold finishedMatchWinner.OnHold = true; Mongo.Teams.Save(finishedMatchWinner); } } // Third phase, don't do this for loser bracket else if ((finishedMatch.Priority == 12 || finishedMatch.Priority == 13) && finishedMatch.Phase == Phase.WinnerBracket) { // Check if other match is also finished var otherPrio = finishedMatch.Priority == 12 ? 13 : 12; var matchFinished = Mongo.Matches.Find( Query<Match>.Where( x => x.Finished && x.Phase == Phase.WinnerBracket && x.Priority == otherPrio)); // It's finished, set finale match if (matchFinished.Count() == 1) { var match = Mongo.Matches.Find(Query<Match>.Where(x => x.Phase == Phase.Finale && x.Priority == 0)).First(); match.BlueTeamId = finishedMatch.WinnerId; match.PurpleTeamId = matchFinished.First().WinnerId; Mongo.Matches.Save(match); // Switch sides match = Mongo.Matches.Find(Query<Match>.Where(x => x.Phase == Phase.Finale && x.Priority == 1)).First(); match.BlueTeamId = matchFinished.First().WinnerId; match.PurpleTeamId = finishedMatch.WinnerId; Mongo.Matches.Save(match); // Switch sides again match = Mongo.Matches.Find(Query<Match>.Where(x => x.Phase == Phase.Finale && x.Priority == 2)).First(); match.BlueTeamId = finishedMatch.WinnerId; match.PurpleTeamId = matchFinished.First().WinnerId; Mongo.Matches.Save(match); // Set team phases var blueTeam = match.BlueTeam; var purpleTeam = match.PurpleTeam; blueTeam.Phase = Phase.Finale; blueTeam.OnHold = false; purpleTeam.Phase = Phase.Finale; purpleTeam.OnHold = false; // Save all to database Mongo.Teams.Save(blueTeam); Mongo.Teams.Save(purpleTeam); // Also set bronze finale match match = Mongo.Matches.Find(Query<Match>.Where(x => x.Phase == Phase.BronzeFinale)).First(); match.BlueTeamId = finishedMatch.BlueTeamId == finishedMatch.WinnerId ? finishedMatch.PurpleTeamId : finishedMatch.BlueTeamId; match.PurpleTeamId = matchFinished.First().BlueTeamId == matchFinished.First().WinnerId ? matchFinished.First().PurpleTeamId : matchFinished.First().BlueTeamId; Mongo.Matches.Save(match); // And set their teams to the correct phase blueTeam = match.BlueTeam; purpleTeam = match.PurpleTeam; blueTeam.Phase = Phase.BronzeFinale; blueTeam.OnHold = false; purpleTeam.Phase = Phase.BronzeFinale; purpleTeam.OnHold = false; // Save all to database Mongo.Teams.Save(blueTeam); Mongo.Teams.Save(purpleTeam); } else { // Not finished, put team on hold finishedMatchWinner.OnHold = true; var loser = finishedMatchWinner.Id == finishedMatch.BlueTeamId ? finishedMatch.PurpleTeam : finishedMatch.BlueTeam; loser.OnHold = true; Mongo.Teams.Save(finishedMatchWinner); Mongo.Teams.Save(loser); } } // Set up loser finale else if ((finishedMatch.Priority == 12 || finishedMatch.Priority == 13) && finishedMatch.Phase == Phase.LoserBracket) { // Check if other match is also finished var otherPrio = finishedMatch.Priority == 12 ? 13 : 12; var matchFinished = Mongo.Matches.Find( Query<Match>.Where( x => x.Finished && x.Phase == Phase.LoserBracket && x.Priority == otherPrio)); // It's finished, set loser finale match if (matchFinished.Count() == 1) { var match = Mongo.Matches.Find(Query<Match>.Where(x => x.Phase == Phase.LoserFinale && x.Priority == 0)).First(); match.BlueTeamId = finishedMatch.WinnerId; match.PurpleTeamId = matchFinished.First().WinnerId; Mongo.Matches.Save(match); // Set team phases var blueTeam = match.BlueTeam; var purpleTeam = match.PurpleTeam; blueTeam.Phase = Phase.LoserFinale; blueTeam.OnHold = false; purpleTeam.Phase = Phase.LoserFinale; purpleTeam.OnHold = false; // Save all to database Mongo.Teams.Save(blueTeam); Mongo.Teams.Save(purpleTeam); } else { // Not finished, put team on hold finishedMatchWinner.OnHold = true; var loser = finishedMatchWinner.Id == finishedMatch.BlueTeamId ? finishedMatch.PurpleTeam : finishedMatch.BlueTeam; loser.OnHold = true; Mongo.Teams.Save(finishedMatchWinner); Mongo.Teams.Save(loser); } } } else if (finishedMatch.Phase == Phase.BronzeFinale) { // Add third and fourth place to database var winner = finishedMatch.Winner; var loser = finishedMatch.BlueTeamId == winner.Id ? finishedMatch.PurpleTeam : finishedMatch.BlueTeam; winner.FinalRanking = 3; loser.FinalRanking = 4; Mongo.Teams.Save(winner); Mongo.Teams.Save(loser); } else if (finishedMatch.Phase == Phase.Finale) { if (finishedMatch.Priority == 2) { // We have played all three matches, add final rankings to database var winsBlueTeam = Mongo.Matches.Count(Query<Match>.Where(x => x.Phase == Phase.Finale && x.WinnerId == finishedMatch.BlueTeamId)); var winner = winsBlueTeam >= 2 ? finishedMatch.BlueTeam : finishedMatch.PurpleTeam; var loser = winner.Id == finishedMatch.BlueTeamId ? finishedMatch.PurpleTeam : finishedMatch.BlueTeam; winner.FinalRanking = 1; loser.FinalRanking = 2; Mongo.Teams.Save(winner); Mongo.Teams.Save(loser); } else if (finishedMatch.Priority == 1) { // We have played two matches so far var winsBlueTeam = Mongo.Matches.Count(Query<Match>.Where(x => x.Phase == Phase.Finale && x.WinnerId == finishedMatch.BlueTeamId)); if (winsBlueTeam == 0 || winsBlueTeam == 2) { // It's already decided, scratch third match Mongo.Matches.Remove(Query<Match>.Where(x => x.Phase == Phase.Finale && x.Priority == 2)); var winner = finishedMatch.Winner; // winner is always also the winner of the previous match var loser = winner.Id == finishedMatch.BlueTeamId ? finishedMatch.PurpleTeam : finishedMatch.BlueTeam; winner.FinalRanking = 1; loser.FinalRanking = 2; Mongo.Teams.Save(winner); Mongo.Teams.Save(loser); } } else if (finishedMatch.Priority == 0) { // This was the first match, do nothing } } }