diff --git a/src/controllers/leaderboard.js b/src/controllers/leaderboard.js index f6a8a23..3d20909 100644 --- a/src/controllers/leaderboard.js +++ b/src/controllers/leaderboard.js @@ -39,7 +39,6 @@ const getRoundLeaderboard = async (roundId) => { score.total = score.points.reduce((p1, p2) => p1 + p2); slotIds.add(score.slot); }) - //add up totals for each slot let leaderboard = []; Array.from(slotIds) @@ -125,7 +124,7 @@ const get2 = async (req, res) => { console.log(e) return res.status(500).json({ status: 500, - message: "Internal Server Error", + message: e.message, }); } @@ -490,6 +489,88 @@ const publish = async (req, res) => { } }; + +const getLeaderBoard = async (req, res) => { + const remove_college_list = [{ name: "Cultural Coordination Committee", location: "Manipal" }, { name: "Kasturba Hospital", location: "Manipal" }, { name: "MAHE", location: "Manipal" }]; + + try { + let events = await EventModel.find({ faculty: false }).sort({ startDate: 1 }); + events = events.filter((ev) => ev.name !== "Staff Variety Entertainment" && ev.name !== "Poetry (Kannada)"); + + let colleges = await CollegeModel.find().sort({ name: 1 }); + colleges = colleges.filter((college) => { // Filter out the colleges that shouldn't be in the leaderboard + return (remove_college_list.find(r_college => r_college.name == college.name && r_college.location == college.location) == undefined); + }) + let set = []; + + for (let i = 0; i < events.length; i++) { + let event = events[i]; + + if (event.rounds.length == 0) continue; + let round = await RoundModel.find({ event: event._id, _id: event.rounds[0], published: true }); + if (round.length == 0) continue; + console.log(round); + let scores = await JudgeScoreModel.find({ round: round[0]._id }); + let slots = await Slot2Model.find({ + round: round[0]._id + }).populate('college'); + + let slotIds = new Set(); + + scores.forEach(score => { + score.total = score.points.reduce((p1, p2) => p1 + p2); + slotIds.add(score.slot); + }) + + + let leaderboard = []; + Array.from(slotIds) + .map(slotId => slots.find(slot => String(slot._id) == slotId)) + .filter(slot => !slot.disqualified)//filter out disqualified teams + .forEach(slot => { + let total = scores.filter(score => score.slot == String(slot._id)).reduce((total, score) => total + score.total, 0); + let bias = getOvertimeMinusPoints(slot.overtime) + total = total - bias; + if (!leaderboard.find(leaderboardItem => leaderboardItem.slot._id == slot._id)) + leaderboard.push({ slot: slot, total }) + }) + + + leaderboard.sort((p1, p2) => p2.total - p1.total); + + let scoreOrder = Array.from(new Set(leaderboard.map(item => item.total))); + leaderboard.forEach(item => { + item.rank = scoreOrder.indexOf(item.total) + 1; + }) + + leaderboard.forEach(item => { + // #TODO, two teams of same college winning in one event. + if (item.rank <= 3) { + set.push({ + college: item.slot.college, + event: event.id, + rank: item.rank + }); + } + }); + + } + + + res.status(200).json({ + status: 200, + message: "Success", + data: set, + }); + + } catch (e) { + return res.status(500).json({ + status: 500, + message: e.message, + }); + } +} + module.exports = { get, get2, @@ -498,5 +579,6 @@ module.exports = { init, publish, update, - getRoundLeaderboard + getRoundLeaderboard, + getLeaderBoard }; diff --git a/src/controllers/settings.js b/src/controllers/settings.js index 57b6dcc..31b0057 100644 --- a/src/controllers/settings.js +++ b/src/controllers/settings.js @@ -70,8 +70,8 @@ const getAll = async (req, res) => { const updateSettings = async (req, res) => { - let { title, editTeamEnabled, downloadCertificateEnabled } = req.body; - if( title === null || editTeamEnabled === null || downloadCertificateEnabled === null) { + let { title, editTeamEnabled, downloadCertificateEnabled, navbarDownloadCertificate } = req.body; + if( title === null || editTeamEnabled === null || downloadCertificateEnabled === null , navbarDownloadCertificate === null) { return res.status(404).json({ status: 400, message: "Bad request", @@ -79,18 +79,20 @@ const updateSettings = async (req, res) => { } if(title == "") title = "MUCAPP"; - + let setting = await SettingModel.findOne(); if(!setting){ // Setting doesn't exist, create it setting = await SettingModel.create({ title: title, editTeamEnabled: editTeamEnabled, downloadCertificateEnabled: downloadCertificateEnabled, + navbarDownloadCertificate: navbarDownloadCertificate, }); }else{ setting.title = title; setting.editTeamEnabled = editTeamEnabled; setting.downloadCertificateEnabled = downloadCertificateEnabled; + setting.navbarDownloadCertificate = navbarDownloadCertificate; await setting.save(); } diff --git a/src/controllers/slotting.js b/src/controllers/slotting.js index 7baaf20..c969b9d 100644 --- a/src/controllers/slotting.js +++ b/src/controllers/slotting.js @@ -10,37 +10,82 @@ const getEventsName = async (req, res) => { const collegeName = req.body.collegeName; const college = await CollegeModel.findOne({ name: collegeName }); if (!college) { - return res.status(404).json({ - status: 404, - message: "Not Found. No college was found for the specified name.", - }); + return res.status(404).json({ status: 404, message: "College not found" }); } - const events = await TeamModel.find({ college: college._id }); - const eventIds = events.map((event) => event.event); - let eventDetails = []; - let eventData = {}; - for (let eventId of eventIds) { - // console.log(eventId); + + // Get unique event IDs using aggregation + const events = await TeamModel.aggregate([ + { $match: { college: college._id } }, + { $group: { _id: "$event" } } + ]); + + const eventDetails = []; + + for (const eventObj of events) { + const eventId = eventObj._id; const event = await EventModel.findById(eventId); - if(event.endDate < Date.now()){ - continue; + + if (!event || event.endDate < Date.now()) continue; + + const rounds = await RoundModel.find({ event: eventId }); + const teams = await TeamModel.find({ + college: college._id, + event: eventId + }); + + const unslottedTeams = []; + + for (const team of teams) { + const missingRounds = []; + + const slotChecks = await Promise.all(rounds.map(async (round) => { + const exists = await Slot2Model.exists({ + round: round._id, + college: college._id, + teamIndex: team.index + }); + + if (!exists) missingRounds.push({ + roundId: round._id, + roundName: round.name + }); + + return exists; + })); + + if (missingRounds.length > 0) { + unslottedTeams.push({ + teamId: team._id, + teamIndex: team.index, + missingRounds, + fullySlotted: false + }); + } + } + + // Only add event if it has unslotted teams + if (unslottedTeams.length > 0) { + eventDetails.push({ + id: event._id, + name: event.name, + unslottedTeams, + totalTeams: teams.length, + slottedTeams: teams.length - unslottedTeams.length + }); } - const eventData = { - name: event.name, - id: event._id, - }; - eventDetails.push(eventData); } + return res.status(200).json({ status: 200, message: "Success", - eventDetails, + data: { + collegeId: college._id, + collegeName: college.name, + events: eventDetails + } }); } catch (err) { - return res.status(500).json({ - status: 500, - message: err.message, - }); + return res.status(500).json({ status: 500, message: err.message }); } }; @@ -142,7 +187,7 @@ const slotCollegeById = async (req, res) => { if (finalStatus === 200) { return res.status(200).json({ status: 200, - message: "Slotting completed for all teams from college", + message: "Slotting completed for all teams from college ✅", }); } else if (finalStatus === 404) { return res.status(404).json({ diff --git a/src/models/Setting.js b/src/models/Setting.js index cc4622b..521e40d 100644 --- a/src/models/Setting.js +++ b/src/models/Setting.js @@ -13,7 +13,11 @@ const schema = { downloadCertificateEnabled:{ type: Boolean, required: true, - } + }, + navbarDownloadCertificate:{ + type: Boolean, + required: true, + }, }; const options = { diff --git a/src/routes/leaderboard.js b/src/routes/leaderboard.js index 9fa3ebd..d0f2325 100644 --- a/src/routes/leaderboard.js +++ b/src/routes/leaderboard.js @@ -20,4 +20,7 @@ router.post("/publish", Leaderboard.publish); // Modify the leaderboard with updated scores of the given college router.patch("/:college", Leaderboard.update); +//Get the published events data for leaderboard +router.get("/getleaderboard", Leaderboard.getLeaderBoard); + module.exports = router;