/* 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 . */ use anyhow::Result; use hurrycurry_protocol::{ book::Diagram, glam::{Vec2, vec2}, }; use std::collections::{BTreeMap, BTreeSet}; pub struct Layout { pub nodes: BTreeMap, pub edges: Vec<(usize, usize)>, } pub fn diagram_layout(diagram: &mut Diagram) -> Result<()> { let mut graph = Graph { vertices: (0..diagram.nodes.len()) .map(|i| vec2(i as f32, i as f32) * 30.) .collect(), edges: diagram.edges.iter().map(|e| (e.src, e.dst)).collect(), }; graph.layout(); diagram .nodes .iter_mut() .zip(graph.vertices.iter()) .for_each(|(n, v)| n.position = *v); Ok(()) } pub struct Graph { pub vertices: Vec, pub edges: Vec<(usize, usize)>, } impl Graph { pub fn layout(&mut self) { let mut layers = Vec::new(); let mut previous_layers = BTreeSet::new(); let mut to_insert = Vec::new(); to_insert.extend(0..self.vertices.len()); while !to_insert.is_empty() { let mut next_layer = Vec::new(); to_insert.retain(|&vi| { for &(src, dst) in &self.edges { if src == vi && !previous_layers.contains(&dst) { return true; } } next_layer.push(vi); false }); previous_layers.extend(next_layer.iter().copied()); layers.push(next_layer); } #[allow(clippy::needless_range_loop)] for y in 0..layers.iter().len() { let mut layer = layers[y].clone(); layer.sort_by_cached_key(|&vi| { self.edges .iter() .find(|&&(src, _)| src == vi) .map_or(0, |&(_, dst)| (self.vertices[dst].x * 100.) as i64) }); for (x, &vi) in layer.iter().enumerate() { self.vertices[vi] = vec2(x as f32 - layer.len() as f32 / 2., y as f32) * 100.; } } } }