1use rustsim_geometry::vec3::Vec3;
4use rustsim_modes::TravelMode;
5use rustsim_transit::{RouteId, StopId};
6
7#[derive(Debug, Clone, Copy, PartialEq)]
10pub struct Waypoint {
11 pub pos: Vec3,
13 pub floor: i32,
15}
16
17impl Waypoint {
18 pub fn ground(x: f64, y: f64) -> Self {
20 Self {
21 pos: [x, y, 0.0],
22 floor: 0,
23 }
24 }
25}
26
27#[derive(Debug, Clone)]
29pub enum Leg {
30 Walk {
32 from: Waypoint,
34 to: Waypoint,
36 },
37 DriveSelf {
39 mode: TravelMode,
41 from: Waypoint,
43 to: Waypoint,
45 },
46 Hail {
48 mode: TravelMode,
50 from: Waypoint,
52 to: Waypoint,
54 },
55 Transit {
57 route: RouteId,
59 board_at: StopId,
61 alight_at: StopId,
63 },
64 Connector {
66 connector_id: u64,
68 },
69}
70
71impl Leg {
72 pub fn mode(&self) -> TravelMode {
74 match self {
75 Leg::Walk { .. } | Leg::Connector { .. } => TravelMode::Pedestrian,
76 Leg::DriveSelf { mode, .. } | Leg::Hail { mode, .. } => *mode,
77 Leg::Transit { .. } => TravelMode::Transit,
78 }
79 }
80}
81
82#[derive(Debug, Clone)]
84pub struct TripPlan {
85 pub id: u64,
87 pub legs: Vec<Leg>,
89}
90
91impl TripPlan {
92 pub fn len(&self) -> usize {
94 self.legs.len()
95 }
96
97 pub fn is_empty(&self) -> bool {
99 self.legs.is_empty()
100 }
101}
102
103#[cfg(test)]
104mod tests {
105 use super::*;
106
107 #[test]
108 fn leg_mode_dispatch() {
109 let walk = Leg::Walk {
110 from: Waypoint::ground(0.0, 0.0),
111 to: Waypoint::ground(1.0, 0.0),
112 };
113 assert_eq!(walk.mode(), TravelMode::Pedestrian);
114
115 let transit = Leg::Transit {
116 route: 1,
117 board_at: 10,
118 alight_at: 20,
119 };
120 assert_eq!(transit.mode(), TravelMode::Transit);
121
122 let drive = Leg::DriveSelf {
123 mode: TravelMode::Vehicle,
124 from: Waypoint::ground(0.0, 0.0),
125 to: Waypoint::ground(5.0, 0.0),
126 };
127 assert_eq!(drive.mode(), TravelMode::Vehicle);
128 }
129}