Skip to content

Instantly share code, notes, and snippets.

@djmitche
Last active August 29, 2015 14:15
Show Gist options
  • Select an option

  • Save djmitche/fdb454900ddca5ede9e8 to your computer and use it in GitHub Desktop.

Select an option

Save djmitche/fdb454900ddca5ede9e8 to your computer and use it in GitHub Desktop.
Elevator Saga Solution
{
init: function(elevators, floors) {
var directions = new Array();
var stopped_at = new Array();
elevators.forEach(function(el, el_idx) {
directions.push('up');
stopped_at.push(null);
});
var setDirection = function(el_idx, direction) {
if (directions[el_idx] != direction) {
var el = elevators[el_idx];
el.goingUpIndicator((direction == 'up'));
el.goingDownIndicator((direction == 'down'));
directions[el_idx] = direction;
}
};
var setDestination = function(el_idx, floor_idx, preferred_direction) {
var el = elevators[el_idx];
var cur_floor = el.currentFloor();
var direction = (floor_idx < cur_floor) ? 'down' :
(floor_idx > cur_floor) ? 'up' :
preferred_direction;
setDirection(el_idx, direction);
if (el.destinationQueue != [floor_idx]) {
el.destinationQueue = [floor_idx];
el.checkDestinationQueue();
}
};
// does this elevator need to stop at this floor in this direction?
var shouldStopAt = function(el_idx, floor_idx, direction) {
var el = elevators[el_idx];
// Don't try to stop on the floor we just stopped at. The
// simulation doesn't allow us to move while the doors are still
// open, so this has the effect of ensuring we don't "stall" at a
// floor remaining passengers don't fit onto the elevator.
if (floor_idx == stopped_at[el_idx]) {
return false;
}
// Otherwise, stopping at the ground floor is always a good idea,
// as it gets a lot more traffic than others
if (floor_idx == 0 && direction == 'up') {
return true;
}
// if the floor indicator is lit, we should stop
var pressed_floors = el.getPressedFloors();
if (pressed_floors.some(function(f) { return f == floor_idx; })) {
return true;
}
// if the button on that floor for that direction is lit, we should
// stop if we're not overloaded
var fl = floors[floor_idx];
var overloaded = (el.loadFactor() > 0.7);
if (!overloaded && fl.buttonStates[direction] == 'activated') {
return true;
}
return false;
};
// get a complete trajectory of this elevator to its extreme, back to
// its other extreme, and returning to where it is now. This is super
// inefficient, but who cares?
var trajectory = function(floor_idx, direction) {
var traj = [];
var i;
// build the overall trajectory, starting at the bottom going up
for (i = 0; i < floors.length; i++) {
traj.push([i, 'up']);
}
for (i = floors.length-1; i >= 0; i--) {
traj.push([i, 'down']);
}
// now rotate that trajectory until we get to the desired state
while ((traj[0][0] != floor_idx) || (traj[0][1] != direction)) {
traj.unshift(traj.pop());
}
return traj;
};
var nextFloor = function(el_idx, floor_idx, direction) {
var el = elevators[el_idx];
var fl, dir, fldir;
for (fldir of trajectory(el.currentFloor(), direction)) {
fl = fldir[0];
dir = fldir[1];
if (shouldStopAt(el_idx, fl, dir)) {
break;
}
}
return [fl, dir];
};
var update = function() {
elevators.forEach(function(el, el_idx) {
var cur_floor = el.currentFloor();
var fldir = nextFloor(el_idx, cur_floor, directions[el_idx]);
var next_floor = fldir[0], next_dir = fldir[1];
setDestination(el_idx, next_floor, next_dir);
});
};
floors.forEach(function(floor) {
floor.on('up_button_pressed', update);
floor.on('down_button_pressed', update);
});
elevators.forEach(function(el, el_idx) {
el.on('stopped_at_floor', function() {
stopped_at[el_idx] = el.currentFloor();
update();
});
el.on('passing_floor', function() {
stopped_at[el_idx] = null;
update();
});
el.on('idle', update);
el.on('floor_button_pressed', update);
});
},
update: function(dt, elevators, floors) {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment