From 82809665ff9392c99499b2c02b83239ec1143689 Mon Sep 17 00:00:00 2001 From: migatu Date: Wed, 1 Jul 2026 15:42:47 +0200 Subject: [PATCH] =?UTF-8?q?Odsiewanie=20szumu=20+=20rozwijanie=20skr=C3=B3?= =?UTF-8?q?t=C3=B3w=20sygnifikator=C3=B3w?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - abbreviations.py: słownik skrót -> pełna nazwa (z SIGNIFICATORS KEY, built-in) + expand(): [Su in [Tau -> "Sun in Taurus", [Sa in 6th H. -> "...6th house", affl. -> afflicted itd. - significators: każda próbka ma pole "expanded" (postać czytelna); hartowanie filtra szumu (efekty zastępcze x/?/-, wiersze *MARKER, legendy/nagłówki). - prezentacja /interpret: pokazuje rozwiniętą postać, surowy skrót w tooltipie. Zweryfikowano na realnym main_base.xlsx: "[Sa or [Ma in the 5th H." -> "Saturn or Mars in the 5th house". 9 testów przechodzi (w tym test_abbreviations). Co-Authored-By: Claude Opus 4.8 --- services/logic/app/abbreviations.py | 58 +++++++++++++++++++ services/logic/app/significators.py | 11 ++-- services/logic/tests/test_abbreviations.py | 22 +++++++ services/logic/tests/test_significators.py | 1 + services/presentation/app/static/styles.css | 1 + .../presentation/app/templates/interpret.html | 2 +- 6 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 services/logic/app/abbreviations.py create mode 100644 services/logic/tests/test_abbreviations.py diff --git a/services/logic/app/abbreviations.py b/services/logic/app/abbreviations.py new file mode 100644 index 0000000..e08b109 --- /dev/null +++ b/services/logic/app/abbreviations.py @@ -0,0 +1,58 @@ +"""Rozwijanie skrótów sygnifikatorów do postaci czytelnej (na bazie SIGNIFICATORS KEY). + +W bazie zapis jest skrótowy z prefiksem `[` (np. `[Su in [Tau`, `[Sa [conj [Su in 6th H.`). +Ten moduł zamienia go na tekst czytelny: „Sun in Taurus", „Saturn conjunction Sun +in 6th house". Słownik pochodzi z pliku SIGNIFICATORS KEY (mały, stabilny — wpięty +jako built-in; można rozszerzać). +""" +from __future__ import annotations + +import re + +# skrót (bez nawiasu) -> pełna nazwa +ABBREVIATIONS: dict[str, str] = { + # znaki zodiaku + "Ari": "Aries", "Tau": "Taurus", "Gem": "Gemini", "Can": "Cancer", + "Leo": "Leo", "Vir": "Virgo", "Lib": "Libra", "Sco": "Scorpio", + "Sag": "Sagittarius", "Cap": "Capricorn", "Aqu": "Aquarius", "Pis": "Pisces", + # planety klasyczne + światła + "Su": "Sun", "Mo": "Moon", "Me": "Mercury", "Ve": "Venus", + "Ma": "Mars", "Ju": "Jupiter", "Sa": "Saturn", + # planety nowożytne + "Ur": "Uranus", "Ne": "Neptune", "Pl": "Pluto", + # węzły i punkty + "NN": "North Node", "SN": "South Node", "Lilith": "Lilith", "Chiron": "Chiron", + # osie + "Asc": "Ascendant", "Dsc": "Descendant", "MC": "Midheaven", "IC": "Imum Coeli", + # aspekty + "conj": "conjunction", "sex": "sextile", "sq": "square", "tri": "trine", + "opp": "opposition", "semisex": "semisextile", "semisq": "semisquare", + "sesquisq": "sesquisquare", "quincunx": "quincunx", "asp": "aspect", + # domy jako tokeny [h1..[h12 + **{f"h{i}": f"{i}th house" for i in range(1, 13)}, + # ruch + "Rx": "retrograde", "R": "retrograde", +} +# poprawki nieregularnych liczebników domów +ABBREVIATIONS.update({"h1": "1st house", "h2": "2nd house", "h3": "3rd house"}) + +# rozwinięcia słów spoza składni `[` +_WORDS = { + "affl.": "afflicted", + "P. Dec.": "parallel of declination", + "espec.": "especially", +} + +_TOKEN = re.compile(r"\[([A-Za-z]+)") +_HOUSE = re.compile(r"(\d+(?:st|nd|rd|th))\s*H\.", re.IGNORECASE) + + +def expand(text: str) -> str: + """Zamienia skróty na pełne nazwy; nieznane tokeny zostawia bez nawiasu.""" + if not text: + return text + out = _TOKEN.sub(lambda m: ABBREVIATIONS.get(m.group(1), m.group(1)), text) + out = _HOUSE.sub(lambda m: f"{m.group(1)} house", out) + for k, v in _WORDS.items(): + out = out.replace(k, v) + return out diff --git a/services/logic/app/significators.py b/services/logic/app/significators.py index 68a3821..f916ff9 100644 --- a/services/logic/app/significators.py +++ b/services/logic/app/significators.py @@ -13,6 +13,7 @@ from __future__ import annotations from typing import Any, Protocol +from app.abbreviations import expand from app.engine.formats import SIGN_ABBR, SIGNS PLANET_ABBR = { @@ -38,11 +39,13 @@ def _effect(row: dict) -> str: def _is_noise(sig: str, effect: str) -> bool: s = sig.strip().lower() + e = effect.strip().lower() return ( - not effect - or s.startswith("significator") + e in ("", "nan", "x", "x?", "?", "-") # efekt pusty/zastępczy + or s.startswith("significator") # wiersz-legenda/nagłówek or "header" in s - or s in ("x", "x?", "nan") + or s.startswith("*") # *MARKER / *header + or s in ("x", "x?", "nan") # znacznik „pomiń rekord" ) @@ -65,7 +68,7 @@ def _facet_samples(rows: list[dict], token: str, limit: int = 4) -> list[dict]: eff = _effect(r) if _is_noise(sig, eff): continue - out.append({"significator": sig.strip(), "effect": eff}) + out.append({"significator": sig.strip(), "expanded": expand(sig.strip()), "effect": eff}) return out diff --git a/services/logic/tests/test_abbreviations.py b/services/logic/tests/test_abbreviations.py new file mode 100644 index 0000000..a584081 --- /dev/null +++ b/services/logic/tests/test_abbreviations.py @@ -0,0 +1,22 @@ +"""Testy rozwijania skrótów sygnifikatorów.""" +from app.abbreviations import expand + + +def test_planet_in_sign(): + assert expand("[Su in [Tau") == "Sun in Taurus" + + +def test_aspect_and_house(): + assert expand("[Sa [conj [Su in 6th H.") == "Saturn conjunction Sun in 6th house" + + +def test_affliction_word_and_house(): + assert expand("[Ne affl. in the 7th H.") == "Neptune afflicted in the 7th house" + + +def test_unknown_token_kept_without_bracket(): + assert expand("[Xyz rising") == "Xyz rising" + + +def test_empty_passthrough(): + assert expand("") == "" diff --git a/services/logic/tests/test_significators.py b/services/logic/tests/test_significators.py index aca4716..6506261 100644 --- a/services/logic/tests/test_significators.py +++ b/services/logic/tests/test_significators.py @@ -25,6 +25,7 @@ def test_sign_and_house_facets(): facets = {f["type"]: f for f in item["facets"]} assert facets["sign"]["count"] == 1 assert facets["sign"]["samples"][0]["effect"] == "efekt znak" + assert facets["sign"]["samples"][0]["expanded"] == "Sun in Taurus" # rozwinięcie skrótu assert facets["house"]["count"] == 1 assert facets["house"]["token"] == "11th H." assert facets["house"]["samples"][0]["effect"] == "efekt dom" diff --git a/services/presentation/app/static/styles.css b/services/presentation/app/static/styles.css index 346db84..d25842c 100644 --- a/services/presentation/app/static/styles.css +++ b/services/presentation/app/static/styles.css @@ -61,3 +61,4 @@ tr:last-child td { border-bottom: none; } .samples td.nowrap { color: var(--accent); padding-right: 1rem; } .facet { margin: .4rem 0 .6rem 1rem; } .facet-head { color: var(--ink); font-size: .9rem; } +.samples td.sig { color: var(--accent); padding-right: 1rem; cursor: help; } diff --git a/services/presentation/app/templates/interpret.html b/services/presentation/app/templates/interpret.html index ee21c32..a1ca720 100644 --- a/services/presentation/app/templates/interpret.html +++ b/services/presentation/app/templates/interpret.html @@ -56,7 +56,7 @@ {% for s in f.samples %} - + {% endfor %}
{{ s.significator }}{{ s.effect }}
{{ s.expanded }}{{ s.effect }}