diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..9ff7dc3 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,25 @@ +FROM debian:testing + +RUN ( \ + set -e; \ + apt-get -yq update; \ + apt-get -yq install \ + build-essential \ + curl \ + mdbook \ + plantuml \ + vim-nox \ + ; \ + apt-get clean; \ +) + +ENV RUSTUP_HOME=/opt/rustup +ENV CARGO_HOME=/opt/cargo + +RUN ( \ + set -e; \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y ; \ + chmod 777 /opt/rustup /opt/cargo; \ +) + +ENV PATH="$PATH:$CARGO_HOME/bin" diff --git a/modular-recipes/repos/minimal_hydroponics_setup/barb_fitting_1_2_inch.toml b/modular-recipes/repos/minimal_hydroponics_setup/barb_fitting_1_2_inch.toml index 48ab75c..38f8d88 100644 --- a/modular-recipes/repos/minimal_hydroponics_setup/barb_fitting_1_2_inch.toml +++ b/modular-recipes/repos/minimal_hydroponics_setup/barb_fitting_1_2_inch.toml @@ -1,11 +1,12 @@ [inputs] -capital = { quantity = { amount=5.75, unit="USDollar" } } +capital = { quantity = { amount=2.59, unit="USDollar" } } [dependencies] operator = {skills=["vendor interaction"]} [action.purchase] vendor = [ + "https://acmehydroponics.net/collections/plumbing/products/fill-drain-1-2-fitting", "https://www.ebay.com/itm/134772441988", "https://www.ebay.com/itm/251050375775?var=554293415440", "https://www.ebay.com/itm/251313018420", diff --git a/modular-recipes/repos/minimal_hydroponics_setup/barb_fitting_1_inch.toml b/modular-recipes/repos/minimal_hydroponics_setup/barb_fitting_1_inch.toml index 1a0994c..e111c11 100644 --- a/modular-recipes/repos/minimal_hydroponics_setup/barb_fitting_1_inch.toml +++ b/modular-recipes/repos/minimal_hydroponics_setup/barb_fitting_1_inch.toml @@ -1,10 +1,11 @@ [inputs] -capital = { quantity = { amount=15.19, unit="USDollar" } } +capital = { quantity = { amount=2.49, unit="USDollar" } } [dependencies] operator = {skills=["vendor interaction"]} [action.purchase] vendor = [ - "https://www.botanicare.com/products/fittings/" + "https://www.botanicare.com/products/fittings/", + "https://acmehydroponics.net/collections/plumbing/products/fill-drain-1-fitting" ] diff --git a/modular-recipes/repos/minimal_hydroponics_setup/filter.toml b/modular-recipes/repos/minimal_hydroponics_setup/filter.toml new file mode 100644 index 0000000..8c03d18 --- /dev/null +++ b/modular-recipes/repos/minimal_hydroponics_setup/filter.toml @@ -0,0 +1,12 @@ +[inputs] +capital = { quantity = { amount=0.96, unit="USDollar" } } + +[dependencies] +operator = {skills=["vendor interaction"]} + +[action.purchase] +vendor = [ + "https://acmehydroponics.net/collections/plumbing/products/screen-fitting-plumbing", + "https://hydrobuilder.com/products/grow1-ebb-flow-screen-fittings-pack-of-10", + "https://www.ebay.com/itm/256644061627" +] diff --git a/modular-recipes/repos/minimal_hydroponics_setup/nutrient_reservoir_lid.toml b/modular-recipes/repos/minimal_hydroponics_setup/nutrient_reservoir_lid.toml index 4b52191..e5a0e69 100644 --- a/modular-recipes/repos/minimal_hydroponics_setup/nutrient_reservoir_lid.toml +++ b/modular-recipes/repos/minimal_hydroponics_setup/nutrient_reservoir_lid.toml @@ -2,8 +2,11 @@ food_safe_bucket_lid = {} [dependencies] -tools = [ "hole saw" ] +tools = [ "hack saw" ] [action] -process = """Drill three holes in the lid the right size to fit the 1 -inch tube, the 1/2 inch tube, and the pump's power cord through.""" +process = """Use the holes drilled in the `plant_tray_basin` to mark +the `food_safe_bucket_lid`. Cut the lid to make room for the two barb +fittings, so the `plant_tray_basin` can sit in the lid comfortably. +This cut will also make room for the `nutrient_pump` power cord to +exit.""" diff --git a/modular-recipes/repos/minimal_hydroponics_setup/overflow_fitting.toml b/modular-recipes/repos/minimal_hydroponics_setup/overflow_fitting.toml new file mode 100644 index 0000000..97fd3c5 --- /dev/null +++ b/modular-recipes/repos/minimal_hydroponics_setup/overflow_fitting.toml @@ -0,0 +1,12 @@ +[inputs] +barb_fitting_1_inch = {} +riser = { quantity = { amount = 2 } } +filter = {} + +[dependencies] +operator = {skills=["assembly"]} + +[action] +process = """ +Attach the risers and filter to the barb fitting. +""" diff --git a/modular-recipes/repos/minimal_hydroponics_setup/plant_tray.toml b/modular-recipes/repos/minimal_hydroponics_setup/plant_tray.toml index 11a60bf..96763db 100644 --- a/modular-recipes/repos/minimal_hydroponics_setup/plant_tray.toml +++ b/modular-recipes/repos/minimal_hydroponics_setup/plant_tray.toml @@ -1,13 +1,15 @@ [inputs] plant_tray_basin = {} clay_pebble_grow_medium = { quantity = { amount=5, unit="Liter" } } -barb_fitting_1_inch = {} -barb_fitting_1_2_inch = {} +pump_fitting = {} +overflow_fitting = {} [dependencies] tools = [ "hack saw" ] [action] -process = """Attach the two fittings. - -Add the grow medium.""" +process = """ +* Attach the pump fitting. +* Attach the overflow fitting. +* Add the grow medium. +""" diff --git a/modular-recipes/repos/minimal_hydroponics_setup/plant_tray_basin.toml b/modular-recipes/repos/minimal_hydroponics_setup/plant_tray_basin.toml index bccefbe..7b229bb 100644 --- a/modular-recipes/repos/minimal_hydroponics_setup/plant_tray_basin.toml +++ b/modular-recipes/repos/minimal_hydroponics_setup/plant_tray_basin.toml @@ -5,10 +5,20 @@ plant_tray_basin = { comment = "Alternatively use commercial plastic bus tubs." food_safe_5_gallon_bucket = {} [dependencies] -tools = [ "hack saw", "step drill" ] +tools = [ "hack saw", "step drill correct size for both barb fittings" ] [action] -process = """* Cut the top of the bucket off, leaving a kind of deep dish -or bowl that will holds the plant growth medium and the plants. +process = """ -* Drill holes for the two fittings.""" +* Drill holes for the two fittings. The holes should be pretty close +together, but far enough apart that there's sufficient room for the nuts +that compress the barb fitting gaskets. + +* Temporarily install the overflow fitting, and mark the wall of the +bucket a few inches above the top of the overflow fitting. + +* Cut the top of the bucket off at the mark. This leaves a kind of deep +dish or bowl that will holds the plant growth medium and the plants. +a few inches above the top of the overflow fitting. + +""" diff --git a/modular-recipes/repos/minimal_hydroponics_setup/pump_fitting.toml b/modular-recipes/repos/minimal_hydroponics_setup/pump_fitting.toml new file mode 100644 index 0000000..55e4d3e --- /dev/null +++ b/modular-recipes/repos/minimal_hydroponics_setup/pump_fitting.toml @@ -0,0 +1,11 @@ +[inputs] +barb_fitting_1_2_inch = {} +filter = {} + +[dependencies] +operator = {skills=["assembly"]} + +[action] +process = """ +Attach the filter to the barb fitting. +""" diff --git a/modular-recipes/repos/minimal_hydroponics_setup/riser.toml b/modular-recipes/repos/minimal_hydroponics_setup/riser.toml new file mode 100644 index 0000000..b154f7e --- /dev/null +++ b/modular-recipes/repos/minimal_hydroponics_setup/riser.toml @@ -0,0 +1,11 @@ +[inputs] +capital = { quantity = { amount=0.97, unit="USDollar" } } + +[dependencies] +operator = {skills=["vendor interaction"]} + +[action.purchase] +vendor = [ + "https://acmehydroponics.net/collections/plumbing/products/extension-fitting-plumbing", + "https://www.ebay.com/itm/256644065109" +] diff --git a/tools/src/bin/parser/main.rs b/tools/src/bin/parser/main.rs index 6db3277..ef0ca9c 100644 --- a/tools/src/bin/parser/main.rs +++ b/tools/src/bin/parser/main.rs @@ -3,26 +3,47 @@ use clap::Parser; #[derive(Debug, clap::Parser)] #[command(version, about, long_about = None)] struct Args { - /// The name of the recipe to build. - target: String, - - /// Directories containing repos. + /// Directories containing repos, eg "../my-repos". #[arg(short, long)] - // repo: String, repo: Vec, + + /// Type of behavior/output. + #[command(subcommand)] + command: Commands, +} + +#[derive(clap::Subcommand, Debug)] +enum Commands { + /// Produce an mdbook of the specified recipe. + Mdbook { + /// The name of the recipe to create MD Book for, eg "my_widget". + target: String, + }, + /// Show parsed recipe, probably not very useful. + Info { + /// The name of the recipe to show info for, eg "my_widget". + target: String, + }, } fn main() -> anyhow::Result<()> { let args = Args::parse(); - // let repo = tools::Repo::new(&args.repo).unwrap(); - // repo.compile(&args.target)?; + let mut repos = tools::Repos::default(); for repo_path in &args.repo { repos.add_repo(repo_path)?; } - let build_plan = repos.compile(&args.target)?; - build_plan.make_mdbook()?; + match &args.command { + Commands::Mdbook { target } => { + let build_plan = repos.compile(target)?; + build_plan.make_mdbook()?; + } + Commands::Info { target } => { + let recipe = repos.get_recipe(target)?; + println!("{:#?}", recipe); + } + } Ok(()) } diff --git a/tools/src/build_plan.rs b/tools/src/build_plan.rs index 858b1cd..3fd22e4 100644 --- a/tools/src/build_plan.rs +++ b/tools/src/build_plan.rs @@ -215,6 +215,8 @@ impl<'a> BuildPlan<'a> { writeln!(bom_md_file, "# Bill of materials")?; writeln!(bom_md_file, "")?; + let mut total_cost: f32 = 0.0; + let mut names: Vec<&String> = self.bom.keys().collect(); names.sort(); for name in names { @@ -226,13 +228,14 @@ impl<'a> BuildPlan<'a> { )))?; let recipe = self.repos.get_recipe(name)?; let unit_cost = recipe.unit_cost()?; - let total_cost = unit_cost * item.quantity.amount; + let item_total_cost = unit_cost * item.quantity.amount; + total_cost += item_total_cost; writeln!(bom_md_file, "* {name}")?; writeln!(bom_md_file, " * quantity {:?}", item.quantity)?; writeln!( bom_md_file, " * cost {:.2} ({:.2} each)", - total_cost, unit_cost + item_total_cost, unit_cost )?; writeln!(bom_md_file, " * vendors:")?; match &recipe.action { @@ -250,6 +253,9 @@ impl<'a> BuildPlan<'a> { } } + writeln!(bom_md_file, "")?; + writeln!(bom_md_file, "Total cost: {:.2}", total_cost)?; + writeln!( summary_md_file, " - [Bill of Materials](overview/bom.md)"