## 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). - Non‑survivory 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 out‑of‑window 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.