Improve training statistics, achievements and stable pace audio

This commit is contained in:
larssand
2026-09-03 06:36:17 +02:00
parent 82d52ed6cd
commit 4f847610dc
16 changed files with 315 additions and 50 deletions

View File

@@ -134,7 +134,8 @@ test("driver statistics remain isolated and aggregate days and sessions", () =>
assert.equal(stats.trainingDays, 2);
assert.equal(stats.bestLapMs, 16500);
assert.equal(stats.averageLapMs, 17167);
assert.equal(stats.controlledLapStreak, 2);
// A flow streak never carries over into another session or stint.
assert.equal(stats.controlledLapStreak, 1);
assert.equal(stats.dailySummaries[0].laps, 1);
assert.equal(stats.dailySummaries[1].laps, 2);
});
@@ -193,6 +194,7 @@ test("split and pit statistics aggregate by personal profile and selected class"
assert.equal(stats.splitCount, 2);
assert.equal(stats.bestSplitMs, 7900);
assert.equal(stats.averageSplitMs, 8000);
assert.equal(stats.latestSplitGainMs, 200);
assert.equal(stats.pitStopCount, 2);
assert.equal(stats.totalPitMs, 22000);
assert.equal(stats.bestPitStopMs, 9500);
@@ -292,6 +294,9 @@ test("active practice stats include only the selected driver's current valid lap
bestLapMs: 16_000,
averageLapMs: 16_500,
lastLapMs: 17_000,
controlZoneMinMs: 16_000,
controlZoneMaxMs: 17_280,
controlledLapStreak: 2,
});
});
@@ -391,6 +396,31 @@ test("a stint shorter than the target duration has no five-minute result", () =>
assert.equal(getBestTrainingDurationResult(stints, 300_000), null);
});
test("training progress recognizes a clean five-minute stint and strong finish", () => {
const ledger = Array.from({ length: 16 }, (_, index) => ({
driverId: "driver_1",
sourceId: "transponder_1",
sessionId: "practice_1",
timestamp: (index + 1) * 20_000,
lapMs: 20_000,
}));
const state = { training: { ledger } };
const stats = buildDriverTrainingStats(state, "driver_1");
const analysis = buildTrainingStintAnalysis(state, "driver_1");
assert.equal(stats.controlZoneMinMs, 20_000);
assert.equal(stats.controlZoneMaxMs, 21_600);
assert.equal(stats.controlledLapStreak, 16);
assert.equal(stats.outlierLaps, 0);
assert.equal(stats.strongFinishStints, 1);
assert.equal(stats.cleanFiveMinuteStints, 1);
assert.equal(stats.achievements.find((item) => item.id === "strong_finish").unlocked, true);
assert.equal(stats.achievements.find((item) => item.id === "clean_five_minute").unlocked, true);
assert.equal(analysis.rows[0].strongFinish, true);
assert.equal(analysis.rows[0].fiveMinuteResult.lapCount, 15);
assert.equal(analysis.rows[0].fiveMinuteResult.totalMs, 300_000);
});
test("recommendations select baseline, consistency, and progression", () => {
assert.equal(buildTrainingRecommendation({ totalLaps: 9 }).level, "baseline");
assert.deepEqual(