gitea 8cc329ab17
build / build (push) Successful in 1m4s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 12m9s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Failing after 1m6s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 38s
Testy / Kontrola składni wszystkich warstw (push) Successful in 20s
feat(prezentacja): zapamiętane predykcje okresowe (PRE-22) + wymaganie o cache-bustingu
Piata wskazowka partnerow: Kalendarz ma pozwalac liczyc predykcje dla KILKU
okresow i je zachowywac, zeby wszystkie trafily potem do raportu („Skompiluj",
PRE-23/24).

Nowy predictions.js — magazyn w localStorage, tak jak wspolne dane formularza
(PRE-21): serwer zostaje bezstanowy, zadne dane urodzeniowe ani tresci z baz nie
laduja po stronie uslugi. Zakladka „Skompiluj" odczyta to samo miejsce przez
window.astrololoPredictions (jedno zrodlo prawdy).

Decyzje projektowe:

- KLUCZEM TOZSAMOSCI JEST OKRES. Ponowne policzenie tego samego zakresu podmienia
  wpis zamiast dokladac duplikat — inaczej lista puchlaby przy kazdej probie
  z innym modelem albo budzetem. Dzieki temu zapis jest idempotentny, wiec dziala
  tez wariant bez strumienia (zapis przy wczytaniu strony z gotowym wynikiem)
  i odswiezenie niczego nie mnozy.
- progress.js OGLASZA gotowy horoskop zdarzeniem `astrololo:horoscope` z profilem,
  zamiast sam zapisywac. To okno postepu, a nie magazyn — zapisywanie zostaje
  odpowiedzialnoscia predictions.js. Filtr po profilu pilnuje, zeby interpretacja
  natalna nie trafila na liste predykcji okresowych.
- Przepelniony magazyn (horoskopy bywaja dlugie) jest ZGLASZANY uzytkownikowi,
  a nie polykany — inaczej wynik znikalby po cichu.

UI: lista zapamietanych predykcji na Kalendarzu — okres, data zapisu, objetosc
i przycisk usuwania. Skrypt podpiety w timeline.html (nie w base.html), zeby nie
kolidowac z rownolegle otwartym #29.

PRE-26 — dopisane wymaganie o wersjonowaniu plikow statycznych. Przy PRE-25
przegladarka podala STARY styles.css i powiekszanie kosmogramu „nie dzialalo",
mimo ze klasa byla nakladana. Objaw jest zdradliwy: szablony sa nowe, wiec strona
wyglada na zaktualizowana, a funkcja po prostu milczy. Po wdrozeniu moze to
spotkac uzytkownikow.

Weryfikacja na zywej aplikacji: dwa okresy zapisane; powtorzenie tego samego
zakresu podmienilo wpis (dalej 2, tekst zaktualizowany); lista posortowana po
dacie; predykcje przetrwaly przejscie na inna zakladke i powrot; interpretacja
natalna NIE wpadla na liste; usuwanie zmniejszylo licznik 2 -> 1 i przerysowalo
liste. Testy: 14 nowych. Calosc: prezentacja 101 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 17:57:24 +02:00
2026-07-20 19:52:21 +02:00
ttt
2026-07-20 14:50:11 +02:00

astrololo

Aplikacja w modelu trójwarstwowym, w pełni modułowa: trzy niezależne usługi, każda komunikuje się wyłącznie z sąsiadem (nigdy „przez głowę”).

┌──────────────────────┐   formularz (w dół)   ┌──────────────────────┐   zapytanie (w dół)   ┌──────────────────────┐
│  PREZENTACJA (:8000) │ ───────────────────▶ │   LOGICZNA (:8001)   │ ───────────────────▶ │  BAZODANOWA (:8002)  │
│  strona WWW + form   │ ◀─────────────────── │  reguły biznesowe    │ ◀─────────────────── │  wyszukiwanie danych │
└──────────────────────┘   wyniki (w górę)     └──────────────────────┘   dane (w górę)       └──────────────────────┘
        HTML/UI                                    pośrednik + logika                         Excel(+cache) ▸ SQL

Każda warstwa to osobny katalog, osobny requirements.txt, osobny Dockerfile i osobne README. Komunikacja przez HTTP/JSON. Warstwa zna tylko adres warstwy bezpośrednio pod nią — nic o jej wnętrzu.

Warstwa Katalog Zna w dół Zadanie
Prezentacji services/presentation LOGIC_URL serwuje stronę, przekazuje formularz, renderuje wyniki
Logiczna services/logic DATA_URL reguły biznesowe, tłumaczenie zapytań, opracowanie wyników
Bazodanowa services/data pliki Excela / SQL tylko wyszukiwanie danych i podanie ich w górę

Szybki start (Docker)

make sample      # przykładowe pliki .xlsx do warstwy bazodanowej
make up          # zbuduj i uruchom 3 warstwy
# otwórz http://localhost:8000

Szybki start (lokalnie, bez Dockera — zalecane)

python -m venv .env && source .env/bin/activate   # venv (jednorazowo)
make install                                       # zależności WSZYSTKICH warstw
make sample                                        # opcjonalnie: dane przykładowe

Potem w 3 osobnych terminalach (w każdym source .env/bin/activate):

make dev-data            # terminal 1  -> :8002
make dev-logic           # terminal 2  -> :8001
make dev-presentation    # terminal 3  -> :8000   ->  http://localhost:8000

make install instaluje zależności wszystkich trzech warstw do aktywnego venv. Testy silnika: make test. Wyczyszczenie cache: make clean-cache.

Modułowość — dowód

  • Wymień prezentację (np. na SPA/React) → reszta bez zmian, kontrakt /api/query stały.
  • Wymień bazę (Excel → SQL) → prezentacja i logika bez zmian (patrz niżej).
  • Każdą warstwę da się uruchomić, testować i wdrażać osobno.

Wydajność warstwy Excela — cache 4-poziomowy

Dziś dane to setki dużych .xlsx, przeszukiwanych po wykrytym nagłówku i układzie kolumn. To kosztowne, więc warstwa bazodanowa ma cache (szczegóły: services/data/README.md):

  1. Schemat (L1, SQLite) — wykryty nagłówek + mapowanie kolumn zapisane raz na wersję pliku.
  2. Dane (L2, Parquet) — znormalizowany arkusz; kolejne odczyty 10100× szybsze niż .xlsx.
  3. Zapytania (L3, in-memory TTL/LRU) — powtarzalne wyszukiwania natychmiast (łatwo podmienić na Redis).
  4. Odwrócony indeks (L4, SQLite)wartość → plik; otwieramy tylko trafione pliki zamiast skanu setek.

Unieważnianie automatyczne: klucz cache = odcisk pliku (mtime+rozmiar, opcjonalnie sha256). Zmiana pliku → przebudowa tylko jego wpisów.

Droga na przyszłość — migracja do SQL

Warstwa bazodanowa ukrywa źródło za interfejsem DataProvider (wzorzec Repository). Migracja:

make migrate                 # ETL: tym samym loaderem Excel -> tabela 'records' + indeksy
export DATA_PROVIDER=sql      # przełącz całą warstwę

SqlDataProvider realizuje ten sam kontrakt /search, więc warstwa logiczna i prezentacji nie zmieniają ani jednej linii. Odwrócony indeks z L4 (SQLite) jest już pomostem — rozbudowa o wszystkie kolumny = docelowa baza.

updater test Mon 20 Jul 2026 19:52:08 CEST

S
Description
No description provided
Readme 1.5 MiB
Languages
Python 83.8%
HTML 7%
JavaScript 6.5%
CSS 1.8%
Makefile 0.6%
Other 0.3%