Skip to content

Instantly share code, notes, and snippets.

@andreyvit
Last active August 29, 2015 14:14
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 andreyvit/c3157090d04c3be58859 to your computer and use it in GitHub Desktop.
Save andreyvit/c3157090d04c3be58859 to your computer and use it in GitHub Desktop.
{
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