{ init: function(elevators, floors) { console.clear(); // Get elevator/building info let elevatorCount = elevators.length; let floorCount = floors.length; let topFloor = floorCount - 1; let bottomFloor = 0; console.log("Starting (" + floorCount + " floors; " + elevatorCount + " elevator" + ((floorCount == 1) ? "s" : "") +")..."); // Direction constants const UP = 0; const DOWN = 1; const IDLE = 2; // Create a data structure for floor requests let requests = [new Set(), new Set()]; // ---- // Functions // ---- function getClosestFloor(currentFloor, floorList, ignoredFloors = new Set(), direction = IDLE){ let closestFloor = currentFloor; let distance = floorCount; let newDistance = distance; floorList.forEach(function(floorNum) { switch (direction) { case UP: newDistance = floorNum - currentFloor; case DOWN: newDistance = currentFloor - floorNum; case IDLE: newDistance = Math.abs(floorNum - currentFloor); } if (newDistance < distance && newDistance > 0 && !(ignoredFloors.has(floorNum))) { closestFloor = floorNum; distance = newDistance; } }) if (closestFloor != currentFloor) { return closestFloor; } else { throw new Error("No floor in selected direction"); } } function sendToNext(elevators, elevatorIndex, destinations, requests, restFloors) { elevator = elevators[elevatorIndex] if (elevator.loadFactor() < 0.8) { if (requests[UP].size > 0 || requests[DOWN].size > 0 || destinations.size > 0) { let allStops = new Set([...destinations, ...requests[UP], ...requests[DOWN]]); try { floorNum = getClosestFloor(elevator.currentFloor(), allStops) //console.log("> Sending elevator[" + elevatorIndex + "] to floor[" + floorNum + "]"); elevator.goToFloor(floorNum); } catch (e) { //console.log("> No closest floor. Sending elevator[" + elevatorIndex + "] to rest floor[" + restFloors[1] + "]"); elevator.goToFloor(restFloors[1]); } } else { //console.log("> Sending elevator[" + elevatorIndex + "] to rest floor[" + restFloors[1] + "]"); elevator.goToFloor(restFloors[1]); } } else { try { floorNum = getClosestFloor(elevator.currentFloor(), destinations) console.log("> Sending elevator[" + elevatorIndex + "] to destination floor[" + floorNum + "]"); elevator.goToFloor(floorNum); } catch (e) { //console.log("> No closest floor. Sending elevator[" + elevatorIndex + "] to rest floor[" + restFloors[1] + "]"); elevator.goToFloor(restFloors[1]); } } } function getClosestElevator(floorNum) { let closestElevator = 0; let distance = floorCount; let newDistance = distance; elevators.forEach(function (elevator, elevatorIndex) { newDistance = Math.abs(elevator.currentFloor() - floorNum); if (newDistance < distance) { distance = newDistance; closestElevator = elevatorIndex; } }); //console.log("Closest is elevator[" + closestElevator + "]") return closestElevator; } function setDirection(elevator, direction){ switch (direction) { case UP: elevator.goingUpIndicator(true); elevator.goingDownIndicator(false); break case DOWN: elevator.goingUpIndicator(false); elevator.goingDownIndicator(true); break default: elevator.goingUpIndicator(true); elevator.goingDownIndicator(true); } } // ---- // Floors // ---- floors.forEach(function (floor) { floor.on("up_button_pressed", function() { //console.log("> Up request on floor[" + floor.level + "]"); requests[UP].add(floor.level); }); floor.on("down_button_pressed", function() { //console.log("> Down request on floor[" + floor.level + "]"); requests[DOWN].add(floor.level); }); }); // ---- // Elevators // ---- elevators.forEach(function (elevator, elevatorIndex) { // Elevator info and variables let destinations = new Set(); const restFloors = [ elevatorIndex * Math.floor(floorCount / (elevatorCount + 1)), (elevatorIndex + 1) * Math.floor(floorCount / (elevatorCount + 1)), (elevatorIndex + 2) * Math.floor(floorCount / (elevatorCount + 1)) ] // Start setDirection(elevator, UP); // Starts on the ground floor console.log("> Elevator[" + elevatorIndex + "] rest floors are " + restFloors[0] + ", " + restFloors[1] + ", and " + restFloors[2] + ". Starting at " + restFloors[0] + ".") elevator.goToFloor(restFloors[0]); // Nearest rest floor // Idle elevator.on("idle", function() { //console.log("> Elevator[" + elevatorIndex + "] is idle") setDirection(elevator, IDLE); if (requests[UP].size == 0 && requests[DOWN].size == 0 && destinations.size == 0) { elevator.goToFloor(restFloors[1]); } else { sendToNext(elevators, elevatorIndex, destinations, requests, restFloors); } }); // Passing elevator.on("passing_floor", function(floorNum, direction) { if (elevator.loadFactor() < 1 && (requests[UP].has(floorNum) || requests[DOWN].has(floorNum))) { elevator.goToFloor(floorNum, true); } }); // Buttons elevator.on("floor_button_pressed", function(floorNum) { //console.log("> Pressed floor[" + floorNum + "] on elevator[" + elevatorIndex + "]"); destinations.add(floorNum); }); // Stopped elevator.on("stopped_at_floor", function(floorNum) { //console.log("> elevator[" + elevatorIndex + "] stopped at floor[" + floorNum + "]"); destinations.delete(floorNum); requests[UP].delete(floorNum); requests[DOWN].delete(floorNum); }); }); }, update: function(dt, elevators, floors) {} }