public Round GenerateMatchups(int tournamentId) { if (!CanGenerateNextRound(tournamentId)) { throw new CantGenerateNewRoundException(); } var previousMatchups = roundRepository.GetAllMatchups(tournamentId); var players = playerRepository.GetAllInTournament(tournamentId); var scores = roundRepository.GetScoresForTournament(tournamentId); var contestants = players.Where(p => p.Active).Select(p => new Contestant { Identifier = p.Id, Affiliation = p.Affiliation, PreviousOpponents = ExtractPreviousOpponentsForPlayer(p, previousMatchups, players, scores), Score = scores.Where(s => s.PlayerId == p.Id).Sum(s => s.Amount), CompensationPoints = p.CompensationPoints }).OrderBy(c => c.Score).ToList(); if (contestants.Count <= 1) { throw new Exception("Not enough active player in tournament to generate round matchups"); } var engine = new MatchupEngine(); var contestantMatchups = engine.GenerateMatchup(contestants.Count % 2 == 0 ? contestants : contestants.Skip(1).ToList()); var round = roundRepository.Add(new Round { RoundNumber = previousMatchups.Any() ? previousMatchups.Max(x => x.Key) + 1 : 1, TournamentId = tournamentId }); roundRepository.AddMatchupsToRound(round.Id, contestantMatchups.Select(x => new Matchup { RoundId = round.Id, TableNumber = x.Table, Player1Id = x.Contestant1.Identifier, Player2Id = x.Contestant2.Identifier }).ToList()); if (contestants.Count % 2 != 0) { //The left over player gets a pseudo matchup and score var leftOverContestant = contestants.First(); roundRepository.AddPseudoMatchupToRound(round.Id, leftOverContestant.Identifier); } return(roundRepository.GetCurrentRound(tournamentId)); }