import React, { useState, useEffect, useCallback } from 'react'; import { View, Text, StyleSheet, TouchableOpacity, Alert, SafeAreaView, StatusBar, Dimensions, Animated, } from 'react-native'; import { ReactionTimeGame as GameClass } from './index'; import { GameDifficulty } from '../../core/types'; const { width: screenWidth, height: screenHeight } = Dimensions.get('window'); interface ReactionTimeGameProps { difficulty?: 'easy' | 'medium' | 'hard' | 'expert'; totalRounds?: number; onGameComplete?: (result: any) => void; onGameStart?: () => void; onRoundComplete?: (roundData: any) => void; showMenu?: boolean; autoStart?: boolean; title?: string; subtitle?: string; showStats?: boolean; enablePractice?: boolean; theme?: { primaryColor?: string; secondaryColor?: string; backgroundColor?: string; textColor?: string; successColor?: string; warningColor?: string; }; } export const ReactionTimeGameComponent: React.FC = ({ difficulty = 'easy', totalRounds = 5, onGameComplete, onGameStart, onRoundComplete, showMenu = true, autoStart = false, title = '⚡ משחק תגובה', subtitle = 'בדוק את מהירות התגובה שלך!', showStats = true, enablePractice = true, theme = { primaryColor: '#3498db', secondaryColor: '#2ecc71', backgroundColor: '#f8f9fa', textColor: '#2c3e50', successColor: '#27ae60', warningColor: '#f39c12' } }) => { const [currentScreen, setCurrentScreen] = useState(showMenu ? 'menu' : 'game'); const [gameInstance, setGameInstance] = useState(null); const [gameState, setGameState] = useState(null); const [isLoading, setIsLoading] = useState(false); const [gameStats, setGameStats] = useState({ currentRound: 0, totalRounds, averageReactionTime: 0, bestReactionTime: 0, successfulRounds: 0, isWaiting: false, showStimulus: false, }); const [internalStats, setInternalStats] = useState({ totalGames: 0, bestAverageTime: 0, bestScore: 0, totalReactions: 0, }); const pulseAnimation = new Animated.Value(1); useEffect(() => { if (autoStart && !showMenu) { startGame(); } }, [autoStart, showMenu]); useEffect(() => { if (gameState?.isWaiting && !gameState?.showStimulus) { // Pulse animation while waiting Animated.loop( Animated.sequence([ Animated.timing(pulseAnimation, { toValue: 1.1, duration: 1000, useNativeDriver: true, }), Animated.timing(pulseAnimation, { toValue: 1, duration: 1000, useNativeDriver: true, }), ]) ).start(); } else { pulseAnimation.setValue(1); } }, [gameState?.isWaiting, gameState?.showStimulus]); const startGame = async () => { setIsLoading(true); try { if (!GameClass) { console.error('❌ GameClass is undefined!'); Alert.alert('שגיאה', 'מחלקת המשחק לא נטענה מהספרייה'); setIsLoading(false); return; } const game = new GameClass(); let gameDifficulty: GameDifficulty; switch (difficulty) { case 'easy': gameDifficulty = GameDifficulty.EASY; break; case 'medium': gameDifficulty = GameDifficulty.MEDIUM; break; case 'hard': gameDifficulty = GameDifficulty.HARD; break; case 'expert': gameDifficulty = GameDifficulty.EXPERT; break; default: gameDifficulty = GameDifficulty.EASY; } await game.initialize({ gameId: 'reaction-time', difficulty: gameDifficulty, totalRounds, customization: { theme: { name: 'default', colors: { primary: theme.primaryColor, secondary: theme.secondaryColor, background: theme.backgroundColor, text: theme.textColor, success: theme.successColor, warning: theme.warningColor, }, }, }, rules: {} } as any); (game as any).on('roundComplete', (roundData: any) => { console.log('🔄 Round complete:', roundData); updateGameStats(game); onRoundComplete?.(roundData); }); (game as any).on('gameComplete', (result: any) => { console.log('🏁 Reaction game complete!', result); const newTotalGames = internalStats.totalGames + 1; const newTotalReactions = internalStats.totalReactions + result.customData?.successfulRounds || 0; setInternalStats(prev => ({ totalGames: newTotalGames, bestAverageTime: prev.bestAverageTime === 0 ? result.customData?.averageReactionTime : Math.min(prev.bestAverageTime, result.customData?.averageReactionTime || 0), bestScore: Math.max(prev.bestScore, result.score || 0), totalReactions: newTotalReactions, })); onGameComplete?.(result); if (showMenu) { Alert.alert( '🎉 כל הכבוד!', `השלמת את משחק התגובה!\n` + `זמן תגובה ממוצע: ${result.customData?.averageReactionTime?.toFixed(0) || 0}ms\n` + `זמן תגובה הטוב ביותר: ${result.customData?.bestReactionTime || 0}ms\n` + `תגובות מוצלחות: ${result.customData?.successfulRounds || 0}/${totalRounds}\n` + `ניקוד: ${result.score}`, [ { text: 'משחק חדש', onPress: () => startGame() }, { text: 'חזור לתפריט', onPress: () => setCurrentScreen('menu') }, ], ); } }); (game as any).on('gameStarted', () => { console.log('🚀 Reaction game started!'); onGameStart?.(); }); setGameInstance(game); setGameState(game.getReactionState()); await game.start(); setIsLoading(false); setCurrentScreen('game'); } catch (error) { console.error('❌ Failed to start reaction game:', error); Alert.alert('שגיאה', 'נכשל בהתחלת משחק התגובה'); setIsLoading(false); } }; const updateGameStats = (game: any) => { const state = game.getReactionState(); setGameStats({ currentRound: state.currentRound, totalRounds: state.totalRounds, averageReactionTime: state.averageReactionTime, bestReactionTime: state.bestReactionTime, successfulRounds: state.successfulRounds, isWaiting: state.isWaiting, showStimulus: state.showStimulus, }); setGameState(state); }; const handleReaction = () => { if (!gameInstance || !gameState) return; gameInstance.processPlayerAction({ type: 'REACTION_TAP', payload: {} }); updateGameStats(gameInstance); }; const startNewRound = () => { if (!gameInstance) return; gameInstance.processPlayerAction({ type: 'START_ROUND', payload: {} }); updateGameStats(gameInstance); }; const formatTime = (ms: number): string => { return `${ms.toFixed(0)}ms`; }; const renderMenuScreen = () => ( {title} {subtitle} {isLoading ? 'טוען...' : 'התחל משחק'} רמת קושי: {difficulty} מספר סיבובים: {totalRounds} {internalStats.totalGames > 0 && ( <> משחקים קודמים: {internalStats.totalGames} זמן ממוצע הטוב ביותר: {formatTime(internalStats.bestAverageTime)} )} ); const renderGameScreen = () => ( משחק תגובה {showStats && ( סיבוב: {gameStats.currentRound + 1}/{gameStats.totalRounds} מוצלחים: {gameStats.successfulRounds} {gameStats.averageReactionTime > 0 && ( ממוצע: {formatTime(gameStats.averageReactionTime)} )} )} {gameStats.isWaiting && !gameStats.showStimulus && ( המתן... הקש כאשר התמונה מופיעה )} {gameStats.showStimulus && ( הקש עכשיו! )} {!gameStats.isWaiting && !gameStats.showStimulus && gameStats.currentRound < gameStats.totalRounds && ( התחל סיבוב )} {showMenu && ( setCurrentScreen('menu')} > חזור לתפריט )} ); return currentScreen === 'menu' ? renderMenuScreen() : renderGameScreen(); }; const styles = StyleSheet.create({ container: { flex: 1, }, menuContent: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20, }, title: { fontSize: 28, fontWeight: 'bold', marginBottom: 10, textAlign: 'center', }, subtitle: { fontSize: 16, marginBottom: 30, textAlign: 'center', opacity: 0.8, }, menuButtons: { width: '100%', marginBottom: 30, }, button: { padding: 15, borderRadius: 10, alignItems: 'center', marginVertical: 5, }, buttonText: { color: 'white', fontSize: 16, fontWeight: 'bold', }, gameInfo: { width: '100%', }, infoText: { fontSize: 14, marginVertical: 2, textAlign: 'center', }, gameContent: { flex: 1, padding: 20, }, header: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20, }, gameTitle: { fontSize: 24, fontWeight: 'bold', }, stats: { alignItems: 'flex-end', }, statText: { fontSize: 14, marginVertical: 2, }, gameArea: { flex: 1, justifyContent: 'center', alignItems: 'center', }, waitingArea: { width: 200, height: 200, borderRadius: 100, justifyContent: 'center', alignItems: 'center', }, waitingText: { color: 'white', fontSize: 24, fontWeight: 'bold', }, waitingSubtext: { color: 'white', fontSize: 14, marginTop: 10, textAlign: 'center', }, stimulusArea: { width: 200, height: 200, borderRadius: 100, justifyContent: 'center', alignItems: 'center', }, stimulusText: { color: 'white', fontSize: 48, }, stimulusSubtext: { color: 'white', fontSize: 16, marginTop: 10, fontWeight: 'bold', }, startRoundButton: { padding: 20, borderRadius: 15, alignItems: 'center', }, controls: { flexDirection: 'row', justifyContent: 'center', marginTop: 20, }, controlButton: { padding: 10, borderRadius: 8, minWidth: 120, alignItems: 'center', }, });