Initial commit
This commit is contained in:
171
resources/docs/EvaluationRuleSet.md
Normal file
171
resources/docs/EvaluationRuleSet.md
Normal file
@@ -0,0 +1,171 @@
|
||||
# EvaluationRuleSet - pravidla vyhodnocení pro rozhodčí
|
||||
|
||||
Tento dokument popisuje vyhodnocovací proces a jednotlivá nastavení rulesetu
|
||||
(`EvaluationRuleSet`). Slouží jako nápověda a vysvětlení dopadu na
|
||||
skóre a výsledky.
|
||||
|
||||
## Stručný popis vyhodnocovacího procesu
|
||||
|
||||
1. **Prepare** - příprava běhu, kontrola locku, vyčištění staging tabulek.
|
||||
2. **ParseLogs** - parsování EDI souboru, naplnění `logs` a `log_qsos`.
|
||||
3. **BuildWorkingSet** - normalizace volacích znaků, lokátorů, příprava `working_qsos`.
|
||||
4. **Match** - párování QSO mezi logy, detekce neshod a typy chyb.
|
||||
5. **UnpairedClassification** - NIL/NO_COUNTERPART/UNIQUE pro nenapárovaná QSO.
|
||||
6. **DuplicateResolution** - výběr přeživších u duplicit podle strategie.
|
||||
7. **Score** - bodování, aplikace policy, penalizací a multiplikátorů.
|
||||
8. **Aggregate** - součty za log (score, counts), výpočet metrik.
|
||||
9. **ApplyLogOverrides** - ruční zásahy do log_results.
|
||||
10. **RecalculateRanks** - přepočet pořadí.
|
||||
11. **Finalize** - uzavření běhu a uvolnění locku.
|
||||
|
||||
## Politiky (společné chování)
|
||||
|
||||
Používané policy hodnoty:
|
||||
- **INVALID**: `is_valid=false`, body 0.
|
||||
- **ZERO_POINTS**: `is_valid=true`, body 0.
|
||||
- **FLAG_ONLY**: `is_valid=true`, body beze změny (jen flag).
|
||||
- **PENALTY**: `is_valid=true`, body 0 (u některých chyb body zůstávají) + penalizace.
|
||||
|
||||
Poznámka: `valid_qso_count` se počítá podle `is_valid`.
|
||||
|
||||
## Nastavení rulesetu a dopad (kde se uplatňuje)
|
||||
|
||||
### Skóre a body
|
||||
- `scoring_mode` (DISTANCE / FIXED_POINTS): určuje typ bodování.
|
||||
Uplatnění: scoring.
|
||||
- `points_per_qso`: fixní body za QSO (FIXED_POINTS).
|
||||
Uplatnění: scoring.
|
||||
- `points_per_km`: body za km (DISTANCE).
|
||||
Uplatnění: scoring.
|
||||
- `distance_rounding` (FLOOR/ROUND/CEIL): zaokrouhlení vzdálenosti.
|
||||
Uplatnění: scoring.
|
||||
- `min_distance_km`: minimální vzdálenost pro bodované QSO.
|
||||
Uplatnění: scoring.
|
||||
|
||||
### Multiplikátory
|
||||
- `use_multipliers`: zapíná multiplikátory.
|
||||
Uplatnění: scoring + agregace.
|
||||
- `multiplier_type` (WWL/DXCC/SECTION/COUNTRY/NONE): typ multiplikátoru.
|
||||
Uplatnění: scoring + agregace.
|
||||
- `multiplier_scope` (PER_BAND/OVERALL): scope multiplikátoru.
|
||||
Uplatnění: agregace.
|
||||
- `multiplier_source` (VALID_ONLY/ALL_MATCHED): z čeho se počítají.
|
||||
Uplatnění: agregace.
|
||||
- `wwl_multiplier_level` (LOCATOR_2/4/6): délka WWL multiplikátoru.
|
||||
Uplatnění: scoring.
|
||||
|
||||
### Error policy a penalizace
|
||||
- `dup_qso_policy`, `nil_qso_policy`: policy pro DUP/NIL.
|
||||
Uplatnění: scoring.
|
||||
- `no_counterpart_log_policy`, `not_in_counterpart_log_policy`, `unique_qso_policy`,
|
||||
`time_mismatch_policy`: policy pro NIL/UNIQUE/TIME_MISMATCH.
|
||||
Uplatnění: scoring.
|
||||
- `busted_call_policy`, `busted_exchange_policy`, `busted_serial_policy`,
|
||||
`busted_locator_policy`, `busted_rst_policy`: policy pro BUSTED chyby.
|
||||
Uplatnění: scoring.
|
||||
- `penalty_*_points`: velikost penalizací pro jednotlivé chyby.
|
||||
Uplatnění: scoring.
|
||||
- `out_of_window_policy`, `penalty_out_of_window_points`: chování mimo časové okno.
|
||||
Uplatnění: scoring.
|
||||
|
||||
### Matching (párování QSO)
|
||||
- `time_tolerance_sec`: tolerance času pro match.
|
||||
Uplatnění: matching.
|
||||
- `allow_time_shift_one_hour`, `time_shift_seconds`: povolený časový posun.
|
||||
Uplatnění: matching.
|
||||
- `allow_time_mismatch_pairing`, `time_mismatch_max_sec`: párování mimo toleranci.
|
||||
Uplatnění: matching.
|
||||
- `callsign_normalization` (STRICT/IGNORE_SUFFIX),
|
||||
`ignore_slash_part`, `ignore_third_part`,
|
||||
`callsign_suffix_max_len`, `callsign_levenshtein_max`:
|
||||
normalizace volacích znaků a fuzzy match.
|
||||
Uplatnění: matching.
|
||||
- `match_tiebreak_order`: pořadí tiebreak kritérií (time_diff, exchange_match, ...).
|
||||
Uplatnění: matching (volba nejlepšího kandidáta).
|
||||
- `match_require_locator_match`, `match_require_exchange_match`:
|
||||
vyžadování shody lokátoru/exchange pro match.
|
||||
Uplatnění: matching.
|
||||
- `exchange_type`, `exchange_requires_*`, `exchange_pattern`:
|
||||
definice a kontrola exchange.
|
||||
Uplatnění: matching.
|
||||
- `letters_in_rst`, `rst_ignore_third_char`: normalizace RST.
|
||||
Uplatnění: matching.
|
||||
- `discard_qso_*`: určuje, zda se neshoda označí jako BUSTED a s jakou stranou (RX/TX).
|
||||
Uplatnění: matching.
|
||||
- `checklog_matching`: zahrnout CHECK logy do matchingu.
|
||||
Uplatnění: matching.
|
||||
|
||||
### Duplicity a unikátní QSO
|
||||
- `dupe_scope` (BAND/BAND_MODE): klíč pro duplicity.
|
||||
Uplatnění: working set + duplicity.
|
||||
- `dup_resolution_strategy`: pořadí pravidel pro výběr přeživších DUP.
|
||||
Uplatnění: duplicate resolution.
|
||||
- `require_unique_qso`: zapíná detekci UNIQUE.
|
||||
Uplatnění: unpaired klasifikace.
|
||||
|
||||
### DQ limity (log-level)
|
||||
- `out_of_window_dq_threshold`: DQ při nadlimitních QSO mimo okno.
|
||||
Uplatnění: agregace.
|
||||
- `time_diff_dq_threshold_percent`, `time_diff_dq_threshold_sec`: DQ při časovém rozptylu.
|
||||
Uplatnění: agregace.
|
||||
- `bad_qso_dq_threshold_percent`: DQ při nadlimitním % chybných QSO.
|
||||
Uplatnění: agregace.
|
||||
|
||||
### 6H operating window
|
||||
- `operating_window_mode` (NONE/BEST_CONTIGUOUS): zapíná 6H operating window.
|
||||
Uplatnění: agregace (vybere nejlepší 6H okno pro log).
|
||||
- `operating_window_hours`: délka 6H okna (aktuálně pevně 6 h).
|
||||
Uplatnění: agregace.
|
||||
- `sixhr_ranking_mode` (IARU/CRK): způsob pořadí pro 6H.
|
||||
Uplatnění: přepočet pořadí (IARU = jedna společná 6H tabulka bez SO/MO, CRK = odděleně SO/MO).
|
||||
|
||||
Poznámka: Pro IARU se 6H okno vybírá jako max. 2 segmenty s pauzou >= 2 h, součet délek <= 6 h.
|
||||
|
||||
### Options (JSON)
|
||||
- `options`: fallback hodnoty, pokud není vyplněn sloupec.
|
||||
Uplatnění: napříč matching/scoring (viz metody `getOption`/`get*` v modelu).
|
||||
|
||||
## Výchozí ruleset (default_vhf_compat)
|
||||
|
||||
Zdroj: `database/seeders/EvaluationRuleSetSeeder.php`
|
||||
|
||||
Nastavení (zkrácené na podstatné hodnoty):
|
||||
- Profil: **Default VHF (compat)**, permisivní matching.
|
||||
- Scoring: `scoring_mode=DISTANCE`, `points_per_qso=1`, `points_per_km=1.0`
|
||||
- Multiplikátory: `use_multipliers=false`, `multiplier_type=WWL`
|
||||
- Policy:
|
||||
- `dup_qso_policy=ZERO_POINTS`
|
||||
- `nil_qso_policy=ZERO_POINTS`
|
||||
- `no_counterpart_log_policy=FLAG_ONLY`
|
||||
- `not_in_counterpart_log_policy=ZERO_POINTS`
|
||||
- `unique_qso_policy=FLAG_ONLY`
|
||||
- `busted_*_policy=ZERO_POINTS`
|
||||
- `time_mismatch_policy=ZERO_POINTS`
|
||||
- penalizace vše 0
|
||||
- Matching:
|
||||
- `time_tolerance_sec=600`
|
||||
- `allow_time_shift_one_hour=true`, `time_shift_seconds=3600`
|
||||
- `allow_time_mismatch_pairing=false`
|
||||
- `callsign_normalization=IGNORE_SUFFIX`
|
||||
- `ignore_slash_part=true`, `ignore_third_part=true`
|
||||
- `letters_in_rst=false`, `rst_ignore_third_char=true`
|
||||
- `match_require_locator_match=false`, `match_require_exchange_match=false`
|
||||
- `match_tiebreak_order=[time_diff, exchange_match, locator_match, report_match, log_qso_id]`
|
||||
- `discard_qso_rec_diff_*=true`, `discard_qso_sent_diff_*=false`
|
||||
- Duplicity:
|
||||
- `dupe_scope=BAND`
|
||||
- `dup_resolution_strategy=[paired_first, ok_first, earlier_time, lower_id]`
|
||||
- Exchange:
|
||||
- `exchange_type=SERIAL_WWL`
|
||||
- `exchange_requires_wwl=true`, `exchange_requires_serial=true`, `exchange_requires_report=true`
|
||||
- DQ limity:
|
||||
- `out_of_window_dq_threshold=600`
|
||||
- `time_diff_dq_threshold_percent=30`
|
||||
- `time_diff_dq_threshold_sec=600`
|
||||
- `bad_qso_dq_threshold_percent=30`
|
||||
|
||||
## Poznámky k interpretaci výsledků
|
||||
|
||||
- `valid_qso_count` = počet QSO s `is_valid=true`.
|
||||
- `discarded_qso_count` = počet QSO s `is_valid=false`.
|
||||
- Penalizace se uplatňuje v `penalty_score` a odčítá se od `base_score`.
|
||||
149
resources/docs/prezentace_pipeline.md
Normal file
149
resources/docs/prezentace_pipeline.md
Normal 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).
|
||||
- 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.
|
||||
Reference in New Issue
Block a user