X-Git-Url: https://irasnyder.com/gitweb/?a=blobdiff_plain;f=elevator.cpp;h=4a5eb37561ba85c667635aea5c0bd826ce012e95;hb=a897a1cb95028e3dbfa370ddafcc9a27110f96a7;hp=f034f633c238fc1a62a0b0d858dac2ec1eddd57f;hpb=28c9908e524bd7bd51e4141e21046e2a60b83bd0;p=cs356-p1-elevator.git diff --git a/elevator.cpp b/elevator.cpp index f034f63..4a5eb37 100644 --- a/elevator.cpp +++ b/elevator.cpp @@ -1,21 +1,23 @@ #include "elevator.hpp" -Elevator::Elevator () - : door_(CLOSED) +Elevator::Elevator (int elevator_number) + : state_(STATE_IDLE) + , wait_(0) , direction_(IDLE) - , current_position_() + , position_() , stops_() - , ELEVATOR_STEP(0.1) + , number_(elevator_number) { // Intentionally Left Empty } -Elevator::Elevator (int starting_floor) - : door_(CLOSED) +Elevator::Elevator (int starting_floor, int elevator_number) + : state_(STATE_IDLE) + , wait_(0) , direction_(IDLE) - , current_position_(starting_floor) + , position_(starting_floor) , stops_() - , ELEVATOR_STEP(0.1) + , number_(elevator_number) { // Intentionally Left Empty } @@ -23,10 +25,9 @@ Elevator::Elevator (int starting_floor) bool Elevator::currently_at_stop () const { StopList::const_iterator it; - Stop current(current_position_, direction_); + Stop current(position_, direction_); - /* Calculate the number of Stops above and below our - * current position */ + /* Calculate the number of Stops above and below our current position */ int stops_above = 0; int stops_below = 0; @@ -43,7 +44,7 @@ bool Elevator::currently_at_stop () const if (direction_ == UP && stops_above == 0) { for (it = stops_.begin (); it != stops_.end (); it++) - if (it->getPosition() == current_position_) + if (it->getPosition() == position_) return true; } @@ -51,7 +52,7 @@ bool Elevator::currently_at_stop () const if (direction_ == DOWN && stops_below == 0) { for (it = stops_.begin (); it != stops_.end (); it++) - if (it->getPosition() == current_position_) + if (it->getPosition() == position_) return true; } @@ -87,10 +88,100 @@ void Elevator::stop_at (Stop &stop) float Elevator::distance_from (Position &pos) const { - if (current_position_ > pos) - return current_position_ - pos; + if (position_ > pos) + return position_ - pos; + + return pos - position_; +} + +float Elevator::distance_from (Stop &s) const +{ + Direction d = s.getDirection(); + Position p = s.getPosition (); + + /* If direction doesn't matter, then only position does */ + if (d == ALL || direction_ == IDLE) + return distance_from (p); + + /* If we're not in the same direction, then we're "really far" away */ + if (d != direction_) + return INT_MAX; + + /* We must be in the correct direction, so pure distance is fine */ + return distance_from (p); +} + +void Elevator::transition_move_up () +{ + direction_ = UP; + position_ += ELEVATOR_STEP; + + // TODO: Call into the GUI to update the position + std::cout << "Updating the GUI with our position: " << position_ << std::endl; +} + +void Elevator::transition_move_down () +{ + direction_ = DOWN; + position_ -= ELEVATOR_STEP; + + // TODO: Call into the GUI to update the position + std::cout << "Updating the GUI with our position: " << position_ << std::endl; +} + +void Elevator::transition_move_idle () +{ + direction_ = IDLE; + // do not change position while IDLE +} + +void Elevator::transition_open_door () +{ + /* Calculate the number of Stops above and below our + * current position */ + StopList::const_iterator it; + Stop current = Stop(position_, direction_); + int stops_above = 0; + int stops_below = 0; + + for (it = stops_.begin(); it != stops_.end(); it++) + { + if (current < *it) + ++stops_above; + + if (current > *it) + ++stops_below; + } + + /* If we are going to switch direction, clear all stops here, + * regardless of direction. + * + * Otherwise, just clear this stop */ + if (direction_ == UP && stops_above == 0) + stops_.remove (Stop(position_, ALL)); + else if (direction_ == DOWN && stops_below == 0) + stops_.remove (Stop(position_, ALL)); + else + stops_.remove (Stop(position_, direction_)); + + // TODO: Call into the GUI to open the door + std::cout << "Opening Door" << std::endl; +} + +void Elevator::transition_close_door () +{ + // TODO: Call into the GUI to close the door + std::cout << "Closing Door" << std::endl; +} + +void Elevator::transition_begin_wait () +{ + wait_ = 10; +} - return pos - current_position_; +void Elevator::transition_continue_wait () +{ + --wait_; } #include @@ -99,38 +190,82 @@ static void debug (const std::string& s) std::cout << s << std::endl; } -void Elevator::move () +static std::string get_state_name (State s) { - static int wait = 0; + std::string sname; - /* Wait around if we need to. - * - * This is an artificial delay to make the elevators work in a - * much more natural fashion. This allows some delay to leave the - * doors open, or for the user to press floor selection buttons - * before the elevator starts moving - */ - if (wait > 0) + switch (s) { - debug ("waiting"); - --wait; - return; + case STATE_IDLE: + sname = "STATE_IDLE"; + break; + case STATE_UP: + sname = "STATE_UP"; + break; + case STATE_DOWN: + sname = "STATE_DOWN"; + break; + case STATE_WAIT: + sname = "STATE_WAIT"; + break; + case STATE_OPEN_DOOR: + sname = "STATE_OPEN_DOOR"; + break; + case STATE_CLOSE_DOOR: + sname = "STATE_CLOSE_DOOR"; + break; + default: + sname = "BAD STATE"; + break; } - /* close the door if it is open. This is a requirement to move */ - if (door_ != CLOSED) + return sname; +} + +static std::string get_event_name (Event e) +{ + std::string ename; + + switch (e) { - debug ("closing door"); - wait = 10; - door_ = CLOSED; - close_door (); - return; + case EVT_IDLE: + ename = "EVT_IDLE"; + break; + case EVT_UP: + ename = "EVT_UP"; + break; + case EVT_DOWN: + ename = "EVT_DOWN"; + break; + case EVT_WAIT: + ename = "EVT_WAIT"; + break; + case EVT_OPEN_DOOR: + ename = "EVT_OPEN_DOOR"; + break; + case EVT_CLOSE_DOOR: + ename = "EVT_CLOSE_DOOR"; + break; + default: + ename = "BAD EVENT"; + break; } + return ename; +} + +static void bad_transition (State s, Event e) +{ + std::cout << "Bad State Transition: " << get_state_name (s) + << " -> " << get_event_name (e) << std::endl; +} + +Event Elevator::find_next_event () const +{ /* Calculate the number of Stops above and below our * current position */ StopList::const_iterator it; - Stop current = Stop(current_position_, direction_); + Stop current = Stop(position_, direction_); int stops_above = 0; int stops_below = 0; @@ -143,103 +278,212 @@ void Elevator::move () ++stops_below; } - /* Check if we are currently at a stop */ - if (currently_at_stop ()) + /* Now figure out which state transition to make */ + switch (state_) { - std::cout << "At A Stop: " << Stop(current_position_, direction_) << std::endl; - std::cout << "above=" << stops_above << " below=" << stops_below << std::endl; - wait = 10; + case STATE_IDLE: - /* Remove all stops here if we are switching direction */ - if (stops_above == 0 && direction_ == UP) - stops_.remove (Stop(current_position_, ALL)); + if (currently_at_stop ()) + return EVT_OPEN_DOOR; - if (stops_below == 0 && direction_ == DOWN) - stops_.remove (Stop(current_position_, ALL)); + if (stops_above > 0) + return EVT_UP; - stops_.remove (Stop(current_position_, direction_)); + if (stops_below > 0) + return EVT_DOWN; - /* Open the door */ - door_ = OPEN; - open_door (); + return EVT_IDLE; - return; - } + break; + case STATE_UP: - /* Check if we need to change direction */ - if (stops_above == 0 && stops_below > 0 && direction_ == UP) - { - debug ("1: DOWN"); - direction_ = DOWN; - } + if (currently_at_stop ()) + return EVT_OPEN_DOOR; - if (stops_below == 0 && stops_above > 0 && direction_ == DOWN) - { - debug ("2: UP"); - direction_ = UP; - } + return EVT_UP; - if (stops_above == 0 && stops_below == 0 && direction_ != IDLE) - { - debug ("3: IDLE"); - direction_ = IDLE; - } + break; + case STATE_DOWN: - if (direction_ == IDLE && stops_above > 0) - { - debug ("4: UP"); - direction_ = UP; - } + if (currently_at_stop ()) + return EVT_OPEN_DOOR; - if (direction_ == IDLE && stops_below > 0) - { - debug ("5: DOWN"); - direction_ = DOWN; - } + return EVT_DOWN; + break; + case STATE_WAIT: + + if (wait_ > 0) + return EVT_WAIT; + + return EVT_CLOSE_DOOR; - /* Move in the correct direction */ - switch (direction_) - { - case IDLE: break; - case UP: - current_position_ += ELEVATOR_STEP; + case STATE_OPEN_DOOR: + + return EVT_WAIT; + break; - case DOWN: - current_position_ -= ELEVATOR_STEP; + case STATE_CLOSE_DOOR: + + if (currently_at_stop ()) + return EVT_OPEN_DOOR; + + if (direction_ == UP && stops_above > 0) + return EVT_UP; + + if (direction_ == DOWN && stops_below > 0) + return EVT_DOWN; + + /* We need to switch directions */ + if (direction_ == UP && stops_above == 0 && stops_below > 0) + return EVT_DOWN; + + if (direction_ == DOWN && stops_below == 0 && stops_above > 0) + return EVT_UP; + + return EVT_IDLE; + break; default: - std::cout << __FILE__ << ":" << __LINE__ << " Unhandled Elevator Position" << std::endl; + std::cout << "find_next_event(): Bad State" << std::endl; break; } - - /* Call the GUI with our updated position */ - update_position (); } -bool Elevator::is_idle () const +void Elevator::move () { - return direction_ == IDLE; -} + /* Generate Events */ + Event e = find_next_event (); -void Elevator::update_position () const -{ - std::cout << "Updating the GUI with our position: " << current_position_ << std::endl; -} + std::cout << "State Transition: " << get_state_name (state_) << " with " + << get_event_name (e) << std::endl; -void Elevator::open_door () const -{ - std::cout << "Opening Door" << std::endl; -} + switch (state_) + { + case STATE_IDLE: + switch (e) + { + case EVT_UP: + state_ = STATE_UP; + transition_move_up (); + break; + case EVT_DOWN: + state_ = STATE_DOWN; + transition_move_down (); + break; + case EVT_IDLE: + state_ = STATE_IDLE; + transition_move_idle (); + break; + case EVT_OPEN_DOOR: + state_ = STATE_OPEN_DOOR; + transition_open_door (); + break; + default: + bad_transition (state_, e); + break; + } // end switch (e) + break; -void Elevator::close_door () const -{ - std::cout << "Closing Door" << std::endl; -} + case STATE_UP: + switch (e) + { + case EVT_UP: + state_ = STATE_UP; + transition_move_up (); + break; + case EVT_OPEN_DOOR: + state_ = STATE_OPEN_DOOR; + transition_open_door (); + break; + default: + bad_transition (state_, e); + break; + } // end switch (e) + break; + case STATE_DOWN: + switch (e) + { + case EVT_DOWN: + state_ = STATE_DOWN; + transition_move_down (); + break; + case EVT_OPEN_DOOR: + state_ = STATE_OPEN_DOOR; + transition_open_door (); + break; + default: + bad_transition (state_, e); + break; + } // end switch (e) + break; + case STATE_WAIT: + switch (e) + { + case EVT_WAIT: + state_ = STATE_WAIT; + transition_continue_wait (); + break; + case EVT_CLOSE_DOOR: + state_ = STATE_CLOSE_DOOR; + transition_close_door (); + break; + default: + bad_transition (state_, e); + break; + } // end switch (e) + break; + case STATE_OPEN_DOOR: + switch (e) + { + case EVT_WAIT: + state_ = STATE_WAIT; + transition_begin_wait (); + break; + default: + bad_transition (state_, e); + break; + } // end switch (e) + break; + + case STATE_CLOSE_DOOR: + switch (e) + { + case EVT_OPEN_DOOR: + state_ = STATE_OPEN_DOOR; + transition_open_door (); + break; + case EVT_UP: + state_ = STATE_UP; + transition_move_up (); + break; + case EVT_DOWN: + state_ = STATE_DOWN; + transition_move_down (); + break; + case EVT_IDLE: + state_ = STATE_IDLE; + transition_move_idle (); + break; + default: + bad_transition (state_, e); + break; + } // end switch (e) + break; + default: + std::cout << "Bad State: " << get_state_name (state_) << std::endl; + break; + } +} + +bool Elevator::is_idle () const +{ + return direction_ == IDLE; +} /* vim: set ts=4 sts=4 sw=4 noexpandtab textwidth=112: */