Skip to main content

rustsim_transit/
dwell.rs

1//! Dwell-time models for transit vehicles at stops.
2//!
3//! The linear dwell-time formula (TCQSM, Transit Capacity and Quality of
4//! Service Manual) is implemented:
5//!
6//! ```text
7//! dwell = min_dwell + a * alighters + b * boarders
8//! ```
9//!
10//! where `a` and `b` are the per-passenger service times.
11
12/// Parameters of the linear dwell-time model.
13#[derive(Debug, Clone, Copy, PartialEq)]
14pub struct DwellParams {
15    /// Minimum dwell time regardless of passenger flow (s).
16    pub min_dwell: f64,
17    /// Service time per alighting passenger (s).
18    pub per_alighter: f64,
19    /// Service time per boarding passenger (s).
20    pub per_boarder: f64,
21}
22
23impl Default for DwellParams {
24    fn default() -> Self {
25        Self {
26            min_dwell: 8.0,
27            per_alighter: 1.8,
28            per_boarder: 2.6,
29        }
30    }
31}
32
33/// Computed dwell time with a breakdown for telemetry.
34#[derive(Debug, Clone, Copy, PartialEq)]
35pub struct DwellTime {
36    /// Total dwell (s).
37    pub total: f64,
38    /// Contribution from alighters (s).
39    pub from_alighters: f64,
40    /// Contribution from boarders (s).
41    pub from_boarders: f64,
42}
43
44/// Compute the dwell time for a given alighter / boarder pair.
45pub fn compute(alighters: u32, boarders: u32, params: &DwellParams) -> DwellTime {
46    let a = params.per_alighter * alighters as f64;
47    let b = params.per_boarder * boarders as f64;
48    DwellTime {
49        total: params.min_dwell + a + b,
50        from_alighters: a,
51        from_boarders: b,
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58
59    #[test]
60    fn default_params_match_tcqsm_range() {
61        let d = compute(5, 10, &DwellParams::default());
62        assert!((d.total - (8.0 + 5.0 * 1.8 + 10.0 * 2.6)).abs() < 1e-9);
63    }
64
65    #[test]
66    fn zero_passengers_gives_min_dwell() {
67        let d = compute(0, 0, &DwellParams::default());
68        assert_eq!(d.total, 8.0);
69    }
70}