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, TournamentSimulation.MatchStrategies.MatchStrategy matchStrategy, List<Competitor> competitors)
        {
            // TODO: implement this strategy
            // reference: http://rulestalk.blogspot.com/2010/10/hebbert-lucas-system.html or http://teamracing.org
            // note: this is basically a round-robin where points are awarded, even if unequal races are sailed

            throw new NotImplementedException();
        }
        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;
        }