initial commit

main
Alina Marquardt 2023-03-18 11:31:28 +00:00
commit 02bd016c8f
3 changed files with 201 additions and 0 deletions

56
.gitignore vendored Normal file
View File

@ -0,0 +1,56 @@
# Created by https://www.toptal.com/developers/gitignore/api/nova,rust,macos
# Edit at https://www.toptal.com/developers/gitignore?templates=nova,rust,macos
### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### macOS Patch ###
# iCloud generated files
*.icloud
### nova ###
.nova/*
### Rust ###
# Generated by Cargo
# will have compiled files and executables
debug/
target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
# End of https://www.toptal.com/developers/gitignore/api/nova,rust,macos

12
Cargo.toml Normal file
View File

@ -0,0 +1,12 @@
[package]
name = "dice-roll"
authors = ["Alina Marquardt <lastfuture@lastfuture.de>"]
version = "0.2.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rand = "0.8.5"
regex = "1"
dialoguer = { version = "0.10.3", features = ["history"] }

133
src/main.rs Normal file
View File

@ -0,0 +1,133 @@
use dialoguer::{theme::ColorfulTheme, Input, History};
use std::collections::VecDeque;
use rand::prelude::*;
use regex::Regex;
struct Die {
sides: u32,
roll: u32,
}
/*impl Die {
fn crit(&self) -> bool {
self.sides == self.roll
}
}*/
fn parse_dice(dice_string: &str) -> (Vec<Die>, String) {
let mut dice: Vec<Die> = vec![];
let re = Regex::new(r"(\d+)d(\d+)").unwrap();
let mut parsed_string = String::new();
for die in re.captures_iter(dice_string) {
let dice_num: u32 = die[1].parse().unwrap();
let sides: u32 = die[2].parse().unwrap();
if dice_num > 0 && sides > 0 {
parsed_string.push_str(&format!("{}d{} + ", dice_num, sides));
for _ in 0..dice_num {
dice.push(Die {
sides,
roll: 0,
})
}
}
}
let parsed_string = &parsed_string;
let mut parsed_string = parsed_string.chars();
for _ in 0..3 {
parsed_string.next_back();
}
let mut parsed_string = parsed_string.as_str();
if dice.is_empty() {
parsed_string = "nothing";
}
(dice, parsed_string.to_owned())
}
fn roll_dice(dice_to_roll: Vec<Die>) -> Vec<Die> {
let mut dice: Vec<Die> = vec![];
for die in dice_to_roll {
dice.push(roll_die(die));
}
dice
}
fn roll_die(die_to_roll: Die) -> Die {
let mut rng = thread_rng();
Die {
sides: die_to_roll.sides,
roll: rng.gen_range(1..=die_to_roll.sides),
}
}
fn main() {
println!();
println!("Use the Up/Down arrows to scroll through history");
let mut history = MyHistory::default();
loop {
println!();
let input: String = Input::<String>::with_theme(&ColorfulTheme::default())
.with_prompt("Roll dice (ex. \"2d8 3d4\") or \"q\"")
.history_with(&mut history)
.interact_text()
.unwrap();
let dice_string: &str = &input.trim().to_lowercase(); // trim and lowercase
if dice_string.eq("q") { break; }
let (mut dice, dice_string) = parse_dice(dice_string);
print!("Rolling {}", dice_string);
dice = roll_dice(dice);
let mut last = 0;
let mut sum = 0;
for die in dice {
if last != die.sides {
println!();
print!("d{}: ", die.sides);
} else {
print!(" + ");
}
print!("{}", die.roll);
sum += die.roll;
last = die.sides;
}
println!();
println!("--==--");
println!("SUM: {}", sum);
}
println!("bye.");
//println!("{} ({} sided die) was a {} {}", die.name, die.sides, die.roll, {if die.crit() {"and A CRIT!"} else {""}});
}
struct MyHistory {
max: usize,
history: VecDeque<String>,
}
impl Default for MyHistory {
fn default() -> Self {
MyHistory {
max: 20,
history: VecDeque::new(),
}
}
}
impl<T: ToString> History<T> for MyHistory {
fn read(&self, pos: usize) -> Option<String> {
self.history.get(pos).cloned()
}
fn write(&mut self, val: &T) {
if self.history.len() == self.max {
self.history.pop_back();
}
self.history.push_front(val.to_string());
}
}