Switch library hierarchy to GW webshop taxonomy
- warhammer_data.py: GW naming throughout - Space Marine chapters are
their own factions under a 'Space Marines' group, systems match the
shop (Age of Sigmar, The Horus Heresy, Other Games, The Old World,
Middle-Earth), classes are GW shop categories (Battleline, Infantry,
Vehicle, Walker, Flyer, Monster, Mounted, Hero, Titanic), group map
extended to AoS grand alliances / Other Games / Old World / Middle-Earth
- gwshop.py: hierarchy remap - GW depth-4 paths are system/group/faction/
class (the shop's last level is the class layer), depth-5 sources keep
a subfaction before it; catalog snapshot regenerated accordingly
- sorter.py: catalog entry is hierarchy-authoritative (group, class, and
faction when GW moved a unit or keyword tables are stale); generic GW
branches ('Unit Type') and a Battleline default never degrade a
confident keyword classification; whole-catalog retry when the faction
pool has no confident match (handles units GW moved between factions);
whole-catalog matching also runs when keyword classification found no
faction; invalid (HTML) items never fuzzy-match; default catalog is
now data/gwshop_catalog.json
- catalogue.py: --apply moves include the group layer, same structure
as the sorter
- docs/SORTING.md: hierarchy rewritten to GW naming with examples
- tests: expectations updated to GW naming (chapters, unit types)
- verified live: 4/4 real files in the test batch now catalog-match,
e.g. The Twin Lance -> 40k/Xenos Armies/T'au Empire/Epic Hero (GW's
current placement) instead of the stale Drukhari keyword
This commit is contained in:
+14
-5
@@ -257,15 +257,24 @@ def build_catalog(hits: list[dict]) -> dict:
|
||||
)
|
||||
continue
|
||||
# primary branch = longest path (most specific), e.g.
|
||||
# [40k, Armies of the Imperium, Adeptus Custodes, Rules & Accessories]
|
||||
# [40k, Space Marines, Raven Guard, Walker]
|
||||
primary = max(paths, key=len)
|
||||
system = primary[0] if len(primary) > 0 else None
|
||||
group = primary[1] if len(primary) > 1 else None
|
||||
faction = primary[2] if len(primary) > 2 else None
|
||||
subfaction = primary[3] if len(primary) > 3 else None
|
||||
# 5th level (if present) is treated as class; GW uses "Rules &
|
||||
# Accessories" etc. rather than force-org classes.
|
||||
klass = primary[4] if len(primary) > 4 else None
|
||||
# The LAST level is the class/category layer (GW uses shop
|
||||
# categories there: Battleline, Walker, Vehicle, "Rules &
|
||||
# Accessories", product lines like "Cadian"). Deeper sources
|
||||
# (miniset style) may carry a real subfaction before it.
|
||||
if len(primary) >= 5:
|
||||
subfaction = primary[3]
|
||||
klass = primary[4]
|
||||
elif len(primary) == 4:
|
||||
subfaction = None
|
||||
klass = primary[3]
|
||||
else:
|
||||
subfaction = None
|
||||
klass = None
|
||||
key = (hit.get("objectID"), tuple(primary))
|
||||
if key in seen:
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user