fix tränings länken och race day

This commit is contained in:
larssand
2026-08-28 21:55:28 +02:00
parent 375bfb2416
commit 28e5c96010
7 changed files with 531 additions and 6 deletions

View File

@@ -173,12 +173,23 @@ function buildPublicTrainingGoal(goal, currentLaps) {
function buildPublicTrainingStats(laps) {
const lapTimes = laps.map((lap) => lap.lapMs);
const recent = lapTimes.slice(-30);
const previous = lapTimes.slice(Math.max(0, lapTimes.length - 60), Math.max(0, lapTimes.length - 30));
const average = (values) => values.length ? Math.round(values.reduce((sum, value) => sum + value, 0) / values.length) : 0;
const sortedRecent = [...recent].sort((left, right) => left - right);
const percentile = (ratio) => sortedRecent.length
? sortedRecent[Math.min(sortedRecent.length - 1, Math.max(0, Math.round((sortedRecent.length - 1) * ratio)))]
: 0;
const percentile = (values, ratio) => {
const sorted = [...values].sort((left, right) => left - right);
return sorted.length
? sorted[Math.min(sorted.length - 1, Math.max(0, Math.round((sorted.length - 1) * ratio)))]
: 0;
};
const spread = (values) => {
const mean = average(values);
return mean ? ((percentile(values, 0.9) - percentile(values, 0.1)) / mean) * 100 : 0;
};
const recentAverageMs = average(recent);
const previousRecentAverageMs = average(previous);
const consistencySpreadPct = spread(recent);
const previousConsistencySpreadPct = spread(previous);
const trendSampleReady = recent.length >= 10 && previous.length >= 10;
const daily = new Map();
laps.forEach((lap) => {
const date = new Date(lap.timestamp);
@@ -211,21 +222,46 @@ function buildPublicTrainingStats(laps) {
const bestThreeConsecutive = getPublicBestConsecutiveLaps(stints, 3);
const bestFiveMinuteResult = getPublicBestDurationResult(stints, 5 * 60 * 1000);
return {
const stats = {
totalLaps: laps.length,
totalSessions: new Set(laps.map((lap) => lap.sessionId).filter(Boolean)).size,
trainingDays: daily.size,
bestLapMs,
averageLapMs: average(lapTimes),
recentAverageMs,
previousRecentAverageMs,
averageTrendMs: trendSampleReady ? previousRecentAverageMs - recentAverageMs : 0,
recentLapCount: recent.length,
consistencySpreadPct: recentAverageMs ? ((percentile(0.9) - percentile(0.1)) / recentAverageMs) * 100 : 0,
consistencySpreadPct,
previousConsistencySpreadPct,
consistencyTrendPct: trendSampleReady ? previousConsistencySpreadPct - consistencySpreadPct : 0,
trendSampleReady,
controlledLapStreak,
dailySummaries,
stintCount: stints.length,
bestThreeConsecutive,
bestFiveMinuteResult,
};
return { ...stats, achievements: buildPublicTrainingAchievements(stats) };
}
function buildPublicTrainingAchievements(stats) {
const definitions = [
["first_session", Number(stats.totalSessions || 0), 1],
["laps_100", Number(stats.totalLaps || 0), 100],
["laps_500", Number(stats.totalLaps || 0), 500],
["laps_1000", Number(stats.totalLaps || 0), 1000],
["laps_1500", Number(stats.totalLaps || 0), 1500],
["days_3", Number(stats.trainingDays || 0), 3],
["days_10", Number(stats.trainingDays || 0), 10],
["controlled_5", Number(stats.controlledLapStreak || 0), 5],
["five_minute", stats.bestFiveMinuteResult ? 1 : 0, 1],
];
return definitions.map(([id, current, target]) => ({
id,
percent: Math.min(100, Math.max(0, (current / target) * 100)),
unlocked: current >= target,
}));
}
function splitPublicTrainingStints(laps, breakThresholdMs = 2 * 60 * 1000) {