private EliminationNode MakeSiblings(EliminationNode nodeA, EliminationNode nodeB) { var oldParent = nodeA.PrimaryParent as ContinuationDecider; var newDecider = new ContinuationDecider(nodeA, nodeB); var newNode = new WinnerNode(newDecider); newDecider.PrimaryParent = newNode; nodeA.PrimaryParent = nodeB.PrimaryParent = newDecider; newNode.PrimaryParent = oldParent; if (oldParent != null) { if (oldParent.ChildA == nodeA) { oldParent.ChildA = newNode; } else if (oldParent.ChildB == nodeA) { oldParent.ChildB = newNode; } } return(newNode); }
private EliminationNode BuildTree(IEnumerable <TournamentTeam> teams) { List <EliminationNode> nodes = new List <EliminationNode>(); if (teams.Count() >= 2) { int ranking = 0; var teamsOrder = from team in teams orderby team.Rating.HasValue ? team.Rating : 0 descending select new TeamRanking { Team = team, Ranking = ranking++, }; int i = 0; int nextRoundAt = 2; int roundNumber = 0; int mask = (1 << roundNumber) - 1; var teamRankings = teamsOrder.ToList(); foreach (var teamRanking in teamRankings) { if (i == nextRoundAt) { nextRoundAt *= 2; roundNumber += 1; mask = (1 << roundNumber) - 1; } var newDecider = new TeamDecider(teamRanking.Team); var newNode = new WinnerNode(newDecider); newDecider.PrimaryParent = newNode; if (nodes.Count > 0) { var match = (from n in nodes let d = n.Decider as TeamDecider where d != null where (teamRankings.Where(tr => tr.Team == n.Team).Single().Ranking & mask) == (teamRanking.Ranking & mask) select n).Single(); nodes.Add(MakeSiblings(match, newNode)); } nodes.Add(newNode); i++; } // Add in byes to even out the left side of the bracket. for (ranking = teamRankings.Count; ranking < nextRoundAt; ranking++) { var match = (from n in nodes let d = n.Decider as TeamDecider where d != null where (teamRankings.Where(tr => tr.Team == n.Team).Single().Ranking & mask) == (ranking & mask) select n).Single(); var newDecider = new ByeDecider(); var newNode = new WinnerNode(newDecider); newDecider.PrimaryParent = newNode; nodes.Add(newNode); nodes.Add(MakeSiblings(match, newNode)); } } var rootNode = (from n in nodes where n.Level == 0 select n).SingleOrDefault(); if (eliminations == 1 || rootNode == null) { return(rootNode); } var maxLevel = nodes.Max(n => n.Level) - 1; var deciders = rootNode.FindDeciders(d => d.Level == maxLevel); var loserNodes = BuildLoserNodes(deciders); while (true) { maxLevel--; deciders = rootNode.FindDeciders(d => d.Level == maxLevel); if (deciders.Count() == 0) { break; } var newLosers = BuildLoserNodes(deciders); while (loserNodes.Count() > newLosers.Count()) { loserNodes = SimplifyNodes(loserNodes); } loserNodes = InterleaveNodes(newLosers, loserNodes); } while (loserNodes.Count > 1) { loserNodes = SimplifyNodes(loserNodes); } var loserRoot = loserNodes[0]; var winnersDecider = new ContinuationDecider(rootNode, loserRoot); var winnersWinner = new WinnerNode(winnersDecider); winnersDecider.PrimaryParent = winnersWinner; var passthrough = new PassThroughDecider(rootNode); var replay = new WinnerNode(passthrough); passthrough.PrimaryParent = replay; var stayDecider = new StayDecider(winnersWinner, replay); var finalWinner = new WinnerNode(stayDecider); stayDecider.PrimaryParent = finalWinner; return(finalWinner); }