- Fix WebSocket server to properly broadcast logs to all connected clients - Integrate professional logging system with real-time WebSocket interface - Add network status indicator with DigitalOcean Spaces connectivity - Implement AWS Signature V4 authentication for private bucket access - Add JSON content loader with backward compatibility to JS modules - Restore navigation breadcrumb system with comprehensive logging - Add multiple content formats: JSON + JS with automatic discovery - Enhance top bar with logger toggle and network status indicator - Remove deprecated temp-games module and clean up unused files 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
279 lines
8.7 KiB
JavaScript
279 lines
8.7 KiB
JavaScript
// === CHINESE STUDY MODE ===
|
|
|
|
class ChineseStudyGame {
|
|
constructor(options) {
|
|
this.container = options.container;
|
|
this.content = options.content;
|
|
this.onScoreUpdate = options.onScoreUpdate || (() => {});
|
|
this.onGameEnd = options.onGameEnd || (() => {});
|
|
|
|
this.score = 0;
|
|
this.isRunning = false;
|
|
|
|
this.init();
|
|
}
|
|
|
|
init() {
|
|
this.createInterface();
|
|
this.setupEventListeners();
|
|
}
|
|
|
|
createInterface() {
|
|
this.container.innerHTML = `
|
|
<div class="chinese-study-container">
|
|
<div class="game-header">
|
|
<h2>🇨🇳 Chinese Study Mode</h2>
|
|
<div class="score-display">Score: <span id="score">0</span></div>
|
|
</div>
|
|
|
|
<div class="study-modes">
|
|
<div class="mode-card" data-mode="characters">
|
|
<div class="mode-icon">📝</div>
|
|
<h3>Character Recognition</h3>
|
|
<p>Learn Chinese characters and their meanings</p>
|
|
<button class="mode-btn">Start Learning</button>
|
|
</div>
|
|
|
|
<div class="mode-card" data-mode="pinyin">
|
|
<div class="mode-icon">🗣️</div>
|
|
<h3>Pinyin Practice</h3>
|
|
<p>Master Chinese pronunciation with pinyin</p>
|
|
<button class="mode-btn">Start Learning</button>
|
|
</div>
|
|
|
|
<div class="mode-card" data-mode="vocabulary">
|
|
<div class="mode-icon">📚</div>
|
|
<h3>Vocabulary Cards</h3>
|
|
<p>Study vocabulary with flashcards</p>
|
|
<button class="mode-btn">Start Learning</button>
|
|
</div>
|
|
|
|
<div class="mode-card" data-mode="writing">
|
|
<div class="mode-icon">✍️</div>
|
|
<h3>Stroke Order</h3>
|
|
<p>Learn proper character writing</p>
|
|
<button class="mode-btn">Start Learning</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="placeholder-content">
|
|
<h3>🚧 Coming Soon!</h3>
|
|
<p>This is a placeholder for the Chinese study mode. Different learning modules will be implemented here.</p>
|
|
<p>Available content: ${this.getContentInfo()}</p>
|
|
</div>
|
|
|
|
<div class="game-controls">
|
|
<button onclick="AppNavigation.goBack()" class="back-btn">← Back to Games</button>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
this.addStyles();
|
|
}
|
|
|
|
setupEventListeners() {
|
|
const modeCards = this.container.querySelectorAll('.mode-card');
|
|
modeCards.forEach(card => {
|
|
card.addEventListener('click', (e) => {
|
|
const mode = card.dataset.mode;
|
|
this.showPlaceholder(mode);
|
|
});
|
|
});
|
|
}
|
|
|
|
showPlaceholder(mode) {
|
|
const modeNames = {
|
|
characters: 'Character Recognition',
|
|
pinyin: 'Pinyin Practice',
|
|
vocabulary: 'Vocabulary Cards',
|
|
writing: 'Stroke Order'
|
|
};
|
|
|
|
const placeholderDiv = this.container.querySelector('.placeholder-content');
|
|
placeholderDiv.innerHTML = `
|
|
<h3>📱 ${modeNames[mode]} Mode</h3>
|
|
<p>This learning module is being developed!</p>
|
|
<p>It will include interactive exercises for ${mode} practice.</p>
|
|
<button onclick="location.reload()" class="retry-btn">← Back to Study Modes</button>
|
|
`;
|
|
|
|
// Add some score for interaction
|
|
this.score += 5;
|
|
this.onScoreUpdate(this.score);
|
|
this.container.querySelector('#score').textContent = this.score;
|
|
}
|
|
|
|
getContentInfo() {
|
|
if (!this.content) return 'No content loaded';
|
|
|
|
let info = [];
|
|
if (this.content.vocabulary) info.push(`${Object.keys(this.content.vocabulary).length} vocabulary items`);
|
|
if (this.content.sentences) info.push(`${this.content.sentences.length} sentences`);
|
|
if (this.content.texts) info.push(`${this.content.texts.length} texts`);
|
|
|
|
return info.length > 0 ? info.join(', ') : 'Basic Chinese content';
|
|
}
|
|
|
|
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: 10px;
|
|
}
|
|
|
|
.score-display {
|
|
font-size: 1.2em;
|
|
color: #059669;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.study-modes {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
|
gap: 20px;
|
|
margin-bottom: 40px;
|
|
}
|
|
|
|
.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);
|
|
}
|
|
|
|
.mode-card:hover {
|
|
border-color: #dc2626;
|
|
transform: translateY(-4px);
|
|
box-shadow: 0 8px 20px rgba(220, 38, 38, 0.15);
|
|
}
|
|
|
|
.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 {
|
|
background: #b91c1c;
|
|
}
|
|
|
|
.placeholder-content {
|
|
background: #fef3c7;
|
|
border: 2px solid #f59e0b;
|
|
border-radius: 12px;
|
|
padding: 24px;
|
|
text-align: center;
|
|
margin-bottom: 30px;
|
|
}
|
|
|
|
.placeholder-content h3 {
|
|
color: #92400e;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.placeholder-content p {
|
|
color: #78350f;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.game-controls {
|
|
text-align: center;
|
|
}
|
|
|
|
.back-btn, .retry-btn {
|
|
background: #6b7280;
|
|
color: white;
|
|
border: none;
|
|
padding: 12px 24px;
|
|
border-radius: 8px;
|
|
cursor: pointer;
|
|
font-size: 1em;
|
|
font-weight: bold;
|
|
transition: background 0.3s ease;
|
|
}
|
|
|
|
.back-btn:hover, .retry-btn:hover {
|
|
background: #4b5563;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.study-modes {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.chinese-study-container {
|
|
padding: 15px;
|
|
}
|
|
|
|
.game-header h2 {
|
|
font-size: 1.8em;
|
|
}
|
|
}
|
|
`;
|
|
document.head.appendChild(style);
|
|
}
|
|
|
|
start() {
|
|
this.isRunning = true;
|
|
logSh('Chinese Study Mode initialized', 'INFO');
|
|
}
|
|
|
|
destroy() {
|
|
this.isRunning = false;
|
|
// Clean up any intervals, event listeners, etc.
|
|
}
|
|
|
|
restart() {
|
|
this.score = 0;
|
|
this.onScoreUpdate(this.score);
|
|
this.container.querySelector('#score').textContent = this.score;
|
|
this.createInterface();
|
|
this.setupEventListeners();
|
|
}
|
|
}
|
|
|
|
// Export to global scope
|
|
window.GameModules = window.GameModules || {};
|
|
window.GameModules.ChineseStudy = ChineseStudyGame; |