add more stats to mobile profile
This commit is contained in:
@@ -29,9 +29,43 @@ function getPublicDriverProfile(drivers, reference) {
|
||||
};
|
||||
}
|
||||
|
||||
const PUBLIC_TRAINING_SECTION_KEYS = ["progress", "achievements", "performance", "goals", "history"];
|
||||
|
||||
function normalizePublicTrainingVisibility(value) {
|
||||
const source = value && typeof value === "object" ? value : {};
|
||||
return Object.fromEntries(PUBLIC_TRAINING_SECTION_KEYS.map((key) => [key, source[key] !== false]));
|
||||
}
|
||||
|
||||
function filterPublicTrainingStats(stats, visibility) {
|
||||
const filtered = {
|
||||
totalLaps: stats.totalLaps, totalSessions: stats.totalSessions, trainingDays: stats.trainingDays,
|
||||
bestLapMs: stats.bestLapMs, averageLapMs: stats.averageLapMs, recentLapCount: stats.recentLapCount,
|
||||
consistencySpreadPct: stats.consistencySpreadPct,
|
||||
};
|
||||
if (visibility.progress) Object.assign(filtered, {
|
||||
recentAverageMs: stats.recentAverageMs, previousRecentAverageMs: stats.previousRecentAverageMs,
|
||||
averageTrendMs: stats.averageTrendMs, previousConsistencySpreadPct: stats.previousConsistencySpreadPct,
|
||||
consistencyTrendPct: stats.consistencyTrendPct, trendSampleReady: stats.trendSampleReady,
|
||||
controlledLapStreak: stats.controlledLapStreak, todayControlledLapStreak: stats.todayControlledLapStreak,
|
||||
todayStrongFinishStints: stats.todayStrongFinishStints, todayCleanFiveMinuteStints: stats.todayCleanFiveMinuteStints,
|
||||
todayCompletedFiveMinuteStints: stats.todayCompletedFiveMinuteStints, paceHistory: stats.dailySummaries.slice(0, 12),
|
||||
});
|
||||
if (visibility.achievements) filtered.achievements = stats.achievements;
|
||||
if (visibility.performance) Object.assign(filtered, {
|
||||
controlZoneMinMs: stats.controlZoneMinMs, controlZoneMaxMs: stats.controlZoneMaxMs,
|
||||
outlierLaps: stats.outlierLaps, strongFinishStints: stats.strongFinishStints,
|
||||
cleanFiveMinuteStints: stats.cleanFiveMinuteStints, stintCount: stats.stintCount,
|
||||
stintSummaries: stats.stintSummaries, bestThreeConsecutive: stats.bestThreeConsecutive,
|
||||
bestFiveMinuteResult: stats.bestFiveMinuteResult,
|
||||
});
|
||||
if (visibility.history) filtered.dailySummaries = stats.dailySummaries;
|
||||
return filtered;
|
||||
}
|
||||
|
||||
function buildPublicTrainingProfile(state, shareToken, updatedAt, sinceTimestamp = 0, windowMs = 0) {
|
||||
const share = findPublicTrainingShare(state, shareToken);
|
||||
if (!share) return null;
|
||||
const visibility = normalizePublicTrainingVisibility(share.visibility);
|
||||
const profileReference = String(share.driverId || "");
|
||||
const drivers = Array.isArray(state?.drivers) ? state.drivers : [];
|
||||
const driverProfile = getPublicDriverProfile(drivers, profileReference);
|
||||
@@ -66,11 +100,11 @@ function buildPublicTrainingProfile(state, shareToken, updatedAt, sinceTimestamp
|
||||
classId,
|
||||
className: String(classes.find((item) => String(item?.id || "") === classId)?.name || "").trim(),
|
||||
brand: brands.join(" / "),
|
||||
stats,
|
||||
channelStats,
|
||||
stats: filterPublicTrainingStats(stats, visibility),
|
||||
channelStats: visibility.performance ? channelStats : {},
|
||||
nextMilestone: getPublicTrainingMilestone(stats.totalLaps),
|
||||
recommendation: getPublicTrainingRecommendation(stats),
|
||||
goals: classGoals,
|
||||
goals: visibility.goals ? classGoals : [],
|
||||
currentSession: sinceTimestamp
|
||||
? buildPublicTrainingWindowStats(classLaps.filter((lap) => lap.timestamp >= sinceTimestamp && (!windowMs || lap.timestamp <= sinceTimestamp + windowMs)))
|
||||
: null,
|
||||
@@ -78,14 +112,15 @@ function buildPublicTrainingProfile(state, shareToken, updatedAt, sinceTimestamp
|
||||
});
|
||||
const activeClass = classProfiles[0] || {
|
||||
classId: "", className: "", brand: "",
|
||||
stats: buildPublicTrainingStats([]), nextMilestone: getPublicTrainingMilestone(0),
|
||||
channelStats: buildPublicTimingChannelStats({}, new Set()),
|
||||
stats: filterPublicTrainingStats(buildPublicTrainingStats([]), visibility), nextMilestone: getPublicTrainingMilestone(0),
|
||||
channelStats: visibility.performance ? buildPublicTimingChannelStats({}, new Set()) : {},
|
||||
recommendation: getPublicTrainingRecommendation({ totalLaps: 0 }), goals: [], currentSession: null,
|
||||
};
|
||||
const settings = state?.settings && typeof state.settings === "object" ? state.settings : {};
|
||||
|
||||
return {
|
||||
updatedAt: String(updatedAt || ""),
|
||||
visibility,
|
||||
profile: {
|
||||
name: String(driver.name || "Driver").trim(),
|
||||
brand: activeClass.brand,
|
||||
@@ -263,6 +298,17 @@ function buildPublicTrainingStats(laps) {
|
||||
})));
|
||||
const bestThreeConsecutive = getPublicBestConsecutiveLaps(stints, 3);
|
||||
const bestFiveMinuteResult = getPublicBestDurationResult(stints, 5 * 60 * 1000);
|
||||
const stintSummaries = stints.map((stint, index) => {
|
||||
const paceLaps = stint.laps.filter((lap) => !lap.excludedFromPace);
|
||||
const values = paceLaps.map((lap) => lap.lapMs);
|
||||
const startedAt = Math.max(0, Number(stint.laps[0]?.timestamp || 0) - Number(stint.laps[0]?.lapMs || 0));
|
||||
const endedAt = Number(stint.laps.at(-1)?.timestamp || startedAt);
|
||||
return {
|
||||
number: index + 1, startedAt, lapCount: stint.laps.length,
|
||||
bestLapMs: values.length ? Math.min(...values) : 0, averageLapMs: average(values),
|
||||
durationMs: Math.max(0, endedAt - startedAt),
|
||||
};
|
||||
}).sort((left, right) => right.startedAt - left.startedAt).slice(0, 8);
|
||||
|
||||
const stats = {
|
||||
totalLaps: laps.length,
|
||||
@@ -290,6 +336,7 @@ function buildPublicTrainingStats(laps) {
|
||||
todayCompletedFiveMinuteStints: todayStintSummary.completedFiveMinuteStints,
|
||||
dailySummaries,
|
||||
stintCount: stints.length,
|
||||
stintSummaries,
|
||||
bestThreeConsecutive,
|
||||
bestFiveMinuteResult,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user