/** * Calculates distance (in km) between origin and destination. * Uses OSRM as primary driving distance source, and falls back to Haversine with a 1.3 multiplier. * * @param {Object} origin - { latitude, longitude } * @param {Object} destination - { latitude, longitude } * @returns {Promise} - Round distance in KM */ export const calculateDrivingDistance = async (origin, destination) => { const lat1 = origin?.latitude; const lon1 = origin?.longitude; const lat2 = destination?.latitude; const lon2 = destination?.longitude; if (lat1 == null || lon1 == null || lat2 == null || lon2 == null) { throw new Error("Invalid coordinates"); } // 1. Try OSRM API (either self-hosted or public demo server for fallback) const osrmBaseUrl = process.env.REACT_APP_OSRM_URL || "https://router.project-osrm.org"; try { const url = `${osrmBaseUrl}/route/v1/driving/${lon1},${lat1};${lon2},${lat2}?overview=false`; const response = await fetch(url); if (response.ok) { const data = await response.json(); if (data.routes && data.routes.length > 0) { const distanceInMeters = data.routes[0].distance; const distanceInKm = distanceInMeters / 1000; return Math.round(distanceInKm); } } } catch (error) { console.warn("OSRM API failed, falling back to Haversine math:", error); } // 2. Fallback: Haversine Formula with 1.3x multiplier const toRad = (val) => (val * Math.PI) / 180; const R = 6371; // Earth radius in km 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)); const aerialDistance = R * c; return Math.round(aerialDistance * 1.3); }; /** * Calculates total charge based on distance and pricing tier * * @param {number} distanceKm * @param {number} basePrice * @param {number} pricePerKm * @param {number} minKm * @returns {number} */ export const calculateTotalCharge = (distanceKm, basePrice, pricePerKm, minKm) => { if (distanceKm < minKm) { return basePrice; } return (distanceKm - minKm) * pricePerKm + basePrice; };