diff --git a/server/src/api/controllers/leaderboardController.js b/server/src/api/controllers/leaderboardController.js index 1d351e3..e3cb7ee 100644 --- a/server/src/api/controllers/leaderboardController.js +++ b/server/src/api/controllers/leaderboardController.js @@ -1,5 +1,12 @@ import { asyncHandler } from '../../middleware/error.js' +import { leaderboard } from '../../models/userManager.js' export default asyncHandler(async (req, res) => { - res.json({ message: 'leaderboard' }) + const users = await leaderboard() + const response = users.map((user) => ({ + username: user.user.username, + completedQuests: user.completedQuests, + numberOfCompletedQuests: user.numberOfCompletedQuests, + })) + res.json(response) }) diff --git a/server/src/models/userManager.js b/server/src/models/userManager.js index 46943dd..8168eb5 100644 --- a/server/src/models/userManager.js +++ b/server/src/models/userManager.js @@ -22,3 +22,46 @@ export async function createUser(username, email, { password, socialLogin }) { return user } + +export function leaderboard() { + return UserProfile.aggregate([ + { + $project: { + user: true, // Include the user field in the projection + completedQuests: { + $map: { + input: { + $filter: { + input: { $objectToArray: '$progress' }, // Convert the progress map to an array + as: 'prog', + cond: { $eq: ['$$prog.v.completed', true] }, // Filter for completed quests + }, + }, + as: 'completedProg', + in: '$$completedProg.k', // Extract the quest IDs + }, + }, + }, + }, + { + $addFields: { + numberOfCompletedQuests: { $size: '$completedQuests' }, // Calculate the size of the completedQuests array + }, + }, + { + $match: { + numberOfCompletedQuests: { $gt: 0 }, // Filter out users who haven't completed any quests + }, + }, + { $sort: { numberOfCompletedQuests: -1 } }, + { + $lookup: { + from: 'users', + localField: 'user', + foreignField: '_id', + as: 'user', + }, + }, + { $unwind: '$user' }, + ]) +}