update
This commit is contained in:
parent
313507f60e
commit
a2b24cd586
|
@ -1,4 +1,4 @@
|
|||
use super::{from_unix_millis, AdministrationRoute, Dose, Estimation, StandardDeviation};
|
||||
use super::{from_unix_millis, AdministrationRoute, Dose};
|
||||
use chrono::{DateTime, Utc};
|
||||
|
||||
#[derive(Default, PartialEq, Debug, Clone)]
|
||||
|
@ -27,31 +27,17 @@ impl From<psychonaut_journal_types::CustomUnit> for CustomUnit {
|
|||
original_unit: custom_unit.original_unit,
|
||||
|
||||
dose: {
|
||||
if let Some(dose) = custom_unit.dose {
|
||||
Dose {
|
||||
value: dose,
|
||||
contains_unknown: false,
|
||||
estimation: {
|
||||
if custom_unit.is_estimate {
|
||||
if let Some(deviation) = custom_unit.estimate_standard_deviation {
|
||||
Estimation::StandardDeviation(StandardDeviation {
|
||||
expectation: custom_unit.dose.unwrap_or_default(),
|
||||
deviation,
|
||||
})
|
||||
if custom_unit.estimate_standard_deviation.is_some() {
|
||||
Dose::new_deviation(
|
||||
custom_unit.dose.unwrap(),
|
||||
custom_unit.estimate_standard_deviation.unwrap(),
|
||||
)
|
||||
} else if custom_unit.is_estimate && custom_unit.dose.is_some() {
|
||||
Dose::new_estimate(custom_unit.dose.unwrap())
|
||||
} else if custom_unit.dose.is_some() {
|
||||
Dose::new_precise(custom_unit.dose.unwrap())
|
||||
} else {
|
||||
Estimation::Estimate
|
||||
}
|
||||
} else {
|
||||
Estimation::Precise
|
||||
}
|
||||
},
|
||||
}
|
||||
} else {
|
||||
Dose {
|
||||
value: 0.0,
|
||||
contains_unknown: true,
|
||||
estimation: Estimation::Estimate,
|
||||
}
|
||||
Dose::new_unknown()
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -65,9 +51,7 @@ impl From<psychonaut_journal_types::CustomUnit> for CustomUnit {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::types::{
|
||||
from_unix_millis, AdministrationRoute, Dose, Estimation, StandardDeviation,
|
||||
};
|
||||
use crate::types::{from_unix_millis, AdministrationRoute, Dose};
|
||||
|
||||
use super::CustomUnit;
|
||||
use psychonaut_journal_types::CustomUnit as PsychonautCustomUnit;
|
||||
|
@ -94,14 +78,7 @@ mod tests {
|
|||
substance_name: "Caffeine".to_string(),
|
||||
unit: "sip".to_string(),
|
||||
original_unit: "mg".to_string(),
|
||||
dose: Dose {
|
||||
value: 10.0,
|
||||
contains_unknown: false,
|
||||
estimation: Estimation::StandardDeviation(StandardDeviation {
|
||||
expectation: 10.0,
|
||||
deviation: 10.0
|
||||
})
|
||||
},
|
||||
dose: Dose::new_deviation(10.0, 10.0),
|
||||
administration_route: AdministrationRoute::Oral,
|
||||
creation_time: from_unix_millis(0),
|
||||
is_archived: false
|
||||
|
|
|
@ -1,11 +1,21 @@
|
|||
use super::Estimation;
|
||||
|
||||
#[derive(Default, PartialEq, Debug, Clone)]
|
||||
pub struct Dose {
|
||||
pub value: f64,
|
||||
pub value: Option<f64>,
|
||||
pub is_estimate: bool,
|
||||
pub contains_unknown: bool,
|
||||
pub estimation: Estimation,
|
||||
pub deviation: Option<f64>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Copy, Clone, Default)]
|
||||
pub enum DoseKind {
|
||||
Unknown,
|
||||
#[default]
|
||||
Precise,
|
||||
Estimate,
|
||||
StandardDeviation,
|
||||
}
|
||||
|
||||
mod add;
|
||||
mod kind;
|
||||
mod multiply;
|
||||
mod new;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::{Dose, Estimation};
|
||||
use super::Dose;
|
||||
|
||||
use std::ops::Add;
|
||||
|
||||
|
@ -30,46 +30,45 @@ impl Add<&Dose> for Dose {
|
|||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: &Self) -> Self::Output {
|
||||
let contains_unknown = self.contains_unknown || rhs.contains_unknown;
|
||||
let estimation = match self.estimation + &rhs.estimation {
|
||||
Estimation::Precise => {
|
||||
if contains_unknown {
|
||||
Estimation::Estimate
|
||||
} else {
|
||||
Estimation::Precise
|
||||
}
|
||||
}
|
||||
value => value,
|
||||
};
|
||||
|
||||
Dose {
|
||||
value: self.value + rhs.value,
|
||||
contains_unknown,
|
||||
estimation,
|
||||
value: {
|
||||
match (self.value, rhs.value) {
|
||||
(None, None) => None,
|
||||
(lhs, rhs) => Some(lhs.unwrap_or_default() + rhs.unwrap_or_default()),
|
||||
}
|
||||
},
|
||||
is_estimate: self.is_estimate || rhs.is_estimate,
|
||||
deviation: {
|
||||
match (self.deviation, rhs.deviation) {
|
||||
(None, None) => None,
|
||||
(Some(lhs), Some(rhs)) => Some(lhs + rhs),
|
||||
(Some(deviation), None) | (_, Some(deviation)) => Some(deviation),
|
||||
}
|
||||
},
|
||||
contains_unknown: {
|
||||
match (
|
||||
self.contains_unknown,
|
||||
rhs.contains_unknown,
|
||||
self.value,
|
||||
rhs.value,
|
||||
) {
|
||||
(true, _, _, _) | (_, true, _, _) | (_, _, None, _) | (_, _, _, None) => true,
|
||||
_ => false,
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::types::StandardDeviation;
|
||||
|
||||
use super::{Dose, Estimation};
|
||||
use super::Dose;
|
||||
|
||||
#[test]
|
||||
fn add() {
|
||||
let lhs = Dose {
|
||||
value: 10.0,
|
||||
..Dose::default()
|
||||
};
|
||||
let rhs = Dose {
|
||||
value: 10.0,
|
||||
..Dose::default()
|
||||
};
|
||||
let result = Dose {
|
||||
value: 20.0,
|
||||
..Dose::default()
|
||||
};
|
||||
let lhs = Dose::new_precise(10.0);
|
||||
let rhs = Dose::new_precise(10.0);
|
||||
let result = Dose::new_precise(20.0);
|
||||
|
||||
assert_eq!(lhs.clone() + rhs.clone(), result);
|
||||
assert_eq!(lhs.clone() + &rhs.clone(), result);
|
||||
|
@ -80,63 +79,24 @@ mod tests {
|
|||
#[test]
|
||||
fn add_with_estimate() {
|
||||
assert_eq!(
|
||||
Dose {
|
||||
value: 10.0,
|
||||
..Dose::default()
|
||||
} + Dose {
|
||||
value: 10.0,
|
||||
estimation: Estimation::Estimate,
|
||||
..Dose::default()
|
||||
},
|
||||
Dose {
|
||||
value: 20.0,
|
||||
estimation: Estimation::Estimate,
|
||||
..Dose::default()
|
||||
}
|
||||
Dose::new_precise(10.0) + Dose::new_estimate(10.0),
|
||||
Dose::new_estimate(20.0)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_with_unknown() {
|
||||
assert_eq!(
|
||||
Dose {
|
||||
value: 10.0,
|
||||
..Dose::default()
|
||||
} + Dose {
|
||||
value: 10.0,
|
||||
contains_unknown: true,
|
||||
..Dose::default()
|
||||
},
|
||||
Dose {
|
||||
value: 20.0,
|
||||
contains_unknown: true,
|
||||
estimation: Estimation::Estimate
|
||||
}
|
||||
Dose::new_precise(10.0) + Dose::new_unknown(),
|
||||
Dose::new_estimate_with_unknown(10.0)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_with_standard_deviation() {
|
||||
fn add_with_deviation() {
|
||||
assert_eq!(
|
||||
Dose {
|
||||
value: 10.0,
|
||||
estimation: Estimation::StandardDeviation(StandardDeviation {
|
||||
expectation: 10.0,
|
||||
deviation: 10.0,
|
||||
}),
|
||||
..Dose::default()
|
||||
} + Dose {
|
||||
value: 10.0,
|
||||
..Dose::default()
|
||||
},
|
||||
Dose {
|
||||
value: 20.0,
|
||||
contains_unknown: false,
|
||||
estimation: Estimation::StandardDeviation(StandardDeviation {
|
||||
expectation: 10.0,
|
||||
deviation: 10.0,
|
||||
}),
|
||||
}
|
||||
Dose::new_deviation(10.0, 10.0) + Dose::new_precise(10.0),
|
||||
Dose::new_deviation(20.0, 10.0),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
37
journal/src/types/dose/kind.rs
Normal file
37
journal/src/types/dose/kind.rs
Normal file
|
@ -0,0 +1,37 @@
|
|||
use super::{Dose, DoseKind};
|
||||
|
||||
impl Dose {
|
||||
pub fn kind(&self) -> DoseKind {
|
||||
if self.value.is_none() {
|
||||
assert!(self.contains_unknown);
|
||||
return DoseKind::Unknown;
|
||||
}
|
||||
|
||||
if self.is_estimate {
|
||||
if self.deviation.is_some() {
|
||||
DoseKind::StandardDeviation
|
||||
} else {
|
||||
DoseKind::Estimate
|
||||
}
|
||||
} else if self.contains_unknown {
|
||||
DoseKind::Estimate
|
||||
} else {
|
||||
DoseKind::Precise
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DoseKind {
|
||||
pub fn unknown(&self) -> bool {
|
||||
matches!(&self, DoseKind::Unknown)
|
||||
}
|
||||
pub fn precise(&self) -> bool {
|
||||
matches!(&self, DoseKind::Precise)
|
||||
}
|
||||
pub fn estimate(&self) -> bool {
|
||||
matches!(&self, DoseKind::Estimate | DoseKind::StandardDeviation)
|
||||
}
|
||||
pub fn standard_deviation(&self) -> bool {
|
||||
matches!(&self, DoseKind::StandardDeviation)
|
||||
}
|
||||
}
|
|
@ -1,6 +1,4 @@
|
|||
use crate::types::StandardDeviation;
|
||||
|
||||
use super::{Dose, Estimation};
|
||||
use super::Dose;
|
||||
|
||||
use std::ops::Mul;
|
||||
|
||||
|
@ -32,66 +30,68 @@ impl Mul<&Dose> for Dose {
|
|||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: &Self) -> Self::Output {
|
||||
let contains_unknown = self.contains_unknown || rhs.contains_unknown;
|
||||
let estimation = match (self.estimation, &rhs.estimation) {
|
||||
(Estimation::StandardDeviation(_), Estimation::StandardDeviation(_)) => {
|
||||
self.estimation * &rhs.estimation
|
||||
}
|
||||
(_, Estimation::StandardDeviation(deviation)) => {
|
||||
Estimation::StandardDeviation(StandardDeviation {
|
||||
expectation: self.value * deviation.expectation,
|
||||
deviation: deviation.deviation,
|
||||
})
|
||||
}
|
||||
(Estimation::StandardDeviation(deviation), _) => {
|
||||
Estimation::StandardDeviation(StandardDeviation {
|
||||
expectation: deviation.expectation * rhs.value,
|
||||
deviation: deviation.deviation,
|
||||
})
|
||||
}
|
||||
_ => self.estimation * &rhs.estimation,
|
||||
};
|
||||
|
||||
let estimation = match estimation {
|
||||
Estimation::Precise => {
|
||||
if contains_unknown {
|
||||
Estimation::Estimate
|
||||
} else {
|
||||
Estimation::Precise
|
||||
}
|
||||
}
|
||||
|
||||
value => value,
|
||||
};
|
||||
|
||||
Dose {
|
||||
value: self.value * rhs.value,
|
||||
contains_unknown,
|
||||
estimation,
|
||||
value: {
|
||||
match (self.value, rhs.value) {
|
||||
(Some(lhs), Some(rhs)) => Some(lhs * rhs),
|
||||
_ => None,
|
||||
}
|
||||
},
|
||||
is_estimate: self.is_estimate || rhs.is_estimate,
|
||||
deviation: {
|
||||
match (self.deviation, &rhs.deviation) {
|
||||
(Some(_), Some(_)) => {
|
||||
let lhs_deviation = self.deviation.unwrap_or_default();
|
||||
let lhs_expectation = self.value.unwrap_or_default();
|
||||
|
||||
let rhs_deviation = rhs.deviation.unwrap_or_default();
|
||||
let rhs_expectation = rhs.value.unwrap_or_default();
|
||||
|
||||
let lhs_sum = lhs_deviation.powi(2) + lhs_expectation.powi(2);
|
||||
let rhs_sum = rhs_deviation.powi(2) + rhs_expectation.powi(2);
|
||||
|
||||
let expectations = lhs_expectation.powi(2) * rhs_expectation.powi(2);
|
||||
|
||||
let product_variance = (lhs_sum * rhs_sum) - expectations;
|
||||
|
||||
if product_variance > 0.0000001 {
|
||||
let deviation = product_variance.sqrt();
|
||||
|
||||
Some(deviation.round())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
(Some(lhs), _) => Some(lhs * rhs.value.unwrap_or_default()),
|
||||
(_, Some(rhs)) => Some(rhs * self.value.unwrap_or_default()),
|
||||
_ => None,
|
||||
}
|
||||
},
|
||||
contains_unknown: {
|
||||
match (
|
||||
self.contains_unknown,
|
||||
rhs.contains_unknown,
|
||||
self.value,
|
||||
rhs.value,
|
||||
) {
|
||||
(true, _, _, _) | (_, true, _, _) | (_, _, None, _) | (_, _, _, None) => true,
|
||||
_ => false,
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::types::StandardDeviation;
|
||||
|
||||
use super::{Dose, Estimation};
|
||||
use super::Dose;
|
||||
|
||||
#[test]
|
||||
fn mul() {
|
||||
let lhs = Dose {
|
||||
value: 10.0,
|
||||
..Dose::default()
|
||||
};
|
||||
let rhs = Dose {
|
||||
value: 10.0,
|
||||
..Dose::default()
|
||||
};
|
||||
let result = Dose {
|
||||
value: 100.0,
|
||||
..Dose::default()
|
||||
};
|
||||
let lhs = Dose::new_precise(10.0);
|
||||
let rhs = Dose::new_precise(10.0);
|
||||
|
||||
let result = Dose::new_precise(100.0);
|
||||
|
||||
assert_eq!(lhs.clone() * rhs.clone(), result);
|
||||
assert_eq!(lhs.clone() * &rhs.clone(), result);
|
||||
|
@ -102,119 +102,40 @@ mod tests {
|
|||
#[test]
|
||||
fn mul_with_estimate() {
|
||||
assert_eq!(
|
||||
Dose {
|
||||
value: 10.0,
|
||||
..Dose::default()
|
||||
} * Dose {
|
||||
value: 10.0,
|
||||
estimation: Estimation::Estimate,
|
||||
..Dose::default()
|
||||
},
|
||||
Dose {
|
||||
value: 100.0,
|
||||
estimation: Estimation::Estimate,
|
||||
..Dose::default()
|
||||
}
|
||||
Dose::new_precise(10.0) * Dose::new_estimate(10.0),
|
||||
Dose::new_estimate(100.0)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mul_with_lhs_standard_deviation() {
|
||||
assert_eq!(
|
||||
Dose {
|
||||
value: 10.0,
|
||||
estimation: Estimation::StandardDeviation(StandardDeviation {
|
||||
expectation: 10.0,
|
||||
deviation: 10.0
|
||||
}),
|
||||
..Dose::default()
|
||||
} * Dose {
|
||||
value: 10.0,
|
||||
estimation: Estimation::Precise,
|
||||
..Dose::default()
|
||||
},
|
||||
Dose {
|
||||
value: 100.0,
|
||||
estimation: Estimation::StandardDeviation(StandardDeviation {
|
||||
expectation: 100.0,
|
||||
deviation: 10.0
|
||||
}),
|
||||
..Dose::default()
|
||||
}
|
||||
Dose::new_deviation(10.0, 10.0) * Dose::new_precise(10.0),
|
||||
Dose::new_deviation(100.0, 100.0)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mul_with_rhs_standard_deviation() {
|
||||
assert_eq!(
|
||||
Dose {
|
||||
value: 10.0,
|
||||
estimation: Estimation::Precise,
|
||||
..Dose::default()
|
||||
} * Dose {
|
||||
value: 10.0,
|
||||
estimation: Estimation::StandardDeviation(StandardDeviation {
|
||||
expectation: 10.0,
|
||||
deviation: 10.0
|
||||
}),
|
||||
..Dose::default()
|
||||
},
|
||||
Dose {
|
||||
value: 100.0,
|
||||
estimation: Estimation::StandardDeviation(StandardDeviation {
|
||||
expectation: 100.0,
|
||||
deviation: 10.0
|
||||
}),
|
||||
..Dose::default()
|
||||
}
|
||||
Dose::new_precise(10.0) * Dose::new_deviation(10.0, 10.0),
|
||||
Dose::new_deviation(100.0, 100.0)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mul_with_standard_deviations() {
|
||||
assert_eq!(
|
||||
Dose {
|
||||
value: 10.0,
|
||||
estimation: Estimation::StandardDeviation(StandardDeviation {
|
||||
expectation: 10.0,
|
||||
deviation: 10.0
|
||||
}),
|
||||
..Dose::default()
|
||||
} * Dose {
|
||||
value: 10.0,
|
||||
estimation: Estimation::StandardDeviation(StandardDeviation {
|
||||
expectation: 10.0,
|
||||
deviation: 10.0
|
||||
}),
|
||||
..Dose::default()
|
||||
},
|
||||
Dose {
|
||||
value: 100.0,
|
||||
estimation: Estimation::StandardDeviation(StandardDeviation {
|
||||
expectation: 100.0,
|
||||
deviation: 173.0
|
||||
}),
|
||||
..Dose::default()
|
||||
}
|
||||
Dose::new_deviation(10.0, 10.0) * Dose::new_deviation(10.0, 10.0),
|
||||
Dose::new_deviation(100.0, 173.0)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mul_with_unknown() {
|
||||
assert_eq!(
|
||||
Dose {
|
||||
value: 10.0,
|
||||
..Dose::default()
|
||||
} * Dose {
|
||||
value: 10.0,
|
||||
contains_unknown: true,
|
||||
..Dose::default()
|
||||
},
|
||||
Dose {
|
||||
value: 100.0,
|
||||
contains_unknown: true,
|
||||
estimation: Estimation::Estimate
|
||||
}
|
||||
Dose::new_precise(10.0) * Dose::new_unknown(),
|
||||
Dose::new_unknown()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
51
journal/src/types/dose/new.rs
Normal file
51
journal/src/types/dose/new.rs
Normal file
|
@ -0,0 +1,51 @@
|
|||
use super::Dose;
|
||||
|
||||
impl Dose {
|
||||
pub fn new_unknown() -> Dose {
|
||||
let value = Dose {
|
||||
value: None,
|
||||
is_estimate: true,
|
||||
contains_unknown: true,
|
||||
..Dose::default()
|
||||
};
|
||||
assert!(value.kind().unknown());
|
||||
value
|
||||
}
|
||||
pub fn new_precise(value: f64) -> Dose {
|
||||
let value = Dose {
|
||||
value: Some(value),
|
||||
..Dose::default()
|
||||
};
|
||||
assert!(value.kind().precise());
|
||||
value
|
||||
}
|
||||
pub fn new_estimate(value: f64) -> Dose {
|
||||
let value = Dose {
|
||||
value: Some(value),
|
||||
is_estimate: true,
|
||||
..Dose::default()
|
||||
};
|
||||
assert!(value.kind().estimate());
|
||||
value
|
||||
}
|
||||
pub fn new_estimate_with_unknown(value: f64) -> Dose {
|
||||
let value = Dose {
|
||||
value: Some(value),
|
||||
is_estimate: true,
|
||||
contains_unknown: true,
|
||||
..Dose::default()
|
||||
};
|
||||
assert!(value.kind().estimate());
|
||||
value
|
||||
}
|
||||
pub fn new_deviation(value: f64, deviation: f64) -> Dose {
|
||||
let value = Dose {
|
||||
value: Some(value),
|
||||
is_estimate: true,
|
||||
deviation: Some(deviation),
|
||||
..Dose::default()
|
||||
};
|
||||
assert!(value.kind().standard_deviation());
|
||||
value
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use super::{Dose, Estimation, Unit};
|
||||
use super::{Dose, Unit};
|
||||
|
||||
pub fn format_dose(dose: &Dose, unit: &Unit) -> String {
|
||||
format!("{}", DoseWithUnitRefs { dose, unit })
|
||||
|
@ -36,8 +36,8 @@ impl Display for DoseWithUnitRefs<'_> {
|
|||
|
||||
match unit {
|
||||
Unit::Simple(unit) => {
|
||||
let is_unknown = dose.contains_unknown && dose.value == 0.0;
|
||||
let is_estimate = dose.estimation.is_estimate() && !is_unknown;
|
||||
let is_unknown = dose.kind().unknown();
|
||||
let is_estimate = dose.kind().estimate();
|
||||
|
||||
if is_estimate {
|
||||
f.write_str("~")?;
|
||||
|
@ -46,7 +46,7 @@ impl Display for DoseWithUnitRefs<'_> {
|
|||
if is_unknown {
|
||||
f.write_str("Unknown")?
|
||||
} else {
|
||||
let dose_rounded = (dose.value * 100.0).round() / 100.0;
|
||||
let dose_rounded = (dose.value.unwrap() * 100.0).round() / 100.0;
|
||||
write!(f, "{}", dose_rounded)?;
|
||||
|
||||
if dose.contains_unknown {
|
||||
|
@ -54,8 +54,8 @@ impl Display for DoseWithUnitRefs<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
if let Estimation::StandardDeviation(deviation) = dose.estimation {
|
||||
write!(f, "±{}", (deviation.deviation * 100.0).round() / 100.0)?;
|
||||
if let Some(deviation) = dose.deviation {
|
||||
write!(f, "±{}", (deviation * 100.0).round() / 100.0)?;
|
||||
}
|
||||
|
||||
f.write_str((" ".to_string() + unit).as_str())
|
||||
|
@ -109,20 +109,13 @@ impl Display for DoseWithUnitRefs<'_> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::types::{AdministrationRoute, CustomUnit, StandardDeviation};
|
||||
use crate::types::{AdministrationRoute, CustomUnit};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn format_dose() {
|
||||
let result = super::format_dose(
|
||||
&Dose {
|
||||
value: 0.0,
|
||||
contains_unknown: false,
|
||||
estimation: Estimation::Precise,
|
||||
},
|
||||
&Unit::Simple("mg".to_string()),
|
||||
);
|
||||
let result = super::format_dose(&Dose::new_precise(0.0), &Unit::Simple("mg".to_string()));
|
||||
assert_eq!(result, "0 mg");
|
||||
}
|
||||
|
||||
|
@ -131,11 +124,7 @@ mod tests {
|
|||
let result = format!(
|
||||
"{}",
|
||||
DoseWithUnit {
|
||||
dose: Dose {
|
||||
value: 0.0,
|
||||
contains_unknown: false,
|
||||
estimation: Estimation::Precise,
|
||||
},
|
||||
dose: Dose::new_precise(0.0),
|
||||
unit: Unit::Simple("mg".to_string())
|
||||
}
|
||||
);
|
||||
|
@ -144,25 +133,14 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn format_dose_estimate() {
|
||||
let result = super::format_dose(
|
||||
&Dose {
|
||||
value: 0.0,
|
||||
contains_unknown: false,
|
||||
estimation: Estimation::Estimate,
|
||||
},
|
||||
&Unit::Simple("mg".to_string()),
|
||||
);
|
||||
let result = super::format_dose(&Dose::new_estimate(0.0), &Unit::Simple("mg".to_string()));
|
||||
assert_eq!(result, "~0 mg");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_dose_contains_unknown() {
|
||||
let result = super::format_dose(
|
||||
&Dose {
|
||||
value: 10.0,
|
||||
contains_unknown: true,
|
||||
estimation: Estimation::Estimate,
|
||||
},
|
||||
&(Dose::new_precise(10.0) + Dose::new_unknown()),
|
||||
&Unit::Simple("mg".to_string()),
|
||||
);
|
||||
assert_eq!(result, "~10+Unknown mg");
|
||||
|
@ -171,14 +149,7 @@ mod tests {
|
|||
#[test]
|
||||
fn format_dose_standard_deviation() {
|
||||
let result = super::format_dose(
|
||||
&Dose {
|
||||
value: 0.0,
|
||||
contains_unknown: false,
|
||||
estimation: Estimation::StandardDeviation(StandardDeviation {
|
||||
expectation: 0.0,
|
||||
deviation: 10.0,
|
||||
}),
|
||||
},
|
||||
&Dose::new_deviation(0.0, 10.0),
|
||||
&Unit::Simple("mg".to_string()),
|
||||
);
|
||||
assert_eq!(result, "~0±10 mg");
|
||||
|
@ -186,25 +157,14 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn format_unknown_dose() {
|
||||
let result = super::format_dose(
|
||||
&Dose {
|
||||
value: 0.0,
|
||||
contains_unknown: true,
|
||||
estimation: Estimation::Estimate,
|
||||
},
|
||||
&Unit::Simple("mg".to_string()),
|
||||
);
|
||||
let result = super::format_dose(&Dose::new_unknown(), &Unit::Simple("mg".to_string()));
|
||||
assert_eq!(result, "Unknown mg");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_unknown_dose_with_custom_unit() {
|
||||
let result = super::format_dose(
|
||||
&Dose {
|
||||
value: 0.0,
|
||||
contains_unknown: true,
|
||||
estimation: Estimation::Estimate,
|
||||
},
|
||||
&Dose::new_unknown(),
|
||||
&Unit::Custom {
|
||||
id: 0,
|
||||
unit: Some(CustomUnit {
|
||||
|
@ -212,11 +172,7 @@ mod tests {
|
|||
substance_name: "Caffeine".to_string(),
|
||||
unit: "sip".to_string(),
|
||||
original_unit: "mg".to_string(),
|
||||
dose: Dose {
|
||||
value: 10.0,
|
||||
contains_unknown: false,
|
||||
estimation: Estimation::Estimate,
|
||||
},
|
||||
dose: Dose::new_estimate(10.0),
|
||||
administration_route: AdministrationRoute::Oral,
|
||||
..CustomUnit::default()
|
||||
}),
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
#[derive(PartialEq, Debug, Copy, Clone, Default)]
|
||||
pub enum Estimation {
|
||||
#[default]
|
||||
Precise,
|
||||
Estimate,
|
||||
StandardDeviation(StandardDeviation),
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Default, Debug, Copy, Clone)]
|
||||
pub struct StandardDeviation {
|
||||
pub expectation: f64,
|
||||
pub deviation: f64,
|
||||
}
|
||||
|
||||
mod add;
|
||||
mod is;
|
||||
mod multiply;
|
|
@ -1,57 +0,0 @@
|
|||
use std::ops::Add;
|
||||
|
||||
use super::{Estimation, StandardDeviation};
|
||||
|
||||
impl Add<&Estimation> for Estimation {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: &Self) -> Self::Output {
|
||||
match (self, rhs) {
|
||||
(Estimation::StandardDeviation(lhs), Estimation::StandardDeviation(rhs)) => {
|
||||
Estimation::StandardDeviation(StandardDeviation {
|
||||
expectation: lhs.expectation + rhs.expectation,
|
||||
deviation: lhs.deviation + rhs.deviation,
|
||||
})
|
||||
}
|
||||
(Estimation::StandardDeviation(deviation), _) => {
|
||||
Estimation::StandardDeviation(deviation)
|
||||
}
|
||||
(_, Estimation::StandardDeviation(deviation)) => {
|
||||
Estimation::StandardDeviation(*deviation)
|
||||
}
|
||||
(Estimation::Estimate, _) | (_, Estimation::Estimate) => Estimation::Estimate,
|
||||
(Estimation::Precise, Estimation::Precise) => Estimation::Precise,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Estimation::*, StandardDeviation as Deviation};
|
||||
|
||||
#[test]
|
||||
fn add() {
|
||||
let deviation = StandardDeviation(Deviation {
|
||||
expectation: 10.0,
|
||||
deviation: 10.0,
|
||||
});
|
||||
|
||||
assert_eq!(Precise + &Precise, Precise);
|
||||
assert_eq!(Precise + &Estimate, Estimate);
|
||||
assert_eq!(Precise + &deviation, deviation);
|
||||
|
||||
assert_eq!(Estimate + &Precise, Estimate);
|
||||
assert_eq!(Estimate + &Estimate, Estimate);
|
||||
assert_eq!(Estimate + &deviation, deviation);
|
||||
|
||||
assert_eq!(deviation + &Precise, deviation);
|
||||
assert_eq!(deviation + &Estimate, deviation);
|
||||
assert_eq!(
|
||||
deviation + &deviation,
|
||||
StandardDeviation(Deviation {
|
||||
expectation: 20.0,
|
||||
deviation: 20.0,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
use super::Estimation;
|
||||
|
||||
impl Estimation {
|
||||
pub fn is_precise(&self) -> bool {
|
||||
matches!(self, Estimation::Precise)
|
||||
}
|
||||
pub fn is_estimate(&self) -> bool {
|
||||
!matches!(self, Estimation::Precise)
|
||||
}
|
||||
pub fn is_standard_deviation(&self) -> bool {
|
||||
matches!(self, Estimation::StandardDeviation(_))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Estimation::*;
|
||||
use crate::types::StandardDeviation as Deviation;
|
||||
|
||||
#[test]
|
||||
fn is() {
|
||||
let deviation = StandardDeviation(Deviation::default());
|
||||
|
||||
assert!(Precise.is_precise());
|
||||
assert!(!Precise.is_estimate());
|
||||
assert!(!Precise.is_standard_deviation());
|
||||
|
||||
assert!(!Estimate.is_precise());
|
||||
assert!(Estimate.is_estimate());
|
||||
assert!(!Estimate.is_standard_deviation());
|
||||
|
||||
assert!(!deviation.is_precise());
|
||||
assert!(deviation.is_estimate());
|
||||
assert!(deviation.is_standard_deviation());
|
||||
}
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
use std::ops::Mul;
|
||||
|
||||
use super::{Estimation, StandardDeviation};
|
||||
|
||||
impl Mul<&Estimation> for Estimation {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: &Self) -> Self::Output {
|
||||
match (self, rhs) {
|
||||
(Estimation::StandardDeviation(lhs), Estimation::StandardDeviation(rhs)) => {
|
||||
let lhs_sum = lhs.deviation.powi(2) + lhs.expectation.powi(2);
|
||||
let rhs_sum = rhs.deviation.powi(2) + rhs.expectation.powi(2);
|
||||
|
||||
let expectations = lhs.expectation.powi(2) * rhs.expectation.powi(2);
|
||||
|
||||
let product_variance = (lhs_sum * rhs_sum) - expectations;
|
||||
|
||||
if product_variance > 0.0000001 {
|
||||
let deviation = product_variance.sqrt();
|
||||
let expectation = lhs.expectation * rhs.expectation;
|
||||
|
||||
Estimation::StandardDeviation(StandardDeviation {
|
||||
expectation,
|
||||
deviation: deviation.round(),
|
||||
})
|
||||
} else {
|
||||
Estimation::Estimate
|
||||
}
|
||||
}
|
||||
(Estimation::StandardDeviation(deviation), _) => {
|
||||
Estimation::StandardDeviation(deviation)
|
||||
}
|
||||
(_, Estimation::StandardDeviation(deviation)) => {
|
||||
Estimation::StandardDeviation(*deviation)
|
||||
}
|
||||
(Estimation::Estimate, _) | (_, Estimation::Estimate) => Estimation::Estimate,
|
||||
(Estimation::Precise, Estimation::Precise) => Estimation::Precise,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Estimation::*, StandardDeviation as Deviation};
|
||||
|
||||
#[test]
|
||||
fn multiply() {
|
||||
let deviation = StandardDeviation(Deviation {
|
||||
expectation: 10.0,
|
||||
deviation: 10.0,
|
||||
});
|
||||
|
||||
assert_eq!(Precise * &Precise, Precise);
|
||||
assert_eq!(Precise * &Estimate, Estimate);
|
||||
assert_eq!(Precise * &deviation, deviation);
|
||||
|
||||
assert_eq!(Estimate * &Precise, Estimate);
|
||||
assert_eq!(Estimate * &Estimate, Estimate);
|
||||
assert_eq!(Estimate * &deviation, deviation);
|
||||
|
||||
assert_eq!(deviation * &Precise, deviation);
|
||||
assert_eq!(deviation * &Estimate, deviation);
|
||||
assert_eq!(
|
||||
deviation * &deviation,
|
||||
StandardDeviation(Deviation {
|
||||
expectation: 100.0,
|
||||
deviation: 173.0,
|
||||
})
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
StandardDeviation(Deviation {
|
||||
expectation: 100.0,
|
||||
deviation: 0.0,
|
||||
}) * &StandardDeviation(Deviation {
|
||||
expectation: 100.0,
|
||||
deviation: 0.0,
|
||||
}),
|
||||
Estimate
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,9 +1,6 @@
|
|||
use chrono::{DateTime, Utc};
|
||||
|
||||
use super::{
|
||||
dose::Dose, from_unix_millis, AdministrationRoute, Consumer, Estimation, StandardDeviation,
|
||||
Unit,
|
||||
};
|
||||
use super::{dose::Dose, from_unix_millis, AdministrationRoute, Consumer, Unit};
|
||||
|
||||
#[derive(PartialEq, Default, Debug, Clone)]
|
||||
pub struct Ingestion {
|
||||
|
@ -25,30 +22,20 @@ impl From<psychonaut_journal_types::Ingestion> for Ingestion {
|
|||
ingestion_time: from_unix_millis(ingestion.ingestion_time),
|
||||
creation_time: from_unix_millis(ingestion.creation_time),
|
||||
|
||||
dose: match ingestion.dose {
|
||||
Some(value) => Dose {
|
||||
value,
|
||||
contains_unknown: false,
|
||||
estimation: {
|
||||
if !ingestion.is_estimate {
|
||||
Estimation::Precise
|
||||
} else if let Some(deviation) = ingestion.estimate_standard_deviation {
|
||||
Estimation::StandardDeviation(StandardDeviation {
|
||||
expectation: ingestion.dose.unwrap_or_default(),
|
||||
deviation,
|
||||
})
|
||||
dose: {
|
||||
if ingestion.estimate_standard_deviation.is_some() {
|
||||
Dose::new_deviation(
|
||||
ingestion.dose.unwrap(),
|
||||
ingestion.estimate_standard_deviation.unwrap(),
|
||||
)
|
||||
} else if ingestion.is_estimate && ingestion.dose.is_some() {
|
||||
Dose::new_estimate(ingestion.dose.unwrap())
|
||||
} else if ingestion.dose.is_some() {
|
||||
Dose::new_precise(ingestion.dose.unwrap())
|
||||
} else {
|
||||
Estimation::Estimate
|
||||
Dose::new_unknown()
|
||||
}
|
||||
},
|
||||
},
|
||||
None => Dose {
|
||||
value: 0.0,
|
||||
contains_unknown: true,
|
||||
estimation: Estimation::Estimate,
|
||||
},
|
||||
},
|
||||
|
||||
unit: match ingestion.custom_unit_id {
|
||||
Some(id) => Unit::Custom { id, unit: None },
|
||||
None => Unit::Simple(ingestion.unit),
|
||||
|
@ -69,7 +56,7 @@ impl From<psychonaut_journal_types::Ingestion> for Ingestion {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::types::{from_unix_millis, AdministrationRoute, Consumer, Dose, Estimation, Unit};
|
||||
use crate::types::{from_unix_millis, AdministrationRoute, Consumer, Dose, Unit};
|
||||
|
||||
use super::Ingestion;
|
||||
use psychonaut_journal_types::Ingestion as PsychonautIngestion;
|
||||
|
@ -95,11 +82,7 @@ mod tests {
|
|||
substance_name: "Caffeine".to_string(),
|
||||
ingestion_time: from_unix_millis(0),
|
||||
creation_time: from_unix_millis(0),
|
||||
dose: Dose {
|
||||
value: 10.0,
|
||||
contains_unknown: false,
|
||||
estimation: Estimation::Precise
|
||||
},
|
||||
dose: Dose::new_precise(10.0),
|
||||
unit: Unit::Simple("mg".to_string()),
|
||||
roa: AdministrationRoute::Oral,
|
||||
consumer: Consumer::Default,
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
mod estimate;
|
||||
use chrono::{DateTime, TimeZone, Utc};
|
||||
pub use estimate::{Estimation, StandardDeviation};
|
||||
|
||||
mod dose;
|
||||
pub use dose::Dose;
|
||||
pub use dose::{Dose, DoseKind};
|
||||
|
||||
mod unit;
|
||||
pub use unit::Unit;
|
||||
|
|
Loading…
Reference in a new issue