# ============================================================================= # QWHPI — Quebec Weekly Housing Price Index # Author : Simon-Pierre Boucher # Contact : contact@spboucher.ai # File : api/app/routers/maps.py # Purpose : Choropleth data endpoint — one metric across geographies. # ============================================================================= """Map data endpoints (region choropleth + assessment gap).""" from __future__ import annotations import polars as pl from fastapi import APIRouter, HTTPException, Query, Request, Response from app.deps import etag_for from app.schemas import MapCell, MapResponse from app.services import data router = APIRouter() METRICS = { "yoy": "yoy_pct", "six_month": "six_month_pct", "three_month": "three_month_pct", "index_level": "index_smoothed", } @router.get("/map", response_model=MapResponse) def map_data( request: Request, response: Response, metric: str = Query("yoy", description=f"one of {sorted(METRICS)} or assessment_gap"), level: str = Query("region", pattern="^(region|municipality)$"), type: str = Query("all"), period: str | None = None, ): """One metric per geography for choropleth rendering.""" c = data.canonical().filter( (pl.col("geography_level") == level) & (pl.col("property_type") == type)) if period is None: period = c.filter(~pl.col("is_partial_month"))["period"].max() if metric == "assessment_gap": gap = data.assessment_gap().filter( (pl.col("property_type") == type) & (pl.col("period") == period) & pl.col("geography_id").str.starts_with("region-" if level == "region" else "")) c_wk = c.filter(pl.col("period") == period).select( "geography_id", "geography_name", "reliability_grade", "transactions") j = c_wk.join(gap, on="geography_id", how="left") cells = [MapCell(geography_id=r["geography_id"], geography_name=r["geography_name"], value=r["median_ratio"], reliability_grade=r["reliability_grade"], transactions=r["transactions"]) for r in j.iter_rows(named=True)] else: if metric not in METRICS: raise HTTPException(422, f"metric must be one of {sorted(METRICS)} or assessment_gap") col = METRICS[metric] wk = c.filter(pl.col("period") == period) if wk.height == 0: raise HTTPException(404, f"no data for period {period}") cells = [MapCell(geography_id=r["geography_id"], geography_name=r["geography_name"], value=r[col], reliability_grade=r["reliability_grade"], transactions=r["transactions"]) for r in wk.iter_rows(named=True)] if etag_for(request, response, metric, level, type, str(period)): return Response(status_code=304) return MapResponse(metric=metric, level=level, property_type=type, period=str(period), cells=cells)