Music Shake 첫 박 시각 · 카운트다운 · 옛 일시 정지 판 정리
This commit is contained in:
@@ -19,6 +19,36 @@ void main() {
|
||||
segments: 3,
|
||||
);
|
||||
|
||||
test('첫 박 · 판 길이가 바뀐 뒤의 옛 일시 정지는 이어하지 않는다 (10/6 대표 지적)', () {
|
||||
const fresh = MusicShakeSetup(
|
||||
videoId: 'v', title: 't', bpm: 114, segments: 368,
|
||||
firstBeat: Duration(milliseconds: 24276),
|
||||
);
|
||||
// 첫 박 도입 전(32박, 첫 박 0)에 저장된 판.
|
||||
const old = QuestSession(state: QuestStage.paused, progress: 19, total: 32);
|
||||
expect(old.fitsShake(fresh), isFalse);
|
||||
const same = QuestSession(
|
||||
state: QuestStage.paused, progress: 19, total: 368,
|
||||
firstBeat: Duration(milliseconds: 24276),
|
||||
);
|
||||
expect(same.fitsShake(fresh), isTrue);
|
||||
});
|
||||
|
||||
test('새 판은 첫 박 leadIn 전부터 틀고, 첫 박이 더 이르면 0 이다 (10/6 B안)', () {
|
||||
const s = MusicShakeSetup(
|
||||
videoId: 'v', title: 't', bpm: 114, segments: 368,
|
||||
firstBeat: Duration(milliseconds: 24276),
|
||||
);
|
||||
expect(s.startAt, const Duration(milliseconds: 21276));
|
||||
expect(
|
||||
const MusicShakeSetup(
|
||||
videoId: 'v', title: 't', bpm: 60, segments: 3,
|
||||
firstBeat: Duration(seconds: 2),
|
||||
).startAt,
|
||||
Duration.zero,
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('재생 중 흔들기만 영상 시각으로 판정 · 끝나면 판정표를 돌려준다', (tester) async {
|
||||
final shakes = StreamController<DateTime>();
|
||||
addTearDown(shakes.close);
|
||||
@@ -35,6 +65,7 @@ void main() {
|
||||
MaterialPageRoute(
|
||||
builder: (_) => MusicShakePlayScreen(
|
||||
setup: setup,
|
||||
countdown: Duration.zero,
|
||||
shakes: shakes.stream,
|
||||
player: (onEvent) {
|
||||
player = onEvent;
|
||||
@@ -141,6 +172,7 @@ void main() {
|
||||
MaterialPageRoute(
|
||||
builder: (_) => MusicShakePlayScreen(
|
||||
setup: setup,
|
||||
countdown: Duration.zero,
|
||||
shakes: shakes.stream,
|
||||
judge: judge,
|
||||
player: (onEvent) {
|
||||
@@ -181,4 +213,48 @@ void main() {
|
||||
expect(resume, contains('player.seekTo(9.91,true);player.playVideo();'));
|
||||
expect(YoutubeEmbed.html('vid'), isNot(contains('playVideo')));
|
||||
});
|
||||
|
||||
testWidgets('재생을 시작하면 3·2·1 을 세는 동안 판정하지 않고, 0 이 되면 판정이 시작된다', (tester) async {
|
||||
final shakes = StreamController<DateTime>();
|
||||
addTearDown(shakes.close);
|
||||
late ValueChanged<ShakePlayerEvent> player;
|
||||
final judge = ShakeJudge(bpm: 60, segments: 3);
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: buildAppTheme(),
|
||||
home: MusicShakePlayScreen(
|
||||
setup: setup,
|
||||
countdown: const Duration(milliseconds: 500), // 화면은 단말 시계로 센다
|
||||
shakes: shakes.stream,
|
||||
judge: judge,
|
||||
player: (onEvent) {
|
||||
player = onEvent;
|
||||
return const SizedBox();
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
player((playing: true, position: Duration.zero, ended: false));
|
||||
await tester.pump(const Duration(milliseconds: 60));
|
||||
expect(find.text('1'), findsOneWidget);
|
||||
shakes.add(DateTime.now()); // 세는 동안의 흔들기는 세지 않는다.
|
||||
await tester.runAsync(() => Future<void>.delayed(const Duration(milliseconds: 700)));
|
||||
await tester.pump(const Duration(milliseconds: 60));
|
||||
await tester.pump(const Duration(milliseconds: 60));
|
||||
expect(find.text('1'), findsNothing);
|
||||
player((playing: true, position: Duration.zero, ended: false));
|
||||
shakes.add(DateTime.now());
|
||||
await tester.pump(const Duration(milliseconds: 60));
|
||||
expect(judge.hits[0], inInclusiveRange(0, 0.01));
|
||||
await tester.pumpWidget(const SizedBox());
|
||||
});
|
||||
|
||||
test('박은 firstBeat 부터 — 인트로의 흔들기는 박이 아니다', () {
|
||||
final j = ShakeJudge(bpm: 60, segments: 2, firstBeat: const Duration(seconds: 17))
|
||||
..add(const Duration(seconds: 1))
|
||||
..add(const Duration(seconds: 17))
|
||||
..add(const Duration(milliseconds: 18300));
|
||||
expect(j.end, const Duration(milliseconds: 18500));
|
||||
expect(j.judgement(), {'perfect': 1, 'good': 1, 'miss': 0, 'maxCombo': 2});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user