Initial commit

This commit is contained in:
Zdeněk Burda
2026-01-09 21:26:40 +01:00
parent e83aec6dca
commit 41e3ce6f25
404 changed files with 61250 additions and 28 deletions

View File

@@ -0,0 +1,149 @@
## 1) "Manažerský souhrn"
- Pipeline je vícekroková, deterministická a auditovaná přes `EvaluationRunEvent`.
- Pořadí: Prepare → Parse → Build working set → Match → Unpaired → Duplicity → Score → Aggregate → Overrides → Ranks → Finalize.
- Kritické kontroly: párování QSO (včetně chyb exchange), klasifikace nenapárovaných (NIL/NO_COUNTERPART/UNIQUE), duplicity, out-of-window.
- Body se počítají podle rulesetu: FIXED_POINTS nebo DISTANCE; politika chyb rozhoduje o validitě, bodech a penalizacích.
- Systém má tři „čekací“ body pro ruční kontrolu (input, matching, score) a podporuje ruční override logů/QSO.
## 2) Podrobný popis pipeline (technicky)
### Spuštění a příprava
1) **StartEvaluationRunJob / EvaluationCoordinator**
- Kontrola locku pro dané kolo (`evaluation:round:{round_id}`), přechod do `RUNNING`.
- Spuštění řetězce jobů (prepare → parse logs).
2) **PrepareRunJob**
- Vyčistí staging data (`qso_results`, `log_results`, `working_qsos`) pro daný run.
- Sestaví scope skupin (band/category/power) a uloží do `evaluation_runs.scope`.
- Vytvoří skeleton `log_results` pro všechny logy (včetně aplikace log overrides na band/kategorii/power).
- Zapisuje auditní eventy.
### Parsování vstupů a working set
3) **DispatchParseLogsJobsJob → ParseLogJob**
- Pro každý log načte EDI a naplní `logs` + `log_qsos`.
- Průběžný progress, chybné soubory jsou hlášeny jako eventy.
- Pro `rules_version=CLAIMED` se aktualizují deklarované výsledky.
4) **DispatchBuildWorkingSetJobsJob → BuildWorkingSetLogJob**
- Vytvoří `working_qsos` (normalizace callsignů, lokátorů, band, match_key, dupe_key).
- Kontroly:
- validace lokátoru (invalid → error v `working_qsos.errors`),
- out-of-window podle času kola,
- normalizace a klíče pro matching/duplikace.
- Logy s override `IGNORED` se vynechají.
- Po dokončení: **PauseEvaluationRunJob → WAITING_REVIEW_INPUT**.
### Matching a klasifikace nenapárovaných
5) **DispatchMatchJobsJob → MatchQsoBucketJob (PASS 1 + PASS 2)**
- Matching běží v „bucketu“ (band + call_norm), dvě fáze:
- PASS 1: pouze exact shody.
- PASS 2: u zbylých QSO povolí fuzzy shody dle rulesetu (tolerance, time shift, Levenshtein).
- Kontroly během matchingu:
- časová tolerance (`time_tolerance_sec`),
- mismatch exchange (callsign/RST/serial/locator) dle `discard_qso_*`,
- time mismatch se jen označí, validita se řeší až ve scoringu,
- ruční QSO override může vynutit match nebo status.
- Výstup: `qso_results` s `matched_log_qso_id`, `error_code`, `error_side`, `match_type`.
6) **DispatchUnpairedJobsJob → UnpairedClassificationBucketJob**
- Pro nenapárované QSO určí:
- `NOT_IN_COUNTERPART_LOG` (protistanice log má),
- `NO_COUNTERPART_LOG` (protistanice log nemá),
- `UNIQUE` (pokud je zapnuté `require_unique_qso`).
- Nastaví `error_code`, `is_nil`, `is_valid=false` (validita se následně řeší policy ve scoringu).
7) **DuplicateResolutionJob**
- Zpracuje duplicity v rámci logu podle `dupe_scope` (BAND/BAND_MODE).
- Strategie výběru „přeživšího“ QSO: `dup_resolution_strategy` (typicky paired_first → ok_first → earlier_time → lower_id).
- Nonsurvivory se označí `DUP` a připraví se na policy v bodech.
- Po dokončení: **PauseEvaluationRunJob → WAITING_REVIEW_MATCH**.
### Bodování a agregace
8) **DispatchScoreJobsJob → ScoreGroupJob**
- Pro každé QSO spočte základní body:
- `FIXED_POINTS`: `points_per_qso`
- `DISTANCE`: vzdálenost z lokátorů × `points_per_km`
- vzdálenost se zaokrouhluje (`distance_rounding`) a respektuje `min_distance_km`.
- Policy rozhodnutí (error_code → policy):
- `INVALID``is_valid=false`
- `ZERO_POINTS` → 0 bodů
- `FLAG_ONLY` → body beze změny
- `PENALTY` → 0 bodů + penalizace (u `BUSTED_RST` může body ponechat)
- Aplikuje se outofwindow policy (`out_of_window_policy`).
- Výsledky: `points`, `penalty_points`, multiplikátor (WWL/DXCC/SECTION/COUNTRY) pro pozdější agregaci.
9) **DispatchAggregateResultsJobsJob → AggregateLogResultsJob**
- Sečte `base_score` (validní QSO) a `penalty_score` (odečet penalizací).
- Pokud jsou multiplikátory aktivní: `multiplier_score = (base + penalty) × multiplier_count`.
- `official_score = max(0, multiplier_score)`.
- Počítá statistiky: valid/dupe/busted/unique/out-of-window/invalid, `score_per_qso`.
- DQ kontroly:
- `out_of_window_dq_threshold`,
- `time_diff_dq_threshold_percent` + `time_diff_dq_threshold_sec`,
- `bad_qso_dq_threshold_percent`.
- 6H: volí nejlepší operating window (pokud zapnuto).
- Navazuje **ApplyLogOverridesJob** + **RecalculateOfficialRanksJob**.
- Po dokončení: **PauseEvaluationRunJob → WAITING_REVIEW_SCORE**.
10) **FinalizeRunJob**
- Znov evidentně aplikuje overrides a přepočítá pořadí (pro jistotu).
- Uzavře běh (`SUCCEEDED`) a uvolní lock.
### Poznámky k ručním zásahům
- **Log overrides**: lze vynutit status/band/kategorii/power/6H; log lze i ignorovat.
- **QSO overrides**: lze vynutit match nebo stav QSO, případně body.
- Tři „čekací“ stavy jsou určeny pro ruční kontrolu a zásah rozhodčího.
## 3) Návrh prezentace (alfa verze a sběr feedbacku)
### Doporučená struktura prezentace (slide deck)
1) **Proč nový vyhodnocovač** cíl: determinismus, auditovatelnost, pravidla v rulesetu.
2) **Pipeline v 1 minutě** jediný graf s pořadím kroků + tři kontrolní „pause“.
3) **Matching principy** 2 passy, tolerance času, co je „busted“ vs „time mismatch“.
4) **NIL/NO_COUNTERPART/UNIQUE** kdy co vzniká a proč.
5) **Duplicity** strategie přeživších, důvod pro samostatný krok.
6) **Bodování** FIXED vs DISTANCE, validita až ve scoringu, policy + penalizace.
7) **Agregace a DQ** multiplikátory, 6H window, limity DQ.
8) **UI a ruční zásahy** ukázka overrides (log/QSO) + auditní eventy.
9) **Co umí alfa a co ještě ne** rizika, co je stabilní, co se bude dolaďovat.
10) **Co od vás potřebujeme** seznam dotazů, sběr pravidel a příkladů.
### Co získat
- Preferované policy pro NIL/DUP/BUSTED/TIME_MISMATCH (validita vs penalizace).
- Reálné hranice tolerancí (čas, matching pravidla, tiebreak priority).
- Pravidla pro 6H: reálná očekávání, jak interpretovat okno a pořadí.
- DQ prahy (out-of-window, bad QSO %, time diff).
- Seznam typických problémových situací z minulých ročníků.
### Otázky, na které se zeptat
- Co je v praxi považováno za „přijatelnou“ odchylku času?
- Kdy je chyba „busted“ vs jen „flag“ (nechat body)?
- Jak zacházet s unikátními QSO (UNIQUE) v různých soutěžích?
- Jaké ruční zásahy děláte dnes nejčastěji a proč?
- Jak má vypadat finální výstup pro rozhodčí (tabulka, export, log detail)?
## Slovníček pojmů a stavů
- **OK**: QSO bez chyb, standardni vstup do bodovani.
- **NIL**: nenaprovane QSO; protistanice se v matchingu nenasla.
- **NO_COUNTERPART_LOG**: protistanice nema zadny log; QSO je klasifikovano jako NIL.
- **NOT_IN_COUNTERPART_LOG**: protistanice log ma, ale konkretni QSO v nem chybi; QSO je klasifikovano jako NIL.
- **UNIQUE**: jediny zaznam o spojeni s danou protistanici v danem scope; pouziva se, pokud je zapnute `require_unique_qso`.
- **DUP**: duplicitni QSO v ramci logu podle `dupe_scope`; pouze "prezivsi" QSO boduje.
- **BUSTED_CALL**: neshoda volaciho znaku (callsign); urcuje se strana chyby (RX/TX).
- **BUSTED_RST**: neshoda RST reportu (pokud je RST soucasti exchange).
- **BUSTED_SERIAL**: neshoda serialu (nebo casti exchange, ktera se mapuje na serial).
- **BUSTED_LOCATOR**: neshoda lokatoru (WWL).
- **TIME_MISMATCH**: QSO sparovano, ale casovy rozdil mimo toleranci; resi se policy ve scoringu.
- **OUT_OF_WINDOW**: QSO mimo casove okno kola; bodovani urcuje `out_of_window_policy`.
- **ERROR_SIDE (RX/TX/NONE)**: kdo udelal chybu (prijem/vysilani/neurceno); ovlivnuje penalizace.