обновил критерии

This commit is contained in:
2025-11-21 23:47:56 +03:00
parent 599170df2c
commit 4c35decfd7

View File

@@ -119,49 +119,64 @@ router.get('/statistics', async (req, res) => {
} }
}); });
// GET /api/ratings/top3 - топ-3 команды/участники // GET /api/ratings/top3 - топ-3 команды и топ-3 участники отдельно
// ВАЖНО: всегда возвращаем объект вида { teams: Top3Item[], participants: Top3Item[] },
// чтобы фронтенд мог безопасно работать с data.teams / data.participants
router.get('/top3', async (req, res) => { router.get('/top3', async (req, res) => {
try { try {
const { type, eventId } = req.query; const { type, eventId } = req.query;
// Получаем статистику // Получаем все активные команды/участников
const teamFilter = { isActive: true }; const teamFilter = { isActive: true };
if (type) teamFilter.type = type;
if (eventId) teamFilter.eventId = eventId; if (eventId) teamFilter.eventId = eventId;
const teams = await Team.find(teamFilter); const teams = await Team.find(teamFilter);
const ratingFilter = {}; const ratingFilter = {};
if (eventId) ratingFilter.eventId = eventId; if (eventId) ratingFilter.eventId = eventId;
const ratings = await Rating.find(ratingFilter) const ratings = await Rating.find(ratingFilter).populate('teamId', 'name type projectName');
.populate('teamId', 'name type projectName');
const calculateTop3 = (sourceTeams) => {
// Группируем и считаем средние баллы const teamScores = sourceTeams.map((team) => {
const teamScores = teams.map(team => { const teamRatings = ratings.filter(
const teamRatings = ratings.filter(r => r.teamId && r.teamId._id.toString() === team._id.toString()); (r) => r.teamId && r.teamId._id.toString() === team._id.toString()
);
const totalScore = teamRatings.length > 0
? teamRatings.reduce((sum, r) => sum + r.totalScore, 0) / teamRatings.length const totalScore =
: 0; teamRatings.length > 0
? teamRatings.reduce((sum, r) => sum + r.totalScore, 0) / teamRatings.length
return { : 0;
team: {
_id: team._id, return {
name: team.name, team: {
type: team.type, _id: team._id,
projectName: team.projectName name: team.name,
}, type: team.type,
totalScore: totalScore, projectName: team.projectName
ratingsCount: teamRatings.length },
}; totalScore,
}); ratingsCount: teamRatings.length
};
// Сортируем по баллам и берем топ-3 });
const top3 = teamScores
.filter(t => t.ratingsCount > 0) return teamScores
.sort((a, b) => b.totalScore - a.totalScore) .filter((t) => t.ratingsCount > 0)
.slice(0, 3); .sort((a, b) => b.totalScore - a.totalScore)
.slice(0, 3);
res.json(top3); };
const teamEntities = teams.filter((t) => t.type === 'team');
const participantEntities = teams.filter((t) => t.type === 'participant');
const teamTop3 = calculateTop3(teamEntities);
const participantTop3 = calculateTop3(participantEntities);
// Параметр type управляет только содержимым, но не форматом ответа
const response = {
teams: !type || type === 'team' ? teamTop3 : [],
participants: !type || type === 'participant' ? participantTop3 : []
};
res.json(response);
} catch (error) { } catch (error) {
res.status(500).json({ error: error.message }); res.status(500).json({ error: error.message });
} }