hrdf_routing_engine/routing/
models.rs

1use chrono::NaiveDateTime;
2use hrdf_parser::{Coordinates, DataStorage, Journey};
3use rustc_hash::FxHashSet;
4use serde::Serialize;
5
6#[derive(Debug, Clone)]
7pub struct RouteSection {
8    journey_id: Option<i32>,
9    departure_stop_id: i32,
10    arrival_stop_id: i32,
11    arrival_at: NaiveDateTime,
12    duration: Option<i16>,
13}
14
15impl RouteSection {
16    pub fn new(
17        journey_id: Option<i32>,
18        departure_stop_id: i32,
19        arrival_stop_id: i32,
20        arrival_at: NaiveDateTime,
21        duration: Option<i16>,
22    ) -> Self {
23        Self {
24            journey_id,
25            departure_stop_id,
26            arrival_stop_id,
27            arrival_at,
28            duration,
29        }
30    }
31
32    // Getters/Setters
33
34    pub fn journey_id(&self) -> Option<i32> {
35        self.journey_id
36    }
37
38    pub fn departure_stop_id(&self) -> i32 {
39        self.departure_stop_id
40    }
41
42    pub fn arrival_stop_id(&self) -> i32 {
43        self.arrival_stop_id
44    }
45
46    pub fn set_arrival_stop_id(&mut self, value: i32) {
47        self.arrival_stop_id = value;
48    }
49
50    pub fn arrival_at(&self) -> NaiveDateTime {
51        self.arrival_at
52    }
53
54    pub fn set_arrival_at(&mut self, value: NaiveDateTime) {
55        self.arrival_at = value;
56    }
57
58    pub fn duration(&self) -> Option<i16> {
59        self.duration
60    }
61
62    // Functions
63
64    pub fn journey<'a>(&'a self, data_storage: &'a DataStorage) -> Option<&Journey> {
65        self.journey_id.map(|id| {
66            data_storage
67                .journeys()
68                .find(id)
69                .unwrap_or_else(|| panic!("Journey {:?} not found.", id))
70        })
71    }
72}
73
74#[derive(Debug, Clone)]
75pub struct Route {
76    sections: Vec<RouteSection>,
77    visited_stops: FxHashSet<i32>,
78}
79
80impl Route {
81    pub fn new(sections: Vec<RouteSection>, visited_stops: FxHashSet<i32>) -> Self {
82        Self {
83            sections,
84            visited_stops,
85        }
86    }
87
88    // Getters/Setters
89
90    pub fn sections(&self) -> &Vec<RouteSection> {
91        &self.sections
92    }
93
94    pub fn visited_stops(&self) -> &FxHashSet<i32> {
95        &self.visited_stops
96    }
97
98    // Functions
99
100    pub fn last_section(&self) -> &RouteSection {
101        // A route always contains at least one section.
102        self.sections.last().unwrap()
103    }
104
105    pub fn last_section_mut(&mut self) -> &mut RouteSection {
106        // A route always contains at least one section.
107        self.sections.last_mut().unwrap()
108    }
109
110    pub fn arrival_stop_id(&self) -> i32 {
111        self.last_section().arrival_stop_id()
112    }
113
114    pub fn arrival_at(&self) -> NaiveDateTime {
115        self.last_section().arrival_at()
116    }
117
118    pub fn has_visited_any_stops(&self, stops: &FxHashSet<i32>) -> bool {
119        !self.visited_stops.is_disjoint(stops)
120    }
121
122    pub fn sections_having_journey(&self) -> Vec<&RouteSection> {
123        self.sections
124            .iter()
125            .filter(|section| section.journey_id().is_some())
126            .collect()
127    }
128
129    pub fn count_connections(&self) -> usize {
130        self.sections_having_journey().len()
131    }
132}
133
134#[derive(Copy, Clone, Eq, PartialEq)]
135pub enum RoutingAlgorithmMode {
136    SolveFromDepartureStopToArrivalStop,
137    SolveFromDepartureStopToReachableArrivalStops,
138}
139
140pub struct RoutingAlgorithmArgs {
141    mode: RoutingAlgorithmMode,
142    arrival_stop_id: Option<i32>,
143    time_limit: Option<NaiveDateTime>,
144}
145
146impl RoutingAlgorithmArgs {
147    pub fn new(
148        mode: RoutingAlgorithmMode,
149        arrival_stop_id: Option<i32>,
150        time_limit: Option<NaiveDateTime>,
151    ) -> Self {
152        Self {
153            mode,
154            arrival_stop_id,
155            time_limit,
156        }
157    }
158
159    pub fn solve_from_departure_stop_to_arrival_stop(arrival_stop_id: i32) -> Self {
160        Self::new(
161            RoutingAlgorithmMode::SolveFromDepartureStopToArrivalStop,
162            Some(arrival_stop_id),
163            None,
164        )
165    }
166
167    pub fn solve_from_departure_stop_to_reachable_arrival_stops(time_limit: NaiveDateTime) -> Self {
168        Self::new(
169            RoutingAlgorithmMode::SolveFromDepartureStopToReachableArrivalStops,
170            None,
171            Some(time_limit),
172        )
173    }
174
175    // Getters/Setters
176
177    pub fn mode(&self) -> RoutingAlgorithmMode {
178        self.mode
179    }
180
181    /// Do not call this function if you are not sure that arrival_stop_id is not None.
182    pub fn arrival_stop_id(&self) -> i32 {
183        self.arrival_stop_id.unwrap()
184    }
185
186    /// Do not call this function if you are not sure that time_limit is not None.
187    pub fn time_limit(&self) -> NaiveDateTime {
188        self.time_limit.unwrap()
189    }
190}
191
192#[derive(Debug, Serialize)]
193pub struct RouteResult {
194    departure_at: NaiveDateTime,
195    arrival_at: NaiveDateTime,
196    sections: Vec<RouteSectionResult>,
197}
198
199impl RouteResult {
200    pub fn new(
201        departure_at: NaiveDateTime,
202        arrival_at: NaiveDateTime,
203        sections: Vec<RouteSectionResult>,
204    ) -> Self {
205        Self {
206            departure_at,
207            arrival_at,
208            sections,
209        }
210    }
211
212    // Getters/Setters
213
214    pub fn arrival_at(&self) -> NaiveDateTime {
215        self.arrival_at
216    }
217
218    pub fn sections(&self) -> &Vec<RouteSectionResult> {
219        &self.sections
220    }
221}
222
223#[derive(Debug, Serialize)]
224pub struct RouteSectionResult {
225    journey_id: Option<i32>,
226    departure_stop_id: i32,
227    departure_stop_lv95_coordinates: Option<Coordinates>,
228    departure_stop_wgs84_coordinates: Option<Coordinates>,
229    arrival_stop_id: i32,
230    arrival_stop_lv95_coordinates: Option<Coordinates>,
231    arrival_stop_wgs84_coordinates: Option<Coordinates>,
232    departure_at: Option<NaiveDateTime>,
233    arrival_at: Option<NaiveDateTime>,
234    duration: Option<i16>,
235}
236
237impl RouteSectionResult {
238    pub fn new(
239        journey_id: Option<i32>,
240        departure_stop_id: i32,
241        departure_stop_lv95_coordinates: Option<Coordinates>,
242        departure_stop_wgs84_coordinates: Option<Coordinates>,
243        arrival_stop_id: i32,
244        arrival_stop_lv95_coordinates: Option<Coordinates>,
245        arrival_stop_wgs84_coordinates: Option<Coordinates>,
246        departure_at: Option<NaiveDateTime>,
247        arrival_at: Option<NaiveDateTime>,
248        duration: Option<i16>,
249    ) -> Self {
250        Self {
251            journey_id,
252            departure_stop_id,
253            departure_stop_lv95_coordinates,
254            departure_stop_wgs84_coordinates,
255            arrival_stop_id,
256            arrival_stop_lv95_coordinates,
257            arrival_stop_wgs84_coordinates,
258            departure_at,
259            arrival_at,
260            duration,
261        }
262    }
263
264    // Getters/Setters
265
266    pub fn departure_stop_id(&self) -> i32 {
267        self.departure_stop_id
268    }
269
270    pub fn departure_at(&self) -> Option<NaiveDateTime> {
271        self.departure_at
272    }
273
274    pub fn arrival_stop_id(&self) -> i32 {
275        self.arrival_stop_id
276    }
277
278    pub fn arrival_stop_lv95_coordinates(&self) -> Option<Coordinates> {
279        self.arrival_stop_lv95_coordinates
280    }
281
282    // pub fn arrival_stop_wgs84_coordinates(&self) -> Option<Coordinates> {
283    //     self.arrival_stop_wgs84_coordinates
284    // }
285
286    pub fn arrival_at(&self) -> Option<NaiveDateTime> {
287        self.arrival_at
288    }
289
290    pub fn duration(&self) -> Option<i16> {
291        self.duration
292    }
293
294    // Functions
295
296    pub fn journey<'a>(&'a self, data_storage: &'a DataStorage) -> Option<&Journey> {
297        self.journey_id.map(|id| {
298            data_storage
299                .journeys()
300                .find(id)
301                .unwrap_or_else(|| panic!("Journey {:?} not found.", id))
302        })
303    }
304
305    pub fn is_walking_trip(&self) -> bool {
306        self.journey_id.is_none()
307    }
308}