diff --git a/src/legs.rs b/src/legs.rs index 3aff684..b56b414 100644 --- a/src/legs.rs +++ b/src/legs.rs @@ -42,27 +42,35 @@ impl Leg { } } +fn grounded_heuristic(prev_position: &Position, position: &Position) -> bool { + let is_flying = matches!( + (&prev_position, &position), + (Position::Flying { .. }, Position::Flying { .. }) + | (Position::Flying { .. }, Position::Grounded { .. }) + ); + let lost_close_to_ground = position.datetime() - prev_position.datetime() + > time::Duration::minutes(5) + && (position.altitude() < 10000.0 || prev_position.altitude() < 10000.0); + + // lost signal for more than 10h => assume it landed somewhere + let lost_somewhere = position.datetime() - prev_position.datetime() > time::Duration::hours(10); + + is_flying && (lost_close_to_ground || lost_somewhere) +} + /// Implementation of the definition of landed in [M-4](../methodology.md). fn landed(prev_position: &Position, position: &Position) -> bool { matches!( (&prev_position, &position), (Position::Flying { .. }, Position::Grounded { .. }) - ) || (matches!( - (&prev_position, &position), - (Position::Flying { .. }, Position::Flying { .. }) - ) && position.datetime() - prev_position.datetime() > time::Duration::minutes(5) - && (position.altitude() < 10000.0 || prev_position.altitude() < 10000.0)) + ) || grounded_heuristic(prev_position, position) } fn is_grounded(prev_position: &Position, position: &Position) -> bool { matches!( (&prev_position, &position), (Position::Grounded { .. }, Position::Grounded { .. }) - ) || (matches!( - (&prev_position, &position), - (Position::Flying { .. }, Position::Flying { .. }) - ) && position.datetime() - prev_position.datetime() > time::Duration::minutes(5) - && (position.altitude() < 10000.0 || prev_position.altitude() < 10000.0)) + ) || grounded_heuristic(prev_position, position) } /// Returns a set of [`Leg`]s from a sequence of [`Position`]s. diff --git a/tests/it/main.rs b/tests/it/main.rs index eb548cf..df22c2e 100644 --- a/tests/it/main.rs +++ b/tests/it/main.rs @@ -103,3 +103,28 @@ async fn case_459257_2023_12_17() -> Result<(), Box> { assert_eq!(legs.len(), 4); Ok(()) } + +/// Case of losing signal for 2 days mid flight. +/// https://globe.adsbexchange.com/?icao=45dd84&lat=9.613&lon=22.035&zoom=3.8&showTrace=2023-12-08 +#[tokio::test] +async fn case_45dd84_2023_12_06() -> Result<(), Box> { + let legs = legs(date!(2023 - 12 - 06), date!(2023 - 12 - 09), "45dd84", None).await?; + assert_eq!(legs.len(), 3); + let day = 24.0 * 60.0 * 60.0; + assert!(legs[0].duration().as_seconds_f32() < day); + assert!(legs[1].duration().as_seconds_f32() < day); + assert!(legs[2].duration().as_seconds_f32() < day); + Ok(()) +} + +#[tokio::test] +async fn case_45c824_2023_12_12() -> Result<(), Box> { + let legs = legs(date!(2023 - 12 - 12), date!(2023 - 12 - 16), "45c824", None).await?; + + assert_eq!(legs.len(), 3); + let day = 24.0 * 60.0 * 60.0; + assert!(legs[0].duration().as_seconds_f32() < day); + assert!(legs[1].duration().as_seconds_f32() < day); + assert!(legs[2].duration().as_seconds_f32() < day); + Ok(()) +}