24 lines
1.8 KiB
JavaScript
24 lines
1.8 KiB
JavaScript
// node scripts/calculate-sus-score-formula.mjs data/raw/sus/chart_m0341_expert.sus
|
|
import { readFile } from 'node:fs/promises';
|
|
import { createHash } from 'node:crypto';
|
|
import { basename } from 'node:path';
|
|
import { susScoreWeight } from './sus-score-weight.mjs';
|
|
import { scoreRatioFromFormula } from '../src/lib/engine/score.ts';
|
|
|
|
const file = process.argv[2];
|
|
if (!file) throw new Error('원본 SUS 경로를 지정하세요.');
|
|
const bytes = await readFile(file);
|
|
const result = susScoreWeight(bytes.toString('utf8'));
|
|
const difficulty = basename(file).match(/_(easy|normal|hard|expert)\.sus$/)?.[1];
|
|
const reference = JSON.parse(await readFile(new URL('../docs/research/song-score-formula-reference.json', import.meta.url), 'utf8'));
|
|
const catalog = JSON.parse(await readFile(new URL('../src/lib/data/exact-chart-catalog.json', import.meta.url), 'utf8'));
|
|
const chart = catalog.charts.find((row) => row.songId === result.songId && row.difficulty === difficulty);
|
|
const song = reference.charts.find((row) => row.songId === result.songId);
|
|
if (!chart || !song) throw new Error('카탈로그 난이도 또는 곡별 계수를 찾지 못했습니다.');
|
|
const local = JSON.parse(await readFile(new URL(`../static${chart.path}`, import.meta.url), 'utf8'));
|
|
const susSha256 = createHash('sha256').update(bytes).digest('hex');
|
|
if (local.source?.susSha256 !== susSha256 || local.notes.length !== result.fullComboNoteCount) throw new Error('현재 서비스와 다른 원본 채보입니다.');
|
|
// SUS SCORE_LEVEL is editor metadata; use the published master difficulty level.
|
|
const formula = { perfectNoteWeight: result.perfectNoteWeight, liveScoreCoefficientPermil: song.liveScoreCoefficientPermil, difficultyLevel: chart.difficultyLevel };
|
|
console.log(JSON.stringify({ ...result, difficulty, susSha256, ...formula, scoreRatio: scoreRatioFromFormula(formula) }, null, 2));
|