034d4d9941a14b37be2ec6a36089cb5cad8655fd
[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*> idle_elevators;
31         Stop requested_stop(floor, direction);
32
33         /* Find all idle Elevators */
34         for (it = elevators_.begin(); it != elevators_.end(); it++)
35                 if (it->is_idle ())
36                 {
37                         /* If we have an IDLE elevator that is currently sitting at the
38                          * requested floor, we should obviously send that. */
39                         if (it->distance_from (requested_stop) == 0)
40                         {
41                                 it->stop_at (requested_stop);
42                                 return;
43                         }
44
45                         /* Was not at the right floor, but still is a good cantidate */
46                         idle_elevators.push_back (&(*it));
47                 }
48
49         if (idle_elevators.size() > 0)
50         {
51                 std::vector<Elevator*>::iterator idle_it;
52                 bool found = false;
53                 float distance = INT_MAX;
54                 Elevator *e;
55
56                 /* Try to send the closest IDLE elevator */
57                 for (idle_it=idle_elevators.begin(); idle_it!=idle_elevators.end(); idle_it++)
58                 {
59                         if ((*idle_it)->distance_from (requested_stop) < distance)
60                         {
61                                 found = true;
62                                 distance = (*idle_it)->distance_from (requested_stop);
63                                 e = *idle_it;
64                         }
65                 }
66
67                 if (found)
68                 {
69                         e->stop_at (requested_stop);
70                         return;
71                 }
72
73                 /* No closest IDLE elevator was found, so choose one randomly */
74                 int num = choose_random_number_in_range (0, idle_elevators.size());
75
76                 idle_elevators.at (num) -> stop_at (requested_stop);
77                 return;
78         }
79
80         /* Find the Elevator which is closest to the requested Stop */
81         bool found = false;
82         float distance = INT_MAX;
83         Elevator *e;
84
85         for (it = elevators_.begin(); it != elevators_.end(); it++)
86         {
87                 if (it->distance_from (requested_stop) < distance)
88                 {
89                         found = true;
90                         distance = it->distance_from (requested_stop);
91                         e = &(*it);
92                 }
93         }
94
95         /* If we found one, send the closest Elevator */
96         if (found)
97         {
98                 e->stop_at (requested_stop);
99                 return;
100         }
101
102         /* Now we're having really bad luck. No elevators are idle, and none are closer than
103          * any other. A random choice will have to do. */
104         int num = choose_random_number_in_range (0, elevators_.size());
105         Elevator &e_ref = elevators_.at (num);
106
107         e_ref.stop_at (requested_stop);
108 }
109
110 void ElevatorController::elevator_request (int elevator_number, int floor)
111 {
112         std::cout << "Request that elevator=" << elevator_number << " stop at floor=" << floor << std::endl;
113
114         /* Check the parameters */
115         if (elevator_number < 0 || elevator_number > number_of_elevators_)
116                 throw bad_elevator ();
117
118         if (floor < 0 || floor > number_of_floors_)
119                 throw bad_floor ();
120
121         /* Construct the Stop to use */
122         Stop s(floor, ALL);
123
124         /* Get the Elevator */
125         Elevator &e = elevators_.at (elevator_number);
126
127         /* Tell it where to stop */
128         e.stop_at (s);
129 }
130
131 void ElevatorController::move_elevators ()
132 {
133         ElevatorList::iterator it;
134
135         for (it = elevators_.begin(); it != elevators_.end(); it++)
136                 it->move();
137 }
138
139 /* vim: set ts=4 sts=4 sw=4 noet tw=112: */