diff options
author | Yaroslav <contact@yaroslavps.com> | 2020-10-06 14:13:14 +0300 |
---|---|---|
committer | Yaroslav <contact@yaroslavps.com> | 2020-10-06 14:13:14 +0300 |
commit | 742b9fa46d74762f58ae939afd980a532cc4636f (patch) | |
tree | 0cd372442e5518dece1a9ec371ae71dccc5faae4 | |
parent | cc688c4dc73d3b13be5aba1bd292cc31265c5d04 (diff) | |
download | finbudg-370dc39882eebda85fa239a976e2fce19b819dbb.tar.gz finbudg-370dc39882eebda85fa239a976e2fce19b819dbb.zip |
Account for days elapsed based on latest datev0.1.2
Instead of counting the number of days for the averge through
the number of iterations, let it be the difference between the latest
date on entry and the start of the period. Id est:
* 'Missing' dates from the input are implicit.
* The order of the days doesn't affect the output (although it doesn't
make sense to put the days out of order).
-rw-r--r-- | Cargo.lock | 2 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | budget/src/lib.rs | 31 | ||||
-rw-r--r-- | budget/tests/budget.rs | 29 | ||||
-rw-r--r-- | budget/tests/test.toml | 6 | ||||
-rw-r--r-- | src/main.rs | 17 |
6 files changed, 46 insertions, 41 deletions
@@ -82,7 +82,7 @@ dependencies = [ [[package]] name = "finbudg" -version = "0.1.0" +version = "0.1.2" dependencies = [ "budget", "chrono", @@ -1,6 +1,6 @@ [package] name = "finbudg" -version = "0.1.1" +version = "0.1.2" edition = "2018" description = "Quick cli tool to calculate your expenses and balance for a set period of time." license = "MIT" diff --git a/budget/src/lib.rs b/budget/src/lib.rs index e8bb8f3..7d7c390 100644 --- a/budget/src/lib.rs +++ b/budget/src/lib.rs @@ -51,6 +51,7 @@ pub struct Calculated { pub balance: f64, pub days_left: f64, pub days_left_essential: f64, + pub last_day: NaiveDate, } #[derive(PartialEq, Eq, Debug)] @@ -96,7 +97,11 @@ pub fn parse_account(path: &str) -> Result<Account, ParseError> { } } -pub fn calculate(account: &Account) -> Calculated { +pub fn calculate(account: &Account) -> Option<Calculated> { + if account.days.len() < 1 { + return None; + } + let mut calculated = Calculated { all_day_average: 0.0, essential_day_average: 0.0, @@ -107,12 +112,13 @@ pub fn calculate(account: &Account) -> Calculated { balance: 0.0, days_left: 0.0, days_left_essential: 0.0, + last_day: account.days.last().unwrap().date, }; - let mut days_calculated = 0; - for day in account.days.iter() { - days_calculated += 1; + if day.date > calculated.last_day { + calculated.last_day = day.date; + } for expense in day.expenses.iter() { calculated.total += expense.price; @@ -135,15 +141,18 @@ pub fn calculate(account: &Account) -> Calculated { } } - calculated.all_day_average = calculated.total / days_calculated as f64; + let days_elapsed = + (calculated.last_day - account.start_date).num_days() + 1; + + calculated.all_day_average = calculated.total / days_elapsed as f64; calculated.essential_day_average = - calculated.essential_subtotal / days_calculated as f64; + calculated.essential_subtotal / days_elapsed as f64; for (category, subtotal) in calculated.categories_subtotal.iter() { calculated.categories_day_average .insert( category.clone(), - subtotal / days_calculated as f64, + subtotal / days_elapsed as f64, ); } @@ -153,11 +162,5 @@ pub fn calculate(account: &Account) -> Calculated { calculated.days_left_essential = calculated.balance / calculated.essential_day_average; - calculated -} - -pub fn get_calculated(path: &str) -> Result<Calculated, ParseError> { - let account = parse_account(path)?; - - Ok(calculate(&account)) + Some(calculated) } diff --git a/budget/tests/budget.rs b/budget/tests/budget.rs index 1cc02e7..feae240 100644 --- a/budget/tests/budget.rs +++ b/budget/tests/budget.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use chrono::prelude::*; +use chrono::NaiveDate; use budget::*; @@ -62,6 +62,10 @@ fn can_parse_account() -> Result<(), ParseError>{ ], }, Day { + date: NaiveDate::from_ymd(2020, 10, 4), + expenses: Vec::<Expense>::new(), + }, + Day { date: NaiveDate::from_ymd(2020, 10, 2), expenses: vec![ Expense { @@ -82,10 +86,6 @@ fn can_parse_account() -> Result<(), ParseError>{ }, ], }, - Day { - date: NaiveDate::from_ymd(2020, 10, 3), - expenses: Vec::<Expense>::new(), - }, ], }; @@ -99,32 +99,33 @@ fn can_parse_account() -> Result<(), ParseError>{ #[test] fn can_calculate() -> Result<(), ParseError> { let mut should_be = Calculated { - all_day_average: 7.57, - essential_day_average: 6.3, + all_day_average: 5.6775, + essential_day_average: 4.725, categories_day_average: HashMap::<String, f64>::new(), essential_subtotal: 18.9, categories_subtotal: HashMap::<String, f64>::new(), total: 22.71, balance: 397.29, - days_left: 52.48216644649934, - days_left_essential: 63.06190476190476, + days_left: 69.9762219286658, + days_left_essential: 84.08253968253969, + last_day: NaiveDate::from_ymd(2020, 10, 04), }; should_be.categories_day_average.insert( "supplies".to_string(), - 1.27, + 0.9525, ); should_be.categories_day_average.insert( "products".to_string(), - 2.3333333333333335, + 1.75, ); should_be.categories_day_average.insert( "transport".to_string(), - 2.3000000000000003, + 1.725, ); should_be.categories_day_average.insert( "utilities".to_string(), - 1.6666666666666667, + 1.25, ); should_be.categories_subtotal.insert( @@ -145,7 +146,7 @@ fn can_calculate() -> Result<(), ParseError> { ); let account = budget::parse_account("tests/test.toml")?; - let actually_is = budget::calculate(&account); + let actually_is = budget::calculate(&account).unwrap(); assert_eq!(actually_is, should_be); diff --git a/budget/tests/test.toml b/budget/tests/test.toml index 1bb1ce7..a29467e 100644 --- a/budget/tests/test.toml +++ b/budget/tests/test.toml @@ -39,6 +39,9 @@ date = 2020-10-01 shared = 2 [[days]] +date = 2020-10-04 + +[[days]] date = 2020-10-02 [[days.expenses]] @@ -52,6 +55,3 @@ date = 2020-10-02 price = 6.9 category = "transport" -[[days]] -date = 2020-10-03 - diff --git a/src/main.rs b/src/main.rs index 04d5277..5c64959 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,7 +33,7 @@ fn main() { ::std::process::exit(1); } }; - let calculated = budget::calculate(&account); + let maybe_calculated = budget::calculate(&account); if no_color && !force_color { colored::control::set_override(false); @@ -41,7 +41,7 @@ fn main() { colored::control::set_override(true); } - output(account, calculated); + output(account, maybe_calculated); } fn get_cli_matches() -> ArgMatches<'static> { @@ -68,7 +68,7 @@ fn get_cli_matches() -> ArgMatches<'static> { .get_matches() } -fn output(account: Account, calculated: Calculated) { +fn output(account: Account, maybe_calculated: Option<Calculated>) { println!( "{}", format!( @@ -78,22 +78,23 @@ fn output(account: Account, calculated: Calculated) { ).cyan(), ); - let last_day = match account.days.last() { - Some(day) => day, + let calculated = match maybe_calculated { + Some(data) => data, None => { - println!("{}", "Your expenses are empty...".italic()); + println!(); + println!("{}", "You have no expenses...".italic()); ::std::process::exit(0); } }; - let days_until_end = account.end_date - last_day.date; + let days_until_end = account.end_date - calculated.last_day; println!( "{}", format!( "Last day on entry: {}", - last_day.date.format("%Y-%m-%d"), + calculated.last_day.format("%Y-%m-%d"), ).cyan(), ); |