← back to Homesonspec
david-weekley: capture city-gated community MapPoint coord (yolo iter-6)
de09b35174d70d47989f2324a817620f0fa373dc · 2026-07-29 02:42:15 -0700 · Steve Abrams
Adds communityGeo() that extracts the community coord from the page JSON,
strictly distinguishing it from the two decoy coords each DW page carries:
- REJECTS the warranty/regional-HQ coord (MapCenter, sibling of WarrantyEmail)
- REJECTS regional sales-office coords (MapPoint inside Offices[]) via a
city-equality gate — one office serves a whole metro (all Phoenix homes ->
one Tempe office), so its city never matches the home's city
- ACCEPTS only a community object (Grouping + Geolocation + Address + MapPoint)
whose MapPoint.Address.City/State equals the home's city+state, plus a coarse
US bbox. A wrong pin is worse than null.
The community coord exists only on per-community DETAIL pages; the per-metro
homes-ready-soon LIST pages this adapter fetches carry only warranty + office
coords, so on those it returns null (no wrong pins). Verified against a cached
list snapshot (null for all cities) and a live detail page (correct San Tan
Valley pin 33.217,-111.539; Tempe office + wrong-city both rejected).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M collectors/david-weekley/src/index.ts
Diff
commit de09b35174d70d47989f2324a817620f0fa373dc
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Wed Jul 29 02:42:15 2026 -0700
david-weekley: capture city-gated community MapPoint coord (yolo iter-6)
Adds communityGeo() that extracts the community coord from the page JSON,
strictly distinguishing it from the two decoy coords each DW page carries:
- REJECTS the warranty/regional-HQ coord (MapCenter, sibling of WarrantyEmail)
- REJECTS regional sales-office coords (MapPoint inside Offices[]) via a
city-equality gate — one office serves a whole metro (all Phoenix homes ->
one Tempe office), so its city never matches the home's city
- ACCEPTS only a community object (Grouping + Geolocation + Address + MapPoint)
whose MapPoint.Address.City/State equals the home's city+state, plus a coarse
US bbox. A wrong pin is worse than null.
The community coord exists only on per-community DETAIL pages; the per-metro
homes-ready-soon LIST pages this adapter fetches carry only warranty + office
coords, so on those it returns null (no wrong pins). Verified against a cached
list snapshot (null for all cities) and a live detail page (correct San Tan
Valley pin 33.217,-111.539; Tempe office + wrong-city both rejected).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
collectors/david-weekley/src/index.ts | 53 +++++++++++++++++++++++++++++++++--
1 file changed, 50 insertions(+), 3 deletions(-)
diff --git a/collectors/david-weekley/src/index.ts b/collectors/david-weekley/src/index.ts
index 8aba17a8..40e5b692 100644
--- a/collectors/david-weekley/src/index.ts
+++ b/collectors/david-weekley/src/index.ts
@@ -65,6 +65,45 @@ function featureValue(block: string, featureClass: string): string | null {
return m ? m[1]!.replace(/\s+/g, " ").trim() : null;
}
+/**
+ * COMMUNITY coordinate from the page JSON — city-gated, warranty-safe. [yolo iter-6]
+ *
+ * DW pages embed several distinct coords and picking the wrong one wrong-pins a home
+ * tens of miles from its city (worse than null), so this only trusts the ONE coord we
+ * can prove is the home's own community:
+ * - REJECTED: the warranty/regional-HQ coord — it lives in a `"MapCenter":{...}` sibling
+ * of `WarrantyEmail`/`WarrantyPhone`/`AfterHoursPhone`. Never a `MapCenter`.
+ * - REJECTED: the regional SALES-OFFICE coords — `"MapPoint"` objects nested inside an
+ * `"Offices":[{OfficeType,Address,DrivingDirections,MapImage,PhoneNumber,MapPoint}]`
+ * array. One office serves a whole metro (e.g. all Phoenix homes → one Tempe office),
+ * so its coord is 10-40mi from most homes. Its Address.City is the office city, which
+ * will NOT match the home's city — the city-gate below rejects it.
+ * - ACCEPTED: the community coord — a community object carrying `"Grouping":"<name>"` +
+ * `"Geolocation":N` + an `Address` whose City/StateAbbreviation is the COMMUNITY's own
+ * city, immediately followed by `"MapPoint":{Latitude,Longitude}`. This only appears on
+ * the per-community DETAIL page (the per-metro `homes-ready-soon` LIST pages carry only
+ * the warranty + office coords, so this returns null there — correct, no wrong pin).
+ *
+ * Gate: the matched community MapPoint's OWN Address.City+State must equal the home's
+ * city+state, AND the coord must sit in a coarse US bbox. City-equality is the strong gate
+ * that distinguishes the community coord from every regional-office coord on the same page.
+ */
+function communityGeo(html: string, city: string | null, state: string | null): { lat: number; lon: number } | null {
+ if (!city || !state) return null;
+ const re = /"Grouping":"[^"]*","Geolocation":\d+,"Address":\{"Line1":"[^"]*","Line2":[^,]*,"City":"([^"]*)","StateAbbreviation":"([^"]*)"[^}]*\},"MapPoint":\{"Latitude":(-?\d+(?:\.\d+)?),"Longitude":(-?\d+(?:\.\d+)?)/g;
+ const wantCity = city.toLowerCase().trim();
+ const wantState = state.toUpperCase().trim();
+ for (const m of html.matchAll(re)) {
+ if (m[1]!.toLowerCase().trim() !== wantCity) continue; // office/HQ coord → City mismatch → reject
+ if (m[2]!.toUpperCase().trim() !== wantState) continue;
+ const lat = Number(m[3]), lon = Number(m[4]);
+ if (!Number.isFinite(lat) || !Number.isFinite(lon) || lat === 0 || lon === 0) continue;
+ if (lat < 15 || lat > 72 || lon < -180 || lon > -60) continue; // coarse US bbox (lon must be west)
+ return { lat, lon };
+ }
+ return null;
+}
+
/** MOVE_IN_READY when "Ready Now"; else UNDER_CONSTRUCTION (dated) */
function statusOf(label: string | null): "MOVE_IN_READY" | "UNDER_CONSTRUCTION" {
if (label && /ready\s*now/i.test(label)) return "MOVE_IN_READY";
@@ -203,12 +242,17 @@ export const davidWeekleyAdapter: SourceAdapter = {
if (homes.length === 0) return { records: [], errors: [] }; // market page with no listed QMIs
const records: ExtractedRecord[] = [];
- // one community record per distinct community on the page (facts-only; geo is a follow-up)
+ // Community coord (city-gated, warranty/office-safe) — present on per-community DETAIL
+ // pages, null on the per-metro LIST pages (they carry only warranty + office coords). A
+ // home inherits its own community's coord only. [yolo iter-6]
+ const cgeoFor = (city: string | null, state: string | null) => communityGeo(html, city, state);
+ // one community record per distinct community on the page (facts-only)
const communitiesSeen = new Set<string>();
for (const h of homes) {
const cname = h.community ?? "Unknown";
if (!communitiesSeen.has(cname)) {
communitiesSeen.add(cname);
+ const cg = cgeoFor(h.city, h.state);
records.push({
entityType: "community",
canonicalHints: { builderSlug: BUILDER_SLUG, communityName: cname },
@@ -220,8 +264,8 @@ export const davidWeekleyAdapter: SourceAdapter = {
zip: fv(h.zip, h.zip, page.url),
county: fv<string>(null, null, page.url),
metro: fv<string>(null, null, page.url),
- lat: fv<number>(null, null, page.url),
- lon: fv<number>(null, null, page.url),
+ lat: fv(cg?.lat ?? null, cg ? String(cg.lat) : null, page.url, cg ? "community MapPoint (city-gated)" : null),
+ lon: fv(cg?.lon ?? null, cg ? String(cg.lon) : null, page.url, cg ? "community MapPoint (city-gated)" : null),
hoaFeeMonthly: fv<number>(null, null, page.url),
schoolDistrict: fv<string>(null, null, page.url),
ageRestricted: fv<boolean>(null, null, page.url),
@@ -233,6 +277,7 @@ export const davidWeekleyAdapter: SourceAdapter = {
for (const h of homes) {
if (!h.street) continue;
+ const cg = cgeoFor(h.city, h.state); // home inherits its own community's city-gated coord (null on list pages)
records.push({
entityType: "inventory_home",
canonicalHints: {
@@ -247,6 +292,8 @@ export const davidWeekleyAdapter: SourceAdapter = {
city: fv(h.city, h.city, page.url),
state: fv(h.state, h.state, page.url),
zip: fv(h.zip, h.zip, page.url),
+ lat: fv(cg?.lat ?? null, cg ? String(cg.lat) : null, page.url, cg ? "community MapPoint (home inherits community coord, city-gated)" : null),
+ lon: fv(cg?.lon ?? null, cg ? String(cg.lon) : null, page.url, cg ? "community MapPoint (home inherits community coord, city-gated)" : null),
price: fv(h.price, h.priceRaw, page.url, h.priceRaw ? `price ${h.priceRaw}` : null),
beds: fv(h.beds, null, page.url),
bathsTotal: fv(h.baths, null, page.url),
← 11a5e5fa pipeline: make evidence delete+create atomic (contrarian fix
·
back to Homesonspec
·
auto-save: 2026-07-29T07:06:42 (3 files) — collectors/dream- 0b79470c →