import assert from 'node:assert/strict'; import test from 'node:test'; import { susScoreWeight } from './sus-score-weight.mjs'; const text = `#MUSIC_ID m0001 #FULL_COMBO_NOTE_COUNT 7 #TOTAL_NOTE_COUNT 7 #NORMAL_NOTE_COUNT 1 #FLICK_NOTE_COUNT 1 #LONG_START_NOTE_COUNT 1 #LONG_END_NOTE_COUNT 0 #LONG_FLICK_END_NOTE_COUNT 1 #LONG_RELAY_NOTE_COUNT 1 #LONG_CONTINUE_NOTE_COUNT 2 #DAMAGE_NOTE_COUNT 0 #GHOST_NOTE_COUNT 0 #000320:140x0K3454 #000320:0xft4424 #00052:1c `; test('비가시·베지어는 분모에만 포함하고 끝 플릭은 1000으로 집계한다', () => { const result = susScoreWeight(text); assert.equal(result.fullComboNoteCount, 7); assert.equal(result.baseWeight, 4350); assert.equal(result.invisibleRelayCount, 1); assert.equal(result.bezierPointCount, 1); assert.equal(result.perfectNoteWeight, 4550); }); test('잘린 토큰·미지원 종류·헤더 불일치는 잘못된 분모 대신 실패한다', () => { for (const changed of [text.replace('0xft', '0x!t'), text + '#001320:4', text + '#001320:64', text.replace('LONG_START_NOTE_COUNT 1', 'LONG_START_NOTE_COUNT 2')]) { assert.throws(() => susScoreWeight(changed)); } }); test('고스트 가이드는 총 오브젝트 수에는 포함하지만 점수 분모에는 포함하지 않는다', () => { const withGhost = text.replace('GHOST_NOTE_COUNT 0', 'GHOST_NOTE_COUNT 2').replace('TOTAL_NOTE_COUNT 7', 'TOTAL_NOTE_COUNT 9'); assert.equal(susScoreWeight(withGhost).perfectNoteWeight, 4550); });