From cf79a3180282f08a6165f4b88f52b78a14b9c688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustav=20S=C3=B6rn=C3=A4s?= Date: Thu, 29 Jul 2021 15:10:48 +0200 Subject: initial searching --- cli/src/main.rs | 17 ++++++++++++--- cli/src/search.rs | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ cli/src/store.rs | 6 +++++- 3 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 cli/src/search.rs diff --git a/cli/src/main.rs b/cli/src/main.rs index 5fd52c7..071e251 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -4,9 +4,14 @@ use std::path::PathBuf; use std::str::FromStr; use structopt::StructOpt; +mod search; mod store; mod transaction; +use search::{Constraint, Search}; +use store::Store; +use transaction::{Transaction, TransactionKind}; + //TODO relative ("yesterday", "-2d", etc) fn parse_date(s: &str) -> Result { NaiveDate::parse_from_str(s, "%Y-%m-%d").map_err(|e| e.to_string()) @@ -16,7 +21,7 @@ fn parse_date(s: &str) -> Result { #[derive(StructOpt)] enum Command { Insert { - kind: transaction::TransactionKind, + kind: TransactionKind, #[structopt(long)] account: String, @@ -62,7 +67,13 @@ struct Mn { } fn main() { - let mut store = store::Store::open(PathBuf::from("store")).unwrap(); + let mut store = Store::open(PathBuf::from("store")).unwrap(); + + let search = Search::new(store.transactions().iter().collect()); + println!("{:?}", search.get()); + let search = search.subtract(Constraint::Category("a".to_string())); + println!("{:?}", search.get()); + let args = Mn::from_args(); eprintln!("{:?}", args); match args.command { @@ -74,7 +85,7 @@ fn main() { description, date, } => { - let transaction = transaction::Transaction { + let transaction = Transaction { kind, to: account, from: "Default".to_string(), diff --git a/cli/src/search.rs b/cli/src/search.rs new file mode 100644 index 0000000..d388a8b --- /dev/null +++ b/cli/src/search.rs @@ -0,0 +1,62 @@ +use chrono::{naive::NaiveDate, Duration}; + +use crate::transaction::{Category, Transaction}; + +pub struct Search<'t> { + filtered: Vec, + transactions: Vec<&'t Transaction>, +} + +pub enum DateFilter { + Absolute { + start: Option, + end: Option, + }, + Relative { + start: Option, + end: Option, + } +} + +pub enum Constraint { + Category(Category), + Date(DateFilter), +} + +impl Constraint { + fn satisfies(&self, t: &Transaction) -> bool { + match self { + Constraint::Category(category) => category == &t.category, + Constraint::Date(_) => todo!(), + } + } +} + +impl<'t> Search<'t> { + pub fn new(transactions: Vec<&'t Transaction>) -> Self { + Self { + filtered: std::iter::successors(Some(0_usize), |n| Some(n.checked_add(1).unwrap())).take(transactions.len()).collect(), + transactions, + } + } + + pub fn get(&self) -> Vec<&'t Transaction> { + self + .filtered + .iter() + .map(|idx| self.transactions[*idx]) + .collect() + } + + pub fn subtract(self, constraint: Constraint) -> Self { + Self { + filtered: self + .filtered + .iter() + .copied() + .filter(|idx| !constraint.satisfies(self.transactions[*idx])) + .collect(), + transactions: self.transactions, + } + } +} diff --git a/cli/src/store.rs b/cli/src/store.rs index 2bba9c8..4e0e36b 100644 --- a/cli/src/store.rs +++ b/cli/src/store.rs @@ -49,9 +49,13 @@ impl Store { Ok(()) } + pub fn transactions(&self) -> &[Transaction] { + &self.transactions + } + pub fn categories(&self) -> Vec { let mut categories: Vec<_> = self - .transactions + .transactions() .iter() .map(|t| t.category.clone()) .collect(); -- cgit v1.2.1