diff options
author | Guillermo Ramos | 2025-03-09 16:07:47 +0100 |
---|---|---|
committer | Guillermo Ramos | 2025-03-14 11:52:04 +0100 |
commit | 5feb5cf771d473ff9f55be40169ca5db2bafd268 (patch) | |
tree | a77d32e59daae7a0e2f98919b85706b18debb090 /src/lib.rs | |
parent | 60f037e68466f2ba2137285cfa8e88782dcd905f (diff) | |
download | hiccup-5feb5cf771d473ff9f55be40169ca5db2bafd268.tar.gz |
Updates in front (RO)
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 48 |
1 files changed, 28 insertions, 20 deletions
@@ -2,6 +2,7 @@ use std::collections::HashMap; use std::fmt; use std::ops::AddAssign; +use serde::Deserialize; use serde::Serialize; #[derive(Clone, Copy, Serialize)] @@ -25,16 +26,16 @@ impl AddAssign for Capital { } #[derive(Serialize)] -pub struct Simulation<'a> { +pub struct Simulation { st: SimState, - updates: SimUpdates<'a>, + updates: SimUpdates, history: Vec<Quota>, topay: Capital, payed: Capital, payed_amortized: f64, } -impl<'a> Simulation<'a> { +impl Simulation { pub fn new(principal: f64, i1: f64, years: u32) -> Self { let pending_quotas = years * 12; let i12 = i1 / 12.0; @@ -66,7 +67,7 @@ impl<'a> Simulation<'a> { } } - pub fn run(&mut self, updates: SimUpdates<'a>) { + pub fn run(&mut self, updates: SimUpdates) { self.updates = updates; let mut st = self.st.clone(); while st.pending_quotas > 0 && st.principal > 0. { @@ -209,25 +210,32 @@ impl fmt::Display for Quota { } } -#[derive(Debug, Default, Serialize)] -pub struct SimUpdates<'a> { - periodically: Vec<(u32, Vec<&'a SimUpdate>)>, - by_month: HashMap<u32, Vec<&'a SimUpdate>>, +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct PeriodicUpdate { + period: u32, + from: Option<u32>, + to: Option<u32>, + update: SimUpdate, +} + +#[derive(Debug, Default, Serialize, Deserialize)] +pub struct SimUpdates { + periodically: Vec<PeriodicUpdate>, + by_month: HashMap<u32, Vec<SimUpdate>>, } -impl<'a> SimUpdates<'a> { - fn get(&self, month: u32) -> Vec<&'a SimUpdate> { +impl SimUpdates { + fn get(&self, month: u32) -> Vec<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); - } + for PeriodicUpdate{period, from, to, update} in periodically.iter() { + let base = from.unwrap_or(0); + if month % period == base && base <= month && to.unwrap_or(month+1) > month { + ret.push(*update); } } if let Some(updates) = by_month.get(&month) { @@ -239,7 +247,7 @@ impl<'a> SimUpdates<'a> { ret } - pub fn and(mut self, other: SimUpdates<'a>) -> Self { + pub fn and(mut self, other: SimUpdates) -> Self { for p in other.periodically.iter() { self.periodically.push(p.clone()); } @@ -250,7 +258,7 @@ impl<'a> SimUpdates<'a> { } } -#[derive(Clone, Debug, Serialize)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub enum SimUpdate { Amortize(f64), } @@ -269,18 +277,18 @@ impl fmt::Display for SimUpdate { impl SimUpdate { pub fn every(&self, months: u32) -> SimUpdates { let mut updates = SimUpdates::default(); - updates.periodically.push((months, vec![self])); + updates.periodically.push(PeriodicUpdate{period: months, from: None, to: None, update: *self}); updates } pub fn at(&self, month: u32) -> SimUpdates { let mut updates = SimUpdates::default(); - updates.by_month.insert(month, vec![self]); + updates.by_month.insert(month, vec![*self]); updates } } -fn flatten_amortizations(updates: Vec<&SimUpdate>) -> Vec<SimUpdate> { +fn flatten_amortizations(updates: Vec<SimUpdate>) -> Vec<SimUpdate> { let mut amortized = 0.; let mut result = vec![]; for update in updates { |