diff --git a/Cargo.toml b/Cargo.toml index 9b04141..c1e127b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ path = "journal_cli/src/main.rs" journal = { path = "./journal" } chrono = { version = "0.4.38", 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"] } prettytable-rs = "0.10.0" serde = { version = "1.0.215", features = ["std", "derive", "serde_derive"] } diff --git a/journal/src/helpers.rs b/journal/src/helpers.rs index 61c0078..7feec84 100644 --- a/journal/src/helpers.rs +++ b/journal/src/helpers.rs @@ -75,6 +75,7 @@ pub fn ingestion_standard_deviation( .expect("Custom Unit could not be found"); if custom_unit.estimate_standard_deviation.is_none() { + println!("{:?}", ingestion.estimate_standard_deviation); return ingestion.estimate_standard_deviation; }; @@ -93,19 +94,17 @@ pub fn ingestion_standard_deviation( } } -// def ingestionStandardDeviation($customUnits): -// . as $ingestion | -// journalTypes::ensureIngestion | +pub fn ingestion_unit( + ingestion: &Ingestion, + 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 -// ($customUnits | map(select(.id == $ingestion.customUnitId))[0]) as $customUnit | - -// ($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; + custom_unit.original_unit.clone() + } else { + ingestion.unit.clone() + } +} \ No newline at end of file diff --git a/journal/src/types.rs b/journal/src/types.rs index fe67227..4f3e351 100644 --- a/journal/src/types.rs +++ b/journal/src/types.rs @@ -35,11 +35,12 @@ pub struct Ingestion { #[serde(with = "ts_milliseconds", rename = "creationDate")] pub creation_time: DateTime, pub dose: Option, + #[serde(rename = "units")] + pub unit: String, #[serde(rename = "isDoseAnEstimate")] pub is_estimate: bool, #[serde(rename = "estimatedDoseStandardDeviation")] pub estimate_standard_deviation: Option, - pub units: String, pub custom_unit_id: Option, #[serde(rename = "administrationRoute")] pub roa: AdministrationRoute, @@ -70,15 +71,15 @@ pub struct Experience { pub type ExperiencesType = Vec; pub trait Experiences { - fn filter_by_title(&self, title: String) -> Vec; - fn get_by_title(&self, title: String) -> Option; + fn filter_by_title(&self, title: &String) -> Vec; + fn get_by_title(&self, title: &String) -> Option; } impl Experiences for ExperiencesType { - fn filter_by_title(&self, title: String) -> Vec { + fn filter_by_title(&self, title: &String) -> Vec { self.iter() .filter_map(|experience| { - if experience.title == title { + if &experience.title == title { Some(experience.clone()) } else { None @@ -86,9 +87,9 @@ impl Experiences for ExperiencesType { }) .collect() } - fn get_by_title(&self, title: String) -> Option { + fn get_by_title(&self, title: &String) -> Option { for experience in self.iter() { - if experience.title == title { + if &experience.title == title { return Some(experience.clone()); } } diff --git a/journal_cli/src/args.rs b/journal_cli/src/args.rs index ee55f9f..c45f5b6 100644 --- a/journal_cli/src/args.rs +++ b/journal_cli/src/args.rs @@ -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)] #[clap()] pub struct Args { - pub export_file: String, - // #[clap(subcommand)] - // pub command: Commands, -} + #[clap(subcommand)] + pub command: Commands, +} \ No newline at end of file diff --git a/journal_cli/src/commands/mod.rs b/journal_cli/src/commands/mod.rs new file mode 100644 index 0000000..899875e --- /dev/null +++ b/journal_cli/src/commands/mod.rs @@ -0,0 +1 @@ +pub mod print_experience; \ No newline at end of file diff --git a/journal_cli/src/commands/print_experience.rs b/journal_cli/src/commands/print_experience.rs new file mode 100644 index 0000000..9609c49 --- /dev/null +++ b/journal_cli/src/commands/print_experience.rs @@ -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> { + 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(()) +} \ No newline at end of file diff --git a/journal_cli/src/main.rs b/journal_cli/src/main.rs index 76711f8..a2fa8a4 100644 --- a/journal_cli/src/main.rs +++ b/journal_cli/src/main.rs @@ -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 commands::print_experience::print_experience; -mod args; +pub mod args; +pub mod commands; +pub mod utils; fn main() -> Result<(), Box> { 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 - .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)); - } - - 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") - ) - } + match command { + args::Commands::PrintExperience(print_experience_args) => + print_experience(&args, &print_experience_args)?, + } Ok(()) } diff --git a/journal_cli/src/utils.rs b/journal_cli/src/utils.rs new file mode 100644 index 0000000..fda5d4c --- /dev/null +++ b/journal_cli/src/utils.rs @@ -0,0 +1,20 @@ +use std::fs::File; +use journal::types::ExportData; + +pub fn load_export_data(filename: &String) -> Result> { + 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) +} \ No newline at end of file