forked from UNN/2026-rff_mp
58 lines
1.7 KiB
Python
58 lines
1.7 KiB
Python
from __future__ import annotations
|
|
|
|
import time
|
|
from dataclasses import dataclass
|
|
|
|
from .models import Cell, Maze
|
|
from .observers import Event, Observer
|
|
from .strategies import PathFindingStrategy
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class SearchStats:
|
|
strategy_name: str
|
|
time_ms: float
|
|
visited_cells: int
|
|
path_length: int
|
|
path: list[Cell]
|
|
|
|
|
|
class MazeSolver:
|
|
def __init__(self, maze: Maze, strategy: PathFindingStrategy) -> None:
|
|
self.maze = maze
|
|
self.strategy = strategy
|
|
self._observers: list[Observer] = []
|
|
|
|
def set_strategy(self, strategy: PathFindingStrategy) -> None:
|
|
self.strategy = strategy
|
|
|
|
def setStrategy(self, strategy: PathFindingStrategy) -> None:
|
|
self.set_strategy(strategy)
|
|
|
|
def add_observer(self, observer: Observer) -> None:
|
|
self._observers.append(observer)
|
|
|
|
def remove_observer(self, observer: Observer) -> None:
|
|
self._observers.remove(observer)
|
|
|
|
def solve(self) -> SearchStats:
|
|
self._notify(Event("search_started", {"strategy": self.strategy.name}))
|
|
started_at = time.perf_counter()
|
|
result = self.strategy.find_path(self.maze, self.maze.start, self.maze.exit)
|
|
elapsed_ms = (time.perf_counter() - started_at) * 1000
|
|
|
|
stats = SearchStats(
|
|
strategy_name=self.strategy.name,
|
|
time_ms=elapsed_ms,
|
|
visited_cells=result.visited_count,
|
|
path_length=len(result.path),
|
|
path=result.path,
|
|
)
|
|
event_name = "path_found" if result.path else "path_not_found"
|
|
self._notify(Event(event_name, {"stats": stats}))
|
|
return stats
|
|
|
|
def _notify(self, event: Event) -> None:
|
|
for observer in self._observers:
|
|
observer.update(event)
|