Created
July 2, 2018 10:56
-
-
Save donaldG21/e9a1e1a64534ae31af7afd7036884507 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Elevator { | |
constructor() { | |
this.currentFloor = 1; | |
this.direction = 'none'; | |
this.needsService = false; | |
this.tripCount = 0; | |
this.trip = null; | |
this.occupied = false; | |
this.destination = null; | |
this.queue = []; | |
} | |
setIdle() { | |
clearInterval(this.trip); | |
this.direction = 'none'; | |
this.occupied = false; | |
this.trip = null; | |
this.queue = []; | |
console.log('completed trip'); | |
} | |
goToNextStop() { | |
this.destination = this.nextStop(); | |
this.direction = travelDirection(this.currentFloor, this.destination); | |
if (this.direction === 'up') { | |
this.move('up'); | |
} else { | |
this.move('down'); | |
} | |
} | |
move(direction) { | |
this.trip = setInterval(() => { | |
direction === 'up' ? this.currentFloor++ : this.currentFloor--; | |
if (this.currentFloor === this.destination) { | |
if (this.queue.length === 1 && this.queue[0].dropoff) { | |
this.tripCount++; | |
return this.setIdle(); | |
} else { | |
this.completeTrip(); | |
} | |
} | |
}, 1000); | |
} | |
completeTrip() { | |
clearInterval(this.trip); | |
var indexes = [], i; | |
for(i = 0; i < this.queue.length; i++) { | |
if (this.queue[i].dropoff && (this.currentFloor == this.queue[i].destination)) { | |
indexes.push(i); | |
} else if (this.currentFloor == this.queue[i].originFloor) { | |
// person is in elevator to be dropped off | |
this.queue[i].dropoff = true; | |
} | |
} | |
for (var i in indexes) { | |
this.queue.splice(i, 1); | |
} | |
this.goToNextStop(); | |
} | |
nextStop() { | |
let floor; | |
if (this.queue.length == 1) { | |
floor = this.queue[0].dropoff ? this.queue[0].destination : this.queue[0].originFloor; | |
} else { | |
// map upcoming stops | |
let qmap = this.queue.map((q) => { | |
return this.q.dropoff ? this.queue.destination : this.queue.originFloor; | |
}); | |
// find next floor in queue in direction of elevator | |
if (this.direction === 'up') { | |
// reduce function | |
// needs tinkering to accurately ensure closest floor in direction | |
floor = qmap.reduce((prev, curr) => { | |
return (curr - c) > (prev - c) ? curr : prev; | |
}); | |
} else if (this.direction === 'down') { | |
floor = qmap.reduce((prev, curr) => { | |
return (curr - c) < (prev - c) ? curr : prev; | |
}); | |
} else { | |
floor = qmap.reduce((prev, curr) => { | |
return (Math.abs(curr - c)) < (Math.abs(prev - c)) ? curr : prev; | |
}); | |
} | |
} | |
return floor; | |
} | |
request(originFloor, destination) { | |
let req = { originFloor: originFloor, destination: destination }; | |
if (this.currentFloor === req.originFloor) { | |
req.dropoff = true; | |
this.occupied = true; | |
this.queue.push(req); | |
this.goToNextStop(); | |
} else { | |
req.dropoff = false; | |
this.queue.push(req); | |
this.goToNextStop(); | |
} | |
} | |
} | |
function callElevator(requestedFloor, destination, direction) { | |
// call unoccupied elevator if on same floor as person requested | |
let ue = elevators.findIndex(x => !x.needsService && !x.occupied && (x.currentFloor == requestedFloor)); | |
if (ue !== -1) { | |
return elevators[ue].request(requestedFloor, destination); | |
} | |
// is there an elevator going in the same direction and passing floor on its way | |
let oe = elevators.findIndex(x => !x.needsService && x.occupied && (x.direction == direction) && (isEnRoute(direction, requestedFloor, x.currentFloor, x.nextStop()))); | |
if (oe !== -1) { | |
return elevators[oe].request(requestedFloor, destination); | |
} | |
// if not, are there any unoccupied elevators TODO: account for moving | |
let emap = elevators.map((e, i) => { | |
return { index: i, floor: e.currentFloor, occupied: e.occupied, needsService: e.needsService }; | |
}).filter((e) => { return e.occupied == false && e.needsService == false }).sort((a, b) => { | |
return (a.floor > b.floor); | |
}); | |
// if so, request the closest one | |
if (emap.length > 0) { | |
let i = emap[0].index; | |
return elevators[i].request(requestedFloor, destination); | |
} | |
console.warn("No cases matched: A person was not able to request an elevator"); | |
} | |
function isEnRoute(direction, requestedFloor, eCurrentFloor, eDestination) { | |
if (direction === 'up') { | |
return (eCurrentFloor <= requestedFloor && requestedFloor <= eDestination); | |
} else { | |
return (eCurrentFloor >= requestedFloor && requestedFloor >= eDestination); | |
} | |
} | |
function travelDirection(currentFloor, destinationFloor) { | |
if (destinationFloor > currentFloor) { | |
return 'up'; | |
} else { | |
return 'down'; | |
} | |
} | |
function genRandomPerson(floors) { | |
currentFloor = Math.floor(Math.random() * (floors - 1 + 1)) + 1; | |
destinationFloor = Math.floor(Math.random() * (floors - 1 + 1)) + 1; | |
while (destinationFloor === currentFloor) { | |
destinationFloor = Math.floor(Math.random() * (floors - 1 + 1)) + 1; | |
} | |
let direction = travelDirection(currentFloor, destinationFloor); | |
callElevator(currentFloor, destinationFloor, direction); | |
} | |
function init(floors, numberOfElevators) { | |
if (numberOfElevators < 2) throw new Error("Minimum number of Elevators must be 2"); | |
const elevators = []; | |
for (i=0; i < numberOfElevators; i++) { | |
let elevator = new Elevator(); | |
elevators.push(elevator); | |
} | |
for (i=0; i<1000; i++) { | |
setTimeout(function() { | |
genRandomPerson(floors); | |
}, 1000); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment