# 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
```bash
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
```bash
uv run pytest tests/unit/ -v           # All unit tests (836 passing)
uv run python -m terminal_client       # Interactive REPL
```

### Code Quality
```bash
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):
```python
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:

```bash
# 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
```bash
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**: 836 passing | **Phase**: 3E-Final Complete | **Updated**: 2025-01-27
