"""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