Skip to main content

traaains/sim/signal/
main.rs

1//! Main signal (hlavní návěstidlo).
2//! [See more](https://cs.wikipedia.org/wiki/Hlavn%C3%AD_n%C3%A1v%C4%9Bstidlo).
3
4use std::fmt::Display;
5
6use strum::{EnumDiscriminants, EnumIter};
7
8/// Helper struct for defining max speeds of a main signal.
9///
10/// Main signals can only show a limited number of speeds, and thus having them represented via an enum makes sense.
11#[derive(Default, PartialEq, Eq, EnumIter)]
12pub enum MaxSpeed {
13    #[default]
14    Thirty,
15    Forty,
16    Sixty,
17    Eighty,
18    Hundred,
19}
20
21impl From<MaxSpeed> for u32 {
22    fn from(value: MaxSpeed) -> Self {
23        match value {
24            MaxSpeed::Thirty => 30,
25            MaxSpeed::Forty => 40,
26            MaxSpeed::Sixty => 60,
27            MaxSpeed::Eighty => 80,
28            MaxSpeed::Hundred => 100,
29        }
30    }
31}
32
33/// Possible states of a main signal.
34///
35/// When one really squints their eyes, a main signal only has three states:
36/// - Stop - either a summoning signal or not
37/// - Warning - together with an optional max speed on the next segment and an optional max speed on the next signal
38/// - Free - together with an optional max speed on the next segment
39#[derive(EnumDiscriminants)]
40#[strum_discriminants(derive(EnumIter))]
41pub enum MainSignalState {
42    Stop {
43        summon: bool,
44    },
45    Warning {
46        /// max speed on the track segment behind this signal
47        max_speed: Option<MaxSpeed>,
48        /// max speed on the next signal,
49        next_speed: Option<MaxSpeed>,
50    },
51    Free {
52        /// max speed
53        max_speed: Option<MaxSpeed>,
54    },
55}
56
57impl Default for MainSignalState {
58    fn default() -> Self {
59        MainSignalState::Stop {
60            summon: Default::default(),
61        }
62    }
63}
64
65impl Display for MainSignalStateDiscriminants {
66    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67        match self {
68            MainSignalStateDiscriminants::Stop => write!(f, "Stop"),
69            MainSignalStateDiscriminants::Warning => write!(f, "Warning"),
70            MainSignalStateDiscriminants::Free => write!(f, "Free"),
71        }
72    }
73}
74
75impl TryFrom<usize> for MainSignalStateDiscriminants {
76    type Error = &'static str;
77
78    fn try_from(value: usize) -> Result<Self, Self::Error> {
79        match value {
80            0 => Ok(MainSignalStateDiscriminants::Stop),
81            1 => Ok(MainSignalStateDiscriminants::Warning),
82            2 => Ok(MainSignalStateDiscriminants::Free),
83            _ => Err("Invalid parameter"),
84        }
85    }
86}
87
88/// Main signal (hlavní návěstidlo).
89#[derive(Default)]
90pub struct MainSignal {
91    pub state: MainSignalState,
92    /// Whether this signal is a repeat of the next signal
93    pub is_repeat: bool,
94}