@alpaca-software/40kdc-data 0.5.11 → 0.5.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/README.md +10 -0
  2. package/dist/author-input-pack.d.ts +27 -0
  3. package/dist/author-input-pack.d.ts.map +1 -0
  4. package/dist/author-input-pack.js +198 -0
  5. package/dist/author-input-pack.js.map +1 -0
  6. package/dist/codegen-data.js +1 -0
  7. package/dist/codegen-data.js.map +1 -1
  8. package/dist/commands/import.d.ts.map +1 -1
  9. package/dist/commands/import.js +3 -1
  10. package/dist/commands/import.js.map +1 -1
  11. package/dist/convert-faction.d.ts.map +1 -1
  12. package/dist/convert-faction.js +22 -2
  13. package/dist/convert-faction.js.map +1 -1
  14. package/dist/data/bundle.generated.js +1 -1
  15. package/dist/data/bundle.generated.js.map +1 -1
  16. package/dist/data/dataset.d.ts +2 -1
  17. package/dist/data/dataset.d.ts.map +1 -1
  18. package/dist/data/dataset.js +2 -0
  19. package/dist/data/dataset.js.map +1 -1
  20. package/dist/data/entities.d.ts +22 -0
  21. package/dist/data/entities.d.ts.map +1 -1
  22. package/dist/data/entities.js +28 -0
  23. package/dist/data/entities.js.map +1 -1
  24. package/dist/data/index.d.ts +3 -1
  25. package/dist/data/index.d.ts.map +1 -1
  26. package/dist/data/index.js +3 -1
  27. package/dist/data/index.js.map +1 -1
  28. package/dist/data/roster-resolve.d.ts +16 -1
  29. package/dist/data/roster-resolve.d.ts.map +1 -1
  30. package/dist/data/roster-resolve.js +19 -0
  31. package/dist/data/roster-resolve.js.map +1 -1
  32. package/dist/data/types.d.ts +3 -1
  33. package/dist/data/types.d.ts.map +1 -1
  34. package/dist/data/types.js +1 -0
  35. package/dist/data/types.js.map +1 -1
  36. package/dist/export/newrecruit-json.d.ts.map +1 -1
  37. package/dist/export/newrecruit-json.js +4 -3
  38. package/dist/export/newrecruit-json.js.map +1 -1
  39. package/dist/export/newrecruit-simple.js +2 -2
  40. package/dist/export/newrecruit-simple.js.map +1 -1
  41. package/dist/export/newrecruit-wtc.d.ts.map +1 -1
  42. package/dist/export/newrecruit-wtc.js +3 -1
  43. package/dist/export/newrecruit-wtc.js.map +1 -1
  44. package/dist/export/rosterizer.d.ts.map +1 -1
  45. package/dist/export/rosterizer.js +6 -7
  46. package/dist/export/rosterizer.js.map +1 -1
  47. package/dist/extract-faction-pack.d.ts +61 -0
  48. package/dist/extract-faction-pack.d.ts.map +1 -0
  49. package/dist/extract-faction-pack.js +318 -0
  50. package/dist/extract-faction-pack.js.map +1 -0
  51. package/dist/gen-conformance.js +37 -4
  52. package/dist/gen-conformance.js.map +1 -1
  53. package/dist/generated.d.ts +46 -2
  54. package/dist/generated.d.ts.map +1 -1
  55. package/dist/generated.js.map +1 -1
  56. package/dist/import/gw-headerless.d.ts +70 -0
  57. package/dist/import/gw-headerless.d.ts.map +1 -0
  58. package/dist/import/gw-headerless.js +343 -0
  59. package/dist/import/gw-headerless.js.map +1 -0
  60. package/dist/import/gw.js +1 -1
  61. package/dist/import/gw.js.map +1 -1
  62. package/dist/import/import-roster.d.ts.map +1 -1
  63. package/dist/import/import-roster.js +8 -0
  64. package/dist/import/import-roster.js.map +1 -1
  65. package/dist/import/listforge-text.js +1 -1
  66. package/dist/import/listforge-text.js.map +1 -1
  67. package/dist/import/listforge.d.ts.map +1 -1
  68. package/dist/import/listforge.js +18 -3
  69. package/dist/import/listforge.js.map +1 -1
  70. package/dist/import/newrecruit-json.d.ts.map +1 -1
  71. package/dist/import/newrecruit-json.js +21 -3
  72. package/dist/import/newrecruit-json.js.map +1 -1
  73. package/dist/import/newrecruit-simple.js +1 -1
  74. package/dist/import/newrecruit-simple.js.map +1 -1
  75. package/dist/import/newrecruit-wtc.js +1 -1
  76. package/dist/import/newrecruit-wtc.js.map +1 -1
  77. package/dist/import/resolve.d.ts.map +1 -1
  78. package/dist/import/resolve.js +46 -18
  79. package/dist/import/resolve.js.map +1 -1
  80. package/dist/import/roster-json.d.ts +5 -3
  81. package/dist/import/roster-json.d.ts.map +1 -1
  82. package/dist/import/roster-json.js +8 -4
  83. package/dist/import/roster-json.js.map +1 -1
  84. package/dist/import/rosterizer.js +3 -3
  85. package/dist/import/rosterizer.js.map +1 -1
  86. package/dist/import/types.d.ts +15 -4
  87. package/dist/import/types.d.ts.map +1 -1
  88. package/dist/import/types.js.map +1 -1
  89. package/dist/index.d.ts +1 -0
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +4 -0
  92. package/dist/index.js.map +1 -1
  93. package/dist/merge-faction-pack.d.ts +2 -0
  94. package/dist/merge-faction-pack.d.ts.map +1 -0
  95. package/dist/merge-faction-pack.js +157 -0
  96. package/dist/merge-faction-pack.js.map +1 -0
  97. package/dist/pack-blocks.d.ts +32 -0
  98. package/dist/pack-blocks.d.ts.map +1 -0
  99. package/dist/pack-blocks.js +99 -0
  100. package/dist/pack-blocks.js.map +1 -0
  101. package/dist/rube-goldberg.js +1 -1
  102. package/dist/rube-goldberg.js.map +1 -1
  103. package/dist/runner.d.ts.map +1 -1
  104. package/dist/runner.js +33 -1
  105. package/dist/runner.js.map +1 -1
  106. package/dist/scope.d.ts +31 -0
  107. package/dist/scope.d.ts.map +1 -0
  108. package/dist/scope.js +34 -0
  109. package/dist/scope.js.map +1 -0
  110. package/dist/seed-detachment-abilities.d.ts +2 -0
  111. package/dist/seed-detachment-abilities.d.ts.map +1 -0
  112. package/dist/seed-detachment-abilities.js +137 -0
  113. package/dist/seed-detachment-abilities.js.map +1 -0
  114. package/dist/translate/effect.d.ts +17 -3
  115. package/dist/translate/effect.d.ts.map +1 -1
  116. package/dist/translate/effect.js +23 -4
  117. package/dist/translate/effect.js.map +1 -1
  118. package/dist/translate/index.d.ts +1 -1
  119. package/dist/translate/index.d.ts.map +1 -1
  120. package/dist/translate/index.js +1 -1
  121. package/dist/translate/index.js.map +1 -1
  122. package/dist/validate.d.ts.map +1 -1
  123. package/dist/validate.js +1 -0
  124. package/dist/validate.js.map +1 -1
  125. package/package.json +3 -1
  126. package/schemas/core/detachment.schema.json +6 -0
  127. package/schemas/core/hull-shape.schema.json +30 -0
  128. package/schemas/core/roster.schema.json +24 -8
  129. package/schemas/core/stratagem.schema.json +2 -2
  130. package/schemas/core/unit-composition.schema.json +7 -0
  131. package/schemas/enrichment/ability-dsl/ability.schema.json +14 -0
@@ -1 +1 @@
1
- {"version":3,"file":"convert-faction.js","sourceRoot":"","sources":["../src/convert-faction.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Generic faction converter: army-assist → 40kdc-data format.\n *\n * Usage: npx tsx tools/src/convert-faction.ts <faction-id>\n * Example: npx tsx tools/src/convert-faction.ts emperors-children\n *\n * Faction configs are registered via side-effect imports from ./converters/configs/.\n */\n\nimport { readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { resolve, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { nameToId, parseStratagemType, parsePlayerTurn, mapPhases } from \"./converters/id-generator.js\";\nimport { parseMove, parseTargetNumber, parseIntStat, parseInvuln } from \"./converters/stat-parser.js\";\nimport { findFactionViewIndex, getViewEntries, getPointsForView, splitIntoViews, type SourceAbility } from \"./converters/view-selector.js\";\nimport { buildWeaponRegistry, type SourceWargear } from \"./converters/weapon-dedup.js\";\nimport { buildWargearOptions } from \"./converters/wargear-options.js\";\nimport { getKeywordsForFaction, type SourceKeyword } from \"./converters/keyword-filter.js\";\nimport { type FactionConfig, getFactionConfig, listFactions } from \"./converters/faction-config.js\";\n\n// Register all faction configs\nimport \"./converters/configs/world-eaters.js\";\nimport \"./converters/configs/emperors-children.js\";\nimport \"./converters/configs/chaos-knights.js\";\nimport \"./converters/configs/imperial-knights.js\";\nimport \"./converters/configs/leagues-of-votann.js\";\nimport \"./converters/configs/drukhari.js\";\nimport \"./converters/configs/genestealer-cults.js\";\nimport \"./converters/configs/grey-knights.js\";\nimport \"./converters/configs/thousand-sons.js\";\nimport \"./converters/configs/death-guard.js\";\nimport \"./converters/configs/adeptus-custodes.js\";\nimport \"./converters/configs/adepta-sororitas.js\";\nimport \"./converters/configs/agents-of-the-imperium.js\";\nimport \"./converters/configs/adeptus-mechanicus.js\";\nimport \"./converters/configs/tau-empire.js\";\nimport \"./converters/configs/tyranids.js\";\nimport \"./converters/configs/necrons.js\";\nimport \"./converters/configs/chaos-daemons.js\";\nimport \"./converters/configs/orks.js\";\nimport \"./converters/configs/aeldari.js\";\nimport \"./converters/configs/chaos-space-marines.js\";\nimport \"./converters/configs/astra-militarum.js\";\nimport \"./converters/configs/adeptus-astartes.js\";\nimport \"./converters/configs/blood-angels.js\";\nimport \"./converters/configs/dark-angels.js\";\nimport \"./converters/configs/space-wolves.js\";\nimport \"./converters/configs/black-templars.js\";\nimport \"./converters/configs/deathwatch.js\";\nimport \"./converters/configs/ultramarines.js\";\nimport \"./converters/configs/imperial-fists.js\";\nimport \"./converters/configs/crimson-fists.js\";\nimport \"./converters/configs/iron-hands.js\";\nimport \"./converters/configs/raven-guard.js\";\nimport \"./converters/configs/salamanders.js\";\nimport \"./converters/configs/white-scars.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst ROOT = resolve(__dirname, \"../..\");\nconst SOURCE = resolve(process.env.HOME!, \"army-assist/src/assets/json\");\nconst GAME_VERSION = { edition: \"10th\", dataslate: \"2025-q3\" };\n\n// ─── Source data types ───────────────────────────────────────────────\n\ninterface SourceDatasheet {\n id: string;\n name: string;\n faction_id: string;\n loadout: string;\n transport: string;\n role: string;\n damaged_w: string;\n damaged_description: string;\n}\n\ninterface SourceModel {\n datasheet_id: string;\n line: string;\n name: string;\n M: string;\n T: string;\n Sv: string;\n inv_sv: string;\n inv_sv_descr: string;\n W: string;\n Ld: string;\n OC: string;\n base_size: string;\n base_size_descr: string;\n}\n\ninterface SourcePoints {\n datasheet_id: string;\n models: string;\n cost: string;\n}\n\ninterface SourceLeader {\n leader_id: string;\n attached_id: string;\n}\n\ninterface SourceEnhancement {\n id: string;\n name: string;\n faction_id: string;\n cost: string;\n detachment: string;\n phases: string[];\n}\n\ninterface SourceStratagem {\n id: string;\n name: string;\n faction_id: string;\n type: string;\n cp_cost: string;\n turn: string;\n phase: string;\n detachment: string;\n phases: string[];\n}\n\ninterface SourceDetachmentAbility {\n name: string;\n faction_id: string;\n detachment: string;\n phases: string[];\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────\n\nfunction readJSON<T>(filename: string): T {\n return JSON.parse(readFileSync(resolve(SOURCE, filename), \"utf-8\"));\n}\n\nfunction writeOutput(relPath: string, data: unknown): void {\n const outPath = resolve(ROOT, relPath);\n writeFileSync(outPath, JSON.stringify(data, null, 2) + \"\\n\");\n console.log(` ✓ ${relPath} (${Array.isArray(data) ? data.length : 1} entries)`);\n}\n\n/** Determine unit role from keywords and abilities. */\nfunction deriveRole(\n keywords: string[],\n abilities: SourceAbility[],\n name: string\n): string | undefined {\n const kw = new Set(keywords.map((k) => k.toLowerCase()));\n if (kw.has(\"epic hero\")) return \"epic-hero\";\n\n if (kw.has(\"character\")) return \"character\";\n const hasLeader = abilities.some(\n (a) => a.type === \"Core\" && a.name === \"Leader\"\n );\n if (hasLeader) return \"character\";\n\n if (kw.has(\"battleline\")) return \"battleline\";\n\n if (\n name.toLowerCase().includes(\"rhino\") ||\n kw.has(\"dedicated transport\")\n )\n return \"dedicated-transport\";\n\n return undefined;\n}\n\n/** Parse base size string. \"32mm\" → { shape: \"round\", diameter: 32 } */\nfunction parseBaseSize(\n s: string\n): { shape: string; diameter?: number; width?: number; length?: number } | undefined {\n if (!s || s.trim() === \"\") return undefined;\n const round = s.match(/(\\d+)\\s*mm/i);\n if (round) return { shape: \"round\", diameter: parseInt(round[1], 10) };\n const oval = s.match(/(\\d+)\\s*x\\s*(\\d+)/i);\n if (oval)\n return {\n shape: \"oval\",\n width: parseInt(oval[1], 10),\n length: parseInt(oval[2], 10),\n };\n return undefined;\n}\n\n/** Parse transport capacity from transport text. */\nfunction parseTransport(\n s: string\n): { capacity: number; keyword_restrictions?: string[]; exclusion_keywords?: string[] } | undefined {\n if (!s || s.trim() === \"\") return undefined;\n // Match \"capacity of N\" or \"N <FACTION> INFANTRY\"\n const capMatch = s.match(/capacity\\s*(?:of\\s*)?(\\d+)/i) || s.match(/(\\d+)\\s+\\S[\\S\\s]*?\\s+(?:infantry|model)/i);\n if (!capMatch) return undefined;\n const capacity = parseInt(capMatch[1], 10);\n const result: { capacity: number; keyword_restrictions?: string[]; exclusion_keywords?: string[] } = { capacity };\n\n if (/jump pack/i.test(s) && /cannot/i.test(s)) {\n result.exclusion_keywords = [\"Jump Pack\"];\n }\n return result;\n}\n\n// ─── Main conversion ─────────────────────────────────────────────────\n\nexport function convertFaction(\n config: FactionConfig,\n options: { wargearOnly?: boolean } = {},\n): void {\n const { sourceFactionId, factionId, factionName, factionAbilityName } = config;\n\n console.log(`Converting ${factionName} (${sourceFactionId} → ${factionId})...`);\n console.log(\"Loading source data from army-assist...\");\n\n const datasheets = readJSON<SourceDatasheet[]>(\"Datasheets.json\");\n const allModels = readJSON<SourceModel[]>(\"Datasheets_models.json\");\n const allWargear = readJSON<SourceWargear[]>(\"Datasheets_wargear.json\");\n const allOptions = readJSON<\n { datasheet_id: string; line: string; description: string | null }[]\n >(\"Datasheets_options.json\");\n const allComposition = readJSON<\n { datasheet_id: string; line: string; description: string }[]\n >(\"Datasheets_unit_composition.json\");\n const allAbilities = readJSON<SourceAbility[]>(\"Datasheets_abilities.json\");\n const allKeywords = readJSON<SourceKeyword[]>(\"Datasheets_keywords.json\");\n const allPoints = readJSON<SourcePoints[]>(\"Datasheets_points.json\");\n const allLeaders = readJSON<SourceLeader[]>(\"Datasheets_leader.json\");\n const enhancements = readJSON<SourceEnhancement[]>(\"Enhancements.json\");\n const stratagems = readJSON<SourceStratagem[]>(\"Stratagems.json\");\n const detachmentAbilities = readJSON<SourceDetachmentAbility[]>(\n \"Detachment_abilities.json\"\n );\n\n // Filter to target faction, skip datasheets with no model data (metadata entries)\n const modelDatasheetIds = new Set(allModels.map((m) => m.datasheet_id));\n const factionDatasheets = datasheets.filter(\n (d) => d.faction_id === sourceFactionId && modelDatasheetIds.has(d.id)\n );\n const factionIds = new Set(factionDatasheets.map((d) => d.id));\n const idToName = new Map(factionDatasheets.map((d) => [d.id, d.name]));\n\n console.log(`Found ${factionDatasheets.length} ${factionName} datasheets\\n`);\n\n // ─── Determine view indices for shared units ───\n const viewIndices = new Map<string, number>();\n for (const ds of factionDatasheets) {\n const dsAbilities = allAbilities.filter(\n (a) => a.datasheet_id === ds.id\n );\n viewIndices.set(ds.id, findFactionViewIndex(dsAbilities, factionAbilityName));\n }\n\n // ─── Build units ───\n console.log(\"Converting units...\");\n const units: Record<string, unknown>[] = [];\n\n const unitWargearMap = new Map<string, SourceWargear[]>();\n const unitAbilityNames = new Map<string, string[]>();\n\n for (const ds of factionDatasheets) {\n const viewIdx = viewIndices.get(ds.id)!;\n\n // Models\n const dsModels = allModels.filter((m) => m.datasheet_id === ds.id);\n const viewModels = getViewEntries(dsModels, viewIdx);\n\n // Abilities (for role derivation and ability name collection)\n const dsAbilities = allAbilities.filter(\n (a) => a.datasheet_id === ds.id\n );\n const viewAbilities = getViewEntries(dsAbilities, viewIdx);\n\n const abilityNames = viewAbilities\n .filter((a) => a.type !== \"Faction\")\n .map((a) => a.name);\n unitAbilityNames.set(ds.id, [...new Set(abilityNames)]);\n\n // Keywords — use faction-aware filtering for shared units\n const dsKeywords = allKeywords.filter(\n (k) => k.datasheet_id === ds.id\n );\n const { factionKeywords, regularKeywords } = getKeywordsForFaction(\n dsKeywords,\n factionName\n );\n\n // Points — select the correct view for shared units\n const allDsPoints = allPoints.filter((p) => p.datasheet_id === ds.id);\n const dsAbilityViews = splitIntoViews(\n allAbilities.filter((a) => a.datasheet_id === ds.id)\n );\n const numViews = dsAbilityViews.length;\n const viewPoints = getPointsForView(allDsPoints, viewIdx, numViews);\n const dsPoints = viewPoints\n .map((p) => ({\n models: parseInt(p.models, 10),\n cost: parseInt(p.cost, 10),\n }))\n .sort((a, b) => a.models - b.models);\n\n // Wargear for this unit's view\n const dsWargear = allWargear.filter(\n (w) => w.datasheet_id === ds.id\n );\n const viewWargear = getViewEntries(dsWargear, viewIdx);\n unitWargearMap.set(ds.id, viewWargear);\n\n // Build stat profiles\n const profiles = viewModels.map((m) => {\n const profile: Record<string, unknown> = {\n name: m.name,\n M: parseMove(m.M),\n T: parseIntStat(m.T),\n W: parseIntStat(m.W),\n Sv: parseTargetNumber(m.Sv)!,\n invuln_sv: parseInvuln(m.inv_sv),\n Ld: parseTargetNumber(m.Ld)!,\n OC: parseIntStat(m.OC),\n };\n return profile;\n });\n\n const role = deriveRole(regularKeywords, viewAbilities, ds.name);\n const baseSize = parseBaseSize(\n viewModels[0]?.base_size ?? \"\"\n );\n const transport = parseTransport(ds.transport);\n\n const modelMin = dsPoints.length > 0 ? dsPoints[0].models : 1;\n const modelMax =\n dsPoints.length > 0 ? dsPoints[dsPoints.length - 1].models : 1;\n\n const unitId = nameToId(ds.name);\n const unit: Record<string, unknown> = {\n id: unitId,\n name: ds.name,\n faction_id: factionId,\n ...(role ? { role } : {}),\n profiles,\n points: dsPoints,\n keywords: regularKeywords,\n faction_keywords: factionKeywords,\n ...(baseSize ? { base_size_mm: baseSize } : {}),\n model_count: { min: modelMin, max: modelMax },\n weapon_ids: [],\n ability_ids: [],\n ...(transport ? { transport_capacity: transport } : {}),\n game_version: GAME_VERSION,\n is_legend: false,\n };\n\n units.push(unit);\n }\n\n // ─── Build weapons ───\n console.log(\"Converting weapons...\");\n const { weapons, unitWeaponIds } = buildWeaponRegistry(\n unitWargearMap,\n GAME_VERSION\n );\n\n // Wire weapon_ids into units\n for (const unit of units) {\n const dsId = factionDatasheets.find((d) => d.name === (unit as { name: string }).name)!.id;\n const weaponIds = unitWeaponIds.get(dsId);\n if (weaponIds) {\n (unit as { weapon_ids: string[] }).weapon_ids = [...weaponIds].sort();\n }\n }\n\n // ─── Build wargear options + non-weapon wargear ───\n console.log(\"Converting wargear options...\");\n const globalWeaponIds = new Set(weapons.map((w) => w.id));\n const {\n wargearOptions,\n wargear: wargearItems,\n unparsed: unparsedOptions,\n } = buildWargearOptions(\n factionDatasheets.map((d) => ({ id: d.id, name: d.name })),\n allModels,\n allOptions,\n allComposition,\n unitWeaponIds,\n globalWeaponIds,\n GAME_VERSION\n );\n\n // ─── Build leader attachments ───\n console.log(\"Converting leader attachments...\");\n const leaderMap = new Map<string, Set<string>>();\n\n for (const l of allLeaders) {\n if (factionIds.has(l.leader_id) && factionIds.has(l.attached_id)) {\n const leaderId = nameToId(idToName.get(l.leader_id)!);\n const attachedId = nameToId(idToName.get(l.attached_id)!);\n if (!leaderMap.has(leaderId)) {\n leaderMap.set(leaderId, new Set());\n }\n leaderMap.get(leaderId)!.add(attachedId);\n }\n }\n\n const leaderAttachments = [...leaderMap.entries()].map(\n ([leaderId, bodyguards]) => ({\n leader_id: leaderId,\n eligible_bodyguard_ids: [...bodyguards].sort(),\n max_leaders_per_unit: 1,\n game_version: GAME_VERSION,\n })\n );\n // ─── Build detachments ───\n console.log(\"Converting detachments...\");\n const factionDetAbilities = detachmentAbilities.filter(\n (d) => d.faction_id === sourceFactionId\n );\n let factionEnhancements = enhancements.filter(\n (e) => e.faction_id === sourceFactionId\n );\n let factionStratagems = stratagems.filter(\n (s) => s.faction_id === sourceFactionId\n );\n\n // Deduplicate detachments (some have multiple ability entries per detachment)\n let detachmentNames = [...new Set(factionDetAbilities.map((da) => da.detachment))];\n\n // Apply detachment filter for subfactions\n if (config.detachmentFilter) {\n detachmentNames = detachmentNames.filter((d) =>\n config.detachmentFilter!.includes(d)\n );\n // Also filter enhancements and stratagems to matching detachments\n const allowedDetachments = new Set(config.detachmentFilter);\n factionEnhancements = factionEnhancements.filter((e) => allowedDetachments.has(e.detachment));\n factionStratagems = factionStratagems.filter((s) => allowedDetachments.has(s.detachment));\n }\n\n const detachments = detachmentNames.map((detName) => {\n const detId = nameToId(detName);\n const detEnhIds = factionEnhancements\n .filter((e) => e.detachment === detName)\n .map((e) => nameToId(e.name));\n const detStratIds = factionStratagems\n .filter((s) => s.detachment === detName)\n .map((s) => nameToId(s.name));\n\n return {\n id: detId,\n name: detName,\n faction_id: factionId,\n detachment_rule_id: null as string | null,\n enhancement_ids: detEnhIds,\n stratagem_ids: detStratIds,\n game_version: GAME_VERSION,\n };\n });\n\n // ─── Build enhancements ───\n console.log(\"Converting enhancements...\");\n const enhancementEntities = factionEnhancements.map((e) => ({\n id: nameToId(e.name),\n name: e.name,\n detachment_id: nameToId(e.detachment),\n cost: parseInt(e.cost, 10),\n keyword_restrictions: [factionName],\n ability_id: null as string | null,\n is_unique: true,\n game_version: GAME_VERSION,\n }));\n\n // ─── Build stratagems ───\n console.log(\"Converting stratagems...\");\n const stratagemEntities = factionStratagems.map((s) => {\n const { type } = parseStratagemType(s.type);\n const phases = mapPhases(s.phases);\n const playerTurn = parsePlayerTurn(s.turn);\n\n return {\n id: nameToId(s.name),\n name: s.name,\n category: \"detachment\" as const,\n type,\n detachment_id: nameToId(s.detachment),\n cp_cost: parseInt(s.cp_cost, 10),\n phases,\n player_turn: playerTurn,\n timing: \"once-per-phase\" as const,\n target_restrictions: null as null,\n ability_id: null as string | null,\n game_version: GAME_VERSION,\n };\n });\n\n // ─── Build phase mappings from source ability phases ───\n console.log(\"Converting phase mappings...\");\n const phaseMappings: Record<string, unknown>[] = [];\n\n // Unit abilities\n for (const ds of factionDatasheets) {\n const viewIdx = viewIndices.get(ds.id)!;\n const dsAbilities = allAbilities.filter(\n (a) => a.datasheet_id === ds.id\n );\n const viewAbilities = getViewEntries(dsAbilities, viewIdx);\n const seen = new Set<string>();\n\n for (const a of viewAbilities) {\n if (a.type === \"Faction\") continue;\n const sourceId = nameToId(a.name);\n if (seen.has(sourceId)) continue;\n seen.add(sourceId);\n\n const sourceType =\n a.type === \"Core\" ? \"ability\" :\n a.type === \"Wargear\" ? \"ability\" :\n \"ability\";\n\n const phases = mapPhases(a.phases);\n if (phases.length > 0) {\n phaseMappings.push({\n source_id: sourceId,\n source_type: sourceType,\n phases,\n game_version: GAME_VERSION,\n authored_by: \"40kdc-community\",\n });\n }\n }\n }\n\n // Stratagem phase mappings\n for (const s of factionStratagems) {\n const phases = mapPhases(s.phases);\n if (phases.length > 0) {\n phaseMappings.push({\n source_id: nameToId(s.name),\n source_type: \"stratagem\",\n phases,\n game_version: GAME_VERSION,\n authored_by: \"40kdc-community\",\n });\n }\n }\n\n // Enhancement phase mappings\n for (const e of factionEnhancements) {\n const phases = mapPhases(e.phases);\n if (phases.length > 0) {\n phaseMappings.push({\n source_id: nameToId(e.name),\n source_type: \"enhancement\",\n phases,\n game_version: GAME_VERSION,\n authored_by: \"40kdc-community\",\n });\n }\n }\n\n // Detachment rule phase mappings\n for (const da of factionDetAbilities) {\n const phases = mapPhases(da.phases);\n if (phases.length > 0) {\n phaseMappings.push({\n source_id: nameToId(da.name),\n source_type: \"detachment-rule\",\n phases,\n game_version: GAME_VERSION,\n authored_by: \"40kdc-community\",\n });\n }\n }\n\n // Deduplicate phase mappings\n const dedupedPhaseMappings = [\n ...new Map(\n phaseMappings.map((pm) => [\n `${(pm as { source_id: string }).source_id}|${(pm as { source_type: string }).source_type}`,\n pm,\n ])\n ).values(),\n ];\n\n // ─── Build unit compositions ───\n console.log(\"Generating unit compositions...\");\n\n const unitCompositions = units.map((u) => {\n const unitId = (u as { id: string }).id;\n const modelCount = (u as { model_count: { min: number; max: number } }).model_count;\n\n const override = config.compositionOverrides[unitId];\n if (override) {\n return {\n unit_id: unitId,\n models: override,\n game_version: GAME_VERSION,\n };\n }\n\n // Single-model unit (vehicles, characters, monsters)\n const profileName = (u as { profiles: { name: string }[] }).profiles[0]?.name;\n return {\n unit_id: unitId,\n models: [\n {\n name: profileName || (u as { name: string }).name,\n min: modelCount.min,\n max: modelCount.max,\n is_leader_model: false,\n },\n ],\n game_version: GAME_VERSION,\n };\n });\n\n // ─── Generate factions.json ───\n const factionEntity = [\n {\n id: factionId,\n name: factionName,\n parent_faction_id: config.parentFactionId,\n game_version: GAME_VERSION,\n keywords: config.factionKeywords,\n aliases: config.aliases,\n faction_rule_id: config.factionRuleId,\n },\n ];\n\n // ─── Write output ──────────────────────────────────────────────────\n const coreDir = `data/core/${factionId}`;\n const enrichDir = `data/enrichment/${factionId}`;\n mkdirSync(resolve(ROOT, coreDir), { recursive: true });\n mkdirSync(resolve(ROOT, enrichDir), { recursive: true });\n\n console.log(\"\\nWriting output files...\");\n\n // `wargearOnly` adds just the wargear data: the rest of the converter's output\n // has drifted from the committed dataset (e.g. weapon keywords are object refs\n // there, strings here), so a full rewrite would regress those files. Adding\n // wargear must not touch them.\n if (!options.wargearOnly) {\n writeOutput(`${coreDir}/factions.json`, factionEntity);\n }\n if (!config.skipUnits) {\n if (!options.wargearOnly) {\n writeOutput(`${coreDir}/units.json`, units);\n writeOutput(`${coreDir}/weapons.json`, weapons);\n writeOutput(`${coreDir}/leader-attachments.json`, leaderAttachments);\n writeOutput(`${coreDir}/unit-compositions.json`, unitCompositions);\n }\n writeOutput(`${coreDir}/wargear-options.json`, wargearOptions);\n if (wargearItems.length > 0) {\n writeOutput(`${coreDir}/wargear.json`, wargearItems);\n }\n if (unparsedOptions.length > 0) {\n // Underscore-prefixed: a report for manual review, skipped by validation\n // and not bundled into the dataset.\n writeOutput(`${coreDir}/_wargear-options.unparsed.json`, unparsedOptions);\n }\n }\n if (!options.wargearOnly) {\n writeOutput(`${coreDir}/detachments.json`, detachments);\n writeOutput(`${coreDir}/enhancements.json`, enhancementEntities);\n writeOutput(`${coreDir}/stratagems.json`, stratagemEntities);\n if (!config.skipUnits) {\n writeOutput(`${enrichDir}/phase-mappings.json`, dedupedPhaseMappings);\n }\n }\n\n // ─── Summary ───\n console.log(`\\n── ${factionName} Summary ──`);\n if (!config.skipUnits) {\n console.log(` Units: ${units.length}`);\n console.log(` Weapons: ${weapons.length}`);\n console.log(` Leader attachments: ${leaderAttachments.length}`);\n console.log(` Unit compositions: ${unitCompositions.length}`);\n console.log(` Wargear options: ${wargearOptions.length}`);\n console.log(` Wargear items: ${wargearItems.length}`);\n console.log(` Unparsed options: ${unparsedOptions.length}`);\n }\n console.log(` Detachments: ${detachments.length}`);\n console.log(` Enhancements: ${enhancementEntities.length}`);\n console.log(` Stratagems: ${stratagemEntities.length}`);\n if (!config.skipUnits) {\n console.log(` Phase mappings: ${dedupedPhaseMappings.length}`);\n }\n console.log(\"\\nDone. Run 'npm run validate' to check output.\");\n}\n\n// ─── CLI entry point ─────────────────────────────────────────────────\n\n// Only run CLI when this module is the entry point (not when imported)\nconst isMain = process.argv[1] &&\n resolve(process.argv[1]).replace(/\\.\\w+$/, \"\") ===\n fileURLToPath(import.meta.url).replace(/\\.\\w+$/, \"\");\n\nif (isMain) {\n const args = process.argv.slice(2);\n const wargearOnly = args.includes(\"--wargear-only\");\n const positional = args.filter((a) => !a.startsWith(\"--\"));\n\n if (positional.length === 0 || args[0] === \"--help\") {\n console.log(\n \"Usage: npx tsx tools/src/convert-faction.ts <faction-id|all> [--wargear-only]\",\n );\n console.log(`Available factions: ${listFactions().join(\", \")}`);\n process.exit(args[0] === \"--help\" ? 0 : 1);\n }\n\n const target = positional[0];\n const factionIds = target === \"all\" ? listFactions() : [target];\n for (const id of factionIds) {\n convertFaction(getFactionConfig(id), { wargearOnly });\n }\n}\n"]}
1
+ {"version":3,"file":"convert-faction.js","sourceRoot":"","sources":["../src/convert-faction.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Generic faction converter: army-assist → 40kdc-data format.\n *\n * Usage: npx tsx tools/src/convert-faction.ts <faction-id>\n * Example: npx tsx tools/src/convert-faction.ts emperors-children\n *\n * Faction configs are registered via side-effect imports from ./converters/configs/.\n */\n\nimport { readFileSync, writeFileSync, mkdirSync, existsSync } from \"node:fs\";\nimport { resolve, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { nameToId, parseStratagemType, parsePlayerTurn, mapPhases } from \"./converters/id-generator.js\";\nimport { parseMove, parseTargetNumber, parseIntStat, parseInvuln } from \"./converters/stat-parser.js\";\nimport { findFactionViewIndex, getViewEntries, getPointsForView, splitIntoViews, type SourceAbility } from \"./converters/view-selector.js\";\nimport { buildWeaponRegistry, type SourceWargear } from \"./converters/weapon-dedup.js\";\nimport { buildWargearOptions } from \"./converters/wargear-options.js\";\nimport { getKeywordsForFaction, type SourceKeyword } from \"./converters/keyword-filter.js\";\nimport { type FactionConfig, getFactionConfig, listFactions } from \"./converters/faction-config.js\";\n\n// Register all faction configs\nimport \"./converters/configs/world-eaters.js\";\nimport \"./converters/configs/emperors-children.js\";\nimport \"./converters/configs/chaos-knights.js\";\nimport \"./converters/configs/imperial-knights.js\";\nimport \"./converters/configs/leagues-of-votann.js\";\nimport \"./converters/configs/drukhari.js\";\nimport \"./converters/configs/genestealer-cults.js\";\nimport \"./converters/configs/grey-knights.js\";\nimport \"./converters/configs/thousand-sons.js\";\nimport \"./converters/configs/death-guard.js\";\nimport \"./converters/configs/adeptus-custodes.js\";\nimport \"./converters/configs/adepta-sororitas.js\";\nimport \"./converters/configs/agents-of-the-imperium.js\";\nimport \"./converters/configs/adeptus-mechanicus.js\";\nimport \"./converters/configs/tau-empire.js\";\nimport \"./converters/configs/tyranids.js\";\nimport \"./converters/configs/necrons.js\";\nimport \"./converters/configs/chaos-daemons.js\";\nimport \"./converters/configs/orks.js\";\nimport \"./converters/configs/aeldari.js\";\nimport \"./converters/configs/chaos-space-marines.js\";\nimport \"./converters/configs/astra-militarum.js\";\nimport \"./converters/configs/adeptus-astartes.js\";\nimport \"./converters/configs/blood-angels.js\";\nimport \"./converters/configs/dark-angels.js\";\nimport \"./converters/configs/space-wolves.js\";\nimport \"./converters/configs/black-templars.js\";\nimport \"./converters/configs/deathwatch.js\";\nimport \"./converters/configs/ultramarines.js\";\nimport \"./converters/configs/imperial-fists.js\";\nimport \"./converters/configs/crimson-fists.js\";\nimport \"./converters/configs/iron-hands.js\";\nimport \"./converters/configs/raven-guard.js\";\nimport \"./converters/configs/salamanders.js\";\nimport \"./converters/configs/white-scars.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst ROOT = resolve(__dirname, \"../..\");\nconst SOURCE = resolve(process.env.HOME!, \"army-assist/src/assets/json\");\nconst GAME_VERSION = { edition: \"10th\", dataslate: \"2025-q3\" };\n\n// ─── Source data types ───────────────────────────────────────────────\n\ninterface SourceDatasheet {\n id: string;\n name: string;\n faction_id: string;\n loadout: string;\n transport: string;\n role: string;\n damaged_w: string;\n damaged_description: string;\n}\n\ninterface SourceModel {\n datasheet_id: string;\n line: string;\n name: string;\n M: string;\n T: string;\n Sv: string;\n inv_sv: string;\n inv_sv_descr: string;\n W: string;\n Ld: string;\n OC: string;\n base_size: string;\n base_size_descr: string;\n}\n\ninterface SourcePoints {\n datasheet_id: string;\n models: string;\n cost: string;\n}\n\ninterface SourceLeader {\n leader_id: string;\n attached_id: string;\n}\n\ninterface SourceEnhancement {\n id: string;\n name: string;\n faction_id: string;\n cost: string;\n detachment: string;\n phases: string[];\n}\n\ninterface SourceStratagem {\n id: string;\n name: string;\n faction_id: string;\n type: string;\n cp_cost: string;\n turn: string;\n phase: string;\n detachment: string;\n phases: string[];\n}\n\ninterface SourceDetachmentAbility {\n name: string;\n faction_id: string;\n detachment: string;\n phases: string[];\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────\n\nfunction readJSON<T>(filename: string): T {\n return JSON.parse(readFileSync(resolve(SOURCE, filename), \"utf-8\"));\n}\n\nfunction writeOutput(relPath: string, data: unknown): void {\n const outPath = resolve(ROOT, relPath);\n writeFileSync(outPath, JSON.stringify(data, null, 2) + \"\\n\");\n console.log(` ✓ ${relPath} (${Array.isArray(data) ? data.length : 1} entries)`);\n}\n\n/** Determine unit role from keywords and abilities. */\nfunction deriveRole(\n keywords: string[],\n abilities: SourceAbility[],\n name: string\n): string | undefined {\n const kw = new Set(keywords.map((k) => k.toLowerCase()));\n if (kw.has(\"epic hero\")) return \"epic-hero\";\n\n if (kw.has(\"character\")) return \"character\";\n const hasLeader = abilities.some(\n (a) => a.type === \"Core\" && a.name === \"Leader\"\n );\n if (hasLeader) return \"character\";\n\n if (kw.has(\"battleline\")) return \"battleline\";\n\n if (\n name.toLowerCase().includes(\"rhino\") ||\n kw.has(\"dedicated transport\")\n )\n return \"dedicated-transport\";\n\n return undefined;\n}\n\n/** Parse base size string. \"32mm\" → { shape: \"round\", diameter: 32 } */\nfunction parseBaseSize(\n s: string\n): { shape: string; diameter?: number; width?: number; length?: number } | undefined {\n if (!s || s.trim() === \"\") return undefined;\n const round = s.match(/(\\d+)\\s*mm/i);\n if (round) return { shape: \"round\", diameter: parseInt(round[1], 10) };\n const oval = s.match(/(\\d+)\\s*x\\s*(\\d+)/i);\n if (oval)\n return {\n shape: \"oval\",\n width: parseInt(oval[1], 10),\n length: parseInt(oval[2], 10),\n };\n return undefined;\n}\n\n/** Parse transport capacity from transport text. */\nfunction parseTransport(\n s: string\n): { capacity: number; keyword_restrictions?: string[]; exclusion_keywords?: string[] } | undefined {\n if (!s || s.trim() === \"\") return undefined;\n // Match \"capacity of N\" or \"N <FACTION> INFANTRY\"\n const capMatch = s.match(/capacity\\s*(?:of\\s*)?(\\d+)/i) || s.match(/(\\d+)\\s+\\S[\\S\\s]*?\\s+(?:infantry|model)/i);\n if (!capMatch) return undefined;\n const capacity = parseInt(capMatch[1], 10);\n const result: { capacity: number; keyword_restrictions?: string[]; exclusion_keywords?: string[] } = { capacity };\n\n if (/jump pack/i.test(s) && /cannot/i.test(s)) {\n result.exclusion_keywords = [\"Jump Pack\"];\n }\n return result;\n}\n\n// ─── Main conversion ─────────────────────────────────────────────────\n\nexport function convertFaction(\n config: FactionConfig,\n options: { wargearOnly?: boolean } = {},\n): void {\n const { sourceFactionId, factionId, factionName, factionAbilityName } = config;\n\n console.log(`Converting ${factionName} (${sourceFactionId} → ${factionId})...`);\n console.log(\"Loading source data from army-assist...\");\n\n const datasheets = readJSON<SourceDatasheet[]>(\"Datasheets.json\");\n const allModels = readJSON<SourceModel[]>(\"Datasheets_models.json\");\n const allWargear = readJSON<SourceWargear[]>(\"Datasheets_wargear.json\");\n const allOptions = readJSON<\n { datasheet_id: string; line: string; description: string | null }[]\n >(\"Datasheets_options.json\");\n const allComposition = readJSON<\n { datasheet_id: string; line: string; description: string }[]\n >(\"Datasheets_unit_composition.json\");\n const allAbilities = readJSON<SourceAbility[]>(\"Datasheets_abilities.json\");\n const allKeywords = readJSON<SourceKeyword[]>(\"Datasheets_keywords.json\");\n const allPoints = readJSON<SourcePoints[]>(\"Datasheets_points.json\");\n const allLeaders = readJSON<SourceLeader[]>(\"Datasheets_leader.json\");\n const enhancements = readJSON<SourceEnhancement[]>(\"Enhancements.json\");\n const stratagems = readJSON<SourceStratagem[]>(\"Stratagems.json\");\n const detachmentAbilities = readJSON<SourceDetachmentAbility[]>(\n \"Detachment_abilities.json\"\n );\n\n // Filter to target faction, skip datasheets with no model data (metadata entries)\n const modelDatasheetIds = new Set(allModels.map((m) => m.datasheet_id));\n const factionDatasheets = datasheets.filter(\n (d) => d.faction_id === sourceFactionId && modelDatasheetIds.has(d.id)\n );\n const factionIds = new Set(factionDatasheets.map((d) => d.id));\n const idToName = new Map(factionDatasheets.map((d) => [d.id, d.name]));\n\n console.log(`Found ${factionDatasheets.length} ${factionName} datasheets\\n`);\n\n // ─── Determine view indices for shared units ───\n const viewIndices = new Map<string, number>();\n for (const ds of factionDatasheets) {\n const dsAbilities = allAbilities.filter(\n (a) => a.datasheet_id === ds.id\n );\n viewIndices.set(ds.id, findFactionViewIndex(dsAbilities, factionAbilityName));\n }\n\n // ─── Build units ───\n console.log(\"Converting units...\");\n const units: Record<string, unknown>[] = [];\n\n const unitWargearMap = new Map<string, SourceWargear[]>();\n const unitAbilityNames = new Map<string, string[]>();\n\n for (const ds of factionDatasheets) {\n const viewIdx = viewIndices.get(ds.id)!;\n\n // Models\n const dsModels = allModels.filter((m) => m.datasheet_id === ds.id);\n const viewModels = getViewEntries(dsModels, viewIdx);\n\n // Abilities (for role derivation and ability name collection)\n const dsAbilities = allAbilities.filter(\n (a) => a.datasheet_id === ds.id\n );\n const viewAbilities = getViewEntries(dsAbilities, viewIdx);\n\n const abilityNames = viewAbilities\n .filter((a) => a.type !== \"Faction\")\n .map((a) => a.name);\n unitAbilityNames.set(ds.id, [...new Set(abilityNames)]);\n\n // Keywords — use faction-aware filtering for shared units\n const dsKeywords = allKeywords.filter(\n (k) => k.datasheet_id === ds.id\n );\n const { factionKeywords, regularKeywords } = getKeywordsForFaction(\n dsKeywords,\n factionName\n );\n\n // Points — select the correct view for shared units\n const allDsPoints = allPoints.filter((p) => p.datasheet_id === ds.id);\n const dsAbilityViews = splitIntoViews(\n allAbilities.filter((a) => a.datasheet_id === ds.id)\n );\n const numViews = dsAbilityViews.length;\n const viewPoints = getPointsForView(allDsPoints, viewIdx, numViews);\n const dsPoints = viewPoints\n .map((p) => ({\n models: parseInt(p.models, 10),\n cost: parseInt(p.cost, 10),\n }))\n .sort((a, b) => a.models - b.models);\n\n // Wargear for this unit's view\n const dsWargear = allWargear.filter(\n (w) => w.datasheet_id === ds.id\n );\n const viewWargear = getViewEntries(dsWargear, viewIdx);\n unitWargearMap.set(ds.id, viewWargear);\n\n // Build stat profiles\n const profiles = viewModels.map((m) => {\n const profile: Record<string, unknown> = {\n name: m.name,\n M: parseMove(m.M),\n T: parseIntStat(m.T),\n W: parseIntStat(m.W),\n Sv: parseTargetNumber(m.Sv)!,\n invuln_sv: parseInvuln(m.inv_sv),\n Ld: parseTargetNumber(m.Ld)!,\n OC: parseIntStat(m.OC),\n };\n return profile;\n });\n\n const role = deriveRole(regularKeywords, viewAbilities, ds.name);\n const baseSize = parseBaseSize(\n viewModels[0]?.base_size ?? \"\"\n );\n const transport = parseTransport(ds.transport);\n\n const modelMin = dsPoints.length > 0 ? dsPoints[0].models : 1;\n const modelMax =\n dsPoints.length > 0 ? dsPoints[dsPoints.length - 1].models : 1;\n\n const unitId = nameToId(ds.name);\n const unit: Record<string, unknown> = {\n id: unitId,\n name: ds.name,\n faction_id: factionId,\n ...(role ? { role } : {}),\n profiles,\n points: dsPoints,\n keywords: regularKeywords,\n faction_keywords: factionKeywords,\n ...(baseSize ? { base_size_mm: baseSize } : {}),\n model_count: { min: modelMin, max: modelMax },\n weapon_ids: [],\n ability_ids: [],\n ...(transport ? { transport_capacity: transport } : {}),\n game_version: GAME_VERSION,\n is_legend: false,\n };\n\n units.push(unit);\n }\n\n // ─── Build weapons ───\n console.log(\"Converting weapons...\");\n const { weapons, unitWeaponIds } = buildWeaponRegistry(\n unitWargearMap,\n GAME_VERSION\n );\n\n // Wire weapon_ids into units\n for (const unit of units) {\n const dsId = factionDatasheets.find((d) => d.name === (unit as { name: string }).name)!.id;\n const weaponIds = unitWeaponIds.get(dsId);\n if (weaponIds) {\n (unit as { weapon_ids: string[] }).weapon_ids = [...weaponIds].sort();\n }\n }\n\n // ─── Build wargear options + non-weapon wargear ───\n console.log(\"Converting wargear options...\");\n const globalWeaponIds = new Set(weapons.map((w) => w.id));\n const {\n wargearOptions,\n wargear: wargearItems,\n unparsed: unparsedOptions,\n } = buildWargearOptions(\n factionDatasheets.map((d) => ({ id: d.id, name: d.name })),\n allModels,\n allOptions,\n allComposition,\n unitWeaponIds,\n globalWeaponIds,\n GAME_VERSION\n );\n\n // ─── Build leader attachments ───\n console.log(\"Converting leader attachments...\");\n const leaderMap = new Map<string, Set<string>>();\n\n for (const l of allLeaders) {\n if (factionIds.has(l.leader_id) && factionIds.has(l.attached_id)) {\n const leaderId = nameToId(idToName.get(l.leader_id)!);\n const attachedId = nameToId(idToName.get(l.attached_id)!);\n if (!leaderMap.has(leaderId)) {\n leaderMap.set(leaderId, new Set());\n }\n leaderMap.get(leaderId)!.add(attachedId);\n }\n }\n\n const leaderAttachments = [...leaderMap.entries()].map(\n ([leaderId, bodyguards]) => ({\n leader_id: leaderId,\n eligible_bodyguard_ids: [...bodyguards].sort(),\n max_leaders_per_unit: 1,\n game_version: GAME_VERSION,\n })\n );\n // ─── Build detachments ───\n console.log(\"Converting detachments...\");\n const factionDetAbilities = detachmentAbilities.filter(\n (d) => d.faction_id === sourceFactionId\n );\n let factionEnhancements = enhancements.filter(\n (e) => e.faction_id === sourceFactionId\n );\n let factionStratagems = stratagems.filter(\n (s) => s.faction_id === sourceFactionId\n );\n\n // Deduplicate detachments (some have multiple ability entries per detachment)\n let detachmentNames = [...new Set(factionDetAbilities.map((da) => da.detachment))];\n\n // Apply detachment filter for subfactions\n if (config.detachmentFilter) {\n detachmentNames = detachmentNames.filter((d) =>\n config.detachmentFilter!.includes(d)\n );\n // Also filter enhancements and stratagems to matching detachments\n const allowedDetachments = new Set(config.detachmentFilter);\n factionEnhancements = factionEnhancements.filter((e) => allowedDetachments.has(e.detachment));\n factionStratagems = factionStratagems.filter((s) => allowedDetachments.has(s.detachment));\n }\n\n // `detachment_points` (11e DP cost) and `force_dispositions` are maintained\n // by hand — army-assist doesn't carry them — so a re-run must NOT drop them.\n // Carry both forward by id from the existing on-disk file.\n const existingDetPath = resolve(ROOT, `data/core/${factionId}/detachments.json`);\n const preservedById = new Map<string, Record<string, unknown>>();\n if (existsSync(existingDetPath)) {\n const existing = JSON.parse(readFileSync(existingDetPath, \"utf-8\")) as Array<\n Record<string, unknown>\n >;\n for (const d of existing) {\n if (typeof d.id === \"string\") preservedById.set(d.id, d);\n }\n }\n\n const detachments = detachmentNames.map((detName) => {\n const detId = nameToId(detName);\n const detEnhIds = factionEnhancements\n .filter((e) => e.detachment === detName)\n .map((e) => nameToId(e.name));\n const detStratIds = factionStratagems\n .filter((s) => s.detachment === detName)\n .map((s) => nameToId(s.name));\n\n const record: Record<string, unknown> = {\n id: detId,\n name: detName,\n faction_id: factionId,\n detachment_rule_id: null as string | null,\n enhancement_ids: detEnhIds,\n stratagem_ids: detStratIds,\n game_version: GAME_VERSION,\n };\n const preserved = preservedById.get(detId);\n if (preserved && \"detachment_points\" in preserved) {\n record.detachment_points = preserved.detachment_points;\n }\n if (preserved && \"force_dispositions\" in preserved) {\n record.force_dispositions = preserved.force_dispositions;\n }\n return record;\n });\n\n // ─── Build enhancements ───\n console.log(\"Converting enhancements...\");\n const enhancementEntities = factionEnhancements.map((e) => ({\n id: nameToId(e.name),\n name: e.name,\n detachment_id: nameToId(e.detachment),\n cost: parseInt(e.cost, 10),\n keyword_restrictions: [factionName],\n ability_id: null as string | null,\n is_unique: true,\n game_version: GAME_VERSION,\n }));\n\n // ─── Build stratagems ───\n console.log(\"Converting stratagems...\");\n const stratagemEntities = factionStratagems.map((s) => {\n const { type } = parseStratagemType(s.type);\n const phases = mapPhases(s.phases);\n const playerTurn = parsePlayerTurn(s.turn);\n\n return {\n id: nameToId(s.name),\n name: s.name,\n category: \"detachment\" as const,\n type,\n detachment_id: nameToId(s.detachment),\n cp_cost: parseInt(s.cp_cost, 10),\n phases,\n player_turn: playerTurn,\n timing: \"once-per-phase\" as const,\n target_restrictions: null as null,\n ability_id: null as string | null,\n game_version: GAME_VERSION,\n };\n });\n\n // ─── Build phase mappings from source ability phases ───\n console.log(\"Converting phase mappings...\");\n const phaseMappings: Record<string, unknown>[] = [];\n\n // Unit abilities\n for (const ds of factionDatasheets) {\n const viewIdx = viewIndices.get(ds.id)!;\n const dsAbilities = allAbilities.filter(\n (a) => a.datasheet_id === ds.id\n );\n const viewAbilities = getViewEntries(dsAbilities, viewIdx);\n const seen = new Set<string>();\n\n for (const a of viewAbilities) {\n if (a.type === \"Faction\") continue;\n const sourceId = nameToId(a.name);\n if (seen.has(sourceId)) continue;\n seen.add(sourceId);\n\n const sourceType =\n a.type === \"Core\" ? \"ability\" :\n a.type === \"Wargear\" ? \"ability\" :\n \"ability\";\n\n const phases = mapPhases(a.phases);\n if (phases.length > 0) {\n phaseMappings.push({\n source_id: sourceId,\n source_type: sourceType,\n phases,\n game_version: GAME_VERSION,\n authored_by: \"40kdc-community\",\n });\n }\n }\n }\n\n // Stratagem phase mappings\n for (const s of factionStratagems) {\n const phases = mapPhases(s.phases);\n if (phases.length > 0) {\n phaseMappings.push({\n source_id: nameToId(s.name),\n source_type: \"stratagem\",\n phases,\n game_version: GAME_VERSION,\n authored_by: \"40kdc-community\",\n });\n }\n }\n\n // Enhancement phase mappings\n for (const e of factionEnhancements) {\n const phases = mapPhases(e.phases);\n if (phases.length > 0) {\n phaseMappings.push({\n source_id: nameToId(e.name),\n source_type: \"enhancement\",\n phases,\n game_version: GAME_VERSION,\n authored_by: \"40kdc-community\",\n });\n }\n }\n\n // Detachment rule phase mappings\n for (const da of factionDetAbilities) {\n const phases = mapPhases(da.phases);\n if (phases.length > 0) {\n phaseMappings.push({\n source_id: nameToId(da.name),\n source_type: \"detachment-rule\",\n phases,\n game_version: GAME_VERSION,\n authored_by: \"40kdc-community\",\n });\n }\n }\n\n // Deduplicate phase mappings\n const dedupedPhaseMappings = [\n ...new Map(\n phaseMappings.map((pm) => [\n `${(pm as { source_id: string }).source_id}|${(pm as { source_type: string }).source_type}`,\n pm,\n ])\n ).values(),\n ];\n\n // ─── Build unit compositions ───\n console.log(\"Generating unit compositions...\");\n\n const unitCompositions = units.map((u) => {\n const unitId = (u as { id: string }).id;\n const modelCount = (u as { model_count: { min: number; max: number } }).model_count;\n\n const override = config.compositionOverrides[unitId];\n if (override) {\n return {\n unit_id: unitId,\n models: override,\n game_version: GAME_VERSION,\n };\n }\n\n // Single-model unit (vehicles, characters, monsters)\n const profileName = (u as { profiles: { name: string }[] }).profiles[0]?.name;\n return {\n unit_id: unitId,\n models: [\n {\n name: profileName || (u as { name: string }).name,\n min: modelCount.min,\n max: modelCount.max,\n is_leader_model: false,\n },\n ],\n game_version: GAME_VERSION,\n };\n });\n\n // ─── Generate factions.json ───\n const factionEntity = [\n {\n id: factionId,\n name: factionName,\n parent_faction_id: config.parentFactionId,\n game_version: GAME_VERSION,\n keywords: config.factionKeywords,\n aliases: config.aliases,\n faction_rule_id: config.factionRuleId,\n },\n ];\n\n // ─── Write output ──────────────────────────────────────────────────\n const coreDir = `data/core/${factionId}`;\n const enrichDir = `data/enrichment/${factionId}`;\n mkdirSync(resolve(ROOT, coreDir), { recursive: true });\n mkdirSync(resolve(ROOT, enrichDir), { recursive: true });\n\n console.log(\"\\nWriting output files...\");\n\n // `wargearOnly` adds just the wargear data: the rest of the converter's output\n // has drifted from the committed dataset (e.g. weapon keywords are object refs\n // there, strings here), so a full rewrite would regress those files. Adding\n // wargear must not touch them.\n if (!options.wargearOnly) {\n writeOutput(`${coreDir}/factions.json`, factionEntity);\n }\n if (!config.skipUnits) {\n if (!options.wargearOnly) {\n writeOutput(`${coreDir}/units.json`, units);\n writeOutput(`${coreDir}/weapons.json`, weapons);\n writeOutput(`${coreDir}/leader-attachments.json`, leaderAttachments);\n writeOutput(`${coreDir}/unit-compositions.json`, unitCompositions);\n }\n writeOutput(`${coreDir}/wargear-options.json`, wargearOptions);\n if (wargearItems.length > 0) {\n writeOutput(`${coreDir}/wargear.json`, wargearItems);\n }\n if (unparsedOptions.length > 0) {\n // Underscore-prefixed: a report for manual review, skipped by validation\n // and not bundled into the dataset.\n writeOutput(`${coreDir}/_wargear-options.unparsed.json`, unparsedOptions);\n }\n }\n if (!options.wargearOnly) {\n writeOutput(`${coreDir}/detachments.json`, detachments);\n writeOutput(`${coreDir}/enhancements.json`, enhancementEntities);\n writeOutput(`${coreDir}/stratagems.json`, stratagemEntities);\n if (!config.skipUnits) {\n writeOutput(`${enrichDir}/phase-mappings.json`, dedupedPhaseMappings);\n }\n }\n\n // ─── Summary ───\n console.log(`\\n── ${factionName} Summary ──`);\n if (!config.skipUnits) {\n console.log(` Units: ${units.length}`);\n console.log(` Weapons: ${weapons.length}`);\n console.log(` Leader attachments: ${leaderAttachments.length}`);\n console.log(` Unit compositions: ${unitCompositions.length}`);\n console.log(` Wargear options: ${wargearOptions.length}`);\n console.log(` Wargear items: ${wargearItems.length}`);\n console.log(` Unparsed options: ${unparsedOptions.length}`);\n }\n console.log(` Detachments: ${detachments.length}`);\n console.log(` Enhancements: ${enhancementEntities.length}`);\n console.log(` Stratagems: ${stratagemEntities.length}`);\n if (!config.skipUnits) {\n console.log(` Phase mappings: ${dedupedPhaseMappings.length}`);\n }\n console.log(\"\\nDone. Run 'npm run validate' to check output.\");\n}\n\n// ─── CLI entry point ─────────────────────────────────────────────────\n\n// Only run CLI when this module is the entry point (not when imported)\nconst isMain = process.argv[1] &&\n resolve(process.argv[1]).replace(/\\.\\w+$/, \"\") ===\n fileURLToPath(import.meta.url).replace(/\\.\\w+$/, \"\");\n\nif (isMain) {\n const args = process.argv.slice(2);\n const wargearOnly = args.includes(\"--wargear-only\");\n const positional = args.filter((a) => !a.startsWith(\"--\"));\n\n if (positional.length === 0 || args[0] === \"--help\") {\n console.log(\n \"Usage: npx tsx tools/src/convert-faction.ts <faction-id|all> [--wargear-only]\",\n );\n console.log(`Available factions: ${listFactions().join(\", \")}`);\n process.exit(args[0] === \"--help\" ? 0 : 1);\n }\n\n const target = positional[0];\n const factionIds = target === \"all\" ? listFactions() : [target];\n for (const id of factionIds) {\n convertFaction(getFactionConfig(id), { wargearOnly });\n }\n}\n"]}