diff --git a/app/api/rooms/[code]/route.ts b/app/api/rooms/[code]/route.ts index 5d8d83d..51b2260 100644 --- a/app/api/rooms/[code]/route.ts +++ b/app/api/rooms/[code]/route.ts @@ -1,5 +1,5 @@ // Route handler pour les actions sur une room specifique -// PATCH /api/rooms/[code] - actions: join, heartbeat, start, navigate, leave, nextRound +// PATCH /api/rooms/[code] - actions: join, heartbeat, start, navigate, surrender, nextRound, resetGame import { NextRequest } from "next/server"; import type { Room, Player } from "../route"; @@ -12,6 +12,7 @@ function dbToRoom(row: { round: number; totalRounds: number; maxPlayers: number; + gameMode: string; startArticle: string; targetArticle: string; roundWinner: string | null; @@ -26,6 +27,7 @@ function dbToRoom(row: { round: row.round, totalRounds: row.totalRounds, maxPlayers: row.maxPlayers, + gameMode: (row.gameMode ?? "race") as Room["gameMode"], startArticle: row.startArticle, targetArticle: row.targetArticle, roundWinner: row.roundWinner, @@ -47,6 +49,33 @@ function prunePlayers(players: Player[]): Player[] { return players.filter((p) => now - p.lastSeen < PLAYER_TIMEOUT_MS); } +// En mode all_finish : calcule les points selon le rang d'arrivée +// 1er = 10pts, 2ème = 7pts, 3ème = 5pts, reste = 3pts, forfait = 0pts +const RANK_POINTS = [10, 7, 5, 3]; +function getRankPoints(rank: number): number { + return RANK_POINTS[rank] ?? RANK_POINTS[RANK_POINTS.length - 1]; +} + +// Vérifie si la manche doit se terminer en mode all_finish +function checkAllFinished(room: Room): boolean { + if (room.gameMode !== "all_finish") return false; + return room.players.every((p) => p.hasWon || p.hasSurrendered); +} + +// Attribue les points en mode all_finish selon l'ordre d'arrivée +function assignAllFinishPoints(room: Room) { + const winners = room.players.filter((p) => p.hasWon); + // On leur attribue les points selon leur rang (ordre d'arrivée = ordre dans le tableau, déjà fixé au moment où ils ont gagné) + winners.forEach((p, i) => { + p.score += getRankPoints(i); + }); + // roundWinner = premier arrivé + if (winners.length > 0) { + room.roundWinner = winners[0].id; + } + room.phase = "results"; +} + // PATCH /api/rooms/[code] export async function PATCH( request: NextRequest, @@ -105,6 +134,7 @@ export async function PATCH( score: 0, currentArticle: "", hasWon: false, + hasSurrendered: false, isHost: false, lastSeen: Date.now(), }; @@ -161,6 +191,7 @@ export async function PATCH( for (const p of room.players) { p.currentArticle = startArticle; p.hasWon = false; + p.hasSurrendered = false; } await saveRoom(room); @@ -202,17 +233,61 @@ export async function PATCH( if ( !player.hasWon && + !player.hasSurrendered && normalize(player.currentArticle) === normalize(room.targetArticle) ) { player.hasWon = true; - const alreadyWon = room.players.some( - (p) => p.hasWon && p.id !== player.id, - ); - if (!alreadyWon) { - player.score += 10; - room.roundWinner = player.id; + if (room.gameMode === "race") { + // Mode course : 1er arrivé gagne la manche immédiatement + const alreadyWon = room.players.some( + (p) => p.hasWon && p.id !== player.id, + ); + if (!alreadyWon) { + player.score += 10; + room.roundWinner = player.id; + room.phase = "results"; + } + } else { + // Mode all_finish : on attend que tout le monde finisse ou abandonne + if (checkAllFinished(room)) { + assignAllFinishPoints(room); + } + } + } + + await saveRoom(room); + return Response.json({ room }); + } + + // Forfait + case "surrender": { + if (room.phase !== "playing") { + return Response.json({ room }); + } + const player = room.players.find((p) => p.id === playerId); + if (!player) { + return Response.json({ error: "Joueur inconnu" }, { status: 404 }); + } + if (player.hasWon || player.hasSurrendered) { + return Response.json({ room }); + } + + player.hasSurrendered = true; + player.lastSeen = Date.now(); + + if (room.gameMode === "race") { + // En mode course, forfait ne termine pas la manche — on attend qu'un vrai gagnant arrive + // Sauf si tous ont abandonné + const anyoneStillPlaying = room.players.some((p) => !p.hasWon && !p.hasSurrendered); + if (!anyoneStillPlaying) { room.phase = "results"; + // Pas de roundWinner si tout le monde a abandonné + } + } else { + // Mode all_finish : si tout le monde a fini ou abandonné, on termine + if (checkAllFinished(room)) { + assignAllFinishPoints(room); } } @@ -235,6 +310,7 @@ export async function PATCH( room.roundStart = null; for (const p of room.players) { p.hasWon = false; + p.hasSurrendered = false; p.currentArticle = ""; } await saveRoom(room); @@ -258,6 +334,7 @@ export async function PATCH( for (const p of room.players) { p.score = 0; p.hasWon = false; + p.hasSurrendered = false; p.currentArticle = ""; } await saveRoom(room); @@ -278,6 +355,7 @@ async function saveRoom(room: Room) { round: room.round, totalRounds: room.totalRounds, maxPlayers: room.maxPlayers, + gameMode: room.gameMode, startArticle: room.startArticle, targetArticle: room.targetArticle, roundWinner: room.roundWinner, diff --git a/app/api/rooms/route.ts b/app/api/rooms/route.ts index 1b18ff5..19e72f5 100644 --- a/app/api/rooms/route.ts +++ b/app/api/rooms/route.ts @@ -12,6 +12,7 @@ export type Player = { score: number; currentArticle: string; hasWon: boolean; + hasSurrendered: boolean; isHost: boolean; lastSeen: number; // timestamp ms }; @@ -23,6 +24,7 @@ export type Room = { round: number; totalRounds: number; maxPlayers: number; + gameMode: "race" | "all_finish"; // race = 1er gagne, all_finish = tout le monde joue startArticle: string; targetArticle: string; roundWinner: string | null; @@ -53,6 +55,7 @@ function dbToRoom(row: { round: number; totalRounds: number; maxPlayers: number; + gameMode: string; startArticle: string; targetArticle: string; roundWinner: string | null; @@ -67,6 +70,7 @@ function dbToRoom(row: { round: row.round, totalRounds: row.totalRounds, maxPlayers: row.maxPlayers, + gameMode: (row.gameMode ?? "race") as Room["gameMode"], startArticle: row.startArticle, targetArticle: row.targetArticle, roundWinner: row.roundWinner, @@ -87,10 +91,11 @@ async function pruneOldRooms() { // Response: { room: Room, playerId: string } export async function POST(request: NextRequest) { const body = await request.json(); - const { playerName, maxPlayers, totalRounds } = body as { + const { playerName, maxPlayers, totalRounds, gameMode } = body as { playerName: string; maxPlayers?: number; totalRounds?: number; + gameMode?: string; }; if ( @@ -125,6 +130,8 @@ export async function POST(request: NextRequest) { const playerId = generatePlayerId(); const now = BigInt(Date.now()); + const clampedMode: Room["gameMode"] = gameMode === "all_finish" ? "all_finish" : "race"; + const players: Player[] = [ { id: playerId, @@ -132,6 +139,7 @@ export async function POST(request: NextRequest) { score: 0, currentArticle: "", hasWon: false, + hasSurrendered: false, isHost: true, lastSeen: Date.now(), }, @@ -145,6 +153,7 @@ export async function POST(request: NextRequest) { round: 0, totalRounds: clampedRounds, maxPlayers: clampedMax, + gameMode: clampedMode, startArticle: "", targetArticle: "", roundWinner: null, diff --git a/app/components/GameScreen.tsx b/app/components/GameScreen.tsx index e34dfb0..92ac6f2 100644 --- a/app/components/GameScreen.tsx +++ b/app/components/GameScreen.tsx @@ -20,15 +20,17 @@ type GameScreenProps = { onRetry: () => void; onNextRound: () => void; onResetGame: () => void; + onSurrender: () => void; }; export function GameScreen({ room, playerId, html, title, loading, loadError, history, clicks, elapsed, - countdown, onNavigate, onRetry, onNextRound, onResetGame, + countdown, onNavigate, onRetry, onNextRound, onResetGame, onSurrender, }: GameScreenProps) { const breadcrumbEndRef = useRef(null); const myPlayer = room.players.find((p) => p.id === playerId); const isHost = myPlayer?.isHost ?? false; + const myFinished = myPlayer?.hasWon || myPlayer?.hasSurrendered; const sortedPlayers = [...room.players].sort((a, b) => b.score - a.score); const winner = room.roundWinner ? room.players.find((p) => p.id === room.roundWinner) : null; @@ -65,7 +67,8 @@ export function GameScreen({
  • #{i + 1} {p.name} - {p.hasWon && Gagnant} + {p.hasWon && ✓ Trouvé} + {p.hasSurrendered && Forfait} {p.score} pts
  • ))} @@ -117,10 +120,26 @@ export function GameScreen({ -
    - {elapsed} - {clicks} clics - {myPlayer?.score ?? 0} pts +
    +
    + {elapsed} + {clicks} clics + {myPlayer?.score ?? 0} pts +
    + {!myFinished && ( + + )} + {myFinished && myPlayer?.hasWon && ( + ✓ Trouvé ! + )} + {myFinished && myPlayer?.hasSurrendered && ( + Forfait + )}
    @@ -156,7 +175,8 @@ export function GameScreen({
  • {p.name} {p.score} pts - {p.hasWon && Gagné !} + {p.hasWon && ✓ Trouvé} + {p.hasSurrendered && Forfait}
  • ))} diff --git a/app/components/LobbyScreen.tsx b/app/components/LobbyScreen.tsx index 0b7563b..bfaa8b5 100644 --- a/app/components/LobbyScreen.tsx +++ b/app/components/LobbyScreen.tsx @@ -17,6 +17,8 @@ type LobbyScreenProps = { setMaxPlayers: (v: number) => void; totalRounds: number; setTotalRounds: (v: number) => void; + gameMode: Room["gameMode"]; + setGameMode: (v: Room["gameMode"]) => void; }; export function LobbyScreen({ @@ -32,6 +34,8 @@ export function LobbyScreen({ setMaxPlayers, totalRounds, setTotalRounds, + gameMode, + setGameMode, }: LobbyScreenProps) { const isHost = room.players.find((p) => p.id === playerId)?.isHost ?? false; const [copied, setCopied] = useState(false); @@ -141,6 +145,17 @@ export function LobbyScreen({

    Paramètres

    +
    + Mode de jeu + +
    Joueurs max diff --git a/app/components/ScreenRouter.tsx b/app/components/ScreenRouter.tsx index 1858ef6..03288e3 100644 --- a/app/components/ScreenRouter.tsx +++ b/app/components/ScreenRouter.tsx @@ -32,6 +32,8 @@ type Props = { setMaxPlayers: Dispatch>; totalRounds: number; setTotalRounds: Dispatch>; + gameMode: "race" | "all_finish"; + setGameMode: Dispatch>; error: string | null; setError: Dispatch>; loading: boolean; @@ -44,6 +46,7 @@ export function ScreenRouter({ playerName, setPlayerName, joinCode, setJoinCode, maxPlayers, setMaxPlayers, totalRounds, setTotalRounds, + gameMode, setGameMode, error, setError, loading, showAuth, setShowAuth, }: Props) { if (screen === "profile") return ( @@ -108,6 +111,7 @@ export function ScreenRouter({ onReset={handlers.handleResetGame} maxPlayers={maxPlayers} setMaxPlayers={setMaxPlayers} totalRounds={totalRounds} setTotalRounds={setTotalRounds} + gameMode={gameMode} setGameMode={setGameMode} /> ); @@ -123,6 +127,7 @@ export function ScreenRouter({ onRetry={multi.retryLoad} onNextRound={handlers.handleNextRound} onResetGame={handlers.handleResetGame} + onSurrender={handlers.handleSurrender} /> ); diff --git a/app/page.tsx b/app/page.tsx index c65bbaa..2b67fae 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -14,6 +14,7 @@ export default function WikiRush() { const [joinCode, setJoinCode] = useState(""); const [maxPlayers, setMaxPlayers] = useState(16); const [totalRounds, setTotalRounds] = useState(3); + const [gameMode, setGameMode] = useState<"race" | "all_finish">("race"); const [error, setError] = useState(null); const [loading, setLoading] = useState(false); const [showAuth, setShowAuth] = useState(false); @@ -22,7 +23,7 @@ export default function WikiRush() { const multi = useMultiGame(); const { session } = useGameEffects({ solo, multi, screen, setScreen, setPlayerName }); - const handlers = useGameHandlers({ solo, multi, playerName, joinCode, maxPlayers, totalRounds, setScreen, setError, setLoading }); + const handlers = useGameHandlers({ solo, multi, playerName, joinCode, maxPlayers, totalRounds, gameMode, setScreen, setError, setLoading }); return ( diff --git a/lib/generated/prisma/internal/class.ts b/lib/generated/prisma/internal/class.ts index f58ea89..b45e728 100644 --- a/lib/generated/prisma/internal/class.ts +++ b/lib/generated/prisma/internal/class.ts @@ -20,7 +20,7 @@ const config: runtime.GetPrismaClientConfig = { "clientVersion": "7.7.0", "engineVersion": "75cbdc1eb7150937890ad5465d861175c6624711", "activeProvider": "postgresql", - "inlineSchema": "generator client {\n provider = \"prisma-client\"\n output = \"../lib/generated/prisma\"\n}\n\ndatasource db {\n provider = \"postgresql\"\n}\n\nmodel User {\n id String @id @default(uuid(7))\n name String\n email String @unique\n password String\n banned Boolean @default(false)\n createdAt DateTime @default(now())\n games Game[]\n dailyResults DailyResult[]\n}\n\nmodel Game {\n id String @id @default(uuid(7))\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n mode String // \"solo\" | \"multi\" | \"daily\" | \"blitz\"\n startArticle String\n targetArticle String\n path String // JSON array de titres\n clicks Int\n timeSeconds Float\n won Boolean @default(true)\n playedAt DateTime @default(now())\n\n @@index([userId])\n}\n\nmodel DailyPuzzle {\n id String @id @default(uuid(7))\n date String @unique // \"YYYY-MM-DD\"\n startArticle String\n targetArticle String\n results DailyResult[]\n}\n\nmodel Room {\n code String @id\n players Json @default(\"[]\")\n phase String @default(\"waiting\")\n round Int @default(0)\n totalRounds Int @default(3)\n maxPlayers Int @default(16)\n startArticle String @default(\"\")\n targetArticle String @default(\"\")\n roundWinner String?\n countdownStart BigInt?\n roundStart BigInt?\n createdAt BigInt\n updatedAt DateTime @updatedAt\n}\n\nmodel DailyResult {\n id String @id @default(uuid(7))\n puzzleId String\n puzzle DailyPuzzle @relation(fields: [puzzleId], references: [id], onDelete: Cascade)\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n path String // JSON\n clicks Int\n timeSeconds Float\n won Boolean\n playedAt DateTime @default(now())\n\n @@unique([puzzleId, userId])\n @@index([puzzleId])\n}\n", + "inlineSchema": "generator client {\n provider = \"prisma-client\"\n output = \"../lib/generated/prisma\"\n}\n\ndatasource db {\n provider = \"postgresql\"\n}\n\nmodel User {\n id String @id @default(uuid(7))\n name String\n email String @unique\n password String\n banned Boolean @default(false)\n createdAt DateTime @default(now())\n games Game[]\n dailyResults DailyResult[]\n}\n\nmodel Game {\n id String @id @default(uuid(7))\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n mode String // \"solo\" | \"multi\" | \"daily\" | \"blitz\"\n startArticle String\n targetArticle String\n path String // JSON array de titres\n clicks Int\n timeSeconds Float\n won Boolean @default(true)\n playedAt DateTime @default(now())\n\n @@index([userId])\n}\n\nmodel DailyPuzzle {\n id String @id @default(uuid(7))\n date String @unique // \"YYYY-MM-DD\"\n startArticle String\n targetArticle String\n results DailyResult[]\n}\n\nmodel Room {\n code String @id\n players Json @default(\"[]\")\n phase String @default(\"waiting\")\n round Int @default(0)\n totalRounds Int @default(3)\n maxPlayers Int @default(16)\n gameMode String @default(\"race\")\n startArticle String @default(\"\")\n targetArticle String @default(\"\")\n roundWinner String?\n countdownStart BigInt?\n roundStart BigInt?\n createdAt BigInt\n updatedAt DateTime @updatedAt\n}\n\nmodel DailyResult {\n id String @id @default(uuid(7))\n puzzleId String\n puzzle DailyPuzzle @relation(fields: [puzzleId], references: [id], onDelete: Cascade)\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n path String // JSON\n clicks Int\n timeSeconds Float\n won Boolean\n playedAt DateTime @default(now())\n\n @@unique([puzzleId, userId])\n @@index([puzzleId])\n}\n", "runtimeDataModel": { "models": {}, "enums": {}, @@ -32,10 +32,10 @@ const config: runtime.GetPrismaClientConfig = { } } -config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"password\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"banned\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"games\",\"kind\":\"object\",\"type\":\"Game\",\"relationName\":\"GameToUser\"},{\"name\":\"dailyResults\",\"kind\":\"object\",\"type\":\"DailyResult\",\"relationName\":\"DailyResultToUser\"}],\"dbName\":null},\"Game\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"GameToUser\"},{\"name\":\"mode\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"startArticle\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"targetArticle\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"path\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"clicks\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"timeSeconds\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"won\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"playedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"DailyPuzzle\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"date\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"startArticle\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"targetArticle\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"results\",\"kind\":\"object\",\"type\":\"DailyResult\",\"relationName\":\"DailyPuzzleToDailyResult\"}],\"dbName\":null},\"Room\":{\"fields\":[{\"name\":\"code\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"players\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"phase\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"round\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"totalRounds\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"maxPlayers\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"startArticle\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"targetArticle\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"roundWinner\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"countdownStart\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"roundStart\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"DailyResult\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"puzzleId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"puzzle\",\"kind\":\"object\",\"type\":\"DailyPuzzle\",\"relationName\":\"DailyPuzzleToDailyResult\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"DailyResultToUser\"},{\"name\":\"path\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"clicks\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"timeSeconds\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"won\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"playedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}") +config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"password\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"banned\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"games\",\"kind\":\"object\",\"type\":\"Game\",\"relationName\":\"GameToUser\"},{\"name\":\"dailyResults\",\"kind\":\"object\",\"type\":\"DailyResult\",\"relationName\":\"DailyResultToUser\"}],\"dbName\":null},\"Game\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"GameToUser\"},{\"name\":\"mode\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"startArticle\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"targetArticle\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"path\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"clicks\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"timeSeconds\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"won\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"playedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"DailyPuzzle\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"date\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"startArticle\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"targetArticle\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"results\",\"kind\":\"object\",\"type\":\"DailyResult\",\"relationName\":\"DailyPuzzleToDailyResult\"}],\"dbName\":null},\"Room\":{\"fields\":[{\"name\":\"code\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"players\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"phase\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"round\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"totalRounds\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"maxPlayers\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"gameMode\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"startArticle\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"targetArticle\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"roundWinner\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"countdownStart\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"roundStart\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"DailyResult\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"puzzleId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"puzzle\",\"kind\":\"object\",\"type\":\"DailyPuzzle\",\"relationName\":\"DailyPuzzleToDailyResult\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"DailyResultToUser\"},{\"name\":\"path\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"clicks\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"timeSeconds\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"won\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"playedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}") config.parameterizationSchema = { - strings: JSON.parse("[\"where\",\"orderBy\",\"cursor\",\"user\",\"games\",\"results\",\"_count\",\"puzzle\",\"dailyResults\",\"User.findUnique\",\"User.findUniqueOrThrow\",\"User.findFirst\",\"User.findFirstOrThrow\",\"User.findMany\",\"data\",\"User.createOne\",\"User.createMany\",\"User.createManyAndReturn\",\"User.updateOne\",\"User.updateMany\",\"User.updateManyAndReturn\",\"create\",\"update\",\"User.upsertOne\",\"User.deleteOne\",\"User.deleteMany\",\"having\",\"_min\",\"_max\",\"User.groupBy\",\"User.aggregate\",\"Game.findUnique\",\"Game.findUniqueOrThrow\",\"Game.findFirst\",\"Game.findFirstOrThrow\",\"Game.findMany\",\"Game.createOne\",\"Game.createMany\",\"Game.createManyAndReturn\",\"Game.updateOne\",\"Game.updateMany\",\"Game.updateManyAndReturn\",\"Game.upsertOne\",\"Game.deleteOne\",\"Game.deleteMany\",\"_avg\",\"_sum\",\"Game.groupBy\",\"Game.aggregate\",\"DailyPuzzle.findUnique\",\"DailyPuzzle.findUniqueOrThrow\",\"DailyPuzzle.findFirst\",\"DailyPuzzle.findFirstOrThrow\",\"DailyPuzzle.findMany\",\"DailyPuzzle.createOne\",\"DailyPuzzle.createMany\",\"DailyPuzzle.createManyAndReturn\",\"DailyPuzzle.updateOne\",\"DailyPuzzle.updateMany\",\"DailyPuzzle.updateManyAndReturn\",\"DailyPuzzle.upsertOne\",\"DailyPuzzle.deleteOne\",\"DailyPuzzle.deleteMany\",\"DailyPuzzle.groupBy\",\"DailyPuzzle.aggregate\",\"Room.findUnique\",\"Room.findUniqueOrThrow\",\"Room.findFirst\",\"Room.findFirstOrThrow\",\"Room.findMany\",\"Room.createOne\",\"Room.createMany\",\"Room.createManyAndReturn\",\"Room.updateOne\",\"Room.updateMany\",\"Room.updateManyAndReturn\",\"Room.upsertOne\",\"Room.deleteOne\",\"Room.deleteMany\",\"Room.groupBy\",\"Room.aggregate\",\"DailyResult.findUnique\",\"DailyResult.findUniqueOrThrow\",\"DailyResult.findFirst\",\"DailyResult.findFirstOrThrow\",\"DailyResult.findMany\",\"DailyResult.createOne\",\"DailyResult.createMany\",\"DailyResult.createManyAndReturn\",\"DailyResult.updateOne\",\"DailyResult.updateMany\",\"DailyResult.updateManyAndReturn\",\"DailyResult.upsertOne\",\"DailyResult.deleteOne\",\"DailyResult.deleteMany\",\"DailyResult.groupBy\",\"DailyResult.aggregate\",\"AND\",\"OR\",\"NOT\",\"id\",\"puzzleId\",\"userId\",\"path\",\"clicks\",\"timeSeconds\",\"won\",\"playedAt\",\"equals\",\"in\",\"notIn\",\"lt\",\"lte\",\"gt\",\"gte\",\"not\",\"contains\",\"startsWith\",\"endsWith\",\"code\",\"players\",\"phase\",\"round\",\"totalRounds\",\"maxPlayers\",\"startArticle\",\"targetArticle\",\"roundWinner\",\"countdownStart\",\"roundStart\",\"createdAt\",\"updatedAt\",\"string_contains\",\"string_starts_with\",\"string_ends_with\",\"array_starts_with\",\"array_ends_with\",\"array_contains\",\"date\",\"every\",\"some\",\"none\",\"mode\",\"name\",\"email\",\"password\",\"banned\",\"puzzleId_userId\",\"is\",\"isNot\",\"connectOrCreate\",\"upsert\",\"createMany\",\"set\",\"disconnect\",\"delete\",\"connect\",\"updateMany\",\"deleteMany\",\"increment\",\"decrement\",\"multiply\",\"divide\"]"), - graph: "mAIxUAsEAACxAQAgCAAArAEAIGEAAK8BADBiAAAQABBjAACvAQAwZAEAAAABggFAAKkBACGPAQEAowEAIZABAQAAAAGRAQEAowEAIZIBIACwAQAhAQAAAAEAIA4DAAC2AQAgYQAAtwEAMGIAAAMAEGMAALcBADBkAQCjAQAhZgEAowEAIWcBAKMBACFoAgClAQAhaQgAtAEAIWogALABACFrQACpAQAhfQEAowEAIX4BAKMBACGOAQEAowEAIQEDAACGAgAgDgMAALYBACBhAAC3AQAwYgAAAwAQYwAAtwEAMGQBAAAAAWYBAKMBACFnAQCjAQAhaAIApQEAIWkIALQBACFqIACwAQAha0AAqQEAIX0BAKMBACF-AQCjAQAhjgEBAKMBACEDAAAAAwAgAQAABAAwAgAABQAgDQMAALYBACAHAAC1AQAgYQAAswEAMGIAAAcAEGMAALMBADBkAQCjAQAhZQEAowEAIWYBAKMBACFnAQCjAQAhaAIApQEAIWkIALQBACFqIACwAQAha0AAqQEAIQIDAACGAgAgBwAAhQIAIA4DAAC2AQAgBwAAtQEAIGEAALMBADBiAAAHABBjAACzAQAwZAEAAAABZQEAowEAIWYBAKMBACFnAQCjAQAhaAIApQEAIWkIALQBACFqIACwAQAha0AAqQEAIZMBAACyAQAgAwAAAAcAIAEAAAgAMAIAAAkAIAMAAAAHACABAAAIADACAAAJACABAAAABwAgAQAAAAMAIAEAAAAHACABAAAAAQAgCwQAALEBACAIAACsAQAgYQAArwEAMGIAABAAEGMAAK8BADBkAQCjAQAhggFAAKkBACGPAQEAowEAIZABAQCjAQAhkQEBAKMBACGSASAAsAEAIQIEAACEAgAgCAAA4AEAIAMAAAAQACABAAARADACAAABACADAAAAEAAgAQAAEQAwAgAAAQAgAwAAABAAIAEAABEAMAIAAAEAIAgEAACCAgAgCAAAgwIAIGQBAAAAAYIBQAAAAAGPAQEAAAABkAEBAAAAAZEBAQAAAAGSASAAAAABAQ4AABUAIAZkAQAAAAGCAUAAAAABjwEBAAAAAZABAQAAAAGRAQEAAAABkgEgAAAAAQEOAAAXADABDgAAFwAwCAQAAOsBACAIAADsAQAgZAEAvQEAIYIBQADBAQAhjwEBAL0BACGQAQEAvQEAIZEBAQC9AQAhkgEgAMABACECAAAAAQAgDgAAGgAgBmQBAL0BACGCAUAAwQEAIY8BAQC9AQAhkAEBAL0BACGRAQEAvQEAIZIBIADAAQAhAgAAABAAIA4AABwAIAIAAAAQACAOAAAcACADAAAAAQAgFQAAFQAgFgAAGgAgAQAAAAEAIAEAAAAQACADBgAA6AEAIBsAAOoBACAcAADpAQAgCWEAAK4BADBiAAAjABBjAACuAQAwZAEAhQEAIYIBQACJAQAhjwEBAIUBACGQAQEAhQEAIZEBAQCFAQAhkgEgAIgBACEDAAAAEAAgAQAAIgAwGgAAIwAgAwAAABAAIAEAABEAMAIAAAEAIAEAAAAFACABAAAABQAgAwAAAAMAIAEAAAQAMAIAAAUAIAMAAAADACABAAAEADACAAAFACADAAAAAwAgAQAABAAwAgAABQAgCwMAAOcBACBkAQAAAAFmAQAAAAFnAQAAAAFoAgAAAAFpCAAAAAFqIAAAAAFrQAAAAAF9AQAAAAF-AQAAAAGOAQEAAAABAQ4AACsAIApkAQAAAAFmAQAAAAFnAQAAAAFoAgAAAAFpCAAAAAFqIAAAAAFrQAAAAAF9AQAAAAF-AQAAAAGOAQEAAAABAQ4AAC0AMAEOAAAtADALAwAA5gEAIGQBAL0BACFmAQC9AQAhZwEAvQEAIWgCAL4BACFpCAC_AQAhaiAAwAEAIWtAAMEBACF9AQC9AQAhfgEAvQEAIY4BAQC9AQAhAgAAAAUAIA4AADAAIApkAQC9AQAhZgEAvQEAIWcBAL0BACFoAgC-AQAhaQgAvwEAIWogAMABACFrQADBAQAhfQEAvQEAIX4BAL0BACGOAQEAvQEAIQIAAAADACAOAAAyACACAAAAAwAgDgAAMgAgAwAAAAUAIBUAACsAIBYAADAAIAEAAAAFACABAAAAAwAgBQYAAOEBACAbAADkAQAgHAAA4wEAIC0AAOIBACAuAADlAQAgDWEAAK0BADBiAAA5ABBjAACtAQAwZAEAhQEAIWYBAIUBACFnAQCFAQAhaAIAhgEAIWkIAIcBACFqIACIAQAha0AAiQEAIX0BAIUBACF-AQCFAQAhjgEBAIUBACEDAAAAAwAgAQAAOAAwGgAAOQAgAwAAAAMAIAEAAAQAMAIAAAUAIAgFAACsAQAgYQAAqwEAMGIAAD8AEGMAAKsBADBkAQAAAAF9AQCjAQAhfgEAowEAIYoBAQAAAAEBAAAAPAAgAQAAADwAIAgFAACsAQAgYQAAqwEAMGIAAD8AEGMAAKsBADBkAQCjAQAhfQEAowEAIX4BAKMBACGKAQEAowEAIQEFAADgAQAgAwAAAD8AIAEAAEAAMAIAADwAIAMAAAA_ACABAABAADACAAA8ACADAAAAPwAgAQAAQAAwAgAAPAAgBQUAAN8BACBkAQAAAAF9AQAAAAF-AQAAAAGKAQEAAAABAQ4AAEQAIARkAQAAAAF9AQAAAAF-AQAAAAGKAQEAAAABAQ4AAEYAMAEOAABGADAFBQAA0gEAIGQBAL0BACF9AQC9AQAhfgEAvQEAIYoBAQC9AQAhAgAAADwAIA4AAEkAIARkAQC9AQAhfQEAvQEAIX4BAL0BACGKAQEAvQEAIQIAAAA_ACAOAABLACACAAAAPwAgDgAASwAgAwAAADwAIBUAAEQAIBYAAEkAIAEAAAA8ACABAAAAPwAgAwYAAM8BACAbAADRAQAgHAAA0AEAIAdhAACqAQAwYgAAUgAQYwAAqgEAMGQBAIUBACF9AQCFAQAhfgEAhQEAIYoBAQCFAQAhAwAAAD8AIAEAAFEAMBoAAFIAIAMAAAA_ACABAABAADACAAA8ACAQYQAAogEAMGIAAFgAEGMAAKIBADB3AQAAAAF4AACkAQAgeQEAowEAIXoCAKUBACF7AgClAQAhfAIApQEAIX0BAKMBACF-AQCjAQAhfwEApgEAIYABBACnAQAhgQEEAKcBACGCAQQAqAEAIYMBQACpAQAhAQAAAFUAIAEAAABVACAQYQAAogEAMGIAAFgAEGMAAKIBADB3AQCjAQAheAAApAEAIHkBAKMBACF6AgClAQAhewIApQEAIXwCAKUBACF9AQCjAQAhfgEAowEAIX8BAKYBACGAAQQApwEAIYEBBACnAQAhggEEAKgBACGDAUAAqQEAIQN_AADGAQAggAEAAMYBACCBAQAAxgEAIAMAAABYACABAABZADACAABVACADAAAAWAAgAQAAWQAwAgAAVQAgAwAAAFgAIAEAAFkAMAIAAFUAIA13AQAAAAF4gAAAAAF5AQAAAAF6AgAAAAF7AgAAAAF8AgAAAAF9AQAAAAF-AQAAAAF_AQAAAAGAAQQAAAABgQEEAAAAAYIBBAAAAAGDAUAAAAABAQ4AAF0AIA13AQAAAAF4gAAAAAF5AQAAAAF6AgAAAAF7AgAAAAF8AgAAAAF9AQAAAAF-AQAAAAF_AQAAAAGAAQQAAAABgQEEAAAAAYIBBAAAAAGDAUAAAAABAQ4AAF8AMAEOAABfADANdwEAvQEAIXiAAAAAAXkBAL0BACF6AgC-AQAhewIAvgEAIXwCAL4BACF9AQC9AQAhfgEAvQEAIX8BAMwBACGAAQQAzQEAIYEBBADNAQAhggEEAM4BACGDAUAAwQEAIQIAAABVACAOAABiACANdwEAvQEAIXiAAAAAAXkBAL0BACF6AgC-AQAhewIAvgEAIXwCAL4BACF9AQC9AQAhfgEAvQEAIX8BAMwBACGAAQQAzQEAIYEBBADNAQAhggEEAM4BACGDAUAAwQEAIQIAAABYACAOAABkACACAAAAWAAgDgAAZAAgAwAAAFUAIBUAAF0AIBYAAGIAIAEAAABVACABAAAAWAAgCAYAAMcBACAbAADKAQAgHAAAyQEAIC0AAMgBACAuAADLAQAgfwAAxgEAIIABAADGAQAggQEAAMYBACAQYQAAlAEAMGIAAGsAEGMAAJQBADB3AQCFAQAheAAAlQEAIHkBAIUBACF6AgCGAQAhewIAhgEAIXwCAIYBACF9AQCFAQAhfgEAhQEAIX8BAJYBACGAAQQAlwEAIYEBBACXAQAhggEEAJgBACGDAUAAiQEAIQMAAABYACABAABqADAaAABrACADAAAAWAAgAQAAWQAwAgAAVQAgAQAAAAkAIAEAAAAJACADAAAABwAgAQAACAAwAgAACQAgAwAAAAcAIAEAAAgAMAIAAAkAIAMAAAAHACABAAAIADACAAAJACAKAwAAxQEAIAcAAMQBACBkAQAAAAFlAQAAAAFmAQAAAAFnAQAAAAFoAgAAAAFpCAAAAAFqIAAAAAFrQAAAAAEBDgAAcwAgCGQBAAAAAWUBAAAAAWYBAAAAAWcBAAAAAWgCAAAAAWkIAAAAAWogAAAAAWtAAAAAAQEOAAB1ADABDgAAdQAwCgMAAMMBACAHAADCAQAgZAEAvQEAIWUBAL0BACFmAQC9AQAhZwEAvQEAIWgCAL4BACFpCAC_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_AQCmAQAhgAEEAKcBACGBAQQApwEAIYIBBACoAQAhgwFAAKkBACELbAEAAAABbQEAAAAEbgEAAAAEbwEAAAABcAEAAAABcQEAAAABcgEAAAABcwEAkwEAIXQBAAAAAXUBAAAAAXYBAAAAAQxsgAAAAAFvgAAAAAFwgAAAAAFxgAAAAAFygAAAAAFzgAAAAAGEAQEAAAABhQEBAAAAAYYBAQAAAAGHAYAAAAABiAGAAAAAAYkBgAAAAAEIbAIAAAABbQIAAAAEbgIAAAAEbwIAAAABcAIAAAABcQIAAAABcgIAAAABcwIAiwEAIQtsAQAAAAFtAQAAAAVuAQAAAAVvAQAAAAFwAQAAAAFxAQAAAAFyAQAAAAFzAQCgAQAhdAEAAAABdQEAAAABdgEAAAABCGwEAAAAAW0EAAAABW4EAAAABW8EAAAAAXAEAAAAAXEEAAAAAXIEAAAAAXMEAJ4BACEIbAQAAAABbQQAAAAEbgQAAAAEbwQAAAABcAQAAAABcQQAAAABcgQAAAABcwQAmgEAIQhsQAAAAAFtQAAAAARuQAAAAARvQAAAAAFwQAAAAAFxQAAAAAFyQAAAAAFzQACMAQAhB2EAAKoBADBiAABSABBjAACqAQAwZAEAhQEAIX0BAIUBACF-AQCFAQAhigEBAIUBACEIBQAArAEAIGEAAKsBADBiAAA_ABBjAACrAQAwZAEAowEAIX0BAKMBACF-AQCjAQAhigEBAKMBACEDiwEAAAcAIIwBAAAHACCNAQAABwAgDWEAAK0BADBiAAA5ABBjAACtAQAwZAEAhQEAIWYBAIUBACFnAQCFAQAhaAIAhgEAIWkIAIcBACFqIACIAQAha0AAiQEAIX0BAIUBACF-AQCFAQAhjgEBAIUBACEJYQAArgEAMGIAACMAEGMAAK4BADBkAQCFAQAhggFAAIkBACGPAQEAhQEAIZABAQCFAQAhkQEBAIUBACGSASAAiAEAIQsEAACxAQAgCAAArAEAIGEAAK8BADBiAAAQABBjAACvAQAwZAEAowEAIYIBQACpAQAhjwEBAKMBACGQAQEAowEAIZEBAQCjAQAhkgEgALABACECbCAAAAABcyAAjgEAIQOLAQAAAwAgjAEAAAMAII0BAAADACACZQEAAAABZgEAAAABDQMAALYBACAHAAC1AQAgYQAAswEAMGIAAAcAEGMAALMBADBkAQCjAQAhZQEAowEAIWYBAKMBACFnAQCjAQAhaAIApQEAIWkIALQBACFqIACwAQAha0AAqQEAIQhsCAAAAAFtCAAAAARuCAAAAARvCAAAAAFwCAAAAAFxCAAAAAFyCAAAAAFzCACQAQAhCgUAAKwBACBhAACrAQAwYgAAPwAQYwAAqwEAMGQBAKMBACF9AQCjAQAhfgEAowEAIYoBAQCjAQAhlAEAAD8AIJUBAAA_ACANBAAAsQEAIAgAAKwBACBhAACvAQAwYgAAEAAQYwAArwEAMGQBAKMBACGCAUAAqQEAIY8BAQCjAQAhkAEBAKMBACGRAQEAowEAIZIBIACwAQAhlAEAABAAIJUBAAAQACAOAwAAtgEAIGEAALcBADBiAAADABBjAAC3AQAwZAEAowEAIWYBAKMBACFnAQCjAQAhaAIApQEAIWkIALQBACFqIACwAQAha0AAqQEAIX0BAKMBACF-AQCjAQAhjgEBAKMBACEAAAAAAAGZAQEAAAABBZkBAgAAAAGfAQIAAAABoAECAAAAAaEBAgAAAAGiAQIAAAABBZkBCAAAAAGfAQgAAAABoAEIAAAAAaEBCAAAAAGiAQgAAAABAZkBIAAAAAEBmQFAAAAAAQUVAACRAgAgFgAAlwIAIJYBAACSAgAglwEAAJYCACCcAQAAPAAgBRUAAI8CACAWAACUAgAglgEAAJACACCXAQAAkwIAIJwBAAABACADFQAAkQIAIJYBAACSAgAgnAEAADwAIAMVAACPAgAglgEAAJACACCcAQAAAQAgAAAAAAAAAZkBAQAAAAEFmQEEAAAAAZ8BBAAAAAGgAQQAAAABoQEEAAAAAaIBBAAAAAEFmQEEAAAAAZ8BBAAAAAGgAQQAAAABoQEEAAAAAaIBBAAAAAEAAAALFQAA0wEAMBYAANgBADCWAQAA1AEAMJcBAADVAQAwmAEAANYBACCZAQAA1wEAMJoBAADXAQAwmwEAANcBADCcAQAA1wEAMJ0BAADZAQAwngEAANoBADAIAwAAxQEAIGQBAAAAAWYBAAAAAWcBAAAAAWgCAAAAAWkIAAAAAWogAAAAAWtAAAAAAQIAAAAJACAVAADeAQAgAwAAAAkAIBUAAN4BACAWAADdAQAgAQ4AAI4CADAOAwAAtgEAIAcAALUBACBhAACzAQAwYgAABwAQYwAAswEAMGQBAAAAAWUBAKMBACFmAQCjAQAhZwEAowEAIWgCAKUBACFpCAC0AQAhaiAAsAEAIWtAAKkBACGTAQAAsgEAIAIAAAAJACAOAADdAQAgAgAAANsBACAOAADcAQAgC2EAANoBADBiAADbAQAQYwAA2gEAMGQBAKMBACFlAQCjAQAhZgEAowEAIWcBAKMBACFoAgClAQAhaQgAtAEAIWogALABACFrQACpAQAhC2EAANoBADBiAADbAQAQYwAA2gEAMGQBAKMBACFlAQCjAQAhZgEAowEAIWcBAKMBACFoAgClAQAhaQgAtAEAIWogALABACFrQACpAQAhB2QBAL0BACFmAQC9AQAhZwEAvQEAIWgCAL4BACFpCAC_AQAhaiAAwAEAIWtAAMEBACEIAwAAwwEAIGQBAL0BACFmAQC9AQAhZwEAvQEAIWgCAL4BACFpCAC_AQAhaiAAwAEAIWtAAMEBACEIAwAAxQEAIGQBAAAAAWYBAAAAAWcBAAAAAWgCAAAAAWkIAAAAAWogAAAAAWtAAAAAAQQVAADTAQAwlgEAANQBADCYAQAA1gEAIJwBAADXAQAwAAAAAAAABRUAAIkCACAWAACMAgAglgEAAIoCACCXAQAAiwIAIJwBAAABACADFQAAiQIAIJYBAACKAgAgnAEAAAEAIAAAAAsVAAD2AQAwFgAA-wEAMJYBAAD3AQAwlwEAAPgBADCYAQAA-QEAIJkBAAD6AQAwmgEAAPoBADCbAQAA-gEAMJwBAAD6AQAwnQEAAPwBADCeAQAA_QEAMAsVAADtAQAwFgAA8QEAMJYBAADuAQAwlwEAAO8BADCYAQAA8AEAIJkBAADXAQAwmgEAANcBADCbAQAA1wEAMJwBAADXAQAwnQEAAPIBADCeAQAA2gEAMAgHAADEAQAgZAEAAAABZQEAAAABZwEAAAABaAIAAAABaQgAAAABaiAAAAABa0AAAAABAgAAAAkAIBUAAPUBACADAAAACQAgFQAA9QEAIBYAAPQBACABDgAAiAIAMAIAAAAJACAOAAD0AQAgAgAAANsBACAOAADzAQAgB2QBAL0BACFlAQC9AQAhZwEAvQEAIWgCAL4BACFpCAC_AQAhaiAAwAEAIWtAAMEBACEIBwAAwgEAIGQBAL0BACFlAQC9AQAhZwEAvQEAIWgCAL4BACFpCAC_AQAhaiAAwAEAIWtAAMEBACEIBwAAxAEAIGQBAAAAAWUBAAAAAWcBAAAAAWgCAAAAAWkIAAAAAWogAAAAAWtAAAAAAQlkAQAAAAFnAQAAAAFoAgAAAAFpCAAAAAFqIAAAAAFrQAAAAAF9AQAAAAF-AQAAAAGOAQEAAAABAgAAAAUAIBUAAIECACADAAAABQAgFQAAgQIAIBYAAIACACABDgAAhwIAMA4DAAC2AQAgYQAAtwEAMGIAAAMAEGMAALcBADBkAQAAAAFmAQCjAQAhZwEAowEAIWgCAKUBACFpCAC0AQAhaiAAsAEAIWtAAKkBACF9AQCjAQAhfgEAowEAIY4BAQCjAQAhAgAAAAUAIA4AAIACACACAAAA_gEAIA4AAP8BACANYQAA_QEAMGIAAP4BABBjAAD9AQAwZAEAowEAIWYBAKMBACFnAQCjAQAhaAIApQEAIWkIALQBACFqIACwAQAha0AAqQEAIX0BAKMBACF-AQCjAQAhjgEBAKMBACENYQAA_QEAMGIAAP4BABBjAAD9AQAwZAEAowEAIWYBAKMBACFnAQCjAQAhaAIApQEAIWkIALQBACFqIACwAQAha0AAqQEAIX0BAKMBACF-AQCjAQAhjgEBAKMBACEJZAEAvQEAIWcBAL0BACFoAgC-AQAhaQgAvwEAIWogAMABACFrQADBAQAhfQEAvQEAIX4BAL0BACGOAQEAvQEAIQlkAQC9AQAhZwEAvQEAIWgCAL4BACFpCAC_AQAhaiAAwAEAIWtAAMEBACF9AQC9AQAhfgEAvQEAIY4BAQC9AQAhCWQBAAAAAWcBAAAAAWgCAAAAAWkIAAAAAWogAAAAAWtAAAAAAX0BAAAAAX4BAAAAAY4BAQAAAAEEFQAA9gEAMJYBAAD3AQAwmAEAAPkBACCcAQAA-gEAMAQVAADtAQAwlgEAAO4BADCYAQAA8AEAIJwBAADXAQAwAAEFAADgAQAgAgQAAIQCACAIAADgAQAgCWQBAAAAAWcBAAAAAWgCAAAAAWkIAAAAAWogAAAAAWtAAAAAAX0BAAAAAX4BAAAAAY4BAQAAAAEHZAEAAAABZQEAAAABZwEAAAABaAIAAAABaQgAAAABaiAAAAABa0AAAAABBwgAAIMCACBkAQAAAAGCAUAAAAABjwEBAAAAAZABAQAAAAGRAQEAAAABkgEgAAAAAQIAAAABACAVAACJAgAgAwAAABAAIBUAAIkCACAWAACNAgAgCQAAABAAIAgAAOwBACAOAACNAgAgZAEAvQEAIYIBQADBAQAhjwEBAL0BACGQAQEAvQEAIZEBAQC9AQAhkgEgAMABACEHCAAA7AEAIGQBAL0BACGCAUAAwQEAIY8BAQC9AQAhkAEBAL0BACGRAQEAvQEAIZIBIADAAQAhB2QBAAAAAWYBAAAAAWcBAAAAAWgCAAAAAWkIAAAAAWogAAAAAWtAAAAAAQcEAACCAgAgZAEAAAABggFAAAAAAY8BAQAAAAGQAQEAAAABkQEBAAAAAZIBIAAAAAECAAAAAQAgFQAAjwIAIARkAQAAAAF9AQAAAAF-AQAAAAGKAQEAAAABAgAAADwAIBUAAJECACADAAAAEAAgFQAAjwIAIBYAAJUCACAJAAAAEAAgBAAA6wEAIA4AAJUCACBkAQC9AQAhggFAAMEBACGPAQEAvQEAIZABAQC9AQAhkQEBAL0BACGSASAAwAEAIQcEAADrAQAgZAEAvQEAIYIBQADBAQAhjwEBAL0BACGQAQEAvQEAIZEBAQC9AQAhkgEgAMABACEDAAAAPwAgFQAAkQIAIBYAAJgCACAGAAAAPwAgDgAAmAIAIGQBAL0BACF9AQC9AQAhfgEAvQEAIYoBAQC9AQAhBGQBAL0BACF9AQC9AQAhfgEAvQEAIYoBAQC9AQAhAwQGAgYABggKAwEDAAECAwABBwAEAgULAwYABQEFDAACBA0ACA4AAAAAAwYACxsADBwADQAAAAMGAAsbAAwcAA0BAwABAQMAAQUGABIbABUcABYtABMuABQAAAAAAAUGABIbABUcABYtABMuABQAAAMGABsbABwcAB0AAAADBgAbGwAcHAAdAAAABQYAIxsAJhwAJy0AJC4AJQAAAAAABQYAIxsAJhwAJy0AJC4AJQIDAAEHAAQCAwABBwAEBQYALBsALxwAMC0ALS4ALgAAAAAABQYALBsALxwAMC0ALS4ALgkCAQoPAQsSAQwTAQ0UAQ8WARAYBxEZCBIbARMdBxQeCRcfARggARkhBx0kCh4lDh8mAiAnAiEoAiIpAiMqAiQsAiUuByYvDycxAigzByk0ECo1Ais2Aiw3By86ETA7FzE9BDI-BDNBBDRCBDVDBDZFBDdHBzhIGDlKBDpMBztNGTxOBD1PBD5QBz9TGkBUHkFWH0JXH0NaH0RbH0VcH0ZeH0dgB0hhIEljH0plB0tmIUxnH01oH05pB09sIlBtKFFuA1JvA1NwA1RxA1VyA1Z0A1d2B1h3KVl5A1p7B1t8Klx9A11-A15_B1-CAStggwEx" + strings: JSON.parse("[\"where\",\"orderBy\",\"cursor\",\"user\",\"games\",\"results\",\"_count\",\"puzzle\",\"dailyResults\",\"User.findUnique\",\"User.findUniqueOrThrow\",\"User.findFirst\",\"User.findFirstOrThrow\",\"User.findMany\",\"data\",\"User.createOne\",\"User.createMany\",\"User.createManyAndReturn\",\"User.updateOne\",\"User.updateMany\",\"User.updateManyAndReturn\",\"create\",\"update\",\"User.upsertOne\",\"User.deleteOne\",\"User.deleteMany\",\"having\",\"_min\",\"_max\",\"User.groupBy\",\"User.aggregate\",\"Game.findUnique\",\"Game.findUniqueOrThrow\",\"Game.findFirst\",\"Game.findFirstOrThrow\",\"Game.findMany\",\"Game.createOne\",\"Game.createMany\",\"Game.createManyAndReturn\",\"Game.updateOne\",\"Game.updateMany\",\"Game.updateManyAndReturn\",\"Game.upsertOne\",\"Game.deleteOne\",\"Game.deleteMany\",\"_avg\",\"_sum\",\"Game.groupBy\",\"Game.aggregate\",\"DailyPuzzle.findUnique\",\"DailyPuzzle.findUniqueOrThrow\",\"DailyPuzzle.findFirst\",\"DailyPuzzle.findFirstOrThrow\",\"DailyPuzzle.findMany\",\"DailyPuzzle.createOne\",\"DailyPuzzle.createMany\",\"DailyPuzzle.createManyAndReturn\",\"DailyPuzzle.updateOne\",\"DailyPuzzle.updateMany\",\"DailyPuzzle.updateManyAndReturn\",\"DailyPuzzle.upsertOne\",\"DailyPuzzle.deleteOne\",\"DailyPuzzle.deleteMany\",\"DailyPuzzle.groupBy\",\"DailyPuzzle.aggregate\",\"Room.findUnique\",\"Room.findUniqueOrThrow\",\"Room.findFirst\",\"Room.findFirstOrThrow\",\"Room.findMany\",\"Room.createOne\",\"Room.createMany\",\"Room.createManyAndReturn\",\"Room.updateOne\",\"Room.updateMany\",\"Room.updateManyAndReturn\",\"Room.upsertOne\",\"Room.deleteOne\",\"Room.deleteMany\",\"Room.groupBy\",\"Room.aggregate\",\"DailyResult.findUnique\",\"DailyResult.findUniqueOrThrow\",\"DailyResult.findFirst\",\"DailyResult.findFirstOrThrow\",\"DailyResult.findMany\",\"DailyResult.createOne\",\"DailyResult.createMany\",\"DailyResult.createManyAndReturn\",\"DailyResult.updateOne\",\"DailyResult.updateMany\",\"DailyResult.updateManyAndReturn\",\"DailyResult.upsertOne\",\"DailyResult.deleteOne\",\"DailyResult.deleteMany\",\"DailyResult.groupBy\",\"DailyResult.aggregate\",\"AND\",\"OR\",\"NOT\",\"id\",\"puzzleId\",\"userId\",\"path\",\"clicks\",\"timeSeconds\",\"won\",\"playedAt\",\"equals\",\"in\",\"notIn\",\"lt\",\"lte\",\"gt\",\"gte\",\"not\",\"contains\",\"startsWith\",\"endsWith\",\"code\",\"players\",\"phase\",\"round\",\"totalRounds\",\"maxPlayers\",\"gameMode\",\"startArticle\",\"targetArticle\",\"roundWinner\",\"countdownStart\",\"roundStart\",\"createdAt\",\"updatedAt\",\"string_contains\",\"string_starts_with\",\"string_ends_with\",\"array_starts_with\",\"array_ends_with\",\"array_contains\",\"date\",\"every\",\"some\",\"none\",\"mode\",\"name\",\"email\",\"password\",\"banned\",\"puzzleId_userId\",\"is\",\"isNot\",\"connectOrCreate\",\"upsert\",\"createMany\",\"set\",\"disconnect\",\"delete\",\"connect\",\"updateMany\",\"deleteMany\",\"increment\",\"decrement\",\"multiply\",\"divide\"]"), + graph: "mAIxUAsEAACxAQAgCAAArAEAIGEAAK8BADBiAAAQABBjAACvAQAwZAEAAAABgwFAAKkBACGQAQEAowEAIZEBAQAAAAGSAQEAowEAIZMBIACwAQAhAQAAAAEAIA4DAAC2AQAgYQAAtwEAMGIAAAMAEGMAALcBADBkAQCjAQAhZgEAowEAIWcBAKMBACFoAgClAQAhaQgAtAEAIWogALABACFrQACpAQAhfgEAowEAIX8BAKMBACGPAQEAowEAIQEDAACGAgAgDgMAALYBACBhAAC3AQAwYgAAAwAQYwAAtwEAMGQBAAAAAWYBAKMBACFnAQCjAQAhaAIApQEAIWkIALQBACFqIACwAQAha0AAqQEAIX4BAKMBACF_AQCjAQAhjwEBAKMBACEDAAAAAwAgAQAABAAwAgAABQAgDQMAALYBACAHAAC1AQAgYQAAswEAMGIAAAcAEGMAALMBADBkAQCjAQAhZQEAowEAIWYBAKMBACFnAQCjAQAhaAIApQEAIWkIALQBACFqIACwAQAha0AAqQEAIQIDAACGAgAgBwAAhQIAIA4DAAC2AQAgBwAAtQEAIGEAALMBADBiAAAHABBjAACzAQAwZAEAAAABZQEAowEAIWYBAKMBACFnAQCjAQAhaAIApQEAIWkIALQBACFqIACwAQAha0AAqQEAIZQBAACyAQAgAwAAAAcAIAEAAAgAMAIAAAkAIAMAAAAHACABAAAIADACAAAJACABAAAABwAgAQAAAAMAIAEAAAAHACABAAAAAQAgCwQAALEBACAIAACsAQAgYQAArwEAMGIAABAAEGMAAK8BADBkAQCjAQAhgwFAAKkBACGQAQEAowEAIZEBAQCjAQAhkgEBAKMBACGTASAAsAEAIQIEAACEAgAgCAAA4AEAIAMAAAAQACABAAARADACAAABACADAAAAEAAgAQAAEQAwAgAAAQAgAwAAABAAIAEAABEAMAIAAAEAIAgEAACCAgAgCAAAgwIAIGQBAAAAAYMBQAAAAAGQAQEAAAABkQEBAAAAAZIBAQAAAAGTASAAAAABAQ4AABUAIAZkAQAAAAGDAUAAAAABkAEBAAAAAZEBAQAAAAGSAQEAAAABkwEgAAAAAQEOAAAXADABDgAAFwAwCAQAAOsBACAIAADsAQAgZAEAvQEAIYMBQADBAQAhkAEBAL0BACGRAQEAvQEAIZIBAQC9AQAhkwEgAMABACECAAAAAQAgDgAAGgAgBmQBAL0BACGDAUAAwQEAIZABAQC9AQAhkQEBAL0BACGSAQEAvQEAIZMBIADAAQAhAgAAABAAIA4AABwAIAIAAAAQACAOAAAcACADAAAAAQAgFQAAFQAgFgAAGgAgAQAAAAEAIAEAAAAQACADBgAA6AEAIBsAAOoBACAcAADpAQAgCWEAAK4BADBiAAAjABBjAACuAQAwZAEAhQEAIYMBQACJAQAhkAEBAIUBACGRAQEAhQEAIZIBAQCFAQAhkwEgAIgBACEDAAAAEAAgAQAAIgAwGgAAIwAgAwAAABAAIAEAABEAMAIAAAEAIAEAAAAFACABAAAABQAgAwAAAAMAIAEAAAQAMAIAAAUAIAMAAAADACABAAAEADACAAAFACADAAAAAwAgAQAABAAwAgAABQAgCwMAAOcBACBkAQAAAAFmAQAAAAFnAQAAAAFoAgAAAAFpCAAAAAFqIAAAAAFrQAAAAAF-AQAAAAF_AQAAAAGPAQEAAAABAQ4AACsAIApkAQAAAAFmAQAAAAFnAQAAAAFoAgAAAAFpCAAAAAFqIAAAAAFrQAAAAAF-AQAAAAF_AQAAAAGPAQEAAAABAQ4AAC0AMAEOAAAtADALAwAA5gEAIGQBAL0BACFmAQC9AQAhZwEAvQEAIWgCAL4BACFpCAC_AQAhaiAAwAEAIWtAAMEBACF-AQC9AQAhfwEAvQEAIY8BAQC9AQAhAgAAAAUAIA4AADAAIApkAQC9AQAhZgEAvQEAIWcBAL0BACFoAgC-AQAhaQgAvwEAIWogAMABACFrQADBAQAhfgEAvQEAIX8BAL0BACGPAQEAvQEAIQIAAAADACAOAAAyACACAAAAAwAgDgAAMgAgAwAAAAUAIBUAACsAIBYAADAAIAEAAAAFACABAAAAAwAgBQYAAOEBACAbAADkAQAgHAAA4wEAIC0AAOIBACAuAADlAQAgDWEAAK0BADBiAAA5ABBjAACtAQAwZAEAhQEAIWYBAIUBACFnAQCFAQAhaAIAhgEAIWkIAIcBACFqIACIAQAha0AAiQEAIX4BAIUBACF_AQCFAQAhjwEBAIUBACEDAAAAAwAgAQAAOAAwGgAAOQAgAwAAAAMAIAEAAAQAMAIAAAUAIAgFAACsAQAgYQAAqwEAMGIAAD8AEGMAAKsBADBkAQAAAAF-AQCjAQAhfwEAowEAIYsBAQAAAAEBAAAAPAAgAQAAADwAIAgFAACsAQAgYQAAqwEAMGIAAD8AEGMAAKsBADBkAQCjAQAhfgEAowEAIX8BAKMBACGLAQEAowEAIQEFAADgAQAgAwAAAD8AIAEAAEAAMAIAADwAIAMAAAA_ACABAABAADACAAA8ACADAAAAPwAgAQAAQAAwAgAAPAAgBQUAAN8BACBkAQAAAAF-AQAAAAF_AQAAAAGLAQEAAAABAQ4AAEQAIARkAQAAAAF-AQAAAAF_AQAAAAGLAQEAAAABAQ4AAEYAMAEOAABGADAFBQAA0gEAIGQBAL0BACF-AQC9AQAhfwEAvQEAIYsBAQC9AQAhAgAAADwAIA4AAEkAIARkAQC9AQAhfgEAvQEAIX8BAL0BACGLAQEAvQEAIQIAAAA_ACAOAABLACACAAAAPwAgDgAASwAgAwAAADwAIBUAAEQAIBYAAEkAIAEAAAA8ACABAAAAPwAgAwYAAM8BACAbAADRAQAgHAAA0AEAIAdhAACqAQAwYgAAUgAQYwAAqgEAMGQBAIUBACF-AQCFAQAhfwEAhQEAIYsBAQCFAQAhAwAAAD8AIAEAAFEAMBoAAFIAIAMAAAA_ACABAABAADACAAA8ACARYQAAogEAMGIAAFgAEGMAAKIBADB3AQAAAAF4AACkAQAgeQEAowEAIXoCAKUBACF7AgClAQAhfAIApQEAIX0BAKMBACF-AQCjAQAhfwEAowEAIYABAQCmAQAhgQEEAKcBACGCAQQApwEAIYMBBACoAQAhhAFAAKkBACEBAAAAVQAgAQAAAFUAIBFhAACiAQAwYgAAWAAQYwAAogEAMHcBAKMBACF4AACkAQAgeQEAowEAIXoCAKUBACF7AgClAQAhfAIApQEAIX0BAKMBACF-AQCjAQAhfwEAowEAIYABAQCmAQAhgQEEAKcBACGCAQQApwEAIYMBBACoAQAhhAFAAKkBACEDgAEAAMYBACCBAQAAxgEAIIIBAADGAQAgAwAAAFgAIAEAAFkAMAIAAFUAIAMAAABYACABAABZADACAABVACADAAAAWAAgAQAAWQAwAgAAVQAgDncBAAAAAXiAAAAAAXkBAAAAAXoCAAAAAXsCAAAAAXwCAAAAAX0BAAAAAX4BAAAAAX8BAAAAAYABAQAAAAGBAQQAAAABggEEAAAAAYMBBAAAAAGEAUAAAAABAQ4AAF0AIA53AQAAAAF4gAAAAAF5AQAAAAF6AgAAAAF7AgAAAAF8AgAAAAF9AQAAAAF-AQAAAAF_AQAAAAGAAQEAAAABgQEEAAAAAYIBBAAAAAGDAQQAAAABhAFAAAAAAQEOAABfADABDgAAXwAwDncBAL0BACF4gAAAAAF5AQC9AQAhegIAvgEAIXsCAL4BACF8AgC-AQAhfQEAvQEAIX4BAL0BACF_AQC9AQAhgAEBAMwBACGBAQQAzQEAIYIBBADNAQAhgwEEAM4BACGEAUAAwQEAIQIAAABVACAOAABiACAOdwEAvQEAIXiAAAAAAXkBAL0BACF6AgC-AQAhewIAvgEAIXwCAL4BACF9AQC9AQAhfgEAvQEAIX8BAL0BACGAAQEAzAEAIYEBBADNAQAhggEEAM0BACGDAQQAzgEAIYQBQADBAQAhAgAAAFgAIA4AAGQAIAIAAABYACAOAABkACADAAAAVQAgFQAAXQAgFgAAYgAgAQAAAFUAIAEAAABYACAIBgAAxwEAIBsAAMoBACAcAADJAQAgLQAAyAEAIC4AAMsBACCAAQAAxgEAIIEBAADGAQAgggEAAMYBACARYQAAlAEAMGIAAGsAEGMAAJQBADB3AQCFAQAheAAAlQEAIHkBAIUBACF6AgCGAQAhewIAhgEAIXwCAIYBACF9AQCFAQAhfgEAhQEAIX8BAIUBACGAAQEAlgEAIYEBBACXAQAhggEEAJcBACGDAQQAmAEAIYQBQACJAQAhAwAAAFgAIAEAAGoAMBoAAGsAIAMAAABYACABAABZADACAABVACABAAAACQAgAQAAAAkAIAMAAAAHACABAAAIADACAAAJACADAAAABwAgAQAACAAwAgAACQAgAwAAAAcAIAEAAAgAMAIAAAkAIAoDAADFAQAgBwAAxAEAIGQBAAAAAWUBAAAAAWYBAAAAAWcBAAAAAWgCAAAAAWkIAAAAAWogAAAAAWtAAAAAAQEOAABzACAIZAEAAAABZQEAAAABZgEAAAABZwEAAAABaAIAAAABaQgAAAABaiAAAAABa0AAAAABAQ4AAHUAMAEOAAB1ADAKAwAAwwEAIAcAAMIBACBkAQC9AQAhZQEAvQEAIWYBAL0BACFnAQC9AQAhaAIAvgEAIWkIAL8BACFqIADAAQAha0AAwQEAIQIAAAAJACAOAAB4ACAIZAEAvQEAIWUBAL0BACFmAQC9AQAhZwEAvQEAIWgCAL4BACFpCAC_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_AQCFAQAhiwEBAIUBACEIBQAArAEAIGEAAKsBADBiAAA_ABBjAACrAQAwZAEAowEAIX4BAKMBACF_AQCjAQAhiwEBAKMBACEDjAEAAAcAII0BAAAHACCOAQAABwAgDWEAAK0BADBiAAA5ABBjAACtAQAwZAEAhQEAIWYBAIUBACFnAQCFAQAhaAIAhgEAIWkIAIcBACFqIACIAQAha0AAiQEAIX4BAIUBACF_AQCFAQAhjwEBAIUBACEJYQAArgEAMGIAACMAEGMAAK4BADBkAQCFAQAhgwFAAIkBACGQAQEAhQEAIZEBAQCFAQAhkgEBAIUBACGTASAAiAEAIQsEAACxAQAgCAAArAEAIGEAAK8BADBiAAAQABBjAACvAQAwZAEAowEAIYMBQACpAQAhkAEBAKMBACGRAQEAowEAIZIBAQCjAQAhkwEgALABACECbCAAAAABcyAAjgEAIQOMAQAAAwAgjQEAAAMAII4BAAADACACZQEAAAABZgEAAAABDQMAALYBACAHAAC1AQAgYQAAswEAMGIAAAcAEGMAALMBADBkAQCjAQAhZQEAowEAIWYBAKMBACFnAQCjAQAhaAIApQEAIWkIALQBACFqIACwAQAha0AAqQEAIQhsCAAAAAFtCAAAAARuCAAAAARvCAAAAAFwCAAAAAFxCAAAAAFyCAAAAAFzCACQAQAhCgUAAKwBACBhAACrAQAwYgAAPwAQYwAAqwEAMGQBAKMBACF-AQCjAQAhfwEAowEAIYsBAQCjAQAhlQEAAD8AIJYBAAA_ACANBAAAsQEAIAgAAKwBACBhAACvAQAwYgAAEAAQYwAArwEAMGQBAKMBACGDAUAAqQEAIZABAQCjAQAhkQEBAKMBACGSAQEAowEAIZMBIACwAQAhlQEAABAAIJYBAAAQACAOAwAAtgEAIGEAALcBADBiAAADABBjAAC3AQAwZAEAowEAIWYBAKMBACFnAQCjAQAhaAIApQEAIWkIALQBACFqIACwAQAha0AAqQEAIX4BAKMBACF_AQCjAQAhjwEBAKMBACEAAAAAAAGaAQEAAAABBZoBAgAAAAGgAQIAAAABoQECAAAAAaIBAgAAAAGjAQIAAAABBZoBCAAAAAGgAQgAAAABoQEIAAAAAaIBCAAAAAGjAQgAAAABAZoBIAAAAAEBmgFAAAAAAQUVAACRAgAgFgAAlwIAIJcBAACSAgAgmAEAAJYCACCdAQAAPAAgBRUAAI8CACAWAACUAgAglwEAAJACACCYAQAAkwIAIJ0BAAABACADFQAAkQIAIJcBAACSAgAgnQEAADwAIAMVAACPAgAglwEAAJACACCdAQAAAQAgAAAAAAAAAZoBAQAAAAEFmgEEAAAAAaABBAAAAAGhAQQAAAABogEEAAAAAaMBBAAAAAEFmgEEAAAAAaABBAAAAAGhAQQAAAABogEEAAAAAaMBBAAAAAEAAAALFQAA0wEAMBYAANgBADCXAQAA1AEAMJgBAADVAQAwmQEAANYBACCaAQAA1wEAMJsBAADXAQAwnAEAANcBADCdAQAA1wEAMJ4BAADZAQAwnwEAANoBADAIAwAAxQEAIGQBAAAAAWYBAAAAAWcBAAAAAWgCAAAAAWkIAAAAAWogAAAAAWtAAAAAAQIAAAAJACAVAADeAQAgAwAAAAkAIBUAAN4BACAWAADdAQAgAQ4AAI4CADAOAwAAtgEAIAcAALUBACBhAACzAQAwYgAABwAQYwAAswEAMGQBAAAAAWUBAKMBACFmAQCjAQAhZwEAowEAIWgCAKUBACFpCAC0AQAhaiAAsAEAIWtAAKkBACGUAQAAsgEAIAIAAAAJACAOAADdAQAgAgAAANsBACAOAADcAQAgC2EAANoBADBiAADbAQAQYwAA2gEAMGQBAKMBACFlAQCjAQAhZgEAowEAIWcBAKMBACFoAgClAQAhaQgAtAEAIWogALABACFrQACpAQAhC2EAANoBADBiAADbAQAQYwAA2gEAMGQBAKMBACFlAQCjAQAhZgEAowEAIWcBAKMBACFoAgClAQAhaQgAtAEAIWogALABACFrQACpAQAhB2QBAL0BACFmAQC9AQAhZwEAvQEAIWgCAL4BACFpCAC_AQAhaiAAwAEAIWtAAMEBACEIAwAAwwEAIGQBAL0BACFmAQC9AQAhZwEAvQEAIWgCAL4BACFpCAC_AQAhaiAAwAEAIWtAAMEBACEIAwAAxQEAIGQBAAAAAWYBAAAAAWcBAAAAAWgCAAAAAWkIAAAAAWogAAAAAWtAAAAAAQQVAADTAQAwlwEAANQBADCZAQAA1gEAIJ0BAADXAQAwAAAAAAAABRUAAIkCACAWAACMAgAglwEAAIoCACCYAQAAiwIAIJ0BAAABACADFQAAiQIAIJcBAACKAgAgnQEAAAEAIAAAAAsVAAD2AQAwFgAA-wEAMJcBAAD3AQAwmAEAAPgBADCZAQAA-QEAIJoBAAD6AQAwmwEAAPoBADCcAQAA-gEAMJ0BAAD6AQAwngEAAPwBADCfAQAA_QEAMAsVAADtAQAwFgAA8QEAMJcBAADuAQAwmAEAAO8BADCZAQAA8AEAIJoBAADXAQAwmwEAANcBADCcAQAA1wEAMJ0BAADXAQAwngEAAPIBADCfAQAA2gEAMAgHAADEAQAgZAEAAAABZQEAAAABZwEAAAABaAIAAAABaQgAAAABaiAAAAABa0AAAAABAgAAAAkAIBUAAPUBACADAAAACQAgFQAA9QEAIBYAAPQBACABDgAAiAIAMAIAAAAJACAOAAD0AQAgAgAAANsBACAOAADzAQAgB2QBAL0BACFlAQC9AQAhZwEAvQEAIWgCAL4BACFpCAC_AQAhaiAAwAEAIWtAAMEBACEIBwAAwgEAIGQBAL0BACFlAQC9AQAhZwEAvQEAIWgCAL4BACFpCAC_AQAhaiAAwAEAIWtAAMEBACEIBwAAxAEAIGQBAAAAAWUBAAAAAWcBAAAAAWgCAAAAAWkIAAAAAWogAAAAAWtAAAAAAQlkAQAAAAFnAQAAAAFoAgAAAAFpCAAAAAFqIAAAAAFrQAAAAAF-AQAAAAF_AQAAAAGPAQEAAAABAgAAAAUAIBUAAIECACADAAAABQAgFQAAgQIAIBYAAIACACABDgAAhwIAMA4DAAC2AQAgYQAAtwEAMGIAAAMAEGMAALcBADBkAQAAAAFmAQCjAQAhZwEAowEAIWgCAKUBACFpCAC0AQAhaiAAsAEAIWtAAKkBACF-AQCjAQAhfwEAowEAIY8BAQCjAQAhAgAAAAUAIA4AAIACACACAAAA_gEAIA4AAP8BACANYQAA_QEAMGIAAP4BABBjAAD9AQAwZAEAowEAIWYBAKMBACFnAQCjAQAhaAIApQEAIWkIALQBACFqIACwAQAha0AAqQEAIX4BAKMBACF_AQCjAQAhjwEBAKMBACENYQAA_QEAMGIAAP4BABBjAAD9AQAwZAEAowEAIWYBAKMBACFnAQCjAQAhaAIApQEAIWkIALQBACFqIACwAQAha0AAqQEAIX4BAKMBACF_AQCjAQAhjwEBAKMBACEJZAEAvQEAIWcBAL0BACFoAgC-AQAhaQgAvwEAIWogAMABACFrQADBAQAhfgEAvQEAIX8BAL0BACGPAQEAvQEAIQlkAQC9AQAhZwEAvQEAIWgCAL4BACFpCAC_AQAhaiAAwAEAIWtAAMEBACF-AQC9AQAhfwEAvQEAIY8BAQC9AQAhCWQBAAAAAWcBAAAAAWgCAAAAAWkIAAAAAWogAAAAAWtAAAAAAX4BAAAAAX8BAAAAAY8BAQAAAAEEFQAA9gEAMJcBAAD3AQAwmQEAAPkBACCdAQAA-gEAMAQVAADtAQAwlwEAAO4BADCZAQAA8AEAIJ0BAADXAQAwAAEFAADgAQAgAgQAAIQCACAIAADgAQAgCWQBAAAAAWcBAAAAAWgCAAAAAWkIAAAAAWogAAAAAWtAAAAAAX4BAAAAAX8BAAAAAY8BAQAAAAEHZAEAAAABZQEAAAABZwEAAAABaAIAAAABaQgAAAABaiAAAAABa0AAAAABBwgAAIMCACBkAQAAAAGDAUAAAAABkAEBAAAAAZEBAQAAAAGSAQEAAAABkwEgAAAAAQIAAAABACAVAACJAgAgAwAAABAAIBUAAIkCACAWAACNAgAgCQAAABAAIAgAAOwBACAOAACNAgAgZAEAvQEAIYMBQADBAQAhkAEBAL0BACGRAQEAvQEAIZIBAQC9AQAhkwEgAMABACEHCAAA7AEAIGQBAL0BACGDAUAAwQEAIZABAQC9AQAhkQEBAL0BACGSAQEAvQEAIZMBIADAAQAhB2QBAAAAAWYBAAAAAWcBAAAAAWgCAAAAAWkIAAAAAWogAAAAAWtAAAAAAQcEAACCAgAgZAEAAAABgwFAAAAAAZABAQAAAAGRAQEAAAABkgEBAAAAAZMBIAAAAAECAAAAAQAgFQAAjwIAIARkAQAAAAF-AQAAAAF_AQAAAAGLAQEAAAABAgAAADwAIBUAAJECACADAAAAEAAgFQAAjwIAIBYAAJUCACAJAAAAEAAgBAAA6wEAIA4AAJUCACBkAQC9AQAhgwFAAMEBACGQAQEAvQEAIZEBAQC9AQAhkgEBAL0BACGTASAAwAEAIQcEAADrAQAgZAEAvQEAIYMBQADBAQAhkAEBAL0BACGRAQEAvQEAIZIBAQC9AQAhkwEgAMABACEDAAAAPwAgFQAAkQIAIBYAAJgCACAGAAAAPwAgDgAAmAIAIGQBAL0BACF-AQC9AQAhfwEAvQEAIYsBAQC9AQAhBGQBAL0BACF-AQC9AQAhfwEAvQEAIYsBAQC9AQAhAwQGAgYABggKAwEDAAECAwABBwAEAgULAwYABQEFDAACBA0ACA4AAAAAAwYACxsADBwADQAAAAMGAAsbAAwcAA0BAwABAQMAAQUGABIbABUcABYtABMuABQAAAAAAAUGABIbABUcABYtABMuABQAAAMGABsbABwcAB0AAAADBgAbGwAcHAAdAAAABQYAIxsAJhwAJy0AJC4AJQAAAAAABQYAIxsAJhwAJy0AJC4AJQIDAAEHAAQCAwABBwAEBQYALBsALxwAMC0ALS4ALgAAAAAABQYALBsALxwAMC0ALS4ALgkCAQoPAQsSAQwTAQ0UAQ8WARAYBxEZCBIbARMdBxQeCRcfARggARkhBx0kCh4lDh8mAiAnAiEoAiIpAiMqAiQsAiUuByYvDycxAigzByk0ECo1Ais2Aiw3By86ETA7FzE9BDI-BDNBBDRCBDVDBDZFBDdHBzhIGDlKBDpMBztNGTxOBD1PBD5QBz9TGkBUHkFWH0JXH0NaH0RbH0VcH0ZeH0dgB0hhIEljH0plB0tmIUxnH01oH05pB09sIlBtKFFuA1JvA1NwA1RxA1VyA1Z0A1d2B1h3KVl5A1p7B1t8Klx9A11-A15_B1-CAStggwEx" } async function decodeBase64AsWasm(wasmBase64: string): Promise { diff --git a/lib/generated/prisma/internal/prismaNamespace.ts b/lib/generated/prisma/internal/prismaNamespace.ts index b1045c0..2db87a3 100644 --- a/lib/generated/prisma/internal/prismaNamespace.ts +++ b/lib/generated/prisma/internal/prismaNamespace.ts @@ -862,6 +862,7 @@ export const RoomScalarFieldEnum = { round: 'round', totalRounds: 'totalRounds', maxPlayers: 'maxPlayers', + gameMode: 'gameMode', startArticle: 'startArticle', targetArticle: 'targetArticle', roundWinner: 'roundWinner', diff --git a/lib/generated/prisma/internal/prismaNamespaceBrowser.ts b/lib/generated/prisma/internal/prismaNamespaceBrowser.ts index f189461..615a8f2 100644 --- a/lib/generated/prisma/internal/prismaNamespaceBrowser.ts +++ b/lib/generated/prisma/internal/prismaNamespaceBrowser.ts @@ -119,6 +119,7 @@ export const RoomScalarFieldEnum = { round: 'round', totalRounds: 'totalRounds', maxPlayers: 'maxPlayers', + gameMode: 'gameMode', startArticle: 'startArticle', targetArticle: 'targetArticle', roundWinner: 'roundWinner', diff --git a/lib/generated/prisma/models/Room.ts b/lib/generated/prisma/models/Room.ts index 7150a69..b71465b 100644 --- a/lib/generated/prisma/models/Room.ts +++ b/lib/generated/prisma/models/Room.ts @@ -50,6 +50,7 @@ export type RoomMinAggregateOutputType = { round: number | null totalRounds: number | null maxPlayers: number | null + gameMode: string | null startArticle: string | null targetArticle: string | null roundWinner: string | null @@ -65,6 +66,7 @@ export type RoomMaxAggregateOutputType = { round: number | null totalRounds: number | null maxPlayers: number | null + gameMode: string | null startArticle: string | null targetArticle: string | null roundWinner: string | null @@ -81,6 +83,7 @@ export type RoomCountAggregateOutputType = { round: number totalRounds: number maxPlayers: number + gameMode: number startArticle: number targetArticle: number roundWinner: number @@ -116,6 +119,7 @@ export type RoomMinAggregateInputType = { round?: true totalRounds?: true maxPlayers?: true + gameMode?: true startArticle?: true targetArticle?: true roundWinner?: true @@ -131,6 +135,7 @@ export type RoomMaxAggregateInputType = { round?: true totalRounds?: true maxPlayers?: true + gameMode?: true startArticle?: true targetArticle?: true roundWinner?: true @@ -147,6 +152,7 @@ export type RoomCountAggregateInputType = { round?: true totalRounds?: true maxPlayers?: true + gameMode?: true startArticle?: true targetArticle?: true roundWinner?: true @@ -250,6 +256,7 @@ export type RoomGroupByOutputType = { round: number totalRounds: number maxPlayers: number + gameMode: string startArticle: string targetArticle: string roundWinner: string | null @@ -289,6 +296,7 @@ export type RoomWhereInput = { round?: Prisma.IntFilter<"Room"> | number totalRounds?: Prisma.IntFilter<"Room"> | number maxPlayers?: Prisma.IntFilter<"Room"> | number + gameMode?: Prisma.StringFilter<"Room"> | string startArticle?: Prisma.StringFilter<"Room"> | string targetArticle?: Prisma.StringFilter<"Room"> | string roundWinner?: Prisma.StringNullableFilter<"Room"> | string | null @@ -305,6 +313,7 @@ export type RoomOrderByWithRelationInput = { round?: Prisma.SortOrder totalRounds?: Prisma.SortOrder maxPlayers?: Prisma.SortOrder + gameMode?: Prisma.SortOrder startArticle?: Prisma.SortOrder targetArticle?: Prisma.SortOrder roundWinner?: Prisma.SortOrderInput | Prisma.SortOrder @@ -324,6 +333,7 @@ export type RoomWhereUniqueInput = Prisma.AtLeast<{ round?: Prisma.IntFilter<"Room"> | number totalRounds?: Prisma.IntFilter<"Room"> | number maxPlayers?: Prisma.IntFilter<"Room"> | number + gameMode?: Prisma.StringFilter<"Room"> | string startArticle?: Prisma.StringFilter<"Room"> | string targetArticle?: Prisma.StringFilter<"Room"> | string roundWinner?: Prisma.StringNullableFilter<"Room"> | string | null @@ -340,6 +350,7 @@ export type RoomOrderByWithAggregationInput = { round?: Prisma.SortOrder totalRounds?: Prisma.SortOrder maxPlayers?: Prisma.SortOrder + gameMode?: Prisma.SortOrder startArticle?: Prisma.SortOrder targetArticle?: Prisma.SortOrder roundWinner?: Prisma.SortOrderInput | Prisma.SortOrder @@ -364,6 +375,7 @@ export type RoomScalarWhereWithAggregatesInput = { round?: Prisma.IntWithAggregatesFilter<"Room"> | number totalRounds?: Prisma.IntWithAggregatesFilter<"Room"> | number maxPlayers?: Prisma.IntWithAggregatesFilter<"Room"> | number + gameMode?: Prisma.StringWithAggregatesFilter<"Room"> | string startArticle?: Prisma.StringWithAggregatesFilter<"Room"> | string targetArticle?: Prisma.StringWithAggregatesFilter<"Room"> | string roundWinner?: Prisma.StringNullableWithAggregatesFilter<"Room"> | string | null @@ -380,6 +392,7 @@ export type RoomCreateInput = { round?: number totalRounds?: number maxPlayers?: number + gameMode?: string startArticle?: string targetArticle?: string roundWinner?: string | null @@ -396,6 +409,7 @@ export type RoomUncheckedCreateInput = { round?: number totalRounds?: number maxPlayers?: number + gameMode?: string startArticle?: string targetArticle?: string roundWinner?: string | null @@ -412,6 +426,7 @@ export type RoomUpdateInput = { round?: Prisma.IntFieldUpdateOperationsInput | number totalRounds?: Prisma.IntFieldUpdateOperationsInput | number maxPlayers?: Prisma.IntFieldUpdateOperationsInput | number + gameMode?: Prisma.StringFieldUpdateOperationsInput | string startArticle?: Prisma.StringFieldUpdateOperationsInput | string targetArticle?: Prisma.StringFieldUpdateOperationsInput | string roundWinner?: Prisma.NullableStringFieldUpdateOperationsInput | string | null @@ -428,6 +443,7 @@ export type RoomUncheckedUpdateInput = { round?: Prisma.IntFieldUpdateOperationsInput | number totalRounds?: Prisma.IntFieldUpdateOperationsInput | number maxPlayers?: Prisma.IntFieldUpdateOperationsInput | number + gameMode?: Prisma.StringFieldUpdateOperationsInput | string startArticle?: Prisma.StringFieldUpdateOperationsInput | string targetArticle?: Prisma.StringFieldUpdateOperationsInput | string roundWinner?: Prisma.NullableStringFieldUpdateOperationsInput | string | null @@ -444,6 +460,7 @@ export type RoomCreateManyInput = { round?: number totalRounds?: number maxPlayers?: number + gameMode?: string startArticle?: string targetArticle?: string roundWinner?: string | null @@ -460,6 +477,7 @@ export type RoomUpdateManyMutationInput = { round?: Prisma.IntFieldUpdateOperationsInput | number totalRounds?: Prisma.IntFieldUpdateOperationsInput | number maxPlayers?: Prisma.IntFieldUpdateOperationsInput | number + gameMode?: Prisma.StringFieldUpdateOperationsInput | string startArticle?: Prisma.StringFieldUpdateOperationsInput | string targetArticle?: Prisma.StringFieldUpdateOperationsInput | string roundWinner?: Prisma.NullableStringFieldUpdateOperationsInput | string | null @@ -476,6 +494,7 @@ export type RoomUncheckedUpdateManyInput = { round?: Prisma.IntFieldUpdateOperationsInput | number totalRounds?: Prisma.IntFieldUpdateOperationsInput | number maxPlayers?: Prisma.IntFieldUpdateOperationsInput | number + gameMode?: Prisma.StringFieldUpdateOperationsInput | string startArticle?: Prisma.StringFieldUpdateOperationsInput | string targetArticle?: Prisma.StringFieldUpdateOperationsInput | string roundWinner?: Prisma.NullableStringFieldUpdateOperationsInput | string | null @@ -492,6 +511,7 @@ export type RoomCountOrderByAggregateInput = { round?: Prisma.SortOrder totalRounds?: Prisma.SortOrder maxPlayers?: Prisma.SortOrder + gameMode?: Prisma.SortOrder startArticle?: Prisma.SortOrder targetArticle?: Prisma.SortOrder roundWinner?: Prisma.SortOrder @@ -516,6 +536,7 @@ export type RoomMaxOrderByAggregateInput = { round?: Prisma.SortOrder totalRounds?: Prisma.SortOrder maxPlayers?: Prisma.SortOrder + gameMode?: Prisma.SortOrder startArticle?: Prisma.SortOrder targetArticle?: Prisma.SortOrder roundWinner?: Prisma.SortOrder @@ -531,6 +552,7 @@ export type RoomMinOrderByAggregateInput = { round?: Prisma.SortOrder totalRounds?: Prisma.SortOrder maxPlayers?: Prisma.SortOrder + gameMode?: Prisma.SortOrder startArticle?: Prisma.SortOrder targetArticle?: Prisma.SortOrder roundWinner?: Prisma.SortOrder @@ -578,6 +600,7 @@ export type RoomSelect = runtime.Types.Extensions.GetOmit<"code" | "players" | "phase" | "round" | "totalRounds" | "maxPlayers" | "startArticle" | "targetArticle" | "roundWinner" | "countdownStart" | "roundStart" | "createdAt" | "updatedAt", ExtArgs["result"]["room"]> +export type RoomOmit = runtime.Types.Extensions.GetOmit<"code" | "players" | "phase" | "round" | "totalRounds" | "maxPlayers" | "gameMode" | "startArticle" | "targetArticle" | "roundWinner" | "countdownStart" | "roundStart" | "createdAt" | "updatedAt", ExtArgs["result"]["room"]> export type $RoomPayload = { name: "Room" @@ -647,6 +673,7 @@ export type $RoomPayload readonly totalRounds: Prisma.FieldRef<"Room", 'Int'> readonly maxPlayers: Prisma.FieldRef<"Room", 'Int'> + readonly gameMode: Prisma.FieldRef<"Room", 'String'> readonly startArticle: Prisma.FieldRef<"Room", 'String'> readonly targetArticle: Prisma.FieldRef<"Room", 'String'> readonly roundWinner: Prisma.FieldRef<"Room", 'String'> diff --git a/lib/useGameHandlers.ts b/lib/useGameHandlers.ts index 456185b..6a0b34d 100644 --- a/lib/useGameHandlers.ts +++ b/lib/useGameHandlers.ts @@ -13,18 +13,19 @@ type Handlers = { joinCode: string; maxPlayers: number; totalRounds: number; + gameMode: "race" | "all_finish"; setScreen: Dispatch>; setError: Dispatch>; setLoading: Dispatch>; }; export function useGameHandlers({ - solo, multi, playerName, joinCode, maxPlayers, totalRounds, setScreen, setError, setLoading, + solo, multi, playerName, joinCode, maxPlayers, totalRounds, gameMode, setScreen, setError, setLoading, }: Handlers) { async function handleCreateRoom() { if (!playerName.trim()) { setError("Entre ton pseudo !"); return; } setLoading(true); setError(null); - const { error: err } = await multi.createRoom(playerName.trim(), maxPlayers, totalRounds); + const { error: err } = await multi.createRoom(playerName.trim(), maxPlayers, totalRounds, gameMode); setLoading(false); if (err) { setError(err); return; } setScreen("lobby"); @@ -67,6 +68,10 @@ export function useGameHandlers({ setScreen("solo"); } + async function handleSurrender() { + await multi.surrender(); + } + return { handleCreateRoom, handleJoinRoom, @@ -75,5 +80,6 @@ export function useGameHandlers({ handleResetGame, handleLeave, handleSolo, + handleSurrender, }; } diff --git a/lib/useMultiGame.ts b/lib/useMultiGame.ts index b7def49..b28bc54 100644 --- a/lib/useMultiGame.ts +++ b/lib/useMultiGame.ts @@ -152,11 +152,11 @@ export function useMultiGame() { // Room actions - async function createRoom(playerName: string, maxPlayers = 16, totalRounds = 3): Promise<{ error?: string }> { + async function createRoom(playerName: string, maxPlayers = 16, totalRounds = 3, gameMode: "race" | "all_finish" = "race"): Promise<{ error?: string }> { const res = await fetch("/api/rooms", { method: "POST", headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ playerName, maxPlayers, totalRounds }), + body: JSON.stringify({ playerName, maxPlayers, totalRounds, gameMode }), }); const data = await res.json() as { room?: Room; playerId?: string; error?: string }; if (!res.ok) return { error: data.error ?? "Erreur" }; @@ -195,6 +195,16 @@ export function useMultiGame() { return {}; } + async function surrender() { + if (!room || !playerId) return; + const res = await fetch(`/api/rooms/${room.code}`, { + method: "PATCH", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ action: "surrender", playerId }), + }); + if (res.ok) setRoom((await res.json() as { room: Room }).room); + } + async function nextRound() { if (!room || !playerId) return; const res = await fetch(`/api/rooms/${room.code}`, { @@ -247,7 +257,7 @@ export function useMultiGame() { return { room, playerId, html, title, loading, loadError, history, clicks: clicksDisplay, elapsed: timer.elapsed, countdown, - createRoom, joinRoom, startGame, nextRound, resetGame, leave, navigate, restore, + createRoom, joinRoom, startGame, nextRound, resetGame, leave, navigate, surrender, restore, retryLoad: () => title && loadArticle(title), }; } diff --git a/prisma/schema.prisma b/prisma/schema.prisma index d465d5e..04f1f9a 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -49,6 +49,7 @@ model Room { round Int @default(0) totalRounds Int @default(3) maxPlayers Int @default(16) + gameMode String @default("race") startArticle String @default("") targetArticle String @default("") roundWinner String?