Files
padelnomics/transform/sqlmesh_padelnomics/models/serving
Deeman 10266c3a24 fix(sql): opportunity_score — supply gap ceiling 4→8/100k + doc findings
Raises supply gap ceiling from 4/100k to 8/100k in
location_opportunity_profile.sql. The original 4/100k hard cliff
truncated opportunity scores to 0 for any city with ≥4 courts/100k,
but our data undercounts ~87% of real courts (FIP: 17,300 Spanish
courts vs 2,239 in our DB). Raising to 8/100k gives a gentler gradient
and fairer partial credit when density data is incomplete.

Documents existing formula behaviour discovered during analysis:
- Income PPS: country-level constants (18k-37k range) saturate the
  /200 ceiling — all EU countries get flat 20/20 pts until city-level
  income data lands.
- Catchment NULL: DuckDB LEAST(1.0, NULL) = 1.0 (ignores nulls), so
  NULL nearest_padel_court_km already yields full 15 pts. COALESCE
  fallback is dead code but harmless.
- Tennis courts within 25km: dim_locations data is empty (all 0 rows)
  — 10-court threshold is correct for when data arrives, contributes
  0 pts everywhere for now.

Effective score impact: minimal (99% of locations have 0 courts/100k,
so supply gap was already at max). Only ~1,050 dense-court cities
see a score increase (from 0 gap pts to partial gap pts).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 06:57:57 +01:00
..

serving

Analytics-ready views consumed by the web app and programmatic SEO. Query these from analytics.py via DuckDB read-only connection.

Naming convention: serving.<purpose> (e.g. serving.city_market_profile)