pleiades_data/coverage/
generation_spec.rs1use pleiades_backend::CelestialBody;
8
9pub const FITTING_OVERSAMPLE: usize = 3;
11
12pub fn fitting_segment_span_days(body: &CelestialBody) -> f64 {
14 match body {
15 CelestialBody::Moon => 4.0,
16 CelestialBody::Mercury => 8.0,
17 CelestialBody::Venus | CelestialBody::Sun => 16.0,
18 CelestialBody::Mars => 32.0,
19 CelestialBody::Jupiter => 128.0,
20 CelestialBody::Saturn => 256.0,
21 CelestialBody::Uranus | CelestialBody::Neptune | CelestialBody::Pluto => 512.0,
22 _ => 16.0,
25 }
26}
27
28pub fn fitting_degree(_body: &CelestialBody) -> usize {
30 8
31}
32
33pub fn fitting_within_span_sample_count(body: &CelestialBody) -> usize {
35 (fitting_degree(body) + 1) * FITTING_OVERSAMPLE
36}
37
38pub fn fitting_segment_boundaries(
40 body: &CelestialBody,
41 start_jd: f64,
42 end_jd: f64,
43) -> Vec<(f64, f64)> {
44 let span = fitting_segment_span_days(body);
45 let mut spans = Vec::new();
46 let mut t0 = start_jd;
47 while t0 < end_jd {
48 let t1 = (t0 + span).min(end_jd);
49 if t1 > t0 {
50 spans.push((t0, t1));
51 }
52 t0 = t1;
53 }
54 spans
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60 use pleiades_backend::CelestialBody;
61
62 #[test]
63 fn spans_match_documented_defaults() {
64 assert_eq!(fitting_segment_span_days(&CelestialBody::Moon), 4.0);
65 assert_eq!(fitting_segment_span_days(&CelestialBody::Mercury), 8.0);
66 assert_eq!(fitting_segment_span_days(&CelestialBody::Venus), 16.0);
67 assert_eq!(fitting_segment_span_days(&CelestialBody::Sun), 16.0);
68 assert_eq!(fitting_segment_span_days(&CelestialBody::Mars), 32.0);
69 assert_eq!(fitting_segment_span_days(&CelestialBody::Jupiter), 128.0);
70 assert_eq!(fitting_segment_span_days(&CelestialBody::Saturn), 256.0);
71 assert_eq!(fitting_segment_span_days(&CelestialBody::Uranus), 512.0);
72 assert_eq!(fitting_segment_span_days(&CelestialBody::Neptune), 512.0);
73 assert_eq!(fitting_segment_span_days(&CelestialBody::Pluto), 512.0);
74 }
75
76 #[test]
77 fn within_span_sample_count_oversamples_degree() {
78 let n = fitting_within_span_sample_count(&CelestialBody::Moon);
79 assert_eq!(
80 n,
81 (fitting_degree(&CelestialBody::Moon) + 1) * FITTING_OVERSAMPLE
82 );
83 assert!(
84 n > fitting_degree(&CelestialBody::Moon) + 1,
85 "must oversample"
86 );
87 }
88
89 #[test]
90 fn boundaries_tile_the_window_without_gaps_or_overlap() {
91 let spans = fitting_segment_boundaries(&CelestialBody::Jupiter, 1000.0, 1500.0);
92 assert_eq!(spans.first().unwrap().0, 1000.0);
93 assert_eq!(spans.last().unwrap().1, 1500.0);
94 for pair in spans.windows(2) {
95 assert_eq!(pair[0].1, pair[1].0, "spans must be contiguous");
96 }
97 for (t0, t1) in &spans {
98 assert!(t1 > t0, "each span is non-empty");
99 }
100 }
101}