quarto_gen/quarto/server/protocol.py
2026-02-13 20:40:40 +01:00

73 lines
1.8 KiB
Python

from __future__ import annotations
from dataclasses import dataclass
from typing import Optional, Union
@dataclass
class ClientHello:
description: str
class ClientQueue:
pass
@dataclass
class ClientMove:
square: Optional[int] # None for initial move MOVE~M
m_value: int # 0-17
@dataclass
class UnknownCommand:
raw: str
ClientCommand = Union[ClientHello, ClientQueue, ClientMove, UnknownCommand]
def parse_client_line(line: str) -> ClientCommand:
parts = line.strip().split("~")
if not parts:
return UnknownCommand(raw=line)
cmd = parts[0]
if cmd == "HELLO" and len(parts) == 2:
return ClientHello(description=parts[1])
if cmd == "QUEUE" and len(parts) == 1:
return ClientQueue()
if cmd == "MOVE":
if len(parts) == 2:
try:
m_value = int(parts[1])
except ValueError:
return UnknownCommand(raw=line)
return ClientMove(square=None, m_value=m_value)
if len(parts) == 3:
try:
square = int(parts[1])
m_value = int(parts[2])
except ValueError:
return UnknownCommand(raw=line)
return ClientMove(square=square, m_value=m_value)
return UnknownCommand(raw=line)
def format_hello(description: str) -> str:
return f"HELLO~{description}"
def format_newgame(player1: str, player2: str) -> str:
return f"NEWGAME~{player1}~{player2}"
def format_move_broadcast(square: Optional[int], m_value: int) -> str:
if square is None:
return f"MOVE~{m_value}"
return f"MOVE~{square}~{m_value}"
def format_gameover(reason: str, winner: Optional[str]) -> str:
if winner is None:
return f"GAMEOVER~{reason}"
return f"GAMEOVER~{reason}~{winner}"