Skip to content

Instantly share code, notes, and snippets.

@alexander-brett
Last active May 24, 2019 15:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexander-brett/0d41143edfab2c5e735da55c794d91ed to your computer and use it in GitHub Desktop.
Save alexander-brett/0d41143edfab2c5e735da55c794d91ed to your computer and use it in GitHub Desktop.
var floors = {};
var floorsVisited = {};
var elevators = [];
var idles = [];
var up = "up";
var down = "down";
function distinct (a){
return a.filter((value, index, self) => self.indexOf(value) === index);
};
function setupElevator(elevator){
//var index = elevators.push({busy: false, e: elevator, intendedDirection: null, });
elevators.push(elevator);
idles.push(elevator);
elevator.on("idle", function(){handleIdle(elevator)});
elevator.on("floor_button_pressed", function(floorNum){handleFloorButtonPressed(elevator, floorNum)});
elevator.on("passing_floor", function(floorNum, direction){handlePassingFloor(elevator, floorNum, direction)});
elevator.on("stopped_at_floor", function(floorNum){handleStoppedAtFloor(elevator, floorNum)});
};
function handleStoppedAtFloor(elevator, floorNum){
if (elevator.goingUpIndicator()){
floorsVisited[floorNum][up] = new Date().getTime();
floors[floorNum][up] = false;
}
else if (elevator.goingDownIndicator()){
floorsVisited[floorNum][down] = new Date().getTime();
floors[floorNum][down] = false;
}
};
function stopAtFloor(elevator, floorNum, direction){
if (elevator.getPressedFloors().indexOf(floorNum) !== -1){
// someone wants to get out
return true;
}
if (elevator.loadFactor() > 0.5) {
// we're pretty full rn
return false;
}
if (!floors[floorNum][direction]){
// nobody's waiting here
return false;
}
if ((direction === up) !== elevator.goingUpIndicator())
{
// we're going the opposite way to our indicator - ie trying to get somewhere
return false;
}
if (elevators.some(e => e.destinationQueue.indexOf(floorNum) !== -1 && e.destinationDirection === direction)){
// someone else is about to stop here
return false;
}
return true;
}
function handlePassingFloor(elevator, floorNum, direction){
if (stopAtFloor(elevator, floorNum, direction)){
direction === up ? setUpIndicator(elevator) : setDownIndicator;
elevator.destinationQueue = [];
elevator.goToFloor(floorNum, true);
}
};
function handleFloorButtonPressed(elevator, floorNum){
goToNextFloor(elevator);
};
function goToNextFloor(elevator){
var currentFloor = elevator.currentFloor();
var pressedFloors = elevator.getPressedFloors();
if (pressedFloors.some(f => f > currentFloor) && pressedFloors.some(f => f < currentFloor)){
throw ("bad floor arrangement");
}
if (pressedFloors[0] > currentFloor){
setUpIndicator(elevator);
elevator.destinationQueue = [];
elevator.goToFloor(elevator.getPressedFloors().sort()[0], true);
} else {
setDownIndicator(elevator);
elevator.destinationQueue = [];
elevator.goToFloor(elevator.getPressedFloors().sort().reverse()[0], true);
}
}
function goToStalestFloor(elevator){
if (Math.random() > 1){
goToFloor(elevator, 0, up);
return;
}
var stalestUp = Object.keys(floorsVisited).sort(function(a,b){
return floorsVisited[a][up]-floorsVisited[b][up]
})[0];
var stalestDown = Object.keys(floorsVisited).sort(function(a,b){
return floorsVisited[a][down]-floorsVisited[b][down]
})[0];
if (floorsVisited[stalestUp][up] < floorsVisited[stalestDown][down]){
goToFloor(elevator, stalestUp, up);
} else {
goToFloor(elevator, stalestDown, down);
}
}
function handleIdle(elevator){
if (elevator.getPressedFloors().length > 0){
goToNextFloor(elevator);
return;
}
if (!tryFindWork(elevator)){
idles.push(elevator);
//elevator.goingUpIndicator(true);
//elevator.goingDownIndicator(true);
goToStalestFloor(elevator);
}
};
function tryFindWork(elevator){
return Object.keys(floors).sort(function(a,b){
return Math.abs(a-elevator.currentFloor()) - Math.abs(b-elevator.currentFloor());
}).some(function(k){
if (idles.some(e => e.destinationQueue.indexOf(k) !== -1)){
return false;
}
if (Math.random() > 0.5){
if (floors[k][up]){
goToFloor(elevator, k, up);
return true;
}
if (floors[k][down]){
goToFloor(elevator, k, down);
return true;
}}
else{
if (floors[k][down]){
goToFloor(elevator, k, down);
return true;
}
if (floors[k][up]){
goToFloor(elevator, k, up);
return true;
}
}
});
}
function tryAssignIdle(floorNum, direction){
var elevator = idles.pop();
if (elevator){
goToFloor(elevator, floorNum, direction);
return true;
}
return false;
};
function setupFloor(floor){
var floorNum = floor.floorNum();
floors[floorNum] = {up: false, down: false};
var now = new Date().getTime();
floorsVisited[floorNum] = {up: now, down: now};
floor.on("up_button_pressed", function(){
tryAssignIdle(floorNum, up);
floors[floorNum][up] = true;
});
floor.on("down_button_pressed", function(){
tryAssignIdle(floorNum, down);
floors[floorNum][down] = true;
});
};
function setUpIndicator(elevator){
elevator.goingDownIndicator(false);
elevator.goingUpIndicator(true);
};
function setDownIndicator(elevator){
elevator.goingUpIndicator(false);
elevator.goingDownIndicator(true);
};
function goToFloor(elevator, floorNum, intendedDirection){
elevator.destinationQueue = [];
elevator.goToFloor(floorNum, true);
if (intendedDirection === up){
setUpIndicator(elevator);
} else {
setDownIndicator(elevator);
}
};
({
init: function(elevators, floors) {
elevators.forEach(setupElevator);
floors.forEach(setupFloor);
},
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