From 8907130570df1a67d30a0266c2ba17c27975d713 Mon Sep 17 00:00:00 2001 From: Guillermo Ramos Date: Tue, 4 Feb 2025 00:09:04 +0100 Subject: Mortgage updates --- src/lib.rs | 100 ++++++++++++++++++++++++++++++++++++++++++++---------------- src/main.rs | 12 ++++++-- 2 files changed, 84 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index fc75ebd..7f8a58a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,10 @@ +use std::collections::HashMap; use std::fmt; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Mortgage { period: u32, - capital: f64, + principal: f64, i12: f64, quota: f64, quotas: u32, @@ -13,65 +14,112 @@ impl fmt::Display for Mortgage { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, - "{:5} | {:4.2}\t{:.2}\t{:.2}\t{:.2}", + "{:3} | {:5} | {:4.2}\t{:.2}\t{:.2}\t{:.2}", + if self.period % 12 == 0 { + format!("Y{}", (self.period / 12) + 1) + } else { + "".to_string() + }, self.period, self.quota, - self.interests(), - self.amortized(), - self.capital + self.quota_interest(), + self.quota_principal(), + self.principal ) } } impl Mortgage { - pub fn new(capital: f64, i1: f64, years: u32) -> Self { + pub fn new(principal: f64, i1: f64, years: u32) -> Self { let quotas = years * 12; let i12 = i1 / 12.0; Mortgage { period: 0, - capital, + principal, i12, - quota: Self::quota(capital, i12, quotas), + quota: Self::quota(principal, i12, quotas), quotas, } } - pub fn run(&mut self) { - let to_pay = self.quota * self.quotas as f64; - let capital = self.capital; - let interest = to_pay - capital; + pub fn run(&mut self, updates: HashMap) { + let principal = self.principal; - println!("Cuota | c\tIn\tAn\tCn"); - while self.quotas > 0 { + let topay_total = self.quota * self.quotas as f64; + let topay_interest = topay_total - principal; + + let mut payed_total = 0.; + let mut payed_principal = 0.; + let mut payed_interest = 0.; + let mut payed_amortized = 0.; + + println!("Año | Cuota | c\t\tIn\tAn\tCn"); + while self.quotas > 0 && self.principal > 0. { println!("{self}"); + if let Some(update) = updates.get(&self.period) { + payed_amortized += self.update(update); + } + payed_total += self.quota; + payed_principal += self.quota_principal(); + payed_interest += self.quota_interest(); self.step(); } + + payed_total += payed_amortized; + + println!("\n# A PRIORI"); + println!( + "== Total a pagar: {:.2} ({} cap + {topay_interest:.2} int)", + topay_total, principal + ); + println!( + "== Los intereses suponen un {:.2}% del total", + 100. * topay_interest / topay_total + ); + + println!("\n# A POSTERIORI"); println!( - "\n== Total a pagar: {:.2} ({} cap + {interest:.2} int)", - to_pay, capital + "== Total pagado: {:.2} ({:.2} cap + {:.2} int + {:.2} amortizado)", + payed_total, payed_principal, payed_interest, payed_amortized ); println!( - "== Los intereses suponen un {:.2}% del capital", - 100. * interest / capital + "== Los intereses suponen un {:.2}% del total", + 100. * payed_interest / payed_total ); println!("\n"); } - fn quota(capital: f64, i12: f64, quotas: u32) -> f64 { - capital * i12 / (1.0 - (1.0 + i12).powi(-(quotas as i32))) + fn update(&mut self, update: &MortgageUpdate) -> f64 { + print!(" [MORTGAGE UPDATE: "); + match update { + MortgageUpdate::Amortize(principal) => { + println!("{principal:.2} amortized to reduce quotas]"); + self.principal -= principal; + self.quota = Self::quota(self.principal, self.i12, self.quotas); + *principal + } + } + } + + fn quota(principal: f64, i12: f64, quotas: u32) -> f64 { + principal * i12 / (1.0 - (1.0 + i12).powi(-(quotas as i32))) } fn step(&mut self) { self.period += 1; self.quotas -= 1; - self.capital = (1.0 + self.i12) * self.capital - self.quota; + self.principal = (1.0 + self.i12) * self.principal - self.quota; } - fn interests(&self) -> f64 { - self.i12 * self.capital + fn quota_interest(&self) -> f64 { + self.i12 * self.principal } - fn amortized(&self) -> f64 { - self.quota - self.interests() + fn quota_principal(&self) -> f64 { + self.quota - self.quota_interest() } } + +pub enum MortgageUpdate { + Amortize(f64), +} diff --git a/src/main.rs b/src/main.rs index 76c7913..bbe01af 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,12 @@ +use hiccup::Mortgage; +use hiccup::MortgageUpdate::{self, *}; +use std::collections::HashMap; + fn main() { - let mut m = hiccup::Mortgage::new(390_000., 0.028, 30); - m.run(); + let mut updates: HashMap = + HashMap::from_iter((1..29).map(|y| (y * 12, Amortize(24_000.)))); + updates.insert(0, Amortize(15_000.)); + let m = Mortgage::new(390_000., 0.028, 30); + m.clone().run(updates); + // m.clone().run(HashMap::new()); } -- cgit v1.2.3