"""sync4 T5: Sunaphaa / Anaphaa / Duradhara (Moon) and Vesi / Vosi / Ubhayachara (Sun) count only Mars, Mercury, Jupiter, Venus, Saturn; Rahu / Ketu alone next to the Moon or Sun do not form them, and Kemadruma ignores the nodes too. Rule logic for the six BVR rules is upstream yinduzhanxing 2dd6062a.""" from __future__ import annotations from pathlib import Path from scripts.yoga_engine import RETIRED_RULE_IDS, YogaEngine RULES = Path(__file__).resolve().parents[1] / "references" / "yoga_rules.json" SIGNS = ["Aries", "Taurus", "Gemini", "Cancer", "Leo", "Virgo", "Libra", "Scorpio", "Sagittarius", "Capricorn", "Aquarius", "Pisces"] def _chart(**signs: str) -> dict: return {name: {"sign": sign, "house": SIGNS.index(sign) + 1, "degree": 15.0, "longitude": SIGNS.index(sign) * 30 + 15.0} for name, sign in signs.items()} def _names(planets: dict) -> set[str]: return {row["name"] for row in YogaEngine(str(RULES)).detect(planets, "Aries")} BASE = dict(Sun="Aquarius", Moon="Libra", Mars="Aquarius", Mercury="Aquarius", Jupiter="Cancer", Venus="Pisces", Saturn="Capricorn", Rahu="Pisces") def test_ketu_alone_behind_the_moon_is_not_anaphaa() -> None: names = _names(_chart(**BASE, Ketu="Virgo")) assert not {"Anaphaa Yoga", "Sunaphaa Yoga", "Duradhara Yoga"} & names def test_saturn_behind_the_moon_is_anaphaa() -> None: signs = {**BASE, "Saturn": "Virgo", "Ketu": "Virgo"} assert "Anaphaa Yoga" in _names(_chart(**signs)) def test_ketu_alone_after_the_sun_is_not_vesi() -> None: signs = {**BASE, "Sun": "Leo", "Ketu": "Virgo", "Mars": "Capricorn", "Mercury": "Capricorn"} assert "Vesi Yoga" not in _names(_chart(**signs)) def test_duplicate_lunar_solar_rules_are_retired() -> None: assert {"sunapha_yoga", "durudhura_yoga", "voshi_yoga", "veshi_yoga", "ubhayachari_yoga"} <= RETIRED_RULE_IDS ids = {rule["id"] for rule in YogaEngine(str(RULES)).rules} assert not ids & RETIRED_RULE_IDS