public override CompetitorRanks GenerateResult(int winsToClinchMatch, Competitor competitorA, Competitor competitorB) { var competitorAWins = 0; var competitorBWins = 0; while (competitorAWins < winsToClinchMatch && competitorBWins < winsToClinchMatch) { var randomRatio = Convert.ToDouble(RandomNumberGenerator.Next(0, 101)) / Convert.ToDouble(100); var ratingRatio = Convert.ToDouble(competitorA.TheoreticalRating) / (Convert.ToDouble(competitorA.TheoreticalRating) + Convert.ToDouble(competitorB.TheoreticalRating)); if (randomRatio < ratingRatio) competitorAWins++; else competitorBWins++; } var ranks = new CompetitorRanks(); if (competitorAWins > competitorBWins) { ranks.Add(competitorA, 1); ranks.Add(competitorB, 2); } else { ranks.Add(competitorB, 1); ranks.Add(competitorA, 2); } return ranks; }
public override CompetitorRanks GenerateResult(MatchStrategies.MatchStrategy matchStrategy, List<Competitor> competitors) { if (competitors.Count == 1) { CompetitorRanks singleRank = new CompetitorRanks(); singleRank.Add(competitors[0], 1); return singleRank; } List<Match> matches = new List<Match>(); for (int i = 0; i < Convert.ToInt32(Math.Round(_numberOfRounds.Value)); i++) { matches.AddRange(GenerateSingleRoundResult(matchStrategy, competitors, 1.0)); } // now run the partial round, if there are any double fractionOfPartialRound = (_numberOfRounds.Value - Math.Round(_numberOfRounds.Value)); if (fractionOfPartialRound > 0.0) matches.AddRange(GenerateSingleRoundResult(matchStrategy, competitors, fractionOfPartialRound)); Matches = matches; return GetTournamentRoundRanks(); }
private void BreakTiesByRoundRobinRanks(CompetitorRanks roundRobinRanks, CompetitorRanks finalRanks) { IEnumerable<KeyValuePair<Competitor, int>> orderedRanks = finalRanks .OrderBy(x => x.Value) .ThenBy(x => roundRobinRanks[x.Key]); int rank = 1; foreach (KeyValuePair<Competitor, int> orderedRank in orderedRanks) { finalRanks[orderedRank.Key] = rank++; } }
private CompetitorRanks GetTournamentRoundRanks() { if (Matches.Count != 4) throw new ArgumentException("Collection count must be 4.", "matches"); // assumption: the matches are in this order: matches 1 and 2 are semis, // match 3 is petit finals, match 4 is finals CompetitorRanks ranks = new CompetitorRanks(); ranks.Add(Matches[3].Winner, 1); ranks.Add(Matches[3].Loser, 2); ranks.Add(Matches[2].Winner, 3); ranks.Add(Matches[2].Loser, 4); return ranks; }
public override CompetitorRanks GenerateResult(int winsToClinchMatch, Competitor competitorA, Competitor competitorB) { var ranks = new CompetitorRanks(); if (competitorA.TheoreticalRating > competitorB.TheoreticalRating) { ranks.Add(competitorA, 1); ranks.Add(competitorB, 2); } else { ranks.Add(competitorB, 1); ranks.Add(competitorA, 2); } return ranks; }
public override CompetitorRanks GenerateResult(int tournamentRunSequence, MatchStrategies.MatchStrategy matchStrategy, List<Competitor> competitors) { // round robin to seed the semifinals TournamentRound rrTR = new TournamentRound(new RrTRS(_numberOfRoundRobinRounds), matchStrategy); CompetitorRanks rrRanks = rrTR.Run(competitors); // run single semifinal knockout round TournamentRound koTR = new TournamentRound(new KoTRS(_winsToClinchKnockoutMatch), matchStrategy); CompetitorRanks koRanks = koTR.Run(rrRanks.OrderBy(x => x.Value).Select(x => x.Key).ToList<Competitor>()); // rank the results first by how they did in the semifinals, then by how they did in the round robin var untypedRanks = koRanks.OrderBy(x => x.Value).ThenBy(x => rrRanks[x.Key]); CompetitorRanks ranks = new CompetitorRanks(); int i = 1; foreach (KeyValuePair<Competitor, int> untypedRank in untypedRanks) { ranks.Add(untypedRank.Key, i++); } return ranks; }
public void BreakTiesTest() { List<Competitor> competitors = Helpers.CompetitorListHelper.GetStandardCompetitors(8); CompetitorRanks roundRobinRanks = new CompetitorRanks(); CompetitorRanks finalRanks = new CompetitorRanks(); int i = 1; foreach (Competitor competitor in competitors) { roundRobinRanks.Add(competitor, i); if (i < 5) finalRanks.Add(competitor, 5); else if (i < 7) finalRanks.Add(competitor, 3); else finalRanks.Add(competitor, 9-i); i++; } RrKoSfFiTS_Accessor target = new RrKoSfFiTS_Accessor(); target.BreakTiesByRoundRobinRanks(roundRobinRanks, finalRanks); var finalRankArray = finalRanks .Select(x => new { x.Key.Name, x.Value }) .OrderBy(x => x.Value) .ToArray(); Assert.AreEqual("H", finalRankArray[0].Name); Assert.AreEqual("G", finalRankArray[1].Name); Assert.AreEqual("E", finalRankArray[2].Name); Assert.AreEqual("F", finalRankArray[3].Name); Assert.AreEqual("A", finalRankArray[4].Name); Assert.AreEqual("B", finalRankArray[5].Name); Assert.AreEqual("C", finalRankArray[6].Name); Assert.AreEqual("D", finalRankArray[7].Name); }
public override CompetitorRanks GenerateResult(int tournamentRunSequence, MatchStrategies.MatchStrategy matchStrategy, List<Competitor> competitors) { if (competitors.Count % 2 != 0) throw new ArgumentException("Collection count must be even.", "competitors"); // round robin to seed the semifinals TournamentRound rrTR = new TournamentRound(new RrTRS(_numberOfRoundRobinRounds), matchStrategy); CompetitorRanks rrRanks = rrTR.Run(competitors); List<Competitor> rankedCompetitors = rrRanks.OrderBy(x => x.Value).Select(x => x.Key).ToList<Competitor>(); CompetitorRanks ranks = new CompetitorRanks(); // run single knockout round for nearby competitors for (int i = 0; i < competitors.Count / 2; i++) { TournamentRound koTR = new TournamentRound(new KoTRS(_winsToClinchKnockoutMatch), matchStrategy); CompetitorRanks koRanks = koTR.Run(new List<Competitor>() { rankedCompetitors[i * 2], rankedCompetitors[(i * 2) + 1] }); ranks.Add(koRanks.First(x => x.Value == 1).Key, (i * 2) + 1); ranks.Add(koRanks.First(x => x.Value == 2).Key, (i * 2) + 2); } return ranks; }
private static bool BreakTieGroupByHeadToHeadMatchPoints(CompetitorRanks tieGroupRanks, List<Match> matches, int firstMatchesToExclude) { bool hasChangedRanks = false; // verify there are ties to break if (tieGroupRanks.Count() < 2) throw new ArgumentException("No tied competitors."); // verify all members of the tie group have the same number of points int tiedRank = 0; foreach (KeyValuePair<Competitor, int> tieMember in tieGroupRanks) { if (tiedRank != 0 && tiedRank != tieMember.Value) throw new ArgumentException("This group contains members who are not tied with the others."); tiedRank = tieMember.Value; } // compare the points in the head-to-head matches first // find all the matches where they go head to head List<Match> headToHeadMatches = matches .Join(tieGroupRanks, match => match.Winner, tieMember => tieMember.Key, (match, tiedCompetitor) => match) .Join(tieGroupRanks, match => match.Loser, tieMember => tieMember.Key, (match, tiedCompetitor) => match) .OrderBy(x => x.RunSequence) .ToList<Match>(); for (int i = 0; i < firstMatchesToExclude; i++) { if (headToHeadMatches.Count > 0) headToHeadMatches.RemoveAt(0); } CompetitorPoints tiedCompetitorPoints = AccumulateMatchPoints(headToHeadMatches); // assign the correct competitor ranks, leaving ties where they exist double lastPointTotal = tiedCompetitorPoints.OrderByDescending(x => x.Value).First().Value; foreach (KeyValuePair<Competitor, double> tiedCompetitorPoint in tiedCompetitorPoints.OrderByDescending(x => x.Value)) { if (tiedCompetitorPoint.Value < lastPointTotal) { tiedRank++; hasChangedRanks = true; } tieGroupRanks[tiedCompetitorPoint.Key] = tiedRank; lastPointTotal = tiedCompetitorPoint.Value; } return hasChangedRanks; }
private static bool BreakTies(CompetitorRanks tournamentRoundRanks, List<Match> matches) { bool hasChangedRanks = false; List<int> distinctTournamentRoundRanks = tournamentRoundRanks.Values.Distinct().ToList<int>(); foreach (int tiedRank in distinctTournamentRoundRanks) { // find all the competitors with the same points CompetitorRanks tieGroupRanks = new CompetitorRanks(tournamentRoundRanks .Where(x => x.Value == tiedRank) .ToDictionary(x => x.Key, x => x.Value)); if (tieGroupRanks.Count() > 1) { if (BreakTieGroupByHeadToHeadMatchPoints(tieGroupRanks, matches, 0)) hasChangedRanks = true; else if (BreakTieGroupByHeadToHeadMatchPoints(tieGroupRanks, matches, 1)) hasChangedRanks = true; } // add the tie resolution results back into the overall ranks foreach (KeyValuePair<Competitor, int> tieGroupRank in tieGroupRanks) { tournamentRoundRanks[tieGroupRank.Key] = tieGroupRank.Value; } } return hasChangedRanks; }
public void BreakTiesTest_NonRandomMatches() { var competitors = Helpers.CompetitorListHelper.GetStandardCompetitors(6); var matches = new List<Match> { (Match)new Match_Accessor { Winner = competitors[0], Loser = competitors[1], RunSequence = 1 }.Target, (Match)new Match_Accessor { Winner = competitors[0], Loser = competitors[2], RunSequence = 2 }.Target, (Match)new Match_Accessor { Winner = competitors[0], Loser = competitors[4], RunSequence = 3 }.Target, (Match)new Match_Accessor { Winner = competitors[0], Loser = competitors[5], RunSequence = 4 }.Target, (Match)new Match_Accessor { Winner = competitors[1], Loser = competitors[2], RunSequence = 5 }.Target, (Match)new Match_Accessor { Winner = competitors[1], Loser = competitors[3], RunSequence = 6 }.Target, (Match)new Match_Accessor { Winner = competitors[1], Loser = competitors[4], RunSequence = 7 }.Target, (Match)new Match_Accessor { Winner = competitors[1], Loser = competitors[5], RunSequence = 8 }.Target, (Match)new Match_Accessor { Winner = competitors[2], Loser = competitors[0], RunSequence = 9 }.Target, (Match)new Match_Accessor { Winner = competitors[2], Loser = competitors[3], RunSequence = 10 }.Target, (Match)new Match_Accessor { Winner = competitors[2], Loser = competitors[4], RunSequence = 11 }.Target, (Match)new Match_Accessor { Winner = competitors[2], Loser = competitors[5], RunSequence = 12 }.Target, (Match)new Match_Accessor { Winner = competitors[3], Loser = competitors[4], RunSequence = 13 }.Target, (Match) new Match_Accessor { Winner = competitors[4], Loser = competitors[5], RunSequence = 14 }.Target, (Match)new Match_Accessor { Winner = competitors[5], Loser = competitors[3], RunSequence = 15 }.Target }; var tournamentRoundRanks = new CompetitorRanks { { competitors[0], 1 }, { competitors[1], 2 }, { competitors[2], 2 }, { competitors[3], 4 }, { competitors[4], 4 }, { competitors[5], 4 } }; while (RrTRS_Accessor.BreakTies(tournamentRoundRanks, matches)) { }; Assert.AreEqual(1, tournamentRoundRanks[competitors[0]]); Assert.AreEqual(2, tournamentRoundRanks[competitors[1]]); Assert.AreEqual(3, tournamentRoundRanks[competitors[2]]); Assert.AreEqual(4, tournamentRoundRanks[competitors[4]]); Assert.AreEqual(5, tournamentRoundRanks[competitors[5]]); Assert.AreEqual(6, tournamentRoundRanks[competitors[3]]); }
public void BreakTiesTest_ThreeWayTie() { var competitors = new List<Competitor> { new Competitor { Name = "A" }, new Competitor { Name = "B" }, new Competitor { Name = "C" } }; var matches = new List<Match>(); var matchAccessor = new Match_Accessor { Winner = competitors[0], Loser = competitors[1], RunSequence = 1 }; matches.Add((Match)matchAccessor.Target); matchAccessor = new Match_Accessor { Winner = competitors[1], Loser = competitors[2], RunSequence = 2 }; matches.Add((Match)matchAccessor.Target); matchAccessor = new Match_Accessor { Winner = competitors[2], Loser = competitors[0], RunSequence = 3 }; matches.Add((Match)matchAccessor.Target); var tournamentRoundRanks = new CompetitorRanks { { competitors[0], 1 }, { competitors[1], 1 }, { competitors[2], 1 } }; while (RrTRS_Accessor.BreakTies(tournamentRoundRanks, matches)) { }; Assert.IsTrue(tournamentRoundRanks[competitors[1]] < tournamentRoundRanks[competitors[2]]); Assert.IsTrue(tournamentRoundRanks[competitors[2]] < tournamentRoundRanks[competitors[0]]); }
public void BreakTiesTest() { var competitors = Helpers.CompetitorListHelper.GetStandardCompetitors(6); var round = new TournamentRound(new RrTRS(), new SimpleRandomMs()); round.Run(competitors); var tournamentRoundRanks = new CompetitorRanks { { competitors[0], 1 }, { competitors[1], 2 }, { competitors[2], 2 }, { competitors[3], 4 }, { competitors[4], 4 }, { competitors[5], 4 } }; RrTRS_Accessor.BreakTies(tournamentRoundRanks, round.Matches); Assert.IsTrue(tournamentRoundRanks[competitors[0]] < tournamentRoundRanks[competitors[1]]); Assert.IsTrue(tournamentRoundRanks[competitors[0]] < tournamentRoundRanks[competitors[2]]); Assert.IsTrue(tournamentRoundRanks[competitors[1]] < tournamentRoundRanks[competitors[3]]); Assert.IsTrue(tournamentRoundRanks[competitors[1]] < tournamentRoundRanks[competitors[4]]); Assert.IsTrue(tournamentRoundRanks[competitors[1]] < tournamentRoundRanks[competitors[5]]); Assert.IsTrue(tournamentRoundRanks[competitors[2]] < tournamentRoundRanks[competitors[3]]); Assert.IsTrue(tournamentRoundRanks[competitors[2]] < tournamentRoundRanks[competitors[4]]); Assert.IsTrue(tournamentRoundRanks[competitors[2]] < tournamentRoundRanks[competitors[5]]); }
public override CompetitorRanks GenerateResult(int tournamentRunSequence, MatchStrategies.MatchStrategy matchStrategy, List<Competitor> competitors) { if (competitors.Count != 8) throw new ArgumentException("Collection count must be 8.", "competitors"); // round robin to seed 2 separate round robins TournamentRound rr1 = new TournamentRound(new RrTRS(_numberOfRr1Rounds), matchStrategy); CompetitorRanks rr1Ranks = rr1.Run(competitors); List<Competitor> rrACompetitors = rr1Ranks .OrderBy(x => x.Value) .Take(4) .Select(x => x.Key) .ToList<Competitor>(); List<Competitor> rrBCompetitors = rr1Ranks .OrderBy(x => x.Value) .Skip(4) .Take(4) .Select(x => x.Key) .ToList<Competitor>(); // round robin to determine 1, 2, 3 TournamentRound rrA = new TournamentRound(new RrTRS(_numberOfRr2Rounds), matchStrategy); CompetitorRanks rrARanks = rrA.Run(rrACompetitors); // round robin to determine 4 TournamentRound rrB = new TournamentRound(new RrTRS(_numberOfRr2Rounds), matchStrategy); CompetitorRanks rrBRanks = rrB.Run(rrBCompetitors); // finals List<Competitor> finalsCompetitors = rrARanks .OrderBy(x => x.Value) .Take(2) .Select(x => x.Key) .ToList<Competitor>(); TournamentRound finals = new TournamentRound(new KoTRS(_winsToClinchFinalMatch), matchStrategy); CompetitorRanks finalsRanks = finals.Run(finalsCompetitors); // petit finals List<Competitor> petitFinalsCompetitors = rrARanks .OrderBy(x => x.Value) .Skip(2) .Take(1) .Select(x => x.Key) .ToList<Competitor>(); Competitor rrBWinner = rrBRanks .OrderBy(x => x.Value) .Take(1) .Select(x => x.Key) .First(); petitFinalsCompetitors.Add(rrBWinner); TournamentRound petitFinals = new TournamentRound(new KoTRS(_winsToClinchPetitFinalMatch), matchStrategy); CompetitorRanks petitFinalsRanks = petitFinals.Run(petitFinalsCompetitors); // consolation round List<Competitor> consolationCompetitors = rrBRanks .OrderBy(x => x.Value) .Skip(1) .Select(x => x.Key) .ToList<Competitor>(); Competitor rrALoser = rrARanks .OrderBy(x => x.Value) .Skip(3) .Take(1) .Select(x => x.Key) .First(); consolationCompetitors.Add(rrALoser); TournamentRound consolationRound = new TournamentRound(new RrTRS(_numberOfRr3Rounds), matchStrategy); CompetitorRanks consolationRanks = consolationRound.Run(consolationCompetitors); CompetitorRanks ranks = new CompetitorRanks(); int i = 1; foreach (var rank in finalsRanks.OrderBy(x => x.Value)) { ranks.Add(rank.Key, i++); } foreach (var rank in petitFinalsRanks.OrderBy(x => x.Value)) { ranks.Add(rank.Key, i++); } foreach (var rank in consolationRanks.OrderBy(x => x.Value)) { ranks.Add(rank.Key, i++); } return ranks; }
public void Run(List<Competitor> competitors) { RunSequence = ++_sequence; _competitors = competitors; _competitorTournamentRanks = _tournamentStrategy.GenerateResult(RunSequence.Value, _matchStrategy, competitors); AssignTournamentRanksToCompetitorObjects(); }