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