<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
background-color: white; /* Ensure the iframe has a white background */
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
.drag-item {
transition: transform 0.2s;
}
.drag-item:hover {
transform: scale(1.1);
}
.drop-zone:hover {
stroke: white !important;
}
.progress-circle {
transition: stroke-dashoffset 0.5s ease-out;
}
</style>
</head>
<body>
<!DOCTYPE html>
Pentagramme Homéopathique – Outil Didactique Interactif
<!-- Header -->
<div class="bg-white bg-opacity-10 backdrop-blur-md rounded-xl p-4 mb-4">
<div class="flex justify-between items-center">
<div>
<h1 class="text-2xl font-bold text-white mb-1">
Pentagramme Homéopathique - Outil Didactique Interactif
</h1>
<p id="modeDescription" class="text-blue-200 text-sm">
Glissez les ronds colorés vers leurs positions correctes
</p>
</div>
<div class="text-right">
<div class="text-white font-bold text-lg">
Progression globale: <span id="globalPercentage">0</span>%
</div>
<div class="text-blue-200 text-sm">
<span id="completedModes">0</span> modes terminés sur <span id="totalModes">10</span>
</div>
<div class="text-white font-bold text-lg mt-1">
Mode actuel: <span id="currentScore">0</span> / 5
</div>
<div id="completionMessage" class="text-green-300 text-sm" style="display: none;">
🎉 Mode complété !
</div>
</div>
</div>
</div>
<div class="flex flex-col h-[calc(100vh-140px)] gap-4">
<!-- Zone principale -->
<div class="flex-1 relative">
<!-- Pentagramme central -->
<div class="bg-white bg-opacity-5 backdrop-blur-md rounded-xl p-6 flex items-center justify-center h-full relative">
<svg id="pentagramme" width="600" height="500" viewBox="0 0 800 600" class="w-full h-full">
<!-- Cercle central -->
<circle cx="400" cy="300" r="190" fill="none" stroke="rgba(255,255,255,0.1)" stroke-width="1"/>
<!-- Lignes du pentagramme -->
<g id="pentagramLines"></g>
<!-- Zones de drop -->
<g id="dropZones"></g>
</svg>
<!-- Menu modes - gauche -->
<div class="absolute left-6 top-6 bg-white bg-opacity-15 backdrop-blur-md rounded-2xl p-4 shadow-2xl border border-white border-opacity-20">
<h3 class="text-white font-bold text-sm mb-3 text-center">
🎯 Modes (<span id="modesProgress">0/10</span> ✓)
</h3>
<div id="modesMenu" class="flex flex-col gap-2 max-h-80 overflow-y-auto">
<!-- Modes seront générés ici -->
</div>
</div>
<!-- Palette - droite -->
<div class="absolute right-6 top-1/2 transform -translate-y-1/2 bg-white bg-opacity-15 backdrop-blur-md rounded-2xl p-4 shadow-2xl border border-white border-opacity-20">
<h3 id="paletteTitle" class="text-white font-bold text-sm mb-4 text-center">
🎯 Éléments
</h3>
<div id="palette" class="space-y-3">
<!-- Items seront générés ici -->
</div>
<!-- Progression -->
<div class="mt-4 pt-3 border-t border-white border-opacity-20">
<div class="text-center text-white text-xs mb-2">
<span id="remainingItems">5</span> restants
</div>
<div class="bg-gray-700 rounded-full h-1.5">
<div id="localProgress" class="bg-green-400 rounded-full h-1.5 transition-all duration-500" style="width: 0%"></div>
</div>
</div>
<!-- Boutons d'actions -->
<div class="mt-4 pt-3 border-t border-white border-opacity-20 space-y-2">
<button id="resetMode" class="w-full bg-blue-500 hover:bg-blue-600 text-white px-3 py-2 rounded-lg transition-colors font-semibold text-xs">
🔄 Recommencer mode
</button>
<button id="resetAll" class="w-full bg-red-500 hover:bg-red-600 text-white px-3 py-2 rounded-lg transition-colors font-semibold text-xs" title="Efface toute la progression globale">
🗑️ Recommencer et effacer tout
</button>
</div>
</div>
<!-- Info bulle ronde - Progression globale -->
<div class="absolute bottom-6 right-6 w-20 h-20 bg-gradient-to-br from-blue-500 to-purple-600 rounded-full flex items-center justify-center shadow-2xl border-4 border-white border-opacity-30 backdrop-blur-md">
<div class="text-center">
<div id="bubblePercentage" class="text-white font-bold text-lg leading-none">0%</div>
<div class="text-blue-100 text-xs leading-none mt-1">
<span id="bubbleProgress">0/55</span>
</div>
</div>
<!-- Cercle de progression -->
<svg class="absolute inset-0 w-full h-full transform -rotate-90" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" stroke="rgba(255,255,255,0.2)" stroke-width="4" fill="none"/>
<circle id="progressCircle" cx="40" cy="40" r="34" stroke="rgba(255,255,255,0.8)" stroke-width="4" fill="none"
stroke-dasharray="213.63" stroke-dashoffset="213.63" class="progress-circle" stroke-linecap="round"/>
</svg>
</div>
</div>
</div>
<!-- Panneau inférieur -->
<div class="bg-white bg-opacity-10 backdrop-blur-md rounded-xl p-4">
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 items-center">
<!-- Légende -->
<div class="bg-black bg-opacity-20 rounded-lg p-3">
<h3 class="text-white font-bold mb-2 text-center text-sm">🎨 Légende</h3>
<div class="grid grid-cols-5 gap-1">
<div class="text-center">
<div class="w-6 h-6 rounded-full flex items-center justify-center mx-auto mb-1" style="background-color: #FF4444;">
<span class="text-xs">🔥</span>
</div>
<span class="text-white text-xs">FEU</span>
</div>
<div class="text-center">
<div class="w-6 h-6 rounded-full flex items-center justify-center mx-auto mb-1" style="background-color: #FFD700;">
<span class="text-xs">🌍</span>
</div>
<span class="text-white text-xs">TERRE</span>
</div>
<div class="text-center">
<div class="w-6 h-6 rounded-full flex items-center justify-center mx-auto mb-1" style="background-color: #C0C0C0;">
<span class="text-xs">⚪</span>
</div>
<span class="text-white text-xs">MÉTAL</span>
</div>
<div class="text-center">
<div class="w-6 h-6 rounded-full flex items-center justify-center mx-auto mb-1" style="background-color: #4169E1;">
<span class="text-xs">💧</span>
</div>
<span class="text-white text-xs">EAU</span>
</div>
<div class="text-center">
<div class="w-6 h-6 rounded-full flex items-center justify-center mx-auto mb-1" style="background-color: #228B22;">
<span class="text-xs">🌱</span>
</div>
<span class="text-white text-xs">BOIS</span>
</div>
</div>
</div>
<!-- Score et progression globale -->
<div class="text-center">
<div class="text-white font-bold text-xl mb-1">
Progression globale: <span id="mainPercentage">0</span>%
</div>
<div class="text-blue-200 text-sm mb-2">
<span id="mainProgress">0</span> / <span id="mainTotal">50</span> éléments
</div>
<div class="bg-gray-700 rounded-full h-2 mt-2">
<div id="mainProgressBar" class="bg-green-500 rounded-full h-2 transition-all duration-500" style="width: 0%"></div>
</div>
<div class="text-white text-sm mt-1">
Mode actuel: <span id="bottomScore">0</span> / 5
</div>
</div>
<!-- Boutons -->
<div class="flex justify-center">
<button id="checkAnswers" class="bg-green-500 hover:bg-green-600 text-white px-6 py-3 rounded-lg transition-colors font-semibold text-lg" disabled>
✅ Vérifier les réponses
</button>
</div>
</div>
</div>
</div>
<script>
// State management
let currentMode = 'elements';
let placedElements = {};
let score = 0;
let showAnswer = false;
let globalProgress = {};
let draggedItem = null;
// Configuration
const centerX = 400;
const centerY = 300;
const radius = 160;
// Positions des pôles
const polePositions = {
FEU: { x: centerX, y: centerY - radius, angle: -90 },
TERRE: { x: centerX + radius * Math.cos(18 * Math.PI / 180), y: centerY - radius * Math.sin(18 * Math.PI / 180), angle: 18 },
METAL: { x: centerX + radius * Math.cos(-54 * Math.PI / 180), y: centerY - radius * Math.sin(-54 * Math.PI / 180), angle: -54 },
EAU: { x: centerX - radius * Math.cos(-54 * Math.PI / 180), y: centerY - radius * Math.sin(-54 * Math.PI / 180), angle: -126 },
BOIS: { x: centerX - radius * Math.cos(18 * Math.PI / 180), y: centerY - radius * Math.sin(18 * Math.PI / 180), angle: 162 }
};
// Base de données
const elementsData = {
FEU: {
nom: 'FEU', couleur: '#FF4444', emoji: '🔥',
organe: 'Cœur', viscere: 'Intestin Grêle', diathese: 'SYCOSE',
patronRemede: 'KALIUM', systemeHormonal: 'Thyroïde',
emotionEquilibree: 'Joie', emotionPathologique: 'Surexcitation',
tissus: 'Vaisseaux', dynamiquePathologique: 'Vide Sang'
},
TERRE: {
nom: 'TERRE', couleur: '#FFD700', emoji: '🌍',
organe: 'Rate', viscere: 'Estomac', diathese: 'ADAPTATION',
patronRemede: 'MERCURIUS', systemeHormonal: 'Hypophyse/Cortex',
emotionEquilibree: 'Réflexion', emotionPathologique: 'Rumination',
tissus: 'Chair/Tissu conjonctif', dynamiquePathologique: 'Humidité-Glaires'
},
METAL: {
nom: 'MÉTAL', couleur: '#C0C0C0', emoji: '⚪',
organe: 'Poumon', viscere: 'Gros Intestin', diathese: 'TUBERCULINISME',
patronRemede: 'PHOSPHORUS', systemeHormonal: 'Cortex surrénalien',
emotionEquilibree: 'Intégrité', emotionPathologique: 'Tristesse',
tissus: 'Peau/Poils', dynamiquePathologique: 'Vide de Wei Qi'
},
EAU: {
nom: 'EAU', couleur: '#4169E1', emoji: '💧',
organe: 'Rein', viscere: 'Vessie', diathese: 'LUÈSE',
patronRemede: 'AURUM', systemeHormonal: 'Oestrogène/sous-cortex/Thymus',
emotionEquilibree: 'Volonté', emotionPathologique: 'Peur',
tissus: 'Os/Moelles', dynamiquePathologique: 'Vide de Jing'
},
BOIS: {
nom: 'BOIS', couleur: '#228B22', emoji: '🌱',
organe: 'Foie', viscere: 'Vésicule Biliaire', diathese: 'PSORE',
patronRemede: 'SULFUR', systemeHormonal: 'Androgènes',
emotionEquilibree: 'Bienveillance', emotionPathologique: 'Colère',
tissus: 'Tendons/Muscles', dynamiquePathologique: 'Stagnation du Qi'
}
};
const modesData = {
elements: {
name: 'Éléments', emoji: '🔥',
items: ['FEU', 'TERRE', 'METAL', 'EAU', 'BOIS'],
desc: 'Glissez les ronds colorés vers leurs positions correctes'
},
organes: {
name: 'Organes', emoji: '🫀',
items: ['Cœur', 'Rate', 'Poumon', 'Rein', 'Foie'],
desc: 'Placez les organes dans leurs éléments correspondants'
},
visceres: {
name: 'Viscères', emoji: '🍃',
items: ['Intestin Grêle', 'Estomac', 'Gros Intestin', 'Vessie', 'Vésicule Biliaire'],
desc: 'Placez les viscères dans leurs éléments correspondants'
},
diatheses: {
name: 'Diathèses', emoji: '🧬',
items: ['SYCOSE', 'ADAPTATION', 'TUBERCULINISME', 'LUÈSE', 'PSORE'],
desc: 'Placez les diathèses dans leurs éléments correspondants'
},
patronsRemedes: {
name: 'Patrons remèdes', emoji: '💊',
items: ['KALIUM', 'MERCURIUS', 'PHOSPHORUS', 'AURUM', 'SULFUR'],
desc: 'Placez les patrons remèdes dans leurs éléments correspondants'
},
systemesHormonaux: {
name: 'Systèmes hormonaux', emoji: '🧪',
items: ['Thyroïde', 'Hypophyse/Cortex', 'Cortex surrénalien', 'Oestrogène/sous-cortex/Thymus', 'Androgènes'],
desc: 'Placez les systèmes hormonaux dans leurs éléments correspondants'
},
emotionsEquilibrees: {
name: 'Émotions équilibrées', emoji: '😊',
items: ['Joie', 'Réflexion', 'Intégrité', 'Volonté', 'Bienveillance'],
desc: 'Placez les émotions équilibrées dans leurs éléments correspondants'
},
emotionsPathologiques: {
name: 'Émotions pathologiques', emoji: '😰',
items: ['Surexcitation', 'Rumination', 'Tristesse', 'Peur', 'Colère'],
desc: 'Placez les émotions pathologiques dans leurs éléments correspondants'
},
tissus: {
name: 'Tissus', emoji: '🦴',
items: ['Vaisseaux', 'Chair/Tissu conjonctif', 'Peau/Poils', 'Os/Moelles', 'Tendons/Muscles'],
desc: 'Placez les tissus dans leurs éléments correspondants'
},
dynamiquesPathologiques: {
name: 'Dynamiques pathologiques', emoji: '⚡',
items: ['Vide Sang', 'Humidité-Glaires', 'Vide de Wei Qi', 'Vide de Jing', 'Stagnation du Qi'],
desc: 'Placez les dynamiques pathologiques dans leurs éléments correspondants'
}
};
// Fonctions utilitaires
function calculateGlobalProgress() {
const totalModes = Object.keys(modesData).length;
const completedModes = Object.keys(globalProgress).filter(mode => globalProgress[mode] === 5).length;
const totalElements = totalModes * 5;
const completedElements = Object.values(globalProgress).reduce((sum, score) => sum + (score || 0), 0);
return {
percentage: Math.round((completedElements / totalElements) * 100),
completed: completedElements,
total: totalElements,
modesCompleted: completedModes,
totalModes: totalModes
};
}
function getAvailableItems() {
const usedItems = Object.values(placedElements);
return modesData[currentMode].items.filter(item => !usedItems.includes(item));
}
function isCorrect(position, item) {
if (currentMode === 'elements') return item === position;
if (currentMode === 'organes') return item === elementsData[position].organe;
if (currentMode === 'visceres') return item === elementsData[position].viscere;
if (currentMode === 'diatheses') return item === elementsData[position].diathese;
if (currentMode === 'patronsRemedes') return item === elementsData[position].patronRemede;
if (currentMode === 'systemesHormonaux') return item === elementsData[position].systemeHormonal;
if (currentMode === 'emotionsEquilibrees') return item === elementsData[position].emotionEquilibree;
if (currentMode === 'emotionsPathologiques') return item === elementsData[position].emotionPathologique;
if (currentMode === 'tissus') return item === elementsData[position].tissus;
if (currentMode === 'dynamiquesPathologiques') return item === elementsData[position].dynamiquePathologique;
return false;
}
// Fonctions de rendu
function renderPentagramLines() {
const lines = [
[[polePositions.FEU.x, polePositions.FEU.y], [polePositions.METAL.x, polePositions.METAL.y]],
[[polePositions.METAL.x, polePositions.METAL.y], [polePositions.BOIS.x, polePositions.BOIS.y]],
[[polePositions.BOIS.x, polePositions.BOIS.y], [polePositions.TERRE.x, polePositions.TERRE.y]],
[[polePositions.TERRE.x, polePositions.TERRE.y], [polePositions.EAU.x, polePositions.EAU.y]],
[[polePositions.EAU.x, polePositions.EAU.y], [polePositions.FEU.x, polePositions.FEU.y]]
];
const container = document.getElementById('pentagramLines');
container.innerHTML = '';
lines.forEach((line, index) => {
const lineEl = document.createElementNS('http://www.w3.org/2000/svg', 'line');
lineEl.setAttribute('x1', line[0][0]);
lineEl.setAttribute('y1', line[0][1]);
lineEl.setAttribute('x2', line[1][0]);
lineEl.setAttribute('y2', line[1][1]);
lineEl.setAttribute('stroke', 'rgba(255,255,255,0.3)');
lineEl.setAttribute('stroke-width', '2');
container.appendChild(lineEl);
});
}
function renderDropZones() {
const container = document.getElementById('dropZones');
container.innerHTML = '';
Object.entries(polePositions).forEach(([position, pos]) => {
// Zone de drop
const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
circle.setAttribute('cx', pos.x);
circle.setAttribute('cy', pos.y);
circle.setAttribute('r', '40');
circle.setAttribute('fill', placedElements[position] ? 'rgba(255,255,255,0.1)' : 'transparent');
circle.setAttribute('stroke', 'rgba(255,255,255,0.4)');
circle.setAttribute('stroke-width', '2');
circle.setAttribute('stroke-dasharray', placedElements[position] ? '0' : '8,4');
circle.classList.add('drop-zone', 'cursor-pointer');
// Drag & Drop
circle.addEventListener('dragover', (e) => {
e.preventDefault();
e.dataTransfer.dropEffect = 'move';
});
circle.addEventListener('drop', (e) => {
e.preventDefault();
if (draggedItem) {
placedElements[position] = draggedItem;
draggedItem = null;
updateDisplay();
}
});
container.appendChild(circle);
// Élément placé
if (placedElements[position]) {
if (currentMode === 'elements') {
const placedCircle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
placedCircle.setAttribute('cx', pos.x);
placedCircle.setAttribute('cy', pos.y);
placedCircle.setAttribute('r', '25');
placedCircle.setAttribute('fill', elementsData[placedElements[position]]?.couleur || '#666');
placedCircle.setAttribute('stroke', 'white');
placedCircle.setAttribute('stroke-width', '3');
placedCircle.style.pointerEvents = 'none';
container.appendChild(placedCircle);
const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
text.setAttribute('x', pos.x);
text.setAttribute('y', pos.y + 3);
text.setAttribute('text-anchor', 'middle');
text.setAttribute('font-size', '20');
text.setAttribute('fill', 'white');
text.setAttribute('font-weight', 'bold');
text.style.pointerEvents = 'none';
text.textContent = elementsData[placedElements[position]]?.emoji || '';
container.appendChild(text);
} else {
const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
rect.setAttribute('x', pos.x - 35);
rect.setAttribute('y', pos.y - 20);
rect.setAttribute('width', '70');
rect.setAttribute('height', '40');
rect.setAttribute('rx', '15');
rect.setAttribute('fill', 'rgba(255,255,255,0.9)');
rect.setAttribute('stroke', elementsData[position]?.couleur || '#666');
rect.setAttribute('stroke-width', '3');
rect.style.pointerEvents = 'none';
container.appendChild(rect);
const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
text.setAttribute('x', pos.x);
text.setAttribute('y', pos.y + 3);
text.setAttribute('text-anchor', 'middle');
text.setAttribute('font-size', '10');
text.setAttribute('fill', '#333');
text.setAttribute('font-weight', 'bold');
text.style.pointerEvents = 'none';
text.textContent = placedElements[position];
container.appendChild(text);
}
}
// Correction
if (showAnswer) {
const correctionCircle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
correctionCircle.setAttribute('cx', pos.x + 30);
correctionCircle.setAttribute('cy', pos.y - 30);
correctionCircle.setAttribute('r', '12');
correctionCircle.setAttribute('fill', isCorrect(position, placedElements[position]) ? '#10b981' : '#ef4444');
correctionCircle.setAttribute('stroke', 'white');
correctionCircle.setAttribute('stroke-width', '2');
container.appendChild(correctionCircle);
const correctionText = document.createElementNS('http://www.w3.org/2000/svg', 'text');
correctionText.setAttribute('x', pos.x + 30);
correctionText.setAttribute('y', pos.y - 25);
correctionText.setAttribute('text-anchor', 'middle');
correctionText.setAttribute('fill', 'white');
correctionText.setAttribute('font-weight', 'bold');
correctionText.style.fontSize = '14px';
correctionText.style.pointerEvents = 'none';
correctionText.textContent = isCorrect(position, placedElements[position]) ? '✓' : '✗';
container.appendChild(correctionText);
}
});
}
function renderModesMenu() {
const container = document.getElementById('modesMenu');
container.innerHTML = '';
Object.entries(modesData).forEach(([key, mode]) => {
const modeScore = globalProgress[key] || 0;
const isCompleted = modeScore === 5;
const button = document.createElement('button');
button.className = `px-3 py-2 rounded-lg transition-all text-xs w-full relative ${
currentMode === key
? 'bg-blue-500 text-white'
: 'bg-white bg-opacity-20 text-blue-200 hover:bg-opacity-30'
}`;
button.innerHTML = `
<div class="flex items-center justify-between">
<span>${mode.emoji} ${mode.name}</span>
<div class="flex items-center gap-1">
<span class="text-xs">${modeScore}/5</span>
${isCompleted ? '<span class="text-green-300">✓</span>' : ''}
</div>
</div>
<div class="w-full bg-gray-600 rounded-full h-1 mt-1">
<div class="${isCompleted ? 'bg-green-400' : 'bg-yellow-400'} h-1 rounded-full transition-all duration-300"
style="width: ${(modeScore / 5) * 100}%"></div>
</div>
`;
button.addEventListener('click', () => changeMode(key));
container.appendChild(button);
});
}
function renderPalette() {
const container = document.getElementById('palette');
container.innerHTML = '';
const availableItems = getAvailableItems();
availableItems.forEach((item, index) => {
const div = document.createElement('div');
div.className = 'cursor-move drag-item shadow-lg border-2 border-white border-opacity-50 flex items-center justify-center mx-auto';
div.draggable = true;
div.title = item;
if (currentMode === 'elements') {
div.style.backgroundColor = elementsData[item]?.couleur || '#666';
div.style.width = '56px';
div.style.height = '56px';
div.style.borderRadius = '50%';
div.innerHTML = `<span class="text-xl">${elementsData[item]?.emoji}</span>`;
} else {
div.style.backgroundColor = 'rgba(255,255,255,0.9)';
div.style.borderColor = 'rgba(255,255,255,0.5)';
div.style.width = '140px';
div.style.height = '50px';
div.style.borderRadius = '20px';
div.innerHTML = `<span class="text-xs font-bold text-gray-800 text-center px-2 leading-tight">${item}</span>`;
}
div.addEventListener('dragstart', (e) => {
draggedItem = item;
e.dataTransfer.effectAllowed = 'move';
});
container.appendChild(div);
});
}
function updateDisplay() {
const globalProgressData = calculateGlobalProgress();
// Header
document.getElementById('modeDescription').textContent = modesData[currentMode].desc;
document.getElementById('globalPercentage').textContent = globalProgressData.percentage;
document.getElementById('completedModes').textContent = globalProgressData.modesCompleted;
document.getElementById('totalModes').textContent = globalProgressData.totalModes;
document.getElementById('currentScore').textContent = score;
document.getElementById('completionMessage').style.display = (score === 5 && showAnswer) ? 'block' : 'none';
// Menu modes
document.getElementById('modesProgress').textContent = `${globalProgressData.modesCompleted}/${globalProgressData.totalModes}`;
// Palette
document.getElementById('paletteTitle').innerHTML = `🎯 ${modesData[currentMode].name}`;
document.getElementById('remainingItems').textContent = 5 - Object.keys(placedElements).length;
document.getElementById('localProgress').style.width = `${(Object.keys(placedElements).length / 5) * 100}%`;
// Bulle
document.getElementById('bubblePercentage').textContent = `${globalProgressData.percentage}%`;
document.getElementById('bubbleProgress').textContent = `${globalProgressData.completed}/${globalProgressData.total}`;
const circumference = 2 * Math.PI * 34;
const offset = circumference * (1 - (globalProgressData.percentage / 100));
document.getElementById('progressCircle').style.strokeDashoffset = offset;
// Panneau inférieur
document.getElementById('mainPercentage').textContent = globalProgressData.percentage;
document.getElementById('mainProgress').textContent = globalProgressData.completed;
document.getElementById('mainTotal').textContent = globalProgressData.total;
document.getElementById('mainProgressBar').style.width = `${globalProgressData.percentage}%`;
document.getElementById('bottomScore').textContent = score;
// Bouton vérifier
document.getElementById('checkAnswers').disabled = Object.keys(placedElements).length === 0;
// Re-render components
renderDropZones();
renderModesMenu();
renderPalette();
}
// Actions
function checkAnswers() {
let correct = 0;
Object.entries(placedElements).forEach(([position, item]) => {
if (isCorrect(position, item)) correct++;
});
score = correct;
showAnswer = true;
globalProgress[currentMode] = correct;
updateDisplay();
}
function resetMode() {
placedElements = {};
showAnswer = false;
score = globalProgress[currentMode] || 0;
updateDisplay();
}
function resetAll() {
globalProgress = {};
placedElements = {};
showAnswer = false;
score = 0;
updateDisplay();
}
function changeMode(newMode) {
currentMode = newMode;
placedElements = {};
showAnswer = false;
score = globalProgress[newMode] || 0;
updateDisplay();
}
// Event listeners
document.getElementById('checkAnswers').addEventListener('click', checkAnswers);
document.getElementById('resetMode').addEventListener('click', resetMode);
document.getElementById('resetAll').addEventListener('click', resetAll);
// Initialisation
function init() {
renderPentagramLines();
updateDisplay();
}
// Démarrer l'application
init();
</script>
<script>
// State management
let currentMode = 'elements';
let placedElements = {};
let score = 0;
let showAnswer = false;
let globalProgress = {};
let draggedItem = null;
// Configuration
const centerX = 400;
const centerY = 300;
const radius = 160;
// Positions des pôles
const polePositions = {
FEU: { x: centerX, y: centerY - radius, angle: -90 },
TERRE: { x: centerX + radius * Math.cos(18 * Math.PI / 180), y: centerY - radius * Math.sin(18 * Math.PI / 180), angle: 18 },
METAL: { x: centerX + radius * Math.cos(-54 * Math.PI / 180), y: centerY - radius * Math.sin(-54 * Math.PI / 180), angle: -54 },
EAU: { x: centerX - radius * Math.cos(-54 * Math.PI / 180), y: centerY - radius * Math.sin(-54 * Math.PI / 180), angle: -126 },
BOIS: { x: centerX - radius * Math.cos(18 * Math.PI / 180), y: centerY - radius * Math.sin(18 * Math.PI / 180), angle: 162 }
};
// Base de données
const elementsData = {
FEU: {
nom: 'FEU', couleur: '#FF4444', emoji: '🔥',
organe: 'Cœur', viscere: 'Intestin Grêle', diathese: 'SYCOSE',
patronRemede: 'KALIUM', systemeHormonal: 'Thyroïde',
emotionEquilibree: 'Joie', emotionPathologique: 'Surexcitation',
tissus: 'Vaisseaux', dynamiquePathologique: 'Vide Sang'
},
TERRE: {
nom: 'TERRE', couleur: '#FFD700', emoji: '🌍',
organe: 'Rate', viscere: 'Estomac', diathese: 'ADAPTATION',
patronRemede: 'MERCURIUS', systemeHormonal: 'Hypophyse/Cortex',
emotionEquilibree: 'Réflexion', emotionPathologique: 'Rumination',
tissus: 'Chair/Tissu conjonctif', dynamiquePathologique: 'Humidité-Glaires'
},
METAL: {
nom: 'MÉTAL', couleur: '#C0C0C0', emoji: '⚪',
organe: 'Poumon', viscere: 'Gros Intestin', diathese: 'TUBERCULINISME',
patronRemede: 'PHOSPHORUS', systemeHormonal: 'Cortex surrénalien',
emotionEquilibree: 'Intégrité', emotionPathologique: 'Tristesse',
tissus: 'Peau/Poils', dynamiquePathologique: 'Vide de Wei Qi'
},
EAU: {
nom: 'EAU', couleur: '#4169E1', emoji: '💧',
organe: 'Rein', viscere: 'Vessie', diathese: 'LUÈSE',
patronRemede: 'AURUM', systemeHormonal: 'Oestrogène/sous-cortex/Thymus',
emotionEquilibree: 'Volonté', emotionPathologique: 'Peur',
tissus: 'Os/Moelles', dynamiquePathologique: 'Vide de Jing'
},
BOIS: {
nom: 'BOIS', couleur: '#228B22', emoji: '🌱',
organe: 'Foie', viscere: 'Vésicule Biliaire', diathese: 'PSORE',
patronRemede: 'SULFUR', systemeHormonal: 'Androgènes',
emotionEquilibree: 'Bienveillance', emotionPathologique: 'Colère',
tissus: 'Tendons/Muscles', dynamiquePathologique: 'Stagnation du Qi'
}
};
const modesData = {
elements: {
name: 'Éléments', emoji: '🔥',
items: ['FEU', 'TERRE', 'METAL', 'EAU', 'BOIS'],
desc: 'Glissez les ronds colorés vers leurs positions correctes'
},
organes: {
name: 'Organes', emoji: '🫀',
items: ['Cœur', 'Rate', 'Poumon', 'Rein', 'Foie'],
desc: 'Placez les organes dans leurs éléments correspondants'
},
visceres: {
name: 'Viscères', emoji: '🍃',
items: ['Intestin Grêle', 'Estomac', 'Gros Intestin', 'Vessie', 'Vésicule Biliaire'],
desc: 'Placez les viscères dans leurs éléments correspondants'
},
diatheses: {
name: 'Diathèses', emoji: '🧬',
items: ['SYCOSE', 'ADAPTATION', 'TUBERCULINISME', 'LUÈSE', 'PSORE'],
desc: 'Placez les diathèses dans leurs éléments correspondants'
},
patronsRemedes: {
name: 'Patrons remèdes', emoji: '💊',
items: ['KALIUM', 'MERCURIUS', 'PHOSPHORUS', 'AURUM', 'SULFUR'],
desc: 'Placez les patrons remèdes dans leurs éléments correspondants'
},
systemesHormonaux: {
name: 'Systèmes hormonaux', emoji: '🧪',
items: ['Thyroïde', 'Hypophyse/Cortex', 'Cortex surrénalien', 'Oestrogène/sous-cortex/Thymus', 'Androgènes'],
desc: 'Placez les systèmes hormonaux dans leurs éléments correspondants'
},
emotionsEquilibrees: {
name: 'Émotions équilibrées', emoji: '😊',
items: ['Joie', 'Réflexion', 'Intégrité', 'Volonté', 'Bienveillance'],
desc: 'Placez les émotions équilibrées dans leurs éléments correspondants'
},
emotionsPathologiques: {
name: 'Émotions pathologiques', emoji: '😰',
items: ['Surexcitation', 'Rumination', 'Tristesse', 'Peur', 'Colère'],
desc: 'Placez les émotions pathologiques dans leurs éléments correspondants'
},
tissus: {
name: 'Tissus', emoji: '🦴',
items: ['Vaisseaux', 'Chair/Tissu conjonctif', 'Peau/Poils', 'Os/Moelles', 'Tendons/Muscles'],
desc: 'Placez les tissus dans leurs éléments correspondants'
},
dynamiquesPathologiques: {
name: 'Dynamiques pathologiques', emoji: '⚡',
items: ['Vide Sang', 'Humidité-Glaires', 'Vide de Wei Qi', 'Vide de Jing', 'Stagnation du Qi'],
desc: 'Placez les dynamiques pathologiques dans leurs éléments correspondants'
}
};
// Fonctions utilitaires
function calculateGlobalProgress() {
const totalModes = Object.keys(modesData).length;
const completedModes = Object.keys(globalProgress).filter(mode => globalProgress[mode] === 5).length;
const totalElements = totalModes * 5;
const completedElements = Object.values(globalProgress).reduce((sum, score) => sum + (score || 0), 0);
return {
percentage: Math.round((completedElements / totalElements) * 100),
completed: completedElements,
total: totalElements,
modesCompleted: completedModes,
totalModes: totalModes
};
}
function getAvailableItems() {
const usedItems = Object.values(placedElements);
return modesData[currentMode].items.filter(item => !usedItems.includes(item));
}
function isCorrect(position, item) {
if (currentMode === 'elements') return item === position;
if (currentMode === 'organes') return item === elementsData[position].organe;
if (currentMode === 'visceres') return item === elementsData[position].viscere;
if (currentMode === 'diatheses') return item === elementsData[position].diathese;
if (currentMode === 'patronsRemedes') return item === elementsData[position].patronRemede;
if (currentMode === 'systemesHormonaux') return item === elementsData[position].systemeHormonal;
if (currentMode === 'emotionsEquilibrees') return item === elementsData[position].emotionEquilibree;
if (currentMode === 'emotionsPathologiques') return item === elementsData[position].emotionPathologique;
if (currentMode === 'tissus') return item === elementsData[position].tissus;
if (currentMode === 'dynamiquesPathologiques') return item === elementsData[position].dynamiquePathologique;
return false;
}
// Fonctions de rendu
function renderPentagramLines() {
const lines = [
[[polePositions.FEU.x, polePositions.FEU.y], [polePositions.METAL.x, polePositions.METAL.y]],
[[polePositions.METAL.x, polePositions.METAL.y], [polePositions.BOIS.x, polePositions.BOIS.y]],
[[polePositions.BOIS.x, polePositions.BOIS.y], [polePositions.TERRE.x, polePositions.TERRE.y]],
[[polePositions.TERRE.x, polePositions.TERRE.y], [polePositions.EAU.x, polePositions.EAU.y]],
[[polePositions.EAU.x, polePositions.EAU.y], [polePositions.FEU.x, polePositions.FEU.y]]
];
const container = document.getElementById('pentagramLines');
container.innerHTML = '';
lines.forEach((line, index) => {
const lineEl = document.createElementNS('http://www.w3.org/2000/svg', 'line');
lineEl.setAttribute('x1', line[0][0]);
lineEl.setAttribute('y1', line[0][1]);
lineEl.setAttribute('x2', line[1][0]);
lineEl.setAttribute('y2', line[1][1]);
lineEl.setAttribute('stroke', 'rgba(255,255,255,0.3)');
lineEl.setAttribute('stroke-width', '2');
container.appendChild(lineEl);
});
}
function renderDropZones() {
const container = document.getElementById('dropZones');
container.innerHTML = '';
Object.entries(polePositions).forEach(([position, pos]) => {
// Zone de drop
const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
circle.setAttribute('cx', pos.x);
circle.setAttribute('cy', pos.y);
circle.setAttribute('r', '40');
circle.setAttribute('fill', placedElements[position] ? 'rgba(255,255,255,0.1)' : 'transparent');
circle.setAttribute('stroke', 'rgba(255,255,255,0.4)');
circle.setAttribute('stroke-width', '2');
circle.setAttribute('stroke-dasharray', placedElements[position] ? '0' : '8,4');
circle.classList.add('drop-zone', 'cursor-pointer');
// Drag & Drop
circle.addEventListener('dragover', (e) => {
e.preventDefault();
e.dataTransfer.dropEffect = 'move';
});
circle.addEventListener('drop', (e) => {
e.preventDefault();
if (draggedItem) {
placedElements[position] = draggedItem;
draggedItem = null;
updateDisplay();
}
});
container.appendChild(circle);
// Élément placé
if (placedElements[position]) {
if (currentMode === 'elements') {
const placedCircle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
placedCircle.setAttribute('cx', pos.x);
placedCircle.setAttribute('cy', pos.y);
placedCircle.setAttribute('r', '25');
placedCircle.setAttribute('fill', elementsData[placedElements[position]]?.couleur || '#666');
placedCircle.setAttribute('stroke', 'white');
placedCircle.setAttribute('stroke-width', '3');
placedCircle.style.pointerEvents = 'none';
container.appendChild(placedCircle);
const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
text.setAttribute('x', pos.x);
text.setAttribute('y', pos.y + 3);
text.setAttribute('text-anchor', 'middle');
text.setAttribute('font-size', '20');
text.setAttribute('fill', 'white');
text.setAttribute('font-weight', 'bold');
text.style.pointerEvents = 'none';
text.textContent = elementsData[placedElements[position]]?.emoji || '';
container.appendChild(text);
} else {
const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
rect.setAttribute('x', pos.x - 35);
rect.setAttribute('y', pos.y - 20);
rect.setAttribute('width', '70');
rect.setAttribute('height', '40');
rect.setAttribute('rx', '15');
rect.setAttribute('fill', 'rgba(255,255,255,0.9)');
rect.setAttribute('stroke', elementsData[position]?.couleur || '#666');
rect.setAttribute('stroke-width', '3');
rect.style.pointerEvents = 'none';
container.appendChild(rect);
const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
text.setAttribute('x', pos.x);
text.setAttribute('y', pos.y + 3);
text.setAttribute('text-anchor', 'middle');
text.setAttribute('font-size', '10');
text.setAttribute('fill', '#333');
text.setAttribute('font-weight', 'bold');
text.style.pointerEvents = 'none';
text.textContent = placedElements[position];
container.appendChild(text);
}
}
// Correction
if (showAnswer) {
const correctionCircle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
correctionCircle.setAttribute('cx', pos.x + 30);
correctionCircle.setAttribute('cy', pos.y - 30);
correctionCircle.setAttribute('r', '12');
correctionCircle.setAttribute('fill', isCorrect(position, placedElements[position]) ? '#10b981' : '#ef4444');
correctionCircle.setAttribute('stroke', 'white');
correctionCircle.setAttribute('stroke-width', '2');
container.appendChild(correctionCircle);
const correctionText = document.createElementNS('http://www.w3.org/2000/svg', 'text');
correctionText.setAttribute('x', pos.x + 30);
correctionText.setAttribute('y', pos.y - 25);
correctionText.setAttribute('text-anchor', 'middle');
correctionText.setAttribute('fill', 'white');
correctionText.setAttribute('font-weight', 'bold');
correctionText.style.fontSize = '14px';
correctionText.style.pointerEvents = 'none';
correctionText.textContent = isCorrect(position, placedElements[position]) ? '✓' : '✗';
container.appendChild(correctionText);
}
});
}
function renderModesMenu() {
const container = document.getElementById('modesMenu');
container.innerHTML = '';
Object.entries(modesData).forEach(([key, mode]) => {
const modeScore = globalProgress[key] || 0;
const isCompleted = modeScore === 5;
const button = document.createElement('button');
button.className = `px-3 py-2 rounded-lg transition-all text-xs w-full relative ${
currentMode === key
? 'bg-blue-500 text-white'
: 'bg-white bg-opacity-20 text-blue-200 hover:bg-opacity-30'
}`;
button.innerHTML = `
<div class="flex items-center justify-between">
<span>${mode.emoji} ${mode.name}</span>
<div class="flex items-center gap-1">
<span class="text-xs">${modeScore}/5</span>
${isCompleted ? '<span class="text-green-300">✓</span>' : ''}
</div>
</div>
<div class="w-full bg-gray-600 rounded-full h-1 mt-1">
<div class="${isCompleted ? 'bg-green-400' : 'bg-yellow-400'} h-1 rounded-full transition-all duration-300"
style="width: ${(modeScore / 5) * 100}%"></div>
</div>
`;
button.addEventListener('click', () => changeMode(key));
container.appendChild(button);
});
}
function renderPalette() {
const container = document.getElementById('palette');
container.innerHTML = '';
const availableItems = getAvailableItems();
availableItems.forEach((item, index) => {
const div = document.createElement('div');
div.className = 'cursor-move drag-item shadow-lg border-2 border-white border-opacity-50 flex items-center justify-center mx-auto';
div.draggable = true;
div.title = item;
if (currentMode === 'elements') {
div.style.backgroundColor = elementsData[item]?.couleur || '#666';
div.style.width = '56px';
div.style.height = '56px';
div.style.borderRadius = '50%';
div.innerHTML = `<span class="text-xl">${elementsData[item]?.emoji}</span>`;
} else {
div.style.backgroundColor = 'rgba(255,255,255,0.9)';
div.style.borderColor = 'rgba(255,255,255,0.5)';
div.style.width = '140px';
div.style.height = '50px';
div.style.borderRadius = '20px';
div.innerHTML = `<span class="text-xs font-bold text-gray-800 text-center px-2 leading-tight">${item}</span>`;
}
div.addEventListener('dragstart', (e) => {
draggedItem = item;
e.dataTransfer.effectAllowed = 'move';
});
container.appendChild(div);
});
}
function updateDisplay() {
const globalProgressData = calculateGlobalProgress();
// Header
document.getElementById('modeDescription').textContent = modesData[currentMode].desc;
document.getElementById('globalPercentage').textContent = globalProgressData.percentage;
document.getElementById('completedModes').textContent = globalProgressData.modesCompleted;
document.getElementById('totalModes').textContent = globalProgressData.totalModes;
document.getElementById('currentScore').textContent = score;
document.getElementById('completionMessage').style.display = (score === 5 && showAnswer) ? 'block' : 'none';
// Menu modes
document.getElementById('modesProgress').textContent = `${globalProgressData.modesCompleted}/${globalProgressData.totalModes}`;
// Palette
document.getElementById('paletteTitle').innerHTML = `🎯 ${modesData[currentMode].name}`;
document.getElementById('remainingItems').textContent = 5 - Object.keys(placedElements).length;
document.getElementById('localProgress').style.width = `${(Object.keys(placedElements).length / 5) * 100}%`;
// Bulle
document.getElementById('bubblePercentage').textContent = `${globalProgressData.percentage}%`;
document.getElementById('bubbleProgress').textContent = `${globalProgressData.completed}/${globalProgressData.total}`;
const circumference = 2 * Math.PI * 34;
const offset = circumference * (1 - (globalProgressData.percentage / 100));
document.getElementById('progressCircle').style.strokeDashoffset = offset;
// Panneau inférieur
document.getElementById('mainPercentage').textContent = globalProgressData.percentage;
document.getElementById('mainProgress').textContent = globalProgressData.completed;
document.getElementById('mainTotal').textContent = globalProgressData.total;
document.getElementById('mainProgressBar').style.width = `${globalProgressData.percentage}%`;
document.getElementById('bottomScore').textContent = score;
// Bouton vérifier
document.getElementById('checkAnswers').disabled = Object.keys(placedElements).length === 0;
// Re-render components
renderDropZones();
renderModesMenu();
renderPalette();
}
// Actions
function checkAnswers() {
let correct = 0;
Object.entries(placedElements).forEach(([position, item]) => {
if (isCorrect(position, item)) correct++;
});
score = correct;
showAnswer = true;
globalProgress[currentMode] = correct;
updateDisplay();
}
function resetMode() {
placedElements = {};
showAnswer = false;
score = globalProgress[currentMode] || 0;
updateDisplay();
}
function resetAll() {
globalProgress = {};
placedElements = {};
showAnswer = false;
score = 0;
updateDisplay();
}
function changeMode(newMode) {
currentMode = newMode;
placedElements = {};
showAnswer = false;
score = globalProgress[newMode] || 0;
updateDisplay();
}
// Event listeners
document.getElementById('checkAnswers').addEventListener('click', checkAnswers);
document.getElementById('resetMode').addEventListener('click', resetMode);
document.getElementById('resetAll').addEventListener('click', resetAll);
// Initialisation
function init() {
renderPentagramLines();
updateDisplay();
}
// Démarrer l'application
init();
</script>
</body>
</html>
