fix: váha prvku komponent počítaná z komponent prošlých filtrem (#55) (#83)

* fix: váha prvku komponent počítaná z komponent prošlých filtrem (#55)

Váha prvku_vaha = 1/n se dosud počítala ze všech komponent dokumentační
jednotky ještě před filtrem na období a areál, takže při aktivním filtru
váhy prvků jedné DJ nedávaly v součtu 1 (DJ se 4 komponentami, filtru
vyhoví 1 → váha 0,25 místo 1).

- nová funkce _component_entries: nejdřív vyfiltruje komponenty, pak
  přidělí váhu 1/n z těch, které prošly; DJ bez komponent má váhu 1
- smoke test vaha_komponent (4×0,25; 1 ze 4 → 1; 2 ze 3 → 2×0,5; bez
  komponent → 1)
- README: pole prvek_vaha v tabulce atributů komponent
- changelog v2.2.0 doplněn (bez povýšení verze)
- OpenSpec změna openspec/changes/fix-component-feature-weight

Ověřeno: živá data (Praha, novověk) – 0 z 1204 DJ se součtem vah ≠ 1,
původní kód 921; check_sources, bandit, detect-secrets, flake8, ruff,
pyqgis4-checker, smoke test v qgis/qgis:ltr i :stable.

Implementace připravena AI (Claude, subagent), ověřena a zkontrolována.

* openspec: archivovat fix-component-feature-weight (#55)

Ruční test v QGIS ověřen správcem: akce i lokality s Načíst komponenty,
bez filtru i s filtrem období – váhy prvků jedné DJ dávají součet 1 a
počítají se jen z vyfiltrovaných komponent. Úkol 3.2 odškrtnut, změna
archivována přes openspec archive --skip-specs.

Připraveno s pomocí AI (Claude).
This commit is contained in:
david-spacil authored and GitHub committed 2026-10-02 17:17:28 +02:00
1 parent 05e62bd23c
commit 6e95973296
9 files changed
+297 -34

No files matched your search

+58 -33
View File
@@ -386,6 +386,49 @@ def tr_code(code):
return TRANSLATIONS.get(code, code)
def _component_entries(dj_meta, komps, passes):
"""
Builds the feature metadata entries of the "Načíst komponenty"
mode: one entry per component that passes the given predicate,
with the weight 1/n where n is the number of passing components,
so the weights of one documentation unit sum to 1 even when a
period/area filter removes some of them. A documentation unit
without components gets a single entry with empty component
fields and weight 1.
dj_meta: metadata shared by the documentation unit (spread into
every entry); komps: its component documents; passes: predicate
komp -> bool deciding whether a component becomes a feature.
"""
if not komps:
# DJ without components – still one feature, weight 1
return [{
**dj_meta,
'komponenta_id': "",
'komponenta_areal': "",
'komponenta_obdobi': "",
'vaha': 1,
}]
prochazejici = [komp for komp in komps if passes(komp)]
vaha = 1 / len(prochazejici) if prochazejici else 1
return [
{
**dj_meta,
'komponenta_id': komp.get('ident_cely', ""),
'komponenta_areal': (
komp.get('komponenta_areal') or {}
).get('value', ""),
'komponenta_obdobi': (
komp.get('komponenta_obdobi') or {}
).get('value', ""),
'vaha': vaha,
}
for komp in prochazejici
]
def komp_projde_filtrem(komp, filter_areal, filter_datace, filters):
# 'or {}' – the key may be present with a None value
areal_id = (komp.get('komponenta_areal') or {}).get('id', "")
@@ -826,31 +869,16 @@ def load_amcr_data(canvas, bb, filters=None,
# One feature per component –
# all data on a single row, no relations needed
if komps:
komps_count = len(komps)
for komp in komps:
if not komp_projde_filtrem(
komp, filter_areal,
# The weight is 1/n of the components
# that pass the period/area filter,
# so one DJ sums to 1
for komp_meta in _component_entries(
dj_meta, komps,
lambda k: komp_projde_filtrem(
k, filter_areal,
filter_datace, filters
):
continue
komp_meta = {
**dj_meta,
'komponenta_id': komp.get(
'ident_cely',
""
),
'komponenta_areal': (
komp.get('komponenta_areal')
or {}
).get('value', ""),
'komponenta_obdobi': (
komp.get('komponenta_obdobi')
or {}
).get('value', ""),
'vaha': 1/komps_count,
}
)
):
pian_lookup[dj_pian_value].append(
komp_meta)
target_pian_ids_count += 1
@@ -860,15 +888,12 @@ def load_amcr_data(canvas, bb, filters=None,
if filter_areal or filter_datace:
continue
empty_meta = {
**dj_meta,
'komponenta_id': "",
'komponenta_areal': "",
'komponenta_obdobi': "",
}
pian_lookup[dj_pian_value].append(
empty_meta)
target_pian_ids_count += 1
for komp_meta in _component_entries(
dj_meta, [], lambda k: True
):
pian_lookup[dj_pian_value].append(
komp_meta)
target_pian_ids_count += 1
else:
target_pian_ids_count += 1
pian_lookup[dj_pian_value].append(dj_meta)