- 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>
332 lines
15 KiB
HTML
332 lines
15 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 Ultra-Modular JSON System</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; }
|
||
.warning { border-left-color: #F59E0B; }
|
||
pre {
|
||
background: #f8f9fa;
|
||
padding: 10px;
|
||
border-radius: 4px;
|
||
overflow-x: auto;
|
||
max-height: 300px;
|
||
}
|
||
.capabilities {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||
gap: 10px;
|
||
margin: 10px 0;
|
||
}
|
||
.capability {
|
||
background: #f8f9fa;
|
||
padding: 8px 12px;
|
||
border-radius: 4px;
|
||
border-left: 3px solid #10B981;
|
||
}
|
||
.compatibility {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||
gap: 10px;
|
||
}
|
||
.game-compat {
|
||
background: #f8f9fa;
|
||
padding: 10px;
|
||
border-radius: 4px;
|
||
}
|
||
.compatible { border-left: 3px solid #10B981; }
|
||
.incompatible { border-left: 3px solid #EF4444; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<h1>🧪 Test du Système Ultra-Modulaire</h1>
|
||
<p>Test de compatibilité avec les nouvelles spécifications JSON</p>
|
||
|
||
<div id="results"></div>
|
||
|
||
<!-- Scripts Core -->
|
||
<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>
|
||
class UltraModularTester {
|
||
constructor() {
|
||
this.results = document.getElementById('results');
|
||
this.jsonLoader = new JSONContentLoader();
|
||
this.contentScanner = new ContentScanner();
|
||
this.tests = [];
|
||
}
|
||
|
||
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 runTests() {
|
||
this.addResult('🚀 Démarrage des tests', 'Test du système de données ultra-modulaire...');
|
||
|
||
await this.testJSONLoader();
|
||
await this.testContentScanner();
|
||
await this.testCapabilityAnalysis();
|
||
await this.testGameCompatibility();
|
||
|
||
this.addResult('✅ Tests terminés', `${this.tests.length} tests exécutés avec succès`, 'success');
|
||
}
|
||
|
||
async testJSONLoader() {
|
||
try {
|
||
// Test de chargement du fichier ultra-commenté
|
||
const response = await fetch('english_exemple_ultra_commented.json');
|
||
const jsonContent = await response.json();
|
||
|
||
this.addResult('📋 Chargement JSON', 'Fichier ultra-commenté chargé avec succès', 'success');
|
||
|
||
// Test de l'adaptation
|
||
const adaptedContent = this.jsonLoader.adapt(jsonContent);
|
||
|
||
this.addResult('🔄 Adaptation JSON → Legacy',
|
||
`<p>Contenu adapté avec succès!</p>
|
||
<p><strong>ID:</strong> ${adaptedContent.id}</p>
|
||
<p><strong>Nom:</strong> ${adaptedContent.name}</p>
|
||
<p><strong>Difficulté:</strong> ${adaptedContent.difficulty} (niveau ${adaptedContent.difficulty_level})</p>
|
||
<p><strong>Langues:</strong> ${adaptedContent.original_lang} → ${adaptedContent.user_lang}</p>
|
||
<p><strong>Vocabulaire:</strong> ${Object.keys(adaptedContent.vocabulary || {}).length} mots</p>
|
||
<p><strong>Tags:</strong> ${(adaptedContent.tags || []).join(', ')}</p>`,
|
||
'success');
|
||
|
||
this.tests.push({ name: 'JSON Loader', status: 'success' });
|
||
return adaptedContent;
|
||
|
||
} catch (error) {
|
||
this.addResult('❌ Erreur JSON Loader', `Erreur: ${error.message}`, 'error');
|
||
this.tests.push({ name: 'JSON Loader', status: 'error', error: error.message });
|
||
return null;
|
||
}
|
||
}
|
||
|
||
async testContentScanner() {
|
||
try {
|
||
// Simuler un module de contenu ultra-modulaire
|
||
const mockModule = {
|
||
id: 'test_ultra_module',
|
||
name: 'Test Ultra Module',
|
||
difficulty_level: 7,
|
||
original_lang: 'english',
|
||
user_lang: 'french',
|
||
tags: ['advanced', 'grammar', 'culture'],
|
||
skills_covered: ['listening', 'speaking', 'cultural_awareness'],
|
||
vocabulary: {
|
||
'sophisticated': {
|
||
user_language: 'sophistiqué',
|
||
type: 'adjective',
|
||
ipa: '/səˈfɪstɪkeɪtɪd/',
|
||
audio_file: 'audio/sophisticated.mp3',
|
||
examples: ['She has sophisticated taste in art'],
|
||
etymology: 'From Latin sophisticatus',
|
||
cultural_significance: 'Often used in academic contexts',
|
||
memory_techniques: ['Visualize a person in elegant clothing']
|
||
}
|
||
},
|
||
grammar: {
|
||
subjunctive: {
|
||
title: 'Subjunctive Mood',
|
||
explanation: 'Used for hypothetical situations',
|
||
examples: [
|
||
{ english: 'If I were rich...', french: 'Si j\'étais riche...' }
|
||
]
|
||
}
|
||
},
|
||
culture: {
|
||
traditions: {
|
||
afternoon_tea: {
|
||
description: 'British afternoon tea tradition',
|
||
cultural_importance: 'High',
|
||
modern_relevance: 'Still practiced in formal settings'
|
||
}
|
||
}
|
||
},
|
||
matching: [
|
||
{
|
||
title: 'Multi-column Grammar Matching',
|
||
type: 'multi_column',
|
||
columns: [
|
||
{ id: 1, name: 'Subject', items: ['I', 'You', 'He'] },
|
||
{ id: 2, name: 'Verb', items: ['am', 'are', 'is'] },
|
||
{ id: 3, name: 'Complement', items: ['happy', 'tired', 'busy'] }
|
||
],
|
||
correct_matches: [
|
||
{ matches: [{ column: 1, item: 'I' }, { column: 2, item: 'am' }, { column: 3, item: 'happy' }] }
|
||
]
|
||
}
|
||
]
|
||
};
|
||
|
||
// Analyser les capacités
|
||
const capabilities = this.contentScanner.analyzeContentCapabilities(mockModule);
|
||
const compatibility = this.contentScanner.calculateGameCompatibility(capabilities);
|
||
|
||
this.addResult('🔍 Analyse des Capacités',
|
||
`<div class="capabilities">
|
||
${Object.entries(capabilities).map(([key, value]) => {
|
||
if (typeof value === 'boolean') {
|
||
return value ? `<div class="capability">✅ ${key}</div>` : '';
|
||
} else if (typeof value === 'number') {
|
||
return `<div class="capability">📊 ${key}: ${value}</div>`;
|
||
}
|
||
return '';
|
||
}).join('')}
|
||
</div>`,
|
||
'success');
|
||
|
||
this.addResult('🎮 Compatibilité des Jeux',
|
||
`<div class="compatibility">
|
||
${Object.entries(compatibility).map(([game, compat]) =>
|
||
`<div class="game-compat ${compat.compatible ? 'compatible' : 'incompatible'}">
|
||
<strong>${game}</strong><br>
|
||
Score: ${compat.score}%<br>
|
||
${compat.compatible ? '✅' : '❌'} ${compat.reason}
|
||
</div>`
|
||
).join('')}
|
||
</div>`,
|
||
'success');
|
||
|
||
this.tests.push({ name: 'Content Scanner', status: 'success' });
|
||
|
||
} catch (error) {
|
||
this.addResult('❌ Erreur Content Scanner', `Erreur: ${error.message}`, 'error');
|
||
this.tests.push({ name: 'Content Scanner', status: 'error', error: error.message });
|
||
}
|
||
}
|
||
|
||
async testCapabilityAnalysis() {
|
||
try {
|
||
// Test de l'analyse de profondeur du vocabulaire
|
||
const testVocab = {
|
||
// Niveau 1: string simple
|
||
'cat': 'chat',
|
||
// Niveau 2: objet de base
|
||
'dog': { user_language: 'chien', type: 'noun' },
|
||
// Niveau 3: avec exemples
|
||
'house': {
|
||
user_language: 'maison',
|
||
type: 'noun',
|
||
examples: ['I live in a big house'],
|
||
grammar_notes: 'Count noun'
|
||
},
|
||
// Niveau 6: tout inclus
|
||
'serendipity': {
|
||
user_language: 'sérendipité',
|
||
type: 'noun',
|
||
ipa: '/ˌsɛrənˈdɪpɪti/',
|
||
examples: ['What a wonderful serendipity!'],
|
||
grammar_notes: 'Abstract noun, uncountable',
|
||
etymology: 'Coined by Horace Walpole in 1754',
|
||
word_family: ['serendipitous', 'serendipitously'],
|
||
cultural_significance: 'Popular concept in Western philosophy',
|
||
memory_techniques: ['Think of happy accidents'],
|
||
visual_associations: ['Four-leaf clover', 'shooting star']
|
||
}
|
||
};
|
||
|
||
const depth = this.contentScanner.analyzeVocabularyDepth({ vocabulary: testVocab });
|
||
|
||
this.addResult('📊 Analyse de Profondeur',
|
||
`<p>Profondeur détectée: <strong>Niveau ${depth}/6</strong></p>
|
||
<p>Le système détecte correctement les 6 niveaux de complexité du vocabulaire.</p>
|
||
<pre>${JSON.stringify(testVocab, null, 2)}</pre>`,
|
||
'success');
|
||
|
||
this.tests.push({ name: 'Capability Analysis', status: 'success' });
|
||
|
||
} catch (error) {
|
||
this.addResult('❌ Erreur Analyse Capacités', `Erreur: ${error.message}`, 'error');
|
||
this.tests.push({ name: 'Capability Analysis', status: 'error', error: error.message });
|
||
}
|
||
}
|
||
|
||
async testGameCompatibility() {
|
||
try {
|
||
// Test des différents types de compatibilité
|
||
const testCases = [
|
||
{
|
||
name: 'Contenu Vocabulaire Riche',
|
||
capabilities: {
|
||
hasVocabulary: true,
|
||
hasAudioFiles: true,
|
||
vocabularyDepth: 4,
|
||
contentRichness: 8
|
||
}
|
||
},
|
||
{
|
||
name: 'Contenu Audio/Prononciation',
|
||
capabilities: {
|
||
hasVocabulary: true,
|
||
hasAudioFiles: true,
|
||
hasIPA: true,
|
||
vocabularyDepth: 3
|
||
}
|
||
},
|
||
{
|
||
name: 'Contenu Culturel',
|
||
capabilities: {
|
||
hasCulture: true,
|
||
hasPoems: true,
|
||
hasCulturalContext: true,
|
||
contentRichness: 6
|
||
}
|
||
}
|
||
];
|
||
|
||
for (const testCase of testCases) {
|
||
const compatibility = this.contentScanner.calculateGameCompatibility(testCase.capabilities);
|
||
|
||
this.addResult(`🎯 Test: ${testCase.name}`,
|
||
`<div class="compatibility">
|
||
${Object.entries(compatibility).map(([game, compat]) =>
|
||
`<div class="game-compat ${compat.compatible ? 'compatible' : 'incompatible'}">
|
||
<strong>${game}</strong><br>
|
||
Score: ${compat.score}%<br>
|
||
${compat.compatible ? '✅' : '❌'} ${compat.reason}
|
||
</div>`
|
||
).join('')}
|
||
</div>`,
|
||
'success');
|
||
}
|
||
|
||
this.tests.push({ name: 'Game Compatibility', status: 'success' });
|
||
|
||
} catch (error) {
|
||
this.addResult('❌ Erreur Compatibilité Jeux', `Erreur: ${error.message}`, 'error');
|
||
this.tests.push({ name: 'Game Compatibility', status: 'error', error: error.message });
|
||
}
|
||
}
|
||
}
|
||
|
||
// Démarrer les tests quand la page est chargée
|
||
document.addEventListener('DOMContentLoaded', async function() {
|
||
const tester = new UltraModularTester();
|
||
await tester.runTests();
|
||
});
|
||
</script>
|
||
</body>
|
||
</html> |