**Core Architecture:** - StrictInterface: Base class with visual error enforcement (red screen, sound, shake) - ProgressItemInterface: Strict contract requiring 4 methods (validate, serialize, getWeight, canComplete) - Implementation validation at startup - app refuses to start if methods missing **Progress Items (8 types with realistic weights):** - VocabularyDiscoveryItem (1pt) - Passive word exposure, no prerequisites - VocabularyMasteryItem (1pt) - Active flashcards, requires discovery - PhraseItem (6pts, 3x vocab) - Requires vocabulary mastery - DialogItem (12pts, 6x vocab) - Complex, requires vocabulary mastery - TextItem (15pts, 7.5x vocab) - Most complex, requires vocabulary mastery - AudioItem (12pts, 6x vocab) - Requires vocabulary mastery - ImageItem (6pts, 3x vocab) - Requires vocabulary discovered - GrammarItem (6pts, 3x vocab) - Requires vocabulary discovered **Realistic Progress Calculation:** - 1 vocab word = 2 points total (discovery + mastery) - Other items weighted 3x-7.5x heavier for realistic progression - Example: 171 vocab (342pts) + 75 phrases (450pts) + 6 dialogs (72pts) + 3 texts (45pts) = 909 total points - Discovering all words = 38% progress (not 76%) **Services:** - ContentProgressAnalyzer: Scans chapter content, creates progress items, calculates total weight - ProgressTracker: Manages state, tracks completion, saves progress to server - ImplementationValidator: Validates all implementations at startup **Integration:** - Application.js validates ALL item implementations before startup - Missing methods trigger full-screen red error with impossible-to-ignore UI - Sound alert + screen shake in dev mode **Pedagogical Flow Enforced:** Discovery (passive) → Mastery (active) → Application (context) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
67 lines
1.7 KiB
JavaScript
67 lines
1.7 KiB
JavaScript
/**
|
|
* VocabularyDiscoveryItem - Progress item for vocabulary discovery (passive exposure)
|
|
* Weight: 1 point
|
|
* Prerequisites: None
|
|
*/
|
|
|
|
import ProgressItemInterface from '../interfaces/ProgressItemInterface.js';
|
|
|
|
class VocabularyDiscoveryItem extends ProgressItemInterface {
|
|
constructor(word, data) {
|
|
super(
|
|
ProgressItemInterface.TYPES.VOCABULARY_DISCOVERY,
|
|
`vocab-discover-${word}`,
|
|
{ word, ...data }
|
|
);
|
|
this.word = word;
|
|
this.data = data;
|
|
}
|
|
|
|
/**
|
|
* Validate item data
|
|
* @override
|
|
*/
|
|
validate() {
|
|
if (!this.word || typeof this.word !== 'string') {
|
|
throw new Error(`VocabularyDiscoveryItem: Invalid word - ${this.word}`);
|
|
}
|
|
if (!this.data) {
|
|
throw new Error(`VocabularyDiscoveryItem: Missing data for word - ${this.word}`);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Serialize to JSON
|
|
* @override
|
|
*/
|
|
serialize() {
|
|
return {
|
|
...this._getBaseSerialization(),
|
|
word: this.word,
|
|
data: this.data
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Get item weight
|
|
* @override
|
|
*/
|
|
getWeight() {
|
|
return ProgressItemInterface.WEIGHTS['vocabulary-discovery'];
|
|
}
|
|
|
|
/**
|
|
* Check if can be completed (no prerequisites for discovery)
|
|
* @override
|
|
*/
|
|
canComplete(userProgress) {
|
|
// Discovery has no prerequisites - can always be completed
|
|
// But shouldn't be completed if already discovered
|
|
const discovered = userProgress.discoveredWords || [];
|
|
return !discovered.includes(this.word);
|
|
}
|
|
}
|
|
|
|
export default VocabularyDiscoveryItem;
|