refactor: разделение кода в session_view.py

This commit is contained in:
2026-08-14 02:42:18 +03:00
parent c657415bf0
commit e3f5828334
5 changed files with 290 additions and 311 deletions
+25 -307
View File
@@ -1,280 +1,12 @@
import sys
from dataclasses import dataclass
from enum import Enum, auto
from typing import Callable, Optional
import wx
from wx.lib.pubsub import pub
def enable_high_dpi_support():
if sys.platform == "win32":
try:
import ctypes
ctypes.windll.shcore.SetProcessDpiAwareness(2)
except Exception:
try:
import ctypes
ctypes.windll.user32.SetProcessDPIAware()
except Exception:
pass
class CardState(Enum):
SETTER_NOT_SET = auto()
SETTER_HIDDEN = auto()
SETTER_REVEALED = auto()
GUESSER_DISABLED = auto()
GUESSER_WAITING = auto()
GUESSER_CORRECT = auto()
GUESSER_WRONG = auto()
class ArrowDirection(Enum):
LEFT = auto()
RIGHT = auto()
@dataclass
class SessionStats:
total: int
setted: int
correct: int
wrong: int
taken_time: float
@property
def accuracy(self) -> float:
accuracy: float
if self.total == 0:
accuracy = 0.0
accuracy = (self.correct / self.total) * 100
return round(accuracy, 1)
class StepState(Enum):
WAITING_FOR_SETTER = auto()
WAITING_FOR_GUESSER = auto()
SESSION_FINISHED = auto()
class PlayerRole(Enum):
SETTER = auto()
GUESSER = auto()
@dataclass(frozen=True)
class MoveResult:
step_index: int
setter_direction: ArrowDirection
setter_card_state: CardState
guesser_direction: Optional[ArrowDirection] = None
guesser_card_state: Optional[CardState] = None
@dataclass(frozen=True)
class CardData:
direction: Optional[ArrowDirection]
state: CardState
@dataclass(frozen=True)
class StepData:
index: int
setter: CardData
guesser: CardData
@dataclass
class Player:
name: str
role: PlayerRole
class SessionState:
def __init__(
self,
local_player: Player,
remote_player: Player,
sequence_length: int = 20,
):
self._local_player = local_player
self._remote_player = remote_player
self._sequence_length = sequence_length
self._setter_moves: list[ArrowDirection] = []
self._guesser_moves: list[ArrowDirection] = []
self._step_state: StepState = StepState.WAITING_FOR_SETTER
@property
def _completed_move_count(self):
return len(self._guesser_moves)
def _get_setter_card_state(self, index: int) -> CardState:
current_index = len(self._setter_moves)
if index > current_index:
return CardState.SETTER_NOT_SET
elif index == current_index:
if self._step_state == StepState.WAITING_FOR_GUESSER:
if self._local_player.role == PlayerRole.SETTER:
return CardState.SETTER_REVEALED
else:
return CardState.SETTER_HIDDEN
return CardState.SETTER_REVEALED
def _get_guesser_card_state(self, index: int) -> CardState:
completed_move_count = self._completed_move_count
if index > completed_move_count:
return CardState.GUESSER_DISABLED
elif index == completed_move_count:
if self._step_state == StepState.WAITING_FOR_GUESSER:
return CardState.GUESSER_WAITING
else:
return CardState.GUESSER_DISABLED
else:
setter_move = self._setter_moves[index]
guesser_move = self._guesser_moves[index]
if setter_move == guesser_move:
return CardState.GUESSER_CORRECT
else:
return CardState.GUESSER_WRONG
def start_session(self) -> None:
index = 0
pub.sendMessage(
"session.session_started",
step=StepData(
index=index,
setter=CardData(
direction=None,
state=self._get_setter_card_state(index),
),
guesser=CardData(
direction=None,
state=self._get_guesser_card_state(index),
),
),
)
def setter_move(self, direction: ArrowDirection) -> bool:
if self._step_state != StepState.WAITING_FOR_SETTER:
return False
self._setter_moves.append(direction)
self._step_state = StepState.WAITING_FOR_GUESSER
index = len(self._setter_moves) - 1
pub.sendMessage(
"session.setter_moved",
step=StepData(
index=index,
setter=CardData(
direction=direction,
state=self._get_setter_card_state(index),
),
guesser=CardData(
direction=direction,
state=self._get_guesser_card_state(index),
),
),
)
return True
def guesser_move(self, direction: ArrowDirection) -> bool:
if self._step_state != StepState.WAITING_FOR_GUESSER:
return False
self._guesser_moves.append(direction)
if self._completed_move_count < self._sequence_length:
self._step_state = StepState.WAITING_FOR_SETTER
else:
self._step_state = StepState.SESSION_FINISHED
index = len(self._guesser_moves) - 1
pub.sendMessage(
"session.guesser_moved",
step=StepData(
index=index,
setter=CardData(
direction=self._setter_moves[index],
state=self._get_setter_card_state(index),
),
guesser=CardData(
direction=self._guesser_moves[index],
state=self._get_guesser_card_state(index),
),
),
)
next = index + 1
pub.sendMessage(
"session.step_closed",
step=StepData(
index=next,
setter=CardData(
direction=None,
state=self._get_setter_card_state(next),
),
guesser=CardData(
direction=None,
state=self._get_guesser_card_state(next),
),
),
)
if self._step_state == StepState.SESSION_FINISHED:
pub.sendMessage("session.session_finished")
return True
def local_move(self, direction: ArrowDirection) -> bool:
if not self.can_local_move():
return False
if self._local_player.role == PlayerRole.SETTER:
return self.setter_move(direction)
else:
return self.guesser_move(direction)
def can_local_move(self) -> bool:
match self._step_state:
case StepState.WAITING_FOR_SETTER:
return self._local_player.role == PlayerRole.SETTER
case StepState.WAITING_FOR_GUESSER:
return self._local_player.role == PlayerRole.GUESSER
case StepState.SESSION_FINISHED:
return False
@property
def setter_name(self) -> str:
if self._local_player.role == PlayerRole.SETTER:
return self._local_player.name
else:
return self._remote_player.name
@property
def guesser_name(self) -> str:
if self._local_player.role == PlayerRole.GUESSER:
return self._local_player.name
else:
return self._remote_player.name
@property
def sequence_length(self) -> int:
return self._sequence_length
from mind_reader.domain import ArrowDirection, CardState, SessionStats, StepData
from mind_reader.state import SessionState
@dataclass(frozen=True)
@@ -379,19 +111,20 @@ class Card(wx.Panel):
class SessionPanel(wx.Panel):
def __init__(self, parent, state: SessionState):
def __init__(
self, parent, setter_name: str, guesser_name: str, sequence_length: int
):
super().__init__(parent)
self._state = state
self._setter_name = self._state.setter_name
self._guesser_name = self._state.guesser_name
self._sequence_length = self._state.sequence_length
self._setter_name = setter_name
self._guesser_name = guesser_name
self._sequence_length = sequence_length
self._setter_sequence: list[Card] = []
self._guesser_sequence: list[Card] = []
self._statusbar = self._get_statusbar()
self._setup_statusbar()
self._setup()
self._fit_parent_frame()
@@ -491,6 +224,22 @@ class SessionPanel(wx.Panel):
return None
def _setup_statusbar(self) -> None:
if not self._statusbar:
return
message = " Ожидание начала игры... "
progress = f" Прогресс 0/{self._sequence_length} "
accuracy = " Точность 0.0% (0/0) "
taken_time = " Время 00:00 "
self._statusbar.SetStatusText(message, 0)
self._statusbar.SetStatusText(progress, 1)
self._statusbar.SetStatusText(accuracy, 2)
self._statusbar.SetStatusText(taken_time, 3)
self._autofit_statusbar([progress, accuracy, message])
def _autofit_statusbar(self, texts: list[str]) -> None:
if not self._statusbar:
return
@@ -616,34 +365,3 @@ class SessionPanel(wx.Panel):
self._statusbar.SetStatusText(taken_time, 3)
self._autofit_statusbar([progress, accuracy, taken_time])
class TestFrame(wx.Frame):
def __init__(self):
super().__init__(None, title="TestFrame")
local = Player("Бывалый", PlayerRole.SETTER)
remote = Player("Балбес", PlayerRole.GUESSER)
session = SessionState(local, remote)
main_panel = SessionPanel(self, session)
main_sizer = wx.BoxSizer(wx.VERTICAL)
main_sizer.Add(main_panel, 1, wx.EXPAND)
self.SetSizer(main_sizer)
s = SessionStats(20, 1, 0, 1, 5.1)
main_panel.update_statusbar(None, s)
session.start_session()
session.setter_move(ArrowDirection.LEFT)
session.guesser_move(ArrowDirection.LEFT)
session.setter_move(ArrowDirection.LEFT)
session.guesser_move(ArrowDirection.RIGHT)
if __name__ == "__main__":
enable_high_dpi_support()
app = wx.App()
frame = TestFrame()
frame.Show()
app.MainLoop()