1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
use super::{track_branch, track_current_run, track_personal_best_run, Prediction};
use crate::{Segment, TimeSpan, TimingMethod};
fn populate_prediction(
predecessor: usize,
target_prediction: &mut Option<Prediction>,
predicted_time: Option<TimeSpan>,
) {
if let Some(predicted_time) = predicted_time {
if target_prediction.map_or(true, |p| predicted_time > p.time) {
*target_prediction = Some(Prediction {
time: predicted_time,
predecessor,
});
}
}
}
fn populate_predictions(
segments: &[Segment],
current_prediction: Option<Prediction>,
segment_index: usize,
predictions: &mut [Option<Prediction>],
use_current_run: bool,
method: TimingMethod,
) {
if let Some(Prediction {
time: current_time, ..
}) = current_prediction
{
populate_prediction(
segment_index,
&mut predictions[segment_index + 1],
segments[segment_index].best_segment_time()[method].map(|t| t + current_time),
);
for &(segment_history_index, _) in segments[segment_index].segment_history().iter() {
let should_track_branch = catch! {
segments[segment_index.checked_sub(1)?]
.segment_history()
.get(segment_history_index)?[method]
.is_some()
}
.unwrap_or(true);
if should_track_branch {
let (index, time) = track_branch(
segments,
Some(current_time),
segment_index,
segment_history_index,
method,
);
populate_prediction(segment_index, &mut predictions[index], time[method]);
}
}
if use_current_run {
let (index, time) =
track_current_run(segments, Some(current_time), segment_index, method);
populate_prediction(segment_index, &mut predictions[index], time[method]);
}
let (index, time) =
track_personal_best_run(segments, Some(current_time), segment_index, method);
populate_prediction(segment_index, &mut predictions[index], time[method]);
}
}
#[allow(clippy::needless_range_loop)]
pub fn calculate(
segments: &[Segment],
predictions: &mut [Option<Prediction>],
use_current_run: bool,
method: TimingMethod,
) -> Option<TimeSpan> {
predictions[0] = Some(Prediction::default());
let end_index = segments.len();
for segment_index in 0..end_index {
populate_predictions(
segments,
predictions[segment_index],
segment_index,
predictions,
use_current_run,
method,
);
}
Some(predictions[end_index]?.time)
}