- 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)
220 lines
8.3 KiB
Markdown
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
|