Files
astrololo/services/logic/app/scoring.py
gitea f6323cac10 Ranking siły (LOG-21) + grupowanie identycznych opisów + geolokalizacja
Punktacja siły (LOG-21):
- scoring.py: siła fasety z sygnałów obliczalnych (typ fasety, rodzaj aspektu,
  ciasnota orbu). Konfigurowalne wagi. Hook na przyszłość: kolumny countas*/level*
  z SIGNIFICATORS KEY (obecnie puste).
- aspekty niosą orb+allowed; fasety dostają "score"; ranking faset malejąco.

Grupowanie:
- opcja group: zwija próbki po opisie (ten sam efekt = jedna grupa z listą
  sygnifikatorów i licznikiem). Checkbox "grupuj identyczne opisy" w /interpret.

Geolokalizacja (bajer):
- "Tu i teraz" (widok Horoskop i Interpretacje) uzupełnia lat/lon z przeglądarki
  (navigator.geolocation; wymaga zgody, https/localhost).

Zweryfikowano na realnym main_base.xlsx: ranking sensowny (ciasna opozycja z
Saturn 9.59 > szeroka koniunkcja z Moon 6.25 > znak/dom 5.0); grupowanie zwija
powtórzone opisy. 41 testów przechodzi.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 01:16:47 +02:00

33 lines
1.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Punktacja siły trafień — do rankingowania faset (zalążek LOG-21).
v1 liczy siłę z sygnałów OBLICZALNYCH:
- typ fasety (aspekt zwykle mocniejszy od znaku/domu),
- rodzaj aspektu (koniunkcja/opozycja mocniejsze od sekstyla),
- ciasnota orbu (im bliżej dokładności, tym mocniej).
Wszystko konfigurowalne. HOOK NA PRZYSZŁOŚĆ: gdy w SIGNIFICATORS KEY zostaną
wypełnione kolumny `countas*`/`level*`, można je tu domieszać per sygnifikator.
"""
from __future__ import annotations
# bazowe wagi faset (łatwe do strojenia)
FACET_BASE = {"sign": 5.0, "house": 5.0, "aspect": 6.0}
# względna siła aspektów głównych
ASPECT_WEIGHT = {
"conjunction": 1.0, "opposition": 0.95, "square": 0.85,
"trine": 0.85, "sextile": 0.65,
}
def score_facet(facet: dict) -> float:
"""Siła fasety w skali ~012. Deterministyczna, konfigurowalna."""
base = FACET_BASE.get(facet.get("type"), 1.0)
if facet.get("type") == "aspect":
weight = ASPECT_WEIGHT.get(facet.get("aspect"), 0.7)
orb = facet.get("orb")
allowed = facet.get("allowed") or 10.0
tight = max(0.0, 1.0 - orb / allowed) if orb is not None and allowed else 0.0
return round(base * weight * (1.0 + tight), 2)
return round(base, 2)