SafeRoute / src /lib /api.ts
ayushsahu45's picture
Create lib/api.ts
fa8a0ea verified
import { getCached, setCache, generateRouteCacheKey, generateGeocodeCacheKey } from './routeCache';
export async function geocode(query: string) {
const cacheKey = generateGeocodeCacheKey(query);
const cached = getCached<any[]>(cacheKey);
if (cached && cached.length > 0) return cached;
try {
// Use server proxy for geocoding (bypasses CORS)
const response = await fetch(`/api/geocode?q=${encodeURIComponent(query)}`);
if (response.ok) {
const data = await response.json();
if (data && data.length > 0) {
const results = data.map((item: any) => ({
id: item.place_id || Math.random(),
place_name: item.display_name || item.place_name,
center: [parseFloat(item.lon || item.center?.[0] || 0), parseFloat(item.lat || item.center?.[1] || 0)]
}));
setCache(cacheKey, results);
return results;
}
}
} catch (error) {
console.error('Geocode error:', error);
}
return [];
}
export async function getRoute(start: [number, number], end: [number, number], profile: string = 'driving') {
const cacheKey = generateRouteCacheKey(start, end, profile);
const cached = getCached<any[]>(cacheKey);
if (cached && cached.length > 0) return cached;
try {
const response = await fetch(
`https://router.project-osrm.org/route/v1/driving/${start[0]},${start[1]};${end[0]},${end[1]}?geometries=geojson&overview=full&steps=true&alternatives=true`,
{ signal: AbortSignal.timeout(10000) }
);
if (response.ok) {
const data = await response.json();
if (data.routes && data.routes.length > 0) {
const routes = data.routes;
if (profile === 'cycling' || profile === 'walking') {
const speedMs = profile === 'cycling' ? 4.16 : 1.38;
routes.forEach((route: any) => {
route.duration = route.distance / speedMs;
});
}
setCache(cacheKey, routes);
return routes;
}
}
} catch (error) {
console.error('Route error:', error);
}
return generateMockRoute(start, end);
}
function generateMockRoute(start: [number, number], end: [number, number]) {
const distance = Math.sqrt(
Math.pow(end[0] - start[0], 2) + Math.pow(end[1] - start[1], 2)
) * 111;
const coords: [number, number][] = [];
const steps = 20;
for (let i = 0; i <= steps; i++) {
const t = i / steps;
coords.push([
start[0] + (end[0] - start[0]) * t,
start[1] + (end[1] - start[1]) * t
]);
}
return [{
geometry: { coordinates: coords },
distance: distance * 1000,
duration: (distance / 40) * 3600,
legs: [{
steps: [
{ maneuver: { type: 'depart', instruction: 'Start from your location' }, distance: 500 },
{ maneuver: { type: 'continue', instruction: 'Continue straight' }, distance: distance * 400 },
{ maneuver: { type: 'arrive', instruction: 'Arrive at your destination' }, distance: 500 }
]
}]
}];
}
export async function getWeather(lat: number, lon: number) {
try {
const response = await fetch(`/api/weather?lat=${lat}&lon=${lon}`);
if (response.ok) {
return await response.json();
}
} catch {}
return { weather: [{ main: 'Clear' }], main: { temp: 298 } };
}
export async function analyzeRoute(coordinates: [number, number][], weatherCondition: string, timeOfDay: number, vehicleType: string = 'driving') {
try {
const response = await fetch('/api/route-analysis', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ coordinates, weather_condition: weatherCondition, time_of_day: timeOfDay, vehicle_type: vehicleType })
});
if (response.ok) {
return await response.json();
}
} catch {}
const segments = [];
const segmentSize = Math.max(1, Math.floor(coordinates.length / 10));
for (let i = 0; i < coordinates.length - 1; i += segmentSize) {
const endIdx = Math.min(i + segmentSize, coordinates.length - 1);
const baseRisk = 0.15 + Math.random() * 0.25;
const weatherMultiplier = weatherCondition === 'Clear' ? 1 : weatherCondition === 'Rain' ? 1.4 : 1.2;
const nightMultiplier = (timeOfDay >= 22 || timeOfDay <= 5) ? 1.25 : 1;
segments.push({
start: coordinates[i],
end: coordinates[endIdx],
risk_probability: Math.min(0.85, baseRisk * weatherMultiplier * nightMultiplier),
traffic_level: 0.25 + Math.random() * 0.4
});
}
return {
segments,
incidents: [],
overallRisk: segments.length > 0 ? segments.reduce((a, b) => a + (b.risk_probability || 0), 0) / segments.length : 0.25
};
}