diff --git a/Cargo.lock b/Cargo.lock index fe8738f..731703f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,55 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys", +] + [[package]] name = "anyhow" version = "1.0.86" @@ -180,6 +229,60 @@ dependencies = [ "winapi", ] +[[package]] +name = "clap" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "cli" +version = "0.1.0" +dependencies = [ + "clap", + "core", +] + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + [[package]] name = "combine" version = "3.8.1" @@ -757,7 +860,7 @@ checksum = "5e27ed0c2cf0c0cc52c6bcf3b45c907f433015e580879d14005386251842fb0a" dependencies = [ "graphql-introspection-query", "graphql-parser 0.4.0", - "heck", + "heck 0.4.0", "lazy_static", "proc-macro2", "quote", @@ -814,6 +917,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.1.18" @@ -953,6 +1062,12 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itoa" version = "0.4.7" @@ -1965,6 +2080,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "syn" version = "1.0.92" @@ -2301,6 +2422,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "uuid" version = "0.8.2" @@ -2447,6 +2574,79 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + [[package]] name = "winreg" version = "0.10.1" diff --git a/Cargo.toml b/Cargo.toml index 81d912d..3c24fe5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ + "cli", "core", "ui", "server" diff --git a/cli/Cargo.toml b/cli/Cargo.toml new file mode 100644 index 0000000..20e22f7 --- /dev/null +++ b/cli/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "cli" +version = "0.1.0" +edition = "2021" + +[dependencies] +core = { path = "../core" } +clap = { version = "4.5.4", features = ["derive"] } diff --git a/cli/src/main.rs b/cli/src/main.rs new file mode 100644 index 0000000..45d8fe7 --- /dev/null +++ b/cli/src/main.rs @@ -0,0 +1,79 @@ +use clap::{Parser, Subcommand}; +use std::num::NonZeroU8; + +use core::{Campaign, DiceType, Roll}; + +/// Dicebag's CLI interface +#[derive(Parser)] +#[command(name = "Dicebag CLI")] +#[command(version, about, long_about = None)] +struct Cli { + #[command(subcommand)] + command: Option, +} + +#[derive(Subcommand)] +enum Commands { + Campaign { + /// Name of the campaign + #[arg(short, long)] + name: String, + + /// Description for the campaign + #[arg(short, long)] + description: String, + }, + Player { + #[arg(short, long)] + name: String, + }, + Roll { + /// Dice type to roll (d4, d6, d8, d10, d12, d20, d100) + #[arg(short, long)] + dice: String, + + /// Number of dice to roll + #[arg(short, long)] + number: Option, + }, +} + +fn main() { + let cli = Cli::parse(); + + match &cli.command { + Some(Commands::Campaign { name, description }) => { + let campaign = Campaign::new(0, name.clone(), description.clone()); + // TODO: Save the campaign + println!("{}: {}", campaign.name(), campaign.description()); + } + Some(Commands::Player { name }) => { + // TODO: Save the player + println!("Hello, {}!", name); + } + Some(Commands::Roll { dice, number }) => match dice.parse::() { + Ok(d) => { + // TODO: Store history somewhere + if number.is_none() { + println!("Rolling a single {:?}...", d); + let result = Roll::roll_one(d); + println!("Result: {}", result); + } else if let Some(n) = number { + let result = Roll::roll(&Roll { + number: *n, + dice: d, + }); + let total = result.iter().sum::(); + println!("Rolling a {:?}, {:?}, total = {}", d, result, total); + } + } + Err(d) => { + println!("Invalid dice type: {}", d); + } + }, + None => { + // TODO: Start the application + println!("Start the app!"); + } + } +} diff --git a/core/src/dice.rs b/core/src/dice.rs index dee28f9..23879a1 100644 --- a/core/src/dice.rs +++ b/core/src/dice.rs @@ -1,7 +1,7 @@ use rand::{thread_rng, Rng}; -use std::num::NonZeroU8; +use std::{num::NonZeroU8, str::FromStr}; -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] #[non_exhaustive] pub enum DiceType { D4, @@ -13,6 +13,28 @@ pub enum DiceType { D100, } +impl FromStr for DiceType { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + match s { + "d4" => Ok(DiceType::D4), + "d6" => Ok(DiceType::D6), + "d8" => Ok(DiceType::D8), + "d10" => Ok(DiceType::D10), + "d12" => Ok(DiceType::D12), + "d20" => Ok(DiceType::D20), + "d100" => Ok(DiceType::D100), + _ => Err("Invalid dice type"), + } + } +} + +fn random_number(die: DiceType) -> i64 { + let mut rng = thread_rng(); + rng.gen_range(1..=die.into()) +} + pub struct Roll { pub number: NonZeroU8, pub dice: DiceType, @@ -20,11 +42,14 @@ pub struct Roll { impl Roll { pub fn roll(roll: &Roll) -> Vec { - let mut rng = thread_rng(); (0..roll.number.into()) - .map(|_| rng.gen_range(1..=roll.dice.into())) + .map(|_| random_number(roll.dice)) .collect::>() } + + pub fn roll_one(dice: DiceType) -> i64 { + random_number(dice) + } } impl From for i64 {