feat(routing): smart street extraction and distinctive naming for main and alternative routes

This commit is contained in:
Hamza-Ayed
2026-08-18 12:25:10 +03:00
parent 0a854c4302
commit ba4ae15eab
+64 -8
View File
@@ -164,12 +164,34 @@ export class MapsService {
const baseDuration = route.time / 1000;
const trafficAwareDuration = baseDuration * trafficFactor;
// Process all paths to add metadata (Names, Tags, Elevation & Slope Warnings)
// 1. Identify the primary route's major artery/street
const mainInstructions = paths[0]?.instructions || [];
const mainStreetName = this.getRouteName(mainInstructions);
// Process all paths to add metadata (Real Street Names, Tags, Elevation & Slope Warnings)
const processedPaths = paths.map((p: any, index: number) => {
const pCoords = this.decodePolyline(p.points);
const pTrafficFactor = this.trafficGrid.getTrafficFactor(pCoords, hr, dow);
const pDuration = Math.round((p.time / 1000) * pTrafficFactor);
const routeName = this.getRouteName(p.instructions);
// For alternative routes, find the distinctive street that differentiates it from the main route
let routeStreet = index === 0
? mainStreetName
: this.getRouteName(p.instructions, mainStreetName || undefined);
// Fallback to any valid street name if differential lookup didn't find one
if (!routeStreet) {
routeStreet = this.getRouteName(p.instructions);
}
// Format route name with Arabic prefix
let finalRouteName = '';
if (routeStreet) {
const cleanStreet = routeStreet.replace(/^عبر\s+/, '').trim();
finalRouteName = `عبر ${cleanStreet}`;
} else {
finalRouteName = index === 0 ? 'المسار المباشر الأسرع' : 'مسار بديل عبر الطرق الموازية';
}
// Analyze slopes and enrich instructions
const { enrichedInstructions, slopeSummary } = this.enrichInstructionsWithSlopeAnalysis(p.instructions, pCoords);
@@ -184,7 +206,7 @@ export class MapsService {
}
return {
routeName: routeName ? `عبر ${routeName}` : `المسار ${index + 1}`,
routeName: finalRouteName,
tags,
distance: p.distance,
duration: pDuration,
@@ -430,18 +452,47 @@ export class MapsService {
}
/**
* Extract the most significant street name from instructions to name the route.
* Intelligently extracts the most descriptive, distinctive street or highway name for a route.
*/
private getRouteName(instructions: any[]): string | null {
private getRouteName(instructions: any[], excludeStreet?: string): string | null {
if (!instructions || instructions.length === 0) return null;
const streetDistances: Record<string, number> = {};
for (const inst of instructions) {
if (inst.street_name && inst.street_name.trim() !== '') {
streetDistances[inst.street_name] = (streetDistances[inst.street_name] || 0) + (inst.distance || 0);
let candidate = inst.street_name?.trim();
// If street_name is empty, check highway ref or destination (e.g., Highway 35 / طريق جرش / طريق المطار)
if (!candidate || candidate === '') {
if (inst.street_destination_ref) {
candidate = `طريق ${inst.street_destination_ref}`;
} else if (inst.street_ref) {
candidate = `طريق ${inst.street_ref}`;
} else if (inst.street_destination) {
candidate = `طريق ${inst.street_destination}`;
}
}
// If still empty, attempt to extract named street from instruction text
if (!candidate || candidate === '') {
const match = inst.text?.match(/(?:عبر|في|إلى|خلال|من خلال)\s+(شارع\s+[\u0621-\u064A0-9\s]+|طريق\s+[\u0621-\u064A0-9\s]+|دوار\s+[\u0621-\u064A0-9\s]+|الدوار\s+[\u0621-\u064A0-9\s]+|جسر\s+[\u0621-\u064A0-9\s]+)/i);
if (match && match[1]) {
candidate = match[1].trim();
}
}
if (candidate && candidate !== '') {
// Remove trailing or leading noise
candidate = candidate.replace(/^عبر\s+/, '').trim();
// If we have an exclusion, only add if different
if (!excludeStreet || candidate !== excludeStreet.replace(/^عبر\s+/, '').trim()) {
streetDistances[candidate] = (streetDistances[candidate] || 0) + (inst.distance || 1);
}
}
}
// Pick candidate with longest distance
let longestStreet: string | null = null;
let maxDist = 0;
@@ -452,6 +503,11 @@ export class MapsService {
}
}
// If no non-excluded street found, fallback to any longest street
if (!longestStreet && excludeStreet) {
return this.getRouteName(instructions);
}
return longestStreet;
}