enum ElevatorState {
MOVING_UP, MOVING_DOWN, IDLE
}
enum Direction {
UP, DOWN
}
class Request {
private int sourceFloor;
private Direction direction;
public Request(int sourceFloor, Direction direction) {
this.sourceFloor = sourceFloor;
this.direction = direction;
}
public int getSourceFloor() { return sourceFloor; }
public Direction getDirection() { return direction; }
}
class Elevator {
private int currentFloor;
private ElevatorState state;
private TreeSet upRequests = new TreeSet<>();
private TreeSet downRequests = new TreeSet<>(Comparator.reverseOrder());
public Elevator() {
this.currentFloor = 0;
this.state = ElevatorState.IDLE;
}
public void addRequest(int floor) {
if (floor > currentFloor) {
upRequests.add(floor);
} else if (floor < currentFloor) {
downRequests.add(floor);
}
}
public void addInternalRequest(int destinationFloor) {
addRequest(destinationFloor);
}
/**
* Simulates the elevator's state transition.
*
* IDLE:
* - Move to MOVING_UP if upRequests exist
* - Move to MOVING_DOWN if no upRequests but downRequests exist
*
* MOVING_UP:
* - Increment currentFloor
* - Stop if currentFloor is in upRequests, remove it, allow destination input
* - If upRequests are empty, switch to MOVING_DOWN if downRequests exist
* - Else, return to IDLE
*
* MOVING_DOWN:
* - Decrement currentFloor
* - Stop if currentFloor is in downRequests, remove it, allow destination input
* - If downRequests are empty, switch to MOVING_UP if upRequests exist
* - Else, return to IDLE
*/
public void step() {
if (state == ElevatorState.IDLE) {
if (!upRequests.isEmpty()) {
state = ElevatorState.MOVING_UP;
} else if (!downRequests.isEmpty()) {
state = ElevatorState.MOVING_DOWN;
} else {
return;
}
}
if (state == ElevatorState.MOVING_UP) {
currentFloor++;
System.out.println("Elevator moving up to floor: " + currentFloor);
if (upRequests.remove(currentFloor)) {
System.out.println("Stopping at floor: " + currentFloor);
int destination = simulateUserDestination();
addInternalRequest(destination);
}
if (upRequests.isEmpty() && !downRequests.isEmpty()) {
state = ElevatorState.MOVING_DOWN;
} else if (upRequests.isEmpty()) {
state = ElevatorState.IDLE;
}
} else if (state == ElevatorState.MOVING_DOWN) {
currentFloor--;
System.out.println("Elevator moving down to floor: " + currentFloor);
if (downRequests.remove(currentFloor)) {
System.out.println("Stopping at floor: " + currentFloor);
int destination = simulateUserDestination();
addInternalRequest(destination);
}
if (downRequests.isEmpty() && !upRequests.isEmpty()) {
state = ElevatorState.MOVING_UP;
} else if (downRequests.isEmpty()) {
state = ElevatorState.IDLE;
}
}
}
private int simulateUserDestination() {
Random random = new Random();
int destination = random.nextInt(10);
while (destination == currentFloor) {
destination = random.nextInt(10);
}
System.out.println("User entered destination floor: " + destination);
return destination;
}
public int getCurrentFloor() { return currentFloor; }
public ElevatorState getState() { return state; }
}
class ElevatorController {
private List elevators;
public ElevatorController(int numberOfElevators) {
elevators = new ArrayList<>();
for (int i = 0; i < numberOfElevators; i++) {
elevators.add(new Elevator());
}
}
public void handleExternalRequest(Request request) {
Elevator bestElevator = findBestElevator(request.getSourceFloor(), request.getDirection());
bestElevator.addRequest(request.getSourceFloor());
}
/**
* Selects the best elevator for the request.
* Priority is given to elevators that:
* - Are IDLE
* - Are moving in the same direction as the request and heading towards the request floor
* - Otherwise, selects the closest elevator by default
*/
private Elevator findBestElevator(int floor, Direction direction) {
Elevator selected = null;
int minDistance = Integer.MAX_VALUE;
for (Elevator elevator : elevators) {
int distance = Math.abs(elevator.getCurrentFloor() - floor);
boolean suitable = false;
if (elevator.getState() == ElevatorState.IDLE) {
suitable = true;
} else if (elevator.getState() == ElevatorState.MOVING_UP && direction == Direction.UP && elevator.getCurrentFloor() <= floor) {
suitable = true;
} else if (elevator.getState() == ElevatorState.MOVING_DOWN && direction == Direction.DOWN && elevator.getCurrentFloor() >= floor) {
suitable = true;
}
if (suitable && distance < minDistance) {
minDistance = distance;
selected = elevator;
}
}
return selected != null ? selected : elevators.get(0);
}
public void stepAllElevators() {
for (Elevator elevator : elevators) {
elevator.step();
System.out.println("Elevator at floor: " + elevator.getCurrentFloor() + " State: " + elevator.getState());
}
}
}
/**
* ElevatorSystemDemo demonstrates the elevator system by initializing a controller,
* submitting some example external requests, and simulating the elevator steps over time.
*/
public class ElevatorSystemDemo {
public static void main(String[] args) throws InterruptedException {
ElevatorController controller = new ElevatorController(3);
controller.handleExternalRequest(new Request(5, Direction.UP));
controller.handleExternalRequest(new Request(2, Direction.DOWN));
for (int i = 0; i < 15; i++) {
System.out.println("Step " + i);
controller.stepAllElevators();
Thread.sleep(1000);
}
}
}