import { readFile, writeFile } from 'node:fs/promises'; import path from 'node:path'; import { assertValidScoreCalibrations } from './score-calibration-validation.mjs'; const calibrationPath = path.resolve('data/score-calibrations.json'); const catalogPath = path.resolve('src/lib/data/exact-chart-catalog.json'); const chartDirectory = path.resolve('static/data/charts'); const calibrations = JSON.parse(await readFile(calibrationPath, 'utf8')); const catalog = JSON.parse(await readFile(catalogPath, 'utf8')); const catalogRows = Array.isArray(catalog) ? catalog : catalog.charts; await assertValidScoreCalibrations(calibrations, { chartDirectory }); for (const calibration of calibrations.charts) { const difficulty = calibration.difficulty.toLowerCase(); const catalogRow = catalogRows.find((row) => row.songId === calibration.songId && row.difficulty.toLowerCase() === difficulty ); // Easy/Normal 실측도 보관하되 현재 생성 대상인 Hard/Expert만 즉시 동기화한다. if (!catalogRow) continue; // 공식 기반 채보는 실측 보정으로 덮어쓰지 않는다. 실측은 검증 자료로 유지한다. if (catalogRow.scoreCalibrationSource === 'formula-v1') continue; catalogRow.scoreRatio = calibration.scoreRatio; catalogRow.scoreCalibrationSource = 'measured'; const chartPath = path.join(chartDirectory, `${calibration.songId}.${difficulty}.json`); const chart = JSON.parse(await readFile(chartPath, 'utf8')); chart.scoreRatio = calibration.scoreRatio; chart.scoreCalibrationSource = 'measured'; await writeFile(chartPath, JSON.stringify(chart)); } await writeFile(catalogPath, `${JSON.stringify(catalog, null, 2)}\n`);