Add class-specific driver training profiles and metadata

This commit is contained in:
larssand
2026-08-24 22:05:50 +02:00
parent 3aeb77a042
commit 6f02e955a5
14 changed files with 559 additions and 128 deletions

View File

@@ -1,3 +1,15 @@
import { getDriverProfile, getDriverProfileReferences } from "./driver_profile_logic.js";
function getTrainingDriverIds(state, driverId, classId = "") {
const profile = getDriverProfile(state, driverId);
if (!profile) return getDriverProfileReferences(state, driverId);
const normalizedClassId = String(classId || "");
return new Set(profile.drivers
.filter((driver) => !normalizedClassId || String(driver.classId || "") === normalizedClassId)
.map((driver) => String(driver.id || ""))
.filter(Boolean));
}
export function normalizeTrainingState(training, { uid }) {
const source = training && typeof training === "object" ? training : {};
const goals = Array.isArray(source.goals)
@@ -5,6 +17,7 @@ export function normalizeTrainingState(training, { uid }) {
.map((goal) => ({
id: String(goal?.id || uid("goal")),
driverId: String(goal?.driverId || ""),
classId: String(goal?.classId || ""),
title: String(goal?.title || "").trim(),
reward: String(goal?.reward || "").trim(),
targetLaps: Math.max(1, Math.round(Number(goal?.targetLaps || 0) || 0)),
@@ -101,10 +114,11 @@ export function syncTrainingLedger(training, state, { uid }) {
return normalizeTrainingState({ goals: normalized.goals, ledger: [...retained, ...current], shares: normalized.shares }, { uid });
}
export function getDriverTrainingLaps(state, driverId) {
export function getDriverTrainingLaps(state, driverId, classId = "") {
const ledger = Array.isArray(state?.training?.ledger) ? state.training.ledger : [];
const profileReferences = getTrainingDriverIds(state, driverId, classId);
return ledger
.filter((entry) => String(entry?.driverId || "") === String(driverId || "") && Number(entry?.lapMs || 0) > 500)
.filter((entry) => profileReferences.has(String(entry?.driverId || "")) && Number(entry?.lapMs || 0) > 500)
.map((entry) => ({
sessionId: String(entry.sessionId || ""),
sessionName: String(entry.sessionName || ""),
@@ -249,8 +263,8 @@ export function getBestTrainingDurationResult(stints, targetMs = 5 * 60 * 1000)
return best;
}
export function buildDriverTrainingStats(state, driverId) {
const laps = getDriverTrainingLaps(state, driverId);
export function buildDriverTrainingStats(state, driverId, classId = "") {
const laps = getDriverTrainingLaps(state, driverId, classId);
const lapTimes = laps.map((lap) => lap.lapMs);
const recentLapTimes = lapTimes.slice(-30);
const earlierLapTimes = lapTimes.slice(0, Math.max(0, lapTimes.length - recentLapTimes.length));
@@ -300,7 +314,7 @@ export function buildDriverTrainingStats(state, driverId) {
};
}
export function buildDriverActivePracticeStats(state, driverId, nowTs = Date.now()) {
export function buildDriverActivePracticeStats(state, driverId, nowTs = Date.now(), classId = "") {
const session = (Array.isArray(state?.sessions) ? state.sessions : [])
.find((item) => String(item?.id || "") === String(state?.activeSessionId || ""));
const practiceTypes = new Set(["open_practice", "free_practice", "practice"]);
@@ -308,9 +322,10 @@ export function buildDriverActivePracticeStats(state, driverId, nowTs = Date.now
const result = state?.resultsBySession?.[session.id];
const startedAt = Math.max(0, Number(session.startedAt || 0) || 0);
const profileReferences = getTrainingDriverIds(state, driverId, classId);
const laps = (Array.isArray(result?.passings) ? result.passings : [])
.filter((passing) => (
String(passing?.driverId || "") === String(driverId || "")
profileReferences.has(String(passing?.driverId || ""))
&& passing?.validLap !== false
&& Number(passing?.lapMs || 0) > 500
&& (!startedAt || Number(passing?.timestamp || 0) >= startedAt)