Port a0ec4bc Extract the shared graded-window tail in views.py from monorepo (drift reconciliation)
Claude-Session: https://claude.ai/code/session_01RdARHDJaYC1wSQRTYM6t3Z
This commit is contained in:
parent
8cec935b06
commit
cc0b1e298f
1 changed files with 17 additions and 8 deletions
|
|
@ -143,6 +143,19 @@ def _attach_dry_streaks(graded: list[dict], *precip_frames) -> None:
|
||||||
g["dsr"] = dsr_map.get(g["date"])
|
g["dsr"] = dsr_map.get(g["date"])
|
||||||
|
|
||||||
|
|
||||||
|
def _graded_window(history, rows, precip_frames, doy) -> tuple[list[dict], dict]:
|
||||||
|
"""The shared tail of the /grade and /forecast payloads: grade `rows` against
|
||||||
|
history, attach dry streaks over `precip_frames`, order newest-first, and pair
|
||||||
|
the result with the target day-of-year's climatology summary. The window
|
||||||
|
*assembly* (recent+archive merge vs future-only filter) differs per builder and
|
||||||
|
stays there; only this post-processing is shared."""
|
||||||
|
graded = _grade_rows(history, rows)
|
||||||
|
_attach_dry_streaks(graded, *precip_frames)
|
||||||
|
graded.reverse() # newest-first for display (the chart reverses to L→R chronological)
|
||||||
|
climo = grading.climatology(history, doy)
|
||||||
|
return graded, climo
|
||||||
|
|
||||||
|
|
||||||
def build_grade(cell, target, days, history, recent, cache_meta, place, run=None, after=14) -> dict:
|
def build_grade(cell, target, days, history, recent, cache_meta, place, run=None, after=14) -> dict:
|
||||||
"""/grade payload: a window of days centered on the target — `days` of history
|
"""/grade payload: a window of days centered on the target — `days` of history
|
||||||
before it, the target itself, then up to `after` days after it — plus the
|
before it, the target itself, then up to `after` days after it — plus the
|
||||||
|
|
@ -167,10 +180,8 @@ def build_grade(cell, target, days, history, recent, cache_meta, place, run=None
|
||||||
# old pandas concat when the two sources' columns differ (e.g. a reduced
|
# old pandas concat when the two sources' columns differ (e.g. a reduced
|
||||||
# recent bundle); grading treats an absent column's value as None.
|
# recent bundle); grading treats an absent column's value as None.
|
||||||
window = pl.concat([rwin, hwin], how="diagonal_relaxed").sort("date")
|
window = pl.concat([rwin, hwin], how="diagonal_relaxed").sort("date")
|
||||||
graded = _grade_rows(history, window)
|
graded, climo = _graded_window(history, window, (history, recent),
|
||||||
_attach_dry_streaks(graded, history, recent)
|
target.timetuple().tm_yday)
|
||||||
graded.reverse() # newest first for display
|
|
||||||
climo = grading.climatology(history, target.timetuple().tm_yday)
|
|
||||||
|
|
||||||
# Summarize what this run actually covered. A fresh history fetch pulls the
|
# Summarize what this run actually covered. A fresh history fetch pulls the
|
||||||
# full ~45-year archive (run_type "full"); a cache hit only fetched the
|
# full ~45-year archive (run_type "full"); a cache hit only fetched the
|
||||||
|
|
@ -274,10 +285,8 @@ def build_forecast(cell, days, history, fc, today, place, run=None) -> dict:
|
||||||
# Strictly future days (tomorrow onward), earliest→latest, capped at `days`.
|
# Strictly future days (tomorrow onward), earliest→latest, capped at `days`.
|
||||||
future = fc.filter(pl.col("date") > today).sort("date").head(days)
|
future = fc.filter(pl.col("date") > today).sort("date").head(days)
|
||||||
with run.phase("grading"):
|
with run.phase("grading"):
|
||||||
graded = _grade_rows(history, future)
|
graded, climo = _graded_window(history, future, (history, fc),
|
||||||
_attach_dry_streaks(graded, history, fc)
|
today.timetuple().tm_yday)
|
||||||
graded.reverse() # furthest-out first, so the chart reverses to L→R chronological
|
|
||||||
climo = grading.climatology(history, today.timetuple().tm_yday)
|
|
||||||
run.set(graded_days=len(graded), place_found=place is not None)
|
run.set(graded_days=len(graded), place_found=place is not None)
|
||||||
return {
|
return {
|
||||||
"api_version": "v2",
|
"api_version": "v2",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue