tktax-histogram 0.2.2

A Rust crate that provides robust monthly histogram utilities for financial transactions, using specialized types from the TKTAX ecosystem.
Documentation
// ---------------- [ File: tktax-histogram/src/histogram_bin.rs ]
crate::ix!();

#[derive(Builder,Clone,Getters,Debug,PartialEq,Eq)]
#[getset(get="pub")]
#[builder(setter(into))]
pub struct HistogramMonthBinTxn {
    date:        NaiveDate,
    amount:      MonetaryAmount,
    description: String,
}

impl fmt::Display for HistogramMonthBinTxn {

    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f, 
            "{} {} {}", 
            self.date, 
            self.amount, 
            self.description
        )
    }
}

#[derive(Builder,Getters,Debug,PartialEq,Eq)]
#[getset(get="pub")]
#[builder(setter(into))]
pub struct HistogramMonthBin {
    price_range: Range<MonetaryAmount>,
    txns:        Vec<HistogramMonthBinTxn>,
}

impl HistogramMonthBin {

    pub fn len(&self) -> usize {
        self.txns.len()
    }

    pub fn price_lo(&self) -> MonetaryAmount {
        self.price_range.start
    }

    pub fn price_hi(&self) -> MonetaryAmount {
        self.price_range.end
    }

    pub fn ntx(&self) -> usize {
        self.txns.len()
    }

    pub fn fmt_bin_header(
        &self, 
        f: &mut fmt::Formatter<'_>) -> fmt::Result 
    {
        // Assuming price_lo() and price_hi() return types that implement Display
        // Convert them to String to be able to trim
        let price_lo_str = format!("{}", self.price_lo()).trim().to_string();
        let price_hi_str = format!("{}", self.price_hi()).trim().to_string();

        // Construct the range string
        let range_str = format!("[ {} to {} ]:", price_lo_str, price_hi_str);

        // Decide on the fixed width for the range part, e.g., 30 characters
        let fixed_width = 30;

        // Format the range string with fixed width, right-padding with spaces if needed
        let range_str_fixed_width = format!("{:width$}", range_str, width = fixed_width);

        // Now, include the fixed width range string and the number of transactions in your output
        writeln!(
            f,
            "{} {:3} transactions",
            range_str_fixed_width,
            self.ntx()
        );

        write!(f, "")
    }

    pub(crate) fn fmt_short(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

        self.fmt_bin_header(f)?;

        write!(f, "")
    }

    pub(crate) fn fmt_and_show_most_populous_bins(
        &self, 
        f: &mut fmt::Formatter<'_>, 
        threshold_item_count_in_bin: usize) -> fmt::Result 
    {
        self.fmt_bin_header(f)?;

        // Display transaction details for heavier bins
        if self.ntx() >= threshold_item_count_in_bin {

            for tx in &self.txns {

                if !self.price_range.contains(&tx.amount) {
                    panic!("bad price {} for range {:?}", tx.amount, self.price_range);
                }

                writeln!(f, "    {}", tx)?;
            }
        }

        write!(f, "")
    }

    pub fn fmt_and_show_heavy_transactions(
        &self, 
        f: &mut fmt::Formatter<'_>, 
        maybe_price_threshold: Option<MonetaryAmount>) -> fmt::Result 
    {
        self.fmt_bin_header(f)?;

        // Display transaction details for bins with a higher price range
        if maybe_price_threshold.is_none() || self.price_lo() >= maybe_price_threshold.unwrap() {

            for tx in &self.txns {

                if !self.price_range.contains(&tx.amount) {
                    panic!("bad price {} for range {:?}", tx.amount, self.price_range);
                }

                writeln!(f, "    {}", tx)?;
            }

            writeln!(f, " ")?;
        }

        write!(f, "")
    }
}