Design an elevator control system method to pick the best elevator for a button press. Consider factors like current location, direction, and destination.
This problem focuses on designing a method within an elevator control system to efficiently select the most suitable elevator in response to a button press on a specific floor. The method needs to account for various factors such as the current location of elevators, their direction of travel, and their existing destinations.
The core component is the ElevatorController
which manages a list of Elevator
objects. When a user presses a button on a floor, the ElevatorController
's pickBestElevator
method is invoked to determine the optimal elevator to handle the request. The key elements are:
We will use in-memory data structures to represent the state of the elevators and requests. For a real-world application, this data could be stored in a database or a distributed cache.
Elevator Table
Field | Type | Description |
---|---|---|
elevatorId | INTEGER | Unique identifier for the elevator. |
currentFloor | INTEGER | The current floor the elevator is on. |
direction | ENUM | The current direction of the elevator (UP, DOWN, IDLE). |
destinationQueue | LIST | A list of floors the elevator is scheduled to visit, ordered by the sequence in which they will be visited. |
status | ENUM | The current status of the elevator (ACTIVE, INACTIVE, MAINTENANCE). Inactive or maintenance elevators should not be considered for requests. |
This system primarily involves internal logic for elevator management, so external API endpoints are limited. However, for monitoring and control, we could define the following endpoints:
GET /elevators
: Returns the status of all elevators.
[
{
"elevatorId": 1,
"currentFloor": 3,
"direction": "UP",
"destinationQueue": [5, 8],
"status": "ACTIVE"
},
{
"elevatorId": 2,
"currentFloor": 7,
"direction": "IDLE",
"destinationQueue": [],
"status": "ACTIVE"
}
]
POST /request
: Accepts a new floor request.
Request:
{
"sourceFloor": 2,
"direction": "UP"
}
Response:
{
"elevatorId": 2
}
pickBestElevator
import java.util.ArrayList;
import java.util.List;
import java.util.Comparator;
enum Direction {UP, DOWN, IDLE}
enum Status {ACTIVE, INACTIVE, MAINTENANCE}
class Elevator {
int elevatorId;
int currentFloor;
Direction direction;
List<Integer> destinationQueue;
Status status;
public Elevator(int elevatorId, int currentFloor, Direction direction, Status status) {
this.elevatorId = elevatorId;
this.currentFloor = currentFloor;
this.direction = direction;
this.destinationQueue = new ArrayList<>();
this.status = status;
}
// Getters and setters
public int distanceTo(int floor) {
return Math.abs(currentFloor - floor);
}
}
class ElevatorController {
List<Elevator> elevators;
public ElevatorController(int numberOfElevators) {
this.elevators = new ArrayList<>();
for (int i = 0; i < numberOfElevators; i++) {
elevators.add(new Elevator(i, 1, Direction.IDLE, Status.ACTIVE)); // Initialize all elevators at floor 1
}
}
public Elevator pickBestElevator(int sourceFloor, Direction requestDirection) {
List<Elevator> availableElevators = new ArrayList<>();
for (Elevator elevator : elevators) {
if (elevator.status == Status.ACTIVE) {
availableElevators.add(elevator);
}
}
if (availableElevators.isEmpty()) {
return null; // No available elevators
}
Elevator bestElevator = availableElevators.stream()
.min(Comparator.comparingDouble(elevator -> calculateCost(elevator, sourceFloor, requestDirection)))
.orElse(null);
if (bestElevator != null) {
bestElevator.destinationQueue.add(sourceFloor);
bestElevator.destinationQueue.sort(Comparator.comparingInt(i -> i)); //Sort the queue
if (bestElevator.currentFloor < sourceFloor) {
bestElevator.direction = Direction.UP;
} else if (bestElevator.currentFloor > sourceFloor) {
bestElevator.direction = Direction.DOWN;
}
}
return bestElevator;
}
private double calculateCost(Elevator elevator, int sourceFloor, Direction requestDirection) {
double cost = elevator.distanceTo(sourceFloor);
// Penalize elevators moving away from the requested floor
if (elevator.direction == Direction.UP && elevator.currentFloor > sourceFloor) {
cost += 50; // Arbitrary penalty
} else if (elevator.direction == Direction.DOWN && elevator.currentFloor < sourceFloor) {
cost += 50; // Arbitrary penalty
}
// Reward idle elevators
if (elevator.direction == Direction.IDLE) {
cost -= 20; // Arbitrary reward
}
return cost;
}
public static void main(String[] args) {
ElevatorController controller = new ElevatorController(3);
Elevator bestElevator = controller.pickBestElevator(5, Direction.UP);
if (bestElevator != null) {
System.out.println("Best elevator: " + bestElevator.elevatorId);
} else {
System.out.println("No elevators available.");
}
}
}
Feature | Pros | Cons |
---|---|---|
Cost-Based Selection | Optimizes for minimal waiting time, balances elevator usage. | Requires careful tuning of cost factors; may not be perfectly fair in all scenarios. |
Prioritizing Idle Elevators | Prevents elevators from being idle for extended periods, improving overall system efficiency. | May lead to sub-optimal choices if an elevator slightly further away is already moving in the right direction. |
In-Memory Data | Simple and fast for prototyping. | Not suitable for large-scale systems; data is lost on system failure. |