Files
akadmin fc6b87515e docs: update documentation for rules engine integration
- HANDOFF.md: Added rules engine section, updated architecture diagram
- state.json: Updated project summary, files_created, files_modified, commit_hash
- README.md: Added rules engine to features and architecture
- ROADMAP.md: Added MTG Rules Engine Integration section (2.10)
2026-07-25 21:25:53 +00:00

220 lines
8.3 KiB
Markdown

# MTG Online Backend
A Python FastAPI application that processes Magic: The Gathering card data from [MTGJSON](https://mtgjson.com/) and stores it in PostgreSQL, with Redis for caching.
## Overview
This project provides a backend API for a Magic: The Gathering Online platform. It downloads and processes MTGJSON v5 dataset dumps, loads them into a PostgreSQL database, and exposes REST endpoints for card data, user authentication, deck management, and game state.
### Key Features
- **MTGJSON Data Pipeline** — Downloads `AllPrintings.psql`, `AllIdentifiers.json`, `Keywords.json`, `CardTypes.json`, and `AllDeckFiles.zip` from MTGJSON v5 on startup or via a `POST /refresh` endpoint.
- **Dual PostgreSQL** — Two databases: `mtgonline` for the application (users, decks, auth) and `mtgdata` for MTG card data.
- **Redis Caching** — Used for card lookup caching and interaction pipeline state.
- **Card Import Feature** — Users can import their card collection (fuzzy matching enabled) for deckbuilding constraints.
- **Deck Management** — Full deck CRUD with precedents, suggestions, and status tracking (DRAFT/FINAL).
- **MTG Rules Engine** — Integrated in `backend/mtg_rules_engine/` for multiplayer game server (rules enforcement, card validation, keyword processing).
- **REST API** — `/docs` (Swagger) available at runtime.
## Architecture
```
mtgonline/
├── backend/ # FastAPI application
│ ├── mtg_rules_engine/ # MTG rules engine (rules enforcement for multiplayer)
│ │ ├── engine.py # Core game engine
│ │ ├── rules_engine.py # Rules engine core
│ │ ├── keywords.py # Card keywords
│ │ ├── keywords_db.py # Keywords database
│ │ ├── keyword_validator.py # Keyword validation
│ │ ├── validator.py # Card validation
│ │ ├── updater.py # Engine updater
│ │ ├── update_check.py # Update checker
│ │ ├── test_engine.py # Engine tests
│ │ └── README.md # Rules engine docs
│ ├── app/
│ │ ├── core/ # Settings, database engines, Redis client
│ │ ├── models/ # SQLAlchemy ORM models (app + MTG)
│ │ ├── routers/ # API route modules
│ │ ├── schemas/ # Pydantic request/response schemas
│ │ ├── services/ # Business logic (MTGJSON manager, card DB, game server)
│ │ └── main.py # FastAPI app entry point
│ ├── scripts/ # Utility scripts (downloads, migrations, checks)
│ ├── Dockerfile
│ └── requirements.txt
├── docker-compose.dev.yml # Development stack (Postgres x2, Redis, Backend)
├── docker-compose.yml # Production stack
├── scripts/ # Shared utility scripts
└── README.md
```
### Data Flow
1. **On startup**, the backend connects to PostgreSQL (both instances) and Redis.
2. It checks `mtg_refresh_log` in the `mtgdata` database for existing data.
3. If no data exists, it downloads MTGJSON files from `https://mtgjson.com/api/v5/`, unzips if needed, and upserts them into `mtgdata` tables (`mtg_sets`, `mtg_cards`, etc.).
4. The data is then available via REST endpoints.
## API Endpoints
### Card Import (`/api/v1/card-import/`)
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/v1/card-import/status` | Get current card import status |
| `POST` | `/api/v1/card-import/` | Import/update card collection |
| `DELETE` | `/api/v1/card-import/` | Delete card import |
| `GET` | `/api/v1/card-import/summary` | Get import summary with match results |
**Card Import Request Body:**
```json
{
"card_names": ["Lightning Bolt", "Shock", "Thoughtseize"]
}
```
**Card Import Response:**
```json
{
"message": "Imported 3 cards successfully",
"card_count": 3,
"card_names": ["Lightning Bolt", "Shock", "Thoughtseize"],
"imported_at": "2026-07-24T04:12:00"
}
```
### User Data Endpoints (`/api/v1/user-data/`)
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/v1/user-data/profile` | Get user profile |
| `PUT` | `/api/v1/user-data/profile` | Update user profile |
| `GET` | `/api/v1/user-data/collection` | Get user card collection |
| `GET` | `/api/v1/user-data/groups` | List user groups |
| `GET` | `/api/v1/user-data/networks` | List user networks |
| `GET` | `/api/v1/user-data/preferences` | Get user preferences |
| `PUT` | `/api/v1/user-data/preferences` | Update user preferences |
| `GET` | `/api/v1/user-data/activity` | Get user activity log |
| `GET` | `/api/v1/user-data/replays` | List user replays |
| `GET` | `/api/v1/user-data/replays/{replay_id}` | Get replay details |
### Deck Management Endpoints
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/v1/decks/` | List user decks |
| `POST` | `/api/v1/decks/` | Create new deck |
| `GET` | `/api/v1/decks/{deck_id}` | Get deck details |
| `PUT` | `/api/v1/decks/{deck_id}` | Update deck |
| `DELETE` | `/api/v1/decks/{deck_id}` | Delete deck |
| `POST` | `/api/v1/decks/{deck_id}/cards` | Add card to deck |
| `PUT` | `/api/v1/decks/{deck_id}/cards/{card_id}` | Update deck card |
| `DELETE` | `/api/v1/decks/{deck_id}/cards/{card_id}` | Remove card from deck |
| `GET` | `/api/v1/decks/{deck_id}/cards` | List deck cards |
| `POST` | `/api/v1/decks/{deck_id}/finalize` | Finalize deck (DRAFT → FINAL) |
| `POST` | `/api/v1/decks/search/cards` | Search cards for deckbuilding |
| `GET` | `/api/v1/decks/precedents/` | List deck precedents |
| `POST` | `/api/v1/decks/precedents/` | Create precedent |
| `GET` | `/api/v1/decks/precedents/{precedent_id}` | Get precedent details |
| `POST` | `/api/v1/decks/precedents/{precedent_id}/use` | Use/clone precedent |
| `GET` | `/api/v1/decks/suggestions/` | List card suggestions |
| `POST` | `/api/v1/decks/suggestions/` | Add card suggestion |
## Quick Start
### Prerequisites
- Docker and Docker Compose
### Run the Stack
```bash
cd /home/wall-o/projects/mtgonline
# Start all services (Postgres x2, Redis, Backend)
docker compose -f docker-compose.dev.yml up -d
# View logs
docker compose -f docker-compose.dev.yml logs -f backend
```
The backend will automatically download MTGJSON data on first startup (this may take several minutes).
### Access
| Service | Address |
|---------------|---------------------|
| Backend API | `http://localhost:5555` |
| Swagger Docs | `http://localhost:5555/docs` |
| Health Check | `http://localhost:5555/health` |
| PostgreSQL (app) | `localhost:5432` |
| PostgreSQL (MTG) | `localhost:5433` |
| Redis | `localhost:6379` |
### Manual Data Refresh
```bash
# Trigger a manual MTGJSON refresh
curl -X POST http://localhost:5555/refresh
```
## Card Import Feature
Users can import their card collection to enable deckbuilding with owned cards. The feature includes fuzzy matching for typos.
### Import Cards
```bash
curl -X POST http://localhost:5555/api/v1/card-import/ \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"card_names": ["Lightning Bolt", "Shock", "Thoughtseize"]
}'
```
### Check Import Status
```bash
curl http://localhost:5555/api/v1/card-import/status \
-H "Authorization: Bearer <token>"
```
### Get Import Summary
```bash
curl http://localhost:5555/api/v1/card-import/summary \
-H "Authorization: Bearer <token>"
```
### Delete Import
```bash
curl -X DELETE http://localhost:5555/api/v1/card-import/ \
-H "Authorization: Bearer <token>"
```
## Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `DATABASE_URL` | `postgresql+asyncpg://mtgonline_user:mtgonline_password@postgres:5432/mtgonline` | Primary database connection |
| `MTG_DATABASE_URL` | `postgresql+asyncpg://mtgonline_user:mtgonline_password@mtgdata:5432/mtgdata` | MTG data database connection |
| `REDIS_URL` | `redis://redis:6379` | Redis connection |
| `DATA_DIR` | `/app/data` | Directory for MTGJSON files |
| `DEBUG` | `False` | Enable debug logging |
## Docker Cleanup
```bash
# Stop and remove all containers
docker compose -f docker-compose.dev.yml down
# Remove images and prune
docker system prune -a --volumes
```
## License
MIT