1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
#[cfg(test)]
mod tests {
    use std;
    #[test]
    fn test_split() {
        let exers = "A,B,C";
        let exers_split = ::cardio::split(exers);
        let expected = ["A", "B", "C"];
        assert_eq!(exers_split, expected);
    }

    #[test]
    fn test_duration() {
        let expected = std::time::Duration::from_secs(60);
        let actual = ::cardio::get_duration(60);
        assert_eq!(expected, actual);
    }
}

/// Functionality related to the cardio exercises.
pub mod cardio {
    pub const BELL: char = 0x07 as char;

    use std;

    /// Splits the exercises from the comma separated string into separate values
    pub fn split<'a>(exercises: &'a str) -> Vec<&'a str> {
        exercises.split(",").collect()
    }

    /// Returns the duration from the seconds
    pub fn get_duration(seconds: u64) -> std::time::Duration {
        std::time::Duration::from_secs(seconds)
    }

    /// Sleeps for the specified amount of seconds
    pub fn sleep(sleep_time: std::time::Duration) {
        std::thread::sleep(sleep_time);
    }

    /// Prints the bell character (This makes a sound)
    pub fn ring_bell() {
        println!("{}", ::cardio::BELL);
    }

    /// Basic structure for the Exercise
    /// This contains the set of exercises, rounds, length of each exercise and length of break between exercises
    pub struct Exercise<'a> {
        exercises: Vec<&'a str>,
        rounds: u64,
        exercise_seconds: std::time::Duration,
        break_seconds: std::time::Duration,
    }

    impl<'a> Exercise<'a> {
        /// Constructor
        pub fn new(
            exercises: &'a str,
            rounds: u64,
            exercise_seconds: u64,
            break_seconds: u64,
        ) -> Self {
            Exercise {
                exercises: ::cardio::split(exercises),
                rounds: rounds,
                exercise_seconds: ::cardio::get_duration(exercise_seconds),
                break_seconds: ::cardio::get_duration(break_seconds),
            }
        }

        /// Starts the exercises.
        /// There is a 5 seconds preparation followed by the specified amount of rounds.
        /// 
        /// Each round contains a set of exercises. Each exercises starts and ends with a bell sound.
        /// 3 bell sounds in a quick succession means the end of the cardio training.
        pub fn start(&self) {
            println!("Starting the exercises in 5 seconds");
            ::cardio::sleep(::cardio::get_duration(5));
            let mut current_round = 1;
            while current_round <= self.rounds {
                println!("*************************************");
                println!("* Round {} starting....", current_round);
                println!("*************************************");

                for exercise in &self.exercises {
                    println!("Starting exercise: {}", exercise.trim());
                    ::cardio::ring_bell();
                    ::cardio::sleep(self.exercise_seconds);
                    ::cardio::ring_bell();
                    println!("Break!");
                    ::cardio::sleep(self.break_seconds);
                }
                current_round = current_round + 1;
            }

            println!("Finished");
            for _ in 1..4 {
                ::cardio::ring_bell();
                ::cardio::sleep(std::time::Duration::from_secs(1));
            }
        }
    }
}