import { useValidatedParams, z, zh } from 'h3-zod'; import prisma from '~~/lib/prisma'; export default defineEventHandler(async (event) => { const { huntId } = await useValidatedParams( event, z.object({ huntId: zh.numAsString }) ); const user = await getUserSession(event); const userId = user.user?.id || 0; // TODO: use one request for this logic const exists = await prisma.hunt.findUnique({ where: { id: huntId, deletedAt: null }, select: { id: true } }); if (!exists) { throw createError({ status: 404, statusText: 'Not found!' }); } const _hunt = await prisma.hunt.findUnique({ where: { id: huntId, deletedAt: null, OR: [ { revealAnswers: true, revealQuests: true }, { creatorId: userId }, { members: { some: { memberId: userId } } } ] }, select: { id: true, name_de: true, name_en: true, start: true, end: true, _count: { select: { teams: true, members: true, quests: true } }, teams: { select: { _count: { select: { members: true, answers: { where: { review: { score: { gt: 0 } } } } } }, id: true, name: true, description: true, answers: { select: { review: { select: { score: true } } }, where: { review: { score: { not: null } } } } } }, quests: { select: { id: true, title_de: true, title_en: true, description_de: true, description_en: true, textSolution: true, points: true, extraPoints: true, answers: { select: { id: true, text: true, review: { select: { score: true } }, picture: { select: { url: true, createdAt: true, creator: { select: { id: true, name: true } } } }, team: { select: { id: true, name: true } } }, where: { review: { showcase: true }, picture: { private: false } }, orderBy: [ { review: { rankingValue: { sort: 'asc', nulls: 'last' } } }, { review: { score: { sort: 'asc', nulls: 'last' } } }, { createdAt: 'asc' } ] } }, where: { OR: [ { answers: { some: { review: { showcase: true } } } } // TODO: showcase solutions to quests // { // textSolution: { not: null } // } ] } } } }); if (!_hunt) { throw createError({ status: 403, statusText: 'Answers are not revealed yet!' }); } const { teams, ...hunt } = _hunt; const userCount = teams.reduce( (sum, team) => sum + team._count.members + 1, 0 ); const leaderboard = teams .map(({ name, id, description, answers, _count }) => ({ name, id, description, answers: _count.answers, score: answers.reduce((sum, a) => sum + (a.review?.score || 0), 0) })) .toSorted((a, b) => b.score - a.score); const totalScore = leaderboard.reduce((sum, team) => sum + team.score, 0); const pictureCount = await prisma.file.count({ where: { answer: { quest: { huntId } } } }); return { userCount, pictureCount, totalScore, leaderboard, ...hunt, quests: hunt.quests.filter((q) => q.answers.length > 0) }; });