Subversion Repositories programming

Rev

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