import { runSimulation } from './runner'; import { GreedyStrategy } from './strategies/greedy'; import { RandomStrategy } from './strategies/random'; import { PersonaStrategy } from './strategies/persona'; import { printConsoleReport, generateJsonReport } from './analysis/report'; import { writeFileSync } from 'node:fs'; import { resolve, dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; import type { SimulationMetrics } from './strategies/types'; const args = process.argv.slice(2); function getArg(name: string, defaultValue: string): string { const idx = args.indexOf(`--${name}`); return idx !== -1 && args[idx + 1] ? args[idx + 1] : defaultValue; } function hasFlag(name: string): boolean { return args.includes(`--${name}`); } const strategyName = getArg('strategy', 'greedy'); const totalTicks = parseInt(getArg('ticks', '28800'), 10); const decisionInterval = parseInt(getArg('interval', '60'), 10); const seedStr = getArg('seed', ''); const seed = seedStr ? parseInt(seedStr, 10) : undefined; const jsonOutput = hasFlag('json'); const verbose = hasFlag('verbose'); const csvOutput = hasFlag('csv'); const strategy = strategyName === 'random' ? new RandomStrategy() : strategyName === 'persona' ? new PersonaStrategy(seed ?? 42) : new GreedyStrategy(); console.log(`Running ${strategyName} simulation: ${totalTicks.toLocaleString()} ticks, interval ${decisionInterval}${seed !== undefined ? `, seed ${seed}` : ''}...`); const result = runSimulation({ totalTicks, decisionInterval, strategy, seed, verbose }); const __dirname = dirname(fileURLToPath(import.meta.url)); if (csvOutput) { const allMetrics = result.metrics; if (allMetrics.length > 0) { const scalarKeys = Object.keys(allMetrics[0]).filter(k => k !== 'completedResearchIds') as (keyof SimulationMetrics)[]; const headers = scalarKeys.join(','); const rows = allMetrics.map(m => scalarKeys.map(k => { const v = m[k]; return typeof v === 'number' ? v : String(v); }).join(','), ); const csv = [headers, ...rows].join('\n'); const csvPath = resolve(__dirname, '..', 'balance-metrics.csv'); writeFileSync(csvPath, csv); console.log(`Metrics CSV written to ${csvPath}`); } } if (jsonOutput) { const report = generateJsonReport(result, { totalTicks, decisionInterval, strategy, seed }); const outPath = resolve(__dirname, '..', 'balance-report.json'); writeFileSync(outPath, JSON.stringify(report, null, 2)); console.log(`Report written to ${outPath}`); printConsoleReport(result, { totalTicks, decisionInterval, strategy, seed }, verbose); if (!report.passed) { console.log('FAILED:'); for (const reason of report.failureReasons) { console.log(` - ${reason}`); } process.exit(1); } else { console.log('PASSED: All balance checks within thresholds.'); } } else { printConsoleReport(result, { totalTicks, decisionInterval, strategy, seed }, verbose); }