Rev 331 | Rev 334 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include "controller.h"
Controller::Controller (int num_floors, int num_elevators) : num_floors (num_floors), num_elevators (num_elevators)
{
assert (num_floors > 2);
assert (num_elevators > 0);
elevators.reserve (num_elevators);
for (int i=0; i<num_elevators; i++)
{
elevators.push_back (Elevator (num_floors));
elevators[i].set_controller (this);
}
}
Controller::~Controller ()
{
}
void Controller::request_elevator (int on_floor, int direction)
{
assert (on_floor <= num_floors);
assert (on_floor > 0);
assert (direction == MOVE_UP || direction == MOVE_DOWN);
float distance = INT_MAX;
int elevator_number;
// check that there is not already an elevator requested
// to this floor. If there is already one, ignore this
// request.
if (floor_already_requested (on_floor))
return;
// find elevator that is closest, AND NOT moving away
// "push" it's button
elevator_number = find_closest_elevator (on_floor, direction);
elevators[elevator_number].push_button (on_floor);
printf ("elevator[%d] gets queued for floor: %d\n", elevator_number, on_floor);
}
/**
* Check if there is an elevator already in the queue to stop
* at the floor given as a parameter.
*/
bool Controller::floor_already_requested (int on_floor)
{
int i;
for (i=0; i<num_elevators; i++)
if (elevators[i].button_is_pushed (on_floor))
return true;
return false;
}
/**
* Return the number of the closest elevator to the
* floor given as a parameter.
*
* We only want to choose elevators that are close and
* heading in the right direction, or the closest elevator
* if it is sitting idle.
*/
int Controller::find_closest_elevator (int to_floor, int in_direction)
{
int i;
float distance = INT_MAX;
float temp_distance;
int answer;
float cur_floor;
int direction;
for (i=0; i<num_elevators; i++)
{
cur_floor = elevators[i].get_current_floor ();
direction = elevators[i].get_direction ();
temp_distance = fabsf (cur_floor - to_floor);
// Automatically discard elevators that are moving in the wrong
// direction, but DO consider ones that are idle.
if (direction != IDLE || direction != in_direction)
continue;
// Check that this elevator is closer
if (temp_distance < distance)
{
// If we are below the floor we want to go to and we
// are moving up, then this is an ok choice
if (cur_floor < to_floor && direction == MOVE_UP)
{
answer = i;
distance = temp_distance;
}
// If we are above the floor we want to go to and we
// are moving down, then this is an ok choice
else if (cur_floor > to_floor && direction == MOVE_DOWN)
{
answer = i;
distance = temp_distance;
}
// If we are closest, but idle, then this is an ok choice
else
{
answer = i;
distance = temp_distance;
}
}
}
return answer;
}
void Controller::disable_elevator (int elevator_number)
{
}
void Controller::enable_elevator (int elevator_number)
{
// make sure elevator is enabled first
}
void Controller::start_all_elevators ()
{
int i;
for (i=0; i<num_elevators; i++)
elevators[i].thread_start ();
}
void Controller::stop_all_elevators ()
{
int i;
for (i=0; i<num_elevators; i++)
elevators[i].thread_stop ();
}
void Controller::pause_all_elevators ()
{
int i;
for (i=0; i<num_elevators; i++)
elevators[i].thread_pause ();
}
void Controller::unpause_all_elevators ()
{
int i;
for (i=0; i<num_elevators; i++)
elevators[i].thread_unpause ();
}