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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
extern crate rand;

use self::rand::distributions::Uniform;
use crate::game::symbol::Symbol::*;
use core::fmt;
use rand::Rng;
use serde_derive::{Deserialize, Serialize};
use std::ops::RangeInclusive;

/// Symbols
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Symbol {
    Blank,
    Cherry,
    Bar,
    DoubleBar,
    TripleBar,
    Seven,
    Jackpot,
}

impl fmt::Display for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

impl Symbol {
    /// The range of numbers for which there are corresponding symbols.
    pub const RANGE: RangeInclusive<u32> = 0..=127;

    /// Searches for the corresponding [`Symbol`] in the range [`RANGE`] for `number`.
    ///
    /// Returns `None` if the `number` is not in the [`Symbol::RANGE`].
    ///
    /// # Examples
    /// ```
    /// # use slot_machine::game::symbol::Symbol;
    /// let symbol = Symbol::from_number(125);
    ///
    /// assert_eq!(symbol, Some(Symbol::Seven))
    /// ```
    pub fn from_number(number: u32) -> Option<Self> {
        let symbol = match number {
            0..=72 => Blank,
            73..=77 => Cherry,
            78..=93 => Bar,
            94..=106 => DoubleBar,
            107..=117 => TripleBar,
            118..=125 => Seven,
            126..=127 => Jackpot,
            _ => return None,
        };

        Some(symbol)
    }

    /// Returns a random [`Symbol`]
    ///
    /// # Examples
    ///
    /// ```
    /// # use slot_machine::game::symbol::Symbol;
    /// let symbol = Symbol::random();
    /// ```
    pub fn random() -> Symbol {
        let uniform = Uniform::new_inclusive(Self::RANGE.start(), Self::RANGE.end());
        let number = rand::thread_rng().sample(uniform);

        Symbol::from_number(number).unwrap()
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn blank_from_number() {
        assert_eq!(Symbol::from_number(0).unwrap(), Symbol::Blank);
        assert_eq!(Symbol::from_number(72).unwrap(), Symbol::Blank);
    }

    #[test]
    fn cherry_from_number() {
        assert_eq!(Symbol::from_number(73).unwrap(), Symbol::Cherry);
        assert_eq!(Symbol::from_number(77).unwrap(), Symbol::Cherry);
    }

    #[test]
    fn bar_from_number() {
        assert_eq!(Symbol::from_number(78).unwrap(), Symbol::Bar);
        assert_eq!(Symbol::from_number(93).unwrap(), Symbol::Bar);
    }

    #[test]
    fn double_bar_from_number() {
        assert_eq!(Symbol::from_number(94).unwrap(), Symbol::DoubleBar);
        assert_eq!(Symbol::from_number(106).unwrap(), Symbol::DoubleBar);
    }

    #[test]
    fn triple_bar_from_number() {
        assert_eq!(Symbol::from_number(107).unwrap(), Symbol::TripleBar);
        assert_eq!(Symbol::from_number(117).unwrap(), Symbol::TripleBar);
    }

    #[test]
    fn seven_from_number() {
        assert_eq!(Symbol::from_number(118).unwrap(), Symbol::Seven);
        assert_eq!(Symbol::from_number(125).unwrap(), Symbol::Seven);
    }

    #[test]
    fn jackpot_from_number() {
        assert_eq!(Symbol::from_number(126).unwrap(), Symbol::Jackpot);
        assert_eq!(Symbol::from_number(127).unwrap(), Symbol::Jackpot);
    }

    #[test]
    fn from_number_assert_error() {
        assert_eq!(Symbol::from_number(128), None);
    }
}