use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Cents, Height, Sats, Version};
use derive_more::{Deref, DerefMut};
use vecdb::{Database, Exit, ReadableVec, Rw, StorageMode};
use crate::{
indexes,
internal::{
AmountPerBlock, DistributionStats, WindowStarts, Windows,
algo::compute_rolling_distribution_from_starts,
},
};
#[derive(Deref, DerefMut, Traversable)]
#[traversable(transparent)]
pub struct RollingDistributionAmountPerBlock<M: StorageMode = Rw>(
pub DistributionStats<Windows<AmountPerBlock<M>>>,
);
impl RollingDistributionAmountPerBlock {
pub(crate) fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
Ok(Self(DistributionStats::try_from_fn(|stat_suffix| {
Windows::try_from_fn(|window_suffix| {
AmountPerBlock::forced_import(
db,
&format!("{name}_{stat_suffix}_{window_suffix}"),
version,
indexes,
)
})
})?))
}
pub(crate) fn compute(
&mut self,
max_from: Height,
windows: &WindowStarts<'_>,
sats_source: &impl ReadableVec<Height, Sats>,
cents_source: &impl ReadableVec<Height, Cents>,
exit: &Exit,
) -> Result<()> {
let mut sats_cache = None;
let mut cents_cache = None;
macro_rules! compute_window {
($w:ident, $starts:expr) => {{
macro_rules! compute_unit {
($unit:ident, $source:expr, $cache:expr) => {
compute_rolling_distribution_from_starts(
max_from,
$starts,
$source,
&mut self.0.min.$w.$unit.height,
&mut self.0.max.$w.$unit.height,
&mut self.0.pct10.$w.$unit.height,
&mut self.0.pct25.$w.$unit.height,
&mut self.0.median.$w.$unit.height,
&mut self.0.pct75.$w.$unit.height,
&mut self.0.pct90.$w.$unit.height,
exit,
$cache,
)?
};
}
compute_unit!(sats, sats_source, &mut sats_cache);
compute_unit!(cents, cents_source, &mut cents_cache);
}};
}
compute_window!(_1y, windows._1y);
compute_window!(_1m, windows._1m);
compute_window!(_1w, windows._1w);
compute_window!(_24h, windows._24h);
Ok(())
}
}