Compare areas
compare_areasCompare two to five areas by category mix, place density, and key differences, with optional weighted priorities for a scored verdict.
Instructions
Compare 2-5 areas side by side: category mix, density, and what differs.
areas is a list of centers sharing one radius_m, each a {"lat": ...,
"lon": ...} dict, a GERS id, or a free-text place/area name, mixed
freely — a named area compares the same radius_m circle around its
resolved point as a coordinate would (not its actual boundary; that's a
later feature). An id/name that failed to resolve returns an indexed
error (areas[i]: ...) with candidates on ambiguity. Any area given by
id/name adds "resolved": [{"index": i, "name", "id", "lat", "lon",
"matched_by"}, ...] for just those areas; absent when every area was
already coordinates. Returns per-area total_places, place density per
km^2, and category_counts aligned across areas for the top ~10
categories by combined count, plus "differentiators" — those categories
ranked by how much they differ, relatively, between areas (the fastest
way to answer "how is area A different from area B"). Returns a
structured {"error": ...} if areas isn't 2-5 centers, or if upstream is
unavailable or the dataset is missing columns this tool depends on for
any area (a partial comparison is not returned).
priorities (optional, up to 6) turns the comparison into a scored
verdict: each entry is {"label": your own term for the criterion,
e.g. "competition"; "category": an Overture taxonomy slug, or
"__density__" for overall place density as a foot-traffic proxy;
"prefer": "more" | "fewer"; "weight": 0.1-5, default 1}. Each area's raw
measure per priority is that category's count (or density) within
radius_m — matched exactly against the category taxonomy (slug plus its
descendants, so "park" never counts parking garages) and counted
explicitly even for categories outside the top-10 alignment above; the
per-priority winner is whichever area is better on that raw measure (a
tie has no winner for that priority); each area's verdict score is the
weight-summed share of each priority normalized against the best area
(measure/max for "more", min/measure for "fewer" — the best area always
gets 1.0, and every area measuring 0 makes all shares 1.0), and the
highest score wins overall (a tie leaves winner_idx null). Adds (never
replaces) "verdict": {"winner_idx", "scores", "reasons" (one sentence
per priority), "margin", and a fixed "measured_note"} — the note,
always present when priorities are given, states plainly that these are
open-data place counts/density, never revenue, rent, actual foot
traffic, or demographics, and that "__density__" is only a proxy. If
the dataset's category columns are all degraded, count-based priorities
can't be measured and the verdict comes back with null winner_idx and
scores plus "degraded": true rather than a fabricated score. Returns
bad_request for more than 6 priorities or a malformed one (missing
label/category, an unrecognized prefer, or a non-numeric weight).
When priorities produced a verdict, the response also carries "map"
(#369) — a render-ready payload, keyword-splattable straight into this
server's map-rendering tool (its keys are exactly that tool's keyword
arguments): a pin per area (the winner picked out by class), a cheap
circle outline per area (radius_m, not a real boundary) labeled with
its score, and a one-line summary restating the winner. Absent when
priorities weren't given, or a verdict couldn't be scored.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| areas | Yes | ||
| radius_m | No | ||
| priorities | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||