Passa al contenuto principale

P2E Territory Control Panel

ActiveMutable

The "P2E Trixel Territory Control" panel is the 3D globe surface that appears at the top of the P2E Situation Room page in network-crm (route /p2e). It is the hero visual for PlayRoll's Italy GTM program — the place where venue candidates, field ambassadors, and contributor nodes are overlaid on a triangular subdivision of Italy.

This page exists because the panel mixes real Supabase-backed data with mock field-ops data, and that mix is not obvious to a viewer. Read this before quoting numbers from the panel in any decision.

Where it lives

  • Component: client/src/components/situation-globe.tsx in network-crm.
  • Mounted in: client/src/pages/p2e-dashboard.tsx (P2E Situation Room).
  • Backed by:
    • /api/v1/p2e/snapshot — programs, contributors, payment reviews, expansion theatres.
    • /api/v1/p2e/italy-places-candidates — 4 412 Italian venue candidates (Google Places sweep).
  • Also mounted in b2b and d2c dashboard modes, but those do not render the territory-control layer.

What the panel is

A Deck.gl globe (_GlobeView) centered on Italy with six layers stacked on top of each other. The user can drag-rotate, zoom (6 LOD bands from "Theatre" down to "Local"), click trixels to drill in, and toggle POI categories / review-verdict filters.

The name "Trixel Territory Control" is GTM-flavored phrasing for a triangular geographic subdivision. There is no game-theoretic territory mechanic underneath — the trixels are pure UI geometry.

Layers — what is shown and where it comes from

#LayerSourceTrust
1Italy land outline + country status fillNatural Earth ne_50m_admin_0_countries.geojson (fetched at runtime from GitHub)✅ Geometry only
2Trixel mask (6 LOD bands: Theatre → Macro → Region → Province → City → Local)Computed in trixel.ts from the Italy polygon — pure geometry, no business data✅ Geometry only
3POI cluster icons + count badgesAggregated from italy_places_direct_deduped.geojson (Google Places sweep)⚠️ See "Venue data" below
4Individual POI sprites (visible at high zoom or after a trixel is selected)Same dataset, normalized by italy-places.ts⚠️ See "Venue data" below
5Field ambassador avatars + selection panelHardcoded MOCK_P2E_AMBASSADORS in the client bundle❌ Mock — not real people
6Ambassador referral lines (ambassador → contributor → POI)Built from the mock ambassadors' hardcoded contributorIds / poiIds arrays❌ Mock — connects mock ambassadors to real contributor IDs by string match
7Contributor graph nodes (yellow dots, LOD-aggregated)useP2ESnapshot()/api/v1/p2e/snapshot → Supabase✅ Live

The bottom-right stats overlay (ACTIVE / NODES / REFS / R{n} TRIXELS / POI CLUSTERS) is computed from the live snapshot (expansion theatres, contributors, referral edges) plus the trixel/POI counts. The ACTIVE / NODES / REFS numbers are trustworthy; the trixel/cluster counts are trustworthy as render-state but they describe the geometry overlay, not the field operation.

Venue data — the ⚠️ case

The POI layer is the only one where the trust answer is "depends":

  • Identity (this place exists, with this lat/lng/phone/address): high confidence. Comes from Google Places Text Search via the sweep in script/p2e_google_places/.
  • Category membership (this place is actually a LAN center / internet cafe / arcade / TCG store): variable. The classifier is a regex + Google primary_type pass in finalize_fresh_google_places_v4.py. Every venue is tagged with one of:
    • A_explicit — name or type explicitly matches the category (~1 159 venues).
    • B_probable / B_auxiliary — weak inference (~4 234 venues).
    • C_review — fresh hit only, classifier abstained (~87 050 venues, hidden from the default frontend filter).
  • Review verdict (the REVIEW PROOF / UNCONFIRMED / CONFLICT filters): a second-pass enrichment in enrich_google_places_reviews.py looks at Google review text for category-specific words. R2_REVIEW_TEXT_SUPPORTS_SET means review text confirms the category; R1_REVIEWS_EXIST_NO_TEXT_MATCH means it has reviews but they don't prove anything.

Default filter behavior in the panel: only A_explicit + B_probable + B_auxiliary venues with at least one Google rating, restricted to R2_REVIEW_TEXT_SUPPORTS_SET verdicts. The "LOW CONF N" toggle lets you reveal the candidates that are below the confidence floor.

Full provenance of the dataset and the storage/security posture live in network-crm/docs/p2e-italy-venue-map-ops.md.

Mock data — the ❌ case

The six ambassadors (Ale Contour / Marco Relay / Giulia Node / Antonio South / Marta Cards / Sara Coast) and every line that originates from them are mock data hardcoded in client/src/components/situation-globe/mock-data.ts. Their reach, openLoops, currentMove, status, and the contributor/POI IDs they "refer" are placeholders. The mock connects to real contributor IDs by string match — so if a contributor id happens to coincide with a hardcoded one (e.g. c-marco), the line goes to a real point on the map but the relationship is fictional.

If/when real field ambassadors enter Supabase, this layer should be re-sourced from the same /api/v1/p2e/snapshot endpoint and the mock data file deleted. Until then, the ambassador panel is demo-grade.

Endpoint security

/api/v1/p2e/italy-places-candidates is gated by getControlIdentity({ requireAuth: true }) and served with a private cache header. Production access requires the Cloudflare Access header (cf-access-authenticated-user-email); local development falls back to a dev identity. Do not serve this endpoint publicly — it carries Google Places PII (phone numbers, addresses).

Operator checklist

When someone is about to act on what the panel shows:

  • Numbers that come from the bottom-right stats overlay (ACTIVE / NODES / REFS) — trust.
  • Yellow contributor dots and the cluster aggregations — trust.
  • The 4 412 venues visible in default filter — identity trustworthy, category needs ambassador/manual confirmation before activation.
  • Anything ambassador-related (avatars, focus, current move, lines) — do not quote. It is demo material.

Open questions

  • Should the mock ambassador layer be hidden behind a feature flag so customer/investor demos can opt-in without baking mock data into prod? (Currently always rendered in p2e mode.)
  • The R{n} TRIXELS count in the stats overlay surfaces the geometry mesh size, not a business count. Worth keeping as a debug stat but should be styled differently from the real KPIs.
  • The 8.5 MB Google Places GeoJSON is committed to the repo. Migration to a CDN is tracked in p2e-italy-venue-map-ops.md. Until then, panel boot pays a one-time fetch cost (now cached for 1h via Cache-Control: private, max-age=3600).