diff --git a/src/cthulhu/dice.rs b/src/cthulhu/dice.rs index 0a4f9e2..0c4f0da 100644 --- a/src/cthulhu/dice.rs +++ b/src/cthulhu/dice.rs @@ -1,5 +1,5 @@ use crate::context::Context; -use crate::dice::calculate_dice_amount; +use crate::dice::calculate_single_die_amount; use crate::error::{BotError, DiceRollingError}; use crate::parser::Amount; use std::convert::TryFrom; @@ -8,7 +8,7 @@ use std::fmt; /// A planned dice roll. #[derive(Clone, Debug, PartialEq)] pub struct DiceRoll { - pub amounts: Vec, + pub amount: Amount, pub modifier: DiceRollModifier, } @@ -188,7 +188,7 @@ impl fmt::Display for RolledDice { pub struct AdvancementRoll { /// The amount (0 to 100) of the existing skill. We must beat this /// target number to advance the skill, or roll above a 95. - pub existing_skill: Vec, + pub existing_skill: Amount, } impl fmt::Display for AdvancementRoll { @@ -343,14 +343,14 @@ fn roll_advancement_dice(target: u32, roller: &mut R) -> RolledAdv pub async fn regular_roll( roll_with_ctx: &DiceRollWithContext<'_>, ) -> Result { - let target = calculate_dice_amount(&roll_with_ctx.0.amounts, roll_with_ctx.1).await?; + let target = calculate_single_die_amount(&roll_with_ctx.0.amount, roll_with_ctx.1).await?; let target = u32::try_from(target).map_err(|_| DiceRollingError::InvalidAmount)?; let mut roller = RngDieRoller(rand::thread_rng()); let rolled_dice = roll_regular_dice(&roll_with_ctx.0.modifier, target, &mut roller); Ok(ExecutedDiceRoll { - target: target, + target, modifier: roll_with_ctx.0.modifier, roll: rolled_dice, }) @@ -359,7 +359,9 @@ pub async fn regular_roll( pub async fn advancement_roll( roll_with_ctx: &AdvancementRollWithContext<'_>, ) -> Result { - let target = calculate_dice_amount(&roll_with_ctx.0.existing_skill, roll_with_ctx.1).await?; + let target = + calculate_single_die_amount(&roll_with_ctx.0.existing_skill, roll_with_ctx.1).await?; + let target = u32::try_from(target).map_err(|_| DiceRollingError::InvalidAmount)?; if target > 100 { @@ -416,10 +418,10 @@ mod tests { #[tokio::test] async fn regular_roll_rejects_negative_numbers() { let roll = DiceRoll { - amounts: vec![Amount { + amount: Amount { operator: Operator::Plus, element: Element::Number(-10), - }], + }, modifier: DiceRollModifier::Normal, }; @@ -445,10 +447,10 @@ mod tests { #[tokio::test] async fn advancement_roll_rejects_negative_numbers() { let roll = AdvancementRoll { - existing_skill: vec![Amount { + existing_skill: Amount { operator: Operator::Plus, element: Element::Number(-10), - }], + }, }; let db = Database::new_temp().unwrap(); @@ -473,10 +475,10 @@ mod tests { #[tokio::test] async fn advancement_roll_rejects_big_numbers() { let roll = AdvancementRoll { - existing_skill: vec![Amount { + existing_skill: Amount { operator: Operator::Plus, element: Element::Number(3000), - }], + }, }; let db = Database::new_temp().unwrap(); diff --git a/src/cthulhu/parser.rs b/src/cthulhu/parser.rs index 6d895b5..27c5274 100644 --- a/src/cthulhu/parser.rs +++ b/src/cthulhu/parser.rs @@ -20,7 +20,6 @@ fn parse_modifier(input: &str) -> Result { //Make diceroll take a vec of Amounts //Split based on :, send first part to parse_modifier. //Send second part to parse_amounts - pub fn parse_regular_roll(input: &str) -> Result { let input: Vec<&str> = input.trim().split(":").collect(); @@ -31,14 +30,13 @@ pub fn parse_regular_roll(input: &str) -> Result { }?; let modifier = parse_modifier(modifiers_str)?; - let amounts = crate::parser::parse_amounts(amounts_str)?; - - Ok(DiceRoll { modifier, amounts }) + let amount = crate::parser::parse_single_amount(amounts_str)?; + Ok(DiceRoll { modifier, amount }) } pub fn parse_advancement_roll(input: &str) -> Result { let input = input.trim(); - let amounts = crate::parser::parse_amounts(input)?; + let amounts = crate::parser::parse_single_amount(input)?; Ok(AdvancementRoll { existing_skill: amounts, @@ -57,26 +55,32 @@ mod tests { assert!(result.is_ok()); assert_eq!( DiceRoll { - amounts: vec![Amount { + amount: Amount { operator: Operator::Plus, element: Element::Number(60) - }], + }, modifier: DiceRollModifier::Normal }, result.unwrap() ); } + #[test] + fn regular_roll_rejects_complex_expressions() { + let result = parse_regular_roll("3 + abc + bob - 4"); + assert!(result.is_err()); + } + #[test] fn regular_roll_accepts_two_bonus() { let result = parse_regular_roll("bb:60"); assert!(result.is_ok()); assert_eq!( DiceRoll { - amounts: vec![Amount { + amount: Amount { operator: Operator::Plus, element: Element::Number(60) - }], + }, modifier: DiceRollModifier::TwoBonus }, result.unwrap() @@ -89,10 +93,10 @@ mod tests { assert!(result.is_ok()); assert_eq!( DiceRoll { - amounts: vec![Amount { + amount: Amount { operator: Operator::Plus, element: Element::Number(60) - }], + }, modifier: DiceRollModifier::OneBonus }, result.unwrap() @@ -105,10 +109,10 @@ mod tests { assert!(result.is_ok()); assert_eq!( DiceRoll { - amounts: vec![Amount { + amount: Amount { operator: Operator::Plus, element: Element::Number(60) - }], + }, modifier: DiceRollModifier::TwoPenalty }, result.unwrap() @@ -121,10 +125,10 @@ mod tests { assert!(result.is_ok()); assert_eq!( DiceRoll { - amounts: vec![Amount { + amount: Amount { operator: Operator::Plus, element: Element::Number(60) - }], + }, modifier: DiceRollModifier::OnePenalty }, result.unwrap() @@ -132,7 +136,7 @@ mod tests { } #[test] - fn regular_roll_accepts_whitespacen() { + fn regular_roll_accepts_whitespace() { assert!(parse_regular_roll("60 ").is_ok()); assert!(parse_regular_roll(" 60").is_ok()); assert!(parse_regular_roll(" 60 ").is_ok()); @@ -167,10 +171,10 @@ mod tests { assert!(result.is_ok()); assert_eq!( AdvancementRoll { - existing_skill: vec![Amount { + existing_skill: Amount { operator: Operator::Plus, element: Element::Number(60) - }] + } }, result.unwrap() ); @@ -187,41 +191,18 @@ mod tests { assert!(result.is_ok()); assert_eq!( AdvancementRoll { - existing_skill: vec![Amount { + existing_skill: Amount { operator: Operator::Plus, element: Element::Variable(String::from("abc")) - }] + } }, result.unwrap() ); } #[test] - fn advancement_roll_allows_complex_expressions() { + fn advancement_roll_rejects_complex_expressions() { let result = parse_advancement_roll("3 + abc + bob - 4"); - assert!(result.is_ok()); - assert_eq!( - AdvancementRoll { - existing_skill: vec![ - Amount { - operator: Operator::Plus, - element: Element::Number(3) - }, - Amount { - operator: Operator::Plus, - element: Element::Variable(String::from("abc")) - }, - Amount { - operator: Operator::Plus, - element: Element::Variable(String::from("bob")) - }, - Amount { - operator: Operator::Minus, - element: Element::Number(4) - } - ] - }, - result.unwrap() - ); + assert!(result.is_err()); } } diff --git a/src/dice.rs b/src/dice.rs index 75ae13f..5b18867 100644 --- a/src/dice.rs +++ b/src/dice.rs @@ -5,6 +5,17 @@ use crate::error::DiceRollingError; use crate::parser::Amount; use crate::parser::Element as NewElement; use futures::stream::{self, StreamExt, TryStreamExt}; +use std::slice; + +/// Calculate the amount of dice to roll by consulting the database +/// and replacing variables with corresponding the amount. Errors out +/// if it cannot find a variable defined, or if the database errors. +pub async fn calculate_single_die_amount( + amount: &Amount, + ctx: &Context<'_>, +) -> Result { + calculate_dice_amount(slice::from_ref(amount), ctx).await +} /// Calculate the amount of dice to roll by consulting the database /// and replacing variables with corresponding amounts. Errors out if diff --git a/src/parser.rs b/src/parser.rs index bc214fc..cb601f7 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -33,7 +33,7 @@ type ParseResult = Result; /// A parsed operator for a number. Whether to add or remove it from /// the total amount of dice rolled. -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum Operator { Plus, Minus,