51 lines
1.4 KiB
TypeScript
51 lines
1.4 KiB
TypeScript
// server/api/leaderboard.get.ts
|
|
|
|
export default defineEventHandler(async () => {
|
|
// --- MVP Compromise: Monthly EXP ---
|
|
// The current schema does not support tracking monthly EXP.
|
|
// For MVP, we will use the total cumulative `User.exp` as a stand-in
|
|
// for "current month's EXP". This should be revisited if true monthly
|
|
// tracking becomes a requirement.
|
|
const users = await prisma.user.findMany({
|
|
where: {
|
|
isAnonymous: false,
|
|
nickname: {
|
|
not: null,
|
|
},
|
|
},
|
|
select: {
|
|
nickname: true,
|
|
avatar: true,
|
|
exp: true,
|
|
},
|
|
orderBy: {
|
|
exp: 'desc',
|
|
},
|
|
take: 50, // Limit to top 50 users
|
|
});
|
|
|
|
// --- Rank Calculation ---
|
|
let currentRank = 0;
|
|
let previousExp = -1; // Ensure any valid EXP is greater than this
|
|
|
|
// To handle shared ranks, we iterate through the sorted users.
|
|
// If the current user's EXP is different from the previous user's EXP,
|
|
// their rank is their position in the 1-based sorted list.
|
|
// If their EXP is the same, they share the rank of the previous user.
|
|
const leaderboard = users.map((user, index) => {
|
|
if (user.exp !== previousExp) {
|
|
currentRank = index + 1; // Ranks are 1-based
|
|
}
|
|
previousExp = user.exp; // Update previous EXP for the next iteration
|
|
|
|
return {
|
|
rank: currentRank,
|
|
nickname: user.nickname,
|
|
avatar: user.avatar,
|
|
exp: user.exp,
|
|
};
|
|
});
|
|
|
|
return { leaderboard };
|
|
});
|