update
This commit is contained in:
parent
13d9436d71
commit
e6ba61b8d9
67
Cargo.lock
generated
67
Cargo.lock
generated
|
@ -84,6 +84,12 @@ version = "3.16.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
|
@ -289,6 +295,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"psychonaut_journal_types",
|
"psychonaut_journal_types",
|
||||||
|
"rand",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -353,6 +360,15 @@ version = "1.20.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prettytable-rs"
|
name = "prettytable-rs"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
|
@ -406,6 +422,36 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_users"
|
name = "redox_users"
|
||||||
version = "0.4.6"
|
version = "0.4.6"
|
||||||
|
@ -706,3 +752,24 @@ name = "windows_x86_64_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.7.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.7.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
|
@ -7,3 +7,4 @@ edition = "2021"
|
||||||
serde = { version = "1.0.215", features = ["std", "derive", "serde_derive"] }
|
serde = { version = "1.0.215", features = ["std", "derive", "serde_derive"] }
|
||||||
chrono = { version = "0.4.38", features = ["serde"] }
|
chrono = { version = "0.4.38", features = ["serde"] }
|
||||||
psychonaut_journal_types = { path = "../psychonaut_journal_types" }
|
psychonaut_journal_types = { path = "../psychonaut_journal_types" }
|
||||||
|
rand = "0.8.5"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::types::{CustomUnitDose, StandardDose};
|
use crate::types::doses::{CustomUnitDose, StandardDose};
|
||||||
|
|
||||||
pub fn calulate_custom_unit_dose(
|
pub fn calulate_custom_unit_dose(
|
||||||
dose: &CustomUnitDose,
|
dose: &CustomUnitDose,
|
||||||
|
|
162
journal/src/journal.rs
Normal file
162
journal/src/journal.rs
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
use chrono::{DateTime, TimeZone, Utc};
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
|
use crate::types::{
|
||||||
|
doses::{CustomUnitDose, Dose, StandardDose, UnknownDose},
|
||||||
|
Consumer, CustomUnit, Estimation, Experience, ExportFormat, Ingestion,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub type JournalType = Box<dyn Journal>;
|
||||||
|
|
||||||
|
pub trait Journal {
|
||||||
|
fn get_custom_unit(&self, id: i64) -> Option<&CustomUnit>;
|
||||||
|
fn get_experience(&self, id: i64) -> Option<&Experience>;
|
||||||
|
fn get_experience_ingestions(&self, id: i64) -> Option<&Vec<Ingestion>>;
|
||||||
|
|
||||||
|
fn first_experience_by_title(&self, title: &str) -> Option<&Experience>;
|
||||||
|
fn maybe_custom_unit(&self, ingestion: &Ingestion) -> Option<&CustomUnit>;
|
||||||
|
|
||||||
|
fn import_psychonaut(&mut self, data: psychonaut_journal_types::ExportData);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type InMemJournal = ExportFormat;
|
||||||
|
|
||||||
|
impl Journal for InMemJournal {
|
||||||
|
fn get_custom_unit(&self, id: i64) -> Option<&CustomUnit> {
|
||||||
|
self.custom_units.get(&id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_experience(&self, id: i64) -> Option<&Experience> {
|
||||||
|
self.experiences.get(&id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_experience_ingestions(&self, id: i64) -> Option<&Vec<Ingestion>> {
|
||||||
|
self.ingestions.get(&id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn maybe_custom_unit(&self, ingestion: &Ingestion) -> Option<&CustomUnit> {
|
||||||
|
match &ingestion.dose {
|
||||||
|
Dose::CustomUnit(dose) => self.get_custom_unit(dose.custom_unit_id),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn first_experience_by_title(&self, title: &str) -> Option<&Experience> {
|
||||||
|
self.experiences
|
||||||
|
.values()
|
||||||
|
.find(|&experience| &experience.title == title)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn import_psychonaut(&mut self, data: psychonaut_journal_types::ExportData) {
|
||||||
|
fn from_unix_millis(time: u64) -> DateTime<Utc> {
|
||||||
|
Utc.timestamp_millis_opt(time as i64).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
|
for custom_unit in data.custom_units.into_iter() {
|
||||||
|
let estimation = if custom_unit.is_estimate {
|
||||||
|
if let Some(standard_deviation) = custom_unit.estimate_standard_deviation {
|
||||||
|
Estimation::StandardDeviation(standard_deviation)
|
||||||
|
} else {
|
||||||
|
Estimation::Estimate
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Estimation::Precise
|
||||||
|
};
|
||||||
|
|
||||||
|
let dose = CustomUnitDose {
|
||||||
|
dose: custom_unit.dose,
|
||||||
|
unit: custom_unit.unit,
|
||||||
|
original_unit: custom_unit.original_unit,
|
||||||
|
custom_unit_id: custom_unit.id,
|
||||||
|
estimation,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.custom_units.insert(
|
||||||
|
custom_unit.id,
|
||||||
|
CustomUnit {
|
||||||
|
id: custom_unit.id,
|
||||||
|
name: custom_unit.name,
|
||||||
|
substance_name: custom_unit.substance_name,
|
||||||
|
|
||||||
|
administration_route: custom_unit.administration_route,
|
||||||
|
dose,
|
||||||
|
|
||||||
|
creation_time: from_unix_millis(custom_unit.creation_time),
|
||||||
|
is_archived: custom_unit.is_archived,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for experience in data.experiences.into_iter() {
|
||||||
|
let experience_id = rng.gen::<i64>();
|
||||||
|
|
||||||
|
let mut ingestions: Vec<Ingestion> = Vec::new();
|
||||||
|
for ingestion in experience.ingestions.into_iter() {
|
||||||
|
let estimation = if !ingestion.is_estimate {
|
||||||
|
Estimation::Precise
|
||||||
|
} else if let Some(standard_deviation) = ingestion.estimate_standard_deviation {
|
||||||
|
Estimation::StandardDeviation(standard_deviation)
|
||||||
|
} else {
|
||||||
|
Estimation::Estimate
|
||||||
|
};
|
||||||
|
|
||||||
|
let dose = if let Some(dose) = ingestion.dose {
|
||||||
|
if let Some(custom_unit_id) = ingestion.custom_unit_id {
|
||||||
|
let custom_unit = self
|
||||||
|
.custom_units
|
||||||
|
.get(&custom_unit_id)
|
||||||
|
.expect("custom unit not found");
|
||||||
|
|
||||||
|
Dose::CustomUnit(CustomUnitDose {
|
||||||
|
dose,
|
||||||
|
unit: custom_unit.dose.unit.clone(),
|
||||||
|
original_unit: custom_unit.dose.original_unit.clone(),
|
||||||
|
estimation,
|
||||||
|
custom_unit_id,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Dose::Standard(StandardDose {
|
||||||
|
dose,
|
||||||
|
unit: ingestion.unit,
|
||||||
|
estimation,
|
||||||
|
contains_unknown: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Dose::Unknown(UnknownDose {
|
||||||
|
unit: ingestion.unit,
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
ingestions.push(Ingestion {
|
||||||
|
substance_name: ingestion.substance_name,
|
||||||
|
ingestion_time: from_unix_millis(ingestion.ingestion_time),
|
||||||
|
creation_time: from_unix_millis(ingestion.creation_time),
|
||||||
|
dose,
|
||||||
|
roa: ingestion.roa,
|
||||||
|
consumer: match ingestion.consumer_name {
|
||||||
|
Some(name) => Consumer::Named(name),
|
||||||
|
None => Consumer::Default,
|
||||||
|
},
|
||||||
|
notes: ingestion.notes,
|
||||||
|
stomach_fullness: ingestion.stomach_fullness,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
self.ingestions.insert(experience_id, ingestions);
|
||||||
|
|
||||||
|
self.experiences.insert(
|
||||||
|
experience_id,
|
||||||
|
Experience {
|
||||||
|
id: experience_id,
|
||||||
|
title: experience.title,
|
||||||
|
text: experience.text,
|
||||||
|
creation_time: from_unix_millis(experience.creation_time),
|
||||||
|
modified_time: from_unix_millis(experience.modified_time),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,2 +1,3 @@
|
||||||
pub mod helpers;
|
pub mod helpers;
|
||||||
|
pub mod journal;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
|
|
@ -1,345 +0,0 @@
|
||||||
use chrono::{DateTime, TimeZone, Utc};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::fmt::{Debug, Display};
|
|
||||||
use std::ops::{Add, Mul};
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
pub type AdministrationRoute = psychonaut_journal_types::AdministrationRoute;
|
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Copy, Clone)]
|
|
||||||
pub enum Estimation {
|
|
||||||
Precise,
|
|
||||||
Estimate,
|
|
||||||
StandardDeviation(f64),
|
|
||||||
}
|
|
||||||
|
|
||||||
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(_))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Add for Estimation {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
fn add(self, rhs: Self) -> Self::Output {
|
|
||||||
match (self, rhs) {
|
|
||||||
(Estimation::StandardDeviation(x), Estimation::StandardDeviation(y)) => {
|
|
||||||
Estimation::StandardDeviation(x + y)
|
|
||||||
}
|
|
||||||
(Estimation::StandardDeviation(x), _) | (_, Estimation::StandardDeviation(x)) => {
|
|
||||||
Estimation::StandardDeviation(x)
|
|
||||||
}
|
|
||||||
(Estimation::Estimate, _) | (_, Estimation::Estimate) => Estimation::Estimate,
|
|
||||||
(Estimation::Precise, Estimation::Precise) => Estimation::Precise,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mul for Estimation {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
fn mul(self, rhs: Self) -> Self::Output {
|
|
||||||
match (self, rhs) {
|
|
||||||
(Estimation::StandardDeviation(x), Estimation::StandardDeviation(y)) => {
|
|
||||||
Estimation::StandardDeviation(x * y)
|
|
||||||
}
|
|
||||||
(Estimation::StandardDeviation(x), _) | (_, Estimation::StandardDeviation(x)) => {
|
|
||||||
Estimation::StandardDeviation(x)
|
|
||||||
}
|
|
||||||
(Estimation::Estimate, _) | (_, Estimation::Estimate) => Estimation::Estimate,
|
|
||||||
(Estimation::Precise, Estimation::Precise) => Estimation::Precise,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct UnknownDose {
|
|
||||||
pub unit: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct StandardDose {
|
|
||||||
pub dose: f64,
|
|
||||||
pub unit: String,
|
|
||||||
pub contains_unknown: bool,
|
|
||||||
pub estimation: Estimation,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Add for StandardDose {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
fn add(self, rhs: Self) -> Self::Output {
|
|
||||||
StandardDose {
|
|
||||||
dose: self.dose + rhs.dose,
|
|
||||||
unit: self.unit,
|
|
||||||
contains_unknown: self.contains_unknown || rhs.contains_unknown,
|
|
||||||
estimation: self.estimation + rhs.estimation,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mul for StandardDose {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
fn mul(self, rhs: Self) -> Self::Output {
|
|
||||||
StandardDose {
|
|
||||||
dose: self.dose * rhs.dose,
|
|
||||||
unit: self.unit,
|
|
||||||
contains_unknown: self.contains_unknown || rhs.contains_unknown,
|
|
||||||
estimation: {
|
|
||||||
let estimation = self.estimation + rhs.estimation;
|
|
||||||
if let Estimation::StandardDeviation(deviation) = estimation {
|
|
||||||
Estimation::StandardDeviation(deviation * rhs.dose)
|
|
||||||
} else {
|
|
||||||
estimation
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<CustomUnitDose> for StandardDose {
|
|
||||||
fn from(value: CustomUnitDose) -> StandardDose {
|
|
||||||
StandardDose {
|
|
||||||
dose: value.dose,
|
|
||||||
unit: value.original_unit,
|
|
||||||
contains_unknown: false,
|
|
||||||
estimation: value.estimation,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct CustomUnitDose {
|
|
||||||
pub dose: f64,
|
|
||||||
pub unit: String,
|
|
||||||
pub original_unit: String,
|
|
||||||
pub estimation: Estimation,
|
|
||||||
pub custom_unit_id: i64,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum Dose {
|
|
||||||
Unknown(UnknownDose),
|
|
||||||
Standard(StandardDose),
|
|
||||||
CustomUnit(CustomUnitDose),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Clone)]
|
|
||||||
pub enum Consumer {
|
|
||||||
Default,
|
|
||||||
Named(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for Consumer {
|
|
||||||
type Err = core::convert::Infallible;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
if s == "default" {
|
|
||||||
Ok(Consumer::Default)
|
|
||||||
} else {
|
|
||||||
Ok(Consumer::Named(s.to_string()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for Consumer {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
Consumer::Default => f.write_str("default"),
|
|
||||||
Consumer::Named(name) => f.write_str(name),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Ingestion {
|
|
||||||
pub substance_name: String,
|
|
||||||
pub ingestion_time: DateTime<Utc>,
|
|
||||||
pub creation_time: DateTime<Utc>,
|
|
||||||
pub dose: Dose,
|
|
||||||
pub roa: AdministrationRoute,
|
|
||||||
pub consumer: Consumer,
|
|
||||||
pub notes: String,
|
|
||||||
pub stomach_fullness: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct CustomSubstance {
|
|
||||||
pub name: String,
|
|
||||||
pub description: String,
|
|
||||||
pub units: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Experience {
|
|
||||||
pub title: String,
|
|
||||||
pub text: String,
|
|
||||||
pub creation_time: DateTime<Utc>,
|
|
||||||
pub modified_time: DateTime<Utc>,
|
|
||||||
pub ingestions: Vec<Ingestion>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct CustomUnit {
|
|
||||||
pub id: i64,
|
|
||||||
pub name: String,
|
|
||||||
pub substance_name: String,
|
|
||||||
|
|
||||||
pub administration_route: AdministrationRoute,
|
|
||||||
pub dose: CustomUnitDose,
|
|
||||||
|
|
||||||
pub creation_time: DateTime<Utc>,
|
|
||||||
pub is_archived: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
|
||||||
pub struct Journal {
|
|
||||||
pub experiences: Vec<Experience>,
|
|
||||||
//pub substance_colours: HashMap<String, String>,
|
|
||||||
//pub custom_substances: HashMap<String, CustomSubstance>,
|
|
||||||
pub custom_units: HashMap<i64, CustomUnit>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Journal {
|
|
||||||
pub fn get_custom_unit(&self, id: i64) -> Option<CustomUnit> {
|
|
||||||
self.custom_units.get(&id).cloned()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn maybe_custom_unit(&self, ingestion: &Ingestion) -> Option<CustomUnit> {
|
|
||||||
match &ingestion.dose {
|
|
||||||
Dose::CustomUnit(dose) => self.get_custom_unit(dose.custom_unit_id),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn first_experience_by_title(&self, title: &String) -> Option<Experience> {
|
|
||||||
for experience in self.experiences.iter() {
|
|
||||||
if &experience.title == title {
|
|
||||||
return Some(experience.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn import(data: psychonaut_journal_types::ExportData) -> Self {
|
|
||||||
fn from_unix_millis(time: u64) -> DateTime<Utc> {
|
|
||||||
Utc.timestamp_millis_opt(time as i64).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut journal = Journal::default();
|
|
||||||
|
|
||||||
for custom_unit in data.custom_units.into_iter() {
|
|
||||||
journal.custom_units.insert(
|
|
||||||
custom_unit.id,
|
|
||||||
CustomUnit {
|
|
||||||
id: custom_unit.id,
|
|
||||||
name: custom_unit.name,
|
|
||||||
substance_name: custom_unit.substance_name,
|
|
||||||
|
|
||||||
administration_route: custom_unit.administration_route,
|
|
||||||
dose: CustomUnitDose {
|
|
||||||
dose: custom_unit.dose,
|
|
||||||
unit: custom_unit.unit,
|
|
||||||
original_unit: custom_unit.original_unit,
|
|
||||||
custom_unit_id: custom_unit.id,
|
|
||||||
estimation: if custom_unit.is_estimate {
|
|
||||||
if let Some(standard_deviation) =
|
|
||||||
custom_unit.estimate_standard_deviation
|
|
||||||
{
|
|
||||||
Estimation::StandardDeviation(standard_deviation)
|
|
||||||
} else {
|
|
||||||
Estimation::Estimate
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Estimation::Precise
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
creation_time: from_unix_millis(custom_unit.creation_time),
|
|
||||||
is_archived: custom_unit.is_archived,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
for experience in data.experiences.into_iter() {
|
|
||||||
let mut ingestions: Vec<Ingestion> = Vec::new();
|
|
||||||
|
|
||||||
for ingestion in experience.ingestions.into_iter() {
|
|
||||||
fn ingestion_estimation(
|
|
||||||
ingestion: &psychonaut_journal_types::Ingestion,
|
|
||||||
) -> Estimation {
|
|
||||||
if !ingestion.is_estimate {
|
|
||||||
Estimation::Precise
|
|
||||||
} else if let Some(standard_deviation) = ingestion.estimate_standard_deviation {
|
|
||||||
Estimation::StandardDeviation(standard_deviation)
|
|
||||||
} else {
|
|
||||||
Estimation::Estimate
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let estimation = ingestion_estimation(&ingestion);
|
|
||||||
|
|
||||||
ingestions.push(Ingestion {
|
|
||||||
substance_name: ingestion.substance_name,
|
|
||||||
ingestion_time: from_unix_millis(ingestion.ingestion_time),
|
|
||||||
creation_time: from_unix_millis(ingestion.creation_time),
|
|
||||||
dose: {
|
|
||||||
if let Some(dose) = ingestion.dose {
|
|
||||||
if let Some(custom_unit_id) = ingestion.custom_unit_id {
|
|
||||||
let custom_unit = journal
|
|
||||||
.custom_units
|
|
||||||
.get(&custom_unit_id)
|
|
||||||
.expect("custom unit not found");
|
|
||||||
|
|
||||||
Dose::CustomUnit(CustomUnitDose {
|
|
||||||
dose,
|
|
||||||
unit: custom_unit.dose.unit.clone(),
|
|
||||||
original_unit: custom_unit.dose.original_unit.clone(),
|
|
||||||
estimation,
|
|
||||||
custom_unit_id,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Dose::Standard(StandardDose {
|
|
||||||
dose,
|
|
||||||
unit: ingestion.unit,
|
|
||||||
estimation,
|
|
||||||
contains_unknown: false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Dose::Unknown(UnknownDose {
|
|
||||||
unit: ingestion.unit,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
roa: ingestion.roa,
|
|
||||||
consumer: match ingestion.consumer_name {
|
|
||||||
Some(name) => Consumer::Named(name),
|
|
||||||
None => Consumer::Default,
|
|
||||||
},
|
|
||||||
notes: ingestion.notes,
|
|
||||||
stomach_fullness: ingestion.stomach_fullness,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
journal.experiences.push(Experience {
|
|
||||||
title: experience.title,
|
|
||||||
text: experience.text,
|
|
||||||
creation_time: from_unix_millis(experience.creation_time),
|
|
||||||
modified_time: from_unix_millis(experience.modified_time),
|
|
||||||
ingestions,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
journal
|
|
||||||
}
|
|
||||||
}
|
|
28
journal/src/types/consumer.rs
Normal file
28
journal/src/types/consumer.rs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
use std::{fmt::Display, str::FromStr};
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
|
pub enum Consumer {
|
||||||
|
Default,
|
||||||
|
Named(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Consumer {
|
||||||
|
type Err = core::convert::Infallible;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
if s == "default" {
|
||||||
|
Ok(Consumer::Default)
|
||||||
|
} else {
|
||||||
|
Ok(Consumer::Named(s.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Consumer {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Consumer::Default => f.write_str("default"),
|
||||||
|
Consumer::Named(name) => f.write_str(name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
6
journal/src/types/custom_substance.rs
Normal file
6
journal/src/types/custom_substance.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct CustomSubstance {
|
||||||
|
pub name: String,
|
||||||
|
pub description: String,
|
||||||
|
pub units: String,
|
||||||
|
}
|
15
journal/src/types/custom_unit.rs
Normal file
15
journal/src/types/custom_unit.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
use crate::types::{doses::CustomUnitDose, AdministrationRoute};
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct CustomUnit {
|
||||||
|
pub id: i64,
|
||||||
|
pub name: String,
|
||||||
|
pub substance_name: String,
|
||||||
|
|
||||||
|
pub administration_route: AdministrationRoute,
|
||||||
|
pub dose: CustomUnitDose,
|
||||||
|
|
||||||
|
pub creation_time: DateTime<Utc>,
|
||||||
|
pub is_archived: bool,
|
||||||
|
}
|
76
journal/src/types/doses.rs
Normal file
76
journal/src/types/doses.rs
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
use std::ops::{Add, Mul};
|
||||||
|
|
||||||
|
use crate::types::Estimation;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Dose {
|
||||||
|
Unknown(UnknownDose),
|
||||||
|
Standard(StandardDose),
|
||||||
|
CustomUnit(CustomUnitDose),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct UnknownDose {
|
||||||
|
pub unit: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct StandardDose {
|
||||||
|
pub dose: f64,
|
||||||
|
pub unit: String,
|
||||||
|
pub contains_unknown: bool,
|
||||||
|
pub estimation: Estimation,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct CustomUnitDose {
|
||||||
|
pub dose: f64,
|
||||||
|
pub unit: String,
|
||||||
|
pub original_unit: String,
|
||||||
|
pub estimation: Estimation,
|
||||||
|
pub custom_unit_id: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add for StandardDose {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
|
StandardDose {
|
||||||
|
dose: self.dose + rhs.dose,
|
||||||
|
unit: self.unit,
|
||||||
|
contains_unknown: self.contains_unknown || rhs.contains_unknown,
|
||||||
|
estimation: self.estimation + rhs.estimation,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mul for StandardDose {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn mul(self, rhs: Self) -> Self::Output {
|
||||||
|
StandardDose {
|
||||||
|
dose: self.dose * rhs.dose,
|
||||||
|
unit: self.unit,
|
||||||
|
contains_unknown: self.contains_unknown || rhs.contains_unknown,
|
||||||
|
estimation: {
|
||||||
|
let estimation = self.estimation + rhs.estimation;
|
||||||
|
if let Estimation::StandardDeviation(deviation) = estimation {
|
||||||
|
Estimation::StandardDeviation(deviation * rhs.dose)
|
||||||
|
} else {
|
||||||
|
estimation
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CustomUnitDose> for StandardDose {
|
||||||
|
fn from(value: CustomUnitDose) -> StandardDose {
|
||||||
|
StandardDose {
|
||||||
|
dose: value.dose,
|
||||||
|
unit: value.original_unit,
|
||||||
|
contains_unknown: false,
|
||||||
|
estimation: value.estimation,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
54
journal/src/types/estimate.rs
Normal file
54
journal/src/types/estimate.rs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
use std::ops::{Add, Mul};
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug, Copy, Clone)]
|
||||||
|
pub enum Estimation {
|
||||||
|
Precise,
|
||||||
|
Estimate,
|
||||||
|
StandardDeviation(f64),
|
||||||
|
}
|
||||||
|
|
||||||
|
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(_))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add for Estimation {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
|
match (self, rhs) {
|
||||||
|
(Estimation::StandardDeviation(x), Estimation::StandardDeviation(y)) => {
|
||||||
|
Estimation::StandardDeviation(x + y)
|
||||||
|
}
|
||||||
|
(Estimation::StandardDeviation(x), _) | (_, Estimation::StandardDeviation(x)) => {
|
||||||
|
Estimation::StandardDeviation(x)
|
||||||
|
}
|
||||||
|
(Estimation::Estimate, _) | (_, Estimation::Estimate) => Estimation::Estimate,
|
||||||
|
(Estimation::Precise, Estimation::Precise) => Estimation::Precise,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mul for Estimation {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn mul(self, rhs: Self) -> Self::Output {
|
||||||
|
match (self, rhs) {
|
||||||
|
(Estimation::StandardDeviation(x), Estimation::StandardDeviation(y)) => {
|
||||||
|
Estimation::StandardDeviation(x * y)
|
||||||
|
}
|
||||||
|
(Estimation::StandardDeviation(x), _) | (_, Estimation::StandardDeviation(x)) => {
|
||||||
|
Estimation::StandardDeviation(x)
|
||||||
|
}
|
||||||
|
(Estimation::Estimate, _) | (_, Estimation::Estimate) => Estimation::Estimate,
|
||||||
|
(Estimation::Precise, Estimation::Precise) => Estimation::Precise,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
journal/src/types/experience.rs
Normal file
10
journal/src/types/experience.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Experience {
|
||||||
|
pub id: i64,
|
||||||
|
pub title: String,
|
||||||
|
pub text: String,
|
||||||
|
pub creation_time: DateTime<Utc>,
|
||||||
|
pub modified_time: DateTime<Utc>,
|
||||||
|
}
|
10
journal/src/types/export.rs
Normal file
10
journal/src/types/export.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::types::{CustomUnit, Experience, Ingestion};
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
pub struct ExportFormat {
|
||||||
|
pub ingestions: HashMap<i64, Vec<Ingestion>>,
|
||||||
|
pub experiences: HashMap<i64, Experience>,
|
||||||
|
pub custom_units: HashMap<i64, CustomUnit>,
|
||||||
|
}
|
15
journal/src/types/ingestion.rs
Normal file
15
journal/src/types/ingestion.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
|
||||||
|
use crate::types::{doses::Dose, AdministrationRoute, Consumer};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Ingestion {
|
||||||
|
pub substance_name: String,
|
||||||
|
pub ingestion_time: DateTime<Utc>,
|
||||||
|
pub creation_time: DateTime<Utc>,
|
||||||
|
pub dose: Dose,
|
||||||
|
pub roa: AdministrationRoute,
|
||||||
|
pub consumer: Consumer,
|
||||||
|
pub notes: String,
|
||||||
|
pub stomach_fullness: Option<String>,
|
||||||
|
}
|
24
journal/src/types/mod.rs
Normal file
24
journal/src/types/mod.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
mod estimate;
|
||||||
|
pub use estimate::Estimation;
|
||||||
|
|
||||||
|
pub mod doses;
|
||||||
|
|
||||||
|
mod consumer;
|
||||||
|
pub use consumer::Consumer;
|
||||||
|
|
||||||
|
mod ingestion;
|
||||||
|
pub use ingestion::Ingestion;
|
||||||
|
|
||||||
|
mod custom_substance;
|
||||||
|
pub use custom_substance::CustomSubstance;
|
||||||
|
|
||||||
|
mod experience;
|
||||||
|
pub use experience::Experience;
|
||||||
|
|
||||||
|
mod custom_unit;
|
||||||
|
pub use custom_unit::CustomUnit;
|
||||||
|
|
||||||
|
mod export;
|
||||||
|
pub use export::ExportFormat;
|
||||||
|
|
||||||
|
pub type AdministrationRoute = psychonaut_journal_types::AdministrationRoute;
|
|
@ -1,14 +1,30 @@
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Subcommand)]
|
#[derive(Debug, Clone, Subcommand)]
|
||||||
#[clap(rename_all = "camelCase")]
|
#[command(rename_all = "camelCase")]
|
||||||
pub enum Commands {
|
pub enum Commands {
|
||||||
PrintExperience(crate::commands::print_experience::PrintExperienceArgs),
|
PrintExperience(crate::commands::print_experience::PrintExperienceArgs),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
// TODO: add env vars back to this,
|
||||||
#[clap()]
|
// clashes with multiple=false when one set as env and other as arg
|
||||||
pub struct Args {
|
#[derive(Debug, Clone, clap::Args)]
|
||||||
#[clap(subcommand)]
|
#[group(required = false, multiple = false)]
|
||||||
pub command: Commands,
|
pub struct JournalFileArgs {
|
||||||
|
// journal file is writable
|
||||||
|
// #[arg(group = "journal_file_args", global = true, long)]
|
||||||
|
// pub journal_file: Option<String>,
|
||||||
|
|
||||||
|
// export file is read-only
|
||||||
|
#[arg(group = "journal_file", global = true, long)]
|
||||||
|
pub psychonaut_export_file: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Parser)]
|
||||||
|
pub struct Args {
|
||||||
|
#[command(subcommand)]
|
||||||
|
pub command: Commands,
|
||||||
|
|
||||||
|
#[command(flatten)]
|
||||||
|
pub journal_file_args: JournalFileArgs,
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,14 @@ use crate::utils::load_journal;
|
||||||
|
|
||||||
#[derive(Debug, Clone, clap::Args)]
|
#[derive(Debug, Clone, clap::Args)]
|
||||||
pub struct PrintExperienceArgs {
|
pub struct PrintExperienceArgs {
|
||||||
|
#[arg(requires = "journal_file")]
|
||||||
pub experience_title: String,
|
pub experience_title: String,
|
||||||
#[clap(long, env = "EXPORT_FILE")]
|
|
||||||
pub export_file: String,
|
pub _x: (),
|
||||||
#[clap(long)]
|
|
||||||
|
#[arg(long)]
|
||||||
pub substance_filter: Option<Vec<String>>,
|
pub substance_filter: Option<Vec<String>>,
|
||||||
#[clap(long, value_delimiter = ',')]
|
#[arg(long, value_delimiter = ',')]
|
||||||
pub consumer_filter: Option<Vec<String>>,
|
pub consumer_filter: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,10 +39,17 @@ pub fn parse_consumer_filter(consumer_filter: Option<Vec<String>>) -> Option<Vec
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_experience(
|
pub fn print_experience(
|
||||||
_global_args: &Args,
|
global_args: &Args,
|
||||||
args: &PrintExperienceArgs,
|
args: &PrintExperienceArgs,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let journal = load_journal(&args.export_file).expect("could not load export data");
|
let journal = load_journal(
|
||||||
|
&global_args
|
||||||
|
.journal_file_args
|
||||||
|
.psychonaut_export_file
|
||||||
|
.clone()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.expect("could not load export data");
|
||||||
|
|
||||||
let experience = journal
|
let experience = journal
|
||||||
.first_experience_by_title(&args.experience_title)
|
.first_experience_by_title(&args.experience_title)
|
||||||
|
@ -48,14 +57,14 @@ pub fn print_experience(
|
||||||
|
|
||||||
//println!("{:#?}", &experience);
|
//println!("{:#?}", &experience);
|
||||||
|
|
||||||
println!("{}", format_experience_title(&experience));
|
println!("{}", format_experience_title(experience));
|
||||||
|
|
||||||
let substance_filter = args.substance_filter.clone();
|
let substance_filter = args.substance_filter.clone();
|
||||||
let consumer_filter = parse_consumer_filter(args.consumer_filter.clone());
|
let consumer_filter = parse_consumer_filter(args.consumer_filter.clone());
|
||||||
|
|
||||||
print_ingestion_log(
|
print_ingestion_log(
|
||||||
&journal,
|
&journal,
|
||||||
&experience,
|
experience,
|
||||||
substance_filter.as_ref(),
|
substance_filter.as_ref(),
|
||||||
consumer_filter.as_ref(),
|
consumer_filter.as_ref(),
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,14 +1,21 @@
|
||||||
use journal::types::{Consumer, Experience, Journal};
|
use journal::{
|
||||||
|
journal::JournalType,
|
||||||
|
types::{Consumer, Experience},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::formatting::{format_ingestion_dose, format_ingestion_roa, format_ingestion_time};
|
use crate::formatting::{format_ingestion_dose, format_ingestion_roa, format_ingestion_time};
|
||||||
|
|
||||||
pub fn print_ingestion_log(
|
pub fn print_ingestion_log(
|
||||||
journal: &Journal,
|
journal: &JournalType,
|
||||||
experience: &Experience,
|
experience: &Experience,
|
||||||
substance_filter: Option<&Vec<String>>,
|
substance_filter: Option<&Vec<String>>,
|
||||||
consumer_filter: Option<&Vec<Consumer>>,
|
consumer_filter: Option<&Vec<Consumer>>,
|
||||||
) {
|
) {
|
||||||
for ingestion in experience.ingestions.iter() {
|
for ingestion in journal
|
||||||
|
.get_experience_ingestions(experience.id)
|
||||||
|
.expect("could not find ingestions for experience")
|
||||||
|
.iter()
|
||||||
|
{
|
||||||
if let Some(substance_filter) = substance_filter {
|
if let Some(substance_filter) = substance_filter {
|
||||||
if !substance_filter.contains(&ingestion.substance_name) {
|
if !substance_filter.contains(&ingestion.substance_name) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -22,14 +29,13 @@ pub fn print_ingestion_log(
|
||||||
}
|
}
|
||||||
|
|
||||||
let custom_unit = journal.maybe_custom_unit(ingestion);
|
let custom_unit = journal.maybe_custom_unit(ingestion);
|
||||||
|
|
||||||
// println!("{:#?} {:#?}", &ingestion, &custom_unit);
|
// println!("{:#?} {:#?}", &ingestion, &custom_unit);
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"{}|{}|{}|{}|{}",
|
"{}|{}|{}|{}|{}",
|
||||||
ingestion.substance_name,
|
ingestion.substance_name,
|
||||||
format_ingestion_dose(&ingestion.dose, custom_unit.as_ref().map(|f| &f.dose)),
|
format_ingestion_dose(&ingestion.dose, custom_unit.map(|f| &f.dose)),
|
||||||
format_ingestion_roa(ingestion, custom_unit.as_ref()),
|
format_ingestion_roa(ingestion, custom_unit),
|
||||||
ingestion.consumer,
|
ingestion.consumer,
|
||||||
format_ingestion_time(ingestion)
|
format_ingestion_time(ingestion)
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use journal::{
|
use journal::{
|
||||||
helpers::calulate_custom_unit_dose,
|
helpers::calulate_custom_unit_dose,
|
||||||
types::{CustomUnit, CustomUnitDose, Dose, Estimation, Experience, Ingestion, StandardDose},
|
types::{
|
||||||
|
doses::{CustomUnitDose, Dose, StandardDose},
|
||||||
|
CustomUnit, Estimation, Experience, Ingestion,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn format_experience_title(experience: &Experience) -> String {
|
pub fn format_experience_title(experience: &Experience) -> String {
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
use journal::types::Journal;
|
use journal::journal::{InMemJournal, Journal, JournalType};
|
||||||
use psychonaut_journal_types::ExportData;
|
use psychonaut_journal_types::ExportData;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
|
||||||
pub fn load_journal(filename: &String) -> Result<Journal, Box<dyn std::error::Error>> {
|
pub fn load_journal(filename: &String) -> Result<JournalType, Box<dyn std::error::Error>> {
|
||||||
let file = File::open(filename)?;
|
let file = File::open(filename)?;
|
||||||
|
|
||||||
let export_data: ExportData = serde_json::from_reader(file)?;
|
let export_data: ExportData = serde_json::from_reader(file)?;
|
||||||
|
|
||||||
let journal = Journal::import(export_data);
|
let mut journal = InMemJournal::default();
|
||||||
|
journal.import_psychonaut(export_data);
|
||||||
|
|
||||||
Ok(journal)
|
Ok(Box::new(journal))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue