225 lines
5.9 KiB
Java
225 lines
5.9 KiB
Java
package commandSystem;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
|
|
import Events.Event;
|
|
import Events.EventType;
|
|
|
|
public class BasicInstructionQueue implements InstructionQueue {
|
|
private ArrayList<Integer> upQueue = new ArrayList<>();
|
|
private ArrayList<Integer> downQueue = new ArrayList<>();
|
|
private boolean emergencyState;
|
|
|
|
private int currentFloor;
|
|
private Direction currentDirection;
|
|
|
|
public BasicInstructionQueue() {
|
|
|
|
upQueue = new ArrayList<Integer>();
|
|
downQueue = new ArrayList<Integer>();
|
|
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 <b>queue</b> 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<Integer> 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);
|
|
}
|
|
}
|