2026-rff_mp/skorohodovsa/task_2/source/view/observer.py
2026-05-25 10:23:00 +03:00

116 lines
4.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Optional
from source.models.base import Maze, Cell
from source.settings import cell_mapping
# ---------------------------------------------------------------------------- #
# События #
# ---------------------------------------------------------------------------- #
@dataclass
class Event:
"""Событие, передаваемое наблюдателям.
Attributes:
type: Тип события ('maze_loaded', 'path_found', 'move', 'no_path').
payload: Дополнительные данные события.
"""
type: str
payload: dict = None
# ---------------------------------------------------------------------------- #
# Интерфейс наблюдателя #
# ---------------------------------------------------------------------------- #
class Observer(ABC):
"""Интерфейс наблюдателя за событиями лабиринта."""
@abstractmethod
def update(self, event: Event) -> None:
"""Обрабатывает входящее событие.
Args:
event: Объект события с типом и данными.
"""
# ---------------------------------------------------------------------------
# Консольный наблюдатель
# ---------------------------------------------------------------------------
class ConsoleView(Observer):
"""Отображает состояние лабиринта и события в консоли."""
# Символ игрока на карте
PLAYER_SYMBOL = "P"
PATH_SYMBOL = "·"
def update(self, event: Event) -> None:
"""Реагирует на события и выводит информацию в консоль.
Args:
event: Объект события.
"""
match event.type:
case "maze_loaded":
print("Лабиринт загружен.")
self.render(event.payload["maze"])
case "path_found":
print(f"Путь найден! Длина: {event.payload['length']} шагов.")
self.render(
event.payload["maze"],
path=event.payload["path"],
)
case "no_path":
print("Путь не найден.")
case "move":
print(f"Ход: {event.payload['direction']}")
self.render(
event.payload["maze"],
player=event.payload["player_cell"],
path=event.payload.get("path"),
)
case _:
print(f"[событие] {event.type}")
def render(
self,
maze: Maze,
player: Optional[Cell] = None,
path: Optional[list[Cell]] = None,
) -> None:
"""Рисует лабиринт в консоли.
Путь отмечается символом '·', позиция игрока — 'P'.
Args:
maze: Объект лабиринта.
player: Текущая клетка игрока (опционально).
path: Список клеток найденного пути (опционально).
"""
path_set = set(path) if path else set()
rows, cols = maze.shape
print("+" + "" * cols + "+")
for y in range(rows):
row_str = "|"
for x in range(cols):
cell = maze[y, x]
if player and cell is player:
row_str += self.PLAYER_SYMBOL
elif cell in path_set:
row_str += self.PATH_SYMBOL
else:
row_str += str(cell)
row_str += "|"
print(row_str)
print("+" + "" * cols + "+")