Skip to content

Instantly share code, notes, and snippets.

@SinisterMinister
Last active September 22, 2015 02:16
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 SinisterMinister/ab4dd1194bd7c260006a to your computer and use it in GitHub Desktop.
Save SinisterMinister/ab4dd1194bd7c260006a to your computer and use it in GitHub Desktop.
{
init: function(elevators, floors) {
var queue = [],
self = this;
for (var i = floors.length - 1; i >= 0; i--) {
floors[i].on("up_button_pressed", self.api.handlers.onUpButton);
floors[i].on("down_button_pressed", self.api.handlers.onDownButton);
floors[i].api = self.api;
floors[i].button
};
for (var i = elevators.length - 1; i >= 0; i--) {
elevators[i].on("idle", self.api.handlers.onIdle);
elevators[i].on("floor_button_pressed", self.api.handlers.onFloorButton);
elevators[i].on("passing_floor", self.api.handlers.onFloorPass);
elevators[i].on("stopped_at_floor", self.api.handlers.onFloorStop);
// Customized API
elevators[i].api = self.api;
elevators[i].currentTask = null;
elevators[i].targetFloor = null;
};
self.api._private.floors = floors;
self.api._private.elevators = elevators;
},
update: function(dt, elevators, floors) {
this.api.delegateNextTaskToIdleElevator();
},
api: {
models: {
Task: function (floorNum, direction) {
this.floorNum = floorNum;
this.direction = direction;
}
},
handlers: {
onUpButton: function () {
console.info("Up button pressed on floor:", this.floorNum());
// Create a new task
this.api.queueTask(this.floorNum(), "up");
},
onDownButton: function () {
console.info("Down button pressed on floor:", this.floorNum());
this.api.queueTask(this.floorNum(), "down");
},
onIdle: function () {
console.info("Elevator is idle", this);
this.api._private.idleElevators.push(this);
},
onFloorButton: function (floorNum) {
console.info("Elevator requested to go to floor", floorNum, this.loadFactor());
this.api.goToFloor(this, floorNum);
},
onFloorPass: function (floorNum, direction) {
console.info("Passing floor", floorNum, direction, this.api._private.queue.slice(0));
// Check to see if there are any tasks for this floor
var active = this.api._private.floors[floorNum].buttonStates[direction] !== "",
handled = false;
for (var i = this.api._private.elevators.length - 1; i >= 0; i--) {
handled = this.api._private.elevators[i].targetFloor === floorNum;
if (handled)
break;
};
if (active && ! handled && this.loadFactor() < .5) {
this.goToFloor(floorNum, true);
this.targetFloor = floorNum;
}
},
onFloorStop: function (floorNum) {
console.info("Stopping on floor", floorNum, this, this.loadFactor());
if (floorNum === 0)
this.api.setDirectionIndicator(this, "up");
if (floorNum === this.api._private.floors.length - 1)
this.api.setDirectionIndicator(this, "down");
if (this.destinationQueue.length > 0) {
this.api.setDirectionIndicator(this, this.api.getDirectionToFloor(this, this.destinationQueue[0]));
}
else {
if (this.currentTask && floorNum !== 0 && floorNum !== this.api._private.floors.length - 1)
this.api.setDirectionIndicator(this, this.currentTask.direction);
}
this.api.clearTask(this.currentFloor(), this.api.getDirectionToFloor(this, floorNum));
}
},
queueTask: function (floorNum, direction) {
// Create a new task
var task = new this.models.Task(floorNum, direction);
// Push the task into the queue
this._private.queue.push(task);
},
findClosestIdleElevator: function (floorNum) {
var currentBest = null;
// Find the best idle elevator
for (var i = this._private.idleElevators.length - 1; i >= 0; i--) {
if (currentBest === null)
currentBest = this._private.idleElevators[i];
else {
if (this.getElevatorDistance(floorNum, this._private.idleElevators[i]) < this.getElevatorDistance(floorNum, currentBest)) {
// Found a better elevator
currentBest = this._private.idleElevators[i];
}
}
};
return currentBest;
},
getElevatorDistance: function (floorNum, elevator) {
return Math.abs(elevator.currentFloor() - floorNum);
},
getClosestTask: function (elevator) {
var currentBest = null;
for (var i = this._private.queue.length - 1; i >= 0; i--) {
if (currentBest === null)
currentBest = this._private.queue[i];
else {
if (this.getElevatorDistance(currentBest.floorNum, elevator) > this.getElevatorDistance(this._private.queue[i].floorNum, elevator))
currentBest = this._private.queue[i];
}
};
return currentBest;
},
delegateNextTaskToIdleElevator: function () {
if (this._private.queue.length === 0 || this._private.idleElevators.length === 0)
return;
var elevator = this._private.idleElevators.shift(),
task = this.getClosestTask(elevator);
// Remove task from queue
this._private.queue.splice(this._private.queue.indexOf(task), 1);
// Run the task
this.runTask(elevator, task);
},
goToFloor: function (elevator, floorNum) {
if (elevator.destinationQueue.indexOf(floorNum) > -1)
return;
// Set the elevator direction indicator
this.setDirectionIndicator(elevator, this.getDirectionToFloor(elevator, floorNum));
elevator.goToFloor(floorNum);
elevator.destinationQueue.sort();
elevator.checkDestinationQueue();
},
getDirectionToFloor: function (elevator, floorNum) {
if (elevator.currentFloor() < floorNum)
return "up";
else
return "down";
},
findTasks: function (floorNum, direction) {
var tasks = [];
for (var i = this._private.queue.length - 1; i >= 0; i--) {
if (this._private.queue[i].floorNum === floorNum && this._private.queue[i].direction === direction)
tasks.push(this._private.queue[i]);
};
return tasks;
},
setDirectionIndicator: function (elevator, direction) {
elevator.goingDownIndicator(false);
elevator.goingUpIndicator(false);
if (direction == "up")
elevator.goingUpIndicator(true);
if (direction == "down")
elevator.goingDownIndicator(true);
},
clearTasks: function (floorNum, direction) {
console.info("Clearing tasks", floorNum, direction);
var tasks = this.findTasks(floorNum, direction);
for (var i = tasks.length - 1; i >= 0; i--) {
this._private.queue.splice(this._private.queue.indexOf(tasks[i]), 1);
};
},
clearTask: function (floorNum, direction) {
console.warn("Clearing task", floorNum, direction)
var tasks = this.findTasks(floorNum, direction);
// Remove the first task
if (tasks.length > 0)
this._private.queue.splice(this._private.queue.indexOf(tasks[0]), 1);
},
runTask: function (elevator, task) {
console.info("Running task", task);
// Send the elevator to the person waiting
this.goToFloor(elevator, task.floorNum);
elevator.currentTask = task;
},
_private: {
queue: [],
idleElevators: [],
floors: [],
elevators: []
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment