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
extern crate rand; use rand:: Rng; use rand::distributions::{Range, IndependentSample}; #[derive(Debug, PartialEq, Eq)] pub struct Dice { number: u32, sides: u32, } impl Dice { pub fn parse(dice: &str) -> Result<Dice, &str> { let tokens: Vec<&str> = dice.split("d").collect(); if tokens.len() != 2 { return Err("Invalid format"); } let number = match tokens[0].parse() { Ok(num) => num, Err(_) => return Err("Expected valid number of dice"), }; let sides = match tokens[1].parse() { Ok(num) => num, Err(_) => return Err("Expected valid number of sides"), }; Ok(Dice { number, sides }) } pub fn generate<R: Rng>(&self, mut rng: &mut R) -> u32 { let between = Range::new(1, self.sides); let mut total = 0; for _ in 0..self.number { total += between.ind_sample(&mut rng); } total } } #[cfg(test)] mod test { use super::*; use rand::{SeedableRng, StdRng}; #[test] fn dice_generate() { let dice = Dice { sides: 6, number: 4 }; let seed: &[_] = &[1, 2, 3, 4]; let mut rng: StdRng = SeedableRng::from_seed(seed); let result = dice.generate(&mut rng); assert_eq!(result, 10); let mut rng = rand::thread_rng(); for _ in 1..100 { let result = dice.generate(&mut rng); assert!(result >= 4); assert!(result <= 24); } } #[test] fn dice_parse_none() { assert!(Dice::parse("d6").is_err()); assert!(Dice::parse("1d").is_err()); assert!(Dice::parse("").is_err()); assert!(Dice::parse("something").is_err()); } #[test] fn dice_parse_correct() { assert_eq!( Dice::parse("6d100"), Ok(Dice { number: 6, sides: 100 })); assert_eq!( Dice::parse("1d5"), Ok(Dice { number: 1, sides: 5})); } }