Last active
August 29, 2015 14:14
-
-
Save andreyvit/c3157090d04c3be58859 to your computer and use it in GitHub Desktop.
Elevator Saga - http://play.elevatorsaga.com/
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
{ | |
init: function(elevators, floors) { | |
var DIR_UP = 1, DIR_DOWN = -1, DIR_IDLE = 0; | |
var FLOOR_NINF = -1, FLOOR_PINF = 1000; | |
var floorUpRequests = [];{ | |
init: function(elevators, floors) { | |
var DIR_UP = 1, DIR_DOWN = -1, DIR_IDLE = 0; | |
var FLOOR_NINF = -1, FLOOR_PINF = 1000; | |
//elevators = elevators.slice(0, 1); | |
var floorUpRequests = []; | |
var floorDownRequests = []; | |
for (var i = 0; i < elevators.length; ++i) { | |
elevators[i].idx = i; | |
handleElevator(elevators[i]); | |
} | |
function handleElevator(elevator) { | |
elevator.cabinRequests = []; | |
elevator.direction = DIR_IDLE; | |
elevator.on("idle", function() { | |
scheduleNextMove(elevator); | |
}); | |
elevator.on("passing_floor", function(floorNum, direction) { | |
}); | |
elevator.on("stopped_at_floor", function(floorNum) { | |
if (elevator.direction == DIR_UP) { | |
removeRequest(floorNum, floorUpRequests); | |
} else if (elevator.direction == DIR_DOWN) { | |
removeRequest(floorNum, floorDownRequests); | |
} | |
removeRequest(floorNum, elevator.cabinRequests); | |
}); | |
elevator.on("floor_button_pressed", function(floorNum) { | |
requestFloor(floorNum, elevator.cabinRequests, "E"+elevator.idx + " cabin"); | |
}); | |
} | |
floors.forEach(function(floor) { | |
var floorNum = floor.floorNum(); | |
floor.on("up_button_pressed", function() { | |
if (false && anyElevatorsAlreadyGoingTo(floorNum)) { | |
return; | |
} | |
requestFloor(floorNum, floorUpRequests, "up"); | |
}); | |
floor.on("down_button_pressed", function() { | |
if (false && anyElevatorsAlreadyGoingTo(floorNum)) { | |
return; | |
} | |
requestFloor(floorNum, floorDownRequests, "down"); | |
}); | |
}); | |
function anyElevatorsAlreadyGoingTo(floorNum, exceptElevator) { | |
var found = false; | |
elevators.forEach(function(other) { | |
if (other !== exceptElevator) { | |
if (other.destinationQueue.indexOf(floorNum) >= 0) { //|| other.cabinRequests.indexOf(floorNum) >= 0) { | |
found = true; | |
} | |
} | |
}); | |
return found; | |
} | |
function requestFloor(floorNum, requests, reason) { | |
if (requests.indexOf(floorNum) < 0) { | |
requests.push(floorNum); | |
requests.sort(); | |
console.log(reason + " floor=" + floorNum + " up=" + JSON.stringify(floorUpRequests) + " dn=" + JSON.stringify(floorDownRequests)); | |
scheduleNextMoveIfIdle(); | |
} | |
} | |
function removeRequest(floorNum, requests) { | |
var idx = requests.indexOf(floorNum); | |
if (idx >= 0) { | |
requests.splice(idx, 1); | |
} | |
} | |
function scheduleNextMoveIfIdle() { | |
elevators.forEach(function(elevator) { | |
if (elevator.direction == DIR_IDLE) { | |
scheduleNextMove(elevator); | |
} | |
}); | |
} | |
function pickMove(elevator) { | |
var floorNum = elevator.currentFloor(); | |
var target, alt; | |
console.log("E" + elevator.idx + " at " + floorNum + " dir=" + elevator.direction + " up="+JSON.stringify(floorUpRequests) + " dn="+JSON.stringify(floorDownRequests) + " cab="+JSON.stringify(elevator.cabinRequests)); | |
if (elevator.direction == DIR_UP || elevator.direction == DIR_IDLE) { | |
target = nextRequest(elevator, floorUpRequests, floorNum-1, FLOOR_PINF, "min"); | |
if (target >= 0) { | |
return { floor: target, direction: DIR_UP }; | |
} | |
target = nextRequest(elevator, floorDownRequests, floorNum-1, FLOOR_PINF, "max"); | |
if (target >= 0) { | |
return { floor: target, direction: DIR_DOWN }; | |
} | |
target = nextRequest(elevator, floorDownRequests, FLOOR_NINF, floorNum, "max"); | |
if (target >= 0) { | |
return { floor: target, direction: DIR_DOWN }; | |
} | |
target = nextRequest(elevator, floorUpRequests, FLOOR_NINF, floorNum, "min"); | |
if (target >= 0) { | |
return { floor: target, direction: DIR_UP }; | |
} | |
} else { | |
target = nextRequest(elevator, floorDownRequests, FLOOR_NINF, floorNum+1, "max"); | |
if (target >= 0) { | |
return { floor: target, direction: DIR_DOWN }; | |
} | |
target = nextRequest(elevator, floorUpRequests, FLOOR_NINF, floorNum+1, "min"); | |
if (target >= 0) { | |
return { floor: target, direction: DIR_UP }; | |
} | |
target = nextRequest(elevator, floorUpRequests, floorNum, FLOOR_PINF, "min"); | |
if (target >= 0) { | |
return { floor: target, direction: DIR_UP }; | |
} | |
target = nextRequest(elevator, floorDownRequests, floorNum, FLOOR_PINF, "max"); | |
if (target >= 0) { | |
return { floor: target, direction: DIR_DOWN }; | |
} | |
} | |
return null; | |
} | |
function scheduleNextMove(elevator) { | |
var move = pickMove(elevator); | |
if (move) { | |
console.log("E" + elevator.idx + " target=" + move.floor + " dir=" + move.direction + " up="+JSON.stringify(floorUpRequests) + " dn="+JSON.stringify(floorDownRequests) + " cab="+JSON.stringify(elevator.cabinRequests)); | |
elevator.direction = move.direction; | |
if (elevator.direction == DIR_UP) { | |
removeRequest(move.floor, floorUpRequests); | |
elevator.goingUpIndicator(true); | |
elevator.goingDownIndicator(false); | |
} else if (elevator.direction == DIR_DOWN) { | |
removeRequest(move.floor, floorDownRequests); | |
elevator.goingUpIndicator(false); | |
elevator.goingDownIndicator(true); | |
} | |
elevator.goToFloor(move.floor); | |
removeRequest(move.floor, elevator.cabinRequests); | |
} else { | |
console.log("E" + elevator.idx + " idle"); | |
elevator.direction = DIR_IDLE; | |
elevator.goingUpIndicator(true); | |
elevator.goingDownIndicator(true); | |
} | |
} | |
function nextRequest(elevator, floorRequests, lo, hi, op) { | |
floorRequests.sort(); | |
var floorLo = lo, floorHi = hi; | |
elevators.forEach(function(other) { | |
if (other == elevator) return; | |
var otherFloor = other.currentFloor(); | |
if (other.direction == DIR_UP) { | |
floorHi = Math.min(floorHi, otherFloor+1); | |
} else if (other.direction == DIR_DOWN) { | |
floorLo = Math.max(floorLo, otherFloor-1); | |
} | |
}); | |
var f1 = nextRequestIn(floorRequests, floorLo, floorHi, op); | |
if (f1 >= 0 && anyElevatorsAlreadyGoingTo(f1, elevator)) { | |
f1 = -1; | |
} | |
var f2 = nextRequestIn(elevator.cabinRequests, lo, hi, op); | |
//console.log("nextRequest("+op+"): f2="+f2 + " cab=" + JSON.stringify(elevator.cabinRequests) + | |
// " f1="+f1 + " rq=" + JSON.stringify(floorRequests) + | |
// " lo="+lo + " hi="+hi + " flo="+floorLo + " fhi="+floorHi); | |
return combineFloors(f1, f2, op); | |
} | |
function combineFloors(f1, f2, op) { | |
if (f1 >= 0 && f2 >= 0) { | |
return Math[op](f1, f2); | |
} else if (f1 >= 0) { | |
return f1; | |
} else { | |
return f2; | |
} | |
} | |
function nextRequestIn(requests, lo, hi, op) { | |
requests.sort(); | |
if (op == "min") { | |
for (var i = 0; i < requests.length; ++i) { | |
if (requests[i] > lo && requests[i] < hi) { | |
return requests[i]; | |
} | |
} | |
} else { | |
for (var i = requests.length - 1; i >= 0; --i) { | |
if (requests[i] > lo && requests[i] < hi) { | |
return requests[i]; | |
} | |
} | |
} | |
return -1; | |
} | |
}, | |
update: function(dt, elevators, floors) { | |
// We normally don't need to do anything here | |
} | |
} | |
var floorDownRequests = []; | |
for (var i = 0; i < elevators.length; ++i) { | |
elevators[i].idx = i; | |
handleElevator(elevators[i]); | |
} | |
function handleElevator(elevator) { | |
elevator.cabinRequests = []; | |
elevator.direction = DIR_IDLE; | |
elevator.on("idle", function() { | |
scheduleNextMove(elevator); | |
}); | |
elevator.on("passing_floor", function(floorNum, direction) { | |
}); | |
elevator.on("stopped_at_floor", function(floorNum) { | |
if (elevator.direction == DIR_UP) { | |
removeRequest(floorNum, floorUpRequests); | |
} else if (elevator.direction == DIR_DOWN) { | |
removeRequest(floorNum, floorDownRequests); | |
} | |
removeRequest(floorNum, elevator.cabinRequests); | |
}); | |
elevator.on("floor_button_pressed", function(floorNum) { | |
requestFloor(floorNum, elevator.cabinRequests, "cabin"); | |
}); | |
} | |
floors.forEach(function(floor) { | |
var floorNum = floor.floorNum(); | |
floor.on("up_button_pressed", function() { | |
requestFloor(floorNum, floorUpRequests, "up"); | |
}); | |
floor.on("down_button_pressed", function() { | |
requestFloor(floorNum, floorDownRequests, "down"); | |
}); | |
}); | |
function requestFloor(floorNum, requests, reason) { | |
if (requests.indexOf(floorNum) < 0) { | |
requests.push(floorNum); | |
requests.sort(); | |
console.log(reason + " floor=" + floorNum + " requests=" + JSON.stringify(requests)); | |
scheduleNextMoveIfIdle(); | |
} | |
} | |
function removeRequest(floorNum, requests) { | |
var idx = requests.indexOf(floorNum); | |
if (idx >= 0) { | |
requests.splice(idx, 1); | |
} | |
} | |
function scheduleNextMoveIfIdle() { | |
elevators.forEach(function(elevator) { | |
if (elevator.direction == DIR_IDLE) { | |
scheduleNextMove(elevator); | |
} | |
}); | |
} | |
function scheduleNextMove(elevator) { | |
var floorNum = elevator.currentFloor(); | |
var target = -1; | |
if (elevator.direction == DIR_UP || elevator.direction == DIR_IDLE) { | |
target = nextRequest(elevator, floorUpRequests, floorNum, FLOOR_PINF, "min"); | |
if (target >= 0) { | |
elevator.direction = DIR_UP; | |
} else { | |
target = nextRequest(elevator, floorDownRequests, floorNum, FLOOR_PINF, "min"); | |
if (target >= 0) { | |
elevator.direction = DIR_UP; | |
} else { | |
target = nextRequest(elevator, floorUpRequests.concat(floorDownRequests), FLOOR_NINF, floorNum, "max"); | |
if (target >= 0) { | |
elevator.direction = DIR_DOWN; | |
} | |
} | |
} | |
} else { | |
target = nextRequest(elevator, floorDownRequests, FLOOR_NINF, floorNum, "max"); | |
if (target >= 0) { | |
elevator.direction = DIR_DOWN; | |
} else { | |
target = nextRequest(elevator, floorUpRequests, FLOOR_NINF, floorNum, "max"); | |
if (target >= 0) { | |
elevator.direction = DIR_DOWN; | |
} else { | |
target = nextRequest(elevator, floorDownRequests.concat(floorUpRequests), floorNum, FLOOR_PINF, "min"); | |
if (target >= 0) { | |
elevator.direction = DIR_UP; | |
} | |
} | |
} | |
} | |
if (target >= 0) { | |
console.log("target=%j", target); | |
elevator.goToFloor(target); | |
if (elevator.direction == DIR_UP) { | |
removeRequest(floorNum, floorUpRequests); | |
} else if (elevator.direction == DIR_DOWN) { | |
removeRequest(floorNum, floorDownRequests); | |
} | |
removeRequest(target, elevator.cabinRequests); | |
} else { | |
elevator.direction = DIR_IDLE; | |
} | |
} | |
function nextRequest(elevator, floorRequests, lo, hi, op) { | |
floorRequests.sort(); | |
var floorLo = lo, floorHi = hi; | |
elevators.forEach(function(other) { | |
var otherFloor = other.currentFloor(); | |
if (other.direction == DIR_UP) { | |
floorHi = Math.min(floorHi, otherFloor+1); | |
} else if (other.direction == DIR_DOWN) { | |
floorLo = Math.max(floorLo, otherFloor-1); | |
} | |
}); | |
var f1 = nextRequestIn(floorRequests, floorLo, floorHi); | |
var f2 = nextRequestIn(elevator.cabinRequests, lo, hi); | |
return combineFloors(f1, f2, op); | |
} | |
function combineFloors(f1, f2, op) { | |
if (f1 >= 0 && f2 >= 0) { | |
return Math[op](f1, f2); | |
} else if (f1 >= 0) { | |
return f1; | |
} else { | |
return f2; | |
} | |
} | |
function nextRequestIn(requests, lo, hi) { | |
for (var i = 0; i < requests.length; ++i) { | |
if (requests[i] > lo && requests[i] < hi) { | |
return requests[i]; | |
} | |
} | |
return -1; | |
} | |
}, | |
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