Last active
June 8, 2016 16:12
-
-
Save adamnew123456/3363055402253d2915e7b1faa21bc8d6 to your computer and use it in GitHub Desktop.
Elevator Saga - Current Attempt
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
{ | |
// NOTE: Only expect this to work on FF, Chrome or Edge. | |
// There are several arrow functions sprinkled around, | |
// and caniuse suggests that these are the only browsers | |
// that can handle them natively | |
init: function(elevators, floors) { | |
// The backlog is (an approximation of) the number of people currently waiting at | |
// the given floor. | |
// | |
// Why an approximation? Well, there are places in the code where a floor's backlog | |
// is set to 0, but shouldn't be. Ocasionally, this will leave people hanging, and | |
// require some tuning for the 'let no-one wait more than X' missions. | |
var backlog = []; | |
floors.forEach((_, i) => { backlog[i] = 0 }); | |
var minList = lst => Math.min.apply(null, lst); | |
var maxList = lst => Math.max.apply(null, lst); | |
// Some challenges will have a lot of people start on a given floor, so | |
// it can pay to tune this a little bit | |
var DEFAULT_FLOOR = 0; | |
// Moves to the busiest floor, or the default floor if no floor has waiters | |
function goToBusiestFloor(elevator) { | |
var maxBacklog = maxList(backlog); | |
// Go to the middle floor, if there aren't any waiting, so that the | |
// travel time to the next floor will be lowest (on average) | |
if (maxBacklog == 0) { | |
elevator.goToFloor(DEFAULT_FLOOR); | |
} else { | |
var maxFloor = backlog.indexOf(maxBacklog); | |
elevator.goToFloor(maxFloor); | |
backlog[maxFloor] = 0; | |
} | |
} | |
function initElevator(elevator, elevatorNum) { | |
// Once the elevator is this perecent full, it will not stop | |
// to pick up new passengers | |
var PASS_FACTOR = 0.95; | |
var direction = 'down'; | |
// Changes the direction of the elevator. If new_dir is *not* given, | |
// then this swaps the direction - otherwise, the new directio is | |
// new_dir | |
function changeDirection(new_dir) { | |
other_dir = { | |
'up': 'down', | |
'down': 'up', | |
}; | |
if (new_dir == 'up' || direction == 'down') { | |
direction = 'up'; | |
} else if (new_dir == 'down' || direction == 'up') { | |
direction = 'down'; | |
} | |
} | |
changeDirection(); | |
// This finds the next floor to go to, considering the current direction (this will avoid | |
// reversing course if at all possible), the floors whose buttons are pressed, and the | |
// floors that are busy and on the way from here to the destionation floor | |
function pickNextPressedFloor(destinations, busy) { | |
switch (direction) { | |
case 'up': | |
// Find the minimum floor that's currently above us | |
var aboveUs = destinations.filter(dest => dest > elevator.currentFloor()); | |
var busyAboveUs; | |
if (elevator.loadFactor() > PASS_FACTOR) { | |
// It doesn't matter how many people are waiting above us, if we | |
// can't pick them up | |
busyAboveUs = []; | |
} else { | |
busyAboveUs = busy.filter(floor => floor > elevator.currentFloor()); | |
} | |
var available = aboveUs.concat(busyAboveUs); | |
if (available.length == 0) { | |
// Go down, and find the next place to go | |
changeDirection(); | |
return pickNextPressedFloor(destinations, busy); | |
} else { | |
elevator.goToFloor(minList(available)); | |
if (elevator.loadFactor() < PASS_FACTOR) { | |
backlog[minList(available)] = 0; | |
} | |
} | |
break; | |
case 'down': | |
// Find the maximium floor that's currently below | |
var belowUs = destinations.filter(dest => dest < elevator.currentFloor()); | |
var busyBelowUs; | |
if (elevator.loadFactor() > PASS_FACTOR) { | |
busyBelowUs = []; | |
} else { | |
busyBelowUs = busy.filter(floor => floor < elevator.currentFloor()); | |
} | |
var available = belowUs.concat(busyBelowUs); | |
if (available.length == 0) { | |
// Go up, and find the next place to go | |
changeDirection(); | |
return pickNextPressedFloor(destinations, busy); | |
} else { | |
elevator.goToFloor(maxList(available)); | |
if (elevator.loadFactor() < PASS_FACTOR) { | |
backlog[maxList(available)] = 0; | |
} | |
} | |
break; | |
} | |
} | |
elevator.on("idle", function() { | |
var destinations = elevator.getPressedFloors(); | |
if (destinations.length == 0) { | |
// No passengers - go find the most densely packed floor and | |
// get to work | |
goToBusiestFloor(elevator); | |
} else { | |
// We're picking out the index of any floor with >0 waiters | |
var busy = (backlog | |
.map((waiting, i) => waiting > 0 ? i: -1) | |
.filter(i => i != -1)); | |
pickNextPressedFloor(destinations, busy); | |
} | |
}) | |
elevator.on("stopped_at_floor", function(floorNum) { | |
backlog[floorNum] = 0; | |
}) | |
} | |
function initFloor(floor, floorNum) { | |
floor.on("up_button_pressed", function() { | |
backlog[floorNum]++; | |
}) | |
floor.on("down_button_pressed", function() { | |
backlog[floorNum]++; | |
}) | |
} | |
for (var i = 0; i < elevators.length; i++) { | |
initElevator(elevators[i], i); | |
} | |
for (var i = 0; i < floors.length; i++) { | |
initFloor(floors[i], i); | |
} | |
}, | |
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