mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-25 23:29:58 -07:00
computer: renames
This commit is contained in:
64
crates/brk_computer/src/internal/multi/date/average.rs
Normal file
64
crates/brk_computer/src/internal/multi/date/average.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
//! ComputedDateAverage - dateindex storage + lazy periods for average-value aggregation.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
|
||||
|
||||
use crate::{ComputeIndexes, indexes};
|
||||
|
||||
use crate::internal::{ComputedVecValue, LazyPeriodsAverage};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ComputedDateAverage<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub dateindex: EagerVec<PcoVec<DateIndex, T>>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub rest: LazyPeriodsAverage<T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedDateAverage<T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let dateindex = EagerVec::forced_import(db, name, version + VERSION)?;
|
||||
|
||||
Ok(Self {
|
||||
rest: LazyPeriodsAverage::from_source(
|
||||
name,
|
||||
version + VERSION,
|
||||
dateindex.boxed_clone(),
|
||||
indexes,
|
||||
),
|
||||
dateindex,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
_starting_indexes: &ComputeIndexes,
|
||||
_exit: &Exit,
|
||||
mut compute: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut EagerVec<PcoVec<DateIndex, T>>) -> Result<()>,
|
||||
{
|
||||
compute(&mut self.dateindex)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
628
crates/brk_computer/src/internal/multi/date/binary_last.rs
Normal file
628
crates/brk_computer/src/internal/multi/date/binary_last.rs
Normal file
@@ -0,0 +1,628 @@
|
||||
//! Binary transform composite from DateIndex - Last aggregation only.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{BinaryTransform, IterableBoxedVec, IterableCloneableVec, LazyVecFrom2};
|
||||
|
||||
use crate::internal::{
|
||||
ComputedBlockLast, ComputedBlockSum, ComputedDateLast, ComputedVecValue, LazyBinaryTransformLast,
|
||||
LazyPeriodsLast, LazyPeriodsSumCum, NumericValue,
|
||||
};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyBinaryDateLast<T, S1T, S2T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
S2T: ComputedVecValue,
|
||||
{
|
||||
pub dateindex: LazyVecFrom2<DateIndex, T, DateIndex, S1T, DateIndex, S2T>,
|
||||
pub weekindex: LazyBinaryTransformLast<WeekIndex, T, S1T, S2T>,
|
||||
pub monthindex: LazyBinaryTransformLast<MonthIndex, T, S1T, S2T>,
|
||||
pub quarterindex: LazyBinaryTransformLast<QuarterIndex, T, S1T, S2T>,
|
||||
pub semesterindex: LazyBinaryTransformLast<SemesterIndex, T, S1T, S2T>,
|
||||
pub yearindex: LazyBinaryTransformLast<YearIndex, T, S1T, S2T>,
|
||||
pub decadeindex: LazyBinaryTransformLast<DecadeIndex, T, S1T, S2T>,
|
||||
}
|
||||
|
||||
impl<T, S1T, S2T> LazyBinaryDateLast<T, S1T, S2T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
S2T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn from_computed_both_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedDateLast<S1T>,
|
||||
source2: &ComputedDateLast<S2T>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformLast::from_lazy_last::<F, _, _, _, _>(
|
||||
name,
|
||||
v,
|
||||
&source1.$p,
|
||||
&source2.$p,
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.dateindex.boxed_clone(),
|
||||
source2.dateindex.boxed_clone(),
|
||||
),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_derived_last_and_computed_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex_source1: IterableBoxedVec<DateIndex, S1T>,
|
||||
source1: &LazyPeriodsLast<S1T>,
|
||||
source2: &ComputedDateLast<S2T>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformLast::from_lazy_last::<F, _, _, _, _>(
|
||||
name,
|
||||
v,
|
||||
&source1.$p,
|
||||
&source2.$p,
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
dateindex_source1,
|
||||
source2.dateindex.boxed_clone(),
|
||||
),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_derived_last_and_block_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex_source1: IterableBoxedVec<DateIndex, S1T>,
|
||||
source1: &LazyPeriodsLast<S1T>,
|
||||
source2: &ComputedBlockLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformLast::from_lazy_last::<F, _, _, _, _>(
|
||||
name,
|
||||
v,
|
||||
&source1.$p,
|
||||
&source2.$p,
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
dateindex_source1,
|
||||
source2.dateindex.0.boxed_clone(),
|
||||
),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_both_derived_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex_source1: IterableBoxedVec<DateIndex, S1T>,
|
||||
source1: &LazyPeriodsLast<S1T>,
|
||||
dateindex_source2: IterableBoxedVec<DateIndex, S2T>,
|
||||
source2: &LazyPeriodsLast<S2T>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformLast::from_lazy_last::<F, _, _, _, _>(
|
||||
name,
|
||||
v,
|
||||
&source1.$p,
|
||||
&source2.$p,
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
dateindex_source1,
|
||||
dateindex_source2,
|
||||
),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_height_and_dateindex_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedBlockLast<S1T>,
|
||||
source2: &ComputedDateLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformLast::from_lazy_last::<F, _, _, _, _>(
|
||||
name,
|
||||
v,
|
||||
&source1.$p,
|
||||
&source2.$p,
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.dateindex.0.boxed_clone(),
|
||||
source2.dateindex.boxed_clone(),
|
||||
),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_dateindex_and_height_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedDateLast<S1T>,
|
||||
source2: &ComputedBlockLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformLast::from_lazy_last::<F, _, _, _, _>(
|
||||
name,
|
||||
v,
|
||||
&source1.$p,
|
||||
&source2.$p,
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.dateindex.boxed_clone(),
|
||||
source2.dateindex.0.boxed_clone(),
|
||||
),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_both_block_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedBlockLast<S1T>,
|
||||
source2: &ComputedBlockLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformLast::from_lazy_last::<F, _, _, _, _>(
|
||||
name,
|
||||
v,
|
||||
&source1.$p,
|
||||
&source2.$p,
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.dateindex.0.boxed_clone(),
|
||||
source2.dateindex.0.boxed_clone(),
|
||||
),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_dateindex_last_and_height_sum<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedDateLast<S1T>,
|
||||
source2: &ComputedBlockSum<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformLast::from_vecs::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.$p.boxed_clone(),
|
||||
source2.$p.boxed_clone(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.dateindex.boxed_clone(),
|
||||
source2.dateindex.0.boxed_clone(),
|
||||
),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_block_last_and_height_sum<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedBlockLast<S1T>,
|
||||
source2: &ComputedBlockSum<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformLast::from_vecs::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.$p.boxed_clone(),
|
||||
source2.$p.boxed_clone(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.dateindex.0.boxed_clone(),
|
||||
source2.dateindex.0.boxed_clone(),
|
||||
),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_both_sum_cum_cumulatives<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex_source1: IterableBoxedVec<DateIndex, S1T>,
|
||||
dates1: &LazyPeriodsSumCum<S1T>,
|
||||
dateindex_source2: IterableBoxedVec<DateIndex, S2T>,
|
||||
dates2: &LazyPeriodsSumCum<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: PartialOrd,
|
||||
S2T: PartialOrd,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformLast::from_vecs::<F>(
|
||||
name,
|
||||
v,
|
||||
dates1.$p.cumulative.boxed_clone(),
|
||||
dates2.$p.cumulative.boxed_clone(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
dateindex_source1,
|
||||
dateindex_source2,
|
||||
),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create from a LazyPeriodsLast source and a BinaryDateLast source.
|
||||
pub fn from_derived_last_and_binary_last<F, S2aT, S2bT>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex_source1: IterableBoxedVec<DateIndex, S1T>,
|
||||
source1: &LazyPeriodsLast<S1T>,
|
||||
source2: &LazyBinaryDateLast<S2T, S2aT, S2bT>,
|
||||
) -> Self
|
||||
where
|
||||
F: BinaryTransform<S1T, S2T, T>,
|
||||
S2aT: ComputedVecValue + JsonSchema,
|
||||
S2bT: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformLast::from_vecs::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.$p.boxed_clone(),
|
||||
source2.$p.boxed_clone(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
dateindex_source1,
|
||||
source2.dateindex.boxed_clone(),
|
||||
),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create from a BinaryDateLast source and a ComputedDateLast source.
|
||||
pub fn from_binary_and_computed_last<F, S1aT, S1bT>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &LazyBinaryDateLast<S1T, S1aT, S1bT>,
|
||||
source2: &ComputedDateLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
F: BinaryTransform<S1T, S2T, T>,
|
||||
S1aT: ComputedVecValue + JsonSchema,
|
||||
S1bT: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformLast::from_vecs::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.$p.boxed_clone(),
|
||||
source2.$p.boxed_clone(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.dateindex.boxed_clone(),
|
||||
source2.dateindex.boxed_clone(),
|
||||
),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create from a BinaryDateLast source and a ComputedBlockLast source.
|
||||
pub fn from_binary_and_block_last<F, S1aT, S1bT>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &LazyBinaryDateLast<S1T, S1aT, S1bT>,
|
||||
source2: &ComputedBlockLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
F: BinaryTransform<S1T, S2T, T>,
|
||||
S1aT: ComputedVecValue + JsonSchema,
|
||||
S1bT: ComputedVecValue + JsonSchema,
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformLast::from_vecs::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.$p.boxed_clone(),
|
||||
source2.$p.boxed_clone(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.dateindex.boxed_clone(),
|
||||
source2.dateindex.0.boxed_clone(),
|
||||
),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create from a ComputedDateLast source and a BinaryDateLast source.
|
||||
pub fn from_computed_and_binary_last<F, S2aT, S2bT>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedDateLast<S1T>,
|
||||
source2: &LazyBinaryDateLast<S2T, S2aT, S2bT>,
|
||||
) -> Self
|
||||
where
|
||||
F: BinaryTransform<S1T, S2T, T>,
|
||||
S2aT: ComputedVecValue + JsonSchema,
|
||||
S2bT: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformLast::from_vecs::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.$p.boxed_clone(),
|
||||
source2.$p.boxed_clone(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.dateindex.boxed_clone(),
|
||||
source2.dateindex.boxed_clone(),
|
||||
),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create from two BinaryDateLast sources.
|
||||
pub fn from_both_binary_last<F, S1aT, S1bT, S2aT, S2bT>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &LazyBinaryDateLast<S1T, S1aT, S1bT>,
|
||||
source2: &LazyBinaryDateLast<S2T, S2aT, S2bT>,
|
||||
) -> Self
|
||||
where
|
||||
F: BinaryTransform<S1T, S2T, T>,
|
||||
S1aT: ComputedVecValue + JsonSchema,
|
||||
S1bT: ComputedVecValue + JsonSchema,
|
||||
S2aT: ComputedVecValue + JsonSchema,
|
||||
S2bT: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformLast::from_vecs::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.$p.boxed_clone(),
|
||||
source2.$p.boxed_clone(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.dateindex.boxed_clone(),
|
||||
source2.dateindex.boxed_clone(),
|
||||
),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
}
|
||||
61
crates/brk_computer/src/internal/multi/date/binary_sum.rs
Normal file
61
crates/brk_computer/src/internal/multi/date/binary_sum.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
//! Binary transform for Sum-only pattern across date periods.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{BinaryTransform, IterableCloneableVec};
|
||||
|
||||
use crate::internal::{ComputedVecValue, ComputedDerivedBlockSum, LazyBinaryTransformSum, NumericValue};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyBinaryDateSum<T, S1T, S2T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
S2T: ComputedVecValue,
|
||||
{
|
||||
pub dateindex: LazyBinaryTransformSum<DateIndex, T, S1T, S2T>,
|
||||
pub weekindex: LazyBinaryTransformSum<WeekIndex, T, S1T, S2T>,
|
||||
pub monthindex: LazyBinaryTransformSum<MonthIndex, T, S1T, S2T>,
|
||||
pub quarterindex: LazyBinaryTransformSum<QuarterIndex, T, S1T, S2T>,
|
||||
pub semesterindex: LazyBinaryTransformSum<SemesterIndex, T, S1T, S2T>,
|
||||
pub yearindex: LazyBinaryTransformSum<YearIndex, T, S1T, S2T>,
|
||||
pub decadeindex: LazyBinaryTransformSum<DecadeIndex, T, S1T, S2T>,
|
||||
}
|
||||
|
||||
impl<T, S1T, S2T> LazyBinaryDateSum<T, S1T, S2T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: NumericValue + JsonSchema,
|
||||
S2T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub fn from_derived<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedDerivedBlockSum<S1T>,
|
||||
source2: &ComputedDerivedBlockSum<S2T>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformSum::from_boxed::<F>(name, v, source1.$p.boxed_clone(), source2.$p.boxed_clone())
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyBinaryTransformSum::from_sum::<F>(name, v, &source1.dateindex, &source2.dateindex),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
}
|
||||
281
crates/brk_computer/src/internal/multi/date/binary_sum_cum.rs
Normal file
281
crates/brk_computer/src/internal/multi/date/binary_sum_cum.rs
Normal file
@@ -0,0 +1,281 @@
|
||||
//! Binary transform for SumCum pattern across date periods.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{BinaryTransform, IterableCloneableVec};
|
||||
|
||||
use crate::internal::{
|
||||
ComputedBlockLast, ComputedBlockSumCum, ComputedDerivedBlockLast,
|
||||
ComputedDerivedBlockSumCum, ComputedVecValue, LazyBinaryTransformSumCum, LazyPeriodsFull,
|
||||
LazyPeriodsSumCum, NumericValue, SumCum,
|
||||
};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyBinaryDateSumCum<T, S1T = T, S2T = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
S2T: ComputedVecValue,
|
||||
{
|
||||
pub dateindex: LazyBinaryTransformSumCum<DateIndex, T, S1T, S2T>,
|
||||
pub weekindex: LazyBinaryTransformSumCum<WeekIndex, T, S1T, S2T>,
|
||||
pub monthindex: LazyBinaryTransformSumCum<MonthIndex, T, S1T, S2T>,
|
||||
pub quarterindex: LazyBinaryTransformSumCum<QuarterIndex, T, S1T, S2T>,
|
||||
pub semesterindex: LazyBinaryTransformSumCum<SemesterIndex, T, S1T, S2T>,
|
||||
pub yearindex: LazyBinaryTransformSumCum<YearIndex, T, S1T, S2T>,
|
||||
pub decadeindex: LazyBinaryTransformSumCum<DecadeIndex, T, S1T, S2T>,
|
||||
}
|
||||
|
||||
impl<T, S1T, S2T> LazyBinaryDateSumCum<T, S1T, S2T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
S2T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn from_computed<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex1: &SumCum<DateIndex, S1T>,
|
||||
periods1: &LazyPeriodsSumCum<S1T>,
|
||||
dateindex2: &SumCum<DateIndex, S2T>,
|
||||
periods2: &LazyPeriodsSumCum<S2T>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformSumCum::from_sources::<F>(
|
||||
name, v,
|
||||
periods1.$p.sum.boxed_clone(), periods2.$p.sum.boxed_clone(),
|
||||
periods1.$p.cumulative.boxed_clone(), periods2.$p.cumulative.boxed_clone(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyBinaryTransformSumCum::from_sum_cum::<F>(name, v, dateindex1, dateindex2),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_derived_full<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex1: &SumCum<DateIndex, S1T>,
|
||||
dates1: &LazyPeriodsFull<S1T>,
|
||||
dateindex2: &SumCum<DateIndex, S2T>,
|
||||
dates2: &LazyPeriodsFull<S2T>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformSumCum::from_lazy_stats_aggregate::<F, _, _, _, _>(
|
||||
name, v, &dates1.$p, &dates2.$p,
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyBinaryTransformSumCum::from_sum_cum::<F>(name, v, dateindex1, dateindex2),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
|
||||
// --- Raw variants (no _sum suffix) for pure SumCum types ---
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn from_computed_sum_raw<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex1: &SumCum<DateIndex, S1T>,
|
||||
periods1: &LazyPeriodsSumCum<S1T>,
|
||||
dateindex2: &SumCum<DateIndex, S2T>,
|
||||
periods2: &LazyPeriodsSumCum<S2T>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformSumCum::from_sources_sum_raw::<F>(
|
||||
name, v,
|
||||
periods1.$p.sum.boxed_clone(), periods2.$p.sum.boxed_clone(),
|
||||
periods1.$p.cumulative.boxed_clone(), periods2.$p.cumulative.boxed_clone(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyBinaryTransformSumCum::from_sum_cum_sum_raw::<F>(name, v, dateindex1, dateindex2),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
|
||||
// --- Methods accepting SumCum + Last sources ---
|
||||
|
||||
pub fn from_computed_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedBlockSumCum<S1T>,
|
||||
source2: &ComputedBlockLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: PartialOrd,
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformSumCum::from_sources_last_sum_raw::<F>(
|
||||
name, v,
|
||||
source1.rest.$p.sum.boxed_clone(),
|
||||
source1.rest.$p.cumulative.boxed_clone(),
|
||||
source2.rest.$p.boxed_clone(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyBinaryTransformSumCum::from_sum_cum_last_sum_raw::<F>(
|
||||
name, v, &source1.dateindex, &source2.dateindex,
|
||||
),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_derived_computed_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedDerivedBlockSumCum<S1T>,
|
||||
source2: &ComputedBlockLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformSumCum::from_sources_last_sum_raw::<F>(
|
||||
name, v,
|
||||
source1.$p.sum.boxed_clone(),
|
||||
source1.$p.cumulative.boxed_clone(),
|
||||
source2.rest.$p.boxed_clone(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyBinaryTransformSumCum::from_sum_cum_last_sum_raw::<F>(
|
||||
name, v, &source1.dateindex, &source2.dateindex,
|
||||
),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_computed_derived_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedBlockSumCum<S1T>,
|
||||
source2: &ComputedDerivedBlockLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: PartialOrd,
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformSumCum::from_sources_last_sum_raw::<F>(
|
||||
name, v,
|
||||
source1.rest.$p.sum.boxed_clone(),
|
||||
source1.rest.$p.cumulative.boxed_clone(),
|
||||
source2.$p.boxed_clone(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyBinaryTransformSumCum::from_sum_cum_last_sum_raw::<F>(
|
||||
name, v, &source1.dateindex, &source2.dateindex,
|
||||
),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_derived_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedDerivedBlockSumCum<S1T>,
|
||||
source2: &ComputedDerivedBlockLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyBinaryTransformSumCum::from_sources_last_sum_raw::<F>(
|
||||
name, v,
|
||||
source1.$p.sum.boxed_clone(),
|
||||
source1.$p.cumulative.boxed_clone(),
|
||||
source2.$p.boxed_clone(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyBinaryTransformSumCum::from_sum_cum_last_sum_raw::<F>(
|
||||
name, v, &source1.dateindex, &source2.dateindex,
|
||||
),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
}
|
||||
64
crates/brk_computer/src/internal/multi/date/first.rs
Normal file
64
crates/brk_computer/src/internal/multi/date/first.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
//! ComputedVecsDate using only first-value aggregation.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
|
||||
|
||||
use crate::{ComputeIndexes, indexes};
|
||||
|
||||
use crate::internal::{ComputedVecValue, LazyPeriodsFirst};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ComputedDateFirst<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub dateindex: EagerVec<PcoVec<DateIndex, T>>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub rest: LazyPeriodsFirst<T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedDateFirst<T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let dateindex = EagerVec::forced_import(db, name, version + VERSION)?;
|
||||
|
||||
Ok(Self {
|
||||
rest: LazyPeriodsFirst::from_source(
|
||||
name,
|
||||
version + VERSION,
|
||||
dateindex.boxed_clone(),
|
||||
indexes,
|
||||
),
|
||||
dateindex,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
_starting_indexes: &ComputeIndexes,
|
||||
_exit: &Exit,
|
||||
mut compute: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut EagerVec<PcoVec<DateIndex, T>>) -> Result<()>,
|
||||
{
|
||||
compute(&mut self.dateindex)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
73
crates/brk_computer/src/internal/multi/date/last.rs
Normal file
73
crates/brk_computer/src/internal/multi/date/last.rs
Normal file
@@ -0,0 +1,73 @@
|
||||
//! ComputedVecsDate using only last-value aggregation.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, IterableVec, PcoVec};
|
||||
|
||||
use crate::{ComputeIndexes, indexes};
|
||||
|
||||
use crate::internal::{ComputedVecValue, LazyPeriodsLast};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ComputedDateLast<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub dateindex: EagerVec<PcoVec<DateIndex, T>>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub rest: LazyPeriodsLast<T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedDateLast<T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let dateindex = EagerVec::forced_import(db, name, version + VERSION)?;
|
||||
|
||||
Ok(Self {
|
||||
rest: LazyPeriodsLast::from_source(
|
||||
name,
|
||||
version + VERSION,
|
||||
dateindex.boxed_clone(),
|
||||
indexes,
|
||||
),
|
||||
dateindex,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
_starting_indexes: &ComputeIndexes,
|
||||
_exit: &Exit,
|
||||
mut compute: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut EagerVec<PcoVec<DateIndex, T>>) -> Result<()>,
|
||||
{
|
||||
compute(&mut self.dateindex)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
_starting_indexes: &ComputeIndexes,
|
||||
_exit: &Exit,
|
||||
_dateindex: Option<&impl IterableVec<DateIndex, T>>,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
62
crates/brk_computer/src/internal/multi/date/lazy_full.rs
Normal file
62
crates/brk_computer/src/internal/multi/date/lazy_full.rs
Normal file
@@ -0,0 +1,62 @@
|
||||
//! Lazy transform for Full date sources.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableCloneableVec, UnaryTransform};
|
||||
|
||||
use crate::internal::{ComputedVecValue, Full, LazyPeriodsFull, LazyTransformFull, LazyTransformStats};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyDateFull<T, S1T = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
{
|
||||
pub dateindex: LazyTransformFull<DateIndex, T, S1T>,
|
||||
pub weekindex: LazyTransformStats<WeekIndex, T, S1T>,
|
||||
pub monthindex: LazyTransformStats<MonthIndex, T, S1T>,
|
||||
pub quarterindex: LazyTransformStats<QuarterIndex, T, S1T>,
|
||||
pub semesterindex: LazyTransformStats<SemesterIndex, T, S1T>,
|
||||
pub yearindex: LazyTransformStats<YearIndex, T, S1T>,
|
||||
pub decadeindex: LazyTransformStats<DecadeIndex, T, S1T>,
|
||||
}
|
||||
|
||||
impl<T, S1T> LazyDateFull<T, S1T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn from_full<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex: &Full<DateIndex, S1T>,
|
||||
source: &LazyPeriodsFull<S1T>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyTransformStats::from_boxed::<F>(
|
||||
name, v,
|
||||
source.$p.average.boxed_clone(), source.$p.min.boxed_clone(),
|
||||
source.$p.max.boxed_clone(), source.$p.sum.boxed_clone(),
|
||||
source.$p.cumulative.boxed_clone(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyTransformFull::from_stats_aggregate::<F>(name, v, dateindex),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
}
|
||||
87
crates/brk_computer/src/internal/multi/date/lazy_last.rs
Normal file
87
crates/brk_computer/src/internal/multi/date/lazy_last.rs
Normal file
@@ -0,0 +1,87 @@
|
||||
//! Lazy transform for Last-only date sources.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableBoxedVec, IterableCloneableVec, UnaryTransform};
|
||||
|
||||
use crate::internal::{ComputedBlockLast, ComputedDateLast, ComputedVecValue, LazyPeriodsLast, LazyTransformLast, NumericValue};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyDateLast<T, S1T = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
{
|
||||
pub dateindex: LazyTransformLast<DateIndex, T, S1T>,
|
||||
pub weekindex: LazyTransformLast<WeekIndex, T, S1T>,
|
||||
pub monthindex: LazyTransformLast<MonthIndex, T, S1T>,
|
||||
pub quarterindex: LazyTransformLast<QuarterIndex, T, S1T>,
|
||||
pub semesterindex: LazyTransformLast<SemesterIndex, T, S1T>,
|
||||
pub yearindex: LazyTransformLast<YearIndex, T, S1T>,
|
||||
pub decadeindex: LazyTransformLast<DecadeIndex, T, S1T>,
|
||||
}
|
||||
|
||||
impl<T, S1T> LazyDateLast<T, S1T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn from_source<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source: &ComputedDateLast<S1T>,
|
||||
) -> Self {
|
||||
Self::from_computed::<F>(name, version, source.dateindex.boxed_clone(), source)
|
||||
}
|
||||
|
||||
pub fn from_computed<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex_source: IterableBoxedVec<DateIndex, S1T>,
|
||||
source: &ComputedDateLast<S1T>,
|
||||
) -> Self {
|
||||
Self::from_derived::<F>(name, version, dateindex_source, &source.rest)
|
||||
}
|
||||
|
||||
pub fn from_derived<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex_source: IterableBoxedVec<DateIndex, S1T>,
|
||||
source: &LazyPeriodsLast<S1T>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyTransformLast::from_lazy_last::<F, _, _>(name, v, &source.$p)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyTransformLast::from_boxed::<F>(name, v, dateindex_source),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_block_source<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source: &ComputedBlockLast<S1T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
{
|
||||
Self::from_derived::<F>(name, version, source.dateindex.0.boxed_clone(), &source.dates)
|
||||
}
|
||||
}
|
||||
57
crates/brk_computer/src/internal/multi/date/lazy_sum.rs
Normal file
57
crates/brk_computer/src/internal/multi/date/lazy_sum.rs
Normal file
@@ -0,0 +1,57 @@
|
||||
//! Lazy transform for Sum-only date sources.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableBoxedVec, IterableCloneableVec, UnaryTransform};
|
||||
|
||||
use crate::internal::{ComputedVecValue, LazyPeriodsSum, LazyTransformSum};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyDateSum<T, S1T = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
{
|
||||
pub dateindex: LazyTransformSum<DateIndex, T, S1T>,
|
||||
pub weekindex: LazyTransformSum<WeekIndex, T, S1T>,
|
||||
pub monthindex: LazyTransformSum<MonthIndex, T, S1T>,
|
||||
pub quarterindex: LazyTransformSum<QuarterIndex, T, S1T>,
|
||||
pub semesterindex: LazyTransformSum<SemesterIndex, T, S1T>,
|
||||
pub yearindex: LazyTransformSum<YearIndex, T, S1T>,
|
||||
pub decadeindex: LazyTransformSum<DecadeIndex, T, S1T>,
|
||||
}
|
||||
|
||||
impl<T, S1T> LazyDateSum<T, S1T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn from_derived<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex_source: IterableBoxedVec<DateIndex, S1T>,
|
||||
source: &LazyPeriodsSum<S1T>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyTransformSum::from_boxed::<F>(name, v, source.$p.boxed_clone())
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyTransformSum::from_boxed::<F>(name, v, dateindex_source),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
}
|
||||
59
crates/brk_computer/src/internal/multi/date/lazy_sum_cum.rs
Normal file
59
crates/brk_computer/src/internal/multi/date/lazy_sum_cum.rs
Normal file
@@ -0,0 +1,59 @@
|
||||
//! Lazy transform for SumCum date sources.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableCloneableVec, UnaryTransform};
|
||||
|
||||
use crate::internal::{ComputedVecValue, LazyPeriodsSumCum, LazyTransformSumCum, SumCum};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyDateSumCum<T, S1T = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
{
|
||||
pub dateindex: LazyTransformSumCum<DateIndex, T, S1T>,
|
||||
pub weekindex: LazyTransformSumCum<WeekIndex, T, S1T>,
|
||||
pub monthindex: LazyTransformSumCum<MonthIndex, T, S1T>,
|
||||
pub quarterindex: LazyTransformSumCum<QuarterIndex, T, S1T>,
|
||||
pub semesterindex: LazyTransformSumCum<SemesterIndex, T, S1T>,
|
||||
pub yearindex: LazyTransformSumCum<YearIndex, T, S1T>,
|
||||
pub decadeindex: LazyTransformSumCum<DecadeIndex, T, S1T>,
|
||||
}
|
||||
|
||||
impl<T, S1T> LazyDateSumCum<T, S1T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn from_sum_cum<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex: &SumCum<DateIndex, S1T>,
|
||||
source: &LazyPeriodsSumCum<S1T>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyTransformSumCum::from_boxed_sum_raw::<F>(
|
||||
name, v, source.$p.sum.boxed_clone(), source.$p.cumulative.boxed_clone(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
dateindex: LazyTransformSumCum::from_sum_cum_sum_raw::<F>(name, v, dateindex),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
}
|
||||
64
crates/brk_computer/src/internal/multi/date/max.rs
Normal file
64
crates/brk_computer/src/internal/multi/date/max.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
//! ComputedVecsDate using only max-value aggregation.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
|
||||
|
||||
use crate::{ComputeIndexes, indexes};
|
||||
|
||||
use crate::internal::{ComputedVecValue, LazyPeriodsMax};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ComputedDateMax<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub dateindex: EagerVec<PcoVec<DateIndex, T>>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub rest: LazyPeriodsMax<T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedDateMax<T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let dateindex = EagerVec::forced_import(db, name, version + VERSION)?;
|
||||
|
||||
Ok(Self {
|
||||
rest: LazyPeriodsMax::from_source(
|
||||
name,
|
||||
version + VERSION,
|
||||
dateindex.boxed_clone(),
|
||||
indexes,
|
||||
),
|
||||
dateindex,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
_starting_indexes: &ComputeIndexes,
|
||||
_exit: &Exit,
|
||||
mut compute: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut EagerVec<PcoVec<DateIndex, T>>) -> Result<()>,
|
||||
{
|
||||
compute(&mut self.dateindex)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
64
crates/brk_computer/src/internal/multi/date/min.rs
Normal file
64
crates/brk_computer/src/internal/multi/date/min.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
//! ComputedVecsDate using only min-value aggregation.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
|
||||
|
||||
use crate::{ComputeIndexes, indexes};
|
||||
|
||||
use crate::internal::{ComputedVecValue, LazyPeriodsMin};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ComputedDateMin<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub dateindex: EagerVec<PcoVec<DateIndex, T>>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub rest: LazyPeriodsMin<T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedDateMin<T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let dateindex = EagerVec::forced_import(db, name, version + VERSION)?;
|
||||
|
||||
Ok(Self {
|
||||
rest: LazyPeriodsMin::from_source(
|
||||
name,
|
||||
version + VERSION,
|
||||
dateindex.boxed_clone(),
|
||||
indexes,
|
||||
),
|
||||
dateindex,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
_starting_indexes: &ComputeIndexes,
|
||||
_exit: &Exit,
|
||||
mut compute: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut EagerVec<PcoVec<DateIndex, T>>) -> Result<()>,
|
||||
{
|
||||
compute(&mut self.dateindex)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
25
crates/brk_computer/src/internal/multi/date/mod.rs
Normal file
25
crates/brk_computer/src/internal/multi/date/mod.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
mod average;
|
||||
mod binary_last;
|
||||
mod binary_sum;
|
||||
mod binary_sum_cum;
|
||||
mod first;
|
||||
mod last;
|
||||
mod lazy_full;
|
||||
mod lazy_last;
|
||||
mod lazy_sum;
|
||||
mod lazy_sum_cum;
|
||||
mod max;
|
||||
mod min;
|
||||
|
||||
pub use average::*;
|
||||
pub use binary_last::*;
|
||||
pub use binary_sum::*;
|
||||
pub use binary_sum_cum::*;
|
||||
pub use first::*;
|
||||
pub use last::*;
|
||||
pub use lazy_full::*;
|
||||
pub use lazy_last::*;
|
||||
pub use lazy_sum::*;
|
||||
pub use lazy_sum_cum::*;
|
||||
pub use max::*;
|
||||
pub use min::*;
|
||||
@@ -0,0 +1,58 @@
|
||||
//! Derived date periods with average-value aggregation.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableBoxedVec, IterableCloneableVec};
|
||||
|
||||
use crate::{indexes, internal::LazyAverage};
|
||||
|
||||
use crate::internal::ComputedVecValue;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyPeriodsAverage<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub weekindex: LazyAverage<WeekIndex, T, DateIndex, WeekIndex>,
|
||||
pub monthindex: LazyAverage<MonthIndex, T, DateIndex, MonthIndex>,
|
||||
pub quarterindex: LazyAverage<QuarterIndex, T, DateIndex, QuarterIndex>,
|
||||
pub semesterindex: LazyAverage<SemesterIndex, T, DateIndex, SemesterIndex>,
|
||||
pub yearindex: LazyAverage<YearIndex, T, DateIndex, YearIndex>,
|
||||
pub decadeindex: LazyAverage<DecadeIndex, T, DateIndex, DecadeIndex>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> LazyPeriodsAverage<T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
{
|
||||
/// Create from an external dateindex source.
|
||||
pub fn from_source(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex_source: IterableBoxedVec<DateIndex, T>,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($idx:ident) => {
|
||||
LazyAverage::from_source_raw(name, v, dateindex_source.clone(), indexes.$idx.identity.boxed_clone())
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
//! Derived date periods with distribution aggregation.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableBoxedVec, IterableCloneableVec};
|
||||
|
||||
use crate::{indexes, internal::LazyDistribution};
|
||||
|
||||
use crate::internal::ComputedVecValue;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyPeriodsDistribution<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub weekindex: LazyDistribution<WeekIndex, T, DateIndex, WeekIndex>,
|
||||
pub monthindex: LazyDistribution<MonthIndex, T, DateIndex, MonthIndex>,
|
||||
pub quarterindex: LazyDistribution<QuarterIndex, T, DateIndex, QuarterIndex>,
|
||||
pub semesterindex: LazyDistribution<SemesterIndex, T, DateIndex, SemesterIndex>,
|
||||
pub yearindex: LazyDistribution<YearIndex, T, DateIndex, YearIndex>,
|
||||
pub decadeindex: LazyDistribution<DecadeIndex, T, DateIndex, DecadeIndex>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> LazyPeriodsDistribution<T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
{
|
||||
/// Create from external dateindex sources for distribution stats.
|
||||
pub fn from_sources(
|
||||
name: &str,
|
||||
version: Version,
|
||||
average_source: IterableBoxedVec<DateIndex, T>,
|
||||
min_source: IterableBoxedVec<DateIndex, T>,
|
||||
max_source: IterableBoxedVec<DateIndex, T>,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($idx:ident) => {
|
||||
LazyDistribution::from_distribution(
|
||||
name, v, average_source.clone(), min_source.clone(), max_source.clone(),
|
||||
indexes.$idx.identity.boxed_clone(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
}
|
||||
58
crates/brk_computer/src/internal/multi/derived_date/first.rs
Normal file
58
crates/brk_computer/src/internal/multi/derived_date/first.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
//! Derived date periods with first-value aggregation.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableBoxedVec, IterableCloneableVec};
|
||||
|
||||
use crate::{indexes, internal::LazyFirst};
|
||||
|
||||
use crate::internal::ComputedVecValue;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyPeriodsFirst<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub weekindex: LazyFirst<WeekIndex, T, DateIndex, WeekIndex>,
|
||||
pub monthindex: LazyFirst<MonthIndex, T, DateIndex, MonthIndex>,
|
||||
pub quarterindex: LazyFirst<QuarterIndex, T, DateIndex, QuarterIndex>,
|
||||
pub semesterindex: LazyFirst<SemesterIndex, T, DateIndex, SemesterIndex>,
|
||||
pub yearindex: LazyFirst<YearIndex, T, DateIndex, YearIndex>,
|
||||
pub decadeindex: LazyFirst<DecadeIndex, T, DateIndex, DecadeIndex>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> LazyPeriodsFirst<T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
{
|
||||
/// Create from an external dateindex source.
|
||||
pub fn from_source(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex_source: IterableBoxedVec<DateIndex, T>,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($idx:ident) => {
|
||||
LazyFirst::from_source(name, v, dateindex_source.clone(), indexes.$idx.identity.boxed_clone())
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
}
|
||||
68
crates/brk_computer/src/internal/multi/derived_date/full.rs
Normal file
68
crates/brk_computer/src/internal/multi/derived_date/full.rs
Normal file
@@ -0,0 +1,68 @@
|
||||
//! Derived date periods with full stats aggregation.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableBoxedVec, IterableCloneableVec};
|
||||
|
||||
use crate::{indexes, internal::LazyFull};
|
||||
|
||||
use crate::internal::ComputedVecValue;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyPeriodsFull<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub weekindex: LazyFull<WeekIndex, T, DateIndex, WeekIndex>,
|
||||
pub monthindex: LazyFull<MonthIndex, T, DateIndex, MonthIndex>,
|
||||
pub quarterindex: LazyFull<QuarterIndex, T, DateIndex, QuarterIndex>,
|
||||
pub semesterindex: LazyFull<SemesterIndex, T, DateIndex, SemesterIndex>,
|
||||
pub yearindex: LazyFull<YearIndex, T, DateIndex, YearIndex>,
|
||||
pub decadeindex: LazyFull<DecadeIndex, T, DateIndex, DecadeIndex>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> LazyPeriodsFull<T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
{
|
||||
/// Create from external dateindex sources for full stats.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn from_sources(
|
||||
name: &str,
|
||||
version: Version,
|
||||
average_source: IterableBoxedVec<DateIndex, T>,
|
||||
min_source: IterableBoxedVec<DateIndex, T>,
|
||||
max_source: IterableBoxedVec<DateIndex, T>,
|
||||
sum_source: IterableBoxedVec<DateIndex, T>,
|
||||
cumulative_source: IterableBoxedVec<DateIndex, T>,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($idx:ident) => {
|
||||
LazyFull::from_stats_aggregate(
|
||||
name, v,
|
||||
average_source.clone(), min_source.clone(), max_source.clone(),
|
||||
sum_source.clone(), cumulative_source.clone(),
|
||||
indexes.$idx.identity.boxed_clone(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
}
|
||||
58
crates/brk_computer/src/internal/multi/derived_date/last.rs
Normal file
58
crates/brk_computer/src/internal/multi/derived_date/last.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
//! Derived date periods with last-value aggregation.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableBoxedVec, IterableCloneableVec};
|
||||
|
||||
use crate::{indexes, internal::LazyLast};
|
||||
|
||||
use crate::internal::ComputedVecValue;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyPeriodsLast<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub weekindex: LazyLast<WeekIndex, T, DateIndex, WeekIndex>,
|
||||
pub monthindex: LazyLast<MonthIndex, T, DateIndex, MonthIndex>,
|
||||
pub quarterindex: LazyLast<QuarterIndex, T, DateIndex, QuarterIndex>,
|
||||
pub semesterindex: LazyLast<SemesterIndex, T, DateIndex, SemesterIndex>,
|
||||
pub yearindex: LazyLast<YearIndex, T, DateIndex, YearIndex>,
|
||||
pub decadeindex: LazyLast<DecadeIndex, T, DateIndex, DecadeIndex>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> LazyPeriodsLast<T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
{
|
||||
/// Create from an external dateindex source.
|
||||
pub fn from_source(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex_source: IterableBoxedVec<DateIndex, T>,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($idx:ident) => {
|
||||
LazyLast::from_source(name, v, dateindex_source.clone(), indexes.$idx.identity.boxed_clone())
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
}
|
||||
88
crates/brk_computer/src/internal/multi/derived_date/lazy.rs
Normal file
88
crates/brk_computer/src/internal/multi/derived_date/lazy.rs
Normal file
@@ -0,0 +1,88 @@
|
||||
//! Generic lazy vecs for all time period indexes.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use serde::Serialize;
|
||||
use vecdb::{ComputeFrom1, Formattable, IterableCloneableVec, LazyVecFrom1, VecValue};
|
||||
|
||||
use crate::indexes;
|
||||
|
||||
/// Lazy vecs for all time period indexes (no height).
|
||||
#[derive(Clone, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyPeriodVecs<T>
|
||||
where
|
||||
T: VecValue + Formattable + Serialize + JsonSchema,
|
||||
{
|
||||
pub dateindex: LazyVecFrom1<DateIndex, T, DateIndex, DateIndex>,
|
||||
pub weekindex: LazyVecFrom1<WeekIndex, T, WeekIndex, WeekIndex>,
|
||||
pub monthindex: LazyVecFrom1<MonthIndex, T, MonthIndex, MonthIndex>,
|
||||
pub quarterindex: LazyVecFrom1<QuarterIndex, T, QuarterIndex, QuarterIndex>,
|
||||
pub semesterindex: LazyVecFrom1<SemesterIndex, T, SemesterIndex, SemesterIndex>,
|
||||
pub yearindex: LazyVecFrom1<YearIndex, T, YearIndex, YearIndex>,
|
||||
pub decadeindex: LazyVecFrom1<DecadeIndex, T, DecadeIndex, DecadeIndex>,
|
||||
}
|
||||
|
||||
impl<T: VecValue + Formattable + Serialize + JsonSchema> LazyPeriodVecs<T> {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
dateindex_fn: ComputeFrom1<DateIndex, T, DateIndex, DateIndex>,
|
||||
weekindex_fn: ComputeFrom1<WeekIndex, T, WeekIndex, WeekIndex>,
|
||||
monthindex_fn: ComputeFrom1<MonthIndex, T, MonthIndex, MonthIndex>,
|
||||
quarterindex_fn: ComputeFrom1<QuarterIndex, T, QuarterIndex, QuarterIndex>,
|
||||
semesterindex_fn: ComputeFrom1<SemesterIndex, T, SemesterIndex, SemesterIndex>,
|
||||
yearindex_fn: ComputeFrom1<YearIndex, T, YearIndex, YearIndex>,
|
||||
decadeindex_fn: ComputeFrom1<DecadeIndex, T, DecadeIndex, DecadeIndex>,
|
||||
) -> Self {
|
||||
Self {
|
||||
dateindex: LazyVecFrom1::init(
|
||||
name,
|
||||
version,
|
||||
indexes.dateindex.identity.boxed_clone(),
|
||||
dateindex_fn,
|
||||
),
|
||||
weekindex: LazyVecFrom1::init(
|
||||
name,
|
||||
version,
|
||||
indexes.weekindex.identity.boxed_clone(),
|
||||
weekindex_fn,
|
||||
),
|
||||
monthindex: LazyVecFrom1::init(
|
||||
name,
|
||||
version,
|
||||
indexes.monthindex.identity.boxed_clone(),
|
||||
monthindex_fn,
|
||||
),
|
||||
quarterindex: LazyVecFrom1::init(
|
||||
name,
|
||||
version,
|
||||
indexes.quarterindex.identity.boxed_clone(),
|
||||
quarterindex_fn,
|
||||
),
|
||||
semesterindex: LazyVecFrom1::init(
|
||||
name,
|
||||
version,
|
||||
indexes.semesterindex.identity.boxed_clone(),
|
||||
semesterindex_fn,
|
||||
),
|
||||
yearindex: LazyVecFrom1::init(
|
||||
name,
|
||||
version,
|
||||
indexes.yearindex.identity.boxed_clone(),
|
||||
yearindex_fn,
|
||||
),
|
||||
decadeindex: LazyVecFrom1::init(
|
||||
name,
|
||||
version,
|
||||
indexes.decadeindex.identity.boxed_clone(),
|
||||
decadeindex_fn,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
58
crates/brk_computer/src/internal/multi/derived_date/max.rs
Normal file
58
crates/brk_computer/src/internal/multi/derived_date/max.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
//! Derived date periods with max-value aggregation.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableBoxedVec, IterableCloneableVec};
|
||||
|
||||
use crate::{indexes, internal::LazyMax};
|
||||
|
||||
use crate::internal::ComputedVecValue;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyPeriodsMax<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub weekindex: LazyMax<WeekIndex, T, DateIndex, WeekIndex>,
|
||||
pub monthindex: LazyMax<MonthIndex, T, DateIndex, MonthIndex>,
|
||||
pub quarterindex: LazyMax<QuarterIndex, T, DateIndex, QuarterIndex>,
|
||||
pub semesterindex: LazyMax<SemesterIndex, T, DateIndex, SemesterIndex>,
|
||||
pub yearindex: LazyMax<YearIndex, T, DateIndex, YearIndex>,
|
||||
pub decadeindex: LazyMax<DecadeIndex, T, DateIndex, DecadeIndex>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> LazyPeriodsMax<T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
{
|
||||
/// Create from an external dateindex source.
|
||||
pub fn from_source(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex_source: IterableBoxedVec<DateIndex, T>,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($idx:ident) => {
|
||||
LazyMax::from_source(name, v, dateindex_source.clone(), indexes.$idx.identity.boxed_clone())
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
}
|
||||
58
crates/brk_computer/src/internal/multi/derived_date/min.rs
Normal file
58
crates/brk_computer/src/internal/multi/derived_date/min.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
//! Derived date periods with min-value aggregation.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableBoxedVec, IterableCloneableVec};
|
||||
|
||||
use crate::{indexes, internal::LazyMin};
|
||||
|
||||
use crate::internal::ComputedVecValue;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyPeriodsMin<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub weekindex: LazyMin<WeekIndex, T, DateIndex, WeekIndex>,
|
||||
pub monthindex: LazyMin<MonthIndex, T, DateIndex, MonthIndex>,
|
||||
pub quarterindex: LazyMin<QuarterIndex, T, DateIndex, QuarterIndex>,
|
||||
pub semesterindex: LazyMin<SemesterIndex, T, DateIndex, SemesterIndex>,
|
||||
pub yearindex: LazyMin<YearIndex, T, DateIndex, YearIndex>,
|
||||
pub decadeindex: LazyMin<DecadeIndex, T, DateIndex, DecadeIndex>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> LazyPeriodsMin<T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
{
|
||||
/// Create from an external dateindex source.
|
||||
pub fn from_source(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex_source: IterableBoxedVec<DateIndex, T>,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($idx:ident) => {
|
||||
LazyMin::from_source(name, v, dateindex_source.clone(), indexes.$idx.identity.boxed_clone())
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
}
|
||||
21
crates/brk_computer/src/internal/multi/derived_date/mod.rs
Normal file
21
crates/brk_computer/src/internal/multi/derived_date/mod.rs
Normal file
@@ -0,0 +1,21 @@
|
||||
mod average;
|
||||
mod distribution;
|
||||
mod first;
|
||||
mod full;
|
||||
mod last;
|
||||
mod lazy;
|
||||
mod max;
|
||||
mod min;
|
||||
mod sum;
|
||||
mod sum_cum;
|
||||
|
||||
pub use average::*;
|
||||
pub use distribution::*;
|
||||
pub use first::*;
|
||||
pub use full::*;
|
||||
pub use last::*;
|
||||
pub use lazy::*;
|
||||
pub use max::*;
|
||||
pub use min::*;
|
||||
pub use sum::*;
|
||||
pub use sum_cum::*;
|
||||
58
crates/brk_computer/src/internal/multi/derived_date/sum.rs
Normal file
58
crates/brk_computer/src/internal/multi/derived_date/sum.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
//! Derived date periods with sum aggregation.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableBoxedVec, IterableCloneableVec};
|
||||
|
||||
use crate::{indexes, internal::LazySum};
|
||||
|
||||
use crate::internal::ComputedVecValue;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyPeriodsSum<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub weekindex: LazySum<WeekIndex, T, DateIndex, WeekIndex>,
|
||||
pub monthindex: LazySum<MonthIndex, T, DateIndex, MonthIndex>,
|
||||
pub quarterindex: LazySum<QuarterIndex, T, DateIndex, QuarterIndex>,
|
||||
pub semesterindex: LazySum<SemesterIndex, T, DateIndex, SemesterIndex>,
|
||||
pub yearindex: LazySum<YearIndex, T, DateIndex, YearIndex>,
|
||||
pub decadeindex: LazySum<DecadeIndex, T, DateIndex, DecadeIndex>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> LazyPeriodsSum<T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
{
|
||||
/// Create from an external dateindex source.
|
||||
pub fn from_source(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex_source: IterableBoxedVec<DateIndex, T>,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($idx:ident) => {
|
||||
LazySum::from_source_raw(name, v, dateindex_source.clone(), indexes.$idx.identity.boxed_clone())
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
//! Derived date periods with sum+cumulative aggregation.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableBoxedVec, IterableCloneableVec};
|
||||
|
||||
use crate::{indexes, internal::LazySumCum};
|
||||
|
||||
use crate::internal::ComputedVecValue;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyPeriodsSumCum<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub weekindex: LazySumCum<WeekIndex, T, DateIndex, WeekIndex>,
|
||||
pub monthindex: LazySumCum<MonthIndex, T, DateIndex, MonthIndex>,
|
||||
pub quarterindex: LazySumCum<QuarterIndex, T, DateIndex, QuarterIndex>,
|
||||
pub semesterindex: LazySumCum<SemesterIndex, T, DateIndex, SemesterIndex>,
|
||||
pub yearindex: LazySumCum<YearIndex, T, DateIndex, YearIndex>,
|
||||
pub decadeindex: LazySumCum<DecadeIndex, T, DateIndex, DecadeIndex>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> LazyPeriodsSumCum<T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
{
|
||||
/// Create from external dateindex sum and cumulative sources.
|
||||
pub fn from_sources(
|
||||
name: &str,
|
||||
version: Version,
|
||||
sum_source: IterableBoxedVec<DateIndex, T>,
|
||||
cumulative_source: IterableBoxedVec<DateIndex, T>,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($idx:ident) => {
|
||||
LazySumCum::from_sources_sum_raw(
|
||||
name, v, sum_source.clone(), cumulative_source.clone(),
|
||||
indexes.$idx.identity.boxed_clone(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
//! Lazy binary transform for derived block with Last aggregation only.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DifficultyEpoch, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{BinaryTransform, IterableCloneableVec};
|
||||
|
||||
use crate::internal::{
|
||||
ComputedBlockLast, ComputedBlockSumCum, ComputedHeightDateLast, ComputedVecValue,
|
||||
LazyBinaryDateLast, LazyBinaryTransformLast, NumericValue,
|
||||
};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyBinaryDerivedBlockLast<T, S1T = T, S2T = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
S2T: ComputedVecValue,
|
||||
{
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub dates: LazyBinaryDateLast<T, S1T, S2T>,
|
||||
pub difficultyepoch: LazyBinaryTransformLast<DifficultyEpoch, T, S1T, S2T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T, S1T, S2T> LazyBinaryDerivedBlockLast<T, S1T, S2T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
S2T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn from_computed_sum_cum<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedBlockSumCum<S1T>,
|
||||
source2: &ComputedBlockSumCum<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: PartialOrd,
|
||||
S2T: PartialOrd,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
dates: LazyBinaryDateLast::from_both_sum_cum_cumulatives::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.dateindex.cumulative.boxed_clone(),
|
||||
&source1.dates,
|
||||
source2.dateindex.cumulative.boxed_clone(),
|
||||
&source2.dates,
|
||||
),
|
||||
difficultyepoch: LazyBinaryTransformLast::from_vecs::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.difficultyepoch.cumulative.boxed_clone(),
|
||||
source2.difficultyepoch.cumulative.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_computed_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedBlockLast<S1T>,
|
||||
source2: &ComputedBlockLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
dates: LazyBinaryDateLast::from_both_block_last::<F>(name, v, source1, source2),
|
||||
difficultyepoch: LazyBinaryTransformLast::from_vecs::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.difficultyepoch.boxed_clone(),
|
||||
source2.difficultyepoch.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_computed_height_date_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedHeightDateLast<S1T>,
|
||||
source2: &ComputedHeightDateLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: PartialOrd,
|
||||
S2T: PartialOrd,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
dates: LazyBinaryDateLast::from_computed_both_last::<F>(
|
||||
name,
|
||||
v,
|
||||
&source1.rest,
|
||||
&source2.rest,
|
||||
),
|
||||
difficultyepoch: LazyBinaryTransformLast::from_vecs::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.difficultyepoch.0.boxed_clone(),
|
||||
source2.difficultyepoch.0.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_computed_height_date_and_block_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedHeightDateLast<S1T>,
|
||||
source2: &ComputedBlockLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: PartialOrd,
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
dates: LazyBinaryDateLast::from_dateindex_and_height_last::<F>(
|
||||
name,
|
||||
v,
|
||||
&source1.rest,
|
||||
source2,
|
||||
),
|
||||
difficultyepoch: LazyBinaryTransformLast::from_vecs::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.difficultyepoch.0.boxed_clone(),
|
||||
source2.difficultyepoch.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
//! Lazy aggregated binary transform for Sum-only pattern across all time periods.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DifficultyEpoch, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{BinaryTransform, IterableCloneableVec};
|
||||
|
||||
use crate::internal::{ComputedVecValue, ComputedDerivedBlockSum, LazyBinaryDateSum, LazyBinaryTransformSum, NumericValue};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyBinaryDerivedBlockSum<T, S1T, S2T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
S2T: ComputedVecValue,
|
||||
{
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub dates: LazyBinaryDateSum<T, S1T, S2T>,
|
||||
pub difficultyepoch: LazyBinaryTransformSum<DifficultyEpoch, T, S1T, S2T>,
|
||||
}
|
||||
|
||||
impl<T, S1T, S2T> LazyBinaryDerivedBlockSum<T, S1T, S2T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: NumericValue + JsonSchema,
|
||||
S2T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub fn from_derived<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedDerivedBlockSum<S1T>,
|
||||
source2: &ComputedDerivedBlockSum<S2T>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
dates: LazyBinaryDateSum::from_derived::<F>(name, v, source1, source2),
|
||||
difficultyepoch: LazyBinaryTransformSum::from_boxed::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.difficultyepoch.boxed_clone(),
|
||||
source2.difficultyepoch.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
//! Lazy aggregated SumCum - binary transform version.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DifficultyEpoch, Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{BinaryTransform, IterableCloneableVec};
|
||||
|
||||
use crate::internal::{
|
||||
ComputedBlockLast, ComputedBlockSumCum, ComputedDerivedBlockLast, ComputedDerivedBlockSumCum,
|
||||
ComputedVecValue, LazyBinaryDateSumCum, LazyBinaryTransformSumCum, LazyFull, LazyPeriodsFull,
|
||||
LazyPeriodsSumCum, LazySumCum, NumericValue, SumCum,
|
||||
};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyBinaryDerivedBlockSumCum<T, S1T = T, S2T = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
S2T: ComputedVecValue,
|
||||
{
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub dates: LazyBinaryDateSumCum<T, S1T, S2T>,
|
||||
pub difficultyepoch: LazyBinaryTransformSumCum<DifficultyEpoch, T, S1T, S2T>,
|
||||
}
|
||||
|
||||
impl<T, S1T, S2T> LazyBinaryDerivedBlockSumCum<T, S1T, S2T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
S2T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn from_computed<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex1: &SumCum<brk_types::DateIndex, S1T>,
|
||||
periods1: &LazyPeriodsSumCum<S1T>,
|
||||
difficultyepoch1: &LazySumCum<DifficultyEpoch, S1T, Height, DifficultyEpoch>,
|
||||
dateindex2: &SumCum<brk_types::DateIndex, S2T>,
|
||||
periods2: &LazyPeriodsSumCum<S2T>,
|
||||
difficultyepoch2: &LazySumCum<DifficultyEpoch, S2T, Height, DifficultyEpoch>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
dates: LazyBinaryDateSumCum::from_computed::<F>(
|
||||
name, v, dateindex1, periods1, dateindex2, periods2,
|
||||
),
|
||||
difficultyepoch: LazyBinaryTransformSumCum::from_sources::<F>(
|
||||
name,
|
||||
v,
|
||||
difficultyepoch1.sum.boxed_clone(),
|
||||
difficultyepoch2.sum.boxed_clone(),
|
||||
difficultyepoch1.cumulative.boxed_clone(),
|
||||
difficultyepoch2.cumulative.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn from_derived_full<F, S1I, S1L, S2I, S2L>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex1: &SumCum<brk_types::DateIndex, S1T>,
|
||||
dates1: &LazyPeriodsFull<S1T>,
|
||||
difficultyepoch1: &LazyFull<DifficultyEpoch, S1T, S1I, S1L>,
|
||||
dateindex2: &SumCum<brk_types::DateIndex, S2T>,
|
||||
dates2: &LazyPeriodsFull<S2T>,
|
||||
difficultyepoch2: &LazyFull<DifficultyEpoch, S2T, S2I, S2L>,
|
||||
) -> Self
|
||||
where
|
||||
F: BinaryTransform<S1T, S2T, T>,
|
||||
S1I: vecdb::VecIndex + 'static,
|
||||
S1L: ComputedVecValue,
|
||||
S2I: vecdb::VecIndex + 'static,
|
||||
S2L: ComputedVecValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
dates: LazyBinaryDateSumCum::from_derived_full::<F>(
|
||||
name, v, dateindex1, dates1, dateindex2, dates2,
|
||||
),
|
||||
difficultyepoch: LazyBinaryTransformSumCum::from_lazy_stats_aggregate::<F, _, _, _, _>(
|
||||
name,
|
||||
v,
|
||||
difficultyepoch1,
|
||||
difficultyepoch2,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
/// Without _sum suffix for pure SumCum types.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn from_computed_sum_raw<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex1: &SumCum<brk_types::DateIndex, S1T>,
|
||||
periods1: &LazyPeriodsSumCum<S1T>,
|
||||
difficultyepoch1: &LazySumCum<DifficultyEpoch, S1T, Height, DifficultyEpoch>,
|
||||
dateindex2: &SumCum<brk_types::DateIndex, S2T>,
|
||||
periods2: &LazyPeriodsSumCum<S2T>,
|
||||
difficultyepoch2: &LazySumCum<DifficultyEpoch, S2T, Height, DifficultyEpoch>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
dates: LazyBinaryDateSumCum::from_computed_sum_raw::<F>(
|
||||
name, v, dateindex1, periods1, dateindex2, periods2,
|
||||
),
|
||||
difficultyepoch: LazyBinaryTransformSumCum::from_sources_sum_raw::<F>(
|
||||
name,
|
||||
v,
|
||||
difficultyepoch1.sum.boxed_clone(),
|
||||
difficultyepoch2.sum.boxed_clone(),
|
||||
difficultyepoch1.cumulative.boxed_clone(),
|
||||
difficultyepoch2.cumulative.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// --- Methods accepting SumCum + Last sources ---
|
||||
|
||||
pub fn from_computed_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedBlockSumCum<S1T>,
|
||||
source2: &ComputedBlockLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: PartialOrd,
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
dates: LazyBinaryDateSumCum::from_computed_last::<F>(name, v, source1, source2),
|
||||
difficultyepoch: LazyBinaryTransformSumCum::from_sources_last_sum_raw::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.difficultyepoch.sum.boxed_clone(),
|
||||
source1.difficultyepoch.cumulative.boxed_clone(),
|
||||
source2.difficultyepoch.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_derived_computed_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedDerivedBlockSumCum<S1T>,
|
||||
source2: &ComputedBlockLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
dates: LazyBinaryDateSumCum::from_derived_computed_last::<F>(name, v, source1, source2),
|
||||
difficultyepoch: LazyBinaryTransformSumCum::from_sources_last_sum_raw::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.difficultyepoch.sum.boxed_clone(),
|
||||
source1.difficultyepoch.cumulative.boxed_clone(),
|
||||
source2.difficultyepoch.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_computed_derived_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedBlockSumCum<S1T>,
|
||||
source2: &ComputedDerivedBlockLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: PartialOrd,
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
dates: LazyBinaryDateSumCum::from_computed_derived_last::<F>(name, v, source1, source2),
|
||||
difficultyepoch: LazyBinaryTransformSumCum::from_sources_last_sum_raw::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.difficultyepoch.sum.boxed_clone(),
|
||||
source1.difficultyepoch.cumulative.boxed_clone(),
|
||||
source2.difficultyepoch.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_derived_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedDerivedBlockSumCum<S1T>,
|
||||
source2: &ComputedDerivedBlockLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
dates: LazyBinaryDateSumCum::from_derived_last::<F>(name, v, source1, source2),
|
||||
difficultyepoch: LazyBinaryTransformSumCum::from_sources_last_sum_raw::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.difficultyepoch.sum.boxed_clone(),
|
||||
source1.difficultyepoch.cumulative.boxed_clone(),
|
||||
source2.difficultyepoch.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
//! ComputedDerivedBlockDistribution - dateindex storage + lazy time periods + difficultyepoch.
|
||||
|
||||
use brk_error::Result;
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, Exit, IterableBoxedVec, IterableCloneableVec, IterableVec};
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, indexes,
|
||||
internal::{
|
||||
ComputedVecValue, LazyPeriodsDistribution, Distribution, LazyDistribution, NumericValue,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ComputedDerivedBlockDistribution<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub dateindex: Distribution<DateIndex, T>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub dates: LazyPeriodsDistribution<T>,
|
||||
pub difficultyepoch: LazyDistribution<DifficultyEpoch, T, Height, DifficultyEpoch>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedDerivedBlockDistribution<T>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
height_source: IterableBoxedVec<Height, T>,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let dateindex = Distribution::forced_import(db, name, version + VERSION)?;
|
||||
let v = version + VERSION;
|
||||
|
||||
let dates = LazyPeriodsDistribution::from_sources(
|
||||
name,
|
||||
v,
|
||||
dateindex.average.0.boxed_clone(),
|
||||
dateindex.minmax.min.0.boxed_clone(),
|
||||
dateindex.minmax.max.0.boxed_clone(),
|
||||
indexes,
|
||||
);
|
||||
|
||||
let difficultyepoch = LazyDistribution::from_distribution(
|
||||
name,
|
||||
v,
|
||||
height_source.boxed_clone(),
|
||||
height_source.boxed_clone(),
|
||||
height_source,
|
||||
indexes.difficultyepoch.identity.boxed_clone(),
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
dateindex,
|
||||
dates,
|
||||
difficultyepoch,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn derive_from(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
height_source: &impl IterableVec<Height, T>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.dateindex.compute(
|
||||
starting_indexes.dateindex,
|
||||
height_source,
|
||||
&indexes.dateindex.first_height,
|
||||
&indexes.dateindex.height_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
//! ComputedDerivedBlockFirst - dateindex storage + difficultyepoch + lazy time periods (first value).
|
||||
|
||||
use brk_error::Result;
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, Exit, IterableBoxedVec, IterableCloneableVec, IterableVec};
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, indexes,
|
||||
internal::{ComputedVecValue, LazyPeriodsFirst, FirstVec, LazyFirst, NumericValue},
|
||||
};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ComputedDerivedBlockFirst<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub dateindex: FirstVec<DateIndex, T>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub dates: LazyPeriodsFirst<T>,
|
||||
pub difficultyepoch: LazyFirst<DifficultyEpoch, T, Height, DifficultyEpoch>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedDerivedBlockFirst<T>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
height_source: IterableBoxedVec<Height, T>,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let dateindex = FirstVec::forced_import(db, name, version + VERSION)?;
|
||||
let v = version + VERSION;
|
||||
|
||||
Ok(Self {
|
||||
dates: LazyPeriodsFirst::from_source(name, v, dateindex.0.boxed_clone(), indexes),
|
||||
difficultyepoch: LazyFirst::from_source(
|
||||
name,
|
||||
v,
|
||||
height_source,
|
||||
indexes.difficultyepoch.identity.boxed_clone(),
|
||||
),
|
||||
dateindex,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn derive_from(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
height_source: &impl IterableVec<Height, T>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.dateindex.compute_first(
|
||||
starting_indexes.dateindex,
|
||||
height_source,
|
||||
&indexes.dateindex.first_height,
|
||||
&indexes.dateindex.height_count,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn compute_all<F>(&mut self, mut compute: F) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut FirstVec<DateIndex, T>) -> Result<()>,
|
||||
{
|
||||
compute(&mut self.dateindex)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
107
crates/brk_computer/src/internal/multi/derived_height/full.rs
Normal file
107
crates/brk_computer/src/internal/multi/derived_height/full.rs
Normal file
@@ -0,0 +1,107 @@
|
||||
//! ComputedDerivedBlockFull - height_cumulative + dateindex storage + difficultyepoch + lazy time periods.
|
||||
|
||||
use brk_error::Result;
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, Exit, IterableBoxedVec, IterableCloneableVec, IterableVec};
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, indexes,
|
||||
internal::{
|
||||
ComputedVecValue, CumulativeVec, LazyPeriodsFull, Full, LazyFull, NumericValue,
|
||||
compute_cumulative_extend,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ComputedDerivedBlockFull<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
#[traversable(rename = "cumulative")]
|
||||
pub height_cumulative: CumulativeVec<Height, T>,
|
||||
pub dateindex: Full<DateIndex, T>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub dates: LazyPeriodsFull<T>,
|
||||
pub difficultyepoch: LazyFull<DifficultyEpoch, T, Height, DifficultyEpoch>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedDerivedBlockFull<T>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
height_source: IterableBoxedVec<Height, T>,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
let height_cumulative = CumulativeVec::forced_import(db, name, v)?;
|
||||
let dateindex = Full::forced_import(db, name, v)?;
|
||||
|
||||
Ok(Self {
|
||||
dates: LazyPeriodsFull::from_sources(
|
||||
name,
|
||||
v,
|
||||
dateindex.distribution.average.0.boxed_clone(),
|
||||
dateindex.distribution.minmax.min.0.boxed_clone(),
|
||||
dateindex.distribution.minmax.max.0.boxed_clone(),
|
||||
dateindex.sum_cum.sum.0.boxed_clone(),
|
||||
dateindex.sum_cum.cumulative.0.boxed_clone(),
|
||||
indexes,
|
||||
),
|
||||
difficultyepoch: LazyFull::from_stats_aggregate(
|
||||
name,
|
||||
v,
|
||||
height_source.boxed_clone(),
|
||||
height_source.boxed_clone(),
|
||||
height_source.boxed_clone(),
|
||||
height_source.boxed_clone(),
|
||||
height_cumulative.0.boxed_clone(),
|
||||
indexes.difficultyepoch.identity.boxed_clone(),
|
||||
),
|
||||
height_cumulative,
|
||||
dateindex,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn derive_from(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
height_source: &impl IterableVec<Height, T>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// Compute height_cumulative from external source
|
||||
self.compute_height_cumulative(starting_indexes.height, height_source, exit)?;
|
||||
|
||||
// Compute dateindex aggregations
|
||||
self.dateindex.compute(
|
||||
starting_indexes.dateindex,
|
||||
height_source,
|
||||
&indexes.dateindex.first_height,
|
||||
&indexes.dateindex.height_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compute_height_cumulative(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
height_source: &impl IterableVec<Height, T>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
compute_cumulative_extend(max_from, height_source, &mut self.height_cumulative.0, exit)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
//! ComputedDerivedBlockLast - dateindex storage + difficultyepoch + lazy time periods.
|
||||
|
||||
use brk_error::Result;
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, Exit, IterableBoxedVec, IterableCloneableVec, IterableVec};
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, indexes,
|
||||
internal::{ComputedVecValue, LazyPeriodsLast, LastVec, LazyLast, NumericValue},
|
||||
};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ComputedDerivedBlockLast<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub dateindex: LastVec<DateIndex, T>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub dates: LazyPeriodsLast<T>,
|
||||
pub difficultyepoch: LazyLast<DifficultyEpoch, T, Height, DifficultyEpoch>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedDerivedBlockLast<T>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
height_source: IterableBoxedVec<Height, T>,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let dateindex = LastVec::forced_import(db, name, version + VERSION)?;
|
||||
let v = version + VERSION;
|
||||
|
||||
Ok(Self {
|
||||
dates: LazyPeriodsLast::from_source(name, v, dateindex.0.boxed_clone(), indexes),
|
||||
difficultyepoch: LazyLast::from_source(
|
||||
name,
|
||||
v,
|
||||
height_source,
|
||||
indexes.difficultyepoch.identity.boxed_clone(),
|
||||
),
|
||||
dateindex,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn derive_from(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
height_source: &impl IterableVec<Height, T>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.dateindex.compute_last(
|
||||
starting_indexes.dateindex,
|
||||
height_source,
|
||||
&indexes.dateindex.first_height,
|
||||
&indexes.dateindex.height_count,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
//! Lazy aggregated Full for block-level sources.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, DifficultyEpoch, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableCloneableVec, UnaryTransform};
|
||||
|
||||
use crate::internal::{
|
||||
ComputedDerivedBlockFull, ComputedVecValue, Full, LazyDateFull, LazyPeriodsFull,
|
||||
LazyTransformStats, NumericValue,
|
||||
};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyDerivedBlockFull<T, S1T = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
{
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub dates: LazyDateFull<T, S1T>,
|
||||
pub difficultyepoch: LazyTransformStats<DifficultyEpoch, T, S1T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T, S1T> LazyDerivedBlockFull<T, S1T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn from_computed<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex: &Full<DateIndex, S1T>,
|
||||
periods: &LazyPeriodsFull<S1T>,
|
||||
difficultyepoch: &crate::internal::LazyFull<
|
||||
DifficultyEpoch,
|
||||
S1T,
|
||||
brk_types::Height,
|
||||
DifficultyEpoch,
|
||||
>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
dates: LazyDateFull::from_full::<F>(name, v, dateindex, periods),
|
||||
difficultyepoch: LazyTransformStats::from_boxed::<F>(
|
||||
name,
|
||||
v,
|
||||
difficultyepoch.average.boxed_clone(),
|
||||
difficultyepoch.min.boxed_clone(),
|
||||
difficultyepoch.max.boxed_clone(),
|
||||
difficultyepoch.sum.boxed_clone(),
|
||||
difficultyepoch.cumulative.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_derived_computed<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source: &ComputedDerivedBlockFull<S1T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
dates: LazyDateFull::from_full::<F>(name, v, &source.dateindex, &source.dates),
|
||||
difficultyepoch: LazyTransformStats::from_boxed::<F>(
|
||||
name,
|
||||
v,
|
||||
source.difficultyepoch.average.boxed_clone(),
|
||||
source.difficultyepoch.min.boxed_clone(),
|
||||
source.difficultyepoch.max.boxed_clone(),
|
||||
source.difficultyepoch.sum.boxed_clone(),
|
||||
source.difficultyepoch.cumulative.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
//! Lazy aggregated Last for block-level sources.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DifficultyEpoch, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableCloneableVec, UnaryTransform};
|
||||
|
||||
use crate::internal::{
|
||||
ComputedBlockLast, ComputedDerivedBlockLast, ComputedHeightDateLast, ComputedVecValue,
|
||||
LazyDateLast, LazyTransformLast, NumericValue,
|
||||
};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyDerivedBlockLast<T, S1T = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
{
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub dates: LazyDateLast<T, S1T>,
|
||||
pub difficultyepoch: LazyTransformLast<DifficultyEpoch, T, S1T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T, S1T> LazyDerivedBlockLast<T, S1T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn from_computed<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source: &ComputedBlockLast<S1T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
dates: LazyDateLast::from_derived::<F>(
|
||||
name,
|
||||
v,
|
||||
source.dateindex.0.boxed_clone(),
|
||||
&source.rest,
|
||||
),
|
||||
difficultyepoch: LazyTransformLast::from_boxed::<F>(
|
||||
name,
|
||||
v,
|
||||
source.difficultyepoch.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_derived_computed<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source: &ComputedDerivedBlockLast<S1T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
dates: LazyDateLast::from_derived::<F>(
|
||||
name,
|
||||
v,
|
||||
source.dateindex.0.boxed_clone(),
|
||||
&source.dates,
|
||||
),
|
||||
difficultyepoch: LazyTransformLast::from_boxed::<F>(
|
||||
name,
|
||||
v,
|
||||
source.difficultyepoch.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_computed_height_date<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source: &ComputedHeightDateLast<S1T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: PartialOrd,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
dates: LazyDateLast::from_derived::<F>(
|
||||
name,
|
||||
v,
|
||||
source.dateindex.boxed_clone(),
|
||||
&source.rest.rest,
|
||||
),
|
||||
difficultyepoch: LazyTransformLast::from_boxed::<F>(
|
||||
name,
|
||||
v,
|
||||
source.difficultyepoch.0.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
//! Lazy aggregated Sum for block-level sources.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableCloneableVec, UnaryTransform};
|
||||
|
||||
use crate::internal::{
|
||||
ComputedDerivedBlockSum, ComputedVecValue, LazyDateSum, LazyPeriodsSum, LazySum,
|
||||
LazyTransformSum, NumericValue, SumVec,
|
||||
};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyDerivedBlockSum<T, S1T = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
{
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub dates: LazyDateSum<T, S1T>,
|
||||
pub difficultyepoch: LazyTransformSum<DifficultyEpoch, T, S1T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T, S1T> LazyDerivedBlockSum<T, S1T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn from_computed<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex: &SumVec<DateIndex, S1T>,
|
||||
periods: &LazyPeriodsSum<S1T>,
|
||||
difficultyepoch: &LazySum<DifficultyEpoch, S1T, Height, DifficultyEpoch>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
dates: LazyDateSum::from_derived::<F>(name, v, dateindex.0.boxed_clone(), periods),
|
||||
difficultyepoch: LazyTransformSum::from_boxed::<F>(
|
||||
name,
|
||||
v,
|
||||
difficultyepoch.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_derived_computed<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source: &ComputedDerivedBlockSum<S1T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
dates: LazyDateSum::from_derived::<F>(
|
||||
name,
|
||||
v,
|
||||
source.dateindex.0.boxed_clone(),
|
||||
&source.dates,
|
||||
),
|
||||
difficultyepoch: LazyTransformSum::from_boxed::<F>(
|
||||
name,
|
||||
v,
|
||||
source.difficultyepoch.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
//! Lazy aggregated SumCum for block-level sources.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableCloneableVec, UnaryTransform};
|
||||
|
||||
use crate::internal::{
|
||||
ComputedDerivedBlockSumCum, ComputedVecValue, LazyDateSumCum, LazyPeriodsSumCum, LazySumCum,
|
||||
LazyTransformSumCum, NumericValue, SumCum,
|
||||
};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyDerivedBlockSumCum<T, S1T = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
{
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub dates: LazyDateSumCum<T, S1T>,
|
||||
pub difficultyepoch: LazyTransformSumCum<DifficultyEpoch, T, S1T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T, S1T> LazyDerivedBlockSumCum<T, S1T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn from_computed<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
dateindex: &SumCum<DateIndex, S1T>,
|
||||
periods: &LazyPeriodsSumCum<S1T>,
|
||||
difficultyepoch: &LazySumCum<DifficultyEpoch, S1T, Height, DifficultyEpoch>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
dates: LazyDateSumCum::from_sum_cum::<F>(name, v, dateindex, periods),
|
||||
difficultyepoch: LazyTransformSumCum::from_boxed_sum_raw::<F>(
|
||||
name,
|
||||
v,
|
||||
difficultyepoch.sum.boxed_clone(),
|
||||
difficultyepoch.cumulative.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_derived_computed<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source: &ComputedDerivedBlockSumCum<S1T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
dates: LazyDateSumCum::from_sum_cum::<F>(name, v, &source.dateindex, &source.dates),
|
||||
difficultyepoch: LazyTransformSumCum::from_boxed_sum_raw::<F>(
|
||||
name,
|
||||
v,
|
||||
source.difficultyepoch.sum.boxed_clone(),
|
||||
source.difficultyepoch.cumulative.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
27
crates/brk_computer/src/internal/multi/derived_height/mod.rs
Normal file
27
crates/brk_computer/src/internal/multi/derived_height/mod.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
mod binary_last;
|
||||
mod binary_sum;
|
||||
mod binary_sum_cum;
|
||||
mod distribution;
|
||||
mod first;
|
||||
mod full;
|
||||
mod last;
|
||||
mod lazy_full;
|
||||
mod lazy_last;
|
||||
mod lazy_sum;
|
||||
mod lazy_sum_cum;
|
||||
mod sum;
|
||||
mod sum_cum;
|
||||
|
||||
pub use binary_last::*;
|
||||
pub use binary_sum::*;
|
||||
pub use binary_sum_cum::*;
|
||||
pub use distribution::*;
|
||||
pub use first::*;
|
||||
pub use full::*;
|
||||
pub use last::*;
|
||||
pub use lazy_full::*;
|
||||
pub use lazy_last::*;
|
||||
pub use lazy_sum::*;
|
||||
pub use lazy_sum_cum::*;
|
||||
pub use sum::*;
|
||||
pub use sum_cum::*;
|
||||
115
crates/brk_computer/src/internal/multi/derived_height/sum.rs
Normal file
115
crates/brk_computer/src/internal/multi/derived_height/sum.rs
Normal file
@@ -0,0 +1,115 @@
|
||||
//! ComputedDerivedBlockSum - dateindex storage + difficultyepoch + lazy time periods.
|
||||
|
||||
use brk_error::Result;
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, DifficultyEpoch, Height, StoredU64, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{
|
||||
AnyStoredVec, AnyVec, Database, Exit, GenericStoredVec, IterableBoxedVec, IterableCloneableVec,
|
||||
IterableVec, VecIndex,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, indexes,
|
||||
internal::{ComputedVecValue, LazyPeriodsSum, LazySum, NumericValue, SumVec},
|
||||
};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ComputedDerivedBlockSum<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub dateindex: SumVec<DateIndex, T>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub dates: LazyPeriodsSum<T>,
|
||||
pub difficultyepoch: LazySum<DifficultyEpoch, T, Height, DifficultyEpoch>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedDerivedBlockSum<T>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
height_source: IterableBoxedVec<Height, T>,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let dateindex = SumVec::forced_import_raw(db, name, version + VERSION)?;
|
||||
let v = version + VERSION;
|
||||
|
||||
Ok(Self {
|
||||
dates: LazyPeriodsSum::from_source(name, v, dateindex.0.boxed_clone(), indexes),
|
||||
difficultyepoch: LazySum::from_source_raw(
|
||||
name,
|
||||
v,
|
||||
height_source,
|
||||
indexes.difficultyepoch.identity.boxed_clone(),
|
||||
),
|
||||
dateindex,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn derive_from(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
height_source: &impl IterableVec<Height, T>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_from(
|
||||
starting_indexes.dateindex,
|
||||
height_source,
|
||||
&indexes.dateindex.first_height,
|
||||
&indexes.dateindex.height_count,
|
||||
exit,
|
||||
)
|
||||
}
|
||||
|
||||
fn compute_from(
|
||||
&mut self,
|
||||
starting_dateindex: DateIndex,
|
||||
height_source: &impl IterableVec<Height, T>,
|
||||
first_indexes: &impl IterableVec<DateIndex, Height>,
|
||||
count_indexes: &impl IterableVec<DateIndex, StoredU64>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let sum_vec = &mut self.dateindex.0;
|
||||
|
||||
let combined_version =
|
||||
height_source.version() + first_indexes.version() + count_indexes.version();
|
||||
sum_vec.validate_computed_version_or_reset(combined_version)?;
|
||||
|
||||
let index = starting_dateindex.to_usize().min(sum_vec.len());
|
||||
|
||||
let mut source_iter = height_source.iter();
|
||||
let mut count_iter = count_indexes.iter().skip(index);
|
||||
|
||||
first_indexes.iter().enumerate().skip(index).try_for_each(
|
||||
|(idx, first_height)| -> Result<()> {
|
||||
let count = *count_iter.next().unwrap() as usize;
|
||||
|
||||
source_iter.set_position(first_height);
|
||||
let sum: T = (&mut source_iter)
|
||||
.take(count)
|
||||
.fold(T::from(0_usize), |acc, v| acc + v);
|
||||
|
||||
sum_vec.truncate_push_at(idx, sum)?;
|
||||
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
let _lock = exit.lock();
|
||||
sum_vec.write()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
158
crates/brk_computer/src/internal/multi/derived_height/sum_cum.rs
Normal file
158
crates/brk_computer/src/internal/multi/derived_height/sum_cum.rs
Normal file
@@ -0,0 +1,158 @@
|
||||
//! ComputedDerivedBlockSumCum - aggregates derived from an external height source.
|
||||
|
||||
use brk_error::Result;
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, DifficultyEpoch, Height, StoredU64, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{
|
||||
AnyStoredVec, AnyVec, Database, Exit, GenericStoredVec, IterableBoxedVec, IterableCloneableVec,
|
||||
IterableVec, VecIndex,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, indexes,
|
||||
internal::{
|
||||
ComputedVecValue, CumulativeVec, LazyPeriodsSumCum, LazySumCum, NumericValue, SumCum,
|
||||
compute_cumulative_extend,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ComputedDerivedBlockSumCum<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
#[traversable(rename = "cumulative")]
|
||||
pub height_cumulative: CumulativeVec<Height, T>,
|
||||
pub dateindex: SumCum<DateIndex, T>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub dates: LazyPeriodsSumCum<T>,
|
||||
pub difficultyepoch: LazySumCum<DifficultyEpoch, T, Height, DifficultyEpoch>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedDerivedBlockSumCum<T>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
height_source: IterableBoxedVec<Height, T>,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let height_cumulative = CumulativeVec::forced_import(db, name, v)?;
|
||||
let dateindex = SumCum::forced_import_sum_raw(db, name, v)?;
|
||||
|
||||
let dates = LazyPeriodsSumCum::from_sources(
|
||||
name,
|
||||
v,
|
||||
dateindex.sum.0.boxed_clone(),
|
||||
dateindex.cumulative.0.boxed_clone(),
|
||||
indexes,
|
||||
);
|
||||
|
||||
let difficultyepoch = LazySumCum::from_sources_sum_raw(
|
||||
name,
|
||||
v,
|
||||
height_source.boxed_clone(),
|
||||
height_cumulative.0.boxed_clone(),
|
||||
indexes.difficultyepoch.identity.boxed_clone(),
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
height_cumulative,
|
||||
dateindex,
|
||||
dates,
|
||||
difficultyepoch,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn derive_from(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
height_source: &impl IterableVec<Height, T>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_height_cumulative(starting_indexes.height, height_source, exit)?;
|
||||
self.compute_dateindex_sum_cum(
|
||||
starting_indexes.dateindex,
|
||||
height_source,
|
||||
&indexes.dateindex.first_height,
|
||||
&indexes.dateindex.height_count,
|
||||
exit,
|
||||
)
|
||||
}
|
||||
|
||||
fn compute_height_cumulative(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
source: &impl IterableVec<Height, T>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
compute_cumulative_extend(max_from, source, &mut self.height_cumulative.0, exit)
|
||||
}
|
||||
|
||||
fn compute_dateindex_sum_cum(
|
||||
&mut self,
|
||||
starting_dateindex: DateIndex,
|
||||
height_source: &impl IterableVec<Height, T>,
|
||||
first_indexes: &impl IterableVec<DateIndex, Height>,
|
||||
count_indexes: &impl IterableVec<DateIndex, StoredU64>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let sum_vec = &mut self.dateindex.sum.0;
|
||||
let cumulative_vec = &mut self.dateindex.cumulative.0;
|
||||
|
||||
let combined_version =
|
||||
height_source.version() + first_indexes.version() + count_indexes.version();
|
||||
sum_vec.validate_computed_version_or_reset(combined_version)?;
|
||||
cumulative_vec.validate_computed_version_or_reset(combined_version)?;
|
||||
|
||||
let index = starting_dateindex
|
||||
.to_usize()
|
||||
.min(sum_vec.len())
|
||||
.min(cumulative_vec.len());
|
||||
|
||||
let mut cumulative = if index > 0 {
|
||||
cumulative_vec.iter().get_unwrap((index - 1).into())
|
||||
} else {
|
||||
T::from(0_usize)
|
||||
};
|
||||
|
||||
let mut source_iter = height_source.iter();
|
||||
let mut count_iter = count_indexes.iter().skip(index);
|
||||
|
||||
first_indexes.iter().enumerate().skip(index).try_for_each(
|
||||
|(idx, first_height)| -> Result<()> {
|
||||
let count = *count_iter.next().unwrap() as usize;
|
||||
|
||||
source_iter.set_position(first_height);
|
||||
let sum: T = (&mut source_iter)
|
||||
.take(count)
|
||||
.fold(T::from(0_usize), |acc, v| acc + v);
|
||||
|
||||
cumulative += sum;
|
||||
sum_vec.truncate_push_at(idx, sum)?;
|
||||
cumulative_vec.truncate_push_at(idx, cumulative)?;
|
||||
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
let _lock = exit.lock();
|
||||
sum_vec.write()?;
|
||||
cumulative_vec.write()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
//! ComputedTxDistribution - computes TxIndex data to height Distribution + dateindex MinMaxAverage + lazy aggregations.
|
||||
//!
|
||||
//! Note: Percentiles are computed at height level only. DateIndex and coarser
|
||||
//! periods only have average+min+max since computing percentiles across all
|
||||
//! transactions per day would be expensive.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, DifficultyEpoch, Height, TxIndex, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{CollectableVec, Database, Exit, IterableCloneableVec};
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, indexes,
|
||||
internal::{
|
||||
ComputedVecValue, LazyPeriodsDistribution, Distribution, LazyDistribution, MinMaxAverage,
|
||||
NumericValue,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct DerivedTxDistribution<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub height: Distribution<Height, T>,
|
||||
pub difficultyepoch: LazyDistribution<DifficultyEpoch, T, Height, DifficultyEpoch>,
|
||||
pub dateindex: MinMaxAverage<DateIndex, T>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub dates: LazyPeriodsDistribution<T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> DerivedTxDistribution<T>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let height = Distribution::forced_import(db, name, version + VERSION)?;
|
||||
let dateindex = MinMaxAverage::forced_import(db, name, version + VERSION)?;
|
||||
let v = version + VERSION;
|
||||
|
||||
let difficultyepoch =
|
||||
LazyDistribution::<DifficultyEpoch, T, Height, DifficultyEpoch>::from_distribution(
|
||||
name,
|
||||
v,
|
||||
height.average.0.boxed_clone(),
|
||||
height.minmax.min.0.boxed_clone(),
|
||||
height.minmax.max.0.boxed_clone(),
|
||||
indexes.difficultyepoch.identity.boxed_clone(),
|
||||
);
|
||||
|
||||
let dates = LazyPeriodsDistribution::from_sources(
|
||||
name,
|
||||
v,
|
||||
dateindex.average.0.boxed_clone(),
|
||||
dateindex.minmax.min.0.boxed_clone(),
|
||||
dateindex.minmax.max.0.boxed_clone(),
|
||||
indexes,
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
height,
|
||||
difficultyepoch,
|
||||
dateindex,
|
||||
dates,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn derive_from(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
txindex_source: &impl CollectableVec<TxIndex, T>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.height.compute(
|
||||
starting_indexes.height,
|
||||
txindex_source,
|
||||
&indexer.vecs.transactions.first_txindex,
|
||||
&indexes.height.txindex_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.dateindex.compute(
|
||||
starting_indexes.dateindex,
|
||||
&self.height.average.0,
|
||||
&indexes.dateindex.first_height,
|
||||
&indexes.dateindex.height_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
106
crates/brk_computer/src/internal/multi/derived_tx/full.rs
Normal file
106
crates/brk_computer/src/internal/multi/derived_tx/full.rs
Normal file
@@ -0,0 +1,106 @@
|
||||
//! DerivedTxFull - aggregates from TxIndex to height Full + dateindex Stats + lazy date periods.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, DifficultyEpoch, Height, TxIndex, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{CollectableVec, Database, Exit, IterableCloneableVec};
|
||||
|
||||
use crate::{
|
||||
indexes, ComputeIndexes,
|
||||
internal::{ComputedVecValue, LazyPeriodsFull, Full, LazyFull, NumericValue, Stats},
|
||||
};
|
||||
|
||||
/// Aggregates from TxIndex to height/dateindex with full stats.
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct DerivedTxFull<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub height: Full<Height, T>,
|
||||
pub difficultyepoch: LazyFull<DifficultyEpoch, T, Height, DifficultyEpoch>,
|
||||
pub dateindex: Stats<DateIndex, T>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub dates: LazyPeriodsFull<T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> DerivedTxFull<T>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let height = Full::forced_import(db, name, version + VERSION)?;
|
||||
let dateindex = Stats::forced_import(db, name, version + VERSION)?;
|
||||
let v = version + VERSION;
|
||||
|
||||
let difficultyepoch =
|
||||
LazyFull::<DifficultyEpoch, T, Height, DifficultyEpoch>::from_stats_aggregate(
|
||||
name,
|
||||
v,
|
||||
height.distribution.average.0.boxed_clone(),
|
||||
height.distribution.minmax.min.0.boxed_clone(),
|
||||
height.distribution.minmax.max.0.boxed_clone(),
|
||||
height.sum_cum.sum.0.boxed_clone(),
|
||||
height.sum_cum.cumulative.0.boxed_clone(),
|
||||
indexes.difficultyepoch.identity.boxed_clone(),
|
||||
);
|
||||
|
||||
let dates = LazyPeriodsFull::from_sources(
|
||||
name,
|
||||
v,
|
||||
dateindex.average.0.boxed_clone(),
|
||||
dateindex.minmax.min.0.boxed_clone(),
|
||||
dateindex.minmax.max.0.boxed_clone(),
|
||||
dateindex.sum_cum.sum.0.boxed_clone(),
|
||||
dateindex.sum_cum.cumulative.0.boxed_clone(),
|
||||
indexes,
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
height,
|
||||
difficultyepoch,
|
||||
dateindex,
|
||||
dates,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn derive_from(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
txindex_source: &impl CollectableVec<TxIndex, T>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.height.compute(
|
||||
starting_indexes.height,
|
||||
txindex_source,
|
||||
&indexer.vecs.transactions.first_txindex,
|
||||
&indexes.height.txindex_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.dateindex.compute(
|
||||
starting_indexes.dateindex,
|
||||
&self.height.distribution.average.0,
|
||||
&indexes.dateindex.first_height,
|
||||
&indexes.dateindex.height_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
//! LazyTxDistribution - lazy txindex source + computed distribution.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{TxIndex, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{CollectableVec, Database, Exit, LazyVecFrom2};
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, indexes,
|
||||
internal::{ComputedVecValue, DerivedTxDistribution, NumericValue},
|
||||
};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyTxDistribution<T, S1, S2>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1: ComputedVecValue,
|
||||
S2: ComputedVecValue,
|
||||
{
|
||||
pub txindex: LazyVecFrom2<TxIndex, T, TxIndex, S1, TxIndex, S2>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub distribution: DerivedTxDistribution<T>,
|
||||
}
|
||||
|
||||
impl<T, S1, S2> LazyTxDistribution<T, S1, S2>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
S1: ComputedVecValue + JsonSchema,
|
||||
S2: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
txindex: LazyVecFrom2<TxIndex, T, TxIndex, S1, TxIndex, S2>,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
let distribution = DerivedTxDistribution::forced_import(db, name, v, indexes)?;
|
||||
Ok(Self {
|
||||
txindex,
|
||||
distribution,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn derive_from(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
LazyVecFrom2<TxIndex, T, TxIndex, S1, TxIndex, S2>: CollectableVec<TxIndex, T>,
|
||||
{
|
||||
self.distribution
|
||||
.derive_from(indexer, indexes, starting_indexes, &self.txindex, exit)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
//! Lazy transform of DerivedTxFull.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, SemesterIndex,
|
||||
Version, WeekIndex, YearIndex,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableCloneableVec, UnaryTransform};
|
||||
|
||||
use crate::internal::{ComputedVecValue, DerivedTxFull, LazyTransformFull, LazyTransformStats};
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyDerivedTxFull<T, S1T = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
{
|
||||
pub height: LazyTransformFull<Height, T, S1T>,
|
||||
pub difficultyepoch: LazyTransformStats<DifficultyEpoch, T, S1T>,
|
||||
pub dateindex: LazyTransformStats<DateIndex, T, S1T>,
|
||||
pub weekindex: LazyTransformStats<WeekIndex, T, S1T>,
|
||||
pub monthindex: LazyTransformStats<MonthIndex, T, S1T>,
|
||||
pub quarterindex: LazyTransformStats<QuarterIndex, T, S1T>,
|
||||
pub semesterindex: LazyTransformStats<SemesterIndex, T, S1T>,
|
||||
pub yearindex: LazyTransformStats<YearIndex, T, S1T>,
|
||||
pub decadeindex: LazyTransformStats<DecadeIndex, T, S1T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T, S1T> LazyDerivedTxFull<T, S1T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn from_computed<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source: &DerivedTxFull<S1T>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! period {
|
||||
($p:ident) => {
|
||||
LazyTransformStats::from_boxed::<F>(
|
||||
name, v,
|
||||
source.$p.average.boxed_clone(), source.$p.min.boxed_clone(),
|
||||
source.$p.max.boxed_clone(), source.$p.sum.boxed_clone(),
|
||||
source.$p.cumulative.boxed_clone(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
height: LazyTransformFull::from_stats_aggregate::<F>(name, v, &source.height),
|
||||
difficultyepoch: period!(difficultyepoch),
|
||||
dateindex: LazyTransformStats::from_boxed::<F>(
|
||||
name, v,
|
||||
source.dateindex.average.0.boxed_clone(),
|
||||
source.dateindex.minmax.min.0.boxed_clone(),
|
||||
source.dateindex.minmax.max.0.boxed_clone(),
|
||||
source.dateindex.sum_cum.sum.0.boxed_clone(),
|
||||
source.dateindex.sum_cum.cumulative.0.boxed_clone(),
|
||||
),
|
||||
weekindex: period!(weekindex),
|
||||
monthindex: period!(monthindex),
|
||||
quarterindex: period!(quarterindex),
|
||||
semesterindex: period!(semesterindex),
|
||||
yearindex: period!(yearindex),
|
||||
decadeindex: period!(decadeindex),
|
||||
}
|
||||
}
|
||||
}
|
||||
9
crates/brk_computer/src/internal/multi/derived_tx/mod.rs
Normal file
9
crates/brk_computer/src/internal/multi/derived_tx/mod.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
mod distribution;
|
||||
mod full;
|
||||
mod lazy_distribution;
|
||||
mod lazy_full;
|
||||
|
||||
pub use distribution::*;
|
||||
pub use full::*;
|
||||
pub use lazy_distribution::*;
|
||||
pub use lazy_full::*;
|
||||
60
crates/brk_computer/src/internal/multi/height/binary_full.rs
Normal file
60
crates/brk_computer/src/internal/multi/height/binary_full.rs
Normal file
@@ -0,0 +1,60 @@
|
||||
//! Lazy binary transform from Full sources.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{BinaryTransform, IterableBoxedVec, LazyVecFrom2};
|
||||
|
||||
use crate::internal::{
|
||||
ComputedBlockFull, ComputedVecValue, DerivedTxFull, LazyBinaryDerivedBlockSumCum, NumericValue,
|
||||
};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyBinaryBlockFull<T, S1T = T, S2T = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
S2T: ComputedVecValue,
|
||||
{
|
||||
#[traversable(wrap = "base")]
|
||||
pub height: LazyVecFrom2<Height, T, Height, S1T, Height, S2T>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub rest: LazyBinaryDerivedBlockSumCum<T, S1T, S2T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T, S1T, S2T> LazyBinaryBlockFull<T, S1T, S2T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: NumericValue + JsonSchema,
|
||||
S2T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub fn from_height_and_txindex<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
height_source1: IterableBoxedVec<Height, S1T>,
|
||||
height_source2: IterableBoxedVec<Height, S2T>,
|
||||
source1: &ComputedBlockFull<S1T>,
|
||||
source2: &DerivedTxFull<S2T>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
height: LazyVecFrom2::transformed::<F>(name, v, height_source1, height_source2),
|
||||
rest: LazyBinaryDerivedBlockSumCum::from_derived_full::<F, _, _, _, _>(
|
||||
name,
|
||||
v,
|
||||
&source1.dateindex.sum_cum,
|
||||
&source1.rest,
|
||||
&source1.difficultyepoch,
|
||||
&source2.dateindex.sum_cum,
|
||||
&source2.dates,
|
||||
&source2.difficultyepoch,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
//! LazyBinaryHeightDateLast - height storage + binary transform lazy date periods.
|
||||
//!
|
||||
//! Use this when height is stored as EagerVec and date periods are lazy binary transforms.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{BinaryTransform, EagerVec, PcoVec};
|
||||
|
||||
use crate::internal::{
|
||||
ComputedDateLast, ComputedHeightDateLast, ComputedVecValue, LazyBinaryDateLast,
|
||||
};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyBinaryHeightDateLast<T, S1T, S2T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
S2T: ComputedVecValue,
|
||||
{
|
||||
pub height: EagerVec<PcoVec<Height, T>>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub rest: LazyBinaryDateLast<T, S1T, S2T>,
|
||||
}
|
||||
|
||||
impl<T, S1T, S2T> LazyBinaryHeightDateLast<T, S1T, S2T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
S2T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn from_computed_both_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
height: EagerVec<PcoVec<Height, T>>,
|
||||
source1: &ComputedDateLast<S1T>,
|
||||
source2: &ComputedDateLast<S2T>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
height,
|
||||
rest: LazyBinaryDateLast::from_computed_both_last::<F>(name, v, source1, source2),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_computed_height_date_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
height: EagerVec<PcoVec<Height, T>>,
|
||||
source1: &ComputedHeightDateLast<S1T>,
|
||||
source2: &ComputedHeightDateLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: JsonSchema + 'static,
|
||||
S2T: JsonSchema + 'static,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
height,
|
||||
rest: LazyBinaryDateLast::from_computed_both_last::<F>(
|
||||
name,
|
||||
v,
|
||||
&source1.rest,
|
||||
&source2.rest,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
290
crates/brk_computer/src/internal/multi/height/binary_last.rs
Normal file
290
crates/brk_computer/src/internal/multi/height/binary_last.rs
Normal file
@@ -0,0 +1,290 @@
|
||||
//! Lazy binary transform from two SumCum sources, producing Last (cumulative) ratios only.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{BinaryTransform, IterableBoxedVec, IterableCloneableVec, LazyVecFrom2};
|
||||
|
||||
use crate::internal::{
|
||||
ComputedBlockLast, ComputedBlockSumCum, ComputedHeightDateLast, ComputedVecValue,
|
||||
LazyBinaryDateLast, LazyBinaryDerivedBlockLast, LazyBinaryTransformLast, LazyPeriodsLast,
|
||||
NumericValue,
|
||||
};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyBinaryBlockLast<T, S1T = T, S2T = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
S2T: ComputedVecValue,
|
||||
{
|
||||
pub height: LazyVecFrom2<Height, T, Height, S1T, Height, S2T>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub rest: LazyBinaryDerivedBlockLast<T, S1T, S2T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T, S1T, S2T> LazyBinaryBlockLast<T, S1T, S2T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
S2T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn from_computed_sum_cum<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedBlockSumCum<S1T>,
|
||||
source2: &ComputedBlockSumCum<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: PartialOrd,
|
||||
S2T: PartialOrd,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
height: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.height_cumulative.0.boxed_clone(),
|
||||
source2.height_cumulative.0.boxed_clone(),
|
||||
),
|
||||
rest: LazyBinaryDerivedBlockLast::from_computed_sum_cum::<F>(name, v, source1, source2),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_computed_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedBlockLast<S1T>,
|
||||
source2: &ComputedBlockLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
height: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.height.boxed_clone(),
|
||||
source2.height.boxed_clone(),
|
||||
),
|
||||
rest: LazyBinaryDerivedBlockLast::from_computed_last::<F>(name, v, source1, source2),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_computed_height_date_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedHeightDateLast<S1T>,
|
||||
source2: &ComputedHeightDateLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: PartialOrd,
|
||||
S2T: PartialOrd,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
height: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.height.boxed_clone(),
|
||||
source2.height.boxed_clone(),
|
||||
),
|
||||
rest: LazyBinaryDerivedBlockLast::from_computed_height_date_last::<F>(
|
||||
name, v, source1, source2,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create from a ComputedHeightDateLast and a LazyBinaryBlockLast.
|
||||
pub fn from_computed_height_date_and_binary_block<F, S2aT, S2bT>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedHeightDateLast<S1T>,
|
||||
source2: &LazyBinaryBlockLast<S2T, S2aT, S2bT>,
|
||||
) -> Self
|
||||
where
|
||||
F: BinaryTransform<S1T, S2T, T>,
|
||||
S1T: PartialOrd,
|
||||
S2aT: ComputedVecValue + JsonSchema,
|
||||
S2bT: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
height: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.height.boxed_clone(),
|
||||
source2.height.boxed_clone(),
|
||||
),
|
||||
rest: LazyBinaryDerivedBlockLast {
|
||||
dates: LazyBinaryDateLast::from_computed_and_binary_last::<F, _, _>(
|
||||
name,
|
||||
v,
|
||||
&source1.rest,
|
||||
&source2.rest.dates,
|
||||
),
|
||||
difficultyepoch: LazyBinaryTransformLast::from_vecs::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.difficultyepoch.0.boxed_clone(),
|
||||
source2.rest.difficultyepoch.boxed_clone(),
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Create from a ComputedHeightDateLast and a ComputedBlockLast.
|
||||
pub fn from_computed_height_date_and_block_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedHeightDateLast<S1T>,
|
||||
source2: &ComputedBlockLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: PartialOrd,
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
height: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.height.boxed_clone(),
|
||||
source2.height.boxed_clone(),
|
||||
),
|
||||
rest: LazyBinaryDerivedBlockLast::from_computed_height_date_and_block_last::<F>(
|
||||
name, v, source1, source2,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create from a LazyBinaryBlockLast and a ComputedBlockLast.
|
||||
pub fn from_binary_block_and_computed_block_last<F, S1aT, S1bT>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &LazyBinaryBlockLast<S1T, S1aT, S1bT>,
|
||||
source2: &ComputedBlockLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
F: BinaryTransform<S1T, S2T, T>,
|
||||
S1aT: ComputedVecValue + JsonSchema,
|
||||
S1bT: ComputedVecValue + JsonSchema,
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
height: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.height.boxed_clone(),
|
||||
source2.height.boxed_clone(),
|
||||
),
|
||||
rest: LazyBinaryDerivedBlockLast {
|
||||
dates: LazyBinaryDateLast::from_binary_and_block_last::<F, _, _>(
|
||||
name,
|
||||
v,
|
||||
&source1.rest.dates,
|
||||
source2,
|
||||
),
|
||||
difficultyepoch: LazyBinaryTransformLast::from_vecs::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.rest.difficultyepoch.boxed_clone(),
|
||||
source2.difficultyepoch.boxed_clone(),
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Create from two LazyBinaryBlockLast sources.
|
||||
pub fn from_both_binary_block<F, S1aT, S1bT, S2aT, S2bT>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &LazyBinaryBlockLast<S1T, S1aT, S1bT>,
|
||||
source2: &LazyBinaryBlockLast<S2T, S2aT, S2bT>,
|
||||
) -> Self
|
||||
where
|
||||
F: BinaryTransform<S1T, S2T, T>,
|
||||
S1aT: ComputedVecValue + JsonSchema,
|
||||
S1bT: ComputedVecValue + JsonSchema,
|
||||
S2aT: ComputedVecValue + JsonSchema,
|
||||
S2bT: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
height: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.height.boxed_clone(),
|
||||
source2.height.boxed_clone(),
|
||||
),
|
||||
rest: LazyBinaryDerivedBlockLast {
|
||||
dates: LazyBinaryDateLast::from_both_binary_last::<F, _, _, _, _>(
|
||||
name,
|
||||
v,
|
||||
&source1.rest.dates,
|
||||
&source2.rest.dates,
|
||||
),
|
||||
difficultyepoch: LazyBinaryTransformLast::from_vecs::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.rest.difficultyepoch.boxed_clone(),
|
||||
source2.rest.difficultyepoch.boxed_clone(),
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Create from separate height, difficultyepoch, and date sources.
|
||||
///
|
||||
/// Use when sources are split across different types (e.g., ValueHeightDateLast + ComputedBlockLast).
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn from_height_difficultyepoch_dates<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
height_source1: IterableBoxedVec<Height, S1T>,
|
||||
height_source2: IterableBoxedVec<Height, S2T>,
|
||||
difficultyepoch_source1: IterableBoxedVec<DifficultyEpoch, S1T>,
|
||||
difficultyepoch_source2: IterableBoxedVec<DifficultyEpoch, S2T>,
|
||||
dateindex_source1: IterableBoxedVec<DateIndex, S1T>,
|
||||
dates_source1: &LazyPeriodsLast<S1T>,
|
||||
dateindex_source2: IterableBoxedVec<DateIndex, S2T>,
|
||||
dates_source2: &LazyPeriodsLast<S2T>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
height: LazyVecFrom2::transformed::<F>(name, v, height_source1, height_source2),
|
||||
rest: LazyBinaryDerivedBlockLast {
|
||||
dates: LazyBinaryDateLast::from_both_derived_last::<F>(
|
||||
name,
|
||||
v,
|
||||
dateindex_source1,
|
||||
dates_source1,
|
||||
dateindex_source2,
|
||||
dates_source2,
|
||||
),
|
||||
difficultyepoch: LazyBinaryTransformLast::from_vecs::<F>(
|
||||
name,
|
||||
v,
|
||||
difficultyepoch_source1,
|
||||
difficultyepoch_source2,
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
71
crates/brk_computer/src/internal/multi/height/binary_sum.rs
Normal file
71
crates/brk_computer/src/internal/multi/height/binary_sum.rs
Normal file
@@ -0,0 +1,71 @@
|
||||
//! Lazy binary transform from two Sum-only sources with height level.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{BinaryTransform, IterableBoxedVec, IterableCloneableVec, LazyVecFrom2};
|
||||
|
||||
use crate::internal::{
|
||||
ComputedBlockSum, ComputedDerivedBlockSum, ComputedVecValue, LazyBinaryDerivedBlockSum,
|
||||
NumericValue,
|
||||
};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyBinaryBlockSum<T, S1T, S2T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
S2T: ComputedVecValue,
|
||||
{
|
||||
#[traversable(rename = "sum")]
|
||||
pub height: LazyVecFrom2<Height, T, Height, S1T, Height, S2T>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub rest: LazyBinaryDerivedBlockSum<T, S1T, S2T>,
|
||||
}
|
||||
|
||||
impl<T, S1T, S2T> LazyBinaryBlockSum<T, S1T, S2T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: NumericValue + JsonSchema,
|
||||
S2T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub fn from_derived<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
height_source1: IterableBoxedVec<Height, S1T>,
|
||||
height_source2: IterableBoxedVec<Height, S2T>,
|
||||
source1: &ComputedDerivedBlockSum<S1T>,
|
||||
source2: &ComputedDerivedBlockSum<S2T>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
height: LazyVecFrom2::transformed::<F>(name, v, height_source1, height_source2),
|
||||
rest: LazyBinaryDerivedBlockSum::from_derived::<F>(name, v, source1, source2),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_computed<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &ComputedBlockSum<S1T>,
|
||||
source2: &ComputedBlockSum<S2T>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
height: LazyVecFrom2::transformed::<F>(
|
||||
name,
|
||||
v,
|
||||
source1.height.boxed_clone(),
|
||||
source2.height.boxed_clone(),
|
||||
),
|
||||
rest: LazyBinaryDerivedBlockSum::from_derived::<F>(name, v, &source1.rest, &source2.rest),
|
||||
}
|
||||
}
|
||||
}
|
||||
210
crates/brk_computer/src/internal/multi/height/binary_sum_cum.rs
Normal file
210
crates/brk_computer/src/internal/multi/height/binary_sum_cum.rs
Normal file
@@ -0,0 +1,210 @@
|
||||
//! Lazy binary transform from two SumCum sources.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{BinaryTransform, IterableBoxedVec, IterableCloneableVec, LazyVecFrom2};
|
||||
|
||||
use crate::internal::{
|
||||
ComputedBlockLast, ComputedBlockSumCum, ComputedDerivedBlockLast, ComputedDerivedBlockSumCum,
|
||||
ComputedVecValue, LazyBinaryDerivedBlockSumCum, NumericValue,
|
||||
};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyBinaryBlockSumCum<T, S1T = T, S2T = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
S2T: ComputedVecValue,
|
||||
{
|
||||
#[traversable(rename = "sum")]
|
||||
pub height: LazyVecFrom2<Height, T, Height, S1T, Height, S2T>,
|
||||
#[traversable(rename = "cumulative")]
|
||||
pub height_cumulative: LazyVecFrom2<Height, T, Height, S1T, Height, S2T>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub rest: LazyBinaryDerivedBlockSumCum<T, S1T, S2T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T, S1T, S2T> LazyBinaryBlockSumCum<T, S1T, S2T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
S2T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn from_computed<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
height_source1: IterableBoxedVec<Height, S1T>,
|
||||
height_source2: IterableBoxedVec<Height, S2T>,
|
||||
source1: &ComputedBlockSumCum<S1T>,
|
||||
source2: &ComputedBlockSumCum<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: PartialOrd,
|
||||
S2T: PartialOrd,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
height: LazyVecFrom2::transformed::<F>(name, v, height_source1, height_source2),
|
||||
height_cumulative: LazyVecFrom2::transformed::<F>(
|
||||
&format!("{name}_cumulative"),
|
||||
v,
|
||||
source1.height_cumulative.0.boxed_clone(),
|
||||
source2.height_cumulative.0.boxed_clone(),
|
||||
),
|
||||
rest: LazyBinaryDerivedBlockSumCum::from_computed_sum_raw::<F>(
|
||||
name,
|
||||
v,
|
||||
&source1.dateindex,
|
||||
&source1.rest,
|
||||
&source1.difficultyepoch,
|
||||
&source2.dateindex,
|
||||
&source2.rest,
|
||||
&source2.difficultyepoch,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_derived<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
height_source1: IterableBoxedVec<Height, S1T>,
|
||||
height_source2: IterableBoxedVec<Height, S2T>,
|
||||
source1: &ComputedDerivedBlockSumCum<S1T>,
|
||||
source2: &ComputedDerivedBlockSumCum<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: PartialOrd,
|
||||
S2T: PartialOrd,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
Self {
|
||||
height: LazyVecFrom2::transformed::<F>(name, v, height_source1, height_source2),
|
||||
height_cumulative: LazyVecFrom2::transformed::<F>(
|
||||
&format!("{name}_cumulative"),
|
||||
v,
|
||||
source1.height_cumulative.0.boxed_clone(),
|
||||
source2.height_cumulative.0.boxed_clone(),
|
||||
),
|
||||
rest: LazyBinaryDerivedBlockSumCum::from_computed_sum_raw::<F>(
|
||||
name,
|
||||
v,
|
||||
&source1.dateindex,
|
||||
source1,
|
||||
&source1.difficultyepoch,
|
||||
&source2.dateindex,
|
||||
source2,
|
||||
&source2.difficultyepoch,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// --- Methods accepting SumCum + Last sources ---
|
||||
|
||||
pub fn from_computed_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
height_source1: IterableBoxedVec<Height, S1T>,
|
||||
height_source2: IterableBoxedVec<Height, S2T>,
|
||||
source1: &ComputedBlockSumCum<S1T>,
|
||||
source2: &ComputedBlockLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: PartialOrd,
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
Self {
|
||||
height: LazyVecFrom2::transformed::<F>(name, v, height_source1, height_source2),
|
||||
height_cumulative: LazyVecFrom2::transformed::<F>(
|
||||
&format!("{name}_cumulative"),
|
||||
v,
|
||||
source1.height_cumulative.0.boxed_clone(),
|
||||
source2.height.boxed_clone(),
|
||||
),
|
||||
rest: LazyBinaryDerivedBlockSumCum::from_computed_last::<F>(name, v, source1, source2),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_derived_computed_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
height_source1: IterableBoxedVec<Height, S1T>,
|
||||
height_source2: IterableBoxedVec<Height, S2T>,
|
||||
source1: &ComputedDerivedBlockSumCum<S1T>,
|
||||
source2: &ComputedBlockLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
Self {
|
||||
height: LazyVecFrom2::transformed::<F>(name, v, height_source1, height_source2),
|
||||
height_cumulative: LazyVecFrom2::transformed::<F>(
|
||||
&format!("{name}_cumulative"),
|
||||
v,
|
||||
source1.height_cumulative.0.boxed_clone(),
|
||||
source2.height.boxed_clone(),
|
||||
),
|
||||
rest: LazyBinaryDerivedBlockSumCum::from_derived_computed_last::<F>(name, v, source1, source2),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_derived_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
height_source1: IterableBoxedVec<Height, S1T>,
|
||||
height_source2: IterableBoxedVec<Height, S2T>,
|
||||
source1: &ComputedDerivedBlockSumCum<S1T>,
|
||||
source2: &ComputedDerivedBlockLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
Self {
|
||||
height: LazyVecFrom2::transformed::<F>(name, v, height_source1.clone(), height_source2.clone()),
|
||||
height_cumulative: LazyVecFrom2::transformed::<F>(
|
||||
&format!("{name}_cumulative"),
|
||||
v,
|
||||
source1.height_cumulative.0.boxed_clone(),
|
||||
height_source2,
|
||||
),
|
||||
rest: LazyBinaryDerivedBlockSumCum::from_derived_last::<F>(name, v, source1, source2),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_computed_derived_last<F: BinaryTransform<S1T, S2T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
height_source1: IterableBoxedVec<Height, S1T>,
|
||||
height_source2: IterableBoxedVec<Height, S2T>,
|
||||
source1: &ComputedBlockSumCum<S1T>,
|
||||
source2: &ComputedDerivedBlockLast<S2T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: PartialOrd,
|
||||
S2T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
Self {
|
||||
height: LazyVecFrom2::transformed::<F>(name, v, height_source1.clone(), height_source2.clone()),
|
||||
height_cumulative: LazyVecFrom2::transformed::<F>(
|
||||
&format!("{name}_cumulative"),
|
||||
v,
|
||||
source1.height_cumulative.0.boxed_clone(),
|
||||
height_source2,
|
||||
),
|
||||
rest: LazyBinaryDerivedBlockSumCum::from_computed_derived_last::<F>(name, v, source1, source2),
|
||||
}
|
||||
}
|
||||
}
|
||||
68
crates/brk_computer/src/internal/multi/height/full.rs
Normal file
68
crates/brk_computer/src/internal/multi/height/full.rs
Normal file
@@ -0,0 +1,68 @@
|
||||
//! ComputedBlock with full stats aggregation.
|
||||
|
||||
use brk_error::Result;
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
|
||||
|
||||
use crate::{ComputeIndexes, indexes};
|
||||
|
||||
use crate::internal::{ComputedVecValue, ComputedDerivedBlockFull, NumericValue};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ComputedBlockFull<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
#[traversable(wrap = "base")]
|
||||
pub height: EagerVec<PcoVec<Height, T>>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub rest: ComputedDerivedBlockFull<T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedBlockFull<T>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let height: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, v)?;
|
||||
|
||||
let rest = ComputedDerivedBlockFull::forced_import(
|
||||
db,
|
||||
name,
|
||||
height.boxed_clone(),
|
||||
v,
|
||||
indexes,
|
||||
)?;
|
||||
|
||||
Ok(Self { height, rest })
|
||||
}
|
||||
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
mut compute: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut EagerVec<PcoVec<Height, T>>) -> Result<()>,
|
||||
{
|
||||
compute(&mut self.height)?;
|
||||
self.rest.derive_from(indexes, starting_indexes, &self.height, exit)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
//! ComputedHeightDateBytes - height + dateindex BytesVec storage.
|
||||
//!
|
||||
//! Use this for simple cases where both height and dateindex are stored BytesVecs
|
||||
//! without any lazy derivations. For OHLC-type data.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, Height, Version};
|
||||
use schemars::JsonSchema;
|
||||
use serde::Serialize;
|
||||
use vecdb::{BytesVec, BytesVecValue, Database, Formattable, ImportableVec};
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ComputedHeightDateBytes<T>
|
||||
where
|
||||
T: BytesVecValue + Formattable + Serialize + JsonSchema,
|
||||
{
|
||||
pub height: BytesVec<Height, T>,
|
||||
pub dateindex: BytesVec<DateIndex, T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedHeightDateBytes<T>
|
||||
where
|
||||
T: BytesVecValue + Formattable + Serialize + JsonSchema + 'static,
|
||||
{
|
||||
pub fn forced_import(db: &Database, name: &str, version: Version) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
Ok(Self {
|
||||
height: BytesVec::forced_import(db, name, v)?,
|
||||
dateindex: BytesVec::forced_import(db, name, v)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
//! ComputedHeightDateFirst - height storage + dateindex storage + lazy periods.
|
||||
//!
|
||||
//! Use this when both height and dateindex are stored EagerVecs with first-value aggregation.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
|
||||
|
||||
use crate::{ComputeIndexes, indexes};
|
||||
|
||||
use crate::internal::{ComputedDateFirst, ComputedVecValue, LazyFirst};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ComputedHeightDateFirst<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub height: EagerVec<PcoVec<Height, T>>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub rest: ComputedDateFirst<T>,
|
||||
pub difficultyepoch: LazyFirst<DifficultyEpoch, T, Height, DifficultyEpoch>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedHeightDateFirst<T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let height: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, v)?;
|
||||
let rest = ComputedDateFirst::forced_import(db, name, v, indexes)?;
|
||||
let difficultyepoch = LazyFirst::from_source(
|
||||
name,
|
||||
v,
|
||||
height.boxed_clone(),
|
||||
indexes.difficultyepoch.identity.boxed_clone(),
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
height,
|
||||
rest,
|
||||
difficultyepoch,
|
||||
})
|
||||
}
|
||||
|
||||
/// Compute rest (dateindex + periods) with the given compute function.
|
||||
pub fn compute_rest<F>(
|
||||
&mut self,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
compute: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut EagerVec<PcoVec<DateIndex, T>>) -> Result<()>,
|
||||
{
|
||||
self.rest.compute_all(starting_indexes, exit, compute)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
//! ComputedHeightDateLast - height storage + dateindex storage + lazy periods.
|
||||
//!
|
||||
//! Use this when both height and dateindex are stored EagerVecs with last-value aggregation.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
|
||||
|
||||
use crate::{indexes, internal::ComputedDateLast, ComputeIndexes};
|
||||
|
||||
use crate::internal::{ComputedVecValue, LazyLast};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ComputedHeightDateLast<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub height: EagerVec<PcoVec<Height, T>>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub rest: ComputedDateLast<T>,
|
||||
pub difficultyepoch: LazyLast<DifficultyEpoch, T, Height, DifficultyEpoch>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedHeightDateLast<T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let height: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, v)?;
|
||||
let rest = ComputedDateLast::forced_import(db, name, v, indexes)?;
|
||||
let difficultyepoch = LazyLast::from_source(
|
||||
name,
|
||||
v,
|
||||
height.boxed_clone(),
|
||||
indexes.difficultyepoch.identity.boxed_clone(),
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
height,
|
||||
rest,
|
||||
difficultyepoch,
|
||||
})
|
||||
}
|
||||
|
||||
/// Compute rest (dateindex + periods) with the given compute function.
|
||||
pub fn compute_rest<F>(
|
||||
&mut self,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
compute: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut EagerVec<PcoVec<DateIndex, T>>) -> Result<()>,
|
||||
{
|
||||
self.rest.compute_all(starting_indexes, exit, compute)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
//! ComputedHeightDateMax - height storage + dateindex storage + lazy periods.
|
||||
//!
|
||||
//! Use this when both height and dateindex are stored EagerVecs with max-value aggregation.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
|
||||
|
||||
use crate::{ComputeIndexes, indexes};
|
||||
|
||||
use crate::internal::{ComputedDateMax, ComputedVecValue, LazyMax};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ComputedHeightDateMax<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub height: EagerVec<PcoVec<Height, T>>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub rest: ComputedDateMax<T>,
|
||||
pub difficultyepoch: LazyMax<DifficultyEpoch, T, Height, DifficultyEpoch>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedHeightDateMax<T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let height: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, v)?;
|
||||
let rest = ComputedDateMax::forced_import(db, name, v, indexes)?;
|
||||
let difficultyepoch = LazyMax::from_source(
|
||||
name,
|
||||
v,
|
||||
height.boxed_clone(),
|
||||
indexes.difficultyepoch.identity.boxed_clone(),
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
height,
|
||||
rest,
|
||||
difficultyepoch,
|
||||
})
|
||||
}
|
||||
|
||||
/// Compute rest (dateindex + periods) with the given compute function.
|
||||
pub fn compute_rest<F>(
|
||||
&mut self,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
compute: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut EagerVec<PcoVec<DateIndex, T>>) -> Result<()>,
|
||||
{
|
||||
self.rest.compute_all(starting_indexes, exit, compute)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
//! ComputedHeightDateMin - height storage + dateindex storage + lazy periods.
|
||||
//!
|
||||
//! Use this when both height and dateindex are stored EagerVecs with min-value aggregation.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
|
||||
|
||||
use crate::{ComputeIndexes, indexes};
|
||||
|
||||
use crate::internal::{ComputedDateMin, ComputedVecValue, LazyMin};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ComputedHeightDateMin<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub height: EagerVec<PcoVec<Height, T>>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub rest: ComputedDateMin<T>,
|
||||
pub difficultyepoch: LazyMin<DifficultyEpoch, T, Height, DifficultyEpoch>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedHeightDateMin<T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let height: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, v)?;
|
||||
let rest = ComputedDateMin::forced_import(db, name, v, indexes)?;
|
||||
let difficultyepoch = LazyMin::from_source(
|
||||
name,
|
||||
v,
|
||||
height.boxed_clone(),
|
||||
indexes.difficultyepoch.identity.boxed_clone(),
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
height,
|
||||
rest,
|
||||
difficultyepoch,
|
||||
})
|
||||
}
|
||||
|
||||
/// Compute rest (dateindex + periods) with the given compute function.
|
||||
pub fn compute_rest<F>(
|
||||
&mut self,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
compute: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut EagerVec<PcoVec<DateIndex, T>>) -> Result<()>,
|
||||
{
|
||||
self.rest.compute_all(starting_indexes, exit, compute)
|
||||
}
|
||||
}
|
||||
74
crates/brk_computer/src/internal/multi/height/last.rs
Normal file
74
crates/brk_computer/src/internal/multi/height/last.rs
Normal file
@@ -0,0 +1,74 @@
|
||||
//! ComputedBlock using only LastVec aggregation.
|
||||
|
||||
use brk_error::Result;
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
|
||||
|
||||
use crate::{ComputeIndexes, indexes};
|
||||
|
||||
use crate::internal::{ComputedVecValue, ComputedDerivedBlockLast, NumericValue};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ComputedBlockLast<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub height: EagerVec<PcoVec<Height, T>>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub rest: ComputedDerivedBlockLast<T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedBlockLast<T>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let height: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, v)?;
|
||||
|
||||
let rest =
|
||||
ComputedDerivedBlockLast::forced_import(db, name, height.boxed_clone(), v, indexes)?;
|
||||
|
||||
Ok(Self { height, rest })
|
||||
}
|
||||
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
mut compute: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut EagerVec<PcoVec<Height, T>>) -> Result<()>,
|
||||
{
|
||||
compute(&mut self.height)?;
|
||||
self.compute_rest(indexes, starting_indexes, exit)
|
||||
}
|
||||
|
||||
/// Compute rest from self.height (for stateful computation patterns).
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.rest
|
||||
.derive_from(indexes, starting_indexes, &self.height, exit)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
//! LazyBlockDistribution - lazy height + derived distribution (avg/min/max) for indexes.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{ComputeFrom1, Database, Exit, IterableCloneableVec, LazyVecFrom1, UnaryTransform};
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, indexes,
|
||||
internal::{ComputedVecValue, ComputedDerivedBlockDistribution, NumericValue},
|
||||
};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
/// Lazy height + derived distribution for indexes.
|
||||
///
|
||||
/// Height is a lazy transform from a source.
|
||||
/// Indexes (dateindex + periods + difficultyepoch) store distribution stats (avg/min/max).
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyBlockDistribution<T, S = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S: ComputedVecValue,
|
||||
{
|
||||
#[traversable(rename = "base")]
|
||||
pub height: LazyVecFrom1<Height, T, Height, S>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub rest: ComputedDerivedBlockDistribution<T>,
|
||||
}
|
||||
|
||||
impl<T, S> LazyBlockDistribution<T, S>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
S: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn forced_import<F: UnaryTransform<S, T>>(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
source: impl IterableCloneableVec<Height, S>,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let height = LazyVecFrom1::transformed::<F>(name, v, source.boxed_clone());
|
||||
|
||||
let rest = ComputedDerivedBlockDistribution::forced_import(
|
||||
db,
|
||||
name,
|
||||
height.boxed_clone(),
|
||||
v,
|
||||
indexes,
|
||||
)?;
|
||||
|
||||
Ok(Self { height, rest })
|
||||
}
|
||||
|
||||
pub fn forced_import_with_init(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
source: impl IterableCloneableVec<Height, S>,
|
||||
indexes: &indexes::Vecs,
|
||||
init_fn: ComputeFrom1<Height, T, Height, S>,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let height = LazyVecFrom1::init(name, v, source.boxed_clone(), init_fn);
|
||||
|
||||
let rest = ComputedDerivedBlockDistribution::forced_import(
|
||||
db,
|
||||
name,
|
||||
height.boxed_clone(),
|
||||
v,
|
||||
indexes,
|
||||
)?;
|
||||
|
||||
Ok(Self { height, rest })
|
||||
}
|
||||
|
||||
pub fn derive_from(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.rest
|
||||
.derive_from(indexes, starting_indexes, &self.height, exit)
|
||||
}
|
||||
}
|
||||
68
crates/brk_computer/src/internal/multi/height/lazy_full.rs
Normal file
68
crates/brk_computer/src/internal/multi/height/lazy_full.rs
Normal file
@@ -0,0 +1,68 @@
|
||||
//! Lazy unary transform from height with Full aggregation.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableBoxedVec, LazyVecFrom1, UnaryTransform};
|
||||
|
||||
use crate::internal::{
|
||||
ComputedBlockFull, ComputedDerivedBlockFull, ComputedVecValue, LazyDerivedBlockFull,
|
||||
NumericValue,
|
||||
};
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyBlockFull<T, S1T = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
{
|
||||
#[traversable(wrap = "base")]
|
||||
pub height: LazyVecFrom1<Height, T, Height, S1T>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub rest: LazyDerivedBlockFull<T, S1T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T, S1T> LazyBlockFull<T, S1T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn from_computed<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
height_source: IterableBoxedVec<Height, S1T>,
|
||||
source: &ComputedBlockFull<S1T>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
Self {
|
||||
height: LazyVecFrom1::transformed::<F>(name, v, height_source),
|
||||
rest: LazyDerivedBlockFull::from_computed::<F>(
|
||||
name,
|
||||
v,
|
||||
&source.dateindex,
|
||||
&source.rest,
|
||||
&source.difficultyepoch,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_derived<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
height_source: IterableBoxedVec<Height, S1T>,
|
||||
source: &ComputedDerivedBlockFull<S1T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
Self {
|
||||
height: LazyVecFrom1::transformed::<F>(name, v, height_source),
|
||||
rest: LazyDerivedBlockFull::from_derived_computed::<F>(name, v, source),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
//! LazyBlockFullHeight - block full with lazy height transform.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, Exit, IterableCloneableVec, LazyVecFrom1, UnaryTransform};
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, indexes,
|
||||
internal::{ComputedVecValue, ComputedDerivedBlockFull, NumericValue},
|
||||
};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
/// Block full aggregation with lazy height transform + computed derived indexes.
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyBlockFullHeight<T, S = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S: ComputedVecValue,
|
||||
{
|
||||
#[traversable(rename = "base")]
|
||||
pub height: LazyVecFrom1<Height, T, Height, S>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub rest: ComputedDerivedBlockFull<T>,
|
||||
}
|
||||
|
||||
impl<T, S> LazyBlockFullHeight<T, S>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
S: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn forced_import<F: UnaryTransform<S, T>>(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
source: impl IterableCloneableVec<Height, S>,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let height = LazyVecFrom1::transformed::<F>(name, v, source.boxed_clone());
|
||||
|
||||
let rest =
|
||||
ComputedDerivedBlockFull::forced_import(db, name, height.boxed_clone(), v, indexes)?;
|
||||
|
||||
Ok(Self { height, rest })
|
||||
}
|
||||
|
||||
pub fn forced_import_with_init(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
source: impl IterableCloneableVec<Height, S>,
|
||||
indexes: &indexes::Vecs,
|
||||
init_fn: vecdb::ComputeFrom1<Height, T, Height, S>,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let height = LazyVecFrom1::init(name, v, source.boxed_clone(), init_fn);
|
||||
|
||||
let rest =
|
||||
ComputedDerivedBlockFull::forced_import(db, name, height.boxed_clone(), v, indexes)?;
|
||||
|
||||
Ok(Self { height, rest })
|
||||
}
|
||||
|
||||
pub fn derive_from(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.rest
|
||||
.derive_from(indexes, starting_indexes, &self.height, exit)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
//! LazyBlockSumCumHeight - block sum+cumulative with lazy height transform.
|
||||
//!
|
||||
//! Use this when you need:
|
||||
//! - Lazy height (binary transform from two sources)
|
||||
//! - Stored cumulative and dateindex aggregates
|
||||
//! - Lazy coarser period lookups
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, Exit, IterableCloneableVec, LazyVecFrom2};
|
||||
|
||||
use crate::{indexes, ComputeIndexes};
|
||||
|
||||
use crate::internal::{ComputedVecValue, ComputedDerivedBlockSumCum, NumericValue};
|
||||
|
||||
/// Block sum+cumulative with lazy binary height transform + computed derived indexes.
|
||||
///
|
||||
/// Height is a lazy binary transform (e.g., mask × source, or price × sats).
|
||||
/// Cumulative and dateindex are stored (computed from lazy height).
|
||||
/// Coarser periods are lazy lookups.
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyBlockSumCumHeight<T, S1T = T, S2T = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
S2T: ComputedVecValue,
|
||||
{
|
||||
#[traversable(rename = "sum")]
|
||||
pub height: LazyVecFrom2<Height, T, Height, S1T, Height, S2T>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub rest: ComputedDerivedBlockSumCum<T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T, S1T, S2T> LazyBlockSumCumHeight<T, S1T, S2T>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
S2T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
height: LazyVecFrom2<Height, T, Height, S1T, Height, S2T>,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let rest = ComputedDerivedBlockSumCum::forced_import(
|
||||
db,
|
||||
name,
|
||||
height.boxed_clone(),
|
||||
v,
|
||||
indexes,
|
||||
)?;
|
||||
|
||||
Ok(Self { height, rest })
|
||||
}
|
||||
|
||||
/// Derive aggregates from the lazy height source.
|
||||
pub fn derive_from(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.rest
|
||||
.derive_from(indexes, starting_indexes, &self.height, exit)
|
||||
}
|
||||
}
|
||||
79
crates/brk_computer/src/internal/multi/height/lazy_last.rs
Normal file
79
crates/brk_computer/src/internal/multi/height/lazy_last.rs
Normal file
@@ -0,0 +1,79 @@
|
||||
//! Lazy unary transform from height with Last aggregation.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableBoxedVec, IterableCloneableVec, LazyVecFrom1, UnaryTransform};
|
||||
|
||||
use crate::internal::{
|
||||
ComputedBlockLast, ComputedDerivedBlockLast, ComputedHeightDateLast, ComputedVecValue,
|
||||
LazyDerivedBlockLast, NumericValue,
|
||||
};
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyBlockLast<T, S1T = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
{
|
||||
pub height: LazyVecFrom1<Height, T, Height, S1T>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub rest: LazyDerivedBlockLast<T, S1T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T, S1T> LazyBlockLast<T, S1T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn from_computed<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
height_source: IterableBoxedVec<Height, S1T>,
|
||||
source: &ComputedBlockLast<S1T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
Self {
|
||||
height: LazyVecFrom1::transformed::<F>(name, v, height_source),
|
||||
rest: LazyDerivedBlockLast::from_computed::<F>(name, v, source),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_derived<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
height_source: IterableBoxedVec<Height, S1T>,
|
||||
source: &ComputedDerivedBlockLast<S1T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
Self {
|
||||
height: LazyVecFrom1::transformed::<F>(name, v, height_source),
|
||||
rest: LazyDerivedBlockLast::from_derived_computed::<F>(name, v, source),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_computed_height_date<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source: &ComputedHeightDateLast<S1T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: PartialOrd,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
Self {
|
||||
height: LazyVecFrom1::transformed::<F>(name, v, source.height.boxed_clone()),
|
||||
rest: LazyDerivedBlockLast::from_computed_height_date::<F>(name, v, source),
|
||||
}
|
||||
}
|
||||
}
|
||||
67
crates/brk_computer/src/internal/multi/height/lazy_sum.rs
Normal file
67
crates/brk_computer/src/internal/multi/height/lazy_sum.rs
Normal file
@@ -0,0 +1,67 @@
|
||||
//! Lazy unary transform from height with Sum aggregation.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableBoxedVec, LazyVecFrom1, UnaryTransform};
|
||||
|
||||
use crate::internal::{
|
||||
ComputedBlockSum, ComputedDerivedBlockSum, ComputedVecValue, LazyDerivedBlockSum, NumericValue,
|
||||
};
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyBlockSum<T, S1T = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
{
|
||||
pub height: LazyVecFrom1<Height, T, Height, S1T>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub rest: LazyDerivedBlockSum<T, S1T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T, S1T> LazyBlockSum<T, S1T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn from_computed<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
height_source: IterableBoxedVec<Height, S1T>,
|
||||
source: &ComputedBlockSum<S1T>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
Self {
|
||||
height: LazyVecFrom1::transformed::<F>(name, v, height_source),
|
||||
rest: LazyDerivedBlockSum::from_computed::<F>(
|
||||
name,
|
||||
v,
|
||||
&source.dateindex,
|
||||
&source.rest,
|
||||
&source.difficultyepoch,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_derived<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
height_source: IterableBoxedVec<Height, S1T>,
|
||||
source: &ComputedDerivedBlockSum<S1T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
Self {
|
||||
height: LazyVecFrom1::transformed::<F>(name, v, height_source),
|
||||
rest: LazyDerivedBlockSum::from_derived_computed::<F>(name, v, source),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
//! Lazy unary transform from height with SumCum aggregation.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{IterableBoxedVec, LazyVecFrom1, UnaryTransform};
|
||||
|
||||
use crate::internal::{
|
||||
ComputedBlockSumCum, ComputedDerivedBlockSumCum, ComputedVecValue, LazyDerivedBlockSumCum,
|
||||
NumericValue,
|
||||
};
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyBlockSumCum<T, S1T = T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
{
|
||||
#[traversable(rename = "sum")]
|
||||
pub height: LazyVecFrom1<Height, T, Height, S1T>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub rest: LazyDerivedBlockSumCum<T, S1T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T, S1T> LazyBlockSumCum<T, S1T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn from_computed<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
height_source: IterableBoxedVec<Height, S1T>,
|
||||
source: &ComputedBlockSumCum<S1T>,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
Self {
|
||||
height: LazyVecFrom1::transformed::<F>(name, v, height_source),
|
||||
rest: LazyDerivedBlockSumCum::from_computed::<F>(
|
||||
name,
|
||||
v,
|
||||
&source.dateindex,
|
||||
&source.rest,
|
||||
&source.difficultyepoch,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_derived<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
height_source: IterableBoxedVec<Height, S1T>,
|
||||
source: &ComputedDerivedBlockSumCum<S1T>,
|
||||
) -> Self
|
||||
where
|
||||
S1T: NumericValue,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
Self {
|
||||
height: LazyVecFrom1::transformed::<F>(name, v, height_source),
|
||||
rest: LazyDerivedBlockSumCum::from_derived_computed::<F>(name, v, source),
|
||||
}
|
||||
}
|
||||
}
|
||||
43
crates/brk_computer/src/internal/multi/height/mod.rs
Normal file
43
crates/brk_computer/src/internal/multi/height/mod.rs
Normal file
@@ -0,0 +1,43 @@
|
||||
mod binary_full;
|
||||
mod binary_height_date_last;
|
||||
mod binary_last;
|
||||
mod binary_sum;
|
||||
mod binary_sum_cum;
|
||||
mod full;
|
||||
mod height_date_bytes;
|
||||
mod height_date_first;
|
||||
mod height_date_last;
|
||||
mod height_date_max;
|
||||
mod height_date_min;
|
||||
mod last;
|
||||
mod lazy_distribution;
|
||||
mod lazy_full;
|
||||
mod lazy_height_full;
|
||||
mod lazy_height_sum_cum;
|
||||
mod lazy_last;
|
||||
mod lazy_sum;
|
||||
mod lazy_sum_cum;
|
||||
mod sum;
|
||||
mod sum_cum;
|
||||
|
||||
pub use binary_full::*;
|
||||
pub use binary_height_date_last::*;
|
||||
pub use binary_last::*;
|
||||
pub use binary_sum::*;
|
||||
pub use binary_sum_cum::*;
|
||||
pub use full::*;
|
||||
pub use height_date_bytes::*;
|
||||
pub use height_date_first::*;
|
||||
pub use height_date_last::*;
|
||||
pub use height_date_max::*;
|
||||
pub use height_date_min::*;
|
||||
pub use last::*;
|
||||
pub use lazy_distribution::*;
|
||||
pub use lazy_full::*;
|
||||
pub use lazy_height_full::*;
|
||||
pub use lazy_height_sum_cum::*;
|
||||
pub use lazy_last::*;
|
||||
pub use lazy_sum::*;
|
||||
pub use lazy_sum_cum::*;
|
||||
pub use sum::*;
|
||||
pub use sum_cum::*;
|
||||
74
crates/brk_computer/src/internal/multi/height/sum.rs
Normal file
74
crates/brk_computer/src/internal/multi/height/sum.rs
Normal file
@@ -0,0 +1,74 @@
|
||||
//! ComputedBlock using Sum-only aggregation.
|
||||
|
||||
use brk_error::Result;
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
|
||||
|
||||
use crate::{ComputeIndexes, indexes};
|
||||
|
||||
use crate::internal::{ComputedVecValue, ComputedDerivedBlockSum, NumericValue};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ComputedBlockSum<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub height: EagerVec<PcoVec<Height, T>>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub rest: ComputedDerivedBlockSum<T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedBlockSum<T>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let height: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, v)?;
|
||||
|
||||
let rest =
|
||||
ComputedDerivedBlockSum::forced_import(db, name, height.boxed_clone(), v, indexes)?;
|
||||
|
||||
Ok(Self { height, rest })
|
||||
}
|
||||
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
mut compute: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut EagerVec<PcoVec<Height, T>>) -> Result<()>,
|
||||
{
|
||||
compute(&mut self.height)?;
|
||||
self.compute_rest(indexes, starting_indexes, exit)
|
||||
}
|
||||
|
||||
/// Compute rest from self.height (for stateful computation patterns).
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.rest
|
||||
.derive_from(indexes, starting_indexes, &self.height, exit)
|
||||
}
|
||||
}
|
||||
106
crates/brk_computer/src/internal/multi/height/sum_cum.rs
Normal file
106
crates/brk_computer/src/internal/multi/height/sum_cum.rs
Normal file
@@ -0,0 +1,106 @@
|
||||
//! ComputedBlock using SumCum aggregation.
|
||||
|
||||
use brk_error::Result;
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{
|
||||
AnyStoredVec, AnyVec, Database, EagerVec, Exit, GenericStoredVec, ImportableVec,
|
||||
IterableCloneableVec, IterableVec, PcoVec, VecIndex,
|
||||
};
|
||||
|
||||
use crate::{indexes, ComputeIndexes};
|
||||
|
||||
use crate::internal::{ComputedVecValue, ComputedDerivedBlockSumCum, NumericValue};
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ComputedBlockSumCum<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
#[traversable(rename = "sum")]
|
||||
pub height: EagerVec<PcoVec<Height, T>>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub rest: ComputedDerivedBlockSumCum<T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedBlockSumCum<T>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let height: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, v)?;
|
||||
|
||||
let rest = ComputedDerivedBlockSumCum::forced_import(
|
||||
db,
|
||||
name,
|
||||
height.boxed_clone(),
|
||||
v,
|
||||
indexes,
|
||||
)?;
|
||||
|
||||
Ok(Self { height, rest })
|
||||
}
|
||||
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
mut compute: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut EagerVec<PcoVec<Height, T>>) -> Result<()>,
|
||||
{
|
||||
compute(&mut self.height)?;
|
||||
self.compute_rest(indexes, starting_indexes, exit)
|
||||
}
|
||||
|
||||
/// Compute rest from self.height (for stateful computation patterns).
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.rest.derive_from(indexes, starting_indexes, &self.height, exit)
|
||||
}
|
||||
|
||||
/// Derive from an external height source (e.g., a LazyVec).
|
||||
pub fn derive_from(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
source: &impl IterableVec<Height, T>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let target_len = source.len();
|
||||
let starting_height = starting_indexes.height.to_usize().min(self.height.len());
|
||||
|
||||
self.height
|
||||
.validate_computed_version_or_reset(source.version())?;
|
||||
|
||||
let mut source_iter = source.iter();
|
||||
for h_idx in starting_height..target_len {
|
||||
let height = Height::from(h_idx);
|
||||
let value = source_iter.get_unwrap(height);
|
||||
self.height.truncate_push(height, value)?;
|
||||
}
|
||||
self.height.write()?;
|
||||
|
||||
self.rest.derive_from(indexes, starting_indexes, &self.height, exit)
|
||||
}
|
||||
}
|
||||
17
crates/brk_computer/src/internal/multi/mod.rs
Normal file
17
crates/brk_computer/src/internal/multi/mod.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
//! Multi-index composite types.
|
||||
|
||||
mod date;
|
||||
mod derived_date;
|
||||
mod derived_height;
|
||||
mod derived_tx;
|
||||
mod height;
|
||||
mod specialized;
|
||||
mod value;
|
||||
|
||||
pub use date::*;
|
||||
pub use derived_date::*;
|
||||
pub use derived_height::*;
|
||||
pub use derived_tx::*;
|
||||
pub use height::*;
|
||||
pub use specialized::*;
|
||||
pub use value::*;
|
||||
@@ -0,0 +1,87 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
DateIndex, DecadeIndex, Height, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex,
|
||||
YearIndex,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use serde::Serialize;
|
||||
use vecdb::{Formattable, IterableCloneableVec, LazyVecFrom1, UnaryTransform, VecValue};
|
||||
|
||||
use crate::indexes;
|
||||
|
||||
/// Lazy constant vecs for all index levels.
|
||||
/// Uses const generic transforms to return the same value for every index.
|
||||
#[derive(Clone, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ConstantVecs<T>
|
||||
where
|
||||
T: VecValue + Formattable + Serialize + JsonSchema,
|
||||
{
|
||||
pub height: LazyVecFrom1<Height, T, Height, Height>,
|
||||
pub dateindex: LazyVecFrom1<DateIndex, T, DateIndex, DateIndex>,
|
||||
pub weekindex: LazyVecFrom1<WeekIndex, T, WeekIndex, WeekIndex>,
|
||||
pub monthindex: LazyVecFrom1<MonthIndex, T, MonthIndex, MonthIndex>,
|
||||
pub quarterindex: LazyVecFrom1<QuarterIndex, T, QuarterIndex, QuarterIndex>,
|
||||
pub semesterindex: LazyVecFrom1<SemesterIndex, T, SemesterIndex, SemesterIndex>,
|
||||
pub yearindex: LazyVecFrom1<YearIndex, T, YearIndex, YearIndex>,
|
||||
pub decadeindex: LazyVecFrom1<DecadeIndex, T, DecadeIndex, DecadeIndex>,
|
||||
}
|
||||
|
||||
impl<T: VecValue + Formattable + Serialize + JsonSchema> ConstantVecs<T> {
|
||||
/// Create constant vecs using a transform that ignores input and returns a constant.
|
||||
pub fn new<F>(name: &str, version: Version, indexes: &indexes::Vecs) -> Self
|
||||
where
|
||||
F: UnaryTransform<Height, T>
|
||||
+ UnaryTransform<DateIndex, T>
|
||||
+ UnaryTransform<WeekIndex, T>
|
||||
+ UnaryTransform<MonthIndex, T>
|
||||
+ UnaryTransform<QuarterIndex, T>
|
||||
+ UnaryTransform<SemesterIndex, T>
|
||||
+ UnaryTransform<YearIndex, T>
|
||||
+ UnaryTransform<DecadeIndex, T>,
|
||||
{
|
||||
Self {
|
||||
height: LazyVecFrom1::transformed::<F>(
|
||||
name,
|
||||
version,
|
||||
indexes.height.identity.boxed_clone(),
|
||||
),
|
||||
dateindex: LazyVecFrom1::transformed::<F>(
|
||||
name,
|
||||
version,
|
||||
indexes.dateindex.identity.boxed_clone(),
|
||||
),
|
||||
weekindex: LazyVecFrom1::transformed::<F>(
|
||||
name,
|
||||
version,
|
||||
indexes.weekindex.identity.boxed_clone(),
|
||||
),
|
||||
monthindex: LazyVecFrom1::transformed::<F>(
|
||||
name,
|
||||
version,
|
||||
indexes.monthindex.identity.boxed_clone(),
|
||||
),
|
||||
quarterindex: LazyVecFrom1::transformed::<F>(
|
||||
name,
|
||||
version,
|
||||
indexes.quarterindex.identity.boxed_clone(),
|
||||
),
|
||||
semesterindex: LazyVecFrom1::transformed::<F>(
|
||||
name,
|
||||
version,
|
||||
indexes.semesterindex.identity.boxed_clone(),
|
||||
),
|
||||
yearindex: LazyVecFrom1::transformed::<F>(
|
||||
name,
|
||||
version,
|
||||
indexes.yearindex.identity.boxed_clone(),
|
||||
),
|
||||
decadeindex: LazyVecFrom1::transformed::<F>(
|
||||
name,
|
||||
version,
|
||||
indexes.decadeindex.identity.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
11
crates/brk_computer/src/internal/multi/specialized/mod.rs
Normal file
11
crates/brk_computer/src/internal/multi/specialized/mod.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
mod constant;
|
||||
mod ohlc;
|
||||
mod percentiles;
|
||||
mod ratio;
|
||||
mod stddev;
|
||||
|
||||
pub use constant::*;
|
||||
pub use ohlc::*;
|
||||
pub use percentiles::*;
|
||||
pub use ratio::*;
|
||||
pub use stddev::*;
|
||||
@@ -0,0 +1,68 @@
|
||||
//! OHLC computed aggregations combining height, dateindex, and period indexes.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Close, High, Low, Open, Version};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::Database;
|
||||
|
||||
use crate::indexes;
|
||||
use crate::internal::{
|
||||
ComputedHeightDateFirst, ComputedHeightDateLast, ComputedHeightDateMax, ComputedHeightDateMin,
|
||||
ComputedVecValue,
|
||||
};
|
||||
|
||||
/// Combined OHLC computed vecs with all indexes (height + dateindex + periods + difficultyepoch).
|
||||
///
|
||||
/// Access pattern: `ohlc.{open,high,low,close}.{height,dateindex,weekindex,...,difficultyepoch}`
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct OHLCComputedVecs<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema + From<f64>,
|
||||
f64: From<T>,
|
||||
{
|
||||
pub open: ComputedHeightDateFirst<Open<T>>,
|
||||
pub high: ComputedHeightDateMax<High<T>>,
|
||||
pub low: ComputedHeightDateMin<Low<T>>,
|
||||
pub close: ComputedHeightDateLast<Close<T>>,
|
||||
}
|
||||
|
||||
impl<T> OHLCComputedVecs<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema + From<f64> + 'static,
|
||||
f64: From<T>,
|
||||
{
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
open: ComputedHeightDateFirst::forced_import(
|
||||
db,
|
||||
&format!("{name}_open"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
high: ComputedHeightDateMax::forced_import(
|
||||
db,
|
||||
&format!("{name}_high"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
low: ComputedHeightDateMin::forced_import(
|
||||
db,
|
||||
&format!("{name}_low"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
close: ComputedHeightDateLast::forced_import(
|
||||
db,
|
||||
&format!("{name}_close"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
//! Lazy OHLC component extractors for height + dateindex.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Close, DateIndex, Height, High, Low, Open};
|
||||
use schemars::JsonSchema;
|
||||
use serde::Serialize;
|
||||
use vecdb::{BytesVecValue, Formattable, LazyVecFrom1, VecIndex};
|
||||
|
||||
/// Lazy OHLC component extractors for a single index type.
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct LazyOHLC<I, T, SourceT>
|
||||
where
|
||||
I: VecIndex + BytesVecValue + Formattable + Serialize + JsonSchema + 'static,
|
||||
T: BytesVecValue + Formattable + Serialize + JsonSchema + 'static,
|
||||
SourceT: BytesVecValue + Formattable + Serialize + JsonSchema + 'static,
|
||||
{
|
||||
pub open: LazyVecFrom1<I, Open<T>, I, SourceT>,
|
||||
pub high: LazyVecFrom1<I, High<T>, I, SourceT>,
|
||||
pub low: LazyVecFrom1<I, Low<T>, I, SourceT>,
|
||||
pub close: LazyVecFrom1<I, Close<T>, I, SourceT>,
|
||||
}
|
||||
|
||||
/// Lazy OHLC component extractors for height + dateindex.
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct LazyHeightDateOHLC<T, SourceT>
|
||||
where
|
||||
T: BytesVecValue + Formattable + Serialize + JsonSchema + 'static,
|
||||
SourceT: BytesVecValue + Formattable + Serialize + JsonSchema + 'static,
|
||||
{
|
||||
pub height: LazyOHLC<Height, T, SourceT>,
|
||||
pub dateindex: LazyOHLC<DateIndex, T, SourceT>,
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
mod computed;
|
||||
mod lazy;
|
||||
mod period;
|
||||
|
||||
pub use computed::*;
|
||||
pub use lazy::*;
|
||||
pub use period::*;
|
||||
@@ -0,0 +1,29 @@
|
||||
//! OHLC period groupings for all time/chain periods.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, SemesterIndex,
|
||||
WeekIndex, YearIndex,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use serde::Serialize;
|
||||
use vecdb::{BytesVec, BytesVecValue, EagerVec, Formattable};
|
||||
|
||||
/// Bundled OHLC vecs for all periods (time + chain based).
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct OHLCPeriodVecs<T>
|
||||
where
|
||||
T: BytesVecValue + Formattable + Serialize + JsonSchema + 'static,
|
||||
{
|
||||
// Time-based periods
|
||||
pub dateindex: EagerVec<BytesVec<DateIndex, T>>,
|
||||
pub week: EagerVec<BytesVec<WeekIndex, T>>,
|
||||
pub month: EagerVec<BytesVec<MonthIndex, T>>,
|
||||
pub quarter: EagerVec<BytesVec<QuarterIndex, T>>,
|
||||
pub semester: EagerVec<BytesVec<SemesterIndex, T>>,
|
||||
pub year: EagerVec<BytesVec<YearIndex, T>>,
|
||||
pub decade: EagerVec<BytesVec<DecadeIndex, T>>,
|
||||
// Chain-based periods
|
||||
pub height: EagerVec<BytesVec<Height, T>>,
|
||||
pub difficultyepoch: EagerVec<BytesVec<DifficultyEpoch, T>>,
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::{Traversable, TreeNode};
|
||||
use brk_types::{DateIndex, Dollars, Version};
|
||||
use rayon::prelude::*;
|
||||
use vecdb::{
|
||||
AnyExportableVec, AnyStoredVec, AnyVec, Database, EagerVec, Exit, GenericStoredVec, PcoVec,
|
||||
};
|
||||
|
||||
use crate::{ComputeIndexes, indexes};
|
||||
|
||||
use super::super::ComputedDateLast;
|
||||
|
||||
pub const PERCENTILES: [u8; 19] = [
|
||||
5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95,
|
||||
];
|
||||
pub const PERCENTILES_LEN: usize = PERCENTILES.len();
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CostBasisPercentiles {
|
||||
pub vecs: [Option<ComputedDateLast<Dollars>>; PERCENTILES_LEN],
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl CostBasisPercentiles {
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
compute: bool,
|
||||
) -> Result<Self> {
|
||||
let vecs = PERCENTILES.map(|p| {
|
||||
compute.then(|| {
|
||||
let metric_name = if name.is_empty() {
|
||||
format!("cost_basis_pct{p:02}")
|
||||
} else {
|
||||
format!("{name}_cost_basis_pct{p:02}")
|
||||
};
|
||||
ComputedDateLast::forced_import(db, &metric_name, version + VERSION, indexes)
|
||||
.unwrap()
|
||||
})
|
||||
});
|
||||
|
||||
Ok(Self { vecs })
|
||||
}
|
||||
|
||||
/// Get minimum length across dateindex-indexed vectors written in block loop.
|
||||
pub fn min_stateful_dateindex_len(&self) -> usize {
|
||||
self.vecs
|
||||
.iter()
|
||||
.filter_map(|v| v.as_ref())
|
||||
.map(|v| v.dateindex.len())
|
||||
.min()
|
||||
.unwrap_or(usize::MAX)
|
||||
}
|
||||
|
||||
/// Push percentile prices at date boundary.
|
||||
/// Only called when dateindex is Some (last height of the day).
|
||||
pub fn truncate_push(
|
||||
&mut self,
|
||||
dateindex: DateIndex,
|
||||
percentile_prices: &[Dollars; PERCENTILES_LEN],
|
||||
) -> Result<()> {
|
||||
for (i, vec) in self.vecs.iter_mut().enumerate() {
|
||||
if let Some(v) = vec {
|
||||
v.dateindex.truncate_push(dateindex, percentile_prices[i])?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn compute_rest(&mut self, starting_indexes: &ComputeIndexes, exit: &Exit) -> Result<()> {
|
||||
for vec in self.vecs.iter_mut().flatten() {
|
||||
vec.compute_rest(
|
||||
starting_indexes,
|
||||
exit,
|
||||
None::<&EagerVec<PcoVec<DateIndex, Dollars>>>,
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get(&self, percentile: u8) -> Option<&ComputedDateLast<Dollars>> {
|
||||
PERCENTILES
|
||||
.iter()
|
||||
.position(|&p| p == percentile)
|
||||
.and_then(|i| self.vecs[i].as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl CostBasisPercentiles {
|
||||
pub fn write(&mut self) -> Result<()> {
|
||||
for vec in self.vecs.iter_mut().flatten() {
|
||||
vec.dateindex.write()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns a parallel iterator over all vecs for parallel writing.
|
||||
pub fn par_iter_mut(&mut self) -> impl ParallelIterator<Item = &mut dyn AnyStoredVec> {
|
||||
self.vecs
|
||||
.iter_mut()
|
||||
.flatten()
|
||||
.map(|v| &mut v.dateindex as &mut dyn AnyStoredVec)
|
||||
.collect::<Vec<_>>()
|
||||
.into_par_iter()
|
||||
}
|
||||
|
||||
/// Validate computed versions or reset if mismatched.
|
||||
pub fn validate_computed_version_or_reset(&mut self, version: Version) -> Result<()> {
|
||||
for vec in self.vecs.iter_mut().flatten() {
|
||||
vec.dateindex.validate_computed_version_or_reset(version)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Traversable for CostBasisPercentiles {
|
||||
fn to_tree_node(&self) -> TreeNode {
|
||||
TreeNode::Branch(
|
||||
PERCENTILES
|
||||
.iter()
|
||||
.zip(self.vecs.iter())
|
||||
.filter_map(|(p, v)| {
|
||||
v.as_ref()
|
||||
.map(|v| (format!("cost_basis_pct{p:02}"), v.to_tree_node()))
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn iter_any_exportable(&self) -> impl Iterator<Item = &dyn AnyExportableVec> {
|
||||
self.vecs
|
||||
.iter()
|
||||
.flatten()
|
||||
.flat_map(|p| p.iter_any_exportable())
|
||||
}
|
||||
}
|
||||
340
crates/brk_computer/src/internal/multi/specialized/ratio.rs
Normal file
340
crates/brk_computer/src/internal/multi/specialized/ratio.rs
Normal file
@@ -0,0 +1,340 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Date, DateIndex, Dollars, StoredF32, Version};
|
||||
use vecdb::{
|
||||
AnyStoredVec, AnyVec, CollectableVec, Database, EagerVec, Exit, GenericStoredVec, IterableVec,
|
||||
PcoVec, VecIndex,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, indexes,
|
||||
internal::{
|
||||
ComputedStandardDeviationVecsDate, LazyBinaryDateLast, PriceTimesRatio,
|
||||
StandardDeviationVecsOptions,
|
||||
},
|
||||
price,
|
||||
utils::get_percentile,
|
||||
};
|
||||
|
||||
use super::super::{ComputedBlockLast, ComputedDateLast};
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct ComputedRatioVecsDate {
|
||||
pub price: Option<ComputedDateLast<Dollars>>,
|
||||
|
||||
pub ratio: ComputedDateLast<StoredF32>,
|
||||
pub ratio_1w_sma: Option<ComputedDateLast<StoredF32>>,
|
||||
pub ratio_1m_sma: Option<ComputedDateLast<StoredF32>>,
|
||||
pub ratio_pct99: Option<ComputedDateLast<StoredF32>>,
|
||||
pub ratio_pct98: Option<ComputedDateLast<StoredF32>>,
|
||||
pub ratio_pct95: Option<ComputedDateLast<StoredF32>>,
|
||||
pub ratio_pct5: Option<ComputedDateLast<StoredF32>>,
|
||||
pub ratio_pct2: Option<ComputedDateLast<StoredF32>>,
|
||||
pub ratio_pct1: Option<ComputedDateLast<StoredF32>>,
|
||||
pub ratio_pct99_usd: Option<LazyBinaryDateLast<Dollars, Dollars, StoredF32>>,
|
||||
pub ratio_pct98_usd: Option<LazyBinaryDateLast<Dollars, Dollars, StoredF32>>,
|
||||
pub ratio_pct95_usd: Option<LazyBinaryDateLast<Dollars, Dollars, StoredF32>>,
|
||||
pub ratio_pct5_usd: Option<LazyBinaryDateLast<Dollars, Dollars, StoredF32>>,
|
||||
pub ratio_pct2_usd: Option<LazyBinaryDateLast<Dollars, Dollars, StoredF32>>,
|
||||
pub ratio_pct1_usd: Option<LazyBinaryDateLast<Dollars, Dollars, StoredF32>>,
|
||||
|
||||
pub ratio_sd: Option<ComputedStandardDeviationVecsDate>,
|
||||
pub ratio_4y_sd: Option<ComputedStandardDeviationVecsDate>,
|
||||
pub ratio_2y_sd: Option<ComputedStandardDeviationVecsDate>,
|
||||
pub ratio_1y_sd: Option<ComputedStandardDeviationVecsDate>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::TWO;
|
||||
|
||||
impl ComputedRatioVecsDate {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
metric_price: Option<&ComputedBlockLast<Dollars>>,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
extended: bool,
|
||||
price_vecs: Option<&price::Vecs>,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! import {
|
||||
($suffix:expr) => {
|
||||
ComputedDateLast::forced_import(db, &format!("{name}_{}", $suffix), v, indexes)
|
||||
.unwrap()
|
||||
};
|
||||
}
|
||||
// Create price sources first so lazy vecs can reference them
|
||||
// Only compute internally when metric_price is None
|
||||
let price = metric_price
|
||||
.is_none()
|
||||
.then(|| ComputedDateLast::forced_import(db, name, v, indexes).unwrap());
|
||||
|
||||
macro_rules! import_sd {
|
||||
($suffix:expr, $days:expr) => {
|
||||
ComputedStandardDeviationVecsDate::forced_import(
|
||||
db,
|
||||
&format!("{name}_{}", $suffix),
|
||||
$days,
|
||||
v,
|
||||
indexes,
|
||||
StandardDeviationVecsOptions::default().add_all(),
|
||||
price_vecs,
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
}
|
||||
|
||||
let ratio_pct99 = extended.then(|| import!("ratio_pct99"));
|
||||
let ratio_pct98 = extended.then(|| import!("ratio_pct98"));
|
||||
let ratio_pct95 = extended.then(|| import!("ratio_pct95"));
|
||||
let ratio_pct5 = extended.then(|| import!("ratio_pct5"));
|
||||
let ratio_pct2 = extended.then(|| import!("ratio_pct2"));
|
||||
let ratio_pct1 = extended.then(|| import!("ratio_pct1"));
|
||||
|
||||
macro_rules! lazy_usd {
|
||||
($ratio:expr, $suffix:expr) => {
|
||||
if let Some(mp) = metric_price {
|
||||
$ratio.as_ref().map(|r| {
|
||||
LazyBinaryDateLast::from_height_and_dateindex_last::<PriceTimesRatio>(
|
||||
&format!("{name}_{}", $suffix),
|
||||
v,
|
||||
mp,
|
||||
r,
|
||||
)
|
||||
})
|
||||
} else {
|
||||
price.as_ref().zip($ratio.as_ref()).map(|(p, r)| {
|
||||
LazyBinaryDateLast::from_computed_both_last::<PriceTimesRatio>(
|
||||
&format!("{name}_{}", $suffix),
|
||||
v,
|
||||
p,
|
||||
r,
|
||||
)
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
ratio: import!("ratio"),
|
||||
ratio_1w_sma: extended.then(|| import!("ratio_1w_sma")),
|
||||
ratio_1m_sma: extended.then(|| import!("ratio_1m_sma")),
|
||||
ratio_sd: extended.then(|| import_sd!("ratio", usize::MAX)),
|
||||
ratio_1y_sd: extended.then(|| import_sd!("ratio_1y", 365)),
|
||||
ratio_2y_sd: extended.then(|| import_sd!("ratio_2y", 2 * 365)),
|
||||
ratio_4y_sd: extended.then(|| import_sd!("ratio_4y", 4 * 365)),
|
||||
ratio_pct99_usd: lazy_usd!(&ratio_pct99, "ratio_pct99_usd"),
|
||||
ratio_pct98_usd: lazy_usd!(&ratio_pct98, "ratio_pct98_usd"),
|
||||
ratio_pct95_usd: lazy_usd!(&ratio_pct95, "ratio_pct95_usd"),
|
||||
ratio_pct5_usd: lazy_usd!(&ratio_pct5, "ratio_pct5_usd"),
|
||||
ratio_pct2_usd: lazy_usd!(&ratio_pct2, "ratio_pct2_usd"),
|
||||
ratio_pct1_usd: lazy_usd!(&ratio_pct1, "ratio_pct1_usd"),
|
||||
price,
|
||||
ratio_pct99,
|
||||
ratio_pct98,
|
||||
ratio_pct95,
|
||||
ratio_pct5,
|
||||
ratio_pct2,
|
||||
ratio_pct1,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
price: &price::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
compute: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut EagerVec<PcoVec<DateIndex, Dollars>>) -> Result<()>,
|
||||
{
|
||||
self.price
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_all(starting_indexes, exit, compute)?;
|
||||
|
||||
let date_to_price_opt: Option<&EagerVec<PcoVec<DateIndex, Dollars>>> = None;
|
||||
self.compute_rest(price, starting_indexes, exit, date_to_price_opt)
|
||||
}
|
||||
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
price: &price::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
price_opt: Option<&impl IterableVec<DateIndex, Dollars>>,
|
||||
) -> Result<()> {
|
||||
let closes = &price.usd.split.close.dateindex;
|
||||
|
||||
let price = price_opt.unwrap_or_else(|| unsafe {
|
||||
std::mem::transmute(&self.price.as_ref().unwrap().dateindex)
|
||||
});
|
||||
|
||||
self.ratio.compute_all(starting_indexes, exit, |v| {
|
||||
v.compute_transform2(
|
||||
starting_indexes.dateindex,
|
||||
closes,
|
||||
price,
|
||||
|(i, close, price, ..)| {
|
||||
if price == Dollars::ZERO {
|
||||
(i, StoredF32::from(1.0))
|
||||
} else {
|
||||
(i, StoredF32::from(*close / price))
|
||||
}
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
if self.ratio_1w_sma.is_none() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let min_ratio_date = DateIndex::try_from(Date::MIN_RATIO).unwrap();
|
||||
|
||||
self.ratio_1w_sma
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_all(starting_indexes, exit, |v| {
|
||||
v.compute_sma_(
|
||||
starting_indexes.dateindex,
|
||||
&self.ratio.dateindex,
|
||||
7,
|
||||
exit,
|
||||
Some(min_ratio_date),
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.ratio_1m_sma
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_all(starting_indexes, exit, |v| {
|
||||
v.compute_sma_(
|
||||
starting_indexes.dateindex,
|
||||
&self.ratio.dateindex,
|
||||
30,
|
||||
exit,
|
||||
Some(min_ratio_date),
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let ratio_version = self.ratio.dateindex.version();
|
||||
self.mut_ratio_vecs()
|
||||
.iter_mut()
|
||||
.try_for_each(|v| -> Result<()> {
|
||||
v.validate_computed_version_or_reset(ratio_version)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let starting_dateindex = self
|
||||
.mut_ratio_vecs()
|
||||
.iter()
|
||||
.map(|v| DateIndex::from(v.len()))
|
||||
.min()
|
||||
.unwrap()
|
||||
.min(starting_indexes.dateindex);
|
||||
|
||||
let min_ratio_date_usize = min_ratio_date.to_usize();
|
||||
|
||||
let mut sorted = self.ratio.dateindex.collect_range(
|
||||
Some(min_ratio_date_usize),
|
||||
Some(starting_dateindex.to_usize()),
|
||||
);
|
||||
|
||||
sorted.sort_unstable();
|
||||
|
||||
// Cache mutable refs before the loop to avoid repeated unwrap chains
|
||||
let pct1_vec = &mut self.ratio_pct1.as_mut().unwrap().dateindex;
|
||||
let pct2_vec = &mut self.ratio_pct2.as_mut().unwrap().dateindex;
|
||||
let pct5_vec = &mut self.ratio_pct5.as_mut().unwrap().dateindex;
|
||||
let pct95_vec = &mut self.ratio_pct95.as_mut().unwrap().dateindex;
|
||||
let pct98_vec = &mut self.ratio_pct98.as_mut().unwrap().dateindex;
|
||||
let pct99_vec = &mut self.ratio_pct99.as_mut().unwrap().dateindex;
|
||||
|
||||
self.ratio
|
||||
.dateindex
|
||||
.iter()
|
||||
.enumerate()
|
||||
.skip(starting_dateindex.to_usize())
|
||||
.try_for_each(|(index, ratio)| -> Result<()> {
|
||||
if index < min_ratio_date_usize {
|
||||
pct1_vec.truncate_push_at(index, StoredF32::NAN)?;
|
||||
pct2_vec.truncate_push_at(index, StoredF32::NAN)?;
|
||||
pct5_vec.truncate_push_at(index, StoredF32::NAN)?;
|
||||
pct95_vec.truncate_push_at(index, StoredF32::NAN)?;
|
||||
pct98_vec.truncate_push_at(index, StoredF32::NAN)?;
|
||||
pct99_vec.truncate_push_at(index, StoredF32::NAN)?;
|
||||
} else {
|
||||
let pos = sorted.binary_search(&ratio).unwrap_or_else(|pos| pos);
|
||||
sorted.insert(pos, ratio);
|
||||
|
||||
pct1_vec.truncate_push_at(index, get_percentile(&sorted, 0.01))?;
|
||||
pct2_vec.truncate_push_at(index, get_percentile(&sorted, 0.02))?;
|
||||
pct5_vec.truncate_push_at(index, get_percentile(&sorted, 0.05))?;
|
||||
pct95_vec.truncate_push_at(index, get_percentile(&sorted, 0.95))?;
|
||||
pct98_vec.truncate_push_at(index, get_percentile(&sorted, 0.98))?;
|
||||
pct99_vec.truncate_push_at(index, get_percentile(&sorted, 0.99))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
{
|
||||
let _lock = exit.lock();
|
||||
self.mut_ratio_vecs()
|
||||
.into_iter()
|
||||
.try_for_each(|v| v.flush())?;
|
||||
}
|
||||
|
||||
macro_rules! compute_pct_rest {
|
||||
($($field:ident),*) => {
|
||||
$(self.$field.as_mut().unwrap().compute_rest(
|
||||
starting_indexes, exit, None as Option<&EagerVec<PcoVec<_, _>>>,
|
||||
)?;)*
|
||||
};
|
||||
}
|
||||
compute_pct_rest!(
|
||||
ratio_pct1,
|
||||
ratio_pct2,
|
||||
ratio_pct5,
|
||||
ratio_pct95,
|
||||
ratio_pct98,
|
||||
ratio_pct99
|
||||
);
|
||||
|
||||
macro_rules! compute_sd {
|
||||
($($field:ident),*) => {
|
||||
$(self.$field.as_mut().unwrap().compute_all(
|
||||
starting_indexes, exit, &self.ratio.dateindex,
|
||||
)?;)*
|
||||
};
|
||||
}
|
||||
compute_sd!(ratio_sd, ratio_4y_sd, ratio_2y_sd, ratio_1y_sd);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn mut_ratio_vecs(&mut self) -> Vec<&mut EagerVec<PcoVec<DateIndex, StoredF32>>> {
|
||||
macro_rules! collect_vecs {
|
||||
($($field:ident),*) => {{
|
||||
let mut vecs = Vec::with_capacity(6);
|
||||
$(if let Some(v) = self.$field.as_mut() { vecs.push(&mut v.dateindex); })*
|
||||
vecs
|
||||
}};
|
||||
}
|
||||
collect_vecs!(
|
||||
ratio_pct1,
|
||||
ratio_pct2,
|
||||
ratio_pct5,
|
||||
ratio_pct95,
|
||||
ratio_pct98,
|
||||
ratio_pct99
|
||||
)
|
||||
}
|
||||
}
|
||||
398
crates/brk_computer/src/internal/multi/specialized/stddev.rs
Normal file
398
crates/brk_computer/src/internal/multi/specialized/stddev.rs
Normal file
@@ -0,0 +1,398 @@
|
||||
use std::mem;
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Close, Date, DateIndex, Dollars, StoredF32, Version};
|
||||
use vecdb::{
|
||||
AnyStoredVec, AnyVec, CollectableVec, Database, EagerVec, Exit, GenericStoredVec, IterableVec,
|
||||
PcoVec, VecIndex,
|
||||
};
|
||||
|
||||
use crate::{ComputeIndexes, indexes, price};
|
||||
|
||||
use crate::internal::{ClosePriceTimesRatio, ComputedDateLast, LazyBinaryDateLast};
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct ComputedStandardDeviationVecsDate {
|
||||
days: usize,
|
||||
|
||||
pub sma: Option<ComputedDateLast<StoredF32>>,
|
||||
|
||||
pub sd: ComputedDateLast<StoredF32>,
|
||||
|
||||
pub zscore: Option<ComputedDateLast<StoredF32>>,
|
||||
|
||||
pub p0_5sd: Option<ComputedDateLast<StoredF32>>,
|
||||
pub p1sd: Option<ComputedDateLast<StoredF32>>,
|
||||
pub p1_5sd: Option<ComputedDateLast<StoredF32>>,
|
||||
pub p2sd: Option<ComputedDateLast<StoredF32>>,
|
||||
pub p2_5sd: Option<ComputedDateLast<StoredF32>>,
|
||||
pub p3sd: Option<ComputedDateLast<StoredF32>>,
|
||||
pub m0_5sd: Option<ComputedDateLast<StoredF32>>,
|
||||
pub m1sd: Option<ComputedDateLast<StoredF32>>,
|
||||
pub m1_5sd: Option<ComputedDateLast<StoredF32>>,
|
||||
pub m2sd: Option<ComputedDateLast<StoredF32>>,
|
||||
pub m2_5sd: Option<ComputedDateLast<StoredF32>>,
|
||||
pub m3sd: Option<ComputedDateLast<StoredF32>>,
|
||||
|
||||
pub _0sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
|
||||
pub p0_5sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
|
||||
pub p1sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
|
||||
pub p1_5sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
|
||||
pub p2sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
|
||||
pub p2_5sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
|
||||
pub p3sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
|
||||
pub m0_5sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
|
||||
pub m1sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
|
||||
pub m1_5sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
|
||||
pub m2sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
|
||||
pub m2_5sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
|
||||
pub m3sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct StandardDeviationVecsOptions {
|
||||
zscore: bool,
|
||||
bands: bool,
|
||||
price_bands: bool,
|
||||
}
|
||||
|
||||
impl StandardDeviationVecsOptions {
|
||||
pub fn add_all(mut self) -> Self {
|
||||
self.zscore = true;
|
||||
self.bands = true;
|
||||
self.price_bands = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_zscore(mut self) -> Self {
|
||||
self.zscore = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_bands(mut self) -> Self {
|
||||
self.bands = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_price_bands(mut self) -> Self {
|
||||
self.bands = true;
|
||||
self.price_bands = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn zscore(&self) -> bool {
|
||||
self.zscore
|
||||
}
|
||||
|
||||
pub fn bands(&self) -> bool {
|
||||
self.bands
|
||||
}
|
||||
|
||||
pub fn price_bands(&self) -> bool {
|
||||
self.price_bands
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputedStandardDeviationVecsDate {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
days: usize,
|
||||
parent_version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
options: StandardDeviationVecsOptions,
|
||||
price_vecs: Option<&price::Vecs>,
|
||||
) -> Result<Self> {
|
||||
let version = parent_version + Version::ONE;
|
||||
|
||||
macro_rules! import {
|
||||
($suffix:expr) => {
|
||||
ComputedDateLast::forced_import(
|
||||
db,
|
||||
&format!("{name}_{}", $suffix),
|
||||
version,
|
||||
indexes,
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
}
|
||||
|
||||
let sma_vec = Some(import!("sma"));
|
||||
let p0_5sd = options.bands().then(|| import!("p0_5sd"));
|
||||
let p1sd = options.bands().then(|| import!("p1sd"));
|
||||
let p1_5sd = options.bands().then(|| import!("p1_5sd"));
|
||||
let p2sd = options.bands().then(|| import!("p2sd"));
|
||||
let p2_5sd = options.bands().then(|| import!("p2_5sd"));
|
||||
let p3sd = options.bands().then(|| import!("p3sd"));
|
||||
let m0_5sd = options.bands().then(|| import!("m0_5sd"));
|
||||
let m1sd = options.bands().then(|| import!("m1sd"));
|
||||
let m1_5sd = options.bands().then(|| import!("m1_5sd"));
|
||||
let m2sd = options.bands().then(|| import!("m2sd"));
|
||||
let m2_5sd = options.bands().then(|| import!("m2_5sd"));
|
||||
let m3sd = options.bands().then(|| import!("m3sd"));
|
||||
|
||||
macro_rules! lazy_usd {
|
||||
($band:expr, $suffix:expr) => {
|
||||
price_vecs
|
||||
.map(|p| &p.usd.split.close)
|
||||
.zip($band.as_ref())
|
||||
.filter(|_| options.price_bands())
|
||||
.map(|(p, b)| {
|
||||
LazyBinaryDateLast::from_computed_both_last::<ClosePriceTimesRatio>(
|
||||
&format!("{name}_{}", $suffix),
|
||||
version,
|
||||
p,
|
||||
b,
|
||||
)
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
days,
|
||||
sd: import!("sd"),
|
||||
zscore: options.zscore().then(|| import!("zscore")),
|
||||
// Lazy USD vecs
|
||||
_0sd_usd: lazy_usd!(&sma_vec, "0sd_usd"),
|
||||
p0_5sd_usd: lazy_usd!(&p0_5sd, "p0_5sd_usd"),
|
||||
p1sd_usd: lazy_usd!(&p1sd, "p1sd_usd"),
|
||||
p1_5sd_usd: lazy_usd!(&p1_5sd, "p1_5sd_usd"),
|
||||
p2sd_usd: lazy_usd!(&p2sd, "p2sd_usd"),
|
||||
p2_5sd_usd: lazy_usd!(&p2_5sd, "p2_5sd_usd"),
|
||||
p3sd_usd: lazy_usd!(&p3sd, "p3sd_usd"),
|
||||
m0_5sd_usd: lazy_usd!(&m0_5sd, "m0_5sd_usd"),
|
||||
m1sd_usd: lazy_usd!(&m1sd, "m1sd_usd"),
|
||||
m1_5sd_usd: lazy_usd!(&m1_5sd, "m1_5sd_usd"),
|
||||
m2sd_usd: lazy_usd!(&m2sd, "m2sd_usd"),
|
||||
m2_5sd_usd: lazy_usd!(&m2_5sd, "m2_5sd_usd"),
|
||||
m3sd_usd: lazy_usd!(&m3sd, "m3sd_usd"),
|
||||
// Stored band sources
|
||||
sma: sma_vec,
|
||||
p0_5sd,
|
||||
p1sd,
|
||||
p1_5sd,
|
||||
p2sd,
|
||||
p2_5sd,
|
||||
p3sd,
|
||||
m0_5sd,
|
||||
m1sd,
|
||||
m1_5sd,
|
||||
m2sd,
|
||||
m2_5sd,
|
||||
m3sd,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compute_all(
|
||||
&mut self,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
source: &impl CollectableVec<DateIndex, StoredF32>,
|
||||
) -> Result<()> {
|
||||
let min_date = DateIndex::try_from(Date::MIN_RATIO).unwrap();
|
||||
|
||||
self.sma
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_all(starting_indexes, exit, |v| {
|
||||
v.compute_sma_(
|
||||
starting_indexes.dateindex,
|
||||
source,
|
||||
self.days,
|
||||
exit,
|
||||
Some(min_date),
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let sma_opt: Option<&EagerVec<PcoVec<DateIndex, StoredF32>>> = None;
|
||||
self.compute_rest(starting_indexes, exit, sma_opt, source)
|
||||
}
|
||||
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
sma_opt: Option<&impl IterableVec<DateIndex, StoredF32>>,
|
||||
source: &impl CollectableVec<DateIndex, StoredF32>,
|
||||
) -> Result<()> {
|
||||
let sma = sma_opt
|
||||
.unwrap_or_else(|| unsafe { mem::transmute(&self.sma.as_ref().unwrap().dateindex) });
|
||||
|
||||
let min_date = DateIndex::try_from(Date::MIN_RATIO).unwrap();
|
||||
|
||||
let source_version = source.version();
|
||||
|
||||
self.mut_stateful_date_vecs()
|
||||
.try_for_each(|v| -> Result<()> {
|
||||
v.validate_computed_version_or_reset(source_version)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let starting_dateindex = self
|
||||
.mut_stateful_date_vecs()
|
||||
.map(|v| DateIndex::from(v.len()))
|
||||
.min()
|
||||
.unwrap()
|
||||
.min(starting_indexes.dateindex);
|
||||
|
||||
let mut sorted = source.collect_range(
|
||||
Some(min_date.to_usize()),
|
||||
Some(starting_dateindex.to_usize()),
|
||||
);
|
||||
|
||||
sorted.sort_unstable();
|
||||
|
||||
macro_rules! band_ref {
|
||||
($field:ident) => {
|
||||
self.$field.as_mut().map(|c| &mut c.dateindex)
|
||||
};
|
||||
}
|
||||
let mut p0_5sd = band_ref!(p0_5sd);
|
||||
let mut p1sd = band_ref!(p1sd);
|
||||
let mut p1_5sd = band_ref!(p1_5sd);
|
||||
let mut p2sd = band_ref!(p2sd);
|
||||
let mut p2_5sd = band_ref!(p2_5sd);
|
||||
let mut p3sd = band_ref!(p3sd);
|
||||
let mut m0_5sd = band_ref!(m0_5sd);
|
||||
let mut m1sd = band_ref!(m1sd);
|
||||
let mut m1_5sd = band_ref!(m1_5sd);
|
||||
let mut m2sd = band_ref!(m2sd);
|
||||
let mut m2_5sd = band_ref!(m2_5sd);
|
||||
let mut m3sd = band_ref!(m3sd);
|
||||
|
||||
let min_date_usize = min_date.to_usize();
|
||||
let mut sma_iter = sma.iter().skip(starting_dateindex.to_usize());
|
||||
|
||||
source
|
||||
.iter()
|
||||
.enumerate()
|
||||
.skip(starting_dateindex.to_usize())
|
||||
.try_for_each(|(index, ratio)| -> Result<()> {
|
||||
if index < min_date_usize {
|
||||
self.sd.dateindex.truncate_push_at(index, StoredF32::NAN)?;
|
||||
|
||||
macro_rules! push_nan {
|
||||
($($band:ident),*) => {
|
||||
$(if let Some(v) = $band.as_mut() { v.truncate_push_at(index, StoredF32::NAN)? })*
|
||||
};
|
||||
}
|
||||
push_nan!(p0_5sd, p1sd, p1_5sd, p2sd, p2_5sd, p3sd, m0_5sd, m1sd, m1_5sd, m2sd, m2_5sd, m3sd);
|
||||
|
||||
// Advance iterator to stay in sync
|
||||
sma_iter.next();
|
||||
} else {
|
||||
let pos = sorted.binary_search(&ratio).unwrap_or_else(|pos| pos);
|
||||
sorted.insert(pos, ratio);
|
||||
|
||||
let average = sma_iter.next().unwrap();
|
||||
|
||||
let population =
|
||||
index.checked_sub(min_date_usize).unwrap().to_usize() as f32 + 1.0;
|
||||
|
||||
let sd = StoredF32::from(
|
||||
(sorted.iter().map(|v| (**v - *average).powi(2)).sum::<f32>() / population)
|
||||
.sqrt(),
|
||||
);
|
||||
|
||||
self.sd.dateindex.truncate_push_at(index, sd)?;
|
||||
if let Some(v) = p0_5sd.as_mut() {
|
||||
v.truncate_push_at(index, average + StoredF32::from(0.5 * *sd))?
|
||||
}
|
||||
if let Some(v) = p1sd.as_mut() {
|
||||
v.truncate_push_at(index, average + sd)?
|
||||
}
|
||||
if let Some(v) = p1_5sd.as_mut() {
|
||||
v.truncate_push_at(index, average + StoredF32::from(1.5 * *sd))?
|
||||
}
|
||||
if let Some(v) = p2sd.as_mut() {
|
||||
v.truncate_push_at(index, average + 2 * sd)?
|
||||
}
|
||||
if let Some(v) = p2_5sd.as_mut() {
|
||||
v.truncate_push_at(index, average + StoredF32::from(2.5 * *sd))?
|
||||
}
|
||||
if let Some(v) = p3sd.as_mut() {
|
||||
v.truncate_push_at(index, average + 3 * sd)?
|
||||
}
|
||||
if let Some(v) = m0_5sd.as_mut() {
|
||||
v.truncate_push_at(index, average - StoredF32::from(0.5 * *sd))?
|
||||
}
|
||||
if let Some(v) = m1sd.as_mut() {
|
||||
v.truncate_push_at(index, average - sd)?
|
||||
}
|
||||
if let Some(v) = m1_5sd.as_mut() {
|
||||
v.truncate_push_at(index, average - StoredF32::from(1.5 * *sd))?
|
||||
}
|
||||
if let Some(v) = m2sd.as_mut() {
|
||||
v.truncate_push_at(index, average - 2 * sd)?
|
||||
}
|
||||
if let Some(v) = m2_5sd.as_mut() {
|
||||
v.truncate_push_at(index, average - StoredF32::from(2.5 * *sd))?
|
||||
}
|
||||
if let Some(v) = m3sd.as_mut() {
|
||||
v.truncate_push_at(index, average - 3 * sd)?
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
drop(sma_iter);
|
||||
|
||||
{
|
||||
let _lock = exit.lock();
|
||||
self.mut_stateful_date_vecs().try_for_each(|v| v.flush())?;
|
||||
}
|
||||
|
||||
self.mut_stateful_computed().try_for_each(|v| {
|
||||
v.compute_rest(
|
||||
starting_indexes,
|
||||
exit,
|
||||
None as Option<&EagerVec<PcoVec<_, _>>>,
|
||||
)
|
||||
})?;
|
||||
|
||||
if let Some(zscore) = self.zscore.as_mut() {
|
||||
zscore.compute_all(starting_indexes, exit, |vec| {
|
||||
vec.compute_zscore(
|
||||
starting_indexes.dateindex,
|
||||
source,
|
||||
sma,
|
||||
&self.sd.dateindex,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn mut_stateful_computed(&mut self) -> impl Iterator<Item = &mut ComputedDateLast<StoredF32>> {
|
||||
[
|
||||
Some(&mut self.sd),
|
||||
self.p0_5sd.as_mut(),
|
||||
self.p1sd.as_mut(),
|
||||
self.p1_5sd.as_mut(),
|
||||
self.p2sd.as_mut(),
|
||||
self.p2_5sd.as_mut(),
|
||||
self.p3sd.as_mut(),
|
||||
self.m0_5sd.as_mut(),
|
||||
self.m1sd.as_mut(),
|
||||
self.m1_5sd.as_mut(),
|
||||
self.m2sd.as_mut(),
|
||||
self.m2_5sd.as_mut(),
|
||||
self.m3sd.as_mut(),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
fn mut_stateful_date_vecs(
|
||||
&mut self,
|
||||
) -> impl Iterator<Item = &mut EagerVec<PcoVec<DateIndex, StoredF32>>> {
|
||||
self.mut_stateful_computed().map(|c| &mut c.dateindex)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
//! Value type for Derived Last pattern from DateIndex (when source is external).
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, DateIndex, Dollars, Sats, Version};
|
||||
use vecdb::{Database, Exit, IterableBoxedVec};
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, indexes,
|
||||
internal::{ComputedDateLast, LazyPeriodsLast, LazyDateLast, SatsToBitcoin},
|
||||
price,
|
||||
traits::ComputeFromBitcoin,
|
||||
utils::OptionExt,
|
||||
};
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct ValueLazyPeriodsLast {
|
||||
pub sats: LazyPeriodsLast<Sats>,
|
||||
pub bitcoin: LazyDateLast<Bitcoin, Sats>,
|
||||
pub dollars: Option<ComputedDateLast<Dollars>>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl ValueLazyPeriodsLast {
|
||||
pub fn from_source(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
source: IterableBoxedVec<DateIndex, Sats>,
|
||||
version: Version,
|
||||
compute_dollars: bool,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let sats = LazyPeriodsLast::from_source(name, version + VERSION, source.clone(), indexes);
|
||||
|
||||
let bitcoin = LazyDateLast::from_derived::<SatsToBitcoin>(
|
||||
&format!("{name}_btc"),
|
||||
version + VERSION,
|
||||
source,
|
||||
&sats,
|
||||
);
|
||||
|
||||
let dollars = compute_dollars.then(|| {
|
||||
ComputedDateLast::forced_import(db, &format!("{name}_usd"), version + VERSION, indexes)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
Ok(Self {
|
||||
sats,
|
||||
bitcoin,
|
||||
dollars,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compute_dollars<F>(&mut self, mut compute: F) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut ComputedDateLast<Dollars>) -> Result<()>,
|
||||
{
|
||||
if let Some(dollars) = self.dollars.as_mut() {
|
||||
compute(dollars)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn compute_dollars_from_price(
|
||||
&mut self,
|
||||
price: Option<&price::Vecs>,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
if let Some(dollars) = self.dollars.as_mut() {
|
||||
let dateindex_to_bitcoin = &*self.bitcoin.dateindex;
|
||||
let dateindex_to_price_close = &price.u().usd.split.close.dateindex;
|
||||
|
||||
dollars.compute_all(starting_indexes, exit, |v| {
|
||||
v.compute_from_bitcoin(
|
||||
starting_indexes.dateindex,
|
||||
dateindex_to_bitcoin,
|
||||
dateindex_to_price_close,
|
||||
exit,
|
||||
)
|
||||
})?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
//! Value type for stateful Last pattern - height and dateindex both stored independently.
|
||||
//!
|
||||
//! Use this when dateindex values are NOT derivable from height (e.g., unrealized metrics
|
||||
//! where end-of-day state differs from last-block-of-day).
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Sats, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
|
||||
|
||||
use crate::{ComputeIndexes, indexes, price};
|
||||
|
||||
use crate::internal::{LazyDerivedBlockValue, LazyValueDifficultyEpochFromHeight};
|
||||
use super::ValueDateLast;
|
||||
|
||||
/// Value type where both height and dateindex are stored independently.
|
||||
/// Dateindex values cannot be derived from height (e.g., unrealized P&L).
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ValueHeightDateLast {
|
||||
#[traversable(rename = "sats")]
|
||||
pub height: EagerVec<PcoVec<Height, Sats>>,
|
||||
#[traversable(flatten)]
|
||||
pub height_value: LazyDerivedBlockValue,
|
||||
#[traversable(flatten)]
|
||||
pub difficultyepoch: LazyValueDifficultyEpochFromHeight,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub indexes: ValueDateLast,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl ValueHeightDateLast {
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
compute_dollars: bool,
|
||||
indexes: &indexes::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let height: EagerVec<PcoVec<Height, Sats>> = EagerVec::forced_import(db, name, v)?;
|
||||
|
||||
let price_source = price.map(|p| p.usd.split.close.height.boxed_clone());
|
||||
|
||||
let height_value =
|
||||
LazyDerivedBlockValue::from_source(name, height.boxed_clone(), v, price_source);
|
||||
|
||||
let difficultyepoch = LazyValueDifficultyEpochFromHeight::from_height_source(
|
||||
name,
|
||||
height.boxed_clone(),
|
||||
indexes.difficultyepoch.identity.boxed_clone(),
|
||||
price,
|
||||
v,
|
||||
);
|
||||
|
||||
let indexes = ValueDateLast::forced_import(db, name, v, compute_dollars, indexes)?;
|
||||
|
||||
Ok(Self {
|
||||
height,
|
||||
height_value,
|
||||
difficultyepoch,
|
||||
indexes,
|
||||
})
|
||||
}
|
||||
|
||||
/// Compute derived periods from dateindex.
|
||||
pub fn compute_dollars_from_price(
|
||||
&mut self,
|
||||
price: Option<&price::Vecs>,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.indexes
|
||||
.compute_dollars_from_price(price, starting_indexes, exit)
|
||||
}
|
||||
}
|
||||
87
crates/brk_computer/src/internal/multi/value/date/last.rs
Normal file
87
crates/brk_computer/src/internal/multi/value/date/last.rs
Normal file
@@ -0,0 +1,87 @@
|
||||
//! Value type for Last pattern from DateIndex.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, Sats, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
|
||||
|
||||
use crate::{ComputeIndexes, indexes, price};
|
||||
|
||||
use super::ValueLazyPeriodsLast;
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ValueDateLast {
|
||||
#[traversable(rename = "sats")]
|
||||
pub sats_dateindex: EagerVec<PcoVec<DateIndex, Sats>>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub rest: ValueLazyPeriodsLast,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl ValueDateLast {
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
compute_dollars: bool,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let sats_dateindex = EagerVec::forced_import(db, name, version + VERSION)?;
|
||||
|
||||
let rest = ValueLazyPeriodsLast::from_source(
|
||||
db,
|
||||
name,
|
||||
sats_dateindex.boxed_clone(),
|
||||
version + VERSION,
|
||||
compute_dollars,
|
||||
indexes,
|
||||
)?;
|
||||
|
||||
Ok(Self {
|
||||
sats_dateindex,
|
||||
rest,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compute_sats<F>(&mut self, mut compute: F) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut EagerVec<PcoVec<DateIndex, Sats>>) -> Result<()>,
|
||||
{
|
||||
compute(&mut self.sats_dateindex)
|
||||
}
|
||||
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
price: Option<&price::Vecs>,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
compute: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut EagerVec<PcoVec<DateIndex, Sats>>) -> Result<()>,
|
||||
{
|
||||
self.compute_sats(compute)?;
|
||||
self.compute_dollars_from_price(price, starting_indexes, exit)
|
||||
}
|
||||
|
||||
pub fn compute_dollars<F>(&mut self, compute: F) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut crate::internal::ComputedDateLast<brk_types::Dollars>) -> Result<()>,
|
||||
{
|
||||
self.rest.compute_dollars(compute)
|
||||
}
|
||||
|
||||
pub fn compute_dollars_from_price(
|
||||
&mut self,
|
||||
price: Option<&price::Vecs>,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.rest
|
||||
.compute_dollars_from_price(price, starting_indexes, exit)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
//! Lazy value type for Last pattern from DateIndex.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Dollars, Sats, Version};
|
||||
use vecdb::{IterableCloneableVec, UnaryTransform};
|
||||
|
||||
use crate::internal::{LazyDateLast, ValueBlockLast, ValueDateLast};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct LazyValueDateLast {
|
||||
pub sats: LazyDateLast<Sats, Sats>,
|
||||
pub bitcoin: LazyDateLast<Bitcoin, Sats>,
|
||||
pub dollars: Option<LazyDateLast<Dollars, Dollars>>,
|
||||
}
|
||||
|
||||
impl LazyValueDateLast {
|
||||
pub fn from_source<SatsTransform, BitcoinTransform, DollarsTransform>(
|
||||
name: &str,
|
||||
source: &ValueDateLast,
|
||||
version: Version,
|
||||
) -> Self
|
||||
where
|
||||
SatsTransform: UnaryTransform<Sats, Sats>,
|
||||
BitcoinTransform: UnaryTransform<Sats, Bitcoin>,
|
||||
DollarsTransform: UnaryTransform<Dollars, Dollars>,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
let sats = LazyDateLast::from_derived::<SatsTransform>(
|
||||
name,
|
||||
v,
|
||||
source.sats_dateindex.boxed_clone(),
|
||||
&source.sats,
|
||||
);
|
||||
|
||||
let bitcoin = LazyDateLast::from_derived::<BitcoinTransform>(
|
||||
&format!("{name}_btc"),
|
||||
v,
|
||||
source.sats_dateindex.boxed_clone(),
|
||||
&source.sats,
|
||||
);
|
||||
|
||||
let dollars = source.dollars.as_ref().map(|dollars_source| {
|
||||
LazyDateLast::from_computed::<DollarsTransform>(
|
||||
&format!("{name}_usd"),
|
||||
v,
|
||||
dollars_source.dateindex.boxed_clone(),
|
||||
dollars_source,
|
||||
)
|
||||
});
|
||||
|
||||
Self { sats, bitcoin, dollars }
|
||||
}
|
||||
|
||||
pub fn from_block_source<SatsTransform, BitcoinTransform, DollarsTransform>(
|
||||
name: &str,
|
||||
source: &ValueBlockLast,
|
||||
version: Version,
|
||||
) -> Self
|
||||
where
|
||||
SatsTransform: UnaryTransform<Sats, Sats>,
|
||||
BitcoinTransform: UnaryTransform<Sats, Bitcoin>,
|
||||
DollarsTransform: UnaryTransform<Dollars, Dollars>,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
let sats = LazyDateLast::from_derived::<SatsTransform>(
|
||||
name,
|
||||
v,
|
||||
source.sats.rest.dateindex.0.boxed_clone(),
|
||||
&source.sats.rest.dates,
|
||||
);
|
||||
|
||||
let bitcoin = LazyDateLast::from_derived::<BitcoinTransform>(
|
||||
&format!("{name}_btc"),
|
||||
v,
|
||||
source.sats.rest.dateindex.0.boxed_clone(),
|
||||
&source.sats.rest.dates,
|
||||
);
|
||||
|
||||
let dollars = source.dollars.as_ref().map(|dollars_source| {
|
||||
LazyDateLast::from_derived::<DollarsTransform>(
|
||||
&format!("{name}_usd"),
|
||||
v,
|
||||
dollars_source.rest.dateindex.0.boxed_clone(),
|
||||
&dollars_source.rest.dates,
|
||||
)
|
||||
});
|
||||
|
||||
Self { sats, bitcoin, dollars }
|
||||
}
|
||||
}
|
||||
9
crates/brk_computer/src/internal/multi/value/date/mod.rs
Normal file
9
crates/brk_computer/src/internal/multi/value/date/mod.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
mod derived_last;
|
||||
mod height_date_last;
|
||||
mod last;
|
||||
mod lazy_last;
|
||||
|
||||
pub use height_date_last::*;
|
||||
pub use derived_last::*;
|
||||
pub use last::*;
|
||||
pub use lazy_last::*;
|
||||
@@ -0,0 +1,3 @@
|
||||
mod sum_cum;
|
||||
|
||||
pub use sum_cum::*;
|
||||
@@ -0,0 +1,96 @@
|
||||
//! Value type for derived SumCum pattern (derives from external height source).
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Close, Dollars, Height, Sats, Version};
|
||||
use vecdb::{Database, Exit, IterableBoxedVec, IterableCloneableVec, IterableVec, LazyVecFrom2};
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, indexes,
|
||||
internal::{
|
||||
ClosePriceTimesSats, ComputedDerivedBlockSumCum, LazyBlockSumCum, LazyBlockSumCumHeight,
|
||||
SatsToBitcoin,
|
||||
},
|
||||
price,
|
||||
};
|
||||
|
||||
/// Value wrapper for derived SumCum (derives from external height source).
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct ValueDerivedBlockSumCum {
|
||||
pub sats: ComputedDerivedBlockSumCum<Sats>,
|
||||
pub bitcoin: LazyBlockSumCum<Bitcoin, Sats>,
|
||||
pub dollars: Option<LazyBlockSumCumHeight<Dollars, Close<Dollars>, Sats>>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl ValueDerivedBlockSumCum {
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
sats_source: IterableBoxedVec<Height, Sats>,
|
||||
price: Option<&price::Vecs>,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let sats = ComputedDerivedBlockSumCum::forced_import(
|
||||
db,
|
||||
name,
|
||||
sats_source.boxed_clone(),
|
||||
v,
|
||||
indexes,
|
||||
)?;
|
||||
|
||||
let bitcoin = LazyBlockSumCum::from_derived::<SatsToBitcoin>(
|
||||
&format!("{name}_btc"),
|
||||
v,
|
||||
sats_source.boxed_clone(),
|
||||
&sats,
|
||||
);
|
||||
|
||||
let dollars = if let Some(price) = price {
|
||||
let dollars_height = LazyVecFrom2::transformed::<ClosePriceTimesSats>(
|
||||
&format!("{name}_usd"),
|
||||
v,
|
||||
price.usd.split.close.height.boxed_clone(),
|
||||
sats_source.boxed_clone(),
|
||||
);
|
||||
|
||||
Some(LazyBlockSumCumHeight::forced_import(
|
||||
db,
|
||||
&format!("{name}_usd"),
|
||||
v,
|
||||
indexes,
|
||||
dollars_height,
|
||||
)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
sats,
|
||||
bitcoin,
|
||||
dollars,
|
||||
})
|
||||
}
|
||||
|
||||
/// Derive aggregates from caller-provided sats height source.
|
||||
pub fn derive_from(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
sats_source: &impl IterableVec<Height, Sats>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.sats
|
||||
.derive_from(indexes, starting_indexes, sats_source, exit)?;
|
||||
|
||||
if let Some(dollars) = self.dollars.as_mut() {
|
||||
dollars.derive_from(indexes, starting_indexes, exit)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
179
crates/brk_computer/src/internal/multi/value/height/binary.rs
Normal file
179
crates/brk_computer/src/internal/multi/value/height/binary.rs
Normal file
@@ -0,0 +1,179 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Dollars, Height, Sats, Version};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{BinaryTransform, IterableBoxedVec, IterableCloneableVec};
|
||||
|
||||
use crate::internal::{
|
||||
ComputedVecValue, ValueDerivedBlockSumCum, LazyBinaryBlockSumCum, LazyValueBlockSumCum,
|
||||
ValueBlockSumCum,
|
||||
};
|
||||
|
||||
/// Lazy value vecs computed from two ValueBlockSumCum sources via binary transforms.
|
||||
/// Used for computing coinbase = subsidy + fee.
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct ValueBinaryBlock {
|
||||
pub sats: LazyBinaryBlockSumCum<Sats, Sats, Sats>,
|
||||
pub bitcoin: LazyBinaryBlockSumCum<Bitcoin, Sats, Sats>,
|
||||
pub dollars: Option<LazyBinaryBlockSumCum<Dollars, Dollars, Dollars>>,
|
||||
}
|
||||
|
||||
impl ValueBinaryBlock {
|
||||
pub fn from_computed<SatsF, BitcoinF, DollarsF>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
height_source1: IterableBoxedVec<Height, Sats>,
|
||||
height_source2: IterableBoxedVec<Height, Sats>,
|
||||
source1: &ValueBlockSumCum,
|
||||
source2: &ValueBlockSumCum,
|
||||
) -> Self
|
||||
where
|
||||
SatsF: BinaryTransform<Sats, Sats, Sats>,
|
||||
BitcoinF: BinaryTransform<Sats, Sats, Bitcoin>,
|
||||
DollarsF: BinaryTransform<Dollars, Dollars, Dollars>,
|
||||
{
|
||||
let sats = LazyBinaryBlockSumCum::from_computed::<SatsF>(
|
||||
name,
|
||||
version,
|
||||
height_source1.boxed_clone(),
|
||||
height_source2.boxed_clone(),
|
||||
&source1.sats,
|
||||
&source2.sats,
|
||||
);
|
||||
|
||||
let bitcoin = LazyBinaryBlockSumCum::from_computed::<BitcoinF>(
|
||||
&format!("{name}_btc"),
|
||||
version,
|
||||
height_source1,
|
||||
height_source2,
|
||||
&source1.sats,
|
||||
&source2.sats,
|
||||
);
|
||||
|
||||
let dollars = source1
|
||||
.dollars
|
||||
.as_ref()
|
||||
.zip(source2.dollars.as_ref())
|
||||
.map(|(d1, d2)| {
|
||||
LazyBinaryBlockSumCum::from_computed::<DollarsF>(
|
||||
&format!("{name}_usd"),
|
||||
version,
|
||||
d1.height.boxed_clone(),
|
||||
d2.height.boxed_clone(),
|
||||
d1,
|
||||
d2,
|
||||
)
|
||||
});
|
||||
|
||||
Self {
|
||||
sats,
|
||||
bitcoin,
|
||||
dollars,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_derived<SatsF, BitcoinF, DollarsF>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
height_source1: IterableBoxedVec<Height, Sats>,
|
||||
height_source2: IterableBoxedVec<Height, Sats>,
|
||||
source1: &ValueDerivedBlockSumCum,
|
||||
source2: &ValueDerivedBlockSumCum,
|
||||
) -> Self
|
||||
where
|
||||
SatsF: BinaryTransform<Sats, Sats, Sats>,
|
||||
BitcoinF: BinaryTransform<Sats, Sats, Bitcoin>,
|
||||
DollarsF: BinaryTransform<Dollars, Dollars, Dollars>,
|
||||
{
|
||||
let sats = LazyBinaryBlockSumCum::from_derived::<SatsF>(
|
||||
name,
|
||||
version,
|
||||
height_source1.boxed_clone(),
|
||||
height_source2.boxed_clone(),
|
||||
&source1.sats,
|
||||
&source2.sats,
|
||||
);
|
||||
|
||||
let bitcoin = LazyBinaryBlockSumCum::from_derived::<BitcoinF>(
|
||||
&format!("{name}_btc"),
|
||||
version,
|
||||
height_source1,
|
||||
height_source2,
|
||||
&source1.sats,
|
||||
&source2.sats,
|
||||
);
|
||||
|
||||
let dollars = source1
|
||||
.dollars
|
||||
.as_ref()
|
||||
.zip(source2.dollars.as_ref())
|
||||
.map(|(d1, d2)| {
|
||||
LazyBinaryBlockSumCum::from_derived::<DollarsF>(
|
||||
&format!("{name}_usd"),
|
||||
version,
|
||||
d1.height_cumulative.0.boxed_clone(),
|
||||
d2.height_cumulative.0.boxed_clone(),
|
||||
d1,
|
||||
d2,
|
||||
)
|
||||
});
|
||||
|
||||
Self {
|
||||
sats,
|
||||
bitcoin,
|
||||
dollars,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_lazy<SatsF, BitcoinF, DollarsF, S1T, S2T>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source1: &LazyValueBlockSumCum<S1T, S2T>,
|
||||
source2: &LazyValueBlockSumCum<S1T, S2T>,
|
||||
) -> Self
|
||||
where
|
||||
SatsF: BinaryTransform<Sats, Sats, Sats>,
|
||||
BitcoinF: BinaryTransform<Sats, Sats, Bitcoin>,
|
||||
DollarsF: BinaryTransform<Dollars, Dollars, Dollars>,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
S2T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
let sats = LazyBinaryBlockSumCum::from_derived::<SatsF>(
|
||||
name,
|
||||
version,
|
||||
source1.sats.height.boxed_clone(),
|
||||
source2.sats.height.boxed_clone(),
|
||||
&source1.sats.rest,
|
||||
&source2.sats.rest,
|
||||
);
|
||||
|
||||
let bitcoin = LazyBinaryBlockSumCum::from_derived::<BitcoinF>(
|
||||
&format!("{name}_btc"),
|
||||
version,
|
||||
source1.sats.height.boxed_clone(),
|
||||
source2.sats.height.boxed_clone(),
|
||||
&source1.sats.rest,
|
||||
&source2.sats.rest,
|
||||
);
|
||||
|
||||
let dollars = source1
|
||||
.dollars
|
||||
.as_ref()
|
||||
.zip(source2.dollars.as_ref())
|
||||
.map(|(d1, d2)| {
|
||||
LazyBinaryBlockSumCum::from_derived::<DollarsF>(
|
||||
&format!("{name}_usd"),
|
||||
version,
|
||||
d1.height.boxed_clone(),
|
||||
d2.height.boxed_clone(),
|
||||
&d1.rest,
|
||||
&d2.rest,
|
||||
)
|
||||
});
|
||||
|
||||
Self {
|
||||
sats,
|
||||
bitcoin,
|
||||
dollars,
|
||||
}
|
||||
}
|
||||
}
|
||||
86
crates/brk_computer/src/internal/multi/value/height/full.rs
Normal file
86
crates/brk_computer/src/internal/multi/value/height/full.rs
Normal file
@@ -0,0 +1,86 @@
|
||||
//! Value type for Full pattern from Height.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Dollars, Height, Sats, Version};
|
||||
use vecdb::{Database, EagerVec, Exit, IterableCloneableVec, PcoVec};
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, indexes,
|
||||
internal::{ComputedBlockFull, LazyBlockFull, SatsToBitcoin},
|
||||
price,
|
||||
traits::ComputeFromBitcoin,
|
||||
};
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct ValueBlockFull {
|
||||
pub sats: ComputedBlockFull<Sats>,
|
||||
pub bitcoin: LazyBlockFull<Bitcoin, Sats>,
|
||||
pub dollars: Option<ComputedBlockFull<Dollars>>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl ValueBlockFull {
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
compute_dollars: bool,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let sats = ComputedBlockFull::forced_import(db, name, v, indexes)?;
|
||||
|
||||
let bitcoin = LazyBlockFull::from_computed::<SatsToBitcoin>(
|
||||
&format!("{name}_btc"),
|
||||
v,
|
||||
sats.height.boxed_clone(),
|
||||
&sats,
|
||||
);
|
||||
|
||||
let dollars = compute_dollars
|
||||
.then(|| ComputedBlockFull::forced_import(db, &format!("{name}_usd"), v, indexes))
|
||||
.transpose()?;
|
||||
|
||||
Ok(Self {
|
||||
sats,
|
||||
bitcoin,
|
||||
dollars,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
mut compute: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut EagerVec<PcoVec<Height, Sats>>) -> Result<()>,
|
||||
{
|
||||
// Compute sats
|
||||
self.sats
|
||||
.compute_all(indexes, starting_indexes, exit, |v| compute(v))?;
|
||||
|
||||
// Compute dollars from bitcoin and price (if enabled)
|
||||
if let (Some(dollars), Some(price)) = (self.dollars.as_mut(), price) {
|
||||
let height_to_bitcoin = &self.bitcoin.height;
|
||||
let height_to_price_close = &price.usd.split.close.height;
|
||||
|
||||
dollars.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_from_bitcoin(
|
||||
starting_indexes.height,
|
||||
height_to_bitcoin,
|
||||
height_to_price_close,
|
||||
exit,
|
||||
)
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
107
crates/brk_computer/src/internal/multi/value/height/last.rs
Normal file
107
crates/brk_computer/src/internal/multi/value/height/last.rs
Normal file
@@ -0,0 +1,107 @@
|
||||
//! Value type for Last pattern from Height.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Dollars, Height, Sats, Version};
|
||||
use vecdb::{Database, EagerVec, Exit, IterableCloneableVec, PcoVec};
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, indexes,
|
||||
internal::{ComputedBlockLast, LazyBlockLast, SatsToBitcoin},
|
||||
price,
|
||||
traits::ComputeFromBitcoin,
|
||||
};
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct ValueBlockLast {
|
||||
pub sats: ComputedBlockLast<Sats>,
|
||||
pub bitcoin: LazyBlockLast<Bitcoin, Sats>,
|
||||
pub dollars: Option<ComputedBlockLast<Dollars>>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl ValueBlockLast {
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
compute_dollars: bool,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let sats = ComputedBlockLast::forced_import(db, name, v, indexes)?;
|
||||
|
||||
let bitcoin = LazyBlockLast::from_computed::<SatsToBitcoin>(
|
||||
&format!("{name}_btc"),
|
||||
v,
|
||||
sats.height.boxed_clone(),
|
||||
&sats,
|
||||
);
|
||||
|
||||
let dollars = compute_dollars
|
||||
.then(|| ComputedBlockLast::forced_import(db, &format!("{name}_usd"), v, indexes))
|
||||
.transpose()?;
|
||||
|
||||
Ok(Self {
|
||||
sats,
|
||||
bitcoin,
|
||||
dollars,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
mut compute: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut EagerVec<PcoVec<Height, Sats>>) -> Result<()>,
|
||||
{
|
||||
// Compute sats (closure receives &mut height vec)
|
||||
self.sats
|
||||
.compute_all(indexes, starting_indexes, exit, |v| compute(v))?;
|
||||
|
||||
self.compute_dollars(indexes, price, starting_indexes, exit)
|
||||
}
|
||||
|
||||
/// Compute derived vecs from existing height data.
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.sats.compute_rest(indexes, starting_indexes, exit)?;
|
||||
self.compute_dollars(indexes, price, starting_indexes, exit)
|
||||
}
|
||||
|
||||
fn compute_dollars(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
if let (Some(dollars), Some(price)) = (self.dollars.as_mut(), price) {
|
||||
let height_to_bitcoin = &self.bitcoin.height;
|
||||
let height_to_price_close = &price.usd.split.close.height;
|
||||
|
||||
dollars.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_from_bitcoin(
|
||||
starting_indexes.height,
|
||||
height_to_bitcoin,
|
||||
height_to_price_close,
|
||||
exit,
|
||||
)
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
//! Lazy binary value wrapper combining height (with price) + difficultyepoch + date last transforms.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Close, Dollars, Sats, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{BinaryTransform, IterableCloneableVec, UnaryTransform};
|
||||
|
||||
use super::{LazyBlockValue, LazyTransformedValueDifficultyEpoch};
|
||||
use crate::internal::LazyValueDateLast;
|
||||
use crate::{internal::ValueBlockLast, price};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
/// Lazy binary value wrapper with height (using price binary transform) + difficultyepoch + date last transforms.
|
||||
///
|
||||
/// Use this when the height-level dollars need a binary transform (e.g., price × sats)
|
||||
/// rather than a unary transform from existing dollars.
|
||||
///
|
||||
/// No merge at this level - denominations (sats, bitcoin, dollars) stay as separate branches.
|
||||
/// Each inner field has merge which combines indexes within each denomination.
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
pub struct LazyBinaryValueBlockLast {
|
||||
#[traversable(flatten)]
|
||||
pub height: LazyBlockValue,
|
||||
#[traversable(flatten)]
|
||||
pub difficultyepoch: LazyTransformedValueDifficultyEpoch,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub dates: LazyValueDateLast,
|
||||
}
|
||||
|
||||
impl LazyBinaryValueBlockLast {
|
||||
pub fn from_block_source<SatsTransform, BitcoinTransform, HeightDollarsTransform, DateDollarsTransform>(
|
||||
name: &str,
|
||||
source: &ValueBlockLast,
|
||||
price: Option<&price::Vecs>,
|
||||
version: Version,
|
||||
) -> Self
|
||||
where
|
||||
SatsTransform: UnaryTransform<Sats, Sats>,
|
||||
BitcoinTransform: UnaryTransform<Sats, Bitcoin>,
|
||||
HeightDollarsTransform: BinaryTransform<Close<Dollars>, Sats, Dollars>,
|
||||
DateDollarsTransform: UnaryTransform<Dollars, Dollars>,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
let price_source = price.map(|p| p.usd.split.close.height.boxed_clone());
|
||||
|
||||
let height = LazyBlockValue::from_sources::<SatsTransform, BitcoinTransform, HeightDollarsTransform>(
|
||||
name,
|
||||
source.sats.height.boxed_clone(),
|
||||
price_source,
|
||||
v,
|
||||
);
|
||||
|
||||
let difficultyepoch = LazyTransformedValueDifficultyEpoch::from_block_source::<
|
||||
SatsTransform,
|
||||
BitcoinTransform,
|
||||
HeightDollarsTransform,
|
||||
>(name, source, price, v);
|
||||
|
||||
let dates = LazyValueDateLast::from_block_source::<SatsTransform, BitcoinTransform, DateDollarsTransform>(
|
||||
name, source, v,
|
||||
);
|
||||
|
||||
Self { height, difficultyepoch, dates }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Close, Dollars, Height, Sats, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{BinaryTransform, IterableBoxedVec, LazyVecFrom1, LazyVecFrom2, UnaryTransform};
|
||||
|
||||
use super::LazyDerivedBlockValue;
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyBlockValue {
|
||||
#[traversable(rename = "sats")]
|
||||
pub sats: LazyVecFrom1<Height, Sats, Height, Sats>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub rest: LazyDerivedBlockValue,
|
||||
}
|
||||
|
||||
impl LazyBlockValue {
|
||||
pub fn from_sources<SatsTransform, BitcoinTransform, DollarsTransform>(
|
||||
name: &str,
|
||||
sats_source: IterableBoxedVec<Height, Sats>,
|
||||
price_source: Option<IterableBoxedVec<Height, Close<Dollars>>>,
|
||||
version: Version,
|
||||
) -> Self
|
||||
where
|
||||
SatsTransform: UnaryTransform<Sats, Sats>,
|
||||
BitcoinTransform: UnaryTransform<Sats, Bitcoin>,
|
||||
DollarsTransform: BinaryTransform<Close<Dollars>, Sats, Dollars>,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
let sats = LazyVecFrom1::transformed::<SatsTransform>(name, v, sats_source.clone());
|
||||
|
||||
let bitcoin = LazyVecFrom1::transformed::<BitcoinTransform>(
|
||||
&format!("{name}_btc"),
|
||||
v,
|
||||
sats_source.clone(),
|
||||
);
|
||||
|
||||
let dollars = price_source.map(|price| {
|
||||
LazyVecFrom2::transformed::<DollarsTransform>(
|
||||
&format!("{name}_usd"),
|
||||
v,
|
||||
price,
|
||||
sats_source,
|
||||
)
|
||||
});
|
||||
|
||||
Self {
|
||||
sats,
|
||||
rest: LazyDerivedBlockValue { bitcoin, dollars },
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
//! Value type with stored height + lazy dollars for SumCum pattern.
|
||||
//!
|
||||
//! Use this when:
|
||||
//! - Sats height is stored (primary source of truth)
|
||||
//! - Sats indexes are derived from height
|
||||
//! - Bitcoin is lazy (transform from sats)
|
||||
//! - Dollars height is lazy (price × sats), with stored indexes
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Close, Dollars, Sats, Version};
|
||||
use vecdb::{Database, Exit, IterableCloneableVec, LazyVecFrom2};
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, indexes,
|
||||
internal::{
|
||||
ClosePriceTimesSats, ComputedBlockSumCum, LazyBlockSumCum, LazyBlockSumCumHeight,
|
||||
SatsToBitcoin,
|
||||
},
|
||||
price,
|
||||
};
|
||||
|
||||
/// Value wrapper with stored sats height + lazy dollars.
|
||||
///
|
||||
/// Sats height is stored (computed directly or from stateful loop).
|
||||
/// Dollars height is lazy (price × sats).
|
||||
/// Cumulative and dateindex aggregates are stored for both.
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct LazyComputedValueBlockSumCum {
|
||||
pub sats: ComputedBlockSumCum<Sats>,
|
||||
pub bitcoin: LazyBlockSumCum<Bitcoin, Sats>,
|
||||
pub dollars: Option<LazyBlockSumCumHeight<Dollars, Close<Dollars>, Sats>>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl LazyComputedValueBlockSumCum {
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let sats = ComputedBlockSumCum::forced_import(db, name, v, indexes)?;
|
||||
|
||||
let bitcoin = LazyBlockSumCum::from_computed::<SatsToBitcoin>(
|
||||
&format!("{name}_btc"),
|
||||
v,
|
||||
sats.height.boxed_clone(),
|
||||
&sats,
|
||||
);
|
||||
|
||||
let dollars = if let Some(price) = price {
|
||||
let dollars_height = LazyVecFrom2::transformed::<ClosePriceTimesSats>(
|
||||
&format!("{name}_usd"),
|
||||
v,
|
||||
price.usd.split.close.height.boxed_clone(),
|
||||
sats.height.boxed_clone(),
|
||||
);
|
||||
|
||||
Some(LazyBlockSumCumHeight::forced_import(
|
||||
db,
|
||||
&format!("{name}_usd"),
|
||||
v,
|
||||
indexes,
|
||||
dollars_height,
|
||||
)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
sats,
|
||||
bitcoin,
|
||||
dollars,
|
||||
})
|
||||
}
|
||||
|
||||
/// Compute rest (derived indexes) from already-computed height.
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.sats.compute_rest(indexes, starting_indexes, exit)?;
|
||||
|
||||
if let Some(dollars) = self.dollars.as_mut() {
|
||||
dollars.derive_from(indexes, starting_indexes, exit)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Close, Dollars, Height, Sats, Version};
|
||||
use vecdb::{IterableBoxedVec, LazyVecFrom1, LazyVecFrom2};
|
||||
|
||||
use crate::internal::{ClosePriceTimesSats, SatsToBitcoin};
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct LazyDerivedBlockValue {
|
||||
pub bitcoin: LazyVecFrom1<Height, Bitcoin, Height, Sats>,
|
||||
pub dollars: Option<LazyVecFrom2<Height, Dollars, Height, Close<Dollars>, Height, Sats>>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl LazyDerivedBlockValue {
|
||||
pub fn from_source(
|
||||
name: &str,
|
||||
sats_source: IterableBoxedVec<Height, Sats>,
|
||||
version: Version,
|
||||
price_source: Option<IterableBoxedVec<Height, Close<Dollars>>>,
|
||||
) -> Self {
|
||||
let bitcoin = LazyVecFrom1::transformed::<SatsToBitcoin>(
|
||||
&format!("{name}_btc"),
|
||||
version + VERSION,
|
||||
sats_source.clone(),
|
||||
);
|
||||
|
||||
let dollars = price_source.map(|price| {
|
||||
LazyVecFrom2::transformed::<ClosePriceTimesSats>(
|
||||
&format!("{name}_usd"),
|
||||
version + VERSION,
|
||||
price,
|
||||
sats_source,
|
||||
)
|
||||
});
|
||||
|
||||
Self { bitcoin, dollars }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
//! Fully lazy value types for DifficultyEpoch indexing.
|
||||
//!
|
||||
//! Two variants exist for different source patterns:
|
||||
//! - `LazyValueDifficultyEpochFromHeight`: For sources without dollars (computes from price × sats)
|
||||
//! - `LazyTransformedValueDifficultyEpoch`: For transformed views (e.g., halved supply)
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Close, DifficultyEpoch, Dollars, Height, Sats, Version};
|
||||
use vecdb::{BinaryTransform, IterableBoxedVec, IterableCloneableVec, LazyVecFrom1, LazyVecFrom2, UnaryTransform};
|
||||
|
||||
use crate::internal::{ClosePriceTimesSats, LazyLast, SatsToBitcoin};
|
||||
use crate::price;
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
/// Lazy value type at difficultyepoch level - computed from height sats + price.
|
||||
///
|
||||
/// Use this when the source only has height-indexed sats (e.g., ValueHeightDateLast).
|
||||
/// Dollars are computed via price × sats binary transform.
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct LazyValueDifficultyEpochFromHeight {
|
||||
pub sats: LazyLast<DifficultyEpoch, Sats, Height, DifficultyEpoch>,
|
||||
pub bitcoin: LazyVecFrom1<DifficultyEpoch, Bitcoin, DifficultyEpoch, Sats>,
|
||||
pub dollars: Option<LazyVecFrom2<DifficultyEpoch, Dollars, DifficultyEpoch, Close<Dollars>, DifficultyEpoch, Sats>>,
|
||||
}
|
||||
|
||||
impl LazyValueDifficultyEpochFromHeight {
|
||||
/// Create from height sats source and difficultyepoch identity.
|
||||
/// Bitcoin is derived from sats. Dollars are computed from price × sats.
|
||||
pub fn from_height_source(
|
||||
name: &str,
|
||||
height_sats: IterableBoxedVec<Height, Sats>,
|
||||
difficultyepoch_identity: IterableBoxedVec<DifficultyEpoch, DifficultyEpoch>,
|
||||
price: Option<&price::Vecs>,
|
||||
version: Version,
|
||||
) -> Self {
|
||||
let v = version + VERSION;
|
||||
|
||||
let sats = LazyLast::from_source(name, v, height_sats, difficultyepoch_identity);
|
||||
|
||||
let bitcoin = LazyVecFrom1::transformed::<SatsToBitcoin>(
|
||||
&format!("{name}_btc"),
|
||||
v,
|
||||
sats.boxed_clone(),
|
||||
);
|
||||
|
||||
let dollars = price.map(|p| {
|
||||
LazyVecFrom2::transformed::<ClosePriceTimesSats>(
|
||||
&format!("{name}_usd"),
|
||||
v,
|
||||
p.usd.split.close.difficultyepoch.boxed_clone(),
|
||||
sats.boxed_clone(),
|
||||
)
|
||||
});
|
||||
|
||||
Self { sats, bitcoin, dollars }
|
||||
}
|
||||
}
|
||||
|
||||
/// Lazy value type at difficultyepoch level - transformed from existing difficultyepoch sources.
|
||||
///
|
||||
/// Use this when creating transformed views (e.g., halved supply) from sources that
|
||||
/// already have difficultyepoch aggregations. Applies transforms to the existing aggregations.
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct LazyTransformedValueDifficultyEpoch {
|
||||
pub sats: LazyVecFrom1<DifficultyEpoch, Sats, DifficultyEpoch, Sats>,
|
||||
pub bitcoin: LazyVecFrom1<DifficultyEpoch, Bitcoin, DifficultyEpoch, Sats>,
|
||||
pub dollars: Option<LazyVecFrom2<DifficultyEpoch, Dollars, DifficultyEpoch, Close<Dollars>, DifficultyEpoch, Sats>>,
|
||||
}
|
||||
|
||||
impl LazyTransformedValueDifficultyEpoch {
|
||||
/// Create transformed difficultyepoch values from a ValueBlockLast source.
|
||||
/// SatsTransform is applied to the source's difficultyepoch sats.
|
||||
/// BitcoinTransform converts source sats to bitcoin (should combine sats transform + conversion).
|
||||
/// Dollars are computed from price × transformed sats.
|
||||
pub fn from_block_source<SatsTransform, BitcoinTransform, DollarsTransform>(
|
||||
name: &str,
|
||||
source: &super::ValueBlockLast,
|
||||
price: Option<&price::Vecs>,
|
||||
version: Version,
|
||||
) -> Self
|
||||
where
|
||||
SatsTransform: UnaryTransform<Sats, Sats>,
|
||||
BitcoinTransform: UnaryTransform<Sats, Bitcoin>,
|
||||
DollarsTransform: BinaryTransform<Close<Dollars>, Sats, Dollars>,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
let sats = LazyVecFrom1::transformed::<SatsTransform>(
|
||||
name,
|
||||
v,
|
||||
source.sats.rest.difficultyepoch.boxed_clone(),
|
||||
);
|
||||
|
||||
let bitcoin = LazyVecFrom1::transformed::<BitcoinTransform>(
|
||||
&format!("{name}_btc"),
|
||||
v,
|
||||
source.sats.rest.difficultyepoch.boxed_clone(),
|
||||
);
|
||||
|
||||
let dollars = price.map(|p| {
|
||||
LazyVecFrom2::transformed::<DollarsTransform>(
|
||||
&format!("{name}_usd"),
|
||||
v,
|
||||
p.usd.split.close.difficultyepoch.boxed_clone(),
|
||||
source.sats.rest.difficultyepoch.boxed_clone(),
|
||||
)
|
||||
});
|
||||
|
||||
Self { sats, bitcoin, dollars }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
//! Fully lazy value type for Height indexing.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Dollars, Height, Sats, Version};
|
||||
use vecdb::{IterableCloneableVec, LazyVecFrom1, UnaryTransform};
|
||||
|
||||
use crate::internal::SatsToBitcoin;
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
/// Fully lazy value type at height level.
|
||||
///
|
||||
/// All fields are lazy transforms from existing sources - no storage.
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct LazyValueBlockHeight {
|
||||
pub sats: LazyVecFrom1<Height, Sats, Height, Sats>,
|
||||
pub bitcoin: LazyVecFrom1<Height, Bitcoin, Height, Sats>,
|
||||
pub dollars: Option<LazyVecFrom1<Height, Dollars, Height, Dollars>>,
|
||||
}
|
||||
|
||||
impl LazyValueBlockHeight {
|
||||
pub fn from_block_source<SatsTransform, DollarsTransform>(
|
||||
name: &str,
|
||||
source: &super::ValueBlockLast,
|
||||
version: Version,
|
||||
) -> Self
|
||||
where
|
||||
SatsTransform: UnaryTransform<Sats, Sats>,
|
||||
DollarsTransform: UnaryTransform<Dollars, Dollars>,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
let sats =
|
||||
LazyVecFrom1::transformed::<SatsTransform>(name, v, source.sats.height.boxed_clone());
|
||||
|
||||
let bitcoin = LazyVecFrom1::transformed::<SatsToBitcoin>(
|
||||
&format!("{name}_btc"),
|
||||
v,
|
||||
source.sats.height.boxed_clone(),
|
||||
);
|
||||
|
||||
let dollars = source.dollars.as_ref().map(|d| {
|
||||
LazyVecFrom1::transformed::<DollarsTransform>(
|
||||
&format!("{name}_usd"),
|
||||
v,
|
||||
d.height.boxed_clone(),
|
||||
)
|
||||
});
|
||||
|
||||
Self { sats, bitcoin, dollars }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
//! Lazy value wrapper for ValueBlockLast - all transforms are lazy.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Dollars, Sats, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
use super::LazyValueBlockHeight;
|
||||
use crate::internal::{LazyValueDateLast, SatsToBitcoin, ValueBlockLast};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
/// Lazy value wrapper with height + date last transforms from ValueBlockLast.
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct LazyValueBlockLast {
|
||||
#[traversable(flatten)]
|
||||
pub height: LazyValueBlockHeight,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub dates: LazyValueDateLast,
|
||||
}
|
||||
|
||||
impl LazyValueBlockLast {
|
||||
pub fn from_block_source<SatsTransform, DollarsTransform>(
|
||||
name: &str,
|
||||
source: &ValueBlockLast,
|
||||
version: Version,
|
||||
) -> Self
|
||||
where
|
||||
SatsTransform: UnaryTransform<Sats, Sats>,
|
||||
DollarsTransform: UnaryTransform<Dollars, Dollars>,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
let height =
|
||||
LazyValueBlockHeight::from_block_source::<SatsTransform, DollarsTransform>(name, source, v);
|
||||
|
||||
let dates = LazyValueDateLast::from_block_source::<SatsTransform, SatsToBitcoin, DollarsTransform>(
|
||||
name, source, v,
|
||||
);
|
||||
|
||||
Self { height, dates }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
//! Value type with lazy binary height + stored derived SumCum.
|
||||
//!
|
||||
//! Use this when the height-level sats is a lazy binary transform (e.g., mask × source).
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Close, Dollars, Height, Sats, Version};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{
|
||||
BinaryTransform, Database, Exit, IterableBoxedVec, IterableCloneableVec, LazyVecFrom2,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, indexes,
|
||||
internal::{
|
||||
ClosePriceTimesSats, ComputedVecValue, LazyBlockSumCum, LazyBlockSumCumHeight,
|
||||
SatsToBitcoin,
|
||||
},
|
||||
price,
|
||||
};
|
||||
|
||||
/// Value wrapper with lazy binary height + stored derived SumCum.
|
||||
///
|
||||
/// Sats height is a lazy binary transform (e.g., mask × source).
|
||||
/// Dollars height is also lazy (price × sats).
|
||||
/// Cumulative and dateindex are stored.
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct LazyValueBlockSumCum<S1T, S2T>
|
||||
where
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
S2T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub sats: LazyBlockSumCumHeight<Sats, S1T, S2T>,
|
||||
pub bitcoin: LazyBlockSumCum<Bitcoin, Sats>,
|
||||
pub dollars: Option<LazyBlockSumCumHeight<Dollars, Close<Dollars>, Sats>>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<S1T, S2T> LazyValueBlockSumCum<S1T, S2T>
|
||||
where
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
S2T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub fn forced_import<F>(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
source1: IterableBoxedVec<Height, S1T>,
|
||||
source2: IterableBoxedVec<Height, S2T>,
|
||||
price: Option<&price::Vecs>,
|
||||
) -> Result<Self>
|
||||
where
|
||||
F: BinaryTransform<S1T, S2T, Sats>,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
let sats_height = LazyVecFrom2::transformed::<F>(name, v, source1, source2);
|
||||
let sats = LazyBlockSumCumHeight::forced_import(db, name, v, indexes, sats_height)?;
|
||||
|
||||
let bitcoin = LazyBlockSumCum::from_derived::<SatsToBitcoin>(
|
||||
&format!("{name}_btc"),
|
||||
v,
|
||||
sats.height.boxed_clone(),
|
||||
&sats.rest,
|
||||
);
|
||||
|
||||
let dollars = if let Some(price) = price {
|
||||
let dollars_height = LazyVecFrom2::transformed::<ClosePriceTimesSats>(
|
||||
&format!("{name}_usd"),
|
||||
v,
|
||||
price.usd.split.close.height.boxed_clone(),
|
||||
sats.height.boxed_clone(),
|
||||
);
|
||||
|
||||
Some(LazyBlockSumCumHeight::forced_import(
|
||||
db,
|
||||
&format!("{name}_usd"),
|
||||
v,
|
||||
indexes,
|
||||
dollars_height,
|
||||
)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
sats,
|
||||
bitcoin,
|
||||
dollars,
|
||||
})
|
||||
}
|
||||
|
||||
/// Derive aggregates from the lazy sats height source.
|
||||
pub fn derive_from(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.sats.derive_from(indexes, starting_indexes, exit)?;
|
||||
|
||||
if let Some(dollars) = self.dollars.as_mut() {
|
||||
dollars.derive_from(indexes, starting_indexes, exit)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
27
crates/brk_computer/src/internal/multi/value/height/mod.rs
Normal file
27
crates/brk_computer/src/internal/multi/value/height/mod.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
mod binary;
|
||||
mod full;
|
||||
mod last;
|
||||
mod lazy_block_value;
|
||||
mod lazy_binary_last;
|
||||
mod lazy_computed_sum_cum;
|
||||
mod lazy_derived;
|
||||
mod lazy_difficultyepoch;
|
||||
mod lazy_height;
|
||||
mod lazy_last;
|
||||
mod lazy_sum_cum;
|
||||
mod sum;
|
||||
mod sum_cum;
|
||||
|
||||
pub use binary::*;
|
||||
pub use full::*;
|
||||
pub use last::*;
|
||||
pub use lazy_block_value::*;
|
||||
pub use lazy_binary_last::*;
|
||||
pub use lazy_computed_sum_cum::*;
|
||||
pub use lazy_derived::*;
|
||||
pub use lazy_difficultyepoch::*;
|
||||
pub use lazy_height::*;
|
||||
pub use lazy_last::*;
|
||||
pub use lazy_sum_cum::*;
|
||||
pub use sum::*;
|
||||
pub use sum_cum::*;
|
||||
86
crates/brk_computer/src/internal/multi/value/height/sum.rs
Normal file
86
crates/brk_computer/src/internal/multi/value/height/sum.rs
Normal file
@@ -0,0 +1,86 @@
|
||||
//! Value type for Sum pattern from Height.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Dollars, Height, Sats, Version};
|
||||
use vecdb::{Database, EagerVec, Exit, IterableCloneableVec, PcoVec};
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, indexes,
|
||||
internal::{ComputedBlockSum, LazyBlockSum, SatsToBitcoin},
|
||||
price,
|
||||
traits::ComputeFromBitcoin,
|
||||
};
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct ValueBlockSum {
|
||||
pub sats: ComputedBlockSum<Sats>,
|
||||
pub bitcoin: LazyBlockSum<Bitcoin, Sats>,
|
||||
pub dollars: Option<ComputedBlockSum<Dollars>>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl ValueBlockSum {
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
compute_dollars: bool,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let sats = ComputedBlockSum::forced_import(db, name, v, indexes)?;
|
||||
|
||||
let bitcoin = LazyBlockSum::from_computed::<SatsToBitcoin>(
|
||||
&format!("{name}_btc"),
|
||||
v,
|
||||
sats.height.boxed_clone(),
|
||||
&sats,
|
||||
);
|
||||
|
||||
let dollars = compute_dollars
|
||||
.then(|| ComputedBlockSum::forced_import(db, &format!("{name}_usd"), v, indexes))
|
||||
.transpose()?;
|
||||
|
||||
Ok(Self {
|
||||
sats,
|
||||
bitcoin,
|
||||
dollars,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
mut compute: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut EagerVec<PcoVec<Height, Sats>>) -> Result<()>,
|
||||
{
|
||||
// Compute sats (closure receives &mut height vec)
|
||||
self.sats
|
||||
.compute_all(indexes, starting_indexes, exit, |v| compute(v))?;
|
||||
|
||||
// Compute dollars from bitcoin and price (if enabled)
|
||||
if let (Some(dollars), Some(price)) = (self.dollars.as_mut(), price) {
|
||||
let height_to_bitcoin = &self.bitcoin.height;
|
||||
let height_to_price_close = &price.usd.split.close.height;
|
||||
|
||||
dollars.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_from_bitcoin(
|
||||
starting_indexes.height,
|
||||
height_to_bitcoin,
|
||||
height_to_price_close,
|
||||
exit,
|
||||
)
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
125
crates/brk_computer/src/internal/multi/value/height/sum_cum.rs
Normal file
125
crates/brk_computer/src/internal/multi/value/height/sum_cum.rs
Normal file
@@ -0,0 +1,125 @@
|
||||
//! Value type for SumCum pattern from Height.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Dollars, Height, Sats, Version};
|
||||
use vecdb::{Database, EagerVec, Exit, IterableCloneableVec, PcoVec};
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, indexes,
|
||||
internal::{ComputedBlockSumCum, LazyBlockSumCum, SatsToBitcoin},
|
||||
price,
|
||||
traits::ComputeFromBitcoin,
|
||||
};
|
||||
use vecdb::IterableVec;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct ValueBlockSumCum {
|
||||
pub sats: ComputedBlockSumCum<Sats>,
|
||||
pub bitcoin: LazyBlockSumCum<Bitcoin, Sats>,
|
||||
pub dollars: Option<ComputedBlockSumCum<Dollars>>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl ValueBlockSumCum {
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
compute_dollars: bool,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let sats = ComputedBlockSumCum::forced_import(db, name, v, indexes)?;
|
||||
|
||||
let bitcoin = LazyBlockSumCum::from_computed::<SatsToBitcoin>(
|
||||
&format!("{name}_btc"),
|
||||
v,
|
||||
sats.height.boxed_clone(),
|
||||
&sats,
|
||||
);
|
||||
|
||||
let dollars = compute_dollars
|
||||
.then(|| ComputedBlockSumCum::forced_import(db, &format!("{name}_usd"), v, indexes))
|
||||
.transpose()?;
|
||||
|
||||
Ok(Self {
|
||||
sats,
|
||||
bitcoin,
|
||||
dollars,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
mut compute: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut EagerVec<PcoVec<Height, Sats>>) -> Result<()>,
|
||||
{
|
||||
// Compute sats (closure receives &mut height vec)
|
||||
self.sats
|
||||
.compute_all(indexes, starting_indexes, exit, |v| compute(v))?;
|
||||
|
||||
self.compute_dollars(indexes, price, starting_indexes, exit)
|
||||
}
|
||||
|
||||
/// Derive from an external height source (e.g., a LazyVec).
|
||||
pub fn derive_from(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
source: &impl IterableVec<Height, Sats>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// Derive sats from source
|
||||
self.sats
|
||||
.derive_from(indexes, starting_indexes, source, exit)?;
|
||||
|
||||
self.compute_dollars(indexes, price, starting_indexes, exit)
|
||||
}
|
||||
|
||||
/// Compute rest (derived indexes) from already-computed height.
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.sats.compute_rest(indexes, starting_indexes, exit)?;
|
||||
self.compute_dollars(indexes, price, starting_indexes, exit)
|
||||
}
|
||||
|
||||
fn compute_dollars(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// Compute dollars from bitcoin and price (if enabled)
|
||||
if let (Some(dollars), Some(price)) = (self.dollars.as_mut(), price) {
|
||||
let height_to_bitcoin = &self.bitcoin.height;
|
||||
let height_to_price_close = &price.usd.split.close.height;
|
||||
|
||||
dollars.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_from_bitcoin(
|
||||
starting_indexes.height,
|
||||
height_to_bitcoin,
|
||||
height_to_price_close,
|
||||
exit,
|
||||
)
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
9
crates/brk_computer/src/internal/multi/value/mod.rs
Normal file
9
crates/brk_computer/src/internal/multi/value/mod.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
mod date;
|
||||
mod derived_height;
|
||||
mod height;
|
||||
mod tx;
|
||||
|
||||
pub use date::*;
|
||||
pub use derived_height::*;
|
||||
pub use height::*;
|
||||
pub use tx::*;
|
||||
@@ -0,0 +1,79 @@
|
||||
//! Value type for Full pattern from TxIndex.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Sats, TxIndex, Version};
|
||||
use vecdb::{CollectableVec, Database, Exit, IterableCloneableVec};
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, indexes,
|
||||
internal::{DerivedTxFull, ValueDollarsTxFull, LazyDerivedTxFull, SatsToBitcoin},
|
||||
price,
|
||||
};
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct ValueDerivedTxFull {
|
||||
pub sats: DerivedTxFull<Sats>,
|
||||
pub bitcoin: LazyDerivedTxFull<Bitcoin, Sats>,
|
||||
pub dollars: Option<ValueDollarsTxFull>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl ValueDerivedTxFull {
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
indexer: &Indexer,
|
||||
price: Option<&price::Vecs>,
|
||||
sats_txindex: &impl IterableCloneableVec<TxIndex, Sats>,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let sats = DerivedTxFull::forced_import(db, name, v, indexes)?;
|
||||
|
||||
let bitcoin =
|
||||
LazyDerivedTxFull::from_computed::<SatsToBitcoin>(&format!("{name}_btc"), v, &sats);
|
||||
|
||||
let dollars = price
|
||||
.map(|price| {
|
||||
ValueDollarsTxFull::forced_import(
|
||||
db,
|
||||
&format!("{name}_usd"),
|
||||
v,
|
||||
indexes,
|
||||
sats_txindex.boxed_clone(),
|
||||
indexer.vecs.transactions.height.boxed_clone(),
|
||||
price.usd.split.close.height.boxed_clone(),
|
||||
)
|
||||
})
|
||||
.transpose()?;
|
||||
|
||||
Ok(Self {
|
||||
sats,
|
||||
bitcoin,
|
||||
dollars,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn derive_from(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
txindex_source: &impl CollectableVec<TxIndex, Sats>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.sats
|
||||
.derive_from(indexer, indexes, starting_indexes, txindex_source, exit)?;
|
||||
|
||||
if let Some(dollars) = self.dollars.as_mut() {
|
||||
dollars.derive_from(indexer, indexes, starting_indexes, exit)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
136
crates/brk_computer/src/internal/multi/value/tx/dollars.rs
Normal file
136
crates/brk_computer/src/internal/multi/value/tx/dollars.rs
Normal file
@@ -0,0 +1,136 @@
|
||||
//! Dollars from TxIndex with lazy txindex and eager aggregates.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
Bitcoin, Close, DateIndex, DifficultyEpoch, Dollars, Height, Sats, TxIndex, Version,
|
||||
};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{Database, Exit, IterableBoxedVec, IterableCloneableVec, LazyVecFrom3};
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, indexes,
|
||||
internal::{LazyPeriodsFull, Full, LazyFull, Stats},
|
||||
};
|
||||
|
||||
/// Lazy dollars at TxIndex: `sats * price[height]`
|
||||
pub type LazyDollarsTxIndex =
|
||||
LazyVecFrom3<TxIndex, Dollars, TxIndex, Sats, TxIndex, Height, Height, Close<Dollars>>;
|
||||
|
||||
/// Dollars with lazy txindex field and eager height/dateindex aggregates.
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct ValueDollarsTxFull {
|
||||
#[traversable(skip)]
|
||||
pub txindex: LazyDollarsTxIndex,
|
||||
pub height: Full<Height, Dollars>,
|
||||
pub difficultyepoch: LazyFull<DifficultyEpoch, Dollars, Height, DifficultyEpoch>,
|
||||
pub dateindex: Stats<DateIndex, Dollars>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub dates: LazyPeriodsFull<Dollars>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl ValueDollarsTxFull {
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
sats_txindex: IterableBoxedVec<TxIndex, Sats>,
|
||||
txindex_to_height: IterableBoxedVec<TxIndex, Height>,
|
||||
height_to_price: IterableBoxedVec<Height, Close<Dollars>>,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let txindex =
|
||||
create_lazy_txindex(name, v, sats_txindex, txindex_to_height, height_to_price);
|
||||
let height = Full::forced_import(db, name, v)?;
|
||||
let dateindex = Stats::forced_import(db, name, v)?;
|
||||
|
||||
let difficultyepoch =
|
||||
LazyFull::<DifficultyEpoch, Dollars, Height, DifficultyEpoch>::from_stats_aggregate(
|
||||
name,
|
||||
v,
|
||||
height.distribution.average.0.boxed_clone(),
|
||||
height.distribution.minmax.min.0.boxed_clone(),
|
||||
height.distribution.minmax.max.0.boxed_clone(),
|
||||
height.sum_cum.sum.0.boxed_clone(),
|
||||
height.sum_cum.cumulative.0.boxed_clone(),
|
||||
indexes.difficultyepoch.identity.boxed_clone(),
|
||||
);
|
||||
|
||||
let dates = LazyPeriodsFull::from_sources(
|
||||
name,
|
||||
v,
|
||||
dateindex.average.0.boxed_clone(),
|
||||
dateindex.minmax.min.0.boxed_clone(),
|
||||
dateindex.minmax.max.0.boxed_clone(),
|
||||
dateindex.sum_cum.sum.0.boxed_clone(),
|
||||
dateindex.sum_cum.cumulative.0.boxed_clone(),
|
||||
indexes,
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
txindex,
|
||||
height,
|
||||
difficultyepoch,
|
||||
dateindex,
|
||||
dates,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn derive_from(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.height.compute(
|
||||
starting_indexes.height,
|
||||
&self.txindex,
|
||||
&indexer.vecs.transactions.first_txindex,
|
||||
&indexes.height.txindex_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.dateindex.compute(
|
||||
starting_indexes.dateindex,
|
||||
&self.height.distribution.average.0,
|
||||
&indexes.dateindex.first_height,
|
||||
&indexes.dateindex.height_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn create_lazy_txindex(
|
||||
name: &str,
|
||||
version: Version,
|
||||
sats_txindex: IterableBoxedVec<TxIndex, Sats>,
|
||||
txindex_to_height: IterableBoxedVec<TxIndex, Height>,
|
||||
height_to_price: IterableBoxedVec<Height, Close<Dollars>>,
|
||||
) -> LazyDollarsTxIndex {
|
||||
LazyVecFrom3::init(
|
||||
&format!("{name}_txindex"),
|
||||
version,
|
||||
sats_txindex,
|
||||
txindex_to_height,
|
||||
height_to_price,
|
||||
|txindex, sats_iter, height_iter, price_iter| {
|
||||
sats_iter.get(txindex).and_then(|sats| {
|
||||
height_iter.get(txindex).and_then(|height| {
|
||||
price_iter
|
||||
.get(height)
|
||||
.map(|close| *close * Bitcoin::from(sats))
|
||||
})
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
55
crates/brk_computer/src/internal/multi/value/tx/full.rs
Normal file
55
crates/brk_computer/src/internal/multi/value/tx/full.rs
Normal file
@@ -0,0 +1,55 @@
|
||||
//! ValueTxFull - eager txindex Sats source + ValueDerivedTxFull (sats/bitcoin/dollars).
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Sats, TxIndex, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{Database, EagerVec, Exit, ImportableVec, PcoVec};
|
||||
|
||||
use crate::{ComputeIndexes, indexes, price};
|
||||
|
||||
use super::ValueDerivedTxFull;
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
pub struct ValueTxFull {
|
||||
#[traversable(rename = "txindex")]
|
||||
pub base: EagerVec<PcoVec<TxIndex, Sats>>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub indexes: ValueDerivedTxFull,
|
||||
}
|
||||
|
||||
impl ValueTxFull {
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
indexer: &Indexer,
|
||||
price: Option<&price::Vecs>,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
let txindex = EagerVec::forced_import(db, name, v)?;
|
||||
let derived =
|
||||
ValueDerivedTxFull::forced_import(db, name, v, indexes, indexer, price, &txindex)?;
|
||||
Ok(Self {
|
||||
base: txindex,
|
||||
indexes: derived,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn derive_from(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.indexes
|
||||
.derive_from(indexer, indexes, starting_indexes, &self.base, exit)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user