이클립스 방어 횟수 즉시 표시·진동 · Music Shake 영상 재생 중 흔들기 판정 · 결과 공유

This commit is contained in:
Sn-Kinos
2026-10-05 21:39:22 +09:00
parent 65669b969e
commit 17c658b272
30 changed files with 1337 additions and 144 deletions
+18 -1
View File
@@ -2,7 +2,8 @@ import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest';
import { getFirestore, FieldValue, Timestamp } from 'firebase-admin/firestore';
import { bootAdmin, shutdownAdmin, wipeUser } from './support.js';
import { distanceMeters, gradeShake } from '../src/quest/verify.js';
import { distanceMeters, gradeShake, videoIdOf } from '../src/quest/verify.js';
import { DEFAULT_POLICY } from '../src/core/config.js';
import { grantPop, refundPop, spendPop } from '../src/ledger/ledger.js';
/**
@@ -43,6 +44,22 @@ describe('Music Shake 판정 (E-02)', () => {
it('구간이 0이면 실격이다', () => {
expect(gradeShake({ perfect: 0, good: 0, miss: 0, maxCombo: 0 }, 0)).toBe('F');
});
it('성공 문턱 · 등급 문턱은 운영값이다 — 🟡 임시값 회신 대기 표시가 붙어 있다', () => {
expect(DEFAULT_POLICY.musicShake.provisional).toBe(true);
const strict = { ...DEFAULT_POLICY.musicShake, passRate: 0.9 };
// 기본 문턱(0.5)이면 C, 운영값을 0.9 로 올리면 실패다.
expect(gradeShake({ perfect: 6, good: 6, miss: 8, maxCombo: 6 }, 20)).toBe('C');
expect(gradeShake({ perfect: 6, good: 6, miss: 8, maxCombo: 6 }, 20, strict)).toBe('F');
});
it('지정 공식 영상 링크에서 영상 ID 를 꺼낸다', () => {
expect(videoIdOf('https://www.youtube.com/watch?v=WMweEpGlu_U')).toBe('WMweEpGlu_U');
expect(videoIdOf('https://youtu.be/WMweEpGlu_U?si=x')).toBe('WMweEpGlu_U');
expect(videoIdOf('https://music.youtube.com/watch?v=WMweEpGlu_U')).toBe('WMweEpGlu_U');
expect(videoIdOf('https://vimeo.com/1')).toBeNull();
expect(videoIdOf(undefined)).toBeNull();
});
});
describe('방문 거리 (E-06)', () => {