tenebrous-dicebot/src/commands.rs

176 lines
4.8 KiB
Rust
Raw Normal View History

use crate::cofd::dice::DicePool;
use crate::dice::ElementExpression;
Dice pool and command parser rewrite to prepare for user variables. This commit refactors the parsing and rolling for the dice pool system to prepare for support of user variables. The nom parser was dropped in favor of the easier-to-understand combine parser in most parts of the code. A breaking change was introduced into the dice pool syntax to allow for proper expressions and variables. The syntax is now "modifiers:pool-amount", e.g. "n:gnosis+8". The simple single-number syntax with no modifiers is also still understood. Dice pool expressions are translated into a Vec of "Amount" objects, stored by the DicePool struct. They have an operator (+ or -) and either a number or variable name. When the dice pool is rolled, this list of Amonuts are is collapsed into a single number that is rolled, as it was before the refactor. The following changes were made to the dice rolling code: - Store Vec<Amount> on DicePool instead of single number to roll. - New struct RolledDicePool to store result of a dice pool roll. - Remove Display trait from DicePool, move it over to RolledDicePool. - Separate extra dice pool info into DicePoolModifiers. - DicePoolModifiers is shared between DicePool and RolledDicePool. - Dice parsing and rolling now return standard Result objects. This commit does NOT enable support of actually using variables. Any dice pool roll containing a variable will result in an eror. The command parser was also rewritten to use combine and rely on the standard Result pattern.
2020-10-04 21:32:50 +00:00
use crate::error::BotError;
use crate::help::HelpTopic;
2020-04-21 06:09:43 +00:00
use crate::roll::Roll;
pub mod parser;
2020-04-21 06:07:03 +00:00
pub struct Execution {
plain: String,
html: String,
}
2020-04-21 06:07:03 +00:00
impl Execution {
pub fn plain(&self) -> &str {
&self.plain
}
2020-04-21 06:07:03 +00:00
pub fn html(&self) -> &str {
&self.html
}
}
pub trait Command {
fn execute(&self) -> Execution;
fn name(&self) -> &'static str;
2020-04-21 06:07:03 +00:00
}
pub struct RollCommand(ElementExpression);
2020-04-21 06:07:03 +00:00
impl Command for RollCommand {
fn name(&self) -> &'static str {
"roll regular dice"
}
2020-04-21 06:07:03 +00:00
fn execute(&self) -> Execution {
let roll = self.0.roll();
let plain = format!("Dice: {}\nResult: {}", self.0, roll);
2020-04-21 06:09:43 +00:00
let html = format!(
2020-04-22 04:19:15 +00:00
"<p><strong>Dice:</strong> {}</p><p><strong>Result</strong>: {}</p>",
2020-04-21 06:09:43 +00:00
self.0, roll
);
Execution { plain, html }
}
}
pub struct PoolRollCommand(DicePool);
impl Command for PoolRollCommand {
fn name(&self) -> &'static str {
"roll dice pool"
}
fn execute(&self) -> Execution {
Dice pool and command parser rewrite to prepare for user variables. This commit refactors the parsing and rolling for the dice pool system to prepare for support of user variables. The nom parser was dropped in favor of the easier-to-understand combine parser in most parts of the code. A breaking change was introduced into the dice pool syntax to allow for proper expressions and variables. The syntax is now "modifiers:pool-amount", e.g. "n:gnosis+8". The simple single-number syntax with no modifiers is also still understood. Dice pool expressions are translated into a Vec of "Amount" objects, stored by the DicePool struct. They have an operator (+ or -) and either a number or variable name. When the dice pool is rolled, this list of Amonuts are is collapsed into a single number that is rolled, as it was before the refactor. The following changes were made to the dice rolling code: - Store Vec<Amount> on DicePool instead of single number to roll. - New struct RolledDicePool to store result of a dice pool roll. - Remove Display trait from DicePool, move it over to RolledDicePool. - Separate extra dice pool info into DicePoolModifiers. - DicePoolModifiers is shared between DicePool and RolledDicePool. - Dice parsing and rolling now return standard Result objects. This commit does NOT enable support of actually using variables. Any dice pool roll containing a variable will result in an eror. The command parser was also rewritten to use combine and rely on the standard Result pattern.
2020-10-04 21:32:50 +00:00
let roll_result = self.0.roll();
let (plain, html) = match roll_result {
Ok(rolled_pool) => {
let plain = format!("Pool: {}\nResult: {}", rolled_pool, rolled_pool.roll);
let html = format!(
"<p><strong>Pool:</strong> {}</p><p><strong>Result</strong>: {}</p>",
rolled_pool, rolled_pool.roll
);
(plain, html)
}
Err(e) => {
let plain = format!("Error: {}", e);
let html = format!("<p><strong>Error:</strong> {}</p>", e);
(plain, html)
}
};
Execution { plain, html }
}
}
pub struct HelpCommand(Option<HelpTopic>);
impl Command for HelpCommand {
fn name(&self) -> &'static str {
"help information"
}
fn execute(&self) -> Execution {
let help = match &self.0 {
Some(topic) => topic.message(),
_ => "There is no help for this topic",
};
let plain = format!("Help: {}", help);
let html = format!("<p><strong>Help:</strong> {}", help.replace("\n", "<br/>"));
Execution { plain, html }
}
}
/// Parse a command string into a dynamic command execution trait
/// object. Returns an error if a command was recognized but not
/// parsed correctly. Returns Ok(None) if no command was recognized.
Dice pool and command parser rewrite to prepare for user variables. This commit refactors the parsing and rolling for the dice pool system to prepare for support of user variables. The nom parser was dropped in favor of the easier-to-understand combine parser in most parts of the code. A breaking change was introduced into the dice pool syntax to allow for proper expressions and variables. The syntax is now "modifiers:pool-amount", e.g. "n:gnosis+8". The simple single-number syntax with no modifiers is also still understood. Dice pool expressions are translated into a Vec of "Amount" objects, stored by the DicePool struct. They have an operator (+ or -) and either a number or variable name. When the dice pool is rolled, this list of Amonuts are is collapsed into a single number that is rolled, as it was before the refactor. The following changes were made to the dice rolling code: - Store Vec<Amount> on DicePool instead of single number to roll. - New struct RolledDicePool to store result of a dice pool roll. - Remove Display trait from DicePool, move it over to RolledDicePool. - Separate extra dice pool info into DicePoolModifiers. - DicePoolModifiers is shared between DicePool and RolledDicePool. - Dice parsing and rolling now return standard Result objects. This commit does NOT enable support of actually using variables. Any dice pool roll containing a variable will result in an eror. The command parser was also rewritten to use combine and rely on the standard Result pattern.
2020-10-04 21:32:50 +00:00
pub fn parse_command(s: &str) -> Result<Option<Box<dyn Command>>, BotError> {
// match parser::parse_command(s) {
// Ok(Some(command)) => match &command {
// //Any command, or text transformed into non-command is
// //sent upwards.
// ("", Some(_)) | (_, None) => Ok(command),
// //TODO replcae with nom all_consuming?
// //Any unconsumed input (whitespace should already be
// // stripped) is considered a parsing error.
// _ => Err(format!("{}: malformed expression", s)),
// },
// Err(err) => Err(err),
// }
parser::parse_command(s)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn chance_die_is_not_malformed() {
assert!(parse_command("!chance").is_ok());
}
#[test]
fn roll_malformed_expression_test() {
assert!(parse_command("!roll 1d20asdlfkj").is_err());
assert!(parse_command("!roll 1d20asdlfkj ").is_err());
}
#[test]
fn roll_dice_pool_malformed_expression_test() {
assert!(parse_command("!pool 8abc").is_err());
assert!(parse_command("!pool 8abc ").is_err());
}
#[test]
fn pool_whitespace_test() {
Dice pool and command parser rewrite to prepare for user variables. This commit refactors the parsing and rolling for the dice pool system to prepare for support of user variables. The nom parser was dropped in favor of the easier-to-understand combine parser in most parts of the code. A breaking change was introduced into the dice pool syntax to allow for proper expressions and variables. The syntax is now "modifiers:pool-amount", e.g. "n:gnosis+8". The simple single-number syntax with no modifiers is also still understood. Dice pool expressions are translated into a Vec of "Amount" objects, stored by the DicePool struct. They have an operator (+ or -) and either a number or variable name. When the dice pool is rolled, this list of Amonuts are is collapsed into a single number that is rolled, as it was before the refactor. The following changes were made to the dice rolling code: - Store Vec<Amount> on DicePool instead of single number to roll. - New struct RolledDicePool to store result of a dice pool roll. - Remove Display trait from DicePool, move it over to RolledDicePool. - Separate extra dice pool info into DicePoolModifiers. - DicePoolModifiers is shared between DicePool and RolledDicePool. - Dice parsing and rolling now return standard Result objects. This commit does NOT enable support of actually using variables. Any dice pool roll containing a variable will result in an eror. The command parser was also rewritten to use combine and rely on the standard Result pattern.
2020-10-04 21:32:50 +00:00
assert!(parse_command("!pool ns3:8 ")
.map(|p| p.is_some())
.expect("was error"));
Dice pool and command parser rewrite to prepare for user variables. This commit refactors the parsing and rolling for the dice pool system to prepare for support of user variables. The nom parser was dropped in favor of the easier-to-understand combine parser in most parts of the code. A breaking change was introduced into the dice pool syntax to allow for proper expressions and variables. The syntax is now "modifiers:pool-amount", e.g. "n:gnosis+8". The simple single-number syntax with no modifiers is also still understood. Dice pool expressions are translated into a Vec of "Amount" objects, stored by the DicePool struct. They have an operator (+ or -) and either a number or variable name. When the dice pool is rolled, this list of Amonuts are is collapsed into a single number that is rolled, as it was before the refactor. The following changes were made to the dice rolling code: - Store Vec<Amount> on DicePool instead of single number to roll. - New struct RolledDicePool to store result of a dice pool roll. - Remove Display trait from DicePool, move it over to RolledDicePool. - Separate extra dice pool info into DicePoolModifiers. - DicePoolModifiers is shared between DicePool and RolledDicePool. - Dice parsing and rolling now return standard Result objects. This commit does NOT enable support of actually using variables. Any dice pool roll containing a variable will result in an eror. The command parser was also rewritten to use combine and rely on the standard Result pattern.
2020-10-04 21:32:50 +00:00
assert!(parse_command(" !pool ns3:8")
.map(|p| p.is_some())
.expect("was error"));
Dice pool and command parser rewrite to prepare for user variables. This commit refactors the parsing and rolling for the dice pool system to prepare for support of user variables. The nom parser was dropped in favor of the easier-to-understand combine parser in most parts of the code. A breaking change was introduced into the dice pool syntax to allow for proper expressions and variables. The syntax is now "modifiers:pool-amount", e.g. "n:gnosis+8". The simple single-number syntax with no modifiers is also still understood. Dice pool expressions are translated into a Vec of "Amount" objects, stored by the DicePool struct. They have an operator (+ or -) and either a number or variable name. When the dice pool is rolled, this list of Amonuts are is collapsed into a single number that is rolled, as it was before the refactor. The following changes were made to the dice rolling code: - Store Vec<Amount> on DicePool instead of single number to roll. - New struct RolledDicePool to store result of a dice pool roll. - Remove Display trait from DicePool, move it over to RolledDicePool. - Separate extra dice pool info into DicePoolModifiers. - DicePoolModifiers is shared between DicePool and RolledDicePool. - Dice parsing and rolling now return standard Result objects. This commit does NOT enable support of actually using variables. Any dice pool roll containing a variable will result in an eror. The command parser was also rewritten to use combine and rely on the standard Result pattern.
2020-10-04 21:32:50 +00:00
assert!(parse_command(" !pool ns3:8 ")
.map(|p| p.is_some())
.expect("was error"));
}
#[test]
fn help_whitespace_test() {
assert!(parse_command("!help stuff ")
.map(|p| p.is_some())
.expect("was error"));
assert!(parse_command(" !help stuff")
.map(|p| p.is_some())
.expect("was error"));
assert!(parse_command(" !help stuff ")
.map(|p| p.is_some())
.expect("was error"));
}
#[test]
fn roll_whitespace_test() {
assert!(parse_command("!roll 1d4 + 5d6 -3 ")
.map(|p| p.is_some())
.expect("was error"));
assert!(parse_command("!roll 1d4 + 5d6 -3 ")
.map(|p| p.is_some())
.expect("was error"));
assert!(parse_command(" !roll 1d4 + 5d6 -3 ")
.map(|p| p.is_some())
.expect("was error"));
}
}