/// <summary>
        /// Construct a depdenency graph of the <see cref="Character"/>'s <see cref="ModifierSource"/>s.
        /// </summary>
        /// <param name="character">
        /// The <see cref="Character"/> to generate the dependency graph for. This cannot be null.
        /// </param>
        /// <param name="modifierSources">
        /// The already extracted list of <see cref="ModifierSource"/>s to use. This cannot be null.
        /// </param>
        /// <returns>
        /// A <see cref="GraphNode{ModifierSource}"/> that is the root node of a dependency graph. The root
        /// node can be ignored and is not part of the graph itself.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// No argument can be null.
        /// </exception>
        internal static GraphNode<ModifierSource> ConstructDependencyGraph(Character character, IList<ModifierSource> modifierSources)
        {
            if (character == null)
            {
                throw new ArgumentNullException("character");
            }
            if (modifierSources == null)
            {
                throw new ArgumentNullException("modifierSources");
            }

            GraphNode<ModifierSource> root;
            IEqualityComparer<ModifierSource> comparer;
            Dictionary<ModifierSource, GraphNode<ModifierSource>> graphNodeLookup;

            // Rather than use "EqualityComparer<ModifierSource>.Default", use identity equality.
            // This allows two instances of the same modifier source with the same name to be used
            // within the graph. This can occur frequently with powers.
            comparer = new IdentityEqualityComparer<ModifierSource>();

            // Optimization for GraphNode.Find().
            graphNodeLookup = new Dictionary<ModifierSource, GraphNode<ModifierSource>>();

            // Construct a dependency graph.
            root = new GraphNode<ModifierSource>(new NullModifierSource(), comparer);
            foreach (ModifierSource modifierSource in modifierSources)
            {
                List<KeyValuePair<ModifierSource, ModifierSource>> dependencies;
                GraphNode<ModifierSource> parentGraphNode;
                GraphNode<ModifierSource> childGraphNode;

                // Get the dependencies
                dependencies = modifierSource.GetDependencies(character);

                // For each dependency, find the source ModifierSource and add
                // the destination under it.
                foreach (KeyValuePair<ModifierSource, ModifierSource> dependency in dependencies)
                {
                    // Find the parent of the dependency
                    if (!graphNodeLookup.TryGetValue(dependency.Key, out parentGraphNode))
                    {
                        parentGraphNode = new GraphNode<ModifierSource>(dependency.Key, comparer);
                        root.AddChild(parentGraphNode);
                        graphNodeLookup[dependency.Key] = parentGraphNode;
                    }

                    // Find the child of the dependency
                    if (!graphNodeLookup.TryGetValue(dependency.Value, out childGraphNode))
                    {
                        childGraphNode = new GraphNode<ModifierSource>(dependency.Value, comparer);
                        graphNodeLookup[dependency.Value] = childGraphNode;
                    }

                    // Add the child to the parent
                    parentGraphNode.AddChild(childGraphNode);
                }
            }

            return root;
        }
Пример #2
0
        public void DisplayExample()
        {
            var graph = new GraphNode(null);

            var boatObj     = new GraphNode(new Mesh("Boat"));
            var crowNestObj = new GraphNode(new Mesh("CrowNest"));
            var pirateObj   = new GraphNode(new Mesh("Pirate"));
            var parrotObj   = new GraphNode(new Mesh("Parrot"));

            graph.AddChild(boatObj);
            boatObj.AddChild(crowNestObj);
            crowNestObj.AddChild(pirateObj);
            pirateObj.AddChild(parrotObj);

            boatObj.SetTransform(new Transform(new Vector3(0, 0, 0)));
            crowNestObj.SetTransform(new Transform(new Vector3(0, 1, 0)));
            pirateObj.SetTransform(new Transform(new Vector3(0, 0.5f, 0)));
            parrotObj.SetTransform(new Transform(new Vector3(0, 0.2f, 0)));

            graph.Render(Transform.Origin, true); // Set dirty the first time

            Console.WriteLine("\nThe boat is moving.\n");
            boatObj.Translate(new Vector3(0, 0, 1));

            graph.Render(Transform.Origin, false);

            Console.WriteLine("\nThe pirate fell down the crow nest!\n");
            pirateObj.Translate(new Vector3(0, -1, 0));

            graph.Render(Transform.Origin, false);
        }
 public void Test_AddChild_CircularReferenceOneLevel()
 {
     GraphNode<string> parent = new GraphNode<string>("parent");
     GraphNode<string> child = new GraphNode<string>("child");
     parent.AddChild(child);
     Assert.That(() => child.AddChild(parent),
         Throws.ArgumentException.And.Property("ParamName").EqualTo("graphNode"));
 }
        public void Find_GivenTwoNodeWithExistingPath_ReturnSuccessResult()
        {
            var node1 = new GraphNode <int>(5);
            var node2 = new GraphNode <int>(7);
            var node3 = new GraphNode <int>(8);

            node1.AddChild(node2);
            node2.AddChild(node3);

            var finder = new FindPathBetweenTwoNode <int>();

            var result = finder.Find(node1, node2);

            result.IsSuccess.Should().BeTrue();
        }
        public void Test_GetDepthFirstEnumerator()
        {
            GraphNode<string> rootGraphNode = new GraphNode<string>("root");
            GraphNode<string> leftParentGraphNode = new GraphNode<string>("leftParent");
            GraphNode<string> leftFirstChildGraphNode = new GraphNode<string>("leftFirstChild");
            GraphNode<string> leftSecondChildGraphNode = new GraphNode<string>("leftSecondChild");
            GraphNode<string> rightParentGraphNode = new GraphNode<string>("rightParent");
            GraphNode<string> rightChildGraphNode = new GraphNode<string>("rightChild");
            GraphNode<string> rightGrandChildGraphNode = new GraphNode<string>("rightGrandChild");

            rootGraphNode.AddChild(leftParentGraphNode);
            leftParentGraphNode.AddChild(leftFirstChildGraphNode);
            leftParentGraphNode.AddChild(leftSecondChildGraphNode);
            rootGraphNode.AddChild(rightParentGraphNode);
            rightParentGraphNode.AddChild(rightChildGraphNode);
            rightChildGraphNode.AddChild(rightGrandChildGraphNode);

            GraphNode<string>[] expected = new[]
            {
                rootGraphNode,
                leftParentGraphNode,
                leftFirstChildGraphNode,
                leftSecondChildGraphNode,
                rightParentGraphNode,
                rightChildGraphNode,
                rightGrandChildGraphNode
            };

            Assert.That(expected.Zip(rootGraphNode.GetDepthFirstEnumerator(), (x, y) => x.Equals(y)).All(x => x), Is.True);
        }
 public void Test_AddChild_Self()
 {
     GraphNode<string> graphNode = new GraphNode<string>(string.Empty);
     Assert.That(() => graphNode.AddChild(graphNode),
         Throws.ArgumentException.And.Property("ParamName").EqualTo("graphNode"));
 }
        public void Test_IsParent_ChildsParent()
        {
            GraphNode<string> parentGraphNode = new GraphNode<string>("parent");
            GraphNode<string> childGraphNode = new GraphNode<string>("child");
            parentGraphNode.AddChild(childGraphNode);

            Assert.That(childGraphNode.IsParent(parentGraphNode));
        }