74 lines
2.0 KiB
JavaScript
74 lines
2.0 KiB
JavaScript
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 };
|