From 3dd660ffad729fbd6e75e6401f5c7f27b9013faf Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 20 Feb 2015 18:08:20 +0200 Subject: [PATCH] Allow direction to be specified for routing waypoints --- data/timetablepanel.ui | 7 ++++ source/engineer/timetablepanel.cpp | 14 ++++++- source/engineer/timetablepanel.h | 1 + source/libr2c2/timetable.cpp | 21 ++++++---- source/libr2c2/timetable.h | 3 +- source/libr2c2/trainroutemetric.cpp | 17 +++++--- source/libr2c2/trainroutemetric.h | 4 +- source/libr2c2/trainrouteplanner.cpp | 31 +++++++------- source/libr2c2/trainrouteplanner.h | 2 +- source/libr2c2/trainrouter.cpp | 61 +++++++++++++++++++--------- source/libr2c2/trainrouter.h | 18 +++++--- 11 files changed, 119 insertions(+), 60 deletions(-) diff --git a/data/timetablepanel.ui b/data/timetablepanel.ui index 5d9b169..d091d92 100644 --- a/data/timetablepanel.ui +++ b/data/timetablepanel.ui @@ -31,6 +31,13 @@ column { text "No selection"; }; + + dropdown "drp_direction" + { + item "Any"; + item "Up"; + item "Down"; + }; }; row diff --git a/source/engineer/timetablepanel.cpp b/source/engineer/timetablepanel.cpp index 4232f2c..5932176 100644 --- a/source/engineer/timetablepanel.cpp +++ b/source/engineer/timetablepanel.cpp @@ -50,6 +50,7 @@ TimetablePanel::TimetablePanel(Engineer &e, R2C2::Train &t): drp_type = dynamic_cast(get_item(widgets, "drp_type")); lbl_target = dynamic_cast(get_item(widgets, "lbl_target")); ent_time = dynamic_cast(get_item(widgets, "ent_time")); + drp_direction = dynamic_cast(get_item(widgets, "drp_direction")); dynamic_cast(get_item(widgets, "btn_pick"))->signal_clicked.connect(sigc::mem_fun(this, &TimetablePanel::pick_clicked)); dynamic_cast(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(drp_type->get_selected_index()+1); row.target = target; + row.direction = static_cast(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); diff --git a/source/engineer/timetablepanel.h b/source/engineer/timetablepanel.h index 930a0a2..e9d0a8c 100644 --- a/source/engineer/timetablepanel.h +++ b/source/engineer/timetablepanel.h @@ -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 rows; bool target_pick; diff --git a/source/libr2c2/timetable.cpp b/source/libr2c2/timetable.cpp index 0d68a7b..b94cbf0 100644 --- a/source/libr2c2/timetable.cpp +++ b/source/libr2c2/timetable.cpp @@ -176,20 +176,19 @@ void Timetable::update_route() current_row = depart; for(list::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(dttype==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::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 &st) const @@ -241,6 +241,8 @@ void Timetable::Row::save(list &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); diff --git a/source/libr2c2/timetable.h b/source/libr2c2/timetable.h index 9ec804e..17a418e 100644 --- a/source/libr2c2/timetable.h +++ b/source/libr2c2/timetable.h @@ -2,12 +2,12 @@ #define LIBR2C2_TIMETABLE_H_ #include +#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(); diff --git a/source/libr2c2/trainroutemetric.cpp b/source/libr2c2/trainroutemetric.cpp index a2cffbc..7e4d485 100644 --- a/source/libr2c2/trainroutemetric.cpp +++ b/source/libr2c2/trainroutemetric.cpp @@ -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; jget_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; jget_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 queue; diff --git a/source/libr2c2/trainroutemetric.h b/source/libr2c2/trainroutemetric.h index c63f25e..156fe88 100644 --- a/source/libr2c2/trainroutemetric.h +++ b/source/libr2c2/trainroutemetric.h @@ -3,12 +3,12 @@ #include #include +#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; diff --git a/source/libr2c2/trainrouteplanner.cpp b/source/libr2c2/trainrouteplanner.cpp index 90d7691..75d746b 100644 --- a/source/libr2c2/trainrouteplanner.cpp +++ b/source/libr2c2/trainrouteplanner.cpp @@ -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()), - 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; iget_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+1waypoints.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+1waypoints.size()) + ++waypoint; + else + { + state = ARRIVED; + return true; + } } - } if(info->first_noncritical->has_track(*track)) critical = false; diff --git a/source/libr2c2/trainrouteplanner.h b/source/libr2c2/trainrouteplanner.h index c7572c0..e3d3770 100644 --- a/source/libr2c2/trainrouteplanner.h +++ b/source/libr2c2/trainrouteplanner.h @@ -34,7 +34,7 @@ private: float speed; Block *first_noncritical; TrainRouter *router; - std::vector waypoints; + std::vector waypoints; std::vector metrics; bool has_duration; std::list routes; diff --git a/source/libr2c2/trainrouter.cpp b/source/libr2c2/trainrouter.cpp index 122b91a..7d52b84 100644 --- a/source/libr2c2/trainrouter.cpp +++ b/source/libr2c2/trainrouter.cpp @@ -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()) + if(msg.value.check_type()) + { + Waypoint wp = msg.value.value(); + add_waypoint(*wp.chain, wp.direction); + } + else if(msg.value.check_type()) add_waypoint(*msg.value.value()); else add_waypoint(*msg.value.value()); @@ -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_iterator i=waypoints.begin(); i!=waypoints.end(); ++i) - metrics.push_back(new TrainRouteMetric(**i)); + for(vector::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), diff --git a/source/libr2c2/trainrouter.h b/source/libr2c2/trainrouter.h index 9fab289..835ec48 100644 --- a/source/libr2c2/trainrouter.h +++ b/source/libr2c2/trainrouter.h @@ -3,6 +3,7 @@ #include #include +#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 waypoints; + std::vector waypoints; bool waypoints_changed; std::vector 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; } -- 2.45.2