resultSummary.ts 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import { type GameDefinition } from '../core/gameDefinition'
  2. import { type GameSessionState } from '../core/gameSessionState'
  3. import { type TelemetryPresentation } from '../telemetry/telemetryPresentation'
  4. export interface ResultSummaryRow {
  5. label: string
  6. value: string
  7. }
  8. export interface ResultSummarySnapshot {
  9. title: string
  10. subtitle: string
  11. heroLabel: string
  12. heroValue: string
  13. rows: ResultSummaryRow[]
  14. }
  15. function resolveTitle(definition: GameDefinition | null, mapTitle: string): string {
  16. if (mapTitle) {
  17. return mapTitle
  18. }
  19. if (definition && definition.title) {
  20. return definition.title
  21. }
  22. return '本局结果'
  23. }
  24. function buildHeroValue(definition: GameDefinition | null, sessionState: GameSessionState, telemetryPresentation: TelemetryPresentation): string {
  25. if (definition && definition.mode === 'score-o') {
  26. return `${sessionState.score}`
  27. }
  28. return telemetryPresentation.timerText
  29. }
  30. function buildHeroLabel(definition: GameDefinition | null): string {
  31. return definition && definition.mode === 'score-o' ? '本局得分' : '本局用时'
  32. }
  33. function buildSubtitle(sessionState: GameSessionState): string {
  34. if (sessionState.status === 'finished') {
  35. return '本局已完成'
  36. }
  37. if (sessionState.status === 'failed') {
  38. return '本局已结束'
  39. }
  40. return '对局摘要'
  41. }
  42. export function buildResultSummarySnapshot(
  43. definition: GameDefinition | null,
  44. sessionState: GameSessionState | null,
  45. telemetryPresentation: TelemetryPresentation,
  46. mapTitle: string,
  47. ): ResultSummarySnapshot {
  48. const resolvedSessionState: GameSessionState = sessionState || {
  49. status: 'idle',
  50. startedAt: null,
  51. endedAt: null,
  52. completedControlIds: [],
  53. skippedControlIds: [],
  54. currentTargetControlId: null,
  55. inRangeControlId: null,
  56. score: 0,
  57. guidanceState: 'searching',
  58. modeState: null,
  59. }
  60. const skippedCount = resolvedSessionState.skippedControlIds.length
  61. const totalControlCount = definition
  62. ? definition.controls.filter((control) => control.kind === 'control').length
  63. : 0
  64. const averageHeartRateText = telemetryPresentation.heartRateValueText !== '--'
  65. ? `${telemetryPresentation.heartRateValueText} ${telemetryPresentation.heartRateUnitText || 'bpm'}`
  66. : '--'
  67. return {
  68. title: resolveTitle(definition, mapTitle),
  69. subtitle: buildSubtitle(resolvedSessionState),
  70. heroLabel: buildHeroLabel(definition),
  71. heroValue: buildHeroValue(definition, resolvedSessionState, telemetryPresentation),
  72. rows: [
  73. { label: '状态', value: resolvedSessionState.status === 'finished' ? '完成' : (resolvedSessionState.status === 'failed' ? '结束' : '进行中') },
  74. { label: '完成点数', value: totalControlCount > 0 ? `${resolvedSessionState.completedControlIds.length}/${totalControlCount}` : `${resolvedSessionState.completedControlIds.length}` },
  75. { label: '跳过点数', value: `${skippedCount}` },
  76. { label: '累计里程', value: telemetryPresentation.mileageText },
  77. { label: '平均速度', value: `${telemetryPresentation.averageSpeedValueText}${telemetryPresentation.averageSpeedUnitText}` },
  78. { label: '当前得分', value: `${resolvedSessionState.score}` },
  79. { label: '累计消耗', value: `${telemetryPresentation.caloriesValueText}${telemetryPresentation.caloriesUnitText}` },
  80. { label: '平均心率', value: averageHeartRateText },
  81. ],
  82. }
  83. }