X-Git-Url: https://irasnyder.com/gitweb/?a=blobdiff_plain;f=elevator.cpp;h=038bc297cba2dbbe30cacdbc1674eef4e9021b49;hb=f95be7131a6221491745f0a001f45589aa6acca3;hp=f034f633c238fc1a62a0b0d858dac2ec1eddd57f;hpb=28c9908e524bd7bd51e4141e21046e2a60b83bd0;p=cs356-p1-elevator.git diff --git a/elevator.cpp b/elevator.cpp index f034f63..038bc29 100644 --- a/elevator.cpp +++ b/elevator.cpp @@ -1,21 +1,24 @@ #include "elevator.hpp" +#include "main.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 +26,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 +45,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 +53,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; } @@ -60,6 +62,14 @@ bool Elevator::currently_at_stop () const if (*it == current) return true; + /* Check if we are IDLE. If so, only the position needs to match */ + if (direction_ == IDLE) + { + for (it = stops_.begin (); it != stops_.end (); it++) + if (it->getPosition() == position_) + return true; + } + /* No match */ return false; } @@ -68,6 +78,9 @@ void Elevator::stop_at (Stop &stop) { StopList::iterator it; + if (stop.getDirection() == IDLE) + throw bad_direction(); +#if 0 /* If this is an "ALL" Stop, it supercedes all others */ if (stop.getDirection() == ALL) { @@ -75,6 +88,7 @@ void Elevator::stop_at (Stop &stop) stops_.push_back (stop); return; } +#endif /* Check if this stop already exists. If so, just leave */ for (it = stops_.begin(); it != stops_.end(); it++) @@ -87,50 +101,63 @@ 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 - current_position_; + return pos - position_; } -#include -static void debug (const std::string& s) +float Elevator::distance_from (Stop &s) const { - std::cout << s << std::endl; + 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::move () +void Elevator::transition_move_up () { - static int wait = 0; + direction_ = UP; + position_ += ELEVATOR_STEP; - /* 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) - { - debug ("waiting"); - --wait; - return; - } + // TODO: Call into the GUI to update the position + gui_update_position_label (number_, (float)position_, direction_); + std::cout << "Updating the GUI with our position: " << position_ << std::endl; +} - /* close the door if it is open. This is a requirement to move */ - if (door_ != CLOSED) - { - debug ("closing door"); - wait = 10; - door_ = CLOSED; - close_door (); - return; - } +void Elevator::transition_move_down () +{ + direction_ = DOWN; + position_ -= ELEVATOR_STEP; + + // TODO: Call into the GUI to update the position + gui_update_position_label (number_, (float)position_, direction_); + std::cout << "Updating the GUI with our position: " << position_ << std::endl; +} +void Elevator::transition_move_idle () +{ + direction_ = IDLE; + // TODO: Call into the GUI to update the position + gui_update_position_label (number_, (float)position_, direction_); + // 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(current_position_, direction_); + Stop current = Stop(position_, direction_); int stops_above = 0; int stops_below = 0; @@ -143,103 +170,387 @@ void Elevator::move () ++stops_below; } - /* Check if we are currently at a stop */ - if (currently_at_stop ()) - { - std::cout << "At A Stop: " << Stop(current_position_, direction_) << std::endl; - std::cout << "above=" << stops_above << " below=" << stops_below << std::endl; - wait = 10; + std::cout << "Elevator: " << number_ << " stopping in direction=" << direction_ << std::endl; - /* Remove all stops here if we are switching direction */ - if (stops_above == 0 && direction_ == UP) - stops_.remove (Stop(current_position_, ALL)); + /* Always unpress the in-elevator button for this stop, as well + * as clear the stop. This is like letting people off at a floor. */ + gui_unpress_request_button (number_, (int)position_); + stops_.remove (Stop(position_, ALL)); - if (stops_below == 0 && direction_ == DOWN) - stops_.remove (Stop(current_position_, ALL)); - stops_.remove (Stop(current_position_, direction_)); - - /* Open the door */ - door_ = OPEN; - open_door (); - - return; - } - - /* Check if we need to change direction */ - if (stops_above == 0 && stops_below > 0 && direction_ == UP) + /* 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) { - debug ("1: DOWN"); - direction_ = DOWN; + stops_.remove (Stop(position_, UP)); + stops_.remove (Stop(position_, DOWN)); + gui_unpress_call_button ((int)position_, UP); + gui_unpress_call_button ((int)position_, DOWN); } - - if (stops_below == 0 && stops_above > 0 && direction_ == DOWN) + else if (direction_ == DOWN && stops_below == 0) { - debug ("2: UP"); - direction_ = UP; + stops_.remove (Stop(position_, UP)); + stops_.remove (Stop(position_, DOWN)); + gui_unpress_call_button ((int)position_, UP); + gui_unpress_call_button ((int)position_, DOWN); } - - if (stops_above == 0 && stops_below == 0 && direction_ != IDLE) + else if (direction_ == IDLE) { - debug ("3: IDLE"); - direction_ = IDLE; + stops_.remove (Stop(position_, UP)); + stops_.remove (Stop(position_, DOWN)); + gui_unpress_call_button ((int)position_, UP); + gui_unpress_call_button ((int)position_, DOWN); } - - if (direction_ == IDLE && stops_above > 0) + else { - debug ("4: UP"); - direction_ = UP; + stops_.remove (Stop(position_, direction_)); + gui_unpress_call_button ((int)position_, direction_); } - if (direction_ == IDLE && stops_below > 0) + // TODO: Call into the GUI to open the door + gui_open_door (number_, (int)position_); + std::cout << "Opening Door" << std::endl; +} + +void Elevator::transition_close_door () +{ + // TODO: Call into the GUI to close the door + gui_close_door (number_, (int)position_); + std::cout << "Closing Door" << std::endl; +} + +void Elevator::transition_begin_wait () +{ + wait_ = 10; +} + +void Elevator::transition_continue_wait () +{ + --wait_; +} + +#include +static void debug (const std::string& s) +{ + std::cout << s << std::endl; +} + +static std::string get_state_name (State s) +{ + std::string sname; + + switch (s) { - debug ("5: DOWN"); - direction_ = DOWN; + 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; } + return sname; +} - /* Move in the correct direction */ - switch (direction_) +static std::string get_event_name (Event e) +{ + std::string ename; + + switch (e) { - case IDLE: + 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 UP: - current_position_ += ELEVATOR_STEP; + case EVT_OPEN_DOOR: + ename = "EVT_OPEN_DOOR"; break; - case DOWN: - current_position_ -= ELEVATOR_STEP; + case EVT_CLOSE_DOOR: + ename = "EVT_CLOSE_DOOR"; break; default: - std::cout << __FILE__ << ":" << __LINE__ << " Unhandled Elevator Position" << std::endl; + ename = "BAD EVENT"; break; } - /* Call the GUI with our updated position */ - update_position (); + return ename; } -bool Elevator::is_idle () const +static void bad_transition (State s, Event e) { - return direction_ == IDLE; + std::cout << "Bad State Transition: " << get_state_name (s) + << " -> " << get_event_name (e) << std::endl; } -void Elevator::update_position () const +Event Elevator::find_next_event () const { - std::cout << "Updating the GUI with our position: " << current_position_ << std::endl; + /* 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; + } + + /* Now figure out which state transition to make */ + switch (state_) + { + case STATE_IDLE: + + if (currently_at_stop ()) + return EVT_OPEN_DOOR; + + if (stops_above > 0) + return EVT_UP; + + if (stops_below > 0) + return EVT_DOWN; + + return EVT_IDLE; + + break; + case STATE_UP: + + if (currently_at_stop ()) + return EVT_OPEN_DOOR; + + return EVT_UP; + + break; + case STATE_DOWN: + + if (currently_at_stop ()) + return EVT_OPEN_DOOR; + + return EVT_DOWN; + + break; + case STATE_WAIT: + + if (wait_ > 0) + return EVT_WAIT; + + return EVT_CLOSE_DOOR; + + break; + case STATE_OPEN_DOOR: + + return EVT_WAIT; + + break; + 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 << "find_next_event(): Bad State" << std::endl; + break; + } } -void Elevator::open_door () const +void Elevator::move () { - std::cout << "Opening Door" << std::endl; + /* Generate Events */ + Event e = find_next_event (); + + std::cout << "State Transition: " << get_state_name (state_) << " with " + << get_event_name (e) << 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; + + 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; + } } -void Elevator::close_door () const +bool Elevator::is_idle () const { - std::cout << "Closing Door" << std::endl; + if (stops_.size() != 0) + return false; + + return direction_ == IDLE; } +int Elevator::getLoad () const +{ + return stops_.size (); +} +bool Elevator::willStopAt (int floor, Direction direction) const +{ + Stop s (floor, direction); + StopList::const_iterator it; + for (it=stops_.begin(); it != stops_.end(); it++) + if (*it == s) + return true; + return false; +} /* vim: set ts=4 sts=4 sw=4 noexpandtab textwidth=112: */