From b5b7de9532cc78c6ce0bb43e63cbf6c43eba114b Mon Sep 17 00:00:00 2001 From: Avi Weinstock Date: Tue, 8 Jun 2021 14:42:51 -0400 Subject: [PATCH 1/2] Add graphviz diagram generator for crafting recipes. --- Cargo.lock | 1 + common/Cargo.toml | 7 ++++ common/src/bin/recipe_graphviz.rs | 58 +++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 common/src/bin/recipe_graphviz.rs diff --git a/Cargo.lock b/Cargo.lock index 145b1f4fee..d6f4c1a325 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5796,6 +5796,7 @@ dependencies = [ "num-derive", "num-traits", "ordered-float 2.5.1", + "petgraph 0.5.1", "rand 0.8.3", "rayon", "ron", diff --git a/common/Cargo.toml b/common/Cargo.toml index 0d9f72e846..7a58d607c5 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -9,6 +9,7 @@ no-assets = [] tracy = ["common-base/tracy"] simd = ["vek/platform_intrinsics"] bin_csv = ["ron", "csv", "structopt"] +bin_graphviz = ["petgraph"] default = ["simd"] @@ -51,6 +52,8 @@ ron = { version = "0.6", default-features = false, optional = true } # csv export csv = { version = "1.1.3", optional = true } structopt = { version = "0.3.13", optional = true } +# graphviz exporters +petgraph = { version = "0.5.1", optional = true } # Data structures hashbrown = { version = "0.11", features = ["rayon", "serde", "nightly"] } @@ -88,3 +91,7 @@ required-features = ["bin_csv"] [[bin]] name = "csv_import" required-features = ["bin_csv"] + +[[bin]] +name = "recipe_graphviz" +required-features = ["bin_graphviz"] diff --git a/common/src/bin/recipe_graphviz.rs b/common/src/bin/recipe_graphviz.rs new file mode 100644 index 0000000000..2feb0540ca --- /dev/null +++ b/common/src/bin/recipe_graphviz.rs @@ -0,0 +1,58 @@ +use hashbrown::HashMap; +use petgraph::{ + dot::{Config, Dot}, + Graph, +}; +use std::{fs::File, io::Write}; +use veloren_common::{ + assets::AssetExt, + comp::item::ItemDesc, + recipe::{RecipeBook, RecipeInput}, +}; + +fn main() { + let recipes = RecipeBook::load_expect_cloned("common.recipe_book"); + let mut graph = Graph::new(); + let mut nodes = HashMap::new(); + let mut add_node = |graph: &mut Graph<_, _>, node: &str| { + nodes + .entry(node.to_owned()) + .or_insert_with(|| graph.add_node(node.to_owned())) + .clone() + }; + for (_, recipe) in recipes.iter() { + let output = recipe.output.0.item_definition_id(); + let inputs = recipe + .inputs + .iter() + .map(|(i, _)| i) + .filter_map(|input| { + if let RecipeInput::Item(item) = input { + Some(item.item_definition_id()) + } else { + None + } + }) + .collect::>(); + let out_node = add_node(&mut graph, output); + for input in inputs.iter() { + let in_node = add_node(&mut graph, input); + graph.add_edge(in_node, out_node, ()); + } + } + let mut f = File::create("recipe_graph.dot").unwrap(); + writeln!(f, "digraph {{").unwrap(); + writeln!(f, "rankdir = \"LR\"").unwrap(); + writeln!( + f, + "{:#?}", + Dot::with_attr_getters( + &graph, + &[Config::EdgeNoLabel, Config::GraphContentOnly], + &|_, _| "".to_owned(), + &|_, _| { "constraint=false".to_owned() } + ) + ) + .unwrap(); + writeln!(f, "}}").unwrap(); +} From b5ae6227c0161f1df7f04128a1d014eaae53cda7 Mon Sep 17 00:00:00 2001 From: Avi Weinstock Date: Tue, 8 Jun 2021 15:08:14 -0400 Subject: [PATCH 2/2] Run clippy for graphviz target in CI and add instructions on how to consume the output. --- .gitlab/CI/check.gitlab-ci.yml | 2 +- common/src/bin/recipe_graphviz.rs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitlab/CI/check.gitlab-ci.yml b/.gitlab/CI/check.gitlab-ci.yml index 60f0e8425f..51f306d8e8 100644 --- a/.gitlab/CI/check.gitlab-ci.yml +++ b/.gitlab/CI/check.gitlab-ci.yml @@ -6,7 +6,7 @@ code-quality: script: - ln -s /dockercache/target target - rm -r target/debug/incremental/* || echo "all good" # TMP FIX FOR 2021-03-22-nightly - - cargo clippy --all-targets --locked --features="bin_csv,bin_bot,asset_tweak" -- -D warnings + - cargo clippy --all-targets --locked --features="bin_csv,bin_graphviz,bin_bot,asset_tweak" -- -D warnings - cargo fmt --all -- --check security: diff --git a/common/src/bin/recipe_graphviz.rs b/common/src/bin/recipe_graphviz.rs index 2feb0540ca..b7fb176207 100644 --- a/common/src/bin/recipe_graphviz.rs +++ b/common/src/bin/recipe_graphviz.rs @@ -15,10 +15,9 @@ fn main() { let mut graph = Graph::new(); let mut nodes = HashMap::new(); let mut add_node = |graph: &mut Graph<_, _>, node: &str| { - nodes + *nodes .entry(node.to_owned()) .or_insert_with(|| graph.add_node(node.to_owned())) - .clone() }; for (_, recipe) in recipes.iter() { let output = recipe.output.0.item_definition_id(); @@ -40,6 +39,8 @@ fn main() { graph.add_edge(in_node, out_node, ()); } } + // you can render the dot file as a png with `dot -Tpng recipe_graph.dot > + // recipe_graph.png` or interactively view it with `xdot recipe_graph.dot` let mut f = File::create("recipe_graph.dot").unwrap(); writeln!(f, "digraph {{").unwrap(); writeln!(f, "rankdir = \"LR\"").unwrap();