Last active
September 22, 2015 02:16
-
-
Save SinisterMinister/ab4dd1194bd7c260006a to your computer and use it in GitHub Desktop.
This file contains hidden or 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
{ | |
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