blockworx/tutorial/levels/
mod.rs1use egui::Rect;
7
8use super::level::Level;
9
10pub const FALLBACK_CAMERA: Rect = Rect {
12 min: egui::Pos2 { x: 0.0, y: 0.0 },
13 max: egui::Pos2 {
14 x: 28.0 * crate::grid::GRID_SIZE,
15 y: 20.0 * crate::grid::GRID_SIZE,
16 },
17};
18
19const SOURCES: &[&str] = &[
20 include_str!("01_first_block.kdl"),
21 include_str!("02_first_route.kdl"),
22 include_str!("03_resize_move.kdl"),
23];
24
25#[cfg(test)]
34pub(super) const GOLDENS: &[(&str, &str, &str)] = &[
35 (
36 "first-block",
37 "src/tutorial/levels/01_first_block.golden.txt",
38 include_str!("01_first_block.golden.txt"),
39 ),
40 (
41 "first-route",
42 "src/tutorial/levels/02_first_route.golden.txt",
43 include_str!("02_first_route.golden.txt"),
44 ),
45 (
46 "resize-move",
47 "src/tutorial/levels/03_resize_move.golden.txt",
48 include_str!("03_resize_move.golden.txt"),
49 ),
50];
51
52pub fn all() -> Vec<Level> {
53 SOURCES
54 .iter()
55 .filter_map(|source| match Level::parse(source) {
56 Ok(level) => Some(level),
57 Err(e) => {
60 tracing::error!("tutorial level failed to parse: {e}");
61 None
62 }
63 })
64 .collect()
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[test]
72 fn every_source_parses() {
73 assert_eq!(all().len(), SOURCES.len());
74 }
75
76 #[test]
77 fn goldens_cover_every_level() {
78 let levels = all();
79 assert_eq!(levels.len(), GOLDENS.len());
80 for (level, (id, _, _)) in levels.iter().zip(GOLDENS) {
81 assert_eq!(&level.id, id, "GOLDENS must match SOURCES order");
82 }
83 }
84}