use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Indexes, StoredF32, StoredF64, Version};
use derive_more::{Deref, DerefMut};
use vecdb::{AnyStoredVec, Exit, ReadableCloneableVec, Rw, StorageMode};
use crate::internal::{Identity, LazyPerBlock, PerBlock, Windows};
use crate::{
distribution::{
metrics::ImportConfig,
state::{CohortState, CostBasisOps, RealizedOps},
},
prices,
};
use super::ActivityCore;
#[derive(Deref, DerefMut, Traversable)]
pub struct ActivityFull<M: StorageMode = Rw> {
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub inner: ActivityCore<M>,
pub coinyears_destroyed: LazyPerBlock<StoredF64, StoredF64>,
pub dormancy: Windows<PerBlock<StoredF32, M>>,
}
impl ActivityFull {
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
let v1 = Version::ONE;
let inner = ActivityCore::forced_import(cfg)?;
let coinyears_destroyed = LazyPerBlock::from_height_source::<Identity<StoredF64>>(
&cfg.name("coinyears_destroyed"),
cfg.version + v1,
inner
.coindays_destroyed
.sum
._1y
.height
.read_only_boxed_clone(),
cfg.indexes,
);
let dormancy = Windows::try_from_fn(|suffix| {
PerBlock::forced_import(
cfg.db,
&cfg.name(&format!("dormancy_{suffix}")),
cfg.version + v1,
cfg.indexes,
)
})?;
Ok(Self {
inner,
coinyears_destroyed,
dormancy,
})
}
pub(crate) fn full_min_len(&self) -> usize {
self.inner.min_len()
}
#[inline(always)]
pub(crate) fn full_push_state(
&mut self,
state: &CohortState<impl RealizedOps, impl CostBasisOps>,
) {
self.inner.push_state(state);
}
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
let mut vecs = self.inner.collect_vecs_mut();
for d in self.dormancy.as_mut_array() {
vecs.push(&mut d.height);
}
vecs
}
pub(crate) fn compute_from_stateful(
&mut self,
starting_indexes: &Indexes,
others: &[&ActivityCore],
exit: &Exit,
) -> Result<()> {
self.inner
.compute_from_stateful(starting_indexes, others, exit)
}
pub(crate) fn compute_rest_part1(
&mut self,
prices: &prices::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.inner
.compute_rest_part1(prices, starting_indexes, exit)?;
for ((dormancy, cdd_sum), tv_sum) in self
.dormancy
.as_mut_array()
.into_iter()
.zip(self.inner.coindays_destroyed.sum.as_array())
.zip(self.inner.minimal.transfer_volume.sum.0.as_array())
{
dormancy.height.compute_transform2(
starting_indexes.height,
&cdd_sum.height,
&tv_sum.btc.height,
|(i, rolling_cdd, rolling_btc, ..)| {
let btc = f64::from(rolling_btc);
if btc == 0.0 {
(i, StoredF32::from(0.0f32))
} else {
(i, StoredF32::from((f64::from(rolling_cdd) / btc) as f32))
}
},
exit,
)?;
}
Ok(())
}
}