Major Changes: - Moved legacy system to Legacy/ folder for archival - Built new modular architecture with strict separation of concerns - Created core system: Module, EventBus, ModuleLoader, Router - Added Application bootstrap with auto-start functionality - Implemented development server with ES6 modules support - Created comprehensive documentation and project context - Converted SBS-7-8 content to JSON format - Copied all legacy games and content to new structure New Architecture Features: - Sealed modules with WeakMap private data - Strict dependency injection system - Event-driven communication only - Inviolable responsibility patterns - Auto-initialization without commands - Component-based UI foundation ready Technical Stack: - Vanilla JS/HTML/CSS only - ES6 modules with proper imports/exports - HTTP development server (no file:// protocol) - Modular CSS with component scoping - Comprehensive error handling and debugging Ready for Phase 2: Converting legacy modules to new architecture 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
804 lines
28 KiB
Markdown
804 lines
28 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## 🎯 IMPORTANT: Check TODO.md First!
|
|
|
|
**ALWAYS check `TODO.md` for the current project tasks and priorities before making any changes.**
|
|
|
|
The `TODO.md` file contains:
|
|
- 🔥 Current tasks in progress
|
|
- 📋 Pending features to implement
|
|
- 🚨 Known issues and blockers
|
|
- ✅ Completed work for reference
|
|
|
|
**Make sure to update TODO.md when:**
|
|
- Starting a new task
|
|
- Completing a task
|
|
- Discovering new issues
|
|
- Planning future improvements
|
|
|
|
## Project Overview
|
|
|
|
Interactive English learning platform for children (8-9 years old) built as a modular Single Page Application. The system provides 9 different educational games that work with various content modules through a flexible architecture.
|
|
|
|
## Key Architecture Patterns
|
|
|
|
### Core System Flow
|
|
1. **AppNavigation** (`js/core/navigation.js`) - Central SPA navigation controller
|
|
2. **ContentScanner** (`js/core/content-scanner.js`) - Auto-discovers available content modules
|
|
3. **GameLoader** (`js/core/game-loader.js`) - Dynamically loads game and content modules
|
|
4. **Content Engine** (`js/core/content-engine.js`) - Processes and adapts content for games
|
|
|
|
### Module Loading System
|
|
- Games and content are loaded dynamically via `GameLoader.loadGame(gameType, contentType)`
|
|
- All modules register themselves on global objects: `window.GameModules` and `window.ContentModules`
|
|
- Content is discovered automatically by `ContentScanner` scanning `js/content/` directory
|
|
- **JSON Content Support**: New JSON-first architecture with backward compatibility to JS modules
|
|
- **JSON Content Loader**: `js/core/json-content-loader.js` transforms JSON content to legacy game format
|
|
- **Offline-First Loading**: Content loads from local files first, with DigitalOcean Spaces fallback
|
|
- Games follow consistent constructor pattern: `new GameClass({ container, content, onScoreUpdate, onGameEnd })`
|
|
|
|
### URL-Based Navigation
|
|
- Single HTML file (`index.html`) handles all navigation via URL parameters
|
|
- Routes: `?page=home|games|levels|play&game=<gameType>&content=<contentType>`
|
|
- Browser back/forward supported through `popstate` events
|
|
- Navigation history maintained in `AppNavigation.navigationHistory`
|
|
- Breadcrumb navigation with clickable path elements
|
|
- **Top Bar**: Fixed header with app title and permanent network status indicator
|
|
- **Network Status**: Real-time connectivity indicator (🟢 Online / 🟠 Connecting / 🔴 Offline)
|
|
- Keyboard shortcuts (ESC = go back)
|
|
|
|
## Content Module Format
|
|
|
|
### Rich Content Schema (New Architecture)
|
|
|
|
Content modules support rich, multimedia educational content with optional properties. The system adapts games and exercises based on available content features:
|
|
|
|
```javascript
|
|
window.ContentModules.ModuleName = {
|
|
name: "Display Name",
|
|
description: "Description text",
|
|
difficulty: "easy|medium|hard|beginner|intermediate|advanced",
|
|
language: "chinese|english|french|spanish", // Target learning language
|
|
hskLevel: "HSK1|HSK2|HSK3|HSK4|HSK5|HSK6", // Chinese proficiency level
|
|
|
|
// Rich vocabulary with optional multimedia
|
|
vocabulary: {
|
|
"word_or_character": {
|
|
translation: "English translation",
|
|
prononciation: "pronunciation guide", // Optional: pronunciation guide
|
|
type: "noun|verb|adjective|greeting|number", // Word classification
|
|
pronunciation: "audio/word.mp3", // Optional: audio file
|
|
difficulty: "HSK1|HSK2|...", // Optional: individual word difficulty
|
|
strokeOrder: ["stroke1", "stroke2"], // Optional: character writing order
|
|
examples: ["example sentence 1"], // Optional: usage examples
|
|
grammarNotes: "special usage rules" // Optional: grammar context
|
|
}
|
|
// OR simple format for basic content:
|
|
// "word": "simple translation"
|
|
},
|
|
|
|
// Grammar rules and explanations
|
|
grammar: {
|
|
topic_name: {
|
|
title: "Grammar Rule Title",
|
|
explanation: "Detailed explanation",
|
|
examples: [
|
|
{ chinese: "中文例子", english: "English example", prononciation: "zhōng wén lì zi" }
|
|
],
|
|
exercises: [/* grammar-specific exercises */]
|
|
}
|
|
},
|
|
|
|
// Audio content with/without text
|
|
audio: {
|
|
withText: [
|
|
{
|
|
title: "Audio Lesson Title",
|
|
audioFile: "audio/lesson1.mp3",
|
|
transcript: "Full text transcript",
|
|
translation: "English translation",
|
|
timestamps: [{ time: 5.2, text: "specific segment" }] // Optional
|
|
}
|
|
],
|
|
withoutText: [
|
|
{
|
|
title: "Listening Challenge",
|
|
audioFile: "audio/challenge1.mp3",
|
|
questions: [
|
|
{ question: "What did they say?", type: "ai_interpreted" }
|
|
]
|
|
}
|
|
]
|
|
},
|
|
|
|
// Poetry and cultural content
|
|
poems: [
|
|
{
|
|
title: "Poem Title",
|
|
content: "Full poem text",
|
|
translation: "English translation",
|
|
audioFile: "audio/poem1.mp3", // Optional
|
|
culturalContext: "Historical background"
|
|
}
|
|
],
|
|
|
|
// Fill-in-the-blank exercises
|
|
fillInBlanks: [
|
|
{
|
|
sentence: "I _____ to school every day",
|
|
options: ["go", "goes", "going", "went"], // Multiple choice options
|
|
correctAnswer: "go",
|
|
explanation: "Present tense with 'I'"
|
|
},
|
|
{
|
|
sentence: "The weather is _____ today",
|
|
type: "open_ended", // AI-interpreted answers
|
|
acceptedAnswers: ["nice", "good", "beautiful", "sunny"],
|
|
aiPrompt: "Evaluate if answer describes weather positively"
|
|
}
|
|
],
|
|
|
|
// Sentence correction exercises
|
|
corrections: [
|
|
{
|
|
incorrect: "I are happy today",
|
|
correct: "I am happy today",
|
|
explanation: "Use 'am' with pronoun 'I'",
|
|
type: "grammar_correction"
|
|
}
|
|
],
|
|
|
|
// Reading comprehension with AI evaluation
|
|
comprehension: [
|
|
{
|
|
text: "Long reading passage...",
|
|
questions: [
|
|
{
|
|
question: "What is the main idea?",
|
|
type: "ai_interpreted",
|
|
evaluationPrompt: "Check if answer captures main theme"
|
|
},
|
|
{
|
|
question: "Multiple choice question?",
|
|
type: "multiple_choice",
|
|
options: ["A", "B", "C", "D"],
|
|
correctAnswer: "B"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
|
|
// Matching exercises (connect lines between columns)
|
|
matching: [
|
|
{
|
|
title: "Match Words to Meanings",
|
|
leftColumn: ["apple", "book", "car"],
|
|
rightColumn: ["苹果", "书", "车"],
|
|
correctPairs: [
|
|
{ left: "apple", right: "苹果" },
|
|
{ left: "book", right: "书" },
|
|
{ left: "car", right: "车" }
|
|
]
|
|
}
|
|
],
|
|
|
|
// Standard content (backward compatibility)
|
|
sentences: [{ english: "...", chinese: "...", prononciation: "..." }],
|
|
texts: [{ title: "...", content: "...", translation: "..." }],
|
|
dialogues: [{ conversation: [...] }]
|
|
};
|
|
```
|
|
|
|
### JSON Content Format (New Architecture)
|
|
|
|
The platform now supports JSON content files for easier editing and maintenance:
|
|
|
|
```json
|
|
{
|
|
"name": "Content Name",
|
|
"description": "Content description",
|
|
"difficulty": "easy|medium|hard",
|
|
"vocabulary": {
|
|
"word": {
|
|
"translation": "French translation",
|
|
"prononciation": "pronunciation guide",
|
|
"type": "noun|verb|adjective"
|
|
}
|
|
},
|
|
"sentences": [
|
|
{
|
|
"english": "English sentence",
|
|
"chinese": "Chinese translation",
|
|
"prononciation": "pronunciation"
|
|
}
|
|
],
|
|
"grammar": { /* grammar rules */ },
|
|
"audio": { /* audio content */ },
|
|
"exercises": { /* exercise definitions */ }
|
|
}
|
|
```
|
|
|
|
**JSON Content Loader Features:**
|
|
- Automatic transformation from JSON to legacy game format
|
|
- Backward compatibility with existing JavaScript content modules
|
|
- Support for all rich content features (vocabulary, grammar, audio, exercises)
|
|
- Offline-first loading with cloud fallback
|
|
|
|
### Content Adaptivity System
|
|
|
|
The platform automatically adapts available games and exercises based on content richness:
|
|
|
|
**Content Analysis:**
|
|
- System scans each content module for available features
|
|
- Generates compatibility scores for each game type
|
|
- Recommends optimal learning activities
|
|
- Handles graceful degradation when content is incomplete
|
|
|
|
**Adaptive Game Selection:**
|
|
- **Rich vocabulary** → Enable advanced matching games, pronunciation practice
|
|
- **Audio files present** → Enable listening exercises, pronunciation challenges
|
|
- **Grammar rules** → Enable correction exercises, structured lessons
|
|
- **Fill-in-blanks data** → Enable cloze tests with multiple choice or AI evaluation
|
|
- **Minimal content** → Fall back to basic vocabulary games
|
|
|
|
**Missing Content Handling:**
|
|
- Display helpful messages: "Add audio files to enable pronunciation practice"
|
|
- Suggest content enrichment opportunities
|
|
- Gracefully disable incompatible game modes
|
|
- Provide content creation tools for missing elements
|
|
|
|
**Example Adaptive Behavior:**
|
|
```javascript
|
|
// Content with only basic vocabulary
|
|
{ vocabulary: { "hello": "你好" } }
|
|
→ Enable: Basic matching, simple quiz
|
|
→ Disable: Audio practice, grammar exercises
|
|
→ Suggest: "Add pronunciation guide and audio for pronunciation practice"
|
|
|
|
// Rich multimedia content
|
|
{ vocabulary: { "hello": { translation: "你好", prononciation: "nǐ hǎo", pronunciation: "audio/hello.mp3" } } }
|
|
→ Enable: All vocabulary games, audio practice, pronunciation scoring
|
|
→ Unlock: Advanced difficulty levels, speed challenges
|
|
```
|
|
|
|
## 🚨 CRITICAL ARCHITECTURE GUIDELINES
|
|
|
|
**NEVER violate these principles to maintain system modularity and maintainability:**
|
|
|
|
### 🎨 CSS Architecture Rules
|
|
|
|
1. **NEVER modify `css/games.css` for game-specific styles**
|
|
- Global CSS is only for shared, reusable components
|
|
- Game-specific styles MUST be injected by the game itself
|
|
|
|
2. **USE the Global CSS Base System:**
|
|
```javascript
|
|
// ✅ CORRECT: Use global classes with specific overrides
|
|
<div class="game-wrapper compact"> // Global base class
|
|
<div class="game-hud"> // Global HUD structure
|
|
<div class="game-area"> // Global game area
|
|
<div class="answer-panel"> // Global answer panel
|
|
|
|
// ✅ CORRECT: Inject game-specific CSS
|
|
injectCSS() {
|
|
const styleSheet = document.createElement('style');
|
|
styleSheet.textContent = `
|
|
.my-game-specific-element { /* Game-only styles */ }
|
|
`;
|
|
document.head.appendChild(styleSheet);
|
|
}
|
|
```
|
|
|
|
3. **CSS Classes Hierarchy:**
|
|
- `.game-wrapper` - Base container (full screen)
|
|
- `.game-wrapper.compact` - Smaller viewport variant
|
|
- `.game-hud` - Top information bar
|
|
- `.game-area` - Main play zone
|
|
- `.answer-panel` - Bottom interaction zone
|
|
- `.answer-btn` - Interactive buttons
|
|
|
|
4. **❌ FORBIDDEN PATTERNS:**
|
|
```css
|
|
/* ❌ NEVER add game-specific classes to games.css */
|
|
.word-storm-wrapper { }
|
|
.my-game-specific-class { }
|
|
|
|
/* ❌ NEVER hardcode game-specific dimensions in global CSS */
|
|
.game-area { height: 600px; } /* This breaks other games */
|
|
```
|
|
|
|
### 🎮 Game Development Standards
|
|
|
|
1. **Self-Contained Games:**
|
|
- Each game MUST inject its own CSS via `injectCSS()`
|
|
- Games MUST use global base classes where possible
|
|
- Game-specific elements get their own CSS only
|
|
|
|
2. **Constructor Pattern (REQUIRED):**
|
|
```javascript
|
|
class MyGame {
|
|
constructor({ container, content, onScoreUpdate, onGameEnd }) {
|
|
this.injectCSS(); // Inject game-specific styles
|
|
this.init(); // Setup interface
|
|
}
|
|
|
|
start() { /* Start game logic */ }
|
|
destroy() { /* Cleanup */ }
|
|
}
|
|
```
|
|
|
|
3. **Module Registration (REQUIRED):**
|
|
```javascript
|
|
// MUST be at end of game file
|
|
window.GameModules = window.GameModules || {};
|
|
window.GameModules.MyGame = MyGame;
|
|
```
|
|
|
|
4. **GameLoader Integration:**
|
|
- Add game mapping in `game-loader.js` → `getModuleName()`
|
|
- Add compatibility rules in `content-game-compatibility.js`
|
|
- Add game config in `navigation.js` → game configuration
|
|
|
|
### 🔧 Modification Guidelines
|
|
|
|
**When adding new games:**
|
|
1. ✅ Use existing global CSS classes
|
|
2. ✅ Inject only game-specific CSS
|
|
3. ✅ Follow constructor pattern
|
|
4. ✅ Add to GameLoader mapping
|
|
|
|
**When modifying existing games:**
|
|
1. ✅ Keep changes within the game file
|
|
2. ✅ Don't break global CSS compatibility
|
|
3. ✅ Test with multiple content types
|
|
|
|
**When adding global features:**
|
|
1. ✅ Add to global CSS base classes
|
|
2. ✅ Ensure backward compatibility
|
|
3. ✅ Update this documentation
|
|
|
|
### 🚀 Benefits of This Architecture
|
|
|
|
- **Modularity**: Each game is self-contained
|
|
- **Reusability**: Base classes work for all games
|
|
- **Maintainability**: Changes don't break other games
|
|
- **Performance**: Only load CSS when game is used
|
|
- **Scalability**: Easy to add new games
|
|
|
|
### ⚠️ Common Mistakes to Avoid
|
|
|
|
**CSS Architecture Violations:**
|
|
```css
|
|
/* ❌ DON'T: Adding game-specific styles to games.css */
|
|
.word-storm-wrapper { height: 80vh; width: 90vw; }
|
|
|
|
/* ✅ DO: Use global classes with game-specific injection */
|
|
// In game file:
|
|
injectCSS() {
|
|
// Game-specific overrides only
|
|
styleSheet.textContent = `.falling-word { animation: wordGlow 2s; }`;
|
|
}
|
|
```
|
|
|
|
**Module Loading Issues:**
|
|
```javascript
|
|
// ❌ DON'T: Forget GameLoader mapping
|
|
// Game won't load because getModuleName() doesn't know about it
|
|
|
|
// ✅ DO: Add to game-loader.js
|
|
const names = {
|
|
'my-game': 'MyGame' // Add this mapping
|
|
};
|
|
```
|
|
|
|
**HTML Structure Violations:**
|
|
```html
|
|
<!-- ❌ DON'T: Create custom wrapper classes -->
|
|
<div class="my-custom-game-wrapper">
|
|
|
|
<!-- ✅ DO: Use standard global structure -->
|
|
<div class="game-wrapper compact">
|
|
<div class="game-hud">
|
|
<div class="game-area">
|
|
<div class="answer-panel">
|
|
```
|
|
|
|
**Integration Checklist:**
|
|
- [ ] Game CSS injected via `injectCSS()`
|
|
- [ ] Global classes used for structure
|
|
- [ ] GameLoader mapping added
|
|
- [ ] Compatibility rules defined
|
|
- [ ] Constructor pattern followed
|
|
- [ ] Module registration at file end
|
|
|
|
## Game Module Format
|
|
|
|
Game modules must export to `window.GameModules` with this pattern:
|
|
```javascript
|
|
class GameName {
|
|
constructor({ container, content, onScoreUpdate, onGameEnd }) {
|
|
this.container = container;
|
|
this.content = content;
|
|
this.onScoreUpdate = onScoreUpdate;
|
|
this.onGameEnd = onGameEnd;
|
|
}
|
|
|
|
start() { /* Initialize game */ }
|
|
destroy() { /* Cleanup */ }
|
|
restart() { /* Reset game state */ }
|
|
}
|
|
|
|
window.GameModules = window.GameModules || {};
|
|
window.GameModules.GameName = GameName;
|
|
```
|
|
|
|
## Configuration System
|
|
|
|
- **Main config**: `config/games-config.json` - defines available games and content
|
|
- **Environment config**: `js/core/env-config.js` - DigitalOcean Spaces configuration and offline settings
|
|
- **Content discovery**: Automatic scanning of both `.js` and `.json` content files
|
|
- Games can be enabled/disabled via `games.{gameType}.enabled`
|
|
- **Cloud Integration**: DigitalOcean Spaces endpoint configuration for remote content
|
|
- **Offline-First Strategy**: Local content prioritized, remote fallback with timeout protection
|
|
- UI settings, scoring rules, and feature flags also in main config
|
|
|
|
## Development Workflow
|
|
|
|
### Running the Application
|
|
Open `index.html` in a web browser - no build process required. All modules load dynamically.
|
|
|
|
### Adding New Games
|
|
1. Create `js/games/{game-name}.js` with proper module export
|
|
2. Add game configuration to `config/games-config.json`
|
|
3. Update `AppNavigation.getDefaultConfig()` if needed
|
|
|
|
### Adding New Content
|
|
**Option 1: JSON Format (Recommended)**
|
|
1. Create `js/content/{content-name}.json` with proper JSON structure
|
|
2. Content will be auto-discovered and loaded via JSON Content Loader
|
|
3. Easier to edit and maintain than JavaScript files
|
|
|
|
**Option 2: JavaScript Format (Legacy)**
|
|
1. Create `js/content/{content-name}.js` with proper module export
|
|
2. Add filename to `ContentScanner.contentFiles` array
|
|
3. Content will be auto-discovered on next app load
|
|
|
|
### Content Creation Tool
|
|
- Built-in content creator at `js/tools/content-creator.js`
|
|
- Accessible via "Créateur de Contenu" button on home page
|
|
- Generates properly formatted content modules
|
|
|
|
## Key Files by Function
|
|
|
|
**Navigation & Loading:**
|
|
- `js/core/navigation.js` - SPA navigation controller (452 lines)
|
|
- `js/core/game-loader.js` - Dynamic module loading (336 lines)
|
|
- `js/core/content-scanner.js` - Auto content discovery (376 lines)
|
|
|
|
**Content Processing:**
|
|
- `js/core/content-engine.js` - Content processing engine (484 lines)
|
|
- `js/core/content-factory.js` - Exercise generation (553 lines)
|
|
- `js/core/content-parsers.js` - Content parsing utilities (484 lines)
|
|
- `js/core/json-content-loader.js` - JSON to legacy format transformation
|
|
- `js/core/env-config.js` - Environment and cloud configuration
|
|
|
|
**Game Implementations:**
|
|
- `js/games/whack-a-mole.js` - Standard version (623 lines)
|
|
- `js/games/whack-a-mole-hard.js` - Difficult version (643 lines)
|
|
- `js/games/memory-match.js` - Memory pairs game (403 lines)
|
|
- `js/games/quiz-game.js` - Quiz system (354 lines)
|
|
- `js/games/fill-the-blank.js` - Sentence completion (418 lines)
|
|
- `js/games/text-reader.js` - Guided text reading (366 lines)
|
|
- `js/games/adventure-reader.js` - RPG-style adventure (949 lines)
|
|
|
|
## Important Implementation Details
|
|
|
|
### Scoring System
|
|
- Games call `this.onScoreUpdate(score)` to update display
|
|
- Final scores saved to localStorage with key pattern: `score_{gameType}_{contentType}`
|
|
- Best scores tracked and displayed in game-end modal
|
|
- Points per correct answer, malus per error, speed bonus
|
|
- Score history and achievement badges
|
|
|
|
### Content Compatibility
|
|
- `ContentScanner` evaluates content compatibility with each game type
|
|
- Compatibility scoring helps recommend best content for each game
|
|
- Games should handle various content formats gracefully
|
|
|
|
### Memory Management
|
|
- `GameLoader.cleanup()` called before loading new games
|
|
- Games should implement `destroy()` method for proper cleanup
|
|
- Previous game instances must be cleaned up to prevent memory leaks
|
|
|
|
### Error Handling
|
|
- Content loading errors logged but don't crash the application
|
|
- Fallback mechanisms for missing content or games
|
|
- User-friendly error messages via `Utils.showToast()`
|
|
|
|
## Design Guidelines
|
|
|
|
### Visual Design Principles
|
|
- Modern, clean design optimized for children (8-9 years old)
|
|
- Large, tactile buttons (minimum 44px for touch interfaces)
|
|
- High contrast colors for accessibility
|
|
- Smooth, non-aggressive animations
|
|
- Emoji icons combined with text labels
|
|
|
|
### Color Palette
|
|
- **Primary**: Blue (#3B82F6) - Trust, learning
|
|
- **Secondary**: Green (#10B981) - Success, validation
|
|
- **Accent**: Orange (#F59E0B) - Energy, attention
|
|
- **Error**: Red (#EF4444) - Clear error indication
|
|
- **Neutral**: Gray (#6B7280) - Text, backgrounds
|
|
|
|
### Accessibility Features
|
|
- Full keyboard navigation support
|
|
- Alternative text for all images
|
|
- Adjustable font sizes
|
|
- High contrast mode compatibility
|
|
- Screen reader friendly markup
|
|
|
|
### Responsive Design
|
|
- Mobile/tablet adaptation
|
|
- Touch-friendly interface
|
|
- Portrait/landscape orientation support
|
|
- Fluid layouts that work on various screen sizes
|
|
- **Fixed Top Bar**: App title and network status always visible
|
|
- **Network Status**: Automatic hiding of status text on mobile devices
|
|
- **Content Margin**: Proper spacing to accommodate fixed header
|
|
|
|
## Git Configuration
|
|
|
|
### Repository
|
|
- **Remote**: Bitbucket repository at `AlexisTrouve/class-generator-system`
|
|
- **Port 443 Configuration**: Git is configured to use SSH over port 443 for network restrictions
|
|
- **Remote URL**: `ssh://git@altssh.bitbucket.org:443/AlexisTrouve/class-generator-system.git`
|
|
|
|
### SSH Configuration
|
|
To push to the repository through port 443, the following SSH configuration is required in `~/.ssh/config`:
|
|
```
|
|
Host altssh.bitbucket.org
|
|
HostName altssh.bitbucket.org
|
|
Port 443
|
|
User git
|
|
IdentityFile ~/.ssh/bitbucket_key
|
|
```
|
|
|
|
### Push Commands
|
|
- Standard push: `git push`
|
|
- Set upstream: `git push --set-upstream origin master`
|
|
|
|
## 🚨 **Developer Guidelines & Common Pitfalls**
|
|
|
|
**Critical information for future developers to avoid common mistakes and maintain code quality.**
|
|
|
|
### **🔥 Template Literals Syntax Errors**
|
|
|
|
**MOST COMMON BUG - Always check this first:**
|
|
|
|
```javascript
|
|
// ❌ FATAL ERROR - Will break entire module
|
|
styleSheet.textContent = \`css here\`; // Backslash = SyntaxError
|
|
|
|
// ✅ CORRECT
|
|
styleSheet.textContent = `css here`; // Backtick (grave accent)
|
|
```
|
|
|
|
**How to debug:**
|
|
```bash
|
|
# Test syntax before browser testing
|
|
node -c js/games/your-game.js
|
|
|
|
# Look for "Invalid or unexpected token" errors
|
|
# Usually points to template literal issues
|
|
```
|
|
|
|
### **🎮 Game Development Best Practices**
|
|
|
|
#### **Required Game Structure:**
|
|
```javascript
|
|
class NewGame {
|
|
constructor({ container, content, onScoreUpdate, onGameEnd }) {
|
|
this.injectCSS(); // CSS injection FIRST
|
|
this.extractContent(); // Content processing
|
|
this.init(); // UI initialization
|
|
}
|
|
|
|
start() {
|
|
// Separate start method - NOT in constructor
|
|
this.startGameLogic();
|
|
}
|
|
|
|
destroy() {
|
|
// Cleanup intervals, event listeners, injected CSS
|
|
this.cleanup();
|
|
}
|
|
}
|
|
|
|
// REQUIRED: Global module registration
|
|
window.GameModules = window.GameModules || {};
|
|
window.GameModules.NewGame = NewGame;
|
|
```
|
|
|
|
#### **CSS Architecture - Zero Tolerance Policy:**
|
|
|
|
```javascript
|
|
// ✅ CORRECT: Inject game-specific CSS
|
|
injectCSS() {
|
|
if (document.getElementById('my-game-styles')) return; // Prevent duplicates
|
|
|
|
const styleSheet = document.createElement('style');
|
|
styleSheet.id = 'my-game-styles';
|
|
styleSheet.textContent = `
|
|
.my-game-element { color: red; }
|
|
.falling-word { animation: myCustomAnimation 2s; }
|
|
`;
|
|
document.head.appendChild(styleSheet);
|
|
}
|
|
|
|
// ❌ FORBIDDEN: Modifying css/games.css for game-specific styles
|
|
// css/games.css should ONLY contain global reusable classes
|
|
```
|
|
|
|
### **🔍 Debug Templates for Quick Testing**
|
|
|
|
#### **Isolated Game Testing:**
|
|
```html
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head><meta charset="UTF-8"></head>
|
|
<body>
|
|
<div id="container" style="width:800px; height:600px; border:1px solid #ccc;"></div>
|
|
|
|
<script>
|
|
window.logSh = (msg, level) => console.log(`[${level}] ${msg}`);
|
|
window.Utils = { storage: { get: () => [], set: () => {} } };
|
|
window.GameModules = {};
|
|
window.ContentModules = {};
|
|
</script>
|
|
|
|
<script src="js/content/your-content.js"></script>
|
|
<script src="js/games/your-game.js"></script>
|
|
|
|
<script>
|
|
try {
|
|
const game = new window.GameModules.YourGame({
|
|
container: document.getElementById('container'),
|
|
content: window.ContentModules.YourContent,
|
|
onScoreUpdate: score => console.log('Score:', score),
|
|
onGameEnd: score => console.log('Game ended:', score)
|
|
});
|
|
if (game.start) game.start();
|
|
console.log('✅ Game loaded successfully!');
|
|
} catch (error) {
|
|
console.error('❌ Error:', error.message);
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
### **🌐 Interface Language Standards**
|
|
|
|
**All UI text must be in English:**
|
|
|
|
```javascript
|
|
// ✅ CORRECT
|
|
"Score: ${score}"
|
|
"Lives: ${lives}"
|
|
"Level Up!"
|
|
"Game Over"
|
|
"Back to Games"
|
|
|
|
// ❌ FORBIDDEN
|
|
"Score: ${score} points" // French
|
|
"Vies: ${lives}" // French
|
|
"Niveau supérieur!" // French
|
|
```
|
|
|
|
### **📋 Integration Checklist**
|
|
|
|
**Before committing any new game:**
|
|
|
|
- [ ] ✅ Syntax check: `node -c js/games/your-game.js`
|
|
- [ ] ✅ CSS injected via `injectCSS()` method
|
|
- [ ] ✅ No modifications to `css/games.css`
|
|
- [ ] ✅ Uses global classes: `.game-wrapper`, `.game-hud`, `.game-area`, `.answer-panel`
|
|
- [ ] ✅ GameLoader mapping added in `getModuleName()`
|
|
- [ ] ✅ Navigation config updated in `navigation.js`
|
|
- [ ] ✅ Constructor pattern followed exactly
|
|
- [ ] ✅ Module export at end of file
|
|
- [ ] ✅ English-only interface text
|
|
- [ ] ✅ Isolated test file created and working
|
|
|
|
### **⚡ Performance & Architecture Notes**
|
|
|
|
**Current System Architecture:**
|
|
- **CSS:** Global base classes + per-game injection
|
|
- **Content:** Auto-discovery + JSON/JS dual support
|
|
- **Navigation:** URL-based SPA with dynamic loading
|
|
- **Modules:** Dynamic import + backward compatibility
|
|
|
|
**Critical Files (DO NOT BREAK):**
|
|
- `js/core/game-loader.js` - Module name mapping
|
|
- `css/games.css` - Global CSS base (game-agnostic only)
|
|
- `js/core/navigation.js` - Game configuration and routing
|
|
|
|
### **🔧 Common Debugging Commands**
|
|
|
|
```bash
|
|
# Check file syntax
|
|
node -c js/games/your-game.js
|
|
|
|
# Check for non-ASCII characters (encoding issues)
|
|
grep -P '[^\x00-\x7F]' js/games/your-game.js
|
|
|
|
# Find template literal issues
|
|
grep -n "\\\`" js/games/your-game.js
|
|
|
|
# Test local server
|
|
python3 -m http.server 8000
|
|
# Then: http://localhost:8000/?page=play&game=your-game&content=available-content
|
|
```
|
|
|
|
### **🚀 Quick Win Tips**
|
|
|
|
1. **Copy working game structure** - Use existing games as templates
|
|
2. **Test isolated first** - Don't debug through the full app initially
|
|
3. **Check browser console** - JavaScript errors are usually obvious
|
|
4. **Verify content compatibility** - Make sure your content has the data your game needs
|
|
5. **Use global CSS classes** - Don't reinvent layout, build on existing structure
|
|
|
|
**Remember: Most bugs are simple syntax errors (especially template literals) or missing module registrations. Check these first!** 🎯
|
|
|
|
## 🤝 **Collaborative Development Best Practices**
|
|
|
|
**Critical lesson learned from real debugging sessions:**
|
|
|
|
### **✅ Always Test Before Committing**
|
|
|
|
**❌ BAD WORKFLOW:**
|
|
1. Write code
|
|
2. Immediately commit
|
|
3. Discover it doesn't work
|
|
4. Debug on committed broken code
|
|
|
|
**✅ GOOD WORKFLOW:**
|
|
1. Write code
|
|
2. **TEST THOROUGHLY**
|
|
3. If broken → debug cooperatively
|
|
4. When working → commit
|
|
|
|
### **🔍 Cooperative Debugging Method**
|
|
|
|
**When user reports: "ça marche pas" or "y'a pas de lettres":**
|
|
|
|
1. **Get specific symptoms** - Don't assume, ask exactly what they see
|
|
2. **Add targeted debug logs** - Console.log the exact variables in question
|
|
3. **Test together** - Have user run and report console output
|
|
4. **Analyze together** - Look at debug output to find root cause
|
|
5. **Fix precisely** - Target the exact issue, don't rewrite everything
|
|
|
|
**Real Example - Letter Discovery Issue:**
|
|
```javascript
|
|
// ❌ ASSUMPTION: "Letters not working, must rewrite everything"
|
|
|
|
// ✅ ACTUAL DEBUG:
|
|
console.log('🔍 DEBUG this.content.letters:', this.content.letters); // undefined
|
|
console.log('🔍 DEBUG this.content.rawContent?.letters:', this.content.rawContent?.letters); // {U: Array(4), V: Array(4), T: Array(4)}
|
|
|
|
// ✅ PRECISE FIX: Check both locations
|
|
const letters = this.content.letters || this.content.rawContent?.letters;
|
|
```
|
|
|
|
### **🎯 Key Principles**
|
|
|
|
- **Communication > Code** - Clear problem description saves hours
|
|
- **Debug logs > Assumptions** - Add console.log to see actual data
|
|
- **Test early, test often** - Don't tunnel vision on untested code
|
|
- **Pair debugging** - Two brains spot issues faster than one
|
|
- **Patience > Speed** - Taking time to understand beats rushing broken fixes
|
|
|
|
**"C'est mieux quand on prend notre temps en coop plutot que de tunnel vision !"** 🎯 |