From 5feb5cf771d473ff9f55be40169ca5db2bafd268 Mon Sep 17 00:00:00 2001 From: Guillermo Ramos Date: Sun, 9 Mar 2025 16:07:47 +0100 Subject: Updates in front (RO) --- src/lib.rs | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) (limited to 'src/lib.rs') diff --git a/src/lib.rs b/src/lib.rs index 423f607..1f4a977 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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, 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>, +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct PeriodicUpdate { + period: u32, + from: Option, + to: Option, + update: SimUpdate, +} + +#[derive(Debug, Default, Serialize, Deserialize)] +pub struct SimUpdates { + periodically: Vec, + by_month: HashMap>, } -impl<'a> SimUpdates<'a> { - fn get(&self, month: u32) -> Vec<&'a SimUpdate> { +impl SimUpdates { + fn get(&self, month: u32) -> Vec { 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 { +fn flatten_amortizations(updates: Vec) -> Vec { let mut amortized = 0.; let mut result = vec![]; for update in updates { -- cgit v1.2.3