"""Uruchomienie porównania z wyrocznią. Punkt wejścia dla CI i dla Joba w klastrze. Dwa tryby: --mode build (domyślny) zestaw BRZEGOWY + tyle samo przypadków z wnętrza. Szybki, deterministyczny, BLOKUJE build przy błędzie. --mode sweep wielki losowy przemiał, o rząd wielkości większy. Do Joba w klastrze; ziarno raportowane, więc każdy błąd da się odtworzyć komendą z raportu. Kod wyjścia: 0 = zgodność w granicach tolerancji, 1 = przekroczenia albo niezgodność dziedziny. Dzięki temu CI może na tym polegać bez parsowania tekstu. """ from __future__ import annotations import argparse import os import sys # Ścieżka do warstwy logicznej: w CI montujemy ją do kontenera swissepha. sys.path.insert(0, os.environ.get("LOGIC_PATH", "/logic")) sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from domain import boundary_cases, interior_cases, random_cases # noqa: E402 from harness import ( # noqa: E402 SWE_CODE, compare_asc_mc, compare_system, format_report, ) # Systemy do sprawdzenia. Rośnie wraz z implementacją kolejnych (Etap 1 i 2) — # dopisanie nazwy tutaj wystarcza, żeby weszła do każdego builda. SYSTEMS = ["whole_sign", "whole_sign_aries", "equal", "equal_mc", "porphyry", "vehlow", "morinus", "regiomontanus", "campanus", "alcabitus", "topocentric", "placidus", "koch"] def main() -> int: p = argparse.ArgumentParser(description="Zgodność domów z wyrocznią (Swiss Ephemeris)") p.add_argument("--mode", choices=("build", "sweep"), default="build") p.add_argument("--seed", type=int, default=0, help="ziarno losowania (do odtworzenia błędu)") p.add_argument("--count", type=int, default=20000, help="liczba przypadków w trybie sweep") p.add_argument("--systems", default=",".join(SYSTEMS)) args = p.parse_args() systems = [s.strip() for s in args.systems.split(",") if s.strip()] unknown = [s for s in systems if s not in SWE_CODE] if unknown: print(f"Nieznane systemy: {unknown}", file=sys.stderr) return 2 if args.mode == "build": boundary = boundary_cases() # Tyle samo z wnętrza, ile brzegowych — brzegi łapią osobliwości, # wnętrze pilnuje, że nie zepsuliśmy zwykłych przypadków. cases = boundary + interior_cases(len(boundary), seed=args.seed) seed_note = args.seed else: cases = random_cases(args.count, seed=args.seed) seed_note = args.seed results = [compare_asc_mc(cases)] results += [compare_system(s, cases) for s in systems] print(f"\nprzypadków wejściowych: {len(cases)} (tryb: {args.mode})") print(format_report(results, seed=seed_note)) failed = [r for r in results if not r.passed] if failed: print("\nBŁĄD: " + ", ".join(r.system for r in failed)) print(f"Odtworzenie: python run.py --mode {args.mode} --seed {args.seed}" + (f" --count {args.count}" if args.mode == "sweep" else "")) return 1 print("\nWszystkie systemy zgodne z wyrocznią w granicach tolerancji.") return 0 if __name__ == "__main__": raise SystemExit(main())