diff --git a/src/lib.rs b/src/lib.rs index ca2b715..8d42251 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -147,8 +147,10 @@ struct Roll { enum RollError { #[error("Roll failed. Empty RollWithModifier")] EmptyRollWithModifier, - #[error("Roll failed. Invalid filter operator")] - InvalidFilterOperator, + #[error("Roll failed. Invalid filter operator '{0}'")] + InvalidFilterOperator(char), + #[error("Roll failed. Invalid segment operator '{0}'")] + InvalidOperator(char), } fn roll_dice_segments(rwms: &[RollWithModifier], mut rng: R) -> Result, RollError> { @@ -203,7 +205,7 @@ fn roll_dice_segments(rwms: &[RollWithModifier], mut rng: R) -> Result { total /= amount; }, '*' => { total *= amount; }, _ => { - return Err(RollError::InvalidFilterOperator); + return Err(RollError::InvalidFilterOperator(*op)); }, } } @@ -212,4 +214,25 @@ fn roll_dice_segments(rwms: &[RollWithModifier], mut rng: R) -> Result,_>>() -} \ No newline at end of file +} + +fn roll_dice(s: &str, mut rng: R) -> Result<(i32, Vec<(Roll, Vec)>)> { + let segments = parse_dice_segments(s)?; + + let groups = group_modifiers_to_dicerolls(&segments); + + let rolls = roll_dice_segments(&groups, &mut rng)?; + + let total = rolls.iter().try_fold(0, |acc,roll| match roll.operator { + '+' => Ok(acc + roll.total), + '-' => Ok(acc - roll.total), + '*' => Ok(acc * roll.total), + '/' => Ok(acc / roll.total), + _ => Err(RollError::InvalidOperator(roll.operator)) + })?; + + let rolls_with_modifiers = rolls.into_iter() + .zip(groups.into_iter().map(|grp| grp.modifiers)).collect(); + + Ok((total, rolls_with_modifiers)) +} diff --git a/src/lib_test.rs b/src/lib_test.rs index 307a24e..dbed58c 100644 --- a/src/lib_test.rs +++ b/src/lib_test.rs @@ -111,3 +111,35 @@ fn test_roll_dice_segments() { Roll{operator: '*', results: vec![6], total: 4}, ])); } + +#[test] +fn test_roll_dice() { + + let input = "4d6d2 + 2 - 1d4"; + + let mut rng = StdRng::seed_from_u64(2); + + let result = roll_dice(input, &mut rng); + + let expected = (8i32, vec![ + (Roll { + operator: '+', + results: vec![5, 5], + total: 12 + }, + vec![Segment::Modifier { op: '+', amount: 2 }]), + + (Roll { + operator: '-', + results: vec![4], + total: 4 + }, + vec![])]); + + if let Ok(result) = result { + assert_eq!(result, expected); + } else { + panic!("Expected Ok, was: {:?}", result); + } + +}