fix tränings länken och race day
This commit is contained in:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user