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