from datetime import datetime from sqlalchemy import DateTime, ForeignKey, SmallInteger, String, UniqueConstraint from sqlalchemy.dialects.postgresql import JSONB from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql import func from app.core.database import Base class Genlocke(Base): __tablename__ = "genlockes" id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] = mapped_column(String(100)) status: Mapped[str] = mapped_column(String(20), index=True) # active, completed, failed genlocke_rules: Mapped[dict] = mapped_column(JSONB, default=dict) nuzlocke_rules: Mapped[dict] = mapped_column(JSONB, default=dict) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now() ) legs: Mapped[list["GenlockeLeg"]] = relationship( back_populates="genlocke", order_by="GenlockeLeg.leg_order" ) class GenlockeLeg(Base): __tablename__ = "genlocke_legs" __table_args__ = ( UniqueConstraint("genlocke_id", "leg_order", name="uq_genlocke_legs_order"), ) id: Mapped[int] = mapped_column(primary_key=True) genlocke_id: Mapped[int] = mapped_column( ForeignKey("genlockes.id", ondelete="CASCADE"), index=True ) game_id: Mapped[int] = mapped_column(ForeignKey("games.id"), index=True) run_id: Mapped[int | None] = mapped_column( ForeignKey("nuzlocke_runs.id"), index=True ) leg_order: Mapped[int] = mapped_column(SmallInteger) retired_pokemon_ids: Mapped[list[int] | None] = mapped_column(JSONB, default=None) genlocke: Mapped["Genlocke"] = relationship(back_populates="legs") game: Mapped["Game"] = relationship() run: Mapped["NuzlockeRun | None"] = relationship()