]> git.tdb.fi Git - r2c2.git/blob - source/libmarklin/block.cpp
Convert engineer to use mspgbase instead of SDL
[r2c2.git] / source / libmarklin / block.cpp
1 #include "control.h"
2 #include "block.h"
3 #include "tracktype.h"
4 #include "trafficmanager.h"
5 #include "turnout.h"
6
7 using namespace Msp;
8
9 #include <iostream>
10 using namespace std;
11
12 namespace Marklin {
13
14 Block::Block(TrafficManager &tm, Track &start):
15         trfc_mgr(tm),
16         id(next_id++),
17         sensor_id(start.get_sensor_id()),
18         train(0)
19 {
20         tracks.insert(&start);
21
22         list<Track *> queue;
23         queue.push_back(&start);
24
25         while(!queue.empty())
26         {
27                 Track *track=queue.front();
28                 queue.erase(queue.begin());
29
30                 const vector<Track *> &links=track->get_links();
31                 for(unsigned i=0; i<links.size(); ++i)
32                         if(links[i] && !tracks.count(links[i]))
33                         {
34                                 if(links[i]->get_sensor_id()==sensor_id)
35                                 {
36                                         queue.push_back(links[i]);
37                                         tracks.insert(links[i]);
38                                 }
39                                 else
40                                         endpoints.push_back(Endpoint(track, i));
41                         }
42         }
43
44         for(unsigned i=0; i<endpoints.size(); ++i)
45         {
46                 unsigned route=1<<i;
47                 endpoints[i].routes|=route;
48                 set<Track *> visited;
49                 find_routes(*endpoints[i].track, endpoints[i].track_ep, route, visited);
50         }
51 }
52
53 int Block::get_endpoint_by_link(const Block &other) const
54 {
55         for(unsigned i=0; i<endpoints.size(); ++i)
56                 if(endpoints[i].link==&other)
57                         return i;
58
59         return -1;
60 }
61
62 int Block::traverse(unsigned epi) const
63 {
64         if(epi>=endpoints.size())
65                 throw InvalidParameterValue("Endpoint index out of range");
66
67         const Endpoint &ep=endpoints[epi];
68         Track *track=ep.track;
69         unsigned track_ep=ep.track_ep;
70
71         while(1)
72         {
73                 unsigned cur_route=0;
74                 unsigned tid=track->get_turnout_id();
75                 if(tid)
76                 {
77                         Turnout &turnout=trfc_mgr.get_control().get_turnout(tid);
78                         cur_route=turnout.get_route();
79                 }
80
81                 int other_ep=track->traverse(track_ep, cur_route);
82                 if(other_ep<0)
83                         return 0;
84
85                 for(unsigned i=0; i<endpoints.size(); ++i)
86                         if(endpoints[i].track==track && endpoints[i].track_ep==static_cast<unsigned>(other_ep))
87                                 return i;
88
89                 Track *next=track->get_link(other_ep);
90                 track_ep=next->get_endpoint_by_link(*track);
91                 track=next;
92
93                 if(tracks.count(track)==0)
94                         return -1;
95         }
96 }
97
98 void Block::check_link(Block &other)
99 {
100         for(vector<Endpoint>::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
101         {
102                 if(i->link)
103                         continue;
104
105                 for(vector<Endpoint>::iterator j=other.endpoints.begin(); j!=other.endpoints.end(); ++j)
106                         if(j->track==i->track->get_link(i->track_ep) && j->track->get_link(j->track_ep)==i->track && !j->link)
107                         {
108                                 i->link=&other;
109                                 j->link=this;
110                         }
111         }
112 }
113
114 Block *Block::get_link(unsigned epi) const
115 {
116         if(epi>=endpoints.size())
117                 throw InvalidParameterValue("Endpoint index out of range");
118         return endpoints[epi].link;
119 }
120
121 bool Block::reserve(const Train *t)
122 {
123         if(!t || !train)
124         {
125                 train=t;
126                 if(train)
127                         cout<<"Block "<<this<<" reserved for train "<<train<<'\n';
128                 else
129                         cout<<"Block "<<this<<" freed\n";
130                 trfc_mgr.signal_block_reserved.emit(*this, train);
131                 return true;
132         }
133         else
134                 return false;
135 }
136
137 void Block::print_debug()
138 {
139         cout<<"Block "<<id;
140         if((*tracks.begin())->get_sensor_id())
141                 cout<<", sensor="<<(*tracks.begin())->get_sensor_id();
142         cout<<'\n';
143         for(vector<Endpoint>::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
144         {
145                 cout<<"  Endpoint, link=";
146                 if(i->link)
147                         cout<<i->link->id;
148                 else
149                         cout<<"none";
150                 cout<<", routes="<<i->routes<<'\n';
151         }
152 }
153
154 void Block::find_routes(Track &track, unsigned track_ep, unsigned route, set<Track *> &visited)
155 {
156         visited.insert(&track);
157
158         const vector<Marklin::Endpoint> &eps=track.get_type().get_endpoints();
159         for(unsigned i=0; i<eps.size(); ++i)
160         {
161                 if(i==track_ep) continue;
162                 Track *link=track.get_link(i);
163                 if(!link) continue;
164                 if(visited.count(link)) continue;
165                 if(!(eps[i].routes&eps[track_ep].routes)) continue;
166
167                 if(tracks.count(link))
168                         find_routes(*link, link->get_endpoint_by_link(track), route, visited);
169                 else
170                 {
171                         for(vector<Endpoint>::iterator j=endpoints.begin(); j!=endpoints.end(); ++j)
172                                 if(j->track==&track && j->track_ep==i)
173                                         j->routes|=route;
174                 }
175         }
176 }
177
178 unsigned Block::next_id=1;
179
180
181 Block::Endpoint::Endpoint(Track *t, unsigned e):
182         track(t),
183         track_ep(e),
184         link(0),
185         routes(0)
186 { }
187
188 } // namespace Marklin