1use std::{fmt::Debug, ops::Add};
4
5use chrono::{Duration, NaiveTime, Timelike};
6
7use crate::event::EventInstance;
8
9#[derive(Clone)]
11pub struct EventSchedule {
12 pub name: &'static str,
14
15 pub offset: NaiveTime,
17
18 pub frequency: Duration,
20
21 pub length: Duration,
23}
24
25impl EventSchedule {
26 pub fn iter(&self) -> Iter {
27 Iter::new(self, Duration::zero())
28 }
29}
30
31impl IntoIterator for EventSchedule {
32 type Item = EventInstance;
33 type IntoIter = IntoIter;
34
35 fn into_iter(self) -> Self::IntoIter {
36 IntoIter::new(self, Duration::zero())
37 }
38}
39
40impl Debug for EventSchedule {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 write!(
43 f,
44 "{}: offset: {}, freq: {}m, len: {}m",
45 self.name,
46 self.offset,
47 self.frequency.num_minutes(),
48 self.length.num_minutes()
49 )
50 }
51}
52
53pub struct IntoIter {
59 event_schedule: EventSchedule,
60 offset: Duration,
61}
62
63impl IntoIter {
64 fn new(event_schedule: EventSchedule, current_time: Duration) -> IntoIter {
66 IntoIter {
68 event_schedule,
69 offset: current_time,
70 }
71 }
72
73 pub fn time(mut self, time: NaiveTime) -> Self {
75 self.offset = Duration::seconds(time.num_seconds_from_midnight() as i64);
76 self
77 }
78
79 pub fn fast_forward(mut self, amount: Duration) -> Self {
81 self.offset = self.offset.add(amount);
82 self
83 }
84
85 pub fn now(&self) -> Option<EventInstance> {
87 let time = self.offset.num_minutes();
88 let offset = self.event_schedule.offset.num_seconds_from_midnight() as i64 / 60;
89 let freq = self.event_schedule.frequency.num_minutes();
90 let length = self.event_schedule.length.num_minutes();
91 let i = time / freq;
92 let relative_time = time - i * freq;
93
94 if relative_time < offset || relative_time >= offset + length {
95 return None;
96 }
97
98 let offset = Duration::minutes(offset + i * freq);
99
100 Some(EventInstance {
101 schedule: self.event_schedule.clone(),
102 start_time: offset,
103 })
104 }
105}
106
107impl Iterator for IntoIter {
108 type Item = EventInstance;
109
110 fn next(&mut self) -> Option<EventInstance> {
111 let time = self.offset.num_minutes();
112 let offset = self.event_schedule.offset.num_seconds_from_midnight() as i64 / 60;
113 let freq = self.event_schedule.frequency.num_minutes();
114 let i = time / freq;
115 let relative_time = time - i * freq;
116
117 let offset = if relative_time < offset {
118 offset
119 } else {
120 offset + freq
121 };
122
123 self.offset = Duration::minutes(offset + i * freq);
124
125 Some(EventInstance {
126 schedule: self.event_schedule.clone(),
127 start_time: self.offset,
128 })
129 }
130}
131
132pub struct Iter<'a> {
133 event_schedule: &'a EventSchedule,
134 offset: Duration,
135}
136
137impl<'a> Iter<'_> {
138 fn new(event_schedule: &'a EventSchedule, current_time: Duration) -> Iter {
140 Iter {
142 event_schedule,
143 offset: current_time,
144 }
145 }
146
147 pub fn time(mut self, time: NaiveTime) -> Self {
149 self.offset = Duration::seconds(time.num_seconds_from_midnight() as i64);
150 self
151 }
152
153 pub fn fast_forward(mut self, amount: Duration) -> Self {
155 self.offset = self.offset.add(amount);
156 self
157 }
158
159 pub fn now(&self) -> Option<EventInstance> {
161 let time = self.offset.num_minutes();
162 let offset = self.event_schedule.offset.num_seconds_from_midnight() as i64 / 60;
163 let freq = self.event_schedule.frequency.num_minutes();
164 let length = self.event_schedule.length.num_minutes();
165 let i = time / freq;
166 let relative_time = time - i * freq;
167
168 if relative_time < offset || relative_time >= offset + length {
169 return None;
170 }
171
172 let offset = Duration::minutes(offset + i * freq);
173 Some(EventInstance {
174 schedule: self.event_schedule.clone(),
175 start_time: offset,
176 })
177 }
178}
179
180impl Iterator for Iter<'_> {
181 type Item = EventInstance;
182
183 fn next(&mut self) -> Option<EventInstance> {
184 let time = self.offset.num_minutes();
185 let offset = self.event_schedule.offset.num_seconds_from_midnight() as i64 / 60;
186 let freq = self.event_schedule.frequency.num_minutes();
187 let i = time / freq;
188 let relative_time = time - i * freq;
189
190 let offset = if relative_time < offset {
191 offset
192 } else {
193 offset + freq
194 };
195
196 self.offset = Duration::minutes(offset + i * freq);
197
198 Some(EventInstance {
199 schedule: self.event_schedule.clone(),
200 start_time: self.offset,
201 })
202 }
203}
204
205pub struct IterMut<'a> {
206 event_schedule: &'a mut EventSchedule,
207 offset: Duration,
208}
209
210impl<'a> IterMut<'_> {
211 fn new(event_schedule: &'a mut EventSchedule, current_time: Duration) -> IterMut {
213 IterMut {
215 event_schedule,
216 offset: current_time,
217 }
218 }
219
220 pub fn time(mut self, time: NaiveTime) -> Self {
222 self.offset = Duration::seconds(time.num_seconds_from_midnight() as i64);
223 self
224 }
225
226 pub fn fast_forward(mut self, amount: Duration) -> Self {
228 self.offset = self.offset.add(amount);
229 self
230 }
231
232 pub fn now(&self) -> Option<EventInstance> {
234 let time = self.offset.num_minutes();
235 let offset = self.event_schedule.offset.num_seconds_from_midnight() as i64 / 60;
236 let freq = self.event_schedule.frequency.num_minutes();
237 let length = self.event_schedule.length.num_minutes();
238 let i = time / freq;
239 let relative_time = time - i * freq;
240
241 if relative_time < offset || relative_time >= offset + length {
242 return None;
243 }
244
245 let offset = Duration::minutes(offset + i * freq);
246 Some(EventInstance {
247 schedule: self.event_schedule.clone(),
248 start_time: offset,
249 })
250 }
251}
252
253impl Iterator for IterMut<'_> {
254 type Item = EventInstance;
255
256 fn next(&mut self) -> Option<EventInstance> {
257 let time = self.offset.num_minutes();
258 let offset = self.event_schedule.offset.num_seconds_from_midnight() as i64 / 60;
259 let freq = self.event_schedule.frequency.num_minutes();
260 let i = time / freq;
261 let relative_time = time - i * freq;
262
263 let offset = if relative_time < offset {
264 offset
265 } else {
266 offset + freq
267 };
268
269 self.offset = Duration::minutes(offset + i * freq);
270
271 Some(EventInstance {
272 schedule: self.event_schedule.clone(),
273 start_time: self.offset,
274 })
275 }
276}