Subversion Repositories programming

Rev

Rev 330 | Rev 332 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
321 ira 1
 
2
#include "elevator.h"
3
 
4
// FIXME
5
// FIXME
6
// FIXME
7
void debug_puts (const char* s)
8
{
331 ira 9
#ifndef NO_DEBUG_PUTS
321 ira 10
    puts (s);
11
#endif
12
}
13
// FIXME
14
// FIXME
15
// FIXME
16
 
17
Elevator::Elevator (int num_floors) : num_floors(num_floors)
18
{
19
    this->terminate = false;
20
    this->pause = false;
21
    this->direction = IDLE;
22
    this->current_floor = 1.0;
331 ira 23
    this->controller = NULL;
321 ira 24
 
328 ira 25
    this->stop_at_floors = std::vector<bool> (num_floors+1, false);
321 ira 26
}
27
 
28
Elevator::~Elevator ()
29
{
30
    this->pause = false;
31
    this->terminate = true;
32
}
33
 
34
int Elevator::get_direction ()
35
{
36
    return this->direction;
37
}
38
 
39
/**
40
 * Return the number of floors above the current one that
41
 * are queued to be stopped at.
42
 */
43
int Elevator::floors_above_current ()
44
{
45
    int i = ((int)current_floor) + 1;
46
    int count = 0;
47
 
48
    for (/* see above */; i<num_floors+1; i++)
49
        if (stop_at_floors[i])
50
            count++;
51
 
52
    return count;
53
}
54
 
55
/**
56
 * Return the number of floors below the current one that
57
 * are queued to be stopped at.
58
 */
59
int Elevator::floors_below_current ()
60
{
61
    int i;
62
    int count = 0;
63
 
64
    if (near_a_floor ())
65
        i = (int)current_floor - 1;
66
    else
67
        i = (int)current_floor;
68
 
69
    for (/* see above */; i>0; i--)
70
        if (stop_at_floors[i])
71
            count++;
72
 
73
    return count;
74
}
75
 
76
void Elevator::push_button (int floor)
77
{
78
    assert (floor <= num_floors && floor > 0);
79
 
80
    this->stop_at_floors[floor] = true;
81
}
82
 
83
/**
84
 * This function is the entry point for a thread.
85
 *
86
 * You must pass the object in, since this is a static function
87
 * and we aren't allowed to access the this pointer.
88
 */
89
void Elevator::thread_entry (const Elevator *me)
90
{
91
    Elevator *pthis = (Elevator*)me;
92
 
93
    while (!pthis->terminate)
94
    {
95
        /* Implement "pausing" */
96
        while (pthis->pause)
97
        {
98
            usleep (ELEVATOR_TIME_PAUSE_USEC);
99
        }
100
 
101
        pthis->run_elevator_logic ();
102
 
329 ira 103
        std::cout << pthis << " Position: " << pthis->current_floor << std::endl;
321 ira 104
        usleep (ELEVATOR_TIME_DELAY_USEC);
105
    }
106
}
107
 
329 ira 108
void Elevator::thread_start ()
109
{
110
    boost::thread t1 (boost::bind (this->thread_entry, this));
111
}
112
 
321 ira 113
void Elevator::run_elevator_logic ()
114
{
115
    int i;
116
 
117
    /* Decide what to do */
118
    switch (direction)
119
    {
120
        case IDLE:
121
 
122
            /* Move towards the direction that has more floors to stop at.
123
             * Prefer DOWN if there is a tie. */
124
            if (has_floors_to_stop_at ())
125
            {
126
                direction = (floors_above_current () > floors_below_current ()) ? MOVE_UP : MOVE_DOWN;
127
                printf ("changed direction to: %s\n", (direction == MOVE_UP) ? "MOVE_UP" : "MOVE_DOWN");
128
            }
129
 
130
            break;
131
 
132
        case MOVE_UP:
133
 
134
            /* Decide if we should stop at the floor we're at */
135
            if (should_stop_at_current_floor ())
136
            {
331 ira 137
                debug_puts ("stop at floor -- while going up");
330 ira 138
                stop_at_floors[(int)(current_floor+0.5)] = false;
331 ira 139
                have_user_enter_buttons ();
321 ira 140
            }
141
 
142
            /* Decide to sit idle if we have no more floors to stop at */
143
            if (!has_floors_to_stop_at ())
144
            {
145
                debug_puts ("decides to sit idle");
146
                direction = IDLE;
147
            }
148
            /* Decide to switch directions if we have no more floors to stop
149
             * at in the current direction, but we have floors in the
150
             * opposite direction to stop at. */
151
            else if (floors_below_current () && !floors_above_current ())
152
            {
153
                debug_puts ("decides to switch direction to down");
154
                direction = MOVE_DOWN;
155
            }
156
            /* Since nothing else applies, we should keep moving in the
157
             * current direction, up. */
158
            else
159
            {
160
                current_floor += ELEVATOR_TIME_MOVE_AMOUNT;
161
                debug_puts ("moving up");
162
 
163
                // TODO: Add a check here to make sure we don't go too high
164
 
165
            }
166
 
167
            break;
168
 
169
        case MOVE_DOWN:
170
 
171
            /* Decide if we should stop at the floor we're at */
172
            if (should_stop_at_current_floor ())
173
            {
174
                debug_puts ("stop at floor -- while going down");
330 ira 175
                stop_at_floors[(int)(current_floor)] = false;
331 ira 176
                have_user_enter_buttons ();
321 ira 177
            }
178
 
179
            /* Decide to sit idle if we have no more floors to stop at */
180
            if (!has_floors_to_stop_at ())
181
            {
182
                debug_puts ("decides to sit idle");
183
                direction = IDLE;
184
            }
185
            /* Decide to switch directions if we have no more floors to stop
186
             * at in the current direction, but we have floors in the
187
             * opposite direction to stop at. */
188
            else if (floors_above_current () && !floors_below_current ())
189
            {
190
                debug_puts ("decides to switch direction to up");
191
                direction = MOVE_UP;
192
            }
193
            /* Since nothing else applies, we should keep moving in the
194
             * current direction, down. */
195
            else
196
            {
197
                current_floor -= ELEVATOR_TIME_MOVE_AMOUNT;
198
                debug_puts ("moving down");
199
 
200
                // TODO: Add a check here to make sure we don't go too low
201
 
202
            }
203
 
204
            break;
205
 
206
        default:
207
 
208
            debug_puts ("bad value of direction");
209
            break;
210
    }
211
}
212
 
213
/**
214
 * Call this to stop the thread from running.
215
 */
331 ira 216
void Elevator::thread_stop ()
321 ira 217
{
218
    this->terminate = true;
219
}
220
 
221
/**
222
 * Call this to pause the thread without exiting it.
223
 */
224
void Elevator::thread_pause ()
225
{
226
    this->pause = true;
227
}
228
 
229
/**
230
 * Call this to unpause the thread.
231
 */
232
void Elevator::thread_unpause ()
233
{
234
    this->pause = false;
235
}
236
 
237
bool Elevator::near_a_floor ()
238
{
330 ira 239
    int i;
321 ira 240
 
330 ira 241
    for (i=1; i<=num_floors; i++)
242
        if (near_floor (i))
243
            return true;
321 ira 244
 
330 ira 245
    return false;
321 ira 246
}
247
 
248
bool Elevator::near_floor (int floor)
249
{
330 ira 250
    const float thresh  = ELEVATOR_TIME_MOVE_AMOUNT / 2.0;
251
    const float greater = floor + thresh;
252
    const float lower   = floor - thresh;
253
 
254
    if (current_floor > lower && current_floor < greater)
321 ira 255
        return true;
256
 
257
    return false;
258
}
259
 
260
bool Elevator::has_floors_to_stop_at ()
261
{
262
    int i;
263
 
264
    for (i=1; i<=num_floors; i++)
265
        if (stop_at_floors[i])
266
            return true;
267
 
268
    return false;
269
}
270
 
271
bool Elevator::should_stop_at_current_floor ()
272
{
273
    int i;
274
 
329 ira 275
    for (i=1; i<=num_floors; i++)
321 ira 276
        if (near_floor (i) && stop_at_floors[i] == true)
277
            return true;
278
 
279
    return false;
280
}
281
 
328 ira 282
bool Elevator::button_is_pushed (int floor)
283
{
284
    assert (floor <= num_floors);
285
    assert (floor > 0);
286
 
287
    return stop_at_floors[floor];
288
}
289
 
290
float Elevator::get_current_floor ()
291
{
292
    return current_floor;
293
}
294
 
331 ira 295
void Elevator::set_controller (Controller *c)
296
{
297
    this->controller = c;
298
}
299
 
300
void Elevator::have_user_enter_buttons ()
301
{
302
    controller->pause_all_elevators ();
303
    sleep (1);
304
 
305
    std::string s;
306
 
307
    std::cout << "Enter floors to stop at for elevator (space seperated): ";
308
    getline (std::cin, s);
309
 
310
    typedef std::vector<std::string> split_vector_type;
311
    split_vector_type SplitVec;
312
    boost::split (SplitVec, s, boost::is_any_of(" "));
313
 
314
    std::cout << "found " << SplitVec.size() << " strings" << std::endl;
315
 
316
    int i, val;
317
    for (i=0; i<SplitVec.size(); i++)
318
    {
319
        val = atoi (SplitVec[i].c_str());
320
 
321
        if (val > 0 && val <= num_floors)
322
            this->push_button (val);
323
    }
324
 
325
    controller->unpause_all_elevators ();
326
}
327