use std::{ iter::Sum, ops::{Add, Div, Mul, Sub}, }; use allocative::Allocative; use crate::utils::{LossyFrom, TARGET_BLOCKS_PER_DAY}; use super::{ AnyDateMap, AnyHeightMap, AnyMap, Date, DateMap, Height, HeightMap, MapKind, MapPath, MapValue, }; #[derive(Allocative, Debug)] pub struct BiMap where Value: MapValue, { pub height: HeightMap, pub date: DateMap, } impl BiMap where Value: MapValue, { pub fn new_bin(version: u32, kind: MapKind, path: &MapPath) -> Self { Self { height: HeightMap::_new_bin(version, kind, path, true), date: DateMap::_new_bin(version, kind, path, false), } } pub fn new_json(version: u32, kind: MapKind, path: &MapPath) -> Self { Self { height: HeightMap::new_json(version, kind, path, true), date: DateMap::new_json(version, kind, path, false), } } // pub fn date_insert_sum_range(&mut self, date: Date, date_blocks_range: &RangeInclusive) // where // Value: Sum, // { // self.date // .insert(date, self.height.sum_range(date_blocks_range)); // } // pub fn multi_date_insert_sum_range( // &mut self, // dates: &[Date], // first_height: &mut DateMap, // last_height: &mut DateMap, // ) where // Value: Sum, // { // dates.iter().for_each(|date| { // let first_height = first_height.get_or_import(date).unwrap(); // let last_height = last_height.get_or_import(date).unwrap(); // let range = (*first_height)..=(*last_height); // self.date.insert(*date, self.height.sum_range(&range)); // }) // } pub fn multi_insert_const(&mut self, heights: &[Height], dates: &[Date], constant: Value) { self.height.multi_insert_const(heights, constant); self.date.multi_insert_const(dates, constant); } pub fn multi_insert_simple_transform( &mut self, heights: &[Height], dates: &[Date], source: &mut BiMap, transform: &F, ) where Value: Div, F: Fn(V) -> Value, V: MapValue, { self.height .multi_insert_simple_transform(heights, &mut source.height, |v, _| transform(v)); self.date .multi_insert_simple_transform(dates, &mut source.date, |v, _| transform(v)); } #[allow(unused)] pub fn multi_insert_add( &mut self, heights: &[Height], dates: &[Date], added: &mut BiMap, adder: &mut BiMap, ) where A: MapValue, B: MapValue, Value: LossyFrom + LossyFrom, Value: Add, { self.height .multi_insert_add(heights, &mut added.height, &mut adder.height); self.date .multi_insert_add(dates, &mut added.date, &mut adder.date); } pub fn multi_insert_subtract( &mut self, heights: &[Height], dates: &[Date], subtracted: &mut BiMap, subtracter: &mut BiMap, ) where A: MapValue, B: MapValue, Value: LossyFrom + LossyFrom, Value: Sub, { self.height .multi_insert_subtract(heights, &mut subtracted.height, &mut subtracter.height); self.date .multi_insert_subtract(dates, &mut subtracted.date, &mut subtracter.date); } pub fn multi_insert_multiply( &mut self, heights: &[Height], dates: &[Date], multiplied: &mut BiMap, multiplier: &mut BiMap, ) where A: MapValue, B: MapValue, Value: LossyFrom + LossyFrom, Value: Mul, { self.height .multi_insert_multiply(heights, &mut multiplied.height, &mut multiplier.height); self.date .multi_insert_multiply(dates, &mut multiplied.date, &mut multiplier.date); } pub fn multi_insert_divide( &mut self, heights: &[Height], dates: &[Date], divided: &mut BiMap, divider: &mut BiMap, ) where A: MapValue, B: MapValue, Value: LossyFrom + LossyFrom, Value: Div + Mul + From, { self.height .multi_insert_divide(heights, &mut divided.height, &mut divider.height); self.date .multi_insert_divide(dates, &mut divided.date, &mut divider.date); } pub fn multi_insert_percentage( &mut self, heights: &[Height], dates: &[Date], divided: &mut BiMap, divider: &mut BiMap, ) where A: MapValue, B: MapValue, Value: LossyFrom + LossyFrom, Value: Div + Mul + From, { self.height .multi_insert_percentage(heights, &mut divided.height, &mut divider.height); self.date .multi_insert_percentage(dates, &mut divided.date, &mut divider.date); } #[allow(unused)] pub fn multi_insert_cumulative( &mut self, heights: &[Height], dates: &[Date], source: &mut BiMap, ) where K: MapValue, Value: LossyFrom, Value: Add + Sub, { self.height .multi_insert_cumulative(heights, &mut source.height); self.date.multi_insert_cumulative(dates, &mut source.date); } pub fn multi_insert_simple_average( &mut self, heights: &[Height], dates: &[Date], source: &mut BiMap, days: usize, ) where Value: Into + From, K: MapValue + Sum, f32: LossyFrom, { self.height.multi_insert_simple_average( heights, &mut source.height, TARGET_BLOCKS_PER_DAY * days, ); self.date .multi_insert_simple_average(dates, &mut source.date, days); } pub fn multi_insert_net_change( &mut self, heights: &[Height], dates: &[Date], source: &mut BiMap, days: usize, ) where Value: Sub, { self.height.multi_insert_net_change( heights, &mut source.height, TARGET_BLOCKS_PER_DAY * days, ); self.date .multi_insert_net_change(dates, &mut source.date, days); } #[allow(unused)] pub fn multi_insert_median( &mut self, heights: &[Height], dates: &[Date], source: &mut BiMap, days: Option, ) where Value: LossyFrom, f32: LossyFrom, { self.height.multi_insert_median( heights, &mut source.height, days.map(|days| TARGET_BLOCKS_PER_DAY * days), ); self.date.multi_insert_median(dates, &mut source.date, days); } #[allow(unused)] pub fn multi_insert_percentile( &mut self, heights: &[Height], dates: &[Date], mut map_and_percentiles: Vec<(&mut BiMap, f32)>, days: Option, ) where Value: LossyFrom, f32: LossyFrom, { let mut date_map_and_percentiles = vec![]; let mut height_map_and_percentiles = vec![]; map_and_percentiles .iter_mut() .for_each(|(map, percentile)| { date_map_and_percentiles.push((&mut map.date, *percentile)); height_map_and_percentiles.push((&mut map.height, *percentile)); }); self.height.multi_insert_percentile( heights, height_map_and_percentiles, days.map(|days| TARGET_BLOCKS_PER_DAY * days), ); self.date .multi_insert_percentile(dates, date_map_and_percentiles, days); } pub fn multi_insert_max( &mut self, heights: &[Height], dates: &[Date], source: &mut BiMap, ) where Value: PartialOrd, { self.height.multi_insert_max(heights, &mut source.height); self.date.multi_insert_max(dates, &mut source.date); } pub fn kind(&self) -> MapKind { self.date.kind() } } pub trait AnyBiMap { #[allow(unused)] fn as_any_map(&self) -> Vec<&(dyn AnyMap + Send + Sync)>; fn as_any_mut_map(&mut self) -> Vec<&mut dyn AnyMap>; fn get_height(&self) -> &(dyn AnyHeightMap + Send + Sync); #[allow(unused)] fn get_mut_height(&mut self) -> &mut dyn AnyHeightMap; fn get_date(&self) -> &(dyn AnyDateMap + Send + Sync); #[allow(unused)] fn get_mut_date(&mut self) -> &mut dyn AnyDateMap; } impl AnyBiMap for BiMap where T: MapValue, { fn as_any_map(&self) -> Vec<&(dyn AnyMap + Send + Sync)> { vec![self.date.as_any_map(), self.height.as_any_map()] } fn as_any_mut_map(&mut self) -> Vec<&mut dyn AnyMap> { vec![self.date.as_any_mut_map(), self.height.as_any_mut_map()] } fn get_height(&self) -> &(dyn AnyHeightMap + Send + Sync) { &self.height } fn get_mut_height(&mut self) -> &mut dyn AnyHeightMap { &mut self.height } fn get_date(&self) -> &(dyn AnyDateMap + Send + Sync) { &self.date } fn get_mut_date(&mut self) -> &mut dyn AnyDateMap { &mut self.date } }