diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 99 | ||||
-rw-r--r-- | src/main.rs | 15 |
2 files changed, 85 insertions, 29 deletions
@@ -22,16 +22,16 @@ impl AddAssign for Capital { } } -pub struct Simulation { +pub struct Simulation<'a> { st: SimState, - updates: SimUpdates, + updates: SimUpdates<'a>, history: Vec<Quota>, topay: Capital, payed: Capital, payed_amortized: f64, } -impl Simulation { +impl<'a> Simulation<'a> { pub fn new(principal: f64, i1: f64, years: u32) -> Self { let pending_quotas = years * 12; let i12 = i1 / 12.0; @@ -59,11 +59,11 @@ impl Simulation { }, payed_amortized: 0., history: vec![], - updates: HashMap::new(), + updates: SimUpdates::new(), } } - pub fn run(&mut self, updates: SimUpdates) { + pub fn run(&mut self, updates: SimUpdates<'a>) { self.updates = updates; let mut st = self.st.clone(); while st.pending_quotas > 0 && st.principal > 0. { @@ -75,17 +75,18 @@ impl Simulation { } fn apply_updates(&mut self, st: &mut SimState) { - match self.updates.get_mut(&st.period) { - Some(SimUpdate::Amortize(principal)) => { - if *principal > st.principal { - *principal = st.principal; - }; - st.principal -= *principal; - st.calculate_monthly(); - self.payed.principal += *principal; - self.payed_amortized += *principal; + for update in self.updates.get(st.period) { + match update { + SimUpdate::Amortize(mut principal) => { + if principal > st.principal { + principal = st.principal; + }; + st.principal -= principal; + st.calculate_monthly(); + self.payed.principal += principal; + self.payed_amortized += principal; + } } - None => (), } } @@ -105,7 +106,7 @@ impl Simulation { println!("Year | Mon | Quota ( Amrtzd + Intrst) | Pending"); for st in self.history.iter() { print!("{st}"); - if let Some(update) = self.updates.get(&st.period) { + for update in self.updates.get(st.period) { print!(" {update}"); } println!(); @@ -205,9 +206,55 @@ impl fmt::Display for Quota { } } -pub type SimUpdates = HashMap<u32, SimUpdate>; +#[derive(Debug)] +pub struct SimUpdates<'a> { + periodically: Vec<(u32, Vec<&'a SimUpdate>)>, + by_month: HashMap<u32, Vec<&'a SimUpdate>>, +} +// pub type SimUpdates<'a> = HashMap<u32, &'a SimUpdate>; +impl<'a> SimUpdates<'a> { + pub fn new() -> Self { + SimUpdates { + periodically: vec![], + by_month: HashMap::new(), + } + } -#[derive(Clone)] + fn get(&self, month: u32) -> Vec<&'a SimUpdate> { + let SimUpdates { + periodically, + by_month, + } = self; + + let mut ret = vec![]; + for (m, updates) in periodically.iter() { + if month % m == 0 { + for update in updates.iter() { + ret.push(*update); + } + } + } + if let Some(updates) = by_month.get(&month) { + for update in updates.iter() { + ret.push(*update); + } + } + // println!(" {self:?}.get({month}) -> {ret:?}"); + ret + } + + pub fn and(mut self, other: SimUpdates<'a>) -> Self { + for p in other.periodically.iter() { + self.periodically.push(p.clone()); + } + for (k, v) in other.by_month { + self.by_month.insert(k, v); + } + self + } +} + +#[derive(Clone, Debug)] pub enum SimUpdate { Amortize(f64), } @@ -217,8 +264,22 @@ impl fmt::Display for SimUpdate { write!(f, "[MORTGAGE UPDATE: ")?; match self { Self::Amortize(principal) => { - write!(f, "{principal:.2} amortized to reduce pending_quotas]") + write!(f, "{principal:.2} amortized to reduce pending quotas]") } } } } + +impl SimUpdate { + pub fn every(&self, months: u32) -> SimUpdates { + let mut updates = SimUpdates::new(); + updates.periodically.push((months, vec![self])); + updates + } + + pub fn at(&self, month: u32) -> SimUpdates { + let mut updates = SimUpdates::new(); + updates.by_month.insert(month, vec![self]); + updates + } +} diff --git a/src/main.rs b/src/main.rs index fa9e01a..80d7ae7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,16 +1,11 @@ -use hiccup::SimUpdate::*; -use hiccup::{SimUpdates, Simulation}; -use std::collections::HashMap; +use hiccup::{SimUpdate::*, SimUpdates, Simulation}; fn main() { - // let mut sim = Simulation::new(390_000., 0.028, 30); - // let updates: SimUpdates = HashMap::from_iter((0..29).map(|y| match y { - // 0 => (0, Amortize(30_000.)), - // _ => (y * 12, Amortize(12_000.)), - // })); + let mut sim = Simulation::new(390_000., 0.028, 30); + let updates: SimUpdates = Amortize(12_000.).every(12).and(Amortize(30_000.).at(1)); - let mut sim = Simulation::new(200_000., 0.01621, 30); - let updates: SimUpdates = HashMap::new(); + // let mut sim = Simulation::new(200_000., 0.01621, 30); + // let updates: SimUpdates = SimUpdates::new(); sim.run(updates); sim.render_table(); |