]> git.tdb.fi Git - r2c2.git/commitdiff
Allow direction to be specified for routing waypoints
authorMikko Rasa <tdb@tdb.fi>
Fri, 20 Feb 2015 16:08:20 +0000 (18:08 +0200)
committerMikko Rasa <tdb@tdb.fi>
Fri, 20 Feb 2015 16:10:21 +0000 (18:10 +0200)
data/timetablepanel.ui
source/engineer/timetablepanel.cpp
source/engineer/timetablepanel.h
source/libr2c2/timetable.cpp
source/libr2c2/timetable.h
source/libr2c2/trainroutemetric.cpp
source/libr2c2/trainroutemetric.h
source/libr2c2/trainrouteplanner.cpp
source/libr2c2/trainrouteplanner.h
source/libr2c2/trainrouter.cpp
source/libr2c2/trainrouter.h

index 5d9b16939aa8a9d74be20b7122648116adecb027..d091d925b0739155489b03938439602c89a21682 100644 (file)
@@ -31,6 +31,13 @@ column
                {
                        text "No selection";
                };
+
+               dropdown "drp_direction"
+               {
+                       item "Any";
+                       item "Up";
+                       item "Down";
+               };
        };
 
        row
index 4232f2cb16db143397b97b8736ef7c057adf6d58..5932176b0536e55518fc9753e06fde28abd2f4a5 100644 (file)
@@ -50,6 +50,7 @@ TimetablePanel::TimetablePanel(Engineer &e, R2C2::Train &t):
        drp_type = dynamic_cast<GLtk::Dropdown *>(get_item(widgets, "drp_type"));
        lbl_target = dynamic_cast<GLtk::Label *>(get_item(widgets, "lbl_target"));
        ent_time = dynamic_cast<GLtk::Entry *>(get_item(widgets, "ent_time"));
+       drp_direction = dynamic_cast<GLtk::Dropdown *>(get_item(widgets, "drp_direction"));
 
        dynamic_cast<GLtk::Button *>(get_item(widgets, "btn_pick"))->signal_clicked.connect(sigc::mem_fun(this, &TimetablePanel::pick_clicked));
        dynamic_cast<GLtk::Button *>(get_item(widgets, "btn_insert"))->signal_clicked.connect(sigc::mem_fun(this, &TimetablePanel::insert_clicked));
@@ -90,6 +91,7 @@ Timetable::Row TimetablePanel::create_row()
 
        row.type = static_cast<Timetable::RowType>(drp_type->get_selected_index()+1);
        row.target = target;
+       row.direction = static_cast<TrackChain::Direction>(drp_direction->get_selected_index());
 
        Regex r_time("([01]?[0-9]|2[0-3]):([0-5][0-9])(:([0-5][0-9]))?");
        RegMatch m = r_time.match(ent_time->get_text());
@@ -113,6 +115,7 @@ void TimetablePanel::row_selected(unsigned i)
                target = row->target;
                if(target)
                        lbl_target->set_text(target->get_name());
+               drp_direction->set_selected_index(row->direction);
                ent_time->set_text(format_time(row->time));
        }
 }
@@ -233,7 +236,16 @@ TimetableRowItem::TimetableRowItem(ValueType row)
                        case Timetable::DEPART: type = "Depart from "; break;
                        case Timetable::THROUGH: type = "Go through "; break;
                        }
-                       add(*new GLtk::Label(type+row->target->get_name()));
+
+                       string dir;
+                       switch(row->direction)
+                       {
+                       case TrackChain::UP: dir = " up"; break;
+                       case TrackChain::DOWN: dir = " down"; break;
+                       default:;
+                       }
+
+                       add(*new GLtk::Label(type+row->target->get_name()+dir));
                }
                else
                        add(*new GLtk::Label);
index 930a0a2cd0e026c36e427826cd47c02c90457ebf..e9d0a8c8771c4e12394846dab9930847ac64308d 100644 (file)
@@ -23,6 +23,7 @@ private:
        R2C2::TrackChain *target;
        Msp::GLtk::Label *lbl_target;
        Msp::GLtk::Entry *ent_time;
+       Msp::GLtk::Dropdown *drp_direction;
        Msp::GLtk::BasicListData<const R2C2::Timetable::Row *> rows;
 
        bool target_pick;
index 0d68a7be8aea5c88f515a60192e4aac62d6267ce..b94cbf08fcfc37ad9d3485aeaf78f1ffe76ec615 100644 (file)
@@ -176,20 +176,19 @@ void Timetable::update_route()
        current_row = depart;
        for(list<Row>::const_iterator i=depart; i!=rows.end(); ++i)
        {
-               if(i->type==ARRIVE)
-               {
-                       train.ai_message(Message("add-waypoint", i->target));
-                       break;
-               }
-               else if(i->type==DEPART)
+               if(i->type==DEPART)
                {
                        Time::TimeDelta dt = i->time-clock.get_current_time();
                        while(dt<Time::zero)
                                dt += Time::day;
                        train.ai_message(Message("set-departure-delay", dt/clock.get_rate()));
                }
-               else if(i->type==THROUGH)
-                       train.ai_message(Message("add-waypoint", i->target));
+               else
+               {
+                       train.ai_message(Message("add-waypoint", TrainRouter::Waypoint(*i->target, i->direction)));
+                       if(i->type==ARRIVE)
+                               break;
+               }
        }
 
        list<Row>::iterator next_depart = find_trip(arrive, 0);
@@ -233,7 +232,8 @@ void Timetable::record_time()
 
 Timetable::Row::Row():
        type(ARRIVE),
-       target(0)
+       target(0),
+       direction(TrackChain::UNSPECIFIED)
 { }
 
 void Timetable::Row::save(list<DataFile::Statement> &st) const
@@ -241,6 +241,8 @@ void Timetable::Row::save(list<DataFile::Statement> &st) const
        st.push_back((DataFile::Statement("type"), type));
        st.push_back((DataFile::Statement("time"), time.raw()));
        st.push_back(target->save_reference());
+       if(direction)
+               st.push_back((DataFile::Statement("direction"), direction));
 }
 
 
@@ -265,6 +267,7 @@ Timetable::Row::Loader::Loader(Row &r, Layout &l):
        layout(l)
 {
        add("block", &Loader::block);
+       add("direction", &Row::direction);
        add("time", &Loader::time);
        add("type", &Row::type);
        add("zone", &Loader::zone);
index 9ec804e0692d02834c72fa2de50bdb4fc6f0c795..17a418ebab2b7c4da358a7a0e5fd78623b67936a 100644 (file)
@@ -2,12 +2,12 @@
 #define LIBR2C2_TIMETABLE_H_
 
 #include <msp/datafile/objectloader.h>
+#include "trackchain.h"
 #include "trainai.h"
 
 namespace R2C2 {
 
 class Layout;
-class TrackChain;
 
 class Timetable: public TrainAI
 {
@@ -49,6 +49,7 @@ public:
 
                RowType type;
                TrackChain *target;
+               TrackChain::Direction direction;
                Msp::Time::TimeDelta time;
 
                Row();
index a2cffbc896504d7df252905a449c63fbbe11c91b..7e4d4856fe91a484f794470ce8a2e66a03151b96 100644 (file)
@@ -7,16 +7,21 @@ using namespace std;
 
 namespace R2C2 {
 
-TrainRouteMetric::TrainRouteMetric(const TrackChain &tc)
+TrainRouteMetric::TrainRouteMetric(const TrackChain &tc, TrackChain::Direction dir)
 {
        const TrackChain::TrackSet &ctracks = tc.get_tracks();
        for(TrackChain::TrackSet::const_iterator i=ctracks.begin(); i!=ctracks.end(); ++i)
        {
-               unsigned nls = (*i)->get_n_link_slots();
-               for(unsigned j=0; j<nls; ++j)
-                       if(Track *link = (*i)->get_link(j))
-                               if(!ctracks.count(link))
-                                       goals.push_back(TrackIter(*i, j));
+               if(dir==TrackChain::UNSPECIFIED)
+               {
+                       unsigned nls = (*i)->get_n_link_slots();
+                       for(unsigned j=0; j<nls; ++j)
+                               if(Track *link = (*i)->get_link(j))
+                                       if(!ctracks.count(link))
+                                               goals.push_back(TrackIter(*i, j));
+               }
+               else if(TrackIter iter = tc.iter_for(**i, reverse_dir))
+                       goals.push_back(iter);
        }
 
        list<TrackIter> queue;
index c63f25e77783adea16d1baf950ec2c359f96e7cc..156fe88c1a1b15294ce7f689c109158cb5b9bdb3 100644 (file)
@@ -3,12 +3,12 @@
 
 #include <map>
 #include <vector>
+#include "trackchain.h"
 
 namespace R2C2 {
 
 class Layout;
 class Track;
-class TrackChain;
 
 // Metrics store iterators facing away from the goal
 class TrainRouteMetric
@@ -39,7 +39,7 @@ private:
 
 public:
        TrainRouteMetric() { }
-       TrainRouteMetric(const TrackChain &);
+       TrainRouteMetric(const TrackChain &, TrackChain::Direction = TrackChain::UNSPECIFIED);
 
        void chain_to(const TrainRouteMetric &);
        float get_distance_from(const Track &, unsigned) const;
index 90d769140725fdc00a708a8c55318f6fb2ea12b2..75d746b3c6dd103cd148ae233f90361a189c2328 100644 (file)
@@ -232,16 +232,16 @@ TrainRoutePlanner::TrainRoutingInfo::TrainRoutingInfo(Train &t):
        speed(train->get_maximum_speed()),
        first_noncritical(train->get_last_critical_block().next().block()),
        router(train->get_ai_of_type<TrainRouter>()),
-       waypoints(router ? router->get_n_waypoints() : 0),
        has_duration(false)
 {
-       if(!waypoints.empty())
+       if(unsigned n_wps = router->get_n_waypoints())
        {
-               metrics.resize(waypoints.size());
-               for(unsigned i=0; i<waypoints.size(); ++i)
+               waypoints.reserve(n_wps),
+               metrics.reserve(n_wps);
+               for(unsigned i=0; i<n_wps; ++i)
                {
-                       waypoints[i] = &router->get_waypoint(i);
-                       metrics[i] = &router->get_metric(i);
+                       waypoints.push_back(router->get_waypoint(i));
+                       metrics.push_back(&router->get_metric(i));
                }
                has_duration = router->get_trip_duration();
        }
@@ -362,17 +362,18 @@ bool TrainRoutePlanner::TrainRoutingState::check_arrival()
 {
        TrackIter next_track = track.next(path);
 
-       const TrackChain *wp_chain = info->waypoints[waypoint];
-       if(wp_chain->has_track(*track) && !wp_chain->has_track(*next_track))
-       {
-               if(waypoint+1<info->waypoints.size())
-                       ++waypoint;
-               else
+       const TrainRouter::Waypoint &wp = info->waypoints[waypoint];
+       if(wp.chain->has_track(*track) && !wp.chain->has_track(*next_track))
+               if(wp.direction==TrackChain::UNSPECIFIED || track==wp.chain->iter_for(*track, wp.direction))
                {
-                       state = ARRIVED;
-                       return true;
+                       if(waypoint+1<info->waypoints.size())
+                               ++waypoint;
+                       else
+                       {
+                               state = ARRIVED;
+                               return true;
+                       }
                }
-       }
 
        if(info->first_noncritical->has_track(*track))
                critical = false;
index c7572c0df41cb48c548fa2c4b0cb40f6afdd4453..e3d3770c52a113bf8f4bcb6c813bb381fc899fba 100644 (file)
@@ -34,7 +34,7 @@ private:
                float speed;
                Block *first_noncritical;
                TrainRouter *router;
-               std::vector<const TrackChain *> waypoints;
+               std::vector<TrainRouter::Waypoint> waypoints;
                std::vector<const TrainRouteMetric *> metrics;
                bool has_duration;
                std::list<Route *> routes;
index 122b91a3bd195837f90455cc3da66289d37ea453..7d52b8437a8bffe8c847c3b05e58142522fecf7f 100644 (file)
@@ -147,26 +147,26 @@ void TrainRouter::route_changed()
 void TrainRouter::set_destination(const TrackChain &d)
 {
        if(waypoints.empty())
-               waypoints.push_back(&d);
+               waypoints.push_back(Waypoint(d));
        else
-               waypoints.back() = &d;
+               waypoints.back() = Waypoint(d);
        waypoints_changed = true;
        metrics_stale = true;
 }
 
-void TrainRouter::add_waypoint(const TrackChain &wp)
+void TrainRouter::add_waypoint(const TrackChain &chain, TrackChain::Direction dir)
 {
-       waypoints.push_back(&wp);
+       waypoints.push_back(Waypoint(chain, dir));
        waypoints_changed = true;
        metrics_stale = true;
 }
 
-const TrackChain &TrainRouter::get_waypoint(unsigned index) const
+const TrainRouter::Waypoint &TrainRouter::get_waypoint(unsigned index) const
 {
        if(index>=waypoints.size())
                throw out_of_range("TrainRouter::is_waypoint");
 
-       return *waypoints[index];
+       return waypoints[index];
 }
 
 const TrainRouteMetric &TrainRouter::get_metric(int index) const
@@ -215,7 +215,12 @@ void TrainRouter::message(const Message &msg)
        }
        else if(msg.type=="add-waypoint")
        {
-               if(msg.value.check_type<TrackChain *>())
+               if(msg.value.check_type<Waypoint>())
+               {
+                       Waypoint wp = msg.value.value<Waypoint>();
+                       add_waypoint(*wp.chain, wp.direction);
+               }
+               else if(msg.value.check_type<TrackChain *>())
                        add_waypoint(*msg.value.value<TrackChain *>());
                else
                        add_waypoint(*msg.value.value<const TrackChain *>());
@@ -262,8 +267,8 @@ void TrainRouter::tick(const Time::TimeDelta &dt)
 
        if(arrival==ADVANCED_TO_END && !train.get_speed())
        {
-               signal_arrived.emit(waypoints.back());
-               signal_event.emit(Message("arrived", waypoints.back()));
+               signal_arrived.emit(waypoints.back().chain);
+               signal_event.emit(Message("arrived", waypoints.back().chain));
                arrival = ARRIVED;
        }
        else if(arrival==ARRIVED && !train.get_block_allocator().is_active())
@@ -369,19 +374,26 @@ void TrainRouter::block_reserved(Block &block, Train *t)
 
 void TrainRouter::train_advanced(Block &block)
 {
-       BlockIter b_iter = train.get_block_allocator().iter_for(block);
-
        if(!waypoints.empty())
        {
                // A waypoint is considered reached when the train has advanced through it.
-               const TrackChain &wp = *waypoints.front();
+               BlockIter b_iter = train.get_block_allocator().iter_for(block);
+               const Waypoint &wp = waypoints.front();
                TrackIter t_iter = b_iter.track_iter();
-               if(wp.has_track(*t_iter))
+               if(wp.chain->has_track(*t_iter))
                {
-                       for(; t_iter; t_iter=t_iter.next())
+                       while(1)
                        {
-                               if(!wp.has_track(*t_iter))
+                               TrackIter next = t_iter.next();
+                               if(!next)
+                                       break;
+
+                               if(!wp.chain->has_track(*next))
                                {
+                                       if(wp.direction!=TrackChain::UNSPECIFIED)
+                                               if(t_iter!=wp.chain->iter_for(*t_iter, wp.direction))
+                                                       break;
+
                                        if(waypoints.size()==1)
                                        {
                                                if(arrival==RESERVED_TO_END)
@@ -389,15 +401,18 @@ void TrainRouter::train_advanced(Block &block)
                                        }
                                        else
                                        {
+                                               const TrackChain *chain = wp.chain;
                                                waypoints.erase(waypoints.begin());
                                                metrics_stale = true;
-                                               signal_waypoint_reached.emit(&wp);
-                                               signal_event.emit(Message("waypoint-reached", &wp));
+                                               signal_waypoint_reached.emit(chain);
+                                               signal_event.emit(Message("waypoint-reached", chain));
                                        }
                                        break;
                                }
-                               else if(!block.has_track(*t_iter))
+                               else if(!block.has_track(*next))
                                        break;
+
+                               t_iter = next;
                        }
                }
        }
@@ -433,8 +448,8 @@ void TrainRouter::create_metrics()
        if(waypoints.empty())
                return;
 
-       for(vector<const TrackChain *>::const_iterator i=waypoints.begin(); i!=waypoints.end(); ++i)
-               metrics.push_back(new TrainRouteMetric(**i));
+       for(vector<Waypoint>::const_iterator i=waypoints.begin(); i!=waypoints.end(); ++i)
+               metrics.push_back(new TrainRouteMetric(*i->chain, i->direction));
 
        for(unsigned i=metrics.size()-1; i-->0; )
                metrics[i]->chain_to(*metrics[i+1]);
@@ -559,6 +574,12 @@ void TrainRouter::apply_plan(Layout &layout, TrainRoutePlanner &planner)
 }
 
 
+TrainRouter::Waypoint::Waypoint(const TrackChain &c, TrackChain::Direction d):
+       chain(&c),
+       direction(d)
+{ }
+
+
 TrainRouter::SequencePoint::SequencePoint(Block &b, unsigned o):
        block(&b),
        preceding_train(0),
index 9fab2892efe15803da1f413277f7a6bd25678122..835ec484737761663da76d30eb97246d0a6178bd 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <list>
 #include <msp/datafile/objectloader.h>
+#include "trackchain.h"
 #include "trainai.h"
 
 namespace R2C2 {
@@ -10,7 +11,6 @@ namespace R2C2 {
 class Block;
 class Layout;
 class Track;
-class TrackChain;
 class TrainRouteMetric;
 class TrainRoutePlanner;
 
@@ -25,6 +25,14 @@ public:
                void route(const std::string &);
        };
 
+       struct Waypoint
+       {
+               const TrackChain *chain;
+               TrackChain::Direction direction;
+
+               Waypoint(const TrackChain &, TrackChain::Direction = TrackChain::UNSPECIFIED);
+       };
+
        struct SequencePoint
        {
                Block *block;
@@ -59,7 +67,7 @@ private:
        RouteList routes;
        RouteList::iterator reserving_route;
        ArrivalState arrival;
-       std::vector<const TrackChain *> waypoints;
+       std::vector<Waypoint> waypoints;
        bool waypoints_changed;
        std::vector<TrainRouteMetric *> metrics;
        bool metrics_stale;
@@ -86,10 +94,10 @@ private:
 
 public:
        void set_destination(const TrackChain &);
-       const TrackChain *get_destination() const { return waypoints.empty() ? 0 : waypoints.back(); }
-       void add_waypoint(const TrackChain &);
+       const TrackChain *get_destination() const { return waypoints.empty() ? 0 : waypoints.back().chain; }
+       void add_waypoint(const TrackChain &, TrackChain::Direction = TrackChain::UNSPECIFIED);
        unsigned get_n_waypoints() const { return waypoints.size(); }
-       const TrackChain &get_waypoint(unsigned) const;
+       const Waypoint &get_waypoint(unsigned) const;
        const TrainRouteMetric &get_metric(int = -1) const;
        void set_departure_delay(const Msp::Time::TimeDelta &);
        const Msp::Time::TimeDelta &get_departure_delay() const { return delay; }