This repository has been archived on 2019-10-19. You can view files and clone it, but cannot push or open issues or pull requests.
projet-gl/src/commandSystem/BasicInstructionQueue.java
2019-10-19 21:44:42 +02:00

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);
}
}