"""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