79418ba583e88c6a81fc14353fa451557dd46a4d
[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                 std::cout << "loop1" << std::endl;
40                 if (it->getLoad() < max_load)
41                         low_load_elevators.push_back (&(*it));
42         }
43
44         std::vector<Elevator*>::iterator lle_it;
45         bool found = false;
46         float distance = INT_MAX;
47         Elevator *e;
48         int num;
49
50         /* Make sure there are lightly loaded elevators */
51         if (low_load_elevators.size() > 0)
52         {
53                 /* Find the closest lightly loaded elevator */
54                 for (lle_it = low_load_elevators.begin(); lle_it != low_load_elevators.end(); lle_it++)
55                 {
56                         std::cout << "loop2" << std::endl;
57                         if ((*lle_it)->distance_from (requested_stop) < distance)
58                         {
59                                 found = true;
60                                 distance = (*lle_it)->distance_from (requested_stop);
61                                 e = *lle_it;
62                         }
63                 }
64
65                 /* Found a closest one, send it */
66                 if (found)
67                 {
68                         std::cout << "Found closest LLE" << std::endl;
69                         e->stop_at (requested_stop);
70                         return;
71                 }
72
73                 /* No closest one, so send randomly */
74                 std::cout << "No closest LLE: choosing randomly" << std::endl;
75                 num = choose_random_number_in_range (0, low_load_elevators.size());
76                 low_load_elevators.at (num) -> stop_at (requested_stop);
77                 return;
78         }
79
80         /* There were no lightly loaded elevators, so just choose randomly */
81         std::cout << "No LLE at all, choosing randomly" << std::endl;
82         num = choose_random_number_in_range (0, elevators_.size());
83         Elevator &e_ref = elevators_.at (num);
84
85         e_ref.stop_at (requested_stop);
86         return;
87
88 #ifdef ALGORITHM_IDLE
89         ElevatorList::iterator it;
90         std::vector<Elevator*> idle_elevators;
91         Stop requested_stop(floor, direction);
92
93         /* Find all idle Elevators */
94         for (it = elevators_.begin(); it != elevators_.end(); it++)
95                 if (it->is_idle ())
96                 {
97                         /* If we have an IDLE elevator that is currently sitting at the
98                          * requested floor, we should obviously send that. */
99                         if (it->distance_from (requested_stop) == 0)
100                         {
101                                 it->stop_at (requested_stop);
102                                 return;
103                         }
104
105                         /* Was not at the right floor, but still is a good cantidate */
106                         idle_elevators.push_back (&(*it));
107                 }
108
109         if (idle_elevators.size() > 0)
110         {
111                 std::vector<Elevator*>::iterator idle_it;
112                 bool found = false;
113                 float distance = INT_MAX;
114                 Elevator *e;
115
116                 /* Try to send the closest IDLE elevator */
117                 for (idle_it=idle_elevators.begin(); idle_it!=idle_elevators.end(); idle_it++)
118                 {
119                         if ((*idle_it)->distance_from (requested_stop) < distance)
120                         {
121                                 found = true;
122                                 distance = (*idle_it)->distance_from (requested_stop);
123                                 e = *idle_it;
124                         }
125                 }
126
127                 if (found)
128                 {
129                         e->stop_at (requested_stop);
130                         return;
131                 }
132
133                 /* No closest IDLE elevator was found, so choose one randomly */
134                 int num = choose_random_number_in_range (0, idle_elevators.size());
135
136                 idle_elevators.at (num) -> stop_at (requested_stop);
137                 return;
138         }
139
140         /* Find the Elevator which is closest to the requested Stop */
141         bool found = false;
142         float distance = INT_MAX;
143         Elevator *e;
144
145         for (it = elevators_.begin(); it != elevators_.end(); it++)
146         {
147                 if (it->distance_from (requested_stop) < distance)
148                 {
149                         found = true;
150                         distance = it->distance_from (requested_stop);
151                         e = &(*it);
152                 }
153         }
154
155         /* If we found one, send the closest Elevator */
156         if (found)
157         {
158                 e->stop_at (requested_stop);
159                 return;
160         }
161
162         /* Now we're having really bad luck. No elevators are idle, and none are closer than
163          * any other. A random choice will have to do. */
164         int num = choose_random_number_in_range (0, elevators_.size());
165         Elevator &e_ref = elevators_.at (num);
166
167         e_ref.stop_at (requested_stop);
168 #endif
169 }
170
171 void ElevatorController::elevator_request (int elevator_number, int floor)
172 {
173         std::cout << "Request that elevator=" << elevator_number << " stop at floor=" << floor << std::endl;
174
175         /* Check the parameters */
176         if (elevator_number < 0 || elevator_number > number_of_elevators_)
177                 throw bad_elevator ();
178
179         if (floor < 0 || floor > number_of_floors_)
180                 throw bad_floor ();
181
182         /* Construct the Stop to use */
183         Stop s(floor, ALL);
184
185         /* Get the Elevator */
186         Elevator &e = elevators_.at (elevator_number);
187
188         /* Tell it where to stop */
189         e.stop_at (s);
190 }
191
192 void ElevatorController::move_elevators ()
193 {
194         ElevatorList::iterator it;
195
196         for (it = elevators_.begin(); it != elevators_.end(); it++)
197                 it->move();
198 }
199
200 /* vim: set ts=4 sts=4 sw=4 noet tw=112: */