mirror of
https://github.com/migatu/astrololo.git
synced 2026-07-14 21:38:37 +00:00
Spięcie osi czasu z bazą interpretacji i widokiem (LOG-14, 1B->2B)
Realizuje przepływ 1B->2B z notes2: predykcyjne sygnifikatory (z datami)
dopasowane do interpretacji z bazy.
Logika:
- timeline.py: zdarzenia niosą strukturę (directed/aspect/target dla dyrekcji,
lord/sign dla profekcji) do budowy tokenów.
- significators.interpret_events + _event_tokens: z każdego zdarzenia buduje
tokeny bazy (dyrekcja: [planeta][aspekt][cel]; profekcja: [władca][znak]) i
dopina interpretacje reużywając _facet_samples (AND tokenów, dedup, rozwinięcie).
- /chart/timeline: flaga interpret=true.
Prezentacja:
- nowa strona /timeline "Kalendarz": formularz (urodzenie + zakres dat) -> oś
czasu z technikami, datami i interpretacjami; nawigacja + wspólne now.js.
Walidacja E2E na realnym main_base.xlsx (2025-2026):
- dyr. Saturn kwadratura MC -> 50 interpret. ("...5th house" -> "abortion/miscarriage")
- Władca Roku Saturn (wiek 42) -> 63; strona renderuje badge dat/technik.
71 testów przechodzi (nowy test_timeline_interpret).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -56,3 +56,17 @@ class LogicClient:
|
||||
r = client.post(f"{self.base_url}/chart/report", json=payload)
|
||||
r.raise_for_status()
|
||||
return r.json()
|
||||
|
||||
def timeline(
|
||||
self, when_utc_iso: str, lat: float, lon: float,
|
||||
from_date: str, to_date: str, interpret: bool = True,
|
||||
) -> dict[str, Any]:
|
||||
"""Oś czasu z technik (+interpretacje z bazy) — woła logic /chart/timeline."""
|
||||
payload = {
|
||||
"when_utc": when_utc_iso, "lat": lat, "lon": lon,
|
||||
"from_date": from_date, "to_date": to_date, "interpret": interpret,
|
||||
}
|
||||
with httpx.Client(timeout=max(settings.http_timeout, 60.0)) as client:
|
||||
r = client.post(f"{self.base_url}/chart/timeline", json=payload)
|
||||
r.raise_for_status()
|
||||
return r.json()
|
||||
|
||||
@@ -132,6 +132,40 @@ def interpret_run(
|
||||
return templates.TemplateResponse(request, "interpret.html", ctx)
|
||||
|
||||
|
||||
# ---------------- Kalendarz (oś czasu z technik + interpretacje) ----------------
|
||||
@app.get("/timeline", response_class=HTMLResponse)
|
||||
def timeline_form(request: Request):
|
||||
return templates.TemplateResponse(request, "timeline.html", {"result": None, "form": {}})
|
||||
|
||||
|
||||
@app.post("/timeline", response_class=HTMLResponse)
|
||||
def timeline_run(
|
||||
request: Request,
|
||||
date: str = Form(...),
|
||||
time: str = Form(...),
|
||||
tz_offset: float = Form(0.0),
|
||||
lat: float = Form(0.0),
|
||||
lon: float = Form(0.0),
|
||||
from_date: str = Form(...),
|
||||
to_date: str = Form(...),
|
||||
):
|
||||
form = {"date": date, "time": time, "tz_offset": tz_offset, "lat": lat, "lon": lon,
|
||||
"from_date": from_date, "to_date": to_date}
|
||||
ctx: dict = {"form": form, "result": None, "error": None, "moment": None}
|
||||
try:
|
||||
iso_utc, label = _build_utc(date, time, tz_offset)
|
||||
ctx["moment"] = label
|
||||
ctx["result"] = logic.timeline(
|
||||
when_utc_iso=iso_utc, lat=lat, lon=lon,
|
||||
from_date=from_date, to_date=to_date, interpret=True,
|
||||
)
|
||||
except httpx.HTTPError as e:
|
||||
ctx["error"] = _logic_error(e)
|
||||
except ValueError as e:
|
||||
ctx["error"] = f"Niepoprawne dane wejściowe: {e}"
|
||||
return templates.TemplateResponse(request, "timeline.html", ctx)
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
def health() -> dict:
|
||||
return {"status": "ok", "layer": "presentation"}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<nav>
|
||||
<a href="/" class="{% block nav_chart %}{% endblock %}">Horoskop</a>
|
||||
<a href="/interpret" class="{% block nav_interp %}{% endblock %}">Interpretacje</a>
|
||||
<a href="/timeline" class="{% block nav_timeline %}{% endblock %}">Kalendarz</a>
|
||||
<a href="/significators" class="{% block nav_sig %}{% endblock %}">Sygnifikatory</a>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Kalendarz{% endblock %}
|
||||
{% block nav_timeline %}active{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<p class="sub">Zbiorcza oś czasu technik predykcyjnych (profekcje, solariusze, dyrekcje solar-arc) z interpretacjami z bazy dla dat.</p>
|
||||
|
||||
<form method="post" action="/timeline">
|
||||
<div class="grid">
|
||||
<label>Data urodzenia
|
||||
<input type="date" name="date" value="{{ form.date or '' }}" required>
|
||||
</label>
|
||||
<label>Godzina (lokalna)
|
||||
<input type="time" name="time" value="{{ form.time or '' }}" required>
|
||||
</label>
|
||||
<label>Strefa (offset h)
|
||||
<input type="number" name="tz_offset" step="0.25" value="{{ form.tz_offset if form.tz_offset is not none else 0 }}">
|
||||
</label>
|
||||
<label>Szerokość (lat)
|
||||
<input type="number" name="lat" step="0.0001" value="{{ form.lat if form.lat is not none else 0 }}">
|
||||
</label>
|
||||
<label>Długość (lon)
|
||||
<input type="number" name="lon" step="0.0001" value="{{ form.lon if form.lon is not none else 0 }}">
|
||||
</label>
|
||||
</div>
|
||||
<div class="grid">
|
||||
<label>Zakres od
|
||||
<input type="date" name="from_date" value="{{ form.from_date or '' }}" required>
|
||||
</label>
|
||||
<label>Zakres do
|
||||
<input type="date" name="to_date" value="{{ form.to_date or '' }}" required>
|
||||
</label>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button type="button" id="nowBtn" class="ghost">Tu i teraz</button>
|
||||
<button type="submit">Pokaż kalendarz</button>
|
||||
<span id="geoNote" class="muted small"></span>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% if error %}<div class="error">{{ error }}</div>{% endif %}
|
||||
|
||||
{% if result %}
|
||||
{% if result.data_error %}<div class="error">{{ result.data_error }}</div>{% endif %}
|
||||
<div class="meta">
|
||||
Silnik: <strong>{{ result.engine }}</strong> ·
|
||||
zdarzeń: {{ result.count }} · zakres {{ result.from }} → {{ result.to }}
|
||||
</div>
|
||||
|
||||
{% for e in result.events %}
|
||||
<div class="sig-item">
|
||||
<div class="sig-head">
|
||||
<span class="badge">{{ e.exact }}</span>
|
||||
<span class="badge">{{ e.technique }}</span>
|
||||
<strong>{{ e.significator }}</strong>
|
||||
<span class="muted small">(okno {{ e.start }} → {{ e.end }})</span>
|
||||
</div>
|
||||
{% if e.interpretations %}
|
||||
<table class="samples">
|
||||
<tbody>
|
||||
{% for s in e.interpretations %}
|
||||
<tr><td class="sig nowrap" title="{{ s.significator }}">{{ s.expanded }}</td><td>{{ s.effect }}</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% if e.interpretations_count > e.interpretations | length %}
|
||||
<div class="muted small">…i {{ e.interpretations_count - (e.interpretations | length) }} więcej</div>
|
||||
{% endif %}
|
||||
{% elif e.technique != 'solar_return' %}
|
||||
<div class="muted small">brak dopasowań w bazie</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<script src="/static/now.js"></script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user