3 This file is part of the MSP Märklin suite
4 Copyright © 2006-2009 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();
59 set_status("Stopped");
63 unsigned n=reserve_more();
66 try_reserve=Time::now()+2*Time::sec;
67 set_status("Blocked");
72 try_reserve=Time::now()+2*Time::sec;
77 loco.set_speed(speed);
79 set_status("Traveling --- kmh");
84 void Train::place(Block *block, unsigned entry)
86 for(list<BlockRef>::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end();)
89 i=rsv_blocks.erase(i);
92 for(list<BlockRef>::iterator i=cur_blocks.begin(); i!=cur_blocks.end();)
95 i=cur_blocks.erase(i);
98 if(!block->reserve(this))
100 set_status("Unplaced");
104 cur_blocks.push_back(BlockRef(block, entry));
106 set_status("Stopped");
109 bool Train::free_block(Block *block)
111 for(list<BlockRef>::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
114 while(i!=rsv_blocks.end())
116 i->block->reserve(0);
117 i=rsv_blocks.erase(i);
125 void Train::tick(const Time::TimeStamp &t)
127 if(try_reserve && t>try_reserve)
129 unsigned n=reserve_more();
132 loco.set_speed(target_speed);
133 set_status("Traveling --- kmh");
134 try_reserve=Time::TimeStamp();
140 try_reserve=t+2*Time::sec;
143 try_reserve=t+2*Time::sec;
147 void Train::sensor_event(bool state, Sensor *sensor)
149 unsigned addr=sensor->get_address();
153 list<BlockRef>::iterator i;
154 for(i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
155 if(i->block->get_sensor_id() && i->block->get_sensor_id()!=addr)
158 if(i!=rsv_blocks.begin())
160 real_speed=static_cast<int>(round(travel_dist/((Time::now()-last_entry_time)/Time::sec)*87*3.6/5))*5;
161 set_status(format("Traveling %3d kmh", real_speed));
165 for(list<BlockRef>::iterator j=rsv_blocks.begin(); j!=i; ++j)
167 j->block->traverse(j->entry, &block_len);
168 cout<<"Advancing: block "<<j->block<<" (sensor "<<j->block->get_sensor_id()<<") length "<<block_len<<'\n';
169 travel_dist+=block_len;
171 last_entry_time=Time::now();
173 cur_blocks.splice(cur_blocks.end(), rsv_blocks, rsv_blocks.begin(), i);
174 cout<<"Train "<<name<<" advanced, "<<cur_blocks.size()<<" cur_blocks, "<<rsv_blocks.size()<<" rsv_blocks\n";
179 unsigned n=reserve_more();
183 try_reserve=Time::now()+2*Time::sec;
184 set_status("Blocked");
189 try_reserve=Time::now()+2*Time::sec;
196 cout<<"Train "<<name<<" finding blocks to free\n";
197 for(list<BlockRef>::iterator i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
198 if(i->block->get_sensor_id()==addr)
201 for(list<BlockRef>::iterator j=cur_blocks.begin(); j!=i; ++j)
202 j->block->reserve(0);
203 cout<<" "<<distance(cur_blocks.begin(), i)<<" blocks freed, ";
204 cur_blocks.erase(cur_blocks.begin(), i);
205 cout<<cur_blocks.size()<<" cur_blocks\n";
213 unsigned Train::reserve_more()
216 if(!rsv_blocks.empty())
217 last=&rsv_blocks.back();
218 else if(!cur_blocks.empty())
219 last=&cur_blocks.back();
223 cout<<"Train "<<name<<" reserving more blocks\n";
226 for(list<BlockRef>::const_iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
227 if(i->block->get_sensor_id())
233 int exit=last->block->traverse(last->entry);
236 Block *link=last->block->get_link(exit);
237 if(link && link->reserve(this))
239 rsv_blocks.push_back(BlockRef(link, link->get_endpoint_by_link(*last->block)));
240 last=&rsv_blocks.back();
241 if(last->block->get_sensor_id())
254 while(last && !last->block->get_sensor_id())
256 last->block->reserve(0);
257 rsv_blocks.erase(--rsv_blocks.end());
258 if(!rsv_blocks.empty())
259 last=&rsv_blocks.back();
264 cout<<" "<<rsv_blocks.size()<<" rsv_blocks\n";
269 void Train::set_status(const string &s)
272 signal_status_changed.emit(s);
275 } // namespace Marklin