feat(chart): 盘面数据 card beside the board, linked both ways
Independent Staging Quality Gate / validate (push) Successful in 29m39s
Independent Staging Quality Gate / publish (push) Successful in 4m3s

The chart page's tables move into one fixed-height card beside the board
with nine tabs: 行星, 虚星, 特殊点, 映射, 八分点, 星力, 大运, 敌友, 瑜伽.
The point tabs and 八分点 are the board's layers, switched together from
either side. 星力, 大运, 敌友 and 瑜伽 mark, tint, link and fade bodies on
the natal board (lib/chart-board-focus.ts).

The planet table gains the ascendant row, nakshatra lord, pada and the
seven Chara karakas, now produced by /api/chart_points from
jaimini.calc_chara_karaka_7 (blocked on a tie). Every card keeps a fixed
height and scrolls inside; tables never wrap and can be dragged sideways.
Hint captions are gone, 八宫点 reads 八分点, and the deep reading keeps
time, energy and birth data only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
This commit is contained in:
2026-10-30 16:27:04 +08:00
co-authored by Claude Opus 5.5
parent 2df7645d2c
commit 5157f96df3
22 changed files with 1519 additions and 611 deletions
+27
View File
@@ -9,6 +9,8 @@ page does not have to run the full reading:
- Yogi / Avayogi: ``annual_native.yogi_sphuta.build_yogi_sphuta_local``
- arudha padas A1–A11 and UL: ``jaimini.calc_arudha_padas``
- friendship (natural, temporary, compound): ``jyotish_engine._build_planetary_friendship_snapshot``
- Chara karakas, seven-planet scheme: ``jaimini.calc_chara_karaka_7``; two of the
seven on the same in-sign degree block the table instead of picking an order
Each block fails on its own (``status: blocked`` + reason); one failure never
fails the response.
@@ -81,6 +83,11 @@ SPECIAL_ORDER = (
"Bhava_Lagna", "Hora_Lagna", "Ghati_Lagna", "ViGhati_Lagna",
"Pranapada_Lagna", "Sree_Lagna", "Indu_Lagna", "Varnada_Lagna",
)
KARAKA_SHORT = {
"Atmakaraka": "AK", "Amatyakaraka": "AmK", "Bhratrikaraka": "BK", "Matrikaraka": "MK",
"Putrakaraka": "PK", "Gnatikaraka": "GK", "Darakaraka": "DK",
}
SEVEN = ("Sun", "Moon", "Mars", "Mercury", "Jupiter", "Venus", "Saturn")
ARUDHA_ORDER = ("A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "A10", "A11", "UL")
@@ -163,6 +170,25 @@ def compute_chart_points(body: dict[str, Any]) -> dict[str, Any]:
})
return {"status": "computed", "rows": rows}
def karakas() -> dict[str, Any]:
from jaimini import calc_chara_karaka_7
degrees = {name: lon % 30 for name in SEVEN if (lon := _longitude(planets.get(name))) is not None}
if len(degrees) < len(SEVEN):
return {"status": "blocked", "reason": "planets_missing"}
# calc_chara_karaka_7 reports four decimals; equal there is a tie it would order arbitrarily.
if len({round(value, 4) for value in degrees.values()}) < len(SEVEN):
return {"status": "blocked", "reason": "tied_degrees"}
table = calc_chara_karaka_7(degrees).get("karaka_table") or {}
rows = sorted(
(
{"key": KARAKA_SHORT[name], "planet": row["planet"], "rank": row["rank"], "degree_in_sign": row["degree_in_sign"]}
for name, row in table.items() if name in KARAKA_SHORT
),
key=lambda row: row["rank"],
)
return {"status": "computed", "scheme": "chara_7", "rows": rows}
def friendship() -> dict[str, Any]:
from jyotish_engine import _build_planetary_friendship_snapshot
@@ -177,4 +203,5 @@ def compute_chart_points(body: dict[str, Any]) -> dict[str, Any]:
"yogi_points": _guard(yogi),
"arudha_padas": _guard(arudha),
"friendship": _guard(friendship),
"chara_karakas": _guard(karakas),
}