// SPDX-FileCopyrightText: 2025 Topola contributors // // SPDX-License-Identifier: MIT use std::ops::ControlFlow; use specctra_core::mesadata::AccessMesadata; use crate::{ autorouter::{ autoroute::{AutorouteContinueStatus, AutorouteExecutionStepper}, invoker::GetDebugOverlayData, permuter::{PermuteRatlines, RatlinesPermuter, SccPermutationsRatlinePermuter}, ratline::RatlineIndex, Autorouter, AutorouterError, AutorouterOptions, }, board::edit::BoardEdit, drawing::graph::PrimitiveIndex, geometry::primitive::PrimitiveShape, router::{navcord::Navcord, navmesh::Navmesh, thetastar::ThetastarStepper}, stepper::{Abort, EstimateProgress, Permutate, Step}, }; pub struct AutorouteExecutionPermutator { stepper: AutorouteExecutionStepper, permuter: RatlinesPermuter, options: AutorouterOptions, } impl AutorouteExecutionPermutator { pub fn new( autorouter: &mut Autorouter, ratlines: Vec, options: AutorouterOptions, ) -> Result { let mut permuter = RatlinesPermuter::SccPermutations(SccPermutationsRatlinePermuter::new( autorouter, ratlines, &options, )); let initially_sorted_ratlines = permuter.next_ratlines_permutation(autorouter).unwrap(); Ok(Self { stepper: AutorouteExecutionStepper::new( autorouter, initially_sorted_ratlines, options, )?, // Note: I assume here that the first permutation is the same as the original order. permuter, options, }) } } impl Step, Option, AutorouteContinueStatus> for AutorouteExecutionPermutator { type Error = AutorouterError; fn step( &mut self, autorouter: &mut Autorouter, ) -> Result, AutorouteContinueStatus>, AutorouterError> { match self.stepper.step(autorouter) { Ok(ok) => Ok(ok), Err(err) => { if !self.options.permutate { return Err(err); } loop { let Some(permutation) = self.permuter.next_ratlines_permutation(autorouter) else { return Ok(ControlFlow::Break(None)); }; match self.stepper.permutate(autorouter, permutation) { Ok(()) => break, Err(AutorouterError::NothingToUndoForPermutation) => continue, Err(err) => return Err(err), } } self.stepper.step(autorouter) } } } } impl Abort> for AutorouteExecutionPermutator { fn abort(&mut self, autorouter: &mut Autorouter) { //self.permutations_iter.all(|_| true); // Why did I add this code here??? self.stepper.abort(autorouter); } } impl EstimateProgress for AutorouteExecutionPermutator { type Value = f64; fn estimate_progress_value(&self) -> f64 { // TODO. self.stepper.estimate_progress_value() } fn estimate_progress_maximum(&self) -> f64 { // TODO. self.stepper.estimate_progress_maximum() } } impl GetDebugOverlayData for AutorouteExecutionPermutator { fn maybe_thetastar(&self) -> Option<&ThetastarStepper> { self.stepper.maybe_thetastar() } fn maybe_navcord(&self) -> Option<&Navcord> { self.stepper.maybe_navcord() } fn ghosts(&self) -> &[PrimitiveShape] { self.stepper.ghosts() } fn obstacles(&self) -> &[PrimitiveIndex] { self.stepper.obstacles() } }