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