update
This commit is contained in:
parent
956c3f6ad1
commit
d7fb6f147a
|
@ -5,24 +5,29 @@ use crate::types::{
|
||||||
pub type JournalType = Box<dyn Journal>;
|
pub type JournalType = Box<dyn Journal>;
|
||||||
|
|
||||||
pub trait Journal {
|
pub trait Journal {
|
||||||
fn get_custom_unit(&self, id: i32) -> Option<CustomUnit>;
|
fn save(&self) -> Result<(), Box<dyn std::error::Error>>;
|
||||||
|
|
||||||
fn get_session(&self, id: i32) -> Option<Session>;
|
fn get_session(&self, id: i32) -> Option<Session>;
|
||||||
fn get_session_ingestions(&self, id: i32) -> Option<Vec<Ingestion>>;
|
fn get_session_ingestions(&self, id: i32) -> Option<Vec<Ingestion>>;
|
||||||
|
|
||||||
fn get_substance(&self, name: &str) -> Option<Substance>;
|
fn get_substance(&self, name: &str) -> Option<Substance>;
|
||||||
fn get_sustenance(&self, sustenance_id: &str) -> Option<Sustenance>;
|
fn get_sustenance(&self, id: &str) -> Option<Sustenance>;
|
||||||
fn get_sustenance_ingestions(&self, sustenance_id: &str) -> Option<Vec<IngestionKind>>;
|
fn get_sustenance_ingestions(&self, id: &str) -> Option<Vec<IngestionKind>>;
|
||||||
|
fn get_custom_unit(&self, id: i32) -> Option<CustomUnit>;
|
||||||
|
|
||||||
|
fn create_session(&mut self, title: &str) -> Session;
|
||||||
|
fn create_substance(&mut self, substance: Substance) -> Substance;
|
||||||
|
fn create_sustenance(&mut self, sustenance: Sustenance) -> Sustenance;
|
||||||
|
fn create_custom_unit(&mut self, unit: CustomUnit) -> CustomUnit;
|
||||||
|
|
||||||
|
fn update_session(&mut self, id: i32, session: Session, create: bool);
|
||||||
|
fn update_substance(&mut self, name: &str, substance: Substance, create: bool);
|
||||||
|
fn update_sustenance(&mut self, id: &str, sustenance: Sustenance, create: bool);
|
||||||
|
fn update_custom_unit(&mut self, id: i32, unit: CustomUnit, create: bool);
|
||||||
|
|
||||||
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_session_ingestions(&mut self, session_id: i32, ingestions: Vec<Ingestion>);
|
||||||
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 first_session_by_title(&self, title: &str) -> Option<Session>;
|
||||||
fn resolve_substance_unit(&self, ingestion: &SubstanceIngestion) -> Option<Unit>;
|
fn resolve_substance_unit(&self, ingestion: &SubstanceIngestion) -> Option<Unit>;
|
||||||
|
|
||||||
fn save(&self) -> Result<(), Box<dyn std::error::Error>>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mod json_journal;
|
mod json_journal;
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
use std::{collections::HashMap, fs::File};
|
use std::{collections::HashMap, fs::File};
|
||||||
|
|
||||||
|
use chrono::Utc;
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
CustomUnit, Ingestion, IngestionKind, Session, Substance, SubstanceIngestion, Sustenance, Unit,
|
CustomUnit, Ingestion, IngestionKind, Session, Substance, SubstanceIngestion, Sustenance, Unit,
|
||||||
};
|
};
|
||||||
|
@ -59,8 +62,8 @@ impl JSONJournal {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Journal for JSONJournal {
|
impl Journal for JSONJournal {
|
||||||
fn get_custom_unit(&self, id: i32) -> Option<CustomUnit> {
|
fn save(&self) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
self.data.custom_units.get(&id).cloned()
|
self.save()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_session(&self, id: i32) -> Option<Session> {
|
fn get_session(&self, id: i32) -> Option<Session> {
|
||||||
|
@ -75,58 +78,12 @@ impl Journal for JSONJournal {
|
||||||
self.data.substances.get(name).cloned()
|
self.data.substances.get(name).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_substance_unit(&self, ingestion: &SubstanceIngestion) -> Option<Unit> {
|
|
||||||
match ingestion.custom_unit_id {
|
|
||||||
None => match self.get_substance(&ingestion.substance_name) {
|
|
||||||
Some(substance) => Some(Unit::Simple(substance.unit)),
|
|
||||||
None => None,
|
|
||||||
},
|
|
||||||
Some(custom_unit_id) => self.get_custom_unit(custom_unit_id).map(Unit::Custom),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn first_session_by_title(&self, title: &str) -> Option<Session> {
|
|
||||||
self.data
|
|
||||||
.sessions
|
|
||||||
.values()
|
|
||||||
.find(|&session| session.title == title)
|
|
||||||
.cloned()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_custom_unit(&mut self, unit: CustomUnit) {
|
|
||||||
self.data.custom_units.insert(unit.id, unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
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, 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> {
|
fn get_sustenance(&self, sustenance_id: &str) -> Option<Sustenance> {
|
||||||
self.data.sustenances.get(sustenance_id).cloned()
|
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>> {
|
fn get_sustenance_ingestions(&self, sustenance_id: &str) -> Option<Vec<IngestionKind>> {
|
||||||
let sustenance = self.get_sustenance(sustenance_id).unwrap();
|
let sustenance = self.get_sustenance(sustenance_id)?;
|
||||||
|
|
||||||
let mut ingestions: Vec<IngestionKind> = Vec::new();
|
let mut ingestions: Vec<IngestionKind> = Vec::new();
|
||||||
for include in sustenance.includes.into_iter() {
|
for include in sustenance.includes.into_iter() {
|
||||||
|
@ -152,4 +109,107 @@ impl Journal for JSONJournal {
|
||||||
|
|
||||||
Some(ingestions)
|
Some(ingestions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_custom_unit(&self, id: i32) -> Option<CustomUnit> {
|
||||||
|
self.data.custom_units.get(&id).cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_session(&mut self, title: &str) -> Session {
|
||||||
|
let id = rand::thread_rng().gen::<i32>();
|
||||||
|
|
||||||
|
let session = Session {
|
||||||
|
id,
|
||||||
|
title: title.to_string(),
|
||||||
|
creation_time: Utc::now(),
|
||||||
|
..Session::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
self.data.sessions.insert(id, session.clone());
|
||||||
|
|
||||||
|
session
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_substance(&mut self, substance: Substance) -> Substance {
|
||||||
|
self.data
|
||||||
|
.substances
|
||||||
|
.insert(substance.name.clone(), substance.clone());
|
||||||
|
|
||||||
|
substance
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_sustenance(&mut self, sustenance: Sustenance) -> Sustenance {
|
||||||
|
self.data
|
||||||
|
.sustenances
|
||||||
|
.insert(sustenance.id.clone(), sustenance.clone());
|
||||||
|
|
||||||
|
sustenance
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_custom_unit(&mut self, unit: CustomUnit) -> CustomUnit {
|
||||||
|
let id = rand::thread_rng().gen::<i32>();
|
||||||
|
|
||||||
|
let unit = CustomUnit { id, ..unit };
|
||||||
|
|
||||||
|
self.data.custom_units.insert(id, unit.clone());
|
||||||
|
|
||||||
|
unit
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_session(&mut self, id: i32, session: Session, create: bool) {
|
||||||
|
assert!(self.data.sessions.contains_key(&id) || create);
|
||||||
|
|
||||||
|
self.data.sessions.insert(id, Session { id, ..session });
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_substance(&mut self, name: &str, substance: Substance, create: bool) {
|
||||||
|
assert!(self.data.substances.contains_key(name) || create);
|
||||||
|
|
||||||
|
self.data.substances.insert(
|
||||||
|
name.to_string(),
|
||||||
|
Substance {
|
||||||
|
name: name.to_string(),
|
||||||
|
..substance
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_sustenance(&mut self, id: &str, sustenance: Sustenance, create: bool) {
|
||||||
|
assert!(self.data.sustenances.contains_key(id) || create);
|
||||||
|
|
||||||
|
self.data.sustenances.insert(
|
||||||
|
id.to_string(),
|
||||||
|
Sustenance {
|
||||||
|
id: id.to_string(),
|
||||||
|
..sustenance
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_custom_unit(&mut self, id: i32, unit: CustomUnit, create: bool) {
|
||||||
|
assert!(self.data.custom_units.contains_key(&id) || create);
|
||||||
|
|
||||||
|
self.data.custom_units.insert(id, CustomUnit { id, ..unit });
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_session_ingestions(&mut self, session_id: i32, ingestions: Vec<Ingestion>) {
|
||||||
|
self.data.ingestions.insert(session_id, ingestions);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn first_session_by_title(&self, title: &str) -> Option<Session> {
|
||||||
|
self.data
|
||||||
|
.sessions
|
||||||
|
.values()
|
||||||
|
.find(|&session| session.title == title)
|
||||||
|
.cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_substance_unit(&self, ingestion: &SubstanceIngestion) -> Option<Unit> {
|
||||||
|
match ingestion.custom_unit_id {
|
||||||
|
None => match self.get_substance(&ingestion.substance_name) {
|
||||||
|
Some(substance) => Some(Unit::Simple(substance.unit)),
|
||||||
|
None => None,
|
||||||
|
},
|
||||||
|
Some(custom_unit_id) => self.get_custom_unit(custom_unit_id).map(Unit::Custom),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::{collections::HashMap, fs::File, path::Path};
|
use std::{collections::HashMap, fs::File, path::Path};
|
||||||
|
|
||||||
use journal::{
|
use journal::{
|
||||||
journal::{JSONJournal, Journal},
|
journal::{JSONJournal, Journal, JournalType},
|
||||||
types::{CustomUnit, Ingestion, Session, Substance},
|
types::{CustomUnit, Ingestion, Session, Substance},
|
||||||
};
|
};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
@ -22,8 +22,13 @@ pub struct JournalImportPsychonautArgs {
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub force_create: bool,
|
pub force_create: bool,
|
||||||
|
|
||||||
#[arg(long, value_hint = clap::ValueHint::FilePath)]
|
#[arg(long)]
|
||||||
pub mappings_file: Option<String>,
|
pub custom_unit_id: Option<i32>,
|
||||||
|
#[arg(long)]
|
||||||
|
pub custom_unit_name: Option<String>,
|
||||||
|
|
||||||
|
#[arg(long)]
|
||||||
|
pub custom_substance: Option<String>,
|
||||||
|
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub infer_missing_substances: bool,
|
pub infer_missing_substances: bool,
|
||||||
|
@ -52,49 +57,126 @@ pub fn journal_import_psychonaut(
|
||||||
let export_file = File::open(args.export_file.clone())?;
|
let export_file = File::open(args.export_file.clone())?;
|
||||||
let export_data: psychonaut_journal_types::ExportData = serde_json::from_reader(export_file)?;
|
let export_data: psychonaut_journal_types::ExportData = serde_json::from_reader(export_file)?;
|
||||||
|
|
||||||
let mappings: Mappings = match args.mappings_file.clone() {
|
|
||||||
Some(filename) => {
|
|
||||||
let mappings_file = File::open(filename)?;
|
|
||||||
let mappings_data: Mappings = serde_json::from_reader(mappings_file)?;
|
|
||||||
mappings_data
|
|
||||||
}
|
|
||||||
None => Mappings::default(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
for custom_unit in export_data.custom_units.into_iter() {
|
fn create_or_update_custom_unit(journal: &mut JournalType, unit: CustomUnit) {
|
||||||
journal.set_custom_unit(CustomUnit::from(custom_unit));
|
match journal.get_custom_unit(unit.id) {
|
||||||
|
Some(custom_unit) => {
|
||||||
|
println!(
|
||||||
|
"Updating Custom Unit ID: {} Name: {}",
|
||||||
|
unit.id, custom_unit.name
|
||||||
|
);
|
||||||
|
journal.update_custom_unit(unit.id, unit, false);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
println!("Creating Custom Unit ID: {} Name: {}", unit.id, unit.name);
|
||||||
|
journal.update_custom_unit(unit.id, unit, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for custom_substance in export_data.custom_substances.into_iter() {
|
if let Some(id) = &args.custom_unit_id {
|
||||||
|
let unit = export_data
|
||||||
|
.custom_units
|
||||||
|
.into_iter()
|
||||||
|
.find(|unit| unit.id == *id);
|
||||||
|
|
||||||
|
match unit {
|
||||||
|
Some(unit) => {
|
||||||
|
create_or_update_custom_unit(&mut journal, CustomUnit::from(unit));
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
panic!("Could not find custom unit with ID: {id}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
} else if let Some(name) = &args.custom_unit_name {
|
||||||
|
let unit = export_data
|
||||||
|
.custom_units
|
||||||
|
.into_iter()
|
||||||
|
.find(|unit| unit.name == *name);
|
||||||
|
|
||||||
|
match unit {
|
||||||
|
Some(unit) => {
|
||||||
|
create_or_update_custom_unit(&mut journal, CustomUnit::from(unit));
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
panic!("Could not find custom unit with name: {name}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
} else if args.custom_substance.is_none() {
|
||||||
|
for custom_unit in export_data.custom_units.into_iter() {
|
||||||
|
create_or_update_custom_unit(&mut journal, CustomUnit::from(custom_unit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_or_check_custom_substance(
|
||||||
|
journal: &mut JournalType,
|
||||||
|
args: &JournalImportPsychonautArgs,
|
||||||
|
custom_substance: Substance,
|
||||||
|
) {
|
||||||
match journal.get_substance(&custom_substance.name) {
|
match journal.get_substance(&custom_substance.name) {
|
||||||
Some(substance) => {
|
Some(substance) => {
|
||||||
if substance.unit != custom_substance.units {
|
println!("Checking substance units {}", custom_substance.name);
|
||||||
|
|
||||||
|
if substance.unit != custom_substance.unit {
|
||||||
panic!(
|
panic!(
|
||||||
"mismatch on units for {}: {} != {} ",
|
"mismatch on unit for {}: {} != {} ",
|
||||||
custom_substance.name, substance.unit, custom_substance.units
|
custom_substance.name, substance.unit, custom_substance.unit
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if args.infer_missing_substances {
|
if args.infer_missing_substances {
|
||||||
journal.set_substance(Substance {
|
println!("Creating substance {}", custom_substance.name);
|
||||||
name: custom_substance.name.clone(),
|
journal.create_substance(custom_substance);
|
||||||
description: custom_substance.description.clone(),
|
|
||||||
unit: custom_substance.units,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(substance_name) = &args.custom_substance {
|
||||||
|
let custom_substance: Option<psychonaut_journal_types::CustomSubstance> = export_data
|
||||||
|
.custom_substances
|
||||||
|
.into_iter()
|
||||||
|
.find(|substance| substance.name == *substance_name);
|
||||||
|
|
||||||
|
match custom_substance {
|
||||||
|
Some(custom_substance) => {
|
||||||
|
create_or_check_custom_substance(
|
||||||
|
&mut journal,
|
||||||
|
args,
|
||||||
|
Substance::from(Substance {
|
||||||
|
name: custom_substance.name.clone(),
|
||||||
|
description: custom_substance.description.clone(),
|
||||||
|
unit: custom_substance.units,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
panic!("Could not find substance with name: {substance_name}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for custom_substance in export_data.custom_substances.into_iter() {
|
||||||
|
create_or_check_custom_substance(
|
||||||
|
&mut journal,
|
||||||
|
args,
|
||||||
|
Substance {
|
||||||
|
name: custom_substance.name.clone(),
|
||||||
|
description: custom_substance.description.clone(),
|
||||||
|
unit: custom_substance.units,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for experience in export_data.experiences.iter() {
|
for experience in export_data.experiences.iter() {
|
||||||
for ingestion in experience.ingestions.iter() {
|
for ingestion in experience.ingestions.iter() {
|
||||||
let substance_name = mappings
|
let substance_name = &ingestion.substance_name;
|
||||||
.substance_names
|
|
||||||
.get(&ingestion.substance_name)
|
|
||||||
.unwrap_or(&ingestion.substance_name);
|
|
||||||
|
|
||||||
let ingestion_unit = match ingestion.custom_unit_id {
|
let ingestion_unit = match ingestion.custom_unit_id {
|
||||||
Some(id) => journal.get_custom_unit(id).unwrap().original_unit,
|
Some(id) => journal.get_custom_unit(id).unwrap().original_unit,
|
||||||
|
@ -111,7 +193,7 @@ pub fn journal_import_psychonaut(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
journal.set_substance(Substance {
|
journal.create_substance(Substance {
|
||||||
name: substance_name.clone(),
|
name: substance_name.clone(),
|
||||||
description: "".to_string(),
|
description: "".to_string(),
|
||||||
unit: ingestion_unit,
|
unit: ingestion_unit,
|
||||||
|
@ -125,14 +207,20 @@ pub fn journal_import_psychonaut(
|
||||||
if journal.first_session_by_title(&experience.title).is_some() {
|
if journal.first_session_by_title(&experience.title).is_some() {
|
||||||
println!("Skipping {} as is already in journal", experience.title);
|
println!("Skipping {} as is already in journal", experience.title);
|
||||||
continue;
|
continue;
|
||||||
|
} else {
|
||||||
|
println!("Creating experience {}", experience.title);
|
||||||
}
|
}
|
||||||
|
|
||||||
let session_id = rng.gen::<i32>();
|
let session_id = rng.gen::<i32>();
|
||||||
|
|
||||||
journal.set_session(Session {
|
journal.update_session(
|
||||||
id: session_id,
|
session_id,
|
||||||
..Session::from(experience.clone())
|
Session {
|
||||||
});
|
id: session_id,
|
||||||
|
..Session::from(experience.clone())
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
let mut ingestions: Vec<Ingestion> = Vec::new();
|
let mut ingestions: Vec<Ingestion> = Vec::new();
|
||||||
for ingestion in experience.ingestions.iter() {
|
for ingestion in experience.ingestions.iter() {
|
||||||
|
|
Loading…
Reference in a new issue