feat: release version 1.0.7
This commit is contained in:
@@ -6,8 +6,20 @@ const outputDirectory = path.resolve('static/data/charts');
|
||||
const catalogPath = path.resolve('src/lib/data/exact-chart-catalog.json');
|
||||
const selectedDifficulties = new Set(['HARD', 'EXPERT']);
|
||||
const chartScoreWeightCoefficient = 0.3713416563352296;
|
||||
const scoreCalibrations = JSON.parse(await readFile(path.resolve('data/score-calibrations.json'), 'utf8'));
|
||||
const scoreCalibrationByKey = new Map(scoreCalibrations.charts.map((row) => [
|
||||
`${row.songId}::${row.difficulty}`,
|
||||
row
|
||||
]));
|
||||
const musicMaster = JSON.parse(await readFile(path.resolve('data/raw/holodoridb/kor/Music.json'), 'utf8'));
|
||||
const musicById = new Map(musicMaster.map((row) => [row.data?.id ?? row.id, row.data ?? row]));
|
||||
const englishMusicText = JSON.parse(await readFile(path.resolve('data/raw/holodoridb/eng/LangMusic_Eng.json'), 'utf8'));
|
||||
const englishTextById = new Map(englishMusicText.map((row) => [row.data?.id ?? row.id, row.data?.text ?? row.text]));
|
||||
const musicDifficultyMaster = JSON.parse(await readFile(path.resolve('data/raw/holodoridb/kor/MusicDifficulty.json'), 'utf8'));
|
||||
const difficultyLevelByKey = new Map(musicDifficultyMaster.map((row) => {
|
||||
const data = row.data ?? row;
|
||||
return [`${data.musicId}::${data.difficultyType.split('_').at(-1)?.toLowerCase()}`, data.difficultyLevel];
|
||||
}));
|
||||
const singerMetadataOverrides = {
|
||||
m0334: { singerType: 'solo', singerCharacterIds: ['chr-04001'] }
|
||||
};
|
||||
@@ -190,8 +202,10 @@ const importPattern = /charts\/([^"/]+\.json)"[^\n]{0,180}?import\("\.\/([^"/]+\
|
||||
for (const match of simulatorModule.matchAll(importPattern)) {
|
||||
const [, chartFile, assetFile] = match;
|
||||
const [songId, difficultyAndLevel] = chartFile.split('.', 2);
|
||||
const difficulty = difficultyAndLevel.split('-')[0].toUpperCase();
|
||||
if (selectedDifficulties.has(difficulty)) imports.push({ songId, difficulty, chartFile, assetFile });
|
||||
const [difficultyName, difficultyLevelText] = difficultyAndLevel.split('-');
|
||||
const difficulty = difficultyName.toUpperCase();
|
||||
const difficultyLevel = Number.parseInt(difficultyLevelText, 10);
|
||||
if (selectedDifficulties.has(difficulty)) imports.push({ songId, difficulty, difficultyLevel, chartFile, assetFile });
|
||||
}
|
||||
|
||||
if (imports.length === 0) throw new Error('수집할 Hard/Expert 채보 모듈을 찾지 못했습니다.');
|
||||
@@ -211,15 +225,15 @@ async function worker() {
|
||||
const music = musicById.get(item.songId);
|
||||
const singerOverride = singerMetadataOverrides[item.songId];
|
||||
const notes = flattenEvents(chartData);
|
||||
const measuredCalibration = scoreCalibrationByKey.get(`${item.songId}::${item.difficulty.toLowerCase()}`);
|
||||
const output = {
|
||||
schemaVersion: 1,
|
||||
songId: item.songId,
|
||||
difficulty: item.difficulty.toLowerCase(),
|
||||
durationSeconds: sourceEntry?.durationSeconds ?? Math.ceil(notes.at(-1)?.timeSeconds ?? 0),
|
||||
// 실측으로 보정된 1노트 기본점수 분모는 기존 채보 가중치 모델을 유지한다.
|
||||
// 실제 점수 타임라인의 롱노트 분류와는 별개의 보정값이다.
|
||||
scoreRatio: calibratedScoreRatio(chartData),
|
||||
scoreCalibrationSource: 'measured-formula-v1',
|
||||
// 실측이 있으면 우선하고, 없을 때만 채보 가중치와 계산기 고유 상수로 추정한다.
|
||||
scoreRatio: measuredCalibration?.scoreRatio ?? calibratedScoreRatio(chartData),
|
||||
scoreCalibrationSource: measuredCalibration ? 'measured' : 'local-estimated-v1',
|
||||
notes,
|
||||
specialStartSeconds: (chartData.sp_activation_events ?? [])
|
||||
.sort((left, right) => left.slot - right.slot)
|
||||
@@ -236,10 +250,13 @@ async function worker() {
|
||||
await writeFile(path.join(outputDirectory, fileName), JSON.stringify(output), 'utf8');
|
||||
normalizedCharts.push({
|
||||
songId: item.songId,
|
||||
title: sourceEntry?.title ?? item.songId,
|
||||
title: englishTextById.get(`la-music_title-${item.songId}`) ?? sourceEntry?.title ?? item.songId,
|
||||
difficulty: item.difficulty.toLowerCase(),
|
||||
difficultyLevel: difficultyLevelByKey.get(`${item.songId}::${item.difficulty.toLowerCase()}`) ??
|
||||
(Number.isFinite(item.difficultyLevel) ? item.difficultyLevel : null),
|
||||
durationSeconds: output.durationSeconds,
|
||||
scoreRatio: output.scoreRatio,
|
||||
scoreCalibrationSource: output.scoreCalibrationSource,
|
||||
totalNotes: notes.length,
|
||||
singerType: output.singerType,
|
||||
singerCharacterIds: output.singerCharacterIds,
|
||||
|
||||
Reference in New Issue
Block a user