-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathElevator.java
More file actions
395 lines (370 loc) · 10.2 KB
/
Elevator.java
File metadata and controls
395 lines (370 loc) · 10.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Iterator;
import java.util.LinkedList;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.text.BadLocationException;
public class Elevator extends JPanel {
// Definition.
private ElevatorDef _def;
// Reference to building.
private Building _building;
// ID.
private int _positionId;
// Mover thread.
private ElevatorMovementThread _mover;
// Door.
private ElevatorDoor _elevatorDoor;
// Reference to current floor at.
private Floor _floorAt;
// Reference to the floor destination.
private Floor _floorDestination;
// Queue of requests to be served.
private LinkedList<ElevatorRequest> _elevatorRequests = new LinkedList<ElevatorRequest>();
// Requests text.
private JTextArea _requestsLog = new JTextArea();
/**
* Constructor.
* @param def
* @param building
* @param id
*/
public Elevator(ElevatorDef def, Building building, int positionId){
// Base constructor.
super();
// Initialize.
_def = def;
_building = building;
_positionId = positionId;
// Initialize the elevator.
initialize();
}
/**
* Initialize.
*/
private void initialize(){
// Set layout.
setLayout(new BorderLayout());
// Setup the size.
setSize(_def.width, _building.getBuildingDef().floorDef.height);
// Position the floor.
setLocation(determinePosition());
// Set the color.
setBackground(_def.primaryColor);
// Create request buttons.
createRequestButtons();
// Create door.
createDoor();
// Call initial moveTo (Just so floorAt, and perhaps other things can get updated).
moveTo(getY());
// Create the mover thread.
_mover = new ElevatorMovementThread(this);
_mover.start(); // Start and handle all logic in here.
// Create the text area of requests.
add(_requestsLog, BorderLayout.SOUTH);
}
/**
* Create the request buttons.
*/
private void createRequestButtons(){
// Create panel.
JPanel panelRequestButtons = new JPanel();
panelRequestButtons.setBackground(_def.secondaryColor);
// Determine grid layout variables.
int dimension = (int) Math.ceil(Math.sqrt((double) _building.getBuildingDef().numFloors));
// Set the grid layout.
panelRequestButtons.setLayout(new GridLayout(dimension, dimension, 2, 2));
// Create buttons inside elevator.
for(int i=0; i<_building.getBuildingDef().numFloors; i++){
// Create the button.
JButton floorNumberButton = new JButton("" + i);
// Add action listener.
floorNumberButton.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e) {
// Get the text in the button.
String text = ((JButton) e.getSource()).getText();
int floorNumber = Integer.parseInt(text);
// Add a request.
addRequest(new ElevatorRequest(_building.getFloorAtLevel(floorNumber)));
}
}
);
// Display.
panelRequestButtons.add(floorNumberButton);
}
// Display panel.
add(panelRequestButtons, BorderLayout.NORTH);
}
/**
* Create the door of the elevator.
*/
private void createDoor(){
// Create the door.
_elevatorDoor = new ElevatorDoor(this);
// Add to display.
add(_elevatorDoor, BorderLayout.CENTER);
}
/**
* Determine the position of where this elevator should go.
* All the elevators are aligned so any amount of elevators can fit.
* @return
*/
private Point determinePosition(){
// Define the point.
Point point = new Point(0, 0);
// Determine new x position.
int x = (_building.getBuildingDef().width / 2) - (_def.width / 2) + (_positionId * (_def.width + _def.spacing));
// Move the point to the new x position.
point.move(x, 0);
// Return the point.
return point;
}
/**
* Called to serve the next request.
* Only call if there is no destination.
*/
public void serveNextRequest(){
// Make sure we already don't have a destination.
if(_floorDestination != null)
return;
// Determine if we have any elevator requests remaining.
if(_elevatorRequests.size() > 0){
// Get the next elevator request.
ElevatorRequest elevatorRequest = removeRequest();
// If there is a request, go to it's floor.
if(elevatorRequest != null){
goToFloor(elevatorRequest.getFloorTo());
}
} else {
// Since there are no elevator requests, check for floor requests.
if(_building.getElevatorSystem().getFloorRequests().size() > 0){
// Get the next floor request.
FloorRequest floorRequest = _building.getElevatorSystem().getFloorRequests().poll();
// If there is a floor request, go to it.
if(floorRequest != null){
goToFloor(floorRequest.getFloorFrom());
}
} else {
// There are no elevator requests and no floor requests.
}
}
}
/**
* Add a new elevator request.
* @param elevatorRequest
*/
public void addRequest(ElevatorRequest elevatorRequest){
// Default boolean.
boolean isDuplicate = false;
// Make sure there is no duplicate.
Iterator<ElevatorRequest> iterator = _elevatorRequests.iterator();
while(iterator.hasNext()){
if(iterator.next().getFloorTo() == elevatorRequest.getFloorTo()){
isDuplicate = true;
break;
}
}
// Add to list (if not duplicate).
if(!isDuplicate){
// Add the request.
_elevatorRequests.add(elevatorRequest);
// Update the log.
updateLog();
}
}
/**
* Remove the request.
* @param elevatorRequest
*/
private void removeRequest(ElevatorRequest elevatorRequest){
// Remove from list.
_elevatorRequests.remove(elevatorRequest);
updateLog();
}
/**
* Remove the first elevator request.
*/
private ElevatorRequest removeRequest(){
// Remove first.
ElevatorRequest elevatorRequest = _elevatorRequests.poll();
updateLog();
// Return the request.
return elevatorRequest;
}
/**
* Called to update the log.
*/
private void updateLog(){
// Clear the text.
_requestsLog.setText("");
// Iterate through elevator requests.
Iterator<ElevatorRequest> iterator = _elevatorRequests.iterator();
while(iterator.hasNext()){
_requestsLog.append(iterator.next().getFloorTo().getLevel() + ", ");
}
}
/**
* Move the elevator to the specified y position.
* @param y
*/
public void moveTo(int y){
// Move the elevator.
move(getX(), y);
// Update floor at.
Floor floorAtNow = calculateFloorAt();
// If we are at some floor, update our reference.
if(floorAtNow != null){
// Arrived at new floor.
arrivedAtFloor(floorAtNow);
}
}
/**
* Called when we have exactly reached a new floor.
* @param floorArrivedAt
*/
private void arrivedAtFloor(Floor floorArrivedAt){
// Update reference.
_floorAt = floorArrivedAt;
// Default boolean.
boolean stopAndOpen = false;
// Do the efficiency checks if we are going to some destination.
if(_floorDestination != null){
// We can let off anyone that wants to get off at this floor,
// even though they might not be first in the queue (but they are along the way).
// Loop through requests.
Iterator<ElevatorRequest> iterator = _elevatorRequests.iterator();
while(iterator.hasNext()){
// Get the next elevator request.
ElevatorRequest elevatorRequest = iterator.next();
// Check if the floor is this floor.
if(elevatorRequest.getFloorTo() == floorArrivedAt){
// Remove the request.
removeRequest(elevatorRequest);
// Set the boolean.
stopAndOpen = true;
// Exit out.
break;
}
}
// Pickup passengers, if there are any on this floor, that want to go
// in the direction that we are currently going.
// Determine the direction the elevator is going.
int direction = getY() - _floorDestination.getY();
// Going down.
if(direction < 0){
// Check if there are any that are going down.
if(floorArrivedAt.hasDownRequest()){
// Set boolean.
stopAndOpen = true;
// Extract all.
floorArrivedAt.clearGoingDownRequest();
}
// Going up.
} else if(direction > 0){
// Check if there are any that are going up.
if(floorArrivedAt.hasUpRequest()){
// Set boolean.
stopAndOpen = true;
// Extract all.
floorArrivedAt.clearGoingUpRequest();
}
// On same floor.
} else {
// Clear requests.
floorArrivedAt.clearGoingDownRequest();
floorArrivedAt.clearGoingUpRequest();
}
}
// If reached destination.
if(floorArrivedAt == _floorDestination){
// Set boolean.
stopAndOpen = true;
// Clear destination.
_floorDestination = null;
// Update the requests log.
updateLog();
}
// Stop and open.
if(stopAndOpen){
_elevatorDoor.open();
}
}
/**
* Calculate the floor we are currently at in THIS instant of time.
* This calculation is made so that the floor that we are EXACTLY at is returned.
* If we are not EXACTLY on some floor, then null is returned.
* @return
*/
private Floor calculateFloorAt(){
// Determine level we are at.
int remainder = getY() % _building.getBuildingDef().floorDef.height;
// There must not be a remainder.
if(remainder == 0){
// Determine exact level.
int level = getY() / _building.getBuildingDef().floorDef.height;
// Return the floor at that level.
return _building.getFloorAtLevel(level);
} else {
// We are in between floors.
return null;
}
}
/**
* Called to tell the elevator to go to the specified floor.
* @param floor
*/
public void goToFloor(Floor floor){
// Set destination.
_floorDestination = floor;
}
/**
* Go to the floor specified by level.
* @param level
*/
public void goToFloor(int level){
// Go to floor at level.
goToFloor(_building.getFloorAtLevel(level));
}
/**
* Getter for the elevator definition.
* @return
*/
public ElevatorDef getElevatorDef(){
return _def;
}
/**
* Getter for the elevator door.
* @return
*/
public ElevatorDoor getElevatorDoor(){
return _elevatorDoor;
}
/**
* Getter for the reference to the building.
* @return
*/
public Building getBuilding(){
return _building;
}
/**
* Getter for the floor at.
* @return
*/
public Floor getFloorAt(){
return _floorAt;
}
/**
* Getter for the floor destination.
* @return
*/
public Floor getFloorDestination(){
return _floorDestination;
}
}