Skip to content

Instantly share code, notes, and snippets.

@cahilfoley
Created August 2, 2019 14:49
Show Gist options
  • Save cahilfoley/e360d4f6feab499b284ea10b0f1386fa to your computer and use it in GitHub Desktop.
Save cahilfoley/e360d4f6feab499b284ea10b0f1386fa to your computer and use it in GitHub Desktop.
Elevator Saga
{
init: function(elevators, floors) {
const priorities = {
CAPACITY: 'CAPACITY',
DISTANCE: 'DISTANCE',
WAITING: 'WAITING'
}
const priority = priorities.DISTANCE
const needsPickup = floors.reduce((acc, floor) => {
acc[floor.floorNum()] = {
waiting: 0,
lastVisit: Date.now()
}
return acc
}, {})
function pickNextFloor(currentFloor = 0) {
return (floors
.map(floor => {
const floorNum = floor.floorNum()
return {
floor: floorNum,
distance: Math.abs(currentFloor - floorNum),
numWaiting: needsPickup[floorNum].waiting,
lastVisit: needsPickup[floorNum].lastVisit
}
})
.filter(floor => floor.numWaiting > 0)
.sort((a, b) => {
switch (priority) {
case priorities.CAPACITY:
return a.numWaiting - b.numWaiting
case priorities.WAITING:
return a.lastVisit - b.lastVisit
case priorities.DISTANCE:
return a.distance - b.distance
default:
return (a.waiting + a.distance) - (b.waiting + b.distance)
}
})[0] || {}).floor
}
function queueFloor(floorNum) {
needsPickup[floorNum].waiting++
console.log('queueFloor', floorNum, needsPickup)
elevators.forEach(elevator => elevator.processQueue())
}
elevators.forEach(elevator => {
elevator.processQueue = function() {
console.log('processing queue', elevator)
if (elevator.destinationQueue.length === 0) {
const nextStop = pickNextFloor(elevator.currentFloor())
if (typeof nextStop === 'number') elevator.goToFloor(nextStop)
}
}
elevator.on('stopped_at_floor', floorNumber => {
needsPickup[floorNumber].waiting = 0
needsPickup[floorNumber].lastVisit = Date.now()
elevator.destinationQueue = elevator.destinationQueue.filter(stop => stop !== floorNumber)
const floorDistances = elevator.destinationQueue.map(floor => {
return {
floor,
distance: Math.abs(floorNumber - floor),
numWaiting: needsPickup[floor].waiting,
lastVisit: needsPickup[floor].lastVisit
}
})
elevator.destinationQueue = floorDistances
.sort((a, b) => {
switch (priority) {
case priorities.CAPACITY:
return a.numWaiting - b.numWaiting
case priorities.WAITING:
return a.lastVisit - b.lastVisit
case priorities.DISTANCE:
return a.distance - b.distance
default:
return (a.waiting + a.distance) - (b.waiting + b.distance)
}
})
.map(({ floor }) => floor)
elevator.checkDestinationQueue()
elevator.processQueue()
})
elevator.on('floor_button_pressed', elevator.goToFloor)
})
floors.forEach(floor => {
const queueThisFloor = () => queueFloor(floor.floorNum())
floor.on('up_button_pressed', queueThisFloor)
floor.on('down_button_pressed', queueThisFloor)
})
},
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