Initial Commit
This commit is contained in:
commit
20af27423b
7
Cargo.toml
Normal file
7
Cargo.toml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
[package]
|
||||||
|
name = "libroller"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Beefki <mousecar23@hotmail.com>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
rand = "0.3"
|
28
src/bin/main.rs
Normal file
28
src/bin/main.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
extern crate libroller;
|
||||||
|
use libroller::config::Config;
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let roll = Config::new(&mut env::args());
|
||||||
|
for rolls in &roll.unwrap_or_else(|e| {println!("Application error: {}", e);
|
||||||
|
std::process::exit(1)})
|
||||||
|
{
|
||||||
|
let x = rolls.to_roll().unwrap_or_else(|e| { println!("Application error: {}", e);
|
||||||
|
std::process::exit(1);
|
||||||
|
});
|
||||||
|
if x.number() > 1 && x.number() < 26 {
|
||||||
|
let mut total = 0;
|
||||||
|
println!("You're rolling {}", x);
|
||||||
|
for value in x.rolls() {
|
||||||
|
println!("You rolled: {}", value);
|
||||||
|
total += value;
|
||||||
|
}
|
||||||
|
println!("Total value of dice = {}", total);
|
||||||
|
println!("");
|
||||||
|
}else {
|
||||||
|
println!("You're rolling {}", x);
|
||||||
|
println!("Total: {}", x.total())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
68
src/config.rs
Normal file
68
src/config.rs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
//! Creates a `Config` struct to be used to gather command line
|
||||||
|
//! arguments at the time the program is called, so it can be
|
||||||
|
//! converted easily to a `Roll`
|
||||||
|
use super::*;
|
||||||
|
use std::num::ParseIntError;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Config {
|
||||||
|
first: String,
|
||||||
|
second: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
/// Takes the arguments passed at launch and returns an Ok(_)
|
||||||
|
/// or a str with a static lifetime. This allows for error
|
||||||
|
/// handling whenever this is called.
|
||||||
|
///
|
||||||
|
/// It checks to see if there are enough arguments passed to make
|
||||||
|
/// a proper `Config` and if not returns an `Err(&str)` that
|
||||||
|
/// explains what happened to the user.
|
||||||
|
///
|
||||||
|
/// #Errors
|
||||||
|
///
|
||||||
|
/// `Config::new(args)` will error when the args given don't match up with
|
||||||
|
/// the required types or when not enough args are passed to create a `Config`
|
||||||
|
pub fn new(args: &mut std::env::Args) -> Result <Vec<Config>, &'static str> {
|
||||||
|
args.next();
|
||||||
|
let mut vec = vec![];
|
||||||
|
|
||||||
|
if args.len() % 2 != 0 {
|
||||||
|
return Err("Number of args not even")
|
||||||
|
}
|
||||||
|
for _ in 0..args.len()/2 {
|
||||||
|
let number = match args.next() {
|
||||||
|
None => return Err("Incorret data type entered for number of dice"),
|
||||||
|
Some(arg) => arg,
|
||||||
|
};
|
||||||
|
let die = match args.next() {
|
||||||
|
None => return Err("Incorrect data type entered for die size"),
|
||||||
|
Some(arg) => arg,
|
||||||
|
};
|
||||||
|
|
||||||
|
let config = Config {
|
||||||
|
first : number,
|
||||||
|
second : die,
|
||||||
|
};
|
||||||
|
vec.push(config)
|
||||||
|
};
|
||||||
|
Ok(vec)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts a `Config` into a `Roll`. Returns a `Result` that's
|
||||||
|
/// either `Ok(Roll)` or an `Err(_)`
|
||||||
|
pub fn to_roll(&self) -> Result<Roll, ParseIntError> {
|
||||||
|
let number = self.first.parse::<u32>()?;
|
||||||
|
let die = self.second.parse::<u32>()?;
|
||||||
|
|
||||||
|
Ok(Roll::new(number, die))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn roll_check() {
|
||||||
|
let x = Config { first: "2".to_string(), second: "6".to_string() };
|
||||||
|
let x = x.to_roll().unwrap();
|
||||||
|
let y = Roll::new(2, 6);
|
||||||
|
assert_eq!(x, y);
|
||||||
|
}
|
7
src/lib.rs
Normal file
7
src/lib.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
//! A simple and efficient library to make dice rolls into easy to use values.
|
||||||
|
pub extern crate rand;
|
||||||
|
pub mod roll;
|
||||||
|
pub mod config;
|
||||||
|
|
||||||
|
pub use roll::*;
|
||||||
|
pub use roll::Roll;
|
113
src/roll.rs
Normal file
113
src/roll.rs
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
//! A struct in which our data is held for rolling. By ensuring that
|
||||||
|
//! only `u32`s are used we prevent the need for additional type
|
||||||
|
//! checking at time of use. */
|
||||||
|
extern crate rand;
|
||||||
|
use rand::Rng;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct Roll {
|
||||||
|
die: u32,
|
||||||
|
number: u32,
|
||||||
|
}
|
||||||
|
impl Roll {
|
||||||
|
/// A fn to create new `Roll` structs, private to prevent
|
||||||
|
/// being used outside the library.
|
||||||
|
pub fn new(number: u32, die: u32) -> Roll {
|
||||||
|
Roll {
|
||||||
|
die: die,
|
||||||
|
number: number,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the value stored in the number field of a roll.
|
||||||
|
/// Allows the fields of `Roll` to be private (and unchangable)
|
||||||
|
/// while still allowing access to act on their internal value
|
||||||
|
/// ```
|
||||||
|
/// let x = Roll::new(&2, &6);
|
||||||
|
/// assert!(x.number() == 2);
|
||||||
|
/// ```
|
||||||
|
pub fn number(&self) -> u32 {
|
||||||
|
self.number
|
||||||
|
}
|
||||||
|
/// Returns the value stored in the die field of a roll.
|
||||||
|
/// Allows the fields of `Roll` to be private (and unchangable)
|
||||||
|
/// while still allowing access to act on their internal value
|
||||||
|
pub fn die(&self) -> u32 {
|
||||||
|
self.die
|
||||||
|
}
|
||||||
|
/// Creates a Vector to hold each of the values rolled. Making
|
||||||
|
///a Vector ensures the ability to work on exactly the same
|
||||||
|
///die rolls easily and accurately, since calling the `Roll`
|
||||||
|
///iterator again will produce new results.
|
||||||
|
pub fn rolls(self) -> Vec<u32> {
|
||||||
|
self.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Used on a `Roll` to return only the final value, ignoring
|
||||||
|
///the values used to add up to that result. Allows `.total()`
|
||||||
|
///syntax when used
|
||||||
|
pub fn total(self) -> u32 {
|
||||||
|
self.sum()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Turns `Roll` into an `Iterator`, causing it to create a series of random
|
||||||
|
///numbers between 1 and the chosen die size. It counts down the number field
|
||||||
|
///of the `Roll` and returns `None` to end the iteration. It's only capable of
|
||||||
|
///returning u32 values, which should never be a problem.
|
||||||
|
impl Iterator for Roll {
|
||||||
|
type Item = u32;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.number != 0 {
|
||||||
|
self.number -= 1;
|
||||||
|
Some(rand::thread_rng().gen_range(1, self.die + 1))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Defines a `Display` format for the `Roll` type. Makes it much easier
|
||||||
|
///to use the `Roll` type as you should be able to just use
|
||||||
|
///```
|
||||||
|
/// ```
|
||||||
|
impl fmt::Display for Roll {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}d{}", self.number, self.die)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn rollnew() {
|
||||||
|
let x = Roll::new(2, 6);
|
||||||
|
let y = Roll { number: 2, die: 6 };
|
||||||
|
assert_eq!(x, y);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn displays() {
|
||||||
|
let x = Roll::new(2, 6);
|
||||||
|
assert_eq!(2, x.number());
|
||||||
|
assert_eq!(6, x.die());
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn rolls() {
|
||||||
|
let x = Roll::new(20, 6);
|
||||||
|
for y in x.rolls() {
|
||||||
|
assert!(y <= x.die());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn totaling() {
|
||||||
|
for _ in 0 .. 21 {
|
||||||
|
let x = Roll::new(2, 6);
|
||||||
|
assert!(x.total() <= 12 && x.total() >= 2);
|
||||||
|
let y = Roll::new(3, 20);
|
||||||
|
assert!(y.total() <= 60 && y.total() >= 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user