From 09f35f84ea74b6ed1a50210221173ee4f9436f7f Mon Sep 17 00:00:00 2001 From: traxys Date: Sat, 9 Dec 2023 18:05:38 +0100 Subject: [PATCH] Add a section for comparing remaining amounts --- src/compare.rs | 85 +++++++++++++++++++++++++++++++++++--------------- src/main.rs | 2 ++ 2 files changed, 62 insertions(+), 25 deletions(-) diff --git a/src/compare.rs b/src/compare.rs index 0715adb..8556ba9 100644 --- a/src/compare.rs +++ b/src/compare.rs @@ -1,4 +1,4 @@ -use std::{cmp::Ordering, collections::BTreeMap, iter}; +use std::{borrow::Cow, cmp::Ordering, collections::BTreeMap, iter}; use enum_map::{Enum, EnumMap}; use iced::{ @@ -20,6 +20,8 @@ pub(crate) struct Compare<'a, F> { pub left: Option<(CompareLoad, Box)>, pub right: Option<(CompareLoad, Box)>, pub archive: &'a BTreeMap, + pub person_1: &'a str, + pub person_2: &'a str, pub on_load: F, } @@ -40,6 +42,7 @@ pub(crate) enum Section { Recurring, Variable, Accounts, + Remaining, } impl Section { @@ -48,6 +51,7 @@ impl Section { Section::Recurring => "Recurring", Section::Variable => "Variable", Section::Accounts => "Accounts", + Section::Remaining => "Remaining", } } } @@ -167,12 +171,15 @@ where let left = self.left.as_ref().map(|(_, r)| &**r); let right = self.right.as_ref().map(|(_, r)| &**r); - fn compare_row<'b, M>( + fn compare_row<'b, S, M>( size: u16, always: Option<&str>, - left: Option<(&str, f64)>, - right: Option<(&str, f64)>, - ) -> Vec<[iced::Element<'b, M>; 4]> { + left: Option<(&S, f64)>, + right: Option<(&S, f64)>, + ) -> Vec<[iced::Element<'b, M>; 4]> + where + S: AsRef + ?Sized, + { let float_text = |f: f64| Some(text(format!("{f:.2}")).size(size)); match (left, right) { @@ -183,24 +190,34 @@ where (None, Some((k, v))) => { vec![text_row( size, - [Some(text(k).size(size)), None, None, float_text(v)], + [Some(text(k.as_ref()).size(size)), None, None, float_text(v)], )] } (Some((k, v)), None) => { vec![text_row( size, - [Some(text(k).size(size)), float_text(v), None, None], + [Some(text(k.as_ref()).size(size)), float_text(v), None, None], )] } - (Some((lk, lv)), Some((rk, rv))) if lk != rk => { + (Some((lk, lv)), Some((rk, rv))) if lk.as_ref() != rk.as_ref() => { vec![ text_row( size, - [Some(text(lk).size(size)), float_text(lv), None, None], + [ + Some(text(lk.as_ref()).size(size)), + float_text(lv), + None, + None, + ], ), text_row( size, - [Some(text(rk).size(size)), None, None, float_text(rv)], + [ + Some(text(rk.as_ref()).size(size)), + None, + None, + float_text(rv), + ], ), ] } @@ -209,7 +226,7 @@ where vec![text_row( size, [ - Some(text(k).size(size)), + Some(text(k.as_ref()).size(size)), float_text(lv), None, float_text(rv), @@ -226,7 +243,7 @@ where vec![text_row( size, [ - Some(text(k).size(size)), + Some(text(k.as_ref()).size(size)), float_text(lv), Some(text(format!("{sign}{}%", difference.abs())).size(size)), float_text(rv), @@ -237,20 +254,21 @@ where } } - fn item_compare<'a, I, M>( + fn item_compare<'a, 's, I, S, M>( collapse: bool, left: Option, right: Option, ) -> Vec<[iced::Element<'a, M>; 4]> where - I: IntoIterator, + I: IntoIterator, + S: Into>, { if collapse { return Vec::new(); } - let to_btree = |i: I| i.into_iter().collect::>(); - + let entry_ref = |(s, v): (S, f64)| (s.into(), v); + let to_btree = |i: I| i.into_iter().map(entry_ref).collect::>(); let float_text = |f: f64| Some(text(format!("{f:.2}")).size(TEXT_NORMAL)); let (left, right) = match (left, right) { @@ -259,7 +277,8 @@ where (Some(u), None) => { return u .into_iter() - .sorted_by_key(|(k, _)| *k) + .map(entry_ref) + .sorted_by(|(ka, _), (kb, _)| ka.cmp(kb)) .map(|(k, v)| { text_row( TEXT_NORMAL, @@ -271,7 +290,8 @@ where (None, Some(u)) => { return u .into_iter() - .sorted_by_key(|(k, _)| *k) + .map(entry_ref) + .sorted_by(|(ka, _), (kb, _)| ka.cmp(kb)) .map(|(k, v)| { text_row( TEXT_NORMAL, @@ -290,16 +310,16 @@ where Right, } - type Peek<'a> = Option<&'a (&'a &'a str, &'a f64)>; + type Peek<'a> = Option<&'a (&'a Cow<'a, str>, &'a f64)>; let needs_to_wait = |l: Peek, r: Peek| match (l, r) { (_, None) | (None, _) => None, - (Some((&l, _)), Some((&r, _))) => match l.cmp(r) { - Ordering::Less => match left.contains_key(r) { + (Some((l, _)), Some((r, _))) => match l.cmp(r) { + Ordering::Less => match left.contains_key(*r) { false => None, true => Some(Side::Left), }, Ordering::Equal => None, - Ordering::Greater => match right.contains_key(l) { + Ordering::Greater => match right.contains_key(*l) { false => None, true => Some(Side::Right), }, @@ -308,15 +328,15 @@ where let mut compare = Vec::new(); - type Item<'a> = Option<(&'a &'a str, &'a f64)>; + type Item<'a> = Option<(&'a Cow<'a, str>, &'a f64)>; let mut insert_row = |l: Item, r: Item| { let mut inserted = false; compare.extend( compare_row( TEXT_NORMAL, None, - l.map(|(a, b)| (*a, *b)), - r.map(|(a, b)| (*a, *b)), + l.map(|(a, b)| (a, *b)), + r.map(|(a, b)| (a, *b)), ) .into_iter() .inspect(|_| { @@ -379,6 +399,21 @@ where std::iter::once(("Main", main_account)).chain(s.savings()) }), + mk_section!(Section::Remaining, move |s| { + let contrib = s.contributions(self.archive); + + let remaining_1 = format!("Equal {}", self.person_1); + let remaining_2 = format!("Equal {}", self.person_2); + + [ + ( + Cow::Borrowed("Same"), + contrib.same_remaining.remaining.person_1, + ), + (remaining_1.into(), contrib.proportional.remaining.person_1), + (remaining_2.into(), contrib.proportional.remaining.person_2), + ] + }), ], )) .into() diff --git a/src/main.rs b/src/main.rs index 222a0ef..3839d88 100644 --- a/src/main.rs +++ b/src/main.rs @@ -521,6 +521,8 @@ impl Application for Glaurung { right: self.compare_load(self.compare_right), archive: &self.archive, on_load: Message::CompareLoad, + person_1: &self.config.person_1, + person_2: &self.config.person_2, }), };