Last active
May 24, 2019 15:32
-
-
Save alexander-brett/0d41143edfab2c5e735da55c794d91ed 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
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