nyx_space/od/simulator/
scheduler.rs1use crate::io::{
20 duration_from_str, duration_to_str, maybe_duration_from_str, maybe_duration_to_str,
21};
22pub use crate::State;
23use hifitime::{Duration, Unit};
24use serde::Deserialize;
25use serde_derive::Serialize;
26use std::fmt::Debug;
27use typed_builder::TypedBuilder;
28
29#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Serialize, Default)]
31pub enum Handoff {
32 #[default]
34 Eager,
35 Greedy,
37 Overlap,
39}
40
41#[derive(Copy, Clone, Debug, Default, Deserialize, PartialEq, Serialize, TypedBuilder)]
43#[builder(doc)]
44pub struct Scheduler {
45 #[builder(default)]
47 pub handoff: Handoff,
48 #[builder(default)]
50 pub cadence: Cadence,
51 #[builder(default = 10)]
53 pub min_samples: u32,
54 #[builder(default = Some(Unit::Second * 1.0), setter(strip_option))]
57 #[serde(
58 serialize_with = "maybe_duration_to_str",
59 deserialize_with = "maybe_duration_from_str"
60 )]
61 pub sample_alignment: Option<Duration>,
62}
63
64#[derive(Copy, Clone, Deserialize, PartialEq, Serialize, Default)]
66pub enum Cadence {
67 #[default]
68 Continuous,
69 Intermittent {
71 #[serde(
72 serialize_with = "duration_to_str",
73 deserialize_with = "duration_from_str"
74 )]
75 on: Duration,
76 #[serde(
77 serialize_with = "duration_to_str",
78 deserialize_with = "duration_from_str"
79 )]
80 off: Duration,
81 },
82}
83
84impl Debug for Cadence {
85 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86 match self {
87 Self::Continuous => write!(f, "Continuous"),
88 Self::Intermittent { on, off } => f
89 .debug_struct("Intermittent")
90 .field("on", &format!("{on}"))
91 .field("off", &format!("{off}"))
92 .finish(),
93 }
94 }
95}
96
97#[cfg(test)]
98mod scheduler_ut {
99 use process::simulator::scheduler::Handoff;
100
101 use crate::od::prelude::*;
102
103 use super::Scheduler;
104
105 #[test]
106 fn serde_cadence() {
107 use hifitime::TimeUnits;
108 use serde_yml;
109
110 let cont: Cadence = serde_yml::from_str("!Continuous").unwrap();
111 assert_eq!(cont, Cadence::Continuous);
112
113 let int: Cadence =
114 serde_yml::from_str("!Intermittent {on: 1 h 35 min, off: 15 h 02 min 3 s}").unwrap();
115 assert_eq!(
116 int,
117 Cadence::Intermittent {
118 on: 1.hours() + 35.0.minutes(),
119 off: 15.hours() + 2.minutes() + 3.seconds()
120 }
121 );
122 assert_eq!(
123 format!("{int:?}"),
124 r#"Intermittent { on: "1 h 35 min", off: "15 h 2 min 3 s" }"#
125 );
126
127 let serialized = serde_yml::to_string(&int).unwrap();
128 let deserd: Cadence = serde_yml::from_str(&serialized).unwrap();
129 assert_eq!(deserd, int);
130 }
131
132 #[test]
133 fn api_and_serde_scheduler() {
134 use hifitime::TimeUnits;
135 use serde_yml;
136
137 let scheduler = Scheduler::default();
138 let serialized = serde_yml::to_string(&scheduler).unwrap();
139 assert_eq!(
140 serialized,
141 "handoff: Eager\ncadence: Continuous\nmin_samples: 0\nsample_alignment: null\n"
142 );
143 let deserd: Scheduler = serde_yml::from_str(&serialized).unwrap();
144 assert_eq!(deserd, scheduler);
145
146 let scheduler = Scheduler::builder()
147 .handoff(Handoff::Eager)
148 .cadence(Cadence::Intermittent {
149 on: 0.2.hours(),
150 off: 17.hours() + 5.minutes(),
151 })
152 .build();
153
154 let serialized = serde_yml::to_string(&scheduler).unwrap();
155 assert_eq!(
156 serialized,
157 "handoff: Eager\ncadence: !Intermittent\n 'on': '12 min'\n 'off': '17 h 5 min'\nmin_samples: 10\nsample_alignment: '1 s'\n"
158 );
159 let deserd: Scheduler = serde_yml::from_str(&serialized).unwrap();
160 assert_eq!(deserd, scheduler);
161 }
162
163 #[test]
164 fn defaults() {
165 let sched = Scheduler::default();
166
167 assert_eq!(sched.cadence, Cadence::Continuous);
168
169 assert_eq!(sched.handoff, Handoff::Eager);
170 }
171}