data: add 64 charts and event challenge
Publish GitHub Pages output / publish (push) Successful in 33s

This commit is contained in:
2026-09-25 20:31:50 +09:00
parent 167c933032
commit 29e70c565d
9 changed files with 119 additions and 2 deletions
+7 -1
View File
@@ -1,9 +1,15 @@
---
updatedAt: 2026-09-24T23:21:41Z
updatedAt: 2026-09-25T11:16:00Z
---
## 2026년 9월 25일
### 64. 악곡과 이벤트 과제곡 선택
`DATA` 아냐 멜핏사의 솔로곡 64.를 추가했습니다. Easy·Normal·Hard·Expert의 정확한 채보와 곡별 점수 계산을 지원합니다.
`IMPROVED` 이벤트 화면에서 이전 챕터의 악곡 선택이 저장돼 있어도 현재 챕터 과제곡을 먼저 선택합니다. 9월 25일 20시부터 아냐와 64.의 이벤트 보너스를 확인할 수 있습니다.
### 배치 분석 고점 달성 확률 추가
`IMPROVED` 배치 분석 결과와 저장 기록 상세에 최고점의 99.5% 이상을 얻을 확률과 기준 점수를 추가했습니다. 기존 99%·95% 확률과 함께 25,000회 반복 계산합니다.
+5 -1
View File
@@ -282,6 +282,10 @@
{"songId":"m0350","difficulty":"easy","susSha256":"a2d614636b37bbf203898d9de074dc70af0c243094eb6ce76dd696c413fc0f6c","fullComboNoteCount":431,"counts":{"NORMAL":104,"FLICK":0,"LONG_START":46,"LONG_END":46,"LONG_FLICK_END":0,"LONG_RELAY":25,"LONG_CONTINUE":210},"invisibleRelayCount":4,"bezierPointCount":0,"baseWeight":219500,"perfectNoteWeight":219900,"liveScoreCoefficientPermil":9,"difficultyLevel":8,"catalogRevision":83,"masterCommit":"5517e40b931fec10253f5b850989346518e233c2"},
{"songId":"m0350","difficulty":"normal","susSha256":"8a660117d447c482ff06f037b3af995575c11af5f3d63861030b331aa1900d9d","fullComboNoteCount":546,"counts":{"NORMAL":192,"FLICK":3,"LONG_START":51,"LONG_END":48,"LONG_FLICK_END":3,"LONG_RELAY":36,"LONG_CONTINUE":213},"invisibleRelayCount":2,"bezierPointCount":0,"baseWeight":322050,"perfectNoteWeight":322250,"liveScoreCoefficientPermil":9,"difficultyLevel":14,"catalogRevision":83,"masterCommit":"5517e40b931fec10253f5b850989346518e233c2"},
{"songId":"m0350","difficulty":"hard","susSha256":"94767b00c3aa93ad93a825e62b7071f94164541ab46acb60086306bb119a158c","fullComboNoteCount":997,"counts":{"NORMAL":257,"FLICK":41,"LONG_START":137,"LONG_END":111,"LONG_FLICK_END":26,"LONG_RELAY":111,"LONG_CONTINUE":314},"invisibleRelayCount":501,"bezierPointCount":0,"baseWeight":616550,"perfectNoteWeight":666650,"liveScoreCoefficientPermil":9,"difficultyLevel":24,"catalogRevision":83,"masterCommit":"5517e40b931fec10253f5b850989346518e233c2"},
{"songId":"m0350","difficulty":"expert","susSha256":"ff6864d6c9fd9dd089f1c30a66e33bc8841527d01877fedac8ea9765037b3ec8","fullComboNoteCount":1538,"counts":{"NORMAL":452,"FLICK":277,"LONG_START":207,"LONG_END":108,"LONG_FLICK_END":99,"LONG_RELAY":23,"LONG_CONTINUE":372},"invisibleRelayCount":1534,"bezierPointCount":0,"baseWeight":1196350,"perfectNoteWeight":1349750,"liveScoreCoefficientPermil":9,"difficultyLevel":29,"catalogRevision":83,"masterCommit":"5517e40b931fec10253f5b850989346518e233c2"}
{"songId":"m0350","difficulty":"expert","susSha256":"ff6864d6c9fd9dd089f1c30a66e33bc8841527d01877fedac8ea9765037b3ec8","fullComboNoteCount":1538,"counts":{"NORMAL":452,"FLICK":277,"LONG_START":207,"LONG_END":108,"LONG_FLICK_END":99,"LONG_RELAY":23,"LONG_CONTINUE":372},"invisibleRelayCount":1534,"bezierPointCount":0,"baseWeight":1196350,"perfectNoteWeight":1349750,"liveScoreCoefficientPermil":9,"difficultyLevel":29,"catalogRevision":83,"masterCommit":"5517e40b931fec10253f5b850989346518e233c2"},
{"songId":"m0352","difficulty":"easy","susSha256":"d31a500a280011ad6da7d48ef23b950ef59fe649e1135408166277f76d35223c","fullComboNoteCount":220,"counts":{"NORMAL":64,"FLICK":0,"LONG_START":21,"LONG_END":21,"LONG_FLICK_END":0,"LONG_RELAY":3,"LONG_CONTINUE":111},"invisibleRelayCount":0,"bezierPointCount":0,"baseWeight":117400,"perfectNoteWeight":117400,"liveScoreCoefficientPermil":7,"difficultyLevel":3,"catalogRevision":84,"masterCommit":"5517e40b931fec10253f5b850989346518e233c2"},
{"songId":"m0352","difficulty":"normal","susSha256":"097fddec319e17d1df3669068e794f826ea24a95b1b1f3a3959211570a309dd9","fullComboNoteCount":364,"counts":{"NORMAL":186,"FLICK":0,"LONG_START":32,"LONG_END":32,"LONG_FLICK_END":0,"LONG_RELAY":13,"LONG_CONTINUE":101},"invisibleRelayCount":0,"bezierPointCount":0,"baseWeight":261400,"perfectNoteWeight":261400,"liveScoreCoefficientPermil":7,"difficultyLevel":11,"catalogRevision":84,"masterCommit":"5517e40b931fec10253f5b850989346518e233c2"},
{"songId":"m0352","difficulty":"hard","susSha256":"f39acc366a08d344740cdad5d5dc80551d1df9f9dcaedb862558677c0e58ce5d","fullComboNoteCount":640,"counts":{"NORMAL":321,"FLICK":30,"LONG_START":74,"LONG_END":63,"LONG_FLICK_END":11,"LONG_RELAY":25,"LONG_CONTINUE":116},"invisibleRelayCount":15,"bezierPointCount":0,"baseWeight":514600,"perfectNoteWeight":516100,"liveScoreCoefficientPermil":7,"difficultyLevel":19,"catalogRevision":84,"masterCommit":"5517e40b931fec10253f5b850989346518e233c2"},
{"songId":"m0352","difficulty":"expert","susSha256":"71b330468b4d87a0db9f5734884934cf17252ed90ed69c8440b88122d550b0cb","fullComboNoteCount":1064,"counts":{"NORMAL":558,"FLICK":33,"LONG_START":135,"LONG_END":104,"LONG_FLICK_END":31,"LONG_RELAY":84,"LONG_CONTINUE":119},"invisibleRelayCount":227,"bezierPointCount":0,"baseWeight":882950,"perfectNoteWeight":905650,"liveScoreCoefficientPermil":7,"difficultyLevel":26,"catalogRevision":84,"masterCommit":"5517e40b931fec10253f5b850989346518e233c2"}
]
}
+84
View File
@@ -16618,6 +16618,90 @@
"releaseTime": 1789988400000,
"path": "/data/charts/m0351.normal.json"
},
{
"songId": "m0352",
"title": "64.",
"difficulty": "easy",
"difficultyLevel": 3,
"durationSeconds": 136,
"scoreRatio": 51.768233530293685,
"scoreCalibrationSource": "formula-v1",
"scoreFormula": {
"perfectNoteWeight": 117400,
"liveScoreCoefficientPermil": 7,
"difficultyLevel": 3
},
"totalNotes": 220,
"singerType": "solo",
"singerCharacterIds": [
"chr-03005"
],
"releaseTime": 1790334000000,
"path": "/data/charts/m0352.easy.json"
},
{
"songId": "m0352",
"title": "64.",
"difficulty": "expert",
"difficultyLevel": 26,
"durationSeconds": 136,
"scoreRatio": 343.2963117395095,
"scoreCalibrationSource": "formula-v1",
"scoreFormula": {
"perfectNoteWeight": 905650,
"liveScoreCoefficientPermil": 7,
"difficultyLevel": 26
},
"totalNotes": 1064,
"singerType": "solo",
"singerCharacterIds": [
"chr-03005"
],
"releaseTime": 1790334000000,
"path": "/data/charts/m0352.expert.json"
},
{
"songId": "m0352",
"title": "64.",
"difficulty": "hard",
"difficultyLevel": 19,
"durationSeconds": 136,
"scoreRatio": 204.36366516195457,
"scoreCalibrationSource": "formula-v1",
"scoreFormula": {
"perfectNoteWeight": 516100,
"liveScoreCoefficientPermil": 7,
"difficultyLevel": 19
},
"totalNotes": 640,
"singerType": "solo",
"singerCharacterIds": [
"chr-03005"
],
"releaseTime": 1790334000000,
"path": "/data/charts/m0352.hard.json"
},
{
"songId": "m0352",
"title": "64.",
"difficulty": "normal",
"difficultyLevel": 11,
"durationSeconds": 136,
"scoreRatio": 109.07118417758491,
"scoreCalibrationSource": "formula-v1",
"scoreFormula": {
"perfectNoteWeight": 261400,
"liveScoreCoefficientPermil": 7,
"difficultyLevel": 11
},
"totalNotes": 364,
"singerType": "solo",
"singerCharacterIds": [
"chr-03005"
],
"releaseTime": 1790334000000,
"path": "/data/charts/m0352.normal.json"
},
{
"songId": "m0353",
"title": "Night Loop",
+14
View File
@@ -39,6 +39,20 @@ test('신규 카드 공통 보너스와 현재 챕터 멤버 보너스를 따로
assert.equal(eventChallengeSongScoreBonusPercent(aki, 'm0349', [aki.featuredCardIds[1]]), 0);
});
test('9월 25일 20시부터 아냐와 64.가 마지막 챕터 보너스를 받는다', () => {
const before = activeEventAt(events, Date.parse('2026-09-25T10:59:59.999Z'))!;
const anya = activeEventAt(events, Date.parse('2026-09-25T11:00:00.000Z'))!;
const featuredAnya = { id: 'card-03005-5-uniq-0084-00', characterId: 'chr-03005', rarity: 5 };
assert.equal(before.id, 'marathon_event-relay-002-chapter-03');
assert.equal(anya.id, 'marathon_event-relay-002-chapter-04');
assert.deepEqual(anya.bonusCharacterIds, ['chr-03005']);
assert.deepEqual(anya.challengeSongBonusCardIds, { m0352: [featuredAnya.id] });
assert.equal(eventBonusBreakdown(anya, [featuredAnya], () => 0).totalPercent, 100);
assert.equal(eventChallengeSongScoreBonusPercent(anya, 'm0352', [featuredAnya.id]), 10);
assert.equal(eventChallengeSongScoreBonusPercent(before, 'm0352', [featuredAnya.id]), 0);
});
test('이벤트 기간 안에서만 진행 중 이벤트를 반환한다', () => {
assert.equal(activeEventAt(events, Date.parse('2026-08-29T02:59:59.999Z')), null);
assert.equal(activeEventAt(events, Date.parse('2026-08-31T00:00:00.000Z'))?.id, currentEvent.id);
+5
View File
@@ -352,6 +352,11 @@
try {
const state = JSON.parse(localStorage.getItem(STORAGE_KEY) ?? 'null') as SavedState | null;
if (state) applySavedState(state);
if (eventMode && currentEvent) {
const challengeSongId = Object.keys(currentEvent.challengeSongBonusCardIds)
.find((songId) => songs.some((song) => song.id === songId));
if (challengeSongId) selectedSongId = challengeSongId;
}
} catch {
localStorage.removeItem(STORAGE_KEY);
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long