// Accès aux questions de quiz en base. No-op si pas de DB (db === null). import { and, eq, inArray, notInArray, sql } from "drizzle-orm" import { db } from "./index" import { quizCategory, quizPlayed, quizQuestion } from "./schema" import type { QuizQuestion } from "../game/modes/quiz/questions" /** * Pool de questions mcq/truefalse non encore jouées par cette room, * mélangées et limitées. Tableau vide si pas de DB ou rien à servir. */ /** Catégories existantes (pour le filtre du lobby). */ export async function listCategories(): Promise { if (!db) { return [] } const rows = await db .select({ name: quizCategory.name }) .from(quizCategory) .orderBy(quizCategory.name) return rows.map((r) => r.name) } export async function loadQuizPool( roomCode: string, limit: number, formats: string[], categories: string[] = [] ): Promise { if (!db || formats.length === 0) { return [] } const alreadyPlayed = db .select({ id: quizPlayed.questionId }) .from(quizPlayed) .where(eq(quizPlayed.roomCode, roomCode)) const rows = await db .select({ id: quizQuestion.id, format: quizQuestion.format, prompt: quizQuestion.prompt, choices: quizQuestion.choices, correctIndex: quizQuestion.correctIndex, acceptedAnswers: quizQuestion.acceptedAnswers, imageUrl: quizQuestion.imageUrl, difficulty: quizQuestion.difficulty, category: quizCategory.name, }) .from(quizQuestion) .leftJoin(quizCategory, eq(quizQuestion.categoryId, quizCategory.id)) .where( and( eq(quizQuestion.active, true), inArray(quizQuestion.format, formats), categories.length > 0 ? inArray(quizCategory.name, categories) : undefined, notInArray(quizQuestion.id, alreadyPlayed) ) ) .orderBy(sql`random()`) .limit(limit) return rows .filter((r) => { if (r.format === "free") { return (r.acceptedAnswers?.length ?? 0) > 0 } if (r.format === "image_reveal") { return !!r.imageUrl && (r.acceptedAnswers?.length ?? 0) > 0 } return r.choices && r.correctIndex !== null }) .map((r) => ({ id: r.id, format: r.format as QuizQuestion["format"], prompt: r.prompt, choices: r.choices ?? undefined, correctIndex: r.correctIndex ?? undefined, acceptedAnswers: r.acceptedAnswers ?? undefined, imageUrl: r.imageUrl ?? undefined, category: r.category ?? "Quiz", difficulty: r.difficulty, })) } /** Marque une question comme jouée par cette room (anti-répétition). */ export async function markQuestionPlayed( roomCode: string, questionId: string ): Promise { if (!db) { return } await db .insert(quizPlayed) .values({ roomCode, questionId }) .onConflictDoNothing() }