import React, { useState, useEffect } from 'react'; import { Button } from '@/components/ui/button'; import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Input } from '@/components/ui/input'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Progress } from '@/components/ui/progress'; import { cn } from '@/lib/utils'; import { motion, AnimatePresence } from 'framer-motion'; import { CheckCircle, Circle, ArrowRight, ArrowLeft, Home, BookOpen, ListChecks } from 'lucide-react'; // --- Utility Functions --- const shuffleArray = (array: T[]): T[] => { const newArray = [...array]; for (let i = newArray.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [newArray[i], newArray[j]] = [newArray[j], newArray[i]]; } return newArray; }; // --- Types --- type QuestionType = 'radio' | 'text' | 'select'; interface Question { id: string; type: QuestionType; text: string; options?: string[]; // For radio and select questions correctAnswer: string; explanation?: string; } interface Lection { id: string; title: string; questions: Question[]; } interface GameState { currentLection: number; currentQuestion: number; answers: { [questionId: string]: string }; scores: { [lectionId: string]: number }; completedLections: string[]; } // --- Constants --- const TOTAL_LECTIONS = 15; const QUESTIONS_PER_LECTION = 3; const POINTS_PER_QUESTION = 10; const PASSING_SCORE = 20; // Example passing score for a lection // --- Mock Data --- const generateMockQuestions = (lectionNumber: number): Question[] => { const lectionPrefix = `Lection ${lectionNumber}: `; const baseId = `L${lectionNumber}-Q`; switch (lectionNumber) { case 1: // Lexical Gaps return [ { id: `${baseId}1`, type: 'radio', text: `${lectionPrefix}Choose the best word: The company's success is ______ on the CEO.`, options: ['reliant', 'dependent', 'contingent', 'subject'], correctAnswer: 'dependent', explanation: "The correct answer is 'dependent'. 'Dependent' means relying on someone or something else for support." }, { id: `${baseId}2`, type: 'radio', text: `${lectionPrefix}Choose the best word: The new policy will have a significant ______ on the economy.`, options: ['affect', 'effect', 'impact', 'influence'], correctAnswer: 'effect', explanation: "The correct answer is 'effect'. 'Effect' is a noun that refers to a result or consequence." }, { id: `${baseId}3`, type: 'radio', text: `${lectionPrefix}Choose the best word: His argument was so ______ that no one could disagree.`, options: ['convincing', 'persuasive', 'compelling', 'forceful'], correctAnswer: 'compelling', explanation: "The correct answer is 'compelling'. 'Compelling' means evoking interest, attention, or admiration in a powerfully irresistible way." }, ]; case 2: // Sentence Transformations return [ { id: `${baseId}4`, type: 'text', text: `${lectionPrefix}Complete the sentence: 'Although it was raining, we went out.' Rewrite using 'Despite': Despite ______`, correctAnswer: 'the rain, we went out', explanation: "The correct answer is 'the rain, we went out'. 'Despite' is followed by a noun phrase." }, { id: `${baseId}5`, type: 'text', text: `${lectionPrefix}Complete the sentence: 'I haven't seen him for years.' Rewrite using 'Last': The last time ______`, correctAnswer: 'I saw him was years ago', explanation: "The correct answer is 'I saw him was years ago'. 'Last time' requires a past simple tense." }, { id: `${baseId}6`, type: 'text', text: `${lectionPrefix}Complete the sentence: 'They will only succeed if they work hard.' Rewrite using 'Unless': They ______`, correctAnswer: 'will not succeed unless they work hard', explanation: "The correct answer is 'will not succeed unless they work hard'. 'Unless' introduces a negative condition." } ]; case 3: // Word Formation return [ { id: `${baseId}7`, type: 'text', text: `${lectionPrefix}Complete the sentence with the correct form of 'happy': His ______ made everyone smile.`, correctAnswer: 'happiness', explanation: "The correct answer is 'happiness'. We need the noun form of 'happy'." }, { id: `${baseId}8`, type: 'text', text: `${lectionPrefix}Complete the sentence with the correct form of 'attend': Her ______ at the meeting was appreciated.`, correctAnswer: 'attendance', explanation: "The correct answer is 'attendance'. We need the noun form of 'attend'." }, { id: `${baseId}9`, type: 'text', text: `${lectionPrefix}Complete the sentence with the correct form of 'create': The artist's ______ was inspiring.`, correctAnswer: 'creation', explanation: "The correct answer is 'creation'. We need the noun form of create." } ]; case 4: // Error Correction return [ { id: `${baseId}10`, type: 'text', text: `${lectionPrefix}Correct the error: 'I am looking forward to see you.'`, correctAnswer: 'I am looking forward to seeing you', explanation: "'Looking forward to' is followed by the gerund form of the verb (seeing)." }, { id: `${baseId}11`, type: 'text', text: `${lectionPrefix}Correct the error: 'She has gone to home.'`, correctAnswer: 'She has gone home', explanation: "The preposition 'to' is not used before 'home' when it refers to one's own home." }, { id: `${baseId}12`, type: 'text', text: `${lectionPrefix}Correct the error: 'Despite of the rain, we went out.'`, correctAnswer: 'Despite the rain, we went out', explanation: "'Despite' is not followed by 'of'." } ]; case 5: // Text Completion return [ { id: `${baseId}13`, type: 'select', text: `${lectionPrefix}Choose the best word to complete the sentence: 'He managed to ______ the challenge with ease.'`, options: ['overcome', 'pass', 'defeat', 'win'], correctAnswer: 'overcome', explanation: "The correct answer is 'overcome'. 'Overcome' means to succeed in dealing with a problem or difficulty." }, { id: `${baseId}14`, type: 'select', text: `${lectionPrefix}Choose the best word to complete the sentence: 'The company is planning to ______ its operations.'`, options: ['expand', 'extend', 'increase', 'develop'], correctAnswer: 'expand', explanation: "The correct answer is 'expand'. 'Expand' means to become or make larger." }, { id: `${baseId}15`, type: 'select', text: `${lectionPrefix}Choose the best word to complete the sentence: 'The government is taking steps to ______ poverty.'`, options: ['eradicate', 'eliminate', 'remove', 'decrease'], correctAnswer: 'eradicate', explanation: "The correct answer is 'eradicate'. 'Eradicate' means to destroy completely; put an end to." } ]; case 6: // Phrasal Verbs return [ { id: `${baseId}16`, type: 'radio', text: `${lectionPrefix}Choose the best phrasal verb: 'I need to ______ my Spanish before I go to Spain.'`, options: ['brush up', 'look up', 'go over', 'take in'], correctAnswer: 'brush up', explanation: "'Brush up' means to improve your knowledge of something you have partly forgotten." }, { id: `${baseId}17`, type: 'radio', text: `${lectionPrefix}Choose the best phrasal verb: 'The meeting was ______ due to the speaker's illness.'`, options: ['put off', 'called off', 'taken off', 'gone off'], correctAnswer: 'called off', explanation: "'Called off' means to cancel an event." }, { id: `${baseId}18`, type: 'radio', text: `${lectionPrefix}Choose the best phrasal verb: 'It took me a long time to ______ the loss of my job.'`, options: ['get over', 'get through', 'get by', 'get on with'], correctAnswer: 'get over', explanation: "'Get over' means to recover from an illness, loss, or upset." }, ]; case 7: // Idioms return [ { id: `${baseId}19`, type: 'text', text: `${lectionPrefix}Complete the idiom: 'He was feeling under the ______.'`, correctAnswer: 'weather', explanation: "'Under the weather' means feeling slightly ill." }, { id: `${baseId}20`, type: 'text', text: `${lectionPrefix}Complete the idiom: 'She passed the exam with flying ______.'`, correctAnswer: 'colours', explanation: "'With flying colours' means with great success." }, { id: `${baseId}21`, type: 'text', text: `${lectionPrefix}Complete the idiom: 'Don't count your ______ before they hatch.'`, correctAnswer: 'chickens', explanation: "'Don't count your chickens before they hatch' means don't be too confident of success before it is certain." } ]; case 8: // Collocations return [ { id: `${baseId}22`, type: 'radio', text: `${lectionPrefix}Choose the best collocation: 'to ______ a mistake.'`, options: ['do', 'make', 'create', 'have'], correctAnswer: 'make', explanation: "The correct collocation is 'make a mistake'." }, { id: `${baseId}23`, type: 'radio', text: `${lectionPrefix}Choose the best collocation: 'to ______ an exam.'`, options: ['take', 'do', 'pass', 'give'], correctAnswer: 'take', explanation: "The correct collocation is 'take an exam'." }, { id: `${baseId}24`, type: 'radio', text: `${lectionPrefix}Choose the best collocation: 'to ______ money.'`, options: ['earn', 'win', 'gain', 'get'], correctAnswer: 'earn', explanation: "The correct collocation is 'earn money'." } ]; case 9: // Prepositions return [ { id: `${baseId}25`, type: 'select', text: `${lectionPrefix}Choose the correct preposition: 'She is good ______ languages.'`, options: ['at', 'in', 'on', 'for'], correctAnswer: 'at', explanation: "The correct preposition is 'at'. We say 'good at' something." }, { id: `${baseId}26`, type: 'select', text: `${lectionPrefix}Choose the correct preposition: 'He is interested ______ history.'`, options: ['in', 'at', 'on', 'for'], correctAnswer: 'in', explanation: "The correct preposition is 'in'. We say 'interested in' something." }, { id: `${baseId}27`, type: 'select', text: `${lectionPrefix}Choose the correct preposition: 'They are dependent ______ their parents.'`, options: ['on', 'at', 'in', 'for'], correctAnswer: 'on', explanation: "The correct preposition is 'on'. We say 'dependent on' someone." } ]; case 10: // Register return [ { id: `${baseId}28`, type: 'radio', text: `${lectionPrefix}Choose the most appropriate word in a formal context: 'I would like to ______ your attention to the following matter.'`, options: ['draw', 'bring', 'point', 'focus'], correctAnswer: 'draw', explanation: "'Draw' is the most formal option in this context." }, { id: `${baseId}29`, type: 'radio', text: `${lectionPrefix}Choose the most appropriate word in an informal context: 'Let's ______ up for a coffee sometime.'`, options: ['arrange', 'meet', 'gather', 'catch'], correctAnswer: 'catch', explanation: "'Catch up' is the most informal option in this context." }, { id: `${baseId}30`, type: 'radio', text: `${lectionPrefix}Choose the most appropriate word in a formal context: 'The company aims to ______ its market share.'`, options: ['increase', 'grow', 'expand', 'boost'], correctAnswer: 'expand', explanation: "'Expand' is the most formal option in this context." } ]; case 11: // Discourse Markers return [ { id: `${baseId}31`, type: 'select', text: `${lectionPrefix}Choose the best discourse marker: '______, I don't agree with your opinion.'`, options: ['However', 'Therefore', 'Moreover', 'Furthermore'], correctAnswer: 'However', explanation: "'However' is used to introduce a contrasting statement." }, { id: `${baseId}32`, type: 'select', text: `${lectionPrefix}Choose the best discourse marker: '______, we need to consider the costs.'`, options: ['Furthermore', 'For example', 'In addition', 'Firstly'], correctAnswer: 'Furthermore', explanation: "'Furthermore' is used to add more information to support an idea." }, { id: `${baseId}33`, type: 'select', text: `${lectionPrefix}Choose the best discourse marker: '______, let me explain the process.'`, options: ['Secondly', 'Firstly', 'Finally', 'In conclusion'], correctAnswer: 'Firstly', explanation: "'Firstly' is used to introduce the first point in a list." } ]; case 12: // Linking Words return [ { id: `${baseId}34`, type: 'text', text: `${lectionPrefix}Complete the sentence with a linking word: '______ it was raining, we decided to go for a walk.'`, correctAnswer: 'Although', explanation: "'Although' is used to introduce a contrast." }, { id: `${baseId}35`, type: 'text', text: `${lectionPrefix}Complete the sentence with a linking word: 'He studied hard; ______, he passed the exam.'`, correctAnswer: 'therefore', explanation: "'Therefore' is used to introduce a result or consequence." }, { id: `${baseId}36`, type: 'text', text: `${lectionPrefix}Complete the sentence with a linking word: 'She is intelligent; ______, she is also very kind.'`, correctAnswer: 'moreover', explanation: "'Moreover' is used to add more information." } ]; case 13: // Conditional Sentences return [ { id: `${baseId}37`, type: 'radio', text: `${lectionPrefix}Choose the correct conditional sentence: 'If I ______ more time, I would travel more.'`, options: ['have', 'had', 'would have', 'will have'], correctAnswer: 'had', explanation: "This is a second conditional, so we use 'had'." }, { id: `${baseId}38`, type: 'radio', text: `${lectionPrefix}Choose the correct conditional sentence: 'If it ______, we will stay at home.'`, options: ['rains', 'rained', 'will rain', 'would rain'], correctAnswer: 'rains', explanation: "This is a first conditional, so we use 'rains'." }, { id: `${baseId}39`, type: 'radio', text: `${lectionPrefix}Choose the correct conditional sentence: 'If you had studied harder, you ______ the exam.'`, options: ['pass', 'passed', 'would pass', 'would have passed'], correctAnswer: 'would have passed', explanation: "This is a third conditional, so we use 'would have passed'." } ]; case 14: // Reported Speech return [ { id: `${baseId}40`, type: 'text', text: `${lectionPrefix}Report the sentence: 'I am going to the cinema,' she said. She said that ______`, correctAnswer: 'she was going to the cinema', explanation: "In reported speech, 'am' changes to 'was'." }, { id: `${baseId}41`, type: 'text', text: `${lectionPrefix}Report the sentence: 'We will be there,' they said. They said that ______`, correctAnswer: 'they would be there', explanation: "In reported speech, 'will' changes to 'would'." }, { id: `${baseId}42`, type: 'text', text: `${lectionPrefix}Report the sentence: 'I have seen that film,' he said. He said that ______`, correctAnswer: 'he had seen that film', explanation: "In reported speech 'have seen' changes to 'had seen'." } ]; case 15: // Wishes and Regrets return [ { id: `${baseId}43`, type: 'text', text: `${lectionPrefix}Complete the sentence: 'I wish I ______ more time last week.'`, correctAnswer: 'had had', explanation: "We use 'had had' to express a wish about the past." }, { id: `${baseId}44`, type: 'text', text: `${lectionPrefix}Complete the sentence: 'If only I ______ how to fix this car!'`, correctAnswer: 'knew', explanation: "We use 'knew' to express a wish about the present." }, { id: `${baseId}45`, type: 'text', text: `${lectionPrefix}Complete the sentence: 'I wish you ______ so much noise last night.'`, correctAnswer: "hadn't made", explanation: "We use 'hadn't made' to express a regret about someone else's past action." } ]; default: return []; } }; const lections: Lection[] = Array.from({ length: TOTAL_LECTIONS }, (_, i) => { const lectionNumber = i + 1; return { id: `lection-${lectionNumber}`, title: `Lection ${lectionNumber}: ${ [ 'Lexical Gaps', 'Sentence Transformations', 'Word Formation', 'Error Correction', 'Text Completion', 'Phrasal Verbs', 'Idioms', 'Collocations', 'Prepositions', 'Register', 'Discourse Markers', 'Linking Words', 'Conditional Sentences', 'Reported Speech', 'Wishes and Regrets', ][i] }`, questions: generateMockQuestions(lectionNumber), }; }); // --- Helper Components --- const QuestionComponent: React.FC<{ question: Question; userAnswer: string; onChange: (answer: string) => void; isAnswered: boolean; showExplanation: boolean; }> = ({ question, userAnswer, onChange, isAnswered, showExplanation }) => { const getQuestionContent = () => { switch (question.type) { case 'radio': return ( {question.options?.map((option, index) => (
))}
); case 'text': return ( onChange(e.target.value)} placeholder="Enter your answer..." disabled={isAnswered} className={isAnswered && userAnswer !== question.correctAnswer ? "border-red-500" : ""} /> ); case 'select': return ( ); default: return

Question type not supported.

; } }; return (

{question.text}

{getQuestionContent()} {isAnswered && showExplanation && (

Explanation: {question.explanation}

)}
); }; const LectionCompleteModal: React.FC<{ isOpen: boolean; onClose: () => void; score: number; totalQuestions: number; lectionTitle: string; isLastLection: boolean; onNextLection: () => void; onRestart: () => void; }> = ({ isOpen, onClose, score, totalQuestions, lectionTitle, isLastLection, onNextLection, onRestart }) => { const percentage = (score / (totalQuestions * POINTS_PER_QUESTION)) * 100; const passed = percentage >= (PASSING_SCORE / POINTS_PER_QUESTION) * 100; // Adjusted for percentage return ( {isOpen && (

Lection Complete!

{lectionTitle}

{passed ? ( ) : ( )}

Your Score: {score} / {totalQuestions * POINTS_PER_QUESTION} ({percentage.toFixed(0)}%)

{passed ? 'Congratulations! You passed the lection.' : 'Try again to improve your score.'}

{isLastLection ? ( ) : ( )}
)}
); }; // --- Main Component --- const UseOfEnglishGame = () => { const [gameState, setGameState] = useState(() => { if (typeof window !== 'undefined') { const savedState = localStorage.getItem('useOfEnglishGameState'); try { return savedState ? JSON.parse(savedState) : { currentLection: 0, currentQuestion: 0, answers: {}, scores: {}, completedLections: [], }; } catch (e) { console.error("Failed to parse saved game state, starting new game", e); return { currentLection: 0, currentQuestion: 0, answers: {}, scores: {}, completedLections: [], }; } } return { currentLection: 0, currentQuestion: 0, answers: {}, scores: {}, completedLections: [], }; }); const [currentAnswer, setCurrentAnswer] = useState(''); const [isAnswered, setIsAnswered] = useState(false); const [showExplanation, setShowExplanation] = useState(false); const [isLectionCompleteModalOpen, setIsLectionCompleteModalOpen] = useState(false); const [userLevel, setUserLevel] = useState(1); // Start at level 1 const [badges, setBadges] = useState([]); const [gameStarted, setGameStarted] = useState(false); // Track if the game has started const [showWelcome, setShowWelcome] = useState(true); // --- Effects --- useEffect(() => { if (typeof window !== 'undefined') { try{ localStorage.setItem('useOfEnglishGameState', JSON.stringify(gameState)); } catch(e){ console.error("Failed to save game state", e); } } }, [gameState]); // --- Game Logic Functions --- const currentLection = lections[gameState.currentLection]; const currentQuestion = currentLection.questions[gameState.currentQuestion]; const progress = ((gameState.currentLection + 1) / TOTAL_LECTIONS) * 100; const handleAnswerChange = (answer: string) => { setCurrentAnswer(answer); }; const checkAnswer = () => { if (isAnswered) return; setIsAnswered(true); setShowExplanation(true); const isCorrect = currentAnswer.toLowerCase().trim() === currentQuestion.correctAnswer.toLowerCase().trim(); if (isCorrect) { setGameState((prev) => ({ ...prev, answers: { ...prev.answers, [currentQuestion.id]: currentAnswer, }, scores: { ...prev.scores, [currentLection.id]: (prev.scores[currentLection.id] || 0) + POINTS_PER_QUESTION, }, })); } else { setGameState((prev) => ({ ...prev, answers: { ...prev.answers, [currentQuestion.id]: currentAnswer, }, })); } }; const handleNextQuestion = () => { if (!isAnswered) return; if (gameState.currentQuestion < currentLection.questions.length - 1) { setGameState((prev) => ({ ...prev, currentQuestion: prev.currentQuestion + 1 })); setCurrentAnswer(''); setIsAnswered(false); setShowExplanation(false); } else { // Lection Complete const lectionScore = gameState.scores[currentLection.id] || 0; setGameState(prev => { const updatedState = { ...prev, completedLections: [...prev.completedLections, currentLection.id], scores: { ...prev.scores, [currentLection.id]: lectionScore, // Ensure score is saved }, currentQuestion: 0, // Reset question for next lection }; return updatedState; }); setIsLectionCompleteModalOpen(true); // Level and Badge Logic const totalScore = Object.values(gameState.scores).reduce((a, b) => a + b, 0) + lectionScore; updateLevelAndBadges(totalScore); } }; const handleNextLection = () => { if (gameState.currentLection < lections.length - 1) { setGameState((prev) => ({ ...prev, currentLection: prev.currentLection + 1, currentQuestion: 0, // Reset to the first question of the new lection })); setIsLectionCompleteModalOpen(false); setCurrentAnswer(''); // Reset current answer setIsAnswered(false); // Allow answering the new question setShowExplanation(false); } }; const handleRestart = () => { setGameState({ currentLection: 0, currentQuestion: 0, answers: {}, scores: {}, completedLections: [], }); setIsLectionCompleteModalOpen(false); setCurrentAnswer(''); setIsAnswered(false); setShowExplanation(false); setUserLevel(1); setBadges([]); setGameStarted(false); // Reset game started state setShowWelcome(true); }; const updateLevelAndBadges = (totalScore: number) => { // Example Leveling System let newLevel = 1; if (totalScore >= 50) newLevel = 2; if (totalScore >= 150) newLevel = 3; if (totalScore >= 300) newLevel = 4; if (totalScore >= 500) newLevel = 5; setUserLevel(newLevel); // Example Badge System const newBadges: string[] = [...badges]; if (gameState.completedLections.length >= 3 && !badges.includes('Explorer')) newBadges.push('Explorer'); if (gameState.completedLections.length >= 7 && !badges.includes('Scholar')) newBadges.push('Scholar'); if (gameState.completedLections.length === TOTAL_LECTIONS && !badges.includes('Master')) newBadges.push('Master'); setBadges(newBadges); }; const startQuiz = () => { setGameStarted(true); setShowWelcome(false); }; const currentScore = gameState.scores[currentLection.id] || 0; const isLastLection = gameState.currentLection === lections.length - 1; return (
{showWelcome && (

Welcome to the Use of English B2 Game!

Test and improve your English skills with this interactive quiz. Complete all 15 lections to become a master!

)} {gameStarted && ( <> {currentLection.title} Question {gameState.currentQuestion + 1} of {currentLection.questions.length}

Your Progress:

Completed {gameState.completedLections.length} of {TOTAL_LECTIONS} lections

Current Score: {currentScore} / {(gameState.currentQuestion + 1) * POINTS_PER_QUESTION}

{/* Display User Level and Badges */}

Your Profile

Level: {userLevel}

Badges:

{badges.length > 0 ? ( badges.map((badge) => ( {badge} )) ) : ( No badges yet. )}
setIsLectionCompleteModalOpen(false)} score={gameState.scores[currentLection.id] || 0} totalQuestions={currentLection.questions.length} lectionTitle={currentLection.title} isLastLection={isLastLection} onNextLection={handleNextLection} onRestart={handleRestart} /> )}
); }; export default UseOfEnglishGame;