nyx_space/od/simulator/
scheduler.rsuse crate::io::{
duration_from_str, duration_to_str, maybe_duration_from_str, maybe_duration_to_str,
};
pub use crate::State;
use hifitime::{Duration, Unit};
use serde::Deserialize;
use serde_derive::Serialize;
use std::fmt::Debug;
use typed_builder::TypedBuilder;
#[cfg(feature = "python")]
use pyo3::prelude::*;
#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Serialize)]
#[cfg_attr(feature = "python", pyclass)]
#[cfg_attr(feature = "python", pyo3(module = "nyx_space.orbit_determination"))]
pub enum Handoff {
Eager,
Greedy,
Overlap,
}
impl Default for Handoff {
fn default() -> Self {
Self::Eager
}
}
#[derive(Copy, Clone, Debug, Default, Deserialize, PartialEq, Serialize, TypedBuilder)]
#[builder(doc)]
#[cfg_attr(feature = "python", pyclass)]
#[cfg_attr(feature = "python", pyo3(module = "nyx_space.orbit_determination"))]
pub struct Scheduler {
#[builder(default)]
pub handoff: Handoff,
#[builder(default)]
pub cadence: Cadence,
#[builder(default = 10)]
pub min_samples: u32,
#[builder(default = Some(Unit::Second * 1.0), setter(strip_option))]
#[serde(
serialize_with = "maybe_duration_to_str",
deserialize_with = "maybe_duration_from_str"
)]
pub sample_alignment: Option<Duration>,
}
#[derive(Copy, Clone, Deserialize, PartialEq, Serialize)]
pub enum Cadence {
Continuous,
Intermittent {
#[serde(
serialize_with = "duration_to_str",
deserialize_with = "duration_from_str"
)]
on: Duration,
#[serde(
serialize_with = "duration_to_str",
deserialize_with = "duration_from_str"
)]
off: Duration,
},
}
impl Default for Cadence {
fn default() -> Self {
Self::Continuous
}
}
impl Debug for Cadence {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Continuous => write!(f, "Continuous"),
Self::Intermittent { on, off } => f
.debug_struct("Intermittent")
.field("on", &format!("{on}"))
.field("off", &format!("{off}"))
.finish(),
}
}
}
#[cfg(test)]
mod scheduler_ut {
use process::simulator::scheduler::Handoff;
use crate::od::prelude::*;
use super::Scheduler;
#[test]
fn serde_cadence() {
use hifitime::TimeUnits;
use serde_yml;
let cont: Cadence = serde_yml::from_str("!Continuous").unwrap();
assert_eq!(cont, Cadence::Continuous);
let int: Cadence =
serde_yml::from_str("!Intermittent {on: 1 h 35 min, off: 15 h 02 min 3 s}").unwrap();
assert_eq!(
int,
Cadence::Intermittent {
on: 1.hours() + 35.0.minutes(),
off: 15.hours() + 2.minutes() + 3.seconds()
}
);
assert_eq!(
format!("{int:?}"),
r#"Intermittent { on: "1 h 35 min", off: "15 h 2 min 3 s" }"#
);
let serialized = serde_yml::to_string(&int).unwrap();
let deserd: Cadence = serde_yml::from_str(&serialized).unwrap();
assert_eq!(deserd, int);
}
#[test]
fn api_and_serde_scheduler() {
use hifitime::TimeUnits;
use serde_yml;
let scheduler = Scheduler::default();
let serialized = serde_yml::to_string(&scheduler).unwrap();
assert_eq!(
serialized,
"handoff: Eager\ncadence: Continuous\nmin_samples: 0\nsample_alignment: null\n"
);
let deserd: Scheduler = serde_yml::from_str(&serialized).unwrap();
assert_eq!(deserd, scheduler);
let scheduler = Scheduler::builder()
.handoff(Handoff::Eager)
.cadence(Cadence::Intermittent {
on: 0.2.hours(),
off: 17.hours() + 5.minutes(),
})
.build();
let serialized = serde_yml::to_string(&scheduler).unwrap();
assert_eq!(
serialized,
"handoff: Eager\ncadence: !Intermittent\n 'on': '12 min'\n 'off': '17 h 5 min'\nmin_samples: 10\nsample_alignment: '1 s'\n"
);
let deserd: Scheduler = serde_yml::from_str(&serialized).unwrap();
assert_eq!(deserd, scheduler);
}
#[test]
fn defaults() {
let sched = Scheduler::default();
assert_eq!(sched.cadence, Cadence::Continuous);
assert_eq!(sched.handoff, Handoff::Eager);
}
}