Subversion Repositories programming

Rev

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

Rev Author Line No. Line
338 ira 1
/*******************************************************************************
2
 * controller.cpp
3
 *
4
 * Implementation for the Controller class.
5
 *
6
 * Copyright 2006, Ira W. Snyder (devel@irasnyder.com)
7
 ******************************************************************************/
321 ira 8
 
9
#include "controller.h"
10
 
11
Controller::Controller (int num_floors, int num_elevators) : num_floors (num_floors), num_elevators (num_elevators)
12
{
13
    assert (num_floors > 2);
14
    assert (num_elevators > 0);
15
 
334 ira 16
    elevator.reserve (num_elevators);
331 ira 17
 
18
    for (int i=0; i<num_elevators; i++)
332 ira 19
    {
334 ira 20
        elevator.push_back (new Elevator (num_floors));
21
        elevator.at(i) -> set_controller (this);
332 ira 22
    }
335 ira 23
 
24
    // Seed the RNG
25
    srandom (time(NULL));
321 ira 26
}
27
 
28
Controller::~Controller ()
29
{
30
}
31
 
329 ira 32
void Controller::request_elevator (int on_floor, int direction)
321 ira 33
{
334 ira 34
    assert (on_floor < num_floors);
35
    assert (on_floor >= 0);
331 ira 36
    assert (direction == MOVE_UP || direction == MOVE_DOWN);
328 ira 37
 
38
    float distance = INT_MAX;
39
    int elevator_number;
40
 
41
    // check that there is not already an elevator requested
42
    // to this floor. If there is already one, ignore this
43
    // request.
44
    if (floor_already_requested (on_floor))
45
        return;
46
 
47
    // find elevator that is closest, AND NOT moving away
48
    // "push" it's button
332 ira 49
    elevator_number = find_closest_elevator (on_floor, direction);
334 ira 50
    elevator.at(elevator_number) -> push_button (on_floor);
332 ira 51
 
339 ira 52
    //printf ("elevator[%d] gets queued for floor: %d\n", elevator_number, on_floor);
321 ira 53
}
54
 
328 ira 55
/**
56
 * Check if there is an elevator already in the queue to stop
57
 * at the floor given as a parameter.
58
 */
59
bool Controller::floor_already_requested (int on_floor)
60
{
336 ira 61
    assert (on_floor >= 0);
62
    assert (on_floor < num_floors);
63
 
328 ira 64
    int i;
65
 
66
    for (i=0; i<num_elevators; i++)
334 ira 67
        if (elevator.at(i) -> button_is_pushed (on_floor))
328 ira 68
            return true;
69
 
70
    return false;
71
}
72
 
73
/**
74
 * Return the number of the closest elevator to the
75
 * floor given as a parameter.
76
 *
77
 * We only want to choose elevators that are close and
78
 * heading in the right direction, or the closest elevator
79
 * if it is sitting idle.
80
 */
332 ira 81
int Controller::find_closest_elevator (int to_floor, int in_direction)
328 ira 82
{
336 ira 83
    assert (to_floor >= 0);
84
    assert (to_floor < num_floors);
85
    assert (in_direction == MOVE_UP || in_direction == MOVE_DOWN);
86
 
328 ira 87
    int i;
88
    float distance = INT_MAX;
89
    float temp_distance;
335 ira 90
    int answer = -1;
328 ira 91
 
92
    float cur_floor;
335 ira 93
    int   cur_direction;
328 ira 94
 
339 ira 95
    //printf ("finding closest elevator: to_floor=%d -- in_direction=%d\n", to_floor, in_direction);
335 ira 96
 
328 ira 97
    for (i=0; i<num_elevators; i++)
98
    {
334 ira 99
        cur_floor = elevator.at(i) -> get_current_floor ();
335 ira 100
        cur_direction = elevator.at(i) -> get_direction ();
328 ira 101
        temp_distance = fabsf (cur_floor - to_floor);
102
 
339 ira 103
        //printf ("cur_floor=%e -- direc=%d -- t_dist=%e\n", cur_floor, cur_direction, temp_distance);
334 ira 104
 
332 ira 105
        // Automatically discard elevators that are moving in the wrong
106
        // direction, but DO consider ones that are idle.
335 ira 107
        if (cur_direction == MOVE_DOWN && in_direction == MOVE_UP)
108
        {
339 ira 109
            //printf ("type 1: skipped elevator[%d]\n", i);
332 ira 110
            continue;
335 ira 111
        }
332 ira 112
 
335 ira 113
        if (cur_direction == MOVE_UP && in_direction == MOVE_DOWN)
114
        {
339 ira 115
            //printf ("type 2: skipped elevator[%d]\n", i);
334 ira 116
            continue;
335 ira 117
        }
334 ira 118
 
335 ira 119
        if (cur_floor < to_floor && cur_direction == MOVE_UP)
328 ira 120
        {
339 ira 121
            //printf ("good cantidate type 1\n");
335 ira 122
            // GOOD CANTIDATE
123
            if (temp_distance < distance)
328 ira 124
            {
125
                answer = i;
126
                distance = temp_distance;
127
            }
335 ira 128
        }
129
 
130
        if (cur_floor > to_floor && cur_direction == MOVE_DOWN)
131
        {
339 ira 132
            //printf ("good cantidate type 2\n");
335 ira 133
            // GOOD CANTIDATE
134
            if (temp_distance < distance)
328 ira 135
            {
136
                answer = i;
137
                distance = temp_distance;
138
            }
139
        }
335 ira 140
 
141
        if (cur_direction == IDLE && temp_distance < distance)
142
        {
339 ira 143
            //printf ("idle cantidate\n");
335 ira 144
            answer = i;
145
            distance = temp_distance;
146
        }
328 ira 147
    }
148
 
335 ira 149
    // If we failed to find an elevator, then we need to
150
    // pick at random.
151
    if (answer == -1)
152
    {
153
        // Pick a random number in the range [0,num_elevators-1]
154
        answer = (int) (0.0 + ((num_elevators - 1.0) * (random() / (RAND_MAX + 1.0))));
155
 
156
        printf ("picked at random: %d\n", answer);
157
 
158
        assert (answer >= 0);
159
        assert (answer < num_elevators);
160
    }
161
 
328 ira 162
    return answer;
163
}
164
 
329 ira 165
void Controller::disable_elevator (int elevator_number)
166
{
167
}
168
 
169
void Controller::enable_elevator (int elevator_number)
170
{
171
    // make sure elevator is enabled first
172
}
173
 
331 ira 174
void Controller::start_all_elevators ()
175
{
176
    int i;
177
 
178
    for (i=0; i<num_elevators; i++)
334 ira 179
        elevator.at(i) -> thread_start ();
331 ira 180
}
181
 
182
void Controller::stop_all_elevators ()
183
{
184
    int i;
185
 
186
    for (i=0; i<num_elevators; i++)
334 ira 187
        elevator.at(i) -> thread_stop ();
331 ira 188
}
189
 
190
void Controller::pause_all_elevators ()
191
{
192
    int i;
193
 
194
    for (i=0; i<num_elevators; i++)
334 ira 195
        elevator.at(i) -> thread_pause ();
331 ira 196
}
197
 
198
void Controller::unpause_all_elevators ()
199
{
200
    int i;
201
 
202
    for (i=0; i<num_elevators; i++)
334 ira 203
        elevator.at(i) -> thread_unpause ();
331 ira 204
}
205
 
334 ira 206