Subversion Repositories programming

Rev

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