const modeDebug = false; // Passez à true pour activer le mode debug const challengeKey = null document.addEventListener('DOMContentLoaded', () => { toggleDebugMode(); // Appliquer le mode debug au chargement de la page }); function toggleDebugMode() { const debugElements = document.querySelectorAll('[data-debug="true"]'); debugElements.forEach(element => { element.style.display = modeDebug ? 'block' : 'none'; }); console.log(`Mode debug ${modeDebug ? 'activé' : 'désactivé'}`); } document.addEventListener('DOMContentLoaded', () => { // Votre code ici }); let wakeLock = null; async function enableWakeLock() { try { if ('wakeLock' in navigator) { const wakeLock = await navigator.wakeLock.request('screen'); console.log('Verrouillage de l’écran activé.'); return wakeLock; } else { console.warn('API Wake Lock non prise en charge par ce navigateur.'); } } catch (error) { console.error('Erreur lors de l’activation du verrouillage de l’écran :', error); } } // Fonction pour réactiver le Wake Lock si la page redevient visible function handleVisibilityChange() { if (wakeLock !== null && document.visibilityState === 'visible') { enableWakeLock(); } } // Activer le Wake Lock au chargement de la page document.addEventListener('DOMContentLoaded', () => { enableWakeLock(); }); function showPopup(challenge, currentDefiKey) { if (!challenge) { console.error("Aucune donnée de défi actif !"); return; } const { image, textFound, mode } = challenge; // Créer l'élément popup const popup = document.createElement('div'); popup.id = 'popup'; popup.style.position = 'fixed'; popup.style.top = '50%'; popup.style.left = '50%'; popup.style.transform = 'translate(-50%, -50%)'; popup.style.padding = '20px'; popup.style.backgroundColor = '#fff'; popup.style.boxShadow = '0 0 10px rgba(0,0,0,0.5)'; popup.style.zIndex = '1000'; popup.style.textAlign = 'center'; // Ajouter l'image const img = document.createElement('img'); img.src = image; img.alt = 'Défi actif'; img.style.width = '100%'; popup.appendChild(img); // Ajouter le texte trouvé const text = document.createElement('p'); text.textContent = `Texte : ${textFound}`; popup.appendChild(text); // Ajouter un bouton "Fermer" const closeButton = document.createElement('button'); closeButton.textContent = 'Fermer'; closeButton.onclick = () => { document.body.removeChild(popup); // Supprimer la popup markChallengeAsResolved(currentDefiKey); // Mettre à jour le défi }; popup.appendChild(closeButton); // Ajouter le popup au corps de la page document.body.appendChild(popup); } // Fonction pour envoyer la requête POST au serveur async function markChallengeAsResolved(defiKey) { try { const response = await fetch('/mark-challenge-resolved', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: 'baptiste', challengeKey: defiKey }), }); const result = await response.json(); console.log("Défi marqué comme résolu :", result.message); } catch (error) { console.error("Erreur lors de la mise à jour du défi :", error); } } // Fonction pour charger les données utilisateur async function fetchUserData() { try { const response = await fetch(`/user/${username}`); const userData = await response.json(); console.log("Données utilisateur :", userData); // Mettre à jour l'interface avec les données document.getElementById('user-name').textContent = userData.nom; document.getElementById('user-avatar').src = userData.avatar; document.getElementById('user-progression').textContent = userData.progression; // Trouver le premier défi non résolu let firstUnresolvedChallenge = null; let challengeNumber = null; for (let i = 1; i <= 6; i++) { const challengeKey = `defi_${i}`; const challenge = userData.defis[challengeKey]; if (challenge.resolu === "non") { firstUnresolvedChallenge = challenge; challengeNumber = i; break; // On arrête dès qu'on trouve le premier défi non résolu } } if (firstUnresolvedChallenge) { const { latitude, longitude } = firstUnresolvedChallenge.geolocalisation; // Mettre à jour la variable globale target target = { latitude, longitude }; // Extraire les informations du défi actif const { image_1, text_found_1, mode } = firstUnresolvedChallenge; // Stocker les informations du défi actif dans une variable globale window.activeChallenge = { image: image_1, textFound: text_found_1, mode: mode, }; // Mettre à jour l'interface avec les coordonnées du défi document.getElementById('target-latitude').textContent = latitude.toFixed(6); document.getElementById('target-longitude').textContent = longitude.toFixed(6); document.getElementById('challenge-number').textContent = `défi n°${challengeNumber}`; } else { console.log("Tous les défis sont résolus !"); target = null; // Réinitialisation de la cible } } catch (error) { console.error("Erreur lors du chargement des données utilisateur :", error); } } // Charger les données utilisateur dès le chargement de la page document.addEventListener('DOMContentLoaded', () => { fetchUserData(); // Charger les données au démarrage setInterval(fetchUserData, 10000); // Actualiser toutes les 10 secondes }); // Coordonnées de la cible //let target = { latitude: 45.141916, longitude: 4.075059 }; // Coordonnées de la cible //let currentHeading = 0; // Orientation actuelle de l'appareil let lastDistance = null; // Variables pour les coins de la droite virtuelle let topLeft = { x: 2, y: 2 }; // Coin supérieur gauche en pixels let bottomRight = { x: window.innerWidth - 100, y: window.innerHeight - 250 }; // Coin inférieur droit en pixels // Fonction pour recalculer les coins dynamiquement function updateCorners() { bottomRight = { x: window.innerWidth - 100, y: window.innerHeight - 250 }; } window.addEventListener('resize', updateCorners); // Fonction utilitaire pour définir le halo function setHaloColor(element, color) { element.style.boxShadow = `0 0 20px 10px ${color}`; } // Fonction pour mettre à jour le style de Avatar function updateAvatarStyle(distance) { const avatar = document.getElementById('user-avatar'); if (distance > 20) { setHaloColor(avatar, 'rgba(0, 0, 255, 0.6)'); // Halo bleu } else if (distance <= 10) { setHaloColor(avatar, 'rgba(255, 0, 0, 0.6)'); // Halo rouge } else { setHaloColor(avatar, 'rgba(27, 28, 29, 0.6)'); // Halo gris } } function positionAvatar(distance) { const avatar = document.getElementById('user-avatar'); if (!avatar) { console.error("L'élément 'user-avatar' n'existe pas dans le DOM."); return; } if (distance > 25) { avatar.style.left = `${topLeft.x}px`; avatar.style.top = `${topLeft.y}px`; } else if (distance <= 5) { avatar.style.left = `${bottomRight.x}px`; avatar.style.top = `${bottomRight.y}px`; } else { const ratio = (25 - distance) / 20; const newX = topLeft.x + (bottomRight.x - topLeft.x) * ratio; const newY = topLeft.y + (bottomRight.y - topLeft.y) * ratio; avatar.style.left = `${newX}px`; avatar.style.top = `${newY}px`; } } // Fonction pour gérer les flèches directionnelles function updateArrows(distance) { const arrowApproaching = document.getElementById('arrow-approaching'); const arrowMovingAway = document.getElementById('arrow-moving-away'); if (lastDistance !== null) { if (distance < lastDistance) { arrowApproaching.style.display = 'block'; arrowMovingAway.style.display = 'none'; } else { arrowApproaching.style.display = 'none'; arrowMovingAway.style.display = 'block'; } } } // Fonction pour calculer la direction vers la cible (bearing) function calculateBearing(lat1, lon1, lat2, lon2) { const toRad = (value) => (value * Math.PI) / 180; const toDeg = (value) => (value * 180) / Math.PI; const dLon = toRad(lon2 - lon1); const y = Math.sin(dLon) * Math.cos(toRad(lat2)); const x = Math.cos(toRad(lat1)) * Math.sin(toRad(lat2)) - Math.sin(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.cos(dLon); return (toDeg(Math.atan2(y, x)) + 360) % 360; // Angle en degrés, ajusté pour être positif } // Fonction pour mettre à jour l'orientation de la flèche function updateCompass(bearing) { const arrow = document.getElementById('arrow-black'); const angle = (bearing - currentHeading + 360) % 360; // Ajuste selon l'orientation actuelle arrow.style.transform = `rotate(${angle}deg)`; // Applique la rotation } // Écoute les changements d'orientation de l'appareil window.addEventListener('deviceorientation', (event) => { currentHeading = event.alpha || 0; // Orientation absolue en degrés }); // Fonction principale pour mettre à jour les éléments function updatePosition(position) { const { latitude, longitude } = position.coords; document.getElementById('latitude').textContent = latitude.toFixed(6); document.getElementById('longitude').textContent = longitude.toFixed(6); if (!target) { console.warn("Aucune cible définie. Impossible de calculer la distance ou la direction."); return; } const distance = calculateDistance(latitude, longitude, target.latitude, target.longitude); document.getElementById('distance').textContent = `${distance.toFixed(0)} m`; const bearing = calculateBearing(latitude, longitude, target.latitude, target.longitude); positionAvatar(distance); updateAvatarStyle(distance); updateArrows(distance); updateCompass(bearing); // Afficher le popup si distance < 5m if (distance < 4000) { showPopup(window.activeChallenge, challengeKey); } lastDistance = distance; } // Fonction pour calculer la distance entre deux points GPS (Haversine Formula) function calculateDistance(lat1, lon1, lat2, lon2) { const R = 6371000; // Rayon de la Terre en mètres const toRad = (value) => (value * Math.PI) / 180; const dLat = toRad(lat2 - lat1); const dLon = toRad(lon2 - lon1); const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2); const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); return R * c; } // Gestion des erreurs de géolocalisation function handleError(error) { const errorMessages = { 1: "Permission refusée", 2: "Position indisponible", 3: "Délai dépassé" }; alert("Erreur de géolocalisation : " + errorMessages[error.code] || "Erreur inconnue"); } // Initialiser la géolocalisation en temps réel function startTracking() { if (!navigator.geolocation) { alert("La géolocalisation n'est pas prise en charge par votre navigateur."); return; } navigator.geolocation.watchPosition(updatePosition, handleError, { enableHighAccuracy: true, maximumAge: 0, timeout: 5000 }); } // Démarrer le suivi dès le chargement de la page startTracking(); const positionUpdateInterval = 1000 * 5; // 5 secondes (à récupérer dynamiquement depuis config.yaml) // Fonction pour envoyer les nouvelles coordonnées au serveur async function updateServerPosition(latitude, longitude) { const now = new Date().toISOString(); // Format ISO 8601 pour last_update const username = 'baptiste'; // Spécifiez le nom de l'utilisateur pour Julien try { const response = await fetch('/update-position', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: username, // Inclure le champ username latitude: latitude, longitude: longitude, last_update: now // Inclure le champ last_update }) }); const result = await response.json(); console.log("Position mise à jour :", result.message); } catch (error) { console.error("Erreur lors de la mise à jour de la position :", error); } } // Mise à jour de la position toutes les X secondes function startPositionUpdates() { setInterval(() => { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(position => { const { latitude, longitude } = position.coords; updateServerPosition(latitude, longitude); }); } else { console.error("La géolocalisation n'est pas prise en charge."); } }, positionUpdateInterval); } // Lancer le suivi dès le chargement de la page document.addEventListener('DOMContentLoaded', () => { startPositionUpdates(); startTracking(); // Fonction existante pour afficher les mises à jour côté client });