wip: без комментариев
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
from ..lobby.domain import Player, PlayerRole
|
||||
from ..session.domain import ArrowDirection, CardState, SessionPhase
|
||||
from ..session.events import (
|
||||
GuesserMoveEvent,
|
||||
NextStepRequestedEvent,
|
||||
PlayerHelloEvent,
|
||||
RevealSecretEvent,
|
||||
SessionEvent,
|
||||
SetterMoveEvent,
|
||||
)
|
||||
|
||||
|
||||
class SessionStateMachine:
|
||||
def __init__(
|
||||
self, setter: Player, guessers: set[Player], sequence_length: int = 20
|
||||
):
|
||||
self._setter = setter
|
||||
self._guessers = guessers
|
||||
|
||||
self._pending_players: set[Player] = set(guessers)
|
||||
self._pending_players.add(setter)
|
||||
|
||||
self._sequence_length = sequence_length
|
||||
self._setter_moves: list[ArrowDirection] = []
|
||||
self._guessers_moves: dict[Player, list[ArrowDirection]] = {
|
||||
player: [] for player in guessers
|
||||
}
|
||||
|
||||
self._phase: SessionPhase = SessionPhase.INITIALIZING
|
||||
|
||||
def process(self, event: SessionEvent) -> bool:
|
||||
match (self._phase, event):
|
||||
case (SessionPhase.INITIALIZING, PlayerHelloEvent(player)):
|
||||
self._pending_players.remove(player)
|
||||
if not self._pending_players:
|
||||
self._phase = SessionPhase.WAITING_FOR_SETTER
|
||||
self._pending_players = {self._setter}
|
||||
return True
|
||||
|
||||
case (
|
||||
SessionPhase.WAITING_FOR_SETTER,
|
||||
SetterMoveEvent(player, direction),
|
||||
):
|
||||
self._pending_players.remove(player)
|
||||
if not self._pending_players:
|
||||
self._setter_moves.append(direction)
|
||||
self._phase = SessionPhase.WAITING_FOR_GUESSER
|
||||
self._pending_players = set(self._guessers)
|
||||
return True
|
||||
|
||||
case (
|
||||
SessionPhase.WAITING_FOR_GUESSER,
|
||||
GuesserMoveEvent(player, direction),
|
||||
):
|
||||
self._guessers_moves[player].append(direction)
|
||||
self._pending_players.remove(player)
|
||||
if not self._pending_players:
|
||||
self._phase = SessionPhase.WAITING_FOR_REVEAL
|
||||
self._pending_players = {self._setter}
|
||||
return True
|
||||
|
||||
case (
|
||||
SessionPhase.WAITING_FOR_REVEAL,
|
||||
RevealSecretEvent(player, direction),
|
||||
):
|
||||
self._pending_players.remove(player)
|
||||
if not self._pending_players:
|
||||
self._phase = SessionPhase.CHECKOUT
|
||||
setter_move_index = len(self._setter_moves) - 1
|
||||
self._setter_moves[setter_move_index] = direction
|
||||
self._pending_players = set(self._guessers)
|
||||
return True
|
||||
|
||||
case (SessionPhase.CHECKOUT, NextStepRequestedEvent(player)):
|
||||
self._pending_players.remove(player)
|
||||
if not self._pending_players:
|
||||
if len(self._setter_moves) >= self._sequence_length:
|
||||
self._phase = SessionPhase.FINISHED
|
||||
self._pending_players.clear()
|
||||
else:
|
||||
self._phase = SessionPhase.WAITING_FOR_SETTER
|
||||
self._pending_players = {self._setter}
|
||||
return True
|
||||
|
||||
case _:
|
||||
return False
|
||||
|
||||
def get_card_state(self, player: Player, index: int) -> CardState:
|
||||
match player.role:
|
||||
case PlayerRole.SETTER:
|
||||
return self._get_setter_card_state(index)
|
||||
case PlayerRole.GUESSER:
|
||||
return self._get_guesser_card_state(player, index)
|
||||
|
||||
def _get_setter_card_state(self, index: int) -> CardState:
|
||||
current_index = self.get_setter_step_number() - 1
|
||||
|
||||
if index > current_index:
|
||||
return CardState.SETTER_NOT_SET
|
||||
|
||||
elif index == current_index:
|
||||
match self._phase:
|
||||
case SessionPhase.INITIALIZING:
|
||||
return CardState.SETTER_NOT_SET
|
||||
case SessionPhase.WAITING_FOR_SETTER:
|
||||
return CardState.SETTER_WAITING
|
||||
case (
|
||||
SessionPhase.WAITING_FOR_GUESSER
|
||||
| SessionPhase.WAITING_FOR_REVEAL
|
||||
):
|
||||
if self._setter_moves[-1] == ArrowDirection.HIDDEN:
|
||||
return CardState.SETTER_HIDDEN
|
||||
else:
|
||||
return CardState.SETTER_REVEALED
|
||||
case SessionPhase.CHECKOUT | SessionPhase.FINISHED:
|
||||
return CardState.SETTER_REVEALED
|
||||
|
||||
else:
|
||||
return CardState.SETTER_REVEALED
|
||||
|
||||
def _get_guesser_card_state(self, player: Player, index: int) -> CardState:
|
||||
def _check_direction(
|
||||
self: SessionStateMachine, player: Player, index: int
|
||||
) -> CardState:
|
||||
if self._setter_moves[index] == self._guessers_moves[player][index]:
|
||||
return CardState.GUESSER_CORRECT
|
||||
else:
|
||||
return CardState.GUESSER_WRONG
|
||||
|
||||
current_index = self.get_guesser_step_number(player) - 1
|
||||
|
||||
if index > current_index:
|
||||
return CardState.GUESSER_DISABLED
|
||||
|
||||
elif index == current_index:
|
||||
match self._phase:
|
||||
case (
|
||||
SessionPhase.INITIALIZING | SessionPhase.WAITING_FOR_SETTER
|
||||
):
|
||||
return CardState.GUESSER_DISABLED
|
||||
case (
|
||||
SessionPhase.WAITING_FOR_GUESSER
|
||||
| SessionPhase.WAITING_FOR_REVEAL
|
||||
):
|
||||
return CardState.GUESSER_WAITING
|
||||
case SessionPhase.CHECKOUT | SessionPhase.FINISHED:
|
||||
return _check_direction(self, player, index)
|
||||
|
||||
else:
|
||||
return _check_direction(self, player, index)
|
||||
|
||||
def _get_step_number(self, enum) -> int:
|
||||
return len(enum)
|
||||
|
||||
def get_setter_step_number(self) -> int:
|
||||
return self._get_step_number(self._setter_moves)
|
||||
|
||||
def get_guesser_step_number(self, player: Player) -> int:
|
||||
return self._get_step_number(self._guessers_moves[player])
|
||||
|
||||
def get_setter_move(self, index: int) -> ArrowDirection | None:
|
||||
try:
|
||||
return self._setter_moves[index]
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
def get_guesser_move(
|
||||
self, player: Player, index: int
|
||||
) -> ArrowDirection | None:
|
||||
try:
|
||||
return self._guessers_moves[player][index]
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
def get_last_setter_move(self) -> ArrowDirection | None:
|
||||
index = self.get_setter_step_number() - 1
|
||||
return self.get_setter_move(index)
|
||||
|
||||
def get_last_guesser_move(self, player: Player) -> ArrowDirection | None:
|
||||
index = self.get_guesser_step_number(player) - 1
|
||||
return self.get_guesser_move(player, index)
|
||||
Reference in New Issue
Block a user