Subversion Repositories programming

Rev

Rev 329 | Rev 332 | 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 = std::vector<Elevator> (num_elevators, Elevator (num_floors));

    for (int i=0; i<num_elevators; i++)
        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);
    elevators[elevator_number].push_button (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 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);

        // 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 ();
}