Catalogue: classify collection into system/faction/force-org class
- dlphelper/warhammer_data.py: keyword taxonomy (40k factions incl. Chaos and Xenos super-faction units, plus AoS/Heresy/Kill Team/Necromunda/Epic/OW) - dlphelper/catalogue.py: manifest+directory scanner, conservative keyword classifier (plural-tolerant word boundaries, longest match wins), markdown and jsonl reports, overrides support, audited --apply moves - catalogue.py CLI; tests/test_catalogue.py offline classifier test - real-data check on the user's dirs: 1624/3333 files classified so far
This commit is contained in:
@@ -0,0 +1,340 @@
|
||||
"""Warhammer taxonomy and unit keyword tables used by the catalogue.
|
||||
|
||||
Two layers:
|
||||
- SYSTEMS: game system -> faction -> keyword aliases (matched against file
|
||||
names). Faction detection is the primary signal; unit names double as
|
||||
faction hints since they are listed under their faction.
|
||||
- CLASSES: keyword -> force-organization class (40k Force Organization slots:
|
||||
HQ, Troops, Elites, Fast Attack, Heavy Support, Flyer, Dedicated Transport,
|
||||
Lords of War, Fortification).
|
||||
|
||||
The unit table grows with the collection; it does not attempt to enumerate
|
||||
every unit Games Workshop ever released - unknown files land in the
|
||||
"unclassified" bucket of the catalogue report so gaps become visible.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Game systems and factions (keyword aliases, lowercase)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
SYSTEMS: dict[str, dict[str, list[str]]] = {
|
||||
"Warhammer 40,000": {
|
||||
# -- Imperium -------------------------------------------------------
|
||||
"Adeptus Astartes": [
|
||||
"space marine", "astartes", "primaris", "ultramarines", "blood angels",
|
||||
"dark angels", "space wolves", "black templars", "imperial fists",
|
||||
"salamanders", "raven guard", "iron hands", "white scars", "grey knights",
|
||||
"deathwatch", "crimson fists", "flesh tearers", "ravenwing", "deathwing",
|
||||
"inner circle", "wulfen", "thunderwolf", "intercessor", "reiver", "aggressor", "inceptor",
|
||||
"hellblaster", "eradicator", "bladeguard", "sternguard", "devastator",
|
||||
"tactical squad", "terminator squad", "assault marine",
|
||||
"redemptor", "contemptor", "dreadnought", "invictor", "repulsor",
|
||||
"land raider", "land speeder", "predator", "vindicator", "whirlwind",
|
||||
"drop pod", "razorback", "stormraven", "storm talon", "stormhawk",
|
||||
"caestus", "chaplain", "librarian", "apothecary", "vexilus",
|
||||
],
|
||||
"Astra Militarum": [
|
||||
"astra militarum", "imperial guard", "cadian", "catachan", "krieg",
|
||||
"death korps", "tempestus", "scion", "valhallan", "steel legion",
|
||||
"tallarn", "vostroyan", "tanith", "gaunt's ghosts", "leman russ",
|
||||
"chimera", "basilisk", "hydra", "wyvern", "manticore", "deathstrike",
|
||||
"sentinel", "taurox", "commissar", "bullgryn", "ogryn", "ratling",
|
||||
"heavy weapon squad", "baneblade", "stormlord", "shadowsword",
|
||||
"hellhammer", "malcador", "macharius", "valkyrie", "vulture",
|
||||
"primaris psyker", "astropath", "priest",
|
||||
],
|
||||
"Adeptus Mechanicus": [
|
||||
"adeptus mechanicus", "mechanicum", "admech", "skitarii",
|
||||
"cult mechanicus", "sicarian", "ruststalker", "infiltrator",
|
||||
"kataphron", "kastelan", "ironstrider", "sydonian",
|
||||
"onager", "dunecrawler", "maniple", "archmagos", "magos", "dominus",
|
||||
"manipulus", "enginseer", "transuranic", "tech-priest", "cybernetica",
|
||||
"thallax", "castellax", "vorax", "ordinatus", "belisarius cawl",
|
||||
],
|
||||
"Adepta Sororitas": [
|
||||
"adepta sororitas", "sisters of battle", "sister of battle",
|
||||
"battle sister", "repentia", "retributor", "canoness", "dialogus",
|
||||
"hospitaller", "seraphim", "zephyrim", "paragon warsuit",
|
||||
"morvenn vahl", "junith", "immersa", "exorcist", "immolator",
|
||||
],
|
||||
"Adeptus Custodes": [
|
||||
"adeptus custodes", "custodes", "custodian", "allarus", "vertus praetor",
|
||||
"venatari", "aquilon", "sagittarum", "hetaeron", "trajann", "constantin valdor",
|
||||
"sisters of silence", "witchseeker", "prosecutor", "vigilator",
|
||||
"caladius", "coronus", "telemon", "achillus", "galatus", "pallas",
|
||||
],
|
||||
"Imperial Knights": [
|
||||
"imperial knight", "knight errant", "knight paladin", "knight crusader",
|
||||
"knight warden", "knight gallant", "knight lancer", "knight acheron",
|
||||
"knight castellan", "knight valiant", "knight preceptor", "questoris",
|
||||
"armiger", "warglaive", "helverin", "morialtis", "canis rex",
|
||||
"cerastus", "atropos", "seneschal",
|
||||
],
|
||||
"Inquisition & Officio Assassinorum": [
|
||||
"inquisition", "inquisitor", "astra telepathica", "witch hunter",
|
||||
"coteaz", "eisenhorn", "ravenor", "kyria draxus",
|
||||
"officio assassinorum", "culexus", "vindicare", "callidus", "eversor",
|
||||
"saint celestine", "living saint", "assassin",
|
||||
],
|
||||
# -- Chaos ----------------------------------------------------------
|
||||
"Chaos Space Marines": [
|
||||
"chaos space marine", "black legion", "iron warriors", "word bearers",
|
||||
"night lords", "alpha legion", "red corsairs", "world eaters",
|
||||
"emperor's children", "chaos terminator", "chosen", "havoc",
|
||||
"raptor", "warp talon", "chaos cultist", "cultist", "daemon prince",
|
||||
"chaos lord", "chaos sorcerer", "abaddon", "huron blackheart",
|
||||
"kharn", "lucius the eternal", "ahriman", "typhus", "fabius bile",
|
||||
"vashtorr", "defiler", "forgefiend", "maulerfiend", "helldrake",
|
||||
"helbrute", "chaos spawn", "obliterator", "chaos rhino",
|
||||
"chaos vindicator", "spartan assault", "mastodon", "typhon",
|
||||
],
|
||||
"Death Guard": [
|
||||
"death guard", "nurgle", "plague marine", "deathshroud", "mortarion",
|
||||
"plaguecaster", "poxwalker", "blightlord", "foetid bloat-drone",
|
||||
"plagueburst crawler", "myphitic blight-hauler", "blight hauler",
|
||||
"tallyman", "foul blightspawn", "biologus putrifier",
|
||||
"plague surgeon", "necrosius",
|
||||
],
|
||||
"Thousand Sons": [
|
||||
"thousand sons", "tzeentch", "rubric marine", "rubricae",
|
||||
"scarab occult", "magnus the red", "ahzek ahriman", "arhiman",
|
||||
"exalted sorcerer", "osiron", "mutalith vortex beast", "tzaangor",
|
||||
"prospero",
|
||||
],
|
||||
"Chaos Daemons": [
|
||||
"chaos daemon", "chaos daemons", "daemonette", "bloodletter",
|
||||
"plaguebearer", "horror", "screamer", "flesh hound", "juggernaut",
|
||||
"keeper of secrets", "skarbrand", "kairos fateweaver", "rotigus",
|
||||
"be'lakor", "great unclean one", "lord of change", "soul grinder",
|
||||
"skull cannon", "burning chariot", "exalted flamer",
|
||||
"fiend of slaanesh", "plague drone", "nurgling", "herald",
|
||||
"skulltaker", "khorne", "slaanesh", "skull lord",
|
||||
"shalaxi helbane",
|
||||
],
|
||||
"Chaos Knights": [
|
||||
"chaos knight", "knight desecrator", "knight despoiler",
|
||||
"knight rampager", "kharibdyss", "renegade knight",
|
||||
],
|
||||
# -- Xenos ----------------------------------------------------------
|
||||
"Orks": [
|
||||
"ork", "orks", "orkz", "nob", "boyz", "grot", "weirdboy", "painboy",
|
||||
"warboss", "ghazghkull", "meganob", "deff dread", "killa kan",
|
||||
"deffkopta", "stormboy", "kommando", "burna boy", "loota",
|
||||
"trukk", "battlewagon", "gorkanaut", "morkanaut", "stompa", "squig",
|
||||
"zagstruk", "snikrot", "speed freek", "boomdakka", "flash gitz",
|
||||
"wazbom blasta", "dakka jet", "burna-bomber", "blitza-bomber",
|
||||
"da troopz", "dad and sonz", "ass sassins", "abby boi",
|
||||
],
|
||||
"T'au Empire": [
|
||||
"tau", "t'au", "ta'u", "kroot", "vespid", "battlesuit", "crisis suit",
|
||||
"broadside", "r'varna", "ghostkeel", "stormsurge",
|
||||
"fire warrior", "pathfinder team", "devilfish", "hammerhead",
|
||||
"sky ray", "piranha", "sniper drone team", "ethereal",
|
||||
"commander farsight", "commander shadowsun", "aun'va", "darkstrider",
|
||||
"longstrike", "mont'ka", "assorted drones", "breacher",
|
||||
"bomber", "tetra", "barracuda", "sun shark", "razorshark",
|
||||
"kv128 stormsurge", "tx4 piranha", "kv46",
|
||||
],
|
||||
"Tyranids": [
|
||||
"tyranid", "hive tyrant", "swarmlord", "carnifex", "hormagaunt",
|
||||
"termagant", "termagaunt", "genestealer brood", "zoanthrope", "venomthrope",
|
||||
"exocrine", "haruspex", "tyranid prime", "tyranid warrior",
|
||||
"ravener", "gargoyle", "spore mine", "mawloc", "trygon",
|
||||
"harridan", "harpy", "crone", "tervigon", "barbed hierodule",
|
||||
"hierodule", "hierophant", "neurothrope", "deathleaper", "lictor", "pyrovore",
|
||||
"biovore", "broodlord", "bio-titan", "dominatrix",
|
||||
],
|
||||
"Genestealer Cults": [
|
||||
"genestealer cult", "genestealer", "aberrant", "acolyte", "neophyte hybrid",
|
||||
"primus", "magus", "patriarch", "purestrain genestealer",
|
||||
"sanctus", "kelermorph", "goliath truck", "rockgrinder",
|
||||
"jackal alcaeus", "cult limo", "hijacked",
|
||||
],
|
||||
"Necrons": [
|
||||
"necron", "c'tan", "canoptek", "wraith", "spyder", "scarab",
|
||||
"tesseract vault", "doomsday ark", "annihilation barge",
|
||||
"ghost ark", "monolith", "doom scythe", "night scythe",
|
||||
"imotekh", "szarekh", "nemesor zahndrekh", "vargard obyron",
|
||||
"lokhrust", "skorpekh", "flayed one", "deathmark", "lychguard",
|
||||
"necron warrior", "necron immortal", "ovoid", "dzaan",
|
||||
],
|
||||
"Aeldari": [
|
||||
"aeldari", "eldar", "craftworld", "ulthwe", "biel-tan", "iyanden",
|
||||
"alaitoc", "saim-hann", "ynnari", "farseer", "warlock",
|
||||
"spiritseer", "autarch", "asurmen", "guardian defender",
|
||||
"ranger", "wraithguard", "wraithblades", "wraithlord",
|
||||
"wraithknight", "dire avenger", "howling banshee",
|
||||
"striking scorpion", "swooping hawk", "warp spider",
|
||||
"fire dragon", "dark reaper", "shining spears", "windrider",
|
||||
"vyper", "wave serpent", "fire prism", "night spinner",
|
||||
"war walker", "hemlock wraithfighter", "crimson hunter",
|
||||
"shade runner", "skyrunner",
|
||||
],
|
||||
"Drukhari": [
|
||||
"drukhari", "dark eldar", "kabal", "wych", "wrack", "haemonculus",
|
||||
"coven", "reaver jetbike", "hellion", "scourge", "mandrake",
|
||||
"kabalite warrior", "raider", "ravager", "venom", "razorwing",
|
||||
"voidraven", "grotesque", "talos", "cronos",
|
||||
"beast pack", "khymera", "razorwing flock", "asdrubael vect",
|
||||
"lilith", "sathonyx", "the twin lance", "luriel",
|
||||
],
|
||||
"Harlequins": [
|
||||
"harlequin", "death jester", "shadowseer", "solitaire",
|
||||
"troupe", "starweaver", "voidweaver",
|
||||
],
|
||||
"Ynnari": [
|
||||
"ynnari", "ynnead", "visarch", "yncarne", "yvraine",
|
||||
],
|
||||
},
|
||||
"Other Systems": {
|
||||
"Age of Sigmar": [
|
||||
"age of sigmar", "stormcast", "eternals", "orruk", "warclan",
|
||||
"kruleboyz", "gloomspite", "sylvaneth", "seraphon", "ossiarch",
|
||||
"nighthaunt", "lumineth", "daughters of khaine", "fyreslayers",
|
||||
"kharadron", "idoneth", "blades of khorne", "maggotkin",
|
||||
"gaunt summoner", "soulblight", "freeguild", "cities of sigmar",
|
||||
"skaven", "chaos warriors", "saurus", "skink", "liberator",
|
||||
"sequitor", "evocator", "vindictor", "kaldor draigo",
|
||||
],
|
||||
"Horus Heresy": [
|
||||
"horus heresy", "legiones astartes", "pre-heresy",
|
||||
"leviathan pattern", "fire raptor", "sicaran", "fellblade",
|
||||
"kratos", "justaerin", "eisenstein", "veteran tactical",
|
||||
"seeker squad", "suzerain", "invictarus", "fulgurite",
|
||||
],
|
||||
"Kill Team": [
|
||||
"kill team", "killteam", "killzone", "operative",
|
||||
"hand of the archon", "void-dance troupe", "veteran guardsmen",
|
||||
],
|
||||
"Necromunda": [
|
||||
"necromunda", "goliath gang", "escher", "orlock", "cawdor",
|
||||
"van saar", "ash wastes", "underhive",
|
||||
],
|
||||
"Legions Imperialis / Epic": [
|
||||
"legions imperialis", "titan legio", "reaver titan",
|
||||
"warhound titan", "warlord titan", "imperator titan",
|
||||
"warmaster titan",
|
||||
],
|
||||
"Warhammer The Old World": [
|
||||
"the old world", "bretonnia", "greenskins", "tomb kings",
|
||||
"khemri", "chaos dwarf", "dog of war", "grail knight",
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Force Organization classes (keyword -> class)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
CLASSES: list[tuple[str, list[str]]] = [
|
||||
("Lords of War", [
|
||||
"titan", "stompa", "gargantuan", "hierophant", "harridan", "hierodule",
|
||||
"baneblade", "stormlord", "shadowsword", "hellhammer", "malcador",
|
||||
"imperator", "warmaster", "tesseract vault", "plaguereaper",
|
||||
"warhound", "warlord titan",
|
||||
]),
|
||||
("Fortification", ["fortification", "bunker", "bastion", "wall of martyrs"]),
|
||||
("Flyer", [
|
||||
"flyer", "heldrake", "dakka jet", "burna-bomber", "blitza-bomber",
|
||||
"bomber", "sky ray", "stormraven", "storm talon", "stormhawk",
|
||||
"caestus", "valkyrie", "vulture", "thunderbolt", "lightning",
|
||||
"marauder", "razorwing", "voidraven", "crimson hunter",
|
||||
"hemlock", "doom scythe", "night scythe", "harpy", "crone",
|
||||
"fire raptor", "barracuda", "sun shark", "razorshark",
|
||||
"wazbom blasta",
|
||||
]),
|
||||
("Dedicated Transport", [
|
||||
"transport", "rhino", "razorback", "chimera", "taurox", "trukk",
|
||||
"battlewagon", "devilfish", "wave serpent", "ghost ark",
|
||||
"land raider", "repulsor", "drop pod", "starweaver", "voidweaver",
|
||||
"goliath truck", "rockgrinder", "cult limo", "raider", "venom",
|
||||
"spartan assault",
|
||||
]),
|
||||
("Fast Attack", [
|
||||
"fast attack", "assault marine", "assault intercessor", "inceptor",
|
||||
"outrider", "bike squad", "scout biker", "thunderwolf", "raptor",
|
||||
"warp talon", "flesh hound", "screamer", "fiend of slaanesh",
|
||||
"hellion", "reaver jetbike", "scourge", "mandrake", "swooping hawk",
|
||||
"shining spears", "windrider", "vyper", "war walker",
|
||||
"canoptek wraith", "canoptek scarab", "canoptek spyder",
|
||||
"ravener", "gargoyle", "spore mine", "mawloc", "trygon",
|
||||
"pyrovore", "khymera", "beast pack", "razorwing flock",
|
||||
"skyrunner", "zephyrim", "seraphim", "sentinel", "jackal",
|
||||
"stormboy", "deffkopta", "warbiker", "skorpekh destroyer",
|
||||
"sicarian", "ironstrider", "sydonian",
|
||||
]),
|
||||
("Heavy Support", [
|
||||
"heavy support", "devastator", "eradicator", "hellblaster", "havoc",
|
||||
"loota", "burna boy", "carnifex", "exocrine", "haruspex",
|
||||
"zoanthrope", "venomthrope", "biovore", "hierodule",
|
||||
"wraithlord", "wraithknight", "fire prism", "night spinner",
|
||||
"predator", "vindicator", "whirlwind", "basilisk", "hydra",
|
||||
"wyvern", "manticore", "deathstrike", "onager dunecrawler",
|
||||
"kastelan", "kataphron", "hammerhead", "broadside", "stormsurge",
|
||||
"r'varna", "soul grinder", "defiler", "forgefiend", "maulerfiend",
|
||||
"plagueburst crawler", "bloat-drone", "blight hauler", "mutalith",
|
||||
"annihilation barge", "doomsday ark", "obront", "dark reaper",
|
||||
"retributor", "paragon warsuit", "morvenn", "exorcist", "immolator",
|
||||
"caladius", "coronus grav", "telemon", "achillus", "galatus",
|
||||
"pallas grav", "skorpekh",
|
||||
]),
|
||||
("Elites", [
|
||||
"elites", "veteran", "terminator", "sternguard", "bladeguard",
|
||||
"aggressor", "reiver", "vanguard veteran", "dreadnought",
|
||||
"redemptor", "contemptor", "leviathan pattern", "wulfen",
|
||||
"wolf guard", "deathshroud", "plague marine", "blightlord",
|
||||
"poxwalker", "rubric marine", "rubricae", "scarab occult",
|
||||
"tzaangor", "chosen", "possessed", "obliterator", "daemonette",
|
||||
"bloodletter", "plaguebearer", "nurgling", "juggernaut",
|
||||
"chaos cultist", "cultist", "acolyte hybrid", "aberrant",
|
||||
"neophyte", "purestrain", "genestealer", "lictor", "deathmark",
|
||||
"flayed one", "lychguard", "wraithguard", "wraithblades",
|
||||
"howling banshee", "striking scorpion", "warp spider",
|
||||
"fire dragon", "incubi", "wrack", "grotesque", "talos", "cronos",
|
||||
"troupe", "killa kan", "deff dread", "meganob", "nobz", "nob",
|
||||
"kommando", "vespid", "sanguinary guard", "sanguinor",
|
||||
"ancient", "allarus", "vertus praetor", "venatari", "aquilon",
|
||||
"sagittarum", "witchseeker", "prosecutor", "vigilator",
|
||||
"vindicare", "callidus", "eversor", "culexus", "assassin",
|
||||
]),
|
||||
("HQ", [
|
||||
"hq", "captain", "chapter master", "primarch", "lieutenant",
|
||||
"librarian", "chaplain", "apothecary", "farseer", "warlock",
|
||||
"spiritseer", "autarch", "warboss", "big mek", "weirdboy",
|
||||
"painboy", "commander", "ethereal", "hive tyrant", "swarmlord",
|
||||
"tyranid prime", "neurothrope", "deathleaper", "patriarch",
|
||||
"primus", "magus", "sanctus", "kelermorph", "overlord",
|
||||
"imotekh", "szarekh", "zahndrekh", "obyron", "plaguecaster",
|
||||
"necrosius", "chaos lord", "chaos sorcerer", "daemon prince",
|
||||
"exalted champion", "herald", "skulltaker", "kairos", "rotigus",
|
||||
"be'lakor", "great unclean one", "lord of change",
|
||||
"keeper of secrets", "skarbrand", "kharn", "abaddon", "typhus",
|
||||
"mortarion", "magnus", "ahriman", "lucius", "fabius bile",
|
||||
"vashtorr", "canoness", "morvenn", "junith", "immersa",
|
||||
"dialogus", "hospitaller", "trajann", "valdor", "inquisitor",
|
||||
"coteaz", "eisenhorn", "ravenor", "draxus", "celestine",
|
||||
"commissar", "priest", "enginseer", "dominus", "manipulus",
|
||||
"archmagos", "magos", "belisarius cawl", "farsight", "shadowsun",
|
||||
"aun'va", "darkstrider", "longstrike", "shade runner",
|
||||
]),
|
||||
("Troops", [
|
||||
"troops", "battleline", "tactical squad", "intercessor",
|
||||
"incursor", "infiltrator", "infantry squad", "conscript",
|
||||
"krieg", "catachan", "cadian", "vostroyan", "penal legion",
|
||||
"ratling", "veteran squad", "fire warrior", "pathfinder team",
|
||||
"kroot", "termagant", "hormagaunt", "necron warrior",
|
||||
"necron immortal", "guardian defender", "storm guardian",
|
||||
"kabalite warrior", "boyz", "gretchin",
|
||||
"scion", "scout squad",
|
||||
]),
|
||||
]
|
||||
|
||||
# Flattened per-system faction keyword index for quick matching
|
||||
FACTION_ALIASES: dict[str, dict[str, str]] = {
|
||||
system: {alias: faction for faction, aliases in factions.items() for alias in aliases}
|
||||
for system, factions in SYSTEMS.items()
|
||||
}
|
||||
|
||||
UNIT_CLASSES: dict[str, str] = {kw: klass for klass, kws in CLASSES for kw in kws}
|
||||
Reference in New Issue
Block a user