10970c579f
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m19s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m29s
Testy / Testy warstwy bazodanowej (ochrona baz) (pull_request) Successful in 9m26s
Testy / Testy astrodemo (pull_request) Failing after 0s
Testy / Testy astroklient (pull_request) Successful in 9m29s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 7s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 5s
build / build (push) Successful in 19s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m25s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m29s
Testy / Testy warstwy bazodanowej (ochrona baz) (push) Successful in 9m26s
Testy / Testy astrodemo (push) Failing after 0s
Testy / Testy astroklient (push) Successful in 9m29s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 7s
Testy / Kontrola składni wszystkich warstw (push) Successful in 5s
Trzeci produkt drabiny: astrodemo (dwie funkcje) → astroklient → astrololo. Po trzech poprzednich krokach jest cienki, bo jest ZŁOŻENIEM, a nie kopią: własne main.py z ośmioma importami, a rdzeń — ekrany, szablony, zasoby — bierze z warstwy prezentacji przy budowaniu obrazu. Jedno źródło, dwa produkty; inaczej te same 2500 linii szablonów żyłyby w dwóch egzemplarzach i rozjechały się w ciągu tygodni, po cichu. CO MA: Horoskop, Interpretacje, Kalendarz, Synastria, Sygnifikatory, wgrywanie plików. Wyszukiwarka miejsca i strefa czasowa zgodnie z ustaleniem. CZEGO NIE MA I DLACZEGO NIE DA SIĘ WŁĄCZYĆ: plików usuniętych wg usun.txt nie ma w obrazie. Nie istnieje uprawnienie, którym dałoby się je odsłonić, bo katalog funkcji składa się ze ZGŁOSZEŃ ekranów obecnych w obrazie. To dlatego „każde konto dostaje wszystko, co ta usługa umie" jest tu bezpieczne i nie wymaga wypisywania listy: zbiór liczy się z katalogu, więc opisuje ten produkt. KONTA jak w astrodemo: z konfiguracji środowiska (ASTROKLIENT_USERS), jeden poziom dostępu, bez pliku kont i bez ekranu ich zakładania. Konta rozdziela się po to, żeby każde miało własną pulę plików. PULE PER KONTO — tu była realna dziura. Warstwa logiczna przenosiła pulę tylko przy raporcie i operacjach na plikach, więc Kalendarz i Sygnifikatory czytałyby CAŁY udział: jedno konto widziałoby pliki drugiego, mimo obietnicy izolacji. Domknięte: TimelineRequest i QueryRequest niosą teraz pulę, a QueryService buduje klienta danych na żądanie. Pula jedzie w każdym żądaniu w dół i bierze się z kontekstu ustawianego przy wejściu, nigdy z formularza. Test podstawia `tenant=ktos-inny` w POST i sprawdza, że w dół poszedł login zalogowanego. WARSTWA WSPÓLNA ROZDZIELONA OD POJĘCIA ADMINISTRATORA. base.html miał wpisany na sztywno warunek `can(request, 'admin')` i odsyłacz do ekranu kont — czyli w produkcie bez tego ekranu zostawał martwy link i nazwa czegoś, czego nie ma. Rejestr niesie teraz wymagane uprawnienie, a szablon dostaje gotową listę. Podstawa przestała też importować moduły służące jednemu ekranowi (konta, stany plików), bo produkt bez tego ekranu wlókł ich zależności. ZAPORA SŁOWNIKOWA NAD REALNYM DRZEWEM. Test buduje złożenie tak samo jak Dockerfile i szuka słów o funkcjach, których nie ma — w odpowiedziach ORAZ w plikach. Pierwsza wersja znalazła dziesięć trafień, w tym trzy moje własne docstringi WYLICZAJĄCE nieobecne funkcje: zdanie „nie ma tu generowania tekstu" mówi wprost, że coś takiego istnieje, więc jest takim samym śladem jak przycisk. Po poprawkach: zero. Test ma kontrolę negatywną — podrzucony plik ma go wywrócić. usun.txt jest DANYMI, nie tekstem w Dockerfile: czyta go też test pilnujący, żeby zgadzał się ze złożeniem w main.py. Rozjazd znaczyłby albo martwy kod w obrazie, albo błąd dopiero przy uruchomieniu. CI: astroklient buduje się z KORZENIA repozytorium (jego Dockerfile sięga po rdzeń), a zmiana w warstwie prezentacji też go przebudowuje — bez tego jego obraz zostawałby ze starymi ekranami, a różnicy nie byłoby widać do zgłoszenia użytkownika. Testy: astroklient 12, presentation 368, astrodemo 28, logic 342, data 42, render 41. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
244 lines
10 KiB
HTML
244 lines
10 KiB
HTML
{# Tabele wyniku horoskopu — używane przez raportu zbiorczego (/compile), żeby
|
|
podsumowanie pokazywało dokładnie to, co policzono (regresja 2026-07-28:
|
|
podsumowanie miało braki). Skopiowane 1:1 z sekcji tabel na „Horoskop" (/).
|
|
TODO: przełączyć też chart.html na ten include, żeby oba widoki nie mogły się
|
|
rozjechać — na razie pilnować ręcznie, że są zgodne. Rysunki (koło/aspektarian/
|
|
deklinacja/antyscja) renderuje rodzic; tu są same tabele. Każda sekcja pokazuje
|
|
się tylko, gdy jej dane są w wyniku (opcja policzona → sekcja jest). #}
|
|
|
|
{# Fallback systemu domów: system nie istniał dla tego miejsca i policzyliśmy
|
|
inny. Musi być WIDOCZNE, bo z samego wykresu tego nie da się poznać. #}
|
|
{% if result.house_warnings %}
|
|
{% for w in result.house_warnings %}
|
|
<p class="notice-warn">{{ w }}</p>
|
|
{% endfor %}
|
|
{% endif %}
|
|
|
|
{% if result.angles %}
|
|
<table class="angles">
|
|
<thead><tr><th>Oś</th><th>Znak</th><th>W znaku</th></tr></thead>
|
|
<tbody>
|
|
{% for key in ["Asc", "MC", "Dsc", "IC"] %}
|
|
{% set a = result.angles[key] %}
|
|
<tr><td>{{ a.name }}</td><td>{{ a.sign }}</td><td class="mono">{{ a.in_sign }}</td></tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% endif %}
|
|
|
|
{# Porównanie systemów domów (PRE-05) — te same osie, inny podział na domy #}
|
|
{% if result.house_systems and result.house_systems | length > 1 %}
|
|
<div class="meta" title="Osie (Asc/MC) są wspólne — różni się podział na domy. Kosmogram rysuje pierwszy z listy.">Porównanie systemów domów ({{ result.house_systems | length }})</div>
|
|
{# Przy komplecie systemów tabela jest szersza niż okno — przewija się SAMA,
|
|
zamiast rozpychać stronę (numer domu zostaje przyklejony do lewej). #}
|
|
<div class="table-scroll">
|
|
<table class="angles">
|
|
<thead><tr><th>Dom</th>{% for hs in result.house_systems %}<th>{{ house_label(hs.system) }}</th>{% endfor %}</tr></thead>
|
|
<tbody>
|
|
{% for i in range(12) %}
|
|
<tr><td>{{ i + 1 }}</td>
|
|
{% for hs in result.house_systems %}
|
|
<td class="mono"><span class="glyph">{{ hs.cusps[i].sign_glyph }}</span> {{ hs.cusps[i].in_sign }}</td>
|
|
{% endfor %}
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th title="Symbol astrologiczny (LOG-22)">Sym.</th>
|
|
<th>Obiekt</th><th>Znak</th><th>W znaku</th><th>Dom</th><th>Kier.</th><th>Prędkość °/d</th>
|
|
<th title="Deklinacja — odległość od równika niebieskiego. OOB = poza zakresem Słońca">Dekl.</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for p in result.positions %}
|
|
<tr>
|
|
<td class="glyph">{{ p.glyph or '' }}{% if p.sign_glyph %} {{ p.sign_glyph }}{% endif %}</td>
|
|
<td>{{ p.name }}</td>
|
|
<td>{{ p.sign }}</td>
|
|
<td class="mono">{{ p.in_sign }}</td>
|
|
<td>{{ p.house if p.house is defined else '—' }}</td>
|
|
<td class="{{ 'retro' if p.direction == 'Rx' else '' }}">{{ p.direction }}</td>
|
|
<td class="mono">{{ '%+.4f' | format(p.speed) }}</td>
|
|
<td class="mono">{% if p.declination is defined %}{{ '%+.2f°' | format(p.declination) }}{% if p.out_of_bounds %} <span class="badge" title="Out of bounds — deklinacja poza zakresem Słońca">OOB</span>{% endif %}{% else %}—{% endif %}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
|
|
{% if result.lots %}
|
|
<div class="meta">Lots hermetyczne ({{ result.lots | length }}) · sekta: <strong>{{ result.sect }}</strong></div>
|
|
<table class="angles">
|
|
<thead><tr><th>Lot</th><th>Znak</th><th>W znaku</th><th>Dom</th><th>Formuła</th></tr></thead>
|
|
<tbody>
|
|
{% for l in result.lots %}
|
|
<tr><td>{{ l.name }}</td><td>{{ l.sign }}</td><td class="mono">{{ l.in_sign }}</td><td>{{ l.house }}</td><td class="muted small">{{ l.formula }}</td></tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% endif %}
|
|
|
|
{% set with_stations = result.positions | selectattr('stations', 'defined') | list %}
|
|
{% if with_stations %}
|
|
<div class="meta">Stacje planet (poprzednia / następna; <span class="badge">blisko</span> = mniej niż 7 dni)</div>
|
|
<table class="angles">
|
|
<thead><tr><th>Planeta</th><th>Poprzednia</th><th>Następna</th></tr></thead>
|
|
<tbody>
|
|
{% for p in with_stations %}
|
|
<tr>
|
|
<td>{{ p.name }}{% if p.stations.station_soon %} <span class="badge">blisko</span>{% endif %}</td>
|
|
<td class="mono">{% if p.stations.prev %}{{ p.stations.prev.type }} · {{ p.stations.prev.date }} · {{ p.stations.prev.degree }} ({{ p.stations.prev.days }} d){% else %}—{% endif %}</td>
|
|
<td class="mono">{% if p.stations.next %}{{ p.stations.next.type }} · {{ p.stations.next.date }} · {{ p.stations.next.degree }} (+{{ p.stations.next.days }} d){% else %}—{% endif %}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% endif %}
|
|
|
|
{% if result.aspects %}
|
|
<div class="meta">Aspekty główne ({{ result.aspects | length }})</div>
|
|
<table class="angles">
|
|
<thead><tr><th>Obiekt 1</th><th>Aspekt</th><th>Obiekt 2</th><th>Orb</th><th title="A = aplikacyjny (dokładność nastąpi), S = separacyjny (już minęła)">A/S</th></tr></thead>
|
|
<tbody>
|
|
{% for a in result.aspects %}
|
|
<tr><td>{{ a.obj1 }}</td><td>{% if a.glyph %}<span class="glyph">{{ a.glyph }}</span> {% endif %}{{ a.aspect }}</td><td>{{ a.obj2 }}</td><td class="mono">{{ '%.2f'|format(a.orb) }}°</td><td>{{ a['as'] if a['as'] is defined else '—' }}</td></tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% endif %}
|
|
|
|
{% if result.parallels %}
|
|
<div class="meta" title="Ciała na tej samej (paralela) lub przeciwnej (kontrparalela) deklinacji — działają jak koniunkcja / opozycja poza ekliptyką">Paralele deklinacji ({{ result.parallels | length }})</div>
|
|
<table class="angles">
|
|
<thead><tr><th>Obiekt 1</th><th>Rodzaj</th><th>Obiekt 2</th><th>Orb</th><th>Dekl.</th></tr></thead>
|
|
<tbody>
|
|
{% for r in result.parallels %}
|
|
<tr>
|
|
<td>{{ r.obj1 }}</td>
|
|
<td>{{ 'paralela' if r.type == 'parallel' else 'kontrparalela' }}</td>
|
|
<td>{{ r.obj2 }}</td>
|
|
<td class="mono">{{ '%.2f'|format(r.orb) }}°</td>
|
|
<td class="mono">{{ '%+.2f'|format(r.dec1) }} / {{ '%+.2f'|format(r.dec2) }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% endif %}
|
|
|
|
{% if result.antiscia %}
|
|
<div class="meta" title="Odbicie względem osi przesileń (antyscja) lub równonocy (kontrantyscja) — punkty „dzielące” tę samą długość dnia">Antyscja ({{ result.antiscia | length }})</div>
|
|
<table class="angles">
|
|
<thead><tr><th>Obiekt 1</th><th>Rodzaj</th><th>Obiekt 2</th><th>Orb</th></tr></thead>
|
|
<tbody>
|
|
{% for r in result.antiscia %}
|
|
<tr>
|
|
<td>{{ r.obj1 }}</td>
|
|
<td>{{ 'antyscja' if r.type == 'antiscion' else 'kontrantyscja' }}</td>
|
|
<td>{{ r.obj2 }}</td>
|
|
<td class="mono">{{ '%.2f'|format(r.orb) }}°</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% endif %}
|
|
|
|
{% if result.tables %}
|
|
{% set tb = result.tables %}
|
|
<div class="meta">Tabele dodatkowe (LOG-23)</div>
|
|
|
|
{% set bal = tb.tally.with_modern_10_plus_asc %}
|
|
<table class="angles">
|
|
<thead><tr><th>Bilans (10 planet + Asc)</th><th colspan="4">Rozkład</th></tr></thead>
|
|
<tbody>
|
|
<tr><td>Żywioły</td>
|
|
{% for e, n in bal.elements.items() %}
|
|
<td>{{ tb.tally.labels.elements[e] }}: <strong>{{ n }}</strong></td>
|
|
{% endfor %}
|
|
</tr>
|
|
<tr><td>Jakości</td>
|
|
{% for q, n in bal.qualities.items() %}
|
|
<td>{{ tb.tally.labels.qualities[q] }}: <strong>{{ n }}</strong></td>
|
|
{% endfor %}
|
|
<td></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
{% if tb.tally.missing_elements or tb.tally.missing_qualities %}
|
|
<p class="muted small">Brak:
|
|
{% for e in tb.tally.missing_elements %}<strong>{{ tb.tally.labels.elements[e] }}</strong>{{ ", " if not loop.last }}{% endfor %}
|
|
{% for q in tb.tally.missing_qualities %}<strong>{{ tb.tally.labels.qualities[q] }}</strong>{{ ", " if not loop.last }}{% endfor %}
|
|
</p>
|
|
{% endif %}
|
|
|
|
{% if tb.moon_phase %}
|
|
<p class="muted small">
|
|
<strong>Faza Księżyca:</strong> {{ tb.moon_phase.phase_pl }} ·
|
|
elongacja {{ '%.2f'|format(tb.moon_phase.angle) }}° ·
|
|
oświetlenie {{ '%.1f'|format(tb.moon_phase.illumination * 100) }}% ·
|
|
{{ 'przybywa' if tb.moon_phase.waxing else 'ubywa' }}
|
|
</p>
|
|
{% endif %}
|
|
|
|
{% if tb.planetary_hours %}
|
|
{% set ph = tb.planetary_hours %}
|
|
<p class="muted small">
|
|
<strong>Godziny planetarne:</strong> władca dnia {{ ph.day_ruler }} ·
|
|
{{ ph.hour_number }}. godzina ({{ ph.period }}), władca {{ ph.hour_ruler }} ·
|
|
godzina trwa {{ ph.hour_length_minutes }} min
|
|
</p>
|
|
{% endif %}
|
|
|
|
{% if tb.prenatal_syzygy %}
|
|
{% set s = tb.prenatal_syzygy %}
|
|
<p class="muted small">
|
|
<strong>Syzygia prenatalna:</strong> {{ s.type_pl }} {{ s.when_utc }}
|
|
({{ s.days_before_birth }} dni przed) w {{ s.in_sign }}
|
|
</p>
|
|
{% endif %}
|
|
|
|
{% if tb.critical_degrees %}
|
|
<div class="meta">Stopnie krytyczne</div>
|
|
<table class="angles">
|
|
<thead><tr><th>Obiekt</th><th>Pozycja</th><th>Uwaga</th></tr></thead>
|
|
<tbody>
|
|
{% for c in tb.critical_degrees %}
|
|
<tr><td>{{ c.name }}</td><td class="mono">{{ c.in_sign }}</td>
|
|
<td class="muted small">{{ c.flags | join('; ') }}</td></tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% endif %}
|
|
|
|
<details class="loc">
|
|
<summary>Podziały: dwunastniki (D12) i nawamsa (D9)</summary>
|
|
<table>
|
|
<thead><tr><th>Obiekt</th><th>D12</th><th>D9</th></tr></thead>
|
|
<tbody>
|
|
{% for d in tb.divisional %}
|
|
<tr><td>{{ d.name }}</td><td class="mono">{{ d.d12_in_sign }}</td>
|
|
<td class="mono">{{ d.d9_in_sign }}</td></tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</details>
|
|
{% endif %}
|
|
|
|
{% if result.cusps %}
|
|
<details class="loc">
|
|
<summary>Cusps domów ({{ house_label(result.house_system) }})</summary>
|
|
<table>
|
|
<thead><tr><th>Dom</th><th>Znak</th><th>Cusp</th></tr></thead>
|
|
<tbody>
|
|
{% for c in result.cusps %}
|
|
<tr><td>{{ c.house }}</td><td>{{ c.sign }}</td><td class="mono">{{ c.in_sign }}</td></tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</details>
|
|
{% endif %}
|