Code for Elevator Saga
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

elevator.js 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. eval({
  2. init: function(elevators, floors) {
  3. // Get elevator/building info
  4. let elevatorCount = elevators.length;
  5. let floorCount = floors.length;
  6. let topFloor = floorCount - 1;
  7. let bottomFloor = 0;
  8. console.clear();
  9. console.log("Starting (" + floorCount + " floors; " + elevatorCount + " elevator" + ((floorCount == 1) ? "s" : "") +")...");
  10. // Direction constants
  11. const UP = 0;
  12. const DOWN = 1;
  13. const IDLE = 2;
  14. // Data structure for floor requests
  15. let requests = [new Set(), new Set()];
  16. // ----
  17. // Functions
  18. // ----
  19. // getNextFloor chooses the best destination for an elevator
  20. // when given the index of the elevator, along with all
  21. // destinations, requests, and rest floors.
  22. function getNextFloor(elevators, elevatorIndex, destinations, requests, restFloors) {
  23. let elevator = elevators[elevatorIndex];
  24. let floorNum = restFloors[1];
  25. if (requests[UP].size == 0 && requests[DOWN].size == 0 && destinations.size == 0) {
  26. // No people; send to rest floor
  27. } else if (destinations.size == 0) {
  28. // No destinations; send to pick up passengers
  29. try {
  30. floorNum = getClosestFloor(elevator.currentFloor(), new Set([...requests[UP], ...requests[DOWN]]));
  31. } catch (e) {
  32. console.log("ERROR: Requests set was empty");
  33. }
  34. } else {
  35. // Prioritize dropping off current passengers
  36. try {
  37. floorNum = getClosestFloor(elevator.currentFloor(), destinations);
  38. } catch (e) {
  39. console.log("ERROR: Destinations set was empty");
  40. }
  41. }
  42. return floorNum;
  43. }
  44. // getClosestFloor takes a floor, a list of floors, an optional
  45. // list of ignored floors, and an optional direction. It
  46. // returns the closest floor from that list in the given
  47. // direction that is not part of the ignored floors list.
  48. function getClosestFloor(currentFloor, floorList, ignoredFloors = new Set(), direction = IDLE) {
  49. let closestFloor = currentFloor;
  50. let distance = floorCount;
  51. let newDistance = distance;
  52. floorList.forEach(function(floorNum) {
  53. switch (direction) {
  54. case UP:
  55. newDistance = floorNum - currentFloor;
  56. break;
  57. case DOWN:
  58. newDistance = currentFloor - floorNum;
  59. break;
  60. case IDLE:
  61. newDistance = Math.abs(floorNum - currentFloor);
  62. }
  63. if (newDistance < distance && newDistance > 0 && !(ignoredFloors.has(floorNum))) {
  64. closestFloor = floorNum;
  65. distance = newDistance;
  66. }
  67. });
  68. if (closestFloor != currentFloor) {
  69. return closestFloor;
  70. } else {
  71. throw new Error("No floor in selected direction");
  72. }
  73. }
  74. // getClosestElevator takes a floor number and returns the
  75. // index of the closest elevator.
  76. function getClosestElevator(floorNum) {
  77. let closestElevator = 0;
  78. let distance = floorCount;
  79. let newDistance = distance;
  80. elevators.forEach(function (elevator, elevatorIndex) {
  81. newDistance = Math.abs(elevator.currentFloor() - floorNum);
  82. if (newDistance < distance) {
  83. distance = newDistance;
  84. closestElevator = elevatorIndex;
  85. }
  86. });
  87. //console.log("Closest is elevator[" + closestElevator + "]")
  88. return closestElevator;
  89. }
  90. // getDirection get the direction (up or down) that an elevator
  91. // will need to travel to get to a specified floor
  92. function getDirection(currentFloor, floorNum) {
  93. let distance = currentFloor - floorNum;
  94. if (distance > 0 || currentFloor == topFloor) {
  95. return DOWN;
  96. } else if (distance < 0 || currentFloor == 0) {
  97. return UP;
  98. } else {
  99. return IDLE;
  100. }
  101. }
  102. // setDirection changes the indicator lights on a specified
  103. // elevator to match the given direction.
  104. function setDirection(elevator, direction) {
  105. switch (direction) {
  106. case UP:
  107. elevator.goingUpIndicator(true);
  108. elevator.goingDownIndicator(false);
  109. break;
  110. case DOWN:
  111. elevator.goingUpIndicator(false);
  112. elevator.goingDownIndicator(true);
  113. break;
  114. default:
  115. elevator.goingUpIndicator(true);
  116. elevator.goingDownIndicator(true);
  117. }
  118. }
  119. // ----
  120. // Floors
  121. // ----
  122. floors.forEach(function (floor) {
  123. floor.on("up_button_pressed", function() {
  124. //console.log("> Up request on floor[" + floor.level + "]");
  125. requests[UP].add(floor.level);
  126. });
  127. floor.on("down_button_pressed", function() {
  128. //console.log("> Down request on floor[" + floor.level + "]");
  129. requests[DOWN].add(floor.level);
  130. });
  131. });
  132. // ----
  133. // Elevators
  134. // ----
  135. elevators.forEach(function (elevator, elevatorIndex) {
  136. // Elevator info and variables
  137. let destinations = new Set();
  138. const restFloors = [
  139. elevatorIndex * Math.floor(floorCount / (elevatorCount + 1)),
  140. (elevatorIndex + 1) * Math.floor(floorCount / (elevatorCount + 1)),
  141. (elevatorIndex + 2) * Math.floor(floorCount / (elevatorCount + 1))
  142. ];
  143. // Next primary stop
  144. let nextFloor = restFloors[0];
  145. // Start
  146. setDirection(elevator, UP); // Starts on the ground floor, must be going up
  147. console.log("> Elevator[" + elevatorIndex + "] rest floors are " + restFloors[0] + ", " + restFloors[1] + ", and " + restFloors[2] + ". Starting at " + restFloors[0] + ".");
  148. elevator.goToFloor(nextFloor); // Nearest rest floor
  149. // Idle
  150. elevator.on("idle", function() {
  151. //console.log("> Elevator[" + elevatorIndex + "] is idle")
  152. nextFloor = getNextFloor(elevators, elevatorIndex, destinations, requests, restFloors);
  153. elevator.goToFloor(nextFloor);
  154. });
  155. // Passing
  156. elevator.on("passing_floor", function(floorNum, direction) {
  157. if (destinations.has(floorNum)
  158. || (elevator.loadFactor() < 1 && elevator.destinationDirection() == "up" && requests[UP].has(floorNum))
  159. || (elevator.loadFactor() < 1 && elevator.destinationDirection() == "down" && requests[DOWN].has(floorNum))) {
  160. elevator.goToFloor(floorNum, true);
  161. }
  162. });
  163. // Buttons
  164. elevator.on("floor_button_pressed", function(floorNum) {
  165. //console.log("> Pressed floor[" + floorNum + "] on elevator[" + elevatorIndex + "]");
  166. destinations.add(floorNum);
  167. });
  168. // Stopped
  169. elevator.on("stopped_at_floor", function(floorNum) {
  170. //console.log("> elevator[" + elevatorIndex + "] stopped at floor[" + floorNum + "]");
  171. setDirection(elevator, getDirection(elevator.currentFloor(), nextFloor));
  172. destinations.delete(floorNum);
  173. if (elevator.goingUpIndicator() == true) {
  174. requests[UP].delete(floorNum);
  175. }
  176. if (elevator.goingDownIndicator() == true) {
  177. requests[DOWN].delete(floorNum);
  178. }
  179. });
  180. });
  181. },
  182. update: function(dt, elevators, floors) {}
  183. });