mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-26 15:49:58 -07:00
server: add support for .json .csv and ?all=true
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use std::{
|
||||
iter::Sum,
|
||||
ops::{Add, Div, Mul, RangeInclusive, Sub},
|
||||
ops::{Add, Div, Mul, Sub},
|
||||
};
|
||||
|
||||
use allocative::Allocative;
|
||||
@@ -36,30 +36,30 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn date_insert_sum_range(&mut self, date: Date, date_blocks_range: &RangeInclusive<u32>)
|
||||
where
|
||||
Value: Sum,
|
||||
{
|
||||
self.date
|
||||
.insert(date, self.height.sum_range(date_blocks_range));
|
||||
}
|
||||
// pub fn date_insert_sum_range(&mut self, date: Date, date_blocks_range: &RangeInclusive<u32>)
|
||||
// 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<Height>,
|
||||
last_height: &mut DateMap<Height>,
|
||||
) 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);
|
||||
// pub fn multi_date_insert_sum_range(
|
||||
// &mut self,
|
||||
// dates: &[Date],
|
||||
// first_height: &mut DateMap<Height>,
|
||||
// last_height: &mut DateMap<Height>,
|
||||
// ) 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));
|
||||
})
|
||||
}
|
||||
// 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);
|
||||
@@ -176,6 +176,7 @@ where
|
||||
.multi_insert_percentage(dates, &mut divided.date, &mut divider.date);
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn multi_insert_cumulative<K>(
|
||||
&mut self,
|
||||
heights: &[Height],
|
||||
@@ -192,27 +193,6 @@ where
|
||||
self.date.multi_insert_cumulative(dates, &mut source.date);
|
||||
}
|
||||
|
||||
pub fn multi_insert_last_x_sum<K>(
|
||||
&mut self,
|
||||
heights: &[Height],
|
||||
dates: &[Date],
|
||||
source: &mut BiMap<K>,
|
||||
days: usize,
|
||||
) where
|
||||
K: MapValue,
|
||||
Value: LossyFrom<K>,
|
||||
Value: Add<Output = Value> + Sub<Output = Value>,
|
||||
{
|
||||
self.height.multi_insert_last_x_sum(
|
||||
heights,
|
||||
&mut source.height,
|
||||
TARGET_BLOCKS_PER_DAY * days,
|
||||
);
|
||||
|
||||
self.date
|
||||
.multi_insert_last_x_sum(dates, &mut source.date, days);
|
||||
}
|
||||
|
||||
pub fn multi_insert_simple_average<K>(
|
||||
&mut self,
|
||||
heights: &[Height],
|
||||
@@ -251,6 +231,7 @@ where
|
||||
.multi_insert_net_change(dates, &mut source.date, days);
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn multi_insert_median(
|
||||
&mut self,
|
||||
heights: &[Height],
|
||||
|
||||
@@ -45,9 +45,8 @@ impl Config {
|
||||
const PATH: &'static str = "./config.toml";
|
||||
|
||||
pub fn import() -> color_eyre::Result<Self> {
|
||||
let mut config_saved =
|
||||
fs::read_to_string(Self::PATH).map_or(Config::default(), |contents| {
|
||||
dbg!(&contents);
|
||||
let mut config_saved = fs::read_to_string(Self::PATH)
|
||||
.map_or(Config::default(), |contents| {
|
||||
toml::from_str(&contents).unwrap_or_default()
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::{fmt, str::FromStr};
|
||||
use std::{cmp::Ordering, fmt, str::FromStr};
|
||||
|
||||
use allocative::{Allocative, Visitor};
|
||||
use bincode::{
|
||||
@@ -7,11 +7,13 @@ use bincode::{
|
||||
error::{DecodeError, EncodeError},
|
||||
BorrowDecode, Decode, Encode,
|
||||
};
|
||||
use chrono::{Datelike, Days, NaiveDate};
|
||||
use chrono::{Datelike, Days, NaiveDate, NaiveDateTime};
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{DateMapChunkId, MapKey};
|
||||
use crate::utils::ONE_DAY_IN_S;
|
||||
|
||||
use super::{DateMapChunkId, MapKey, Timestamp};
|
||||
|
||||
const NUMBER_OF_UNSAFE_DATES: usize = 2;
|
||||
const MIN_YEAR: i32 = 2009;
|
||||
@@ -49,6 +51,28 @@ impl Date {
|
||||
pub fn difference_in_days_between(&self, older: Self) -> u32 {
|
||||
(**self - *older).num_days() as u32
|
||||
}
|
||||
|
||||
pub fn to_timestamp(self) -> Timestamp {
|
||||
Timestamp::wrap(NaiveDateTime::from(*self).and_utc().timestamp() as u32)
|
||||
}
|
||||
|
||||
/// Returns value between 0.0 and 1.0 depending on its completion
|
||||
///
|
||||
/// Any date before today (utc) will return 1.0
|
||||
///
|
||||
/// Any date after today (utc) will panic even though it should return 0.0, as it shouldn't happen in the code
|
||||
///
|
||||
/// Any date equal to today will have a completion between 0.0 and 1.0
|
||||
pub fn get_day_completion(self) -> f64 {
|
||||
let now = Timestamp::now();
|
||||
let today = Date::today();
|
||||
|
||||
match self.cmp(&today) {
|
||||
Ordering::Less => 1.0,
|
||||
Ordering::Equal => *(now - self.to_timestamp()) as f64 / ONE_DAY_IN_S as f64,
|
||||
Ordering::Greater => unreachable!("0.0 but shouldn't be called"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MapKey<DateMapChunkId> for Date {
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
use std::iter::Sum;
|
||||
|
||||
use crate::{Date, HeightMap};
|
||||
|
||||
use super::{AnyMap, DateMapChunkId, GenericMap, Height, MapValue, SerializedBTreeMap};
|
||||
|
||||
pub type DateMap<Value> = GenericMap<Date, Value, DateMapChunkId, SerializedBTreeMap<Date, Value>>;
|
||||
|
||||
impl<T> DateMap<T>
|
||||
impl<Value> DateMap<Value>
|
||||
where
|
||||
T: MapValue,
|
||||
Value: MapValue,
|
||||
{
|
||||
pub fn multi_insert_last(
|
||||
&mut self,
|
||||
dates: &[Date],
|
||||
source: &mut HeightMap<T>,
|
||||
source: &mut HeightMap<Value>,
|
||||
last_height: &mut DateMap<Height>,
|
||||
) {
|
||||
dates.iter().for_each(|date| {
|
||||
@@ -23,6 +25,24 @@ where
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
pub fn multi_insert_sum_range(
|
||||
&mut self,
|
||||
dates: &[Date],
|
||||
height_map: &HeightMap<Value>,
|
||||
first_height: &mut DateMap<Height>,
|
||||
last_height: &mut DateMap<Height>,
|
||||
) 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.insert(*date, height_map.sum_range(&range));
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AnyDateMap: AnyMap {
|
||||
|
||||
@@ -413,11 +413,11 @@ where
|
||||
&mut self,
|
||||
keys: &[Key],
|
||||
source: &mut GenericMap<Key, SourceValue, ChunkId, SourceSerialized>,
|
||||
transform: F,
|
||||
mut transform: F,
|
||||
) where
|
||||
SourceValue: MapValue,
|
||||
SourceSerialized: MapSerialized<Key, SourceValue, ChunkId>,
|
||||
F: Fn(SourceValue, &Key) -> Value,
|
||||
F: FnMut(SourceValue, &Key) -> Value,
|
||||
{
|
||||
keys.iter().for_each(|key| {
|
||||
self.insert(*key, transform(source.get_or_import(key).unwrap(), key));
|
||||
|
||||
@@ -23,6 +23,7 @@ pub trait MapValue:
|
||||
{
|
||||
}
|
||||
|
||||
impl MapValue for u8 {}
|
||||
impl MapValue for u16 {}
|
||||
impl MapValue for u32 {}
|
||||
impl MapValue for u64 {}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
use std::{collections::BTreeMap, fmt::Debug};
|
||||
use std::{collections::BTreeMap, fmt::Debug, path::Path};
|
||||
|
||||
use allocative::Allocative;
|
||||
use bincode::{Decode, Encode};
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
|
||||
use super::{MapChunkId, MapKey, MapSerialized, MapValue};
|
||||
use crate::Serialization;
|
||||
|
||||
use super::{DateMap, MapChunkId, MapKey, MapSerialized, MapValue};
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Encode, Decode, Allocative)]
|
||||
pub struct SerializedBTreeMap<Key, Value>
|
||||
@@ -12,7 +14,37 @@ where
|
||||
Key: Ord,
|
||||
{
|
||||
version: u32,
|
||||
map: BTreeMap<Key, Value>,
|
||||
pub map: BTreeMap<Key, Value>,
|
||||
}
|
||||
|
||||
impl<Key, Value> SerializedBTreeMap<Key, Value>
|
||||
where
|
||||
Key: Ord,
|
||||
{
|
||||
pub fn import_all<ChunkId>(path: &Path, serialization: &Serialization) -> Self
|
||||
where
|
||||
Self: Debug + Serialize + DeserializeOwned + Encode + Decode,
|
||||
ChunkId: MapChunkId,
|
||||
Key: MapKey<ChunkId>,
|
||||
Value: MapValue,
|
||||
{
|
||||
let mut s = None;
|
||||
|
||||
DateMap::<usize>::_read_dir(path, serialization)
|
||||
.iter()
|
||||
.for_each(|(_, path)| {
|
||||
let map = serialization.import::<Self>(path).unwrap();
|
||||
|
||||
if s.is_none() {
|
||||
s.replace(map);
|
||||
} else {
|
||||
#[allow(clippy::unnecessary_unwrap)]
|
||||
s.as_mut().unwrap().map.extend(map.map);
|
||||
}
|
||||
});
|
||||
|
||||
s.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Key, Value, ChunkId> MapSerialized<Key, Value, ChunkId> for SerializedBTreeMap<Key, Value>
|
||||
|
||||
@@ -1,15 +1,42 @@
|
||||
use std::{cmp::Ordering, collections::BTreeMap, fmt::Debug};
|
||||
use std::{cmp::Ordering, collections::BTreeMap, fmt::Debug, path::Path};
|
||||
|
||||
use allocative::Allocative;
|
||||
use bincode::{Decode, Encode};
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
|
||||
use super::{MapChunkId, MapKey, MapSerialized, MapValue};
|
||||
use crate::Serialization;
|
||||
|
||||
use super::{HeightMap, MapChunkId, MapKey, MapSerialized, MapValue};
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Encode, Decode, Allocative)]
|
||||
pub struct SerializedVec<Value> {
|
||||
version: u32,
|
||||
map: Vec<Value>,
|
||||
pub map: Vec<Value>,
|
||||
}
|
||||
|
||||
impl<Value> SerializedVec<Value> {
|
||||
pub fn import_all(path: &Path, serialization: &Serialization) -> Self
|
||||
where
|
||||
Self: Debug + Serialize + DeserializeOwned + Encode + Decode,
|
||||
Value: MapValue,
|
||||
{
|
||||
let mut s = None;
|
||||
|
||||
HeightMap::<usize>::_read_dir(path, serialization)
|
||||
.iter()
|
||||
.for_each(|(_, path)| {
|
||||
let mut map = serialization.import::<Self>(path).unwrap();
|
||||
|
||||
if s.is_none() {
|
||||
s.replace(map);
|
||||
} else {
|
||||
#[allow(clippy::unnecessary_unwrap)]
|
||||
s.as_mut().unwrap().map.append(&mut map.map);
|
||||
}
|
||||
});
|
||||
|
||||
s.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Key, Value, ChunkId> MapSerialized<Key, Value, ChunkId> for SerializedVec<Value>
|
||||
|
||||
@@ -36,6 +36,10 @@ impl Timestamp {
|
||||
Self(timestamp)
|
||||
}
|
||||
|
||||
pub fn now() -> Self {
|
||||
Self(chrono::offset::Utc::now().timestamp() as u32)
|
||||
}
|
||||
|
||||
pub fn to_date(self) -> Date {
|
||||
Date::wrap(
|
||||
Utc.timestamp_opt(i64::from(self.0), 0)
|
||||
|
||||
Reference in New Issue
Block a user