X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibr2c2%2Ftimetable.cpp;h=b94cbf08fcfc37ad9d3485aeaf78f1ffe76ec615;hb=3dd660ffad729fbd6e75e6401f5c7f27b9013faf;hp=f0e49ffb85eac5c0aded58018c5a4c6a289c3490;hpb=9ad36841021cdd5c7f14d52e946d8ecdb602cf78;p=r2c2.git diff --git a/source/libr2c2/timetable.cpp b/source/libr2c2/timetable.cpp index f0e49ff..b94cbf0 100644 --- a/source/libr2c2/timetable.cpp +++ b/source/libr2c2/timetable.cpp @@ -1,8 +1,11 @@ +#include #include +#include "aicontrol.h" #include "clock.h" #include "layout.h" #include "timetable.h" #include "train.h" +#include "trainrouter.h" #include "zone.h" using namespace std; @@ -13,8 +16,14 @@ namespace R2C2 { Timetable::Timetable(Train &t): TrainAI(t), current_row(rows.end()), - update_pending(false) + update_pending(false), + sync_to_clock(true) { + if(!train.get_ai_of_type()) + new AIControl(train); + if(!train.get_ai_of_type()) + new TrainRouter(train); + train.signal_ai_event.connect(sigc::mem_fun(this, &Timetable::event)); } @@ -107,7 +116,7 @@ void Timetable::save(list &st) const } } -void Timetable::check_update(list::const_iterator i) +void Timetable::check_update(const list::const_iterator &i) { for(list::const_iterator j=current_row; (j!=rows.end() && j!=i); ++j) if(j->type==ARRIVE) @@ -115,28 +124,47 @@ void Timetable::check_update(list::const_iterator i) update_pending = true; } +list::iterator Timetable::find_trip(const list::iterator &begin, list::iterator *arrive) +{ + list::iterator i = find_if(begin, rows.end(), RowTypeMatch(DEPART)); + if(i==rows.end()) + return i; + + list::iterator j = find_if(i, rows.end(), RowTypeMatch(ARRIVE)); + if(j==rows.end()) + return j; + + if(arrive) + *arrive = j; + return i; +} + void Timetable::update_route() { update_pending = false; if(rows.empty()) return; - list::iterator depart = rows.end(); - for(list::iterator i=current_row;; ) - { - if(i==rows.end()) - { - i = rows.begin(); - depart = rows.end(); - } + const Clock &clock = train.get_layout().get_clock(); - if(i->type==DEPART) - depart = i; - else if(depart!=rows.end() && i->type==ARRIVE) - break; + if(sync_to_clock) + { + sync_to_clock = false; + current_row = rows.begin(); + for(list::iterator i=rows.begin(); i!=rows.end(); ++i) + if(i->type==DEPART && i->time>=clock.get_current_time()) + { + current_row = i; + break; + } + } - ++i; - if(i==current_row) + list::iterator arrive; + list::iterator depart = find_trip(current_row, &arrive); + if(depart==rows.end()) + { + depart = find_trip(rows.begin(), &arrive); + if(depart==rows.end()) { current_row = rows.end(); return; @@ -148,21 +176,31 @@ 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("set-destination-zone", i->zone)); - break; - } - else if(i->type==DEPART) + if(i->type==DEPART) { - const Clock &clock = train.get_layout().get_clock(); Time::TimeDelta dt = i->time-clock.get_current_time(); while(dttarget, i->direction))); + if(i->type==ARRIVE) + break; } } + + list::iterator next_depart = find_trip(arrive, 0); + if(next_depart==rows.end()) + next_depart = find_trip(rows.begin(), 0); + if(next_depart!=rows.end()) + { + Time::TimeDelta dt = next_depart->time-depart->time; + while(dt<=Time::zero) + dt += Time::day; + train.ai_message(Message("set-trip-duration", dt/clock.get_rate())); + } } void Timetable::event(TrainAI &, const Message &msg) @@ -170,26 +208,41 @@ void Timetable::event(TrainAI &, const Message &msg) if(msg.type=="arrived") { if(current_row->type==ARRIVE) + record_time(); + update_pending = true; + } + else if(msg.type=="waypoint-reached") + { + const TrackChain *wp = msg.value.value(); + if(current_row->type==THROUGH && current_row->target==wp) { - current_row->time = train.get_layout().get_clock().get_current_time(); - unsigned i = distance(rows.begin(), current_row); - signal_row_modified.emit(i, *current_row); + record_time(); + ++current_row; } - update_pending = true; } } +void Timetable::record_time() +{ + current_row->time = train.get_layout().get_clock().get_current_time(); + unsigned i = distance(rows.begin(), current_row); + signal_row_modified.emit(i, *current_row); +} + Timetable::Row::Row(): type(ARRIVE), - zone(0) + target(0), + direction(TrackChain::UNSPECIFIED) { } 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((DataFile::Statement("zone"), zone->get_group(), zone->get_number())); + st.push_back(target->save_reference()); + if(direction) + st.push_back((DataFile::Statement("direction"), direction)); } @@ -213,14 +266,16 @@ Timetable::Row::Loader::Loader(Row &r, Layout &l): DataFile::ObjectLoader(r), layout(l) { - add("zone", &Loader::zone); + add("block", &Loader::block); + add("direction", &Row::direction); add("time", &Loader::time); add("type", &Row::type); + add("zone", &Loader::zone); } -void Timetable::Row::Loader::zone(const string &name, unsigned number) +void Timetable::Row::Loader::block(unsigned id) { - obj.zone = &layout.get_zone(name, number); + obj.target = &layout.get_block(id); } void Timetable::Row::Loader::time(Time::RawTime t) @@ -228,6 +283,11 @@ void Timetable::Row::Loader::time(Time::RawTime t) obj.time = Time::TimeDelta(t); } +void Timetable::Row::Loader::zone(const string &name, unsigned number) +{ + obj.target = &layout.get_zone(name, number); +} + void operator<<(LexicalConverter &conv, Timetable::RowType rt) { @@ -235,6 +295,7 @@ void operator<<(LexicalConverter &conv, Timetable::RowType rt) { case Timetable::ARRIVE: conv.result("ARRIVE"); return; case Timetable::DEPART: conv.result("DEPART"); return; + case Timetable::THROUGH: conv.result("THROUGH"); return; default: throw lexical_error(format("conversion of RowType(%d) to string", rt)); } } @@ -245,6 +306,8 @@ void operator>>(const LexicalConverter &conv, Timetable::RowType &rt) rt = Timetable::ARRIVE; else if(conv.get()=="DEPART") rt = Timetable::DEPART; + else if(conv.get()=="THROUGH") + rt = Timetable::THROUGH; else throw lexical_error(format("conversion of '%s' to RowType", conv.get())); }