mirror of
https://github.com/migatu/astrololo.git
synced 2026-07-14 21:38:37 +00:00
b013831492
Pierwsze techniki predykcyjne. Profekcje (LOG-10): - engine/profections.py: Whole Sign, wiek mod 12; profektowany Asc + Władca Roku (władca domicylowy) + profekcje MC/Su/Mo. Obsługa 29 lutego. - endpoint /chart/profections (zakres lat: start_age, count). Returns (LOG-12): - engine/returns.py: moment powrotu Słońca/Księżyca do długości natalnej; skan dobowy + bisekcja do ~sekundy, z pominięciem artefaktu zawinięcia 0/360. - endpoint /chart/return (kind solar|lunar, around) — zwraca pełny horoskop na znaleziony moment (oba warianty użycia po stronie technik wyżej). Walidacja: - profekcje zgodne co do joty z tabelą astro-seek z notes3 (wiek 0..42: Asc + Władca Roku + MC/Su/Mo). - Solar Return 2026: Słońce wraca do Tau 10°08'22" = natalny stopień; Lunar Return trafia natalny Księżyc <2'; samospójność potwierdzona. - 62 testy przechodzą (nowe: test_profections, test_returns). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
71 lines
2.6 KiB
Python
71 lines
2.6 KiB
Python
"""Profekcje roczne (LOG-10) — hellenistyczna technika time-lord.
|
|
|
|
Zasada (Whole Sign): co każde urodziny profektowany Ascendent przeskakuje o jeden
|
|
znak do przodu (wiek mod 12). Władca Roku (Lord of Year) = władca domicylowy
|
|
znaku profektowanego Asc. Profektować można każdy punkt natalny (MC, Słońce…) —
|
|
wszystkie przeskakują o tyle samo znaków.
|
|
|
|
Referencja: tabela profekcji w notes3 (astro-seek) dla horoskopu 30.04.1984
|
|
(wiek 0: Can/Moon, 1: Leo/Sun, …, 42: Cap/Saturn).
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
|
|
from app.engine.formats import SIGNS, sign_index
|
|
|
|
# władcy domicylowi (tradycyjni) — zgodni z tabelą referencyjną notes3
|
|
DOMICILE_RULERS = {
|
|
"Aries": "Mars", "Taurus": "Venus", "Gemini": "Mercury", "Cancer": "Moon",
|
|
"Leo": "Sun", "Virgo": "Mercury", "Libra": "Venus", "Scorpio": "Mars",
|
|
"Sagittarius": "Jupiter", "Capricorn": "Saturn", "Aquarius": "Saturn",
|
|
"Pisces": "Jupiter",
|
|
}
|
|
|
|
|
|
def age_at(birth_utc: datetime, when_utc: datetime) -> int:
|
|
"""Pełne lata między urodzeniem a danym momentem (wiek profekcyjny)."""
|
|
age = when_utc.year - birth_utc.year
|
|
if (when_utc.month, when_utc.day) < (birth_utc.month, birth_utc.day):
|
|
age -= 1
|
|
return max(age, 0)
|
|
|
|
|
|
def profected_sign(natal_lon: float, age: int) -> str:
|
|
"""Znak, do którego profektował punkt natalny po `age` latach."""
|
|
return SIGNS[(sign_index(natal_lon) + age) % 12]
|
|
|
|
|
|
def profection_rows(
|
|
natal_points: dict[str, float],
|
|
birth_utc: datetime,
|
|
start_age: int,
|
|
count: int,
|
|
) -> list[dict]:
|
|
"""Tabela profekcji dla zakresu lat życia.
|
|
|
|
natal_points: nazwa -> natalna długość ekliptyczna (musi zawierać 'Asc').
|
|
Każdy wiersz: wiek, data początku roku profekcyjnego (urodziny), znak
|
|
profektowanego Asc, Władca Roku oraz profekcje pozostałych punktów.
|
|
"""
|
|
def _birthday(year: int) -> datetime:
|
|
try:
|
|
return birth_utc.replace(year=year)
|
|
except ValueError: # 29 lutego w roku nieprzestępnym
|
|
return birth_utc.replace(year=year, day=28)
|
|
|
|
rows: list[dict] = []
|
|
for age in range(start_age, start_age + count):
|
|
asc_sign = profected_sign(natal_points["Asc"], age)
|
|
row = {
|
|
"age": age,
|
|
"from": _birthday(birth_utc.year + age).strftime("%Y-%m-%d"),
|
|
"profected_asc": asc_sign,
|
|
"lord_of_year": DOMICILE_RULERS[asc_sign],
|
|
}
|
|
for name, lon in natal_points.items():
|
|
if name != "Asc":
|
|
row[name] = profected_sign(lon, age)
|
|
rows.append(row)
|
|
return rows
|