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 } else {
136 self.rounds -= 1;
137 }
138 }
139 }
140
141 pub fn distance<T>(a: T, b: T) -> T
142 where
143 T: std::ops::Sub<Output = T> + std::cmp::PartialOrd + Copy,
144 {
145 if a > b { a - b } else { b - a }
146 }
147
148 #[cfg(test)]
149 mod tests {
150 use super::*;
151
152 #[test]
153 fn test_timer_reset() {
154 let mut timer = Timer {
155 current_time: Time {
156 seconds: 30,
157 minutes: 2,
158 tenths: 1,
159 },
160 rounds: 10,
161 current_round: 5,
162 running: true,
163 };
164 timer.reset();
165 assert_eq!(timer.current_time.seconds, DEFAULT_SECONDS);
166 assert_eq!(timer.current_time.minutes, DEFAULT_MINUTES);
167 assert_eq!(timer.current_time.tenths, 0);
168 assert_eq!(timer.rounds, DEFAULT_ROUNDS);
169 assert_eq!(timer.current_round, 1);
170 assert!(!timer.running);
171 }
172
173 #[test]
174 fn test_timer_increment_rounds() {
175 let mut timer = Timer {
176 current_time: Time {
177 seconds: 0,
178 minutes: 1,
179 tenths: 0,
180 },
181 rounds: 15,
182 current_round: 1,
183 running: true,
184 };
185 timer.increment_rounds();
186 assert_eq!(timer.rounds, 16);
187 }
188
189 #[test]
190 fn test_decrement_rounds() {
191 let mut timer = Timer {
192 current_time: Time {
193 seconds: 0,
194 minutes: 1,
195 tenths: 0,
196 },
197 rounds: 15,
198 current_round: 1,
199 running: true,
200 };
201 timer.decrement_rounds();
202 assert_eq!(timer.rounds, 14);
203 timer.rounds = 1;
204 timer.decrement_rounds();
205 assert_eq!(timer.rounds, 1);
206 }
207
208 #[test]
209 fn test_time_increment_seconds() {
210 let mut time = Time {
211 seconds: 0,
212 minutes: 1,
213 tenths: 0,
214 };
215 time.increment_seconds();
216 assert_eq!(time.seconds, 1);
217 assert_eq!(time.minutes, 1);
218 time.seconds = 59;
219 time.increment_seconds();
220 assert_eq!(time.seconds, 0);
221 assert_eq!(time.minutes, 2);
222 }
223
224 #[test]
225 fn test_time_decrement_seconds() {
226 let mut time = Time {
227 seconds: 0,
228 minutes: 0,
229 tenths: 0,
230 };
231 time.decrement_seconds(60);
232 assert_eq!(time.seconds, 0);
233 assert_eq!(time.minutes, 0);
234 assert_eq!(time.tenths, 0);
235 time.seconds = 1;
236 time.decrement_seconds(60);
237 assert_eq!(time.seconds, 0);
238 assert_eq!(time.minutes, 0);
239 assert_eq!(time.tenths, 0);
240 time.seconds = 0;
241 time.minutes = 1;
242 time.decrement_seconds(60);
243 assert_eq!(time.seconds, 59);
244 assert_eq!(time.minutes, 0);
245 assert_eq!(time.tenths, 0);
246 }
247
248 #[test]
249 fn test_increment_quarter() {
250 let mut time = Time {
251 seconds: 0,
252 minutes: 0,
253 tenths: 0,
254 };
255 time.increment_quarter();
256 assert_eq!(time.seconds, 15);
257 assert_eq!(time.minutes, 0);
258 assert_eq!(time.tenths, 0);
259 time.seconds = 45;
260 time.increment_quarter();
261 assert_eq!(time.seconds, 0);
262 assert_eq!(time.minutes, 1);
263 assert_eq!(time.tenths, 0);
264 }
265
266 #[test]
267 fn test_decrement_quarter() {
268 let mut time = Time {
269 seconds: 0,
270 minutes: 0,
271 tenths: 0,
272 };
273 time.decrement_quarter();
274 assert_eq!(time.seconds, 0);
275 assert_eq!(time.minutes, 0);
276 assert_eq!(time.tenths, 0);
277 time.seconds = 15;
278 time.decrement_quarter();
279 assert_eq!(time.seconds, 0);
280 assert_eq!(time.minutes, 0);
281 assert_eq!(time.tenths, 0);
282 time.seconds = 0;
283 time.minutes = 1;
284 time.decrement_quarter();
285 assert_eq!(time.seconds, 45);
286 assert_eq!(time.minutes, 0);
287 assert_eq!(time.tenths, 0);
288 time.seconds = 12;
289 time.decrement_quarter();
290 assert_eq!(time.seconds, 0);
291 assert_eq!(time.minutes, 0);
292 assert_eq!(time.tenths, 0);
293 }
294
295 #[test]
296 fn test_time_reset() {
297 let mut time = Time {
298 seconds: 30,
299 minutes: 2,
300 tenths: 3,
301 };
302 time.reset();
303 assert_eq!(time.seconds, DEFAULT_SECONDS);
304 assert_eq!(time.minutes, DEFAULT_MINUTES);
305 assert_eq!(time.tenths, 0);
306 }
307
308 #[test]
309 fn test_time_increment_minutes() {
310 let mut time = Time {
311 seconds: 0,
312 minutes: 1,
313 tenths: 0,
314 };
315 time.increment_minutes();
316 assert_eq!(time.seconds, 0);
317 assert_eq!(time.minutes, 2);
318 assert_eq!(time.tenths, 0);
319 }
320
321 #[test]
322 fn test_time_decrement_minutes() {
323 let mut time = Time {
324 seconds: 0,
325 minutes: 1,
326 tenths: 0,
327 };
328 time.decrement_minutes();
329 assert_eq!(time.seconds, 0);
330 assert_eq!(time.minutes, 0);
331 assert_eq!(time.tenths, 0);
332 time.decrement_minutes();
333 assert_eq!(time.seconds, 0);
334 assert_eq!(time.minutes, 0);
335 assert_eq!(time.tenths, 0);
336 }
337
338 #[test]
339 fn test_time_tick() {
340 let mut time = Time {
341 seconds: 0,
342 minutes: 1,
343 tenths: 0,
344 };
345 time.tick(60);
346 assert_eq!(time.seconds, 59);
347 assert_eq!(time.minutes, 0);
348 assert_eq!(time.tenths, 9);
349 time.tenths = 0;
350 time.tick(60);
351 assert_eq!(time.seconds, 58);
352 assert_eq!(time.minutes, 0);
353 assert_eq!(time.tenths, 9);
354 time.seconds = 0;
355 time.minutes = 0;
356 time.tenths = 1;
357 time.tick(60);
358 assert_eq!(time.seconds, 0);
359 assert_eq!(time.minutes, 0);
360 assert_eq!(time.tenths, 0);
361 }
362
363 #[test]
364 fn test_time_double_tick() {
365 let mut time = Time {
366 seconds: 0,
367 minutes: 0,
368 tenths: 0,
369 };
370 time.tick(60);
371 assert_eq!(time.seconds, 0);
372 assert_eq!(time.minutes, 0);
373 assert_eq!(time.tenths, 0);
374 }
375
376 #[test]
377 fn test_time_zero() {
378 let mut time = Time {
379 seconds: 0,
380 minutes: 0,
381 tenths: 0,
382 };
383 assert!(time.is_zero());
384 time.seconds = 1;
385 assert!(!time.is_zero());
386 time.seconds = 0;
387 time.minutes = 1;
388 assert!(!time.is_zero());
389 time.minutes = 0;
390 time.tenths = 1;
391 assert!(!time.is_zero());
392 }
393
394 #[test]
395 fn test_distance() {
396 assert_eq!(distance(1, 2), 1);
397 assert_eq!(distance(2, 1), 1);
398 assert_eq!(distance(1, 1), 0);
399 }
400
401 #[test]
402 fn test_tick_countdown_sequence() {
403 let mut time = Time {
406 seconds: 14,
407 minutes: 0,
408 tenths: 2,
409 };
410 time.tick(60);
412 assert_eq!(time.seconds, 14);
413 assert_eq!(time.tenths, 1);
414 time.tick(60);
416 assert_eq!(time.seconds, 14);
417 assert_eq!(time.tenths, 0);
418 time.tick(60);
420 assert_eq!(time.seconds, 13);
421 assert_eq!(time.tenths, 9);
422 time.tick(60);
424 assert_eq!(time.seconds, 13);
425 assert_eq!(time.tenths, 8);
426 }
427
428 #[test]
429 fn test_15_second_timer_countdown() {
430 let mut time = Time {
433 seconds: 15,
434 minutes: 0,
435 tenths: 0,
436 };
437
438 time.tick(60);
440 assert_eq!(time.seconds, 14, "After first tick from 15.0");
441 assert_eq!(time.tenths, 9, "After first tick from 15.0");
442
443 for expected_tenth in (0..=8).rev() {
445 time.tick(60);
446 assert_eq!(
447 time.seconds, 14,
448 "Second mismatch at tenth {}",
449 expected_tenth
450 );
451 assert_eq!(
452 time.tenths, expected_tenth,
453 "Tenth mismatch at {}",
454 expected_tenth
455 );
456 }
457
458 time.tick(60);
460 assert_eq!(time.seconds, 13);
461 assert_eq!(time.tenths, 9);
462 }
463
464 #[test]
465 fn test_full_15_second_countdown() {
466 let mut time = Time {
468 seconds: 15,
469 minutes: 0,
470 tenths: 0,
471 };
472
473 let mut history = Vec::new();
474
475 while !time.is_zero() {
477 history.push((time.minutes, time.seconds, time.tenths));
478 time.tick(60);
479 }
480
481 println!("History around 14:");
483 for (i, (m, s, t)) in history.iter().enumerate() {
484 if *s >= 13 && *s <= 15 {
485 println!(" [{}]: {}:{}.{}", i, m, s, t);
486 }
487 }
488
489 println!("Total history length: {}", history.len());
490
491 assert_eq!(history[0], (0, 15, 0));
493 assert_eq!(history[1], (0, 14, 9));
495 }
496
497 #[test]
498 fn test_total_seconds() {
499 let mut time = Time {
500 seconds: 0,
501 minutes: 0,
502 tenths: 0,
503 };
504 assert_eq!(time.total_seconds(), 0);
505 time.seconds = 1;
506 assert_eq!(time.total_seconds(), 1);
507 time.seconds = 0;
508 time.minutes = 1;
509 assert_eq!(time.total_seconds(), 60);
510 time.seconds = 1;
511 assert_eq!(time.total_seconds(), 61);
512 }
513 }
514}