Files
pdga-rating/src/services/tour-service.js
T
Samuel Enocsson d7f7bed8c6 fix: use fixed point scale for tour scoring
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).
2026-03-20 07:39:43 +01:00

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
};