This was a major rewrite, but it seems to be working out more sanely now.
Signed-off-by: Ira W. Snyder <devel@irasnyder.com>
#ifndef DIRECTION_HPP
#define DIRECTION_HPP
-enum direction { IDLE, UP, DOWN, ALL };
+typedef enum { IDLE, UP, DOWN, ALL } Direction;
#endif /* DIRECTION_HPP */
#include "elevator.hpp"
Elevator::Elevator ()
- : _stops()
- , _pos()
- , _direction(IDLE)
- , _door_status(CLOSED)
+ : door_(CLOSED)
+ , direction_(IDLE)
+ , current_position_()
+ , stops_()
+ , ELEVATOR_STEP(0.1)
{
// Intentionally Left Empty
}
-void Elevator::stop_at (int floor, enum direction _direction)
+bool Elevator::currently_at_stop () const
{
- std::cout << "Adding Stop: Floor=" << floor << " Dir=" << _direction << std::endl;
+ StopList::const_iterator it;
+ Stop current(current_position_, direction_);
- _stops.push_back (Stop(floor, _direction));
+ for (it = stops_.begin (); it != stops_.end (); it++)
+ if (*it == current)
+ return true;
+
+ return false;
+}
+
+void Elevator::stop_at (Stop &stop)
+{
+ StopList::iterator it;
+
+ /* If this is an "ALL" Stop, it supercedes all others */
+ if (stop.getDirection() == ALL)
+ {
+ stops_.remove (stop);
+ stops_.push_back (stop);
+ return;
+ }
+
+ /* Check if this stop already exists. If so, just leave */
+ for (it = stops_.begin(); it != stops_.end(); it++)
+ if (*it == stop)
+ return;
+
+ /* The stop did not already exist, so add it */
+ stops_.push_back (stop);
+}
+
+float Elevator::distance_from (Position &pos) const
+{
+ if (current_position_ > pos)
+ return current_position_ - pos;
+
+ return pos - current_position_;
}
-/*
- * Will check if direction needs to be changed, then change it.
- *
- * Will move this Elevator one step in the correct direction.
- *
- * The correct direction is defined based on the current direction:
- *
- * IDLE: Move in the direction that has the most stops
- * - Ex: if there are 10 stops above us, and two below, move DOWN
- *
- * UP: Move upwards
- *
- * DOWN: Move downwards
- */
void Elevator::move ()
{
- /* Check if we are at a stop. If we are:
- * 1) Open the doors
- * 2) Clear the call button
+ static int wait = 0;
+
+ /* 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 (currently_at_stop ())
+ if (wait > 0)
{
- std::cout << "At a stop, right now" << std::endl;
+ --wait;
return;
}
- /* Check if we have any more stops to attend to. If we do not, go IDLE */
- if (_stops.size() == 0)
+ /* close the door if it is open. This is a requirement to move */
+ if (door_ != CLOSED)
{
- _direction = IDLE;
+ wait = 10;
+ close_door ();
return;
}
- /* Find the best direction to move in, and set our direction to that */
- if (_direction == IDLE)
- _direction = find_best_direction ();
+ if (currently_at_stop ())
+ {
+ wait = 10; // delay around for 10 steps
+ stops_.remove (Stop(current_position_, direction_));
+ open_door (); // call into the GUI to open the door
+ return;
+ }
+
+ /* Calculate the number of Stops above and below our
+ * current position */
+ StopList::const_iterator it;
+ Stop current = Stop(current_position_, direction_);
+ int stops_above = 0;
+ int stops_below = 0;
+
+ for (it = stops_.begin(); it != stops_.begin(); it++)
+ {
+ if (current < *it)
+ ++stops_above;
+
+ if (current > *it)
+ ++stops_below;
+ }
+
+ /* Check if we need to change direction */
+ if (direction_ == UP && stops_above == 0 && stops_below > 0)
+ direction_ = DOWN;
+
+ if (direction_ == DOWN && stops_below == 0 && stops_above > 0)
+ direction_ = UP;
+
+ if (stops_above == 0 && stops_below == 0)
+ direction_ = IDLE;
+
- /* Move */
- switch (_direction)
+ /* Move in the correct direction */
+ switch (direction_)
{
+ case IDLE:
+ break;
case UP:
- _pos += elevator_step;
+ current_position_ += ELEVATOR_STEP;
break;
case DOWN:
- _pos -= elevator_step;
+ current_position_ -= ELEVATOR_STEP;
break;
default:
- throw bad_direction ();
+ std::cout << __FILE__ << ":" << __LINE__ << " Unhandled Elevator Position" << std::endl;
break;
}
- std::cout << "at position: " << _pos << std::endl;
+ /* Call the GUI with our updated position */
+ update_position ();
}
-enum direction Elevator::find_best_direction ()
+bool Elevator::is_idle () const
{
- /* Make sure that the current direction is IDLE */
- if (_direction != IDLE)
- throw bad_direction();
-
- std::vector<Stop>::const_iterator it;
- int above, below;
-
- /* Find out how many are above and below our current position */
- for (above=0, below=0, it = _stops.begin(); it != _stops.end(); it++)
- {
- if (_pos < (*it))
- above++;
-
- if (_pos > (*it))
- below++;
- }
-
- /* If we have nothing, then stay IDLE */
- if (above == 0 && below == 0)
- return IDLE;
-
- /* If they are the same, always go up first.
- *
- * This comes from the design meeting on 2007-10-03 */
- if (above == below)
- return UP;
-
- /* Otherwise, go in the direction that has the most stops */
- return above > below ? UP : DOWN;
+ return direction_ == IDLE;
}
-bool Elevator::currently_at_stop ()
+void Elevator::update_position () const
{
- std::vector<Stop>::iterator it;
- Stop current (_pos, _direction);
+ std::cout << "Updating the GUI with our position" << std::endl;
+}
- for (it = _stops.begin (); it != _stops.end (); it++)
- {
- std::cout << "cas(): current=" << current << " it=" << *it << std::endl;
- if (*it == current)
- return true;
- }
+void Elevator::open_door () const
+{
+ std::cout << "Opening Door" << std::endl;
+}
- return false;
+void Elevator::close_door () const
+{
+ std::cout << "Closing Door" << std::endl;
}
#define ELEVATOR_HPP
#include <iostream>
-#include <vector>
-#include "position.hpp"
+#include <list>
#include "direction.hpp"
+#include "position.hpp"
#include "stop.hpp"
-
-enum door_status { CLOSED, OPEN };
-const float elevator_step = 0.1;
-
-class bad_direction { };
+typedef enum { CLOSED, OPEN } DoorStatus;
+typedef std::list<Stop> StopList;
class Elevator
{
public:
- /*
- * PURPOSE: Construct a new Elevator object
- *
- * REQUIRE: Nothing
- *
- * PROMISE: A new Elevator will be constructed
- */
Elevator ();
- /*
- * PURPOSE: Tell the elevator to stop at the given floor,
- * PURPOSE: going in the given direction.
- *
- * REQUIRE: floor is a valid floor
- * REQUIRE: direction is either UP or DOWN
- *
- * PROMISE: The elevator will stop at the floor when it gets there
- */
- void stop_at (int floor, enum direction _direction);
-
- /*
- * PURPOSE: The elevator will move 1/10th of a floor in the current
- * PURPOSE: direction.
- *
- * REQUIRE: Nothing
- *
- * PROMISE: The elevator will move if it has floors to stop at, otherwise
- * PROMISE: it will sit idle at its current place.
- */
+ void stop_at (Stop &stop);
+ float distance_from (Position& pos) const;
void move ();
-
- protected:
- /*
- * PURPOSE: Find the direction we should move in
- *
- * REQUIRE: _direction must be IDLE
- *
- * PROMISE: The best direction to move will be returned
- */
- enum direction find_best_direction ();
-
- /*
- * PURPOSE: Figure out if we are currently at a Stop in _stops
- *
- * REQUIRE: Nothing
- *
- * PROMISE: Return true if we are at a Stop in _stops, false otherwise
- */
- bool currently_at_stop ();
+ bool is_idle () const;
private:
- /* Storage for all of the places that we will be stopping */
- std::vector<Stop> _stops;
+ /* Callbacks into the GUI */
+ void open_door () const;
+ void close_door () const;
+ void update_position () const;
- /* Storage for the current elevator position */
- Position _pos;
+ /* Analyze the list of stops */
+ bool currently_at_stop () const;
- /* Stores the current direction */
- enum direction _direction;
-
- /* Stores the current door status */
- enum door_status _door_status;
+ /* Elevator Status Variables */
+ DoorStatus door_;
+ Direction direction_;
+ Position current_position_;
+ StopList stops_;
+ const float ELEVATOR_STEP;
};
+
#endif /* ELEVATOR_HPP */
/* vim: set ts=4 sts=4 sw=4 noexpandtab textwidth=112: */
#include "position.hpp"
Position::Position ()
- : _major(0)
- , _minor(0)
+ : major_(0)
+ , minor_(0)
{
// Intentionally Empty
}
Position::Position (int initial_position)
- : _major(initial_position)
- , _minor(0)
+ : major_(initial_position)
+ , minor_(0)
{
// Intentionally Empty
}
-bool Position::operator== (const Position& rhs)
+bool Position::operator== (const Position& rhs) const
{
- return (_major == rhs._major) && (_minor == rhs._minor);
+ return (major_ == rhs.major_) && (minor_ == rhs.minor_);
}
-
-bool Position::operator== (const int rhs)
+bool Position::operator!= (const Position& rhs) const
{
- return (_major == rhs) && (_minor == 0);
+ return ! (*this == rhs);
}
Position& Position::operator+= (const float rhs)
int major = (int)rhs;
int minor = (int)((rhs - major) * 10);
- _major += major;
- _minor += minor;
+ major_ += major;
+ minor_ += minor;
/* Check for overflow */
- if (_minor >= 10)
+ if (minor_ >= 10)
{
- _major += 1;
- _minor -= 10;
+ major_ += 1;
+ minor_ -= 10;
}
return *this;
return *this;
}
-bool Position::operator< (const Position& rhs)
+bool Position::operator< (const Position& rhs) const
{
- if (_major < rhs._major)
+ if (major_ < rhs.major_)
return true;
- if (_major == rhs._major)
- if (_minor < rhs._minor)
+ if (major_ == rhs.major_)
+ if (minor_ < rhs.minor_)
return true;
return false;
}
-bool Position::operator> (const Position& rhs)
+bool Position::operator> (const Position& rhs) const
{
- if (_major > rhs._major)
+ if (major_ > rhs.major_)
return true;
- if (_major == rhs._major)
- if (_minor > rhs._minor)
+ if (major_ == rhs.major_)
+ if (minor_ > rhs.minor_)
return true;
return false;
}
-std::ostream& operator<< (std::ostream& os, Position& rhs)
+Position Position::operator- (const Position& rhs) const
{
- os << "Position: " << rhs._major << "." << rhs._minor;
- return os;
+ Position temp;
+
+ int major = major_ - rhs.major_;
+ int minor = minor_ - rhs.minor_;
+
+ /* Check for underflow */
+ if (minor < 0)
+ {
+ minor += 10;
+ major -= 1;
+ }
+
+ temp.major_ = major;
+ temp.minor_ = minor;
+
+ return temp;
}
+Position::operator float() const
+{
+ float temp;
+
+ temp = major_;
+ temp += minor_ / 10.0;
+
+ return temp;
+}
+
+std::ostream& operator<< (std::ostream& os, const Position& rhs)
+{
+ os << "Position(" << rhs.major_ << "." << rhs.minor_ << ")";
+ return os;
+}
/* vim: set ts=4 sts=4 sw=4 noexpandtab textwidth=112: */
class Position
{
+ friend std::ostream& operator<< (std::ostream& os, const Position& rhs);
+
public:
- /*
- * PURPOSE: Construct a new Position object
- *
- * REQUIRE: Nothing
- *
- * PROMISE: A new Position object will be created, that
- * PROMISE: starts at position 0.
- */
Position ();
-
- /*
- * PURPOSE: Construct a new Position object
- *
- * REQUIRE: Nothing
- *
- * PROMISE: A new Position object will be created, and will
- * PROMISE: start at position initial_position
- */
Position (int initial_position);
- /*
- * PURPOSE: Compare two position objects
- *
- * REQUIRE: rhs is a valid Position object
- *
- * PROMISE: True if rhs is at the same position, false otherwise
- */
- bool operator== (const Position& rhs);
-
- /*
- * PURPOSE: Compare a Position and a float
- *
- * REQUIRE: Nothing
- *
- * PROMISE: True if rhs is within 0.05 of this Position
- */
- bool operator== (const int rhs);
-
- /*
- * PURPOSE: Add to this Position
- *
- * REQUIRE: Nothing
- *
- * PROMISE: This Position will have the rhs added to it
- */
Position& operator+= (const float rhs);
-
- /*
- * PURPOSE: Subtract from this Position
- *
- * REQUIRE: Nothing
- *
- * PROMISE: This Position will have the rhs added to it
- */
Position& operator-= (const float rhs);
- bool operator< (const Position& rhs);
- bool operator> (const Position& rhs);
-
- friend std::ostream& operator<< (std::ostream& os, Position& rhs);
+ bool operator== (const Position& rhs) const;
+ bool operator!= (const Position& rhs) const;
+ bool operator< (const Position& rhs) const;
+ bool operator> (const Position& rhs) const;
+ Position operator- (const Position& rhs) const;
+ operator float() const;
- protected:
- int _major;
- int _minor;
private:
+ int major_;
+ int minor_;
};
#endif /* POSITION_HPP */
#include "stop.hpp"
-Stop::Stop (int floor, enum direction mydirection)
- : Position(floor)
- , _direction(mydirection)
+Stop::Stop (const Position& position, const Direction& direction)
+ : position_(position)
+ , direction_(direction)
{
// Intentionally Left Empty
}
-Stop::Stop (Position pos, enum direction mydirection)
- : Position (pos)
- , _direction (mydirection)
+bool Stop::operator== (const Stop& rhs) const
{
- // Intentionally Left Empty
+ if (rhs.position_ != position_)
+ return false;
+
+ if (direction_ == ALL || rhs.direction_ == ALL)
+ return true;
+
+ return (rhs.direction_ == direction_);
+}
+
+bool Stop::operator< (const Stop& rhs) const
+{
+ /* If we do not use the direction to help differentiate, then it is
+ * possible that an object can be neither less, greater, or equal */
+ return ((position_ < rhs.position_) || (direction_ < rhs.direction_));
}
-bool Stop::operator== (Stop& rhs)
+bool Stop::operator> (const Stop& rhs) const
{
- return (Position::operator==(rhs)) && (_direction == rhs._direction);
+ return (position_ > rhs.position_);
}
-std::ostream& operator<< (std::ostream& os, Stop& rhs)
+const Direction Stop::getDirection () const
{
- os << "Stop: " << "help me" << " dir=" << rhs._direction;
+ return direction_;
+}
+
+std::ostream& operator<< (std::ostream& os, const Stop& rhs)
+{
+ os << "Stop(" << rhs.position_ << ", " << rhs.direction_ << ")";
return os;
}
+
/* vim: set ts=4 sts=4 sw=4 noexpandtab textwidth=112: */
#include "position.hpp"
#include "direction.hpp"
-class Stop : public Position
+class Stop
{
+ friend std::ostream& operator<< (std::ostream &os, const Stop& rhs);
+
public:
- /* PURPOSE: Construct a new Stop object, and set the floor and direction
- *
- * REQUIRE: Nothing
- *
- * PROMISE: A new Stop object will be created
- */
- Stop (int floor, enum direction mydirection);
-
-
- Stop (Position pos, enum direction mydirection);
-
- /*
- * PURPOSE: Check if this and another Stop object is equivalent
- *
- * REQUIRE: rhs is a valid Stop object
- *
- * PROMISE: Return true if this and rhs are equivalent, false otherwise
- */
- bool operator== (Stop& rhs);
- friend std::ostream& operator<< (std::ostream& os, Stop& rhs);
+ Stop (const Position& position, const Direction& direction);
- private:
+ bool operator== (const Stop& rhs) const;
+ bool operator< (const Stop& rhs) const;
+ bool operator> (const Stop& rhs) const;
- /* Storage for the direction */
- enum direction _direction;
+ const Direction getDirection () const;
+
+ private:
+ Position position_;
+ Direction direction_;
};
#endif /* STOP_HPP */
#include <iostream>
+#include <list>
using namespace std;
+#include "stop.hpp"
+#include "position.hpp"
#include "elevator.hpp"
+
int main (int argc, char *argv[])
{
Elevator e;
- e.stop_at (1, DOWN);
- e.stop_at (2, DOWN);
- e.move ();
+ Stop s(1, UP);
+ e.stop_at (s);
e.move ();
e.move ();
e.move ();
return 0;
}
+/* vim: set ts=4 sts=4 sw=4 noet tw=112: */