-
Notifications
You must be signed in to change notification settings - Fork 0
/
PatientSmartBrain.java
228 lines (216 loc) · 8.66 KB
/
PatientSmartBrain.java
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
import java.util.LinkedList;
import java.util.Iterator;
import java.sql.Time;
public class PatientSmartBrain extends Brain {
private int weightBuffer = Params.maxWeight;
//when this is set to true, the elevator will make a single pass
//up, then down, then reset this to false
private boolean waiting;
//if at least this percentage of the floors have
//some sort of request, stop waiting and serve them
private double serveCondition;
//if that percentage isn't reached after this many seconds,
//serve them anyways
private int maxWaitingTime; //in seconds
private Time beganWaiting;
private int timesChangedDirection;
private int maxDirectionChanges;
public PatientSmartBrain () {
goingUp = true;
nextMovementCmd = null;
waiting = true;
maxDirectionChanges = Params.maxDirectionalChanges;
serveCondition = Params.serveCondition;
maxWaitingTime = Params.timeToWait;
beganWaiting = Params.testStartTime;
timesChangedDirection = 0;
}
@Override
public Cmd decide (Cmd prevCommand, ElevatorInfo theElevator) {
//should always check end condition first
if (!theElevator.continueOperate()) {
theElevator.finished();
return Cmd.finish;
}
//see if we should start/stop waiting
if (waiting) {
double percentile = getRequestPercentage(theElevator);
int timeWaitedSoFar = TimeManip.difference(beganWaiting, theElevator.currentTime);
if (percentile >= serveCondition) {
endWaiting(theElevator);
if (theElevator.verbose) {
System.out.println("\nBecause request percentile " + percentile + " is >= condition " + serveCondition + ", we are now serving\n");
}
} else if (timeWaitedSoFar >= maxWaitingTime) {
endWaiting(theElevator);
if (theElevator.verbose) {
System.out.println("\nBecause time waited " + timeWaitedSoFar + " is >= time to wait " + maxWaitingTime + ", we are now serving\n");
}
} else {
if (theElevator.verbose) {
System.out.println("\nBecause request percentile " + percentile + " is < condition " + serveCondition);
System.out.println("\nAnd because time waited " + timeWaitedSoFar + " is < time to wait " + maxWaitingTime + ", we are still waiting\n");
}
return Cmd.wait;
}
} else {
if (timesChangedDirection >= maxDirectionChanges) {
if (theElevator.verbose) {
System.out.println("\nBecause we have changed direction " + timesChangedDirection + ", which is equal to max changes " + maxDirectionChanges + ", we are now waiting");
}
//negate the last change in direction that was made...
//once we begin running again, if it still ought to have been pointing
//in the direction that it is currently, updateGoingUp() will
//handle that
goingUp = !goingUp;
beginWaiting(theElevator);
return Cmd.wait;
} else if (noRequests(theElevator)) {
if (theElevator.verbose) {
System.out.println("\nBecause there are no requests in or outside the elevator, we are now waiting\n");
}
beginWaiting(theElevator);
return Cmd.wait;
}
}
updateGoingUp(theElevator);
theElevator.printStatus();
//if thedoors are open, close them
if (prevCommand == Cmd.open) {
return Cmd.close;
}
//we've already made a decision regarding where to go
else if (nextMovementCmd != null) {
Cmd temp = nextMovementCmd;
nextMovementCmd = null;
return temp;
}
//ensures doors are opened if desired
if (shouldOpenDoors(theElevator, prevCommand)) {
nextMovementCmd = decideNextMovementCommand(theElevator);
return Cmd.open;
}
return goingUp ? Cmd.up : Cmd.down;
}
@Override
public Cmd decideNextMovementCommand (ElevatorInfo theElevator) {
return goingUp ? Cmd.up : Cmd.down;
}
@Override
public boolean shouldOpenDoors (ElevatorInfo theElevator, Cmd prevCommand){
int theFloor = theElevator.currentFloor;
if (prevCommand == Cmd.close || prevCommand == Cmd.open) {
//if we previously opened the doors but there
//are still people waiting, we are at capacity.
//to continue opening the doors would cause an infinite loop
return false;
}
if (theElevator.building.hasUpRequest(theFloor) && goingUp && !nearMaxCapacity(theElevator)) {
return true;
} else if (theElevator.building.hasDownRequest(theFloor) && !goingUp && !nearMaxCapacity(theElevator)) {
return true;
} else if (theElevator.buttonsPressed.contains(theFloor)) {
return true;
}
return false;
}
//called each frame to modify 'goingUp' boolean
private void updateGoingUp (ElevatorInfo theElevator) {
int theFloor = theElevator.currentFloor;
if (goingUp) {
if (theElevator.atMaxFloor() || noRequestsAboveThisFloor(theElevator)) {
goingUp = false;
timesChangedDirection++;
}
} else {
if (theElevator.atGroundFloor() || noRequestsBelowThisFloor(theElevator)) {
goingUp = true;
timesChangedDirection++;
}
}
}
//DONE
private boolean noRequestsAboveThisFloor (ElevatorInfo theElevator) {
Building b = theElevator.building;
//check building's buttons
if (b.hasUpRequest(theElevator.currentFloor)) {
return false;
}
for (int i = theElevator.currentFloor + 1; i <= theElevator.floors; i++) {
if (b.hasRequest(i)) {
return false;
}
}
//check elevator shaft's buttons
Iterator<Integer> buttonIterator = theElevator.buttonsPressed.iterator();
while (buttonIterator.hasNext()) {
int theButton = buttonIterator.next();
if (theButton > theElevator.currentFloor) {
return false;
}
}
return true;
}
private boolean noRequestsBelowThisFloor (ElevatorInfo theElevator) {
Building b = theElevator.building;
//check building's buttons
if (b.hasDownRequest(theElevator.currentFloor)) {
return false;
}
for (int i = theElevator.currentFloor - 1; i >= 1; i--) {
if (b.hasRequest(i)) {
return false;
}
}
//check elevator shaft's buttons
Iterator<Integer> buttonIterator = theElevator.buttonsPressed.iterator();
while (buttonIterator.hasNext()) {
int theButton = buttonIterator.next();
if (theButton < theElevator.currentFloor) {
return false;
}
}
return true;
}
private boolean nearMaxCapacity (ElevatorInfo e) {
return (e.currentWeight >= e.capacity - (3/4 * Params.maxWeight));
}
//note that, because we make the distinction between up and down requests,
//the max value that can be returned is 2.0 aka 200%
public double getRequestPercentage (ElevatorInfo theElevator) {
Building b = theElevator.building;
int totalRequests = 0;
for (int i = 1; i <= theElevator.floors; i++) {
if (b.hasUpRequest(i)) {
totalRequests++;
}
if (b.hasDownRequest(i)) {
totalRequests++;
}
}
return (double)totalRequests / theElevator.floors;
}
public boolean noRequests (ElevatorInfo theElevator) {
Building b = theElevator.building;
if (!theElevator.buttonsPressed.isEmpty()) {
return false;
}
for (int i = 1; i <= theElevator.floors; i++) {
if (b.hasRequest(i)) {
return false;
}
}
return true;
}
//these two methods manage the various data members associated with waiting
//conditions, to simplify code elsewhere
private void beginWaiting (ElevatorInfo theElevator) {
waiting = true;
beganWaiting = theElevator.currentTime;
}
private void endWaiting (ElevatorInfo theElevator) {
waiting = false;
updateGoingUp(theElevator);
timesChangedDirection = 0;
}
}