66 lines
2.2 KiB
JavaScript
66 lines
2.2 KiB
JavaScript
/**
|
|
* 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<number>} - 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;
|
|
};
|