diff --git a/mnemo_cards_web_v2/lib/di/user_scope/modules/tests_module.dart b/mnemo_cards_web_v2/lib/di/user_scope/modules/tests_module.dart index 851e2d5..78d3d8f 100644 --- a/mnemo_cards_web_v2/lib/di/user_scope/modules/tests_module.dart +++ b/mnemo_cards_web_v2/lib/di/user_scope/modules/tests_module.dart @@ -1,5 +1,7 @@ import 'package:yx_scope/yx_scope.dart'; +import 'package:game_tests/game_tests.dart'; + import '../../../domain/services/game_session_manager.dart'; import '../../../domain/services/game_sound_service.dart'; import '../../../domain/services/test_manager.dart'; @@ -27,12 +29,18 @@ class TestsModule extends ScopeModule { () => GameSoundService(), ); + // Game test settings + late final gameTestSettingsDep = dep( + () => const GameTestSettings(), + ); + // Tests State Manager late final testsStateManagerDep = dep( () => TestsStateManager( testManager: testManagerDep.get, gameSessionManager: gameSessionManagerDep.get, gameSoundService: gameSoundServiceDep.get, + settings: gameTestSettingsDep.get, ), ); @@ -40,4 +48,5 @@ class TestsModule extends ScopeModule { GameSoundService get gameSoundService => gameSoundServiceDep.get; TestManager get testManager => testManagerDep.get; TestsStateManager get testsStateManager => testsStateManagerDep.get; + GameTestSettings get gameTestSettings => gameTestSettingsDep.get; } diff --git a/mnemo_cards_web_v2/lib/domain/state/tests_state_manager.dart b/mnemo_cards_web_v2/lib/domain/state/tests_state_manager.dart index ebd5872..6ba87b9 100644 --- a/mnemo_cards_web_v2/lib/domain/state/tests_state_manager.dart +++ b/mnemo_cards_web_v2/lib/domain/state/tests_state_manager.dart @@ -1,8 +1,9 @@ import 'dart:developer'; -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:mnemo_cards_common/mnemo_cards_common.dart'; import 'package:flutter/services.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:game_tests/game_tests.dart'; +import 'package:mnemo_cards_common/mnemo_cards_common.dart'; import 'package:yx_state/yx_state.dart'; import '../models/game_question.dart'; @@ -51,14 +52,21 @@ class TestsStateManager extends StateManager { required TestManager testManager, required GameSessionManager gameSessionManager, required GameSoundService gameSoundService, + GameTestSettings settings = const GameTestSettings(), }) : _testManager = testManager, _gameSessionManager = gameSessionManager, _gameSoundService = gameSoundService, - super(const TestsState.loading()); + _settings = settings, + super(const TestsState.loading()) { + _gameSessionManager.configureDelays( + answerFeedbackDelay: () => _settings.feedbackDelay, + ); + } final TestManager _testManager; final GameSessionManager _gameSessionManager; final GameSoundService _gameSoundService; + final GameTestSettings _settings; String? _currentPackId; TestDto? _currentTest; @@ -158,26 +166,34 @@ class TestsStateManager extends StateManager { final isCorrect = _gameSessionManager.getQuestionResult(questionId)?.isCorrect ?? false; - // Play sound based on answer correctness - if (isCorrect) { - await _gameSoundService.playCorrectAnswer(); - await HapticFeedback.lightImpact(); - } else { - await _gameSoundService.playWrongAnswer(); - await HapticFeedback.mediumImpact(); + // Play sound/haptics based on settings + if (_settings.enableSounds) { + if (isCorrect) { + await _gameSoundService.playCorrectAnswer(); + } else { + await _gameSoundService.playWrongAnswer(); + } + } + + if (_settings.enableHaptics) { + if (isCorrect) { + await HapticFeedback.lightImpact(); + } else { + await HapticFeedback.mediumImpact(); + } } // Update state with answer feedback emit(currentState.copyWith( isAnswerSubmitted: true, isCorrect: isCorrect, - answerFeedbackDelay: _gameSessionManager.feedbackDelay, + answerFeedbackDelay: _settings.feedbackDelay, questionResults: _gameSessionManager.questionResults, )); // Auto-advance after delay if correct, or allow manual navigation if (isCorrect) { - await Future.delayed(const Duration(milliseconds: 1500)); + await Future.delayed(_settings.feedbackDelay); await _nextQuestion.call(emit); } }); diff --git a/mnemo_cards_web_v2/pubspec.lock b/mnemo_cards_web_v2/pubspec.lock index 5b61090..d452881 100644 --- a/mnemo_cards_web_v2/pubspec.lock +++ b/mnemo_cards_web_v2/pubspec.lock @@ -671,6 +671,13 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" + game_tests: + dependency: "direct main" + description: + path: "../games/packages/game_tests" + relative: true + source: path + version: "0.0.1" get_it: dependency: transitive description: diff --git a/mnemo_cards_web_v2/pubspec.yaml b/mnemo_cards_web_v2/pubspec.yaml index 99e151c..58635d7 100644 --- a/mnemo_cards_web_v2/pubspec.yaml +++ b/mnemo_cards_web_v2/pubspec.yaml @@ -78,6 +78,8 @@ dependencies: path: ../games/packages/payloads_shared bridge_core: path: ../games/packages/bridge_core + game_tests: + path: ../games/packages/game_tests collection: any copy_with_extension: any diff --git a/mnemo_cards_web_v2/test/domain/state/tests_state_manager_test.dart b/mnemo_cards_web_v2/test/domain/state/tests_state_manager_test.dart index 87bf583..e718a5a 100644 --- a/mnemo_cards_web_v2/test/domain/state/tests_state_manager_test.dart +++ b/mnemo_cards_web_v2/test/domain/state/tests_state_manager_test.dart @@ -1,8 +1,10 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; +import 'package:game_tests/game_tests.dart'; import 'package:mnemo_cards_common/mnemo_cards_common.dart'; import 'package:mnemo_cards_web_v2/domain/models/game_question.dart'; import 'package:mnemo_cards_web_v2/domain/services/game_session_manager.dart'; +import 'package:mnemo_cards_web_v2/domain/services/game_sound_service.dart'; import 'package:mnemo_cards_web_v2/domain/services/test_manager.dart'; import 'package:mnemo_cards_web_v2/domain/state/tests_state_manager.dart'; @@ -11,17 +13,26 @@ class MockTestManager extends Mock implements TestManager {} class MockGameSessionManager extends Mock implements GameSessionManager {} +class MockGameSoundService extends Mock implements GameSoundService {} + void main() { late MockTestManager mockTestManager; late MockGameSessionManager mockGameSessionManager; + late MockGameSoundService mockGameSoundService; late TestsStateManager testsStateManager; setUp(() { mockTestManager = MockTestManager(); mockGameSessionManager = MockGameSessionManager(); + mockGameSoundService = MockGameSoundService(); testsStateManager = TestsStateManager( testManager: mockTestManager, gameSessionManager: mockGameSessionManager, + gameSoundService: mockGameSoundService, + settings: const GameTestSettings( + enableHaptics: false, + enableSounds: false, + ), ); }); @@ -35,12 +46,12 @@ void main() { name: 'Test Game', questions: [ SimpleTestQuestionBody( - id: 'q1', + id: 1, text: 'What is 2+2?', buttons: [ - TestButtonDto(id: '3', text: '3'), - TestButtonDto(id: '4', text: '4'), - TestButtonDto(id: '5', text: '5'), + TestButtonDto.text('3', '3'), + TestButtonDto.text('4', '4'), + TestButtonDto.text('5', '5'), ], answer: '4', word: 'four', @@ -96,16 +107,16 @@ void main() { name: 'Multi Question Test', questions: [ SimpleTestQuestionBody( - id: 'q1', + id: 1, text: 'Q1?', - buttons: [TestButtonDto(id: 'A', text: 'A')], + buttons: [TestButtonDto.text('A', 'A')], answer: 'A', word: 'one', ), SimpleTestQuestionBody( - id: 'q2', + id: 2, text: 'Q2?', - buttons: [TestButtonDto(id: 'B', text: 'B')], + buttons: [TestButtonDto.text('B', 'B')], answer: 'B', word: 'two', ),