import { type RemoteMapConfig } from '../../utils/remoteMapConfig' import { type GameAudioConfig } from '../audio/audioConfig' import { type GameHapticsConfig, type GameUiEffectsConfig } from '../feedback/feedbackConfig' import { getGameModeDefaults } from './gameModeDefaults' import { resolveSystemSettingsState, type ResolvedSystemSettingsState, } from './systemSettingsState' import { type CourseStyleConfig } from '../presentation/courseStyleConfig' import { type GpsMarkerStyleConfig } from '../presentation/gpsMarkerStyleConfig' import { type TrackVisualizationConfig } from '../presentation/trackStyleConfig' import { mergeTelemetrySources, type PlayerTelemetryProfile } from '../telemetry/playerTelemetryProfile' import { type TelemetryConfig } from '../telemetry/telemetryConfig' export interface RuntimeMapProfile { title: string tileSource: string projectionModeText: string magneticDeclinationText: string cpRadiusMeters: number projection: string magneticDeclinationDeg: number minZoom: number maxZoom: number initialZoom: number initialCenterTileX: number initialCenterTileY: number tileBoundsByZoom: RemoteMapConfig['tileBoundsByZoom'] courseStatusText: string } export interface RuntimeGameProfile { mode: RemoteMapConfig['gameMode'] sessionCloseAfterMs: number sessionCloseWarningMs: number minCompletedControlsBeforeFinish: number punchPolicy: RemoteMapConfig['punchPolicy'] punchRadiusMeters: number requiresFocusSelection: boolean skipEnabled: boolean skipRadiusMeters: number skipRequiresConfirm: boolean autoFinishOnLastControl: boolean defaultControlScore: number | null } export interface RuntimePresentationProfile { course: CourseStyleConfig track: TrackVisualizationConfig gpsMarker: GpsMarkerStyleConfig } export interface RuntimeFeedbackProfile { audio: GameAudioConfig haptics: GameHapticsConfig uiEffects: GameUiEffectsConfig } export interface RuntimeTelemetryProfile { config: TelemetryConfig playerProfile: PlayerTelemetryProfile | null } export interface RuntimeSettingsProfile extends ResolvedSystemSettingsState { lockLifetimeActive: boolean } export interface CompiledRuntimeProfile { map: RuntimeMapProfile game: RuntimeGameProfile settings: RuntimeSettingsProfile telemetry: RuntimeTelemetryProfile presentation: RuntimePresentationProfile feedback: RuntimeFeedbackProfile } export interface CompileRuntimeProfileOptions { playerTelemetryProfile?: PlayerTelemetryProfile | null settingsLockLifetimeActive?: boolean storedSettingsKey?: string } export function compileRuntimeProfile( config: RemoteMapConfig, options?: CompileRuntimeProfileOptions, ): CompiledRuntimeProfile { const modeDefaults = getGameModeDefaults(config.gameMode) const lockLifetimeActive = !!(options && options.settingsLockLifetimeActive === true) const playerTelemetryProfile = options && options.playerTelemetryProfile ? Object.assign({}, options.playerTelemetryProfile) : null const settings = resolveSystemSettingsState( config.systemSettingsConfig, options && options.storedSettingsKey ? options.storedSettingsKey : undefined, lockLifetimeActive, ) return { map: { title: config.configTitle, tileSource: config.tileSource, projectionModeText: config.projectionModeText, magneticDeclinationText: config.magneticDeclinationText, cpRadiusMeters: config.cpRadiusMeters, projection: config.projection, magneticDeclinationDeg: config.magneticDeclinationDeg, minZoom: config.minZoom, maxZoom: config.maxZoom, initialZoom: config.defaultZoom, initialCenterTileX: config.initialCenterTileX, initialCenterTileY: config.initialCenterTileY, tileBoundsByZoom: config.tileBoundsByZoom, courseStatusText: config.courseStatusText, }, game: { mode: config.gameMode, sessionCloseAfterMs: config.sessionCloseAfterMs || modeDefaults.sessionCloseAfterMs, sessionCloseWarningMs: config.sessionCloseWarningMs || modeDefaults.sessionCloseWarningMs, minCompletedControlsBeforeFinish: config.minCompletedControlsBeforeFinish, punchPolicy: config.punchPolicy, punchRadiusMeters: config.punchRadiusMeters, requiresFocusSelection: config.requiresFocusSelection, skipEnabled: config.skipEnabled, skipRadiusMeters: config.skipRadiusMeters, skipRequiresConfirm: config.skipRequiresConfirm, autoFinishOnLastControl: config.autoFinishOnLastControl, defaultControlScore: config.defaultControlScore, }, settings: { values: settings.values, locks: settings.locks, lockLifetimeActive, }, telemetry: { config: mergeTelemetrySources(config.telemetryConfig, playerTelemetryProfile), playerProfile: playerTelemetryProfile, }, presentation: { course: config.courseStyleConfig, track: config.trackStyleConfig, gpsMarker: config.gpsMarkerStyleConfig, }, feedback: { audio: config.audioConfig, haptics: config.hapticsConfig, uiEffects: config.uiEffectsConfig, }, } }