Files
Jyotisha/scripts/birth_window_range_reading.py
ClaudeandClaude Opus 5.5 c1a69445b5 refactor: retire event-scored rectification backend (BUG-1644)
Remove the V5 scoring pipeline, dynamic rectification, minute-rectification
evaluations and the research scripts built on them, plus their API routes.
Keep the upstream skill layer (gate, questionnaire, active events), the
varga-segments scan and the consult range reading (moved to
scripts/birth_window_range_reading.py).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXozbkyFNqbu8pVEtZ7W
2026-11-06 02:40:28 +08:00

88 lines
3.3 KiB
Python

"""Stable vs minute-sensitive reading themes across a declared birth window.
Serves `/api/rectification/v5/range_reading` for consultation (a person whose
birth time is a range). Moved out of the retired rectification V5 API service
on 2026-11-06; behaviour unchanged.
"""
from __future__ import annotations
from typing import Any, Mapping
def range_reading(request: Mapping[str, Any]) -> dict[str, Any]:
"""Stable vs minute-sensitive themes for one unresolved clock window."""
from types import SimpleNamespace
from scripts.jyotish_engine import _build_birth_time_sensitivity
body = dict(request or {})
birth_date = str(body.get("birth_date") or "").strip()
if birth_date:
year_text, month_text, day_text = birth_date.split("-", 2)
year, month, day = int(year_text), int(month_text), int(day_text)
else:
year, month, day = int(body["year"]), int(body["month"]), int(body["day"])
representative = str(body.get("representative_time") or "")[:5]
if len(representative) == 5 and representative[2] == ":":
hour, minute = int(representative[:2]), int(representative[3:])
else:
hour = int(body.get("hour") or 12)
minute = int(body.get("minute") or 0)
representative = f"{hour:02d}:{minute:02d}"
raw_range = body.get("candidate_range")
if isinstance(raw_range, Mapping):
start_time = str(raw_range.get("start_time") or "")[:5]
end_time = str(raw_range.get("end_time") or "")[:5]
representative = str(raw_range.get("representative_time") or representative)[:5]
else:
start_time = str(body.get("start_time") or "")[:5]
end_time = str(body.get("end_time") or "")[:5]
hour, minute = int(representative[:2]), int(representative[3:])
accuracy = str(body.get("birth_time_accuracy") or "provisional")
args = SimpleNamespace(
year=year,
month=month,
day=day,
hour=hour,
minute=minute,
second=0,
lat=float(body["lat"]),
lon=float(body["lon"]),
tz=float(body["tz"]),
ayanamsa=body.get("ayanamsa") or "raman",
node_mode=body.get("node_mode") or "mean",
birth_time_accuracy=accuracy,
candidate_range={
"start_time": start_time,
"end_time": end_time,
"representative_time": representative,
},
representative_time=representative,
declared_window_start=None,
declared_window_end=None,
uncertainty_before_minutes=None,
uncertainty_after_minutes=None,
)
sensitivity = _build_birth_time_sensitivity(args)
themes = sensitivity.get("theme_sensitivity")
themes = themes if isinstance(themes, dict) else {}
stable = [
key for key, row in themes.items()
if isinstance(row, dict) and row.get("status") == "stable"
]
sensitive = [
key for key, row in themes.items()
if isinstance(row, dict) and row.get("status") == "sensitive"
]
return {
"window": sensitivity.get("window"),
"stable_themes": stable,
"sensitive_themes": sensitive,
"claim_boundary": sensitivity.get("claim_boundary"),
"theme_sensitivity": themes,
"accuracy": sensitivity.get("accuracy"),
"status": sensitivity.get("status"),
}