Add Elevator Number to Elevators
[cs356-p1-elevator.git] / elevator.cpp
1 #include "elevator.hpp"
2
3 Elevator::Elevator (int elevator_number)
4         : state_(STATE_IDLE)
5         , wait_(0)
6         , direction_(IDLE)
7         , position_()
8         , stops_()
9         , number_(elevator_number)
10 {
11         // Intentionally Left Empty
12 }
13
14 Elevator::Elevator (int starting_floor, int elevator_number)
15         : state_(STATE_IDLE)
16         , wait_(0)
17         , direction_(IDLE)
18         , position_(starting_floor)
19         , stops_()
20         , number_(elevator_number)
21 {
22         // Intentionally Left Empty
23 }
24
25 bool Elevator::currently_at_stop () const
26 {
27         StopList::const_iterator it;
28         Stop current(position_, direction_);
29
30         /* Calculate the number of Stops above and below our current position */
31         int stops_above = 0;
32         int stops_below = 0;
33
34         for (it = stops_.begin(); it != stops_.end(); it++)
35         {
36                 if (current < *it)
37                         ++stops_above;
38
39                 if (current > *it)
40                         ++stops_below;
41         }
42
43         /* Check if we are at the top. If so, only the position needs to match */
44         if (direction_ == UP && stops_above == 0)
45         {
46                 for (it = stops_.begin (); it != stops_.end (); it++)
47                         if (it->getPosition() == position_)
48                                 return true;
49         }
50
51         /* Check if we are at the bottom. If so, only the position needs to match */
52         if (direction_ == DOWN && stops_below == 0)
53         {
54                 for (it = stops_.begin (); it != stops_.end (); it++)
55                         if (it->getPosition() == position_)
56                                 return true;
57         }
58
59         /* Check if we match exactly */
60         for (it = stops_.begin (); it != stops_.end (); it++)
61                 if (*it == current)
62                         return true;
63
64         /* No match */
65         return false;
66 }
67
68 void Elevator::stop_at (Stop &stop)
69 {
70         StopList::iterator it;
71
72         /* If this is an "ALL" Stop, it supercedes all others */
73         if (stop.getDirection() == ALL)
74         {
75                 stops_.remove (stop);
76                 stops_.push_back (stop);
77                 return;
78         }
79
80         /* Check if this stop already exists. If so, just leave */
81         for (it = stops_.begin(); it != stops_.end(); it++)
82                 if (*it == stop)
83                         return;
84
85         /* The stop did not already exist, so add it */
86         stops_.push_back (stop);
87 }
88
89 float Elevator::distance_from (Position &pos) const
90 {
91         if (position_ > pos)
92                 return position_ - pos;
93
94         return pos - position_;
95 }
96
97 float Elevator::distance_from (Stop &s) const
98 {
99         Direction d = s.getDirection();
100         Position  p = s.getPosition ();
101
102         /* If direction doesn't matter, then only position does */
103         if (d == ALL || direction_ == IDLE)
104                 return distance_from (p);
105
106         /* If we're not in the same direction, then we're "really far" away */
107         if (d != direction_)
108                 return INT_MAX;
109
110         /* We must be in the correct direction, so pure distance is fine */
111         return distance_from (p);
112 }
113
114 void Elevator::transition_move_up ()
115 {
116         direction_ = UP;
117         position_ += ELEVATOR_STEP;
118
119         // TODO: Call into the GUI to update the position
120         std::cout << "Updating the GUI with our position: " << position_ << std::endl;
121 }
122
123 void Elevator::transition_move_down ()
124 {
125         direction_ = DOWN;
126         position_ -= ELEVATOR_STEP;
127
128         // TODO: Call into the GUI to update the position
129         std::cout << "Updating the GUI with our position: " << position_ << std::endl;
130 }
131
132 void Elevator::transition_move_idle ()
133 {
134         direction_ = IDLE;
135         // do not change position while IDLE
136 }
137
138 void Elevator::transition_open_door ()
139 {
140         /* Calculate the number of Stops above and below our
141          * current position */
142         StopList::const_iterator it;
143         Stop current = Stop(position_, direction_);
144         int stops_above = 0;
145         int stops_below = 0;
146
147         for (it = stops_.begin(); it != stops_.end(); it++)
148         {
149                 if (current < *it)
150                         ++stops_above;
151
152                 if (current > *it)
153                         ++stops_below;
154         }
155
156         /* If we are going to switch direction, clear all stops here,
157          * regardless of direction.
158          *
159          * Otherwise, just clear this stop */
160         if      (direction_ == UP && stops_above == 0)
161                 stops_.remove (Stop(position_, ALL));
162         else if (direction_ == DOWN && stops_below == 0)
163                 stops_.remove (Stop(position_, ALL));
164         else
165                 stops_.remove (Stop(position_, direction_));
166
167         // TODO: Call into the GUI to open the door
168         std::cout << "Opening Door" << std::endl;
169 }
170
171 void Elevator::transition_close_door ()
172 {
173         // TODO: Call into the GUI to close the door
174         std::cout << "Closing Door" << std::endl;
175 }
176
177 void Elevator::transition_begin_wait ()
178 {
179         wait_ = 10;
180 }
181
182 void Elevator::transition_continue_wait ()
183 {
184         --wait_;
185 }
186
187 #include <string>
188 static void debug (const std::string& s)
189 {
190         std::cout << s << std::endl;
191 }
192
193 static std::string get_state_name (State s)
194 {
195         std::string sname;
196
197         switch (s)
198         {
199                 case STATE_IDLE:
200                         sname = "STATE_IDLE";
201                         break;
202                 case STATE_UP:
203                         sname = "STATE_UP";
204                         break;
205                 case STATE_DOWN:
206                         sname = "STATE_DOWN";
207                         break;
208                 case STATE_WAIT:
209                         sname = "STATE_WAIT";
210                         break;
211                 case STATE_OPEN_DOOR:
212                         sname = "STATE_OPEN_DOOR";
213                         break;
214                 case STATE_CLOSE_DOOR:
215                         sname = "STATE_CLOSE_DOOR";
216                         break;
217                 default:
218                         sname = "BAD STATE";
219                         break;
220         }
221
222         return sname;
223 }
224
225 static std::string get_event_name (Event e)
226 {
227         std::string ename;
228
229         switch (e)
230         {
231                 case EVT_IDLE:
232                         ename = "EVT_IDLE";
233                         break;
234                 case EVT_UP:
235                         ename = "EVT_UP";
236                         break;
237                 case EVT_DOWN:
238                         ename = "EVT_DOWN";
239                         break;
240                 case EVT_WAIT:
241                         ename = "EVT_WAIT";
242                         break;
243                 case EVT_OPEN_DOOR:
244                         ename = "EVT_OPEN_DOOR";
245                         break;
246                 case EVT_CLOSE_DOOR:
247                         ename = "EVT_CLOSE_DOOR";
248                         break;
249                 default:
250                         ename = "BAD EVENT";
251                         break;
252         }
253
254         return ename;
255 }
256
257 static void bad_transition (State s, Event e)
258 {
259         std::cout << "Bad State Transition: " << get_state_name (s)
260                           << " -> " << get_event_name (e) << std::endl;
261 }
262
263 Event Elevator::find_next_event () const
264 {
265         /* Calculate the number of Stops above and below our
266          * current position */
267         StopList::const_iterator it;
268         Stop current = Stop(position_, direction_);
269         int stops_above = 0;
270         int stops_below = 0;
271
272         for (it = stops_.begin(); it != stops_.end(); it++)
273         {
274                 if (current < *it)
275                         ++stops_above;
276
277                 if (current > *it)
278                         ++stops_below;
279         }
280
281         /* Now figure out which state transition to make */
282         switch (state_)
283         {
284                 case STATE_IDLE:
285
286                         if (currently_at_stop ())
287                                 return EVT_OPEN_DOOR;
288
289                         if (stops_above > 0)
290                                 return EVT_UP;
291
292                         if (stops_below > 0)
293                                 return EVT_DOWN;
294
295                         return EVT_IDLE;
296
297                         break;
298                 case STATE_UP:
299
300                         if (currently_at_stop ())
301                                 return EVT_OPEN_DOOR;
302
303                         return EVT_UP;
304
305                         break;
306                 case STATE_DOWN:
307
308                         if (currently_at_stop ())
309                                 return EVT_OPEN_DOOR;
310
311                         return EVT_DOWN;
312
313                         break;
314                 case STATE_WAIT:
315
316                         if (wait_ > 0)
317                                 return EVT_WAIT;
318
319                         return EVT_CLOSE_DOOR;
320
321                         break;
322                 case STATE_OPEN_DOOR:
323
324                         return EVT_WAIT;
325
326                         break;
327                 case STATE_CLOSE_DOOR:
328
329                         if (currently_at_stop ())
330                                 return EVT_OPEN_DOOR;
331
332                         if (direction_ == UP && stops_above > 0)
333                                 return EVT_UP;
334
335                         if (direction_ == DOWN && stops_below > 0)
336                                 return EVT_DOWN;
337
338                         /* We need to switch directions */
339                         if (direction_ == UP && stops_above == 0 && stops_below > 0)
340                                 return EVT_DOWN;
341
342                         if (direction_ == DOWN && stops_below == 0 && stops_above > 0)
343                                 return EVT_UP;
344
345                         return EVT_IDLE;
346
347                         break;
348                 default:
349                         std::cout << "find_next_event(): Bad State" << std::endl;
350                         break;
351         }
352 }
353
354 void Elevator::move ()
355 {
356         /* Generate Events */
357         Event e = find_next_event ();
358
359         std::cout << "State Transition: " << get_state_name (state_) << " with "
360                           << get_event_name (e) << std::endl;
361
362         switch (state_)
363         {
364                 case STATE_IDLE:
365                         switch (e)
366                         {
367                                 case EVT_UP:
368                                         state_ = STATE_UP;
369                                         transition_move_up ();
370                                         break;
371                                 case EVT_DOWN:
372                                         state_ = STATE_DOWN;
373                                         transition_move_down ();
374                                         break;
375                                 case EVT_IDLE:
376                                         state_ = STATE_IDLE;
377                                         transition_move_idle ();
378                                         break;
379                                 case EVT_OPEN_DOOR:
380                                         state_ = STATE_OPEN_DOOR;
381                                         transition_open_door ();
382                                         break;
383                                 default:
384                                         bad_transition (state_, e);
385                                         break;
386                         } // end switch (e)
387                         break;
388
389                 case STATE_UP:
390                         switch (e)
391                         {
392                                 case EVT_UP:
393                                         state_ = STATE_UP;
394                                         transition_move_up ();
395                                         break;
396                                 case EVT_OPEN_DOOR:
397                                         state_ = STATE_OPEN_DOOR;
398                                         transition_open_door ();
399                                         break;
400                                 default:
401                                         bad_transition (state_, e);
402                                         break;
403                         } // end switch (e)
404                         break;
405
406                 case STATE_DOWN:
407                         switch (e)
408                         {
409                                 case EVT_DOWN:
410                                         state_ = STATE_DOWN;
411                                         transition_move_down ();
412                                         break;
413                                 case EVT_OPEN_DOOR:
414                                         state_ = STATE_OPEN_DOOR;
415                                         transition_open_door ();
416                                         break;
417                                 default:
418                                         bad_transition (state_, e);
419                                         break;
420                         } // end switch (e)
421                         break;
422
423                 case STATE_WAIT:
424                         switch (e)
425                         {
426                                 case EVT_WAIT:
427                                         state_ = STATE_WAIT;
428                                         transition_continue_wait ();
429                                         break;
430                                 case EVT_CLOSE_DOOR:
431                                         state_ = STATE_CLOSE_DOOR;
432                                         transition_close_door ();
433                                         break;
434                                 default:
435                                         bad_transition (state_, e);
436                                         break;
437                         } // end switch (e)
438                         break;
439
440                 case STATE_OPEN_DOOR:
441                         switch (e)
442                         {
443                                 case EVT_WAIT:
444                                         state_ = STATE_WAIT;
445                                         transition_begin_wait ();
446                                         break;
447                                 default:
448                                         bad_transition (state_, e);
449                                         break;
450                         } // end switch (e)
451                         break;
452
453                 case STATE_CLOSE_DOOR:
454                         switch (e)
455                         {
456                                 case EVT_OPEN_DOOR:
457                                         state_ = STATE_OPEN_DOOR;
458                                         transition_open_door ();
459                                         break;
460                                 case EVT_UP:
461                                         state_ = STATE_UP;
462                                         transition_move_up ();
463                                         break;
464                                 case EVT_DOWN:
465                                         state_ = STATE_DOWN;
466                                         transition_move_down ();
467                                         break;
468                                 case EVT_IDLE:
469                                         state_ = STATE_IDLE;
470                                         transition_move_idle ();
471                                         break;
472                                 default:
473                                         bad_transition (state_, e);
474                                         break;
475                         } // end switch (e)
476                         break;
477
478                 default:
479                         std::cout << "Bad State: " << get_state_name (state_) << std::endl;
480                         break;
481         }
482 }
483
484 bool Elevator::is_idle () const
485 {
486         return direction_ == IDLE;
487 }
488
489 /* vim: set ts=4 sts=4 sw=4 noexpandtab textwidth=112: */