Composed parsing and rolling functionality into roll_dice function

This commit is contained in:
Ådne E. Moldesæter 2020-08-27 20:19:13 +02:00
parent c8de11d2b1
commit 6a1f5b6035
2 changed files with 59 additions and 4 deletions

View File

@ -147,8 +147,10 @@ struct Roll {
enum RollError { enum RollError {
#[error("Roll failed. Empty RollWithModifier")] #[error("Roll failed. Empty RollWithModifier")]
EmptyRollWithModifier, EmptyRollWithModifier,
#[error("Roll failed. Invalid filter operator")] #[error("Roll failed. Invalid filter operator '{0}'")]
InvalidFilterOperator, InvalidFilterOperator(char),
#[error("Roll failed. Invalid segment operator '{0}'")]
InvalidOperator(char),
} }
fn roll_dice_segments<R: Rng>(rwms: &[RollWithModifier], mut rng: R) -> Result<Vec<Roll>, RollError> { fn roll_dice_segments<R: Rng>(rwms: &[RollWithModifier], mut rng: R) -> Result<Vec<Roll>, RollError> {
@ -203,7 +205,7 @@ fn roll_dice_segments<R: Rng>(rwms: &[RollWithModifier], mut rng: R) -> Result<V
'/' => { total /= amount; }, '/' => { total /= amount; },
'*' => { total *= amount; }, '*' => { total *= amount; },
_ => { _ => {
return Err(RollError::InvalidFilterOperator); return Err(RollError::InvalidFilterOperator(*op));
}, },
} }
} }
@ -212,4 +214,25 @@ fn roll_dice_segments<R: Rng>(rwms: &[RollWithModifier], mut rng: R) -> Result<V
Ok(Roll{operator, results, total}) Ok(Roll{operator, results, total})
}) })
.collect::<Result<Vec<_>,_>>() .collect::<Result<Vec<_>,_>>()
} }
fn roll_dice<R : Rng>(s: &str, mut rng: R) -> Result<(i32, Vec<(Roll, Vec<Segment>)>)> {
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))
}

View File

@ -111,3 +111,35 @@ fn test_roll_dice_segments() {
Roll{operator: '*', results: vec![6], total: 4}, 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);
}
}