mirror of https://codeberg.org/topola/topola.git
router: use `Step` and new `StepBack` traits in `Route` and `Trace`
This commit is contained in:
parent
1305487c7f
commit
7830806834
|
|
@ -8,6 +8,7 @@ use crate::{
|
|||
tracer::Tracer,
|
||||
Router, RouterAstarStrategy, RouterError, RouterStatus,
|
||||
},
|
||||
step::Step,
|
||||
};
|
||||
|
||||
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 {
|
||||
&self.astar.graph
|
||||
}
|
||||
|
|
@ -89,3 +70,22 @@ impl Route {
|
|||
&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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ use crate::{
|
|||
},
|
||||
graph::{GetPetgraphIndex, MakeRef},
|
||||
layout::Layout,
|
||||
step::{IsFinished, Step, StepBack},
|
||||
};
|
||||
|
||||
use super::{
|
||||
|
|
@ -25,7 +26,7 @@ use super::{
|
|||
draw::DrawException,
|
||||
navmesh::{Navmesh, NavmeshEdgeReference, NavmeshError, NavvertexIndex},
|
||||
route::Route,
|
||||
trace::Trace,
|
||||
trace::{Trace, TraceStepInput},
|
||||
tracer::{Tracer, TracerException},
|
||||
};
|
||||
|
||||
|
|
@ -42,6 +43,12 @@ pub enum RouterStatus {
|
|||
Finished(BandTermsegIndex),
|
||||
}
|
||||
|
||||
impl IsFinished for RouterStatus {
|
||||
fn finished(&self) -> bool {
|
||||
matches!(self, RouterStatus::Finished(..))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RouterAstarStrategy<'a, R: AccessRules> {
|
||||
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 width = self.trace.width;
|
||||
let result = self
|
||||
.trace
|
||||
.step(&mut self.tracer, navmesh, edge.target(), width);
|
||||
let result = self.trace.step(&mut TraceStepInput {
|
||||
tracer: &mut self.tracer,
|
||||
navmesh,
|
||||
to: edge.target(),
|
||||
width,
|
||||
});
|
||||
|
||||
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) {
|
||||
self.trace.undo_step(&mut self.tracer);
|
||||
self.trace.step_back(&mut self.tracer);
|
||||
}
|
||||
|
||||
fn estimate_cost(&mut self, navmesh: &Navmesh, vertex: NavvertexIndex) -> f64 {
|
||||
|
|
|
|||
|
|
@ -9,11 +9,14 @@ use crate::{
|
|||
head::{BareHead, CaneHead, Head},
|
||||
rules::AccessRules,
|
||||
},
|
||||
router::{
|
||||
step::{Step, StepBack},
|
||||
};
|
||||
|
||||
use super::{
|
||||
draw::Draw,
|
||||
navmesh::{BinavvertexNodeIndex, Navmesh, NavvertexIndex},
|
||||
tracer::TracerStatus,
|
||||
tracer::{Tracer, TracerException},
|
||||
},
|
||||
};
|
||||
|
||||
#[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(
|
||||
&mut self,
|
||||
tracer: &mut Tracer<impl AccessRules>,
|
||||
|
|
@ -116,3 +92,49 @@ impl Trace {
|
|||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,13 @@ use thiserror::Error;
|
|||
use crate::{
|
||||
drawing::{band::BandTermsegIndex, dot::FixedDotIndex, rules::AccessRules},
|
||||
layout::Layout,
|
||||
router::{
|
||||
step::{IsFinished, Step, StepBack},
|
||||
};
|
||||
|
||||
use super::{
|
||||
draw::{Draw, DrawException},
|
||||
navmesh::{Navmesh, NavvertexIndex},
|
||||
trace::Trace,
|
||||
},
|
||||
trace::{Trace, TraceStepInput},
|
||||
};
|
||||
|
||||
#[derive(Error, Debug, Clone, Copy)]
|
||||
|
|
@ -19,6 +21,17 @@ pub enum TracerException {
|
|||
CannotWrap,
|
||||
}
|
||||
|
||||
pub enum TracerStatus {
|
||||
Running,
|
||||
Finished,
|
||||
}
|
||||
|
||||
impl IsFinished for TracerStatus {
|
||||
fn finished(&self) -> bool {
|
||||
matches!(self, TracerStatus::Finished)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Tracer<'a, R: AccessRules> {
|
||||
pub layout: &'a mut Layout<R>,
|
||||
|
|
@ -78,7 +91,12 @@ impl<'a, R: AccessRules> Tracer<'a, R> {
|
|||
width: f64,
|
||||
) -> Result<(), TracerException> {
|
||||
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);
|
||||
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))]
|
||||
pub fn undo_path(&mut self, trace: &mut Trace, step_count: usize) {
|
||||
for _ in 0..step_count {
|
||||
trace.undo_step(self);
|
||||
let _ = trace.step_back(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@ pub trait IsFinished {
|
|||
fn finished(&self) -> bool;
|
||||
}
|
||||
|
||||
pub trait Step<C, S: IsFinished, E> {
|
||||
fn step(&mut self, context: &mut C) -> Result<S, E>;
|
||||
pub trait Step<I, S: IsFinished, 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>;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue