import type { GameState } from '@ai-tycoon/shared'; import { INITIAL_SETTINGS, SAVE_VERSION, INITIAL_ECONOMY, INITIAL_INFRASTRUCTURE, INITIAL_COMPUTE, INITIAL_RESEARCH, INITIAL_MODELS, INITIAL_MARKET, INITIAL_COMPETITORS, INITIAL_TALENT, INITIAL_DATA, INITIAL_REPUTATION, INITIAL_ACHIEVEMENTS, } from '@ai-tycoon/shared'; export type DeepPartial = T extends object ? { [K in keyof T]?: DeepPartial } : T; function deepMerge(target: T, source: DeepPartial): T { if (source === undefined || source === null) return target; if (typeof target !== 'object' || target === null) return source as T; if (Array.isArray(source)) return source as unknown as T; const result = { ...target }; for (const key of Object.keys(source) as (keyof T)[]) { const srcVal = source[key]; if (srcVal === undefined) continue; const tgtVal = result[key]; if ( typeof tgtVal === 'object' && tgtVal !== null && !Array.isArray(tgtVal) && typeof srcVal === 'object' && srcVal !== null && !Array.isArray(srcVal) ) { result[key] = deepMerge(tgtVal, srcVal as DeepPartial); } else { result[key] = srcVal as T[keyof T]; } } return result; } function baseState(): GameState { return { meta: { saveVersion: SAVE_VERSION, companyName: 'TestCorp', currentEra: 'startup', tickCount: 0, lastTickTimestamp: Date.now(), gameSpeed: 1, isPaused: false, createdAt: Date.now(), totalPlayTime: 0, settings: { ...INITIAL_SETTINGS }, }, economy: structuredClone(INITIAL_ECONOMY), infrastructure: structuredClone(INITIAL_INFRASTRUCTURE), compute: structuredClone(INITIAL_COMPUTE), research: structuredClone(INITIAL_RESEARCH), models: structuredClone(INITIAL_MODELS), market: structuredClone(INITIAL_MARKET), competitors: structuredClone(INITIAL_COMPETITORS), talent: structuredClone(INITIAL_TALENT), data: structuredClone(INITIAL_DATA), reputation: structuredClone(INITIAL_REPUTATION), achievements: structuredClone(INITIAL_ACHIEVEMENTS), }; } export function createTestState(overrides?: DeepPartial): GameState { const state = baseState(); if (!overrides) return state; return deepMerge(state, overrides); }