/** * Calcule la durée estimée d'un trajet en heures à partir des adresses. * Utilise Nominatim pour géocoder et la formule de Haversine pour la distance. */ export async function calculerDureeTrajet( adresseDepart: string, adresseArrivee: string ): Promise { if (!adresseDepart?.trim() || !adresseArrivee?.trim()) { return null; } try { const departResponse = await fetch( `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(adresseDepart.trim())}&limit=1&countrycodes=fr`, { headers: { 'User-Agent': 'MAD Platform', 'Accept-Language': 'fr-FR,fr;q=0.9', }, } ); if (!departResponse.ok) return null; await new Promise((resolve) => setTimeout(resolve, 1000)); const arriveeResponse = await fetch( `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(adresseArrivee.trim())}&limit=1&countrycodes=fr`, { headers: { 'User-Agent': 'MAD Platform', 'Accept-Language': 'fr-FR,fr;q=0.9', }, } ); if (!arriveeResponse.ok) return null; const [departData, arriveeData] = await Promise.all([ departResponse.json(), arriveeResponse.json(), ]); if (!departData?.length || !arriveeData?.length) return null; const lat1 = parseFloat(departData[0].lat); const lon1 = parseFloat(departData[0].lon); const lat2 = parseFloat(arriveeData[0].lat); const lon2 = parseFloat(arriveeData[0].lon); const R = 6371; // Rayon de la Terre en km const dLat = ((lat2 - lat1) * Math.PI) / 180; const dLon = ((lon2 - lon1) * Math.PI) / 180; const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos((lat1 * Math.PI) / 180) * Math.cos((lat2 * Math.PI) / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2); const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); const distance = R * c; const distanceWithDetour = distance * 1.3; const vitesseMoyenne = 50; // km/h const dureeEnHeures = distanceWithDetour / vitesseMoyenne; return Math.round(dureeEnHeures * 10) / 10; } catch { return null; } }