# Magic: The Gathering

# Magic: The Gathering

> _Dernière mise à jour : 2026-05-10_

## Source

- **Bulk Scryfall** : `https://api.scryfall.com/bulk-data` → `all_cards.json` téléchargé localement
- **Traduction** : Haiku traduit les cartes manquantes (FR souvent en retard sur l'anglais sur Scryfall)
- **Collection Qdrant** : `magic-cards`
- **Data dir** : `MAGIC_CARDS_DATA_DIR` (défaut `/app/data/magic-cards`)
  - `all-cards.json` : bulk Scryfall (téléchargé)
  - `cards.json` : extrait + dédupliqué par `oracle_id`, version FR

## Code

| Fichier | Rôle |
|---|---|
| `src/services/cards/sources/magic.ts` | Implémente `CardSource` (load, normalize, getImageUrl) |
| `scripts/magic-cards/download-bulk.ts` | Télécharge `all-cards.json` Scryfall |
| `scripts/magic-cards/extract-cards.ts` | Filtre + dédupe par oracle_id, version FR |
| `scripts/magic-cards/translate-missing.ts` | Bat ch Haiku traduit cartes manquantes (~3000/batch) |
| `scripts/magic-cards/ingest.ts` | Pousse vers Qdrant `magic-cards` |
| `scripts/meta-mtg/sync.ts` | Sync 17Lands API |
| `scripts/meta-mtg/sync-constructed.ts` | Scrape MTGGoldfish |
| `scripts/meta-mtg/sync-tournament.ts` | Scrape MTGTop8 |
| `scripts/meta-mtg/fix-legalities.ts` | Re-vérifie les formats Standard après rotation |

## Payload Qdrant `magic-cards`

```typescript
{
  id: pointId,
  name: string,            // FR
  name_en: string,         // EN
  set_label: string,       // ex: "Strixhaven (STX)"
  rarity: 'common' | 'uncommon' | 'rare' | 'mythic',
  card_type: string,       // "Creature — Human Wizard"
  mana_cost: string,       // "{2}{U}{U}"
  cmc: number,             // 4
  card_mtg_color_identity: string[],  // ['U', 'B']
  card_mtg_legal_formats: string[],   // ['standard', 'modern', 'legacy', ...]
  card_mtg_layout: string, // 'normal' | 'modal_dfc' | 'transform' | etc.
  faces: [...],            // pour double-face
  power: string,
  toughness: string,
  text: string,            // ability text (effet)
  image_url: string,       // CDN Scryfall
}
```

## Symboles UI

- Webfont `mana-font` (Andrew Gioia) chargée depuis npm package
- Helper `frontend/src/lib/mana.ts` : regex `/{[WUBRGCSTXP0-9/]+}/g` → `<i class="ms ms-w">`
- Active uniquement si `game.hasCardDatabase === 'magic-cards'` (guard dans `useArbiterMarkdown`)

## Méta-game

3 sources combinées :

- **17Lands** : draft analytics (winrate, pick order). Activable via `META_MTG_SET=BLB` (code set 17Lands).
- **MTGGoldfish** : constructed metagame. Activable via `META_MTG_FORMATS=standard,modern,pioneer`.
- **MTGTop8** : top 8 tournois. Activable via `META_TOURNAMENT_ENABLED=true` + `META_TOURNAMENT_FORMATS`.

Toutes les sources poussent dans Qdrant comme chunks `[META]`. Le RAG retrieval méta filtre sur `meta_format` + `meta_set` selon la question.

## Deckbuilding

- Spec Haiku par défaut Standard : `60 mainboard, 15 sideboard, max 4 par non-basique`
- Filtre Qdrant : `card_mtg_legal_formats` contient `spec.format`
- Post-filtre TS : `card_mtg_color_identity ⊆ spec.colors` (Qdrant ne gère pas bien le subset)
- Basic lands FR/EN whitelistés pour bypass max copies : Plains/Island/Swamp/Mountain/Forest/Wastes + Plaine/Île/Marais/Montagne/Forêt

## Set matching

`set-aliases.ts` normalise les noms d'extensions :
- "Strixhaven" → "STX"
- "Wilds of Eldraine" → "WOE"
- etc.

Permet à l'utilisateur de citer un set par son nom complet, le filtre Qdrant s'applique sur le code 3 lettres.

## Multi-query MTG

`retrieve/multi-query-mtg.ts` : Haiku décompose la question en JSON :
```typescript
{
  colors: string[],       // ['R', 'G']
  cmcMax: number,         // 3
  types: string[],        // ['Creature']
  themes: string[],       // ['elf', 'tribal']
  format: string,         // 'standard'
  set: string             // 'BLB'
}
```

Chaque champ devient un filter Qdrant natif (payload matching) → réduit le candidate set avant le rerank.

## Workflow update

Voir `mettre-a-jour-cartes.md` pour le détail (workflow 4 étapes : download → extract → translate-missing → ingest, + fix-legalities post-rotation).