// === MODULE QUIZ GAME === class QuizGame { constructor(options) { this.container = options.container; this.content = options.content; this.onScoreUpdate = options.onScoreUpdate || (() => {}); this.onGameEnd = options.onGameEnd || (() => {}); // Game state this.vocabulary = []; this.currentQuestion = 0; this.totalQuestions = 10; this.score = 0; this.correctAnswers = 0; this.currentQuestionData = null; this.hasAnswered = false; // Extract vocabulary this.vocabulary = this.extractVocabulary(this.content); this.init(); } init() { // Check if we have enough vocabulary if (!this.vocabulary || this.vocabulary.length < 4) { console.error('Not enough vocabulary for Quiz Game'); this.showInitError(); return; } // Adjust total questions based on available vocabulary this.totalQuestions = Math.min(this.totalQuestions, this.vocabulary.length); this.createGameInterface(); this.generateQuestion(); } showInitError() { this.container.innerHTML = `

❌ Error loading

This content doesn't have enough vocabulary for Quiz Game.

The game needs at least 4 vocabulary items.

`; } extractVocabulary(content) { let vocabulary = []; console.log('📝 Extracting vocabulary from:', content?.name || 'content'); // Use raw module content if available if (content.rawContent) { console.log('📦 Using raw module content'); return this.extractVocabularyFromRaw(content.rawContent); } // Modern format with contentItems if (content.contentItems && Array.isArray(content.contentItems)) { console.log('🆕 ContentItems format detected'); const vocabItems = content.contentItems.filter(item => item.type === 'vocabulary'); if (vocabItems.length > 0) { vocabulary = vocabItems[0].items || []; } } // Legacy format with vocabulary array else if (content.vocabulary && Array.isArray(content.vocabulary)) { console.log('📚 Vocabulary array format detected'); vocabulary = content.vocabulary; } return this.finalizeVocabulary(vocabulary); } extractVocabularyFromRaw(rawContent) { console.log('🔧 Extracting from raw content:', rawContent.name || 'Module'); let vocabulary = []; // Check vocabulary object format (key-value pairs) if (rawContent.vocabulary && typeof rawContent.vocabulary === 'object' && !Array.isArray(rawContent.vocabulary)) { vocabulary = Object.entries(rawContent.vocabulary).map(([english, translation]) => ({ english: english, french: translation })); console.log(`📝 ${vocabulary.length} vocabulary pairs extracted from object`); } // Check vocabulary array format else if (rawContent.vocabulary && Array.isArray(rawContent.vocabulary)) { vocabulary = rawContent.vocabulary; console.log(`📚 ${vocabulary.length} vocabulary items extracted from array`); } return this.finalizeVocabulary(vocabulary); } finalizeVocabulary(vocabulary) { // Filter and validate vocabulary vocabulary = vocabulary.filter(item => item && item.english && (item.french || item.translation || item.chinese) ).map(item => ({ english: item.english, french: item.french || item.translation || item.chinese })); if (vocabulary.length === 0) { console.error('❌ No valid vocabulary found'); // Demo vocabulary as fallback vocabulary = [ { english: "cat", french: "chat" }, { english: "dog", french: "chien" }, { english: "house", french: "maison" }, { english: "car", french: "voiture" }, { english: "book", french: "livre" }, { english: "water", french: "eau" }, { english: "food", french: "nourriture" }, { english: "friend", french: "ami" } ]; console.warn('🚨 Using demo vocabulary'); } // Shuffle vocabulary for random questions vocabulary = vocabulary.sort(() => Math.random() - 0.5); console.log(`✅ Quiz Game: ${vocabulary.length} vocabulary items finalized`); return vocabulary; } createGameInterface() { this.container.innerHTML = `
1 / ${this.totalQuestions} Score: 0
Loading question...
Choose the correct translation!
`; this.setupEventListeners(); } setupEventListeners() { document.getElementById('next-btn').addEventListener('click', () => this.nextQuestion()); document.getElementById('restart-btn').addEventListener('click', () => this.restart()); } generateQuestion() { if (this.currentQuestion >= this.totalQuestions) { this.gameComplete(); return; } this.hasAnswered = false; // Get current vocabulary item const correctAnswer = this.vocabulary[this.currentQuestion]; // Generate 3 wrong answers from other vocabulary items const wrongAnswers = this.vocabulary .filter(item => item !== correctAnswer) .sort(() => Math.random() - 0.5) .slice(0, 3) .map(item => item.french); // Combine and shuffle all options const allOptions = [correctAnswer.french, ...wrongAnswers].sort(() => Math.random() - 0.5); this.currentQuestionData = { question: correctAnswer.english, correctAnswer: correctAnswer.french, options: allOptions }; this.renderQuestion(); this.updateProgress(); } renderQuestion() { const { question, options } = this.currentQuestionData; // Update question text document.getElementById('question-text').innerHTML = ` What is the translation of "${question}"? `; // Clear and generate options const optionsArea = document.getElementById('options-area'); optionsArea.innerHTML = ''; options.forEach((option, index) => { const optionButton = document.createElement('button'); optionButton.className = 'quiz-option'; optionButton.textContent = option; optionButton.addEventListener('click', () => this.selectAnswer(option, optionButton)); optionsArea.appendChild(optionButton); }); // Hide next button document.getElementById('next-btn').style.display = 'none'; } selectAnswer(selectedAnswer, buttonElement) { if (this.hasAnswered) return; this.hasAnswered = true; const isCorrect = selectedAnswer === this.currentQuestionData.correctAnswer; // Disable all option buttons and show results const allOptions = document.querySelectorAll('.quiz-option'); allOptions.forEach(btn => { btn.disabled = true; if (btn.textContent === this.currentQuestionData.correctAnswer) { btn.classList.add('correct'); } else if (btn === buttonElement && !isCorrect) { btn.classList.add('wrong'); } else if (btn !== buttonElement && btn.textContent !== this.currentQuestionData.correctAnswer) { btn.classList.add('disabled'); } }); // Update score and feedback if (isCorrect) { this.correctAnswers++; this.score += 10; this.showFeedback('✅ Correct! Well done!', 'success'); } else { this.score = Math.max(0, this.score - 5); this.showFeedback(`❌ Wrong! Correct answer: "${this.currentQuestionData.correctAnswer}"`, 'error'); } this.updateScore(); // Show next button or finish if (this.currentQuestion < this.totalQuestions - 1) { document.getElementById('next-btn').style.display = 'block'; } else { setTimeout(() => this.gameComplete(), 2000); } } nextQuestion() { this.currentQuestion++; this.generateQuestion(); } updateProgress() { const progressFill = document.getElementById('progress-fill'); const progressPercent = ((this.currentQuestion + 1) / this.totalQuestions) * 100; progressFill.style.width = `${progressPercent}%`; document.getElementById('question-counter').textContent = `${this.currentQuestion + 1} / ${this.totalQuestions}`; } updateScore() { document.getElementById('score-display').textContent = `Score: ${this.score}`; this.onScoreUpdate(this.score); } gameComplete() { const accuracy = Math.round((this.correctAnswers / this.totalQuestions) * 100); // Bonus for high accuracy if (accuracy >= 90) { this.score += 50; // Excellence bonus } else if (accuracy >= 70) { this.score += 20; // Good performance bonus } this.updateScore(); this.showFeedback( `🎉 Quiz completed! ${this.correctAnswers}/${this.totalQuestions} correct (${accuracy}%)`, 'success' ); setTimeout(() => { this.onGameEnd(this.score); }, 3000); } showFeedback(message, type = 'info') { const feedbackArea = document.getElementById('feedback-area'); feedbackArea.innerHTML = `
${message}
`; } start() { console.log('❓ Quiz Game: Starting'); this.showFeedback('Choose the correct translation for each word!', 'info'); } restart() { console.log('🔄 Quiz Game: Restarting'); this.reset(); this.start(); } reset() { this.currentQuestion = 0; this.score = 0; this.correctAnswers = 0; this.hasAnswered = false; this.currentQuestionData = null; // Re-shuffle vocabulary this.vocabulary = this.vocabulary.sort(() => Math.random() - 0.5); this.generateQuestion(); this.updateScore(); } destroy() { this.container.innerHTML = ''; } } // Module registration window.GameModules = window.GameModules || {}; window.GameModules.QuizGame = QuizGame;