Files
geocaching_js/static/js/script.js
2024-12-17 19:19:08 +01:00

390 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const modeDebug = false; // 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 lactivation 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 = '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
});