supreme_replay_analyzer/
checkpoint_times.rs1use crate::Level;
4use crate::models::{AnalyzeResult, CheckpointTimesComputed};
5use crate::plane_intersection::{LevelPlaneIntersection, get_plane_intersections_with_level_data};
6
7#[must_use]
8pub fn extract_checkpoint_times(
9 analyze_result: &AnalyzeResult,
10 level_name: &str,
11 level_data: &[Level],
12) -> CheckpointTimesComputed {
13 let coords = match &analyze_result.coords {
14 Some(c) => c,
15 None => {
16 return CheckpointTimesComputed {
17 start_computed: None,
18 cp1_computed: None,
19 cp2_computed: None,
20 finish_computed: None,
21 };
22 }
23 };
24
25 let level_plane_intersections =
27 get_plane_intersections_with_level_data(&coords.rows, level_data);
28
29 if level_name == "ForestMediumOrHard" {
31 let forest_medium_intersection = level_plane_intersections
32 .iter()
33 .find(|lpc| lpc.name == "ForestMedium");
34
35 let (start_computed, cp1_computed, cp2_computed, finish_computed) = if let Some(lpc) =
36 forest_medium_intersection
37 {
38 (
39 get_first_valid_intersection_time(lpc, "Start_Point", analyze_result.lag_start_ms),
40 get_first_valid_intersection_time(
41 lpc,
42 "Check_Point_1",
43 analyze_result.lag_start_ms,
44 ),
45 get_first_valid_intersection_time(
46 lpc,
47 "Check_Point_2",
48 analyze_result.lag_start_ms,
49 ),
50 get_first_valid_intersection_time(lpc, "Finish_Point", analyze_result.lag_start_ms),
51 )
52 } else {
53 (None, None, None, None)
54 };
55
56 return CheckpointTimesComputed {
57 start_computed,
58 cp1_computed,
59 cp2_computed,
60 finish_computed,
61 };
62 }
63
64 let level_intersection = level_plane_intersections
66 .iter()
67 .find(|lpc| lpc.name == level_name);
68
69 let (start_computed, cp1_computed, cp2_computed, finish_computed) = if let Some(lpc) =
70 level_intersection
71 {
72 (
73 get_first_valid_intersection_time(lpc, "Start_Point", analyze_result.lag_start_ms),
74 get_first_valid_intersection_time(lpc, "Check_Point_1", analyze_result.lag_start_ms),
75 get_first_valid_intersection_time(lpc, "Check_Point_2", analyze_result.lag_start_ms),
76 get_first_valid_intersection_time(lpc, "Finish_Point", analyze_result.lag_start_ms),
77 )
78 } else {
79 (None, None, None, None)
80 };
81
82 CheckpointTimesComputed {
83 start_computed,
84 cp1_computed,
85 cp2_computed,
86 finish_computed,
87 }
88}
89
90fn get_first_valid_intersection_time(
91 lpc: &LevelPlaneIntersection,
92 object_name: &str,
93 start_lag_ms: f32, ) -> Option<f32> {
95 const PLANE_RADIUS: f32 = 90.5;
96 lpc.intersections
97 .iter()
98 .filter(|c| c.object_name == object_name && c.distance <= PLANE_RADIUS)
99 .map(|c| c.exact_time_with_start_lag_ms - start_lag_ms) .next()
101}