@proximap/cli 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -116,7 +116,9 @@ function renderGeocode(places, ambiguous = false) {
116
116
  const lines = [];
117
117
  if (ambiguous) {
118
118
  lines.push(
119
- pc.yellow(`\u26A0 Ambiguous \u2014 ${places.length} distinct places match this name; pick one:`),
119
+ pc.yellow(
120
+ `\u26A0 Ambiguous \u2014 distinct places share this name; showing ${places.length} candidates, pick one:`
121
+ ),
120
122
  ""
121
123
  );
122
124
  }
@@ -242,7 +244,7 @@ function renderComparison(report) {
242
244
  }
243
245
 
244
246
  // src/index.ts
245
- var VERSION = "1.0.0";
247
+ var VERSION = "1.0.1";
246
248
  function collect(value, previous) {
247
249
  return [...previous, value];
248
250
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/render.ts"],"sourcesContent":["import { readFileSync, writeFileSync } from 'node:fs';\nimport {\n compareLocations,\n DatasetPlacesProvider,\n detectGaps,\n disambiguateLocation,\n findNearbyAmenities,\n ODBL_ATTRIBUTION,\n planErrands,\n reachableAmenities,\n snapshotArea,\n toCSV,\n toGeoJSON,\n ValhallaRoutingProvider,\n walkabilityScore,\n type CategoryWeight,\n type FacetFilters,\n type SnapshotDataset,\n type TravelMode,\n} from '@proximap/core';\nimport { Command } from 'commander';\nimport {\n renderComparison,\n renderErrands,\n renderGaps,\n renderGeocode,\n renderNearby,\n renderReachable,\n renderScore,\n} from './render';\n\nconst VERSION = '1.0.0';\n\ninterface NearOptions {\n radius: string;\n category: string[];\n filter: string[];\n accessible?: boolean;\n openNow?: boolean;\n openAt?: string;\n by?: string;\n mode: string;\n explain?: boolean;\n dataset?: string;\n limit: string;\n lang?: string;\n json?: boolean;\n format?: string;\n}\n\ninterface SnapshotCommandOptions {\n out?: string;\n radius: string;\n category: string[];\n lang?: string;\n}\n\ninterface BulkCommandOptions {\n ideal: string;\n max: string;\n lang?: string;\n}\n\ninterface GeocodeCommandOptions {\n limit: string;\n lang?: string;\n json?: boolean;\n}\n\ninterface GapsCommandOptions {\n category: string[];\n radius: string;\n threshold: string;\n lang?: string;\n json?: boolean;\n}\n\ninterface ScoreCommandOptions {\n ideal: string;\n max: string;\n lang?: string;\n json?: boolean;\n}\n\ninterface CompareCommandOptions {\n weights?: string;\n ideal: string;\n max: string;\n lang?: string;\n json?: boolean;\n}\n\ninterface ReachableCommandOptions {\n within: string;\n mode: string;\n category: string[];\n lang?: string;\n json?: boolean;\n}\n\ninterface ErrandsCommandOptions {\n category: string[];\n mode: string;\n end?: string;\n candidates: string;\n radius: string;\n lang?: string;\n json?: boolean;\n}\n\nfunction collect(value: string, previous: string[]): string[] {\n return [...previous, value];\n}\n\nfunction parsePositiveInt(value: string, name: string): number {\n const parsed = Number.parseInt(value, 10);\n if (!Number.isFinite(parsed) || parsed <= 0) {\n throw new Error(`--${name} must be a positive integer (got \"${value}\")`);\n }\n return parsed;\n}\n\nconst FALSY = new Set(['no', 'false', '0', '']);\n\nconst MODE_ALIASES: Record<string, TravelMode> = {\n walk: 'walk',\n walking: 'walk',\n foot: 'walk',\n bike: 'bike',\n cycling: 'bike',\n bicycle: 'bike',\n drive: 'drive',\n driving: 'drive',\n car: 'drive',\n};\n\nfunction parseMode(value: string): TravelMode {\n const mode = MODE_ALIASES[value.trim().toLowerCase()];\n if (!mode) throw new Error(`--mode must be walk, bike, or drive (got \"${value}\")`);\n return mode;\n}\n\n/** Parse a time budget like \"15\", \"15min\", or \"15 minutes\" into minutes. */\nfunction parseWithin(value: string): number {\n const match = value\n .trim()\n .toLowerCase()\n .match(/^(\\d+(?:\\.\\d+)?)\\s*(?:m|min|mins|minutes)?$/);\n const minutes = match ? Number(match[1]) : NaN;\n if (!Number.isFinite(minutes) || minutes <= 0) {\n throw new Error(`--within must be a positive number of minutes (got \"${value}\")`);\n }\n return minutes;\n}\n\n/** Parse repeatable `--filter key=value` (or bare `key`) pairs into FacetFilters. */\nfunction parseFilters(pairs: string[]): FacetFilters {\n const filters: FacetFilters = {};\n const tags: Record<string, string | boolean> = {};\n const push = (field: 'diet' | 'cuisine' | 'payment', value: string): void => {\n if (!value) return;\n const existing = filters[field];\n filters[field] = existing\n ? [...(Array.isArray(existing) ? existing : [existing]), value]\n : value;\n };\n\n for (const pair of pairs) {\n const eq = pair.indexOf('=');\n const key = (eq === -1 ? pair : pair.slice(0, eq)).trim().toLowerCase();\n const raw = eq === -1 ? '' : pair.slice(eq + 1).trim();\n const bool = eq === -1 ? true : !FALSY.has(raw.toLowerCase());\n\n switch (key) {\n case 'diet':\n case 'cuisine':\n case 'payment':\n push(key, raw);\n break;\n case 'wheelchair':\n filters.wheelchair = raw || 'yes';\n break;\n case 'wifi':\n case 'internet':\n case 'internet_access':\n filters.internetAccess = bool;\n break;\n case 'takeaway':\n filters.takeaway = bool;\n break;\n case 'delivery':\n filters.delivery = bool;\n break;\n case 'outdoor':\n case 'outdoor_seating':\n filters.outdoorSeating = bool;\n break;\n default:\n tags[key] = eq === -1 ? true : raw;\n break;\n }\n }\n if (Object.keys(tags).length > 0) filters.tags = tags;\n return filters;\n}\n\n/** Load a proximap snapshot file for offline POI queries. */\nfunction loadDataset(path: string): SnapshotDataset {\n const data: unknown = JSON.parse(readFileSync(path, 'utf8'));\n if (!data || typeof data !== 'object' || !Array.isArray((data as SnapshotDataset).pois)) {\n throw new Error(`not a proximap snapshot (no \"pois\" array): ${path}`);\n }\n return data as SnapshotDataset;\n}\n\n/** Quote a CSV field when it contains a comma, quote, or newline (RFC 4180). */\nfunction csvField(value: string): string {\n return /[\",\\n\\r]/.test(value) ? `\"${value.replace(/\"/g, '\"\"')}\"` : value;\n}\n\nasync function runNear(query: string, options: NearOptions): Promise<void> {\n const radiusMeters = parsePositiveInt(options.radius, 'radius');\n const limit = parsePositiveInt(options.limit, 'limit');\n\n const filters = parseFilters(options.filter);\n const open = options.openAt ? { at: options.openAt } : options.openNow ? 'now' : undefined;\n const byTravelTime = options.by !== undefined && /time/i.test(options.by);\n const places = options.dataset\n ? new DatasetPlacesProvider(loadDataset(options.dataset))\n : undefined;\n const result = await findNearbyAmenities(query, {\n radiusMeters,\n limit,\n ...(places ? { places } : {}),\n ...(options.category.length > 0 ? { categories: options.category } : {}),\n ...(Object.keys(filters).length > 0 ? { filters } : {}),\n ...(options.accessible ? { accessible: true } : {}),\n ...(open ? { open } : {}),\n // Use the key-free public Valhalla engine for real road-network times; core\n // falls back to straight-line estimates if it is unavailable.\n ...(byTravelTime\n ? {\n rankBy: 'travelTime' as const,\n mode: parseMode(options.mode),\n routing: new ValhallaRoutingProvider(),\n }\n : {}),\n ...(options.explain ? { explain: true } : {}),\n ...(options.lang ? { language: options.lang } : {}),\n });\n\n if (options.format) {\n const format = options.format.toLowerCase();\n if (format === 'geojson')\n process.stdout.write(`${JSON.stringify(toGeoJSON(result), null, 2)}\\n`);\n else if (format === 'csv') process.stdout.write(`${toCSV(result)}\\n`);\n else throw new Error(`unknown --format \"${options.format}\" (use geojson or csv)`);\n // Keep the ODbL notice off stdout so the data stays pipeable to a file.\n process.stderr.write(`${ODBL_ATTRIBUTION}\\n`);\n return;\n }\n\n const output = options.json ? JSON.stringify(result, null, 2) : renderNearby(result);\n process.stdout.write(`${output}\\n`);\n}\n\nasync function runGeocode(query: string, options: GeocodeCommandOptions): Promise<void> {\n const result = await disambiguateLocation(query, {\n limit: parsePositiveInt(options.limit, 'limit'),\n ...(options.lang ? { language: options.lang } : {}),\n });\n const output = options.json\n ? JSON.stringify(result, null, 2)\n : renderGeocode(result.candidates, result.ambiguous);\n process.stdout.write(`${output}\\n`);\n}\n\nasync function runGaps(query: string, options: GapsCommandOptions): Promise<void> {\n const searchRadiusMeters = parsePositiveInt(options.radius, 'radius');\n const thresholdMeters = parsePositiveInt(options.threshold, 'threshold');\n const report = await detectGaps(query, {\n searchRadiusMeters,\n thresholdMeters,\n ...(options.category.length > 0 ? { categories: options.category } : {}),\n ...(options.lang ? { language: options.lang } : {}),\n });\n const output = options.json ? JSON.stringify(report, null, 2) : renderGaps(report);\n process.stdout.write(`${output}\\n`);\n}\n\nasync function runScore(query: string, options: ScoreCommandOptions): Promise<void> {\n const idealMeters = parsePositiveInt(options.ideal, 'ideal');\n const maxMeters = parsePositiveInt(options.max, 'max');\n if (maxMeters <= idealMeters) {\n throw new Error('--max must be greater than --ideal');\n }\n const report = await walkabilityScore(query, {\n decay: { idealMeters, maxMeters },\n ...(options.lang ? { language: options.lang } : {}),\n });\n const output = options.json ? JSON.stringify(report, null, 2) : renderScore(report);\n process.stdout.write(`${output}\\n`);\n}\n\n/** Parse `term=weight,term=weight` into CategoryWeight[]. */\nfunction parseWeights(spec: string): CategoryWeight[] {\n const weights: CategoryWeight[] = [];\n for (const part of spec.split(',')) {\n const [term, value] = part.split('=');\n const name = (term ?? '').trim();\n const weight = Number(value);\n if (!name || !Number.isFinite(weight) || weight <= 0) {\n throw new Error(`invalid --weights entry: \"${part}\" (use term=weight, e.g. food=2)`);\n }\n weights.push({ term: name, weight });\n }\n if (weights.length === 0) throw new Error('--weights needs at least one term=weight');\n return weights;\n}\n\nasync function runCompare(queries: string[], options: CompareCommandOptions): Promise<void> {\n const idealMeters = parsePositiveInt(options.ideal, 'ideal');\n const maxMeters = parsePositiveInt(options.max, 'max');\n if (maxMeters <= idealMeters) {\n throw new Error('--max must be greater than --ideal');\n }\n const categories = options.weights ? parseWeights(options.weights) : undefined;\n const report = await compareLocations(queries, {\n decay: { idealMeters, maxMeters },\n ...(categories ? { categories } : {}),\n ...(options.lang ? { language: options.lang } : {}),\n });\n const output = options.json ? JSON.stringify(report, null, 2) : renderComparison(report);\n process.stdout.write(`${output}\\n`);\n}\n\nasync function runReachable(query: string, options: ReachableCommandOptions): Promise<void> {\n const result = await reachableAmenities(query, {\n within: parseWithin(options.within),\n mode: parseMode(options.mode),\n routing: new ValhallaRoutingProvider(),\n ...(options.category.length > 0 ? { categories: options.category } : {}),\n ...(options.lang ? { language: options.lang } : {}),\n });\n const output = options.json ? JSON.stringify(result, null, 2) : renderReachable(result);\n process.stdout.write(`${output}\\n`);\n}\n\nasync function runErrands(query: string, options: ErrandsCommandOptions): Promise<void> {\n if (options.category.length === 0) {\n throw new Error('errands needs at least one -c/--category');\n }\n const plan = await planErrands(query, {\n categories: options.category,\n mode: parseMode(options.mode),\n candidatesPerCategory: parsePositiveInt(options.candidates, 'candidates'),\n searchRadiusMeters: parsePositiveInt(options.radius, 'radius'),\n ...(options.end ? { end: options.end } : {}),\n ...(options.lang ? { language: options.lang } : {}),\n });\n const output = options.json ? JSON.stringify(plan, null, 2) : renderErrands(plan);\n process.stdout.write(`${output}\\n`);\n}\n\nasync function runSnapshot(query: string, options: SnapshotCommandOptions): Promise<void> {\n const dataset = await snapshotArea(query, {\n radiusMeters: parsePositiveInt(options.radius, 'radius'),\n ...(options.category.length > 0 ? { categories: options.category } : {}),\n ...(options.lang ? { language: options.lang } : {}),\n });\n const json = JSON.stringify(dataset, null, 2);\n if (options.out) {\n writeFileSync(options.out, `${json}\\n`, 'utf8');\n process.stderr.write(`Wrote ${dataset.pois.length} POIs to ${options.out}\\n`);\n } else {\n process.stdout.write(`${json}\\n`);\n }\n process.stderr.write(`${ODBL_ATTRIBUTION}\\n`);\n}\n\nasync function runBulk(file: string, options: BulkCommandOptions): Promise<void> {\n const idealMeters = parsePositiveInt(options.ideal, 'ideal');\n const maxMeters = parsePositiveInt(options.max, 'max');\n if (maxMeters <= idealMeters) throw new Error('--max must be greater than --ideal');\n\n const locations = readFileSync(file, 'utf8')\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line.length > 0 && !line.startsWith('#'));\n\n process.stdout.write('location,lat,lng,score,confidence,missing\\n');\n for (const location of locations) {\n try {\n const report = await walkabilityScore(location, {\n decay: { idealMeters, maxMeters },\n ...(options.lang ? { language: options.lang } : {}),\n });\n const { lat, lng } = report.origin.location;\n process.stdout.write(\n `${csvField(location)},${lat},${lng},${report.score},${report.confidence},${csvField(report.missing.join(';'))}\\n`,\n );\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n process.stdout.write(`${csvField(location)},,,,,${csvField(`error: ${message}`)}\\n`);\n }\n }\n process.stderr.write(`${ODBL_ATTRIBUTION}\\n`);\n}\n\nfunction fail(error: unknown): never {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`proximap: ${message}\\n`);\n process.exit(1);\n}\n\nconst program = new Command();\nprogram\n .name('proximap')\n .description('Find and rank what is near any place — powered by OpenStreetMap.')\n .version(VERSION)\n .showHelpAfterError('(run with --help for usage)');\n\nprogram\n .command('near')\n .description('list nearby amenities ranked by distance')\n .argument('<query...>', 'place name, address, or \"lat,lng\"')\n .option('-r, --radius <meters>', 'search radius in metres', '1000')\n .option(\n '-c, --category <term>',\n 'restrict to a category or term, e.g. coffee (repeatable)',\n collect,\n [],\n )\n .option(\n '-f, --filter <key=value>',\n 'facet filter, e.g. diet=vegan, payment=contactless, wifi (repeatable)',\n collect,\n [],\n )\n .option('--accessible', 'rank step-free / wheelchair-accessible places first')\n .option('--open-now', 'keep only places open right now (unknown hours kept, labelled)')\n .option('--open-at <when>', 'keep only places open at an ISO time, e.g. 2026-06-20T21:00')\n .option('--by <metric>', 'rank by distance (default) or travel-time')\n .option('--mode <mode>', 'travel mode for --by travel-time: walk, bike, drive', 'walk')\n .option('--explain', 'annotate each result with a short ranking reason')\n .option(\n '--dataset <file>',\n 'query a local snapshot file offline (use \"lat,lng\" for full offline)',\n )\n .option('-n, --limit <count>', 'maximum number of results', '20')\n .option('--lang <code>', 'preferred language for place names (e.g. en)')\n .option('--json', 'output raw JSON instead of a list')\n .option('--format <type>', 'export results as geojson or csv (ODbL notice on stderr)')\n .action((parts: string[], options: NearOptions) => runNear(parts.join(' '), options));\n\nprogram\n .command('geocode')\n .description('resolve a place name to coordinates')\n .argument('<query...>', 'place name or address')\n .option('-n, --limit <count>', 'maximum number of candidates', '5')\n .option('--lang <code>', 'preferred language')\n .option('--json', 'output raw JSON')\n .action((parts: string[], options: GeocodeCommandOptions) =>\n runGeocode(parts.join(' '), options),\n );\n\nprogram\n .command('gaps')\n .description('report which everyday amenities are missing near a place')\n .argument('<query...>', 'place name, address, or \"lat,lng\"')\n .option(\n '-c, --category <term>',\n 'category to check (repeatable; default: daily needs)',\n collect,\n [],\n )\n .option('-r, --radius <meters>', 'how far to search for the nearest match', '5000')\n .option('-t, --threshold <meters>', 'distance beyond which a category is a gap', '1500')\n .option('--lang <code>', 'preferred language')\n .option('--json', 'output raw JSON')\n .action((parts: string[], options: GapsCommandOptions) => runGaps(parts.join(' '), options));\n\nprogram\n .command('score')\n .description('rate how walkable / well-served a place is (0-100, with a breakdown)')\n .argument('<query...>', 'place name, address, or \"lat,lng\"')\n .option('--ideal <meters>', 'distance that still scores full marks (≈5-min walk)', '400')\n .option('--max <meters>', 'distance beyond which a category scores zero (≈30-min walk)', '2400')\n .option('--lang <code>', 'preferred language')\n .option('--json', 'output raw JSON')\n .action((parts: string[], options: ScoreCommandOptions) => runScore(parts.join(' '), options));\n\nprogram\n .command('reachable')\n .description('list amenities reachable within a time budget (isochrone)')\n .argument('<query...>', 'place name, address, or \"lat,lng\"')\n .option('--within <minutes>', 'time budget, e.g. 15 or 15min', '15')\n .option('--mode <mode>', 'travel mode: walk, bike, drive', 'walk')\n .option('-c, --category <term>', 'restrict to a category or term (repeatable)', collect, [])\n .option('--lang <code>', 'preferred language')\n .option('--json', 'output raw JSON')\n .action((parts: string[], options: ReachableCommandOptions) =>\n runReachable(parts.join(' '), options),\n );\n\nprogram\n .command('errands')\n .description('plan the shortest trip that hits one of each category')\n .argument('<query...>', 'starting place name, address, or \"lat,lng\"')\n .option('-c, --category <term>', 'a category to hit one of (repeatable, required)', collect, [])\n .option('--mode <mode>', 'travel mode: walk, bike, drive', 'walk')\n .option('--end <place>', 'optional fixed end point')\n .option('--candidates <count>', 'nearest candidates considered per category', '5')\n .option('-r, --radius <meters>', 'how far to look for candidates', '3000')\n .option('--lang <code>', 'preferred language')\n .option('--json', 'output raw JSON')\n .action((parts: string[], options: ErrandsCommandOptions) =>\n runErrands(parts.join(' '), options),\n );\n\nprogram\n .command('compare')\n .description('compare 2+ locations by access to what you care about')\n .argument('<locations...>', 'two or more quoted place names, addresses, or \"lat,lng\"')\n .option(\n '-w, --weights <list>',\n 'comma list term=weight, e.g. food=2,transport=3 (default: daily needs)',\n )\n .option('--ideal <meters>', 'distance that still scores full marks', '400')\n .option('--max <meters>', 'distance beyond which a category scores zero', '2400')\n .option('--lang <code>', 'preferred language')\n .option('--json', 'output raw JSON')\n .action((locations: string[], options: CompareCommandOptions) => runCompare(locations, options));\n\nprogram\n .command('snapshot')\n .description(\"capture an area's POIs to a file for offline reuse (ODbL — yours to store)\")\n .argument('<query...>', 'area center: place name, address, or \"lat,lng\"')\n .option('-o, --out <file>', 'write the snapshot JSON to this file (else stdout)')\n .option('-r, --radius <meters>', 'radius to capture', '2000')\n .option(\n '-c, --category <term>',\n 'restrict the capture to a category/term (repeatable)',\n collect,\n [],\n )\n .option('--lang <code>', 'preferred language')\n .action((parts: string[], options: SnapshotCommandOptions) =>\n runSnapshot(parts.join(' '), options),\n );\n\nprogram\n .command('bulk')\n .description('walkability-score many locations from a file (one per line) → CSV')\n .argument('<file>', 'text file with one place/address/\"lat,lng\" per line (# comments allowed)')\n .option('--ideal <meters>', 'distance that still scores full marks', '400')\n .option('--max <meters>', 'distance beyond which a category scores zero', '2400')\n .option('--lang <code>', 'preferred language')\n .action((file: string, options: BulkCommandOptions) => runBulk(file, options));\n\nprogram.parseAsync().catch(fail);\n","import {\n CATEGORY_LABELS,\n formatDistance,\n formatDuration,\n type ComparisonReport,\n type ErrandPlan,\n type GapReport,\n type NearbyResult,\n type OpenState,\n type Place,\n type RankedPoi,\n type ReachableResult,\n type WalkabilityReport,\n} from '@proximap/core';\nimport pc from 'picocolors';\n\nconst MODE_WORDS: Record<string, string> = { walk: 'walking', bike: 'cycling', drive: 'driving' };\n\nfunction coordString(lat: number, lng: number): string {\n return `${lat.toFixed(5)}, ${lng.toFixed(5)}`;\n}\n\n/** Render a nearby-search result as a numbered list (by distance, or travel time). */\nexport function renderNearby(result: NearbyResult): string {\n const { origin, results, total, routing } = result;\n const lines: string[] = [\n pc.bold(origin.displayName),\n pc.dim(\n `${coordString(origin.location.lat, origin.location.lng)} · ${total} found, showing ${results.length}`,\n ),\n ];\n if (routing) {\n const word = MODE_WORDS[routing.mode] ?? routing.mode;\n lines.push(\n pc.dim(\n routing.fellBack\n ? `ranked by ${word} time (straight-line estimate — routing engine unavailable)`\n : `ranked by ${word} time via ${routing.provider}`,\n ),\n );\n }\n lines.push('');\n\n if (results.length === 0) {\n lines.push(pc.dim('No amenities found within the search radius.'));\n return lines.join('\\n');\n }\n\n const rankWidth = String(results.length).length;\n for (const poi of results) {\n const rank = String(poi.rank).padStart(rankWidth);\n const label = CATEGORY_LABELS[poi.category];\n const name = poi.name ?? poi.kind ?? label;\n const distance = formatDistance(poi.distanceMeters);\n const metric =\n poi.travelSeconds !== undefined\n ? `${formatDuration(poi.travelSeconds)} · ${distance}`\n : distance;\n // With --explain, the reason (\"closest open cafe, 240 m\") replaces the meta.\n const meta = pc.dim(poi.rankingReason ?? `${label} · ${metric}`);\n const tags = `${accessibilityMark(poi.tags.wheelchair)}${poi.rankingReason ? '' : openMark(poi)}`;\n lines.push(`${pc.dim(`${rank}.`)} ${name} ${meta}${tags}`);\n }\n return lines.join('\\n');\n}\n\n/** A compact step-free indicator for the nearby list, shown only when tagged. */\nfunction accessibilityMark(wheelchair: string | undefined): string {\n if (wheelchair === 'yes') return ` ${pc.green('♿')}`;\n if (wheelchair === 'limited') return ` ${pc.yellow('♿ limited')}`;\n return '';\n}\n\nconst localHhmm = (iso: string): string => {\n const date = new Date(iso);\n return `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;\n};\n\n/** An open/closed indicator, shown only when an `open` query was made. */\nfunction openMark(poi: RankedPoi): string {\n const state: OpenState | undefined = poi.openState;\n if (state === 'open') {\n const till = poi.nextChange ? ` ${pc.dim(`till ${localHhmm(poi.nextChange)}`)}` : '';\n return ` ${pc.green('open')}${till}`;\n }\n if (state === 'unknown') return ` ${pc.dim('hours?')}`;\n return '';\n}\n\n/** Render an isochrone-reachability result: what's within the time budget. */\nexport function renderReachable(result: ReachableResult): string {\n const { origin, results, withinMinutes, mode, isochrone, count } = result;\n const word = MODE_WORDS[mode] ?? mode;\n const basis = isochrone ? 'isochrone' : 'straight-line estimate';\n const lines: string[] = [\n pc.bold(origin.displayName),\n pc.dim(\n `${coordString(origin.location.lat, origin.location.lng)} · ` +\n `${count} reachable within ${withinMinutes} min ${word} (${basis})`,\n ),\n '',\n ];\n if (results.length === 0) {\n lines.push(pc.dim('Nothing reachable within that budget.'));\n return lines.join('\\n');\n }\n const rankWidth = String(results.length).length;\n for (const poi of results) {\n const rank = String(poi.rank).padStart(rankWidth);\n const label = CATEGORY_LABELS[poi.category];\n const name = poi.name ?? poi.kind ?? label;\n const distance = formatDistance(poi.distanceMeters);\n const metric =\n poi.travelSeconds !== undefined\n ? `${formatDuration(poi.travelSeconds)} · ${distance}`\n : distance;\n lines.push(\n `${pc.dim(`${rank}.`)} ${name} ${pc.dim(`${label} · ${metric}`)}${accessibilityMark(poi.tags.wheelchair)}`,\n );\n }\n return lines.join('\\n');\n}\n\n/** Render geocoding candidates with their addresses and coordinates. */\nexport function renderGeocode(places: Place[], ambiguous = false): string {\n if (places.length === 0) return 'No matches found.';\n\n const rankWidth = String(places.length).length;\n const lines: string[] = [];\n if (ambiguous) {\n lines.push(\n pc.yellow(`⚠ Ambiguous — ${places.length} distinct places match this name; pick one:`),\n '',\n );\n }\n places.forEach((place, index) => {\n const rank = String(index + 1).padStart(rankWidth);\n lines.push(`${pc.dim(`${rank}.`)} ${pc.bold(place.name)}`);\n lines.push(` ${pc.dim(place.displayName)}`);\n lines.push(` ${pc.dim(coordString(place.location.lat, place.location.lng))}`);\n });\n return lines.join('\\n');\n}\n\nfunction titleCase(value: string): string {\n return value.charAt(0).toUpperCase() + value.slice(1);\n}\n\n/** Render an amenity-gap report as a checklist with distances. */\nexport function renderGaps(report: GapReport): string {\n const { origin, gaps, missing, searchRadiusMeters, thresholdMeters } = report;\n const lines: string[] = [\n pc.bold(origin.displayName),\n pc.dim(\n `${coordString(origin.location.lat, origin.location.lng)} · searched ${formatDistance(searchRadiusMeters)}, gap if > ${formatDistance(thresholdMeters)}`,\n ),\n '',\n ];\n for (const gap of gaps) {\n const mark = gap.isGap ? pc.red('✗') : pc.green('✓');\n const detail =\n gap.nearestMeters === null\n ? pc.dim(`none within ${formatDistance(searchRadiusMeters)}`)\n : pc.dim(formatDistance(gap.nearestMeters));\n lines.push(`${mark} ${titleCase(gap.category)} ${detail}`);\n }\n lines.push('');\n lines.push(\n missing.length === 0\n ? pc.green('No gaps — all requested categories are nearby.')\n : pc.dim(`Missing (not found in OSM): ${missing.join(', ')}`),\n );\n return lines.join('\\n');\n}\n\n/** Render a walkability report: headline score, per-category breakdown, gaps. */\nexport function renderScore(report: WalkabilityReport): string {\n const { origin, score, confidence, breakdown, missing, decay } = report;\n const lines: string[] = [\n pc.bold(origin.displayName),\n pc.dim(\n `${coordString(origin.location.lat, origin.location.lng)} · ` +\n `walkability ${pc.bold(String(score))}/100 · confidence ${Math.round(confidence * 100)}%`,\n ),\n pc.dim(\n `full credit ≤ ${formatDistance(decay.idealMeters)}, none ≥ ${formatDistance(decay.maxMeters)}`,\n ),\n '',\n ];\n\n const nameWidth = Math.max(...breakdown.map((b) => titleCase(b.category).length));\n for (const entry of breakdown) {\n const mark =\n entry.subScore >= 0.67 ? pc.green('✓') : entry.subScore > 0 ? pc.yellow('~') : pc.red('✗');\n const name = titleCase(entry.category).padEnd(nameWidth);\n const detail =\n entry.nearestMeters === null\n ? pc.dim('none in range')\n : pc.dim(formatDistance(entry.nearestMeters));\n const pct = pc.dim(`${Math.round(entry.subScore * 100)}%`.padStart(4));\n lines.push(`${mark} ${name} ${pct} ${detail}`);\n }\n\n lines.push('');\n lines.push(\n missing.length === 0\n ? pc.green('All daily needs reachable within range.')\n : pc.dim(`Not found in OSM within range: ${missing.join(', ')}`),\n );\n if (confidence < 0.5) {\n lines.push(\n pc.yellow('Low confidence — OSM coverage here looks sparse; treat the score as a floor.'),\n );\n }\n return lines.join('\\n');\n}\n\n/** Render an errand plan: ordered stops with per-leg time, total, and any gaps. */\nexport function renderErrands(plan: ErrandPlan): string {\n const { origin, end, stops, totalSeconds, totalMeters, missing, mode } = plan;\n const word = MODE_WORDS[mode] ?? mode;\n const lines: string[] = [\n pc.bold(`Errand plan from ${origin.displayName}`),\n pc.dim(\n `${stops.length} stop${stops.length === 1 ? '' : 's'} · ` +\n `${formatDuration(totalSeconds)} ${word} · ${formatDistance(totalMeters)} (straight-line estimate)`,\n ),\n '',\n ];\n if (stops.length === 0) {\n lines.push(pc.dim('No reachable stops for the requested categories.'));\n }\n const stepWidth = String(stops.length).length;\n stops.forEach((stop, index) => {\n const step = String(index + 1).padStart(stepWidth);\n const name = stop.poi.name ?? stop.poi.kind ?? stop.category;\n const leg = pc.dim(`+${formatDuration(stop.legSeconds)} · ${formatDistance(stop.legMeters)}`);\n lines.push(`${pc.dim(`${step}.`)} ${pc.bold(titleCase(stop.category))}: ${name} ${leg}`);\n });\n if (end) lines.push(pc.dim(` ↳ end: ${end.displayName}`));\n if (missing.length > 0) {\n lines.push('');\n lines.push(pc.dim(`Not found nearby: ${missing.join(', ')}`));\n }\n return lines.join('\\n');\n}\n\n/** Render a location-comparison scorecard: ranked locations + per-dimension winners. */\nexport function renderComparison(report: ComparisonReport): string {\n const weightStr = report.weights.map((w) => `${titleCase(w.term)}×${w.weight}`).join(', ');\n const lines: string[] = [pc.bold('Location comparison'), pc.dim(`weights: ${weightStr}`), ''];\n\n const rankWidth = String(report.ranked.length).length;\n report.ranked.forEach((entry, position) => {\n const location = report.locations[entry.index]!;\n const marker = position === 0 ? pc.green('★') : ' ';\n const rank = String(position + 1).padStart(rankWidth);\n lines.push(`${marker} ${pc.dim(`${rank}.`)} ${pc.bold(entry.origin.displayName)}`);\n lines.push(\n ` ${pc.dim(`${entry.score}/100 · confidence ${Math.round(location.confidence * 100)}%`)}`,\n );\n });\n\n lines.push('');\n lines.push(pc.bold('Best per category:'));\n const nameWidth = Math.max(...report.dimensions.map((d) => titleCase(d.category).length));\n for (const dimension of report.dimensions) {\n const name = titleCase(dimension.category).padEnd(nameWidth);\n let detail: string;\n if (dimension.bestIndex === null) {\n detail = pc.dim('none found');\n } else {\n const location = report.locations[dimension.bestIndex]!;\n const entry = location.breakdown.find((b) => b.category === dimension.category);\n const distance =\n entry && entry.nearestMeters !== null\n ? pc.dim(` (${formatDistance(entry.nearestMeters)})`)\n : '';\n detail = `${location.origin.name}${distance}`;\n }\n lines.push(` ${name} ${detail}`);\n }\n return lines.join('\\n');\n}\n"],"mappings":";;;AAAA,SAAS,cAAc,qBAAqB;AAC5C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAKK;AACP,SAAS,eAAe;;;ACpBxB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAUK;AACP,OAAO,QAAQ;AAEf,IAAM,aAAqC,EAAE,MAAM,WAAW,MAAM,WAAW,OAAO,UAAU;AAEhG,SAAS,YAAY,KAAa,KAAqB;AACrD,SAAO,GAAG,IAAI,QAAQ,CAAC,CAAC,KAAK,IAAI,QAAQ,CAAC,CAAC;AAC7C;AAGO,SAAS,aAAa,QAA8B;AACzD,QAAM,EAAE,QAAQ,SAAS,OAAO,QAAQ,IAAI;AAC5C,QAAM,QAAkB;AAAA,IACtB,GAAG,KAAK,OAAO,WAAW;AAAA,IAC1B,GAAG;AAAA,MACD,GAAG,YAAY,OAAO,SAAS,KAAK,OAAO,SAAS,GAAG,CAAC,SAAM,KAAK,mBAAmB,QAAQ,MAAM;AAAA,IACtG;AAAA,EACF;AACA,MAAI,SAAS;AACX,UAAM,OAAO,WAAW,QAAQ,IAAI,KAAK,QAAQ;AACjD,UAAM;AAAA,MACJ,GAAG;AAAA,QACD,QAAQ,WACJ,aAAa,IAAI,qEACjB,aAAa,IAAI,aAAa,QAAQ,QAAQ;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACA,QAAM,KAAK,EAAE;AAEb,MAAI,QAAQ,WAAW,GAAG;AACxB,UAAM,KAAK,GAAG,IAAI,8CAA8C,CAAC;AACjE,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAEA,QAAM,YAAY,OAAO,QAAQ,MAAM,EAAE;AACzC,aAAW,OAAO,SAAS;AACzB,UAAM,OAAO,OAAO,IAAI,IAAI,EAAE,SAAS,SAAS;AAChD,UAAM,QAAQ,gBAAgB,IAAI,QAAQ;AAC1C,UAAM,OAAO,IAAI,QAAQ,IAAI,QAAQ;AACrC,UAAM,WAAW,eAAe,IAAI,cAAc;AAClD,UAAM,SACJ,IAAI,kBAAkB,SAClB,GAAG,eAAe,IAAI,aAAa,CAAC,SAAM,QAAQ,KAClD;AAEN,UAAM,OAAO,GAAG,IAAI,IAAI,iBAAiB,GAAG,KAAK,SAAM,MAAM,EAAE;AAC/D,UAAM,OAAO,GAAG,kBAAkB,IAAI,KAAK,UAAU,CAAC,GAAG,IAAI,gBAAgB,KAAK,SAAS,GAAG,CAAC;AAC/F,UAAM,KAAK,GAAG,GAAG,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,IAAI,KAAK,IAAI,GAAG,IAAI,EAAE;AAAA,EAC5D;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAGA,SAAS,kBAAkB,YAAwC;AACjE,MAAI,eAAe,MAAO,QAAO,KAAK,GAAG,MAAM,QAAG,CAAC;AACnD,MAAI,eAAe,UAAW,QAAO,KAAK,GAAG,OAAO,gBAAW,CAAC;AAChE,SAAO;AACT;AAEA,IAAM,YAAY,CAAC,QAAwB;AACzC,QAAM,OAAO,IAAI,KAAK,GAAG;AACzB,SAAO,GAAG,OAAO,KAAK,SAAS,CAAC,EAAE,SAAS,GAAG,GAAG,CAAC,IAAI,OAAO,KAAK,WAAW,CAAC,EAAE,SAAS,GAAG,GAAG,CAAC;AAClG;AAGA,SAAS,SAAS,KAAwB;AACxC,QAAM,QAA+B,IAAI;AACzC,MAAI,UAAU,QAAQ;AACpB,UAAM,OAAO,IAAI,aAAa,IAAI,GAAG,IAAI,QAAQ,UAAU,IAAI,UAAU,CAAC,EAAE,CAAC,KAAK;AAClF,WAAO,KAAK,GAAG,MAAM,MAAM,CAAC,GAAG,IAAI;AAAA,EACrC;AACA,MAAI,UAAU,UAAW,QAAO,KAAK,GAAG,IAAI,QAAQ,CAAC;AACrD,SAAO;AACT;AAGO,SAAS,gBAAgB,QAAiC;AAC/D,QAAM,EAAE,QAAQ,SAAS,eAAe,MAAM,WAAW,MAAM,IAAI;AACnE,QAAM,OAAO,WAAW,IAAI,KAAK;AACjC,QAAM,QAAQ,YAAY,cAAc;AACxC,QAAM,QAAkB;AAAA,IACtB,GAAG,KAAK,OAAO,WAAW;AAAA,IAC1B,GAAG;AAAA,MACD,GAAG,YAAY,OAAO,SAAS,KAAK,OAAO,SAAS,GAAG,CAAC,SACnD,KAAK,qBAAqB,aAAa,QAAQ,IAAI,KAAK,KAAK;AAAA,IACpE;AAAA,IACA;AAAA,EACF;AACA,MAAI,QAAQ,WAAW,GAAG;AACxB,UAAM,KAAK,GAAG,IAAI,uCAAuC,CAAC;AAC1D,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AACA,QAAM,YAAY,OAAO,QAAQ,MAAM,EAAE;AACzC,aAAW,OAAO,SAAS;AACzB,UAAM,OAAO,OAAO,IAAI,IAAI,EAAE,SAAS,SAAS;AAChD,UAAM,QAAQ,gBAAgB,IAAI,QAAQ;AAC1C,UAAM,OAAO,IAAI,QAAQ,IAAI,QAAQ;AACrC,UAAM,WAAW,eAAe,IAAI,cAAc;AAClD,UAAM,SACJ,IAAI,kBAAkB,SAClB,GAAG,eAAe,IAAI,aAAa,CAAC,SAAM,QAAQ,KAClD;AACN,UAAM;AAAA,MACJ,GAAG,GAAG,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,IAAI,KAAK,GAAG,IAAI,GAAG,KAAK,SAAM,MAAM,EAAE,CAAC,GAAG,kBAAkB,IAAI,KAAK,UAAU,CAAC;AAAA,IAC3G;AAAA,EACF;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAGO,SAAS,cAAc,QAAiB,YAAY,OAAe;AACxE,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,QAAM,YAAY,OAAO,OAAO,MAAM,EAAE;AACxC,QAAM,QAAkB,CAAC;AACzB,MAAI,WAAW;AACb,UAAM;AAAA,MACJ,GAAG,OAAO,2BAAiB,OAAO,MAAM,6CAA6C;AAAA,MACrF;AAAA,IACF;AAAA,EACF;AACA,SAAO,QAAQ,CAAC,OAAO,UAAU;AAC/B,UAAM,OAAO,OAAO,QAAQ,CAAC,EAAE,SAAS,SAAS;AACjD,UAAM,KAAK,GAAG,GAAG,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,GAAG,KAAK,MAAM,IAAI,CAAC,EAAE;AACzD,UAAM,KAAK,MAAM,GAAG,IAAI,MAAM,WAAW,CAAC,EAAE;AAC5C,UAAM,KAAK,MAAM,GAAG,IAAI,YAAY,MAAM,SAAS,KAAK,MAAM,SAAS,GAAG,CAAC,CAAC,EAAE;AAAA,EAChF,CAAC;AACD,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,UAAU,OAAuB;AACxC,SAAO,MAAM,OAAO,CAAC,EAAE,YAAY,IAAI,MAAM,MAAM,CAAC;AACtD;AAGO,SAAS,WAAW,QAA2B;AACpD,QAAM,EAAE,QAAQ,MAAM,SAAS,oBAAoB,gBAAgB,IAAI;AACvE,QAAM,QAAkB;AAAA,IACtB,GAAG,KAAK,OAAO,WAAW;AAAA,IAC1B,GAAG;AAAA,MACD,GAAG,YAAY,OAAO,SAAS,KAAK,OAAO,SAAS,GAAG,CAAC,kBAAe,eAAe,kBAAkB,CAAC,cAAc,eAAe,eAAe,CAAC;AAAA,IACxJ;AAAA,IACA;AAAA,EACF;AACA,aAAW,OAAO,MAAM;AACtB,UAAM,OAAO,IAAI,QAAQ,GAAG,IAAI,QAAG,IAAI,GAAG,MAAM,QAAG;AACnD,UAAM,SACJ,IAAI,kBAAkB,OAClB,GAAG,IAAI,eAAe,eAAe,kBAAkB,CAAC,EAAE,IAC1D,GAAG,IAAI,eAAe,IAAI,aAAa,CAAC;AAC9C,UAAM,KAAK,GAAG,IAAI,IAAI,UAAU,IAAI,QAAQ,CAAC,KAAK,MAAM,EAAE;AAAA,EAC5D;AACA,QAAM,KAAK,EAAE;AACb,QAAM;AAAA,IACJ,QAAQ,WAAW,IACf,GAAG,MAAM,qDAAgD,IACzD,GAAG,IAAI,+BAA+B,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,EAChE;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAGO,SAAS,YAAY,QAAmC;AAC7D,QAAM,EAAE,QAAQ,OAAO,YAAY,WAAW,SAAS,MAAM,IAAI;AACjE,QAAM,QAAkB;AAAA,IACtB,GAAG,KAAK,OAAO,WAAW;AAAA,IAC1B,GAAG;AAAA,MACD,GAAG,YAAY,OAAO,SAAS,KAAK,OAAO,SAAS,GAAG,CAAC,qBACvC,GAAG,KAAK,OAAO,KAAK,CAAC,CAAC,wBAAqB,KAAK,MAAM,aAAa,GAAG,CAAC;AAAA,IAC1F;AAAA,IACA,GAAG;AAAA,MACD,sBAAiB,eAAe,MAAM,WAAW,CAAC,iBAAY,eAAe,MAAM,SAAS,CAAC;AAAA,IAC/F;AAAA,IACA;AAAA,EACF;AAEA,QAAM,YAAY,KAAK,IAAI,GAAG,UAAU,IAAI,CAAC,MAAM,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC;AAChF,aAAW,SAAS,WAAW;AAC7B,UAAM,OACJ,MAAM,YAAY,OAAO,GAAG,MAAM,QAAG,IAAI,MAAM,WAAW,IAAI,GAAG,OAAO,GAAG,IAAI,GAAG,IAAI,QAAG;AAC3F,UAAM,OAAO,UAAU,MAAM,QAAQ,EAAE,OAAO,SAAS;AACvD,UAAM,SACJ,MAAM,kBAAkB,OACpB,GAAG,IAAI,eAAe,IACtB,GAAG,IAAI,eAAe,MAAM,aAAa,CAAC;AAChD,UAAM,MAAM,GAAG,IAAI,GAAG,KAAK,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,SAAS,CAAC,CAAC;AACrE,UAAM,KAAK,GAAG,IAAI,IAAI,IAAI,KAAK,GAAG,KAAK,MAAM,EAAE;AAAA,EACjD;AAEA,QAAM,KAAK,EAAE;AACb,QAAM;AAAA,IACJ,QAAQ,WAAW,IACf,GAAG,MAAM,yCAAyC,IAClD,GAAG,IAAI,kCAAkC,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,EACnE;AACA,MAAI,aAAa,KAAK;AACpB,UAAM;AAAA,MACJ,GAAG,OAAO,mFAA8E;AAAA,IAC1F;AAAA,EACF;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAGO,SAAS,cAAc,MAA0B;AACtD,QAAM,EAAE,QAAQ,KAAK,OAAO,cAAc,aAAa,SAAS,KAAK,IAAI;AACzE,QAAM,OAAO,WAAW,IAAI,KAAK;AACjC,QAAM,QAAkB;AAAA,IACtB,GAAG,KAAK,oBAAoB,OAAO,WAAW,EAAE;AAAA,IAChD,GAAG;AAAA,MACD,GAAG,MAAM,MAAM,QAAQ,MAAM,WAAW,IAAI,KAAK,GAAG,SAC/C,eAAe,YAAY,CAAC,IAAI,IAAI,SAAM,eAAe,WAAW,CAAC;AAAA,IAC5E;AAAA,IACA;AAAA,EACF;AACA,MAAI,MAAM,WAAW,GAAG;AACtB,UAAM,KAAK,GAAG,IAAI,kDAAkD,CAAC;AAAA,EACvE;AACA,QAAM,YAAY,OAAO,MAAM,MAAM,EAAE;AACvC,QAAM,QAAQ,CAAC,MAAM,UAAU;AAC7B,UAAM,OAAO,OAAO,QAAQ,CAAC,EAAE,SAAS,SAAS;AACjD,UAAM,OAAO,KAAK,IAAI,QAAQ,KAAK,IAAI,QAAQ,KAAK;AACpD,UAAM,MAAM,GAAG,IAAI,IAAI,eAAe,KAAK,UAAU,CAAC,SAAM,eAAe,KAAK,SAAS,CAAC,EAAE;AAC5F,UAAM,KAAK,GAAG,GAAG,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,GAAG,KAAK,UAAU,KAAK,QAAQ,CAAC,CAAC,KAAK,IAAI,KAAK,GAAG,EAAE;AAAA,EAC1F,CAAC;AACD,MAAI,IAAK,OAAM,KAAK,GAAG,IAAI,kBAAa,IAAI,WAAW,EAAE,CAAC;AAC1D,MAAI,QAAQ,SAAS,GAAG;AACtB,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,GAAG,IAAI,qBAAqB,QAAQ,KAAK,IAAI,CAAC,EAAE,CAAC;AAAA,EAC9D;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAGO,SAAS,iBAAiB,QAAkC;AACjE,QAAM,YAAY,OAAO,QAAQ,IAAI,CAAC,MAAM,GAAG,UAAU,EAAE,IAAI,CAAC,OAAI,EAAE,MAAM,EAAE,EAAE,KAAK,IAAI;AACzF,QAAM,QAAkB,CAAC,GAAG,KAAK,qBAAqB,GAAG,GAAG,IAAI,YAAY,SAAS,EAAE,GAAG,EAAE;AAE5F,QAAM,YAAY,OAAO,OAAO,OAAO,MAAM,EAAE;AAC/C,SAAO,OAAO,QAAQ,CAAC,OAAO,aAAa;AACzC,UAAM,WAAW,OAAO,UAAU,MAAM,KAAK;AAC7C,UAAM,SAAS,aAAa,IAAI,GAAG,MAAM,QAAG,IAAI;AAChD,UAAM,OAAO,OAAO,WAAW,CAAC,EAAE,SAAS,SAAS;AACpD,UAAM,KAAK,GAAG,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,GAAG,KAAK,MAAM,OAAO,WAAW,CAAC,EAAE;AACjF,UAAM;AAAA,MACJ,QAAQ,GAAG,IAAI,GAAG,MAAM,KAAK,wBAAqB,KAAK,MAAM,SAAS,aAAa,GAAG,CAAC,GAAG,CAAC;AAAA,IAC7F;AAAA,EACF,CAAC;AAED,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,GAAG,KAAK,oBAAoB,CAAC;AACxC,QAAM,YAAY,KAAK,IAAI,GAAG,OAAO,WAAW,IAAI,CAAC,MAAM,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC;AACxF,aAAW,aAAa,OAAO,YAAY;AACzC,UAAM,OAAO,UAAU,UAAU,QAAQ,EAAE,OAAO,SAAS;AAC3D,QAAI;AACJ,QAAI,UAAU,cAAc,MAAM;AAChC,eAAS,GAAG,IAAI,YAAY;AAAA,IAC9B,OAAO;AACL,YAAM,WAAW,OAAO,UAAU,UAAU,SAAS;AACrD,YAAM,QAAQ,SAAS,UAAU,KAAK,CAAC,MAAM,EAAE,aAAa,UAAU,QAAQ;AAC9E,YAAM,WACJ,SAAS,MAAM,kBAAkB,OAC7B,GAAG,IAAI,KAAK,eAAe,MAAM,aAAa,CAAC,GAAG,IAClD;AACN,eAAS,GAAG,SAAS,OAAO,IAAI,GAAG,QAAQ;AAAA,IAC7C;AACA,UAAM,KAAK,KAAK,IAAI,KAAK,MAAM,EAAE;AAAA,EACnC;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;;;AD5PA,IAAM,UAAU;AA+EhB,SAAS,QAAQ,OAAe,UAA8B;AAC5D,SAAO,CAAC,GAAG,UAAU,KAAK;AAC5B;AAEA,SAAS,iBAAiB,OAAe,MAAsB;AAC7D,QAAM,SAAS,OAAO,SAAS,OAAO,EAAE;AACxC,MAAI,CAAC,OAAO,SAAS,MAAM,KAAK,UAAU,GAAG;AAC3C,UAAM,IAAI,MAAM,KAAK,IAAI,qCAAqC,KAAK,IAAI;AAAA,EACzE;AACA,SAAO;AACT;AAEA,IAAM,QAAQ,oBAAI,IAAI,CAAC,MAAM,SAAS,KAAK,EAAE,CAAC;AAE9C,IAAM,eAA2C;AAAA,EAC/C,MAAM;AAAA,EACN,SAAS;AAAA,EACT,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAAA,EACT,SAAS;AAAA,EACT,OAAO;AAAA,EACP,SAAS;AAAA,EACT,KAAK;AACP;AAEA,SAAS,UAAU,OAA2B;AAC5C,QAAM,OAAO,aAAa,MAAM,KAAK,EAAE,YAAY,CAAC;AACpD,MAAI,CAAC,KAAM,OAAM,IAAI,MAAM,6CAA6C,KAAK,IAAI;AACjF,SAAO;AACT;AAGA,SAAS,YAAY,OAAuB;AAC1C,QAAM,QAAQ,MACX,KAAK,EACL,YAAY,EACZ,MAAM,6CAA6C;AACtD,QAAM,UAAU,QAAQ,OAAO,MAAM,CAAC,CAAC,IAAI;AAC3C,MAAI,CAAC,OAAO,SAAS,OAAO,KAAK,WAAW,GAAG;AAC7C,UAAM,IAAI,MAAM,uDAAuD,KAAK,IAAI;AAAA,EAClF;AACA,SAAO;AACT;AAGA,SAAS,aAAa,OAA+B;AACnD,QAAM,UAAwB,CAAC;AAC/B,QAAM,OAAyC,CAAC;AAChD,QAAM,OAAO,CAAC,OAAuC,UAAwB;AAC3E,QAAI,CAAC,MAAO;AACZ,UAAM,WAAW,QAAQ,KAAK;AAC9B,YAAQ,KAAK,IAAI,WACb,CAAC,GAAI,MAAM,QAAQ,QAAQ,IAAI,WAAW,CAAC,QAAQ,GAAI,KAAK,IAC5D;AAAA,EACN;AAEA,aAAW,QAAQ,OAAO;AACxB,UAAM,KAAK,KAAK,QAAQ,GAAG;AAC3B,UAAM,OAAO,OAAO,KAAK,OAAO,KAAK,MAAM,GAAG,EAAE,GAAG,KAAK,EAAE,YAAY;AACtE,UAAM,MAAM,OAAO,KAAK,KAAK,KAAK,MAAM,KAAK,CAAC,EAAE,KAAK;AACrD,UAAM,OAAO,OAAO,KAAK,OAAO,CAAC,MAAM,IAAI,IAAI,YAAY,CAAC;AAE5D,YAAQ,KAAK;AAAA,MACX,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACH,aAAK,KAAK,GAAG;AACb;AAAA,MACF,KAAK;AACH,gBAAQ,aAAa,OAAO;AAC5B;AAAA,MACF,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACH,gBAAQ,iBAAiB;AACzB;AAAA,MACF,KAAK;AACH,gBAAQ,WAAW;AACnB;AAAA,MACF,KAAK;AACH,gBAAQ,WAAW;AACnB;AAAA,MACF,KAAK;AAAA,MACL,KAAK;AACH,gBAAQ,iBAAiB;AACzB;AAAA,MACF;AACE,aAAK,GAAG,IAAI,OAAO,KAAK,OAAO;AAC/B;AAAA,IACJ;AAAA,EACF;AACA,MAAI,OAAO,KAAK,IAAI,EAAE,SAAS,EAAG,SAAQ,OAAO;AACjD,SAAO;AACT;AAGA,SAAS,YAAY,MAA+B;AAClD,QAAM,OAAgB,KAAK,MAAM,aAAa,MAAM,MAAM,CAAC;AAC3D,MAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAS,KAAyB,IAAI,GAAG;AACvF,UAAM,IAAI,MAAM,8CAA8C,IAAI,EAAE;AAAA,EACtE;AACA,SAAO;AACT;AAGA,SAAS,SAAS,OAAuB;AACvC,SAAO,WAAW,KAAK,KAAK,IAAI,IAAI,MAAM,QAAQ,MAAM,IAAI,CAAC,MAAM;AACrE;AAEA,eAAe,QAAQ,OAAe,SAAqC;AACzE,QAAM,eAAe,iBAAiB,QAAQ,QAAQ,QAAQ;AAC9D,QAAM,QAAQ,iBAAiB,QAAQ,OAAO,OAAO;AAErD,QAAM,UAAU,aAAa,QAAQ,MAAM;AAC3C,QAAM,OAAO,QAAQ,SAAS,EAAE,IAAI,QAAQ,OAAO,IAAI,QAAQ,UAAU,QAAQ;AACjF,QAAM,eAAe,QAAQ,OAAO,UAAa,QAAQ,KAAK,QAAQ,EAAE;AACxE,QAAM,SAAS,QAAQ,UACnB,IAAI,sBAAsB,YAAY,QAAQ,OAAO,CAAC,IACtD;AACJ,QAAM,SAAS,MAAM,oBAAoB,OAAO;AAAA,IAC9C;AAAA,IACA;AAAA,IACA,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,IAC3B,GAAI,QAAQ,SAAS,SAAS,IAAI,EAAE,YAAY,QAAQ,SAAS,IAAI,CAAC;AAAA,IACtE,GAAI,OAAO,KAAK,OAAO,EAAE,SAAS,IAAI,EAAE,QAAQ,IAAI,CAAC;AAAA,IACrD,GAAI,QAAQ,aAAa,EAAE,YAAY,KAAK,IAAI,CAAC;AAAA,IACjD,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA,IAGvB,GAAI,eACA;AAAA,MACE,QAAQ;AAAA,MACR,MAAM,UAAU,QAAQ,IAAI;AAAA,MAC5B,SAAS,IAAI,wBAAwB;AAAA,IACvC,IACA,CAAC;AAAA,IACL,GAAI,QAAQ,UAAU,EAAE,SAAS,KAAK,IAAI,CAAC;AAAA,IAC3C,GAAI,QAAQ,OAAO,EAAE,UAAU,QAAQ,KAAK,IAAI,CAAC;AAAA,EACnD,CAAC;AAED,MAAI,QAAQ,QAAQ;AAClB,UAAM,SAAS,QAAQ,OAAO,YAAY;AAC1C,QAAI,WAAW;AACb,cAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,UAAU,MAAM,GAAG,MAAM,CAAC,CAAC;AAAA,CAAI;AAAA,aAC/D,WAAW,MAAO,SAAQ,OAAO,MAAM,GAAG,MAAM,MAAM,CAAC;AAAA,CAAI;AAAA,QAC/D,OAAM,IAAI,MAAM,qBAAqB,QAAQ,MAAM,wBAAwB;AAEhF,YAAQ,OAAO,MAAM,GAAG,gBAAgB;AAAA,CAAI;AAC5C;AAAA,EACF;AAEA,QAAM,SAAS,QAAQ,OAAO,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,aAAa,MAAM;AACnF,UAAQ,OAAO,MAAM,GAAG,MAAM;AAAA,CAAI;AACpC;AAEA,eAAe,WAAW,OAAe,SAA+C;AACtF,QAAM,SAAS,MAAM,qBAAqB,OAAO;AAAA,IAC/C,OAAO,iBAAiB,QAAQ,OAAO,OAAO;AAAA,IAC9C,GAAI,QAAQ,OAAO,EAAE,UAAU,QAAQ,KAAK,IAAI,CAAC;AAAA,EACnD,CAAC;AACD,QAAM,SAAS,QAAQ,OACnB,KAAK,UAAU,QAAQ,MAAM,CAAC,IAC9B,cAAc,OAAO,YAAY,OAAO,SAAS;AACrD,UAAQ,OAAO,MAAM,GAAG,MAAM;AAAA,CAAI;AACpC;AAEA,eAAe,QAAQ,OAAe,SAA4C;AAChF,QAAM,qBAAqB,iBAAiB,QAAQ,QAAQ,QAAQ;AACpE,QAAM,kBAAkB,iBAAiB,QAAQ,WAAW,WAAW;AACvE,QAAM,SAAS,MAAM,WAAW,OAAO;AAAA,IACrC;AAAA,IACA;AAAA,IACA,GAAI,QAAQ,SAAS,SAAS,IAAI,EAAE,YAAY,QAAQ,SAAS,IAAI,CAAC;AAAA,IACtE,GAAI,QAAQ,OAAO,EAAE,UAAU,QAAQ,KAAK,IAAI,CAAC;AAAA,EACnD,CAAC;AACD,QAAM,SAAS,QAAQ,OAAO,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,WAAW,MAAM;AACjF,UAAQ,OAAO,MAAM,GAAG,MAAM;AAAA,CAAI;AACpC;AAEA,eAAe,SAAS,OAAe,SAA6C;AAClF,QAAM,cAAc,iBAAiB,QAAQ,OAAO,OAAO;AAC3D,QAAM,YAAY,iBAAiB,QAAQ,KAAK,KAAK;AACrD,MAAI,aAAa,aAAa;AAC5B,UAAM,IAAI,MAAM,oCAAoC;AAAA,EACtD;AACA,QAAM,SAAS,MAAM,iBAAiB,OAAO;AAAA,IAC3C,OAAO,EAAE,aAAa,UAAU;AAAA,IAChC,GAAI,QAAQ,OAAO,EAAE,UAAU,QAAQ,KAAK,IAAI,CAAC;AAAA,EACnD,CAAC;AACD,QAAM,SAAS,QAAQ,OAAO,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,YAAY,MAAM;AAClF,UAAQ,OAAO,MAAM,GAAG,MAAM;AAAA,CAAI;AACpC;AAGA,SAAS,aAAa,MAAgC;AACpD,QAAM,UAA4B,CAAC;AACnC,aAAW,QAAQ,KAAK,MAAM,GAAG,GAAG;AAClC,UAAM,CAAC,MAAM,KAAK,IAAI,KAAK,MAAM,GAAG;AACpC,UAAM,QAAQ,QAAQ,IAAI,KAAK;AAC/B,UAAM,SAAS,OAAO,KAAK;AAC3B,QAAI,CAAC,QAAQ,CAAC,OAAO,SAAS,MAAM,KAAK,UAAU,GAAG;AACpD,YAAM,IAAI,MAAM,6BAA6B,IAAI,kCAAkC;AAAA,IACrF;AACA,YAAQ,KAAK,EAAE,MAAM,MAAM,OAAO,CAAC;AAAA,EACrC;AACA,MAAI,QAAQ,WAAW,EAAG,OAAM,IAAI,MAAM,0CAA0C;AACpF,SAAO;AACT;AAEA,eAAe,WAAW,SAAmB,SAA+C;AAC1F,QAAM,cAAc,iBAAiB,QAAQ,OAAO,OAAO;AAC3D,QAAM,YAAY,iBAAiB,QAAQ,KAAK,KAAK;AACrD,MAAI,aAAa,aAAa;AAC5B,UAAM,IAAI,MAAM,oCAAoC;AAAA,EACtD;AACA,QAAM,aAAa,QAAQ,UAAU,aAAa,QAAQ,OAAO,IAAI;AACrE,QAAM,SAAS,MAAM,iBAAiB,SAAS;AAAA,IAC7C,OAAO,EAAE,aAAa,UAAU;AAAA,IAChC,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;AAAA,IACnC,GAAI,QAAQ,OAAO,EAAE,UAAU,QAAQ,KAAK,IAAI,CAAC;AAAA,EACnD,CAAC;AACD,QAAM,SAAS,QAAQ,OAAO,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,iBAAiB,MAAM;AACvF,UAAQ,OAAO,MAAM,GAAG,MAAM;AAAA,CAAI;AACpC;AAEA,eAAe,aAAa,OAAe,SAAiD;AAC1F,QAAM,SAAS,MAAM,mBAAmB,OAAO;AAAA,IAC7C,QAAQ,YAAY,QAAQ,MAAM;AAAA,IAClC,MAAM,UAAU,QAAQ,IAAI;AAAA,IAC5B,SAAS,IAAI,wBAAwB;AAAA,IACrC,GAAI,QAAQ,SAAS,SAAS,IAAI,EAAE,YAAY,QAAQ,SAAS,IAAI,CAAC;AAAA,IACtE,GAAI,QAAQ,OAAO,EAAE,UAAU,QAAQ,KAAK,IAAI,CAAC;AAAA,EACnD,CAAC;AACD,QAAM,SAAS,QAAQ,OAAO,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,gBAAgB,MAAM;AACtF,UAAQ,OAAO,MAAM,GAAG,MAAM;AAAA,CAAI;AACpC;AAEA,eAAe,WAAW,OAAe,SAA+C;AACtF,MAAI,QAAQ,SAAS,WAAW,GAAG;AACjC,UAAM,IAAI,MAAM,0CAA0C;AAAA,EAC5D;AACA,QAAM,OAAO,MAAM,YAAY,OAAO;AAAA,IACpC,YAAY,QAAQ;AAAA,IACpB,MAAM,UAAU,QAAQ,IAAI;AAAA,IAC5B,uBAAuB,iBAAiB,QAAQ,YAAY,YAAY;AAAA,IACxE,oBAAoB,iBAAiB,QAAQ,QAAQ,QAAQ;AAAA,IAC7D,GAAI,QAAQ,MAAM,EAAE,KAAK,QAAQ,IAAI,IAAI,CAAC;AAAA,IAC1C,GAAI,QAAQ,OAAO,EAAE,UAAU,QAAQ,KAAK,IAAI,CAAC;AAAA,EACnD,CAAC;AACD,QAAM,SAAS,QAAQ,OAAO,KAAK,UAAU,MAAM,MAAM,CAAC,IAAI,cAAc,IAAI;AAChF,UAAQ,OAAO,MAAM,GAAG,MAAM;AAAA,CAAI;AACpC;AAEA,eAAe,YAAY,OAAe,SAAgD;AACxF,QAAM,UAAU,MAAM,aAAa,OAAO;AAAA,IACxC,cAAc,iBAAiB,QAAQ,QAAQ,QAAQ;AAAA,IACvD,GAAI,QAAQ,SAAS,SAAS,IAAI,EAAE,YAAY,QAAQ,SAAS,IAAI,CAAC;AAAA,IACtE,GAAI,QAAQ,OAAO,EAAE,UAAU,QAAQ,KAAK,IAAI,CAAC;AAAA,EACnD,CAAC;AACD,QAAM,OAAO,KAAK,UAAU,SAAS,MAAM,CAAC;AAC5C,MAAI,QAAQ,KAAK;AACf,kBAAc,QAAQ,KAAK,GAAG,IAAI;AAAA,GAAM,MAAM;AAC9C,YAAQ,OAAO,MAAM,SAAS,QAAQ,KAAK,MAAM,YAAY,QAAQ,GAAG;AAAA,CAAI;AAAA,EAC9E,OAAO;AACL,YAAQ,OAAO,MAAM,GAAG,IAAI;AAAA,CAAI;AAAA,EAClC;AACA,UAAQ,OAAO,MAAM,GAAG,gBAAgB;AAAA,CAAI;AAC9C;AAEA,eAAe,QAAQ,MAAc,SAA4C;AAC/E,QAAM,cAAc,iBAAiB,QAAQ,OAAO,OAAO;AAC3D,QAAM,YAAY,iBAAiB,QAAQ,KAAK,KAAK;AACrD,MAAI,aAAa,YAAa,OAAM,IAAI,MAAM,oCAAoC;AAElF,QAAM,YAAY,aAAa,MAAM,MAAM,EACxC,MAAM,OAAO,EACb,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,EACzB,OAAO,CAAC,SAAS,KAAK,SAAS,KAAK,CAAC,KAAK,WAAW,GAAG,CAAC;AAE5D,UAAQ,OAAO,MAAM,6CAA6C;AAClE,aAAW,YAAY,WAAW;AAChC,QAAI;AACF,YAAM,SAAS,MAAM,iBAAiB,UAAU;AAAA,QAC9C,OAAO,EAAE,aAAa,UAAU;AAAA,QAChC,GAAI,QAAQ,OAAO,EAAE,UAAU,QAAQ,KAAK,IAAI,CAAC;AAAA,MACnD,CAAC;AACD,YAAM,EAAE,KAAK,IAAI,IAAI,OAAO,OAAO;AACnC,cAAQ,OAAO;AAAA,QACb,GAAG,SAAS,QAAQ,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,OAAO,KAAK,IAAI,OAAO,UAAU,IAAI,SAAS,OAAO,QAAQ,KAAK,GAAG,CAAC,CAAC;AAAA;AAAA,MAChH;AAAA,IACF,SAAS,OAAO;AACd,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,cAAQ,OAAO,MAAM,GAAG,SAAS,QAAQ,CAAC,QAAQ,SAAS,UAAU,OAAO,EAAE,CAAC;AAAA,CAAI;AAAA,IACrF;AAAA,EACF;AACA,UAAQ,OAAO,MAAM,GAAG,gBAAgB;AAAA,CAAI;AAC9C;AAEA,SAAS,KAAK,OAAuB;AACnC,QAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,UAAQ,OAAO,MAAM,aAAa,OAAO;AAAA,CAAI;AAC7C,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,UAAU,IAAI,QAAQ;AAC5B,QACG,KAAK,UAAU,EACf,YAAY,uEAAkE,EAC9E,QAAQ,OAAO,EACf,mBAAmB,6BAA6B;AAEnD,QACG,QAAQ,MAAM,EACd,YAAY,0CAA0C,EACtD,SAAS,cAAc,mCAAmC,EAC1D,OAAO,yBAAyB,2BAA2B,MAAM,EACjE;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA,CAAC;AACH,EACC;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA,CAAC;AACH,EACC,OAAO,gBAAgB,qDAAqD,EAC5E,OAAO,cAAc,gEAAgE,EACrF,OAAO,oBAAoB,6DAA6D,EACxF,OAAO,iBAAiB,2CAA2C,EACnE,OAAO,iBAAiB,uDAAuD,MAAM,EACrF,OAAO,aAAa,kDAAkD,EACtE;AAAA,EACC;AAAA,EACA;AACF,EACC,OAAO,uBAAuB,6BAA6B,IAAI,EAC/D,OAAO,iBAAiB,8CAA8C,EACtE,OAAO,UAAU,mCAAmC,EACpD,OAAO,mBAAmB,0DAA0D,EACpF,OAAO,CAAC,OAAiB,YAAyB,QAAQ,MAAM,KAAK,GAAG,GAAG,OAAO,CAAC;AAEtF,QACG,QAAQ,SAAS,EACjB,YAAY,qCAAqC,EACjD,SAAS,cAAc,uBAAuB,EAC9C,OAAO,uBAAuB,gCAAgC,GAAG,EACjE,OAAO,iBAAiB,oBAAoB,EAC5C,OAAO,UAAU,iBAAiB,EAClC;AAAA,EAAO,CAAC,OAAiB,YACxB,WAAW,MAAM,KAAK,GAAG,GAAG,OAAO;AACrC;AAEF,QACG,QAAQ,MAAM,EACd,YAAY,0DAA0D,EACtE,SAAS,cAAc,mCAAmC,EAC1D;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA,CAAC;AACH,EACC,OAAO,yBAAyB,2CAA2C,MAAM,EACjF,OAAO,4BAA4B,6CAA6C,MAAM,EACtF,OAAO,iBAAiB,oBAAoB,EAC5C,OAAO,UAAU,iBAAiB,EAClC,OAAO,CAAC,OAAiB,YAAgC,QAAQ,MAAM,KAAK,GAAG,GAAG,OAAO,CAAC;AAE7F,QACG,QAAQ,OAAO,EACf,YAAY,sEAAsE,EAClF,SAAS,cAAc,mCAAmC,EAC1D,OAAO,oBAAoB,4DAAuD,KAAK,EACvF,OAAO,kBAAkB,oEAA+D,MAAM,EAC9F,OAAO,iBAAiB,oBAAoB,EAC5C,OAAO,UAAU,iBAAiB,EAClC,OAAO,CAAC,OAAiB,YAAiC,SAAS,MAAM,KAAK,GAAG,GAAG,OAAO,CAAC;AAE/F,QACG,QAAQ,WAAW,EACnB,YAAY,2DAA2D,EACvE,SAAS,cAAc,mCAAmC,EAC1D,OAAO,sBAAsB,iCAAiC,IAAI,EAClE,OAAO,iBAAiB,kCAAkC,MAAM,EAChE,OAAO,yBAAyB,+CAA+C,SAAS,CAAC,CAAC,EAC1F,OAAO,iBAAiB,oBAAoB,EAC5C,OAAO,UAAU,iBAAiB,EAClC;AAAA,EAAO,CAAC,OAAiB,YACxB,aAAa,MAAM,KAAK,GAAG,GAAG,OAAO;AACvC;AAEF,QACG,QAAQ,SAAS,EACjB,YAAY,uDAAuD,EACnE,SAAS,cAAc,4CAA4C,EACnE,OAAO,yBAAyB,mDAAmD,SAAS,CAAC,CAAC,EAC9F,OAAO,iBAAiB,kCAAkC,MAAM,EAChE,OAAO,iBAAiB,0BAA0B,EAClD,OAAO,wBAAwB,8CAA8C,GAAG,EAChF,OAAO,yBAAyB,kCAAkC,MAAM,EACxE,OAAO,iBAAiB,oBAAoB,EAC5C,OAAO,UAAU,iBAAiB,EAClC;AAAA,EAAO,CAAC,OAAiB,YACxB,WAAW,MAAM,KAAK,GAAG,GAAG,OAAO;AACrC;AAEF,QACG,QAAQ,SAAS,EACjB,YAAY,uDAAuD,EACnE,SAAS,kBAAkB,yDAAyD,EACpF;AAAA,EACC;AAAA,EACA;AACF,EACC,OAAO,oBAAoB,yCAAyC,KAAK,EACzE,OAAO,kBAAkB,gDAAgD,MAAM,EAC/E,OAAO,iBAAiB,oBAAoB,EAC5C,OAAO,UAAU,iBAAiB,EAClC,OAAO,CAAC,WAAqB,YAAmC,WAAW,WAAW,OAAO,CAAC;AAEjG,QACG,QAAQ,UAAU,EAClB,YAAY,iFAA4E,EACxF,SAAS,cAAc,gDAAgD,EACvE,OAAO,oBAAoB,oDAAoD,EAC/E,OAAO,yBAAyB,qBAAqB,MAAM,EAC3D;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA,CAAC;AACH,EACC,OAAO,iBAAiB,oBAAoB,EAC5C;AAAA,EAAO,CAAC,OAAiB,YACxB,YAAY,MAAM,KAAK,GAAG,GAAG,OAAO;AACtC;AAEF,QACG,QAAQ,MAAM,EACd,YAAY,wEAAmE,EAC/E,SAAS,UAAU,0EAA0E,EAC7F,OAAO,oBAAoB,yCAAyC,KAAK,EACzE,OAAO,kBAAkB,gDAAgD,MAAM,EAC/E,OAAO,iBAAiB,oBAAoB,EAC5C,OAAO,CAAC,MAAc,YAAgC,QAAQ,MAAM,OAAO,CAAC;AAE/E,QAAQ,WAAW,EAAE,MAAM,IAAI;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/render.ts"],"sourcesContent":["import { readFileSync, writeFileSync } from 'node:fs';\nimport {\n compareLocations,\n DatasetPlacesProvider,\n detectGaps,\n disambiguateLocation,\n findNearbyAmenities,\n ODBL_ATTRIBUTION,\n planErrands,\n reachableAmenities,\n snapshotArea,\n toCSV,\n toGeoJSON,\n ValhallaRoutingProvider,\n walkabilityScore,\n type CategoryWeight,\n type FacetFilters,\n type SnapshotDataset,\n type TravelMode,\n} from '@proximap/core';\nimport { Command } from 'commander';\nimport {\n renderComparison,\n renderErrands,\n renderGaps,\n renderGeocode,\n renderNearby,\n renderReachable,\n renderScore,\n} from './render';\n\nconst VERSION = '1.0.1';\n\ninterface NearOptions {\n radius: string;\n category: string[];\n filter: string[];\n accessible?: boolean;\n openNow?: boolean;\n openAt?: string;\n by?: string;\n mode: string;\n explain?: boolean;\n dataset?: string;\n limit: string;\n lang?: string;\n json?: boolean;\n format?: string;\n}\n\ninterface SnapshotCommandOptions {\n out?: string;\n radius: string;\n category: string[];\n lang?: string;\n}\n\ninterface BulkCommandOptions {\n ideal: string;\n max: string;\n lang?: string;\n}\n\ninterface GeocodeCommandOptions {\n limit: string;\n lang?: string;\n json?: boolean;\n}\n\ninterface GapsCommandOptions {\n category: string[];\n radius: string;\n threshold: string;\n lang?: string;\n json?: boolean;\n}\n\ninterface ScoreCommandOptions {\n ideal: string;\n max: string;\n lang?: string;\n json?: boolean;\n}\n\ninterface CompareCommandOptions {\n weights?: string;\n ideal: string;\n max: string;\n lang?: string;\n json?: boolean;\n}\n\ninterface ReachableCommandOptions {\n within: string;\n mode: string;\n category: string[];\n lang?: string;\n json?: boolean;\n}\n\ninterface ErrandsCommandOptions {\n category: string[];\n mode: string;\n end?: string;\n candidates: string;\n radius: string;\n lang?: string;\n json?: boolean;\n}\n\nfunction collect(value: string, previous: string[]): string[] {\n return [...previous, value];\n}\n\nfunction parsePositiveInt(value: string, name: string): number {\n const parsed = Number.parseInt(value, 10);\n if (!Number.isFinite(parsed) || parsed <= 0) {\n throw new Error(`--${name} must be a positive integer (got \"${value}\")`);\n }\n return parsed;\n}\n\nconst FALSY = new Set(['no', 'false', '0', '']);\n\nconst MODE_ALIASES: Record<string, TravelMode> = {\n walk: 'walk',\n walking: 'walk',\n foot: 'walk',\n bike: 'bike',\n cycling: 'bike',\n bicycle: 'bike',\n drive: 'drive',\n driving: 'drive',\n car: 'drive',\n};\n\nfunction parseMode(value: string): TravelMode {\n const mode = MODE_ALIASES[value.trim().toLowerCase()];\n if (!mode) throw new Error(`--mode must be walk, bike, or drive (got \"${value}\")`);\n return mode;\n}\n\n/** Parse a time budget like \"15\", \"15min\", or \"15 minutes\" into minutes. */\nfunction parseWithin(value: string): number {\n const match = value\n .trim()\n .toLowerCase()\n .match(/^(\\d+(?:\\.\\d+)?)\\s*(?:m|min|mins|minutes)?$/);\n const minutes = match ? Number(match[1]) : NaN;\n if (!Number.isFinite(minutes) || minutes <= 0) {\n throw new Error(`--within must be a positive number of minutes (got \"${value}\")`);\n }\n return minutes;\n}\n\n/** Parse repeatable `--filter key=value` (or bare `key`) pairs into FacetFilters. */\nfunction parseFilters(pairs: string[]): FacetFilters {\n const filters: FacetFilters = {};\n const tags: Record<string, string | boolean> = {};\n const push = (field: 'diet' | 'cuisine' | 'payment', value: string): void => {\n if (!value) return;\n const existing = filters[field];\n filters[field] = existing\n ? [...(Array.isArray(existing) ? existing : [existing]), value]\n : value;\n };\n\n for (const pair of pairs) {\n const eq = pair.indexOf('=');\n const key = (eq === -1 ? pair : pair.slice(0, eq)).trim().toLowerCase();\n const raw = eq === -1 ? '' : pair.slice(eq + 1).trim();\n const bool = eq === -1 ? true : !FALSY.has(raw.toLowerCase());\n\n switch (key) {\n case 'diet':\n case 'cuisine':\n case 'payment':\n push(key, raw);\n break;\n case 'wheelchair':\n filters.wheelchair = raw || 'yes';\n break;\n case 'wifi':\n case 'internet':\n case 'internet_access':\n filters.internetAccess = bool;\n break;\n case 'takeaway':\n filters.takeaway = bool;\n break;\n case 'delivery':\n filters.delivery = bool;\n break;\n case 'outdoor':\n case 'outdoor_seating':\n filters.outdoorSeating = bool;\n break;\n default:\n tags[key] = eq === -1 ? true : raw;\n break;\n }\n }\n if (Object.keys(tags).length > 0) filters.tags = tags;\n return filters;\n}\n\n/** Load a proximap snapshot file for offline POI queries. */\nfunction loadDataset(path: string): SnapshotDataset {\n const data: unknown = JSON.parse(readFileSync(path, 'utf8'));\n if (!data || typeof data !== 'object' || !Array.isArray((data as SnapshotDataset).pois)) {\n throw new Error(`not a proximap snapshot (no \"pois\" array): ${path}`);\n }\n return data as SnapshotDataset;\n}\n\n/** Quote a CSV field when it contains a comma, quote, or newline (RFC 4180). */\nfunction csvField(value: string): string {\n return /[\",\\n\\r]/.test(value) ? `\"${value.replace(/\"/g, '\"\"')}\"` : value;\n}\n\nasync function runNear(query: string, options: NearOptions): Promise<void> {\n const radiusMeters = parsePositiveInt(options.radius, 'radius');\n const limit = parsePositiveInt(options.limit, 'limit');\n\n const filters = parseFilters(options.filter);\n const open = options.openAt ? { at: options.openAt } : options.openNow ? 'now' : undefined;\n const byTravelTime = options.by !== undefined && /time/i.test(options.by);\n const places = options.dataset\n ? new DatasetPlacesProvider(loadDataset(options.dataset))\n : undefined;\n const result = await findNearbyAmenities(query, {\n radiusMeters,\n limit,\n ...(places ? { places } : {}),\n ...(options.category.length > 0 ? { categories: options.category } : {}),\n ...(Object.keys(filters).length > 0 ? { filters } : {}),\n ...(options.accessible ? { accessible: true } : {}),\n ...(open ? { open } : {}),\n // Use the key-free public Valhalla engine for real road-network times; core\n // falls back to straight-line estimates if it is unavailable.\n ...(byTravelTime\n ? {\n rankBy: 'travelTime' as const,\n mode: parseMode(options.mode),\n routing: new ValhallaRoutingProvider(),\n }\n : {}),\n ...(options.explain ? { explain: true } : {}),\n ...(options.lang ? { language: options.lang } : {}),\n });\n\n if (options.format) {\n const format = options.format.toLowerCase();\n if (format === 'geojson')\n process.stdout.write(`${JSON.stringify(toGeoJSON(result), null, 2)}\\n`);\n else if (format === 'csv') process.stdout.write(`${toCSV(result)}\\n`);\n else throw new Error(`unknown --format \"${options.format}\" (use geojson or csv)`);\n // Keep the ODbL notice off stdout so the data stays pipeable to a file.\n process.stderr.write(`${ODBL_ATTRIBUTION}\\n`);\n return;\n }\n\n const output = options.json ? JSON.stringify(result, null, 2) : renderNearby(result);\n process.stdout.write(`${output}\\n`);\n}\n\nasync function runGeocode(query: string, options: GeocodeCommandOptions): Promise<void> {\n const result = await disambiguateLocation(query, {\n limit: parsePositiveInt(options.limit, 'limit'),\n ...(options.lang ? { language: options.lang } : {}),\n });\n const output = options.json\n ? JSON.stringify(result, null, 2)\n : renderGeocode(result.candidates, result.ambiguous);\n process.stdout.write(`${output}\\n`);\n}\n\nasync function runGaps(query: string, options: GapsCommandOptions): Promise<void> {\n const searchRadiusMeters = parsePositiveInt(options.radius, 'radius');\n const thresholdMeters = parsePositiveInt(options.threshold, 'threshold');\n const report = await detectGaps(query, {\n searchRadiusMeters,\n thresholdMeters,\n ...(options.category.length > 0 ? { categories: options.category } : {}),\n ...(options.lang ? { language: options.lang } : {}),\n });\n const output = options.json ? JSON.stringify(report, null, 2) : renderGaps(report);\n process.stdout.write(`${output}\\n`);\n}\n\nasync function runScore(query: string, options: ScoreCommandOptions): Promise<void> {\n const idealMeters = parsePositiveInt(options.ideal, 'ideal');\n const maxMeters = parsePositiveInt(options.max, 'max');\n if (maxMeters <= idealMeters) {\n throw new Error('--max must be greater than --ideal');\n }\n const report = await walkabilityScore(query, {\n decay: { idealMeters, maxMeters },\n ...(options.lang ? { language: options.lang } : {}),\n });\n const output = options.json ? JSON.stringify(report, null, 2) : renderScore(report);\n process.stdout.write(`${output}\\n`);\n}\n\n/** Parse `term=weight,term=weight` into CategoryWeight[]. */\nfunction parseWeights(spec: string): CategoryWeight[] {\n const weights: CategoryWeight[] = [];\n for (const part of spec.split(',')) {\n const [term, value] = part.split('=');\n const name = (term ?? '').trim();\n const weight = Number(value);\n if (!name || !Number.isFinite(weight) || weight <= 0) {\n throw new Error(`invalid --weights entry: \"${part}\" (use term=weight, e.g. food=2)`);\n }\n weights.push({ term: name, weight });\n }\n if (weights.length === 0) throw new Error('--weights needs at least one term=weight');\n return weights;\n}\n\nasync function runCompare(queries: string[], options: CompareCommandOptions): Promise<void> {\n const idealMeters = parsePositiveInt(options.ideal, 'ideal');\n const maxMeters = parsePositiveInt(options.max, 'max');\n if (maxMeters <= idealMeters) {\n throw new Error('--max must be greater than --ideal');\n }\n const categories = options.weights ? parseWeights(options.weights) : undefined;\n const report = await compareLocations(queries, {\n decay: { idealMeters, maxMeters },\n ...(categories ? { categories } : {}),\n ...(options.lang ? { language: options.lang } : {}),\n });\n const output = options.json ? JSON.stringify(report, null, 2) : renderComparison(report);\n process.stdout.write(`${output}\\n`);\n}\n\nasync function runReachable(query: string, options: ReachableCommandOptions): Promise<void> {\n const result = await reachableAmenities(query, {\n within: parseWithin(options.within),\n mode: parseMode(options.mode),\n routing: new ValhallaRoutingProvider(),\n ...(options.category.length > 0 ? { categories: options.category } : {}),\n ...(options.lang ? { language: options.lang } : {}),\n });\n const output = options.json ? JSON.stringify(result, null, 2) : renderReachable(result);\n process.stdout.write(`${output}\\n`);\n}\n\nasync function runErrands(query: string, options: ErrandsCommandOptions): Promise<void> {\n if (options.category.length === 0) {\n throw new Error('errands needs at least one -c/--category');\n }\n const plan = await planErrands(query, {\n categories: options.category,\n mode: parseMode(options.mode),\n candidatesPerCategory: parsePositiveInt(options.candidates, 'candidates'),\n searchRadiusMeters: parsePositiveInt(options.radius, 'radius'),\n ...(options.end ? { end: options.end } : {}),\n ...(options.lang ? { language: options.lang } : {}),\n });\n const output = options.json ? JSON.stringify(plan, null, 2) : renderErrands(plan);\n process.stdout.write(`${output}\\n`);\n}\n\nasync function runSnapshot(query: string, options: SnapshotCommandOptions): Promise<void> {\n const dataset = await snapshotArea(query, {\n radiusMeters: parsePositiveInt(options.radius, 'radius'),\n ...(options.category.length > 0 ? { categories: options.category } : {}),\n ...(options.lang ? { language: options.lang } : {}),\n });\n const json = JSON.stringify(dataset, null, 2);\n if (options.out) {\n writeFileSync(options.out, `${json}\\n`, 'utf8');\n process.stderr.write(`Wrote ${dataset.pois.length} POIs to ${options.out}\\n`);\n } else {\n process.stdout.write(`${json}\\n`);\n }\n process.stderr.write(`${ODBL_ATTRIBUTION}\\n`);\n}\n\nasync function runBulk(file: string, options: BulkCommandOptions): Promise<void> {\n const idealMeters = parsePositiveInt(options.ideal, 'ideal');\n const maxMeters = parsePositiveInt(options.max, 'max');\n if (maxMeters <= idealMeters) throw new Error('--max must be greater than --ideal');\n\n const locations = readFileSync(file, 'utf8')\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line.length > 0 && !line.startsWith('#'));\n\n process.stdout.write('location,lat,lng,score,confidence,missing\\n');\n for (const location of locations) {\n try {\n const report = await walkabilityScore(location, {\n decay: { idealMeters, maxMeters },\n ...(options.lang ? { language: options.lang } : {}),\n });\n const { lat, lng } = report.origin.location;\n process.stdout.write(\n `${csvField(location)},${lat},${lng},${report.score},${report.confidence},${csvField(report.missing.join(';'))}\\n`,\n );\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n process.stdout.write(`${csvField(location)},,,,,${csvField(`error: ${message}`)}\\n`);\n }\n }\n process.stderr.write(`${ODBL_ATTRIBUTION}\\n`);\n}\n\nfunction fail(error: unknown): never {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`proximap: ${message}\\n`);\n process.exit(1);\n}\n\nconst program = new Command();\nprogram\n .name('proximap')\n .description('Find and rank what is near any place — powered by OpenStreetMap.')\n .version(VERSION)\n .showHelpAfterError('(run with --help for usage)');\n\nprogram\n .command('near')\n .description('list nearby amenities ranked by distance')\n .argument('<query...>', 'place name, address, or \"lat,lng\"')\n .option('-r, --radius <meters>', 'search radius in metres', '1000')\n .option(\n '-c, --category <term>',\n 'restrict to a category or term, e.g. coffee (repeatable)',\n collect,\n [],\n )\n .option(\n '-f, --filter <key=value>',\n 'facet filter, e.g. diet=vegan, payment=contactless, wifi (repeatable)',\n collect,\n [],\n )\n .option('--accessible', 'rank step-free / wheelchair-accessible places first')\n .option('--open-now', 'keep only places open right now (unknown hours kept, labelled)')\n .option('--open-at <when>', 'keep only places open at an ISO time, e.g. 2026-06-20T21:00')\n .option('--by <metric>', 'rank by distance (default) or travel-time')\n .option('--mode <mode>', 'travel mode for --by travel-time: walk, bike, drive', 'walk')\n .option('--explain', 'annotate each result with a short ranking reason')\n .option(\n '--dataset <file>',\n 'query a local snapshot file offline (use \"lat,lng\" for full offline)',\n )\n .option('-n, --limit <count>', 'maximum number of results', '20')\n .option('--lang <code>', 'preferred language for place names (e.g. en)')\n .option('--json', 'output raw JSON instead of a list')\n .option('--format <type>', 'export results as geojson or csv (ODbL notice on stderr)')\n .action((parts: string[], options: NearOptions) => runNear(parts.join(' '), options));\n\nprogram\n .command('geocode')\n .description('resolve a place name to coordinates')\n .argument('<query...>', 'place name or address')\n .option('-n, --limit <count>', 'maximum number of candidates', '5')\n .option('--lang <code>', 'preferred language')\n .option('--json', 'output raw JSON')\n .action((parts: string[], options: GeocodeCommandOptions) =>\n runGeocode(parts.join(' '), options),\n );\n\nprogram\n .command('gaps')\n .description('report which everyday amenities are missing near a place')\n .argument('<query...>', 'place name, address, or \"lat,lng\"')\n .option(\n '-c, --category <term>',\n 'category to check (repeatable; default: daily needs)',\n collect,\n [],\n )\n .option('-r, --radius <meters>', 'how far to search for the nearest match', '5000')\n .option('-t, --threshold <meters>', 'distance beyond which a category is a gap', '1500')\n .option('--lang <code>', 'preferred language')\n .option('--json', 'output raw JSON')\n .action((parts: string[], options: GapsCommandOptions) => runGaps(parts.join(' '), options));\n\nprogram\n .command('score')\n .description('rate how walkable / well-served a place is (0-100, with a breakdown)')\n .argument('<query...>', 'place name, address, or \"lat,lng\"')\n .option('--ideal <meters>', 'distance that still scores full marks (≈5-min walk)', '400')\n .option('--max <meters>', 'distance beyond which a category scores zero (≈30-min walk)', '2400')\n .option('--lang <code>', 'preferred language')\n .option('--json', 'output raw JSON')\n .action((parts: string[], options: ScoreCommandOptions) => runScore(parts.join(' '), options));\n\nprogram\n .command('reachable')\n .description('list amenities reachable within a time budget (isochrone)')\n .argument('<query...>', 'place name, address, or \"lat,lng\"')\n .option('--within <minutes>', 'time budget, e.g. 15 or 15min', '15')\n .option('--mode <mode>', 'travel mode: walk, bike, drive', 'walk')\n .option('-c, --category <term>', 'restrict to a category or term (repeatable)', collect, [])\n .option('--lang <code>', 'preferred language')\n .option('--json', 'output raw JSON')\n .action((parts: string[], options: ReachableCommandOptions) =>\n runReachable(parts.join(' '), options),\n );\n\nprogram\n .command('errands')\n .description('plan the shortest trip that hits one of each category')\n .argument('<query...>', 'starting place name, address, or \"lat,lng\"')\n .option('-c, --category <term>', 'a category to hit one of (repeatable, required)', collect, [])\n .option('--mode <mode>', 'travel mode: walk, bike, drive', 'walk')\n .option('--end <place>', 'optional fixed end point')\n .option('--candidates <count>', 'nearest candidates considered per category', '5')\n .option('-r, --radius <meters>', 'how far to look for candidates', '3000')\n .option('--lang <code>', 'preferred language')\n .option('--json', 'output raw JSON')\n .action((parts: string[], options: ErrandsCommandOptions) =>\n runErrands(parts.join(' '), options),\n );\n\nprogram\n .command('compare')\n .description('compare 2+ locations by access to what you care about')\n .argument('<locations...>', 'two or more quoted place names, addresses, or \"lat,lng\"')\n .option(\n '-w, --weights <list>',\n 'comma list term=weight, e.g. food=2,transport=3 (default: daily needs)',\n )\n .option('--ideal <meters>', 'distance that still scores full marks', '400')\n .option('--max <meters>', 'distance beyond which a category scores zero', '2400')\n .option('--lang <code>', 'preferred language')\n .option('--json', 'output raw JSON')\n .action((locations: string[], options: CompareCommandOptions) => runCompare(locations, options));\n\nprogram\n .command('snapshot')\n .description(\"capture an area's POIs to a file for offline reuse (ODbL — yours to store)\")\n .argument('<query...>', 'area center: place name, address, or \"lat,lng\"')\n .option('-o, --out <file>', 'write the snapshot JSON to this file (else stdout)')\n .option('-r, --radius <meters>', 'radius to capture', '2000')\n .option(\n '-c, --category <term>',\n 'restrict the capture to a category/term (repeatable)',\n collect,\n [],\n )\n .option('--lang <code>', 'preferred language')\n .action((parts: string[], options: SnapshotCommandOptions) =>\n runSnapshot(parts.join(' '), options),\n );\n\nprogram\n .command('bulk')\n .description('walkability-score many locations from a file (one per line) → CSV')\n .argument('<file>', 'text file with one place/address/\"lat,lng\" per line (# comments allowed)')\n .option('--ideal <meters>', 'distance that still scores full marks', '400')\n .option('--max <meters>', 'distance beyond which a category scores zero', '2400')\n .option('--lang <code>', 'preferred language')\n .action((file: string, options: BulkCommandOptions) => runBulk(file, options));\n\nprogram.parseAsync().catch(fail);\n","import {\n CATEGORY_LABELS,\n formatDistance,\n formatDuration,\n type ComparisonReport,\n type ErrandPlan,\n type GapReport,\n type NearbyResult,\n type OpenState,\n type Place,\n type RankedPoi,\n type ReachableResult,\n type WalkabilityReport,\n} from '@proximap/core';\nimport pc from 'picocolors';\n\nconst MODE_WORDS: Record<string, string> = { walk: 'walking', bike: 'cycling', drive: 'driving' };\n\nfunction coordString(lat: number, lng: number): string {\n return `${lat.toFixed(5)}, ${lng.toFixed(5)}`;\n}\n\n/** Render a nearby-search result as a numbered list (by distance, or travel time). */\nexport function renderNearby(result: NearbyResult): string {\n const { origin, results, total, routing } = result;\n const lines: string[] = [\n pc.bold(origin.displayName),\n pc.dim(\n `${coordString(origin.location.lat, origin.location.lng)} · ${total} found, showing ${results.length}`,\n ),\n ];\n if (routing) {\n const word = MODE_WORDS[routing.mode] ?? routing.mode;\n lines.push(\n pc.dim(\n routing.fellBack\n ? `ranked by ${word} time (straight-line estimate — routing engine unavailable)`\n : `ranked by ${word} time via ${routing.provider}`,\n ),\n );\n }\n lines.push('');\n\n if (results.length === 0) {\n lines.push(pc.dim('No amenities found within the search radius.'));\n return lines.join('\\n');\n }\n\n const rankWidth = String(results.length).length;\n for (const poi of results) {\n const rank = String(poi.rank).padStart(rankWidth);\n const label = CATEGORY_LABELS[poi.category];\n const name = poi.name ?? poi.kind ?? label;\n const distance = formatDistance(poi.distanceMeters);\n const metric =\n poi.travelSeconds !== undefined\n ? `${formatDuration(poi.travelSeconds)} · ${distance}`\n : distance;\n // With --explain, the reason (\"closest open cafe, 240 m\") replaces the meta.\n const meta = pc.dim(poi.rankingReason ?? `${label} · ${metric}`);\n const tags = `${accessibilityMark(poi.tags.wheelchair)}${poi.rankingReason ? '' : openMark(poi)}`;\n lines.push(`${pc.dim(`${rank}.`)} ${name} ${meta}${tags}`);\n }\n return lines.join('\\n');\n}\n\n/** A compact step-free indicator for the nearby list, shown only when tagged. */\nfunction accessibilityMark(wheelchair: string | undefined): string {\n if (wheelchair === 'yes') return ` ${pc.green('♿')}`;\n if (wheelchair === 'limited') return ` ${pc.yellow('♿ limited')}`;\n return '';\n}\n\nconst localHhmm = (iso: string): string => {\n const date = new Date(iso);\n return `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;\n};\n\n/** An open/closed indicator, shown only when an `open` query was made. */\nfunction openMark(poi: RankedPoi): string {\n const state: OpenState | undefined = poi.openState;\n if (state === 'open') {\n const till = poi.nextChange ? ` ${pc.dim(`till ${localHhmm(poi.nextChange)}`)}` : '';\n return ` ${pc.green('open')}${till}`;\n }\n if (state === 'unknown') return ` ${pc.dim('hours?')}`;\n return '';\n}\n\n/** Render an isochrone-reachability result: what's within the time budget. */\nexport function renderReachable(result: ReachableResult): string {\n const { origin, results, withinMinutes, mode, isochrone, count } = result;\n const word = MODE_WORDS[mode] ?? mode;\n const basis = isochrone ? 'isochrone' : 'straight-line estimate';\n const lines: string[] = [\n pc.bold(origin.displayName),\n pc.dim(\n `${coordString(origin.location.lat, origin.location.lng)} · ` +\n `${count} reachable within ${withinMinutes} min ${word} (${basis})`,\n ),\n '',\n ];\n if (results.length === 0) {\n lines.push(pc.dim('Nothing reachable within that budget.'));\n return lines.join('\\n');\n }\n const rankWidth = String(results.length).length;\n for (const poi of results) {\n const rank = String(poi.rank).padStart(rankWidth);\n const label = CATEGORY_LABELS[poi.category];\n const name = poi.name ?? poi.kind ?? label;\n const distance = formatDistance(poi.distanceMeters);\n const metric =\n poi.travelSeconds !== undefined\n ? `${formatDuration(poi.travelSeconds)} · ${distance}`\n : distance;\n lines.push(\n `${pc.dim(`${rank}.`)} ${name} ${pc.dim(`${label} · ${metric}`)}${accessibilityMark(poi.tags.wheelchair)}`,\n );\n }\n return lines.join('\\n');\n}\n\n/** Render geocoding candidates with their addresses and coordinates. */\nexport function renderGeocode(places: Place[], ambiguous = false): string {\n if (places.length === 0) return 'No matches found.';\n\n const rankWidth = String(places.length).length;\n const lines: string[] = [];\n if (ambiguous) {\n // Ambiguity means at least two genuinely distinct rivals exist among the\n // candidates — not that every candidate is distinct, so label the count\n // \"candidates\" rather than overstating \"N distinct places\".\n lines.push(\n pc.yellow(\n `⚠ Ambiguous — distinct places share this name; showing ${places.length} candidates, pick one:`,\n ),\n '',\n );\n }\n places.forEach((place, index) => {\n const rank = String(index + 1).padStart(rankWidth);\n lines.push(`${pc.dim(`${rank}.`)} ${pc.bold(place.name)}`);\n lines.push(` ${pc.dim(place.displayName)}`);\n lines.push(` ${pc.dim(coordString(place.location.lat, place.location.lng))}`);\n });\n return lines.join('\\n');\n}\n\nfunction titleCase(value: string): string {\n return value.charAt(0).toUpperCase() + value.slice(1);\n}\n\n/** Render an amenity-gap report as a checklist with distances. */\nexport function renderGaps(report: GapReport): string {\n const { origin, gaps, missing, searchRadiusMeters, thresholdMeters } = report;\n const lines: string[] = [\n pc.bold(origin.displayName),\n pc.dim(\n `${coordString(origin.location.lat, origin.location.lng)} · searched ${formatDistance(searchRadiusMeters)}, gap if > ${formatDistance(thresholdMeters)}`,\n ),\n '',\n ];\n for (const gap of gaps) {\n const mark = gap.isGap ? pc.red('✗') : pc.green('✓');\n const detail =\n gap.nearestMeters === null\n ? pc.dim(`none within ${formatDistance(searchRadiusMeters)}`)\n : pc.dim(formatDistance(gap.nearestMeters));\n lines.push(`${mark} ${titleCase(gap.category)} ${detail}`);\n }\n lines.push('');\n lines.push(\n missing.length === 0\n ? pc.green('No gaps — all requested categories are nearby.')\n : pc.dim(`Missing (not found in OSM): ${missing.join(', ')}`),\n );\n return lines.join('\\n');\n}\n\n/** Render a walkability report: headline score, per-category breakdown, gaps. */\nexport function renderScore(report: WalkabilityReport): string {\n const { origin, score, confidence, breakdown, missing, decay } = report;\n const lines: string[] = [\n pc.bold(origin.displayName),\n pc.dim(\n `${coordString(origin.location.lat, origin.location.lng)} · ` +\n `walkability ${pc.bold(String(score))}/100 · confidence ${Math.round(confidence * 100)}%`,\n ),\n pc.dim(\n `full credit ≤ ${formatDistance(decay.idealMeters)}, none ≥ ${formatDistance(decay.maxMeters)}`,\n ),\n '',\n ];\n\n const nameWidth = Math.max(...breakdown.map((b) => titleCase(b.category).length));\n for (const entry of breakdown) {\n const mark =\n entry.subScore >= 0.67 ? pc.green('✓') : entry.subScore > 0 ? pc.yellow('~') : pc.red('✗');\n const name = titleCase(entry.category).padEnd(nameWidth);\n const detail =\n entry.nearestMeters === null\n ? pc.dim('none in range')\n : pc.dim(formatDistance(entry.nearestMeters));\n const pct = pc.dim(`${Math.round(entry.subScore * 100)}%`.padStart(4));\n lines.push(`${mark} ${name} ${pct} ${detail}`);\n }\n\n lines.push('');\n lines.push(\n missing.length === 0\n ? pc.green('All daily needs reachable within range.')\n : pc.dim(`Not found in OSM within range: ${missing.join(', ')}`),\n );\n if (confidence < 0.5) {\n lines.push(\n pc.yellow('Low confidence — OSM coverage here looks sparse; treat the score as a floor.'),\n );\n }\n return lines.join('\\n');\n}\n\n/** Render an errand plan: ordered stops with per-leg time, total, and any gaps. */\nexport function renderErrands(plan: ErrandPlan): string {\n const { origin, end, stops, totalSeconds, totalMeters, missing, mode } = plan;\n const word = MODE_WORDS[mode] ?? mode;\n const lines: string[] = [\n pc.bold(`Errand plan from ${origin.displayName}`),\n pc.dim(\n `${stops.length} stop${stops.length === 1 ? '' : 's'} · ` +\n `${formatDuration(totalSeconds)} ${word} · ${formatDistance(totalMeters)} (straight-line estimate)`,\n ),\n '',\n ];\n if (stops.length === 0) {\n lines.push(pc.dim('No reachable stops for the requested categories.'));\n }\n const stepWidth = String(stops.length).length;\n stops.forEach((stop, index) => {\n const step = String(index + 1).padStart(stepWidth);\n const name = stop.poi.name ?? stop.poi.kind ?? stop.category;\n const leg = pc.dim(`+${formatDuration(stop.legSeconds)} · ${formatDistance(stop.legMeters)}`);\n lines.push(`${pc.dim(`${step}.`)} ${pc.bold(titleCase(stop.category))}: ${name} ${leg}`);\n });\n if (end) lines.push(pc.dim(` ↳ end: ${end.displayName}`));\n if (missing.length > 0) {\n lines.push('');\n lines.push(pc.dim(`Not found nearby: ${missing.join(', ')}`));\n }\n return lines.join('\\n');\n}\n\n/** Render a location-comparison scorecard: ranked locations + per-dimension winners. */\nexport function renderComparison(report: ComparisonReport): string {\n const weightStr = report.weights.map((w) => `${titleCase(w.term)}×${w.weight}`).join(', ');\n const lines: string[] = [pc.bold('Location comparison'), pc.dim(`weights: ${weightStr}`), ''];\n\n const rankWidth = String(report.ranked.length).length;\n report.ranked.forEach((entry, position) => {\n const location = report.locations[entry.index]!;\n const marker = position === 0 ? pc.green('★') : ' ';\n const rank = String(position + 1).padStart(rankWidth);\n lines.push(`${marker} ${pc.dim(`${rank}.`)} ${pc.bold(entry.origin.displayName)}`);\n lines.push(\n ` ${pc.dim(`${entry.score}/100 · confidence ${Math.round(location.confidence * 100)}%`)}`,\n );\n });\n\n lines.push('');\n lines.push(pc.bold('Best per category:'));\n const nameWidth = Math.max(...report.dimensions.map((d) => titleCase(d.category).length));\n for (const dimension of report.dimensions) {\n const name = titleCase(dimension.category).padEnd(nameWidth);\n let detail: string;\n if (dimension.bestIndex === null) {\n detail = pc.dim('none found');\n } else {\n const location = report.locations[dimension.bestIndex]!;\n const entry = location.breakdown.find((b) => b.category === dimension.category);\n const distance =\n entry && entry.nearestMeters !== null\n ? pc.dim(` (${formatDistance(entry.nearestMeters)})`)\n : '';\n detail = `${location.origin.name}${distance}`;\n }\n lines.push(` ${name} ${detail}`);\n }\n return lines.join('\\n');\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proximap/cli",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Command-line interface for proximap — find and rank what's near any place.",
5
5
  "keywords": [
6
6
  "cli",
@@ -40,7 +40,7 @@
40
40
  "prepublishOnly": "npm run build"
41
41
  },
42
42
  "dependencies": {
43
- "@proximap/core": "^1.0.0",
43
+ "@proximap/core": "^1.0.1",
44
44
  "commander": "^15.0.0",
45
45
  "picocolors": "^1.1.1"
46
46
  }