Skip to content

Commit

Permalink
refactor(cli): ♻️ update handling of duration strings and phases (#497)
Browse files Browse the repository at this point in the history
  • Loading branch information
keinsell authored Jun 9, 2024
1 parent 9f3df61 commit d0c41a9
Show file tree
Hide file tree
Showing 39 changed files with 3,531 additions and 7,097 deletions.
22 changes: 22 additions & 0 deletions .idea/dataSources.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion .idea/neuronek.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/runConfigurations/Start_ETL_Workflow.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions .idea/scopes/apps_cli.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions apps/cli/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions apps/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ clap-markdown = "0.1.3"
human-panic = "2.0.0"
clap_complete = "4.4.10"
dateless = "0.3.1"
iso8601-duration = { version = "0.2.0",features = ["serde", "chrono"] }

[features]
default = []
Expand Down
2 changes: 1 addition & 1 deletion apps/cli/src/cli/bin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ use async_std::task;

use crate::cli::main::cli;

fn main() {
pub fn main() {
task::block_on(cli());
}
6 changes: 3 additions & 3 deletions apps/cli/src/cli/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use structopt::StructOpt;

use crate::cli::ingestion::create_ingestion::handle_create_ingestion;
use crate::cli::ingestion::delete_ingestion::delete_ingestion;
use crate::cli::ingestion::IngestionCommand;
use crate::cli::ingestion::plan_ingestion::handle_plan_ingestion;
use crate::cli::ingestion::IngestionCommand;
use crate::cli::substance::list_substances::list_substances;
use crate::ingestion::list_ingestion;
use crate::orm;
Expand Down Expand Up @@ -77,8 +77,6 @@ pub async fn cli() {

CommandLineInterface::clap().gen_completions(env!("CARGO_PKG_NAME"), Shell::Bash, "target");

let cli = CommandLineInterface::from_args();

#[cfg(feature = "dev")]
{
use crate::orm::refresh_database_as_developer;
Expand All @@ -87,6 +85,8 @@ pub async fn cli() {

migrate_database(&db).await;

let cli = CommandLineInterface::from_args();

match cli.command {
Commands::Ingestion(ingestion) => match ingestion {
IngestionCommand::Create(create_ingestion_command) => {
Expand Down
5 changes: 2 additions & 3 deletions apps/cli/src/core/phase.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::ops::Range;
use std::str::FromStr;

use chrono::TimeDelta;
use std::time::Duration;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Eq, Hash)]
Expand Down Expand Up @@ -41,7 +40,7 @@ impl FromStr for PhaseClassification {
}
}

pub type DurationRange = Range<TimeDelta>;
pub type DurationRange = Range<Duration>;

#[derive(Debug, Clone)]
pub struct Phase {
Expand Down
2 changes: 1 addition & 1 deletion apps/cli/src/ingestion.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::fmt::Debug;

use chrono::{DateTime, Local, Utc};
use chrono_english::{Dialect, parse_date_string};
use chrono_english::{parse_date_string, Dialect};
use chrono_humanize::HumanTime;
use db::ingestion::ActiveModel;
use db::prelude::Ingestion;
Expand Down
119 changes: 87 additions & 32 deletions apps/cli/src/ingestion_analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@
// and try to extract and provide as much information as it's
// possible. This is a very important part of the application

use std::fmt::Debug;
use std::time::Duration;

use chrono::TimeDelta;
use chrono::{Local};
use chrono_english::{Dialect, parse_date_string};
use chrono_humanize::HumanTime;
use log::{debug, error, info};
use log::{debug, error};
use serde::{Deserialize, Serialize};

use crate::core::ingestion::IngestionPhases;
use crate::core::mass::deserialize_mass_unit;
use crate::core::ingestion::{IngestionPhase, IngestionPhases};
use crate::core::mass::{deserialize_mass_unit, Mass};
use crate::core::phase::PhaseClassification;
use crate::core::route_of_administration::{
get_dosage_classification_by_mass_and_route_of_administration,
Expand All @@ -36,6 +38,7 @@ pub struct IngestionAnalysis {
substance_name: String,
route_of_administration_classification: RouteOfAdministrationClassification,
dosage_classification: DosageClassification,
dosage: Mass,
phases: IngestionPhases,
total_duration: Duration,
}
Expand Down Expand Up @@ -77,35 +80,103 @@ pub async fn analyze_future_ingestion(

let phases = get_phases_by_route_of_administration(&route_of_administration);

let total_duration = phases.iter().fold(TimeDelta::seconds(0), |acc, phase| {
let total_duration = phases.iter().fold(Duration::default(), |acc, phase| {
if phase.phase_classification == PhaseClassification::Afterglow {
return acc;
} else {
println!(
"Adding {:?} into total duration (total duration is {:?})",
phase.duration_range.end.to_string(),
acc.to_string()
);

acc + phase.duration_range.end
let added = acc + phase.duration_range.end;
return added;
}
});

println!("{:?}", HumanTime::from(total_duration).to_string());
let mut ingestion_phases: IngestionPhases = IngestionPhases::new();

let route_of_administration_phases = route_of_administration.phases.clone();
let parsed_time = parse_date_string(&create_ingestion.ingested_at, Local::now(), Dialect::Us)
.unwrap_or_else(|_| Local::now());

// Start with onset phase, create ingestion phase and add it to ingestion phases
let onset_phase = route_of_administration_phases.get(&PhaseClassification::Onset).unwrap();

let onset_ingestion_phase = IngestionPhase {
phase_classification: PhaseClassification::Onset,
duration: onset_phase.duration_range.clone(),
start_time: parsed_time,
end_time: parsed_time + onset_phase.duration_range.end,
};



let comeup_phase = route_of_administration_phases.get(&PhaseClassification::Comeup).unwrap();

let comeup_ingestion_phase = IngestionPhase {
phase_classification: PhaseClassification::Comeup,
duration: comeup_phase.duration_range.clone(),
start_time: onset_ingestion_phase.end_time.clone(),
end_time: onset_ingestion_phase.end_time + comeup_phase.duration_range.end,
};

let peak_phase = route_of_administration_phases.get(&PhaseClassification::Peak).unwrap();

let peak_ingestion_phase = IngestionPhase {
phase_classification: PhaseClassification::Peak,
duration: peak_phase.duration_range.clone(),
start_time: comeup_ingestion_phase.end_time.clone(),
end_time: comeup_ingestion_phase.end_time + peak_phase.duration_range.end,
};

let offset_phase = route_of_administration_phases.get(&PhaseClassification::Offset).unwrap();

let offset_ingestion_phase = IngestionPhase {
phase_classification: PhaseClassification::Offset,
duration: offset_phase.duration_range.clone(),
start_time: peak_ingestion_phase.end_time.clone(),
end_time: peak_ingestion_phase.end_time + offset_phase.duration_range.end,
};

let afterglow_phase = route_of_administration_phases.get(&PhaseClassification::Afterglow).unwrap();

let afterglow_ingestion_phase = IngestionPhase {
phase_classification: PhaseClassification::Afterglow,
duration: afterglow_phase.duration_range.clone(),
start_time: offset_ingestion_phase.end_time.clone(),
end_time: offset_ingestion_phase.end_time + afterglow_phase.duration_range.end,
};

ingestion_phases.insert(PhaseClassification::Onset, onset_ingestion_phase);
ingestion_phases.insert(PhaseClassification::Comeup, comeup_ingestion_phase);
ingestion_phases.insert(PhaseClassification::Peak, peak_ingestion_phase);
ingestion_phases.insert(PhaseClassification::Offset, offset_ingestion_phase);
ingestion_phases.insert(PhaseClassification::Afterglow, afterglow_ingestion_phase);

let ingestion_analysis = IngestionAnalysis {
substance_name: substance.name.clone(),
dosage: ingestion_mass.clone(),
route_of_administration_classification: route_of_administration.classification,
dosage_classification,
phases: Default::default(),
total_duration: total_duration.to_std().unwrap(),
phases:ingestion_phases,
total_duration,
};

info!("{:?}", ingestion_analysis);
pretty_print_ingestion_analysis(&ingestion_analysis);

Ok(ingestion_analysis)
}

pub fn pretty_print_ingestion_analysis(ingestion_analysis: &IngestionAnalysis) {
println!("Ingestion Analysis for {:?}", ingestion_analysis.substance_name);
println!("Route of Administration: {:?}", ingestion_analysis.route_of_administration_classification);
println!("Dosage: {:?}", ingestion_analysis.dosage);
println!("Dosage Classification: {:?}", ingestion_analysis.dosage_classification);
println!("Total Duration: {:?}", HumanTime::from(chrono::Duration::from_std(ingestion_analysis.total_duration).unwrap()).to_string());
println!("Phases:");
for (phase_classification, phase) in ingestion_analysis.phases.iter() {
println!("* {:?}: {:?}", phase_classification, HumanTime::from(phase.start_time).to_string());
}
}



#[cfg(test)]
mod tests {
use std::time::Duration;
Expand Down Expand Up @@ -164,22 +235,6 @@ mod tests {
.any(|phase| phase.0.clone() == PhaseClassification::Onset),
"Onset phase should be present in ingestion phases"
);

// let expected_ingestion_phases = Vec::<IngestionPhase>::new();
//
// expected_ingestion_phases.push(IngestionPhase {
// phase_classification: PhaseClassification::Onset,
// duration: DurationRange {
// start: Duration::minutes(5),
// end: Duration::seconds(10),
// },
// humanized_duration: Range {},
// start_time: Default::default(),
// duration_range: (0..30).into(),
// end_time: Default::default(),
// });
//
// // Adjust this as necessary
}
Err(e) => panic!("Test failed: {}", e),
}
Expand Down
2 changes: 1 addition & 1 deletion apps/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ mod orm;
mod service;

fn main() {
task::block_on(cli());
cli::bin::main()
}
2 changes: 1 addition & 1 deletion apps/cli/src/orm.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use db::Migrator;
use log::debug;
use sea_orm::*;
use sea_orm::DatabaseConnection;
use sea_orm::*;
use sea_orm_migration::*;
use xdg::BaseDirectories;

Expand Down
Loading

0 comments on commit d0c41a9

Please sign in to comment.