390 lines
13 KiB
JavaScript
390 lines
13 KiB
JavaScript
const modeDebug = true; // Passez à true pour activer le mode debug
|
||
|
||
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) {
|
||
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';
|
||
|
||
// 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 à trouver : ${textFound}`;
|
||
popup.appendChild(text);
|
||
|
||
// Ajouter une action en fonction du mode
|
||
if (mode === 'message') {
|
||
const message = document.createElement('p');
|
||
message.textContent = "Mode : Message";
|
||
popup.appendChild(message);
|
||
} else if (mode === 'reponse') {
|
||
const input = document.createElement('input');
|
||
input.type = 'text';
|
||
input.placeholder = 'Entrez votre réponse';
|
||
popup.appendChild(input);
|
||
|
||
const submitButton = document.createElement('button');
|
||
submitButton.textContent = 'Envoyer';
|
||
popup.appendChild(submitButton);
|
||
}
|
||
|
||
// Ajouter un bouton pour fermer
|
||
const closeButton = document.createElement('button');
|
||
closeButton.textContent = 'Fermer';
|
||
closeButton.onclick = () => document.body.removeChild(popup);
|
||
popup.appendChild(closeButton);
|
||
|
||
// Ajouter le popup au corps de la page
|
||
document.body.appendChild(popup);
|
||
}
|
||
|
||
// 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 < 4) {
|
||
showPopup(window.activeChallenge);
|
||
}
|
||
|
||
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 = 'julien'; // 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
|
||
});
|
||
|
||
|
||
|