update
This commit is contained in:
parent
93105359f9
commit
956c3f6ad1
|
@ -1,6 +1,5 @@
|
|||
use crate::types::{
|
||||
AdministrationRoute, Consumer, CustomUnit, Ingestion, Session, Substance, SubstanceIngestion,
|
||||
Unit,
|
||||
CustomUnit, Ingestion, IngestionKind, Session, Substance, SubstanceIngestion, Sustenance, Unit,
|
||||
};
|
||||
|
||||
pub type JournalType = Box<dyn Journal>;
|
||||
|
@ -9,19 +8,16 @@ pub trait Journal {
|
|||
fn get_custom_unit(&self, id: i32) -> Option<CustomUnit>;
|
||||
fn get_session(&self, id: i32) -> Option<Session>;
|
||||
fn get_session_ingestions(&self, id: i32) -> Option<Vec<Ingestion>>;
|
||||
fn get_session_substance_ingestions_by(
|
||||
&self,
|
||||
id: i32,
|
||||
substance_filter: Option<&Vec<String>>,
|
||||
route_filter: Option<&Vec<AdministrationRoute>>,
|
||||
consumer_filter: Option<&Vec<Consumer>>,
|
||||
) -> Option<Vec<Ingestion>>;
|
||||
fn get_substance(&self, name: &String) -> Option<Substance>;
|
||||
|
||||
fn set_custom_unit(&mut self, unit_id: i32, unit: CustomUnit);
|
||||
fn set_session(&mut self, session_id: i32, session: Session);
|
||||
fn get_substance(&self, name: &str) -> Option<Substance>;
|
||||
fn get_sustenance(&self, sustenance_id: &str) -> Option<Sustenance>;
|
||||
fn get_sustenance_ingestions(&self, sustenance_id: &str) -> Option<Vec<IngestionKind>>;
|
||||
|
||||
fn set_custom_unit(&mut self, unit: CustomUnit);
|
||||
fn set_session(&mut self, session: Session);
|
||||
fn set_session_ingestions(&mut self, session_id: i32, ingestions: Vec<Ingestion>);
|
||||
fn set_substance(&mut self, name: &String, substance: Substance);
|
||||
fn set_substance(&mut self, substance: Substance);
|
||||
fn set_sustenance(&mut self, sustenance: Sustenance);
|
||||
|
||||
fn first_session_by_title(&self, title: &str) -> Option<Session>;
|
||||
fn resolve_substance_unit(&self, ingestion: &SubstanceIngestion) -> Option<Unit>;
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use std::{collections::HashMap, fs::File};
|
||||
|
||||
use crate::types::{
|
||||
AdministrationRoute, Consumer, CustomUnit, Ingestion, IngestionKind, Session, Substance,
|
||||
SubstanceIngestion, Unit,
|
||||
CustomUnit, Ingestion, IngestionKind, Session, Substance, SubstanceIngestion, Sustenance, Unit,
|
||||
};
|
||||
|
||||
use super::{Journal, JournalType};
|
||||
|
@ -10,6 +9,7 @@ use super::{Journal, JournalType};
|
|||
#[derive(Debug, Default, Clone)]
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct JSONJournalData {
|
||||
pub sustenances: HashMap<String, Sustenance>,
|
||||
pub substances: HashMap<String, Substance>,
|
||||
pub ingestions: HashMap<i32, Vec<Ingestion>>,
|
||||
pub sessions: HashMap<i32, Session>,
|
||||
|
@ -23,12 +23,12 @@ pub struct JSONJournal {
|
|||
}
|
||||
|
||||
impl JSONJournal {
|
||||
pub fn create(filename: &String) -> Result<JournalType, Box<dyn std::error::Error>> {
|
||||
pub fn create(filename: &str) -> Result<JournalType, Box<dyn std::error::Error>> {
|
||||
let data: JSONJournalData = JSONJournalData::default();
|
||||
|
||||
let journal = JSONJournal {
|
||||
data,
|
||||
filename: filename.clone(),
|
||||
filename: filename.to_string(),
|
||||
};
|
||||
|
||||
journal.save()?;
|
||||
|
@ -36,13 +36,15 @@ impl JSONJournal {
|
|||
Ok(Box::new(journal))
|
||||
}
|
||||
|
||||
pub fn load(filename: &String) -> Result<JournalType, Box<dyn std::error::Error>> {
|
||||
pub fn load(filename: &str) -> Result<JournalType, Box<dyn std::error::Error>> {
|
||||
let file = File::open(filename)?;
|
||||
|
||||
let data: JSONJournalData = serde_json::from_reader(file)?;
|
||||
//println!("{data:#?}");
|
||||
|
||||
let journal = JSONJournal {
|
||||
data,
|
||||
filename: filename.clone(),
|
||||
filename: filename.to_string(),
|
||||
};
|
||||
|
||||
Ok(Box::new(journal))
|
||||
|
@ -69,52 +71,7 @@ impl Journal for JSONJournal {
|
|||
self.data.ingestions.get(&id).cloned()
|
||||
}
|
||||
|
||||
fn get_session_substance_ingestions_by(
|
||||
&self,
|
||||
id: i32,
|
||||
substance_filter: Option<&Vec<String>>,
|
||||
route_filter: Option<&Vec<AdministrationRoute>>,
|
||||
consumer_filter: Option<&Vec<Consumer>>,
|
||||
) -> Option<Vec<Ingestion>> {
|
||||
if let Some(ingestions) = self.get_session_ingestions(id) {
|
||||
let ingestions = ingestions
|
||||
.clone()
|
||||
.into_iter()
|
||||
.filter(|ingestion| {
|
||||
if let Some(consumer_filter) = consumer_filter {
|
||||
if !consumer_filter.contains(&ingestion.consumer) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
let ingestion = match &ingestion.kind {
|
||||
IngestionKind::Substance(ingestion) => ingestion,
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
if let Some(substance_filter) = substance_filter {
|
||||
if !substance_filter.contains(&ingestion.substance_name) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(route_filter) = route_filter {
|
||||
if !route_filter.contains(&ingestion.roa) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
})
|
||||
.collect::<Vec<Ingestion>>();
|
||||
|
||||
Some(ingestions)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn get_substance(&self, name: &String) -> Option<Substance> {
|
||||
fn get_substance(&self, name: &str) -> Option<Substance> {
|
||||
self.data.substances.get(name).cloned()
|
||||
}
|
||||
|
||||
|
@ -136,23 +93,63 @@ impl Journal for JSONJournal {
|
|||
.cloned()
|
||||
}
|
||||
|
||||
fn set_custom_unit(&mut self, unit_id: i32, unit: CustomUnit) {
|
||||
self.data.custom_units.insert(unit_id, unit);
|
||||
fn set_custom_unit(&mut self, unit: CustomUnit) {
|
||||
self.data.custom_units.insert(unit.id, unit);
|
||||
}
|
||||
|
||||
fn set_session(&mut self, session_id: i32, session: Session) {
|
||||
self.data.sessions.insert(session_id, session);
|
||||
fn set_session(&mut self, session: Session) {
|
||||
self.data.sessions.insert(session.id, session);
|
||||
}
|
||||
|
||||
fn set_session_ingestions(&mut self, session_id: i32, ingestions: Vec<Ingestion>) {
|
||||
self.data.ingestions.insert(session_id, ingestions);
|
||||
}
|
||||
|
||||
fn set_substance(&mut self, name: &String, substance: Substance) {
|
||||
self.data.substances.insert(name.clone(), substance);
|
||||
fn set_substance(&mut self, substance: Substance) {
|
||||
self.data
|
||||
.substances
|
||||
.insert(substance.name.clone(), substance);
|
||||
}
|
||||
|
||||
fn save(&self) -> Result<(), Box<dyn std::error::Error>> {
|
||||
self.save()
|
||||
}
|
||||
|
||||
fn get_sustenance(&self, sustenance_id: &str) -> Option<Sustenance> {
|
||||
self.data.sustenances.get(sustenance_id).cloned()
|
||||
}
|
||||
|
||||
fn set_sustenance(&mut self, sustenance: Sustenance) {
|
||||
self.data
|
||||
.sustenances
|
||||
.insert(sustenance.id.clone(), sustenance);
|
||||
}
|
||||
|
||||
fn get_sustenance_ingestions(&self, sustenance_id: &str) -> Option<Vec<IngestionKind>> {
|
||||
let sustenance = self.get_sustenance(sustenance_id).unwrap();
|
||||
|
||||
let mut ingestions: Vec<IngestionKind> = Vec::new();
|
||||
for include in sustenance.includes.into_iter() {
|
||||
match include {
|
||||
IngestionKind::Unknown => continue,
|
||||
IngestionKind::Hydration { amount } => {
|
||||
ingestions.push(IngestionKind::Hydration { amount })
|
||||
}
|
||||
IngestionKind::Substance(substance_ingestion) => {
|
||||
ingestions.push(IngestionKind::Substance(substance_ingestion))
|
||||
}
|
||||
IngestionKind::Sustenance(sustenance_ingestion) => {
|
||||
ingestions.push(IngestionKind::Sustenance(sustenance_ingestion.clone()));
|
||||
|
||||
ingestions.append(
|
||||
&mut self
|
||||
.get_sustenance_ingestions(&sustenance_ingestion.sustenance_id)
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(ingestions)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,9 @@ pub enum IngestionKind {
|
|||
Unknown,
|
||||
Substance(SubstanceIngestion),
|
||||
Sustenance(SustenanceIngestion),
|
||||
Hydration {
|
||||
amount: u64,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Default, Debug, Clone)]
|
||||
|
@ -35,9 +38,8 @@ pub struct SubstanceIngestion {
|
|||
#[derive(PartialEq, Default, Debug, Clone)]
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct SustenanceIngestion {
|
||||
pub sustenance_name: String,
|
||||
pub sustenance_category: String,
|
||||
pub amount: (u8, u8, u8),
|
||||
pub sustenance_id: String,
|
||||
pub amount: f64,
|
||||
}
|
||||
|
||||
impl From<psychonaut_journal_types::Ingestion> for Ingestion {
|
||||
|
|
|
@ -13,11 +13,17 @@ mod consumer;
|
|||
pub use consumer::Consumer;
|
||||
|
||||
mod ingestion;
|
||||
pub use ingestion::{Ingestion, IngestionKind, SubstanceIngestion};
|
||||
pub use ingestion::{Ingestion, IngestionKind, SubstanceIngestion, SustenanceIngestion};
|
||||
|
||||
mod substance;
|
||||
pub use substance::Substance;
|
||||
|
||||
mod nutrients;
|
||||
pub use nutrients::Nutrients;
|
||||
|
||||
mod sustenance;
|
||||
pub use sustenance::Sustenance;
|
||||
|
||||
mod session;
|
||||
pub use session::Session;
|
||||
|
||||
|
|
5
journal/src/types/nutrients.rs
Normal file
5
journal/src/types/nutrients.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
#[derive(Debug, Clone)]
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct Nutrients {
|
||||
pub kcal: u64,
|
||||
}
|
13
journal/src/types/sustenance.rs
Normal file
13
journal/src/types/sustenance.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
use super::{IngestionKind, Nutrients};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct Sustenance {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
|
||||
pub unit: String,
|
||||
pub nutrients: Option<Nutrients>,
|
||||
|
||||
pub includes: Vec<IngestionKind>,
|
||||
}
|
|
@ -64,7 +64,7 @@ pub fn journal_import_psychonaut(
|
|||
let mut rng = rand::thread_rng();
|
||||
|
||||
for custom_unit in export_data.custom_units.into_iter() {
|
||||
journal.set_custom_unit(custom_unit.id, CustomUnit::from(custom_unit));
|
||||
journal.set_custom_unit(CustomUnit::from(custom_unit));
|
||||
}
|
||||
|
||||
for custom_substance in export_data.custom_substances.into_iter() {
|
||||
|
@ -79,14 +79,11 @@ pub fn journal_import_psychonaut(
|
|||
}
|
||||
None => {
|
||||
if args.infer_missing_substances {
|
||||
journal.set_substance(
|
||||
&custom_substance.name,
|
||||
Substance {
|
||||
name: custom_substance.name.clone(),
|
||||
description: custom_substance.description.clone(),
|
||||
unit: custom_substance.units,
|
||||
},
|
||||
);
|
||||
journal.set_substance(Substance {
|
||||
name: custom_substance.name.clone(),
|
||||
description: custom_substance.description.clone(),
|
||||
unit: custom_substance.units,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -114,14 +111,11 @@ pub fn journal_import_psychonaut(
|
|||
}
|
||||
}
|
||||
None => {
|
||||
journal.set_substance(
|
||||
substance_name,
|
||||
Substance {
|
||||
name: substance_name.clone(),
|
||||
description: "".to_string(),
|
||||
unit: ingestion_unit,
|
||||
},
|
||||
);
|
||||
journal.set_substance(Substance {
|
||||
name: substance_name.clone(),
|
||||
description: "".to_string(),
|
||||
unit: ingestion_unit,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -135,13 +129,10 @@ pub fn journal_import_psychonaut(
|
|||
|
||||
let session_id = rng.gen::<i32>();
|
||||
|
||||
journal.set_session(
|
||||
session_id,
|
||||
Session {
|
||||
id: session_id,
|
||||
..Session::from(experience.clone())
|
||||
},
|
||||
);
|
||||
journal.set_session(Session {
|
||||
id: session_id,
|
||||
..Session::from(experience.clone())
|
||||
});
|
||||
|
||||
let mut ingestions: Vec<Ingestion> = Vec::new();
|
||||
for ingestion in experience.ingestions.iter() {
|
||||
|
|
|
@ -12,8 +12,6 @@ pub struct PrintSessionArgs {
|
|||
#[command(flatten)]
|
||||
pub journal_location: JournalLocation,
|
||||
|
||||
#[arg(long)]
|
||||
pub substance_filter: Option<Vec<String>>,
|
||||
#[arg(long, value_delimiter = ',')]
|
||||
pub consumer_filter: Option<Vec<String>>,
|
||||
}
|
||||
|
@ -46,15 +44,9 @@ pub fn print_session(args: &PrintSessionArgs) -> Result<(), Box<dyn std::error::
|
|||
|
||||
println!("{}", format_session_title(&session));
|
||||
|
||||
let substance_filter = args.substance_filter.clone();
|
||||
let consumer_filter = parse_consumer_filter(args.consumer_filter.clone());
|
||||
|
||||
print_ingestion_log(
|
||||
&journal,
|
||||
&session,
|
||||
substance_filter.as_ref(),
|
||||
consumer_filter.as_ref(),
|
||||
);
|
||||
print_ingestion_log(&journal, &session, consumer_filter.as_ref());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,36 +1,144 @@
|
|||
use journal::{
|
||||
journal::JournalType,
|
||||
types::{format_dose, Consumer, IngestionKind, Session},
|
||||
types::{
|
||||
format_dose, Consumer, Dose, Ingestion, IngestionKind, Session, SubstanceIngestion,
|
||||
SustenanceIngestion,
|
||||
},
|
||||
};
|
||||
|
||||
use crate::formatting::{format_ingestion_time, format_substance_ingestion_roa};
|
||||
|
||||
fn print_substance_ingestion(
|
||||
journal: &JournalType,
|
||||
ingestion: &Ingestion,
|
||||
substance_ingestion: &SubstanceIngestion,
|
||||
) {
|
||||
let unit = journal.resolve_substance_unit(substance_ingestion).unwrap();
|
||||
|
||||
println!(
|
||||
"Substance|{}|{}|{}|{}|{}",
|
||||
substance_ingestion.substance_name,
|
||||
format_dose(&substance_ingestion.dose, &unit),
|
||||
format_substance_ingestion_roa(substance_ingestion, &unit),
|
||||
ingestion.consumer,
|
||||
format_ingestion_time(ingestion)
|
||||
)
|
||||
}
|
||||
|
||||
fn print_sustenance_ingestion(
|
||||
journal: &JournalType,
|
||||
ingestion: &Ingestion,
|
||||
sustenance_ingestion: &SustenanceIngestion,
|
||||
) {
|
||||
let sustenance = journal
|
||||
.get_sustenance(&sustenance_ingestion.sustenance_id)
|
||||
.unwrap();
|
||||
|
||||
println!(
|
||||
"Sustenance|{}|{} {}|{}|{}",
|
||||
sustenance.name,
|
||||
sustenance_ingestion.amount,
|
||||
sustenance.unit,
|
||||
ingestion.consumer,
|
||||
format_ingestion_time(ingestion)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn resolve_ingestion(journal: &JournalType, ingestion: &IngestionKind) -> Vec<IngestionKind> {
|
||||
//println!("{ingestion:?}");
|
||||
|
||||
let mut ingestions: Vec<IngestionKind> = Vec::new();
|
||||
|
||||
match &ingestion {
|
||||
IngestionKind::Substance(substance) => {
|
||||
ingestions.push(IngestionKind::Substance(substance.clone()));
|
||||
}
|
||||
IngestionKind::Hydration { amount: _ } => {
|
||||
ingestions.push(ingestion.clone());
|
||||
}
|
||||
IngestionKind::Sustenance(sustenance) => {
|
||||
let sustenance_ingestions = journal
|
||||
.get_sustenance_ingestions(&sustenance.sustenance_id)
|
||||
.unwrap();
|
||||
|
||||
for sustenance_ingestion in sustenance_ingestions.into_iter() {
|
||||
match sustenance_ingestion {
|
||||
IngestionKind::Substance(substance_ingestion) => {
|
||||
ingestions.push(IngestionKind::Substance(SubstanceIngestion {
|
||||
dose: Dose::new_precise(sustenance.amount) * substance_ingestion.dose,
|
||||
..substance_ingestion
|
||||
}))
|
||||
}
|
||||
IngestionKind::Sustenance(sustenance_ingestion) => {
|
||||
ingestions.push(IngestionKind::Sustenance(SustenanceIngestion {
|
||||
amount: sustenance.amount * sustenance_ingestion.amount,
|
||||
..sustenance_ingestion
|
||||
}))
|
||||
}
|
||||
IngestionKind::Hydration { amount } => {
|
||||
ingestions.push(IngestionKind::Hydration {
|
||||
amount: (sustenance.amount * amount as f64).round() as u64,
|
||||
})
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
//println!("{ingestions:#?}");
|
||||
ingestions
|
||||
}
|
||||
|
||||
pub fn print_ingestion(journal: &JournalType, ingestion: &Ingestion, kind: &IngestionKind) {
|
||||
match kind {
|
||||
IngestionKind::Unknown => {}
|
||||
IngestionKind::Substance(substance_ingestion) => {
|
||||
print_substance_ingestion(journal, ingestion, substance_ingestion);
|
||||
}
|
||||
IngestionKind::Sustenance(sustenance_ingestion) => {
|
||||
print_sustenance_ingestion(journal, ingestion, sustenance_ingestion);
|
||||
}
|
||||
IngestionKind::Hydration { amount } => {
|
||||
println!(
|
||||
"Hydration|{} ml|{}|{}",
|
||||
amount,
|
||||
ingestion.consumer,
|
||||
format_ingestion_time(ingestion)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_ingestion_log(
|
||||
journal: &JournalType,
|
||||
session: &Session,
|
||||
substance_filter: Option<&Vec<String>>,
|
||||
consumer_filter: Option<&Vec<Consumer>>,
|
||||
) {
|
||||
for ingestion in journal
|
||||
.get_session_substance_ingestions_by(session.id, substance_filter, None, consumer_filter)
|
||||
.get_session_ingestions(session.id)
|
||||
.expect("could not find ingestions for session")
|
||||
.iter()
|
||||
{
|
||||
let substance_ingestion = match &ingestion.kind {
|
||||
IngestionKind::Substance(substance_ingestion) => substance_ingestion,
|
||||
_ => continue,
|
||||
};
|
||||
if let Some(consumer_filter) = consumer_filter {
|
||||
if !consumer_filter.contains(&ingestion.consumer) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let unit = journal.resolve_substance_unit(substance_ingestion).unwrap();
|
||||
// println!("{:#?} {:#?}", &ingestion, &custom_unit);
|
||||
match &ingestion.kind {
|
||||
IngestionKind::Sustenance(_) => {
|
||||
print_ingestion(journal, ingestion, &ingestion.kind);
|
||||
|
||||
println!(
|
||||
"{}|{}|{}|{}|{}",
|
||||
substance_ingestion.substance_name,
|
||||
format_dose(&substance_ingestion.dose, &unit),
|
||||
format_substance_ingestion_roa(substance_ingestion, &unit),
|
||||
ingestion.consumer,
|
||||
format_ingestion_time(ingestion)
|
||||
)
|
||||
for kind in resolve_ingestion(journal, &ingestion.kind) {
|
||||
print!("- ");
|
||||
print_ingestion(journal, ingestion, &kind)
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
print_ingestion(journal, ingestion, &ingestion.kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue