d7f7bed8c6
1st=10, 2nd=8, 3rd=6, 4th=4, 5th=3, 6th=2, 7th=1, rest=0. Ties get same points, next rank skips (1,1,3 pattern).
83 lines
2.3 KiB
JavaScript
83 lines
2.3 KiB
JavaScript
const crypto = require('crypto');
|
|
const { getTourCourses, getResultsForTour, getTourPlayers } = require('../models/tour');
|
|
|
|
function generateTourCode() {
|
|
return crypto.randomBytes(3).toString('hex').toUpperCase();
|
|
}
|
|
|
|
function isTourActive(tour) {
|
|
const now = new Date().toISOString().split('T')[0];
|
|
return now >= tour.start_date && now <= tour.end_date;
|
|
}
|
|
|
|
function isTourFinished(tour) {
|
|
const now = new Date().toISOString().split('T')[0];
|
|
return now > tour.end_date;
|
|
}
|
|
|
|
async function calculateLeaderboard(tourId) {
|
|
const courses = await getTourCourses(tourId);
|
|
const results = await getResultsForTour(tourId);
|
|
const players = await getTourPlayers(tourId);
|
|
|
|
// Group results by course
|
|
const resultsByCourse = {};
|
|
for (const course of courses) {
|
|
resultsByCourse[course.tour_course_id] = results
|
|
.filter(r => r.tour_course_id === course.tour_course_id)
|
|
.sort((a, b) => a.total_strokes - b.total_strokes);
|
|
}
|
|
|
|
// Calculate points per course
|
|
const playerPoints = {};
|
|
for (const player of players) {
|
|
playerPoints[player.pdga_number] = {
|
|
player_name: player.player_name,
|
|
pdga_number: player.pdga_number,
|
|
courses: {},
|
|
total_points: 0
|
|
};
|
|
}
|
|
|
|
const pointsByRank = [10, 8, 6, 4, 3, 2, 1];
|
|
|
|
for (const course of courses) {
|
|
const courseResults = resultsByCourse[course.tour_course_id] || [];
|
|
|
|
let rank = 1;
|
|
for (let i = 0; i < courseResults.length; i++) {
|
|
// Check for ties with previous player
|
|
if (i > 0 && courseResults[i].total_strokes > courseResults[i - 1].total_strokes) {
|
|
rank = i + 1;
|
|
}
|
|
|
|
const points = rank <= pointsByRank.length ? pointsByRank[rank - 1] : 0;
|
|
const r = courseResults[i];
|
|
const relativePar = r.total_strokes - course.par;
|
|
|
|
if (playerPoints[r.pdga_number]) {
|
|
playerPoints[r.pdga_number].courses[course.tour_course_id] = {
|
|
total_strokes: r.total_strokes,
|
|
relative_par: relativePar,
|
|
points: points,
|
|
rank: rank
|
|
};
|
|
playerPoints[r.pdga_number].total_points += points;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Sort by total points descending
|
|
const leaderboard = Object.values(playerPoints)
|
|
.sort((a, b) => b.total_points - a.total_points);
|
|
|
|
return { courses, leaderboard };
|
|
}
|
|
|
|
module.exports = {
|
|
generateTourCode,
|
|
isTourActive,
|
|
isTourFinished,
|
|
calculateLeaderboard
|
|
};
|