use super::*;
#[test]
fn test_empty_tracker_returns_zero() {
let tracker = VelocityTracker1D::new();
assert_eq!(tracker.calculate_velocity(), 0.0);
}
#[test]
fn test_single_point_returns_zero() {
let mut tracker = VelocityTracker1D::new();
tracker.add_data_point(0, 100.0);
assert_eq!(tracker.calculate_velocity(), 0.0);
}
#[test]
fn test_constant_velocity() {
let mut tracker = VelocityTracker1D::new();
tracker.add_data_point(0, 0.0);
tracker.add_data_point(10, 100.0);
tracker.add_data_point(20, 200.0);
tracker.add_data_point(30, 300.0);
let velocity = tracker.calculate_velocity();
assert!(
(velocity - 10000.0).abs() < 1000.0,
"Expected ~10000, got {velocity}"
);
}
#[test]
fn test_reset() {
let mut tracker = VelocityTracker1D::new();
tracker.add_data_point(0, 0.0);
tracker.add_data_point(10, 100.0);
tracker.reset();
assert_eq!(tracker.calculate_velocity(), 0.0);
}
#[test]
fn test_negative_velocity() {
let mut tracker = VelocityTracker1D::new();
tracker.add_data_point(0, 300.0);
tracker.add_data_point(10, 200.0);
tracker.add_data_point(20, 100.0);
let velocity = tracker.calculate_velocity();
assert!(velocity < 0.0, "Expected negative velocity, got {velocity}");
}
#[test]
fn test_velocity_capped() {
let mut tracker = VelocityTracker1D::new();
tracker.add_data_point(0, 0.0);
tracker.add_data_point(1, 10_000.0);
tracker.add_data_point(2, 20_000.0);
let velocity = tracker.calculate_velocity_with_max(8_000.0);
assert_eq!(velocity, 8_000.0);
tracker.reset();
tracker.add_data_point(0, 20_000.0);
tracker.add_data_point(1, 10_000.0);
tracker.add_data_point(2, 0.0);
let velocity = tracker.calculate_velocity_with_max(8_000.0);
assert_eq!(velocity, -8_000.0);
}
#[test]
fn test_old_samples_ignored() {
let mut tracker = VelocityTracker1D::new();
tracker.add_data_point(0, 0.0);
tracker.add_data_point(150, 100.0);
tracker.add_data_point(160, 200.0);
tracker.add_data_point(170, 300.0);
let velocity = tracker.calculate_velocity();
assert!(
velocity.abs() > 0.0,
"Should calculate velocity from recent samples"
);
}
#[test]
fn test_gap_over_stopped_threshold_returns_zero() {
let mut tracker = VelocityTracker1D::new();
tracker.add_data_point(0, 0.0);
tracker.add_data_point(ASSUME_STOPPED_MS + 1, 100.0);
let velocity = tracker.calculate_velocity();
assert_eq!(velocity, 0.0);
}
fn velocity_of(positions: &[f32]) -> f32 {
let mut tracker = VelocityTracker1D::new();
for (index, position) in positions.iter().enumerate() {
tracker.add_data_point(index as i64 * 8, *position);
}
tracker.calculate_velocity()
}
#[test]
fn a_small_move_back_at_the_end_keeps_the_fling_s_direction() {
let velocity = velocity_of(&[0.0, 8.0, 16.0, 24.0, 32.0, 24.0]);
assert!((velocity - 900.0).abs() < 1.0, "{velocity}");
let velocity = velocity_of(&[0.0, 2.0, 4.0, 6.0, 8.0, 2.0]);
assert!((velocity - 200.0).abs() < 1.0, "{velocity}");
}
#[test]
fn a_pointer_that_stops_in_its_last_sample_keeps_most_of_its_speed() {
let moving = velocity_of(&[0.0, 8.0, 16.0, 24.0, 32.0, 40.0]);
let stopped = velocity_of(&[0.0, 8.0, 16.0, 24.0, 32.0, 32.0]);
assert!((moving - 1_000.0).abs() < 1.0, "{moving}");
assert!((stopped - 950.0).abs() < 1.0, "{stopped}");
}
#[test]
fn motion_before_a_rest_is_no_part_of_the_velocity() {
let mut tracker = VelocityTracker1D::new();
for (time, position) in [(0, 0.0), (8, 80.0), (16, 160.0), (216, 160.0), (224, 161.0)] {
tracker.add_data_point(time, position);
}
let velocity = tracker.calculate_velocity();
assert!((velocity - 6.25).abs() < 0.1, "{velocity}");
}