summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-08-29 15:36:44 +0200
committermetamuffin <metamuffin@disroot.org>2024-08-29 16:47:50 +0200
commitb234ca89e3d858048d3145e3d90c32200d02e38f (patch)
treedb8bf3de36fbffa8543cb482c5eb923e4a802f96
parente7139dde289170f21ac23f62918c0ee1f47bb974 (diff)
downloadhurrycurry-b234ca89e3d858048d3145e3d90c32200d02e38f.tar
hurrycurry-b234ca89e3d858048d3145e3d90c32200d02e38f.tar.bz2
hurrycurry-b234ca89e3d858048d3145e3d90c32200d02e38f.tar.zst
start with simplfied graph
-rw-r--r--server/src/bin/graph_summary.rs154
1 files changed, 154 insertions, 0 deletions
diff --git a/server/src/bin/graph_summary.rs b/server/src/bin/graph_summary.rs
new file mode 100644
index 00000000..12df0b1a
--- /dev/null
+++ b/server/src/bin/graph_summary.rs
@@ -0,0 +1,154 @@
+/*
+ Hurry Curry! - a game about cooking
+ Copyright 2024 metamuffin
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, version 3 of the License only.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+*/
+use anyhow::{anyhow, Result};
+use hurrycurry_protocol::{ItemIndex, Recipe, TileIndex};
+use hurrycurry_server::data::DataIndex;
+use std::collections::HashSet;
+
+#[tokio::main]
+async fn main() -> Result<()> {
+ let mut index = DataIndex::default();
+ index.reload()?;
+
+ println!("digraph {{");
+
+ let rn = std::env::args()
+ .nth(1)
+ .ok_or(anyhow!("first arg should be recipe set name"))?;
+
+ let (data, sdata, _) = index.generate(format!("5star-{rn}")).await?;
+
+ struct Node {
+ inputs: Vec<ItemIndex>,
+ outputs: Vec<ItemIndex>,
+ tool_item: Option<ItemIndex>,
+ tool_tile: Option<TileIndex>,
+ instant: bool,
+ demand: bool,
+ }
+
+ let map_items = sdata
+ .initial_map
+ .iter()
+ .flat_map(|(_, (_, i))| *i)
+ .collect::<HashSet<_>>();
+
+ let mut nodes = Vec::new();
+ for r in &data.recipes {
+ nodes.push(Node {
+ inputs: r.inputs(),
+ outputs: r.outputs(),
+ tool_item: None,
+ tool_tile: r.tile(),
+ instant: matches!(r, Recipe::Instant { .. }),
+ demand: false,
+ })
+ }
+ for d in &data.demands {
+ nodes.push(Node {
+ demand: true,
+ instant: false,
+ inputs: vec![d.input],
+ outputs: d.output.into_iter().collect(),
+ tool_item: None,
+ tool_tile: None,
+ })
+ }
+
+ loop {
+ let node_count_before = nodes.len();
+
+ let mut has_fdeps = vec![false; data.item_names.len()];
+ for n in &nodes {
+ for ItemIndex(i) in &n.inputs {
+ has_fdeps[*i] = true;
+ }
+ }
+ // Remove demand outputs
+ for n in &mut nodes {
+ n.outputs.retain(|_item| !n.demand);
+ }
+ // Remove outputs that are not depended on
+ for n in &mut nodes {
+ n.outputs.retain(|item| n.demand || has_fdeps[item.0])
+ }
+ // Remove outputs that exist on the map, like pots and plates
+ for n in &mut nodes {
+ n.outputs.retain(|item| !map_items.contains(item))
+ }
+ // Convert map item inputs to tools
+ for n in &mut nodes {
+ n.inputs.retain(|i| {
+ if map_items.contains(i) {
+ n.tool_item = Some(*i);
+ false
+ } else {
+ true
+ }
+ })
+ }
+ // Remove outputless recipes
+ nodes.retain(|n| n.demand || !n.outputs.is_empty());
+
+ if nodes.len() == node_count_before {
+ break;
+ }
+ }
+
+ let mut items = HashSet::<ItemIndex>::new();
+ for n in &nodes {
+ items.extend(&n.inputs);
+ items.extend(&n.outputs);
+ }
+
+ for ItemIndex(i) in items {
+ println!("i{i} [label=\"{}\"]", data.item_name(ItemIndex(i)))
+ }
+ for (ni, node) in nodes.iter().enumerate() {
+ let color = if node.demand {
+ "#c4422b"
+ } else if node.instant {
+ "#5452d8"
+ } else {
+ "#47c42b"
+ };
+ println!(
+ "r{ni} [label=\"{}\" shape=box color={color:?} fillcolor={color:?} style=filled]",
+ if let Some(tool) = node.tool_tile {
+ data.tile_name(tool)
+ } else if let Some(tool) = node.tool_item {
+ data.item_name(tool)
+ } else if node.instant {
+ "Combine"
+ } else if node.demand {
+ "Demand"
+ } else {
+ "Passive"
+ }
+ );
+ for ItemIndex(input) in &node.inputs {
+ println!("i{input} -> r{ni}")
+ }
+ for ItemIndex(output) in &node.outputs {
+ println!("r{ni} -> i{output}")
+ }
+ }
+
+ println!("}}");
+ Ok(())
+}