commit cc1e49c79485668fa5139e6ab300fdbd17eef056 Author: Zachary Dziura Date: Fri Mar 9 23:05:39 2018 -0500 Release v0.1.0 Implements the Silver Standard conversion on a given list of currency values, defaulting to gold coins. The list of coins are each converted to a base copper coin value, then added together, and finally converted to the given Silver Standard value. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0a880fe --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +# Created by https://www.gitignore.io/api/rust + +### Rust ### +# Generated by Cargo +# will have compiled files and executables +/target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + + +# End of https://www.gitignore.io/api/rust diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..e69de29 diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..05ac0a5 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "sterling" +version = "0.1.0" +description = "Converts a given D&D 5e currency value to the Silver Standard." +authors = ["Zachary Dziura "] + +[dependencies] +clap = "2.31.1" +lazy_static = "1.0.0" +regex = "0.2" + +[profile.release] +lto = true \ No newline at end of file diff --git a/MIT.md b/MIT.md new file mode 100644 index 0000000..2e138dc --- /dev/null +++ b/MIT.md @@ -0,0 +1,26 @@ +The MIT License (MIT) +===================== + +Copyright © `` `` + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the “Software”), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + diff --git a/README.md b/README.md new file mode 100644 index 0000000..c48222c --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +# Sterling + +Converts a given D&D 5e currency value to the Silver Standard. Inspired by the Reddit posts titled +[The Silver Hack: Making Money Matter](https://www.reddit.com/r/DnDBehindTheScreen/comments/80f6kt/the_silver_hack_making_money_matter/), +and [I make Silver Standard for 5th Edition (Spreadsheets.)](https://www.reddit.com/r/dndnext/comments/5tt5g8/i_make_silver_standard_for_5_edition_spreadsheets/). + +## Usage + +``` +sterling [VALUE]... + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +ARGS: + ... 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'. +``` + +## Abstract + +Items and expenses are, by default, assigned arbitrary currency values within the official D&D 5th +edition source books. Many of the officially priced items use the "Gold Standard"; that is, items +are priced in gold coins by default. While there is nothing wrong with using official currency +values within your campaign, it leads to the perceived value of gold to be less in the eyes of your +players. Gold has been sought after as both a commodity and a currency for centuries, and your +campaign aught to treat gold similarly! + +## Explanation + +The basis of the Silver Standard treats 1 gold coin from the official D&D 5e source books as 1 +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, +while a suit of heavy plate armor equals fifteen gold coins, rather than fifteen hundred. \ No newline at end of file diff --git a/UNLICENSE.md b/UNLICENSE.md new file mode 100644 index 0000000..368c4aa --- /dev/null +++ b/UNLICENSE.md @@ -0,0 +1,27 @@ +Unlicense (Public Domain) +============================ + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to <> diff --git a/WAIVER.sigs b/WAIVER.sigs new file mode 100644 index 0000000..1596bce --- /dev/null +++ b/WAIVER.sigs @@ -0,0 +1,24 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA256 + +I dedicate any and all copyright interest in this software to the +public domain. I make this dedication for the benefit of the public at +large and to the detriment of my heirs and successors. I intend this +dedication to be an overt act of relinquishment in perpetuity of all +present and future rights to this software under copyright law. +-----BEGIN PGP SIGNATURE----- + +iQIzBAEBCAAdFiEEMqo2ba6LuiYDXB5kdkVeHsxAMfYFAlqjHbsACgkQdkVeHsxA +MfZy5hAAoSrAqT7Mm3d/r0rRuVTTotvZye6PgKdIx+XSdAYVeRjFrtOumldEDq84 +peE9JjunmfUxqvYPmk8CC6gzdVkkHNh0MM4WHop/qoQGwSQD36G5TvnTEc2SjIYd +NVHbTCz8MpIJ8wzn2EH5x8S3BWIy7XB3NJhIuPBsJzSUSniP5d4J3tJw/2hiO34E +PaKGSfLk9fAErgXUk+PEn98dXuPHeyrFYsSRQZP5yiTlH7eVloe8VTFIjUF+P0qA +XrHWKaEVQYWPXMBTpF8pfPg4rFVnu7F7Pl145AAmQJJo45VLmfDBNWAGQHYMXoyZ +bsCd9hQ9zhZMSXi7CBwMQc6itTKVetv1vH0DB77RLfOs+flvqASV1v1mhgBuxWIy +E0XzMcR1LtSPu9bdNxc/ClDGbFe5NfZU+dbUqTmpPZBgvfF0I/N/hw5RuDusS+hF +m0uvyRL0xIKIgTcNKgfU6pMe4gzVyPCqJ13kJVHfh7RFQ0MV7eQ3eowf8JDnrYZY +8DHJpnLxXKLfPeLY73iQFifFSFPjvpD5ObbDcXMZYToaC39d1n6MtUkh0o5aF8L4 +sA9OGScTevQN9U4bO6AcaUXkqrHuQ9mIk+oP2w1e44O/Fwo9UoBNK0Quc7yA86KJ +tnDsTCZNW9HnwuZvXOuLaUEtWP0DYWDmsQmuIhT5VPAhGp7nv0s= +=2YGI +-----END PGP SIGNATURE----- diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..d666f38 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,120 @@ +#[macro_use] +extern crate clap; +#[macro_use] +extern crate lazy_static; +extern crate regex; + +use std::fmt; +use std::ops::Add; +use std::process; + +use regex::Regex; + +fn main() { + lazy_static! { + static ref RE: Regex = Regex::new(r"(\d+)([cegps])?").unwrap(); + } + + let app = clap_app!(sterling => + (version: "0.1.0") + (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'.") + ); + + if let Some(values) = app.get_matches().values_of("VALUE") { + let coins: Vec<&str> = values.collect(); + + let total_copper_value: usize = coins + .iter() + .map(|coin| { + 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) + } else { + panic!("Error: Invalid coin value \"{}\"", coin); + } + }) + .fold(0 as usize, |total, value| total + value); + + println!("{}", exchange_copper(total_copper_value)); + } 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'."); + process::exit(1); + } +} + +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 exchange_copper(copper: usize) -> CurrencyValue { + CurrencyValue { + platinum: copper / 1000000, + gold: (copper % 1000000) / 10000, + silver: ((copper % 1000000) % 10000) / 100, + copper: ((copper % 1000000) % 10000) % 100, + } +} + +#[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, + } + } +}