use brk_traversable::Traversable;
use brk_types::{Dollars, Height, StoredF32, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{DeltaChange, DeltaRate, LazyDeltaVec, LazyVecFrom1, ReadableCloneableVec, VecValue};
use crate::{
indexes,
internal::{
BpsType, CachedWindowStarts, CentsType, DerivedResolutions, LazyPerBlock, NumericValue,
Percent, Resolutions, Windows,
},
};
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyDeltaFromHeight<S, T, Op: 'static>
where
S: VecValue,
T: NumericValue + JsonSchema,
{
pub height: LazyDeltaVec<Height, S, T, Op>,
#[traversable(flatten)]
pub resolutions: Box<Resolutions<T>>,
}
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(transparent)]
pub struct LazyDeltaPercentFromHeight<S, B>(
pub Percent<LazyDeltaFromHeight<S, B, DeltaRate>, LazyPerBlock<StoredF32, B>>,
)
where
S: VecValue,
B: BpsType;
#[derive(Clone, Traversable)]
pub struct LazyRollingDeltasFromHeight<S, C, B>
where
S: VecValue,
C: NumericValue + JsonSchema,
B: BpsType,
{
pub absolute: Windows<LazyDeltaFromHeight<S, C, DeltaChange>>,
pub rate: Windows<LazyDeltaPercentFromHeight<S, B>>,
}
impl<S, C, B> LazyRollingDeltasFromHeight<S, C, B>
where
S: VecValue + Into<f64>,
C: NumericValue + JsonSchema + From<f64>,
B: BpsType + From<f64>,
{
pub fn new(
name: &str,
version: Version,
source: &(impl ReadableCloneableVec<Height, S> + 'static),
cached_starts: &CachedWindowStarts,
indexes: &indexes::Vecs,
) -> Self {
let src = source.read_only_boxed_clone();
let make_slot = |suffix: &str, cached_start: &vecdb::CachedVec<Height, Height>| {
let full_name = format!("{name}_{suffix}");
let cached = cached_start.clone();
let starts_version = cached.version();
let change_vec = LazyDeltaVec::<Height, S, C, DeltaChange>::new(
&full_name,
version,
src.clone(),
starts_version,
{
let cached = cached.clone();
move || cached.get()
},
);
let change_resolutions = Resolutions::forced_import(
&full_name,
change_vec.read_only_boxed_clone(),
version,
indexes,
);
let absolute = LazyDeltaFromHeight {
height: change_vec,
resolutions: Box::new(change_resolutions),
};
let rate_bps_name = format!("{full_name}_rate_bps");
let rate_vec = LazyDeltaVec::<Height, S, B, DeltaRate>::new(
&rate_bps_name,
version,
src.clone(),
starts_version,
move || cached.get(),
);
let rate_resolutions = Resolutions::forced_import(
&rate_bps_name,
rate_vec.read_only_boxed_clone(),
version,
indexes,
);
let bps = LazyDeltaFromHeight {
height: rate_vec,
resolutions: Box::new(rate_resolutions),
};
let rate_ratio_name = format!("{full_name}_rate_ratio");
let ratio = LazyPerBlock {
height: LazyVecFrom1::transformed::<B::ToRatio>(
&rate_ratio_name,
version,
bps.height.read_only_boxed_clone(),
),
resolutions: Box::new(DerivedResolutions::from_derived_computed::<B::ToRatio>(
&rate_ratio_name,
version,
&bps.resolutions,
)),
};
let rate_name = format!("{full_name}_rate");
let percent = LazyPerBlock {
height: LazyVecFrom1::transformed::<B::ToPercent>(
&rate_name,
version,
bps.height.read_only_boxed_clone(),
),
resolutions: Box::new(DerivedResolutions::from_derived_computed::<B::ToPercent>(
&rate_name,
version,
&bps.resolutions,
)),
};
let rate = LazyDeltaPercentFromHeight(Percent {
bps,
ratio,
percent,
});
(absolute, rate)
};
let (absolute, rate) = cached_starts.0.map_with_suffix(make_slot).unzip();
Self { absolute, rate }
}
}
#[derive(Clone, Traversable)]
pub struct LazyDeltaFiatFromHeight<S, C>
where
S: VecValue,
C: CentsType,
{
pub usd: LazyPerBlock<Dollars, C>,
pub cents: LazyDeltaFromHeight<S, C, DeltaChange>,
}
#[derive(Clone, Traversable)]
pub struct LazyRollingDeltasFiatFromHeight<S, C, B>
where
S: VecValue,
C: CentsType,
B: BpsType,
{
pub absolute: Windows<LazyDeltaFiatFromHeight<S, C>>,
pub rate: Windows<LazyDeltaPercentFromHeight<S, B>>,
}
impl<S, C, B> LazyRollingDeltasFiatFromHeight<S, C, B>
where
S: VecValue + Into<f64>,
C: CentsType + From<f64>,
B: BpsType + From<f64>,
{
pub fn new(
name: &str,
version: Version,
source: &(impl ReadableCloneableVec<Height, S> + 'static),
cached_starts: &CachedWindowStarts,
indexes: &indexes::Vecs,
) -> Self {
let src = source.read_only_boxed_clone();
let make_slot = |suffix: &str, cached_start: &vecdb::CachedVec<Height, Height>| {
let full_name = format!("{name}_{suffix}");
let cached = cached_start.clone();
let starts_version = cached.version();
let cents_name = format!("{full_name}_cents");
let change_vec = LazyDeltaVec::<Height, S, C, DeltaChange>::new(
¢s_name,
version,
src.clone(),
starts_version,
{
let cached = cached.clone();
move || cached.get()
},
);
let change_resolutions = Resolutions::forced_import(
¢s_name,
change_vec.read_only_boxed_clone(),
version,
indexes,
);
let cents = LazyDeltaFromHeight {
height: change_vec,
resolutions: Box::new(change_resolutions),
};
let usd = LazyPerBlock {
height: LazyVecFrom1::transformed::<C::ToDollars>(
&full_name,
version,
cents.height.read_only_boxed_clone(),
),
resolutions: Box::new(DerivedResolutions::from_derived_computed::<C::ToDollars>(
&full_name,
version,
¢s.resolutions,
)),
};
let absolute = LazyDeltaFiatFromHeight { usd, cents };
let rate_bps_name = format!("{full_name}_rate_bps");
let rate_vec = LazyDeltaVec::<Height, S, B, DeltaRate>::new(
&rate_bps_name,
version,
src.clone(),
starts_version,
move || cached.get(),
);
let rate_resolutions = Resolutions::forced_import(
&rate_bps_name,
rate_vec.read_only_boxed_clone(),
version,
indexes,
);
let bps = LazyDeltaFromHeight {
height: rate_vec,
resolutions: Box::new(rate_resolutions),
};
let rate_ratio_name = format!("{full_name}_rate_ratio");
let ratio = LazyPerBlock {
height: LazyVecFrom1::transformed::<B::ToRatio>(
&rate_ratio_name,
version,
bps.height.read_only_boxed_clone(),
),
resolutions: Box::new(DerivedResolutions::from_derived_computed::<B::ToRatio>(
&rate_ratio_name,
version,
&bps.resolutions,
)),
};
let rate_name = format!("{full_name}_rate");
let percent = LazyPerBlock {
height: LazyVecFrom1::transformed::<B::ToPercent>(
&rate_name,
version,
bps.height.read_only_boxed_clone(),
),
resolutions: Box::new(DerivedResolutions::from_derived_computed::<B::ToPercent>(
&rate_name,
version,
&bps.resolutions,
)),
};
let rate = LazyDeltaPercentFromHeight(Percent {
bps,
ratio,
percent,
});
(absolute, rate)
};
let (absolute, rate) = cached_starts.0.map_with_suffix(make_slot).unzip();
Self { absolute, rate }
}
}