from datetime import datetime from pydantic import BaseModel, Field from app.schemas.user import UserPublic class MarathonBase(BaseModel): title: str = Field(..., min_length=1, max_length=100) description: str | None = None class MarathonCreate(MarathonBase): start_date: datetime duration_days: int = Field(default=30, ge=1, le=365) is_public: bool = False game_proposal_mode: str = Field(default="all_participants", pattern="^(all_participants|organizer_only)$") # Shop/Consumables settings allow_skips: bool = True max_skips_per_participant: int | None = Field(None, ge=1, le=100) allow_consumables: bool = True class MarathonUpdate(BaseModel): title: str | None = Field(None, min_length=1, max_length=100) description: str | None = None start_date: datetime | None = None is_public: bool | None = None game_proposal_mode: str | None = Field(None, pattern="^(all_participants|organizer_only)$") auto_events_enabled: bool | None = None # Shop/Consumables settings allow_skips: bool | None = None max_skips_per_participant: int | None = Field(None, ge=1, le=100) allow_consumables: bool | None = None class ParticipantInfo(BaseModel): id: int role: str = "participant" total_points: int current_streak: int drop_count: int joined_at: datetime # Shop: coins and consumables status coins_earned: int = 0 skips_used: int = 0 has_active_boost: bool = False has_lucky_dice: bool = False lucky_dice_multiplier: float | None = None can_undo: bool = False class Config: from_attributes = True class ParticipantWithUser(ParticipantInfo): user: UserPublic class MarathonResponse(MarathonBase): id: int creator: UserPublic status: str invite_code: str is_public: bool game_proposal_mode: str auto_events_enabled: bool cover_url: str | None start_date: datetime | None end_date: datetime | None participants_count: int games_count: int created_at: datetime my_participation: ParticipantInfo | None = None # Certification certification_status: str = "none" is_certified: bool = False # Shop/Consumables settings allow_skips: bool = True max_skips_per_participant: int | None = None allow_consumables: bool = True class Config: from_attributes = True class SetParticipantRole(BaseModel): role: str = Field(..., pattern="^(participant|organizer)$") class MarathonListItem(BaseModel): id: int title: str status: str is_public: bool cover_url: str | None participants_count: int start_date: datetime | None end_date: datetime | None # Certification badge is_certified: bool = False class Config: from_attributes = True class JoinMarathon(BaseModel): invite_code: str class MarathonPublicInfo(BaseModel): """Public info about marathon for invite page (no auth required)""" id: int title: str description: str | None status: str cover_url: str | None participants_count: int creator_nickname: str class Config: from_attributes = True class LeaderboardEntry(BaseModel): rank: int user: UserPublic total_points: int current_streak: int completed_count: int dropped_count: int