Skip to content

Instantly share code, notes, and snippets.

@donaldG21
Created July 2, 2018 10:56
Show Gist options
  • Save donaldG21/e9a1e1a64534ae31af7afd7036884507 to your computer and use it in GitHub Desktop.
Save donaldG21/e9a1e1a64534ae31af7afd7036884507 to your computer and use it in GitHub Desktop.
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