// packages/feature_game_finddiff/lib/controllers/finddiff_controller.dart import 'dart:async'; import 'dart:math'; import 'package:flutter/material.dart'; import '../models/finddiff_models.dart'; class FindDiffController with ChangeNotifier { late FindDiffDifficulty difficulty; late String userId; late String? userName; List _items = []; List get items => _items; // 게임 상태 int _currentRound = 0; int get currentRound => _currentRound; int _score = 0; int get score => _score; int _incorrectCount = 0; int get incorrectCount => _incorrectCount; bool _isGameCompleted = false; bool get isGameCompleted => _isGameCompleted; // 타이머 Timer? _timer; int _remainingTime = 0; int get remainingTime => _remainingTime; // [🔥 신규] 게임 시작 여부 (가이드 확인 후 true) bool _isGameStarted = false; bool get isGameStarted => _isGameStarted; // [🔥 신규] 피드백 상태 bool _showFeedback = false; bool get showFeedback => _showFeedback; bool _isLastAnswerCorrect = false; bool get isLastAnswerCorrect => _isLastAnswerCorrect; final Random _random = Random(); void setUserInfo(String userId, String? userName) { this.userId = userId; this.userName = userName; } void startNewGame(FindDiffDifficulty level) { difficulty = level; _score = 0; _incorrectCount = 0; _currentRound = 1; _isGameCompleted = false; _isGameStarted = false; // 대기 상태 _showFeedback = false; _generateLevel(); // [🔥 수정] 여기서 타이머를 시작하지 않음 notifyListeners(); } void restartGame() { startNewGame(difficulty); } // [🔥 신규] UI에서 호출할 타이머 시작 함수 void startGameTimer() { if (_isGameStarted) return; _isGameStarted = true; _startTimer(); notifyListeners(); } void _generateLevel() { _items.clear(); final int totalItems = difficulty.totalItems; final int targetIndex = _random.nextInt(totalItems); // 1. 기본 속성 결정 IconData baseIcon = Icons.circle; Color baseColor = Colors.blue; double baseAngle = 0.0; // 난이도별 속성 설정 if (difficulty.diffType == FindDiffType.icon) { final pair = FindDiffDifficulties.iconPairs[_random.nextInt(FindDiffDifficulties.iconPairs.length)]; baseIcon = pair[0]; } else { baseIcon = FindDiffDifficulties.basicIcons[_random.nextInt(FindDiffDifficulties.basicIcons.length)]; baseColor = Color.fromARGB(255, _random.nextInt(200), _random.nextInt(200), _random.nextInt(200)); } // 2. 아이템 생성 for (int i = 0; i < totalItems; i++) { bool isTarget = (i == targetIndex); IconData icon = baseIcon; Color color = baseColor; double angle = baseAngle; if (isTarget) { // 정답 아이템 변형 switch (difficulty.diffType) { case FindDiffType.color: int offset = (difficulty.levelIndex >= 4) ? 30 : 60; color = Color.fromARGB( 255, (baseColor.red + offset) % 255, (baseColor.green + offset) % 255, (baseColor.blue + offset) % 255, ); break; case FindDiffType.icon: final pair = FindDiffDifficulties.iconPairs.firstWhere((p) => p.contains(baseIcon)); icon = (baseIcon == pair[0]) ? pair[1] : pair[0]; break; case FindDiffType.rotate: angle = 0.5; // 약 30도 회전 break; } } _items.add(FindDiffItem( id: i, icon: icon, color: color, angle: angle, isTarget: isTarget, )); } _remainingTime = difficulty.timeLimitSeconds; } void _startTimer() { _timer?.cancel(); _timer = Timer.periodic(const Duration(seconds: 1), (timer) { _remainingTime--; if (_remainingTime <= 0) { // 시간 초과: 오답 처리 및 다음 문제 _handleAnswer(false); } notifyListeners(); }); } void onItemTapped(FindDiffItem item) { if (!_isGameStarted || _isGameCompleted || _showFeedback) return; _handleAnswer(item.isTarget); } void _handleAnswer(bool isCorrect) { _timer?.cancel(); // 잠시 멈춤 _showFeedback = true; _isLastAnswerCorrect = isCorrect; if (isCorrect) { _score++; } else { _incorrectCount++; } notifyListeners(); // 피드백 후 다음 라운드 Future.delayed(const Duration(milliseconds: 500), () { if (_score >= 10) { // [목표] 10문제 맞추면 클리어 _isGameCompleted = true; } else { _currentRound++; _showFeedback = false; _generateLevel(); _startTimer(); // 타이머 재개 } notifyListeners(); }); } @override void dispose() { _timer?.cancel(); super.dispose(); } }