add SummaryStats util type to tidepool
This commit is contained in:
parent
517a64156a
commit
8b60c03232
|
@ -34,6 +34,95 @@ pub struct Profile {
|
||||||
// TODO: histograms about selected nodes
|
// TODO: histograms about selected nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct SummaryStats<T: Copy> {
|
||||||
|
count: usize,
|
||||||
|
min: Option<T>,
|
||||||
|
max: Option<T>,
|
||||||
|
sum: Option<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Copy> Default for SummaryStats<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
SummaryStats {
|
||||||
|
count: 0,
|
||||||
|
min: None,
|
||||||
|
max: None,
|
||||||
|
sum: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Copy> SummaryStats<T> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn count(&self) -> usize {
|
||||||
|
self.count
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn min(&self) -> Option<T> {
|
||||||
|
self.min
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn max(&self) -> Option<T> {
|
||||||
|
self.max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> SummaryStats<T>
|
||||||
|
where
|
||||||
|
T: Ord + Copy + std::ops::Add<T, Output = T>,
|
||||||
|
{
|
||||||
|
pub fn insert(&mut self, x: T) {
|
||||||
|
self.count += 1;
|
||||||
|
self.min = Some(self.min.map_or(x, |y| x.min(y)));
|
||||||
|
self.max = Some(self.max.map_or(x, |y| x.max(y)));
|
||||||
|
self.sum = Some(self.sum.map_or(x, |y| x + y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SummaryStats<f64> {
|
||||||
|
pub fn insert_f64(&mut self, x: f64) {
|
||||||
|
self.count += 1;
|
||||||
|
self.min = Some(self.min.map_or(x, |y| x.min(y)));
|
||||||
|
self.max = Some(self.max.map_or(x, |y| x.max(y)));
|
||||||
|
self.sum = Some(self.sum.map_or(x, |y| x + y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> SummaryStats<T>
|
||||||
|
where
|
||||||
|
T: Copy + std::ops::Div<usize, Output = T>,
|
||||||
|
{
|
||||||
|
pub fn avg(&self) -> Option<T> {
|
||||||
|
self.sum.map(|x| x / self.count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> SummaryStats<T>
|
||||||
|
where
|
||||||
|
T: Copy,
|
||||||
|
f64: From<T>,
|
||||||
|
{
|
||||||
|
pub fn avg_f64(&self) -> Option<f64> {
|
||||||
|
self.sum.map(|x| f64::from(x) / self.count as f64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Serialize for SummaryStats<T>
|
||||||
|
where
|
||||||
|
T: Serialize + Copy + std::ops::Div<usize, Output = T>,
|
||||||
|
{
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
ser::summary_stats(self, serializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mod ser {
|
mod ser {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -78,4 +167,27 @@ mod ser {
|
||||||
{
|
{
|
||||||
dur.as_secs_f64().serialize(serializer)
|
dur.as_secs_f64().serialize(serializer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn summary_stats<S, T>(stats: &SummaryStats<T>, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
T: Serialize + Copy + std::ops::Div<usize, Output = T>,
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct Stats<T> {
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
min: Option<T>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
max: Option<T>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
avg: Option<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
Stats {
|
||||||
|
min: stats.min,
|
||||||
|
max: stats.max,
|
||||||
|
avg: stats.avg(),
|
||||||
|
}
|
||||||
|
.serialize(serializer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue