// Modèle de domaine partagé entre client et serveur. // Le serveur est la source de vérité ; le client n'affiche qu'un état reçu. /** Statut courant d'une room (machine à états du jeu). */ export type RoomStatus = "lobby" | "in_round" | "reveal" | "scores" | "ended" /** Types d'épreuves disponibles. Étendre = ajouter une valeur + un module GameRound. */ export type RoundType = "blindtest" | "quiz" /** Type de partie choisi au lobby : mélange par défaut, ou un seul mode. */ export type GameType = "mixed" | "quiz" | "image" | "blindtest" /** Modes de blindtest, déterminent la forme du vote et le barème. */ export type BlindtestMode = "title_artist" | "who_added" | "mixed" /** Formats de question quiz. */ export type QuizFormat = "mcq" | "truefalse" | "free" | "image_reveal" /** Joueur connecté à une room. */ export interface Player { id: string name: string connected: boolean } /** Configuration d'une épreuve planifiée dans la séquence de la partie. */ export interface RoundConfig { type: RoundType } /** Réglages de la room, modifiables dans le lobby par l'hôte. */ export interface RoomSettings { /** Type de partie choisi dans le lobby (pilote l'UI partagée). */ gameType: GameType blindtestMode: BlindtestMode /** Durée d'une manche en secondes (def. 60). */ roundDuration: number /** Nombre de titres que chaque joueur soumet (blindtest). */ tracksPerPlayer: number /** Séquence d'épreuves de la partie. */ rounds: RoundConfig[] } /** Réglages par défaut d'une nouvelle room. */ export const DEFAULT_ROOM_SETTINGS: RoomSettings = { gameType: "mixed", blindtestMode: "title_artist", roundDuration: 60, tracksPerPlayer: 2, rounds: [], } // --- Votes --------------------------------------------------------------- /** Vote blindtest, forme selon RoomSettings.blindtestMode. */ export type BlindtestAnswer = | { title: string; artist: string } | { guessedPlayerId: string } | { title: string; artist: string; guessedPlayerId: string } /** Vote quiz, forme selon le format de la question. */ export type QuizAnswer = { choiceIndex: number } | { text: string } /** Réponse soumise par un joueur pour la manche en cours. */ export type Answer = BlindtestAnswer | QuizAnswer // --- Scores -------------------------------------------------------------- /** Score d'un joueur. */ export interface PlayerScore { playerId: string score: number } /** Variation de score appliquée à l'issue d'une manche. */ export interface ScoreDelta { playerId: string delta: number } // --- Snapshot diffusé au client (room:state) ----------------------------- /** * Vue publique de la room poussée à tous les clients. * Ne contient JAMAIS de réponse non révélée ni d'info secrète (ex: submittedBy). */ export interface RoomSnapshot { code: string status: RoomStatus hostId: string players: Player[] settings: RoomSettings scores: PlayerScore[] /** Index de la manche en cours, -1 dans le lobby. */ currentRound: number /** Nombre total de manches planifiées. */ totalRounds: number /** Blindtest : nombre de titres soumis par joueur (comptes seulement, jamais les titres). */ submissions: { playerId: string; count: number }[] }