use std::path::Path; use brk_core::{ Bitcoin, DateIndex, DecadeIndex, DifficultyEpoch, Dollars, Height, MonthIndex, QuarterIndex, Result, Sats, SemesterIndex, TxIndex, Version, WeekIndex, YearIndex, }; use brk_exit::Exit; use brk_indexer::Indexer; use brk_vec::{ AnyCollectableVec, AnyVec, CloneableAnyIterableVec, CollectableVec, Computation, EagerVec, Format, StoredIndex, VecIterator, }; use crate::{ Indexes, fetched, grouped::{ComputedVecBuilder, Source}, indexes, }; use super::{ComputedType, EagerVecBuilder, VecBuilderOptions}; #[derive(Clone)] pub struct ComputedVecsFromTxindex where T: ComputedType + PartialOrd, { pub txindex: Option>>, pub height: EagerVecBuilder, pub dateindex: EagerVecBuilder, pub weekindex: ComputedVecBuilder, pub difficultyepoch: EagerVecBuilder, pub monthindex: ComputedVecBuilder, pub quarterindex: ComputedVecBuilder, pub semesterindex: ComputedVecBuilder, pub yearindex: ComputedVecBuilder, // TODO: pub halvingepoch: StorableVecGeneator, pub decadeindex: ComputedVecBuilder, } const VERSION: Version = Version::ZERO; impl ComputedVecsFromTxindex where T: ComputedType + Ord + From + 'static, f64: From, { #[allow(clippy::too_many_arguments)] pub fn forced_import( path: &Path, name: &str, source: Source, version: Version, format: Format, computation: Computation, indexes: &indexes::Vecs, options: VecBuilderOptions, ) -> color_eyre::Result { let txindex = source.is_compute().then(|| { Box::new( EagerVec::forced_import(path, name, version + VERSION + Version::ZERO, format) .unwrap(), ) }); let height = EagerVecBuilder::forced_import( path, name, version + VERSION + Version::ZERO, format, options, )?; let options = options.remove_percentiles(); let dateindex = EagerVecBuilder::forced_import( path, name, version + VERSION + Version::ZERO, format, options, )?; Ok(Self { weekindex: ComputedVecBuilder::forced_import( path, name, version + VERSION + Version::ZERO, format, computation, None, &dateindex, indexes.weekindex_to_weekindex.boxed_clone(), options.into(), )?, monthindex: ComputedVecBuilder::forced_import( path, name, version + VERSION + Version::ZERO, format, Computation::Lazy, None, &dateindex, indexes.monthindex_to_monthindex.boxed_clone(), options.into(), )?, quarterindex: ComputedVecBuilder::forced_import( path, name, version + VERSION + Version::ZERO, format, Computation::Lazy, None, &dateindex, indexes.quarterindex_to_quarterindex.boxed_clone(), options.into(), )?, semesterindex: ComputedVecBuilder::forced_import( path, name, version + VERSION + Version::ZERO, format, Computation::Lazy, None, &dateindex, indexes.semesterindex_to_semesterindex.boxed_clone(), options.into(), )?, yearindex: ComputedVecBuilder::forced_import( path, name, version + VERSION + Version::ZERO, format, Computation::Lazy, None, &dateindex, indexes.yearindex_to_yearindex.boxed_clone(), options.into(), )?, decadeindex: ComputedVecBuilder::forced_import( path, name, version + VERSION + Version::ZERO, format, Computation::Lazy, None, &dateindex, indexes.decadeindex_to_decadeindex.boxed_clone(), options.into(), )?, txindex, height, dateindex, difficultyepoch: EagerVecBuilder::forced_import( path, name, version + VERSION + Version::ZERO, format, options, )?, // halvingepoch: StorableVecGeneator::forced_import(path, name, version + VERSION + Version::ZERO, format, options)?, }) } // #[allow(unused)] // pub fn compute_all( // &mut self, // indexer: &Indexer, // indexes: &indexes::Vecs, // starting_indexes: &Indexes, // exit: &Exit, // mut compute: F, // ) -> color_eyre::Result<()> // where // F: FnMut( // &mut EagerVec, // &Indexer, // &indexes::Vecs, // &Indexes, // &Exit, // ) -> Result<()>, // { // compute( // self.txindex.as_mut().unwrap(), // indexer, // indexes, // starting_indexes, // exit, // )?; // let txindex: Option<&StoredVec> = None; // self.compute_rest(indexer, indexes, starting_indexes, exit, txindex)?; // Ok(()) // } pub fn compute_rest( &mut self, indexer: &Indexer, indexes: &indexes::Vecs, starting_indexes: &Indexes, exit: &Exit, txindex: Option<&impl CollectableVec>, ) -> Result<()> { if let Some(txindex) = txindex { self.height.compute( starting_indexes.height, txindex, &indexer.vecs.height_to_first_txindex, &indexes.height_to_txindex_count, exit, )?; } else { let txindex = self.txindex.as_ref().unwrap().as_ref(); self.height.compute( starting_indexes.height, txindex, &indexer.vecs.height_to_first_txindex, &indexes.height_to_txindex_count, exit, )?; } self.compute_after_height(indexes, starting_indexes, exit) } fn compute_after_height( &mut self, indexes: &indexes::Vecs, starting_indexes: &Indexes, exit: &Exit, ) -> Result<()> { self.dateindex.from_aligned( starting_indexes.dateindex, &self.height, &indexes.dateindex_to_first_height, &indexes.dateindex_to_height_count, exit, )?; self.weekindex.compute_if_necessary( starting_indexes.weekindex, &indexes.weekindex_to_first_dateindex, exit, )?; self.monthindex.compute_if_necessary( starting_indexes.monthindex, &indexes.monthindex_to_dateindex_count, exit, )?; self.quarterindex.compute_if_necessary( starting_indexes.quarterindex, &indexes.quarterindex_to_monthindex_count, exit, )?; self.semesterindex.compute_if_necessary( starting_indexes.semesterindex, &indexes.semesterindex_to_monthindex_count, exit, )?; self.yearindex.compute_if_necessary( starting_indexes.yearindex, &indexes.yearindex_to_monthindex_count, exit, )?; self.decadeindex.compute_if_necessary( starting_indexes.decadeindex, &indexes.decadeindex_to_yearindex_count, exit, )?; self.difficultyepoch.from_aligned( starting_indexes.difficultyepoch, &self.height, &indexes.difficultyepoch_to_first_height, &indexes.difficultyepoch_to_height_count, exit, )?; Ok(()) } pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> { [ self.txindex .as_ref() .map_or(vec![], |v| vec![v.as_ref() as &dyn AnyCollectableVec]), self.height.vecs(), self.dateindex.vecs(), self.weekindex.vecs(), self.difficultyepoch.vecs(), self.monthindex.vecs(), self.quarterindex.vecs(), self.semesterindex.vecs(), self.yearindex.vecs(), // self.halvingepoch.vecs(), self.decadeindex.vecs(), ] .into_iter() .flatten() .collect::>() } } impl ComputedVecsFromTxindex { pub fn compute_rest_from_sats( &mut self, indexer: &Indexer, indexes: &indexes::Vecs, starting_indexes: &Indexes, exit: &Exit, sats: &ComputedVecsFromTxindex, txindex: Option<&impl CollectableVec>, ) -> Result<()> { let txindex_version = if let Some(txindex) = txindex { txindex.version() } else { self.txindex.as_ref().unwrap().as_ref().version() }; self.height .validate_computed_version_or_reset_file(txindex_version)?; let starting_index = self.height.starting_index(starting_indexes.height); (starting_index.unwrap_to_usize()..indexer.vecs.height_to_weight.len()) .map(Height::from) .try_for_each(|height| -> Result<()> { if let Some(first) = self.height.first.as_mut() { first.forced_push_at( height, Bitcoin::from( sats.height .unwrap_first() .into_iter() .unwrap_get_inner(height), ), exit, )?; } if let Some(average) = self.height.average.as_mut() { average.forced_push_at( height, Bitcoin::from( sats.height .unwrap_average() .into_iter() .unwrap_get_inner(height), ), exit, )?; } if let Some(sum) = self.height.sum.as_mut() { sum.forced_push_at( height, Bitcoin::from( sats.height .unwrap_sum() .into_iter() .unwrap_get_inner(height), ), exit, )?; } if let Some(max) = self.height.max.as_mut() { max.forced_push_at( height, Bitcoin::from( sats.height .unwrap_max() .into_iter() .unwrap_get_inner(height), ), exit, )?; } if let Some(_90p) = self.height._90p.as_mut() { _90p.forced_push_at( height, Bitcoin::from( sats.height .unwrap_90p() .into_iter() .unwrap_get_inner(height), ), exit, )?; } if let Some(_75p) = self.height._75p.as_mut() { _75p.forced_push_at( height, Bitcoin::from( sats.height .unwrap_75p() .into_iter() .unwrap_get_inner(height), ), exit, )?; } if let Some(median) = self.height.median.as_mut() { median.forced_push_at( height, Bitcoin::from( sats.height .unwrap_median() .into_iter() .unwrap_get_inner(height), ), exit, )?; } if let Some(_25p) = self.height._25p.as_mut() { _25p.forced_push_at( height, Bitcoin::from( sats.height .unwrap_25p() .into_iter() .unwrap_get_inner(height), ), exit, )?; } if let Some(_10p) = self.height._10p.as_mut() { _10p.forced_push_at( height, Bitcoin::from( sats.height .unwrap_10p() .into_iter() .unwrap_get_inner(height), ), exit, )?; } if let Some(min) = self.height.min.as_mut() { min.forced_push_at( height, Bitcoin::from( sats.height .unwrap_min() .into_iter() .unwrap_get_inner(height), ), exit, )?; } if let Some(last) = self.height.last.as_mut() { last.forced_push_at( height, Bitcoin::from( sats.height .unwrap_last() .into_iter() .unwrap_get_inner(height), ), exit, )?; } if let Some(cumulative) = self.height.cumulative.as_mut() { cumulative.forced_push_at( height, Bitcoin::from( sats.height .unwrap_cumulative() .into_iter() .unwrap_get_inner(height), ), exit, )?; } Ok(()) })?; self.height.safe_flush(exit)?; self.compute_after_height(indexes, starting_indexes, exit) } } impl ComputedVecsFromTxindex { #[allow(clippy::too_many_arguments)] pub fn compute_rest_from_bitcoin( &mut self, indexer: &Indexer, indexes: &indexes::Vecs, starting_indexes: &Indexes, exit: &Exit, bitcoin: &ComputedVecsFromTxindex, txindex: Option<&impl CollectableVec>, fetched: &fetched::Vecs, ) -> Result<()> { let txindex_version = if let Some(txindex) = txindex { txindex.version() } else { self.txindex.as_ref().unwrap().as_ref().version() }; self.height .validate_computed_version_or_reset_file(txindex_version)?; let starting_index = self.height.starting_index(starting_indexes.height); let mut close_iter = fetched.chainindexes_to_close.height.into_iter(); (starting_index.unwrap_to_usize()..indexer.vecs.height_to_weight.len()) .map(Height::from) .try_for_each(|height| -> Result<()> { let price = *close_iter.unwrap_get_inner(height); if let Some(first) = self.height.first.as_mut() { first.forced_push_at( height, price * bitcoin .height .unwrap_first() .into_iter() .unwrap_get_inner(height), exit, )?; } if let Some(average) = self.height.average.as_mut() { average.forced_push_at( height, price * bitcoin .height .unwrap_average() .into_iter() .unwrap_get_inner(height), exit, )?; } if let Some(sum) = self.height.sum.as_mut() { sum.forced_push_at( height, price * bitcoin .height .unwrap_sum() .into_iter() .unwrap_get_inner(height), exit, )?; } if let Some(max) = self.height.max.as_mut() { max.forced_push_at( height, price * bitcoin .height .unwrap_max() .into_iter() .unwrap_get_inner(height), exit, )?; } if let Some(_90p) = self.height._90p.as_mut() { _90p.forced_push_at( height, price * bitcoin .height .unwrap_90p() .into_iter() .unwrap_get_inner(height), exit, )?; } if let Some(_75p) = self.height._75p.as_mut() { _75p.forced_push_at( height, price * bitcoin .height .unwrap_75p() .into_iter() .unwrap_get_inner(height), exit, )?; } if let Some(median) = self.height.median.as_mut() { median.forced_push_at( height, price * bitcoin .height .unwrap_median() .into_iter() .unwrap_get_inner(height), exit, )?; } if let Some(_25p) = self.height._25p.as_mut() { _25p.forced_push_at( height, price * bitcoin .height .unwrap_25p() .into_iter() .unwrap_get_inner(height), exit, )?; } if let Some(_10p) = self.height._10p.as_mut() { _10p.forced_push_at( height, price * bitcoin .height .unwrap_10p() .into_iter() .unwrap_get_inner(height), exit, )?; } if let Some(min) = self.height.min.as_mut() { min.forced_push_at( height, price * bitcoin .height .unwrap_min() .into_iter() .unwrap_get_inner(height), exit, )?; } if let Some(last) = self.height.last.as_mut() { last.forced_push_at( height, price * bitcoin .height .unwrap_last() .into_iter() .unwrap_get_inner(height), exit, )?; } if let Some(cumulative) = self.height.cumulative.as_mut() { cumulative.forced_push_at( height, price * bitcoin .height .unwrap_cumulative() .into_iter() .unwrap_get_inner(height), exit, )?; } Ok(()) })?; self.height.safe_flush(exit)?; self.compute_after_height(indexes, starting_indexes, exit) } }