public void AddSecondaryParent(EliminationNode secondaryParent)
 {
     if(secondaryParent != null && !this.secondaryParents.Contains(secondaryParent))
     {
         this.secondaryParents.Add(secondaryParent);
     }
 }
 public PassThroughDecider(EliminationNode node)
 {
     if (node == null)
     {
         throw new ArgumentNullException("node");
     }
     this.node = node;
 }
        public ContinuationDecider(EliminationNode nodeA, EliminationNode nodeB)
        {
            if (nodeA == null)
            {
                throw new ArgumentNullException("nodeA");
            }

            if (nodeB == null)
            {
                throw new ArgumentNullException("nodeB");
            }

            this.nodeA = nodeA;
            this.nodeB = nodeB;
        }
        public StayDecider(EliminationNode previousWinnerNode, EliminationNode stayNode)
        {
            if (previousWinnerNode == null)
            {
                throw new ArgumentNullException("previousWinnerNode");
            }

            if (stayNode == null)
            {
                throw new ArgumentNullException("stayNode");
            }

            this.previousWinnerNode = previousWinnerNode;
            this.stayNode = stayNode;
        }
Example #5
0
 public ContinuationDecider(EliminationNode nodeA, EliminationNode nodeB)
 {
     this.nodeA = nodeA ?? throw new ArgumentNullException(nameof(nodeA));
     this.nodeB = nodeB ?? throw new ArgumentNullException(nameof(nodeB));
 }
        protected void RenderTree(IGraphics g, TournamentNameTable names, float x, float y, float textHeight, EliminationNode nodeA, EliminationNode nodeB)
        {
            var m = this.MeasureTree(g, names, textHeight, nodeA, nodeB);
            var mA = nodeA == null ? null : nodeA.Measure(g, names, textHeight);
            var mB = nodeB == null ? null : nodeB.Measure(g, names, textHeight);

            if (mA == null && mB == null)
            {
                return;
            }
            else if (mA != null && mB != null)
            {
                // Preline
                g.DrawLine(
                    BracketPen,
                    new PointF(
                        x + (m.Width - BracketPreIndent),
                        y + m.CenterLine),
                    new PointF(
                        x + m.Width,
                        y + m.CenterLine));

                // V-Line
                g.DrawLine(
                    BracketPen,
                    new PointF(
                        x + (m.Width - BracketPreIndent),
                        y + mA.CenterLine),
                    new PointF(
                        x + (m.Width - BracketPreIndent),
                        y + mA.Height + BracketVSpacing + mB.CenterLine));

                // Post-Line-A
                g.DrawLine(
                    BracketPen,
                    new PointF(
                        x + (m.Width - BracketPreIndent - BracketPostIndent),
                        y + mA.CenterLine),
                    new PointF(
                        x + (m.Width - BracketPreIndent),
                        y + mA.CenterLine));

                // Post-Line-B
                g.DrawLine(
                    BracketPen,
                    new PointF(
                        x + (m.Width - BracketPreIndent - BracketPostIndent),
                        y + mA.Height + BracketVSpacing + mB.CenterLine),
                    new PointF(
                        x + (m.Width - BracketPreIndent),
                        y + mA.Height + BracketVSpacing + mB.CenterLine));

                nodeA.Render(g, names, x + (m.Width - (mA.Width + BracketPreIndent + BracketPostIndent)), y, textHeight);
                nodeB.Render(g, names, x + (m.Width - (mB.Width + BracketPreIndent + BracketPostIndent)), y + mA.Height + BracketVSpacing, textHeight);
            }
            else if (mA != null)
            {
                // TODO: Render Lines?
                nodeA.Render(g, names, x, y, textHeight);
            }
            else
            {
                // TODO: Render Lines?
                nodeB.Render(g, names, x, y, textHeight);
            }
        }
        protected NodeMeasurement MeasureTree(IGraphics g, TournamentNameTable names, float textHeight, EliminationNode nodeA, EliminationNode nodeB)
        {
            var mA = nodeA == null ? null : nodeA.Measure(g, names, textHeight);
            var mB = nodeB == null ? null : nodeB.Measure(g, names, textHeight);

            if (mA == null && mB == null)
            {
                return null;
            }
            else if (mA != null && mB != null)
            {
                return new NodeMeasurement(
                    Math.Max(mA.Width, mB.Width) + BracketPreIndent + BracketPostIndent,
                    mA.Height + mB.Height + BracketVSpacing,
                    (mA.CenterLine + (mA.Height + BracketVSpacing + mB.CenterLine)) / 2);
            }
            else if (mA != null)
            {
                return new NodeMeasurement(
                    mA.Width + BracketPreIndent + BracketPostIndent,
                    mA.Height,
                    mA.CenterLine);
            }
            else
            {
                return new NodeMeasurement(
                    mB.Width + BracketPreIndent + BracketPostIndent,
                    mB.Height,
                    mB.CenterLine);
            }
        }
Example #8
0
 public StayDecider(EliminationNode previousWinnerNode, EliminationNode stayNode)
 {
     this.PreviousWinnerNode = previousWinnerNode ?? throw new ArgumentNullException(nameof(previousWinnerNode));
     this.StayNode           = stayNode ?? throw new ArgumentNullException(nameof(stayNode));
 }
        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 static void LockByes(EliminationNode rootNode)
        {
            var deciders = rootNode.FindDeciders(d => d.IsDecided && !d.Locked).ToList();

            foreach (var d in deciders)
            {
                d.Lock();
            }
        }
 public void Reset()
 {
     this.loadedTeams = null;
     this.loadedRootNode = null;
     this.state = PairingsGeneratorState.NotInitialized;
 }
        public void LoadState(IEnumerable<TournamentTeam> teams, IList<TournamentRound> rounds)
        {
            if (teams == null)
            {
                throw new ArgumentNullException("teams");
            }

            if (rounds == null)
            {
                throw new ArgumentNullException("rounds");
            }

            if (rounds.Where(r => r.Pairings.Where(p => p.TeamScores.Count > 2).Any()).Any())
            {
                throw new InvalidTournamentStateException("At least one pairing had more than two teams competing.  This is invalid in a single elimination tournament.");
            }

            var rootNode = BuildTree(teams);
            bool byesLocked = false;

            foreach (var round in rounds)
            {
                foreach (var pairing in round.Pairings)
                {
                    // TODO: We must sort the byes to the top.

                    if (pairing.TeamScores.Count == 0)
                    {
                        continue;
                    }
                tryagainwithbyeslocked:
                    bool success = rootNode.ApplyPairing(pairing);

                    if (!success)
                    {
                        var teamScoreA = pairing.TeamScores[0];
                        var teamScoreB = pairing.TeamScores.Count > 1 ? pairing.TeamScores[1] : null;

                        if (teamScoreA == null)
                        {
                            teamScoreA = teamScoreB;
                            teamScoreB = null;
                        }

                        if (teamScoreA == null)
                            continue;

                        var teamA = teamScoreA != null ? teamScoreA.Team : null;
                        var teamB = teamScoreB != null ? teamScoreB.Team : null;
                        var scoreA = teamScoreA != null ? teamScoreA.Score : null;
                        var scoreB = teamScoreB != null ? teamScoreB.Score : null;

                        var nodesA = teamA == null ? null : rootNode.FindDeciders(d => d.IsDecided && !d.Locked && d.GetWinner() != null && d.GetWinner().TeamId == teamA.TeamId);
                        var nodesB = teamB == null ? null : rootNode.FindDeciders(d => d.IsDecided && !d.Locked && d.GetWinner() != null && d.GetWinner().TeamId == teamB.TeamId);

                        if (nodesA == null || nodesA.Count() == 0 || nodesB == null || nodesB.Count() == 0)
                        {
                            if (!byesLocked)
                            {
                                byesLocked = true;
                                LockByes(rootNode);
                                goto tryagainwithbyeslocked;
                            }
                            throw new InvalidTournamentStateException("There was at least one pairing that could not be matched: The requested team was not available to play.");
                        }

                        if (nodesA.Count() > 1 || nodesB.Count() > 1)
                        {
                            if (!byesLocked)
                            {
                                byesLocked = true;
                                LockByes(rootNode);
                                goto tryagainwithbyeslocked;
                            }
                            throw new InvalidTournamentStateException("There was at least one pairing that could not be matched: The requested team was not able to be decided unambiguously.");
                        }

                        var deciderA = nodesA.Single();
                        var deciderB = nodesB.Single();

                        var parentDecider = deciderA.PrimaryParent.PrimaryParent as ContinuationDecider;
                        if (parentDecider == null)
                        {
                            parentDecider = deciderB.PrimaryParent.PrimaryParent as ContinuationDecider;
                            if (parentDecider == null)
                            {
                                if (!byesLocked)
                                {
                                    byesLocked = true;
                                    LockByes(rootNode);
                                    goto tryagainwithbyeslocked;
                                }
                                throw new InvalidTournamentStateException("There was at least one pairing that could not be matched: The requested pairing was not compatible with the state of the tournament.");
                            }
                        }

                        if (parentDecider.ChildA.Decider == deciderA || parentDecider.ChildA.Decider == deciderB)
                        {
                            if (parentDecider.ChildA.Decider == deciderA)
                            {
                                SwapDeciders(parentDecider.ChildB.Decider, deciderB);
                            }
                            else
                            {
                                SwapDeciders(parentDecider.ChildB.Decider, deciderA);
                            }
                        }
                        else
                        {
                            if (parentDecider.ChildB.Decider == deciderA)
                            {
                                SwapDeciders(parentDecider.ChildA.Decider, deciderB);
                            }
                            else
                            {
                                SwapDeciders(parentDecider.ChildA.Decider, deciderA);
                            }
                        }

                        success = rootNode.ApplyPairing(pairing);

                        if (!success)
                        {
                            if (!byesLocked)
                            {
                                byesLocked = true;
                                LockByes(rootNode);
                                goto tryagainwithbyeslocked;
                            }
                            throw new InvalidTournamentStateException("A swap was performed to match the tournament to the actual state, but applying the pairing failed.");
                        }
                    }
                }
            }

            this.loadedRootNode = rootNode;
            this.loadedTeams = new List<TournamentTeam>(teams);
            this.state = PairingsGeneratorState.Initialized;
        }
Example #13
0
        protected NodeMeasurement MeasureTree(IGraphics g, TournamentNameTable names, float textHeight, EliminationNode nodeA, EliminationNode nodeB)
        {
            var mA = nodeA?.Measure(g, names, textHeight);
            var mB = nodeB?.Measure(g, names, textHeight);

            if (mA == null && mB == null)
            {
                return(null);
            }
            else if (mA != null && mB != null)
            {
                return(new NodeMeasurement(
                           Math.Max(mA.Width, mB.Width) + BracketPreIndent + BracketPostIndent,
                           mA.Height + mB.Height + BracketVSpacing,
                           (mA.CenterLine + (mA.Height + BracketVSpacing + mB.CenterLine)) / 2));
            }
            else if (mA != null)
            {
                return(new NodeMeasurement(
                           mA.Width + BracketPreIndent + BracketPostIndent,
                           mA.Height,
                           mA.CenterLine));
            }
            else
            {
                return(new NodeMeasurement(
                           mB.Width + BracketPreIndent + BracketPostIndent,
                           mB.Height,
                           mB.CenterLine));
            }
        }
 public void SwapChildren()
 {
     var tempNode = this.nodeA;
     this.nodeA = this.nodeB;
     this.nodeB = tempNode;
 }
Example #15
0
        protected void RenderTree(IGraphics g, TournamentNameTable names, float x, float y, float textHeight, EliminationNode nodeA, EliminationNode nodeB)
        {
            var m  = this.MeasureTree(g, names, textHeight, nodeA, nodeB);
            var mA = nodeA?.Measure(g, names, textHeight);
            var mB = nodeB?.Measure(g, names, textHeight);

            if (mA == null && mB == null)
            {
                return;
            }
            else if (mA != null && mB != null)
            {
                // Preline
                g.DrawLine(
                    BracketPen,
                    new PointF(
                        x + (m.Width - BracketPreIndent),
                        y + m.CenterLine),
                    new PointF(
                        x + m.Width,
                        y + m.CenterLine));

                // V-Line
                g.DrawLine(
                    BracketPen,
                    new PointF(
                        x + (m.Width - BracketPreIndent),
                        y + mA.CenterLine),
                    new PointF(
                        x + (m.Width - BracketPreIndent),
                        y + mA.Height + BracketVSpacing + mB.CenterLine));

                // Post-Line-A
                g.DrawLine(
                    BracketPen,
                    new PointF(
                        x + (m.Width - BracketPreIndent - BracketPostIndent),
                        y + mA.CenterLine),
                    new PointF(
                        x + (m.Width - BracketPreIndent),
                        y + mA.CenterLine));

                // Post-Line-B
                g.DrawLine(
                    BracketPen,
                    new PointF(
                        x + (m.Width - BracketPreIndent - BracketPostIndent),
                        y + mA.Height + BracketVSpacing + mB.CenterLine),
                    new PointF(
                        x + (m.Width - BracketPreIndent),
                        y + mA.Height + BracketVSpacing + mB.CenterLine));

                nodeA.Render(g, names, x + (m.Width - (mA.Width + BracketPreIndent + BracketPostIndent)), y, textHeight);
                nodeB.Render(g, names, x + (m.Width - (mB.Width + BracketPreIndent + BracketPostIndent)), y + mA.Height + BracketVSpacing, textHeight);
            }
            else if (mA != null)
            {
                // TODO: Render Lines?
                nodeA.Render(g, names, x, y, textHeight);
            }
            else
            {
                // TODO: Render Lines?
                nodeB.Render(g, names, x, y, textHeight);
            }
        }
        public void LoadState(IEnumerable <User> teams, IList <TournamentRound> rounds)
        {
            if (teams == null)
            {
                throw new ArgumentNullException("teams");
            }

            if (rounds == null)
            {
                throw new ArgumentNullException("rounds");
            }

            if (rounds.Where(r => r.Pairings.Where(p => p.TeamScores.Count > 2).Any()).Any())
            {
                throw new InvalidTournamentStateException("At least one pairing had more than two teams competing.  This is invalid in a single elimination tournament.");
            }

            var  rootNode   = BuildTree(teams);
            bool byesLocked = false;

            foreach (var round in rounds)
            {
                foreach (var pairing in round.Pairings)
                {
                    // TODO: We must sort the byes to the top.

                    if (pairing.TeamScores.Count == 0)
                    {
                        continue;
                    }
tryagainwithbyeslocked:
                    bool success = rootNode.ApplyPairing(pairing);

                    if (!success)
                    {
                        var teamScoreA = pairing.TeamScores[0];
                        var teamScoreB = pairing.TeamScores.Count > 1 ? pairing.TeamScores[1] : null;

                        if (teamScoreA == null)
                        {
                            teamScoreA = teamScoreB;
                            teamScoreB = null;
                        }

                        if (teamScoreA == null)
                        {
                            continue;
                        }

                        var teamA  = teamScoreA != null ? teamScoreA.Team : null;
                        var teamB  = teamScoreB != null ? teamScoreB.Team : null;
                        var scoreA = teamScoreA != null ? teamScoreA.Score : null;
                        var scoreB = teamScoreB != null ? teamScoreB.Score : null;

                        var nodesA = teamA == null ? null : rootNode.FindDeciders(d => d.IsDecided && !d.Locked && d.GetWinner() != null && d.GetWinner().Id == teamA.Id);
                        var nodesB = teamB == null ? null : rootNode.FindDeciders(d => d.IsDecided && !d.Locked && d.GetWinner() != null && d.GetWinner().Id == teamB.Id);

                        if (nodesA == null || nodesA.Count() == 0 || nodesB == null || nodesB.Count() == 0)
                        {
                            if (!byesLocked)
                            {
                                byesLocked = true;
                                LockByes(rootNode);
                                goto tryagainwithbyeslocked;
                            }
                            throw new InvalidTournamentStateException("There was at least one pairing that could not be matched: The requested team was not available to play.");
                        }

                        if (nodesA.Count() > 1 || nodesB.Count() > 1)
                        {
                            if (!byesLocked)
                            {
                                byesLocked = true;
                                LockByes(rootNode);
                                goto tryagainwithbyeslocked;
                            }
                            throw new InvalidTournamentStateException("There was at least one pairing that could not be matched: The requested team was not able to be decided unambiguously.");
                        }

                        var deciderA = nodesA.Single();
                        var deciderB = nodesB.Single();

                        var parentDecider = deciderA.PrimaryParent.PrimaryParent as ContinuationDecider;
                        if (parentDecider == null)
                        {
                            parentDecider = deciderB.PrimaryParent.PrimaryParent as ContinuationDecider;
                            if (parentDecider == null)
                            {
                                if (!byesLocked)
                                {
                                    byesLocked = true;
                                    LockByes(rootNode);
                                    goto tryagainwithbyeslocked;
                                }
                                throw new InvalidTournamentStateException("There was at least one pairing that could not be matched: The requested pairing was not compatible with the state of the tournament.");
                            }
                        }

                        if (parentDecider.ChildA.Decider == deciderA || parentDecider.ChildA.Decider == deciderB)
                        {
                            if (parentDecider.ChildA.Decider == deciderA)
                            {
                                SwapDeciders(parentDecider.ChildB.Decider, deciderB);
                            }
                            else
                            {
                                SwapDeciders(parentDecider.ChildB.Decider, deciderA);
                            }
                        }
                        else
                        {
                            if (parentDecider.ChildB.Decider == deciderA)
                            {
                                SwapDeciders(parentDecider.ChildA.Decider, deciderB);
                            }
                            else
                            {
                                SwapDeciders(parentDecider.ChildA.Decider, deciderA);
                            }
                        }

                        success = rootNode.ApplyPairing(pairing);

                        if (!success)
                        {
                            if (!byesLocked)
                            {
                                byesLocked = true;
                                LockByes(rootNode);
                                goto tryagainwithbyeslocked;
                            }
                            throw new InvalidTournamentStateException("A swap was performed to match the tournament to the actual state, but applying the pairing failed.");
                        }
                    }
                }
            }

            this.loadedRootNode = rootNode;
            this.loadedTeams    = new List <User>(teams);
            this.state          = PairingsGeneratorState.Initialized;
        }
 public void Reset()
 {
     this.loadedTeams    = null;
     this.loadedRootNode = null;
     this.state          = PairingsGeneratorState.NotInitialized;
 }
Example #18
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PassThroughDecider"/> class.
 /// </summary>
 /// <param name="passThroughNode">The node whose winner will be passed through.</param>
 public PassThroughDecider(EliminationNode passThroughNode)
 {
     this.PassThroughNode = passThroughNode ?? throw new ArgumentNullException(nameof(passThroughNode));
 }