Add comprehensive Chinese reading course (乐读) with 4 chapters of vocabulary, texts, and exercises. Include architecture documentation for module development and progress tracking system. Content: - LEDU book metadata with 12 chapter outline - Chapter 1: Food culture (民以食为天) - 45+ vocabulary, etiquette - Chapter 2: Shopping (货比三家) - comparative shopping vocabulary - Chapter 3: Sports & fitness (生命在于运动) - exercise habits - Chapter 4: Additional vocabulary and grammar Documentation: - Architecture principles and patterns - Module creation guide (Game, DRS, Progress) - Interface system (C++ style contracts) - Progress tracking and prerequisites Game Enhancements: - MarioEducational helper classes (Physics, Renderer, Sound, Enemies) - VocabularyModule TTS improvements - Updated CLAUDE.md with project status 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
6.4 KiB
Architecture Guide
🏗️ Core Principles
1. Single Responsibility
Each module has exactly one purpose. No mixing of concerns.
2. Event-Driven Communication
All inter-module communication happens through EventBus. Zero direct dependencies.
// ❌ BAD - Direct access
const gameManager = window.app.modules.gameManager;
gameManager.startGame();
// ✅ GOOD - EventBus
eventBus.emit('game:start', { difficulty: 'medium' });
3. Sealed Modules
Modules cannot be modified after creation using Object.seal().
constructor() {
super('ModuleName');
this._privateState = {};
Object.seal(this); // Prevents adding/removing properties
}
4. WeakMap Private State
Internal data is completely inaccessible from outside.
const privateData = new WeakMap();
class SecureModule {
constructor() {
privateData.set(this, {
apiKey: 'secret',
internalState: {}
});
}
getPrivateData() {
return privateData.get(this);
}
}
5. Dependency Injection
No globals. Everything injected through constructor.
class GameModule extends Module {
constructor(name, dependencies, config) {
super(name, ['eventBus', 'renderer']);
// Dependencies injected, not accessed globally
this._eventBus = dependencies.eventBus;
this._renderer = dependencies.renderer;
this._config = config;
}
}
🔄 Module Lifecycle
1. REGISTRATION → Application.js modules array
2. LOADING → ModuleLoader imports class
3. INSTANTIATION → new Module(name, deps, config)
4. INITIALIZATION → module.init() called
5. READY → Module emits 'ready' event
6. DESTRUCTION → module.destroy() on cleanup
📦 System Components
Core Layer (src/core/)
Module.js - Abstract base class
- WeakMap private state
- Lifecycle management (init/destroy)
- State validation
- Abstract enforcement
EventBus.js - Event communication
- Module registration required
- Event history tracking
- Cross-module isolation
- Memory leak prevention
ModuleLoader.js - Dependency injection
- Topological sort for dependencies
- Circular dependency detection
- Proper initialization order
- Dynamic import system
Router.js - Navigation system
- Route guards
- Middleware execution
- State management
- History integration
Application.js - Bootstrap system
- Auto-initialization
- Module registration
- Lifecycle coordination
- Debug panel
DRS Layer (src/DRS/)
Exercise Modules (exercise-modules/)
- VocabularyModule - Flashcard spaced repetition
- TextAnalysisModule - AI text comprehension
- GrammarAnalysisModule - AI grammar correction
- TranslationModule - AI translation validation
- OpenResponseModule - Free-form AI evaluation
Services (services/)
- IAEngine - Multi-provider AI system
- LLMValidator - Answer validation
- ContentLoader - Content generation
- ProgressTracker - Progress management
- PrerequisiteEngine - Prerequisite checking
Interfaces (interfaces/)
- StrictInterface - Base enforcement class
- ProgressItemInterface - Progress tracking contract
- ProgressSystemInterface - Progress system contract
- DRSExerciseInterface - Exercise module contract
Games Layer (src/games/)
Independent game modules for entertainment (NOT part of DRS).
- FlashcardLearning.js - Standalone flashcard game
- Future games...
🚫 Separation Rules
DRS vs Games - NEVER MIX
DRS = Educational exercises with strict interfaces Games = Entertainment with different architecture
// ❌ FORBIDDEN - DRS importing games
import FlashcardLearning from '../games/FlashcardLearning.js';
// ✅ CORRECT - DRS uses its own modules
import VocabularyModule from './exercise-modules/VocabularyModule.js';
🔒 Security Layers
- Object.seal() - Prevents property addition/deletion
- Object.freeze() - Prevents prototype modification
- WeakMap - Internal state hidden
- Abstract enforcement - Missing methods throw errors
- Validation at boundaries - All inputs validated
📊 Data Flow
User Action
↓
UI Component
↓
Event Emission (EventBus)
↓
Module Event Handler
↓
Business Logic
↓
State Update
↓
Event Emission (state changed)
↓
UI Update
🎯 Module Types
1. Core Modules
System-level functionality. Never modify these.
2. Game Modules
Entertainment-focused, extend Module base class.
3. DRS Exercise Modules
Educational exercises, implement DRSExerciseInterface.
4. Service Modules
Support functionality (AI, progress, content).
5. UI Components
Reusable interface elements (future phase).
⚡ Performance Targets
- <100ms module loading time
- <50ms event propagation time
- <200ms application startup time
- Zero memory leaks in module lifecycle
🧪 Testing Strategy
- Unit Tests - Individual module behavior
- Integration Tests - Module communication via EventBus
- Interface Tests - Contract compliance (ImplementationValidator)
- E2E Tests - Complete user flows
📋 Architecture Checklist
For every new feature:
- Single responsibility maintained
- EventBus for all communication
- No direct module dependencies
- Proper dependency injection
- Object.seal() applied
- Abstract methods implemented
- Lifecycle methods complete
- Memory cleanup in destroy()
- Interface compliance validated
- No global variables used
🔍 Debug Tools
// Application status
window.app.getStatus()
// Module inspection
window.app.getCore().moduleLoader.getStatus()
// Event history
window.app.getCore().eventBus.getEventHistory()
// Navigate programmatically
window.app.getCore().router.navigate('/path')
🚨 Common Violations
- Direct module access → Use EventBus
- Global variables → Use dependency injection
- Mixed responsibilities → Split into separate modules
- No cleanup → Implement destroy() properly
- Hardcoded dependencies → Declare in constructor
- Missing validation → Validate all inputs
- Modifying core → Extend, don't modify
📖 Further Reading
docs/creating-new-module.md- Module creation guidedocs/interfaces.md- Interface system detailsdocs/progress-system.md- Progress tracking guideREADME.md- Project overview