Phase 2.1: Card mirror system for deckbuilding features
- Created MtgCardMirror and DeckCardLink models in mirror_models.py - Created card_mirror_service.py with sync_mirrors functionality - Added sync_mirrors() method to mtgjson_manager.py - Added mirror_get_db() dependency to database.py - Added DecklistFile.status column (DRAUGHT/FINAL) - Updated DeckCreate schema with status field - Added DeckWithCardsResponse schema with card_count - Updated deck router to query card mirrors and return card counts - Added plain text deck content support
This commit is contained in:
@@ -903,6 +903,88 @@ class MTGJSONManager:
|
||||
'duration': duration,
|
||||
})
|
||||
|
||||
async def sync_mirrors(self):
|
||||
"""Sync mirrored cards from mtg_cards to mtg_cards_mirror.
|
||||
|
||||
This should be called after a successful refresh to ensure
|
||||
the mirror table is up-to-date with the latest card data.
|
||||
"""
|
||||
from sqlalchemy import insert, update
|
||||
|
||||
logger.info("Syncing card mirrors...")
|
||||
|
||||
async with mtg_async_session() as session:
|
||||
# Get all cards from mtg_cards
|
||||
cards_stmt = text("""
|
||||
SELECT id, name, mana_cost, type_line, oracle_text, power, toughness,
|
||||
rarity, layout, artist, flavor_text, numbers, identifiers, images,
|
||||
image, card_parts, keywords, legalities, set_code, set_name
|
||||
FROM mtg_cards
|
||||
""")
|
||||
result = await session.execute(cards_stmt)
|
||||
cards = result.fetchall()
|
||||
|
||||
synced_count = 0
|
||||
for card in cards:
|
||||
# Upsert into mtg_cards_mirror
|
||||
await session.execute(text("""
|
||||
INSERT INTO mtg_cards_mirror (source_id, name, mana_cost, type_line, oracle_text,
|
||||
power, toughness, rarity, layout, artist, flavor_text,
|
||||
numbers, identifiers, images, image, card_parts,
|
||||
keywords, legalities, set_code, set_name)
|
||||
VALUES (:source_id, :name, :mana_cost, :type_line, :oracle_text,
|
||||
:power, :toughness, :rarity, :layout, :artist, :flavor_text,
|
||||
:numbers, :identifiers, :images, :image, :card_parts,
|
||||
:keywords, :legalities, :set_code, :set_name)
|
||||
ON CONFLICT (name) DO UPDATE SET
|
||||
mana_cost = EXCLUDED.mana_cost,
|
||||
type_line = EXCLUDED.type_line,
|
||||
oracle_text = EXCLUDED.oracle_text,
|
||||
power = EXCLUDED.power,
|
||||
toughness = EXCLUDED.toughness,
|
||||
rarity = EXCLUDED.rarity,
|
||||
layout = EXCLUDED.layout,
|
||||
artist = EXCLUDED.artist,
|
||||
flavor_text = EXCLUDED.flavor_text,
|
||||
numbers = EXCLUDED.numbers,
|
||||
identifiers = EXCLUDED.identifiers,
|
||||
images = EXCLUDED.images,
|
||||
image = EXCLUDED.image,
|
||||
card_parts = EXCLUDED.card_parts,
|
||||
keywords = EXCLUDED.keywords,
|
||||
legalities = EXCLUDED.legalities,
|
||||
set_code = EXCLUDED.set_code,
|
||||
set_name = EXCLUDED.set_name,
|
||||
synced_at = CURRENT_TIMESTAMP
|
||||
"""), {
|
||||
'source_id': card[0],
|
||||
'name': card[1],
|
||||
'mana_cost': card[2],
|
||||
'type_line': card[3],
|
||||
'oracle_text': card[4],
|
||||
'power': card[5],
|
||||
'toughness': card[6],
|
||||
'rarity': card[7],
|
||||
'layout': card[8],
|
||||
'artist': card[9],
|
||||
'flavor_text': card[10],
|
||||
'numbers': card[11],
|
||||
'identifiers': card[12],
|
||||
'images': card[13],
|
||||
'image': card[14],
|
||||
'card_parts': card[15],
|
||||
'keywords': card[16],
|
||||
'legalities': card[17],
|
||||
'set_code': card[18],
|
||||
'set_name': card[19],
|
||||
})
|
||||
synced_count += 1
|
||||
|
||||
await session.commit()
|
||||
logger.info(f"Synced {synced_count} card mirrors")
|
||||
|
||||
return synced_count
|
||||
|
||||
async def run_refresh(self) -> bool:
|
||||
"""Run complete refresh cycle from local files."""
|
||||
logger.info("Starting local file refresh")
|
||||
|
||||
Reference in New Issue
Block a user