Class_generator/Legacy/js/tools/ultra-modular-validator.js
StillHammer 38920cc858 Complete architectural rewrite with ultra-modular system
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>
2025-09-22 07:08:39 +08:00

393 lines
14 KiB
JavaScript

// === VALIDATEUR ET CONVERTISSEUR ULTRA-MODULAIRE ===
// Utilitaire pour valider et convertir les spécifications JSON ultra-modulaires
class UltraModularValidator {
constructor() {
this.jsonLoader = new JSONContentLoader();
this.contentScanner = new ContentScanner();
this.validationRules = this.initValidationRules();
}
initValidationRules() {
return {
// Champs obligatoires
required: ['id', 'name'],
// Champs recommandés pour une expérience optimale
recommended: ['description', 'difficulty_level', 'original_lang', 'user_lang', 'tags'],
// Types de contenu supportés
contentTypes: ['vocabulary', 'sentences', 'grammar', 'audio', 'dialogues', 'poems', 'culture', 'matching', 'fillInBlanks', 'corrections', 'comprehension'],
// Niveaux de difficulté valides
difficultyLevels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
// Langues supportées
supportedLanguages: ['english', 'french', 'spanish', 'german', 'chinese', 'japanese']
};
}
/**
* Valide une spécification JSON ultra-modulaire
*/
async validateSpecification(jsonContent) {
const validation = {
valid: true,
errors: [],
warnings: [],
suggestions: [],
score: 0,
capabilities: null,
compatibility: null
};
try {
// 1. Validation de structure de base
this.validateBasicStructure(jsonContent, validation);
// 2. Validation des métadonnées
this.validateMetadata(jsonContent, validation);
// 3. Validation du contenu éducatif
this.validateEducationalContent(jsonContent, validation);
// 4. Analyse des capacités
const capabilities = this.contentScanner.analyzeContentCapabilities(jsonContent);
validation.capabilities = capabilities;
// 5. Analyse de compatibilité des jeux
const compatibility = this.contentScanner.calculateGameCompatibility(capabilities);
validation.compatibility = compatibility;
// 6. Calcul du score de qualité
validation.score = this.calculateQualityScore(jsonContent, capabilities, compatibility);
// 7. Suggestions d'amélioration
this.generateSuggestions(jsonContent, capabilities, validation);
} catch (error) {
validation.valid = false;
validation.errors.push(`Erreur fatale de validation: ${error.message}`);
}
return validation;
}
/**
* Valide la structure de base du JSON
*/
validateBasicStructure(jsonContent, validation) {
// Vérifier les champs obligatoires
for (const field of this.validationRules.required) {
if (!jsonContent[field]) {
validation.errors.push(`Champ obligatoire manquant: ${field}`);
validation.valid = false;
}
}
// Vérifier les champs recommandés
for (const field of this.validationRules.recommended) {
if (!jsonContent[field]) {
validation.warnings.push(`Champ recommandé manquant: ${field}`);
}
}
// Valider l'ID
if (jsonContent.id && !/^[a-z0-9_]+$/.test(jsonContent.id)) {
validation.errors.push('ID invalide: utilisez uniquement lettres minuscules, chiffres et underscores');
validation.valid = false;
}
}
/**
* Valide les métadonnées
*/
validateMetadata(jsonContent, validation) {
// Valider le niveau de difficulté
if (jsonContent.difficulty_level && !this.validationRules.difficultyLevels.includes(jsonContent.difficulty_level)) {
validation.errors.push(`Niveau de difficulté invalide: ${jsonContent.difficulty_level}. Utilisez 1-10`);
validation.valid = false;
}
// Valider les langues
if (jsonContent.original_lang && !this.validationRules.supportedLanguages.includes(jsonContent.original_lang)) {
validation.warnings.push(`Langue d'origine non standard: ${jsonContent.original_lang}`);
}
if (jsonContent.user_lang && !this.validationRules.supportedLanguages.includes(jsonContent.user_lang)) {
validation.warnings.push(`Langue utilisateur non standard: ${jsonContent.user_lang}`);
}
// Valider les tags
if (jsonContent.tags && !Array.isArray(jsonContent.tags)) {
validation.errors.push('Les tags doivent être un tableau');
validation.valid = false;
}
// Valider les compétences couvertes
if (jsonContent.skills_covered && !Array.isArray(jsonContent.skills_covered)) {
validation.errors.push('Les compétences couvertes doivent être un tableau');
validation.valid = false;
}
}
/**
* Valide le contenu éducatif
*/
validateEducationalContent(jsonContent, validation) {
let contentFound = false;
// Vérifier qu'il y a au moins un type de contenu
for (const contentType of this.validationRules.contentTypes) {
if (jsonContent[contentType]) {
contentFound = true;
this.validateContentSection(contentType, jsonContent[contentType], validation);
}
}
if (!contentFound) {
validation.errors.push('Aucun contenu éducatif trouvé');
validation.valid = false;
}
}
/**
* Valide une section de contenu spécifique
*/
validateContentSection(contentType, content, validation) {
switch (contentType) {
case 'vocabulary':
this.validateVocabulary(content, validation);
break;
case 'matching':
this.validateMatching(content, validation);
break;
case 'fillInBlanks':
this.validateFillInBlanks(content, validation);
break;
// ... autres validations spécifiques
}
}
/**
* Valide la section vocabulaire (6 niveaux de complexité)
*/
validateVocabulary(vocabulary, validation) {
if (typeof vocabulary !== 'object') {
validation.errors.push('Le vocabulaire doit être un objet');
return;
}
const entries = Object.entries(vocabulary);
if (entries.length === 0) {
validation.warnings.push('Section vocabulaire vide');
return;
}
let maxDepth = 0;
for (const [word, definition] of entries) {
if (typeof definition === 'string') {
maxDepth = Math.max(maxDepth, 1);
} else if (typeof definition === 'object') {
maxDepth = Math.max(maxDepth, 2);
// Détecter les niveaux avancés
if (definition.examples || definition.grammar_notes) maxDepth = Math.max(maxDepth, 3);
if (definition.etymology || definition.word_family) maxDepth = Math.max(maxDepth, 4);
if (definition.cultural_significance) maxDepth = Math.max(maxDepth, 5);
if (definition.memory_techniques || definition.visual_associations) maxDepth = Math.max(maxDepth, 6);
} else {
validation.warnings.push(`Définition invalide pour "${word}": doit être une chaîne ou un objet`);
}
}
validation.suggestions.push(`Niveau de vocabulaire détecté: ${maxDepth}/6 - ${this.getVocabularyLevelDescription(maxDepth)}`);
}
/**
* Valide le système de matching multi-colonnes
*/
validateMatching(matching, validation) {
if (!Array.isArray(matching)) {
validation.errors.push('La section matching doit être un tableau');
return;
}
for (const exercise of matching) {
if (exercise.columns && Array.isArray(exercise.columns)) {
// Nouveau format multi-colonnes
if (exercise.columns.length < 2) {
validation.warnings.push('Exercise matching: au moins 2 colonnes recommandées');
}
if (!exercise.correct_matches || !Array.isArray(exercise.correct_matches)) {
validation.errors.push('Exercise matching: correct_matches requis pour format multi-colonnes');
}
} else if (exercise.leftColumn && exercise.rightColumn) {
// Format traditionnel
if (exercise.leftColumn.length !== exercise.rightColumn.length) {
validation.warnings.push('Exercise matching: colonnes de tailles différentes');
}
} else {
validation.errors.push('Exercise matching: format invalide (colonnes manquantes)');
}
}
}
/**
* Valide les exercices à trous
*/
validateFillInBlanks(fillInBlanks, validation) {
if (!Array.isArray(fillInBlanks)) {
validation.errors.push('La section fillInBlanks doit être un tableau');
return;
}
for (const exercise of fillInBlanks) {
if (!exercise.sentence) {
validation.errors.push('Exercise fillInBlanks: sentence requis');
continue;
}
if (!exercise.sentence.includes('___')) {
validation.warnings.push('Exercise fillInBlanks: aucun blank (___) trouvé dans la phrase');
}
if (exercise.type === 'open_ended') {
if (!exercise.aiPrompt && !exercise.acceptedAnswers) {
validation.errors.push('Exercise fillInBlanks open_ended: aiPrompt ou acceptedAnswers requis');
}
} else {
if (!exercise.options || !exercise.correctAnswer) {
validation.errors.push('Exercise fillInBlanks: options et correctAnswer requis');
}
}
}
}
/**
* Calcule un score de qualité (0-100)
*/
calculateQualityScore(jsonContent, capabilities, compatibility) {
let score = 0;
// Score de base (métadonnées complètes)
if (jsonContent.id) score += 5;
if (jsonContent.name) score += 5;
if (jsonContent.description) score += 5;
if (jsonContent.difficulty_level) score += 5;
if (jsonContent.original_lang && jsonContent.user_lang) score += 10;
if (jsonContent.tags && jsonContent.tags.length > 0) score += 5;
if (jsonContent.skills_covered && jsonContent.skills_covered.length > 0) score += 5;
// Score de contenu éducatif (40 points max)
if (capabilities.hasVocabulary) score += 10;
if (capabilities.hasGrammar) score += 5;
if (capabilities.hasSentences) score += 5;
if (capabilities.hasExercises) score += 10;
if (capabilities.hasAudioFiles) score += 5;
if (capabilities.hasCulture) score += 5;
// Bonus pour la richesse du contenu
score += Math.min(15, capabilities.vocabularyDepth * 2.5);
score += Math.min(10, capabilities.contentRichness);
// Bonus pour la compatibilité des jeux
const compatibleGames = Object.values(compatibility).filter(game => game.compatible).length;
score += Math.min(10, compatibleGames * 2);
return Math.round(Math.min(100, score));
}
/**
* Génère des suggestions d'amélioration
*/
generateSuggestions(jsonContent, capabilities, validation) {
// Suggestions basées sur les capacités manquantes
if (!capabilities.hasAudioFiles) {
validation.suggestions.push('Ajoutez des fichiers audio pour débloquer les jeux de prononciation');
}
if (!capabilities.hasExercises) {
validation.suggestions.push('Ajoutez des exercices (fillInBlanks, corrections) pour plus d\'interactivité');
}
if (!capabilities.hasCulture) {
validation.suggestions.push('Ajoutez du contenu culturel pour enrichir l\'apprentissage');
}
if (capabilities.vocabularyDepth < 3) {
validation.suggestions.push('Enrichissez le vocabulaire avec des exemples et notes grammaticales');
}
// Suggestions basées sur la compatibilité des jeux
const incompatibleGames = Object.entries(validation.compatibility)
.filter(([game, compat]) => !compat.compatible)
.map(([game]) => game);
if (incompatibleGames.length > 0) {
validation.suggestions.push(`Jeux non compatibles: ${incompatibleGames.join(', ')} - vérifiez les requis de contenu`);
}
}
/**
* Convertit une spécification ultra-modulaire vers le format legacy
*/
async convertToLegacy(jsonContent) {
const adaptedContent = this.jsonLoader.adapt(jsonContent);
// Générer un module JavaScript compatible
const jsModule = this.generateLegacyModule(adaptedContent);
return {
adaptedContent,
jsModule,
stats: this.jsonLoader.analyzeContent(adaptedContent)
};
}
/**
* Génère un module JavaScript pour compatibilité legacy
*/
generateLegacyModule(adaptedContent) {
const moduleName = this.toPascalCase(adaptedContent.id);
return `// Module généré automatiquement depuis la spécification ultra-modulaire
// ID: ${adaptedContent.id}
// Généré le: ${new Date().toISOString()}
window.ContentModules = window.ContentModules || {};
window.ContentModules.${moduleName} = ${JSON.stringify(adaptedContent, null, 4)};
console.log('📦 Module ${moduleName} chargé depuis spécification ultra-modulaire');`;
}
/**
* Helpers
*/
getVocabularyLevelDescription(level) {
const descriptions = {
1: 'Basique (chaînes simples)',
2: 'Standard (objets avec traduction)',
3: 'Enrichi (avec exemples)',
4: 'Avancé (avec étymologie)',
5: 'Expert (avec contexte culturel)',
6: 'Maître (avec techniques mnémotechniques)'
};
return descriptions[level] || 'Niveau inconnu';
}
toPascalCase(str) {
return str.split(/[_-]/).map(word =>
word.charAt(0).toUpperCase() + word.slice(1)
).join('');
}
}
// Export global
window.UltraModularValidator = UltraModularValidator;
// Export Node.js (optionnel)
if (typeof module !== 'undefined' && module.exports) {
module.exports = UltraModularValidator;
}