use derive_more::{AsRef, Display, From};
use uom::si::f64::{Length, Time, Velocity};
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Display, From, AsRef)]
pub struct DetectorId(#[as_ref(forward)] pub String);
pub use crate::sumo::Point;
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Display, From, AsRef)]
pub struct LaneRef(#[as_ref(forward)] pub String);
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum LanePosition {
FromStart(Length),
FromEnd(Length),
}
#[derive(Debug, Clone, PartialEq)]
pub struct DetectorGate {
pub lane: LaneRef,
pub position: LanePosition,
pub friendly_position: Option<bool>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct E1Detector {
pub id: DetectorId,
pub lane: LaneRef,
pub position: LanePosition,
pub file: String,
pub period: Option<Time>,
pub length: Option<Length>,
pub name: Option<String>,
pub friendly_position: Option<bool>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum LaneCoverage {
SingleLane(LaneRef),
LaneChain(Vec<LaneRef>),
}
#[derive(Debug, Clone, PartialEq)]
pub struct E2Detector {
pub id: DetectorId,
pub coverage: Option<LaneCoverage>,
pub position: Option<LanePosition>,
pub end_position: Option<LanePosition>,
pub length: Option<Length>,
pub file: String,
pub period: Option<Time>,
pub name: Option<String>,
pub friendly_position: Option<bool>,
pub speed_threshold: Option<Velocity>,
pub time_threshold: Option<Time>,
pub jam_threshold: Option<Length>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct E3Detector {
pub id: DetectorId,
pub entries: Vec<DetectorGate>,
pub exits: Vec<DetectorGate>,
pub file: String,
pub period: Option<Time>,
pub name: Option<String>,
pub icon_position: Option<Point>,
pub speed_threshold: Option<Velocity>,
pub time_threshold: Option<Time>,
pub open_entry: Option<bool>,
pub detect_persons: Vec<PersonMode>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PersonMode {
Walk,
Bicycle,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct UnknownPersonMode(pub String);
impl std::str::FromStr for PersonMode {
type Err = UnknownPersonMode;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"walk" => Self::Walk,
"bicycle" => Self::Bicycle,
other => return Err(UnknownPersonMode(other.to_string())),
})
}
}
impl PersonMode {
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
Self::Walk => "walk",
Self::Bicycle => "bicycle",
}
}
}
impl std::fmt::Display for PersonMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}
impl AsRef<str> for PersonMode {
fn as_ref(&self) -> &str {
self.as_str()
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Additional {
pub induction_loops: Vec<E1Detector>,
pub lane_area_detectors: Vec<E2Detector>,
pub entry_exit_detectors: Vec<E3Detector>,
}