diff --git a/apps/api/src/maps/maps.service.ts b/apps/api/src/maps/maps.service.ts index 3111e46..007895a 100644 --- a/apps/api/src/maps/maps.service.ts +++ b/apps/api/src/maps/maps.service.ts @@ -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 = {}; + 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; }