aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs99
-rw-r--r--src/main.rs15
2 files changed, 85 insertions, 29 deletions
diff --git a/src/lib.rs b/src/lib.rs
index bef9ffe..e523ee1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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();