aboutsummaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
authorGuillermo Ramos2025-03-09 16:07:47 +0100
committerGuillermo Ramos2025-03-14 11:52:04 +0100
commit5feb5cf771d473ff9f55be40169ca5db2bafd268 (patch)
treea77d32e59daae7a0e2f98919b85706b18debb090 /src/lib.rs
parent60f037e68466f2ba2137285cfa8e88782dcd905f (diff)
downloadhiccup-5feb5cf771d473ff9f55be40169ca5db2bafd268.tar.gz
Updates in front (RO)
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs48
1 files changed, 28 insertions, 20 deletions
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<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 {