62 lines
2.4 KiB
Python
62 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Summarize reviewable PyJHora comparison matrices without overstating coverage."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import csv
|
|
import json
|
|
from collections import Counter, defaultdict
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
|
|
REQUIRED_FULL_PARITY = ("D1", "D9", "D10", "D2", "D4", "Vimshottari", "Shadbala", "Ashtakavarga")
|
|
MATRIX_SECTION_MAP = {"ascendant": "D1", "planet": "D1", "dasha": "Vimshottari", "D9": "D9", "D10": "D10"}
|
|
|
|
|
|
def summarize_matrix(path: str | Path, *, settings: dict[str, Any]) -> dict[str, Any]:
|
|
path = Path(path)
|
|
rows = list(csv.DictReader(path.open(encoding="utf-8")))
|
|
status_counts = Counter(str(row.get("status") or "unknown") for row in rows)
|
|
sections: dict[str, dict[str, int]] = defaultdict(lambda: {"total": 0, "match": 0, "mismatch": 0})
|
|
covered = set()
|
|
for row in rows:
|
|
section = MATRIX_SECTION_MAP.get(str(row.get("section") or ""))
|
|
if not section:
|
|
continue
|
|
covered.add(section)
|
|
sections[section]["total"] += 1
|
|
if row.get("status") == "match":
|
|
sections[section]["match"] += 1
|
|
elif row.get("status") == "mismatch":
|
|
sections[section]["mismatch"] += 1
|
|
missing = [field for field in REQUIRED_FULL_PARITY if field not in covered]
|
|
return {
|
|
"scope": "pyjhora_same_chart_parity_summary",
|
|
"matrix_path": str(path),
|
|
"tested": bool(rows),
|
|
"settings": settings,
|
|
"row_counts": dict(status_counts),
|
|
"coverage": dict(sorted(sections.items())),
|
|
"covered_outputs": sorted(covered),
|
|
"missing_required_outputs": missing,
|
|
"status": "partial_verified" if rows and not status_counts.get("mismatch") else "partial_mismatch",
|
|
"full_parity_verified": not missing and not status_counts.get("mismatch"),
|
|
"boundary": "Only covered outputs are compared. This summary cannot promote full parity while required outputs are absent.",
|
|
}
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("matrix")
|
|
parser.add_argument("--ayanamsa", default="lahiri")
|
|
parser.add_argument("--node-mode", default="mean", choices=["mean", "true"])
|
|
args = parser.parse_args()
|
|
print(json.dumps(summarize_matrix(args.matrix, settings={"ayanamsa": args.ayanamsa, "node_mode": args.node_mode}), ensure_ascii=False, indent=2))
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|