mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2026-10-10 07:36:29 +00:00
handle corrupt time data
This commit is contained in:
1 parent
f0851086c0
commit
e8c4eb92f9
2 files changed
+47
-3
No files matched your search
@@ -283,13 +283,18 @@ pub struct GlobalStatistics {
|
||||
}
|
||||
|
||||
impl GlobalStatistics {
|
||||
/// Average speed over the total time, unknown if that is not a positive duration (for
|
||||
/// example a range with a single timestamp, or timestamps going backwards).
|
||||
pub fn total_speed(&self) -> Option<f64> {
|
||||
self.total_time.map(|t| speed(self.total_distance, t))
|
||||
self.total_time
|
||||
.filter(|t| *t > 0)
|
||||
.map(|t| speed(self.total_distance, t))
|
||||
}
|
||||
|
||||
/// Average speed over the moving time, unknown if there is no moving time.
|
||||
pub fn moving_speed(&self) -> Option<f64> {
|
||||
self.moving_distance
|
||||
.zip(self.moving_time)
|
||||
.zip(self.moving_time.filter(|t| *t > 0))
|
||||
.map(|(d, t)| speed(d, t))
|
||||
}
|
||||
|
||||
|
||||
@@ -195,7 +195,8 @@ impl StatisticsBuffer {
|
||||
}
|
||||
|
||||
let delta = |values: &[f64]| values[end] - values[start];
|
||||
let delta_time = |values: &[i64]| values[end] - values[start];
|
||||
// the total time is the span of the timestamps, which is negative where they go backwards
|
||||
let delta_time = |values: &[i64]| (values[end] - values[start]).max(0);
|
||||
let time = |i: usize| {
|
||||
let time = self.time.as_ref()?[i];
|
||||
(time != NO_TIME).then_some(time)
|
||||
@@ -559,6 +560,44 @@ mod tests {
|
||||
assert_eq!(slice.end_time, global.end_time);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_slices_of_corrupt_timestamps_are_never_negative_nor_infinite() {
|
||||
let (mut segment, _) = computed("data/with_time.gpx");
|
||||
let n = segment.len();
|
||||
assert!(n > 40);
|
||||
// timestamps that go back, then forward, and some that are missing
|
||||
let times: Vec<_> = segment.iter().map(|p| p.time.unwrap()).collect();
|
||||
segment.update_all(|i, pt| {
|
||||
pt.time = match i {
|
||||
10..=19 => Some(times[29 - i]),
|
||||
20..=24 => None,
|
||||
25..=29 => Some(times[0] - 1_000 * i as i64),
|
||||
_ => pt.time,
|
||||
};
|
||||
});
|
||||
let stats = Statistics::compute(&segment);
|
||||
let mut buffer = StatisticsBuffer::default();
|
||||
buffer.update(&[(&segment, &stats)]);
|
||||
|
||||
for start in 0..n {
|
||||
for end in start..n {
|
||||
let slice = buffer.slice(start, end).unwrap();
|
||||
for time in [slice.total_time, slice.moving_time].into_iter().flatten() {
|
||||
assert!(time >= 0, "time of {start}..={end}");
|
||||
}
|
||||
for speed in [slice.total_speed(), slice.moving_speed()]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
{
|
||||
assert!(
|
||||
speed.is_finite() && speed >= 0.0,
|
||||
"speed of {start}..={end}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_slice_of_a_range() {
|
||||
let (segment, s) = computed("data/with_time.gpx");
|
||||
|
||||
Reference in new issue
Block a user