Files
Jyotisha/scripts/rectification/horary_observation.py
T

99 lines
3.6 KiB
Python

"""Display-only Horary recast for birth-time rectification.
If the user gives the time they first asked the question, recast a natal-like
chart at that local datetime. Never score it. Never block propose or confirm.
"""
from __future__ import annotations
import re
from typing import Any
from scripts.rectification.house_table import SIGNS_CN
from scripts.rectification.kp_cusp_observation import observe_kp_cusps
_CLOCK = re.compile(r"(?:[01]?\d|2[0-3]):[0-5]\d")
def _question_clock(event: dict[str, Any]) -> str:
summary = str(event.get("summary") or "")
match = _CLOCK.search(summary)
if match:
hour, minute = match.group(0).split(":")
return f"{int(hour):02d}:{int(minute):02d}"
return "12:00"
def build_horary_observation(request: dict[str, Any]) -> dict[str, Any]:
events = [
event for event in (request.get("events") or [])
if isinstance(event, dict) and event.get("event_kind") == "horary_query"
]
if not events:
return {
"status": "skipped",
"user_meaning": "没有第一次问起这件事的时间,占问观察未执行。",
"unique_minute_claim": False,
}
try:
lat = float(request["lat"])
lon = float(request["lon"])
tz = float(request["tz"])
except (KeyError, TypeError, ValueError):
return {
"status": "blocked",
"user_meaning": "占问时间已记录,但观察盘未能重算。不计分,不挡提出门。",
"unique_minute_claim": False,
}
event = events[0]
date_text = str(event.get("date_start") or "")[:10]
clock = _question_clock(event)
try:
year, month, day = (int(part) for part in date_text.split("-"))
hour, minute = (int(part) for part in clock.split(":"))
import domain_calculation_service
chart = domain_calculation_service.compute_chart({
"year": year,
"month": month,
"day": day,
"hour": hour,
"minute": minute,
"lat": float(request["lat"]),
"lon": float(request["lon"]),
"tz": float(request["tz"]),
"ayanamsa": "lahiri",
"node_mode": "mean",
})
asc = chart.get("ascendant") or {}
sign = str(asc.get("sign") or "")
lagna = SIGNS_CN.get(sign, sign)
birth_info = chart.get("birth_info") if isinstance(chart.get("birth_info"), dict) else {}
kp = observe_kp_cusps(birth_info.get("julian_day"), float(request["lat"]), float(request["lon"]))
angles = {}
if kp.get("status") == "executed":
for house in ("1", "4", "7", "10"):
row = (kp.get("houses") or {}).get(house) or {}
angles[house] = {
"sub_lord": row.get("sub_lord"),
"nakshatra_lord": row.get("nakshatra_lord"),
}
return {
"status": "executed",
"question_date": date_text,
"question_time": clock,
"lagna": lagna if lagna else None,
"kp_angles": angles,
"user_meaning": (
f"已按问起时间 {date_text} {clock} 重算占问盘作观察,不计分,不确认唯一分钟。"
),
"unique_minute_claim": False,
}
except (TypeError, ValueError, KeyError, OverflowError, OSError):
return {
"status": "blocked",
"question_date": date_text,
"question_time": clock,
"user_meaning": "占问时间已记录,但观察盘未能重算。不计分,不挡提出门。",
"unique_minute_claim": False,
}