qui-fdes / index.html
GabrielVidal's picture
Add 2 files
1396c8e verified
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Qui est-ce ? FDES Edition</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.card {
perspective: 1000px;
width: 150px;
height: 200px;
cursor: pointer;
transition: transform 0.3s;
}
.card:hover {
transform: scale(1.05);
}
.card-inner {
position: relative;
width: 100%;
height: 100%;
transform-style: preserve-3d;
transition: transform 0.6s;
}
.card.flipped .card-inner {
transform: rotateY(180deg);
}
.card-front, .card-back {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
border-radius: 10px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 10px;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.card-back {
transform: rotateY(180deg);
overflow-y: auto;
}
.card-icon {
font-size: 3rem;
margin-bottom: 10px;
}
.progress-bar {
height: 10px;
background-color: #e0e0e0;
border-radius: 5px;
overflow: hidden;
}
.progress-fill {
height: 100%;
background-color: #4CAF50;
transition: width 0.3s;
}
@media (max-width: 640px) {
.card {
width: 100px;
height: 150px;
}
.card-icon {
font-size: 2rem;
}
}
</style>
</head>
<body class="bg-gray-100 min-h-screen">
<div class="container mx-auto px-4 py-8">
<!-- Header -->
<header class="text-center mb-8">
<h1 class="text-3xl md:text-4xl font-bold text-green-800 mb-2">Qui est-ce ? FDES Edition</h1>
<p class="text-gray-600">Découvrez les impacts environnementaux des produits de construction</p>
<div class="mt-4">
<span class="inline-block bg-green-100 text-green-800 px-3 py-1 rounded-full text-sm font-semibold">
<i class="fas fa-leaf mr-1"></i> Base INIES
</span>
</div>
</header>
<!-- Game Area -->
<div class="bg-white rounded-xl shadow-lg p-6 mb-8">
<!-- Game Info -->
<div class="flex flex-wrap justify-between items-center mb-6">
<div class="mb-4 sm:mb-0">
<h2 class="text-xl font-semibold text-gray-800">Tour <span id="turn-count">1</span></h2>
<p class="text-gray-600">Cartes restantes: <span id="remaining-cards">24</span></p>
</div>
<div class="w-full sm:w-auto">
<div class="progress-bar">
<div class="progress-fill" style="width: 100%"></div>
</div>
<p class="text-right text-sm text-gray-600 mt-1">Difficulté: Moyenne</p>
</div>
</div>
<!-- Cards Grid -->
<div id="cards-container" class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-4 mb-8">
<!-- Cards will be dynamically inserted here -->
</div>
<!-- Question Area -->
<div class="bg-gray-50 rounded-lg p-4">
<h3 class="text-lg font-semibold mb-3 text-gray-800">Poser une question</h3>
<div class="flex flex-wrap gap-3 mb-4">
<button class="filter-btn bg-green-100 hover:bg-green-200 text-green-800 px-4 py-2 rounded-lg transition" data-filter="category">
<i class="fas fa-tag mr-2"></i>Catégorie
</button>
<button class="filter-btn bg-blue-100 hover:bg-blue-200 text-blue-800 px-4 py-2 rounded-lg transition" data-filter="manufacturer">
<i class="fas fa-industry mr-2"></i>Fabricant
</button>
<button class="filter-btn bg-purple-100 hover:bg-purple-200 text-purple-800 px-4 py-2 rounded-lg transition" data-filter="impact">
<i class="fas fa-fire mr-2"></i>Impact environnemental
</button>
<button class="filter-btn bg-yellow-100 hover:bg-yellow-200 text-yellow-800 px-4 py-2 rounded-lg transition" data-filter="health">
<i class="fas fa-heartbeat mr-2"></i>Santé
</button>
</div>
<div id="question-options" class="hidden bg-white p-4 rounded-lg shadow-inner mb-4">
<!-- Options will be dynamically inserted here -->
</div>
<div class="flex justify-between items-center">
<button id="submit-guess" class="bg-red-500 hover:bg-red-600 text-white px-6 py-2 rounded-lg font-medium transition">
<i class="fas fa-lightbulb mr-2"></i>Faire une supposition
</button>
<button id="submit-question" class="bg-green-600 hover:bg-green-700 text-white px-6 py-2 rounded-lg font-medium transition hidden">
<i class="fas fa-question mr-2"></i>Poser la question
</button>
</div>
</div>
</div>
<!-- Game Instructions -->
<div class="bg-white rounded-xl shadow-lg p-6">
<h2 class="text-xl font-semibold mb-4 text-gray-800">Comment jouer ?</h2>
<div class="grid md:grid-cols-3 gap-4">
<div class="bg-blue-50 p-4 rounded-lg">
<div class="flex items-center mb-2">
<div class="bg-blue-100 p-2 rounded-full mr-3">
<i class="fas fa-1 text-blue-600"></i>
</div>
<h3 class="font-medium text-blue-800">Choisissez un produit</h3>
</div>
<p class="text-gray-700">Sélectionnez mentalement une carte produit sans la retourner.</p>
</div>
<div class="bg-green-50 p-4 rounded-lg">
<div class="flex items-center mb-2">
<div class="bg-green-100 p-2 rounded-full mr-3">
<i class="fas fa-2 text-green-600"></i>
</div>
<h3 class="font-medium text-green-800">Répondez aux questions</h3>
</div>
<p class="text-gray-700">L'ordinateur pose des questions pour éliminer des options.</p>
</div>
<div class="bg-purple-50 p-4 rounded-lg">
<div class="flex items-center mb-2">
<div class="bg-purple-100 p-2 rounded-full mr-3">
<i class="fas fa-3 text-purple-600"></i>
</div>
<h3 class="font-medium text-purple-800">Devinez le produit</h3>
</div>
<p class="text-gray-700">L'ordinateur tente de deviner votre produit en fonction des réponses.</p>
</div>
</div>
</div>
</div>
<script>
// Sample FDES data
const products = [
{
id: 1,
name: "Brique terre cuite",
category: "Maçonnerie",
manufacturer: "Terreal",
icon: "fas fa-home",
color: "bg-red-100",
textColor: "text-red-800",
co2: "0.8 kg CO₂ eq/m²",
health: "Aucun risque sanitaire connu",
recyclability: "90% recyclable"
},
{
id: 2,
name: "Béton cellulaire",
category: "Maçonnerie",
manufacturer: "Siporex",
icon: "fas fa-cubes",
color: "bg-gray-100",
textColor: "text-gray-800",
co2: "1.2 kg CO₂ eq/m²",
health: "Poussières irritantes",
recyclability: "70% recyclable"
},
{
id: 3,
name: "Panneau OSB",
category: "Bois",
manufacturer: "Kronoply",
icon: "fas fa-tree",
color: "bg-amber-100",
textColor: "text-amber-800",
co2: "0.5 kg CO₂ eq/m²",
health: "Colles sans formaldéhyde",
recyclability: "95% valorisable"
},
{
id: 4,
name: "Laine de verre",
category: "Isolation",
manufacturer: "Isover",
icon: "fas fa-igloo",
color: "bg-blue-100",
textColor: "text-blue-800",
co2: "1.5 kg CO₂ eq/m²",
health: "Protection respiratoire recommandée",
recyclability: "60% recyclable"
},
{
id: 5,
name: "Plaque de plâtre",
category: "Cloison",
manufacturer: "Placo",
icon: "fas fa-border-style",
color: "bg-white",
textColor: "text-gray-800",
co2: "0.7 kg CO₂ eq/m²",
health: "Poussières gypse non toxiques",
recyclability: "85% recyclable"
},
{
id: 6,
name: "Carrelage céramique",
category: "Revêtement",
manufacturer: "Novoceram",
icon: "fas fa-border-all",
color: "bg-indigo-100",
textColor: "text-indigo-800",
co2: "1.8 kg CO₂ eq/m²",
health: "Aucun risque sanitaire",
recyclability: "100% recyclable"
},
{
id: 7,
name: "Parquet chêne",
category: "Revêtement",
manufacturer: "Tarkett",
icon: "fas fa-border-all",
color: "bg-amber-100",
textColor: "text-amber-800",
co2: "0.9 kg CO₂ eq/m²",
health: "Traitement écologique",
recyclability: "100% biodégradable"
},
{
id: 8,
name: "Laine de roche",
category: "Isolation",
manufacturer: "Rockwool",
icon: "fas fa-igloo",
color: "bg-gray-100",
textColor: "text-gray-800",
co2: "1.6 kg CO₂ eq/m²",
health: "Protection respiratoire recommandée",
recyclability: "65% recyclable"
}
];
// Game state
let remainingProducts = [...products];
let currentFilter = null;
let selectedProduct = null;
let turnCount = 1;
// Initialize the game
function initGame() {
renderCards();
updateGameInfo();
// Event listeners for filter buttons
document.querySelectorAll('.filter-btn').forEach(btn => {
btn.addEventListener('click', function() {
currentFilter = this.dataset.filter;
showQuestionOptions(currentFilter);
});
});
// Event listener for submit question button
document.getElementById('submit-question').addEventListener('click', processQuestion);
// Event listener for guess button
document.getElementById('submit-guess').addEventListener('click', makeGuess);
}
// Render all product cards
function renderCards() {
const container = document.getElementById('cards-container');
container.innerHTML = '';
remainingProducts.forEach(product => {
const card = document.createElement('div');
card.className = 'card';
card.dataset.id = product.id;
card.innerHTML = `
<div class="card-inner">
<div class="card-front ${product.color} ${product.textColor}">
<div class="card-icon">
<i class="${product.icon}"></i>
</div>
<div class="text-center font-medium text-sm">${product.category}</div>
</div>
<div class="card-back bg-white">
<h4 class="font-bold text-center mb-2">${product.name}</h4>
<div class="text-xs">
<p><span class="font-semibold">Fabricant:</span> ${product.manufacturer}</p>
<p><span class="font-semibold">CO₂:</span> ${product.co2}</p>
<p><span class="font-semibold">Santé:</span> ${product.health}</p>
<p><span class="font-semibold">Recyclage:</span> ${product.recyclability}</p>
</div>
</div>
</div>
`;
container.appendChild(card);
});
}
// Update game info display
function updateGameInfo() {
document.getElementById('remaining-cards').textContent = remainingProducts.length;
document.getElementById('turn-count').textContent = turnCount;
// Update progress bar
const progress = (remainingProducts.length / products.length) * 100;
document.querySelector('.progress-fill').style.width = `${progress}%`;
}
// Show question options based on filter
function showQuestionOptions(filter) {
const optionsContainer = document.getElementById('question-options');
optionsContainer.innerHTML = '';
optionsContainer.classList.remove('hidden');
document.getElementById('submit-question').classList.remove('hidden');
let options = [];
let questionText = '';
switch(filter) {
case 'category':
questionText = 'Le produit appartient-il à la catégorie...';
options = [...new Set(products.map(p => p.category))];
break;
case 'manufacturer':
questionText = 'Le produit est-il fabriqué par...';
options = [...new Set(products.map(p => p.manufacturer))];
break;
case 'impact':
questionText = 'L\'impact CO₂ du produit est-il...';
options = ['Faible (<1 kg CO₂ eq/m²)', 'Moyen (1-1.5 kg CO₂ eq/m²)', 'Élevé (>1.5 kg CO₂ eq/m²)'];
break;
case 'health':
questionText = 'Le produit présente-t-il...';
options = ['Aucun risque sanitaire', 'Risques limités', 'Protection nécessaire'];
break;
}
optionsContainer.innerHTML = `
<h4 class="font-medium mb-3">${questionText}</h4>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2">
${options.map(opt => `
<label class="flex items-center bg-gray-100 hover:bg-gray-200 rounded-lg p-3 cursor-pointer transition">
<input type="radio" name="questionOption" value="${opt}" class="mr-2">
${opt}
</label>
`).join('')}
</div>
`;
}
// Process the selected question
function processQuestion() {
const selectedOption = document.querySelector('input[name="questionOption"]:checked');
if (!selectedOption) {
alert('Veuillez sélectionner une option');
return;
}
const optionValue = selectedOption.value;
let filteredProducts = [];
switch(currentFilter) {
case 'category':
filteredProducts = remainingProducts.filter(p => p.category === optionValue);
break;
case 'manufacturer':
filteredProducts = remainingProducts.filter(p => p.manufacturer === optionValue);
break;
case 'impact':
if (optionValue.includes('Faible')) {
filteredProducts = remainingProducts.filter(p => parseFloat(p.co2) < 1);
} else if (optionValue.includes('Moyen')) {
filteredProducts = remainingProducts.filter(p => parseFloat(p.co2) >= 1 && parseFloat(p.co2) <= 1.5);
} else {
filteredProducts = remainingProducts.filter(p => parseFloat(p.co2) > 1.5);
}
break;
case 'health':
if (optionValue.includes('Aucun')) {
filteredProducts = remainingProducts.filter(p => p.health.includes('Aucun'));
} else if (optionValue.includes('limités')) {
filteredProducts = remainingProducts.filter(p => !p.health.includes('Aucun') && !p.health.includes('Protection'));
} else {
filteredProducts = remainingProducts.filter(p => p.health.includes('Protection'));
}
break;
}
// Computer makes a guess if only one product remains
if (filteredProducts.length === 1) {
setTimeout(() => {
alert(`L'ordinateur pense que vous avez sélectionné: ${filteredProducts[0].name}`);
endGame(true);
}, 500);
return;
}
// If no products match, computer learns the answer was no
if (filteredProducts.length === 0) {
alert(`Aucun produit ne correspond à cette caractéristique. L'ordinateur élimine ces options.`);
} else {
remainingProducts = filteredProducts;
turnCount++;
updateGameInfo();
renderCards();
}
// Reset question UI
document.getElementById('question-options').classList.add('hidden');
document.getElementById('submit-question').classList.add('hidden');
}
// Player makes a guess
function makeGuess() {
if (remainingProducts.length === 0) {
alert('Aucun produit restant à deviner');
return;
}
const options = remainingProducts.map(p => p.name).join('\n');
const guess = prompt(`Faites votre supposition parmi ces produits:\n\n${options}`);
if (guess) {
const found = remainingProducts.find(p => p.name === guess);
if (found) {
alert(`Correct! Vous avez deviné: ${guess}`);
endGame(false);
} else {
alert('Incorrect. Continuez à poser des questions.');
}
}
}
// End the game
function endGame(computerWon) {
if (computerWon) {
alert('L\'ordinateur a gagné ! Voulez-vous rejouer ?');
} else {
alert('Vous avez gagné ! Voulez-vous rejouer ?');
}
if (confirm('Nouvelle partie ?')) {
resetGame();
}
}
// Reset the game
function resetGame() {
remainingProducts = [...products];
turnCount = 1;
currentFilter = null;
selectedProduct = null;
document.getElementById('question-options').classList.add('hidden');
document.getElementById('submit-question').classList.add('hidden');
renderCards();
updateGameInfo();
}
// Initialize the game when page loads
window.addEventListener('DOMContentLoaded', initGame);
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=GabrielVidal/qui-fdes" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>