]> git.tdb.fi Git - r2c2.git/blob - source/libr2c2/zone.cpp
New routing system for trains
[r2c2.git] / source / libr2c2 / zone.cpp
1 #include <msp/strings/format.h>
2 #include "block.h"
3 #include "layout.h"
4 #include "track.h"
5 #include "zone.h"
6
7 using namespace std;
8 using namespace Msp;
9
10 namespace R2C2 {
11
12 Zone::Zone(Layout &l):
13         layout(l),
14         number(0)
15 {
16         layout.add_zone(*this);
17 }
18
19 Zone::~Zone()
20 {
21         layout.remove_zone(*this);
22 }
23
24 void Zone::set_name(const string &g, const string &q, unsigned n)
25 {
26         group = g;
27         qualifier = q;
28         number = n;
29
30         signal_name_changed.emit(group, qualifier, number);
31 }
32
33 string Zone::get_name() const
34 {
35         string result = group;
36         if(!qualifier.empty())
37         {
38                 result += ' ';
39                 result += qualifier;
40         }
41         if(number)
42                 result += format(" %d", number);
43         return result;
44 }
45
46 void Zone::add_track(Track &track)
47 {
48         if(!is_valid(track))
49                 throw logic_error("unconnected");
50
51         tracks.insert(&track);
52 }
53
54 bool Zone::add_tracks(const TrackSet &trks)
55 {
56         TrackSet pending = trks;
57         bool first = true;
58         while(1)
59         {
60                 bool ok = false;
61                 for(TrackSet::const_iterator i=pending.begin(); i!=pending.end(); ++i)
62                         if(is_valid(**i))
63                         {
64                                 tracks.insert(*i);
65                                 pending.erase(i);
66                                 ok = true;
67                                 break;
68                         }
69
70                 if(!ok)
71                 {
72                         if(first)
73                                 throw logic_error("unconnected");
74                         return pending.empty();
75                 }
76
77                 first = false;
78         }
79 }
80
81 bool Zone::has_track(Track &t) const
82 {
83         return tracks.count(&t);
84 }
85
86 void Zone::save(list<DataFile::Statement> &st) const
87 {
88         st.push_back((DataFile::Statement("group"), group));
89         if(!qualifier.empty())
90                 st.push_back((DataFile::Statement("qualifier"), qualifier));
91         if(number)
92                 st.push_back((DataFile::Statement("number"), number));
93
94         set<unsigned> block_ids;
95         for(TrackSet::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
96                 block_ids.insert((*i)->get_block().get_id());
97
98         for(set<unsigned>::const_iterator i=block_ids.begin(); i!=block_ids.end(); ++i)
99                 st.push_back((DataFile::Statement("block"), *i));
100 }
101
102 bool Zone::is_valid(Track &t) const
103 {
104         if(tracks.empty())
105                 return true;
106
107         const vector<Track *> &links = t.get_links();
108         for(vector<Track *>::const_iterator i=links.begin(); i!=links.end(); ++i)
109                 if(*i && tracks.count(*i))
110                         return true;
111
112         return false;
113 }
114
115
116 Zone::Loader::Loader(Zone &z):
117         DataFile::ObjectLoader<Zone>(z)
118 {
119         add("block",     &Loader::block);
120         add("group",     &Zone::group);
121         add("number",    &Zone::number);
122         add("qualifier", &Zone::qualifier);
123 }
124
125 void Zone::Loader::block(unsigned b)
126 {
127         Block &blk = obj.layout.get_block(b);
128         const set<Track *> &btracks = blk.get_tracks();
129         obj.tracks.insert(btracks.begin(), btracks.end());
130 }
131
132 } // namespace R2C2