]> git.tdb.fi Git - r2c2.git/blob - source/libmarklin/train.cpp
Convert engineer to use mspgbase instead of SDL
[r2c2.git] / source / libmarklin / train.cpp
1 #include <msp/time/units.h>
2 #include <msp/time/utils.h>
3 #include "control.h"
4 #include "trafficmanager.h"
5 #include "train.h"
6
7 using namespace Msp;
8
9 #include <iostream>
10 using namespace std;
11
12 namespace Marklin {
13
14 Train::Train(TrafficManager &tm, Locomotive &l):
15         trfc_mgr(tm),
16         loco(l),
17         target_speed(0)
18 {
19         trfc_mgr.add_train(this);
20
21         const map<unsigned, Sensor *> &sensors=trfc_mgr.get_control().get_sensors();
22         for(map<unsigned, Sensor *>::const_iterator i=sensors.begin(); i!=sensors.end(); ++i)
23                 i->second->signal_state_changed.connect(sigc::bind(sigc::mem_fun(this, &Train::sensor_event), i->second));
24 }
25
26 void Train::set_name(const string &n)
27 {
28         name=n;
29
30         signal_name_changed.emit(name);
31 }
32
33 void Train::set_speed(unsigned speed)
34 {
35         target_speed=speed;
36         if(!target_speed)
37         {
38                 for(list<BlockRef>::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
39                         i->block->reserve(0);
40                 rsv_blocks.clear();
41         }
42         else if(rsv_blocks.empty() && !reserve_more())
43                 return;
44         loco.set_speed(speed);
45 }
46
47 void Train::place(Block *block, unsigned entry)
48 {
49         for(list<BlockRef>::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end();)
50         {
51                 i->block->reserve(0);
52                 i=rsv_blocks.erase(i);
53         }
54
55         for(list<BlockRef>::iterator i=cur_blocks.begin(); i!=cur_blocks.end();)
56         {
57                 i->block->reserve(0);
58                 i=cur_blocks.erase(i);
59         }
60
61         if(!block->reserve(this))
62                 return;
63
64         cur_blocks.push_back(BlockRef(block, entry));
65 }
66
67 bool Train::free_block(Block *block)
68 {
69         for(list<BlockRef>::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
70                 if(i->block==block)
71                 {
72                         while(i!=rsv_blocks.end())
73                         {
74                                 i->block->reserve(0);
75                                 i=rsv_blocks.erase(i);
76                         }
77                         return true;
78                 }
79
80         return false;
81 }
82
83 void Train::tick(const Time::TimeStamp &t)
84 {
85         if(try_reserve && t>try_reserve)
86         {
87                 if(reserve_more())
88                 {
89                         loco.set_speed(target_speed);
90                         try_reserve=Time::TimeStamp();
91                 }
92                 else
93                         try_reserve=t+2*Time::sec;
94         }
95 }
96
97 void Train::sensor_event(bool state, Sensor *sensor)
98 {
99         if(!loco.get_speed())
100                 return;
101
102         unsigned addr=sensor->get_address();
103
104         if(state)
105         {
106                 list<BlockRef>::iterator i;
107                 for(i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
108                         if(i->block->get_sensor_id() && i->block->get_sensor_id()!=addr)
109                                 break;
110                 cur_blocks.splice(cur_blocks.end(), rsv_blocks, rsv_blocks.begin(), i);
111
112                 cout<<"Train "<<this<<" advanced, "<<cur_blocks.size()<<" cur_blocks, "<<rsv_blocks.size()<<" rsv_blocks\n";
113
114                 if(rsv_blocks.empty() && !reserve_more())
115                 {
116                         loco.set_speed(0);
117                         try_reserve=Time::now()+2*Time::sec;
118                 }
119         }
120         else
121         {
122                 cout<<"Train "<<this<<" finding blocks to free\n";
123                 list<BlockRef>::iterator i;
124                 for(i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
125                 {
126                         if(i->block->get_sensor_id()==addr)
127                         {
128                                 ++i;
129                                 for(list<BlockRef>::iterator j=cur_blocks.begin(); j!=i; ++j)
130                                         j->block->reserve(0);
131                                 cout<<"  "<<distance(cur_blocks.begin(),i )<<" blocks freed, ";
132                                 cur_blocks.erase(cur_blocks.begin(), i);
133                                 cout<<cur_blocks.size()<<" cur_blocks\n";
134                         }
135                 }
136
137                 reserve_more();
138         }
139 }
140
141 bool Train::reserve_more()
142 {
143         BlockRef *last=0;
144         if(!rsv_blocks.empty())
145                 last=&rsv_blocks.back();
146         else if(!cur_blocks.empty())
147                 last=&cur_blocks.back();
148         if(!last)
149                 return false;
150
151         cout<<"Train "<<this<<" reserving more blocks\n";
152
153         bool result=false;
154         unsigned size=rsv_blocks.size();
155         while(size<2)
156         {
157                 int exit=last->block->traverse(last->entry);
158                 if(exit>=0) 
159                 {
160                         Block *link=last->block->get_link(exit);
161                         if(link && link->reserve(this))
162                         {
163                                 rsv_blocks.push_back(BlockRef(link, link->get_endpoint_by_link(*last->block)));
164                                 last=&rsv_blocks.back();
165                                 ++size;
166                                 result=true;
167                         }
168                         else
169                                 break;
170                 }
171                 else
172                         break;
173         }
174
175         cout<<"  "<<rsv_blocks.size()<<" rsv_blocks\n";
176
177         return result;
178 }
179
180 } // namespace Marklin