/// <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; }
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)); }