use std::collections::btree_map::Entry;
use super::prelude::*;
#[apply(cmd_args!)]
pub struct Pay {
#[pos]
pub amount: Money,
#[named]
pub who: Dir,
}
impl Command for Pay {
type Args = Self;
}
impl Run for Pay {
fn run(self: Box<Self>, ctx: &mut State) -> Output {
let mut difference: Value = self.amount.into();
difference.align_to(&self.who);
match ctx.balances.entry(self.who.into()) {
Entry::Occupied(mut entry) => *entry.get_mut() += difference,
Entry::Vacant(entry) => {
entry.insert(difference);
}
}
None
}
}
#[cfg(test)]
mod tests {
use crate::{Set, eval, ext::math::Integer};
#[test]
fn basic() {
let rt = eval(
"
create entity A
create entity B
create entity C
pay 1€ from=A to=B
pay 5€ from=B to=A
pay 3€ from=A to=C
",
)
.unwrap();
let s = |lit: &str| lit.to_string();
let i = Integer::from;
assert_eq!(
rt.to_state()
.balances
.into_iter()
.map(|(pair, bal)| {
(
pair.into_iter()
.map(|e| e.name().to_owned())
.collect::<Vec<_>>(),
bal.0,
)
})
.collect::<Set<_>>(),
[
(vec![s("A"), s("B")], i(-400)),
(vec![s("A"), s("C")], i(300))
]
.into_iter()
.collect::<Set<_>>(),
);
}
}