BUGFIX: Elevators did not handle Requests in the correct order
[cs356-p1-elevator.git] / elevatorcontroller.cpp
1 #include "elevatorcontroller.hpp"
2
3 ElevatorController::ElevatorController (int floors, int elevators)
4         : number_of_floors_(floors)
5         , number_of_elevators_(elevators)
6         , elevators_()
7 {
8         /* Seed the RNG */
9         std::srand ( std::time (NULL) );
10
11         /* Create and add all of the elevators */
12         for (int i=0; i<number_of_elevators_; i++)
13                 elevators_.push_back (Elevator(i));
14 }
15
16 static int choose_random_number_in_range (int low, int high)
17 {
18         return std::rand () % high + low;
19 }
20
21 void ElevatorController::call_elevator_to (int floor, Direction direction)
22 {
23         std::cout << "Called elevator to: floor=" << floor << " direction=" << direction << std::endl;
24
25         /* Check the parameters */
26         if (floor < 0 || floor > number_of_floors_)
27                 throw bad_floor ();
28
29         ElevatorList::iterator it;
30         std::vector<Elevator*> low_load_elevators;
31         Stop requested_stop (floor, direction);
32         const int max_load = number_of_floors_ / 3;
33
34         std::cout << "Using max load: " << max_load << std::endl;
35
36         /* Find all elevators with "low load" */
37         for (it=elevators_.begin(); it != elevators_.end(); it++)
38         {
39                 if (it->getLoad() <= max_load)
40                         low_load_elevators.push_back (&(*it));
41         }
42
43         std::vector<Elevator*>::iterator lle_it;
44         bool found = false;
45         float distance = INT_MAX;
46         Elevator *e;
47         int num;
48
49         /* Make sure there are lightly loaded elevators */
50         if (low_load_elevators.size() > 0)
51         {
52                 /* Find the closest lightly loaded elevator */
53                 for (lle_it = low_load_elevators.begin(); lle_it != low_load_elevators.end(); lle_it++)
54                 {
55                         if ((*lle_it)->distance_from (requested_stop) < distance)
56                         {
57                                 found = true;
58                                 distance = (*lle_it)->distance_from (requested_stop);
59                                 e = *lle_it;
60                         }
61                 }
62
63                 /* Found a closest one, send it */
64                 if (found)
65                 {
66                         std::cout << "Found closest LLE" << std::endl;
67                         e->stop_at (requested_stop);
68                         return;
69                 }
70
71                 /* No closest one, so send randomly */
72                 std::cout << "No closest LLE: choosing randomly" << std::endl;
73                 num = choose_random_number_in_range (0, low_load_elevators.size());
74                 low_load_elevators.at (num) -> stop_at (requested_stop);
75                 return;
76         }
77
78         /* There were no lightly loaded elevators, so just choose randomly */
79         std::cout << "No LLE at all, choosing randomly" << std::endl;
80         num = choose_random_number_in_range (0, elevators_.size());
81         Elevator &e_ref = elevators_.at (num);
82
83         e_ref.stop_at (requested_stop);
84         return;
85
86 #ifdef ALGORITHM_IDLE
87         ElevatorList::iterator it;
88         std::vector<Elevator*> idle_elevators;
89         Stop requested_stop(floor, direction);
90
91         /* Find all idle Elevators */
92         for (it = elevators_.begin(); it != elevators_.end(); it++)
93                 if (it->is_idle ())
94                 {
95                         /* If we have an IDLE elevator that is currently sitting at the
96                          * requested floor, we should obviously send that. */
97                         if (it->distance_from (requested_stop) == 0)
98                         {
99                                 it->stop_at (requested_stop);
100                                 return;
101                         }
102
103                         /* Was not at the right floor, but still is a good cantidate */
104                         idle_elevators.push_back (&(*it));
105                 }
106
107         if (idle_elevators.size() > 0)
108         {
109                 std::vector<Elevator*>::iterator idle_it;
110                 bool found = false;
111                 float distance = INT_MAX;
112                 Elevator *e;
113
114                 /* Try to send the closest IDLE elevator */
115                 for (idle_it=idle_elevators.begin(); idle_it!=idle_elevators.end(); idle_it++)
116                 {
117                         if ((*idle_it)->distance_from (requested_stop) < distance)
118                         {
119                                 found = true;
120                                 distance = (*idle_it)->distance_from (requested_stop);
121                                 e = *idle_it;
122                         }
123                 }
124
125                 if (found)
126                 {
127                         e->stop_at (requested_stop);
128                         return;
129                 }
130
131                 /* No closest IDLE elevator was found, so choose one randomly */
132                 int num = choose_random_number_in_range (0, idle_elevators.size());
133
134                 idle_elevators.at (num) -> stop_at (requested_stop);
135                 return;
136         }
137
138         /* Find the Elevator which is closest to the requested Stop */
139         bool found = false;
140         float distance = INT_MAX;
141         Elevator *e;
142
143         for (it = elevators_.begin(); it != elevators_.end(); it++)
144         {
145                 if (it->distance_from (requested_stop) < distance)
146                 {
147                         found = true;
148                         distance = it->distance_from (requested_stop);
149                         e = &(*it);
150                 }
151         }
152
153         /* If we found one, send the closest Elevator */
154         if (found)
155         {
156                 e->stop_at (requested_stop);
157                 return;
158         }
159
160         /* Now we're having really bad luck. No elevators are idle, and none are closer than
161          * any other. A random choice will have to do. */
162         int num = choose_random_number_in_range (0, elevators_.size());
163         Elevator &e_ref = elevators_.at (num);
164
165         e_ref.stop_at (requested_stop);
166 #endif
167 }
168
169 void ElevatorController::elevator_request (int elevator_number, int floor)
170 {
171         std::cout << "Request that elevator=" << elevator_number << " stop at floor=" << floor << std::endl;
172
173         /* Check the parameters */
174         if (elevator_number < 0 || elevator_number > number_of_elevators_)
175                 throw bad_elevator ();
176
177         if (floor < 0 || floor > number_of_floors_)
178                 throw bad_floor ();
179
180         /* Construct the Stop to use */
181         Stop s(floor, ALL);
182
183         /* Get the Elevator */
184         Elevator &e = elevators_.at (elevator_number);
185
186         /* Tell it where to stop */
187         e.stop_at (s);
188 }
189
190 void ElevatorController::move_elevators ()
191 {
192         ElevatorList::iterator it;
193
194         for (it = elevators_.begin(); it != elevators_.end(); it++)
195                 it->move();
196 }
197
198 bool ElevatorController::oneElevatorWillStillStopAt (int floor, Direction direction) const
199 {
200         ElevatorList::const_iterator it;
201
202         for (it=elevators_.begin(); it!=elevators_.end(); it++)
203                 if (it->willStopAt (floor, direction))
204                         return true;
205
206         return false;
207 }
208
209 /* vim: set ts=4 sts=4 sw=4 noet tw=112: */