Add spin session functionality and update game mechanics

- Introduced a new `spin_sessions` table to track user spin activities.
- Updated the API to include a new endpoint for spinning games, allowing users to place bets and specify spin counts.
- Enhanced game information structure and added validation for bets and spin counts.
- Implemented the `Forest Fortune` slot game mechanics, including payline evaluation and scatter functionality.
- Updated dependencies in `pyproject.toml` for development and added `httpx` for HTTP requests.
- Added unit tests for the new slot mechanics and API endpoints to ensure functionality and reliability.
This commit is contained in:
Redsandy
2026-08-12 15:27:24 +03:00
parent c9f66f330e
commit 5125b52583
18 changed files with 1023 additions and 32 deletions

96
app/slots/types.py Normal file
View File

@@ -0,0 +1,96 @@
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
],
}