<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Les Champions des Nombres</title>
<script src="https://cdn.tailwindcss.org"></script>
<style>
/* Ergonomie et masquage du curseur */
html, body {
height: 100%; margin: 0; padding: 0;
overflow: hidden; background: #ffffff;
user-select: none; cursor: none;
}
.app-container {
height: 100vh; width: 100vw;
display: flex; flex-direction: column;
}
/* Blocs visuels : Dizaines */
.block-tens {
width: 180px; height: 35px;
background: #22c55e; border: 2px solid #166534;
border-radius: 8px; display: flex; flex-direction: row; gap: 2px; padding: 2px;
}
.block-tens-segment { flex: 1; background: #4ade80; border-radius: 2px; border: 1px solid #166534; }
/* Blocs visuels : Unités */
.block-unit {
width: 45px; height: 45px;
background: #facc15; border: 2px solid #a16207;
border-radius: 8px; display: inline-block; margin: 3px;
}
/* Boutons de réponse GÉANTS */
.btn-answer {
transition: all 0.1s;
touch-action: manipulation;
border-bottom-width: 16px;
font-size: 7rem;
}
.btn-answer:active {
transform: translateY(8px);
border-bottom-width: 4px;
}
/* Animation du score */
@keyframes pop {
0% { transform: scale(1); }
50% { transform: scale(1.3); }
100% { transform: scale(1); }
}
.score-pop { animation: pop 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); }
/* Overlay de félicitations */
#celebration-overlay {
display: none;
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(255, 255, 255, 0.98);
z-index: 100;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
}
</style>
</head>
<body class="font-sans">
<div class="app-container">
<!-- Écran de félicitations -->
<div id="celebration-overlay">
<h2 class="text-6xl font-black text-green-600 mb-6 uppercase">BRAVO CHAMPION !</h2>
<p id="celebration-text" class="text-3xl font-bold text-gray-700 mb-8 px-10"></p>
<div id="reward-image-container" class="mb-10 p-6 bg-yellow-100 rounded-full border-8 border-yellow-400 shadow-2xl">
<!-- Image de récompense générée -->
</div>
<button onclick="closeCelebration()" class="bg-green-500 text-white px-20 py-10 rounded-[50px] font-black text-5xl shadow-2xl hover:bg-green-600 active:scale-95 border-b-[12px] border-green-800">
CONTINUER ➔
</button>
</div>
<!-- Titre -->
<div class="bg-green-600 py-4 text-white text-center shadow-lg">
<h1 class="text-3xl font-black uppercase">Compte et clique sur le bon nombre !</h1>
</div>
<div class="flex-1 flex flex-col p-6 gap-6 overflow-hidden">
<!-- Zone de Visualisation -->
<div class="h-[35%] flex flex-col justify-center items-center bg-gray-50 rounded-[50px] border-4 border-gray-100 p-8 shadow-inner">
<div id="visual-container" class="flex flex-col gap-6 items-center transform scale-125">
<!-- Généré par JS -->
</div>
</div>
<!-- Message de Feedback -->
<div id="feedback" class="h-20 flex items-center justify-center font-black rounded-3xl text-4xl uppercase transition-all"></div>
<!-- Grille de Réponses -->
<div id="options-grid" class="flex-1 grid grid-cols-2 gap-8">
<!-- Généré par JS -->
</div>
<!-- Score Géant -->
<div class="flex items-center justify-between gap-10 pt-4 border-t-8 border-yellow-400 bg-yellow-50 px-12 py-6 rounded-t-[70px] shadow-2xl">
<div class="flex items-center gap-10">
<span class="text-yellow-800 text-4xl font-black italic uppercase">Points :</span>
<div id="score-display" class="bg-yellow-400 text-white px-24 py-6 rounded-[50px] font-black text-9xl shadow-[0_15px_0_0_#ca8a04] border-8 border-white text-center min-w-[320px]">
0
</div>
</div>
<button onclick="newGame()" class="bg-gray-200 text-gray-500 px-16 py-10 rounded-4xl font-bold text-2xl active:bg-gray-300 border-b-8 border-gray-400">
Passer ➔
</button>
</div>
</div>
</div>
<script>
const apiKey = ""; // Clé API fournie au runtime
let currentNumber = 0;
let score = 0;
let isAnswering = false;
function createTensBlock() {
const block = document.createElement('div');
block.className = 'block-tens shadow-md';
for(let i=0; i<10; i++) {
const seg = document.createElement('div');
seg.className = 'block-tens-segment';
block.appendChild(seg);
}
return block;
}
function createUnitBlock() {
const u = document.createElement('div');
u.className = 'block-unit shadow-md';
return u;
}
async function generateRewardImage(points) {
const container = document.getElementById('reward-image-container');
container.innerHTML = `<div class="w-64 h-64 flex items-center justify-center text-yellow-600 font-black text-2xl">RECOMPENSE...</div>`;
try {
const prompt = `Un magnifique trophée doré brillant pour un enfant champion de mathématiques avec le nombre ${points} gravé, style dessin animé 3d, couleurs vives, fond blanc`;
const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/imagen-4.0-generate-001:predict?key=${apiKey}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
instances: [{ prompt: prompt }],
parameters: { sampleCount: 1 }
})
});
const result = await response.json();
if (result.predictions && result.predictions[0]) {
const imageUrl = `data:image/png;base64,${result.predictions[0].bytesBase64Encoded}`;
container.innerHTML = `<img src="${imageUrl}" alt="Trophée" class="w-80 h-80 object-contain rounded-3xl">`;
} else { throw new Error(); }
} catch (e) {
container.innerHTML = `<div class="text-[10rem] animate-bounce">🏆</div>`;
}
}
function showCelebration() {
const overlay = document.getElementById('celebration-overlay');
const text = document.getElementById('celebration-text');
text.innerText = `C'est fantastique ! Tu as atteint ${score} points !`;
overlay.style.display = 'flex';
generateRewardImage(score);
}
function closeCelebration() {
document.getElementById('celebration-overlay').style.display = 'none';
newGame();
}
function newGame() {
isAnswering = false;
const feedback = document.getElementById('feedback');
feedback.innerText = "";
feedback.className = "h-20 flex items-center justify-center font-black rounded-3xl text-4xl uppercase";
currentNumber = Math.floor(Math.random() * 30) + 10;
const tCount = Math.floor(currentNumber / 10);
const uCount = currentNumber % 10;
const container = document.getElementById('visual-container');
container.innerHTML = '';
const tensWrap = document.createElement('div');
tensWrap.className = 'flex flex-col gap-3';
for(let i=0; i<tCount; i++) tensWrap.appendChild(createTensBlock());
container.appendChild(tensWrap);
if(uCount > 0) {
const unitsWrap = document.createElement('div');
unitsWrap.className = 'flex flex-wrap justify-center gap-2 max-w-[500px] mt-2';
for(let i=0; i<uCount; i++) unitsWrap.appendChild(createUnitBlock());
container.appendChild(unitsWrap);
}
generateOptions();
}
function generateOptions() {
const grid = document.getElementById('options-grid');
grid.innerHTML = '';
let choices = [currentNumber];
let reversed = parseInt(currentNumber.toString().split('').reverse().join(''));
if(reversed !== currentNumber && reversed < 100) choices.push(reversed);
while(choices.length < 4) {
let r = Math.floor(Math.random() * 40) + 10;
if(!choices.includes(r)) choices.push(r);
}
choices.sort(() => Math.random() - 0.5);
choices.forEach(val => {
const btn = document.createElement('button');
btn.className = "btn-answer bg-white border-4 border-green-500 border-b-green-700 rounded-[60px] font-black text-green-700 shadow-2xl flex items-center justify-center";
btn.innerText = val;
btn.onclick = () => checkAnswer(val);
grid.appendChild(btn);
});
}
function checkAnswer(val) {
if (isAnswering) return;
const feedback = document.getElementById('feedback');
const scoreDisplay = document.getElementById('score-display');
if (val === currentNumber) {
isAnswering = true;
feedback.innerText = "BRAVO ! C'EST JUSTE ! 🌟";
feedback.className = "h-20 flex items-center justify-center font-black rounded-3xl text-4xl uppercase bg-green-500 text-white shadow-xl";
score++;
scoreDisplay.innerText = score;
scoreDisplay.classList.add('score-pop');
setTimeout(() => scoreDisplay.classList.remove('score-pop'), 500);
if (score > 0 && score % 10 === 0) {
setTimeout(showCelebration, 1200);
} else {
setTimeout(newGame, 1500);
}
} else {
feedback.innerText = "REGARDE BIEN... 🔍";
feedback.className = "h-20 flex items-center justify-center font-black rounded-3xl text-4xl uppercase bg-red-500 text-white shadow-xl";
}
}
window.onload = newGame;
</script>
</body>
</html>