router: use `Step` and new `StepBack` traits in `Route` and `Trace`

This commit is contained in:
Mikolaj Wielgus 2024-08-03 19:17:00 +02:00
parent 1305487c7f
commit 7830806834
5 changed files with 120 additions and 66 deletions

View File

@ -8,6 +8,7 @@ use crate::{
tracer::Tracer, tracer::Tracer,
Router, RouterAstarStrategy, RouterError, RouterStatus, Router, RouterAstarStrategy, RouterError, RouterStatus,
}, },
step::Step,
}; };
pub struct Route { pub struct Route {
@ -53,26 +54,6 @@ impl Route {
} }
} }
pub fn step(
&mut self,
router: &mut Router<impl AccessRules>,
) -> Result<RouterStatus, RouterError> {
let tracer = Tracer::new(router.layout_mut());
let target = self.astar.graph.destination();
let mut strategy = RouterAstarStrategy::new(tracer, &mut self.trace, target);
let result = match self.astar.step(&mut strategy)? {
AstarStatus::Probing | AstarStatus::Probed | AstarStatus::Visited => {
Ok(RouterStatus::Running)
}
AstarStatus::Finished(_cost, _path, band) => Ok(RouterStatus::Finished(band)),
};
self.ghosts = strategy.probe_ghosts;
self.obstacles = strategy.probe_obstacles;
result
}
pub fn navmesh(&self) -> &Navmesh { pub fn navmesh(&self) -> &Navmesh {
&self.astar.graph &self.astar.graph
} }
@ -89,3 +70,22 @@ impl Route {
&self.obstacles &self.obstacles
} }
} }
impl<'a, R: AccessRules> Step<Router<'a, R>, RouterStatus, RouterError> for Route {
fn step(&mut self, router: &mut Router<R>) -> Result<RouterStatus, RouterError> {
let tracer = Tracer::new(router.layout_mut());
let target = self.astar.graph.destination();
let mut strategy = RouterAstarStrategy::new(tracer, &mut self.trace, target);
let result = match self.astar.step(&mut strategy)? {
AstarStatus::Probing | AstarStatus::Probed | AstarStatus::Visited => {
Ok(RouterStatus::Running)
}
AstarStatus::Finished(_cost, _path, band) => Ok(RouterStatus::Finished(band)),
};
self.ghosts = strategy.probe_ghosts;
self.obstacles = strategy.probe_obstacles;
result
}
}

View File

@ -18,6 +18,7 @@ use crate::{
}, },
graph::{GetPetgraphIndex, MakeRef}, graph::{GetPetgraphIndex, MakeRef},
layout::Layout, layout::Layout,
step::{IsFinished, Step, StepBack},
}; };
use super::{ use super::{
@ -25,7 +26,7 @@ use super::{
draw::DrawException, draw::DrawException,
navmesh::{Navmesh, NavmeshEdgeReference, NavmeshError, NavvertexIndex}, navmesh::{Navmesh, NavmeshEdgeReference, NavmeshError, NavvertexIndex},
route::Route, route::Route,
trace::Trace, trace::{Trace, TraceStepInput},
tracer::{Tracer, TracerException}, tracer::{Tracer, TracerException},
}; };
@ -42,6 +43,12 @@ pub enum RouterStatus {
Finished(BandTermsegIndex), Finished(BandTermsegIndex),
} }
impl IsFinished for RouterStatus {
fn finished(&self) -> bool {
matches!(self, RouterStatus::Finished(..))
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct RouterAstarStrategy<'a, R: AccessRules> { pub struct RouterAstarStrategy<'a, R: AccessRules> {
pub tracer: Tracer<'a, R>, pub tracer: Tracer<'a, R>,
@ -107,9 +114,12 @@ impl<'a, R: AccessRules> AstarStrategy<Navmesh, f64, BandTermsegIndex>
let prev_bihead_length = self.bihead_length(); let prev_bihead_length = self.bihead_length();
let width = self.trace.width; let width = self.trace.width;
let result = self let result = self.trace.step(&mut TraceStepInput {
.trace tracer: &mut self.tracer,
.step(&mut self.tracer, navmesh, edge.target(), width); navmesh,
to: edge.target(),
width,
});
let probe_length = self.bihead_length() - prev_bihead_length; let probe_length = self.bihead_length() - prev_bihead_length;
@ -141,7 +151,7 @@ impl<'a, R: AccessRules> AstarStrategy<Navmesh, f64, BandTermsegIndex>
} }
fn remove_probe(&mut self, _navmesh: &Navmesh) { fn remove_probe(&mut self, _navmesh: &Navmesh) {
self.trace.undo_step(&mut self.tracer); self.trace.step_back(&mut self.tracer);
} }
fn estimate_cost(&mut self, navmesh: &Navmesh, vertex: NavvertexIndex) -> f64 { fn estimate_cost(&mut self, navmesh: &Navmesh, vertex: NavvertexIndex) -> f64 {

View File

@ -9,11 +9,14 @@ use crate::{
head::{BareHead, CaneHead, Head}, head::{BareHead, CaneHead, Head},
rules::AccessRules, rules::AccessRules,
}, },
router::{ step::{Step, StepBack},
};
use super::{
draw::Draw, draw::Draw,
navmesh::{BinavvertexNodeIndex, Navmesh, NavvertexIndex}, navmesh::{BinavvertexNodeIndex, Navmesh, NavvertexIndex},
tracer::TracerStatus,
tracer::{Tracer, TracerException}, tracer::{Tracer, TracerException},
},
}; };
#[derive(Debug)] #[derive(Debug)]
@ -32,33 +35,6 @@ impl Trace {
} }
} }
#[debug_ensures(ret.is_ok() -> matches!(self.head, Head::Cane(..)))]
#[debug_ensures(ret.is_ok() -> self.path.len() == old(self.path.len() + 1))]
#[debug_ensures(ret.is_err() -> self.path.len() == old(self.path.len()))]
pub fn step(
&mut self,
tracer: &mut Tracer<impl AccessRules>,
navmesh: &Navmesh,
to: NavvertexIndex,
width: f64,
) -> Result<(), TracerException> {
self.head = self.wrap(tracer, navmesh, self.head, to, width)?.into();
self.path.push(to);
Ok::<(), TracerException>(())
}
#[debug_ensures(self.path.len() == old(self.path.len() - 1))]
pub fn undo_step(&mut self, tracer: &mut Tracer<impl AccessRules>) {
if let Head::Cane(head) = self.head {
self.head = Draw::new(tracer.layout).undo_cane(head).unwrap();
} else {
panic!();
}
self.path.pop();
}
fn wrap( fn wrap(
&mut self, &mut self,
tracer: &mut Tracer<impl AccessRules>, tracer: &mut Tracer<impl AccessRules>,
@ -116,3 +92,49 @@ impl Trace {
navmesh.node_weight(navvertex).unwrap().maybe_cw navmesh.node_weight(navvertex).unwrap().maybe_cw
} }
} }
pub struct TraceStepInput<'a: 'b, 'b, R: AccessRules> {
pub tracer: &'b mut Tracer<'a, R>,
pub navmesh: &'b Navmesh,
pub to: NavvertexIndex,
pub width: f64,
}
impl<'a, 'b, R: AccessRules> Step<TraceStepInput<'a, 'b, R>, TracerStatus, TracerException>
for Trace
{
#[debug_ensures(ret.is_ok() -> matches!(self.head, Head::Cane(..)))]
#[debug_ensures(ret.is_ok() -> self.path.len() == old(self.path.len() + 1))]
#[debug_ensures(ret.is_err() -> self.path.len() == old(self.path.len()))]
fn step(
&mut self,
input: &mut TraceStepInput<'a, 'b, R>,
) -> Result<TracerStatus, TracerException> {
self.head = self
.wrap(
input.tracer,
input.navmesh,
self.head,
input.to,
input.width,
)?
.into();
self.path.push(input.to);
Ok(TracerStatus::Running)
}
}
impl<'a, R: AccessRules> StepBack<Tracer<'a, R>, TracerStatus, TracerException> for Trace {
#[debug_ensures(self.path.len() == old(self.path.len() - 1))]
fn step_back(&mut self, tracer: &mut Tracer<'a, R>) -> Result<TracerStatus, TracerException> {
if let Head::Cane(head) = self.head {
self.head = Draw::new(tracer.layout).undo_cane(head).unwrap();
} else {
panic!();
}
self.path.pop();
Ok(TracerStatus::Running)
}
}

View File

@ -4,11 +4,13 @@ use thiserror::Error;
use crate::{ use crate::{
drawing::{band::BandTermsegIndex, dot::FixedDotIndex, rules::AccessRules}, drawing::{band::BandTermsegIndex, dot::FixedDotIndex, rules::AccessRules},
layout::Layout, layout::Layout,
router::{ step::{IsFinished, Step, StepBack},
};
use super::{
draw::{Draw, DrawException}, draw::{Draw, DrawException},
navmesh::{Navmesh, NavvertexIndex}, navmesh::{Navmesh, NavvertexIndex},
trace::Trace, trace::{Trace, TraceStepInput},
},
}; };
#[derive(Error, Debug, Clone, Copy)] #[derive(Error, Debug, Clone, Copy)]
@ -19,6 +21,17 @@ pub enum TracerException {
CannotWrap, CannotWrap,
} }
pub enum TracerStatus {
Running,
Finished,
}
impl IsFinished for TracerStatus {
fn finished(&self) -> bool {
matches!(self, TracerStatus::Finished)
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct Tracer<'a, R: AccessRules> { pub struct Tracer<'a, R: AccessRules> {
pub layout: &'a mut Layout<R>, pub layout: &'a mut Layout<R>,
@ -78,7 +91,12 @@ impl<'a, R: AccessRules> Tracer<'a, R> {
width: f64, width: f64,
) -> Result<(), TracerException> { ) -> Result<(), TracerException> {
for (i, vertex) in path.iter().enumerate() { for (i, vertex) in path.iter().enumerate() {
if let Err(err) = trace.step(self, navmesh, *vertex, width) { if let Err(err) = trace.step(&mut TraceStepInput {
tracer: self,
navmesh,
to: *vertex,
width,
}) {
self.undo_path(trace, i); self.undo_path(trace, i);
return Err(err.into()); return Err(err.into());
} }
@ -90,7 +108,7 @@ impl<'a, R: AccessRules> Tracer<'a, R> {
#[debug_ensures(trace.path.len() == old(trace.path.len() - step_count))] #[debug_ensures(trace.path.len() == old(trace.path.len() - step_count))]
pub fn undo_path(&mut self, trace: &mut Trace, step_count: usize) { pub fn undo_path(&mut self, trace: &mut Trace, step_count: usize) {
for _ in 0..step_count { for _ in 0..step_count {
trace.undo_step(self); let _ = trace.step_back(self);
} }
} }
} }

View File

@ -2,6 +2,10 @@ pub trait IsFinished {
fn finished(&self) -> bool; fn finished(&self) -> bool;
} }
pub trait Step<C, S: IsFinished, E> { pub trait Step<I, S: IsFinished, E> {
fn step(&mut self, context: &mut C) -> Result<S, E>; fn step(&mut self, input: &mut I) -> Result<S, E>;
}
pub trait StepBack<I, S: IsFinished, E> {
fn step_back(&mut self, input: &mut I) -> Result<S, E>;
} }