1use serde_repr::{Deserialize_repr, Serialize_repr};
2
3#[derive(Debug, thiserror::Error)]
4pub enum VehicleError {
5 #[error("vehicle not found")]
6 VehicleNotFound = 256,
7 #[error("bogie not found")]
8 BogieNotFound = 512,
9 #[error("axle not found")]
10 AxleNotFound = 1024,
11 #[error("coupling not found")]
12 CouplingNotFound = 2048,
13 #[error("pantograph not found")]
14 PantographNotFound = 4096,
15 #[error("unknown error")]
16 Unknown = 0,
17}
18
19impl From<u32> for VehicleError {
20 fn from(value: u32) -> Self {
21 match value {
22 256 => VehicleError::VehicleNotFound,
23 512 => VehicleError::BogieNotFound,
24 1024 => VehicleError::AxleNotFound,
25 2048 => VehicleError::PantographNotFound,
26 _ => VehicleError::Unknown,
27 }
28 }
29}
30
31#[cfg(feature = "ffi")]
32#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
33pub struct Bogie {
34 index: usize,
35}
36
37#[cfg(feature = "ffi")]
38impl Bogie {
39 pub fn get(index: usize) -> Result<Self, VehicleError> {
40 match unsafe { lotus_script_sys::vehicle::bogie_is_valid(index as u32) } {
41 0 => Ok(Self { index }),
42 e => Err(e.into()),
43 }
44 }
45
46 pub fn set_rail_brake_force_newton(self, value: f32) {
53 unsafe { lotus_script_sys::vehicle::set_rail_brake_force_newton(self.index as u32, value) };
54 }
55}
56
57#[cfg(feature = "ffi")]
58#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
59pub struct Axle {
60 bogie_index: usize,
61 axle_index: usize,
62}
63
64#[cfg(feature = "ffi")]
65impl Axle {
66 pub fn get(bogie_index: usize, axle_index: usize) -> Result<Self, VehicleError> {
67 match unsafe {
68 lotus_script_sys::vehicle::axle_is_valid(bogie_index as u32, axle_index as u32)
69 } {
70 0 => Ok(Self {
71 bogie_index,
72 axle_index,
73 }),
74 e => Err(e.into()),
75 }
76 }
77
78 pub fn velocity_var_name(self) -> String {
79 format!("v_Axle_mps_{}_{}", self.bogie_index, self.axle_index)
80 }
81
82 pub fn bogie(self) -> Bogie {
83 Bogie {
84 index: self.bogie_index,
85 }
86 }
87
88 pub fn axle_index(self) -> usize {
89 self.axle_index
90 }
91
92 pub fn bogie_index(self) -> usize {
93 self.bogie_index
94 }
95
96 pub fn inverse_radius(self) -> f32 {
101 let inverse_radius = unsafe {
102 lotus_script_sys::vehicle::inverse_radius(
103 self.bogie_index as u32,
104 self.axle_index as u32,
105 )
106 };
107 assert!(!inverse_radius.is_nan());
108 assert_ne!(inverse_radius, f32::NEG_INFINITY);
109 assert_ne!(inverse_radius, f32::INFINITY);
110 inverse_radius
111 }
112
113 pub fn surface_type(self) -> SurfaceType {
115 let surface_type = unsafe {
116 lotus_script_sys::vehicle::surface_type(self.bogie_index as u32, self.axle_index as u32)
117 };
118 SurfaceType::try_from(surface_type).unwrap()
119 }
120
121 pub fn rail_quality(self) -> RailQuality {
123 let quality = unsafe {
124 lotus_script_sys::vehicle::rail_quality(self.bogie_index as u32, self.axle_index as u32)
125 };
126 RailQuality::try_from(quality).unwrap()
127 }
128
129 pub fn set_traction_force_newton(self, value: f32) {
133 unsafe {
134 lotus_script_sys::vehicle::set_traction_force_newton(
135 self.bogie_index as u32,
136 self.axle_index as u32,
137 value,
138 )
139 };
140 }
141
142 pub fn set_brake_force_newton(self, value: f32) {
148 unsafe {
149 lotus_script_sys::vehicle::set_brake_force_newton(
150 self.bogie_index as u32,
151 self.axle_index as u32,
152 value,
153 )
154 };
155 }
156}
157
158#[cfg(feature = "ffi")]
159#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
160pub struct Pantograph {
161 index: usize,
162}
163
164#[cfg(feature = "ffi")]
165impl Pantograph {
166 pub fn get(index: usize) -> Result<Self, VehicleError> {
167 match unsafe { lotus_script_sys::vehicle::pantograph_is_valid(index as u32) } {
168 0 => Ok(Self { index }),
169 e => Err(e.into()),
170 }
171 }
172
173 pub fn height(self) -> f32 {
175 let height = unsafe { lotus_script_sys::vehicle::pantograph_height(self.index as u32) };
176 assert!(!height.is_nan());
177 assert_ne!(height, f32::INFINITY);
178 height
179 }
180
181 pub fn voltage(self) -> f32 {
184 let voltage = unsafe { lotus_script_sys::vehicle::pantograph_voltage(self.index as u32) };
185 assert!(!voltage.is_nan());
186 assert_ne!(voltage, f32::INFINITY);
187 voltage
188 }
189}
190
191#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize_repr, Deserialize_repr)]
193#[repr(u8)]
194pub enum RailQuality {
195 Smooth = 0,
196 Rough = 1,
197 FroggySmooth = 2,
198 FroggyRough = 3,
199 FlatGroove = 4,
200 HighSpeedSmooth = 5,
201 SmoothDirt = 6,
202 RoughDirt = 7,
203 Deraileur = 8,
204}
205
206impl TryFrom<u32> for RailQuality {
207 type Error = VehicleError;
208
209 fn try_from(value: u32) -> Result<Self, Self::Error> {
210 match value {
211 0 => Ok(RailQuality::Smooth),
212 1 => Ok(RailQuality::Rough),
213 2 => Ok(RailQuality::FroggySmooth),
214 3 => Ok(RailQuality::FroggyRough),
215 4 => Ok(RailQuality::FlatGroove),
216 5 => Ok(RailQuality::HighSpeedSmooth),
217 6 => Ok(RailQuality::SmoothDirt),
218 7 => Ok(RailQuality::RoughDirt),
219 8 => Ok(RailQuality::Deraileur),
220 value => Err(value.into()),
221 }
222 }
223}
224
225#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize_repr, Deserialize_repr)]
227#[repr(u8)]
228pub enum SurfaceType {
229 Gravel = 0,
230 Street = 1,
231 Grass = 2,
232}
233
234impl TryFrom<u32> for SurfaceType {
235 type Error = VehicleError;
236
237 fn try_from(value: u32) -> Result<Self, Self::Error> {
238 match value {
239 0 => Ok(SurfaceType::Gravel),
240 1 => Ok(SurfaceType::Street),
241 2 => Ok(SurfaceType::Grass),
242 value => Err(value.into()),
243 }
244 }
245}