diff options
author | metamuffin <metamuffin@disroot.org> | 2025-10-06 23:03:32 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-10-06 23:03:40 +0200 |
commit | 176e6bc6c4c29bea3be2aceca99743b997c76c97 (patch) | |
tree | 1161e7a966843324756340da4b6452492902fa07 /server/tools/src/recipe_diagram.rs | |
parent | ea86b11b682500160f37b35ea8f06b081cd05036 (diff) | |
download | hurrycurry-176e6bc6c4c29bea3be2aceca99743b997c76c97.tar hurrycurry-176e6bc6c4c29bea3be2aceca99743b997c76c97.tar.bz2 hurrycurry-176e6bc6c4c29bea3be2aceca99743b997c76c97.tar.zst |
Move data code to own crate + general data refactor
Diffstat (limited to 'server/tools/src/recipe_diagram.rs')
-rw-r--r-- | server/tools/src/recipe_diagram.rs | 239 |
1 files changed, 0 insertions, 239 deletions
diff --git a/server/tools/src/recipe_diagram.rs b/server/tools/src/recipe_diagram.rs deleted file mode 100644 index 0be75433..00000000 --- a/server/tools/src/recipe_diagram.rs +++ /dev/null @@ -1,239 +0,0 @@ -/* - Hurry Curry! - a game about cooking - Copyright (C) 2025 Hurry Curry! Contributors - - 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::Result; -use hurrycurry_protocol::{ - Gamedata, ItemIndex, Message, Recipe, RecipeIndex, - book::{Diagram, DiagramEdge, DiagramNode, NodeStyle}, - glam::Vec2, -}; -use hurrycurry_server::data::Serverdata; -use std::{ - cmp::Reverse, - collections::{BTreeMap, BTreeSet, HashSet}, -}; - -pub(crate) fn recipe_diagram( - data: &Gamedata, - serverdata: &Serverdata, - target_items: &[&str], -) -> Result<Diagram> { - let ambient_items = serverdata - .initial_map - .iter() - .flat_map(|(_, (_, item))| item) - .copied() - .collect::<HashSet<_>>(); - - let mut need = BTreeSet::from_iter( - target_items - .iter() - .map(|name| data.get_item_by_name(name).unwrap()), - ); - let mut have = BTreeSet::<ItemIndex>::new(); - let mut recipes = BTreeSet::new(); - - #[derive(PartialEq, PartialOrd, Eq, Ord)] - struct GraphRecipe { - index: RecipeIndex, - inputs: Vec<ItemIndex>, - outputs: Vec<ItemIndex>, - } - - while let Some(item) = need.pop_last() { - for (ri, r) in data.recipes() { - if r.outputs().contains(&item) { - let gr = GraphRecipe { - inputs: r - .inputs() - .iter() - .filter(|i| !ambient_items.contains(i)) - .copied() - .collect(), - outputs: r - .outputs() - .iter() - .filter(|i| !ambient_items.contains(i)) - .copied() - .collect(), - index: ri, - }; - need.extend(gr.inputs.iter().filter(|i| !have.contains(&i))); - have.extend(&gr.outputs); - recipes.insert(gr); - } - } - } - - let mut diag = Diagram::default(); - let mut item_index = BTreeMap::new(); - for i in have { - item_index.insert(i, diag.nodes.len()); - diag.nodes.push(DiagramNode { - label: Message::Item(i), - position: Vec2::ZERO, - style: if target_items.contains(&data.item_name(i)) { - NodeStyle::FinalProduct - } else { - NodeStyle::IntermediateProduct - }, - }); - } - for r in recipes { - let index = diag.nodes.len(); - let recipe = data.recipe(r.index); - - if matches!(recipe, Recipe::Instant { .. }) && r.inputs.len() >= 1 && r.outputs.len() >= 1 { - for i in r.inputs { - diag.edges.push(DiagramEdge { - src: item_index[&i], - dst: item_index[&r.outputs[0]], - label: None, - }); - } - continue; - } - if matches!(recipe, Recipe::Passive { tile: None, .. }) - && r.inputs.len() == 1 - && r.outputs.len() == 1 - { - diag.nodes[item_index[&r.inputs[0]]].style = NodeStyle::ProcessPassive; - diag.edges.push(DiagramEdge { - src: item_index[&r.inputs[0]], - dst: item_index[&r.outputs[0]], - label: None, - }); - continue; - } - - let (kind, style) = match recipe { - Recipe::Passive { .. } => ("Passive", NodeStyle::ProcessPassive), - Recipe::Active { .. } => ("Active", NodeStyle::ProcessActive), - Recipe::Instant { .. } => ("Instant", NodeStyle::ProcessInstant), - }; - diag.nodes.push(DiagramNode { - position: Vec2::ZERO, - label: if let Some(tile) = recipe.tile() { - Message::Tile(tile) - } else { - Message::Text(kind.to_string()) - }, - style, - }); - - for i in r.inputs { - diag.edges.push(DiagramEdge { - src: item_index[&i], - dst: index, - label: None, - }); - } - for o in r.outputs { - diag.edges.push(DiagramEdge { - src: index, - dst: item_index[&o], - label: None, - }); - } - } - - merge_combine_clusters(&mut diag); - remove_orphan_nodes(&mut diag); - - Ok(diag) -} - -fn merge_combine_clusters(diag: &mut Diagram) { - let instant_nodes = diag - .nodes - .iter() - .enumerate() - .filter(|(_, n)| matches!(n.style, NodeStyle::IntermediateProduct)) - .map(|(i, _)| i) - .collect::<Vec<_>>(); - - for ni in instant_nodes { - let inputs = diag - .edges - .iter() - .enumerate() - .filter(|(_, e)| e.dst == ni) - .map(|(i, e)| (i, e.src)) - .collect::<Vec<_>>(); - let outputs = diag - .edges - .iter() - .enumerate() - .filter(|(_, e)| e.src == ni) - .map(|(i, e)| (i, e.dst)) - .collect::<Vec<_>>(); - - if outputs - .iter() - .all(|&(_, ni)| diag.nodes[ni].style.is_procuct()) - && inputs - .iter() - .all(|&(_, ni)| diag.nodes[ni].style.is_procuct()) - { - let mut to_remove = inputs - .iter() - .map(|&(i, _)| i) - .chain(outputs.iter().map(|&(i, _)| i)) - .collect::<Vec<_>>(); - to_remove.sort_by_key(|x| Reverse(*x)); - for i in to_remove { - diag.edges.remove(i); - } - - for &input in &inputs { - for &output in &outputs { - if !diag - .edges - .iter() - .any(|e| e.src == input.1 && e.dst == output.1) - { - diag.edges.push(DiagramEdge { - src: input.1, - dst: output.1, - label: None, - }); - } - } - } - } - } -} - -fn remove_orphan_nodes(diag: &mut Diagram) { - let mut to_remove = diag - .nodes - .iter() - .enumerate() - .filter(|&(i, _)| !diag.edges.iter().any(|e| e.src == i || e.dst == i)) - .map(|(i, _)| i) - .collect::<Vec<_>>(); - to_remove.sort_by_key(|x| Reverse(*x)); - - for e in &mut diag.edges { - e.src -= to_remove.iter().filter(|&&i| i < e.src).count(); - e.dst -= to_remove.iter().filter(|&&i| i < e.dst).count(); - } - for i in to_remove { - diag.nodes.remove(i); - } -} |