feat: synastria — aspekty między dwoma horoskopami (PRE-04)
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m32s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m28s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 11s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 9s
build / build (push) Successful in 25s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 11m18s
Testy / Kontrola składni wszystkich warstw (push) Successful in 31s
Testy / Build obrazu silnika B (swisseph) (push) Failing after 13m6s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Failing after 13m25s
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m32s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m28s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 11s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 9s
build / build (push) Successful in 25s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 11m18s
Testy / Kontrola składni wszystkich warstw (push) Successful in 31s
Testy / Build obrazu silnika B (swisseph) (push) Failing after 13m6s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Failing after 13m25s
Pierwsza technika relacyjna z pełnym UI (Returns były już w kalendarzu od LOG-12). Dwie osoby → aspekty MIĘDZY ich horoskopami (planeta osoby A do planety osoby B). Silnik: `find_cross_aspects(a, b, orb, luminary_bonus, minor)` — każdy obiekt A × każdy obiekt B. `obj1` = osoba A, `obj2` = osoba B. Statyczne (dwa natale, brak wspólnego czasu) → bez applying/separating. Par sztywnych (NN/SN) NIE wycinamy — między dwiema osobami to realny aspekt, nie artefakt definicji. Wspólny matcher `_first_aspect` (z find_aspects), więc orb/bonus/aspekty poboczne działają tak samo. Endpoint `POST /chart/synastry` (dwie osoby + zodiak + ustawienia aspektów) → pozycje obu + siatka aspektów z glifami. Prezentacja: zakładka „Synastria", formularz dwóch osób (pętla po a_/b_), tabela aspektów A · aspekt · B · orb. Weryfikacja na żywym API: 13+13 obiektów, 63 aspekty synastryczne z poprawnymi glifami i bonusem świateł (A.Sun ☌ B.Venus przy orbie 8.67 = 8+2). Testy: logika +4 (cross-aspekty, kolejność A/B, brak filtra par sztywnych, brak applying), prezentacja +7 (trasa, formularz dwóch osób, klient, tabela). Logika 277, prezentacja 228. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit was merged in pull request #51.
This commit is contained in:
@@ -277,6 +277,49 @@ def compile_pdf(payload: dict):
|
||||
headers={"Content-Disposition": 'attachment; filename="raport.pdf"'})
|
||||
|
||||
|
||||
# ---------------- Synastria (technika relacyjna) ----------------
|
||||
@app.get("/synastry", response_class=HTMLResponse)
|
||||
def synastry_form(request: Request):
|
||||
# domyślne liczby, żeby pola number nie były puste (puste → błąd przy wysyłce)
|
||||
form = {"a_tz_offset": 0, "a_lat": 0, "a_lon": 0, "b_tz_offset": 0, "b_lat": 0, "b_lon": 0,
|
||||
"aspect_orb": 8, "aspect_luminary_bonus": 2}
|
||||
return templates.TemplateResponse(request, "synastry.html", {"result": None, "form": form})
|
||||
|
||||
|
||||
@app.post("/synastry", response_class=HTMLResponse)
|
||||
def synastry_run(
|
||||
request: Request,
|
||||
a_person: str = Form(""), a_date: str = Form(...), a_time: str = Form(...),
|
||||
a_tz_offset: float = Form(0.0), a_lat: float = Form(0.0), a_lon: float = Form(0.0),
|
||||
b_person: str = Form(""), b_date: str = Form(...), b_time: str = Form(...),
|
||||
b_tz_offset: float = Form(0.0), b_lat: float = Form(0.0), b_lon: float = Form(0.0),
|
||||
zodiac: str = Form("tropical"),
|
||||
aspect_orb: float = Form(8.0), aspect_luminary_bonus: float = Form(2.0),
|
||||
aspect_minor: bool = Form(False),
|
||||
):
|
||||
"""Synastria (PRE-04): dwie osoby → aspekty między ich horoskopami."""
|
||||
form = {"a_person": a_person, "a_date": a_date, "a_time": a_time, "a_tz_offset": a_tz_offset,
|
||||
"a_lat": a_lat, "a_lon": a_lon, "b_person": b_person, "b_date": b_date,
|
||||
"b_time": b_time, "b_tz_offset": b_tz_offset, "b_lat": b_lat, "b_lon": b_lon,
|
||||
"zodiac": zodiac, "aspect_orb": aspect_orb,
|
||||
"aspect_luminary_bonus": aspect_luminary_bonus, "aspect_minor": aspect_minor}
|
||||
ctx: dict = {"form": form, "result": None, "error": None}
|
||||
try:
|
||||
iso_a, _ = _build_utc(a_date, a_time, a_tz_offset)
|
||||
iso_b, _ = _build_utc(b_date, b_time, b_tz_offset)
|
||||
ctx["result"] = logic.synastry(
|
||||
{"when_utc": iso_a, "lat": a_lat, "lon": a_lon},
|
||||
{"when_utc": iso_b, "lat": b_lat, "lon": b_lon},
|
||||
zodiac=zodiac, aspect_orb=aspect_orb,
|
||||
aspect_luminary_bonus=aspect_luminary_bonus, aspect_minor=aspect_minor,
|
||||
)
|
||||
except httpx.HTTPError as e:
|
||||
ctx["error"] = _logic_error(e)
|
||||
except ValueError as e:
|
||||
ctx["error"] = f"Niepoprawne dane wejściowe: {e}"
|
||||
return templates.TemplateResponse(request, "synastry.html", ctx)
|
||||
|
||||
|
||||
# ---------------- Sygnifikatory (wyszukiwarka w bazach) ----------------
|
||||
@app.get("/significators", response_class=HTMLResponse)
|
||||
def significators_form(request: Request):
|
||||
|
||||
Reference in New Issue
Block a user