import type { TravelTimeEntry } from '../hooks/useTravelTime'; function mergeTimeRanges( current: [number, number] | null, next: [number, number] | null ): [number, number] | null { if (!current) return next; if (!next) return current; return [Math.max(current[0], next[0]), Math.min(current[1], next[1])]; } export function dedupeTravelTimeEntries(entries: TravelTimeEntry[]): TravelTimeEntry[] { const result: TravelTimeEntry[] = []; const indexByKey = new Map(); for (const entry of entries) { if (!entry.slug) { result.push(entry); continue; } const key = `${entry.mode}:${entry.slug}`; const existingIndex = indexByKey.get(key); if (existingIndex == null) { indexByKey.set(key, result.length); result.push({ ...entry }); continue; } const existing = result[existingIndex]; result[existingIndex] = { ...existing, label: existing.label || entry.label, timeRange: mergeTimeRanges(existing.timeRange, entry.timeRange), useBest: existing.useBest || entry.useBest, }; } return result; } export function buildTravelParam( entries: TravelTimeEntry[], excludeFieldKey?: string, includeUnboundedExcludedRange = false ): string { const segments: string[] = []; for (const entry of dedupeTravelTimeEntries(entries)) { if (!entry.slug) continue; let segment = `${entry.mode}:${entry.slug}`; if (entry.useBest) segment += ':best'; const isExcluded = excludeFieldKey === `tt_${entry.mode}_${entry.slug}`; if (isExcluded && includeUnboundedExcludedRange) { segment += ':0:1440'; } else if (!isExcluded && entry.timeRange) { segment += `:${entry.timeRange[0]}:${entry.timeRange[1]}`; } segments.push(segment); } return segments.join('|'); }