From 3637346c1ab5826e069664772be95e46715ae529 Mon Sep 17 00:00:00 2001 From: Funnisimo Date: Tue, 23 Aug 2022 10:01:13 -0500 Subject: [PATCH 1/3] export colors mods separately to aid precise imports --- bracket-color/Cargo.toml | 6 +++--- bracket-color/examples/util/mod.rs | 2 +- bracket-color/src/lib.rs | 14 +++++++------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/bracket-color/Cargo.toml b/bracket-color/Cargo.toml index 3c5122c0..564d5439 100755 --- a/bracket-color/Cargo.toml +++ b/bracket-color/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bracket-color" -version = "0.8.2" +version = "0.8.3" authors = ["Herbert Wolverson "] edition = "2018" publish = true @@ -17,13 +17,13 @@ palette = [ "lazy_static", "parking_lot" ] [dependencies] serde = { version = "~1.0.110", features = ["derive"], optional = true } -crossterm = { version = "~0.24", optional = true } +crossterm = { version = "~0.25", optional = true } lazy_static = { version = "1.4.0", optional = true } parking_lot = { version = "~0.12", optional = true } bevy = { version = "0.8", optional = true } [dev-dependencies] -crossterm = "~0.24" +crossterm = "~0.25" [[example]] name = "colors" diff --git a/bracket-color/examples/util/mod.rs b/bracket-color/examples/util/mod.rs index cafaf439..b620f9ed 100755 --- a/bracket-color/examples/util/mod.rs +++ b/bracket-color/examples/util/mod.rs @@ -2,7 +2,7 @@ use bracket_color::prelude::*; use crossterm::queue; use crossterm::style::{Print, SetForegroundColor}; use std::convert::TryInto; -use std::io::{stdout, Write}; +use std::io::stdout; pub fn print_color(color: RGB, text: &str) { queue!(stdout(), SetForegroundColor(color.try_into().unwrap())).expect("Command Fail"); diff --git a/bracket-color/src/lib.rs b/bracket-color/src/lib.rs index ab9a0908..84721e17 100755 --- a/bracket-color/src/lib.rs +++ b/bracket-color/src/lib.rs @@ -31,20 +31,20 @@ extern crate lazy_static; /// Import color pair support -mod color_pair; +pub mod color_pair; /// Import HSV color support -mod hsv; +pub mod hsv; /// Import Lerp as an iterator -mod lerpit; +pub mod lerpit; /// Import library of named colors -mod named; +pub mod named; /// Import Palette support #[cfg(feature = "palette")] -mod palette; +pub mod palette; /// Import RGB color support -mod rgb; +pub mod rgb; /// Import RGBA color support -mod rgba; +pub mod rgba; /// Exports the color functions/types in the `prelude` namespace. pub mod prelude { From f74a2a81be46803889adebfe7c6a3edad9c8ced9 Mon Sep 17 00:00:00 2001 From: Funnisimo Date: Tue, 23 Aug 2022 10:02:40 -0500 Subject: [PATCH 2/3] use updated bracket-color --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 992aa165..c1bc8267 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ webgpu = [ "bracket-terminal/webgpu" ] [dependencies] bracket-algorithm-traits = { path = "./bracket-algorithm-traits", version = "~0.8.2" } -bracket-color = { path = "./bracket-color", version = "~0.8.2", features = [ "palette" ] } +bracket-color = { path = "./bracket-color", version = "~0.8.3", features = [ "palette" ] } bracket-geometry = { path = "./bracket-geometry", version = "~0.8.2" } bracket-noise = { path = "./bracket-noise", version = "~0.8.2" } bracket-pathfinding = { path = "./bracket-pathfinding", version = "~0.8.2" } From d699589f0b6b195fa90ed050867a08db70b46d11 Mon Sep 17 00:00:00 2001 From: Funnisimo Date: Wed, 12 Oct 2022 10:26:49 -0500 Subject: [PATCH 3/3] updated DiceType --- bracket-random/Cargo.toml | 42 +++++----- bracket-random/src/lib.rs | 4 - bracket-random/src/parsing.rs | 141 +++++++++++++++++++++++++--------- 3 files changed, 124 insertions(+), 63 deletions(-) diff --git a/bracket-random/Cargo.toml b/bracket-random/Cargo.toml index 17ae6003..904bc761 100755 --- a/bracket-random/Cargo.toml +++ b/bracket-random/Cargo.toml @@ -1,40 +1,40 @@ [package] -name = "bracket-random" -version = "0.8.7" -authors = ["Herbert Wolverson "] -edition = "2021" -publish = true +name = "bracket-random" +version = "0.8.7" +authors = ["Herbert Wolverson "] +edition = "2021" +publish = true description = "Random number generator (xorshift based), focused on dice rolling. Optionally includes parsing of RPG-style dice strings (e.g. \"3d6+12\"). Part of the bracket-lib family." -homepage = "https://github.com/thebracket/bracket-lib" -repository = "https://github.com/thebracket/bracket-lib" -readme = "README.md" -keywords = ["roguelike", "gamedev", "random", "xorshift", "dice"] -categories = ["game-engines", "random"] -license = "MIT" +homepage = "https://github.com/thebracket/bracket-lib" +repository = "https://github.com/thebracket/bracket-lib" +readme = "README.md" +keywords = ["roguelike", "gamedev", "random", "xorshift", "dice"] +categories = ["game-engines", "random"] +license = "MIT" [features] -default = [ "parsing" ] -parsing = [ "regex", "lazy_static" ] -serde = [ "serde_crate", "rand_xorshift/serde1" ] +default = ["parsing"] +parsing = [] +serde = ["serde_crate", "rand_xorshift/serde1"] [dependencies] rand_xorshift = { version = "0.3.0" } -regex = { version = "1.3.6", optional = true } -lazy_static = { version = "1.4.0", optional = true } -serde_crate = { version = "~1.0.110", features = ["derive"], optional = true, package = "serde" } +serde_crate = { version = "~1.0.110", features = [ + "derive", +], optional = true, package = "serde" } rand = { version = "0.8", default-features = false } [target.'cfg(not(any(target_arch = "wasm32")))'.dependencies] getrandom = { version = "0.2.2" } [target.wasm32-unknown-unknown.dependencies] -js-sys = "0.3.48" +js-sys = "0.3.48" wasm-bindgen = "0.2" [dev-dependencies] -criterion = "~0.4" +criterion = "~0.4" serde_json = "~1.0" [[bench]] -name = "dice" -harness = false \ No newline at end of file +name = "dice" +harness = false diff --git a/bracket-random/src/lib.rs b/bracket-random/src/lib.rs index 4ceeac61..a7f256fa 100755 --- a/bracket-random/src/lib.rs +++ b/bracket-random/src/lib.rs @@ -1,7 +1,3 @@ -#[cfg(feature = "parsing")] -#[macro_use] -extern crate lazy_static; - mod random; #[cfg(feature = "parsing")] diff --git a/bracket-random/src/parsing.rs b/bracket-random/src/parsing.rs index 0ac7ab56..af2e259f 100755 --- a/bracket-random/src/parsing.rs +++ b/bracket-random/src/parsing.rs @@ -1,6 +1,7 @@ -use regex::Regex; +use std::convert::From; use std::error; use std::fmt; +use std::str::FromStr; #[cfg(feature = "serde")] use serde_crate::{Deserialize, Serialize}; @@ -31,19 +32,51 @@ impl DiceType { impl Default for DiceType { fn default() -> DiceType { DiceType { - n_dice: 1, - die_type: 4, + n_dice: 0, + die_type: 0, bonus: 0, } } } +#[cfg(feature = "parsing")] +impl FromStr for DiceType { + type Err = DiceParseError; + + fn from_str(s: &str) -> Result { + parse_dice_string(s) + } +} + +#[cfg(feature = "parsing")] +impl From<&str> for DiceType { + fn from(text: &str) -> Self { + match parse_dice_string(text) { + Ok(d) => d, + Err(text) => panic!("Failed to convert dice string: {}", text.0), + } + } +} + +impl fmt::Display for DiceType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.n_dice { + 0 => write!(f, "{}", self.bonus), + _x => match self.bonus { + 0 => write!(f, "{}d{}", self.n_dice, self.die_type), + _x if _x > 0 => write!(f, "{}d{}+{}", self.n_dice, self.die_type, self.bonus), + _y => write!(f, "{}d{}{}", self.n_dice, self.die_type, self.bonus), + }, + } + } +} + #[derive(Debug, Clone)] -pub struct DiceParseError; +pub struct DiceParseError(String); impl std::fmt::Display for DiceParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Invalid dice string") + write!(f, "Invalid dice string: {}", self.0) } } @@ -56,43 +89,54 @@ impl error::Error for DiceParseError { #[allow(dead_code)] // Parses a dice string, of the type "1d6+3", "3d8-4" or "1d20". +// It also parses ranges like "8-12" or constants like "9". #[cfg(feature = "parsing")] -pub fn parse_dice_string(dice: &str) -> Result { - let dice = &dice.split_whitespace().collect::>().join(""); - lazy_static! { - static ref DICE_RE: Regex = Regex::new(r"(\d+)d(\d+)([\+\-]\d+)?").unwrap(); - } - let mut result: DiceType = DiceType::default(); - let mut did_something = false; - for cap in DICE_RE.captures_iter(dice) { - did_something = true; - if let Some(group) = cap.get(1) { - match group.as_str().parse::() { - Ok(number) => result.n_dice = number, - Err(_) => return Err(DiceParseError {}), - } - } else { - return Err(DiceParseError {}); - } - if let Some(group) = cap.get(2) { - match group.as_str().parse::() { - Ok(number) => result.die_type = number, - Err(_) => return Err(DiceParseError {}), - } - } else { - return Err(DiceParseError {}); +pub fn parse_dice_string(text: &str) -> Result { + let mut dice = text.trim(); + if dice.contains(&['d', 'D']) { + let mut plus = 0_i32; + + if dice.contains("-") { + let mut split = dice.split("-").map(|p| p.trim()); + dice = split.next().unwrap(); + plus = 0 - split.next().unwrap_or("0").parse().unwrap_or(0); + } else if dice.contains("+") { + let mut split = dice.split("+").map(|p| p.trim()); + dice = split.next().unwrap(); + plus = split.next().unwrap_or("0").parse().unwrap_or(0); } - if let Some(group) = cap.get(3) { - match group.as_str().parse::() { - Ok(number) => result.bonus = number, - Err(_) => return Err(DiceParseError {}), - } + + let parts: Vec<&str> = dice.split(&['d', 'D']).map(|p| p.trim()).collect(); + if parts.len() == 1 { + return Err(DiceParseError(dice.to_string())); + } else if parts.len() == 2 { + let count = match parts[0].len() { + 0 => 1_i32, + _ => match parts[0].parse() { + Ok(v) => v, + Err(_) => return Err(DiceParseError(dice.to_string())), + }, + }; + let sides = parts[1].parse().unwrap_or(0_i32); + return Ok(DiceType::new(count, sides, plus)); } + } else if dice.contains("-") && !dice.starts_with("-") { + let mut split = dice.split("-").map(|p| p.trim()); + let low: i32 = split.next().unwrap().trim().parse().unwrap_or(0); + let hi: i32 = split.next().unwrap().trim().parse().unwrap_or(0); + + let count = 1; + let sides = hi - low + 1; + let plus = low as i32 - 1; + return Ok(DiceType::new(count, sides, plus)); + } else { + let plus = match dice.trim().parse() { + Ok(v) => v, + Err(_) => return Err(DiceParseError(dice.to_string())), + }; + return Ok(DiceType::new(0, 0, plus)); } - if !did_something { - return Err(DiceParseError {}); - } - Ok(result) + Err(DiceParseError(dice.to_string())) } #[cfg(test)] @@ -102,6 +146,23 @@ mod tests { #[test] fn parse_1d6() { assert_eq!(parse_dice_string("1d6").unwrap(), DiceType::new(1, 6, 0)); + assert_eq!(parse_dice_string("1 d6").unwrap(), DiceType::new(1, 6, 0)); + assert_eq!(parse_dice_string("1D6").unwrap(), DiceType::new(1, 6, 0)); + assert_eq!(parse_dice_string("1D 6").unwrap(), DiceType::new(1, 6, 0)); + } + + #[test] + fn parse_const() { + assert_eq!(parse_dice_string("6").unwrap(), DiceType::new(0, 0, 6)); + assert_eq!(parse_dice_string("16").unwrap(), DiceType::new(0, 0, 16)); + assert_eq!(parse_dice_string("-6").unwrap(), DiceType::new(0, 0, -6)); + } + + #[test] + fn parse_range() { + assert_eq!(parse_dice_string("6-10").unwrap(), DiceType::new(1, 5, 5)); + assert_eq!(parse_dice_string("1-16").unwrap(), DiceType::new(1, 16, 0)); + assert_eq!(parse_dice_string("0-6").unwrap(), DiceType::new(1, 7, -1)); } #[test] @@ -110,6 +171,10 @@ mod tests { parse_dice_string("1d20+4").unwrap(), DiceType::new(1, 20, 4) ); + assert_eq!( + parse_dice_string("1 D 20 -4").unwrap(), + DiceType::new(1, 20, -4) + ); } #[test]