1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
/*
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::{
book::Diagram,
glam::{Vec2, vec2},
};
use std::collections::{BTreeMap, BTreeSet};
pub struct Layout {
pub nodes: BTreeMap<String, Vec2>,
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<Vec2>,
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);
}
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.;
}
}
}
}
|