const db = require('../db'); async function upsertLeaderboardEntry(userId, grade, { elo, bestTime, correctAnswers = 0 } = {}) { const existing = await db.leaderboardEntry.findUnique({ where: { userId_grade: { userId, grade } }, }); return db.leaderboardEntry.upsert({ where: { userId_grade: { userId, grade } }, create: { userId, grade, elo: elo ?? 800, bestTime: bestTime ?? null, gamesPlayed: 1, totalCorrect: correctAnswers, }, update: { ...(elo !== undefined && { elo }), ...(bestTime !== undefined && (existing?.bestTime == null || bestTime < existing.bestTime) ? { bestTime } : {}), gamesPlayed: { increment: 1 }, totalCorrect: { increment: correctAnswers }, }, }); } async function getLeaderboard(grade, sortBy = 'elo', limit = 10) { const orderBy = sortBy === 'bestTime' ? { bestTime: { sort: 'asc', nulls: 'last' } } : { elo: 'desc' }; const entries = await db.leaderboardEntry.findMany({ where: { grade }, orderBy, take: limit, include: { user: { select: { displayName: true, avatarUrl: true, username: true } }, }, }); return entries.map((entry, index) => ({ ...entry, ...entry.user, rank: index + 1 })); } async function getUserRank(userId, grade, sortBy = 'elo') { const entry = await db.leaderboardEntry.findUnique({ where: { userId_grade: { userId, grade } }, }); if (!entry) return null; if (sortBy === 'bestTime') { if (entry.bestTime === null) return { rank: null, entry }; const count = await db.leaderboardEntry.count({ where: { grade, AND: [ { bestTime: { not: null } }, { bestTime: { lt: entry.bestTime } }, ], }, }); return { rank: count + 1, entry }; } const count = await db.leaderboardEntry.count({ where: { grade, elo: { gt: entry.elo } }, }); return { rank: count + 1, entry }; } module.exports = { upsertLeaderboardEntry, getLeaderboard, getUserRank };