feat: implemented path rendering

This commit is contained in:
antifallobst 2023-09-14 23:21:06 +02:00
parent 0f479302dd
commit ddedf745f4
Signed by: antifallobst
GPG Key ID: 2B4F402172791BAF
2 changed files with 171 additions and 12 deletions

View File

@ -1,5 +1,6 @@
use anyhow::{Error, Result}; use anyhow::{Error, Result};
use slab::Slab; use slab::Slab;
use std::fmt::{Display, Formatter};
use std::path::Path; use std::path::Path;
#[derive(Debug)] #[derive(Debug)]
@ -11,6 +12,9 @@ struct Edge {
#[derive(Debug)] #[derive(Debug)]
struct Node { struct Node {
edges: Slab<Edge>, edges: Slab<Edge>,
x: usize,
y: usize,
z: usize,
} }
#[derive(Debug)] #[derive(Debug)]
@ -27,6 +31,19 @@ enum MapNode {
Unknown(char), 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<Action>);
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct DijkstraNode { struct DijkstraNode {
parent: usize, parent: usize,
@ -40,8 +57,13 @@ impl Edge {
} }
impl Node { impl Node {
fn new() -> Self { fn new(x: usize, y: usize, z: usize) -> Self {
Self { edges: Slab::new() } 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::<Vec<String>>()
.join("\n"),
layers[1]
.iter()
.map(|chrs| String::from_iter(chrs))
.collect::<Vec<String>>()
.join("\n")
)
}
}
impl Graph { impl Graph {
fn default() -> Self { fn default() -> Self {
Self { Self {
@ -75,15 +188,18 @@ impl Graph {
.unwrap() .unwrap()
.1 .1
.split("\n\n") .split("\n\n")
.map(|block| { .enumerate()
.map(|(z, block)| {
block block
.lines() .lines()
.map(|line| { .enumerate()
.map(|(y, line)| {
line.chars() line.chars()
.map(|c| match c { .enumerate()
.map(|(x, c)| match c {
'#' => MapNode::Wall, '#' => MapNode::Wall,
'.' | 'A' | 'B' => { '.' | 'A' | 'B' => {
let id = graph.nodes.insert(Node::new()); let id = graph.nodes.insert(Node::new(x, y, z));
if c == 'A' { if c == 'A' {
graph.start = id; graph.start = id;
@ -104,16 +220,16 @@ impl Graph {
// connect nodes // connect nodes
for (z, map) in maps.iter().enumerate() { for (z, map) in maps.iter().enumerate() {
print!("\n"); // print!("\n");
for (y, row) in map.iter().enumerate() { for (y, row) in map.iter().enumerate() {
print!("\n"); // print!("\n");
for (x, map_node) in row.iter().enumerate() { for (x, map_node) in row.iter().enumerate() {
match map_node { match map_node {
MapNode::Wall => print!("--- "), MapNode::Wall => continue, // print!("--- "),
MapNode::Floor(id) => { MapNode::Floor(id) => {
let node = graph.nodes.get_mut(id.to_owned()).unwrap(); let node = graph.nodes.get_mut(id.to_owned()).unwrap();
print!("{:03} ", id); // print!("{:03} ", id);
if let MapNode::Floor(i) = row[x - 1] { if let MapNode::Floor(i) = row[x - 1] {
node.edges.insert(Edge::new(i, 1)); node.edges.insert(Edge::new(i, 1));
@ -138,7 +254,7 @@ impl Graph {
} }
} }
} }
print!("\n"); // print!("\n");
Ok(graph) Ok(graph)
} }
@ -204,4 +320,46 @@ impl Graph {
Ok(path) Ok(path)
} }
pub fn path_to_actions(&self, path: &Vec<usize>) -> Result<Actions> {
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<Action> = 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))
}
} }

View File

@ -21,7 +21,8 @@ fn main() -> Result<()> {
let graph = Graph::new(Path::new(&args.file))?; let graph = Graph::new(Path::new(&args.file))?;
let path = graph.dijkstra()?; let path = graph.dijkstra()?;
println!("Path: {:?}", path); let actions = graph.path_to_actions(&path)?;
println!("{}", actions);
Ok(()) Ok(())
} }