// Backtracks the path from input node public IEnumerator BacktrackShortestPath(Node node, WaitForSeconds demoStepDuration) { // Start backtracking from end node back to start node while (node != null) { // Node representation listVisual.RemoveCurrentNode(); yield return(demoStepDuration); // Change color of node node.CurrentColor = UtilGraph.SHORTEST_PATH_COLOR; // Change color of edge leading to previous node Edge backtrackEdge = node.PrevEdge; if (backtrackEdge == null) { break; } backtrackEdge.CurrentColor = UtilGraph.SHORTEST_PATH_COLOR; // Set "next" node if (backtrackEdge is DirectedEdge) { ((DirectedEdge)backtrackEdge).PathBothWaysActive = true; } node = backtrackEdge.OtherNodeConnected(node); if (backtrackEdge is DirectedEdge) { ((DirectedEdge)backtrackEdge).PathBothWaysActive = false; // incase using same graph again at some point } yield return(demoStepDuration); listVisual.DestroyCurrentNode(); yield return(demoStepDuration); } }
// 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); }