]> git.tdb.fi Git - r2c2.git/blob - source/libmarklin/train.cpp
Add Track::get_endpoint_position to avoid duplicating calculations
[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         trfc_mgr.get_control().signal_sensor_event.connect(sigc::mem_fun(this, &Train::sensor_event));
17 }
18
19 void Train::set_name(const string &n)
20 {
21         name=n;
22
23         signal_name_changed.emit(name);
24 }
25
26 void Train::set_speed(unsigned speed)
27 {
28         target_speed=speed;
29         if(rsv_blocks.empty() && !reserve_more())
30                 return;
31         loco.set_speed(speed);
32 }
33
34 void Train::place(Block *block, const Block::Endpoint *entry)
35 {
36         for(BlockRefSeq::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end();)
37         {
38                 i->block->reserve(0);
39                 i=rsv_blocks.erase(i);
40         }
41
42         for(BlockRefSeq::iterator i=cur_blocks.begin(); i!=cur_blocks.end();)
43         {
44                 i->block->reserve(0);
45                 i=cur_blocks.erase(i);
46         }
47
48         if(!block->reserve(this))
49                 return;
50
51         cur_blocks.push_back(BlockRef(block, entry));
52 }
53
54 bool Train::free_block(Block *block)
55 {
56         for(BlockRefSeq::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
57                 if(i->block==block)
58                 {
59                         while(i!=rsv_blocks.end())
60                         {
61                                 i->block->reserve(0);
62                                 i=rsv_blocks.erase(i);
63                         }
64                         return true;
65                 }
66
67         return false;
68 }
69
70 void Train::sensor_event(unsigned addr, bool state)
71 {
72         if(!loco.get_speed())
73                 return;
74
75         if(state)
76         {
77                 BlockRefSeq::iterator i;
78                 for(i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
79                         if(i->block->get_sensor_id() && i->block->get_sensor_id()!=addr)
80                                 break;
81                 cur_blocks.splice(cur_blocks.end(), rsv_blocks, rsv_blocks.begin(), i);
82
83                 cout<<"Train advanced, "<<cur_blocks.size()<<" cur_blocks, "<<rsv_blocks.size()<<" rsv_blocks\n";
84
85                 reserve_more();
86                 if(rsv_blocks.empty())
87                         loco.set_speed(0);
88         }
89         else
90         {
91                 cout<<"Finding blocks to free\n";
92                 BlockRefSeq::iterator i;
93                 for(i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
94                         if(i->block->get_sensor_id()==addr)
95                                 break;
96                 if(i!=cur_blocks.end())
97                 {
98                         cout<<"found\n";
99                         ++i;
100                         for(BlockRefSeq::iterator j=cur_blocks.begin(); j!=i; ++j)
101                                 j->block->reserve(0);
102                         cur_blocks.erase(cur_blocks.begin(), i);
103                         cout<<cur_blocks.size()<<" cur_blocks\n";
104                 }
105
106                 reserve_more();
107         }
108 }
109
110 bool Train::reserve_more()
111 {
112         BlockRef *last=0;
113         if(!rsv_blocks.empty())
114                 last=&rsv_blocks.back();
115         else if(!cur_blocks.empty())
116                 last=&cur_blocks.back();
117         if(!last)
118                 return false;
119
120         bool result=false;
121         unsigned size=rsv_blocks.size();
122         while(size<5)
123         {
124                 const Block::Endpoint *exit=last->block->traverse(last->entry);
125                 if(exit && exit->link->reserve(this))
126                 {
127                         rsv_blocks.push_back(BlockRef(exit->link, exit->link->get_endpoint_by_link(last->block)));
128                         last=&rsv_blocks.back();
129                         ++size;
130                         result=true;
131                 }
132                 else
133                         break;
134         }
135
136         return result;
137 }
138
139 } // namespace Marklin