from typing import List, Optional, TYPE_CHECKING from uuid import UUID, uuid4 from pydantic import BaseModel from sqlmodel import SQLModel, Field, Relationship, JSON, Column, ForeignKeyConstraint from database.exercices.models import Example if TYPE_CHECKING: from database.auth.models import User class RoomBase(SQLModel): name: str = Field(max_length=20) public: bool = Field(default=False) global_results: bool = Field(default=False) class RoomCreate(RoomBase): pass class Room(RoomBase, table=True): id: Optional[int] = Field(default=None, primary_key=True) id_code: str = Field(index=True) members: List['Member'] = Relationship(back_populates="room",sa_relationship_kwargs={"cascade": "all, delete, delete-orphan"}) parcours: List['Parcours'] = Relationship(back_populates="room",sa_relationship_kwargs={"cascade": "all, delete, delete-orphan"}) class AnonymousBase(SQLModel): username: str = Field(max_length=20) class AnonymousCreate(AnonymousBase): pass class Anonymous(AnonymousBase, table=True): id: Optional[int] = Field(default=None, primary_key=True) reconnect_code: str = Field(index=True) clientId: Optional[UUID] = Field(default=uuid4(), index=True) member: 'Member' = Relationship(back_populates="anonymous") class Member(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) id_code: str = Field(index=True) user_id: Optional[int] = Field(foreign_key="user.id", default=None) user: Optional["User"] = Relationship(back_populates='members') anonymous_id: Optional[int] = Field( foreign_key="anonymous.id", default=None) anonymous: Optional[Anonymous] = Relationship(back_populates="member") room_id: int = Field(foreign_key="room.id") room: Room = Relationship(back_populates='members') challengers: List["Challenger"] = Relationship(back_populates="member", sa_relationship_kwargs={"cascade": "all, delete, delete-orphan"}) corrections: List["TmpCorrection"] = Relationship(back_populates="member", sa_relationship_kwargs={"cascade": "all, delete, delete-orphan"}) is_admin: bool = False waiting: bool = False online: bool = False waiter_code: Optional[str] = Field(default=None) class ExercicesCreate(SQLModel): exercice_id: str quantity: int = 10 class Exercices(ExercicesCreate): name: str examples: Example class Challenger(SQLModel, table=True): member_id: int = Field(foreign_key="member.id", primary_key=True) parcours_id: int = Field(foreign_key="parcours.id", primary_key=True) parcours: "Parcours" = Relationship(back_populates="challengers") member: "Member" = Relationship(back_populates="challengers") #challenges: list["Challenge"] = Relationship(back_populates="challenger") avg: Optional[float] = Field(default=None) best: Optional[int] = Field(default=None) best_time: Optional[int] = Field(default=None) validated: bool = Field(default=False) class Parcours(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) id_code: str = Field(index=True, unique=True) room_id: int = Field(foreign_key="room.id") room: Room = Relationship(back_populates='parcours') challengers: list[Challenger] = Relationship(back_populates="parcours", sa_relationship_kwargs={"cascade": "all, delete, delete-orphan"}) name: str time: int max_mistakes: int exercices: List[Exercices] = Field(sa_column=Column(JSON)) challenges: List["Challenge"] = Relationship(back_populates="parcours", sa_relationship_kwargs={"cascade": "all, delete, delete-orphan"}) corrections: List["TmpCorrection"] = Relationship( back_populates="parcours", sa_relationship_kwargs={"cascade": "all, delete, delete-orphan"}) class Note(BaseModel): value: int total: int class TimedNote(Note): time: int class ParcoursReadShort(SQLModel): name: str best_note: str | None = None validated: bool = False id_code: str avg: float | None = None class ParcoursReadUpdate(SQLModel): id_code: str name: str time: int max_mistakes: int exercices: List[Exercices] update_challenges: bool = False class ChallengerInfo(BaseModel): name: str id_code: str validated: bool = False class ChallengerAverage(ChallengerInfo): avg: float class Challenges(SQLModel): id_code: str mistakes: int time: int isCorriged: bool canCorrige: bool = True validated: bool = False class ChallengeInfo(BaseModel): challenger: ChallengerInfo challenges: list[Challenges] #total: int class Tops(BaseModel): challenger: ChallengerInfo mistakes: int time: int class ParcoursRead(SQLModel): tops: list[Tops] name: str time: int max_mistakes: int id_code: str exercices: List[Exercices] challenges: dict[str, ChallengeInfo] rank: int | None pb: dict[str, int] | None memberRank: int | None validated: bool ranking: list[ChallengerAverage] #avg: float | None class ParcoursCreate(SQLModel): name: str time: int max_mistakes: int exercices: List[ExercicesCreate] class NotCorrigedInput(BaseModel): index: int value: str class CorrigedInput(NotCorrigedInput): correction: str | None valid: bool | None class ParsedGeneratorOut(BaseModel): calcul: str inputs: List[NotCorrigedInput] class CorrigedGeneratorOut(BaseModel): calcul: str inputs: List[CorrigedInput] class Challenge(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) id_code: str = Field(index=True, unique=True) ''' challenger_id: int = Field(foreign_key="member.id") challenger: Member = Relationship(back_populates="challenges") ''' parcours_id: int = Field(foreign_key="parcours.id_code") parcours: Parcours = Relationship(back_populates="challenges") challenger_pid: int challenger_mid: int __table_args__ = (ForeignKeyConstraint(["challenger_pid", "challenger_mid"], ["challenger.parcours_id","challenger.member_id"]), {}) #challenger: "Challenger" = Relationship(back_populates="challenges") data: Optional[List] = Field( sa_column=Column(JSON), default=[]) time: int ''' note: Note = Field( sa_column=Column(JSON)) ''' mistakes: int #note_value: int validated: bool isCorriged: bool class ExoInfo(BaseModel): id_code: str name: str consigne: str | None class CorrigedData(BaseModel): exo: ExoInfo data: List[CorrigedGeneratorOut] class CorrectionData(BaseModel): exo: ExoInfo data: List[ParsedGeneratorOut] class ChallengeRead(SQLModel): id_code: str data: Optional[List[CorrigedData]] = [] time: int mistakes: int validated: bool isCorriged: bool class TmpCorrection(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) id_code: str = Field(index=True) parcours_id: str = Field(foreign_key="parcours.id_code") parcours: Parcours = Relationship(back_populates="corrections") member_id: int = Field(foreign_key="member.id") member: Member = Relationship(back_populates="corrections") data: List = Field(sa_column=Column(JSON)) class AnonymousRead(AnonymousBase): reconnect_code: str class Username(SQLModel): username: str class MemberRead(SQLModel): username: str reconnect_code: str = '' isUser: bool isAdmin: bool id_code: str clientId: str = "" online: bool class RoomRead(RoomBase): id_code: str class RoomAndMember(BaseModel): room: RoomRead member: MemberRead class Waiter(BaseModel): username: str waiter_id: str class RoomInfo(RoomRead): public: bool name: str members: List[MemberRead | Waiter] parcours: List[ParcoursReadShort] class RoomConnectionInfos(BaseModel): room: str member: str | None = None