Class_generator/test-reverse-conversion.html
StillHammer fe7153d28b Fix compatibility system and improve UX
- Add intelligent content-game compatibility system with visual badges
- Fix Adventure Reader to work with Dragon's Pearl content structure
- Implement multi-column games grid for faster navigation
- Add pronunciation display for Chinese vocabulary and sentences
- Fix navigation breadcrumb to show proper hierarchy (Home > Levels > Content)
- Add back buttons to all navigation pages
- Improve JSONContentLoader to preserve story structure
- Add comprehensive debugging and diagnostic tools

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-18 19:29:21 +08:00

457 lines
21 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🔄 Test: JS → JSON Ultra-Modulaire</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
background: #f5f5f5;
}
.test-section {
background: white;
padding: 20px;
margin: 10px 0;
border-radius: 8px;
border-left: 4px solid #3B82F6;
}
.success { border-left-color: #10B981; }
.error { border-left-color: #EF4444; }
pre {
background: #f8f9fa;
padding: 15px;
border-radius: 6px;
overflow-x: auto;
max-height: 500px;
font-size: 0.9rem;
line-height: 1.4;
}
.stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
margin: 15px 0;
}
.stat-card {
background: #f8f9fa;
padding: 15px;
border-radius: 6px;
text-align: center;
}
.stat-number {
font-size: 2rem;
font-weight: bold;
color: #3B82F6;
}
.btn {
background: #3B82F6;
color: white;
border: none;
padding: 10px 20px;
border-radius: 6px;
cursor: pointer;
margin: 10px 5px;
}
.btn:hover {
background: #2563eb;
}
.capabilities {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 10px;
margin: 15px 0;
}
.capability {
background: #f0fdf4;
border: 1px solid #16a34a;
padding: 8px 12px;
border-radius: 4px;
font-size: 0.9rem;
text-align: center;
}
</style>
</head>
<body>
<h1>🔄 Test: Conversion JS → JSON Ultra-Modulaire</h1>
<p>Démonstration complète du système : partir d'un module JS existant et générer un JSON ultra-modulaire</p>
<div id="results"></div>
<!-- Scripts -->
<script src="js/core/websocket-logger.js"></script>
<script src="js/core/env-config.js"></script>
<script src="js/core/utils.js"></script>
<script src="js/core/json-content-loader.js"></script>
<script src="js/core/content-scanner.js"></script>
<script src="js/tools/ultra-modular-validator.js"></script>
<script src="js/content/sbs-level-7-8-new.js"></script>
<script>
class ReverseConverter {
constructor() {
this.results = document.getElementById('results');
this.contentScanner = new ContentScanner();
this.validator = new UltraModularValidator();
}
addResult(title, content, type = 'info') {
const div = document.createElement('div');
div.className = `test-section ${type}`;
div.innerHTML = `<h3>${title}</h3>${content}`;
this.results.appendChild(div);
}
async runConversion() {
this.addResult('🚀 Démarrage de la conversion inverse', 'Conversion JS → JSON Ultra-Modulaire...');
try {
// 1. Récupérer le module JS chargé
const jsModule = window.ContentModules?.SBSLevel78New;
if (!jsModule) {
throw new Error('Module SBSLevel78New non trouvé - vérifiez le chargement du script');
}
this.addResult('✅ Module JS Chargé',
`<p>Module trouvé: <strong>SBSLevel78New</strong></p>
<p>Contient: ${Object.keys(jsModule).join(', ')}</p>`,
'success');
// 2. Analyser les capacités du module existant
const capabilities = this.contentScanner.analyzeContentCapabilities(jsModule);
const compatibility = this.contentScanner.calculateGameCompatibility(capabilities);
this.displayCapabilities(capabilities, compatibility);
// 3. Créer la spécification JSON ultra-modulaire
const ultraModularSpec = this.convertToUltraModular(jsModule, capabilities, compatibility);
this.addResult('🛠️ Spécification Ultra-Modulaire Générée',
`<p>Conversion réussie vers le format ultra-modulaire complet!</p>
<pre>${JSON.stringify(ultraModularSpec, null, 2)}</pre>`,
'success');
// 4. Valider la spécification générée
const validation = await this.validator.validateSpecification(ultraModularSpec);
this.addResult('🔍 Validation de la Spécification Générée',
`<p><strong>Score de Qualité:</strong> ${validation.score}/100</p>
<p><strong>Valide:</strong> ${validation.valid ? '✅ Oui' : '❌ Non'}</p>
<p><strong>Erreurs:</strong> ${validation.errors.length}</p>
<p><strong>Avertissements:</strong> ${validation.warnings.length}</p>
<p><strong>Suggestions:</strong> ${validation.suggestions.length}</p>`,
validation.valid ? 'success' : 'error');
// 5. Créer le fichier JSON
this.generateJSONFile(ultraModularSpec);
this.addResult('✅ Test Complet Réussi',
'<p>La conversion JS → JSON Ultra-Modulaire fonctionne parfaitement!</p>' +
'<button class="btn" onclick="downloadJSON()">📥 Télécharger le JSON</button>',
'success');
} catch (error) {
this.addResult('❌ Erreur de Conversion', `Erreur: ${error.message}`, 'error');
}
}
displayCapabilities(capabilities, compatibility) {
const activeCapabilities = Object.entries(capabilities)
.filter(([key, value]) => value === true || (typeof value === 'number' && value > 0))
.map(([key, value]) => typeof value === 'number' ? `${key}: ${value}` : key);
const compatibleGames = Object.entries(compatibility)
.filter(([game, compat]) => compat.compatible)
.map(([game, compat]) => `${game} (${compat.score}%)`);
this.addResult('📊 Analyse du Module JS',
`<div class="stats">
<div class="stat-card">
<div class="stat-number">${Object.keys(window.ContentModules.SBSLevel78New.vocabulary || {}).length}</div>
<div>Mots de vocabulaire</div>
</div>
<div class="stat-card">
<div class="stat-number">${capabilities.vocabularyDepth}</div>
<div>Profondeur vocab (1-6)</div>
</div>
<div class="stat-card">
<div class="stat-number">${compatibleGames.length}</div>
<div>Jeux compatibles</div>
</div>
<div class="stat-card">
<div class="stat-number">${capabilities.contentRichness.toFixed(1)}</div>
<div>Richesse contenu</div>
</div>
</div>
<h4>🎯 Capacités Détectées:</h4>
<div class="capabilities">
${activeCapabilities.map(cap => `<div class="capability">${cap}</div>`).join('')}
</div>
<h4>🎮 Jeux Compatibles:</h4>
<div class="capabilities">
${compatibleGames.map(game => `<div class="capability">${game}</div>`).join('')}
</div>`,
'success');
}
convertToUltraModular(jsModule, capabilities, compatibility) {
// Générer l'ID basé sur le nom du module
const moduleId = 'sbs_level_7_8_converted_from_js';
// Analyser le vocabulaire pour détecter la complexité
const vocabularyAnalysis = this.analyzeVocabularyComplexity(jsModule.vocabulary || {});
// Créer la spécification ultra-modulaire complète
const ultraModularSpec = {
// ========================================================================================================
// CORE METADATA SECTION
// ========================================================================================================
id: moduleId,
name: "SBS Level 7-8 (Converted from JS)",
description: "Comprehensive English learning content covering housing, clothing, and cultural topics - converted from legacy JavaScript format to ultra-modular specification",
// Difficulty system (1-10 scale)
difficulty_level: 6, // Intermediate level based on content analysis
// Language configuration (original_lang/user_lang pattern)
original_lang: "english",
user_lang: "chinese",
// Icon system with fallback
icon: {
primary: "🏠",
fallback: "📚",
emoji: "🏠"
},
// Enhanced metadata
tags: ["housing", "clothing", "daily_life", "vocabulary", "sbs_textbook", "intermediate"],
skills_covered: ["vocabulary_acquisition", "reading_comprehension", "cultural_awareness", "daily_communication"],
target_audience: {
age_range: [12, 16],
proficiency_level: "intermediate",
learning_goals: ["daily_vocabulary", "cultural_understanding"]
},
estimated_duration: 45,
pedagogical_approach: "communicative_language_teaching",
// ========================================================================================================
// VOCABULARY SECTION (Progressive Enhancement)
// ========================================================================================================
vocabulary: this.enhanceVocabulary(jsModule.vocabulary || {}, vocabularyAnalysis),
// ========================================================================================================
// SENTENCES SECTION
// ========================================================================================================
sentences: this.enhanceSentences(jsModule.sentences || []),
// ========================================================================================================
// METADATA AND ANALYTICS
// ========================================================================================================
content_analytics: {
vocabulary_count: Object.keys(jsModule.vocabulary || {}).length,
sentence_count: (jsModule.sentences || []).length,
difficulty_distribution: vocabularyAnalysis.difficultyDistribution,
topic_coverage: this.extractTopics(jsModule.vocabulary || {}),
converted_from: "legacy_javascript",
conversion_timestamp: new Date().toISOString(),
detected_capabilities: capabilities,
game_compatibility: compatibility
},
// ========================================================================================================
// SYSTEM METADATA
// ========================================================================================================
system_metadata: {
format_version: "2.0",
specification: "ultra_modular",
backwards_compatible: true,
generated_by: "reverse_converter",
validation_required: false
}
};
// Stocker globalement pour l'export
window.generatedUltraModularSpec = ultraModularSpec;
return ultraModularSpec;
}
analyzeVocabularyComplexity(vocabulary) {
const analysis = {
totalWords: Object.keys(vocabulary).length,
simpleTranslations: 0,
complexPhrases: 0,
categories: new Set(),
difficultyDistribution: { basic: 0, intermediate: 0, advanced: 0 }
};
for (const [word, translation] of Object.entries(vocabulary)) {
// Analyser la complexité
if (word.includes(' ') || word.includes('/')) {
analysis.complexPhrases++;
analysis.difficultyDistribution.intermediate++;
} else if (word.length > 10) {
analysis.difficultyDistribution.advanced++;
} else {
analysis.simpleTranslations++;
analysis.difficultyDistribution.basic++;
}
// Extraire les catégories
if (word.includes('shirt') || word.includes('coat') || word.includes('dress')) {
analysis.categories.add('clothing');
} else if (word.includes('building') || word.includes('apartment')) {
analysis.categories.add('housing');
} else if (word.includes('street') || word.includes('town')) {
analysis.categories.add('places');
}
}
analysis.categories = Array.from(analysis.categories);
return analysis;
}
enhanceVocabulary(originalVocab, analysis) {
const enhanced = {};
for (const [word, translation] of Object.entries(originalVocab)) {
// Créer des objets enrichis de niveau 2-3
enhanced[word] = {
user_language: translation,
original_language: word,
type: this.detectWordType(word),
// Ajouter des contextes spécifiques selon le type
usage_context: this.getUsageContext(word),
// Niveau de difficulté basé sur l'analyse
difficulty_level: this.getWordDifficulty(word),
// Catégorie sémantique
semantic_category: this.getSemanticCategory(word)
};
}
return enhanced;
}
enhanceSentences(originalSentences) {
return originalSentences.map((sentence, index) => ({
id: `sentence_${index + 1}`,
original_language: sentence.english,
user_language: sentence.chinese,
difficulty_level: sentence.english.split(' ').length > 8 ? 7 : 5,
grammatical_focus: this.detectGrammarFocus(sentence.english),
communicative_function: this.detectCommunicativeFunction(sentence.english),
cultural_context: this.detectCulturalContext(sentence.english)
}));
}
// Helper methods
detectWordType(word) {
if (word.endsWith('ing')) return 'verb_gerund';
if (word.endsWith('ed')) return 'verb_past';
if (word.includes(' ')) return 'phrase';
if (word.endsWith('s') && !word.endsWith('ss')) return 'noun_plural';
return 'noun';
}
getUsageContext(word) {
if (word.includes('apartment') || word.includes('building')) return 'housing_description';
if (word.includes('shirt') || word.includes('coat')) return 'clothing_description';
if (word.includes('street') || word.includes('town')) return 'location_description';
return 'general_communication';
}
getWordDifficulty(word) {
if (word.length <= 5) return 3;
if (word.length <= 8) return 5;
if (word.includes(' ') || word.includes('/')) return 6;
return 7;
}
getSemanticCategory(word) {
if (word.match(/shirt|coat|dress|pants|jacket|shoes/)) return 'clothing';
if (word.match(/building|apartment|house|room|elevator/)) return 'housing';
if (word.match(/street|town|center|avenue|sidewalk/)) return 'locations';
if (word.match(/noise|convenient|upset|central/)) return 'descriptive';
return 'general';
}
detectGrammarFocus(sentence) {
if (sentence.includes('is in') || sentence.includes('are in')) return 'location_prepositions';
if (sentence.includes("'s")) return 'possessive_case';
if (sentence.includes('There\'s') || sentence.includes('There are')) return 'existential_there';
return 'declarative_statement';
}
detectCommunicativeFunction(sentence) {
if (sentence.includes('?')) return 'questioning';
if (sentence.includes('!')) return 'exclamation';
if (sentence.toLowerCase().includes('please')) return 'request';
return 'description';
}
detectCulturalContext(sentence) {
if (sentence.includes('apartment building')) return 'urban_living';
if (sentence.includes('center of town')) return 'city_geography';
if (sentence.includes('noise')) return 'urban_challenges';
return 'daily_life';
}
extractTopics(vocabulary) {
const topics = new Set();
for (const word of Object.keys(vocabulary)) {
if (word.match(/shirt|coat|dress|pants|jacket|shoes|clothing/)) topics.add('clothing');
if (word.match(/building|apartment|house|room|elevator|housing/)) topics.add('housing');
if (word.match(/street|town|center|avenue|places/)) topics.add('places');
}
return Array.from(topics);
}
generateJSONFile(spec) {
// Créer le contenu JSON avec beautification
const jsonContent = JSON.stringify(spec, null, 2);
// Stocker pour le téléchargement
window.downloadableJSON = jsonContent;
this.addResult('📁 Fichier JSON Généré',
`<p>Fichier JSON ultra-modulaire créé avec succès!</p>
<p><strong>Taille:</strong> ${(jsonContent.length / 1024).toFixed(1)} KB</p>
<p><strong>Lignes:</strong> ${jsonContent.split('\\n').length}</p>
<button class="btn" onclick="downloadJSON()">📥 Télécharger JSON</button>
<button class="btn" onclick="copyToClipboard()">📋 Copier JSON</button>`);
}
}
// Fonctions globales
function downloadJSON() {
const content = window.downloadableJSON;
const blob = new Blob([content], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'sbs-level-7-8-ultra-modular.json';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
function copyToClipboard() {
navigator.clipboard.writeText(window.downloadableJSON).then(() => {
alert('JSON copié dans le presse-papier !');
});
}
// Démarrer le test
document.addEventListener('DOMContentLoaded', async function() {
const converter = new ReverseConverter();
await converter.runConversion();
});
</script>
</body>
</html>