112 lines
5.8 KiB
Python
112 lines
5.8 KiB
Python
import uuid
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import String, Text, DateTime, Integer, ForeignKey, JSON, Enum as SAEnum
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from app.models.database import Base, gen_uuid
|
|
from app.models.schemas import GamePhase, CharacterRole, CharacterStatus, ClueType, ClueVisibility
|
|
|
|
|
|
class Script(Base):
|
|
__tablename__ = "scripts"
|
|
|
|
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=gen_uuid)
|
|
title: Mapped[str] = mapped_column(String(200), nullable=False)
|
|
background: Mapped[str] = mapped_column(Text, default="")
|
|
raw_content: Mapped[str] = mapped_column(Text, default="")
|
|
parsed_data: Mapped[dict] = mapped_column(JSON, default=dict)
|
|
character_count: Mapped[int] = mapped_column(Integer, default=0)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
|
|
|
characters: Mapped[list["Character"]] = relationship(back_populates="script", cascade="all, delete-orphan")
|
|
clues: Mapped[list["Clue"]] = relationship(back_populates="script", cascade="all, delete-orphan")
|
|
|
|
|
|
class Character(Base):
|
|
__tablename__ = "characters"
|
|
|
|
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=gen_uuid)
|
|
script_id: Mapped[str] = mapped_column(String(36), ForeignKey("scripts.id"), nullable=False)
|
|
name: Mapped[str] = mapped_column(String(100), nullable=False)
|
|
role: Mapped[CharacterRole] = mapped_column(SAEnum(CharacterRole), default=CharacterRole.SUSPECT)
|
|
status: Mapped[CharacterStatus] = mapped_column(SAEnum(CharacterStatus), default=CharacterStatus.ALIVE)
|
|
personality: Mapped[str] = mapped_column(Text, default="")
|
|
speaking_style: Mapped[str] = mapped_column(Text, default="")
|
|
background: Mapped[str] = mapped_column(Text, default="")
|
|
secret: Mapped[str] = mapped_column(Text, default="")
|
|
motive: Mapped[str] = mapped_column(Text, default="")
|
|
avatar_url: Mapped[str] = mapped_column(String(500), default="")
|
|
hermes_profile: Mapped[str] = mapped_column(String(100), default="")
|
|
soul_md: Mapped[str] = mapped_column(Text, default="")
|
|
knowledge_base: Mapped[str] = mapped_column(Text, default="")
|
|
is_revealed_killer: Mapped[bool] = mapped_column(default=False)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
|
|
|
script: Mapped["Script"] = relationship(back_populates="characters")
|
|
messages: Mapped[list["Message"]] = relationship(back_populates="character", cascade="all, delete-orphan")
|
|
|
|
|
|
class Message(Base):
|
|
__tablename__ = "messages"
|
|
|
|
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=gen_uuid)
|
|
session_id: Mapped[str] = mapped_column(String(36), default="")
|
|
character_id: Mapped[str] = mapped_column(String(36), ForeignKey("characters.id"), nullable=True)
|
|
game_phase: Mapped[str] = mapped_column(String(50), default="")
|
|
msg_type: Mapped[str] = mapped_column(String(50), default="character")
|
|
content: Mapped[str] = mapped_column(Text, nullable=False)
|
|
target_character_id: Mapped[str] = mapped_column(String(36), nullable=True)
|
|
clue_id: Mapped[str] = mapped_column(String(36), nullable=True)
|
|
metadata: Mapped[dict] = mapped_column(JSON, default=dict)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
|
|
|
character: Mapped["Character"] = relationship(back_populates="messages")
|
|
|
|
|
|
class Clue(Base):
|
|
__tablename__ = "clues"
|
|
|
|
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=gen_uuid)
|
|
script_id: Mapped[str] = mapped_column(String(36), ForeignKey("scripts.id"), nullable=False)
|
|
name: Mapped[str] = mapped_column(String(200), nullable=False)
|
|
content: Mapped[str] = mapped_column(Text, nullable=False)
|
|
clue_type: Mapped[ClueType] = mapped_column(SAEnum(ClueType), default=ClueType.PHYSICAL)
|
|
owner_id: Mapped[str] = mapped_column(String(36), nullable=True)
|
|
phase: Mapped[str] = mapped_column(String(50), default="round1_search")
|
|
visibility: Mapped[ClueVisibility] = mapped_column(SAEnum(ClueVisibility), default=ClueVisibility.ALL)
|
|
visible_to: Mapped[list] = mapped_column(JSON, default=list)
|
|
is_unlocked: Mapped[bool] = mapped_column(default=False)
|
|
unlocked_by: Mapped[str] = mapped_column(String(36), nullable=True)
|
|
unlocked_at: Mapped[datetime] = mapped_column(DateTime, nullable=True)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
|
|
|
script: Mapped["Script"] = relationship(back_populates="clues")
|
|
|
|
|
|
class GameState(Base):
|
|
__tablename__ = "game_state"
|
|
|
|
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=gen_uuid)
|
|
current_phase: Mapped[str] = mapped_column(String(50), default="intro")
|
|
current_speaker_id: Mapped[str] = mapped_column(String(36), nullable=True)
|
|
speaker_order: Mapped[list] = mapped_column(JSON, default=list)
|
|
active_script_id: Mapped[str] = mapped_column(String(36), nullable=True)
|
|
is_running: Mapped[bool] = mapped_column(default=False)
|
|
is_paused: Mapped[bool] = mapped_column(default=False)
|
|
phase_started_at: Mapped[datetime] = mapped_column(DateTime, nullable=True)
|
|
config: Mapped[dict] = mapped_column(JSON, default=dict)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
|
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
|
|
|
|
class Vote(Base):
|
|
__tablename__ = "votes"
|
|
|
|
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=gen_uuid)
|
|
voter_id: Mapped[str] = mapped_column(String(36), nullable=False)
|
|
target_id: Mapped[str] = mapped_column(String(36), nullable=False)
|
|
round_number: Mapped[int] = mapped_column(Integer, default=1)
|
|
reason: Mapped[str] = mapped_column(Text, default="")
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|