let map; // Carte unique let baptisteMarker = null; // Marker de Baptiste let julienMarker = null; // Marker de Julien // ------------------------------------- // SECTION : Fonctions Utilitaires // ------------------------------------- // Calcul du temps d'inactivité en secondes function calculateDeltaInSeconds(lastUpdate) { const lastUpdateTime = new Date(lastUpdate).getTime(); const currentTime = Date.now(); return Math.floor((currentTime - lastUpdateTime) / 1000); } // Ajout d'un pin personnalisé function addCustomPin(coordinates, iconUrl, popupText, offsetX = 20, offsetY = 40) { const customIcon = L.icon({ iconUrl: iconUrl, iconSize: [40, 40], iconAnchor: [offsetX, offsetY], popupAnchor: [0, -40], }); return L.marker(coordinates, { icon: customIcon }).bindPopup(popupText); } // Initialisation de la carte function initializeMap(centerCoordinates = [ 45.142066, 4.076664]) { // Initialiser la carte map = L.map('map', { center: centerCoordinates, // Coordonnées du centre zoom: 20, // Niveau de zoom par défaut minZoom: 15, // Zoom minimum autorisé maxZoom: 20 // Zoom maximum autorisé }); // Définir les différentes couches de la carte const osmStandard = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors', }); const cycleOSM = L.tileLayer('https://{s}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png', { attribution: '© CycleOSM', }); const satellite = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', { attribution: '© ESRI World Imagery', }); // Nouvelle couche de tuiles personnalisées const customTiles = L.tileLayer('https://jeu.maison43.duckdns.org/tiles/messinhac/{z}/{x}/{y}.png', { attribution: '© Mes Tuiles Personnalisées', maxZoom: 20, // Assure un zoom maximal compatible avec tes tuiles }); // Ajouter OpenStreetMap comme layer par défaut customTiles.addTo(map); // Ajouter un contrôle pour basculer entre les couches const baseLayers = { "OpenStreetMap Standard": osmStandard, "CycleOSM": cycleOSM, "Satellite": satellite, "Tuiles Personnalisées": customTiles, // Ajout de la nouvelle couche ici }; L.control.layers(baseLayers).addTo(map); } // ------------------------------------- // SECTION : Gestion des Utilisateurs // ------------------------------------- // Fonction générique pour mettre à jour un utilisateur async function updateAvatarPosition(username, markerRefName) { try { const response = await fetch(`/data/${username}.yaml`); const userData = await response.json(); const newCoordinates = [ userData.position_actuelle.latitude, userData.position_actuelle.longitude, ]; // Référence globale au marker let marker = markerRefName === 'baptiste' ? baptisteMarker : julienMarker; if (marker) { // Met à jour directement la position du marker marker.setLatLng(newCoordinates); } else { // Créez le marker pour la première fois const newMarker = addCustomPin( newCoordinates, userData.avatar || 'default-avatar.png', `${username} : ${userData.progression}` ); newMarker.addTo(map); // Met à jour la variable globale if (markerRefName === 'baptiste') { baptisteMarker = newMarker; } else if (markerRefName === 'julien') { julienMarker = newMarker; } } console.log(`Position de ${username} mise à jour :`, newCoordinates); } catch (error) { console.error(`Erreur lors de la mise à jour de la position de ${username} :`, error); } } // Fonction générique pour charger les pins des défis async function loadChallengePins(username) { try { const response = await fetch(`/data/${username}.yaml`); const userData = await response.json(); const offsetX = userData.pin_offset?.x || 20; const offsetY = userData.pin_offset?.y || 40; for (let i = 1; i <= 6; i++) { const defi = userData.defis[`defi_${i}`]; if (!defi) continue; const defiMarker = addCustomPin( [defi.geolocalisation.latitude, defi.geolocalisation.longitude], defi.pin || 'default-pin.png', `Défi ${i} - trouvé ${defi.resolu}`, offsetX, offsetY ); defiMarker.addTo(map); // Ajouter le label "option" si résolu est "oui" if (defi.resolu === "oui") { defiMarker.bindTooltip(`Défi ${i}`, { permanent: true, // Affiche le label en permanence direction: "bottom", // Positionne le label au-dessus du marqueur offset: [0, -5] // Ajuste l'offset pour éviter que le label chevauche le marqueur }); } } console.log(`Pins des défis pour ${username} chargés avec succès.`); } catch (error) { console.error(`Erreur lors du chargement des défis pour ${username} :`, error); } } // Fonction générique pour récupérer et afficher les données utilisateur async function fetchUserData(username, domElements) { try { const response = await fetch(`/data/${username}.yaml`); const userData = await response.json(); const lastUpdate = userData.position_actuelle.last_update; const inactivitySeconds = calculateDeltaInSeconds(lastUpdate); // Mise à jour des éléments HTML document.getElementById(domElements.name).textContent = `${userData.nom}`; document.getElementById(domElements.progression).textContent = `Progression : ${userData.progression}`; document.getElementById(domElements.avatar).src = userData.avatar; document.getElementById(domElements.longitude).textContent = userData.position_actuelle.longitude; document.getElementById(domElements.latitude).textContent = userData.position_actuelle.latitude; document.getElementById(domElements.inactive).textContent = `Inactif depuis : ${inactivitySeconds} s`; console.log(`Données de ${username} mises à jour.`); } catch (error) { console.error(`Erreur lors de la récupération des données de ${username} :`, error); } } // ------------------------------------- // SECTION : Événements DOM // ------------------------------------- document.addEventListener("DOMContentLoaded", async () => { initializeMap(); // Charger les pins des défis await loadChallengePins('baptiste'); await loadChallengePins('julien'); // Planifier les mises à jour des positions des utilisateurs setInterval(() => updateAvatarPosition('baptiste', 'baptiste'), 3000); setInterval(() => updateAvatarPosition('julien', 'julien'), 3000); setInterval(() =>loadChallengePins('baptiste'), 3000); setInterval(() =>loadChallengePins('julien'), 3000); // Mettre à jour les avatars et les données utilisateur setInterval(() => updateAvatarPosition('baptiste', { value: baptisteMarker }), 3000); setInterval(() => updateAvatarPosition('julien', { value: julienMarker }), 3000); setInterval(() => fetchUserData('baptiste', { name: 'user-name', progression: 'user-progression', avatar: 'user-avatar', longitude: 'user-longitude', latitude: 'user-latitude', inactive: 'user-inactive', }), 3000); setInterval(() => fetchUserData('julien', { name: 'user-name-julien', progression: 'user-progression-julien', avatar: 'user-avatar-julien', longitude: 'user-longitude-julien', latitude: 'user-latitude-julien', inactive: 'user-inactive-julien', }), 3000); });