138 lines
5.1 KiB
TypeScript
138 lines
5.1 KiB
TypeScript
import { type GameDefinition } from '../core/gameDefinition'
|
|
import { type GameSessionState } from '../core/gameSessionState'
|
|
import { type TelemetryPresentation } from '../telemetry/telemetryPresentation'
|
|
|
|
export interface ResultSummaryRow {
|
|
label: string
|
|
value: string
|
|
}
|
|
|
|
export interface ResultSummarySnapshot {
|
|
title: string
|
|
subtitle: string
|
|
heroLabel: string
|
|
heroValue: string
|
|
rows: ResultSummaryRow[]
|
|
}
|
|
|
|
export interface ResultSummaryMetrics {
|
|
totalScore?: number
|
|
baseScore?: number
|
|
bonusScore?: number
|
|
quizCorrectCount?: number
|
|
quizWrongCount?: number
|
|
quizTimeoutCount?: number
|
|
}
|
|
|
|
function resolveTitle(definition: GameDefinition | null, mapTitle: string): string {
|
|
if (mapTitle) {
|
|
return mapTitle
|
|
}
|
|
if (definition && definition.title) {
|
|
return definition.title
|
|
}
|
|
return '本局结果'
|
|
}
|
|
|
|
function buildHeroValue(
|
|
definition: GameDefinition | null,
|
|
sessionState: GameSessionState,
|
|
telemetryPresentation: TelemetryPresentation,
|
|
metrics?: ResultSummaryMetrics,
|
|
): string {
|
|
const totalScore = metrics && typeof metrics.totalScore === 'number'
|
|
? metrics.totalScore
|
|
: sessionState.score
|
|
if (definition && definition.mode === 'score-o') {
|
|
return `${totalScore}`
|
|
}
|
|
return telemetryPresentation.elapsedTimerText
|
|
}
|
|
|
|
function buildHeroLabel(definition: GameDefinition | null): string {
|
|
return definition && definition.mode === 'score-o' ? '本局得分' : '本局用时'
|
|
}
|
|
|
|
function buildSubtitle(sessionState: GameSessionState): string {
|
|
if (sessionState.status === 'finished') {
|
|
return '本局已完成'
|
|
}
|
|
if (sessionState.endReason === 'timed_out') {
|
|
return '本局超时结束'
|
|
}
|
|
if (sessionState.status === 'failed') {
|
|
return '本局已结束'
|
|
}
|
|
return '对局摘要'
|
|
}
|
|
|
|
export function buildResultSummarySnapshot(
|
|
definition: GameDefinition | null,
|
|
sessionState: GameSessionState | null,
|
|
telemetryPresentation: TelemetryPresentation,
|
|
mapTitle: string,
|
|
metrics?: ResultSummaryMetrics,
|
|
): ResultSummarySnapshot {
|
|
const resolvedSessionState: GameSessionState = sessionState || {
|
|
status: 'idle',
|
|
endReason: null,
|
|
startedAt: null,
|
|
endedAt: null,
|
|
completedControlIds: [],
|
|
skippedControlIds: [],
|
|
currentTargetControlId: null,
|
|
inRangeControlId: null,
|
|
score: 0,
|
|
guidanceState: 'searching',
|
|
modeState: null,
|
|
}
|
|
const skippedCount = resolvedSessionState.skippedControlIds.length
|
|
const totalControlCount = definition
|
|
? definition.controls.filter((control) => control.kind === 'control').length
|
|
: 0
|
|
const averageHeartRateText = telemetryPresentation.heartRateValueText !== '--'
|
|
? `${telemetryPresentation.heartRateValueText} ${telemetryPresentation.heartRateUnitText || 'bpm'}`
|
|
: '--'
|
|
const totalScore = metrics && typeof metrics.totalScore === 'number' ? metrics.totalScore : resolvedSessionState.score
|
|
const baseScore = metrics && typeof metrics.baseScore === 'number' ? metrics.baseScore : resolvedSessionState.score
|
|
const bonusScore = metrics && typeof metrics.bonusScore === 'number' ? metrics.bonusScore : 0
|
|
const quizCorrectCount = metrics && typeof metrics.quizCorrectCount === 'number' ? metrics.quizCorrectCount : 0
|
|
const quizWrongCount = metrics && typeof metrics.quizWrongCount === 'number' ? metrics.quizWrongCount : 0
|
|
const quizTimeoutCount = metrics && typeof metrics.quizTimeoutCount === 'number' ? metrics.quizTimeoutCount : 0
|
|
const includeQuizRows = bonusScore > 0 || quizCorrectCount > 0 || quizWrongCount > 0 || quizTimeoutCount > 0
|
|
const rows: ResultSummaryRow[] = [
|
|
{
|
|
label: '状态',
|
|
value: resolvedSessionState.endReason === 'timed_out'
|
|
? '超时结束'
|
|
: resolvedSessionState.status === 'finished'
|
|
? '完成'
|
|
: (resolvedSessionState.status === 'failed' ? '结束' : '进行中'),
|
|
},
|
|
{ label: '完成点数', value: totalControlCount > 0 ? `${resolvedSessionState.completedControlIds.length}/${totalControlCount}` : `${resolvedSessionState.completedControlIds.length}` },
|
|
{ label: '跳过点数', value: `${skippedCount}` },
|
|
{ label: '总分', value: `${totalScore}` },
|
|
]
|
|
|
|
if (includeQuizRows) {
|
|
rows.push({ label: '基础积分', value: `${baseScore}` })
|
|
rows.push({ label: '答题奖励积分', value: `${bonusScore}` })
|
|
rows.push({ label: '答题正确数', value: `${quizCorrectCount}` })
|
|
rows.push({ label: '答题错误数', value: `${quizWrongCount}` })
|
|
rows.push({ label: '答题超时数', value: `${quizTimeoutCount}` })
|
|
}
|
|
|
|
rows.push({ label: '累计里程', value: telemetryPresentation.mileageText })
|
|
rows.push({ label: '平均速度', value: `${telemetryPresentation.averageSpeedValueText}${telemetryPresentation.averageSpeedUnitText}` })
|
|
rows.push({ label: '累计消耗', value: `${telemetryPresentation.caloriesValueText}${telemetryPresentation.caloriesUnitText}` })
|
|
rows.push({ label: '平均心率', value: averageHeartRateText })
|
|
|
|
return {
|
|
title: resolveTitle(definition, mapTitle),
|
|
subtitle: buildSubtitle(resolvedSessionState),
|
|
heroLabel: buildHeroLabel(definition),
|
|
heroValue: buildHeroValue(definition, resolvedSessionState, telemetryPresentation, metrics),
|
|
rows,
|
|
}
|
|
}
|