fix: floating point arithmetic is shaky
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
https://floating-point-gui.de/
This commit is contained in:
parent
b29e56bc5c
commit
7fff3aaaaf
3 changed files with 530 additions and 128 deletions
416
Cargo.lock
generated
416
Cargo.lock
generated
|
@ -2,12 +2,143 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bitvec"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
|
||||
dependencies = [
|
||||
"funty",
|
||||
"radium",
|
||||
"tap",
|
||||
"wyz",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "borsh"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b"
|
||||
dependencies = [
|
||||
"borsh-derive",
|
||||
"hashbrown 0.13.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "borsh-derive"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7"
|
||||
dependencies = [
|
||||
"borsh-derive-internal",
|
||||
"borsh-schema-derive-internal",
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "borsh-derive-internal"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "borsh-schema-derive-internal"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytecheck"
|
||||
version = "0.6.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627"
|
||||
dependencies = [
|
||||
"bytecheck_derive",
|
||||
"ptr_meta",
|
||||
"simdutf8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytecheck_derive"
|
||||
version = "0.6.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "funty"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.10"
|
||||
|
@ -19,25 +150,295 @@ dependencies = [
|
|||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
dependencies = [
|
||||
"ahash 0.7.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
|
||||
dependencies = [
|
||||
"ahash 0.8.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.147"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785"
|
||||
dependencies = [
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ptr_meta"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1"
|
||||
dependencies = [
|
||||
"ptr_meta_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ptr_meta_derive"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "radium"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rend"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "581008d2099240d37fb08d77ad713bcaec2c4d89d50b5b21a8bb1996bbab68ab"
|
||||
dependencies = [
|
||||
"bytecheck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rkyv"
|
||||
version = "0.7.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0200c8230b013893c0b2d6213d6ec64ed2b9be2e0e016682b7224ff82cff5c58"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"bytecheck",
|
||||
"hashbrown 0.12.3",
|
||||
"ptr_meta",
|
||||
"rend",
|
||||
"rkyv_derive",
|
||||
"seahash",
|
||||
"tinyvec",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rkyv_derive"
|
||||
version = "0.7.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2e06b915b5c230a17d7a736d1e2e63ee753c256a8614ef3f5147b13a4f5541d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust_decimal"
|
||||
version = "1.31.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a2ab0025103a60ecaaf3abf24db1db240a4e1c15837090d2c32f625ac98abea"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"borsh",
|
||||
"byteorder",
|
||||
"bytes",
|
||||
"num-traits",
|
||||
"rand",
|
||||
"rkyv",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust_decimal_macros"
|
||||
version = "1.31.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9c3bcd00383608992fd3e960f0a6e93a3b1e98218451aa1ca05a44505e5d52a"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"rust_decimal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
||||
|
||||
[[package]]
|
||||
name = "seahash"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.183"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c"
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.105"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simdutf8"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a"
|
||||
|
||||
[[package]]
|
||||
name = "split"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"rust_decimal",
|
||||
"rust_decimal_macros",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tap"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec_macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.4.1"
|
||||
|
@ -48,8 +449,23 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wyz"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
|
||||
dependencies = [
|
||||
"tap",
|
||||
]
|
||||
|
|
|
@ -12,4 +12,6 @@ edition = "2021"
|
|||
#build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
rust_decimal = "1.31.0"
|
||||
rust_decimal_macros = "1.31.0"
|
||||
uuid = { version = "1.4.1", features = ["v4", "serde"] }
|
||||
|
|
240
src/lib.rs
240
src/lib.rs
|
@ -17,18 +17,16 @@
|
|||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
use rust_decimal::prelude::*;
|
||||
use rust_decimal_macros::dec;
|
||||
use uuid::Uuid;
|
||||
|
||||
pub trait Purchasable {
|
||||
fn cost(&self) -> f64;
|
||||
fn cost(&self) -> Decimal;
|
||||
fn name(&self) -> &str;
|
||||
fn paid_by(&self) -> Rc<dyn Actor>;
|
||||
}
|
||||
|
||||
pub fn money_owned(splits: &[Split]) {
|
||||
for split in splits.iter() {}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Split {
|
||||
purchase: Rc<dyn Purchasable>,
|
||||
|
@ -36,68 +34,78 @@ pub struct Split {
|
|||
parties: Vec<Rc<dyn Actor>>,
|
||||
}
|
||||
|
||||
|
||||
//#[derive(Clone)]
|
||||
//pub struct Split {
|
||||
// shares: ShareHashMap,
|
||||
// paid_by: Rc<dyn Actor>,
|
||||
//}
|
||||
|
||||
impl Split {
|
||||
pub fn new(purchase: Rc<dyn Purchasable>, split_strategy: SplitStrategy, parties: Vec<Rc<dyn Actor>>) -> Self {
|
||||
pub fn new(
|
||||
purchase: Rc<dyn Purchasable>,
|
||||
split_strategy: SplitStrategy,
|
||||
parties: Vec<Rc<dyn Actor>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
split_strategy, parties, purchase
|
||||
split_strategy,
|
||||
parties,
|
||||
purchase,
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn iter(&self) -> SplitIter {
|
||||
// let iter = self.shares.iter();
|
||||
// let paid_by = self.paid_by;
|
||||
// SplitIter { iter, paid_by}
|
||||
// }
|
||||
//
|
||||
// pub fn insert(&mut self, actor: Rc<dyn Actor>, amount: f64) {
|
||||
// let name = actor.name().to_owned();
|
||||
// self.shares.insert(name, (actor, amount));
|
||||
// }
|
||||
pub fn money_owed(&self) -> ShareHashMap {
|
||||
match &self.split_strategy {
|
||||
SplitStrategy::Unequal(shares) => {
|
||||
let mut s = shares.clone();
|
||||
let payer = self.purchase.paid_by();
|
||||
if let Some((_, money)) = s.get_mut(payer.name()) {
|
||||
*money = dec!(0.0);
|
||||
}
|
||||
s
|
||||
}
|
||||
SplitStrategy::Equal => {
|
||||
let mut shares = ShareHashMap::default();
|
||||
let cost = self.purchase.cost();
|
||||
let total_parties = Decimal::new(self.parties.len() as i64, 0);
|
||||
for actor in self.parties.iter() {
|
||||
if *actor == self.purchase.paid_by() {
|
||||
shares.insert(actor.name().to_owned(), (actor.clone(), dec!(0.00)));
|
||||
} else {
|
||||
shares.insert(
|
||||
actor.name().to_owned(),
|
||||
(actor.clone(), cost / total_parties),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&mut self, actor: Rc<dyn Actor>) -> Option<f64> {
|
||||
shares
|
||||
}
|
||||
SplitStrategy::Shares(c) => {
|
||||
let mut shares = ShareHashMap::default();
|
||||
let cost = self.purchase.cost();
|
||||
for (actor_name, (actor, share)) in c.iter() {
|
||||
//if actor.name() == split.purchase.paid_by().name() {
|
||||
if *actor == self.purchase.paid_by() {
|
||||
shares.insert(actor_name.clone(), (actor.clone(), dec!(0.00)));
|
||||
} else {
|
||||
shares.insert(actor_name.clone(), (actor.clone(), cost * share));
|
||||
}
|
||||
}
|
||||
shares
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&mut self, actor: Rc<dyn Actor>) -> Option<Decimal> {
|
||||
unimplemented!();
|
||||
// if let Some((_actor, cost)) = self.shares.get(actor.name()) {
|
||||
// Some(*cost)
|
||||
// } else {
|
||||
// None
|
||||
// }
|
||||
}
|
||||
}
|
||||
// if let Some((_actor, cost)) = self.shares.get(actor.name()) {
|
||||
// Some(*cost)
|
||||
// } else {
|
||||
// None
|
||||
// }
|
||||
}
|
||||
|
||||
//pub struct SplitIter<'a> {
|
||||
// iter: std::collections::hash_map::Iter<'a, String, (Rc<dyn Actor>, f64)>,
|
||||
// paid_by: Rc<dyn Actor>,
|
||||
//}
|
||||
//
|
||||
//impl<'a> Iterator for SplitIter<'a> {
|
||||
// type Item = (Rc<dyn Actor>, f64);
|
||||
//
|
||||
// fn next(&mut self) -> Option<Self::Item> {
|
||||
// if let Some((_, (actor, cost))) = self.iter.next() {
|
||||
// Some((actor.clone(), *cost))
|
||||
// } else {
|
||||
// None
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
impl Split {
|
||||
pub fn validate(&self) -> bool {
|
||||
self.split_strategy.validate(&self)
|
||||
self.split_strategy.validate(self.purchase.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// key is a string for getting Eq and PartialEq w object safety
|
||||
pub type ShareHashMap = HashMap<String, (Rc<dyn Actor>, f64)>;
|
||||
|
||||
pub type ShareHashMap = HashMap<String, (Rc<dyn Actor>, Decimal)>;
|
||||
|
||||
/*
|
||||
* SPLITTING STRATEGIES:
|
||||
|
@ -113,74 +121,35 @@ pub enum SplitStrategy {
|
|||
}
|
||||
|
||||
impl SplitStrategy {
|
||||
pub fn validate(&self, split: &Split) -> bool {
|
||||
fn validate(&self, purchase: &dyn Purchasable) -> bool {
|
||||
match self {
|
||||
SplitStrategy::Unequal(shares) => {
|
||||
let mut total = 0.00;
|
||||
let mut total = dec!(0.00);
|
||||
for (_actor_str, (_actor_obj, share)) in shares.iter() {
|
||||
total += share;
|
||||
}
|
||||
|
||||
let cost = split.purchase.cost();
|
||||
let cost = purchase.cost();
|
||||
println!("Unequal sharing: expected {cost} got {total}");
|
||||
total == cost
|
||||
}
|
||||
SplitStrategy::Shares(shares) => {
|
||||
let mut total = 0.00;
|
||||
let cost = split.purchase.cost();
|
||||
let mut total_shares = 0.00;
|
||||
let mut total = dec!(0.00);
|
||||
let cost = purchase.cost();
|
||||
let mut total_shares = dec!(0.00);
|
||||
for (_actor_str, (_actor_obj, share)) in shares.iter() {
|
||||
total_shares += share;
|
||||
total += cost * share;
|
||||
println!("Shares: {:?}, total: {total_shares}", share);
|
||||
}
|
||||
|
||||
println!("Unequal sharing: expected shares 1 got {total_shares}");
|
||||
println!("Unequal sharing: expected {cost} got {total}");
|
||||
total_shares == 1.00 && total == cost
|
||||
total_shares == dec!(1.00) && total == cost
|
||||
}
|
||||
SplitStrategy::Equal => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn money_owed(&self, split: &Split) -> ShareHashMap {
|
||||
match self {
|
||||
SplitStrategy::Unequal(shares) => {
|
||||
let mut s = shares.clone();
|
||||
let payer = split.purchase.paid_by();
|
||||
if let Some((_,money)) = s.get_mut(payer.name()) {
|
||||
*money = 0.0;
|
||||
}
|
||||
s
|
||||
|
||||
}
|
||||
SplitStrategy::Equal => {
|
||||
let mut shares = ShareHashMap::default();
|
||||
let cost = split.purchase.cost();
|
||||
for actor in split.parties.iter() {
|
||||
if *actor == split.purchase.paid_by() {
|
||||
shares.insert(actor.name().to_owned(), (actor.clone(), 0.00));
|
||||
} else {
|
||||
shares.insert(actor.name().to_owned(), (actor.clone(), cost / split.parties.len() as f64));
|
||||
}
|
||||
}
|
||||
|
||||
shares
|
||||
}
|
||||
SplitStrategy::Shares(c) => {
|
||||
let mut shares = ShareHashMap::default();
|
||||
let cost = split.purchase.cost();
|
||||
for (actor_name,(actor, share)) in c.iter() {
|
||||
//if actor.name() == split.purchase.paid_by().name() {
|
||||
if *actor == split.purchase.paid_by() {
|
||||
shares.insert(actor_name.clone(), (actor.clone(), 0.00));
|
||||
} else {
|
||||
shares.insert(actor_name.clone(), (actor.clone(), cost * share));
|
||||
}
|
||||
}
|
||||
shares
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Actor {
|
||||
|
@ -209,7 +178,12 @@ impl Person {
|
|||
let owes = Vec::default();
|
||||
let spent = Vec::default();
|
||||
|
||||
Self { name, spent, owes, id}
|
||||
Self {
|
||||
name,
|
||||
spent,
|
||||
owes,
|
||||
id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,23 +208,22 @@ impl Actor for Person {
|
|||
fn id(&self) -> &Uuid {
|
||||
&self.id
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub struct Item {
|
||||
cost: f64,
|
||||
cost: Decimal,
|
||||
name: String,
|
||||
payer: Rc<dyn Actor>,
|
||||
}
|
||||
|
||||
impl Item {
|
||||
pub fn new(name: String, cost: f64, payer: Rc<dyn Actor>) -> Self {
|
||||
pub fn new(name: String, cost: Decimal, payer: Rc<dyn Actor>) -> Self {
|
||||
Self { cost, name, payer }
|
||||
}
|
||||
}
|
||||
|
||||
impl Purchasable for Item {
|
||||
fn cost(&self) -> f64 {
|
||||
fn cost(&self) -> Decimal {
|
||||
self.cost
|
||||
}
|
||||
fn name(&self) -> &str {
|
||||
|
@ -278,45 +251,47 @@ mod tests {
|
|||
let person3: Rc<dyn Actor> = Rc::new(Person::new("person3".into(), Uuid::new_v4()));
|
||||
let person4: Rc<dyn Actor> = Rc::new(Person::new("person4".into(), Uuid::new_v4()));
|
||||
|
||||
let item = Item::new("test item".into(), 240.00, person1.clone());
|
||||
let item = Item::new("test item".into(), dec!(240.00), person1.clone());
|
||||
let actors = vec![
|
||||
person1.clone(),
|
||||
person2.clone(),
|
||||
person3.clone(),
|
||||
person4.clone(),
|
||||
];
|
||||
|
||||
|
||||
// equal split
|
||||
let strategy = SplitStrategy::Equal;
|
||||
|
||||
let mut split = Split::new(Rc::new(item), strategy, actors);
|
||||
assert!(split.split_strategy.validate(&split));
|
||||
let dues = split.split_strategy.money_owed(&split);
|
||||
for (_actor_name,(actor, due)) in dues.iter() {
|
||||
assert!(split.validate());
|
||||
let dues = split.money_owed();
|
||||
for (_actor_name, (actor, due)) in dues.iter() {
|
||||
if split.purchase.paid_by().name() == actor.name() {
|
||||
assert_eq!(*due, 0.00);
|
||||
assert_eq!(*due, dec!(0.00));
|
||||
} else {
|
||||
assert_eq!(*due, split.purchase.cost() / split.parties.len() as f64);
|
||||
assert_eq!(
|
||||
*due,
|
||||
split.purchase.cost() / Decimal::new(split.parties.len() as i64, 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// share split
|
||||
let mut shares = ShareHashMap::default();
|
||||
shares.insert(person1.name().to_owned(), (person1.clone(), 0.3));
|
||||
shares.insert(person2.name().to_owned(), (person2.clone(), 0.4));
|
||||
shares.insert(person3.name().to_owned(), (person3.clone(), 0.2));
|
||||
shares.insert(person4.name().to_owned(), (person4.clone(), 0.1));
|
||||
shares.insert(person1.name().to_owned(), (person1.clone(), dec!(0.3)));
|
||||
shares.insert(person2.name().to_owned(), (person2.clone(), dec!(0.4)));
|
||||
shares.insert(person3.name().to_owned(), (person3.clone(), dec!(0.2)));
|
||||
shares.insert(person4.name().to_owned(), (person4.clone(), dec!(0.1)));
|
||||
let strategy = SplitStrategy::Shares(shares.clone());
|
||||
|
||||
split.split_strategy = strategy;
|
||||
assert!(split.split_strategy.validate(&split));
|
||||
assert!(split.validate());
|
||||
|
||||
let dues = split.split_strategy.money_owed(&split);
|
||||
let dues = split.money_owed();
|
||||
for (actor_name, (actor, due)) in dues.iter() {
|
||||
println!("Testing for actor: {actor_name} with due: {due}");
|
||||
if split.purchase.paid_by().name() == actor.name() {
|
||||
assert_eq!(*due, 0.00);
|
||||
assert_eq!(*due, dec!(0.00));
|
||||
} else {
|
||||
let (_, share) = shares.get(actor_name).unwrap();
|
||||
assert_eq!(*due, split.purchase.cost() * *share);
|
||||
|
@ -325,15 +300,24 @@ mod tests {
|
|||
|
||||
// Unequal split
|
||||
let mut shares = ShareHashMap::default();
|
||||
shares.insert(person1.name().to_owned(), (person1.clone(), 0.3 * split.purchase.cost()));
|
||||
shares.insert(person2.name().to_owned(), (person2.clone(), 0.4 * split.purchase.cost()));
|
||||
shares.insert(person3.name().to_owned(), (person3.clone(), 0.2 * split.purchase.cost()));
|
||||
shares.insert(person4.name().to_owned(), (person4.clone(), 0.1 * split.purchase.cost()));
|
||||
shares.insert(
|
||||
person1.name().to_owned(),
|
||||
(person1.clone(), dec!(0.3) * split.purchase.cost()),
|
||||
);
|
||||
shares.insert(
|
||||
person2.name().to_owned(),
|
||||
(person2.clone(), dec!(0.4) * split.purchase.cost()),
|
||||
);
|
||||
shares.insert(
|
||||
person3.name().to_owned(),
|
||||
(person3.clone(), dec!(0.2) * split.purchase.cost()),
|
||||
);
|
||||
shares.insert(
|
||||
person4.name().to_owned(),
|
||||
(person4.clone(), dec!(0.1) * split.purchase.cost()),
|
||||
);
|
||||
let strategy = SplitStrategy::Unequal(shares);
|
||||
split.split_strategy = strategy;
|
||||
assert!(split.split_strategy.validate(&split));
|
||||
|
||||
|
||||
assert!(split.validate());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue