From 65cf266d3657a07b34626d4e9a990d3d2e02880b Mon Sep 17 00:00:00 2001 From: Jean SIMARD Date: Tue, 17 Sep 2024 15:06:18 +0200 Subject: [PATCH] editoast: make intersection as a type Signed-off-by: Jean SIMARD --- editoast/src/views/path/projection.rs | 49 ++++++++++++++++--- .../src/views/train_schedule/projection.rs | 3 +- editoast/src/views/work_schedules.rs | 10 ++-- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/editoast/src/views/path/projection.rs b/editoast/src/views/path/projection.rs index 1ddcce447d4..6b0c439f1a1 100644 --- a/editoast/src/views/path/projection.rs +++ b/editoast/src/views/path/projection.rs @@ -134,7 +134,7 @@ impl<'a> PathProjection<'a> { /// If there is no common track section range, the returned list is empty. /// The positions in the intersection list are guaranteed to increase. In other words `list[n].0 < list[n].1 <= list[n+1].0 < list[n+1].1` /// These positions can then be use in conjunction with [PathProjection::get_location]. - pub fn get_intersections(&self, track_ranges: &[TrackRange]) -> Vec<(u64, u64)> { + pub fn get_intersections(&self, track_ranges: &[TrackRange]) -> Vec { // Handle the length computation in mm let mut next_pos: u64 = 0; let mut current_pos: u64; @@ -206,10 +206,35 @@ impl<'a> PathProjection<'a> { } } +/// Represent the intersection between a track range and a path, relative to the beginning of the path +#[cfg_attr(test, derive(Debug, PartialEq))] +pub struct Intersection { + /// Distance of the beginning of the intersection relative to the beginning of the path + start: u64, + /// Distance of the end of the intersection relative to the beginning of the path + end: u64, +} +impl From<(u64, u64)> for Intersection { + fn from((start, end): (u64, u64)) -> Self { + debug_assert!( + start <= end, + "intersection should have a 'start' ({start}) smaller than 'end' ({end})" + ); + Self { start, end } + } +} +impl Intersection { + pub fn start(&self) -> u64 { + self.start + } + pub fn end(&self) -> u64 { + self.end + } +} struct IntersectionBuilder { start: Option, current: u64, - intersections: Vec<(u64, u64)>, + intersections: Vec, } impl IntersectionBuilder { @@ -224,7 +249,8 @@ impl IntersectionBuilder { fn finish(&mut self) { if let Some(start) = self.start { assert_ne!(start, self.current); - self.intersections.push((start, self.current)); + self.intersections + .push(Intersection::from((start, self.current))); } self.start = None; } @@ -396,7 +422,7 @@ mod tests { ]; let boundaries = projection.get_intersections(&track_ranges); - let expected: Vec<(u64, u64)> = vec![(50, 730)]; + let expected: Vec = vec![Intersection::from((50, 730))]; assert_eq!(boundaries, expected); } @@ -421,7 +447,10 @@ mod tests { ]; let boundaries = projection.get_intersections(&track_ranges); - let expected: Vec<(u64, u64)> = vec![(100, 350), (350, 420)]; + let expected: Vec = vec![ + Intersection::from((100, 350)), + Intersection::from((350, 420)), + ]; assert_eq!(boundaries, expected); } @@ -447,7 +476,11 @@ mod tests { ]; let boundaries = projection.get_intersections(&track_ranges); - let expected: Vec<(u64, u64)> = vec![(50, 300), (400, 450), (550, 620)]; + let expected: Vec = vec![ + Intersection::from((50, 300)), + Intersection::from((400, 450)), + Intersection::from((550, 620)), + ]; assert_eq!(boundaries, expected); } @@ -461,7 +494,7 @@ mod tests { let boundaries = projection.get_intersections(&track_ranges); - let expected: Vec<(u64, u64)> = vec![]; + let expected: Vec = vec![]; assert_eq!(boundaries, expected); } @@ -474,7 +507,7 @@ mod tests { let boundaries = projection.get_intersections(&track_ranges); - let expected: Vec<(u64, u64)> = vec![]; + let expected: Vec = vec![]; assert_eq!(boundaries, expected); } } diff --git a/editoast/src/views/train_schedule/projection.rs b/editoast/src/views/train_schedule/projection.rs index fb7e1405a5f..4fbcc8c5222 100644 --- a/editoast/src/views/train_schedule/projection.rs +++ b/editoast/src/views/train_schedule/projection.rs @@ -399,7 +399,8 @@ fn compute_space_time_curves( let mut space_time_curves = vec![]; for intersection in intersections { - let (start, end) = intersection; + let start = intersection.start(); + let end = intersection.end(); let start_index = find_index_upper(positions, start); let end_index = find_index_upper(positions, end); diff --git a/editoast/src/views/work_schedules.rs b/editoast/src/views/work_schedules.rs index e8917ca9765..b8dd4550079 100644 --- a/editoast/src/views/work_schedules.rs +++ b/editoast/src/views/work_schedules.rs @@ -21,6 +21,7 @@ use crate::models::prelude::*; use crate::models::work_schedules::WorkSchedule; use crate::models::work_schedules::WorkScheduleGroup; use crate::models::work_schedules::WorkScheduleType; +use crate::views::path::projection::Intersection; use crate::views::path::projection::PathProjection; use crate::views::AuthorizationError; use crate::views::AuthorizerExt; @@ -202,7 +203,7 @@ struct WorkScheduleProjection { /// a list of intervals `(a, b)` that represent the projections of the work schedule track ranges: /// - `a` is the distance from the beginning of the path to the beginning of the track range /// - `b` is the distance from the beginning of the path to the end of the track range - pub path_position_ranges: Vec<(u64, u64)>, + pub path_position_ranges: Vec, } #[utoipa::path( @@ -258,6 +259,7 @@ async fn project_path( // project this work_schedule on the path (ws, path_projection.get_intersections(&path_track_ranges)) }) + .map(Intersection::from) .filter_map(|(ws, path_position_ranges)| { if path_position_ranges.is_empty() { None @@ -414,13 +416,13 @@ pub mod test { vec![TrackRange::new("d", 50.0, 100.0)], ], vec![ - vec![(0, 100000), (250000, 300000)], - vec![(350000, 400000)] + vec![Intersection::from((0, 100000)), Intersection::from((250000, 300000))], + vec![Intersection::from((350000, 400000))] ], )] async fn work_schedule_project_path_on_ws_group( #[case] work_schedule_track_ranges: Vec>, - #[case] expected_path_position_ranges: Vec>, + #[case] expected_path_position_ranges: Vec>, ) { // GIVEN let app = TestAppBuilder::default_app();