Beispiel #1
0
    //  --------------------------------------- Reset methods ---------------------------------------
    public override void DestroyAndReset()
    {
        base.DestroyAndReset();

        chosenNodes           = 0;
        numberOfNodesToChoose = 0;

        // Variable reset
        backtracking       = false;
        userTestGoalActive = false;
        usingCalculator    = false;

        // Delete list visual
        listVisual.DestroyAndReset();
        updateListVisualInstruction = null;

        // Delete graph
        graphManager.DeleteGraph();

        // Reset algorithm
        graphAlgorithm.ResetSetup();

        // Pseudocode
        pseudoCodeViewer.DestroyContent();

        // Pointer
        pointer.ResetPointer();

        StartCoroutine(ActivateTaskObjects(false));

        calculator.ResetDevice();
        demoDevice.ResetDevice();
    }
Beispiel #2
0
    private IEnumerator RecursiveDFS(Node currentNode)
    {
        // Line 4: Pop node from stack
        currentNode.Traversed = true;
        ListVisualInstruction removeCurrentNode = new ListVisualInstruction(UtilGraph.REMOVE_CURRENT_NODE, instNr, currentNode, 0);

        recursiveInstructions.Add(instNr, new TraverseInstruction(UtilGraph.POP_INST, instNr++, currentNode, currentNode.PrevEdge, false, true, removeCurrentNode));

        for (int i = 0; i < currentNode.Edges.Count; i++)
        {
            Edge connectedEdge = currentNode.Edges[i];
            Node connectedNode = connectedEdge.OtherNodeConnected(currentNode);

            // Line 6: If statement (condition)
            recursiveInstructions.Add(instNr, new TraverseInstruction(UtilGraph.IF_NOT_VISITED_INST, instNr++, connectedNode, connectedEdge, false, false));
            if (!connectedNode.Visited)
            {
                connectedNode.PrevEdge = connectedEdge;

                // Line 7: Push node on top of stack
                ListVisualInstruction addConnectedNode = new ListVisualInstruction(UtilGraph.ADD_NODE, instNr, connectedNode);
                recursiveInstructions.Add(instNr, new TraverseInstruction(UtilGraph.PUSH_INST, instNr++, connectedNode, connectedEdge, true, false, addConnectedNode));

                connectedNode.Visited = true;

                // Line 9: End for-loop (comment out the next line to see the order of all the nodes traversed - not as planned, but kinda useful)
                recursiveInstructions.Add(instNr, new TraverseInstruction(UtilGraph.END_FOR_LOOP_INST, instNr++, currentNode, false, false)); // <-- instructions.Add(instNr++, new ListVisualInstruction(UtilGraph.DESTROY_CURRENT_NODE, instNr, currentNode));
                yield return(RecursiveDFS(connectedNode));
            }
            // Line 8: End if statement
            //recursiveInstructions.Add(instNr++, new TraverseInstruction(UtilGraph.END_IF_INST, instNr, connectedNode, edge, false, false));
        }
        // Line 9: End for-loop
        //recursiveInstructions.Add(instNr++, new TraverseInstruction(UtilGraph.END_FOR_LOOP_INST, instNr, currentNode, false, false)); // <-- instructions.Add(instNr++, new ListVisualInstruction(UtilGraph.DESTROY_CURRENT_NODE, instNr, currentNode));
    }
Beispiel #3
0
 public TraverseInstruction(string instruction, int instructionNr, Node node, bool visitInst, bool traverseInst, ListVisualInstruction listVisualInstruction) : base(instruction, instructionNr)
 {
     this.node                  = node;
     this.visitInst             = visitInst;
     this.traverseInst          = traverseInst;
     this.listVisualInstruction = listVisualInstruction;
 }
Beispiel #4
0
    public ShortestPathInstruction(string instruction, int instructionNr, Node currentNode, Node connectedNode, Edge currentEdge, ListVisualInstruction listVisualInstruction) : base(instruction, instructionNr)
    {
        this.currentNode   = currentNode;
        this.connectedNode = connectedNode;
        this.currentEdge   = currentEdge;

        connectedNodeOldDist       = connectedNode.Dist;
        connectedNodeNewDist       = CurrentNode.Dist + currentEdge.Cost;
        this.listVisualInstruction = listVisualInstruction;
    }
Beispiel #5
0
    public ShortestPathInstruction(string instruction, int instructionNr, Node connectedNode, Edge prevEdge, ListVisualInstruction listVisualInstruction) : base(instruction, instructionNr)
    {
        this.connectedNode = connectedNode;

        if (connectedNode.PrevEdge != null)
        {
            oldPrevEdge = connectedNode.PrevEdge;
        }

        this.prevEdge = prevEdge;
        this.listVisualInstruction = listVisualInstruction;
    }
Beispiel #6
0
    // User test backtracking
    public void ShortestPatBacktrackingInstructions(Dictionary <int, InstructionBase> instructions, int instNr)
    {
        // Start backtracking from end node back to start node
        Node node = EndNode;

        instructions.Add(instNr, new InstructionBase(UtilGraph.MARK_END_NODE, instNr++));

        // Fix list visual
        instructions.Add(instNr, new ListVisualInstruction(UtilGraph.PREPARE_BACKTRACKING, instNr++, node)); // Prepares backtracking list + moving current (end) node out of list

        // Set current node (remove from list)
        instructions.Add(instNr, new ListVisualInstruction(UtilGraph.BACKTRACK_REMOVE_CURRENT_NODE, instNr++, node));

        while (node != null)
        {
            // Backtrack by using each node's prevEdge
            Edge backtrackEdge = node.PrevEdge;

            // Stop when we reach the start node
            if (backtrackEdge == null)
            {
                break;
            }

            // Set "next" node
            if (backtrackEdge is DirectedEdge)
            {
                ((DirectedEdge)backtrackEdge).PathBothWaysActive = true;
            }

            // Set the next node via the prevEdge
            node = backtrackEdge.OtherNodeConnected(node);

            // Add instruction for traversing + list visual
            ListVisualInstruction removeCurrentNodeRep = new ListVisualInstruction(UtilGraph.BACKTRACK_REMOVE_CURRENT_NODE, instNr, node, backtrackEdge);
            instructions.Add(instNr, new TraverseInstruction(UtilGraph.BACKTRACK, instNr++, node, false, true, removeCurrentNodeRep));

            if (backtrackEdge is DirectedEdge)
            {
                ((DirectedEdge)backtrackEdge).PathBothWaysActive = false; // incase using same graph again at some point
            }
            //// Destroy node rep
            //instructions.Add(instNr++, new ListVisualInstruction(UtilGraph.DESTROY_CURRENT_NODE, instNr));
        }
        instructions.Add(instNr, new ListVisualInstruction(UtilGraph.DESTROY_CURRENT_NODE, instNr++));
        instructions.Add(instNr, new InstructionBase(Util.FINAL_INSTRUCTION, instNr++));
    }
Beispiel #7
0
    public Dictionary <int, InstructionBase> RecursiveInstructions(Node startNode)
    {
        Debug.Log("Preparing for recursive instruction farming");
        recursiveInstructions = new Dictionary <int, InstructionBase>();
        instNr = 0;

        // Line 0: Update start node
        recursiveInstructions.Add(instNr, new TraverseInstruction(Util.FIRST_INSTRUCTION, instNr++, startNode, false, false));

        // Line 2: Push start node
        startNode.Visited = true;
        ListVisualInstruction addStartNode = new ListVisualInstruction(UtilGraph.ADD_NODE, instNr, startNode);

        recursiveInstructions.Add(instNr, new TraverseInstruction(UtilGraph.PUSH_INST, instNr++, startNode, true, false, addStartNode));

        Debug.Log("Starting recursive instruction farming");
        StartCoroutine(RecursiveDFS(startNode));

        // Line 10: End while-loop
        //recursiveInstructions.Add(instNr++, new InstructionBase(UtilGraph.END_WHILE_INST, instNr));

        return(recursiveInstructions);
    }
Beispiel #8
0
    // Instructions from the New Demo/Step-by-step
    public void ExecuteInstruction(ListVisualInstruction instruction, bool increment)
    {
        switch (instruction.Instruction)
        {
        case UtilGraph.ADD_NODE:
            if (increment)
            {
                AddListObject(instruction.Node);
            }
            else
            {
                // Reverse of adding: Find node, remove it from the list, and destroy it
                NodeRepresentation nodeRep = FindNodeRepresentation(instruction.Node);
                if (nodeRep != null)
                {
                    nodeRepresentations.Remove(nodeRep);
                    Destroy(nodeRep.gameObject);
                }
            }
            break;

        case UtilGraph.PRIORITY_ADD_NODE:
            if (increment)
            {
                PriorityAdd(instruction.Node, instruction.Index);
            }
            else
            {
                NodeRepresentation nodeRep = FindNodeRepresentation(instruction.Node);
                nodeRepresentations.Remove(nodeRep);
                Destroy(nodeRep.gameObject);     // Fix other indexes????
            }
            break;

        case UtilGraph.REMOVE_CURRENT_NODE:
            if (increment)
            {
                RemoveCurrentNode();
            }
            else
            {
                // Reverse of removing current node: insert and move it back into the list
                currentNode.CurrentColor = Color.white;
                graphMain.WaitForSupportToComplete++;
                switch (listType)
                {
                case Util.QUEUE:
                    nodeRepresentations.Insert(0, currentNode);
                    currentNode.ListIndex = 0;
                    StartCoroutine(ReverseRemoveCurrentNode(currentNode, true));
                    break;

                case Util.STACK:
                    nodeRepresentations.Add(currentNode);
                    currentNode.ListIndex = nodeRepresentations.Count - 1;
                    StartCoroutine(ReverseRemoveCurrentNode(currentNode, false));
                    break;

                case Util.PRIORITY_LIST:
                    nodeRepresentations.Insert(0, currentNode);
                    currentNode.ListIndex = instruction.Index;
                    StartCoroutine(ReverseRemoveCurrentNode(currentNode, true));
                    break;
                }
            }
            break;

        case UtilGraph.DESTROY_CURRENT_NODE:
            if (increment)
            {
                DestroyCurrentNode();
            }
            else
            {
                // Reverse of destroying: Instantiate a new one and place it in the current node spot
                currentNode = CreateNodeRepresentation(instruction.Node, currentNodePoint.position, -1);
                currentNode.CurrentColor = UtilGraph.TRAVERSE_COLOR;
            }
            break;

        case UtilGraph.SET_START_NODE_DIST_TO_ZERO:
            if (!increment)
            {
                instruction.Node.Dist = UtilGraph.INF;
            }

            FindNodeRepresentation(instruction.Node).UpdateSurfaceText(UtilGraph.DIST_UPDATE_COLOR);
            break;

        case UtilGraph.HAS_NODE_REPRESENTATION:
            /* This case has two outcomes:
             * 1) If the node doesn't have any node representations in the current list, then create and add a new one
             * 2) There is currently a node representation, so update this one
             */

            Node node  = instruction.Node;
            int  index = instruction.Index;

            if (increment)
            {
                instruction.HasNodeRepresentation = HasNodeRepresentation(node);
            }

            if (!instruction.HasNodeRepresentation)     // Case 1
            {
                if (increment)
                {
                    PriorityAdd(node, index);
                }
                else
                {
                    ExecuteInstruction(new ListVisualInstruction(UtilGraph.PRIORITY_ADD_NODE, instruction.InstructionNr, node), false);
                }
            }
            else     // Case 2
            {
                if (increment)
                {
                    graphMain.WaitForSupportToComplete++;
                    StartCoroutine(UpdateValueAndPositionOf(node, index, increment));
                }
            }
            break;

        case UtilGraph.END_NODE_FOUND:
            // Start backtracking
            if (increment)
            {
                graphMain.GetTeachingAlgorithm().PseudoCodeViewer.DestroyContent();
            }
            else
            {
                graphMain.GetTeachingAlgorithm().PseudoCodeViewer.PseudoCodeSetup();
            }
            break;

        case UtilGraph.PREPARE_BACKTRACKING:
            if (increment)
            {
                CreateBackTrackList(instruction.Node);
                //RemoveCurrentNode();
            }
            else
            {
                Debug.Log("Nein....");
            }
            break;

        case UtilGraph.BACKTRACK_REMOVE_CURRENT_NODE:
            if (increment)
            {
                DestroyCurrentNode();
                RemoveCurrentNode();

                if (graphMain.Settings.Difficulty < Util.EXAMINATION)
                {
                    instruction.Node.CurrentColor = UtilGraph.SHORTEST_PATH_COLOR;

                    if (instruction.BacktrackEdge != null)
                    {
                        instruction.BacktrackEdge.CurrentColor = UtilGraph.SHORTEST_PATH_COLOR;
                    }
                }
            }
            else
            {
                instruction.Node.CurrentColor = UtilGraph.TRAVERSED_COLOR;

                if (instruction.BacktrackEdge != null)
                {
                    instruction.BacktrackEdge.CurrentColor = UtilGraph.VISITED_COLOR;
                }

                ExecuteInstruction(new ListVisualInstruction(UtilGraph.REMOVE_CURRENT_NODE, Util.NO_INSTRUCTION_NR), false);
            }

            break;

        default: Debug.Log("List visual instruction '" + instruction.Instruction + "' invalid."); break;
        }
        timeForDebugUpdate = true;
    }
Beispiel #9
0
    public Dictionary <int, InstructionBase> TraverseUserTestInstructions(Node startNode)
    {
        Dictionary <int, InstructionBase> instructions = new Dictionary <int, InstructionBase>();
        int instNr = 0;

        // Line 0: Update start node
        instructions.Add(instNr, new TraverseInstruction(Util.FIRST_INSTRUCTION, instNr++, startNode, false, false));

        // Line 1: Create emtpy list (queue)
        Queue <Node> queue = new Queue <Node>();

        instructions.Add(instNr, new InstructionBase(UtilGraph.EMPTY_LIST_CONTAINER, instNr++));

        // Line 2: Enqueue first node
        queue.Enqueue(startNode);
        startNode.Visited = true;
        ListVisualInstruction addStartNode = new ListVisualInstruction(UtilGraph.ADD_NODE, instNr, startNode);

        instructions.Add(instNr, new TraverseInstruction(UtilGraph.ENQUEUE_NODE_INST, instNr++, startNode, true, false, addStartNode));

        while (queue.Count > 0)
        {
            // Line 4: While loop
            instructions.Add(instNr, new InstructionLoop(UtilGraph.WHILE_LIST_NOT_EMPTY_INST, instNr++, queue.Count));

            // Line 5: Dequeue node
            Node currentNode = queue.Dequeue();
            currentNode.Traversed = true;

            ListVisualInstruction removeCurrentNode = new ListVisualInstruction(UtilGraph.REMOVE_CURRENT_NODE, instNr, currentNode, 0);
            instructions.Add(instNr, new TraverseInstruction(UtilGraph.DEQUEUE_NODE_INST, instNr++, currentNode, currentNode.PrevEdge, false, true, removeCurrentNode));

            // Go through each edge connected to current node
            // Line 6: For-loop update
            instructions.Add(instNr, new TraverseInstruction(UtilGraph.FOR_ALL_NEIGHBORS_INST, instNr++, currentNode, false, false)); //new InstructionLoop(UtilGraph.FOR_ALL_NEIGHBORS_INST, instNr, i, currentNode.Edges.Count, Util.NO_INDEX_VALUE));
            for (int i = 0; i < currentNode.Edges.Count; i++)
            {
                Edge edge          = currentNode.Edges[i];
                Node connectedNode = edge.OtherNodeConnected(currentNode);

                // No need to check the edge we came from
                if (edge == currentNode.PrevEdge)
                {
                    continue;
                }

                // Optimizing check
                //if (connectedNode.Visited || connectedNode.Traversed)
                //    continue;

                // Line 7: check neighbor
                instructions.Add(instNr, new TraverseInstruction(UtilGraph.IF_NOT_VISITED_INST, instNr++, connectedNode, edge, false, false)); // check if correct ***

                // Check if node has already been traversed or already is marked
                if (!connectedNode.Visited)
                {
                    // Line 8: Enqueue node
                    queue.Enqueue(connectedNode);
                    connectedNode.Visited = true;
                    ListVisualInstruction addConnectedNode = new ListVisualInstruction(UtilGraph.ADD_NODE, instNr, connectedNode);
                    instructions.Add(instNr, new TraverseInstruction(UtilGraph.ENQUEUE_NODE_INST, instNr++, connectedNode, edge, true, false, addConnectedNode));

                    // Set prev edge
                    connectedNode.PrevEdge = edge;
                }
                instructions.Add(instNr, new TraverseInstruction(UtilGraph.END_IF_INST, instNr++, connectedNode, edge, false, false));
            }
            // Line 5: Update for-loop
            instructions.Add(instNr, new InstructionLoop(UtilGraph.FOR_ALL_NEIGHBORS_INST, instNr++, UtilGraph.NEIGHBORS_VISITED));
            // Line 9: End for-loop
            instructions.Add(instNr, new TraverseInstruction(UtilGraph.END_FOR_LOOP_INST, instNr++, currentNode, false, false)); // <-- instructions.Add(instNr++, new ListVisualInstruction(UtilGraph.DESTROY_CURRENT_NODE, instNr, currentNode));
        }
        // Line 3: condition
        instructions.Add(instNr, new InstructionLoop(UtilGraph.WHILE_LIST_NOT_EMPTY_INST, instNr++, 0));
        // Line 10: end while-loop
        instructions.Add(instNr, new InstructionBase(UtilGraph.END_WHILE_INST, instNr++));

        instructions.Add(instNr, new InstructionBase(Util.FINAL_INSTRUCTION, instNr++));
        return(instructions);
    }
Beispiel #10
0
    public Dictionary <int, InstructionBase> ShortestPathUserTestInstructions(Node startNode, Node endNode)
    {
        Dictionary <int, InstructionBase> instructions = new Dictionary <int, InstructionBase>();
        int instNr = 0;

        // Line 0: (update startnode)
        instructions.Add(instNr, new InstructionBase(Util.FIRST_INSTRUCTION, instNr++));

        // Line 1: Set all vertices of G to inifity
        graphMain.GraphManager.SetAllNodesDist(UtilGraph.INF);
        instructions.Add(instNr, new InstructionBase(UtilGraph.SET_ALL_NODES_TO_INFINITY, instNr++));

        // Line 2: Create (priority) list
        List <Node> list = new List <Node>();

        instructions.Add(instNr, new InstructionBase(UtilGraph.EMPTY_LIST_CONTAINER, instNr++));

        // Line 3: Add starting node and set its cost to 0
        list.Add(startNode);
        startNode.Visited = true;
        startNode.Dist    = 0;
        ListVisualInstruction addStartNode = new ListVisualInstruction(UtilGraph.PRIORITY_ADD_NODE, instNr, startNode, 0);

        instructions.Add(instNr, new TraverseInstruction(UtilGraph.ADD_NODE, instNr++, startNode, true, false, addStartNode));

        // Line 4: Set total cost (Dist) of start node to 0
        instructions.Add(instNr, new InstructionBase(UtilGraph.SET_START_NODE_DIST_TO_ZERO, instNr++));

        while (list.Count > 0 && !objectiveFound)
        {
            // Line 5: Update while-loop
            instructions.Add(instNr, new InstructionLoop(UtilGraph.WHILE_LIST_NOT_EMPTY_INST, instNr++, list.Count));

            //
            Node currentNode = list[list.Count - 1];
            list.RemoveAt(list.Count - 1);

            // Line 6: Remove element with lowest distance
            ListVisualInstruction removeCurrentNode = new ListVisualInstruction(UtilGraph.REMOVE_CURRENT_NODE, instNr, currentNode);
            instructions.Add(instNr, new TraverseInstruction(UtilGraph.PRIORITY_REMOVE_NODE, instNr++, currentNode, false, true, removeCurrentNode));
            //instructions.Add(instNr++, new ListVisualInstruction(UtilGraph.REMOVE_CURRENT_NODE, instNr, currentNode));

            // Stop search if end node found and we dont want shortest path to all - stop when first visited instead? (not always global optimal)
            if (!shortestPathOnToAll && currentNode == endNode)
            {
                instructions.Add(instNr, new ListVisualInstruction(UtilGraph.END_NODE_FOUND, instNr++, currentNode));
                objectiveFound = true;
                break;
            }

            // Check all nodes connected with current node
            List <Edge> edges = currentNode.Edges;

            // Line 7: Update for-loop
            instructions.Add(instNr, new TraverseInstruction(UtilGraph.FOR_ALL_NEIGHBORS_INST, instNr++, currentNode, false, false));
            for (int i = 0; i < edges.Count; i++)
            {
                // Checking edge
                Edge currentEdge = edges[i];

                // Dont check edge we came from
                if (currentEdge == currentNode.PrevEdge)
                {
                    continue;
                }

                // Checking node on the other side of the edge (directed edge scenario)
                Node connectedNode = currentEdge.OtherNodeConnected(currentNode);
                if (connectedNode == null || connectedNode.Traversed)
                {
                    continue;
                }

                if (!connectedNode.Visited)
                {
                    connectedNode.Visited = true;
                }

                // Cost between nodes
                int currentDistAndEdgeCost = currentNode.Dist + currentEdge.Cost;

                // Line 8: Relax connected node
                instructions.Add(instNr, new TraverseInstruction(UtilGraph.RELAX_NEIGHBOR_NODE, instNr++, connectedNode, currentEdge, true, false));

                // Line 9: If statement
                instructions.Add(instNr, new ShortestPathInstruction(UtilGraph.IF_DIST_PLUS_EDGE_COST_LESS_THAN, instNr++, currentNode, connectedNode, currentEdge));

                // Update cost of connected node
                if (currentDistAndEdgeCost < connectedNode.Dist)
                {
                    // Line 10: Update total cost (Dist) of connected node (w)
                    connectedNode.Dist = currentDistAndEdgeCost;
                    instructions.Add(instNr, new ShortestPathInstruction(UtilGraph.UPDATE_CONNECTED_NODE_DIST, instNr++, currentNode, connectedNode, currentEdge));

                    // Line 11: Update prev edge (Prev) of connected node (w)
                    instructions.Add(instNr, new ShortestPathInstruction(UtilGraph.UPDATE_CONNECTED_NODE_PREV_EDGE, instNr++, connectedNode, currentEdge));
                    connectedNode.PrevEdge = currentEdge;


                    if (!list.Contains(connectedNode))
                    {
                        list.Add(connectedNode);
                    }

                    // Sort list such that the lowest distance node gets out first
                    list.Sort();


                    // List visual
                    int index = list.IndexOf(connectedNode);

                    // Line 12: Add to list
                    instructions.Add(instNr, new ListVisualInstruction(UtilGraph.HAS_NODE_REPRESENTATION, instNr++, connectedNode, index, UtilGraph.PRIORITY_ADD_NODE, UtilGraph.UPDATE_LIST_VISUAL_VALUE_AND_POSITION));

                    //instructions.Add(instNr++, new InstructionBase(UtilGraph.PRIORITY_ADD_NODE, instNr));
                }
                // Line 13: End if
                instructions.Add(instNr, new InstructionBase(UtilGraph.END_IF_INST, instNr++));
            }
            // Line 7: Update for-loop
            instructions.Add(instNr, new InstructionLoop(UtilGraph.FOR_ALL_NEIGHBORS_INST, instNr++, UtilGraph.NEIGHBORS_VISITED));

            // Line 14: End for-loop
            instructions.Add(instNr, new InstructionBase(UtilGraph.END_FOR_LOOP_INST, instNr++)); // <--- instructions.Add(instNr++, new ListVisualInstruction(UtilGraph.DESTROY_CURRENT_NODE, instNr, currentNode));

            currentNode.Traversed = true;
        }
        // Line 5: condition
        instructions.Add(instNr, new InstructionLoop(UtilGraph.WHILE_LIST_NOT_EMPTY_INST, instNr++, 0));
        // Line 15: End while-loop
        instructions.Add(instNr, new InstructionBase(UtilGraph.END_WHILE_INST, instNr++));

        if (objectiveFound)
        {
            graphMain.GraphManager.ShortestPatBacktrackingInstructions(instructions, instNr);
        }
        else
        {
            instructions.Add(instNr, new InstructionBase(UtilGraph.NO_PATH_FOUND, instNr++));
        }

        // Gather instruction for backtracking
        return(instructions);
    }
Beispiel #11
0
    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--;
    }
Beispiel #12
0
    public Dictionary <int, InstructionBase> TraverseUserTestInstructions(Node startNode)
    {
        Dictionary <int, InstructionBase> instructions = new Dictionary <int, InstructionBase>();
        int instNr = 0;

        // Line 0: Update start node
        instructions.Add(instNr, new TraverseInstruction(Util.FIRST_INSTRUCTION, instNr++, startNode, false, false));

        // Line 1: Create an empty list (stack)
        Stack <Node> stack = new Stack <Node>();

        instructions.Add(instNr, new InstructionBase(UtilGraph.EMPTY_LIST_CONTAINER, instNr++));

        // Line 2: Push start node
        stack.Push(startNode);
        startNode.Visited = true;
        ListVisualInstruction addStartNode = new ListVisualInstruction(UtilGraph.ADD_NODE, instNr, startNode);

        instructions.Add(instNr, new TraverseInstruction(UtilGraph.PUSH_INST, instNr++, startNode, true, false, addStartNode));

        while (stack.Count > 0)
        {
            // Line 3: Update while-loop
            instructions.Add(instNr, new InstructionLoop(UtilGraph.WHILE_LIST_NOT_EMPTY_INST, instNr++, stack.Count));

            // Line 4: Pop node from stack
            Node currentNode = stack.Pop();
            currentNode.Traversed = true;
            ListVisualInstruction removeCurrentNode = new ListVisualInstruction(UtilGraph.REMOVE_CURRENT_NODE, instNr, currentNode, 0);
            instructions.Add(instNr, new TraverseInstruction(UtilGraph.POP_INST, instNr++, currentNode, currentNode.PrevEdge, false, true, removeCurrentNode));

            // Go through each edge connected to current node
            // Line 5: Update for-loop
            instructions.Add(instNr, new TraverseInstruction(UtilGraph.FOR_ALL_NEIGHBORS_INST, instNr++, currentNode, false, false));
            for (int i = 0; i < currentNode.Edges.Count; i++)
            {
                Edge edge          = currentNode.Edges[i];
                Node connectedNode = edge.OtherNodeConnected(currentNode);

                // No need to check the edge we came from
                if (edge == currentNode.PrevEdge)
                {
                    continue;
                }

                // Optimizing check
                //if (connectedNode.Visited || connectedNode.Traversed)
                //    continue;

                // Line 6: If statement (condition)
                instructions.Add(instNr, new TraverseInstruction(UtilGraph.IF_NOT_VISITED_INST, instNr++, connectedNode, edge, false, false));

                if (!connectedNode.Visited)
                {
                    // Line 7: Push node on top of stack
                    stack.Push(connectedNode);
                    connectedNode.Visited = true;
                    ListVisualInstruction addConnectedNode = new ListVisualInstruction(UtilGraph.ADD_NODE, instNr, connectedNode);
                    instructions.Add(instNr, new TraverseInstruction(UtilGraph.PUSH_INST, instNr++, connectedNode, edge, true, false, addConnectedNode));

                    // Set prev edge
                    connectedNode.PrevEdge = edge;
                }
                // Line 8: End if statement
                instructions.Add(instNr, new TraverseInstruction(UtilGraph.END_IF_INST, instNr++, connectedNode, edge, false, false));
            }
            // Line 5: Update for-loop
            instructions.Add(instNr, new InstructionLoop(UtilGraph.FOR_ALL_NEIGHBORS_INST, instNr++, UtilGraph.NEIGHBORS_VISITED));
            // Line 9: End for-loop
            instructions.Add(instNr, new TraverseInstruction(UtilGraph.END_FOR_LOOP_INST, instNr++, currentNode, false, false)); // <-- instructions.Add(instNr++, new ListVisualInstruction(UtilGraph.DESTROY_CURRENT_NODE, instNr, currentNode));
        }
        // Line 3: condition
        instructions.Add(instNr, new InstructionLoop(UtilGraph.WHILE_LIST_NOT_EMPTY_INST, instNr++, 0));
        // Line 10: End while-loop
        instructions.Add(instNr, new InstructionBase(UtilGraph.END_WHILE_INST, instNr++));

        instructions.Add(instNr, new InstructionBase(Util.FINAL_INSTRUCTION, instNr++));
        return(instructions);
    }
Beispiel #13
0
    // 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);
    }
Beispiel #14
0
    protected override void UserTestUpdate()
    {
        // If a node is set to be visited or traversed, wait until it has been achieved
        if (userTestGoalActive && !posManager.PlayerWithinGoalPosition)
        {
            return;
        }
        else
        {
            userTestGoalActive = false;
        }

        // First check if user test setup is complete
        if (userTestManager.HasInstructions())
        {
            // If a calculation is required to progress in the algorithm
            if (algorithmName == Util.DIJKSTRA && usingCalculator)
            {
                // Check if it's in process and whether the equal button has been clicked
                if (calculator.CalculationInProcess && calculator.EqualButtonClicked)
                {
                    InstructionBase         inst   = userTestManager.GetInstruction();
                    ShortestPathInstruction spInst = null;
                    if (inst != null && inst.Instruction == UtilGraph.IF_DIST_PLUS_EDGE_COST_LESS_THAN)
                    {
                        spInst = ((ShortestPathInstruction)userTestManager.GetInstruction());
                    }
                    else
                    {
                        return;
                    }

                    // When equal buttons has been clicked, check  whether the input data is correct
                    int node1Dist = spInst.CurrentNode.Dist;
                    int edgeCost  = spInst.CurrentEdge.Cost;
                    int node2Dist = spInst.ConnectedNode.Dist;

                    bool correctUserInput = calculator.ControlUserInput(node1Dist, edgeCost, node2Dist);

                    // If input data was correct, then progress to next instruction (add only one)
                    if (correctUserInput && userTestManager.ReadyForNext != userTestManager.UserActionToProceed)
                    {
                        userTestManager.IncrementTotalCorrect();
                        userTestManager.ReadyForNext += 1;

                        ((Dijkstra)graphAlgorithm).IfStatementContent = calculator.IfStatementContent();
                        pseudoCodeViewer.SetCodeLine(((Dijkstra)graphAlgorithm).CollectLine(9), Util.BLACKBOARD_TEXT_COLOR);
                        calculator.FeedbackReceived = true;
                    }
                    else if (!calculator.FeedbackReceived)
                    {
                        userTestManager.Mistake();
                        calculator.FeedbackReceived = true;
                    }
                }
                else if (!calculator.CalculationInProcess)
                {
                    // Feedback is given on the calculator, so when calculationInProcess = false (calculation completed), we continue
                    usingCalculator       = false;
                    pointer.AllowShooting = true;
                }
            }

            // Continue when user has finished sub task, or else whenever ready
            if (userTestManager.ReadyForNext == userTestManager.UserActionToProceed)
            {
                if (graphSettings.Difficulty <= UtilGraph.LIST_VISUAL_MAX_DIFFICULTY && updateListVisualInstruction != null)
                {
                    listVisual.ExecuteInstruction(updateListVisualInstruction, true);
                    updateListVisualInstruction = null;
                }

                // Reset counter
                userTestManager.ReadyForNext = 0;

                // Check if we still have any instructions
                if (!userTestManager.HasInstructions()) // ???
                {
                    graphAlgorithm.IsTaskCompleted = true;
                }
                else
                {
                    // Still got instructions?
                    bool hasInstruction = userTestManager.IncrementToNextInstruction();

                    // Hot fix - solve in some other way?
                    if (hasInstruction)
                    {
                        userTestManager.ReadyForNext += PrepareNextInstruction(userTestManager.GetInstruction());
                    }
                }
            }

            if (Settings.UserTestScore)
            {
                blackboard.ChangeText(1, userTestManager.FillInBlackboard());
            }
        }
    }