package commandSystem; import java.util.ArrayList; import java.util.Collections; import Events.Event; import Events.EventType; public class BasicInstructionQueue implements InstructionQueue { private ArrayList upQueue = new ArrayList<>(); private ArrayList downQueue = new ArrayList<>(); private boolean emergencyState; private int currentFloor; private Direction currentDirection; public BasicInstructionQueue() { upQueue = new ArrayList(); downQueue = new ArrayList(); emergencyState = false; currentFloor = 0; currentDirection = Direction.UP; } public boolean computeEvent(Event event) { boolean haveToWait = false; /* * Emergency state prevents any event from affecting the queue except the cancel * emergency stop event. */ if (emergencyState && event.getType() != EventType.CANCELEMERGENCYSTOP) return haveToWait; switch (event.getType()) { /* * The elevator will have to stop at this floor when it's headed in the same * direction the call is directed to. */ case CALLFROMFLOOR: if (currentFloor == event.getIncomingCallFloor()) break; switch (event.getRequestedDirection()) { /* * Adds the instruction to the upQueue then sorts it. */ case UP: if (!upQueue.contains(event.getIncomingCallFloor())) appSort(upQueue, event.getIncomingCallFloor(), false); break; /* * Adds the instruction to the downQueue then sorts it. */ case DOWN: if (!downQueue.contains(event.getIncomingCallFloor())) appSort(downQueue, event.getIncomingCallFloor(), true); break; default: break; } break; /* * If the requested floor is under the elevator, adds the instruction to the * downQueue then sorts it. if it's above, adds the instruction to the upQueue * then sorts it. If it's the same floor, doesn't do anything. */ case CALLFROMELEVATOR: if (event.getRequestedFloor() > currentFloor && !upQueue.contains(event.getRequestedFloor())) appSort(upQueue, event.getRequestedFloor(), false); else if (event.getRequestedFloor() < currentFloor && !upQueue.contains(event.getRequestedFloor())) appSort(downQueue, event.getRequestedFloor(), true); break; /* * Puts emergencyState to true. Blocks every event from affecting the queue and * clears it. */ case EMERGENCYSTOP: emergencyState = true; clearQueues(); break; /* * Puts emergencyState to false. Unblocks events. */ case CANCELEMERGENCYSTOP: emergencyState = false; break; /* * Refreshes the local values of current floor and current rrentFloodirection with the * ones given by the event. These values will */ case REACHEDFLOORSIGNAL: currentFloor = event.getCurrentFloor(); currentDirection = event.getCurrentDirection(); if (currentFloor == getNextInstruction()) { removeInstruction(currentFloor); haveToWait = true; } break; default: break; } return haveToWait; } /** * Returns the next floor the elevator has to go to * * @return the next floor if it exists, else -1 */ public int getNextInstruction() { int nextFloor = -1; // System.out.println("we go " + currentDirection + " current floor: " + currentFloor + " queues: " + upQueue + downQueue); switch (currentDirection) { // get the first element of upQueue that is ABOVE the elevator's current floor case UP: for (int i = 0; i < upQueue.size() && nextFloor < 0; i++) { if (upQueue.get(i) >= currentFloor) { nextFloor = upQueue.get(i); } } // change direction if every floor in upQueue is UNDER the elevator's current // floor if (nextFloor < 0 && downQueue.size() > 0) { nextFloor = downQueue.get(0); } if (nextFloor < 0 && upQueue.size() > 0) { nextFloor = upQueue.get(0); } break; // get the first element of downQueue that is UNDER the elevator's current floor case DOWN: for (int i = 0; i < downQueue.size() && nextFloor < 0; i++) { if (downQueue.get(i) <= currentFloor) { nextFloor = downQueue.get(i); } } // change direction if every floor in downQueue is ABOVE the elevator's current // floor if (nextFloor < 0 && upQueue.size() > 0) { nextFloor = upQueue.get(0); } if (nextFloor < 0 && downQueue.size() > 0) { nextFloor = downQueue.get(0); } break; default: break; } return nextFloor; } /** * Adds a new floor to the argument's queue then sorts the elements. * * @param queue the list to be sorted. * @param floor the index of the floor that will be added. * @param reversed if set to true, the queue will be sorted by descending order. */ private void appSort(ArrayList queue, int floor, boolean reversed) { queue.add(floor); if (reversed) Collections.sort(queue, Collections.reverseOrder()); else Collections.sort(queue); } /** * Removes one instruction from the queue - has to be called when the elevator * reaches targeted floor. * * @param floor the reached floor. * @param currentDirection the direction of the elevator. */ private void removeInstruction(int floor) { switch (currentDirection) { /* current floor: 0 queues: [0, 1, 2, 3][4, 3, 2, 1] Next instruction: 0 * Elevator is headed upwards. */ case UP: if (upQueue.contains(floor)) upQueue.remove(upQueue.indexOf(floor)); else downQueue.remove(downQueue.indexOf(floor)); break; /* * Elevator is headed downwards. */ case DOWN: if (downQueue.contains(floor)) downQueue.remove(downQueue.indexOf(floor)); else upQueue.remove(upQueue.indexOf(floor)); break; default: break; } // eliminate floor if next instruction is floor because already satisfied if (getNextInstruction() == floor) { removeInstruction(floor); } } /** * Clears both queues. */ private void clearQueues() { downQueue.removeAll(downQueue); upQueue.removeAll(upQueue); } }