from __future__ import annotations from dataclasses import dataclass, field from decimal import Decimal from typing import Any # grid[reel][row], reel 0..4, row 0..4 (0 = top) Grid = list[list[str]] @dataclass class PaylineWin: line_index: int symbol: str count: int amount: Decimal path: list[int] @dataclass class SpinOutcome: grid: Grid line_wins: list[PaylineWin] scatter_count: int scatter_win: Decimal total_win: Decimal meta_triggered: bool @dataclass class SessionMetaState: level: int = 1 multiplier: int = 1 triggered: bool = False def after_trigger(self) -> SessionMetaState: level = self.level + 1 return SessionMetaState(level=level, multiplier=level, triggered=True) @dataclass class SpinResult: index: int grid: Grid line_wins: list[PaylineWin] scatter_count: int scatter_win: Decimal total_win: Decimal level: int multiplier: int meta_triggered: bool @dataclass class SessionResult: bet: Decimal spin_count: int total_bet: Decimal total_win: Decimal max_level: int trigger_count: int spins: list[SpinResult] = field(default_factory=list) def to_payload(self) -> dict[str, Any]: return { "bet": str(self.bet), "spin_count": self.spin_count, "total_bet": str(self.total_bet), "total_win": str(self.total_win), "max_level": self.max_level, "trigger_count": self.trigger_count, "spins": [ { "index": s.index, "grid": s.grid, "line_wins": [ { "line_index": w.line_index, "symbol": w.symbol, "count": w.count, "amount": str(w.amount), "path": w.path, } for w in s.line_wins ], "scatter_count": s.scatter_count, "scatter_win": str(s.scatter_win), "total_win": str(s.total_win), "level": s.level, "multiplier": s.multiplier, "meta_triggered": s.meta_triggered, } for s in self.spins ], }