Skip to main content

pleiades_data/
thresholds.rs

1//! Published per-body-class accuracy ceilings and size/latency budgets (the
2//! public contract). The hold-out gate (accuracy_baseline.rs) asserts measured
3//! <= ceiling; the tight golden drift test stays as the regression catcher.
4
5use pleiades_backend::CelestialBody;
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8pub enum BodyClass {
9    Luminary,
10    InnerPlanet,
11    OuterPlanet,
12    Asteroid,
13}
14
15pub fn body_class(body: &CelestialBody) -> BodyClass {
16    match body {
17        CelestialBody::Sun | CelestialBody::Moon => BodyClass::Luminary,
18        CelestialBody::Mercury | CelestialBody::Venus | CelestialBody::Mars => {
19            BodyClass::InnerPlanet
20        }
21        CelestialBody::Jupiter
22        | CelestialBody::Saturn
23        | CelestialBody::Uranus
24        | CelestialBody::Neptune
25        | CelestialBody::Pluto => BodyClass::OuterPlanet,
26        _ => BodyClass::Asteroid,
27    }
28}
29
30#[derive(Clone, Copy, Debug)]
31pub struct AccuracyCeiling {
32    pub lon_arcsec: f64,
33    pub lat_arcsec: f64,
34    pub dist_km: f64,
35    pub lon_speed_arcsec_per_day: f64,
36    pub lat_speed_arcsec_per_day: f64,
37    pub radial_speed_au_per_day: f64,
38}
39
40/// Finalized speed and distance ceilings (Task 11, 2026-06-20).
41///
42/// Speed ceilings are set to round numbers ≥ ~10× the measured maxima from the
43/// committed packaged artifact baseline:
44///
45/// | class           | measured lon_speed | measured lat_speed | measured dist_km |
46/// |-----------------|--------------------|--------------------|------------------|
47/// | Luminary/Inner  | 0.0303 arcsec/day  | 0.0231 arcsec/day  | 0.654 km (Venus) |
48/// | Outer           | 0.0013 arcsec/day  | 0.0013 arcsec/day  | 54.828 km (Uranus)|
49///
50/// Chosen ceilings:
51/// - Luminary/Inner: lon/lat speed → 0.5 arcsec/day (~16× headroom on Moon's 0.0303);
52///   dist_km → 50 km (~76× headroom on Venus's 0.654 km).
53/// - Outer: lon/lat speed → 0.05 arcsec/day (~38× headroom on worst 0.0013);
54///   dist_km → 1_000 km (~18× headroom on Uranus's 54.828 km).
55/// - Radial speed: all bodies show < 1e-7 AU/day measured; ceiling 1e-4 AU/day gives
56///   >1000× headroom; kept tighter than the original placeholder (1e-3) to signal intent.
57pub fn accuracy_ceiling(body: &CelestialBody) -> AccuracyCeiling {
58    match body_class(body) {
59        BodyClass::Luminary | BodyClass::InnerPlanet => AccuracyCeiling {
60            lon_arcsec: 1.0,
61            lat_arcsec: 1.0,
62            dist_km: 50.0,
63            lon_speed_arcsec_per_day: 0.5,
64            lat_speed_arcsec_per_day: 0.5,
65            radial_speed_au_per_day: 1.0e-4,
66        },
67        BodyClass::OuterPlanet => AccuracyCeiling {
68            lon_arcsec: 5.0,
69            lat_arcsec: 5.0,
70            dist_km: 1_000.0,
71            lon_speed_arcsec_per_day: 0.05,
72            lat_speed_arcsec_per_day: 0.05,
73            radial_speed_au_per_day: 1.0e-4,
74        },
75        BodyClass::Asteroid => AccuracyCeiling {
76            lon_arcsec: 30.0,
77            lat_arcsec: 30.0,
78            dist_km: 5_000_000.0,
79            lon_speed_arcsec_per_day: 120.0,
80            lat_speed_arcsec_per_day: 120.0,
81            radial_speed_au_per_day: 1.0e-2,
82        },
83    }
84}
85
86#[derive(Clone, Copy, Debug)]
87pub struct ArtifactBudgets {
88    pub max_encoded_bytes: usize,
89    pub decode_latency_target_ms: f64,
90    pub single_lookup_target_ms: f64,
91    pub batch_throughput_target_per_s: f64,
92    pub chart_workload_target_ms: f64,
93}
94
95pub const PACKAGED_BUDGETS: ArtifactBudgets = ArtifactBudgets {
96    max_encoded_bytes: 12_000_000,   // ~10.0 MB measured + headroom
97    decode_latency_target_ms: 400.0, // ~260 ms measured
98    single_lookup_target_ms: 6.0,    // ~3.3 ms measured
99    batch_throughput_target_per_s: 1_000.0,
100    chart_workload_target_ms: 50.0,
101};
102
103#[cfg(test)]
104mod tests {
105    use super::*;
106    use pleiades_backend::CelestialBody;
107
108    #[test]
109    fn classes_map_bodies_correctly() {
110        assert_eq!(body_class(&CelestialBody::Sun), BodyClass::Luminary);
111        assert_eq!(body_class(&CelestialBody::Moon), BodyClass::Luminary);
112        assert_eq!(body_class(&CelestialBody::Mercury), BodyClass::InnerPlanet);
113        assert_eq!(body_class(&CelestialBody::Pluto), BodyClass::OuterPlanet);
114    }
115
116    #[test]
117    fn outer_planets_have_looser_longitude_ceiling_than_inner() {
118        assert!(
119            accuracy_ceiling(&CelestialBody::Uranus).lon_arcsec
120                > accuracy_ceiling(&CelestialBody::Mercury).lon_arcsec
121        );
122    }
123
124    #[test]
125    fn size_budget_exceeds_current_artifact() {
126        // current ~10 MB; budget has headroom but is finite. Bind to a local so
127        // the bounds check is a runtime assertion over the published budget
128        // rather than a const-folded tautology (clippy::assertions_on_constants).
129        let max_encoded_bytes = PACKAGED_BUDGETS.max_encoded_bytes;
130        assert!(max_encoded_bytes >= 10_000_000);
131        assert!(max_encoded_bytes <= 16_000_000);
132    }
133}