/// <summary> /// Resets the Bracket. /// Affects Matches, Rankings, and bracket status. /// </summary> protected override void ResetBracketData() { base.ResetBracketData(); if (null == GroupRankings) { GroupRankings = new List <List <IPlayerScore> >(); } GroupRankings.Clear(); }
/// <summary> /// Sets this Bracket's main data from a related BracketModel. /// Data affected includes most fields, as well as the playerlist. /// </summary> /// <param name="_model">Related BracketModel</param> protected override void SetDataFromModel(BracketModel _model) { // Call the base (Bracket) method to set common data and playerlist: base.SetDataFromModel(_model); this.NumberOfGroups = _model.NumberOfGroups; if (_model.Matches.Count > 0) { foreach (MatchModel matchModel in _model.Matches) { // Convert each MatchModel to a Match, and add: Matches.Add(matchModel.MatchNumber, new Match(matchModel)); } this.NumberOfMatches = Matches.Count; this.NumberOfRounds = Matches.Values .Max(m => m.RoundIndex); this.IsFinished = Matches.Values .All(m => m.IsFinished); } // "Recreate" the groups: List <List <IPlayer> > playerGroups = DividePlayersIntoGroups(); for (int g = 0; g < playerGroups.Count; ++g) { // Use these groups to remake the GroupRankings: GroupRankings.Add(new List <IPlayerScore>()); foreach (IPlayer player in playerGroups[g]) { // Make a new ranking object for each Player, // and add it to Rankings and GroupRankings: IPlayerScore pScore = new PlayerScore(player.Id, player.Name); Rankings.Add(pScore); GroupRankings[g].Add(pScore); } } // Go through the Matches to recalculate the current Rankings: RecalculateRankings(); if (this.IsFinalized && false == Validate()) { throw new BracketValidationException ("Bracket is Finalized but not Valid!"); } }
/// <summary> /// Uses the playerlist to generate the bracket structure & matchups. /// This divides the players into the given number of groups, /// then creates & populates all the Match objects. /// If any Matches already exist, they will be deleted first. /// If there are too few players, nothing will be made. /// </summary> /// <param name="_gamesPerMatch">Max games for every Match</param> public override void CreateBracket(int _gamesPerMatch = 1) { // First, clear any existing Matches and results: ResetBracketData(); if (NumberOfGroups < 2 || NumberOfGroups * 2 > Players.Count) { return; } // DividePlayersIntoGroups() uses our chosen method to separate the playerlist: List <List <IPlayer> > playerGroups = DividePlayersIntoGroups(); GroupRankings.Capacity = NumberOfGroups; List <IBracket> groups = new List <IBracket>(); for (int g = 0; g < playerGroups.Count; ++g) { // For each group, generate a full round robin bracket: groups.Add(new RoundRobinBracket(playerGroups[g], _gamesPerMatch, MaxRounds)); } /* * So now we've generated all of our Matches. * We want to copy them into our main Bracket, but there's a problem: * each new round robin numbers their Matches from 1. * We need unique MatchNumbers, so we go through and create * new "copy" Matches, but with those unique MatchNumbers we need. */ // For every group... for (int g = 0; g < groups.Count; ++g) { // For every Match within that group... for (int m = 1; m <= groups[g].NumberOfMatches; ++m) { ++NumberOfMatches; IMatch currMatch = groups[g].GetMatch(m); // Copy the Match into our main Bracket: if (0 == g) { Matches.Add(currMatch.MatchNumber, (currMatch as Match)); } else { // If we're in a group after the first, we need to: // create a new Match, and give it a higher MatchNumber. Match match = new Match(); match.SetMaxGames(currMatch.MaxGames); match.SetRoundIndex(currMatch.RoundIndex); match.SetMatchIndex(currMatch.MatchIndex); match.SetMatchNumber(NumberOfMatches); match.AddPlayer(currMatch.Players[(int)PlayerSlot.Defender]); match.AddPlayer(currMatch.Players[(int)PlayerSlot.Challenger]); Matches.Add(match.MatchNumber, match); } // Apply a GroupNumber to the Match: Matches[NumberOfMatches].SetGroupNumber(g + 1); } // Each round robin generated initial Rankings lists. // Copy them into Rankings and GroupRankings. // Since we COPY instead of recreating, modifying one PlayerScore // will modify it in both of these locations. Handy! Rankings.AddRange(groups[g].Rankings); GroupRankings.Add(groups[g].Rankings); } NumberOfRounds = Matches.Values .Max(m => m.RoundIndex); Rankings.Sort(SortRankingRanks); }