Release/0.3.0

This commit is contained in:
Zachary Dziura 2018-05-16 20:58:35 +00:00
parent 26aecf26ec
commit abfb69e82d
12 changed files with 410 additions and 191 deletions

2
.gitignore vendored
View file

@ -21,3 +21,5 @@ Cargo.lock
.history
# End of https://www.gitignore.io/api/rust
sterling-conf.yml

24
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,24 @@
image: "rust:latest"
stages:
- test
- deploy
cargo:test:
stage: test
only:
- master
script:
- cargo test --verbose
cargo:build:
stage: deploy
only:
- master
script:
- cargo build --release
cache:
paths:
- target/
artifacts:
paths:
- target/release/sterling

27
.travis.yml Normal file
View file

@ -0,0 +1,27 @@
language: rust
os:
- osx
branches:
only:
- master
rust:
- stable
script:
- cargo test --verbose
- cargo build --release
before_deploy:
- git config --local user.name "Zachary Dziura"
- git config --local user.email "zcdziura@gmail.com"
- git tag "$(date +'%Y%m%d%H%M%S')-$(git log --format=%h -1)-osx"
deploy:
provider: releases
api_key:
secure: "NVH5d3CH0QUyFSu0MbeB3WvSo52qwjxH98wIL7kieD/kbTrTzTCbTWiTCV+/OM41nWOdxTy9T5TLqDsrh4k4xCkb4VbKTcsfIpBaQqwMvT6Co/GgLr4xSiHBI/ENBVwbnyDavMxh/E5AAAPF/HgGci2tEqzNuu9V7jon6uhb8+WovbfZeEA4tSNLsWV5g3MwssMfdaWzDPTHsiWXFPn6AVhkmy4fKAIHoUtp37A7bqx1hGPpFD3OGYN1oDxtJK5jRBSXegyWh08RQkLQ74PJTWD6Xw+Hvp1ewP1vitP69VJgsBC496jPasqAEOVeD3KogtcmBEyaIG+I5LZWLTibs41qF83cxJDdWxw69H827IXSQobM+7Sc51chWJR0H3OA1yDPQvorI1C17zvXd4wPpDfSUeY5ZqAplnYMOxk3jDbbX099bEyRE/skWHRaqL99fV7i5bO3aHDFP/BDjp03hnzpvfKs9zm05e87LStriNYQ5NsCPkdX+W18Q15DLhS2D9cp37PPAUA5jLNUFiEY5x9fwl5XEpefBqrqmE8qbmkc9GTr3MZikmTfB51Nx5NvkybCTKhMoKw5AhNLmw0fnkaqxrei7Uif7WqxTkngJep6VLidmt2pRJ9Qj3AWOXsLZJPm0ZQuo71dWC049EeEVtfQkyz/9K2J+iNVRgdiEeg="
file_glob: true
file: target/release/sterling
skip_cleanup: true
on:
repo: zcdziura/sterling
branch: master
addons:
artifacts: true

View file

@ -1,6 +1,6 @@
[package]
name = "sterling"
version = "0.2.0"
version = "0.3.0"
description = "Converts a given D&D 5e currency value to the Silver Standard."
authors = ["Zachary Dziura <zcdziura@gmail.com>"]
readme = "README.md"
@ -9,9 +9,9 @@ repository = "https://gitlab.com/zcdziura/sterling"
keywords = ["dnd", "coins", "converter", "currency", "5e"]
[dependencies]
clap = "2.31.1"
lazy_static = "1.0.0"
regex = "0.2"
clap = "2.31"
lazy_static = "1.0"
regex = "1.0"
serde = "1.0"
serde_derive = "1.0"
serde_yaml = "0.7"

View file

@ -8,22 +8,28 @@ and [I make Silver Standard for 5th Edition (Spreadsheets.)](https://www.reddit.
```
USAGE:
sterling.exe [FLAGS] [OPTIONS] [VALUE]...
sterling [FLAGS] [OPTIONS] [VALUE]... [SUBCOMMAND]
FLAGS:
-f, --full Print currencies with full name, rather than with alias.
-h, --help Prints help information
-V, --version Prints version information
-o, --optional Include currencies marked as optional when converting.
-f, --full Print currencies with full name, rather than with alias.
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
-c, --config <CONFIG> Specify location of config file; defaults to './sterling-conf.yml'.
ARGS:
<VALUE>... The value to be converted; should be suffixed with the coin's short-hand
abbreviation, i.e. p, g, e, s, or c.
<VALUE>... The value to be converted; should be suffixed with the coin's short-hand abbreviation, i.e. p, g,
e, s, or c.
SUBCOMMANDS:
add Add two currency amounts together; uses the currencies defined in your config file
help Prints this message or the help of the given subcommand(s)
sub Subtract two currency amounts from one another; uses the currencies defined in your config file
```
## Examples
## Converting Currency Examples
```
// Convert one hundred platinum coins:
@ -41,22 +47,43 @@ 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
// detailed below, including optional currencies
sterling --full -o -c "~/Documents/D&D/sterling-conf.yml" 1p 36g 12e 82s 469c // 27 sterling, 9 farthing
```
## Adding and Subtracting Currency Examples
```
// Add together ten and twenty pense, using the custom config file detailed below
sterling add "10p" "20p" // 1s, 10p
// Subtract two sterling and ten pence from one florin
sterling sub "1F" "2s 10p" --full // 33 sterling, 10 pence
// Subtract one florin from two sterling and ten pence. Note that, regardless of order, the smaller
// value is ALWAYS subtracted from the larger value.
sterling sub "2s 10p" "1F" --full // 33 sterling, 10 pence
```
Note that `sterling` doesn't allow for negative currencies. Therefore, when subtracting currencies,
the smaller currency value will always be subtracted from the larger currency value, regardless of
the order of the currencies in the `sub` command.
## 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!
in whatever location as supplied by the `-c` flag. You can also specify that a currency be optional,
which will prevent that currency from being used when converting values, unless the `-o` flag is
passed. 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"
optional: true
-
name: "sterling"
rate: 240
@ -94,15 +121,16 @@ while a suit of heavy plate armor equals fifteen gold coins, rather than fifteen
## Installation
Make sure that you first have `rust` and `cargo` installed onto your computer before downloading
`sterling`. Just follow the simple
[Installation Guide](https://doc.rust-lang.org/cargo/getting-started/installation.html) on the
official Rust language website to install both programs.
The easiest way to install `sterling` is to do so with `cargo`, the build tool that's installed
along with the `rust` compiler. If you already have `rust` and `cargo` installed onto your computer,
simply run the following command from a command prompt:
Once `rust` and `cargo` are installed onto your computer, run the following command:
```
$ cargo install sterling
```
`cargo install sterling`
This will install `sterling` into the `.cargo/bin` directory within your User directory
(`/home/YOUR_USER_NAME` on Linux and macOS, `C:\Users\YOUR_USER_NAME` on Windows). Be sure to add
this directory to your PATH.
If you do not have the `rust` compiler installed, you can also find pre-built binaries for 64-bit
Windows, macOS, and Linux computers in the "Tags" navigation link, which is displayed above this
README. Simply download the correct binary for your computer's operating system, extract it
somewhere into your file system (such as a "bin" folder within your user directory), and add that
location to your system's PATH.

29
appveyor.yml Normal file
View file

@ -0,0 +1,29 @@
os: Visual Studio 2015
branches:
only:
- master
environment:
matrix:
- channel: stable
target: x86_64-pc-windows-gnu
artifacts:
- path: target/release/sterling.exe
name: sterling
install:
- appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
- rustup-init -yv --default-toolchain %channel% --default-host %target%
- set PATH=%PATH%;%USERPROFILE%\.cargo\bin
- rustc -vV
- cargo -vV
build: false
test_script:
- cargo test --verbose
- cargo build --release
deploy:
provider: GitHub
description: ''
auth_token:
secure: bvA/4J1T0h65ur6tsg6k/wlZFjP3qr2QsyRsmGMEmm7DOF61xmzTnjuBcPjQYrba
artifact: target/release/sterling.exe
on:
branch: master

View file

@ -1,6 +1,6 @@
use std::convert::From;
use std::error::Error;
use std::fmt::{self, Display, Formatter};
use std::convert::From;
use std::fs::File;
use std::io::{self, BufReader, ErrorKind};
@ -18,10 +18,10 @@ pub fn load_config(filename: &str) -> Result<Vec<Currency>, ConfigError> {
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),
Currency::new("platinum", 1000000, "p", None, None),
Currency::new("gold", 10000, "g", None, None),
Currency::new("silver", 100, "s", None, None),
Currency::new("copper", 1, "c", None, None),
]
}

155
src/convert.rs Normal file
View file

@ -0,0 +1,155 @@
use currency::Currency;
use regex::Regex;
pub fn convert_to_copper(amount: usize, coin_denomination: &str) -> usize {
match coin_denomination {
"p" => amount * 1000,
"g" => amount * 100,
"e" => amount * 50,
"s" => amount * 10,
"c" => amount,
_ => unreachable!("Invalid coin type; must be a valid coin found in the PHB."),
}
}
pub fn calculate_total_copper_value(coins: Vec<&str>) -> Result<usize, &'static str> {
let regex: Regex = Regex::new(r"(\d+)([cegps])").unwrap();
for coin in coins.iter() {
if let None = regex.captures(coin) {
return Err(
"Sterling Error: Invalid coin value. Make sure all coins are denoted properly.",
);
}
}
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))
}
pub 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()
}
pub 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()
}
#[cfg(test)]
mod tests {
use convert::*;
use currency::Currency;
lazy_static! {
static ref STANDARD_CURRENCIES: [Currency; 4] = [
Currency::new("platinum", 1000000, "p", None, None),
Currency::new("gold", 10000, "g", None, None),
Currency::new("silver", 100, "s", None, None),
Currency::new("copper", 1, "c", None, 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, None).with_value(0),
Currency::new("gold", 10000, "g", None, None).with_value(0),
Currency::new("silver", 100, "s", None, None).with_value(0),
Currency::new("copper", 1, "c", None, 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, None).with_value(0),
Currency::new("gold", 10000, "g", None, None).with_value(0),
Currency::new("silver", 100, "s", None, None).with_value(1),
Currency::new("copper", 1, "c", None, 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, None).with_value(0),
Currency::new("gold", 10000, "g", None, None).with_value(1),
Currency::new("silver", 100, "s", None, None).with_value(0),
Currency::new("copper", 1, "c", None, 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, None).with_value(1),
Currency::new("gold", 10000, "g", None, None).with_value(0),
Currency::new("silver", 100, "s", None, None).with_value(0),
Currency::new("copper", 1, "c", None, None).with_value(0),
];
assert_eq!(currencies, exchange(1000000, STANDARD_CURRENCIES.to_vec()));
}
}

View file

@ -7,16 +7,24 @@ pub struct Currency {
pub value: Option<usize>,
pub alias: String,
pub plural: Option<String>,
pub optional: Option<bool>,
}
impl Currency {
pub fn new(name: &str, rate: usize, alias: &str, plural: Option<String>) -> Currency {
pub fn new(
name: &str,
rate: usize,
alias: &str,
plural: Option<String>,
optional: Option<bool>,
) -> Currency {
Currency {
name: name.to_owned(),
rate,
value: None,
alias: alias.to_owned(),
plural,
optional,
}
}
@ -27,6 +35,14 @@ impl Currency {
value: Some(value),
alias: self.alias.clone(),
plural: self.plural.clone(),
optional: None,
}
}
pub fn is_optional(&self) -> bool {
match self.optional {
Some(optional) => optional,
None => false,
}
}
@ -50,10 +66,6 @@ impl Currency {
}
}
// impl Display for Currency {
// fn
// }
impl Ord for Currency {
fn cmp(&self, other: &Currency) -> Ordering {
self.value.cmp(&other.value)

View file

@ -10,8 +10,10 @@ extern crate serde_derive;
extern crate serde_yaml;
mod config;
mod convert;
mod currency;
use std::collections::HashMap;
use std::io::ErrorKind;
use std::process;
@ -21,11 +23,24 @@ use regex::Regex;
fn main() {
let app = clap_app!(sterling =>
(version: "0.2.0")
(version: env!("CARGO_PKG_VERSION"))
(about: "Converts a given D&D 5e currency value to the Silver Standard.")
(@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 OPTIONAL: -o --optional "Include currencies marked as optional when converting.")
(@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.")
(@subcommand add =>
(about: "Add two currency amounts together; uses the currencies defined in your config file")
(@arg AUGEND: +required "The augend of the addition function; i.e. the left side")
(@arg ADDEND: +required "The addend of the addition function; i.e. the right side")
(@arg PRINT_FULL: -f --full "Print currencies with full name, rather than with alias.")
)
(@subcommand sub =>
(about: "Subtract two currency amounts from one another; uses the currencies defined in your config file")
(@arg MINUEND: +required "The minuend of the subtraction function; i.e. the left side")
(@arg SUBTRAHEND: +required "The subtrahend of the subtraction function; i.e. the right side")
(@arg PRINT_FULL: -f --full "Print currencies with full name, rather than with alias.")
)
);
let matches = app.get_matches();
@ -34,17 +49,61 @@ fn main() {
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);
}
};
let currencies: Vec<Currency> =
match parse_currency_config(config_result, matches.value_of("CONFIG")) {
Ok(currencies) => currencies
.iter()
.filter(|c| {
let has_add_subcommand = match matches.subcommand_matches("add") {
Some(_) => true,
None => false,
};
if let Some(values) = matches.values_of("VALUE") {
if has_add_subcommand {
true
} else if !matches.is_present("OPTIONAL") {
!c.is_optional()
} else {
true
}
})
.cloned()
.collect(),
Err(error) => {
eprintln!("{}", error);
process::exit(1);
}
};
if let Some(matches) = matches.subcommand_matches("add") {
let (lhs, rhs) = get_copper_value(
&currencies,
matches.value_of("AUGEND").unwrap(),
matches.value_of("ADDEND").unwrap(),
);
let converted_currencies = convert::convert_currencies(lhs + rhs, currencies);
let display_strings: Vec<String> =
create_display_strings(converted_currencies, matches.is_present("PRINT_FULL"));
println!("{}", (&display_strings).join(", "));
} else if let Some(matches) = matches.subcommand_matches("sub") {
let (lhs, rhs) = get_copper_value(
&currencies,
matches.value_of("MINUEND").unwrap(),
matches.value_of("SUBTRAHEND").unwrap(),
);
let difference = if lhs > rhs { lhs - rhs } else { rhs - lhs };
let converted_currencies = convert::convert_currencies(difference, currencies);
let display_strings: Vec<String> =
create_display_strings(converted_currencies, matches.is_present("PRINT_FULL"));
println!("{}", (&display_strings).join(", "));
} else if let Some(values) = matches.values_of("VALUE") {
let coins: Vec<&str> = values.collect();
let total_copper_value = match calculate_total_copper_value(coins) {
let total_copper_value = match convert::calculate_total_copper_value(coins) {
Ok(total_copper_value) => total_copper_value,
Err(err) => {
eprintln!("{}", err);
@ -52,7 +111,7 @@ fn main() {
}
};
let converted_currencies = convert_currencies(total_copper_value, currencies);
let converted_currencies = convert::convert_currencies(total_copper_value, currencies);
let display_strings: Vec<String> =
create_display_strings(converted_currencies, matches.is_present("PRINT_FULL"));
@ -72,68 +131,19 @@ fn parse_currency_config(
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))
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 {
match coin_denomination {
"p" => amount * 1000,
"g" => amount * 100,
"e" => amount * 50,
"s" => amount * 10,
"c" => amount,
_ => unreachable!("Invalid coin type; must be a valid coin found in the PHB."),
}
}
fn calculate_total_copper_value(coins: Vec<&str>) -> Result<usize, &'static str> {
let regex: Regex = Regex::new(r"(\d+)([cegps])").unwrap();
for coin in coins.iter() {
if let None = regex.captures(coin) {
return Err(
"Sterling Error: Invalid coin value. Make sure all coins are denoted properly."
)
}
}
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()
@ -147,103 +157,35 @@ fn create_display_strings(converted_currencies: Vec<Currency>, is_print_full: bo
.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),
];
fn get_copper_value(currencies: &[Currency], lhs: &str, rhs: &str) -> (usize, usize) {
let mut rates: HashMap<String, usize> = HashMap::with_capacity(currencies.len());
for currency in currencies {
rates.insert(currency.alias.clone(), currency.rate);
}
#[test]
fn test_convert_copper_to_copper() {
assert_eq!(1, convert_to_copper(1, "c"));
}
let aliases = currencies
.iter()
.cloned()
.map(|c| c.alias)
.fold(String::new(), |group, a| group + &a);
#[test]
fn test_convert_silver_to_copper() {
assert_eq!(10, convert_to_copper(1, "s"));
}
let regex: Regex = Regex::new(&format!("(\\d+)([{}])", aliases)).unwrap();
#[test]
fn test_convert_electrum_to_copper() {
assert_eq!(50, convert_to_copper(1, "e"));
}
let left_hand_side: usize = regex.captures_iter(lhs).fold(0, |sum, cap| {
let value: usize = cap[1].parse().unwrap();
let rate: usize = *rates.get(&cap[2]).unwrap();
let product = value * rate;
#[test]
fn test_convert_gold_to_copper() {
assert_eq!(100, convert_to_copper(1, "g"));
}
sum + product
});
#[test]
fn test_convert_platinum_to_copper() {
assert_eq!(1000, convert_to_copper(1, "p"));
}
let right_hand_side: usize = regex.captures_iter(rhs).fold(0, |sum, cap| {
let value: usize = cap[1].parse().unwrap();
let rate: usize = *rates.get(&cap[2]).unwrap();
let product = value * rate;
#[test]
fn test_calculate_total_copper_value() {
let values = vec!["1p", "1g", "1e", "1s", "1c"];
assert_eq!(1161, calculate_total_copper_value(values).unwrap());
}
sum + product
});
#[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()));
}
(left_hand_side, right_hand_side)
}