Files
mtgonline/backend/scripts/interaction_schema.py
T

191 lines
7.1 KiB
Python

"""
MTG Card Interaction Database Schema
Defines the database schema for storing card interactions.
Includes tables for synergies, counters, evolutions, and statistics.
"""
from sqlalchemy import create_engine, Column, Integer, String, Float, DateTime, ForeignKey, UniqueConstraint
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from datetime import datetime
Base = declarative_base()
class CardSynergy(Base):
"""
Synergy between two cards.
Synergies are positive interactions where cards work well together.
Examples: Archetype support, mechanic combos, mana base compatibility.
"""
__tablename__ = 'mtg_card_synergies'
id = Column(Integer, primary_key=True, autoincrement=True)
card_a_id = Column(Integer, ForeignKey('mtg_cards.id'), nullable=False)
card_b_id = Column(Integer, ForeignKey('mtg_cards.id'), nullable=False)
synergy_type = Column(String(50), nullable=False) # 'archetype', 'mechanic', 'mana', 'combo'
strength = Column(Integer, nullable=False) # 1-5 (1=weak, 5=strong)
notes = Column(String(500), nullable=True)
confidence = Column(Float, nullable=False, default=0.8)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Unique constraint to prevent duplicates
__table_args__ = (
UniqueConstraint('card_a_id', 'card_b_id', 'synergy_type', name='uq_synergy_pair_type'),
)
# Relationships
card_a = relationship('MtgCard', foreign_keys=[card_a_id])
card_b = relationship('MtgCard', foreign_keys=[card_b_id])
def __repr__(self):
return f"<CardSynergy(id={self.id}, card_a={self.card_a_id}, card_b={self.card_b_id}, type={self.synergy_type})>"
class CardCounter(Base):
"""
Counter relationship between two cards.
Counters are negative interactions where one card is disadvantaged by another.
Examples: Different color identities, outclassed stats, countered by specific spells.
"""
__tablename__ = 'mtg_card_counters'
id = Column(Integer, primary_key=True, autoincrement=True)
card_a_id = Column(Integer, ForeignKey('mtg_cards.id'), nullable=False)
card_b_id = Column(Integer, ForeignKey('mtg_cards.id'), nullable=False)
counter_type = Column(String(50), nullable=False) # 'color', 'stats', 'spell', 'keyword'
strength = Column(Integer, nullable=False) # 1-5 (1=weak, 5=strong)
notes = Column(String(500), nullable=True)
confidence = Column(Float, nullable=False, default=0.7)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Unique constraint to prevent duplicates
__table_args__ = (
UniqueConstraint('card_a_id', 'card_b_id', 'counter_type', name='uq_counter_pair_type'),
)
# Relationships
card_a = relationship('MtgCard', foreign_keys=[card_a_id])
card_b = relationship('MtgCard', foreign_keys=[card_b_id])
def __repr__(self):
return f"<CardCounter(id={self.id}, card_a={self.card_a_id}, card_b={self.card_b_id}, type={self.counter_type})>"
class CardEvolution(Base):
"""
Evolution relationship for a card.
Evolutions track when a card has been reprinted, transformed, or evolved.
Examples: Same name in different sets, transform pairs, double-sided cards.
"""
__tablename__ = 'mtg_card_evolution'
id = Column(Integer, primary_key=True, autoincrement=True)
card_id = Column(Integer, ForeignKey('mtg_cards.id'), nullable=False)
evolved_card_id = Column(Integer, ForeignKey('mtg_cards.id'), nullable=False)
evolution_type = Column(String(50), nullable=False) # 'reprint', 'transform', 'double_sided'
strength = Column(Integer, nullable=False) # 1-5 (1=weak, 5=strong)
notes = Column(String(500), nullable=True)
confidence = Column(Float, nullable=False, default=0.9)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Unique constraint to prevent duplicates
__table_args__ = (
UniqueConstraint('card_id', 'evolved_card_id', 'evolution_type', name='uq_evolution_pair_type'),
)
# Relationships
card = relationship('MtgCard', foreign_keys=[card_id])
evolved_card = relationship('MtgCard', foreign_keys=[evolved_card_id])
def __repr__(self):
return f"<CardEvolution(id={self.id}, card={self.card_id}, evolved={self.evolved_card_id}, type={self.evolution_type})>"
class CardInteractionStats(Base):
"""
Aggregated interaction statistics for a card.
Tracks total interactions, average strength, and primary archetypes/themes.
"""
__tablename__ = 'mtg_card_interaction_stats'
id = Column(Integer, primary_key=True, autoincrement=True)
card_id = Column(Integer, ForeignKey('mtg_cards.id'), nullable=False, unique=True)
# Interaction counts
total_synergies = Column(Integer, nullable=False, default=0)
total_counters = Column(Integer, nullable=False, default=0)
total_evolutions = Column(Integer, nullable=False, default=0)
total_partners = Column(Integer, nullable=False, default=0) # Cards that partner well
# Mechanic/archetype counts
total_mechanics = Column(Integer, nullable=False, default=0)
total_archetypes = Column(Integer, nullable=False, default=0)
total_themes = Column(Integer, nullable=False, default=0)
# Synergy strength metrics
avg_synergy_strength = Column(Float, nullable=False, default=0.0)
max_synergy_strength = Column(Integer, nullable=False, default=0)
# Primary archetype and theme
primary_archetype = Column(String(50), nullable=True)
primary_theme = Column(String(50), nullable=True)
# Metadata
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
def __repr__(self):
return f"<CardInteractionStats(id={self.id}, card_id={self.card_id})>"
def create_interaction_tables(engine):
"""
Create all interaction tables in the database.
Args:
engine: SQLAlchemy engine
"""
Base.metadata.create_all(engine)
print("✅ Interaction tables created successfully")
def drop_interaction_tables(engine):
"""
Drop all interaction tables from the database.
Args:
engine: SQLAlchemy engine
"""
Base.metadata.drop_all(engine)
print("✅ Interaction tables dropped successfully")
if __name__ == "__main__":
# Example usage
from dotenv import load_dotenv
import os
load_dotenv()
db_url = os.getenv('MTG_DATABASE_URL', 'postgresql+psycopg2://mtgonline:mtgonline_pass@172.18.0.2:5432/mtgdata')
engine = create_engine(db_url)
# Create tables
create_interaction_tables(engine)
# Print table names
from sqlalchemy import inspect
inspector = inspect(engine)
print("\n📊 Tables created:")
for table in inspector.get_table_names():
if 'mtg_card_' in table:
print(f" - {table}")