feat(routing): smart street extraction and distinctive naming for main and alternative routes
This commit is contained in:
@@ -164,12 +164,34 @@ export class MapsService {
|
|||||||
const baseDuration = route.time / 1000;
|
const baseDuration = route.time / 1000;
|
||||||
const trafficAwareDuration = baseDuration * trafficFactor;
|
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 processedPaths = paths.map((p: any, index: number) => {
|
||||||
const pCoords = this.decodePolyline(p.points);
|
const pCoords = this.decodePolyline(p.points);
|
||||||
const pTrafficFactor = this.trafficGrid.getTrafficFactor(pCoords, hr, dow);
|
const pTrafficFactor = this.trafficGrid.getTrafficFactor(pCoords, hr, dow);
|
||||||
const pDuration = Math.round((p.time / 1000) * pTrafficFactor);
|
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
|
// Analyze slopes and enrich instructions
|
||||||
const { enrichedInstructions, slopeSummary } = this.enrichInstructionsWithSlopeAnalysis(p.instructions, pCoords);
|
const { enrichedInstructions, slopeSummary } = this.enrichInstructionsWithSlopeAnalysis(p.instructions, pCoords);
|
||||||
@@ -184,7 +206,7 @@ export class MapsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
routeName: routeName ? `عبر ${routeName}` : `المسار ${index + 1}`,
|
routeName: finalRouteName,
|
||||||
tags,
|
tags,
|
||||||
distance: p.distance,
|
distance: p.distance,
|
||||||
duration: pDuration,
|
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;
|
if (!instructions || instructions.length === 0) return null;
|
||||||
|
|
||||||
const streetDistances: Record<string, number> = {};
|
const streetDistances: Record<string, number> = {};
|
||||||
|
|
||||||
for (const inst of instructions) {
|
for (const inst of instructions) {
|
||||||
if (inst.street_name && inst.street_name.trim() !== '') {
|
let candidate = inst.street_name?.trim();
|
||||||
streetDistances[inst.street_name] = (streetDistances[inst.street_name] || 0) + (inst.distance || 0);
|
|
||||||
|
// 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 longestStreet: string | null = null;
|
||||||
let maxDist = 0;
|
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;
|
return longestStreet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user