feat: pzmm conflict detection + content-type categorization
- mod_files manifest table populated at parse time - POST /api/conflicts endpoint - mod_types fingerprinting feeds derive_category - DD filelist regex broadened to cover conflict-eligible exts - media/maps/<*>/* excluded from manifest (per-mod namespaced, no conflict value, can be tens of MB per mod) Plan: docs/plans/2026-05-04-pzmm-conflict-and-typing.md
This commit is contained in:
58
api/categorize.py
Normal file
58
api/categorize.py
Normal file
@@ -0,0 +1,58 @@
|
||||
"""Public helper for mapping pzmm content-type tags to sortof CATEGORY_ORDER.
|
||||
|
||||
The same mapping is also inlined in `mlos_sort.py` (both api/ and worker/
|
||||
copies, deliberately — worker uses a separate venv with no FastAPI deps,
|
||||
so it cannot import from api/). This module exposes the helper for
|
||||
non-mlos consumers (e.g. /api/conflicts diagnostics output) without
|
||||
forcing them to drag in the whole sorter module.
|
||||
|
||||
Source: pzmm core/mods.py:detect_mod_types ordering, mapped to sortof's
|
||||
CATEGORY_ORDER buckets per docs/plans/2026-05-04-pzmm-conflict-and-typing.md
|
||||
§3.4.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
# Items / Animations / Lua / Unknown intentionally absent — too generic to
|
||||
# drive a category decision; callers should fall through to other heuristics.
|
||||
_TYPE_TO_CAT: Dict[str, str] = {
|
||||
"Maps": "map",
|
||||
"Vehicles": "vehicle",
|
||||
"Weapons": "weapon",
|
||||
"Clothing": "wearable",
|
||||
"Traits": "code",
|
||||
"Professions": "profession",
|
||||
"Recipes": "crafting",
|
||||
"Tiles": "tile",
|
||||
"Textures": "texture",
|
||||
"Sounds": "sound",
|
||||
"UI": "ui",
|
||||
"Translations": "translation",
|
||||
"Patch": "patch",
|
||||
"Dependency": "tweaks",
|
||||
"Framework": "tweaks",
|
||||
}
|
||||
|
||||
|
||||
def types_to_category(mod_types: List[str], name: str = "") -> Optional[str]:
|
||||
"""First mod_type that maps to a sortof CATEGORY_ORDER bucket wins.
|
||||
|
||||
Returns the bucket name (e.g. "weapon", "vehicle"), or None when:
|
||||
- mod_types is empty (manifest not yet built), or
|
||||
- mod_types contains only skip-types (Items / Animations / Lua / Unknown).
|
||||
|
||||
The `name` arg is used for the vehicle_spawn refinement only — when a
|
||||
Vehicles-tagged mod is named like "spawn zone X", the more specific
|
||||
`vehicle_spawn` bucket wins over the generic `vehicle`.
|
||||
"""
|
||||
if not mod_types:
|
||||
return None
|
||||
for t in mod_types:
|
||||
cat = _TYPE_TO_CAT.get(t)
|
||||
if cat:
|
||||
if cat == "vehicle" and name and "spawn zone" in name.lower():
|
||||
return "vehicle_spawn"
|
||||
return cat
|
||||
return None
|
||||
Reference in New Issue
Block a user