290 lines
9.4 KiB
JavaScript
290 lines
9.4 KiB
JavaScript
|
||
|
||
|
||
|
||
|
||
let target = null; // Variable globale pour stocker la cible
|
||
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();
|
||
});
|
||
|
||
|
||
|
||
|
||
|
||
// 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, key, key_number } = firstUnresolvedChallenge;
|
||
|
||
// Stocker les informations du défi actif dans une variable globale
|
||
window.activeChallenge = {
|
||
image: image_1,
|
||
textFound: text_found_1,
|
||
mode: mode,
|
||
key: `defi_${challengeNumber}`,
|
||
key_number: challengeNumber
|
||
};
|
||
|
||
// 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('user-progression').textContent = 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 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);
|
||
}
|
||
|
||
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
|
||
});
|
||
|
||
|
||
|