2020-10-31 14:03:18 +00:00
|
|
|
use super::dice::{AdvancementRoll, DiceRoll, DiceRollModifier};
|
2021-05-21 14:44:03 +00:00
|
|
|
use crate::parser::dice::DiceParsingError;
|
2020-10-31 14:03:18 +00:00
|
|
|
|
|
|
|
//TOOD convert these to use parse_amounts from the common dice code.
|
|
|
|
|
2020-11-04 20:09:39 +00:00
|
|
|
fn parse_modifier(input: &str) -> Result<DiceRollModifier, DiceParsingError> {
|
2021-11-05 20:52:12 +00:00
|
|
|
match input.trim() {
|
|
|
|
"bb" => Ok(DiceRollModifier::TwoBonus),
|
|
|
|
"b" => Ok(DiceRollModifier::OneBonus),
|
|
|
|
"pp" => Ok(DiceRollModifier::TwoPenalty),
|
|
|
|
"p" => Ok(DiceRollModifier::OnePenalty),
|
|
|
|
"" => Ok(DiceRollModifier::Normal),
|
|
|
|
_ => Err(DiceParsingError::InvalidModifiers),
|
2020-10-31 20:29:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-04 20:09:39 +00:00
|
|
|
//Make diceroll take a vec of Amounts
|
|
|
|
//Split based on :, send first part to parse_modifier.
|
|
|
|
//Send second part to parse_amounts
|
2020-10-31 14:03:18 +00:00
|
|
|
pub fn parse_regular_roll(input: &str) -> Result<DiceRoll, DiceParsingError> {
|
2021-11-05 20:52:12 +00:00
|
|
|
let (amount, modifiers_str) = crate::parser::dice::parse_single_amount(input)?;
|
2020-11-04 20:09:39 +00:00
|
|
|
let modifier = parse_modifier(modifiers_str)?;
|
2021-05-13 20:24:17 +00:00
|
|
|
Ok(DiceRoll { modifier, amount })
|
2020-10-31 14:03:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn parse_advancement_roll(input: &str) -> Result<AdvancementRoll, DiceParsingError> {
|
|
|
|
let input = input.trim();
|
2021-11-05 20:52:12 +00:00
|
|
|
let (amounts, unconsumed_input) = crate::parser::dice::parse_single_amount(input)?;
|
2020-10-31 14:03:18 +00:00
|
|
|
|
2021-11-05 20:52:12 +00:00
|
|
|
if unconsumed_input.len() == 0 {
|
|
|
|
Ok(AdvancementRoll {
|
|
|
|
existing_skill: amounts,
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
Err(DiceParsingError::InvalidAmount)
|
|
|
|
}
|
2020-10-31 13:52:46 +00:00
|
|
|
}
|
|
|
|
|
2020-10-31 14:03:18 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
2021-11-05 20:52:12 +00:00
|
|
|
use crate::parser::dice::{Amount, DiceParsingError, Element, Operator};
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_modifier_rejects_bad_value() {
|
|
|
|
let modifier = parse_modifier("qqq");
|
|
|
|
assert!(matches!(modifier, Err(DiceParsingError::InvalidModifiers)))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_modifier_accepts_one_bonus() {
|
|
|
|
let modifier = parse_modifier("b");
|
|
|
|
assert!(matches!(modifier, Ok(DiceRollModifier::OneBonus)))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_modifier_accepts_two_bonus() {
|
|
|
|
let modifier = parse_modifier("bb");
|
|
|
|
assert!(matches!(modifier, Ok(DiceRollModifier::TwoBonus)))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_modifier_accepts_two_penalty() {
|
|
|
|
let modifier = parse_modifier("pp");
|
|
|
|
assert!(matches!(modifier, Ok(DiceRollModifier::TwoPenalty)))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_modifier_accepts_one_penalty() {
|
|
|
|
let modifier = parse_modifier("p");
|
|
|
|
assert!(matches!(modifier, Ok(DiceRollModifier::OnePenalty)))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_modifier_accepts_normal() {
|
|
|
|
let modifier = parse_modifier("");
|
|
|
|
assert!(matches!(modifier, Ok(DiceRollModifier::Normal)))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_modifier_accepts_normal_unaffected_by_whitespace() {
|
|
|
|
let modifier = parse_modifier(" ");
|
|
|
|
assert!(matches!(modifier, Ok(DiceRollModifier::Normal)))
|
|
|
|
}
|
2020-10-31 14:03:18 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn regular_roll_accepts_single_number() {
|
|
|
|
let result = parse_regular_roll("60");
|
|
|
|
assert!(result.is_ok());
|
|
|
|
assert_eq!(
|
|
|
|
DiceRoll {
|
2021-05-13 20:24:17 +00:00
|
|
|
amount: Amount {
|
2020-11-04 20:09:39 +00:00
|
|
|
operator: Operator::Plus,
|
|
|
|
element: Element::Number(60)
|
2021-05-13 20:24:17 +00:00
|
|
|
},
|
2020-10-31 14:03:18 +00:00
|
|
|
modifier: DiceRollModifier::Normal
|
|
|
|
},
|
|
|
|
result.unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-05-13 20:24:17 +00:00
|
|
|
#[test]
|
|
|
|
fn regular_roll_rejects_complex_expressions() {
|
|
|
|
let result = parse_regular_roll("3 + abc + bob - 4");
|
|
|
|
assert!(result.is_err());
|
|
|
|
}
|
|
|
|
|
2020-10-31 20:29:55 +00:00
|
|
|
#[test]
|
|
|
|
fn regular_roll_accepts_two_bonus() {
|
2021-11-05 20:52:12 +00:00
|
|
|
let result = parse_regular_roll("60 bb");
|
2020-10-31 20:29:55 +00:00
|
|
|
assert!(result.is_ok());
|
|
|
|
assert_eq!(
|
|
|
|
DiceRoll {
|
2021-05-13 20:24:17 +00:00
|
|
|
amount: Amount {
|
2020-11-04 20:09:39 +00:00
|
|
|
operator: Operator::Plus,
|
|
|
|
element: Element::Number(60)
|
2021-05-13 20:24:17 +00:00
|
|
|
},
|
2020-10-31 20:29:55 +00:00
|
|
|
modifier: DiceRollModifier::TwoBonus
|
|
|
|
},
|
|
|
|
result.unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn regular_roll_accepts_one_bonus() {
|
2021-11-05 20:52:12 +00:00
|
|
|
let result = parse_regular_roll("60 b");
|
2020-10-31 20:29:55 +00:00
|
|
|
assert!(result.is_ok());
|
|
|
|
assert_eq!(
|
|
|
|
DiceRoll {
|
2021-05-13 20:24:17 +00:00
|
|
|
amount: Amount {
|
2020-11-04 20:09:39 +00:00
|
|
|
operator: Operator::Plus,
|
|
|
|
element: Element::Number(60)
|
2021-05-13 20:24:17 +00:00
|
|
|
},
|
2020-10-31 20:29:55 +00:00
|
|
|
modifier: DiceRollModifier::OneBonus
|
|
|
|
},
|
|
|
|
result.unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn regular_roll_accepts_two_penalty() {
|
2021-11-05 20:52:12 +00:00
|
|
|
let result = parse_regular_roll("60 pp");
|
2020-10-31 20:29:55 +00:00
|
|
|
assert!(result.is_ok());
|
|
|
|
assert_eq!(
|
|
|
|
DiceRoll {
|
2021-05-13 20:24:17 +00:00
|
|
|
amount: Amount {
|
2020-11-04 20:09:39 +00:00
|
|
|
operator: Operator::Plus,
|
|
|
|
element: Element::Number(60)
|
2021-05-13 20:24:17 +00:00
|
|
|
},
|
2020-10-31 20:29:55 +00:00
|
|
|
modifier: DiceRollModifier::TwoPenalty
|
|
|
|
},
|
|
|
|
result.unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn regular_roll_accepts_one_penalty() {
|
2021-11-05 20:52:12 +00:00
|
|
|
let result = parse_regular_roll("60 p");
|
2020-10-31 20:29:55 +00:00
|
|
|
assert!(result.is_ok());
|
|
|
|
assert_eq!(
|
|
|
|
DiceRoll {
|
2021-05-13 20:24:17 +00:00
|
|
|
amount: Amount {
|
2020-11-04 20:09:39 +00:00
|
|
|
operator: Operator::Plus,
|
|
|
|
element: Element::Number(60)
|
2021-05-13 20:24:17 +00:00
|
|
|
},
|
2020-10-31 20:29:55 +00:00
|
|
|
modifier: DiceRollModifier::OnePenalty
|
|
|
|
},
|
|
|
|
result.unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-10-31 14:03:18 +00:00
|
|
|
#[test]
|
2021-05-13 20:24:17 +00:00
|
|
|
fn regular_roll_accepts_whitespace() {
|
2020-10-31 14:03:18 +00:00
|
|
|
assert!(parse_regular_roll("60 ").is_ok());
|
|
|
|
assert!(parse_regular_roll(" 60").is_ok());
|
|
|
|
assert!(parse_regular_roll(" 60 ").is_ok());
|
2020-10-31 20:29:55 +00:00
|
|
|
|
2021-11-05 20:52:12 +00:00
|
|
|
assert!(parse_regular_roll("60bb ").is_ok());
|
|
|
|
assert!(parse_regular_roll(" 60 bb").is_ok());
|
|
|
|
assert!(parse_regular_roll(" 60 bb ").is_ok());
|
2020-10-31 20:29:55 +00:00
|
|
|
|
2021-11-05 20:52:12 +00:00
|
|
|
assert!(parse_regular_roll("60b ").is_ok());
|
|
|
|
assert!(parse_regular_roll(" 60 b").is_ok());
|
|
|
|
assert!(parse_regular_roll(" 60 b ").is_ok());
|
2020-10-31 20:29:55 +00:00
|
|
|
|
2021-11-05 20:52:12 +00:00
|
|
|
assert!(parse_regular_roll("60pp ").is_ok());
|
|
|
|
assert!(parse_regular_roll(" 60 pp").is_ok());
|
|
|
|
assert!(parse_regular_roll(" 60 pp ").is_ok());
|
2020-10-31 20:29:55 +00:00
|
|
|
|
2021-11-05 20:52:12 +00:00
|
|
|
assert!(parse_regular_roll("60p ").is_ok());
|
|
|
|
assert!(parse_regular_roll(" 60p ").is_ok());
|
|
|
|
assert!(parse_regular_roll(" 60 p ").is_ok());
|
2020-10-31 14:03:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn advancement_roll_accepts_whitespacen() {
|
|
|
|
assert!(parse_advancement_roll("60 ").is_ok());
|
|
|
|
assert!(parse_advancement_roll(" 60").is_ok());
|
|
|
|
assert!(parse_advancement_roll(" 60 ").is_ok());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn advancement_roll_accepts_single_number() {
|
|
|
|
let result = parse_advancement_roll("60");
|
|
|
|
assert!(result.is_ok());
|
2021-03-18 20:54:49 +00:00
|
|
|
assert_eq!(
|
|
|
|
AdvancementRoll {
|
2021-05-13 20:24:17 +00:00
|
|
|
existing_skill: Amount {
|
2021-03-18 20:54:49 +00:00
|
|
|
operator: Operator::Plus,
|
|
|
|
element: Element::Number(60)
|
2021-05-13 20:24:17 +00:00
|
|
|
}
|
2021-03-18 20:54:49 +00:00
|
|
|
},
|
|
|
|
result.unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn advancement_roll_allows_big_numbers() {
|
|
|
|
assert!(parse_advancement_roll("3000").is_ok());
|
2020-10-31 14:03:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2021-03-18 20:54:49 +00:00
|
|
|
fn advancement_roll_allows_variables() {
|
|
|
|
let result = parse_advancement_roll("abc");
|
|
|
|
assert!(result.is_ok());
|
|
|
|
assert_eq!(
|
|
|
|
AdvancementRoll {
|
2021-05-13 20:24:17 +00:00
|
|
|
existing_skill: Amount {
|
2021-03-18 20:54:49 +00:00
|
|
|
operator: Operator::Plus,
|
|
|
|
element: Element::Variable(String::from("abc"))
|
2021-05-13 20:24:17 +00:00
|
|
|
}
|
2021-03-18 20:54:49 +00:00
|
|
|
},
|
|
|
|
result.unwrap()
|
|
|
|
);
|
2020-10-31 14:03:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2021-05-13 20:24:17 +00:00
|
|
|
fn advancement_roll_rejects_complex_expressions() {
|
2021-03-18 20:54:49 +00:00
|
|
|
let result = parse_advancement_roll("3 + abc + bob - 4");
|
2021-05-13 20:24:17 +00:00
|
|
|
assert!(result.is_err());
|
2020-10-31 14:03:18 +00:00
|
|
|
}
|
2020-10-31 13:52:46 +00:00
|
|
|
}
|