3 This file is part of the MSP Märklin suite
4 Copyright © 2006-2008 Mikkosoft Productions, Mikko Rasa
5 Distributed under the GPL
9 #include <msp/strings/formatter.h>
10 #include <msp/time/units.h>
11 #include <msp/time/utils.h>
13 #include "trafficmanager.h"
23 Train::Train(TrafficManager &tm, Locomotive &l):
31 trfc_mgr.add_train(this);
33 const map<unsigned, Sensor *> &sensors=trfc_mgr.get_control().get_sensors();
34 for(map<unsigned, Sensor *>::const_iterator i=sensors.begin(); i!=sensors.end(); ++i)
35 i->second->signal_state_changed.connect(sigc::bind(sigc::mem_fun(this, &Train::sensor_event), i->second));
38 void Train::set_name(const string &n)
42 signal_name_changed.emit(name);
45 void Train::set_speed(unsigned speed)
47 unsigned old_speed=target_speed;
52 // XXX We might roll onto a new sensor and get confused - should delay freeing blocks a bit
53 for(list<BlockRef>::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
56 try_reserve=Time::TimeStamp();
58 else if(rsv_blocks.empty() && !reserve_more())
61 loco.set_speed(speed);
62 if(!old_speed && target_speed)
63 set_status("Traveling --- kmh");
64 else if(old_speed && !target_speed)
65 set_status("Stopped");
68 void Train::place(Block *block, unsigned entry)
70 for(list<BlockRef>::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end();)
73 i=rsv_blocks.erase(i);
76 for(list<BlockRef>::iterator i=cur_blocks.begin(); i!=cur_blocks.end();)
79 i=cur_blocks.erase(i);
82 if(!block->reserve(this))
84 set_status("Unplaced");
88 cur_blocks.push_back(BlockRef(block, entry));
90 set_status("Stopped");
93 bool Train::free_block(Block *block)
95 for(list<BlockRef>::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
98 while(i!=rsv_blocks.end())
100 i->block->reserve(0);
101 i=rsv_blocks.erase(i);
109 void Train::tick(const Time::TimeStamp &t)
111 if(try_reserve && t>try_reserve)
113 if(reserve_more() || !rsv_blocks.empty())
115 loco.set_speed(target_speed);
116 set_status("Traveling --- kmh");
117 try_reserve=Time::TimeStamp();
120 try_reserve=t+2*Time::sec;
124 void Train::sensor_event(bool state, Sensor *sensor)
126 unsigned addr=sensor->get_address();
130 list<BlockRef>::iterator i;
131 for(i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
132 if(i->block->get_sensor_id() && i->block->get_sensor_id()!=addr)
135 if(i!=rsv_blocks.begin())
137 real_speed=static_cast<int>(round(travel_dist/((Time::now()-last_entry_time)/Time::sec)*87*3.6/5))*5;
138 set_status(format("Traveling %3d kmh", real_speed));
142 for(list<BlockRef>::iterator j=rsv_blocks.begin(); j!=i; ++j)
144 j->block->traverse(j->entry, &block_len);
145 cout<<"Advancing: block "<<j->block<<" (sensor "<<j->block->get_sensor_id()<<") length "<<block_len<<'\n';
146 travel_dist+=block_len;
148 last_entry_time=Time::now();
150 cur_blocks.splice(cur_blocks.end(), rsv_blocks, rsv_blocks.begin(), i);
151 cout<<"Train "<<name<<" advanced, "<<cur_blocks.size()<<" cur_blocks, "<<rsv_blocks.size()<<" rsv_blocks\n";
154 if(target_speed && !reserve_more() && rsv_blocks.empty())
157 try_reserve=Time::now()+2*Time::sec;
158 set_status("Blocked");
163 cout<<"Train "<<name<<" finding blocks to free\n";
164 list<BlockRef>::iterator i;
165 for(i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
167 if(i->block->get_sensor_id()==addr)
170 for(list<BlockRef>::iterator j=cur_blocks.begin(); j!=i; ++j)
171 j->block->reserve(0);
172 cout<<" "<<distance(cur_blocks.begin(), i)<<" blocks freed, ";
173 cur_blocks.erase(cur_blocks.begin(), i);
174 cout<<cur_blocks.size()<<" cur_blocks\n";
183 bool Train::reserve_more()
186 if(!rsv_blocks.empty())
187 last=&rsv_blocks.back();
188 else if(!cur_blocks.empty())
189 last=&cur_blocks.back();
193 cout<<"Train "<<name<<" reserving more blocks\n";
196 unsigned size=rsv_blocks.size();
199 int exit=last->block->traverse(last->entry);
202 Block *link=last->block->get_link(exit);
203 if(link && link->reserve(this))
205 rsv_blocks.push_back(BlockRef(link, link->get_endpoint_by_link(*last->block)));
206 last=&rsv_blocks.back();
217 cout<<" "<<rsv_blocks.size()<<" rsv_blocks\n";
222 void Train::set_status(const string &s)
225 signal_status_changed.emit(s);
228 } // namespace Marklin