Release v0.2.0
This commit is contained in:
parent
01e8097fcc
commit
26aecf26ec
6 changed files with 409 additions and 93 deletions
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -12,5 +12,12 @@ Cargo.lock
|
||||||
# These are backup files generated by rustfmt
|
# These are backup files generated by rustfmt
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
|
|
||||||
|
### VisualStudioCode ###
|
||||||
|
.vscode/
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.history
|
||||||
|
|
||||||
# End of https://www.gitignore.io/api/rust
|
# End of https://www.gitignore.io/api/rust
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "sterling"
|
name = "sterling"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
description = "Converts a given D&D 5e currency value to the Silver Standard."
|
description = "Converts a given D&D 5e currency value to the Silver Standard."
|
||||||
authors = ["Zachary Dziura <zcdziura@gmail.com>"]
|
authors = ["Zachary Dziura <zcdziura@gmail.com>"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@ -12,6 +12,10 @@ keywords = ["dnd", "coins", "converter", "currency", "5e"]
|
||||||
clap = "2.31.1"
|
clap = "2.31.1"
|
||||||
lazy_static = "1.0.0"
|
lazy_static = "1.0.0"
|
||||||
regex = "0.2"
|
regex = "0.2"
|
||||||
|
serde = "1.0"
|
||||||
|
serde_derive = "1.0"
|
||||||
|
serde_yaml = "0.7"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
|
panic = "abort"
|
57
README.md
57
README.md
|
@ -7,15 +7,20 @@ and [I make Silver Standard for 5th Edition (Spreadsheets.)](https://www.reddit.
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
sterling [VALUE]...
|
USAGE:
|
||||||
|
sterling.exe [FLAGS] [OPTIONS] [VALUE]...
|
||||||
|
|
||||||
FLAGS:
|
FLAGS:
|
||||||
|
-f, --full Print currencies with full name, rather than with alias.
|
||||||
-h, --help Prints help information
|
-h, --help Prints help information
|
||||||
-V, --version Prints version information
|
-V, --version Prints version information
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
-c, --config <CONFIG> Specify location of config file; defaults to './sterling-conf.yml'.
|
||||||
|
|
||||||
ARGS:
|
ARGS:
|
||||||
<VALUE>... The value to be converted; should be suffixed with the coin's short-hand
|
<VALUE>... The value to be converted; should be suffixed with the coin's short-hand
|
||||||
abbreviation, i.e. p, g, e, s, or c. Defaults coin type to 'g'.
|
abbreviation, i.e. p, g, e, s, or c.
|
||||||
```
|
```
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
@ -25,16 +30,52 @@ ARGS:
|
||||||
sterling 100p // 10g
|
sterling 100p // 10g
|
||||||
|
|
||||||
// Convert one hundred platinum, fifty gold coins:
|
// Convert one hundred platinum, fifty gold coins:
|
||||||
sterling 100p 50g // 10g 5s
|
sterling 100p 50g // 10g, 5s
|
||||||
|
|
||||||
// Convert fifteen thousand copper coins:
|
// Convert fifteen thousand copper coins, printing the full names of the coins:
|
||||||
sterling 15000c // 1g 50s
|
sterling -f 15000c // 1 gold, 50 silver
|
||||||
|
|
||||||
// Convert one platinum, thirty-six gold, twelve electrum, eighty-two silver, and four hundred
|
// Convert one platinum, thirty-six gold, twelve electrum, eighty-two silver, and four hundred
|
||||||
// sixty-nine copper coins
|
// sixty-nine copper coins, printing the full names of the coins
|
||||||
sterling 1p 36g 12e 82s 469c // 64s 89c
|
sterling --full 1p 36g 12e 82s 469c // 64 silver, 89 copper
|
||||||
|
|
||||||
|
// Convert one platinum, thirty-six gold, twelve electrum, eighty-two silver, and four hundred
|
||||||
|
// sixty-nine copper coins, printing the full names of the coins, using the custom config file
|
||||||
|
// detailed below.
|
||||||
|
sterling --full -c "~/Documents/D&D/sterling-conf.yml" 1p 36g 12e 82s 469c // 27 sterling, 9 farthing
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Custom Currencies
|
||||||
|
|
||||||
|
`sterling` allows for user-defined currencies, with their own names and conversion rates. By
|
||||||
|
default, `sterling` will look at a file within the current directory called `sterling-conf.yml`, or
|
||||||
|
in whatever location as supplied by the `-c` flag. Below is an example `sterling-conf.yml` file,
|
||||||
|
showing the actual currencies that I use within my own campaign!
|
||||||
|
|
||||||
|
```
|
||||||
|
-
|
||||||
|
name: "florin"
|
||||||
|
rate: 8640
|
||||||
|
alias: "F"
|
||||||
|
-
|
||||||
|
name: "sterling"
|
||||||
|
rate: 240
|
||||||
|
alias: "s"
|
||||||
|
-
|
||||||
|
name: "penny"
|
||||||
|
rate: 12
|
||||||
|
alias: "p"
|
||||||
|
plural: "pence"
|
||||||
|
-
|
||||||
|
name: "farthing"
|
||||||
|
rate: 1
|
||||||
|
alias: "f"
|
||||||
|
```
|
||||||
|
|
||||||
|
Please note that the `rate` value is defined as the number of copper coins that goes into one of
|
||||||
|
that particular currency. In the example above, twelve copper coins goes into one "penny", and
|
||||||
|
two-hundred forty copper coins goes into one "sterling".
|
||||||
|
|
||||||
## Abstract
|
## Abstract
|
||||||
|
|
||||||
Items and expenses are, by default, assigned arbitrary currency values within the official D&D 5th
|
Items and expenses are, by default, assigned arbitrary currency values within the official D&D 5th
|
||||||
|
@ -46,7 +87,7 @@ campaign aught to treat gold similarly!
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
The basis of the Silver Standard treats 1 gold coin from the official D&D 5e source books as 1
|
The basis of the Silver Standard treats one gold coin from the official D&D 5e source books as one
|
||||||
silver coin, and that there are one hundred of a given coin to every one of the next highest valued
|
silver coin, and that there are one hundred of a given coin to every one of the next highest valued
|
||||||
coin. That's all. Thus, one hundred fifty copper coins equals one silver and fifty copper coins,
|
coin. That's all. Thus, one hundred fifty copper coins equals one silver and fifty copper coins,
|
||||||
while a suit of heavy plate armor equals fifteen gold coins, rather than fifteen hundred.
|
while a suit of heavy plate armor equals fifteen gold coins, rather than fifteen hundred.
|
||||||
|
|
62
src/config.rs
Normal file
62
src/config.rs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
use std::convert::From;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{self, BufReader, ErrorKind};
|
||||||
|
|
||||||
|
use serde_yaml;
|
||||||
|
|
||||||
|
use currency::Currency;
|
||||||
|
|
||||||
|
pub fn load_config(filename: &str) -> Result<Vec<Currency>, ConfigError> {
|
||||||
|
let config_file = File::open(filename)?;
|
||||||
|
let mut configs: Vec<Currency> = serde_yaml::from_reader(BufReader::new(config_file))?;
|
||||||
|
configs.sort_by(|a, b| b.cmp(a));
|
||||||
|
|
||||||
|
Ok(configs)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn default_config() -> Vec<Currency> {
|
||||||
|
vec![
|
||||||
|
Currency::new("platinum", 1000000, "p", None),
|
||||||
|
Currency::new("gold", 10000, "g", None),
|
||||||
|
Currency::new("silver", 100, "s", None),
|
||||||
|
Currency::new("copper", 1, "c", None),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ConfigError {
|
||||||
|
desc: String,
|
||||||
|
pub kind: ErrorKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for ConfigError {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
write!(f, "Sterling Error: {}", self.desc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for ConfigError {
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
&self.desc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<io::Error> for ConfigError {
|
||||||
|
fn from(error: io::Error) -> Self {
|
||||||
|
ConfigError {
|
||||||
|
desc: error.description().to_owned(),
|
||||||
|
kind: error.kind(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<serde_yaml::Error> for ConfigError {
|
||||||
|
fn from(error: serde_yaml::Error) -> Self {
|
||||||
|
ConfigError {
|
||||||
|
desc: error.description().to_owned(),
|
||||||
|
kind: ErrorKind::Other,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
73
src/currency.rs
Normal file
73
src/currency.rs
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct Currency {
|
||||||
|
pub name: String,
|
||||||
|
pub rate: usize,
|
||||||
|
pub value: Option<usize>,
|
||||||
|
pub alias: String,
|
||||||
|
pub plural: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Currency {
|
||||||
|
pub fn new(name: &str, rate: usize, alias: &str, plural: Option<String>) -> Currency {
|
||||||
|
Currency {
|
||||||
|
name: name.to_owned(),
|
||||||
|
rate,
|
||||||
|
value: None,
|
||||||
|
alias: alias.to_owned(),
|
||||||
|
plural,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_value(&mut self, value: usize) -> Currency {
|
||||||
|
Currency {
|
||||||
|
name: self.name.clone(),
|
||||||
|
rate: self.rate,
|
||||||
|
value: Some(value),
|
||||||
|
alias: self.alias.clone(),
|
||||||
|
plural: self.plural.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn alias_display(&self) -> String {
|
||||||
|
self.value.unwrap_or(0).to_string() + &self.alias
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn full_display(&self) -> String {
|
||||||
|
let mut display = self.value.unwrap_or(0).to_string() + " ";
|
||||||
|
|
||||||
|
if self.value.unwrap_or(0) > 1 {
|
||||||
|
match &self.plural {
|
||||||
|
&Some(ref plural) => display = display + &plural,
|
||||||
|
&None => display = display + &self.name,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
display = display + &self.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
display
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// impl Display for Currency {
|
||||||
|
// fn
|
||||||
|
// }
|
||||||
|
|
||||||
|
impl Ord for Currency {
|
||||||
|
fn cmp(&self, other: &Currency) -> Ordering {
|
||||||
|
self.value.cmp(&other.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for Currency {
|
||||||
|
fn partial_cmp(&self, other: &Currency) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for Currency {
|
||||||
|
fn eq(&self, other: &Currency) -> bool {
|
||||||
|
self.value == other.value
|
||||||
|
}
|
||||||
|
}
|
295
src/main.rs
295
src/main.rs
|
@ -1,50 +1,87 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate clap;
|
extern crate clap;
|
||||||
|
#[allow(unused_imports)]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
extern crate regex;
|
extern crate regex;
|
||||||
|
extern crate serde;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_derive;
|
||||||
|
extern crate serde_yaml;
|
||||||
|
|
||||||
use std::fmt;
|
mod config;
|
||||||
use std::ops::Add;
|
mod currency;
|
||||||
|
|
||||||
|
use std::io::ErrorKind;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
|
use config::ConfigError;
|
||||||
|
use currency::Currency;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
lazy_static! {
|
|
||||||
static ref RE: Regex = Regex::new(r"(\d+)([cegps])?").unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
let app = clap_app!(sterling =>
|
let app = clap_app!(sterling =>
|
||||||
(version: "0.1.0")
|
(version: "0.2.0")
|
||||||
(about: "Converts a given D&D 5e currency value to the Silver Standard.")
|
(about: "Converts a given D&D 5e currency value to the Silver Standard.")
|
||||||
(@arg VALUE: ... "The value to be converted; should be suffixed with the coin's short-hand abbreviation, i.e. p, g, e, s, or c. Defaults coin type to 'g'.")
|
(@arg CONFIG: -c --config +takes_value "Specify location of config file; defaults to './sterling-conf.yml'.")
|
||||||
|
(@arg PRINT_FULL: -f --full "Print currencies with full name, rather than with alias.")
|
||||||
|
(@arg VALUE: ... "The value to be converted; should be suffixed with the coin's short-hand abbreviation, i.e. p, g, e, s, or c.")
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(values) = app.get_matches().values_of("VALUE") {
|
let matches = app.get_matches();
|
||||||
|
let config_result = config::load_config(match matches.value_of("CONFIG") {
|
||||||
|
Some(file) => file,
|
||||||
|
None => "./sterling-conf.yml",
|
||||||
|
});
|
||||||
|
|
||||||
|
let currencies = match parse_currency_config(config_result, matches.value_of("CONFIG")) {
|
||||||
|
Ok(currencies) => currencies,
|
||||||
|
Err(error) => {
|
||||||
|
eprintln!("{}", error);
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(values) = matches.values_of("VALUE") {
|
||||||
let coins: Vec<&str> = values.collect();
|
let coins: Vec<&str> = values.collect();
|
||||||
|
let total_copper_value = match calculate_total_copper_value(coins) {
|
||||||
|
Ok(total_copper_value) => total_copper_value,
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("{}", err);
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let total_copper_value: usize = coins
|
let converted_currencies = convert_currencies(total_copper_value, currencies);
|
||||||
.iter()
|
let display_strings: Vec<String> =
|
||||||
.map(|coin| {
|
create_display_strings(converted_currencies, matches.is_present("PRINT_FULL"));
|
||||||
if let Some(captures) = RE.captures(coin) {
|
|
||||||
let amount: usize = captures.get(1).unwrap().as_str().parse().unwrap();
|
|
||||||
let denomination = captures.get(2).map_or("g", |d| d.as_str());
|
|
||||||
|
|
||||||
convert_to_copper(amount, denomination)
|
println!("{}", (&display_strings).join(", "));
|
||||||
} else {
|
|
||||||
panic!("Error: Invalid coin value \"{}\"", coin);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.fold(0 as usize, |total, value| total + value);
|
|
||||||
|
|
||||||
println!("{}", exchange_copper(total_copper_value));
|
|
||||||
} else {
|
} else {
|
||||||
println!("Please enter at least one value; should be suffixed with the coin's short-hand abbreviation, i.e. p, g, e, s, or c. Defaults coin type to 'g'.");
|
eprintln!("Please enter at least one value; should be suffixed with the coin's short-hand abbreviation, i.e. p, g, e, s, or c.");
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_currency_config(
|
||||||
|
config_result: Result<Vec<Currency>, ConfigError>,
|
||||||
|
config_file_path: Option<&str>,
|
||||||
|
) -> Result<Vec<Currency>, String> {
|
||||||
|
match config_result {
|
||||||
|
Ok(values) => Ok(values),
|
||||||
|
Err(error) => match error.kind {
|
||||||
|
ErrorKind::NotFound => {
|
||||||
|
if let Some(file_path) = config_file_path {
|
||||||
|
Err(format!("Sterling Error: Can't find configuration file: \"{}\"", &file_path))
|
||||||
|
} else {
|
||||||
|
Ok(config::default_config())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => Err(format!("Sterling Error: {}", error)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn convert_to_copper(amount: usize, coin_denomination: &str) -> usize {
|
fn convert_to_copper(amount: usize, coin_denomination: &str) -> usize {
|
||||||
match coin_denomination {
|
match coin_denomination {
|
||||||
"p" => amount * 1000,
|
"p" => amount * 1000,
|
||||||
|
@ -56,65 +93,157 @@ fn convert_to_copper(amount: usize, coin_denomination: &str) -> usize {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exchange_copper(copper: usize) -> CurrencyValue {
|
fn calculate_total_copper_value(coins: Vec<&str>) -> Result<usize, &'static str> {
|
||||||
CurrencyValue {
|
let regex: Regex = Regex::new(r"(\d+)([cegps])").unwrap();
|
||||||
platinum: copper / 1000000,
|
for coin in coins.iter() {
|
||||||
gold: (copper % 1000000) / 10000,
|
if let None = regex.captures(coin) {
|
||||||
silver: ((copper % 1000000) % 10000) / 100,
|
return Err(
|
||||||
copper: ((copper % 1000000) % 10000) % 100,
|
"Sterling Error: Invalid coin value. Make sure all coins are denoted properly."
|
||||||
}
|
)
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct CurrencyValue {
|
|
||||||
platinum: usize,
|
|
||||||
gold: usize,
|
|
||||||
silver: usize,
|
|
||||||
copper: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for CurrencyValue {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
let &CurrencyValue {
|
|
||||||
platinum,
|
|
||||||
gold,
|
|
||||||
silver,
|
|
||||||
copper,
|
|
||||||
} = self;
|
|
||||||
|
|
||||||
let mut output = String::new();
|
|
||||||
|
|
||||||
if platinum > 0 {
|
|
||||||
output = output + &format!("{}p ", platinum);
|
|
||||||
}
|
|
||||||
|
|
||||||
if gold > 0 {
|
|
||||||
output = output + &format!("{}g ", gold);
|
|
||||||
}
|
|
||||||
|
|
||||||
if silver > 0 {
|
|
||||||
output = output + &format!("{}s ", silver);
|
|
||||||
}
|
|
||||||
|
|
||||||
if copper > 0 {
|
|
||||||
output = output + &format!("{}c", copper);
|
|
||||||
} else if output.is_empty() {
|
|
||||||
output.push_str("0cp");
|
|
||||||
}
|
|
||||||
|
|
||||||
write!(f, "{}", output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Add for CurrencyValue {
|
|
||||||
type Output = CurrencyValue;
|
|
||||||
|
|
||||||
fn add(self, other: CurrencyValue) -> CurrencyValue {
|
|
||||||
CurrencyValue {
|
|
||||||
platinum: self.platinum + other.platinum,
|
|
||||||
gold: self.gold + other.gold,
|
|
||||||
silver: self.silver + other.silver,
|
|
||||||
copper: self.copper + other.copper,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let converted_values = coins.iter().map(|coin| {
|
||||||
|
let captures = regex.captures(coin).unwrap();
|
||||||
|
let amount: usize = captures[1].parse().unwrap();
|
||||||
|
let denomination = captures[2].to_owned();
|
||||||
|
convert_to_copper(amount, &denomination)
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(converted_values.fold(0 as usize, |total, value| total + value))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exchange(copper: usize, mut currencies: Vec<Currency>) -> Vec<Currency> {
|
||||||
|
let mut val = copper;
|
||||||
|
currencies
|
||||||
|
.iter_mut()
|
||||||
|
.map(|currency| {
|
||||||
|
let value = val / currency.rate;
|
||||||
|
val = val % currency.rate;
|
||||||
|
|
||||||
|
currency.with_value(value)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_currencies(copper_value: usize, currencies: Vec<Currency>) -> Vec<Currency> {
|
||||||
|
exchange(copper_value, currencies)
|
||||||
|
.iter()
|
||||||
|
.filter(|c| (*c).value.unwrap_or(0) > 0)
|
||||||
|
.cloned()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_display_strings(converted_currencies: Vec<Currency>, is_print_full: bool) -> Vec<String> {
|
||||||
|
converted_currencies
|
||||||
|
.iter()
|
||||||
|
.map(|c| {
|
||||||
|
if is_print_full {
|
||||||
|
c.full_display()
|
||||||
|
} else {
|
||||||
|
c.alias_display()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use currency::Currency;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref STANDARD_CURRENCIES: [Currency; 4] = [
|
||||||
|
Currency::new("platinum", 1000000, "p", None),
|
||||||
|
Currency::new("gold", 10000, "g", None),
|
||||||
|
Currency::new("silver", 100, "s", None),
|
||||||
|
Currency::new("copper", 1, "c", None),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_convert_copper_to_copper() {
|
||||||
|
assert_eq!(1, convert_to_copper(1, "c"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_convert_silver_to_copper() {
|
||||||
|
assert_eq!(10, convert_to_copper(1, "s"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_convert_electrum_to_copper() {
|
||||||
|
assert_eq!(50, convert_to_copper(1, "e"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_convert_gold_to_copper() {
|
||||||
|
assert_eq!(100, convert_to_copper(1, "g"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_convert_platinum_to_copper() {
|
||||||
|
assert_eq!(1000, convert_to_copper(1, "p"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_calculate_total_copper_value() {
|
||||||
|
let values = vec!["1p", "1g", "1e", "1s", "1c"];
|
||||||
|
assert_eq!(1161, calculate_total_copper_value(values).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_calculate_total_copper_value_bad_inputs() {
|
||||||
|
let values = vec!["1p", "1g", "1f", "1s", "1c"];
|
||||||
|
assert_eq!(1161, calculate_total_copper_value(values).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_exchange_to_copper() {
|
||||||
|
let currencies = vec![
|
||||||
|
Currency::new("platinum", 1000000, "p", None).with_value(0),
|
||||||
|
Currency::new("gold", 10000, "g", None).with_value(0),
|
||||||
|
Currency::new("silver", 100, "s", None).with_value(0),
|
||||||
|
Currency::new("copper", 1, "c", None).with_value(1),
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_eq!(currencies, exchange(1, STANDARD_CURRENCIES.to_vec()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_exchange_to_silver() {
|
||||||
|
let currencies = vec![
|
||||||
|
Currency::new("platinum", 1000000, "p", None).with_value(0),
|
||||||
|
Currency::new("gold", 10000, "g", None).with_value(0),
|
||||||
|
Currency::new("silver", 100, "s", None).with_value(1),
|
||||||
|
Currency::new("copper", 1, "c", None).with_value(0),
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_eq!(currencies, exchange(100, STANDARD_CURRENCIES.to_vec()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_exchange_to_gold() {
|
||||||
|
let currencies = vec![
|
||||||
|
Currency::new("platinum", 1000000, "p", None).with_value(0),
|
||||||
|
Currency::new("gold", 10000, "g", None).with_value(1),
|
||||||
|
Currency::new("silver", 100, "s", None).with_value(0),
|
||||||
|
Currency::new("copper", 1, "c", None).with_value(0),
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_eq!(currencies, exchange(10000, STANDARD_CURRENCIES.to_vec()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_exchange_to_platinum() {
|
||||||
|
let currencies = vec![
|
||||||
|
Currency::new("platinum", 1000000, "p", None).with_value(1),
|
||||||
|
Currency::new("gold", 10000, "g", None).with_value(0),
|
||||||
|
Currency::new("silver", 100, "s", None).with_value(0),
|
||||||
|
Currency::new("copper", 1, "c", None).with_value(0),
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_eq!(currencies, exchange(1000000, STANDARD_CURRENCIES.to_vec()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue