]> git.tdb.fi Git - r2c2.git/blob - source/libmarklin/train.cpp
Initial revision
[r2c2.git] / source / libmarklin / train.cpp
1 #include "control.h"
2 #include "trafficmanager.h"
3 #include "train.h"
4
5 namespace Marklin {
6
7 Train::Train(TrafficManager &tm, Locomotive &l):
8         trfc_mgr(tm),
9         loco(l),
10         target_speed(0)
11 {
12         trfc_mgr.add_train(this);
13         trfc_mgr.get_control().signal_sensor_event.connect(sigc::mem_fun(this, &Train::sensor_event));
14 }
15
16 void Train::set_speed(unsigned speed)
17 {
18         target_speed=speed;
19         if(rsv_sections.empty() && !reserve_more())
20                 return;
21         loco.set_speed(speed);
22 }
23
24 void Train::place(Section *sect, const Section::Endpoint *entry)
25 {
26         for(SectRefSeq::iterator i=rsv_sections.begin(); i!=rsv_sections.end();)
27         {
28                 i->section->reserve(0);
29                 i=rsv_sections.erase(i);
30         }
31
32         for(SectRefSeq::iterator i=cur_sections.begin(); i!=cur_sections.end();)
33         {
34                 i->section->reserve(0);
35                 i=cur_sections.erase(i);
36         }
37
38         if(!sect->reserve(this))
39                 return;
40
41         cur_sections.push_back(SectionRef(sect, entry));
42 }
43
44 bool Train::free_section(Section *sect)
45 {
46         for(SectRefSeq::iterator i=rsv_sections.begin(); i!=rsv_sections.end(); ++i)
47                 if(i->section==sect)
48                 {
49                         while(i!=rsv_sections.end())
50                         {
51                                 i->section->reserve(0);
52                                 i=rsv_sections.erase(i);
53                         }
54                         return true;
55                 }
56
57         return false;
58 }
59
60 void Train::sensor_event(unsigned addr, bool state)
61 {
62         if(state)
63         {
64                 SectRefSeq::iterator i;
65                 for(i=rsv_sections.begin(); i!=rsv_sections.end(); ++i)
66                         if(i->section->get_sensor_id() && i->section->get_sensor_id()!=addr)
67                                 break;
68                 cur_sections.splice(cur_sections.begin(), rsv_sections, rsv_sections.begin(), i);
69
70                 reserve_more();
71                 if(rsv_sections.empty())
72                         loco.set_speed(0);
73         }
74         else
75         {
76                 SectRefSeq::iterator i;
77                 for(i=cur_sections.begin(); i!=cur_sections.end(); ++i)
78                         if(i->section->get_sensor_id()==addr)
79                                 break;
80                 if(i!=cur_sections.end())
81                 {
82                         ++i;
83                         for(SectRefSeq::iterator j=cur_sections.begin(); j!=i; ++j)
84                                 j->section->reserve(0);
85                         cur_sections.erase(cur_sections.begin(), i);
86                 }
87
88                 reserve_more();
89         }
90 }
91
92 bool Train::reserve_more()
93 {
94         SectionRef *last=0;
95         if(!rsv_sections.empty())
96                 last=&rsv_sections.back();
97         else if(!cur_sections.empty())
98                 last=&cur_sections.back();
99         if(!last)
100                 return false;
101
102         bool result=false;
103         unsigned size=rsv_sections.size();
104         while(size<5)
105         {
106                 const Section::Endpoint *exit=last->section->traverse(last->entry);
107                 if(exit->link->reserve(this))
108                 {
109                         rsv_sections.push_back(SectionRef(exit->link, exit->link->get_endpoint_by_link(last->section)));
110                         last=&rsv_sections.back();
111                         ++size;
112                         result=true;
113                 }
114                 else
115                         break;
116         }
117
118         return result;
119 }
120
121 } // namespace Marklin