anvilkit_core/time/
timer.rs1use std::time::Duration;
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum TimerState {
24 Running,
26 Paused,
28 Finished,
30}
31
32#[derive(Debug, Clone)]
71pub struct Timer {
72 duration: Duration,
74 elapsed: Duration,
76 repeating: bool,
78 state: TimerState,
80 just_finished: bool,
82}
83
84impl Timer {
85 pub fn new(duration: Duration) -> Self {
102 Self {
103 duration,
104 elapsed: Duration::ZERO,
105 repeating: false,
106 state: TimerState::Running,
107 just_finished: false,
108 }
109 }
110
111 pub fn repeating(duration: Duration) -> Self {
127 Self {
128 duration,
129 elapsed: Duration::ZERO,
130 repeating: true,
131 state: TimerState::Running,
132 just_finished: false,
133 }
134 }
135
136 pub fn from_seconds(seconds: f32) -> Self {
147 Self::new(Duration::from_secs_f32(seconds))
148 }
149
150 pub fn repeating_from_seconds(seconds: f32) -> Self {
162 Self::repeating(Duration::from_secs_f32(seconds))
163 }
164
165 pub fn from_millis(millis: u64) -> Self {
167 Self::new(Duration::from_millis(millis))
168 }
169
170 pub fn repeating_from_millis(millis: u64) -> Self {
172 Self::repeating(Duration::from_millis(millis))
173 }
174
175 pub fn tick(&mut self, delta: Duration) {
202 self.just_finished = false;
203
204 if self.state != TimerState::Running {
205 return;
206 }
207
208 let _old_elapsed = self.elapsed;
209 self.elapsed += delta;
210
211 if self.elapsed >= self.duration {
213 self.just_finished = true;
214
215 if self.repeating {
216 let overflow = self.elapsed - self.duration;
218 self.elapsed = overflow;
219
220 while self.elapsed >= self.duration {
223 self.elapsed -= self.duration;
224 }
225 } else {
226 self.elapsed = self.duration;
228 self.state = TimerState::Finished;
229 }
230 }
231 }
232
233 pub fn finished(&self) -> bool {
251 match self.state {
252 TimerState::Finished => true,
253 _ => self.repeating && self.just_finished,
254 }
255 }
256
257 pub fn just_finished(&self) -> bool {
279 self.just_finished
280 }
281
282 pub fn elapsed(&self) -> Duration {
284 self.elapsed
285 }
286
287 pub fn elapsed_seconds(&self) -> f32 {
289 self.elapsed.as_secs_f32()
290 }
291
292 pub fn duration(&self) -> Duration {
294 self.duration
295 }
296
297 pub fn duration_seconds(&self) -> f32 {
299 self.duration.as_secs_f32()
300 }
301
302 pub fn percent(&self) -> f32 {
316 if self.duration.is_zero() {
317 1.0
318 } else {
319 (self.elapsed.as_secs_f32() / self.duration.as_secs_f32()).min(1.0)
320 }
321 }
322
323 pub fn remaining(&self) -> Duration {
337 self.duration.saturating_sub(self.elapsed)
338 }
339
340 pub fn remaining_seconds(&self) -> f32 {
342 self.remaining().as_secs_f32()
343 }
344
345 pub fn reset(&mut self) {
363 self.elapsed = Duration::ZERO;
364 self.state = TimerState::Running;
365 self.just_finished = false;
366 }
367
368 pub fn pause(&mut self) {
386 if self.state == TimerState::Running {
387 self.state = TimerState::Paused;
388 }
389 }
390
391 pub fn resume(&mut self) {
406 if self.state == TimerState::Paused {
407 self.state = TimerState::Running;
408 }
409 }
410
411 pub fn set_duration(&mut self, duration: Duration) {
429 self.duration = duration;
430
431 if self.elapsed >= self.duration {
433 if self.repeating {
434 self.elapsed = Duration::ZERO;
435 self.just_finished = true;
436 } else {
437 self.elapsed = self.duration;
438 self.state = TimerState::Finished;
439 self.just_finished = true;
440 }
441 }
442 }
443
444 pub fn set_repeating(&mut self, repeating: bool) {
458 self.repeating = repeating;
459
460 if repeating {
461 if self.state == TimerState::Finished {
463 self.elapsed = Duration::ZERO;
464 self.state = TimerState::Running;
465 }
466 } else {
467 if self.elapsed >= self.duration {
469 self.state = TimerState::Finished;
470 }
471 }
472 }
473
474 pub fn is_repeating(&self) -> bool {
476 self.repeating
477 }
478
479 pub fn is_running(&self) -> bool {
481 self.state == TimerState::Running
482 }
483
484 pub fn is_paused(&self) -> bool {
486 self.state == TimerState::Paused
487 }
488
489 pub fn state(&self) -> TimerState {
491 self.state
492 }
493
494 pub fn finish(&mut self) {
510 self.elapsed = self.duration;
511 self.just_finished = true;
512
513 if !self.repeating {
514 self.state = TimerState::Finished;
515 }
516 }
517}
518
519#[cfg(test)]
520mod tests {
521 use super::*;
522 use std::time::Duration;
523 use approx::assert_relative_eq;
524
525 #[test]
526 fn test_timer_creation() {
527 let timer = Timer::from_seconds(2.0);
528 assert_eq!(timer.duration_seconds(), 2.0);
529 assert!(!timer.is_repeating());
530 assert!(timer.is_running());
531 assert!(!timer.finished());
532 }
533
534 #[test]
535 fn test_repeating_timer_creation() {
536 let timer = Timer::repeating_from_seconds(1.5);
537 assert_eq!(timer.duration_seconds(), 1.5);
538 assert!(timer.is_repeating());
539 assert!(timer.is_running());
540 }
541
542 #[test]
543 fn test_timer_tick() {
544 let mut timer = Timer::from_seconds(1.0);
545
546 timer.tick(Duration::from_millis(500));
548 assert_eq!(timer.percent(), 0.5);
549 assert!(!timer.finished());
550 assert!(!timer.just_finished());
551
552 timer.tick(Duration::from_millis(500));
554 assert!(timer.finished());
555 assert!(timer.just_finished());
556 assert_eq!(timer.percent(), 1.0);
557
558 timer.tick(Duration::from_millis(1));
560 assert!(timer.finished());
561 assert!(!timer.just_finished()); }
563
564 #[test]
565 fn test_repeating_timer() {
566 let mut timer = Timer::repeating_from_seconds(1.0);
567
568 timer.tick(Duration::from_secs(1));
570 assert!(timer.finished());
571 assert!(timer.just_finished());
572
573 timer.tick(Duration::from_millis(1));
575 assert!(!timer.finished());
576 assert!(!timer.just_finished());
577 assert!(timer.elapsed_seconds() < 0.1);
578 }
579
580 #[test]
581 fn test_timer_overflow() {
582 let mut timer = Timer::repeating_from_seconds(1.0);
583
584 timer.tick(Duration::from_millis(2500)); assert!(timer.just_finished());
588 assert_relative_eq!(timer.elapsed_seconds(), 0.5, epsilon = 1e-3);
589 }
590
591 #[test]
592 fn test_timer_pause_resume() {
593 let mut timer = Timer::from_seconds(1.0);
594
595 timer.tick(Duration::from_millis(300));
596 assert_eq!(timer.percent(), 0.3);
597
598 timer.pause();
599 assert!(timer.is_paused());
600
601 timer.tick(Duration::from_millis(500));
603 assert_eq!(timer.percent(), 0.3);
604
605 timer.resume();
606 assert!(timer.is_running());
607
608 timer.tick(Duration::from_millis(700));
609 assert!(timer.finished());
610 }
611
612 #[test]
613 fn test_timer_reset() {
614 let mut timer = Timer::from_seconds(1.0);
615 timer.tick(Duration::from_millis(800));
616
617 assert_eq!(timer.percent(), 0.8);
618
619 timer.reset();
620 assert_eq!(timer.percent(), 0.0);
621 assert!(!timer.finished());
622 assert!(timer.is_running());
623 }
624
625 #[test]
626 fn test_timer_set_duration() {
627 let mut timer = Timer::from_seconds(2.0);
628 timer.tick(Duration::from_secs(1));
629
630 timer.set_duration(Duration::from_secs(3));
632 assert_eq!(timer.percent(), 1.0 / 3.0);
633
634 timer.set_duration(Duration::from_millis(500));
636 assert!(timer.finished());
637 assert!(timer.just_finished());
638 }
639
640 #[test]
641 fn test_timer_remaining() {
642 let mut timer = Timer::from_seconds(5.0);
643 timer.tick(Duration::from_secs(2));
644
645 assert_eq!(timer.remaining(), Duration::from_secs(3));
646 assert_eq!(timer.remaining_seconds(), 3.0);
647 }
648
649 #[test]
650 fn test_timer_finish() {
651 let mut timer = Timer::from_seconds(10.0);
652 timer.finish();
653
654 assert!(timer.finished());
655 assert!(timer.just_finished());
656 assert_eq!(timer.percent(), 1.0);
657 }
658
659 #[test]
660 fn test_timer_state_transitions() {
661 let mut timer = Timer::from_seconds(1.0);
662
663 assert_eq!(timer.state(), TimerState::Running);
664
665 timer.pause();
666 assert_eq!(timer.state(), TimerState::Paused);
667
668 timer.resume();
669 assert_eq!(timer.state(), TimerState::Running);
670
671 timer.tick(Duration::from_secs(1));
672 assert_eq!(timer.state(), TimerState::Finished);
673 }
674
675 #[test]
676 fn test_zero_duration_timer() {
677 let mut timer = Timer::new(Duration::ZERO);
678 assert_eq!(timer.percent(), 1.0);
679
680 timer.tick(Duration::from_millis(1));
681 assert!(timer.finished());
682 assert!(timer.just_finished());
683 }
684
685 #[test]
686 fn test_timer_set_repeating() {
687 let mut timer = Timer::from_seconds(1.0);
688 timer.tick(Duration::from_secs(1));
689
690 assert!(timer.finished());
691
692 timer.set_repeating(true);
694 timer.tick(Duration::from_millis(1));
695
696 assert!(!timer.finished());
698 assert!(timer.elapsed_seconds() < 0.1);
699 }
700
701 #[test]
702 fn test_timer_from_millis() {
703 let timer = Timer::from_millis(500);
704 assert_eq!(timer.duration(), Duration::from_millis(500));
705 assert!(!timer.is_repeating());
706 }
707
708 #[test]
709 fn test_timer_repeating_from_millis() {
710 let timer = Timer::repeating_from_millis(250);
711 assert_eq!(timer.duration(), Duration::from_millis(250));
712 assert!(timer.is_repeating());
713 }
714
715 #[test]
716 fn test_timer_pause_prevents_finish() {
717 let mut timer = Timer::from_seconds(1.0);
718 timer.tick(Duration::from_millis(500));
719 timer.pause();
720 timer.tick(Duration::from_secs(10));
721
722 assert!(!timer.finished());
724 assert_relative_eq!(timer.percent(), 0.5, epsilon = 1e-3);
725 }
726
727 #[test]
728 fn test_timer_resume_finished_timer() {
729 let mut timer = Timer::from_seconds(1.0);
730 timer.tick(Duration::from_secs(1));
731 assert!(timer.finished());
732
733 timer.resume();
735 assert!(timer.finished());
736 }
737
738 #[test]
739 fn test_timer_pause_already_paused() {
740 let mut timer = Timer::from_seconds(1.0);
741 timer.pause();
742 timer.pause(); assert!(timer.is_paused());
744 }
745
746 #[test]
747 fn test_timer_resume_when_running() {
748 let mut timer = Timer::from_seconds(1.0);
749 timer.resume(); assert!(timer.is_running());
751 }
752
753 #[test]
754 fn test_timer_elapsed_seconds() {
755 let mut timer = Timer::from_seconds(2.0);
756 timer.tick(Duration::from_millis(750));
757 assert_relative_eq!(timer.elapsed_seconds(), 0.75, epsilon = 1e-3);
758 }
759
760 #[test]
761 fn test_timer_remaining_after_finish() {
762 let mut timer = Timer::from_seconds(1.0);
763 timer.tick(Duration::from_secs(2));
764 assert_eq!(timer.remaining(), Duration::ZERO);
765 }
766
767 #[test]
768 fn test_repeating_timer_rapid_ticks() {
769 let mut timer = Timer::repeating(Duration::from_millis(100));
770
771 for _ in 0..20 {
773 timer.tick(Duration::from_millis(10));
774 }
775
776 assert!(timer.elapsed_seconds() < 0.1);
778 }
779
780 #[test]
781 fn test_timer_set_duration_while_running() {
782 let mut timer = Timer::from_seconds(5.0);
783 timer.tick(Duration::from_secs(2));
784
785 timer.set_duration(Duration::from_secs(10));
787 assert!(!timer.finished());
788 assert_relative_eq!(timer.percent(), 0.2, epsilon = 1e-3);
789 }
790
791 #[test]
792 fn test_timer_finish_repeating() {
793 let mut timer = Timer::repeating_from_seconds(1.0);
794 timer.finish();
795
796 assert!(timer.just_finished());
797 assert_eq!(timer.state(), TimerState::Running);
799 }
800}