public override CompetitorRanks GenerateResult(TournamentSimulation.MatchStrategies.MatchStrategy matchStrategy, List<Competitor> competitors)
        {
            TournamentRoundStrategy tournamentRoundStrategy = new KoTRS(_winsToClinchMatch);
            List<TournamentRound> tournamentRounds = new List<TournamentRound>();
            TournamentRound tournamentRound;

            tournamentRound = new TournamentRound(tournamentRoundStrategy, matchStrategy);
            tournamentRound.Run(competitors);
            tournamentRounds.Add(tournamentRound);

            while (tournamentRound.Matches.Count > 1)
            {
                List<Competitor> winners = tournamentRound.Matches
                    .Select(x => x.Winner)
                    .ToList<Competitor>();

                tournamentRound = new TournamentRound(tournamentRoundStrategy, matchStrategy);
                tournamentRound.Run(winners);
                tournamentRounds.Add(tournamentRound);
            }

            List<Match> matches = new List<Match>();
            foreach (TournamentRound round in tournamentRounds)
            {
                matches.AddRange(round.Matches);
            }

            Matches = matches;

            CompetitorPoints competitorPoints = AccumulateMatchPoints(matches);
            return competitorPoints.GetCompetitorRanks();
        }
        public override CompetitorRanks GenerateResult(int tournamentRunSequence, TournamentSimulation.MatchStrategies.MatchStrategy matchStrategy, List<Competitor> competitors)
        {
            // round robin to seed the semifinals
            TournamentRound roundRobinTR = new TournamentRound(new RrTRS(_numberOfRoundRobinRounds), matchStrategy);
            CompetitorRanks rrRanks = roundRobinTR.Run(competitors);

            List<Competitor> rrRankedCompetitors = rrRanks
                .OrderBy(x => x.Value)
                .Select(x => x.Key)
                .ToList<Competitor>();

            List<Competitor> top4 = rrRankedCompetitors
                .Take(4)
                .ToList<Competitor>();

            // semifinals round
            TournamentRound semifinalsTR = new TournamentRound(new KoSfPfFiTRS(_winsToClinchKnockoutSemifinalsMatch, _winsToClinchKnockoutFinalsMatch, _winsToClinchKnockoutPetitFinalsMatch), matchStrategy);
            CompetitorRanks semiRanks = semifinalsTR.Run(top4);

            List<Competitor> bottom4 = rrRankedCompetitors
                .Skip(4)
                .Take(4)
                .ToList<Competitor>();

            // give everyone else 5th
            foreach (Competitor competitor in bottom4)
            {
                semiRanks.Add(competitor, 5);
            }

            return semiRanks;
        }
        public override CompetitorRanks GenerateResult(int tournamentRunSequence, MatchStrategy matchStrategy, List<Competitor> competitors)
        {
            TournamentRoundStrategy tournamentRoundStrategy = new KoSfFiTRS(_winsToClinchMatch);

            TournamentRound tournamentRound = new TournamentRound(tournamentRoundStrategy, matchStrategy);
            
            return tournamentRound.Run(competitors);
        }
        public override CompetitorRanks GenerateResult(int tournamentRunSequence, MatchStrategies.MatchStrategy matchStrategy, List<Competitor> competitors)
        {
            // round robin to seed the semifinals
            TournamentRound roundRobinTR = new TournamentRound(new RrTRS(_numberOfRoundRobinRounds), matchStrategy);
            CompetitorRanks rrRanks = roundRobinTR.Run(competitors);

            List<Competitor> rrRankedCompetitors = rrRanks
                .OrderBy(x => x.Value)
                .Select(x => x.Key)
                .ToList<Competitor>();

            // semifinals round
            TournamentRound semifinals5TR = new TournamentRound(new KoSf5PfFiTRS(_winsToClinchKnockoutSemifinalsMatch, _winsToClinchKnockoutFinalsMatch, _winsToClinchKnockoutPetitFinalsMatch), matchStrategy);
            
            return semifinals5TR.Run(rrRankedCompetitors);
        }
        public override CompetitorRanks GenerateResult(TournamentSimulation.MatchStrategies.MatchStrategy matchStrategy, List<Competitor> competitors)
        {
            if (competitors.Count != 4)
                throw new ArgumentException("Collection count must be 4.", "competitors");

            List<TournamentRound> tournamentRounds = new List<TournamentRound>();

            // semifinal round
            TournamentRoundStrategy semifinalTRS = new KoTRS(_winsToClinchSemifinalMatch);
            TournamentRound semifinalRound = new TournamentRound(semifinalTRS, matchStrategy);
            semifinalRound.Run(competitors);
            tournamentRounds.Add(semifinalRound);

            // petit final round
            List<Competitor> losers = semifinalRound.Matches
                .Select(x => x.Loser)
                .ToList<Competitor>();

            TournamentRoundStrategy petitFinalTRS = new KoTRS(_winsToClinchPetitMatch);
            TournamentRound petitFinalRound = new TournamentRound(petitFinalTRS, matchStrategy);
            petitFinalRound.Run(losers);
            tournamentRounds.Add(petitFinalRound);

            // final round
            List<Competitor> winners = semifinalRound.Matches
                .Select(x => x.Winner)
                .ToList<Competitor>();

            TournamentRoundStrategy finalTRS = new KoTRS(_winsToClinchFinalsMatch);
            TournamentRound finalRound = new TournamentRound(finalTRS, matchStrategy);
            finalRound.Run(winners);
            tournamentRounds.Add(finalRound);

            // return the matches that were run
            // return the matches that were run
            List<Match> matches = tournamentRounds
                .SelectMany(x => x.Matches)
                .Select(x => x)
                .ToList<Match>();

            Matches = matches;

            return GetTournamentRoundRanks();
        }
        public override CompetitorRanks GenerateResult(int tournamentRunSequence, TournamentSimulation.MatchStrategies.MatchStrategy matchStrategy, List<Competitor> competitors)
        {
            // round robin to seed the quarterfinals
            TournamentRound roundRobinTR = new TournamentRound(new RrTRS(_numberOfRoundRobinRounds), matchStrategy);
            CompetitorRanks rrRanks = roundRobinTR.Run(competitors);
            List<Competitor> rr1RankedCompetitors = rrRanks
                .OrderBy(x => x.Value)
                .Select(x => x.Key)
                .ToList<Competitor>();

            // TODO: move all this complexity to a new TournamentRoundStrategy that includes multiple stages of the knockout round quarterfinals through finals
            // knockout through finals
            TournamentRoundStrategy knockoutTRS = new KoTRS(_winsToClinchKnockoutMatch);
            TournamentRound knockoutTR = new TournamentRound(knockoutTRS, matchStrategy);
            knockoutTR.Run(rr1RankedCompetitors);

            List<TournamentRound> knockoutRounds = new List<TournamentRound>();
            knockoutRounds.Add(knockoutTR);
                
            while (knockoutTR.Matches.Count > 1)
            {
                List<Competitor> winningCompetitorsToMoveOn = new List<Competitor>();
                foreach (Match match in knockoutTR.Matches)
                {
                    winningCompetitorsToMoveOn.Add(match.Winner);
                }

                knockoutTR = new TournamentRound(knockoutTRS, matchStrategy);
                knockoutTR.Run(winningCompetitorsToMoveOn);

                knockoutRounds.Add(knockoutTR);
            }

            CompetitorPoints competitorPoints = AccumulatePointsFromTournamentRounds(knockoutRounds);
            CompetitorRanks ranks = competitorPoints.GetCompetitorRanks();

            BreakTiesByRoundRobinRanks(rrRanks, ranks);

            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 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;
        }
 public override CompetitorRanks GenerateResult(int tournamentRunSequence, MatchStrategy matchStrategy, List<Competitor> competitors)
 {
     TournamentRound tournamentRound = new TournamentRound(new RrTRS(_numberOfRounds, _winsToClinchMatch), matchStrategy);
     return tournamentRound.Run(competitors);
 }
        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 override CompetitorRanks GenerateResult(MatchStrategies.MatchStrategy matchStrategy, List<Competitor> competitors)
        {
            if (competitors.Count != 5)
                throw new ArgumentException("Collection count must be 5.", "competitors");

            List<TournamentRound> tournamentRounds = new List<TournamentRound>();

            // petit final qualifier round
            List<Competitor> petitQualifiers = new List<Competitor>();
            petitQualifiers.Add(competitors[3]);
            petitQualifiers.Add(competitors[4]);

            TournamentRoundStrategy knockoutTRS_petitQualifier = new KoTRS(_winsToClinchSemifinalMatch);
            TournamentRound petitQualifierRound = new TournamentRound(knockoutTRS_petitQualifier, matchStrategy);
            petitQualifierRound.Run(petitQualifiers);
            tournamentRounds.Add(petitQualifierRound);

            // final qualifier round
            List<Competitor> finalsQualifiers = new List<Competitor>();
            finalsQualifiers.Add(competitors[1]);
            finalsQualifiers.Add(competitors[2]);

            TournamentRoundStrategy knockoutTRS_finalQualifier = new KoTRS(_winsToClinchSemifinalMatch);
            TournamentRound finalQualifierRound = new TournamentRound(knockoutTRS_finalQualifier, matchStrategy);
            finalQualifierRound.Run(finalsQualifiers);
            tournamentRounds.Add(finalQualifierRound);

            // petit final round
            List<Competitor> petitFinalsCompetitors = petitQualifierRound.Matches
                .Select(x => x.Winner)
                .Union(finalQualifierRound.Matches
                    .Select(x => x.Loser))
                .ToList<Competitor>();

            TournamentRoundStrategy petitFinalTRS = new KoTRS(_winsToClinchPetitMatch);
            TournamentRound petitFinalRound = new TournamentRound(petitFinalTRS, matchStrategy);
            petitFinalRound.Run(petitFinalsCompetitors);
            tournamentRounds.Add(petitFinalRound);

            // final round
            List<Competitor> finalsCompetitors = finalQualifierRound.Matches
                .Select(x => x.Winner)
                .ToList<Competitor>();

            finalsCompetitors.Add(competitors[0]);

            TournamentRoundStrategy finalTRS = new KoTRS(_winsToClinchFinalsMatch);
            TournamentRound finalRound = new TournamentRound(finalTRS, matchStrategy);
            finalRound.Run(finalsCompetitors);
            tournamentRounds.Add(finalRound);

            // return the matches that were run
            List<Match> matches = tournamentRounds
                .SelectMany(x => x.Matches)
                .Select(x => x)
                .ToList<Match>();

            Matches = matches;

            return GetTournamentRoundRanks();
        }