// === CHINESE STUDY MODE ===
class ChineseStudyGame {
constructor(options) {
this.container = options.container;
this.content = options.content;
this.onScoreUpdate = options.onScoreUpdate || (() => {});
this.onGameEnd = options.onGameEnd || (() => {});
// Game state
this.vocabulary = [];
this.currentMode = null;
this.currentIndex = 0;
this.score = 0;
this.correctAnswers = 0;
this.isRunning = false;
this.studyState = 'menu'; // 'menu', 'playing', 'review'
// Extract vocabulary
this.vocabulary = this.extractVocabulary(this.content);
this.init();
}
init() {
// Check if we have enough vocabulary
if (!this.vocabulary || this.vocabulary.length === 0) {
logSh('No Chinese vocabulary found for Chinese Study Game', 'ERROR');
this.showInitError();
return;
}
this.createGameInterface();
}
showInitError() {
this.container.innerHTML = `
❌ Error loading
This content doesn't have Chinese vocabulary for the Chinese Study Game.
The game needs vocabulary with Chinese characters, translations, and optional pinyin.
← Back
`;
this.addStyles();
}
extractVocabulary(content) {
let vocabulary = [];
logSh('🔍 Extracting Chinese vocabulary from:', content?.name || 'content', 'INFO');
// Priority 1: Use raw module content (simple format)
if (content.rawContent) {
logSh('📦 Using raw module content', 'INFO');
return this.extractVocabularyFromRaw(content.rawContent);
}
// Priority 2: Ultra-modular format (vocabulary object) - ONLY format supported
if (content.vocabulary && typeof content.vocabulary === 'object' && !Array.isArray(content.vocabulary)) {
logSh('✨ Ultra-modular format detected (vocabulary object)', 'INFO');
vocabulary = Object.entries(content.vocabulary).map(([word, data]) => {
// Support ultra-modular format ONLY
if (typeof data === 'object' && data.user_language) {
return {
chinese: word, // Clé = caractère chinois
translation: data.user_language.split(';')[0], // First translation
fullTranslation: data.user_language, // Complete translation
pronunciation: data.pronunciation || '', // Pinyin
type: data.type || 'general',
hskLevel: data.hskLevel || null,
examples: data.examples || [],
strokeOrder: data.strokeOrder || []
};
}
// Legacy fallback - simple string (temporary, will be removed)
else if (typeof data === 'string') {
return {
chinese: word,
translation: data.split(';')[0],
fullTranslation: data,
pronunciation: '',
type: 'general',
hskLevel: null
};
}
return null;
}).filter(Boolean);
}
// No other formats supported - ultra-modular only
return this.finalizeVocabulary(vocabulary);
}
extractVocabularyFromRaw(rawContent) {
logSh('🔧 Extracting from raw content:', rawContent.name || 'Module', 'INFO');
let vocabulary = [];
// Extract from vocabulary object in raw content
if (rawContent.vocabulary && typeof rawContent.vocabulary === 'object') {
vocabulary = Object.entries(rawContent.vocabulary).map(([word, data]) => {
if (typeof data === 'object' && data.user_language) {
return {
chinese: word,
translation: data.user_language.split(';')[0],
fullTranslation: data.user_language,
pronunciation: data.pronunciation || '',
type: data.type || 'general',
hskLevel: data.hskLevel || null,
examples: data.examples || [],
strokeOrder: data.strokeOrder || []
};
} else if (typeof data === 'string') {
return {
chinese: word,
translation: data.split(';')[0],
fullTranslation: data,
pronunciation: '',
type: 'general',
hskLevel: null
};
}
return null;
}).filter(Boolean);
}
return vocabulary;
}
finalizeVocabulary(vocabulary) {
if (vocabulary.length === 0) {
logSh('⚠️ No valid vocabulary found', 'WARNING');
return [];
}
// Shuffle vocabulary
vocabulary = vocabulary.sort(() => Math.random() - 0.5);
logSh(`✅ Vocabulary extraction complete: ${vocabulary.length} items`, 'INFO');
return vocabulary;
}
createGameInterface() {
if (this.studyState === 'menu') {
this.createModeSelection();
} else if (this.studyState === 'playing') {
this.createStudyMode();
}
this.addStyles();
}
createModeSelection() {
const hasPinyin = this.vocabulary.some(item => item.pronunciation);
const hasHSK = this.vocabulary.some(item => item.hskLevel);
this.container.innerHTML = `
📚
Flashcards
Study characters with flip cards
Start Learning
🧠
Character Recognition
Match characters to their meanings
${!hasPinyin ? '
Requires pinyin data
' : ''}
Start Learning
🗣️
Pinyin Practice
Learn pronunciation with pinyin
${!hasPinyin ? '
Requires pinyin data
' : ''}
Start Learning
📊
HSK Review
Study by HSK difficulty levels
${!hasHSK ? '
Requires HSK level data
' : ''}
Start Learning
📖 Vocabulary Preview
${this.vocabulary.slice(0, 6).map(item => `
${item.chinese}
${item.translation}
${item.pronunciation ? `${item.pronunciation} ` : ''}
${item.hskLevel ? `${item.hskLevel} ` : ''}
`).join('')}
${this.vocabulary.length > 6 ? `
... and ${this.vocabulary.length - 6} more
` : ''}
← Back to Games
`;
this.setupModeListeners();
}
createStudyMode() {
const currentItem = this.vocabulary[this.currentIndex];
const progress = Math.round(((this.currentIndex + 1) / this.vocabulary.length) * 100);
let modeContent = '';
switch (this.currentMode) {
case 'flashcards':
modeContent = this.createFlashcardMode(currentItem);
break;
case 'recognition':
modeContent = this.createRecognitionMode(currentItem);
break;
case 'pinyin':
modeContent = this.createPinyinMode(currentItem);
break;
case 'hsk':
modeContent = this.createHSKMode(currentItem);
break;
}
this.container.innerHTML = `
${modeContent}
← Previous
Next →
`;
this.setupStudyListeners();
}
setupModeListeners() {
const modeCards = this.container.querySelectorAll('.mode-card:not([data-disabled])');
modeCards.forEach(card => {
card.addEventListener('click', (e) => {
const mode = card.dataset.mode;
this.startMode(mode);
});
});
}
setupStudyListeners() {
// Bind this context to methods for onclick handlers
window.chineseStudyInstance = this;
// Override global onclick handlers
this.container.querySelector('.back-to-menu-btn').onclick = () => this.backToMenu();
this.container.querySelector('.prev-btn').onclick = () => this.previousItem();
this.container.querySelector('.next-btn').onclick = () => this.nextItem();
// Setup mode-specific listeners
this.setupModeSpecificListeners();
}
setupModeSpecificListeners() {
if (this.currentMode === 'flashcards') {
const flashcard = this.container.querySelector('.flashcard');
if (flashcard) {
flashcard.addEventListener('click', () => this.flipCard());
}
} else if (this.currentMode === 'recognition') {
const options = this.container.querySelectorAll('.option-btn');
options.forEach(option => {
option.addEventListener('click', (e) => this.selectOption(e.target.dataset.translation));
});
} else if (this.currentMode === 'pinyin') {
const pinyinInput = this.container.querySelector('.pinyin-input');
if (pinyinInput) {
pinyinInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') this.checkPinyinAnswer();
});
}
const checkBtn = this.container.querySelector('.check-pinyin-btn');
if (checkBtn) {
checkBtn.onclick = () => this.checkPinyinAnswer();
}
}
}
startMode(mode) {
this.currentMode = mode;
this.studyState = 'playing';
this.currentIndex = 0;
this.correctAnswers = 0;
this.createGameInterface();
}
backToMenu() {
this.studyState = 'menu';
this.currentMode = null;
this.createGameInterface();
}
getModeTitle() {
const titles = {
flashcards: '📚 Flashcards',
recognition: '🧠 Character Recognition',
pinyin: '🗣️ Pinyin Practice',
hsk: '📊 HSK Review'
};
return titles[this.currentMode] || 'Chinese Study';
}
createFlashcardMode(item) {
return `
${item.chinese}
Click to reveal translation
${item.translation}
${item.pronunciation ? `
${item.pronunciation}
` : ''}
${item.type ? `
${item.type}
` : ''}
${item.hskLevel ? `
${item.hskLevel}
` : ''}
✅ I know this
❌ Need practice
`;
}
createRecognitionMode(item) {
// Create wrong options
const wrongOptions = this.vocabulary
.filter(v => v.chinese !== item.chinese)
.sort(() => Math.random() - 0.5)
.slice(0, 3)
.map(v => v.translation);
const allOptions = [...wrongOptions, item.translation].sort(() => Math.random() - 0.5);
return `
${item.chinese}
${item.pronunciation ? `
${item.pronunciation}
` : ''}
What does this character mean?
${allOptions.map(option => `
${option}
`).join('')}
`;
}
createPinyinMode(item) {
return `
${item.chinese}
${item.translation}
Enter the pinyin pronunciation:
Check Answer
${item.pronunciation ? `
Correct: ${item.pronunciation}
` : ''}
`;
}
createHSKMode(item) {
const hskInfo = item.hskLevel || 'No HSK level';
return `
${item.chinese}
${item.translation}
${item.pronunciation ? `
${item.pronunciation}
` : ''}
${item.type ? `
Type: ${item.type}
` : ''}
${item.examples && item.examples.length > 0 ? `
Examples:
${item.examples.slice(0, 2).map(ex => `
${ex}
`).join('')}
` : ''}
😊 Easy
🤔 Medium
😅 Hard
`;
}
// Navigation methods
nextItem() {
if (this.currentIndex < this.vocabulary.length - 1) {
this.currentIndex++;
this.createStudyMode();
}
}
previousItem() {
if (this.currentIndex > 0) {
this.currentIndex--;
this.createStudyMode();
}
}
// Flashcard methods
flipCard() {
const flashcard = this.container.querySelector('.flashcard');
const isFlipped = flashcard.dataset.flipped === 'true';
flashcard.dataset.flipped = (!isFlipped).toString();
}
markAsKnown(known) {
const points = known ? 10 : 5;
this.score += points;
this.correctAnswers += known ? 1 : 0;
this.onScoreUpdate(this.score);
this.updateScoreDisplay();
// Auto-advance after a short delay
setTimeout(() => {
if (this.currentIndex < this.vocabulary.length - 1) {
this.nextItem();
} else {
this.endStudySession();
}
}, 1000);
}
// Recognition mode methods
selectOption(selectedTranslation) {
const currentItem = this.vocabulary[this.currentIndex];
const isCorrect = selectedTranslation === currentItem.translation;
const feedback = this.container.querySelector('.result-feedback');
if (isCorrect) {
this.score += 15;
this.correctAnswers++;
feedback.innerHTML = '✅ Correct! Well done!';
feedback.className = 'result-feedback correct';
} else {
this.score = Math.max(0, this.score - 5);
feedback.innerHTML = `❌ Incorrect. The correct answer is: ${currentItem.translation}`;
feedback.className = 'result-feedback incorrect';
}
feedback.style.display = 'block';
this.onScoreUpdate(this.score);
this.updateScoreDisplay();
// Disable all option buttons
const options = this.container.querySelectorAll('.option-btn');
options.forEach(btn => btn.disabled = true);
// Auto-advance after a delay
setTimeout(() => {
if (this.currentIndex < this.vocabulary.length - 1) {
this.nextItem();
} else {
this.endStudySession();
}
}, 2000);
}
// Pinyin mode methods
checkPinyinAnswer() {
const input = this.container.querySelector('.pinyin-input');
const userAnswer = input.value.trim().toLowerCase();
const currentItem = this.vocabulary[this.currentIndex];
const correctPinyin = currentItem.pronunciation ? currentItem.pronunciation.toLowerCase() : '';
const feedback = this.container.querySelector('.pinyin-feedback');
const correctAnswer = this.container.querySelector('.correct-answer');
if (correctPinyin && this.normalizePinyin(userAnswer) === this.normalizePinyin(correctPinyin)) {
this.score += 20;
this.correctAnswers++;
feedback.innerHTML = '🎉 Excellent pronunciation!';
feedback.className = 'pinyin-feedback correct';
} else {
this.score = Math.max(0, this.score - 3);
feedback.innerHTML = '🤔 Not quite right. Try again or see the correct answer below.';
feedback.className = 'pinyin-feedback incorrect';
if (correctAnswer) correctAnswer.style.display = 'block';
}
feedback.style.display = 'block';
input.disabled = true;
this.container.querySelector('.check-pinyin-btn').disabled = true;
this.onScoreUpdate(this.score);
this.updateScoreDisplay();
// Auto-advance after a delay
setTimeout(() => {
if (this.currentIndex < this.vocabulary.length - 1) {
this.nextItem();
} else {
this.endStudySession();
}
}, 3000);
}
normalizePinyin(pinyin) {
// Remove tone marks and accents for easier comparison
return pinyin.replace(/[āáǎàēéěèīíǐìōóǒòūúǔùüǖǘǚǜ]/g, (match) => {
const toneMap = {
'ā': 'a', 'á': 'a', 'ǎ': 'a', 'à': 'a',
'ē': 'e', 'é': 'e', 'ě': 'e', 'è': 'e',
'ī': 'i', 'í': 'i', 'ǐ': 'i', 'ì': 'i',
'ō': 'o', 'ó': 'o', 'ǒ': 'o', 'ò': 'o',
'ū': 'u', 'ú': 'u', 'ǔ': 'u', 'ù': 'u',
'ü': 'u', 'ǖ': 'u', 'ǘ': 'u', 'ǚ': 'u', 'ǜ': 'u'
};
return toneMap[match] || match;
}).replace(/\s+/g, '');
}
// HSK mode methods
markDifficulty(difficulty) {
const points = {
'easy': 5,
'medium': 8,
'hard': 12
};
this.score += points[difficulty];
this.correctAnswers++;
this.onScoreUpdate(this.score);
this.updateScoreDisplay();
// Visual feedback
const buttons = this.container.querySelectorAll('.difficulty-btn');
buttons.forEach(btn => btn.disabled = true);
const selectedBtn = this.container.querySelector(`.difficulty-btn.${difficulty}`);
selectedBtn.style.backgroundColor = '#10b981';
selectedBtn.style.color = 'white';
// Auto-advance after a delay
setTimeout(() => {
if (this.currentIndex < this.vocabulary.length - 1) {
this.nextItem();
} else {
this.endStudySession();
}
}, 1500);
}
updateScoreDisplay() {
const scoreElement = this.container.querySelector('#score');
if (scoreElement) {
scoreElement.textContent = this.score;
}
}
endStudySession() {
const accuracy = Math.round((this.correctAnswers / this.vocabulary.length) * 100);
this.container.innerHTML = `
🎓 Study Session Complete!
${this.score}
Final Score
${this.correctAnswers}/${this.vocabulary.length}
Correct
${accuracy >= 80 ? '🌟 Excellent work! You\'ve mastered these characters!' :
accuracy >= 60 ? '👍 Good job! Keep practicing to improve further.' :
'💪 Nice effort! More practice will help you improve.'}
🔄 Study Again
← Back to Games
`;
this.addStyles();
// Trigger game end callback
this.onGameEnd({
score: this.score,
accuracy: accuracy,
mode: this.currentMode,
totalItems: this.vocabulary.length,
correctAnswers: this.correctAnswers
});
}
addStyles() {
const style = document.createElement('style');
style.textContent = `
.chinese-study-container {
max-width: 1000px;
margin: 0 auto;
padding: 20px;
font-family: 'Arial', sans-serif;
}
.game-header {
text-align: center;
margin-bottom: 30px;
border-bottom: 2px solid #e5e7eb;
padding-bottom: 20px;
}
.game-header h2 {
color: #dc2626;
font-size: 2.2em;
margin-bottom: 15px;
}
.game-stats {
display: flex;
justify-content: center;
gap: 20px;
flex-wrap: wrap;
margin-top: 10px;
}
.score-display, .vocab-count, .hsk-indicator, .pinyin-indicator {
font-size: 1em;
padding: 5px 12px;
border-radius: 20px;
font-weight: bold;
}
.score-display {
background: #10b981;
color: white;
}
.vocab-count {
background: #3b82f6;
color: white;
}
.hsk-indicator, .pinyin-indicator {
background: #f59e0b;
color: white;
font-size: 0.9em;
}
.study-modes {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.mode-card {
background: linear-gradient(135deg, #fff 0%, #f8fafc 100%);
border: 2px solid #e5e7eb;
border-radius: 16px;
padding: 24px;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
position: relative;
}
.mode-card:not([data-disabled]):hover {
border-color: #dc2626;
transform: translateY(-4px);
box-shadow: 0 8px 20px rgba(220, 38, 38, 0.15);
}
.mode-card[data-disabled="true"] {
opacity: 0.6;
cursor: not-allowed;
background: #f9fafb;
}
.mode-requirement {
background: #fee2e2;
color: #dc2626;
padding: 4px 8px;
border-radius: 12px;
font-size: 0.8em;
margin-bottom: 10px;
}
.mode-icon {
font-size: 3em;
margin-bottom: 12px;
}
.mode-card h3 {
color: #374151;
margin-bottom: 8px;
font-size: 1.3em;
}
.mode-card p {
color: #6b7280;
margin-bottom: 16px;
line-height: 1.5;
}
.mode-btn {
background: #dc2626;
color: white;
border: none;
padding: 10px 20px;
border-radius: 8px;
cursor: pointer;
font-weight: bold;
transition: background 0.3s ease;
}
.mode-btn:hover:not(:disabled) {
background: #b91c1c;
}
.mode-btn:disabled {
background: #9ca3af;
cursor: not-allowed;
}
.vocabulary-preview {
background: #f8fafc;
border: 1px solid #e5e7eb;
border-radius: 12px;
padding: 20px;
margin-bottom: 30px;
}
.vocabulary-preview h4 {
color: #374151;
margin-bottom: 15px;
text-align: center;
}
.preview-items {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 10px;
}
.preview-item {
background: white;
border: 1px solid #e5e7eb;
border-radius: 8px;
padding: 10px;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
gap: 4px;
}
.preview-item .chinese {
font-size: 1.4em;
font-weight: bold;
color: #dc2626;
}
.preview-item .translation {
color: #374151;
font-size: 0.9em;
}
.preview-item .pinyin {
color: #6b7280;
font-size: 0.8em;
font-style: italic;
}
.preview-item .hsk-badge {
background: #f59e0b;
color: white;
padding: 2px 6px;
border-radius: 10px;
font-size: 0.7em;
font-weight: bold;
}
.more-items {
grid-column: 1/-1;
text-align: center;
color: #6b7280;
font-style: italic;
padding: 10px;
}
/* Study Mode Styles */
.study-mode-active {
max-width: 800px;
}
.study-header {
background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%);
color: white;
border-radius: 12px;
padding: 20px;
margin-bottom: 30px;
}
.mode-title {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.mode-title h2 {
margin: 0;
font-size: 1.8em;
}
.back-to-menu-btn {
background: rgba(255,255,255,0.2);
color: white;
border: 1px solid rgba(255,255,255,0.3);
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
transition: background 0.3s ease;
}
.back-to-menu-btn:hover {
background: rgba(255,255,255,0.3);
}
.progress-section {
display: flex;
align-items: center;
gap: 15px;
flex-wrap: wrap;
}
.progress-bar {
flex: 1;
min-width: 200px;
height: 8px;
background: rgba(255,255,255,0.3);
border-radius: 4px;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: white;
transition: width 0.3s ease;
}
.progress-text {
font-weight: bold;
min-width: 60px;
}
.study-content {
background: white;
border: 1px solid #e5e7eb;
border-radius: 12px;
padding: 30px;
margin-bottom: 20px;
min-height: 300px;
display: flex;
align-items: center;
justify-content: center;
}
/* Flashcard Styles */
.flashcard-container {
width: 100%;
max-width: 400px;
text-align: center;
}
.flashcard {
width: 100%;
height: 250px;
position: relative;
transform-style: preserve-3d;
transition: transform 0.6s;
cursor: pointer;
margin-bottom: 20px;
}
.flashcard[data-flipped="true"] {
transform: rotateY(180deg);
}
.flashcard-front, .flashcard-back {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
border: 2px solid #e5e7eb;
border-radius: 12px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 20px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
.flashcard-back {
transform: rotateY(180deg);
background: #f8fafc;
}
.chinese-character {
font-size: 4em;
font-weight: bold;
color: #dc2626;
margin-bottom: 10px;
}
.card-hint {
color: #6b7280;
font-style: italic;
}
.translation {
font-size: 1.5em;
color: #374151;
margin-bottom: 10px;
}
.pronunciation {
color: #6b7280;
font-style: italic;
margin-bottom: 8px;
}
.word-type, .hsk-level {
background: #e5e7eb;
color: #374151;
padding: 4px 8px;
border-radius: 12px;
font-size: 0.8em;
margin-bottom: 4px;
}
.hsk-level {
background: #f59e0b;
color: white;
}
.flashcard-actions {
display: flex;
gap: 15px;
justify-content: center;
}
.know-btn, .dont-know-btn {
padding: 12px 24px;
border: none;
border-radius: 8px;
font-weight: bold;
cursor: pointer;
transition: all 0.3s ease;
}
.know-btn {
background: #10b981;
color: white;
}
.know-btn:hover {
background: #059669;
}
.dont-know-btn {
background: #f59e0b;
color: white;
}
.dont-know-btn:hover {
background: #d97706;
}
/* Recognition Mode Styles */
.recognition-container {
width: 100%;
text-align: center;
}
.question-section {
margin-bottom: 30px;
}
.pronunciation-hint {
color: #6b7280;
font-style: italic;
margin-bottom: 15px;
}
.question-text {
font-size: 1.2em;
color: #374151;
margin-bottom: 20px;
}
.options-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 15px;
margin-bottom: 20px;
}
.option-btn {
background: #f8fafc;
border: 2px solid #e5e7eb;
border-radius: 8px;
padding: 15px;
cursor: pointer;
font-size: 1em;
transition: all 0.3s ease;
}
.option-btn:hover:not(:disabled) {
border-color: #dc2626;
background: #fef2f2;
}
.option-btn:disabled {
cursor: not-allowed;
opacity: 0.6;
}
.result-feedback {
padding: 15px;
border-radius: 8px;
font-weight: bold;
margin-bottom: 15px;
}
.result-feedback.correct {
background: #d1fae5;
color: #065f46;
border: 1px solid #10b981;
}
.result-feedback.incorrect {
background: #fee2e2;
color: #991b1b;
border: 1px solid #ef4444;
}
/* Pinyin Mode Styles */
.pinyin-container {
width: 100%;
text-align: center;
}
.character-section {
margin-bottom: 30px;
}
.translation-hint {
font-size: 1.2em;
color: #6b7280;
margin-top: 10px;
}
.pinyin-exercise {
margin-bottom: 20px;
}
.pinyin-label {
display: block;
font-weight: bold;
color: #374151;
margin-bottom: 10px;
}
.pinyin-input {
padding: 12px;
border: 2px solid #e5e7eb;
border-radius: 8px;
font-size: 1.1em;
width: 250px;
max-width: 100%;
margin-bottom: 15px;
margin-right: 10px;
}
.pinyin-input:focus {
outline: none;
border-color: #dc2626;
}
.check-pinyin-btn {
background: #dc2626;
color: white;
border: none;
padding: 12px 20px;
border-radius: 8px;
cursor: pointer;
font-weight: bold;
}
.check-pinyin-btn:hover:not(:disabled) {
background: #b91c1c;
}
.check-pinyin-btn:disabled {
background: #9ca3af;
cursor: not-allowed;
}
.pinyin-feedback {
padding: 15px;
border-radius: 8px;
font-weight: bold;
margin-bottom: 15px;
}
.pinyin-feedback.correct {
background: #d1fae5;
color: #065f46;
border: 1px solid #10b981;
}
.pinyin-feedback.incorrect {
background: #fee2e2;
color: #991b1b;
border: 1px solid #ef4444;
}
.correct-answer {
background: #f0f9ff;
color: #0c4a6e;
border: 1px solid #3b82f6;
padding: 10px;
border-radius: 8px;
font-weight: bold;
}
/* HSK Mode Styles */
.hsk-container {
width: 100%;
text-align: center;
}
.hsk-header {
margin-bottom: 30px;
}
.hsk-level-badge {
background: #f59e0b;
color: white;
padding: 8px 16px;
border-radius: 20px;
font-weight: bold;
display: inline-block;
margin-bottom: 10px;
}
.character-difficulty {
color: #6b7280;
font-size: 1em;
}
.character-study {
margin-bottom: 30px;
}
.character-details {
background: #f8fafc;
border-radius: 8px;
padding: 20px;
margin-top: 15px;
}
.character-details .translation {
font-size: 1.3em;
margin-bottom: 10px;
}
.character-details .word-type {
background: #e5e7eb;
color: #374151;
padding: 4px 12px;
border-radius: 12px;
font-size: 0.9em;
display: inline-block;
margin-bottom: 15px;
}
.examples {
text-align: left;
margin-top: 15px;
}
.examples h5 {
color: #374151;
margin-bottom: 8px;
text-align: center;
}
.example {
background: white;
border: 1px solid #e5e7eb;
border-radius: 6px;
padding: 8px;
margin-bottom: 5px;
color: #6b7280;
}
.hsk-actions {
display: flex;
gap: 15px;
justify-content: center;
flex-wrap: wrap;
}
.difficulty-btn {
padding: 12px 20px;
border: 2px solid #e5e7eb;
border-radius: 8px;
background: white;
cursor: pointer;
font-weight: bold;
transition: all 0.3s ease;
min-width: 100px;
}
.difficulty-btn.easy {
border-color: #10b981;
color: #10b981;
}
.difficulty-btn.easy:hover:not(:disabled) {
background: #10b981;
color: white;
}
.difficulty-btn.medium {
border-color: #f59e0b;
color: #f59e0b;
}
.difficulty-btn.medium:hover:not(:disabled) {
background: #f59e0b;
color: white;
}
.difficulty-btn.hard {
border-color: #ef4444;
color: #ef4444;
}
.difficulty-btn.hard:hover:not(:disabled) {
background: #ef4444;
color: white;
}
.difficulty-btn:disabled {
cursor: not-allowed;
opacity: 0.7;
}
/* Study Controls */
.study-controls {
display: flex;
justify-content: space-between;
gap: 15px;
}
.prev-btn, .next-btn {
background: #6b7280;
color: white;
border: none;
padding: 12px 24px;
border-radius: 8px;
cursor: pointer;
font-weight: bold;
transition: background 0.3s ease;
flex: 1;
max-width: 150px;
}
.prev-btn:hover:not(:disabled), .next-btn:hover:not(:disabled) {
background: #4b5563;
}
.prev-btn:disabled, .next-btn:disabled {
background: #9ca3af;
cursor: not-allowed;
}
/* Study Complete Styles */
.study-complete {
text-align: center;
padding: 40px 20px;
}
.study-complete h2 {
color: #dc2626;
font-size: 2.5em;
margin-bottom: 30px;
}
.final-stats {
display: flex;
justify-content: center;
gap: 30px;
margin-bottom: 30px;
flex-wrap: wrap;
}
.stat-item {
background: #f8fafc;
border: 1px solid #e5e7eb;
border-radius: 12px;
padding: 20px;
min-width: 120px;
}
.stat-value {
font-size: 2em;
font-weight: bold;
color: #dc2626;
margin-bottom: 5px;
}
.stat-label {
color: #6b7280;
font-size: 0.9em;
}
.completion-message {
background: #f0f9ff;
border: 1px solid #3b82f6;
border-radius: 12px;
padding: 20px;
color: #1e40af;
font-size: 1.1em;
font-weight: bold;
margin-bottom: 30px;
}
.final-actions {
display: flex;
gap: 15px;
justify-content: center;
flex-wrap: wrap;
}
.restart-btn, .menu-btn, .back-btn {
padding: 12px 24px;
border: none;
border-radius: 8px;
cursor: pointer;
font-weight: bold;
transition: background 0.3s ease;
font-size: 1em;
}
.restart-btn {
background: #10b981;
color: white;
}
.restart-btn:hover {
background: #059669;
}
.menu-btn {
background: #3b82f6;
color: white;
}
.menu-btn:hover {
background: #2563eb;
}
.back-btn {
background: #6b7280;
color: white;
}
.back-btn:hover {
background: #4b5563;
}
.game-controls {
text-align: center;
}
.game-error {
text-align: center;
padding: 40px 20px;
background: #fee2e2;
border: 1px solid #ef4444;
border-radius: 12px;
}
.game-error h3 {
color: #991b1b;
margin-bottom: 15px;
}
.game-error p {
color: #7f1d1d;
margin-bottom: 10px;
}
@media (max-width: 768px) {
.chinese-study-container {
padding: 15px;
}
.game-header h2 {
font-size: 1.8em;
}
.study-modes {
grid-template-columns: 1fr;
}
.preview-items {
grid-template-columns: 1fr;
}
.game-stats {
flex-direction: column;
align-items: center;
gap: 10px;
}
.chinese-character {
font-size: 3em;
}
.flashcard {
height: 200px;
}
.options-grid {
grid-template-columns: 1fr;
}
.final-stats {
flex-direction: column;
align-items: center;
gap: 15px;
}
.final-actions {
flex-direction: column;
align-items: center;
}
.hsk-actions {
flex-direction: column;
align-items: center;
}
.study-controls {
flex-direction: column;
}
.prev-btn, .next-btn {
max-width: none;
}
.mode-title {
flex-direction: column;
gap: 10px;
text-align: center;
}
.progress-section {
flex-direction: column;
gap: 10px;
}
}
`;
document.head.appendChild(style);
}
start() {
this.isRunning = true;
logSh('Chinese Study Mode initialized with ultra-modular format', 'INFO');
}
destroy() {
this.isRunning = false;
// Clean up global references
if (window.chineseStudyInstance === this) {
delete window.chineseStudyInstance;
}
logSh('Chinese Study Mode destroyed', 'INFO');
}
restart() {
this.score = 0;
this.correctAnswers = 0;
this.currentIndex = 0;
this.studyState = 'menu';
this.currentMode = null;
this.onScoreUpdate(this.score);
// Re-shuffle vocabulary
this.vocabulary = this.vocabulary.sort(() => Math.random() - 0.5);
this.createGameInterface();
logSh('Chinese Study Mode restarted', 'INFO');
}
}
// Export to global scope
window.GameModules = window.GameModules || {};
window.GameModules.ChineseStudy = ChineseStudyGame;