import { randomUUID } from "crypto"; import { getGameTerms, getDistractors } from "@lila/db"; import type { GameRequest, GameSession, GameQuestion, AnswerOption, AnswerSubmission, AnswerResult, } from "@lila/shared"; import type { GameSessionStore } from "../gameSessionStore/index.js"; import { NotFoundError } from "../errors/AppError.js"; import { shuffleArray } from "../lib/utils.js"; export const createGameSession = async ( request: GameRequest, store: GameSessionStore, ): Promise => { const terms = await getGameTerms( request.source_language, request.target_language, request.pos, request.difficulty, request.rounds, ); const answerKey = new Map(); const questions: GameQuestion[] = await Promise.all( terms.map(async (term) => { const distractorTexts = await getDistractors( term.termId, term.targetText, request.target_language, request.pos, request.difficulty, 3, ); const optionTexts = [term.targetText, ...distractorTexts]; const shuffledTexts = shuffleArray(optionTexts); const correctOptionId = shuffledTexts.indexOf(term.targetText); const options: AnswerOption[] = shuffledTexts.map((text, index) => ({ optionId: index, text, })); const questionId = randomUUID(); answerKey.set(questionId, correctOptionId); return { questionId, prompt: term.sourceText, gloss: term.sourceGloss, options, }; }), ); const sessionId = randomUUID(); await store.create(sessionId, { answers: answerKey }); return { sessionId, questions }; }; export const evaluateAnswer = async ( submission: AnswerSubmission, store: GameSessionStore, ): Promise => { const session = await store.get(submission.sessionId); if (!session) { throw new NotFoundError(`Game session not found: ${submission.sessionId}`); } const correctOptionId = session.answers.get(submission.questionId); if (correctOptionId === undefined) { throw new NotFoundError(`Question not found: ${submission.questionId}`); } return { questionId: submission.questionId, isCorrect: submission.selectedOptionId === correctOptionId, correctOptionId, selectedOptionId: submission.selectedOptionId, }; };