From ddedf745f41fdfc20d2ce61171ed07465929ba83 Mon Sep 17 00:00:00 2001 From: antifallobst Date: Thu, 14 Sep 2023 23:21:06 +0200 Subject: [PATCH] feat: implemented path rendering --- zauberschule/src/graph.rs | 180 +++++++++++++++++++++++++++++++++++--- zauberschule/src/main.rs | 3 +- 2 files changed, 171 insertions(+), 12 deletions(-) diff --git a/zauberschule/src/graph.rs b/zauberschule/src/graph.rs index dd06e3e..39bc17e 100644 --- a/zauberschule/src/graph.rs +++ b/zauberschule/src/graph.rs @@ -1,5 +1,6 @@ use anyhow::{Error, Result}; use slab::Slab; +use std::fmt::{Display, Formatter}; use std::path::Path; #[derive(Debug)] @@ -11,6 +12,9 @@ struct Edge { #[derive(Debug)] struct Node { edges: Slab, + x: usize, + y: usize, + z: usize, } #[derive(Debug)] @@ -27,6 +31,19 @@ enum MapNode { Unknown(char), } +#[derive(Debug)] +pub enum Action { + Start(usize, usize), + End(usize, usize), + Up(usize, usize), + Down(usize, usize), + Left(usize, usize), + Right(usize, usize), + ChangeFloor(usize, usize), +} + +pub struct Actions(pub Vec); + #[derive(Debug, Clone)] struct DijkstraNode { parent: usize, @@ -40,8 +57,13 @@ impl Edge { } impl Node { - fn new() -> Self { - Self { edges: Slab::new() } + fn new(x: usize, y: usize, z: usize) -> Self { + Self { + edges: Slab::new(), + x, + y, + z, + } } } @@ -54,6 +76,97 @@ impl DijkstraNode { } } +impl Display for Actions { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let mut x1 = usize::MAX; + let mut x2 = 0usize; + let mut y1 = usize::MAX; + let mut y2 = 0usize; + + for action in self.0.iter() { + match action { + Action::Start(x, y) + | Action::End(x, y) + | Action::Up(x, y) + | Action::Down(x, y) + | Action::Right(x, y) + | Action::Left(x, y) + | Action::ChangeFloor(x, y) => { + let x_pos = x.to_owned(); + let y_pos = y.to_owned(); + + if x_pos < x1 { + x1 = x_pos; + } + if x_pos > x2 { + x2 = x_pos; + } + if y_pos < y1 { + y1 = y_pos; + } + if y_pos > y2 { + y2 = y_pos; + } + } + } + } + + let mut layers = vec![vec![vec![' '; x2 - x1 + 1]; y2 - y1 + 1]; 2]; + let mut z = 0usize; + let mut start = true; + + for action in self.0.iter() { + match action { + Action::Start(x, y) => { + layers[z][y - y1][x - x1] = 'A'; + } + Action::End(x, y) => { + layers[z][y - y1][x - x1] = 'B'; + start = false; + } + Action::Up(x, y) => { + layers[z][y - y1][x - x1] = '↑'; + start = false; + } + Action::Down(x, y) => { + layers[z][y - y1][x - x1] = '↓'; + start = false; + } + Action::Left(x, y) => { + layers[z][y - y1][x - x1] = '←'; + start = false; + } + Action::Right(x, y) => { + layers[z][y - y1][x - x1] = '→'; + start = false; + } + Action::ChangeFloor(x, y) => { + if !start { + layers[z][y - y1][x - x1] = '!'; + } + z = (z + 1) % 2; + layers[z][y - y1][x - x1] = '!'; + } + } + } + + write!( + f, + "Layer 0:\n{}\n\nLayer 1:\n{}", + layers[0] + .iter() + .map(|chrs| String::from_iter(chrs)) + .collect::>() + .join("\n"), + layers[1] + .iter() + .map(|chrs| String::from_iter(chrs)) + .collect::>() + .join("\n") + ) + } +} + impl Graph { fn default() -> Self { Self { @@ -75,15 +188,18 @@ impl Graph { .unwrap() .1 .split("\n\n") - .map(|block| { + .enumerate() + .map(|(z, block)| { block .lines() - .map(|line| { + .enumerate() + .map(|(y, line)| { line.chars() - .map(|c| match c { + .enumerate() + .map(|(x, c)| match c { '#' => MapNode::Wall, '.' | 'A' | 'B' => { - let id = graph.nodes.insert(Node::new()); + let id = graph.nodes.insert(Node::new(x, y, z)); if c == 'A' { graph.start = id; @@ -104,16 +220,16 @@ impl Graph { // connect nodes for (z, map) in maps.iter().enumerate() { - print!("\n"); + // print!("\n"); for (y, row) in map.iter().enumerate() { - print!("\n"); + // print!("\n"); for (x, map_node) in row.iter().enumerate() { match map_node { - MapNode::Wall => print!("--- "), + MapNode::Wall => continue, // print!("--- "), MapNode::Floor(id) => { let node = graph.nodes.get_mut(id.to_owned()).unwrap(); - print!("{:03} ", id); + // print!("{:03} ", id); if let MapNode::Floor(i) = row[x - 1] { node.edges.insert(Edge::new(i, 1)); @@ -138,7 +254,7 @@ impl Graph { } } } - print!("\n"); + // print!("\n"); Ok(graph) } @@ -204,4 +320,46 @@ impl Graph { Ok(path) } + + pub fn path_to_actions(&self, path: &Vec) -> Result { + let start = self.nodes.get(self.start).unwrap(); + let mut x = start.x; + let mut y = start.y; + let mut z = start.z; + let mut last_id = self.start; + + let mut actions: Vec = path + .iter() + .map(|id| { + let node = self.nodes.get(id.to_owned()).unwrap(); + + let action = { + if id.to_owned() == self.start { + Action::Start(node.x, node.y) + } else if x > node.x { + Action::Left(node.x, node.y) + } else if x < node.x { + Action::Right(node.x, node.y) + } else if y > node.y { + Action::Up(node.x, node.y) + } else if y < node.y { + Action::Down(node.x, node.y) + } else { + Action::ChangeFloor(node.x, node.y) + } + }; + + x = node.x; + y = node.y; + z = node.z; + last_id = id.to_owned(); + + action + }) + .collect(); + + actions.push(Action::End(x, y)); + + Ok(Actions(actions)) + } } diff --git a/zauberschule/src/main.rs b/zauberschule/src/main.rs index 62ed735..3be2b18 100644 --- a/zauberschule/src/main.rs +++ b/zauberschule/src/main.rs @@ -21,7 +21,8 @@ fn main() -> Result<()> { let graph = Graph::new(Path::new(&args.file))?; let path = graph.dijkstra()?; - println!("Path: {:?}", path); + let actions = graph.path_to_actions(&path)?; + println!("{}", actions); Ok(()) }