mirror of https://codeberg.org/topola/topola.git
refactor: make `Step::step(...)` return `ControlFlow<...>`
This is an iteration on what was suggested in https://codeberg.org/topola/topola/pulls/79 . This removes the need to create a new status type for steppers that have only one intermediate state, and removes unidiomatic `TryInto<...>` usage to determine if a stepper has finished.
This commit is contained in:
parent
a9e42eef17
commit
23d1eaa722
|
|
@ -1,15 +1,15 @@
|
||||||
//! Manages autorouting of ratlines in a layout, tracking status and processed
|
//! Manages autorouting of ratlines in a layout, tracking status and processed
|
||||||
//! routing steps.
|
//! routing steps.
|
||||||
|
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use petgraph::graph::EdgeIndex;
|
use petgraph::graph::EdgeIndex;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
board::mesadata::AccessMesadata,
|
board::mesadata::AccessMesadata,
|
||||||
drawing::{band::BandTermsegIndex, graph::PrimitiveIndex},
|
drawing::{band::BandTermsegIndex, graph::PrimitiveIndex},
|
||||||
geometry::primitive::PrimitiveShape,
|
geometry::primitive::PrimitiveShape,
|
||||||
router::{
|
router::{navcord::NavcordStepper, navmesh::Navmesh, route::RouteStepper, Router},
|
||||||
navcord::NavcordStepper, navmesh::Navmesh, route::RouteStepper, Router, RouterStatus,
|
|
||||||
},
|
|
||||||
stepper::Step,
|
stepper::Step,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -19,29 +19,11 @@ use super::{
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Represents the current status of the autoroute operation.
|
/// Represents the current status of the autoroute operation.
|
||||||
pub enum AutorouteStatus {
|
pub enum AutorouteContinueStatus {
|
||||||
/// The autoroute is currently running and in progress.
|
/// The autoroute is currently running and in progress.
|
||||||
Running,
|
Running,
|
||||||
/// A specific segment has been successfully routed.
|
/// A specific segment has been successfully routed.
|
||||||
Routed(BandTermsegIndex),
|
Routed(BandTermsegIndex),
|
||||||
/// The autoroute process has completed successfully.
|
|
||||||
Finished,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryInto<()> for AutorouteStatus {
|
|
||||||
type Error = ();
|
|
||||||
/// Attempts to get the [`Result`] from the [`AutorouteStatus`].
|
|
||||||
///
|
|
||||||
/// This implementation allows transitioning from [`AutorouteStatus`] to a
|
|
||||||
/// [`Result`]. It returns success for the [`AutorouteStatus::Finished`] state
|
|
||||||
/// or an error for [`AutorouteStatus::Running`] or [`AutorouteStatus::Routed`] states.
|
|
||||||
fn try_into(self) -> Result<(), ()> {
|
|
||||||
match self {
|
|
||||||
AutorouteStatus::Running => Err(()),
|
|
||||||
AutorouteStatus::Routed(..) => Err(()),
|
|
||||||
AutorouteStatus::Finished => Ok(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Manages the autorouting process across multiple ratlines.
|
/// Manages the autorouting process across multiple ratlines.
|
||||||
|
|
@ -87,17 +69,22 @@ impl AutorouteExecutionStepper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M: AccessMesadata> Step<Autorouter<M>, AutorouteStatus, ()> for AutorouteExecutionStepper {
|
impl<M: AccessMesadata> Step<Autorouter<M>, (), AutorouteContinueStatus>
|
||||||
|
for AutorouteExecutionStepper
|
||||||
|
{
|
||||||
type Error = AutorouterError;
|
type Error = AutorouterError;
|
||||||
|
|
||||||
fn step(&mut self, autorouter: &mut Autorouter<M>) -> Result<AutorouteStatus, AutorouterError> {
|
fn step(
|
||||||
|
&mut self,
|
||||||
|
autorouter: &mut Autorouter<M>,
|
||||||
|
) -> Result<ControlFlow<(), AutorouteContinueStatus>, AutorouterError> {
|
||||||
let Some(curr_ratline) = self.curr_ratline else {
|
let Some(curr_ratline) = self.curr_ratline else {
|
||||||
return Ok(AutorouteStatus::Finished);
|
return Ok(ControlFlow::Break(()));
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(ref mut route) = self.route else {
|
let Some(ref mut route) = self.route else {
|
||||||
// Shouldn't happen.
|
// Shouldn't happen.
|
||||||
return Ok(AutorouteStatus::Finished);
|
return Ok(ControlFlow::Break(()));
|
||||||
};
|
};
|
||||||
|
|
||||||
let (source, target) = autorouter.ratline_endpoints(curr_ratline);
|
let (source, target) = autorouter.ratline_endpoints(curr_ratline);
|
||||||
|
|
@ -106,8 +93,8 @@ impl<M: AccessMesadata> Step<Autorouter<M>, AutorouteStatus, ()> for AutorouteEx
|
||||||
let mut router =
|
let mut router =
|
||||||
Router::new(autorouter.board.layout_mut(), self.options.router_options);
|
Router::new(autorouter.board.layout_mut(), self.options.router_options);
|
||||||
|
|
||||||
let RouterStatus::Finished(band_termseg) = route.step(&mut router)? else {
|
let ControlFlow::Break(band_termseg) = route.step(&mut router)? else {
|
||||||
return Ok(AutorouteStatus::Running);
|
return Ok(ControlFlow::Continue(AutorouteContinueStatus::Running));
|
||||||
};
|
};
|
||||||
band_termseg
|
band_termseg
|
||||||
};
|
};
|
||||||
|
|
@ -139,7 +126,9 @@ impl<M: AccessMesadata> Step<Autorouter<M>, AutorouteStatus, ()> for AutorouteEx
|
||||||
//return Ok(AutorouteStatus::Finished);
|
//return Ok(AutorouteStatus::Finished);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(AutorouteStatus::Routed(band_termseg))
|
Ok(ControlFlow::Continue(AutorouteContinueStatus::Routed(
|
||||||
|
band_termseg,
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
//! Manages the comparison of detours between two ratlines, tracking their
|
//! Manages the comparison of detours between two ratlines, tracking their
|
||||||
//! routing statuses and recording their lengths.
|
//! routing statuses and recording their lengths.
|
||||||
|
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use petgraph::graph::EdgeIndex;
|
use petgraph::graph::EdgeIndex;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -13,28 +15,11 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
autoroute::{AutorouteExecutionStepper, AutorouteStatus},
|
autoroute::{AutorouteContinueStatus, AutorouteExecutionStepper},
|
||||||
invoker::{GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles},
|
invoker::{GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles},
|
||||||
Autorouter, AutorouterError, AutorouterOptions,
|
Autorouter, AutorouterError, AutorouterOptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub enum CompareDetoursStatus {
|
|
||||||
Running,
|
|
||||||
Finished(f64, f64),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryInto<(f64, f64)> for CompareDetoursStatus {
|
|
||||||
type Error = ();
|
|
||||||
fn try_into(self) -> Result<(f64, f64), ()> {
|
|
||||||
match self {
|
|
||||||
CompareDetoursStatus::Running => Err(()),
|
|
||||||
CompareDetoursStatus::Finished(total_length1, total_length2) => {
|
|
||||||
Ok((total_length1, total_length2))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CompareDetoursExecutionStepper {
|
pub struct CompareDetoursExecutionStepper {
|
||||||
autoroute: AutorouteExecutionStepper,
|
autoroute: AutorouteExecutionStepper,
|
||||||
next_autoroute: Option<AutorouteExecutionStepper>,
|
next_autoroute: Option<AutorouteExecutionStepper>,
|
||||||
|
|
@ -66,25 +51,22 @@ impl CompareDetoursExecutionStepper {
|
||||||
|
|
||||||
// XXX: Do we really need this to be a stepper? We don't use at the moment, as sorting functions
|
// XXX: Do we really need this to be a stepper? We don't use at the moment, as sorting functions
|
||||||
// aren't steppable either. It may be useful for debugging later on tho.
|
// aren't steppable either. It may be useful for debugging later on tho.
|
||||||
impl<M: AccessMesadata> Step<Autorouter<M>, CompareDetoursStatus, (f64, f64)>
|
impl<M: AccessMesadata> Step<Autorouter<M>, (f64, f64)> for CompareDetoursExecutionStepper {
|
||||||
for CompareDetoursExecutionStepper
|
|
||||||
{
|
|
||||||
type Error = AutorouterError;
|
type Error = AutorouterError;
|
||||||
|
|
||||||
fn step(
|
fn step(
|
||||||
&mut self,
|
&mut self,
|
||||||
autorouter: &mut Autorouter<M>,
|
autorouter: &mut Autorouter<M>,
|
||||||
) -> Result<CompareDetoursStatus, AutorouterError> {
|
) -> Result<ControlFlow<(f64, f64)>, AutorouterError> {
|
||||||
if self.done {
|
if self.done {
|
||||||
return Ok(CompareDetoursStatus::Finished(
|
return Ok(ControlFlow::Break((self.total_length1, self.total_length2)));
|
||||||
self.total_length1,
|
|
||||||
self.total_length2,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.autoroute.step(autorouter)? {
|
match self.autoroute.step(autorouter)? {
|
||||||
AutorouteStatus::Running => Ok(CompareDetoursStatus::Running),
|
ControlFlow::Continue(AutorouteContinueStatus::Running) => {
|
||||||
AutorouteStatus::Routed(band_termseg) => {
|
Ok(ControlFlow::Continue(()))
|
||||||
|
}
|
||||||
|
ControlFlow::Continue(AutorouteContinueStatus::Routed(band_termseg)) => {
|
||||||
let length = band_termseg
|
let length = band_termseg
|
||||||
.ref_(autorouter.board.layout().drawing())
|
.ref_(autorouter.board.layout().drawing())
|
||||||
.length();
|
.length();
|
||||||
|
|
@ -95,22 +77,19 @@ impl<M: AccessMesadata> Step<Autorouter<M>, CompareDetoursStatus, (f64, f64)>
|
||||||
self.total_length2 += length;
|
self.total_length2 += length;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(CompareDetoursStatus::Running)
|
Ok(ControlFlow::Continue(()))
|
||||||
}
|
}
|
||||||
AutorouteStatus::Finished => {
|
ControlFlow::Break(()) => {
|
||||||
if let Some(next_autoroute) = self.next_autoroute.take() {
|
if let Some(next_autoroute) = self.next_autoroute.take() {
|
||||||
autorouter.undo_autoroute_ratlines(vec![self.ratline1, self.ratline2])?;
|
autorouter.undo_autoroute_ratlines(vec![self.ratline1, self.ratline2])?;
|
||||||
self.autoroute = next_autoroute;
|
self.autoroute = next_autoroute;
|
||||||
|
|
||||||
Ok(CompareDetoursStatus::Running)
|
Ok(ControlFlow::Continue(()))
|
||||||
} else {
|
} else {
|
||||||
self.done = true;
|
self.done = true;
|
||||||
autorouter.undo_autoroute_ratlines(vec![self.ratline2, self.ratline1])?;
|
autorouter.undo_autoroute_ratlines(vec![self.ratline2, self.ratline1])?;
|
||||||
|
|
||||||
Ok(CompareDetoursStatus::Finished(
|
Ok(ControlFlow::Break((self.total_length1, self.total_length2)))
|
||||||
self.total_length1,
|
|
||||||
self.total_length2,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use enum_dispatch::enum_dispatch;
|
use enum_dispatch::enum_dispatch;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{board::mesadata::AccessMesadata, layout::via::ViaWeight, stepper::Step};
|
use crate::{board::mesadata::AccessMesadata, layout::via::ViaWeight, stepper::Step};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
autoroute::{AutorouteExecutionStepper, AutorouteStatus},
|
autoroute::AutorouteExecutionStepper,
|
||||||
compare_detours::{CompareDetoursExecutionStepper, CompareDetoursStatus},
|
compare_detours::CompareDetoursExecutionStepper,
|
||||||
invoker::{Invoker, InvokerError, InvokerStatus},
|
invoker::{Invoker, InvokerError},
|
||||||
measure_length::MeasureLengthExecutionStepper,
|
measure_length::MeasureLengthExecutionStepper,
|
||||||
place_via::PlaceViaExecutionStepper,
|
place_via::PlaceViaExecutionStepper,
|
||||||
remove_bands::RemoveBandsExecutionStepper,
|
remove_bands::RemoveBandsExecutionStepper,
|
||||||
|
|
@ -38,28 +40,25 @@ impl ExecutionStepper {
|
||||||
fn step_catch_err<M: AccessMesadata>(
|
fn step_catch_err<M: AccessMesadata>(
|
||||||
&mut self,
|
&mut self,
|
||||||
autorouter: &mut Autorouter<M>,
|
autorouter: &mut Autorouter<M>,
|
||||||
) -> Result<InvokerStatus, InvokerError> {
|
) -> Result<ControlFlow<String>, InvokerError> {
|
||||||
Ok(match self {
|
Ok(match self {
|
||||||
ExecutionStepper::Autoroute(autoroute) => match autoroute.step(autorouter)? {
|
ExecutionStepper::Autoroute(autoroute) => match autoroute.step(autorouter)? {
|
||||||
AutorouteStatus::Running => InvokerStatus::Running,
|
ControlFlow::Continue(..) => ControlFlow::Continue(()),
|
||||||
AutorouteStatus::Routed(..) => InvokerStatus::Running,
|
ControlFlow::Break(..) => ControlFlow::Break("finished autorouting".to_string()),
|
||||||
AutorouteStatus::Finished => {
|
|
||||||
InvokerStatus::Finished("finished autorouting".to_string())
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
ExecutionStepper::PlaceVia(place_via) => {
|
ExecutionStepper::PlaceVia(place_via) => {
|
||||||
place_via.doit(autorouter)?;
|
place_via.doit(autorouter)?;
|
||||||
InvokerStatus::Finished("finished placing via".to_string())
|
ControlFlow::Break("finished placing via".to_string())
|
||||||
}
|
}
|
||||||
ExecutionStepper::RemoveBands(remove_bands) => {
|
ExecutionStepper::RemoveBands(remove_bands) => {
|
||||||
remove_bands.doit(autorouter)?;
|
remove_bands.doit(autorouter)?;
|
||||||
InvokerStatus::Finished("finished removing bands".to_string())
|
ControlFlow::Break("finished removing bands".to_string())
|
||||||
}
|
}
|
||||||
ExecutionStepper::CompareDetours(compare_detours) => {
|
ExecutionStepper::CompareDetours(compare_detours) => {
|
||||||
match compare_detours.step(autorouter)? {
|
match compare_detours.step(autorouter)? {
|
||||||
CompareDetoursStatus::Running => InvokerStatus::Running,
|
ControlFlow::Continue(()) => ControlFlow::Continue(()),
|
||||||
CompareDetoursStatus::Finished(total_length1, total_length2) => {
|
ControlFlow::Break((total_length1, total_length2)) => {
|
||||||
InvokerStatus::Finished(format!(
|
ControlFlow::Break(format!(
|
||||||
"total detour lengths are {} and {}",
|
"total detour lengths are {} and {}",
|
||||||
total_length1, total_length2
|
total_length1, total_length2
|
||||||
))
|
))
|
||||||
|
|
@ -68,24 +67,24 @@ impl ExecutionStepper {
|
||||||
}
|
}
|
||||||
ExecutionStepper::MeasureLength(measure_length) => {
|
ExecutionStepper::MeasureLength(measure_length) => {
|
||||||
let length = measure_length.doit(autorouter)?;
|
let length = measure_length.doit(autorouter)?;
|
||||||
InvokerStatus::Finished(format!("Total length of selected bands: {}", length))
|
ControlFlow::Break(format!("Total length of selected bands: {}", length))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M: AccessMesadata> Step<Invoker<M>, InvokerStatus, ()> for ExecutionStepper {
|
impl<M: AccessMesadata> Step<Invoker<M>, String> for ExecutionStepper {
|
||||||
type Error = InvokerError;
|
type Error = InvokerError;
|
||||||
|
|
||||||
fn step(&mut self, invoker: &mut Invoker<M>) -> Result<InvokerStatus, InvokerError> {
|
fn step(&mut self, invoker: &mut Invoker<M>) -> Result<ControlFlow<String>, InvokerError> {
|
||||||
match self.step_catch_err(&mut invoker.autorouter) {
|
match self.step_catch_err(&mut invoker.autorouter) {
|
||||||
Ok(InvokerStatus::Running) => Ok(InvokerStatus::Running),
|
Ok(ControlFlow::Continue(())) => Ok(ControlFlow::Continue(())),
|
||||||
Ok(InvokerStatus::Finished(msg)) => {
|
Ok(ControlFlow::Break(msg)) => {
|
||||||
if let Some(command) = invoker.ongoing_command.take() {
|
if let Some(command) = invoker.ongoing_command.take() {
|
||||||
invoker.history.do_(command);
|
invoker.history.do_(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(InvokerStatus::Finished(msg))
|
Ok(ControlFlow::Break(msg))
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
invoker.ongoing_command = None;
|
invoker.ongoing_command = None;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
//! Manages the execution of routing commands within the autorouting system.
|
//! Manages the execution of routing commands within the autorouting system.
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::{cmp::Ordering, ops::ControlFlow};
|
||||||
|
|
||||||
use contracts_try::debug_requires;
|
use contracts_try::debug_requires;
|
||||||
use derive_getters::{Dissolve, Getters};
|
use derive_getters::{Dissolve, Getters};
|
||||||
|
|
@ -46,12 +46,6 @@ pub trait GetObstacles {
|
||||||
fn obstacles(&self) -> &[PrimitiveIndex];
|
fn obstacles(&self) -> &[PrimitiveIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum InvokerStatus {
|
|
||||||
Running,
|
|
||||||
Finished(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Error, Debug, Clone)]
|
#[derive(Error, Debug, Clone)]
|
||||||
pub enum InvokerError {
|
pub enum InvokerError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
|
@ -60,16 +54,6 @@ pub enum InvokerError {
|
||||||
Autorouter(#[from] AutorouterError),
|
Autorouter(#[from] AutorouterError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryInto<()> for InvokerStatus {
|
|
||||||
type Error = ();
|
|
||||||
fn try_into(self) -> Result<(), ()> {
|
|
||||||
match self {
|
|
||||||
InvokerStatus::Running => Err(()),
|
|
||||||
InvokerStatus::Finished(..) => Ok(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Getters, Dissolve)]
|
#[derive(Getters, Dissolve)]
|
||||||
pub struct Invoker<M: AccessMesadata> {
|
pub struct Invoker<M: AccessMesadata> {
|
||||||
pub(super) autorouter: Autorouter<M>,
|
pub(super) autorouter: Autorouter<M>,
|
||||||
|
|
@ -95,12 +79,9 @@ impl<M: AccessMesadata> Invoker<M> {
|
||||||
let mut execute = self.execute_stepper(command)?;
|
let mut execute = self.execute_stepper(command)?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let status = match execute.step(self) {
|
let status = execute.step(self)?;
|
||||||
Ok(status) => status,
|
|
||||||
Err(err) => return Err(err),
|
|
||||||
};
|
|
||||||
|
|
||||||
if let InvokerStatus::Finished(..) = status {
|
if let ControlFlow::Break(..) = status {
|
||||||
self.history.set_undone(std::iter::empty());
|
self.history.set_undone(std::iter::empty());
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
@ -183,7 +164,7 @@ impl<M: AccessMesadata> Invoker<M> {
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let InvokerStatus::Finished(..) = status {
|
if let ControlFlow::Break(..) = status {
|
||||||
return Ok(self.history.redo()?);
|
return Ok(self.history.redo()?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use topola::{
|
use topola::{
|
||||||
autorouter::{
|
autorouter::{
|
||||||
execution::ExecutionStepper,
|
execution::ExecutionStepper,
|
||||||
invoker::{
|
invoker::{
|
||||||
GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles, Invoker, InvokerError,
|
GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles, Invoker, InvokerError,
|
||||||
InvokerStatus,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
board::mesadata::AccessMesadata,
|
board::mesadata::AccessMesadata,
|
||||||
|
|
@ -14,49 +15,13 @@ use topola::{
|
||||||
stepper::{Abort, Step},
|
stepper::{Abort, Step},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::interaction::{
|
use crate::interaction::{InteractionContext, InteractionError, InteractionStepper};
|
||||||
InteractionContext, InteractionError, InteractionStatus, InteractionStepper,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct ActivityContext<'a, M: AccessMesadata> {
|
pub struct ActivityContext<'a, M: AccessMesadata> {
|
||||||
pub interaction: InteractionContext,
|
pub interaction: InteractionContext,
|
||||||
pub invoker: &'a mut Invoker<M>,
|
pub invoker: &'a mut Invoker<M>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum ActivityStatus {
|
|
||||||
Running,
|
|
||||||
Finished(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<InteractionStatus> for ActivityStatus {
|
|
||||||
fn from(status: InteractionStatus) -> Self {
|
|
||||||
match status {
|
|
||||||
InteractionStatus::Running => ActivityStatus::Running,
|
|
||||||
InteractionStatus::Finished(msg) => ActivityStatus::Finished(msg),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<InvokerStatus> for ActivityStatus {
|
|
||||||
fn from(status: InvokerStatus) -> Self {
|
|
||||||
match status {
|
|
||||||
InvokerStatus::Running => ActivityStatus::Running,
|
|
||||||
InvokerStatus::Finished(msg) => ActivityStatus::Finished(msg),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryInto<()> for ActivityStatus {
|
|
||||||
type Error = ();
|
|
||||||
fn try_into(self) -> Result<(), ()> {
|
|
||||||
match self {
|
|
||||||
ActivityStatus::Running => Err(()),
|
|
||||||
ActivityStatus::Finished(..) => Ok(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Error, Debug, Clone)]
|
#[derive(Error, Debug, Clone)]
|
||||||
pub enum ActivityError {
|
pub enum ActivityError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
|
@ -70,15 +35,18 @@ pub enum ActivityStepper {
|
||||||
Execution(ExecutionStepper),
|
Execution(ExecutionStepper),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M: AccessMesadata> Step<ActivityContext<'_, M>, ActivityStatus, ()> for ActivityStepper {
|
impl<M: AccessMesadata> Step<ActivityContext<'_, M>, String> for ActivityStepper {
|
||||||
type Error = ActivityError;
|
type Error = ActivityError;
|
||||||
|
|
||||||
fn step(&mut self, context: &mut ActivityContext<M>) -> Result<ActivityStatus, ActivityError> {
|
fn step(
|
||||||
|
&mut self,
|
||||||
|
context: &mut ActivityContext<M>,
|
||||||
|
) -> Result<ControlFlow<String>, ActivityError> {
|
||||||
match self {
|
match self {
|
||||||
ActivityStepper::Interaction(interaction) => {
|
ActivityStepper::Interaction(interaction) => {
|
||||||
Ok(interaction.step(&mut context.interaction)?.into())
|
Ok(interaction.step(&mut context.interaction)?)
|
||||||
}
|
}
|
||||||
ActivityStepper::Execution(execution) => Ok(execution.step(context.invoker)?.into()),
|
ActivityStepper::Execution(execution) => Ok(execution.step(context.invoker)?),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -87,9 +55,11 @@ impl<M: AccessMesadata> Abort<ActivityContext<'_, M>> for ActivityStepper {
|
||||||
fn abort(&mut self, context: &mut ActivityContext<M>) {
|
fn abort(&mut self, context: &mut ActivityContext<M>) {
|
||||||
match self {
|
match self {
|
||||||
ActivityStepper::Interaction(interaction) => {
|
ActivityStepper::Interaction(interaction) => {
|
||||||
Ok(interaction.abort(&mut context.interaction))
|
interaction.abort(&mut context.interaction)
|
||||||
}
|
}
|
||||||
ActivityStepper::Execution(execution) => execution.finish(context.invoker), // TODO.
|
ActivityStepper::Execution(execution) => {
|
||||||
|
execution.finish(context.invoker);
|
||||||
|
} // TODO.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -136,7 +106,7 @@ impl GetObstacles for ActivityStepper {
|
||||||
|
|
||||||
pub struct ActivityStepperWithStatus {
|
pub struct ActivityStepperWithStatus {
|
||||||
activity: ActivityStepper,
|
activity: ActivityStepper,
|
||||||
maybe_status: Option<ActivityStatus>,
|
maybe_status: Option<ControlFlow<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActivityStepperWithStatus {
|
impl ActivityStepperWithStatus {
|
||||||
|
|
@ -147,17 +117,18 @@ impl ActivityStepperWithStatus {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn maybe_status(&self) -> Option<ActivityStatus> {
|
pub fn maybe_status(&self) -> Option<ControlFlow<String>> {
|
||||||
self.maybe_status.clone()
|
self.maybe_status.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M: AccessMesadata> Step<ActivityContext<'_, M>, ActivityStatus, ()>
|
impl<M: AccessMesadata> Step<ActivityContext<'_, M>, String> for ActivityStepperWithStatus {
|
||||||
for ActivityStepperWithStatus
|
|
||||||
{
|
|
||||||
type Error = ActivityError;
|
type Error = ActivityError;
|
||||||
|
|
||||||
fn step(&mut self, context: &mut ActivityContext<M>) -> Result<ActivityStatus, ActivityError> {
|
fn step(
|
||||||
|
&mut self,
|
||||||
|
context: &mut ActivityContext<M>,
|
||||||
|
) -> Result<ControlFlow<String>, ActivityError> {
|
||||||
let status = self.activity.step(context)?;
|
let status = self.activity.step(context)?;
|
||||||
self.maybe_status = Some(status.clone());
|
self.maybe_status = Some(status.clone());
|
||||||
Ok(status.into())
|
Ok(status.into())
|
||||||
|
|
@ -166,7 +137,7 @@ impl<M: AccessMesadata> Step<ActivityContext<'_, M>, ActivityStatus, ()>
|
||||||
|
|
||||||
impl<M: AccessMesadata> Abort<ActivityContext<'_, M>> for ActivityStepperWithStatus {
|
impl<M: AccessMesadata> Abort<ActivityContext<'_, M>> for ActivityStepperWithStatus {
|
||||||
fn abort(&mut self, context: &mut ActivityContext<M>) {
|
fn abort(&mut self, context: &mut ActivityContext<M>) {
|
||||||
self.maybe_status = Some(ActivityStatus::Finished(String::from("aborted")));
|
self.maybe_status = Some(ControlFlow::Break(String::from("aborted")));
|
||||||
self.activity.abort(context);
|
self.activity.abort(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use topola::{
|
use topola::{
|
||||||
autorouter::invoker::{GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles},
|
autorouter::invoker::{GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles},
|
||||||
|
|
@ -13,22 +15,6 @@ pub struct InteractionContext {
|
||||||
// (we will need an additional struct to hold a reference to a `Board<...>`)
|
// (we will need an additional struct to hold a reference to a `Board<...>`)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum InteractionStatus {
|
|
||||||
Running,
|
|
||||||
Finished(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryInto<()> for InteractionStatus {
|
|
||||||
type Error = ();
|
|
||||||
fn try_into(self) -> Result<(), ()> {
|
|
||||||
match self {
|
|
||||||
InteractionStatus::Running => Err(()),
|
|
||||||
InteractionStatus::Finished(..) => Ok(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Error, Debug, Clone)]
|
#[derive(Error, Debug, Clone)]
|
||||||
pub enum InteractionError {
|
pub enum InteractionError {
|
||||||
#[error("nothing to interact with")]
|
#[error("nothing to interact with")]
|
||||||
|
|
@ -42,14 +28,14 @@ pub enum InteractionStepper {
|
||||||
// - interactively moving a footprint.
|
// - interactively moving a footprint.
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Step<InteractionContext, InteractionStatus, ()> for InteractionStepper {
|
impl Step<InteractionContext, String> for InteractionStepper {
|
||||||
type Error = InteractionError;
|
type Error = InteractionError;
|
||||||
|
|
||||||
fn step(
|
fn step(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut InteractionContext,
|
context: &mut InteractionContext,
|
||||||
) -> Result<InteractionStatus, InteractionError> {
|
) -> Result<ControlFlow<String>, InteractionError> {
|
||||||
Ok(InteractionStatus::Finished(String::from("")))
|
Ok(ControlFlow::Break(String::from("")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ use topola::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
activity::{ActivityContext, ActivityError, ActivityStatus, ActivityStepperWithStatus},
|
activity::{ActivityContext, ActivityError, ActivityStepperWithStatus},
|
||||||
interaction::InteractionContext,
|
interaction::InteractionContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -68,8 +68,8 @@ impl<M: AccessMesadata> Interactor<M> {
|
||||||
interaction: InteractionContext {},
|
interaction: InteractionContext {},
|
||||||
invoker: &mut self.invoker,
|
invoker: &mut self.invoker,
|
||||||
}) {
|
}) {
|
||||||
Ok(ActivityStatus::Running) => ControlFlow::Continue(()),
|
Ok(ControlFlow::Continue(())) => ControlFlow::Continue(()),
|
||||||
Ok(ActivityStatus::Finished(..)) => ControlFlow::Break(Ok(())),
|
Ok(ControlFlow::Break(msg)) => ControlFlow::Break(Ok(())),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
self.activity = None;
|
self.activity = None;
|
||||||
ControlFlow::Break(Err(err))
|
ControlFlow::Break(Err(err))
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{path::Path, sync::mpsc::Sender};
|
use std::{ops::ControlFlow, path::Path, sync::mpsc::Sender};
|
||||||
|
|
||||||
use topola::{
|
use topola::{
|
||||||
autorouter::{
|
autorouter::{
|
||||||
|
|
@ -11,7 +11,7 @@ use topola::{
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
action::{Action, Switch, Trigger},
|
action::{Action, Switch, Trigger},
|
||||||
activity::{ActivityContext, ActivityStatus, ActivityStepperWithStatus},
|
activity::{ActivityContext, ActivityStepperWithStatus},
|
||||||
app::{execute, handle_file},
|
app::{execute, handle_file},
|
||||||
interaction::InteractionContext,
|
interaction::InteractionContext,
|
||||||
translator::Translator,
|
translator::Translator,
|
||||||
|
|
@ -130,7 +130,7 @@ impl MenuBar {
|
||||||
.maybe_activity()
|
.maybe_activity()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(true, |activity| {
|
.map_or(true, |activity| {
|
||||||
matches!(activity.maybe_status(), Some(ActivityStatus::Finished(..)))
|
matches!(activity.maybe_status(), Some(ControlFlow::Break(..)))
|
||||||
}),
|
}),
|
||||||
None => false,
|
None => false,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
use crate::{
|
use std::ops::ControlFlow;
|
||||||
activity::{ActivityStatus, ActivityStepperWithStatus},
|
|
||||||
translator::Translator,
|
use crate::{activity::ActivityStepperWithStatus, translator::Translator, viewport::Viewport};
|
||||||
viewport::Viewport,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct StatusBar {}
|
pub struct StatusBar {}
|
||||||
|
|
||||||
|
|
@ -25,7 +23,7 @@ impl StatusBar {
|
||||||
let mut message = String::from("");
|
let mut message = String::from("");
|
||||||
|
|
||||||
if let Some(activity) = maybe_activity {
|
if let Some(activity) = maybe_activity {
|
||||||
if let Some(ActivityStatus::Finished(msg)) = activity.maybe_status() {
|
if let Some(ControlFlow::Break(msg)) = activity.maybe_status() {
|
||||||
message = msg;
|
message = msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use topola::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
activity::{ActivityContext, ActivityStatus, ActivityStepperWithStatus},
|
activity::{ActivityContext, ActivityStepperWithStatus},
|
||||||
error_dialog::ErrorDialog,
|
error_dialog::ErrorDialog,
|
||||||
interaction::InteractionContext,
|
interaction::InteractionContext,
|
||||||
interactor::Interactor,
|
interactor::Interactor,
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||||
use std::collections::{BinaryHeap, HashMap, VecDeque};
|
use std::collections::{BinaryHeap, HashMap, VecDeque};
|
||||||
|
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use petgraph::algo::Measure;
|
use petgraph::algo::Measure;
|
||||||
use petgraph::visit::{EdgeRef, GraphBase, IntoEdgeReferences, IntoEdges};
|
use petgraph::visit::{EdgeRef, GraphBase, IntoEdgeReferences, IntoEdges};
|
||||||
|
|
@ -138,44 +139,19 @@ where
|
||||||
pub is_probing: bool,
|
pub is_probing: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum AstarContinueStatus {
|
||||||
|
Probing,
|
||||||
|
Probed,
|
||||||
|
Visited,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug, Clone)]
|
#[derive(Error, Debug, Clone)]
|
||||||
pub enum AstarError {
|
pub enum AstarError {
|
||||||
#[error("A* search found no path")]
|
#[error("A* search found no path")]
|
||||||
NotFound,
|
NotFound,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum AstarStatus<G, K, R>
|
|
||||||
where
|
|
||||||
G: GraphBase,
|
|
||||||
G::NodeId: Eq + Hash,
|
|
||||||
for<'a> &'a G: IntoEdges<NodeId = G::NodeId, EdgeId = G::EdgeId> + MakeEdgeRef,
|
|
||||||
K: Measure + Copy,
|
|
||||||
{
|
|
||||||
Probing,
|
|
||||||
Probed,
|
|
||||||
Visited,
|
|
||||||
Finished(K, Vec<G::NodeId>, R),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<G, K, R> TryInto<(K, Vec<G::NodeId>, R)> for AstarStatus<G, K, R>
|
|
||||||
where
|
|
||||||
G: GraphBase,
|
|
||||||
G::NodeId: Eq + Hash,
|
|
||||||
for<'a> &'a G: IntoEdges<NodeId = G::NodeId, EdgeId = G::EdgeId> + MakeEdgeRef,
|
|
||||||
K: Measure + Copy,
|
|
||||||
{
|
|
||||||
type Error = ();
|
|
||||||
fn try_into(self) -> Result<(K, Vec<G::NodeId>, R), ()> {
|
|
||||||
match self {
|
|
||||||
AstarStatus::Probing => Err(()),
|
|
||||||
AstarStatus::Probed => Err(()),
|
|
||||||
AstarStatus::Visited => Err(()),
|
|
||||||
AstarStatus::Finished(cost, path, result) => Ok((cost, path, result)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<G, K> Astar<G, K>
|
impl<G, K> Astar<G, K>
|
||||||
where
|
where
|
||||||
G: GraphBase,
|
G: GraphBase,
|
||||||
|
|
@ -203,7 +179,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G, K, R, S: AstarStrategy<G, K, R>> Step<S, AstarStatus<G, K, R>, (K, Vec<G::NodeId>, R)>
|
impl<G, K, R, S: AstarStrategy<G, K, R>> Step<S, (K, Vec<G::NodeId>, R), AstarContinueStatus>
|
||||||
for Astar<G, K>
|
for Astar<G, K>
|
||||||
where
|
where
|
||||||
G: GraphBase,
|
G: GraphBase,
|
||||||
|
|
@ -213,7 +189,10 @@ where
|
||||||
{
|
{
|
||||||
type Error = AstarError;
|
type Error = AstarError;
|
||||||
|
|
||||||
fn step(&mut self, strategy: &mut S) -> Result<AstarStatus<G, K, R>, AstarError> {
|
fn step(
|
||||||
|
&mut self,
|
||||||
|
strategy: &mut S,
|
||||||
|
) -> Result<ControlFlow<(K, Vec<G::NodeId>, R), AstarContinueStatus>, AstarError> {
|
||||||
if let Some(curr_node) = self.maybe_curr_node {
|
if let Some(curr_node) = self.maybe_curr_node {
|
||||||
if self.is_probing {
|
if self.is_probing {
|
||||||
strategy.remove_probe(&self.graph);
|
strategy.remove_probe(&self.graph);
|
||||||
|
|
@ -235,7 +214,7 @@ where
|
||||||
// No need to add neighbors that we have already reached through a
|
// No need to add neighbors that we have already reached through a
|
||||||
// shorter path than now.
|
// shorter path than now.
|
||||||
if *entry.get() <= next_score {
|
if *entry.get() <= next_score {
|
||||||
return Ok(AstarStatus::Probed);
|
return Ok(ControlFlow::Continue(AstarContinueStatus::Probed));
|
||||||
}
|
}
|
||||||
entry.insert(next_score);
|
entry.insert(next_score);
|
||||||
}
|
}
|
||||||
|
|
@ -250,10 +229,10 @@ where
|
||||||
self.visit_next.push(MinScored(next_estimate_score, next));
|
self.visit_next.push(MinScored(next_estimate_score, next));
|
||||||
|
|
||||||
self.is_probing = true;
|
self.is_probing = true;
|
||||||
return Ok(AstarStatus::Probing);
|
return Ok(ControlFlow::Continue(AstarContinueStatus::Probing));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(AstarStatus::Probed);
|
return Ok(ControlFlow::Continue(AstarContinueStatus::Probed));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.maybe_curr_node = None;
|
self.maybe_curr_node = None;
|
||||||
|
|
@ -266,7 +245,7 @@ where
|
||||||
if let Some(result) = strategy.is_goal(&self.graph, node, &self.path_tracker) {
|
if let Some(result) = strategy.is_goal(&self.graph, node, &self.path_tracker) {
|
||||||
let path = self.path_tracker.reconstruct_path_to(node);
|
let path = self.path_tracker.reconstruct_path_to(node);
|
||||||
let cost = self.scores[&node];
|
let cost = self.scores[&node];
|
||||||
return Ok(AstarStatus::Finished(cost, path, result));
|
return Ok(ControlFlow::Break((cost, path, result)));
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.estimate_scores.entry(node) {
|
match self.estimate_scores.entry(node) {
|
||||||
|
|
@ -274,7 +253,7 @@ where
|
||||||
// If the node has already been visited with an equal or lower score than
|
// If the node has already been visited with an equal or lower score than
|
||||||
// now, then we do not need to re-visit it.
|
// now, then we do not need to re-visit it.
|
||||||
if *entry.get() <= estimate_score {
|
if *entry.get() <= estimate_score {
|
||||||
return Ok(AstarStatus::Visited);
|
return Ok(ControlFlow::Continue(AstarContinueStatus::Visited));
|
||||||
}
|
}
|
||||||
entry.insert(estimate_score);
|
entry.insert(estimate_score);
|
||||||
}
|
}
|
||||||
|
|
@ -286,6 +265,6 @@ where
|
||||||
self.maybe_curr_node = Some(node);
|
self.maybe_curr_node = Some(node);
|
||||||
self.edge_ids = self.graph.edges(node).map(|edge| edge.id()).collect();
|
self.edge_ids = self.graph.edges(node).map(|edge| edge.id()).collect();
|
||||||
|
|
||||||
Ok(AstarStatus::Visited)
|
Ok(ControlFlow::Continue(AstarContinueStatus::Visited))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,16 @@
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
drawing::{
|
drawing::{
|
||||||
band::BandTermsegIndex, dot::FixedDotIndex, graph::PrimitiveIndex, rules::AccessRules,
|
band::BandTermsegIndex, dot::FixedDotIndex, graph::PrimitiveIndex, rules::AccessRules,
|
||||||
},
|
},
|
||||||
geometry::primitive::PrimitiveShape,
|
geometry::primitive::PrimitiveShape,
|
||||||
router::{
|
router::{
|
||||||
astar::{Astar, AstarError, AstarStatus},
|
astar::{Astar, AstarError},
|
||||||
navcord::NavcordStepper,
|
navcord::NavcordStepper,
|
||||||
navcorder::Navcorder,
|
navcorder::Navcorder,
|
||||||
navmesh::{Navmesh, NavmeshError},
|
navmesh::{Navmesh, NavmeshError},
|
||||||
Router, RouterAstarStrategy, RouterStatus,
|
Router, RouterAstarStrategy,
|
||||||
},
|
},
|
||||||
stepper::Step,
|
stepper::Step,
|
||||||
};
|
};
|
||||||
|
|
@ -73,19 +75,20 @@ impl RouteStepper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, R: AccessRules> Step<Router<'a, R>, RouterStatus, BandTermsegIndex> for RouteStepper {
|
impl<'a, R: AccessRules> Step<Router<'a, R>, BandTermsegIndex> for RouteStepper {
|
||||||
type Error = AstarError;
|
type Error = AstarError;
|
||||||
|
|
||||||
fn step(&mut self, router: &mut Router<R>) -> Result<RouterStatus, AstarError> {
|
fn step(
|
||||||
|
&mut self,
|
||||||
|
router: &mut Router<R>,
|
||||||
|
) -> Result<ControlFlow<BandTermsegIndex>, AstarError> {
|
||||||
let navcorder = Navcorder::new(router.layout_mut());
|
let navcorder = Navcorder::new(router.layout_mut());
|
||||||
let target = self.astar.graph.destination();
|
let target = self.astar.graph.destination();
|
||||||
let mut strategy = RouterAstarStrategy::new(navcorder, &mut self.navcord, target);
|
let mut strategy = RouterAstarStrategy::new(navcorder, &mut self.navcord, target);
|
||||||
|
|
||||||
let result = match self.astar.step(&mut strategy)? {
|
let result = match self.astar.step(&mut strategy)? {
|
||||||
AstarStatus::Probing | AstarStatus::Probed | AstarStatus::Visited => {
|
ControlFlow::Continue(..) => Ok(ControlFlow::Continue(())),
|
||||||
Ok(RouterStatus::Running)
|
ControlFlow::Break((_cost, _path, band)) => Ok(ControlFlow::Break(band)),
|
||||||
}
|
|
||||||
AstarStatus::Finished(_cost, _path, band) => Ok(RouterStatus::Finished(band)),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.ghosts = strategy.probe_ghosts;
|
self.ghosts = strategy.probe_ghosts;
|
||||||
|
|
|
||||||
|
|
@ -36,22 +36,6 @@ pub struct RouterOptions {
|
||||||
pub squeeze_through_under_bands: bool,
|
pub squeeze_through_under_bands: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum RouterStatus {
|
|
||||||
Running,
|
|
||||||
Finished(BandTermsegIndex),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryInto<BandTermsegIndex> for RouterStatus {
|
|
||||||
type Error = ();
|
|
||||||
fn try_into(self) -> Result<BandTermsegIndex, ()> {
|
|
||||||
match self {
|
|
||||||
RouterStatus::Running => Err(()),
|
|
||||||
RouterStatus::Finished(band_termseg) => Ok(band_termseg),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RouterAstarStrategy<'a, R: AccessRules> {
|
pub struct RouterAstarStrategy<'a, R: AccessRules> {
|
||||||
pub navcorder: Navcorder<'a, R>,
|
pub navcorder: Navcorder<'a, R>,
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
pub trait Step<C, S: TryInto<O>, O> {
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
|
pub trait Step<Ctx, B, C = ()> {
|
||||||
type Error;
|
type Error;
|
||||||
|
|
||||||
fn step(&mut self, context: &mut C) -> Result<S, Self::Error>;
|
fn step(&mut self, context: &mut Ctx) -> Result<ControlFlow<B, C>, Self::Error>;
|
||||||
|
|
||||||
fn finish(&mut self, context: &mut C) -> Result<O, Self::Error> {
|
fn finish(&mut self, context: &mut Ctx) -> Result<B, Self::Error> {
|
||||||
loop {
|
loop {
|
||||||
if let Ok(outcome) = self.step(context)?.try_into() {
|
if let ControlFlow::Break(outcome) = self.step(context)? {
|
||||||
return Ok(outcome);
|
return Ok(outcome);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue