| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- import { type LonLatPoint } from '../../utils/projection'
- import { type GameLaunchEnvelope } from '../../utils/gameLaunch'
- import { type GameSessionState } from './gameSessionState'
- export interface RecoveryTelemetrySnapshot {
- distanceMeters: number
- currentSpeedKmh: number | null
- averageSpeedKmh: number | null
- heartRateBpm: number | null
- caloriesKcal: number | null
- lastGpsPoint: LonLatPoint | null
- lastGpsAt: number | null
- lastGpsAccuracyMeters: number | null
- }
- export interface RecoveryViewportSnapshot {
- zoom: number
- centerTileX: number
- centerTileY: number
- rotationDeg: number
- gpsLockEnabled: boolean
- hasGpsCenteredOnce: boolean
- }
- export interface RecoveryRuntimeSnapshot {
- gameState: GameSessionState
- telemetry: RecoveryTelemetrySnapshot
- viewport: RecoveryViewportSnapshot
- currentGpsPoint: LonLatPoint | null
- currentGpsAccuracyMeters: number | null
- currentGpsInsideMap: boolean
- bonusScore: number
- quizCorrectCount: number
- quizWrongCount: number
- quizTimeoutCount: number
- }
- export interface SessionRecoverySnapshot {
- schemaVersion: 1
- savedAt: number
- launchEnvelope: GameLaunchEnvelope
- configAppId: string
- configVersion: string
- runtime: RecoveryRuntimeSnapshot
- }
- const SESSION_RECOVERY_STORAGE_KEY = 'cmr.sessionRecovery.v1'
- function cloneLonLatPoint(point: LonLatPoint | null): LonLatPoint | null {
- if (!point) {
- return null
- }
- return {
- lon: point.lon,
- lat: point.lat,
- }
- }
- function cloneGameSessionState(state: GameSessionState): GameSessionState {
- return {
- status: state.status,
- endReason: state.endReason,
- startedAt: state.startedAt,
- endedAt: state.endedAt,
- completedControlIds: state.completedControlIds.slice(),
- skippedControlIds: state.skippedControlIds.slice(),
- currentTargetControlId: state.currentTargetControlId,
- inRangeControlId: state.inRangeControlId,
- score: state.score,
- guidanceState: state.guidanceState,
- modeState: state.modeState
- ? JSON.parse(JSON.stringify(state.modeState)) as Record<string, unknown>
- : null,
- }
- }
- export function cloneSessionRecoverySnapshot(snapshot: SessionRecoverySnapshot): SessionRecoverySnapshot {
- return {
- schemaVersion: 1,
- savedAt: snapshot.savedAt,
- launchEnvelope: JSON.parse(JSON.stringify(snapshot.launchEnvelope)) as GameLaunchEnvelope,
- configAppId: snapshot.configAppId,
- configVersion: snapshot.configVersion,
- runtime: {
- gameState: cloneGameSessionState(snapshot.runtime.gameState),
- telemetry: {
- distanceMeters: snapshot.runtime.telemetry.distanceMeters,
- currentSpeedKmh: snapshot.runtime.telemetry.currentSpeedKmh,
- averageSpeedKmh: snapshot.runtime.telemetry.averageSpeedKmh,
- heartRateBpm: snapshot.runtime.telemetry.heartRateBpm,
- caloriesKcal: snapshot.runtime.telemetry.caloriesKcal,
- lastGpsPoint: cloneLonLatPoint(snapshot.runtime.telemetry.lastGpsPoint),
- lastGpsAt: snapshot.runtime.telemetry.lastGpsAt,
- lastGpsAccuracyMeters: snapshot.runtime.telemetry.lastGpsAccuracyMeters,
- },
- viewport: {
- zoom: snapshot.runtime.viewport.zoom,
- centerTileX: snapshot.runtime.viewport.centerTileX,
- centerTileY: snapshot.runtime.viewport.centerTileY,
- rotationDeg: snapshot.runtime.viewport.rotationDeg,
- gpsLockEnabled: snapshot.runtime.viewport.gpsLockEnabled,
- hasGpsCenteredOnce: snapshot.runtime.viewport.hasGpsCenteredOnce,
- },
- currentGpsPoint: cloneLonLatPoint(snapshot.runtime.currentGpsPoint),
- currentGpsAccuracyMeters: snapshot.runtime.currentGpsAccuracyMeters,
- currentGpsInsideMap: snapshot.runtime.currentGpsInsideMap,
- bonusScore: snapshot.runtime.bonusScore,
- quizCorrectCount: snapshot.runtime.quizCorrectCount,
- quizWrongCount: snapshot.runtime.quizWrongCount,
- quizTimeoutCount: snapshot.runtime.quizTimeoutCount,
- },
- }
- }
- function normalizeSessionRecoverySnapshot(raw: unknown): SessionRecoverySnapshot | null {
- if (!raw || typeof raw !== 'object') {
- return null
- }
- const candidate = raw as SessionRecoverySnapshot
- if (candidate.schemaVersion !== 1 || !candidate.runtime || !candidate.runtime.gameState) {
- return null
- }
- return cloneSessionRecoverySnapshot(candidate)
- }
- export function loadSessionRecoverySnapshot(): SessionRecoverySnapshot | null {
- try {
- return normalizeSessionRecoverySnapshot(wx.getStorageSync(SESSION_RECOVERY_STORAGE_KEY))
- } catch {
- return null
- }
- }
- export function saveSessionRecoverySnapshot(snapshot: SessionRecoverySnapshot): void {
- try {
- wx.setStorageSync(SESSION_RECOVERY_STORAGE_KEY, cloneSessionRecoverySnapshot(snapshot))
- } catch {}
- }
- export function clearSessionRecoverySnapshot(): void {
- try {
- wx.removeStorageSync(SESSION_RECOVERY_STORAGE_KEY)
- } catch {}
- }
|