"""Zbiorcza oś czasu z technik (LOG-14).""" import datetime as dt from app.engine.timeline import ( NAIBOD_KEY, build_timeline, profection_events, solar_arc_directions, ) BIRTH = dt.datetime(1984, 4, 30, 7, 35, tzinfo=dt.timezone.utc) # natalne długości (z horoskopu referencyjnego) NATAL = { "Asc": 112.18, "MC": 352.59, "Sun": 40.14, "Moon": 30.55, "Mercury": 27.38, "Venus": 27.68, "Mars": 234.54, "Jupiter": 282.96, "Saturn": 223.31, "Uranus": 252.81, "Neptune": 271.22, "Pluto": 210.48, } def _win(y0, y1): return (dt.datetime(y0, 1, 1, tzinfo=dt.timezone.utc), dt.datetime(y1, 12, 31, tzinfo=dt.timezone.utc)) def test_profection_events_in_window(): lo, hi = _win(2024, 2026) rows = profection_events(NATAL["Asc"], BIRTH, lo, hi) # rok profekcyjny wiek 42 zaczyna się 30.04.2026 -> Asc Capricorn ages = [r["significator"] for r in rows] assert any("Asc Capricorn" in a and "wiek 42" in a for a in ages) def test_solar_arc_exact_matches_arc_over_key(): lo, hi = _win(2020, 2030) rows = solar_arc_directions(NATAL, BIRTH, lo, hi, key=NAIBOD_KEY) assert rows, "brak dyrekcji w oknie" # dla każdej dyrekcji: łuk = (wiek * klucz), a data = urodziny + wiek -> spójne for r in rows[:5]: exact = dt.date.fromisoformat(r["exact"]) age_years = (dt.datetime(exact.year, exact.month, exact.day, tzinfo=dt.timezone.utc) - BIRTH).days / 365.2422 assert 36 <= age_years <= 47 # okno 2020-2030 = wiek ~36-46 assert r["technique"] == "solar_arc" and "dyr." in r["significator"] def test_directed_sun_conjunct_natal_mc_date(): # Sun natal 40.14 -> MC natal 352.59: łuk koniunkcji = (352.59-40.14)%360 = 312.45 # to > lifespan przy Naibod (~317 lat) -> NIE powinno być w oknie życia lo, hi = _win(1984, 2084) rows = solar_arc_directions(NATAL, BIRTH, lo, hi) sun_mc = [r for r in rows if r["significator"] == "dyr. Sun koniunkcja MC"] assert not sun_mc # łuk 312° = poza życiem def test_build_timeline_sorted_and_merged(): events = build_timeline(_FakeEngine(), _FakeNatal(), NATAL, "2025-01-01", "2027-01-01", techniques=["profection", "solar_arc"]) assert events dates = [e["exact"] for e in events] assert dates == sorted(dates) # posortowane po dacie dokładnej techs = {e["technique"] for e in events} assert "profection" in techs and "solar_arc" in techs class _FakeNatal: when_utc = BIRTH class _FakeEngine: """Silnik-atrapa — build_timeline z solar_return by go użył, tu go pomijamy."""