1pub mod countdown_timer;
2pub mod emomtimer {
3 pub enum Msg {
4 Start,
5 Stop,
6 Reset,
7 IncrementSecond,
8 DecrementSecond,
9 IncrementQuarter,
10 DecrementQuarter,
11 IncrementRound,
12 DecrementRound,
13 Tick,
14 }
15
16 pub const DEFAULT_MINUTES: usize = 1;
17 pub const DEFAULT_SECONDS: usize = 0;
18 pub const DEFAULT_ROUNDS: usize = 5;
19
20 #[derive(Debug, Clone, Copy, PartialEq)]
21 pub struct Time {
22 pub seconds: usize,
23 pub minutes: usize,
24 pub tenths: usize,
25 }
26
27 impl Time {
28 pub fn reset(&mut self) {
29 self.seconds = DEFAULT_SECONDS;
30 self.minutes = DEFAULT_MINUTES;
31 self.tenths = 0;
32 }
33
34 pub fn is_zero(&self) -> bool {
35 self.seconds == 0 && self.minutes == 0 && self.tenths == 0
36 }
37
38 pub fn tick(&mut self, max_seconds: usize) {
39 if self.is_zero() {
40 return;
41 }
42 if self.tenths > 0 {
44 self.tenths -= 1;
45 } else {
46 self.decrement_seconds(max_seconds);
48 if !self.is_zero() {
50 self.tenths = 9;
51 }
52 }
53 }
54
55 pub fn increment_seconds(&mut self) {
56 self.seconds += 1;
57 if self.seconds == 60 {
58 self.seconds = 0;
59 self.increment_minutes()
60 }
61 }
62
63 pub fn decrement_seconds(&mut self, max_seconds: usize) {
64 if self.is_zero() {
65 self.seconds = 0;
66 self.minutes = 0;
67 self.tenths = 0;
68 } else if self.seconds == 0 {
69 self.seconds = max_seconds - 1;
70 self.decrement_minutes()
71 } else {
72 self.seconds -= 1;
73 }
74 }
75
76 pub fn increment_quarter(&mut self) {
77 self.seconds += 15;
78 if self.seconds >= 60 {
79 self.seconds -= 60;
80 self.increment_minutes();
81 }
82 }
83
84 pub fn decrement_quarter(&mut self) {
85 if self.minutes == 0 && self.seconds < 15 {
86 self.seconds = 0;
87 self.minutes = 0;
88 self.tenths = 0;
89 } else if self.seconds < 15 {
90 self.seconds += 45;
91 self.decrement_minutes();
92 } else {
93 self.seconds -= 15;
94 }
95 }
96
97 pub fn increment_minutes(&mut self) {
98 self.minutes += 1;
99 }
100
101 pub fn decrement_minutes(&mut self) {
102 if self.minutes > 0 {
103 self.minutes -= 1;
104 }
105 }
106
107 pub fn total_seconds(&self) -> usize {
109 self.seconds + self.minutes * 60
110 }
111 }
112
113 pub struct Timer {
114 pub current_time: Time,
115 pub rounds: usize,
116 pub current_round: usize,
117 pub running: bool,
118 }
119
120 impl Timer {
121 pub fn reset(&mut self) {
122 self.current_time.reset();
123 self.rounds = DEFAULT_ROUNDS;
124 self.current_round = 1;
125 self.running = false;
126 }
127
128 pub fn increment_rounds(&mut self) {
129 self.rounds += 1;
130 }
131
132 pub fn decrement_rounds(&mut self) {
133 if self.rounds > 1 {
134 self.rounds -= 1;
135 }
136 if self.current_round > self.rounds {
137 self.current_round = self.rounds;
138 }
139 }
140 }
141
142 pub fn distance<T>(a: T, b: T) -> T
143 where
144 T: std::ops::Sub<Output = T> + std::cmp::PartialOrd + Copy,
145 {
146 if a > b { a - b } else { b - a }
147 }
148
149 #[cfg(test)]
150 mod tests {
151 use super::*;
152
153 #[test]
154 fn test_timer_reset() {
155 let mut timer = Timer {
156 current_time: Time {
157 seconds: 30,
158 minutes: 2,
159 tenths: 1,
160 },
161 rounds: 10,
162 current_round: 5,
163 running: true,
164 };
165 timer.reset();
166 assert_eq!(timer.current_time.seconds, DEFAULT_SECONDS);
167 assert_eq!(timer.current_time.minutes, DEFAULT_MINUTES);
168 assert_eq!(timer.current_time.tenths, 0);
169 assert_eq!(timer.rounds, DEFAULT_ROUNDS);
170 assert_eq!(timer.current_round, 1);
171 assert!(!timer.running);
172 }
173
174 #[test]
175 fn test_timer_increment_rounds() {
176 let mut timer = Timer {
177 current_time: Time {
178 seconds: 0,
179 minutes: 1,
180 tenths: 0,
181 },
182 rounds: 15,
183 current_round: 1,
184 running: true,
185 };
186 timer.increment_rounds();
187 assert_eq!(timer.rounds, 16);
188 }
189
190 #[test]
191 fn test_decrement_rounds() {
192 let mut timer = Timer {
193 current_time: Time {
194 seconds: 0,
195 minutes: 1,
196 tenths: 0,
197 },
198 rounds: 15,
199 current_round: 1,
200 running: true,
201 };
202 timer.decrement_rounds();
203 assert_eq!(timer.rounds, 14);
204 timer.rounds = 1;
205 timer.decrement_rounds();
206 assert_eq!(timer.rounds, 1);
207 }
208
209 #[test]
210 fn test_decrement_rounds_clamps_current_round() {
211 let mut timer = Timer {
212 current_time: Time {
213 seconds: 0,
214 minutes: 1,
215 tenths: 0,
216 },
217 rounds: 4,
218 current_round: 4,
219 running: false,
220 };
221 timer.decrement_rounds();
222 assert_eq!(timer.rounds, 3);
223 assert_eq!(timer.current_round, 3);
224 }
225
226 #[test]
227 fn test_time_increment_seconds() {
228 let mut time = Time {
229 seconds: 0,
230 minutes: 1,
231 tenths: 0,
232 };
233 time.increment_seconds();
234 assert_eq!(time.seconds, 1);
235 assert_eq!(time.minutes, 1);
236 time.seconds = 59;
237 time.increment_seconds();
238 assert_eq!(time.seconds, 0);
239 assert_eq!(time.minutes, 2);
240 }
241
242 #[test]
243 fn test_time_decrement_seconds() {
244 let mut time = Time {
245 seconds: 0,
246 minutes: 0,
247 tenths: 0,
248 };
249 time.decrement_seconds(60);
250 assert_eq!(time.seconds, 0);
251 assert_eq!(time.minutes, 0);
252 assert_eq!(time.tenths, 0);
253 time.seconds = 1;
254 time.decrement_seconds(60);
255 assert_eq!(time.seconds, 0);
256 assert_eq!(time.minutes, 0);
257 assert_eq!(time.tenths, 0);
258 time.seconds = 0;
259 time.minutes = 1;
260 time.decrement_seconds(60);
261 assert_eq!(time.seconds, 59);
262 assert_eq!(time.minutes, 0);
263 assert_eq!(time.tenths, 0);
264 }
265
266 #[test]
267 fn test_increment_quarter() {
268 let mut time = Time {
269 seconds: 0,
270 minutes: 0,
271 tenths: 0,
272 };
273 time.increment_quarter();
274 assert_eq!(time.seconds, 15);
275 assert_eq!(time.minutes, 0);
276 assert_eq!(time.tenths, 0);
277 time.seconds = 45;
278 time.increment_quarter();
279 assert_eq!(time.seconds, 0);
280 assert_eq!(time.minutes, 1);
281 assert_eq!(time.tenths, 0);
282 }
283
284 #[test]
285 fn test_decrement_quarter() {
286 let mut time = Time {
287 seconds: 0,
288 minutes: 0,
289 tenths: 0,
290 };
291 time.decrement_quarter();
292 assert_eq!(time.seconds, 0);
293 assert_eq!(time.minutes, 0);
294 assert_eq!(time.tenths, 0);
295 time.seconds = 15;
296 time.decrement_quarter();
297 assert_eq!(time.seconds, 0);
298 assert_eq!(time.minutes, 0);
299 assert_eq!(time.tenths, 0);
300 time.seconds = 0;
301 time.minutes = 1;
302 time.decrement_quarter();
303 assert_eq!(time.seconds, 45);
304 assert_eq!(time.minutes, 0);
305 assert_eq!(time.tenths, 0);
306 time.seconds = 12;
307 time.decrement_quarter();
308 assert_eq!(time.seconds, 0);
309 assert_eq!(time.minutes, 0);
310 assert_eq!(time.tenths, 0);
311 }
312
313 #[test]
314 fn test_time_reset() {
315 let mut time = Time {
316 seconds: 30,
317 minutes: 2,
318 tenths: 3,
319 };
320 time.reset();
321 assert_eq!(time.seconds, DEFAULT_SECONDS);
322 assert_eq!(time.minutes, DEFAULT_MINUTES);
323 assert_eq!(time.tenths, 0);
324 }
325
326 #[test]
327 fn test_time_increment_minutes() {
328 let mut time = Time {
329 seconds: 0,
330 minutes: 1,
331 tenths: 0,
332 };
333 time.increment_minutes();
334 assert_eq!(time.seconds, 0);
335 assert_eq!(time.minutes, 2);
336 assert_eq!(time.tenths, 0);
337 }
338
339 #[test]
340 fn test_time_decrement_minutes() {
341 let mut time = Time {
342 seconds: 0,
343 minutes: 1,
344 tenths: 0,
345 };
346 time.decrement_minutes();
347 assert_eq!(time.seconds, 0);
348 assert_eq!(time.minutes, 0);
349 assert_eq!(time.tenths, 0);
350 time.decrement_minutes();
351 assert_eq!(time.seconds, 0);
352 assert_eq!(time.minutes, 0);
353 assert_eq!(time.tenths, 0);
354 }
355
356 #[test]
357 fn test_time_tick() {
358 let mut time = Time {
359 seconds: 0,
360 minutes: 1,
361 tenths: 0,
362 };
363 time.tick(60);
364 assert_eq!(time.seconds, 59);
365 assert_eq!(time.minutes, 0);
366 assert_eq!(time.tenths, 9);
367 time.tenths = 0;
368 time.tick(60);
369 assert_eq!(time.seconds, 58);
370 assert_eq!(time.minutes, 0);
371 assert_eq!(time.tenths, 9);
372 time.seconds = 0;
373 time.minutes = 0;
374 time.tenths = 1;
375 time.tick(60);
376 assert_eq!(time.seconds, 0);
377 assert_eq!(time.minutes, 0);
378 assert_eq!(time.tenths, 0);
379 }
380
381 #[test]
382 fn test_time_double_tick() {
383 let mut time = Time {
384 seconds: 0,
385 minutes: 0,
386 tenths: 0,
387 };
388 time.tick(60);
389 assert_eq!(time.seconds, 0);
390 assert_eq!(time.minutes, 0);
391 assert_eq!(time.tenths, 0);
392 }
393
394 #[test]
395 fn test_time_zero() {
396 let mut time = Time {
397 seconds: 0,
398 minutes: 0,
399 tenths: 0,
400 };
401 assert!(time.is_zero());
402 time.seconds = 1;
403 assert!(!time.is_zero());
404 time.seconds = 0;
405 time.minutes = 1;
406 assert!(!time.is_zero());
407 time.minutes = 0;
408 time.tenths = 1;
409 assert!(!time.is_zero());
410 }
411
412 #[test]
413 fn test_distance() {
414 assert_eq!(distance(1, 2), 1);
415 assert_eq!(distance(2, 1), 1);
416 assert_eq!(distance(1, 1), 0);
417 }
418
419 #[test]
420 fn test_tick_countdown_sequence() {
421 let mut time = Time {
424 seconds: 14,
425 minutes: 0,
426 tenths: 2,
427 };
428 time.tick(60);
430 assert_eq!(time.seconds, 14);
431 assert_eq!(time.tenths, 1);
432 time.tick(60);
434 assert_eq!(time.seconds, 14);
435 assert_eq!(time.tenths, 0);
436 time.tick(60);
438 assert_eq!(time.seconds, 13);
439 assert_eq!(time.tenths, 9);
440 time.tick(60);
442 assert_eq!(time.seconds, 13);
443 assert_eq!(time.tenths, 8);
444 }
445
446 #[test]
447 fn test_15_second_timer_countdown() {
448 let mut time = Time {
451 seconds: 15,
452 minutes: 0,
453 tenths: 0,
454 };
455
456 time.tick(60);
458 assert_eq!(time.seconds, 14, "After first tick from 15.0");
459 assert_eq!(time.tenths, 9, "After first tick from 15.0");
460
461 for expected_tenth in (0..=8).rev() {
463 time.tick(60);
464 assert_eq!(
465 time.seconds, 14,
466 "Second mismatch at tenth {}",
467 expected_tenth
468 );
469 assert_eq!(
470 time.tenths, expected_tenth,
471 "Tenth mismatch at {}",
472 expected_tenth
473 );
474 }
475
476 time.tick(60);
478 assert_eq!(time.seconds, 13);
479 assert_eq!(time.tenths, 9);
480 }
481
482 #[test]
483 fn test_full_15_second_countdown() {
484 let mut time = Time {
486 seconds: 15,
487 minutes: 0,
488 tenths: 0,
489 };
490
491 let mut history = Vec::new();
492
493 while !time.is_zero() {
495 history.push((time.minutes, time.seconds, time.tenths));
496 time.tick(60);
497 }
498
499 println!("History around 14:");
501 for (i, (m, s, t)) in history.iter().enumerate() {
502 if *s >= 13 && *s <= 15 {
503 println!(" [{}]: {}:{}.{}", i, m, s, t);
504 }
505 }
506
507 println!("Total history length: {}", history.len());
508
509 assert_eq!(history[0], (0, 15, 0));
511 assert_eq!(history[1], (0, 14, 9));
513 }
514
515 #[test]
516 fn test_total_seconds() {
517 let mut time = Time {
518 seconds: 0,
519 minutes: 0,
520 tenths: 0,
521 };
522 assert_eq!(time.total_seconds(), 0);
523 time.seconds = 1;
524 assert_eq!(time.total_seconds(), 1);
525 time.seconds = 0;
526 time.minutes = 1;
527 assert_eq!(time.total_seconds(), 60);
528 time.seconds = 1;
529 assert_eq!(time.total_seconds(), 61);
530 }
531 }
532}