]> git.tdb.fi Git - r2c2.git/blob - source/libr2c2/dummy.cpp
ba23449ad304a50fe99f043114b439795c0cc666
[r2c2.git] / source / libr2c2 / dummy.cpp
1 #include <cstdlib>
2 #include <msp/core/maputils.h>
3 #include <msp/strings/utils.h>
4 #include <msp/time/utils.h>
5 #include "dummy.h"
6
7 using namespace std;
8 using namespace Msp;
9
10 namespace R2C2 {
11
12 Dummy::Dummy(const Options &opts):
13         power(true),
14         turnout_delay(opts.get("turnout_delay", 0.0f)*Time::sec),
15         turnout_fail_rate(opts.get("turnout_fail_rate", 0.0f)*RAND_MAX)
16 { }
17
18 void Dummy::set_power(bool p)
19 {
20         power = p;
21         signal_power.emit(power);
22 }
23
24 void Dummy::halt(bool h)
25 {
26         halted = h;
27         if(halted)
28         {
29                 for(map<unsigned, LocoState>::iterator i=locos.begin(); i!=locos.end(); ++i)
30                         if(i->second.speed)
31                                 set_loco_speed(i->first, 0);
32         }
33         signal_halt.emit(halted);
34 }
35
36 const char *Dummy::enumerate_protocols(unsigned i) const
37 {
38         if(i==0)
39                 return "dummy";
40         return 0;
41 }
42
43 unsigned Dummy::get_protocol_speed_steps(const string &) const
44 {
45         return 0;
46 }
47
48 unsigned Dummy::add_turnout(unsigned addr, const TrackType &)
49 {
50         turnouts[addr];
51         return addr;
52 }
53
54 void Dummy::set_turnout(unsigned addr, unsigned state)
55 {
56         TurnoutState &turnout = turnouts[addr];
57         if(turnout.state==state && turnout.pending==state)
58         {
59                 signal_turnout.emit(addr, state);
60                 return;
61         }
62
63         turnout.pending = state;
64         if(turnout_delay)
65                 turnout.timeout = Time::now()+turnout_delay;
66         else
67         {
68                 if(!turnout_fail_rate || rand()>=turnout_fail_rate)
69                         turnout.state = state;
70                 signal_turnout.emit(addr, state);
71         }
72 }
73
74 unsigned Dummy::get_turnout(unsigned addr) const
75 {
76         map<unsigned, TurnoutState>::const_iterator i = turnouts.find(addr);
77         if(i!=turnouts.end())
78                 return i->second.state;
79         return 0;
80 }
81
82 void Dummy::set_loco_speed(unsigned addr, unsigned speed)
83 {
84         if(speed && halted)
85                 return;
86
87         LocoState &loco = locos[addr];
88         loco.speed = speed;
89         signal_loco_speed.emit(addr, speed, loco.reverse);
90 }
91
92 void Dummy::set_loco_reverse(unsigned addr, bool rev)
93 {
94         LocoState &loco = locos[addr];
95         loco.reverse = rev;
96         signal_loco_speed.emit(addr, loco.speed, rev);
97 }
98
99 void Dummy::set_loco_function(unsigned addr, unsigned func, bool state)
100 {
101         signal_loco_function.emit(addr, func, state);
102 }
103
104 void Dummy::set_sensor(unsigned addr, bool state)
105 {
106         if(sensors[addr]!=state)
107         {
108                 sensors[addr] = state;
109                 signal_sensor.emit(addr, state);
110         }
111 }
112
113 bool Dummy::get_sensor(unsigned addr) const
114 {
115         map<unsigned, bool>::const_iterator i = sensors.find(addr);
116         if(i!=sensors.end())
117                 return i->second;
118         return false;
119 }
120
121 float Dummy::get_telemetry_value(const string &name) const
122 {
123         throw key_error(name);
124 }
125
126 void Dummy::tick()
127 {
128         Time::TimeStamp t = Time::now();
129         for(map<unsigned, TurnoutState>::iterator i=turnouts.begin(); i!=turnouts.end(); ++i)
130         {
131                 if(i->second.timeout && t>=i->second.timeout)
132                 {
133                         if(turnout_fail_rate && rand()<turnout_fail_rate)
134                         {
135                                 signal_turnout_failed.emit(i->first);
136                                 i->second.pending = i->second.state;
137                         }
138                         i->second.state = i->second.pending;
139                         i->second.timeout = Time::TimeStamp();
140                         signal_turnout.emit(i->first, i->second.state);
141                 }
142         }
143 }
144
145 } // namespace R2C2