From acf2e040c375726ead66dfcd4273ff96a2082bdb Mon Sep 17 00:00:00 2001 From: Sebastian Kuzminsky Date: Wed, 2 Apr 2025 22:40:41 -0600 Subject: [PATCH] add list of printed parts to BuildPlan and mdbook overview --- tools/src/build_plan.rs | 71 ++++++++++++++++++++++++++++++++++++++++- tools/src/quantity.rs | 7 ++++ tools/src/repos.rs | 44 ++++++++++++++++++------- 3 files changed, 109 insertions(+), 13 deletions(-) diff --git a/tools/src/build_plan.rs b/tools/src/build_plan.rs index a9e77ef..83356fd 100644 --- a/tools/src/build_plan.rs +++ b/tools/src/build_plan.rs @@ -38,6 +38,11 @@ pub struct BuildPlan<'a> { /// Values are Items, which are just the name and a Quantity. pub bom: std::collections::HashMap, + /// Printed parts needed to build this Item. + /// Keys are the names of Items. + /// Values are Items, which are just the name and a Quantity. + pub prints: std::collections::HashMap, + /// Tools needed to build this Item. pub tools: std::collections::HashSet, @@ -52,6 +57,7 @@ impl<'a> BuildPlan<'a> { BuildPlan { name: target, bom: std::collections::HashMap::::new(), + prints: std::collections::HashMap::::new(), tools: std::collections::HashSet::::new(), skills: std::collections::HashSet::::new(), repos, @@ -128,6 +134,7 @@ impl<'a> BuildPlan<'a> { writeln!(summary_md_file, "- [Overview](overview/overview.md)")?; self.write_mdbook_bom(&overview_dirname, summary_md_file)?; + self.write_mdbook_prints(&overview_dirname, summary_md_file)?; self.write_mdbook_tools(&overview_dirname, summary_md_file)?; self.write_mdbook_skills(&overview_dirname, summary_md_file)?; @@ -188,6 +195,68 @@ impl<'a> BuildPlan<'a> { Ok(()) } + fn write_mdbook_prints( + &self, + overview_dirname: &str, + summary_md_file: &mut std::fs::File, + ) -> Result<(), MdbookError> { + if self.prints.len() == 0 { + return Ok(()); + } + + let prints_md_filename = format!("{overview_dirname}/prints.md"); + let mut prints_md_file = std::fs::File::create(&prints_md_filename)?; + + writeln!(prints_md_file, "# Printed parts")?; + writeln!(prints_md_file, "")?; + + let mut names: Vec<&String> = self.prints.keys().collect(); + names.sort(); + for name in names { + self.write_mdbook_printed_part(&mut prints_md_file, &name)?; + } + + writeln!(summary_md_file, " - [Printed parts](overview/prints.md)")?; + + Ok(()) + } + + fn write_mdbook_printed_part( + &self, + prints_md_file: &mut std::fs::File, + name: &str, + ) -> Result<(), MdbookError> { + let item = self + .prints + .get(name) + .ok_or(MdbookError::BuildPlanError(format!( + "item {name} not found" + )))?; + writeln!(prints_md_file, "## {name}")?; + writeln!( + prints_md_file, + "Quantity: {:?}\n", + item.quantity.amount as usize + )?; + + let recipe = self.repos.get_recipe(name)?; + match &recipe.action { + crate::recipe::Action::print(printed_part) => { + writeln!( + prints_md_file, + "Model: [{}]({})\n", + printed_part.model, printed_part.model + )?; + writeln!(prints_md_file, "Print profile: {}\n", printed_part.profile)?; + } + _ => { + panic!("printed part {} has wrong Action {:?}", name, recipe.action); + } + } + + Ok(()) + } + fn write_mdbook_tools( &self, overview_dirname: &str, @@ -240,7 +309,7 @@ impl<'a> BuildPlan<'a> { summary_md_file: &mut std::fs::File, ) -> Result<(), MdbookError> { let recipe = self.repos.get_recipe(recipe_name)?; - if recipe.is_vitamin() { + if recipe.is_vitamin() || recipe.is_print() { return Ok(()); } diff --git a/tools/src/quantity.rs b/tools/src/quantity.rs index 54a8f0c..528b411 100644 --- a/tools/src/quantity.rs +++ b/tools/src/quantity.rs @@ -62,3 +62,10 @@ impl std::ops::Add<&Quantity> for Quantity { } } } + +impl std::ops::AddAssign for Quantity { + fn add_assign(&mut self, rhs: usize) { + assert_eq!(self.unit, None); + self.amount += rhs as f32; + } +} diff --git a/tools/src/repos.rs b/tools/src/repos.rs index 0bf921a..6916485 100644 --- a/tools/src/repos.rs +++ b/tools/src/repos.rs @@ -129,21 +129,41 @@ impl Repos { recipe: &Recipe, // the recipe for the thing we're making indent: usize, ) -> Result<(), RecipeCompileError> { + if let Some(tools) = &recipe.dependencies.tools { + for tool in tools.iter() { + build_plan.tools.insert(tool.clone()); + } + } + + if let Some(operator) = &recipe.dependencies.operator { + for skill in operator.skills.iter() { + build_plan.skills.insert(skill.clone()); + } + } + + if recipe.is_print() { + match build_plan.prints.get_mut(recipe_name) { + Some(item) => { + item.quantity += quantity; + } + None => { + build_plan.prints.insert( + String::from(recipe_name), + crate::build_plan::Item { + name: String::from(recipe_name), + quantity: crate::quantity::Quantity { + amount: quantity as f32, + unit: None, + }, + }, + ); + } + } + } + for (input_name, input_info) in recipe.inputs.iter() { let input_recipe = self.get_recipe(input_name)?; - if let Some(tools) = &recipe.dependencies.tools { - for tool in tools.iter() { - build_plan.tools.insert(tool.clone()); - } - } - - if let Some(operator) = &recipe.dependencies.operator { - for skill in operator.skills.iter() { - build_plan.skills.insert(skill.clone()); - } - } - if input_recipe.is_vitamin() { match build_plan.bom.get_mut(input_name) { Some(item) => {