79bce8ae90
- engine/lots.py: formuła Lot = C + A − B z odwracaniem w horoskopach nocnych (zamiana A<->B); 7 Lots hermetycznych (Fortuna, Duch, Eros, Konieczność, Odwaga, Zwycięstwo, Nemezis) — Fortuna i Duch liczone pierwsze, bo pozostałe się do nich odwołują. Dwa warianty: degree (domyślny) i sign (całe znaki). - build_chart: liczy sektę (reużyta is_day_birth z Firdarii) i zwraca lots ze znakiem, pozycją i domem; parametr lots_method. - wyszukiwarka: token [PF (tak Fortuna występuje w realnej bazie) + rozwinięcie skrótu do "Part of Fortune". - widok Horoskop: tabela Lots z formułami i sektą. Walidacja (dwie niezależne wyrocznie z notes3): - Fortuna = Can 12°35'27" vs astro-seek Can 12°35'24" (3 sekundy różnicy), dom 1; - Duch potwierdzony przez swoją antyscję (Taurus 28°14' z tabeli antyscji); - odwracanie nocne: Fortuna nocna == Duch dzienny i odwrotnie; - Lots pochodne faktycznie używają Fortuny/Ducha; wariant sign trafia w 0° znaku. 85 testów przechodzi (nowy test_lots). Odblokowuje Zodiacal Releasing (LOG-11), które startuje z Fortuny/Ducha. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
61 lines
2.3 KiB
Python
61 lines
2.3 KiB
Python
"""Lots / punkty arabskie (LOG-08) — 7 Lots hermetycznych.
|
||
|
||
Formuła: Lot = C + A − B (od punktu C odmierzamy odległość między A i B).
|
||
Większość Lots **odwraca się w horoskopach nocnych** (zamiana A↔B) — np.
|
||
Fortuna: dzień Asc + Mo − Su, noc Asc + Su − Mo.
|
||
|
||
Dwa warianty liczenia (notes3):
|
||
- `degree` (domyślny) — dokładny stopień,
|
||
- `sign` — liczone całymi znakami (Lot wypada na 0° wyliczonego znaku).
|
||
|
||
Kolejność ma znaczenie: Fortuna i Duch liczone są pierwsze, bo pozostałe Lots
|
||
odwołują się do nich.
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
from app.engine.formats import norm360, sign_index
|
||
|
||
# (nazwa, C, A, B, odwracalny w nocy)
|
||
LOT_DEFS: list[tuple[str, str, str, str, bool]] = [
|
||
("Fortune", "Asc", "Moon", "Sun", True),
|
||
("Spirit", "Asc", "Sun", "Moon", True),
|
||
("Eros", "Asc", "Venus", "Spirit", True),
|
||
("Necessity", "Asc", "Fortune", "Mercury", True),
|
||
("Courage", "Asc", "Fortune", "Mars", True),
|
||
("Victory", "Asc", "Jupiter", "Spirit", True),
|
||
("Nemesis", "Asc", "Fortune", "Saturn", True),
|
||
]
|
||
|
||
METHODS = ("degree", "sign")
|
||
|
||
|
||
def compute_lots(
|
||
points: dict[str, float], is_day: bool, method: str = "degree"
|
||
) -> list[dict]:
|
||
"""points: nazwa → długość natalna (wymagane Asc + planety formuł).
|
||
|
||
Zwraca listę {name, longitude, formula} w kolejności definicji.
|
||
"""
|
||
if method not in METHODS:
|
||
raise ValueError(f"nieznana metoda liczenia Lots: {method}")
|
||
|
||
vals = dict(points)
|
||
out: list[dict] = []
|
||
for name, c, a, b, reversible in LOT_DEFS:
|
||
first, second = (a, b) if (is_day or not reversible) else (b, a)
|
||
if any(k not in vals for k in (c, first, second)):
|
||
continue # brak składnika — pomijamy
|
||
if method == "sign":
|
||
idx = (sign_index(vals[c]) + sign_index(vals[first])
|
||
- sign_index(vals[second])) % 12
|
||
lon = idx * 30.0
|
||
else:
|
||
lon = norm360(vals[c] + vals[first] - vals[second])
|
||
vals[name] = lon # dostępny dla kolejnych Lots
|
||
out.append({
|
||
"name": name,
|
||
"longitude": lon,
|
||
"formula": f"{c} + {first} − {second}",
|
||
})
|
||
return out
|