This commit is contained in:
chaos 2024-11-19 20:30:24 +00:00
parent f81ce78e6f
commit 215662e1c8
8 changed files with 115 additions and 66 deletions

View file

@ -11,7 +11,7 @@ path = "journal_cli/src/main.rs"
journal = { path = "./journal" } journal = { path = "./journal" }
chrono = { version = "0.4.38", features = ["serde"] } chrono = { version = "0.4.38", features = ["serde"] }
chrono-tz = { version = "0.10.0", features = ["serde"] } chrono-tz = { version = "0.10.0", features = ["serde"] }
clap = { version = "4.5.21", features = ["derive"] } clap = { version = "4.5.21", features = ["derive", "env"] }
log = { version = "0.4.22", features = ["std", "serde"] } log = { version = "0.4.22", features = ["std", "serde"] }
prettytable-rs = "0.10.0" prettytable-rs = "0.10.0"
serde = { version = "1.0.215", features = ["std", "derive", "serde_derive"] } serde = { version = "1.0.215", features = ["std", "derive", "serde_derive"] }

View file

@ -75,6 +75,7 @@ pub fn ingestion_standard_deviation(
.expect("Custom Unit could not be found"); .expect("Custom Unit could not be found");
if custom_unit.estimate_standard_deviation.is_none() { if custom_unit.estimate_standard_deviation.is_none() {
println!("{:?}", ingestion.estimate_standard_deviation);
return ingestion.estimate_standard_deviation; return ingestion.estimate_standard_deviation;
}; };
@ -93,19 +94,17 @@ pub fn ingestion_standard_deviation(
} }
} }
// def ingestionStandardDeviation($customUnits): pub fn ingestion_unit(
// . as $ingestion | ingestion: &Ingestion,
// journalTypes::ensureIngestion | custom_units: &CustomUnitsType,
) -> String {
if let Some(custom_unit_id) = ingestion.custom_unit_id {
let custom_unit = custom_units
.get_by_id(custom_unit_id)
.expect("Custom Unit could not be found");
// if .customUnitId != null then custom_unit.original_unit.clone()
// ($customUnits | map(select(.id == $ingestion.customUnitId))[0]) as $customUnit | } else {
ingestion.unit.clone()
// ($ingestion.dose // 0) as $expectationX | }
// ($ingestion.estimatedDoseStandardDeviation // 0) as $standardDeviationX | }
// ($customUnit.dose // 0) as $expectationY |
// ($customUnit.estimatedDoseStandardDeviation // 0) as $standardDeviationY |
// addStandardDeviations($expectationX; $standardDeviationX; $expectationY; $standardDeviationY)
// else
// .estimatedDoseStandardDeviation
// end;

View file

@ -35,11 +35,12 @@ pub struct Ingestion {
#[serde(with = "ts_milliseconds", rename = "creationDate")] #[serde(with = "ts_milliseconds", rename = "creationDate")]
pub creation_time: DateTime<Utc>, pub creation_time: DateTime<Utc>,
pub dose: Option<f64>, pub dose: Option<f64>,
#[serde(rename = "units")]
pub unit: String,
#[serde(rename = "isDoseAnEstimate")] #[serde(rename = "isDoseAnEstimate")]
pub is_estimate: bool, pub is_estimate: bool,
#[serde(rename = "estimatedDoseStandardDeviation")] #[serde(rename = "estimatedDoseStandardDeviation")]
pub estimate_standard_deviation: Option<f64>, pub estimate_standard_deviation: Option<f64>,
pub units: String,
pub custom_unit_id: Option<i64>, pub custom_unit_id: Option<i64>,
#[serde(rename = "administrationRoute")] #[serde(rename = "administrationRoute")]
pub roa: AdministrationRoute, pub roa: AdministrationRoute,
@ -70,15 +71,15 @@ pub struct Experience {
pub type ExperiencesType = Vec<Experience>; pub type ExperiencesType = Vec<Experience>;
pub trait Experiences { pub trait Experiences {
fn filter_by_title(&self, title: String) -> Vec<Experience>; fn filter_by_title(&self, title: &String) -> Vec<Experience>;
fn get_by_title(&self, title: String) -> Option<Experience>; fn get_by_title(&self, title: &String) -> Option<Experience>;
} }
impl Experiences for ExperiencesType { impl Experiences for ExperiencesType {
fn filter_by_title(&self, title: String) -> Vec<Experience> { fn filter_by_title(&self, title: &String) -> Vec<Experience> {
self.iter() self.iter()
.filter_map(|experience| { .filter_map(|experience| {
if experience.title == title { if &experience.title == title {
Some(experience.clone()) Some(experience.clone())
} else { } else {
None None
@ -86,9 +87,9 @@ impl Experiences for ExperiencesType {
}) })
.collect() .collect()
} }
fn get_by_title(&self, title: String) -> Option<Experience> { fn get_by_title(&self, title: &String) -> Option<Experience> {
for experience in self.iter() { for experience in self.iter() {
if experience.title == title { if &experience.title == title {
return Some(experience.clone()); return Some(experience.clone());
} }
} }

View file

@ -1,9 +1,14 @@
use clap::Parser; use clap::{Parser, Subcommand};
#[derive(Debug, Clone, Subcommand)]
#[clap(rename_all = "camelCase")]
pub enum Commands {
PrintExperience(crate::commands::print_experience::PrintExperienceArgs)
}
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
#[clap()] #[clap()]
pub struct Args { pub struct Args {
pub export_file: String, #[clap(subcommand)]
// #[clap(subcommand)] pub command: Commands,
// pub command: Commands, }
}

View file

@ -0,0 +1 @@
pub mod print_experience;

View file

@ -0,0 +1,51 @@
use crate::args::Args;
use crate::utils::load_export_data;
use journal;
use journal::helpers::{
ingestion_contains_estimate, ingestion_dose, ingestion_standard_deviation, ingestion_unit,
};
use journal::types::Experiences;
#[derive(Debug, Clone, clap::Args)]
pub struct PrintExperienceArgs {
pub experience_title: String,
#[clap(long, env = "EXPORT_FILE")]
pub export_file: String,
}
pub fn print_experience(_global_args: &Args, args: &PrintExperienceArgs) -> Result<(), Box<dyn std::error::Error>> {
let export_data = load_export_data(&args.export_file).expect("could not load export data");
let experience = export_data
.experiences
.get_by_title(&args.experience_title)
.expect("could not find experience");
for ingestion in experience.ingestions.iter() {
let contains_estimate = ingestion_contains_estimate(ingestion, &export_data.custom_units);
let standard_deviation = ingestion_standard_deviation(ingestion, &export_data.custom_units);
println!(
"{}: {}{}{}{}",
ingestion.substance_name,
if contains_estimate { "~" } else { "" },
format!(
"{:.2}",
ingestion_dose(ingestion, &export_data.custom_units).unwrap()
)
.trim_end_matches(".00"),
if standard_deviation.is_some() {
format!(
"±{:.2}",
standard_deviation.unwrap()
)
} else {
"".to_string()
}
.trim_end_matches(".00"),
ingestion_unit(ingestion, &export_data.custom_units),
)
}
Ok(())
}

View file

@ -1,49 +1,21 @@
use journal;
use journal::helpers::{ingestion_contains_estimate, ingestion_dose, ingestion_standard_deviation};
use journal::types::Experiences;
use serde_json;
use std::fs::File;
use clap::Parser; use clap::Parser;
use commands::print_experience::print_experience;
mod args; pub mod args;
pub mod commands;
pub mod utils;
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = args::Args::parse(); let args = args::Args::parse();
let file = File::open(args.export_file)?; let command = args.command.to_owned();
let mut export_data: journal::types::ExportData = serde_json::from_reader(file)?; //println!("{:#?}", args);
export_data match command {
.experiences args::Commands::PrintExperience(print_experience_args) =>
.sort_by(|a, b| a.modified_time.cmp(&b.modified_time)); print_experience(&args, &print_experience_args)?,
}
for experience in export_data.experiences.iter_mut() {
experience
.ingestions
.sort_by(|a, b| a.ingestion_time.cmp(&b.ingestion_time));
}
let experience = export_data
.experiences
.get_by_title("20 Apr 2024".to_string())
.unwrap();
println!("{:#?}", experience);
for ingestion in experience.ingestions.iter() {
println!(
"{}: {}{}",
ingestion.substance_name,
format!("{:.2}", ingestion_dose(ingestion, &export_data.custom_units).unwrap()).trim_end_matches(".00"),
if ingestion_contains_estimate(ingestion, &export_data.custom_units) {
format!("±{:.2}", ingestion_standard_deviation(ingestion, &export_data.custom_units).or(Some(0.0)).unwrap())
} else {
"".to_string()
}.trim_end_matches(".00")
)
}
Ok(()) Ok(())
} }

20
journal_cli/src/utils.rs Normal file
View file

@ -0,0 +1,20 @@
use std::fs::File;
use journal::types::ExportData;
pub fn load_export_data(filename: &String) -> Result<ExportData, Box<dyn std::error::Error>> {
let file = File::open(filename)?;
let export_data: ExportData = serde_json::from_reader(file)?;
// export_data
// .experiences
// .sort_by(|a, b| a.modified_time.cmp(&b.modified_time));
//for experience in export_data.experiences.iter_mut() {
// experience
// .ingestions
// .sort_by(|a, b| a.ingestion_time.cmp(&b.ingestion_time));
//}
Ok(export_data)
}