Skip to content

Instantly share code, notes, and snippets.

@adamduren
Last active October 20, 2022 15:27
Show Gist options
  • Save adamduren/c698ac45d9ff466c19145e006c4b0d73 to your computer and use it in GitHub Desktop.
Save adamduren/c698ac45d9ff466c19145e006c4b0d73 to your computer and use it in GitHub Desktop.
Elevator Saga
{
init: function(elevators, floors) {
const DIR_UP = 'up';
const DIR_DOWN = 'down';
const pendingPickupDirectionDownFloors = new Set();
const pendingPickupDirectionUpFloors = new Set();
const buttonPressedHandlerFactory = (floor, direction) => () => {
console.log(`Button pressed on floor ${floor.floorNum()} going ${direction}`);
// If there is already an elevator on the floor, we don't need to do anything
if (elevators.some(elevator => elevator.currentFloor() === floor.floorNum())) {
console.log(`Elevator already on floor ${floor.floorNum()}`);
return;
}
// If an elevator is idle, we can just send it to the floor
for (const elevator of elevators) {
console.log(floor.floorNum(), direction, elevator.destinationQueue);
if (elevator.destinationQueue.length === 0) {
elevator.goToFloor(floor.floorNum());
if (direction === DIR_DOWN) {
elevator.goingUpIndicator(true);
} else {
elevator.goingDownIndicator(true);
}
return;
}
}
// Otherwise, we need to add the floor to the pending pickup list
if (direction === DIR_UP) {
pendingPickupDirectionUpFloors.add(floor.floorNum());
} else {
pendingPickupDirectionDownFloors.add(floor.floorNum());
}
};
const handlePassingFloorFactory = (elevator) => (floorNum, direction) => {
console.log('Passing floor', floorNum, direction);
const pendingPickupFloors = direction === DIR_UP ? pendingPickupDirectionUpFloors : pendingPickupDirectionDownFloors;
if (pendingPickupFloors.has(floorNum)) {
elevator.goToFloor(floorNum, true);
pendingPickupFloors.delete(floorNum);
// Remove floor if already in queue
const nextQueue = elevator.destinationQueue.filter((dest) => dest !== floorNum);
elevator.destinationQueue = nextQueue;
elevator.checkDestinationQueue();
}
};
const handleFloorButtonPressedFactory = (elevator) => (floorNum) => {
console.log('Floor button pressed', floorNum);
elevator.goToFloor(floorNum);
};
const handleElevatorIdleFactory = (elevator) => () => {
console.log('Elevator idle');
// Find next pickup floor
if (pendingPickupDirectionUpFloors.size > 0) {
const nextFloor = Math.min(...pendingPickupDirectionUpFloors);
elevator.goToFloor(nextFloor);
pendingPickupDirectionUpFloors.delete(nextFloor);
elevator.goingUpIndicator(true);
elevator.goingDownIndicator(false);
} else if (pendingPickupDirectionDownFloors.size > 0) {
const nextFloor = Math.max(...pendingPickupDirectionDownFloors);
elevator.goToFloor(nextFloor);
pendingPickupDirectionDownFloors.delete(nextFloor);
elevator.goingUpIndicator(false);
elevator.goingDownIndicator(true);
}
};
// Give all the elevators the same config
for (const elevator of elevators) {
// Whenever the elevator is idle (has no more queued destinations) ...
elevator.on('idle', handleElevatorIdleFactory(elevator));
elevator.on('floor_button_pressed', handleFloorButtonPressedFactory(elevator))
elevator.on('passing_floor', handlePassingFloorFactory(elevator));
}
for (const floor of floors) {
// Add to queue pickup queue when a button is pressed
floor.on('up_button_pressed', buttonPressedHandlerFactory(floor, DIR_UP));
floor.on('down_button_pressed', buttonPressedHandlerFactory(floor, DIR_DOWN));
}
},
update: function(dt, elevators, floors) {
// We normally don't need to do anything here
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment