Music Shake 첫 박 시각 · 카운트다운 · 옛 일시 정지 판 정리

This commit is contained in:
Sn-Kinos
2026-10-06 12:23:47 +09:00
parent 4e8d989f29
commit 14fef64999
24 changed files with 300 additions and 34 deletions
+28 -8
View File
@@ -408,7 +408,7 @@ service cloud.firestore {
}, SetOptions(merge: true));
await db.doc('quests/shake').set({
'type': 'musicshake', 'title': '응원 흔들기', 'dailyLimit': 1,
'totalSegments': 3, 'bpm': 120,
'totalSegments': 3, 'bpm': 120, 'firstBeatMs': 17000,
'link': {'url': 'https://youtu.be/WMweEpGlu_U', 'title': 'BTS - Butter'},
});
final backend = _RecordingBackend(db);
@@ -423,20 +423,22 @@ service cloud.firestore {
expect(setup.videoId, 'WMweEpGlu_U');
expect(setup.title, 'BTS - Butter');
expect((setup.bpm, setup.segments), (120.0, 3));
expect(setup.firstBeat, const Duration(seconds: 17));
expect((setup.windows.perfect, setup.windows.good), (0.1, 0.4));
// 판을 끝내기 전에는 서버를 부르지 않는다.
await expectLater(repo.verify(card), throwsA(isA<BackendException>()));
expect(backend.calls, isEmpty);
repo.recordShake(ShakeJudge(bpm: 120, segments: 3, windows: setup.windows)
..add(Duration.zero));
repo.recordShake(ShakeJudge(bpm: 120, segments: 3, firstBeat: setup.firstBeat, windows: setup.windows)
..add(setup.firstBeat));
await repo.verify(card);
final call = backend.calls.single;
expect(call.name, 'fnQuestVerifyMusicShake');
expect(call.payload['questId'], 'shake');
expect(call.payload['trackId'], 'WMweEpGlu_U');
expect(call.payload['totalSegments'], 3);
expect(call.payload['firstBeatMs'], 17000);
expect(call.payload['judgement'], {'perfect': 1, 'good': 0, 'miss': 2, 'maxCombo': 1});
});
@@ -661,7 +663,7 @@ service cloud.firestore {
final ref = db.doc('users/$_uid/questProgress/shake');
final repo = FirestoreQuestRepository(_RecordingBackend(db));
await ref.set({'session': {'state': 'inProgress', 'progress': 43, 'total': 60}});
await ref.set({'session': {'state': 'inProgress', 'progress': 43, 'total': 60, 'firstBeatMs': 0}});
var card = _card(await repo.load(), 'shake');
// 앱이 꺼진 진행중도 진행 화면 밖이므로 일시 정지다.
expect(card.stage, QuestStage.paused);
@@ -669,7 +671,7 @@ service cloud.firestore {
expect(QuestTab.inProgress.accepts(card), isTrue);
await ref.set({'session': {
'state': 'completed', 'progress': 60, 'total': 60,
'state': 'completed', 'progress': 60, 'total': 60, 'firstBeatMs': 0,
'judgement': {'perfect': 50, 'good': 5, 'miss': 5, 'maxCombo': 30},
}});
card = _card(await repo.load(), 'shake');
@@ -680,7 +682,7 @@ service cloud.firestore {
test('목록에서 바로 받는 Music Shake 는 서버 세션의 판정표를 보낸다', () async {
final db = await shakeSeed();
await db.doc('users/$_uid/questProgress/shake').set({'session': {
'state': 'completed', 'progress': 60, 'total': 60,
'state': 'completed', 'progress': 60, 'total': 60, 'firstBeatMs': 0,
'judgement': {'perfect': 50, 'good': 5, 'miss': 5, 'maxCombo': 30},
}});
final backend = _RecordingBackend(db);
@@ -733,11 +735,11 @@ service cloud.firestore {
'type': 'musicshake', 'title': '두 번째', 'totalSegments': 30, 'bpm': 100,
});
await db.doc('users/$_uid/questProgress/shake').set({'session': {
'state': 'paused', 'progress': 43, 'total': 60,
'state': 'paused', 'progress': 43, 'total': 60, 'firstBeatMs': 0,
'updatedAt': Timestamp.fromMillisecondsSinceEpoch(2000),
}});
await db.doc('users/$_uid/questProgress/shake2').set({'session': {
'state': 'paused', 'progress': 3, 'total': 30,
'state': 'paused', 'progress': 3, 'total': 30, 'firstBeatMs': 0,
'updatedAt': Timestamp.fromMillisecondsSinceEpoch(1000),
}});
final repo = FirestoreQuestRepository(_RecordingBackend(db));
@@ -745,5 +747,23 @@ service cloud.firestore {
expect(card?.id, 'shake');
expect((card?.session?.progress, card?.session?.total), (43, 60));
});
test('운영값이 바뀐 옛 Music Shake 판은 일시 정지로 보이지 않고 시작하기다 (10/6)', () async {
final db = await shakeSeed();
await db.doc('quests/shake').update({'firstBeatMs': 24276});
await db.doc('users/$_uid/questProgress/shake').set({'session': {
'state': 'paused', 'progress': 43, 'total': 60, 'firstBeatMs': 0,
}});
final repo = FirestoreQuestRepository(_RecordingBackend(db));
final card = _card(await repo.load(), 'shake');
expect((card.stage, card.session, card.staleShake), (QuestStage.notStarted, null, true));
expect(await repo.pausedQuest(), isNull);
// 맞는 판은 그대로 일시 정지다.
await db.doc('users/$_uid/questProgress/shake').set({'session': {
'state': 'paused', 'progress': 43, 'total': 60, 'firstBeatMs': 24276,
}});
final ok = _card(await repo.load(), 'shake');
expect((ok.stage, ok.staleShake), (QuestStage.paused, false));
});
});
}