use std::marker::PhantomData;
use brk_traversable::Traversable;
use brk_types::{Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{
BinaryTransform, CachedBoxedVec, DeltaAvg, LazyDeltaVec, ReadOnlyClone, ReadableCloneableVec,
UnaryTransform,
};
use crate::{
indexes,
internal::{CachedWindowStartVec, FixedRatio, LazyRollingRatioVec, NumericValue, Windows},
};
use super::LazyPercentPerBlock;
struct ReverseOperands<F>(PhantomData<F>);
impl<S, D, T, F> BinaryTransform<S, D, T> for ReverseOperands<F>
where
F: BinaryTransform<D, S, T>,
{
#[inline]
fn apply(source: S, cached: D) -> T {
F::apply(cached, source)
}
}
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(transparent)]
pub struct LazyPercentRollingWindows<B: FixedRatio>(pub Windows<LazyPercentPerBlock<B>>);
impl<B: FixedRatio> LazyPercentRollingWindows<B> {
pub(crate) fn from_cumulative_ratio<S, D, F>(
name: &str,
version: Version,
numerator: &(impl ReadableCloneableVec<Height, S> + 'static),
denominator: CachedBoxedVec<Height, D>,
cached_starts: &Windows<&CachedWindowStartVec>,
indexes: &indexes::Vecs,
) -> Self
where
S: NumericValue,
D: NumericValue,
F: BinaryTransform<S, D, B> + Send + Sync + 'static,
{
Self::from_cumulative_operands::<S, D, F>(
name,
version,
numerator,
denominator,
cached_starts,
indexes,
)
}
pub(crate) fn from_cumulative_ratio_with_denominator_transform<S, D, F>(
name: &str,
version: Version,
numerator: &(impl ReadableCloneableVec<Height, S> + 'static),
denominator: CachedBoxedVec<Height, D>,
denominator_transform: fn(Height, D) -> D,
cached_starts: &Windows<&CachedWindowStartVec>,
indexes: &indexes::Vecs,
) -> Self
where
S: NumericValue,
D: NumericValue,
F: BinaryTransform<S, D, B> + Send + Sync + 'static,
{
let source = numerator.read_only_boxed_clone();
Self(cached_starts.map_with_suffix(|suffix, cached_start| {
let full_name = format!("{name}_{suffix}");
let ratio = LazyRollingRatioVec::<S, D, B, F>::with_cached_transform(
&format!("{full_name}_{}_source", B::SUFFIX),
version,
source.clone(),
denominator.clone(),
cached_start.read_only_cached_boxed_clone(),
denominator_transform,
);
LazyPercentPerBlock::from_height_source(&full_name, version, ratio, indexes)
}))
}
pub(crate) fn from_cumulative_ratio_with_cached_numerator<S, D, F>(
name: &str,
version: Version,
numerator: CachedBoxedVec<Height, S>,
denominator: &(impl ReadableCloneableVec<Height, D> + 'static),
cached_starts: &Windows<&CachedWindowStartVec>,
indexes: &indexes::Vecs,
) -> Self
where
S: NumericValue,
D: NumericValue,
F: BinaryTransform<S, D, B> + Send + Sync + 'static,
{
Self::from_cumulative_operands::<D, S, ReverseOperands<F>>(
name,
version,
denominator,
numerator,
cached_starts,
indexes,
)
}
fn from_cumulative_operands<S, D, F>(
name: &str,
version: Version,
source: &(impl ReadableCloneableVec<Height, S> + 'static),
cached: CachedBoxedVec<Height, D>,
cached_starts: &Windows<&CachedWindowStartVec>,
indexes: &indexes::Vecs,
) -> Self
where
S: NumericValue,
D: NumericValue,
F: BinaryTransform<S, D, B> + Send + Sync + 'static,
{
let source = source.read_only_boxed_clone();
Self(cached_starts.map_with_suffix(|suffix, cached_start| {
let full_name = format!("{name}_{suffix}");
let ratio = LazyRollingRatioVec::<S, D, B, F>::new(
&format!("{full_name}_{}_source", B::SUFFIX),
version,
source.clone(),
cached.clone(),
cached_start.read_only_cached_boxed_clone(),
);
LazyPercentPerBlock::from_height_source(&full_name, version, ratio, indexes)
}))
}
pub(crate) fn from_uncached_cumulative_average<T>(
name: &str,
version: Version,
cumulative: &(impl ReadableCloneableVec<Height, T> + 'static),
cached_starts: &Windows<&CachedWindowStartVec>,
indexes: &indexes::Vecs,
) -> Self
where
T: NumericValue + JsonSchema,
{
let cumulative_source = cumulative.read_only_boxed_clone();
Self(cached_starts.map_with_suffix(|suffix, cached_start| {
let full_name = format!("{name}_{suffix}");
let cached = cached_start.read_only_clone();
let starts_version = cached.version();
let average = LazyDeltaVec::<Height, T, B, DeltaAvg>::new(
&format!("{full_name}_{}_source", B::SUFFIX),
version,
cumulative_source.clone(),
starts_version,
move || cached.cached(),
);
LazyPercentPerBlock::from_uncached_height_source(&full_name, version, average, indexes)
}))
}
pub(crate) fn from_lazy_rolling<F: UnaryTransform<B, B>>(
name: &str,
version: Version,
source: &Self,
) -> Self {
Self(source.0.map_with_suffix(|suffix, source_window| {
LazyPercentPerBlock::from_lazy_percent::<F>(
&format!("{name}_{suffix}"),
version,
source_window,
)
}))
}
}