use super::*;
fn rigid_body(position: glam::Vec3, velocity: glam::Vec3) -> boxcars::RigidBody {
boxcars::RigidBody {
sleeping: false,
location: glam_to_vec(&position),
rotation: boxcars::Quaternion {
x: 0.0,
y: 0.0,
z: 0.0,
w: 1.0,
},
linear_velocity: Some(glam_to_vec(&velocity)),
angular_velocity: Some(glam_to_vec(&glam::Vec3::ZERO)),
}
}
fn ball(z: f32, velocity: glam::Vec3) -> BallFrameState {
BallFrameState::Present(BallSample {
rigid_body: rigid_body(glam::Vec3::new(0.0, 0.0, z), velocity),
})
}
fn frame(frame_number: usize) -> FrameInfo {
FrameInfo {
frame_number,
time: frame_number as f32 * 0.1,
dt: 0.1,
seconds_remaining: None,
}
}
fn touch(frame_number: usize, player_id: PlayerId) -> TouchEvent {
TouchEvent {
time: frame_number as f32 * 0.1,
frame: frame_number,
team_is_team_0: true,
player: Some(player_id),
closest_approach_distance: Some(0.0),
}
}
#[test]
fn records_half_volley_touch_after_floor_bounce() {
let player_id = boxcars::RemoteId::Steam(1);
let mut calculator = HalfVolleyCalculator::new();
calculator
.update(
&frame(1),
&ball(BALL_RADIUS_Z + 200.0, glam::Vec3::new(0.0, 0.0, -900.0)),
&TouchState::default(),
true,
)
.unwrap();
calculator
.update(
&frame(2),
&ball(BALL_RADIUS_Z + 5.0, glam::Vec3::new(0.0, 0.0, 400.0)),
&TouchState::default(),
true,
)
.unwrap();
calculator
.update(
&frame(4),
&ball(BALL_RADIUS_Z + 80.0, glam::Vec3::new(0.0, 1600.0, 100.0)),
&TouchState {
touch_events: vec![touch(4, player_id.clone())],
..TouchState::default()
},
true,
)
.unwrap();
let event = calculator.events().first().expect("half-volley event");
assert_eq!(event.player, player_id.clone());
assert_eq!(event.bounce_frame, 2);
assert_eq!(event.frame, 4);
assert_eq!(calculator.team_zero_stats().count, 1);
assert_eq!(calculator.player_stats().get(&player_id).unwrap().count, 1);
}
#[test]
fn rejects_slow_post_bounce_touches() {
let player_id = boxcars::RemoteId::Steam(1);
let mut calculator = HalfVolleyCalculator::new();
calculator
.update(
&frame(1),
&ball(BALL_RADIUS_Z + 200.0, glam::Vec3::new(0.0, 0.0, -900.0)),
&TouchState::default(),
true,
)
.unwrap();
calculator
.update(
&frame(2),
&ball(BALL_RADIUS_Z + 5.0, glam::Vec3::new(0.0, 0.0, 400.0)),
&TouchState::default(),
true,
)
.unwrap();
calculator
.update(
&frame(3),
&ball(BALL_RADIUS_Z + 60.0, glam::Vec3::new(0.0, 800.0, 50.0)),
&TouchState {
touch_events: vec![touch(3, player_id)],
..TouchState::default()
},
true,
)
.unwrap();
assert!(calculator.events().is_empty());
}
#[test]
fn rejects_stale_bounces() {
let player_id = boxcars::RemoteId::Steam(1);
let mut calculator = HalfVolleyCalculator::with_config(HalfVolleyCalculatorConfig {
max_bounce_to_touch_seconds: 0.2,
..HalfVolleyCalculatorConfig::default()
});
calculator
.update(
&frame(1),
&ball(BALL_RADIUS_Z + 200.0, glam::Vec3::new(0.0, 0.0, -900.0)),
&TouchState::default(),
true,
)
.unwrap();
calculator
.update(
&frame(2),
&ball(BALL_RADIUS_Z + 5.0, glam::Vec3::new(0.0, 0.0, 400.0)),
&TouchState::default(),
true,
)
.unwrap();
calculator
.update(
&frame(6),
&ball(BALL_RADIUS_Z + 60.0, glam::Vec3::new(0.0, 1600.0, 50.0)),
&TouchState {
touch_events: vec![touch(6, player_id)],
..TouchState::default()
},
true,
)
.unwrap();
assert!(calculator.events().is_empty());
}