strat-gameplay-webapp/backend/CLAUDE.md
Cal Corum 529c5b1b99 CLAUDE: Implement uncapped hit interactive decision tree (Issue #6)
Add full multi-step decision workflow for SINGLE_UNCAPPED and DOUBLE_UNCAPPED
outcomes, replacing the previous stub that fell through to basic single/double
advancement. The decision tree follows the same interactive pattern as X-Check
resolution with 5 phases: lead runner advance, defensive throw, trail runner
advance, throw target selection, and safe/out speed check.

- game_models.py: PendingUncappedHit model, 5 new decision phases
- game_engine.py: initiate_uncapped_hit(), 5 submit methods, 3 result builders
- handlers.py: 5 new WebSocket event handlers
- ai_opponent.py: 5 AI decision stubs (conservative defaults)
- play_resolver.py: Updated TODO comments for fallback paths
- 80 new backend tests (2481 total): workflow (49), handlers (23), truth tables (8)
- Fix GameplayPanel.spec.ts: add missing Pinia setup, fix component references

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 09:33:58 -06:00

4.6 KiB

Backend - Paper Dynasty Game Engine

Overview

FastAPI-based real-time game backend handling WebSocket communication, game state management, and database persistence for both SBA and PD leagues.

Tech Stack: FastAPI (Python 3.13), Socket.io, PostgreSQL 14+, SQLAlchemy 2.0, Pydantic v2, pytest

Project Structure

backend/
├── app/
│   ├── main.py           # FastAPI + Socket.io init
│   ├── config.py         # pydantic-settings
│   ├── core/             # Game engine - see core/CLAUDE.md
│   ├── config/           # League configs - see config/CLAUDE.md
│   ├── models/           # Pydantic + SQLAlchemy - see models/CLAUDE.md
│   ├── websocket/        # Socket.io handlers - see websocket/CLAUDE.md
│   ├── api/              # REST endpoints - see api/CLAUDE.md
│   ├── database/         # Async persistence - see database/CLAUDE.md
│   ├── services/         # Business logic (LineupService, PD API client)
│   └── utils/            # Logging, auth - see utils/CLAUDE.md
├── tests/                # See tests/CLAUDE.md
├── terminal_client/      # Interactive testing - see terminal_client/CLAUDE.md
└── logs/                 # Daily rotating logs (gitignored)

Development

Quick Start

cd backend
uv sync                    # Install dependencies
uv run alembic upgrade head # Apply database migrations
uv run python -m app.main  # Start server at localhost:8000

Testing

uv run pytest tests/unit/ -v           # All unit tests (2481 passing)
uv run python -m terminal_client       # Interactive REPL

Code Quality

uv run mypy app/           # Type checking
uv run ruff check app/     # Linting
uv run ruff format app/    # Formatting

Key Patterns

Hybrid State Management

  • In-memory: Active game states for <500ms response
  • PostgreSQL: Persistent storage for recovery
  • Pattern: Write-through cache (update memory + async DB write)

League-Agnostic Core

  • Game engine works for any league
  • Config-driven behavior (SbaConfig, PdConfig)
  • Polymorphic player models (BasePlayer → SbaPlayer, PdPlayer)

DateTime

Always use Pendulum (never Python's datetime):

import pendulum
now = pendulum.now('UTC')

Environment

Database

  • Server: PostgreSQL at 10.10.0.42:5432
  • Database: paperdynasty_dev
  • Connection: postgresql+asyncpg://...

Environment Variables

Copy .env.example to .env and configure. Key variables:

# Required
DATABASE_URL=postgresql+asyncpg://user:pass@host:5432/db
SECRET_KEY=your-secret-key-min-32-chars
DISCORD_CLIENT_ID=your-discord-client-id
DISCORD_CLIENT_SECRET=your-discord-client-secret

# OAuth URLs (update for your domain)
DISCORD_REDIRECT_URI=http://localhost:3000/auth/callback
DISCORD_SERVER_REDIRECT_URI=http://localhost:8000/api/auth/discord/callback/server
FRONTEND_URL=http://localhost:3000

# Access Control
ALLOWED_DISCORD_IDS=  # Comma-separated user IDs, empty = all users

# CORS (JSON array format)
CORS_ORIGINS=["http://localhost:3000","http://localhost:3001"]

# League APIs
SBA_API_URL=https://api.sba.manticorum.com
SBA_API_KEY=your-sba-api-key
PD_API_URL=https://pd-api.example.com
PD_API_KEY=your-pd-api-key

Multi-Domain Deployment: When deploying to a new domain, update FRONTEND_URL, DISCORD_*_REDIRECT_URI, and CORS_ORIGINS. See root README.md for full checklist.

Python Environment

  • Version: Python 3.13.3
  • Package Manager: UV (fast, reliable)
  • Virtual Environment: backend/.venv/

Testing Policy

REQUIRED: 100% unit tests passing before any commit

uv run pytest tests/unit/ -q  # Must show all passing

Coding Standards

  • Formatting: Ruff (88 chars, black-compatible)
  • Linting: Ruff (replaces flake8, includes isort, pyupgrade)
  • Type Hints: Required for public functions
  • Logging: logger = logging.getLogger(f'{__name__}.ClassName')
  • Error Handling: "Raise or Return" - no silent failures

Performance Targets

Metric Target
Action response < 500ms
WebSocket delivery < 200ms
DB writes < 100ms (async)
State recovery < 2 seconds

References

  • WebSocket Protocol Spec: ../.claude/WEBSOCKET_PROTOCOL_SPEC.md - Complete event catalog and workflow
  • Type Checking Guide: .claude/type-checking-guide.md
  • Code Review: .claude/CODE_REVIEW_GAME_ENGINE.md
  • Implementation Plans: ../.claude/implementation/
  • Full PRD: ../prd-web-scorecard-1.1.md

Tests: 2481 passing | Phase: 3E-Final Complete | Updated: 2026-02-11