Skip to content

Commit 168af52

Browse files
committed
added_jury_score_functionalities
1 parent 83ec213 commit 168af52

File tree

7 files changed

+434
-19
lines changed

7 files changed

+434
-19
lines changed

backend/src/controllers/team.controller.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,56 @@ exports.getLeaderboard = async (req, res) => {
170170
}
171171
};
172172

173+
// @desc Update jury score for a team
174+
// @route PUT /api/teams/:id/jury-score
175+
// @access Admin only
176+
exports.updateJuryScore = async (req, res) => {
177+
try {
178+
const { juryScore } = req.body;
179+
180+
// Validate the jury score (admin enters 0-100, but we store 0-50 as it's 50% of final score)
181+
if (juryScore === undefined || juryScore < 0 || juryScore > 100) {
182+
return res.status(400).json({
183+
success: false,
184+
message: 'Jury score must be a number between 0 and 100'
185+
});
186+
}
187+
188+
// Convert the 0-100 score to 0-50 (50% of final score)
189+
const normalizedJuryScore = juryScore / 2;
190+
191+
const team = await Team.findOneAndUpdate(
192+
{ _id: req.params.id, isActive: true },
193+
{ juryScore: normalizedJuryScore },
194+
{ new: true, runValidators: true }
195+
).select('-password');
196+
197+
if (!team) {
198+
return res.status(404).json({
199+
success: false,
200+
message: 'Team not found'
201+
});
202+
}
203+
204+
// Notify clients about the leaderboard update
205+
const io = req.app.get('io');
206+
if (io) {
207+
io.to('leaderboard-room').emit('leaderboard-update');
208+
}
209+
210+
res.json({
211+
success: true,
212+
data: team
213+
});
214+
} catch (error) {
215+
console.error('Error updating jury score:', error);
216+
res.status(400).json({
217+
success: false,
218+
message: error.message
219+
});
220+
}
221+
};
222+
173223
// @desc Get current team data
174224
// @route GET /api/teams/me
175225
// @access Private

backend/src/models/team.model.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ const teamSchema = new mongoose.Schema({
3333
type: Number,
3434
default: 0
3535
},
36+
juryScore: {
37+
type: Number,
38+
default: 0
39+
},
3640
isActive: {
3741
type: Boolean,
3842
default: true

backend/src/routes/public.routes.js

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ const Challenge = require('../models/challenge.model');
99
router.get('/leaderboard', async (req, res) => {
1010
try {
1111
const teams = await Team.find({ role: 'team' })
12-
.select('teamName points completedChallenges')
13-
.sort('-points')
12+
.select('teamName points juryScore completedChallenges')
1413
.lean();
1514

1615
// Get all challenges to calculate progress percentage
@@ -22,8 +21,8 @@ router.get('/leaderboard', async (req, res) => {
2221
totalChallengePoints += challenge.points || 0;
2322
});
2423

25-
// Calculate percentage and format response
26-
const leaderboard = teams.map((team, index) => {
24+
// Calculate combined scores and format response
25+
const leaderboard = teams.map(team => {
2726
// For progress bar, calculate based on points earned vs total possible points
2827
const progressPercentage = totalChallengePoints > 0
2928
? Math.round((team.points || 0) / totalChallengePoints * 100)
@@ -32,14 +31,34 @@ router.get('/leaderboard', async (req, res) => {
3231
// Still keep track of completed challenges count
3332
const completedCount = team.completedChallenges ? team.completedChallenges.length : 0;
3433

34+
// Calculate normalized challenge score (50% of final score)
35+
const normalizedChallengeScore = totalChallengePoints > 0
36+
? ((team.points || 0) / totalChallengePoints) * 50
37+
: 0;
38+
39+
// Jury score (50% of final score)
40+
const juryScore = team.juryScore || 0;
41+
42+
// Calculate final combined score (challenge score + jury score)
43+
const finalScore = normalizedChallengeScore + juryScore;
44+
3545
return {
36-
rank: index + 1,
3746
teamName: team.teamName,
38-
points: team.points,
47+
challengePoints: team.points || 0,
48+
juryScore: juryScore,
49+
finalScore: parseFloat(finalScore.toFixed(2)),
3950
progress: progressPercentage,
4051
completedCount
4152
};
4253
});
54+
55+
// Sort by final score in descending order
56+
leaderboard.sort((a, b) => b.finalScore - a.finalScore);
57+
58+
// Add rank after sorting
59+
leaderboard.forEach((team, index) => {
60+
team.rank = index + 1;
61+
});
4362

4463
res.json({
4564
success: true,

backend/src/routes/team.routes.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ const {
77
updateTeam,
88
deleteTeam,
99
getLeaderboard,
10-
getCurrentTeam
10+
getCurrentTeam,
11+
updateJuryScore
1112
} = require('../controllers/team.controller');
1213
const { protect, authorize } = require('../middleware/auth.middleware');
1314

@@ -27,4 +28,7 @@ router
2728
.put(authorize('admin'), updateTeam)
2829
.delete(authorize('admin'), deleteTeam);
2930

31+
// Route for updating jury scores
32+
router.put('/:id/jury-score', authorize('admin'), updateJuryScore);
33+
3034
module.exports = router;

frontend/src/pages/Admin/Admin.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Leaderboard from "../Dashboard/LeaderBoard";
66
import TeamManagement from "./Teams";
77
import ChallengeValidation from "./ChallengeValidation";
88
import TeamProgress from "./TeamProgress";
9+
import JuryScoreManagement from "./JuryScoreManagement";
910
import Graph from "../../components/graph";
1011

1112
export default function Admin() {
@@ -87,7 +88,7 @@ export default function Admin() {
8788
<div className="flex flex-wrap mb-8 mt-10 bg-gradient-to-br from-gray-800 to-gray-900 rounded-xl p-1.5 border border-gray-700 w-fit shadow-xl overflow-x-auto">
8889
{[
8990
// Only show Teams and Challenges tabs for admins
90-
...(userRole === 'admin' ? ["Teams", "Challenges"] : []),
91+
...(userRole === 'admin' ? ["Teams", "Challenges", "Jury Scores"] : []),
9192
// These tabs are available for both admins and mentors
9293
"Submissions",
9394
"Leaderboard",
@@ -120,6 +121,7 @@ export default function Admin() {
120121
{/* Only render Challenge and Team management for admins */}
121122
{activeTab == "Challenges" && userRole === 'admin' && <ChallengeManagement />}
122123
{activeTab == "Teams" && userRole === 'admin' && <TeamManagement />}
124+
{activeTab == "Jury Scores" && userRole === 'admin' && <JuryScoreManagement />}
123125

124126
{/* These components are available for both admins and mentors */}
125127
{activeTab == "Leaderboard" && (

0 commit comments

Comments
 (0)