private void UpdateNodeStatus(InstructionBase instruction) { if (instruction is TraverseInstruction) { TraverseInstruction travInst = (TraverseInstruction)instruction; // If visit (shoot at node) if (travInst.VisitInst) { visitNextMove = true; animator.SetBool(UtilGraph.NODE_VISIT_ANIMATION, true); } // This node is the next to be traversed (player move to node) if (travInst.TraverseInst) { traverseNextMove = true; animator.SetBool(UtilGraph.NODE_TRAVERSE_ANIMATION, true); } } }
// BFS / DFS Shares most of instructions protected IEnumerator UserTestHighlightTraverse(InstructionBase instruction) { Node currentNode = null, connectedNode = null; // Gather information from instruction if (instruction is TraverseInstruction) { TraverseInstruction travInst = (TraverseInstruction)instruction; switch (instruction.Instruction) { case UtilGraph.IF_NOT_VISITED_INST: case UtilGraph.END_IF_INST: connectedNode = travInst.Node; break; case UtilGraph.ENQUEUE_NODE_INST: case UtilGraph.PUSH_INST: if (travInst.Node != graphMain.GraphManager.StartNode) { connectedNode = travInst.Node; } else { currentNode = travInst.Node; } break; default: currentNode = travInst.Node; break; } edge = travInst.PrevEdge; } else if (instruction is InstructionLoop) { i = ((InstructionLoop)instruction).I; } // Remove highlight from previous instruction pseudoCodeViewer.ChangeColorOfText(prevHighlightedLineOfCode, Util.BLACKBOARD_TEXT_COLOR); // Gather part of code to highlight int lineOfCode = Util.NO_VALUE; useHighlightColor = Util.HIGHLIGHT_STANDARD_COLOR; switch (instruction.Instruction) { case Util.FIRST_INSTRUCTION: SetNodePseudoCode(currentNode, 0); lineOfCode = 0; break; case UtilGraph.EMPTY_LIST_CONTAINER: lineOfCode = 1; break; case UtilGraph.ENQUEUE_NODE_INST: // BFS case UtilGraph.PUSH_INST: // DFS useHighlightColor = Util.HIGHLIGHT_USER_ACTION; if (!startNodeAdded) { lineOfCode = 2; SetNodePseudoCode(currentNode, 1); startNodeAdded = true; } else { lineOfCode = 7; SetNodePseudoCode(connectedNode, 2); } break; case UtilGraph.WHILE_LIST_NOT_EMPTY_INST: lineOfCode = 3; lengthOfList = i.ToString(); useHighlightColor = UseConditionColor(i != 0); break; case UtilGraph.DEQUEUE_NODE_INST: // BFS case UtilGraph.POP_INST: // DFS lineOfCode = 4; SetNodePseudoCode(currentNode, 1); useHighlightColor = Util.HIGHLIGHT_USER_ACTION; break; case UtilGraph.FOR_ALL_NEIGHBORS_INST: lineOfCode = 5; if (i != UtilGraph.NEIGHBORS_VISITED) { SetNodePseudoCode(((TraverseInstruction)instruction).Node, 1); } useHighlightColor = UseConditionColor(i != UtilGraph.NEIGHBORS_VISITED); break; case UtilGraph.IF_NOT_VISITED_INST: lineOfCode = 6; SetNodePseudoCode(connectedNode, 2); useHighlightColor = UseConditionColor(!connectedNode.Visited); break; case UtilGraph.END_IF_INST: lineOfCode = 8; break; case UtilGraph.END_FOR_LOOP_INST: lineOfCode = 9; break; case UtilGraph.END_WHILE_INST: lineOfCode = 10; break; } prevHighlightedLineOfCode = lineOfCode; // Highlight part of code in pseudocode yield return(HighlightPseudoCode(CollectLine(lineOfCode), useHighlightColor)); graphMain.WaitForSupportToComplete--; }
// BFS / DFS Shares most of instructions protected IEnumerator ExecuteDemoTraverseAlgorithm(InstructionBase instruction, bool increment) { Node currentNode = null, connectedNode = null; // Gather information from instruction if (instruction is TraverseInstruction) { TraverseInstruction travInst = (TraverseInstruction)instruction; switch (instruction.Instruction) { case UtilGraph.IF_NOT_VISITED_INST: case UtilGraph.END_IF_INST: connectedNode = travInst.Node; break; case UtilGraph.ENQUEUE_NODE_INST: case UtilGraph.PUSH_INST: if (travInst.Node != graphMain.GraphManager.StartNode) { connectedNode = travInst.Node; } else { currentNode = travInst.Node; } break; default: currentNode = travInst.Node; break; } edge = travInst.PrevEdge; // Do list visual instruction if there is one if (travInst.ListVisualInstruction != null) { graphMain.ListVisual.ExecuteInstruction(travInst.ListVisualInstruction, increment); } } else if (instruction is InstructionLoop) { i = ((InstructionLoop)instruction).I; } // Remove highlight from previous instruction pseudoCodeViewer.ChangeColorOfText(prevHighlightedLineOfCode, Util.BLACKBOARD_TEXT_COLOR); // Gather part of code to highlight int lineOfCode = Util.NO_VALUE; useHighlightColor = Util.HIGHLIGHT_STANDARD_COLOR; switch (instruction.Instruction) { case Util.FIRST_INSTRUCTION: lineOfCode = 0; if (increment) { SetNodePseudoCode(currentNode, 0); } else { startNodeAlpha = 's'; } break; case UtilGraph.EMPTY_LIST_CONTAINER: lineOfCode = 1; break; case UtilGraph.ENQUEUE_NODE_INST: // BFS case UtilGraph.PUSH_INST: // DFS if (increment) { if (!startNodeAdded) { lineOfCode = 2; SetNodePseudoCode(currentNode, 1); startNodeAdded = true; } else { lineOfCode = 7; SetNodePseudoCode(connectedNode, 2); connectedNode.Visited = ((TraverseInstruction)instruction).VisitInst; if (edge != null) { edge.CurrentColor = UtilGraph.VISITED_COLOR; } } } else { if (connectedNode == null) { startNodeAdded = false; } if (!startNodeAdded) { lineOfCode = 2; startNodeAlpha = 's'; // SetNodePseudoCode(currentNode, 1); } else { lineOfCode = 7; connectedNode.Visited = !((TraverseInstruction)instruction).VisitInst; if (edge != null) { SetNodePseudoCode(connectedNode, 2); edge.CurrentColor = Util.STANDARD_COLOR; } else { node2Alpha = 'v'; startNodeAdded = false; } } } break; case UtilGraph.WHILE_LIST_NOT_EMPTY_INST: lineOfCode = 3; lengthOfList = i.ToString(); useHighlightColor = UseConditionColor(i != 0); break; case UtilGraph.DEQUEUE_NODE_INST: // BFS case UtilGraph.POP_INST: // DFS lineOfCode = 4; if (increment) { SetNodePseudoCode(currentNode, 1); currentNode.CurrentColor = UtilGraph.TRAVERSE_COLOR; if (edge != null) { edge.CurrentColor = UtilGraph.TRAVERSED_COLOR; } } else { node1Alpha = 'w'; currentNode.CurrentColor = UtilGraph.VISITED_COLOR; if (edge != null) { edge.CurrentColor = UtilGraph.VISITED_COLOR; } } break; case UtilGraph.FOR_ALL_NEIGHBORS_INST: lineOfCode = 5; if (increment) { if (i != UtilGraph.NEIGHBORS_VISITED) { SetNodePseudoCode(((TraverseInstruction)instruction).Node, 1); } useHighlightColor = UseConditionColor(i != UtilGraph.NEIGHBORS_VISITED); } else { if (currentNode == startNode) { node1Alpha = 'w'; } } break; case UtilGraph.IF_NOT_VISITED_INST: lineOfCode = 6; if (increment) { SetNodePseudoCode(connectedNode, 2); useHighlightColor = UseConditionColor(!connectedNode.Visited); if (edge != null) { connectedNode.PrevEdge = edge; edge.CurrentColor = UtilGraph.TRAVERSE_COLOR; } connectedNode.CurrentColor = UtilGraph.TRAVERSE_COLOR; } else { node2Alpha = 'v'; connectedNode.CurrentColor = connectedNode.PrevColor; if (edge != null) { edge.CurrentColor = edge.PrevColor; } } break; case UtilGraph.END_IF_INST: lineOfCode = 8; if (increment) { if (connectedNode.CurrentColor == UtilGraph.TRAVERSE_COLOR) { connectedNode.CurrentColor = connectedNode.PrevColor; if (edge != null) { edge.CurrentColor = edge.PrevColor; } } } else { connectedNode.CurrentColor = connectedNode.PrevColor; if (edge != null) { edge.CurrentColor = edge.PrevColor; } } break; case UtilGraph.END_FOR_LOOP_INST: lineOfCode = 9; currentNode.Traversed = increment; // Destroy current node in list visual / Recreate it graphMain.ListVisual.ExecuteInstruction(new ListVisualInstruction(UtilGraph.DESTROY_CURRENT_NODE, Util.NO_INSTRUCTION_NR, currentNode), increment); break; case UtilGraph.END_WHILE_INST: lineOfCode = 10; IsTaskCompleted = increment; break; } prevHighlightedLineOfCode = lineOfCode; // Highlight part of code in pseudocode pseudoCodeViewer.SetCodeLine(CollectLine(lineOfCode), useHighlightColor); yield return(demoStepDuration); graphMain.WaitForSupportToComplete--; }
public override IEnumerator ExecuteDemoInstruction(InstructionBase instruction, bool increment) { Node currentNode = null, connectedNode = null; Edge currentEdge = null, prevEdge = null; // Gather information from instruction if (instruction is TraverseInstruction) { TraverseInstruction travInst = (TraverseInstruction)instruction; if (instruction.Instruction == UtilGraph.ADD_NODE || instruction.Instruction == UtilGraph.PRIORITY_REMOVE_NODE || instruction.Instruction == UtilGraph.FOR_ALL_NEIGHBORS_INST) { currentNode = travInst.Node; } else { connectedNode = travInst.Node; } currentEdge = travInst.PrevEdge; // Do list visual instruction if there is one if (travInst.ListVisualInstruction != null) { graphMain.ListVisual.ExecuteInstruction(travInst.ListVisualInstruction, increment); } } else if (instruction is ShortestPathInstruction) { ShortestPathInstruction spInst = (ShortestPathInstruction)instruction; currentNode = spInst.CurrentNode; connectedNode = spInst.ConnectedNode; currentEdge = spInst.CurrentEdge; prevEdge = spInst.PrevEdge; // Do list visual instruction if there is one if (spInst.ListVisualInstruction != null) { graphMain.ListVisual.ExecuteInstruction(spInst.ListVisualInstruction, increment); } } else if (instruction is InstructionLoop) { i = ((InstructionLoop)instruction).I; //j = ((InstructionLoop)instruction).J; //k = ((InstructionLoop)instruction).K; } // Remove highlight from previous instruction pseudoCodeViewer.ChangeColorOfText(prevHighlightedLineOfCode, Util.BLACKBOARD_TEXT_COLOR); // Gather part of code to highlight int lineOfCode = Util.NO_VALUE; useHighlightColor = Util.HIGHLIGHT_STANDARD_COLOR; switch (instruction.Instruction) { case Util.FIRST_INSTRUCTION: lineOfCode = 0; if (increment) { SetNodePseudoCode(graphMain.GraphManager.StartNode, 0); } else { startNodeAlpha = 's'; } break; case UtilGraph.SET_ALL_NODES_TO_INFINITY: lineOfCode = 1; if (increment) { graphMain.GraphManager.SetAllNodesDist(UtilGraph.INF); } else { graphMain.GraphManager.SetAllNodesDist(UtilGraph.INIT_NODE_DIST); } break; case UtilGraph.EMPTY_LIST_CONTAINER: lineOfCode = 2; break; case UtilGraph.ADD_NODE: SetNodePseudoCode(currentNode, 0); // start node lineOfCode = 3; if (increment) { currentNode.Visited = ((TraverseInstruction)instruction).VisitInst; } else { currentNode.Visited = !((TraverseInstruction)instruction).VisitInst; } break; case UtilGraph.SET_START_NODE_DIST_TO_ZERO: lineOfCode = 4; if (increment) { startNode.Dist = 0; } else { startNode.Dist = UtilGraph.INF; } // Update list visual ListVisualInstruction setStartNodeToZero = new ListVisualInstruction(UtilGraph.SET_START_NODE_DIST_TO_ZERO, 0, startNode, 0); graphMain.ListVisual.ExecuteInstruction(setStartNodeToZero, increment); break; case UtilGraph.WHILE_LIST_NOT_EMPTY_INST: lineOfCode = 5; lengthOfList = i.ToString(); useHighlightColor = UseConditionColor(i != 0); break; case UtilGraph.PRIORITY_REMOVE_NODE: lineOfCode = 6; if (increment) { // Hide all edge cost to make it easier to see node distances graphMain.GraphManager.MakeEdgeCostVisible(false); SetNodePseudoCode(currentNode, 1); yield return(demoStepDuration); // Show the next node we'll work from currentNode.CurrentColor = UtilGraph.TRAVERSE_COLOR; currentNode.DisplayEdgeCost(true); // Display edge costs again graphMain.GraphManager.MakeEdgeCostVisible(true); } else { currentNode.CurrentColor = UtilGraph.VISITED_COLOR; currentNode.DisplayEdgeCost(false); } break; case UtilGraph.FOR_ALL_NEIGHBORS_INST: lineOfCode = 7; if (increment) { if (i != UtilGraph.NEIGHBORS_VISITED) { SetNodePseudoCode(currentNode, 1); } useHighlightColor = UseConditionColor(i != UtilGraph.NEIGHBORS_VISITED); } else { if (currentNode == startNode) { node1Alpha = 'w'; } } break; case UtilGraph.RELAX_NEIGHBOR_NODE: SetNodePseudoCode(connectedNode, 2); lineOfCode = 8; if (increment) { connectedNode.Visited = ((TraverseInstruction)instruction).VisitInst; if (currentEdge != null) { currentEdge.CurrentColor = UtilGraph.VISITED_COLOR; } } else { connectedNode.Visited = !((TraverseInstruction)instruction).VisitInst; if (currentEdge != null) { currentEdge.CurrentColor = Util.STANDARD_COLOR; } } break; case UtilGraph.IF_DIST_PLUS_EDGE_COST_LESS_THAN: lineOfCode = 9; if (increment) { SetNodePseudoCode(connectedNode, 2); edgeCost = currentEdge.Cost; ifStatementContent = CreateIfStatementContent(currentNode.Dist, edgeCost, connectedNode.Dist); } else { // TODO } break; case UtilGraph.UPDATE_CONNECTED_NODE_DIST: lineOfCode = 10; if (increment) { connectedNode.Dist = ((ShortestPathInstruction)instruction).ConnectedNodeNewDist; } else { connectedNode.Dist = ((ShortestPathInstruction)instruction).ConnectedNodeOldDist; } break; case UtilGraph.UPDATE_CONNECTED_NODE_PREV_EDGE: lineOfCode = 11; if (increment) { connectedNode.PrevEdge = prevEdge; } else { connectedNode.PrevEdge = ((ShortestPathInstruction)instruction).OldPrevEdge; } break; case UtilGraph.HAS_NODE_REPRESENTATION: // update/add lineOfCode = 12; ListVisualInstruction listVisualInst = (ListVisualInstruction)instruction; graphMain.ListVisual.ExecuteInstruction(listVisualInst, increment); break; case UtilGraph.END_IF_INST: lineOfCode = 13; break; case UtilGraph.END_FOR_LOOP_INST: lineOfCode = 14; if (this.currentNode != null) { this.currentNode.Traversed = increment; } // Destroy current node in list visual graphMain.ListVisual.ExecuteInstruction(new ListVisualInstruction(UtilGraph.DESTROY_CURRENT_NODE, Util.NO_INSTRUCTION_NR, this.currentNode), increment); break; case UtilGraph.END_WHILE_INST: lineOfCode = 15; IsTaskCompleted = increment; break; } prevHighlightedLineOfCode = lineOfCode; // Highlight part of code in pseudocode yield return(HighlightPseudoCode(CollectLine(lineOfCode), useHighlightColor)); graphMain.WaitForSupportToComplete--; }
// Update the node status based on the instruction protected void UpdateNodeState() { if (nodeInstruction != null) { // Debugging instruction = nodeInstruction.Instruction; status = nodeInstruction.Status; // This node is the next to be visited (shot at) if (nodeInstruction is TraverseInstruction) { TraverseInstruction travInst = (TraverseInstruction)nodeInstruction; // If visit (shoot at node) if (travInst.VisitInst) { visitNextMove = true; if (graphMain.Settings.Difficulty <= UtilGraph.ANIMATION_DIRECTION_MAX_DIFFICULTY) { animator.SetBool("NodeCheck", true); } } // This node is the next to be traversed (player move to node) if (travInst.TraverseInst) { traverseNextMove = true; if (graphMain.Settings.Difficulty <= UtilGraph.ANIMATION_DIRECTION_MAX_DIFFICULTY) { animator.SetBool("NodeTraverse", true); } } // Set the edge between the node we traversed from to reach this node if (travInst.PrevEdge != null) { switch (algorithm) { case Util.BFS: case Util.DFS: case Util.DFS_RECURSIVE: prevEdge = travInst.PrevEdge; break; case Util.DIJKSTRA: currentEdge = travInst.PrevEdge; break; } } } else if (nodeInstruction is ShortestPathInstruction) { ShortestPathInstruction spInst = (ShortestPathInstruction)nodeInstruction; switch (spInst.Instruction) { case UtilGraph.UPDATE_CONNECTED_NODE_DIST: if (spInst.CurrentNode == this) { spInst.ConnectedNode.Dist = spInst.ConnectedNodeNewDist; } else if (spInst.ConnectedNode == this) { Dist = spInst.ConnectedNodeNewDist; } break; case UtilGraph.UPDATE_CONNECTED_NODE_PREV_EDGE: if (spInst.CurrentNode == this) { spInst.ConnectedNode.PrevEdge = spInst.PrevEdge; } else if (spInst.ConnectedNode == this) { prevEdge = spInst.PrevEdge; } break; } } } }
// User test public int PrepareNextInstruction(InstructionBase instruction) { string inst = instruction.Instruction; Debug.Log(">>> " + instruction.DebugInfo()); // First check whether the instruction contains a node and/or destination bool gotNode = !graphAlgorithm.SkipDict[Util.SKIP_NO_ELEMENT].Contains(inst); bool noDestination = graphAlgorithm.SkipDict[Util.SKIP_NO_DESTINATION].Contains(inst); // List visual Update if (instruction is ListVisualInstruction) { // Only provide list visual support until <lvl> if (graphSettings.Difficulty > UtilGraph.LIST_VISUAL_MAX_DIFFICULTY) { return(1); } ListVisualInstruction listVisualInst = (ListVisualInstruction)instruction; listVisual.ExecuteInstruction(listVisualInst, true); //Debug.Log("List visual instruction: " + listVisualInst.DebugInfo()); } else { Node node = null; if (gotNode) { if (instruction is TraverseInstruction) { TraverseInstruction traverseInstruction = (TraverseInstruction)instruction; //Debug.Log("Traverse instruction: " + traverseInstruction.DebugInfo()); // Get the Sorting element node = traverseInstruction.Node; // Hands out the next instruction node.Instruction = traverseInstruction; // Set goal posManager.CurrentGoal = node; // Reset if pointer must be used on the same node twice if (traverseInstruction.VisitInst && pointer.prevNodeShot == node) { pointer.prevNodeShot = null; } // Reset position manager if the user already stands on top of the node if (traverseInstruction.TraverseInst && posManager.ReportedNode == node) { posManager.ReportedNode = null; } // Give this sorting element permission to give feedback to progress to next intstruction node.NextMove = NextIsUserMove(inst); // Traverse instruction extra switch (inst) { // Highlight the node we are currently going to work at case UtilGraph.DEQUEUE_NODE_INST: case UtilGraph.POP_INST: case UtilGraph.PRIORITY_REMOVE_NODE: // Hide all edge cost to make it easier to see node distances if (graphSettings.GraphTask == UtilGraph.SHORTEST_PATH) { graphManager.MakeEdgeCostVisible(false); } break; case UtilGraph.FOR_ALL_NEIGHBORS_INST: // Make edge cost visible again if (graphSettings.GraphTask == UtilGraph.SHORTEST_PATH) { graphManager.MakeEdgeCostVisible(true); } break; } // Perform list visual instruction in next step (when current instruction has been correctly performed) if (traverseInstruction.ListVisualInstruction != null) { updateListVisualInstruction = traverseInstruction.ListVisualInstruction; } } else if (instruction is ShortestPathInstruction) { ShortestPathInstruction spInst = (ShortestPathInstruction)instruction; //Debug.Log("Shortest path instruction: " + spInst.DebugInfo()); // Get the Sorting element if (spInst.CurrentNode != null) { node = spInst.CurrentNode; } else { node = spInst.ConnectedNode; } // Hands out the next instruction node.Instruction = spInst; // Set goal posManager.CurrentGoal = node; // Give this sorting element permission to give feedback to progress to next intstruction node.NextMove = NextIsUserMove(inst); // Shortest path extra switch (inst) { case UtilGraph.IF_DIST_PLUS_EDGE_COST_LESS_THAN: // Turn off highlight effect of previous line pseudoCodeViewer.ChangeColorOfText(8, Util.BLACKBOARD_TEXT_COLOR); // Since we highlighted the color and/or text position of the node/edge we are working on (highlighting purpose) in the previous instruction, now we reset them // Changed color of node spInst.ConnectedNode.CurrentColor = UtilGraph.VISITED_COLOR; // Reset text color/position of the edge cost spInst.CurrentEdge.CurrentColor = UtilGraph.VISITED_COLOR; // Perform sub task: calculate dist (current node) + edge cost to the connected node if (!autoCalculation) { usingCalculator = true; pointer.AllowShooting = false; calculator.InitCalculation(Calculator.GRAPH_TASK); calculator.SpawnDeviceInfrontOfPlayer(); } break; } // Perform list visual instruction in next step (when current instruction has been correctly performed) if (spInst.ListVisualInstruction != null) { updateListVisualInstruction = spInst.ListVisualInstruction; } } } } // Display help on blackboard if (graphSettings.Difficulty <= Util.PSEUDO_CODE_HIGHTLIGHT_MAX_DIFFICULTY) { WaitForSupportToComplete++; StartCoroutine(graphAlgorithm.UserTestHighlightPseudoCode(instruction, gotNode));// && !noDestination)); } // InstructionBase extra switch (inst) { case UtilGraph.SET_ALL_NODES_TO_INFINITY: graphManager.SetAllNodesDist(UtilGraph.INF); break; case UtilGraph.SET_START_NODE_DIST_TO_ZERO: // Find start node and set distance to 0 Node startNode = graphManager.StartNode; startNode.Dist = 0; // If list visual: update value if (Settings.Difficulty <= UtilGraph.LIST_VISUAL_MAX_DIFFICULTY) { listVisual.FindNodeRepresentation(startNode).UpdateSurfaceText(UtilGraph.DIST_UPDATE_COLOR); } break; case UtilGraph.MARK_END_NODE: Node endNode = graphManager.EndNode; endNode.CurrentColor = UtilGraph.SHORTEST_PATH_COLOR; endNode.PrevEdge.CurrentColor = UtilGraph.SHORTEST_PATH_COLOR; break; case UtilGraph.END_FOR_LOOP_INST: if (graphSettings.Difficulty <= UtilGraph.LIST_VISUAL_MAX_DIFFICULTY) { listVisual.DestroyCurrentNode(); } break; case UtilGraph.NO_PATH_FOUND: case Util.FINAL_INSTRUCTION: // No path found WaitForSupportToComplete++; StartCoroutine(FinishUserTest()); break; } //Debug.Log("Got node: " + gotNode + ", no destination: " + noDestination); if (gotNode && !noDestination) { return(0); } //Debug.Log("Nothing to do for player, get another instruction"); return(1); }