Subversion Repositories programming

Rev

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