@alpaca-software/40kdc-data 0.1.1 → 0.1.3
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.
- package/README.md +2 -0
- package/dist/abilities-resolver/index.d.ts +9 -0
- package/dist/abilities-resolver/index.d.ts.map +1 -0
- package/dist/abilities-resolver/index.js +9 -0
- package/dist/abilities-resolver/index.js.map +1 -0
- package/dist/abilities-resolver/resolver.d.ts +73 -0
- package/dist/abilities-resolver/resolver.d.ts.map +1 -0
- package/dist/abilities-resolver/resolver.js +142 -0
- package/dist/abilities-resolver/resolver.js.map +1 -0
- package/dist/audit-coverage.d.ts +78 -0
- package/dist/audit-coverage.d.ts.map +1 -0
- package/dist/audit-coverage.js +341 -0
- package/dist/audit-coverage.js.map +1 -0
- package/dist/author-batch.d.ts +147 -0
- package/dist/author-batch.d.ts.map +1 -0
- package/dist/author-batch.js +675 -0
- package/dist/author-batch.js.map +1 -0
- package/dist/author-input.d.ts +37 -0
- package/dist/author-input.d.ts.map +1 -0
- package/dist/author-input.js +162 -0
- package/dist/author-input.js.map +1 -0
- package/dist/bundle-schemas.d.ts +1 -0
- package/dist/bundle-schemas.d.ts.map +1 -0
- package/dist/bundle-schemas.js +1 -0
- package/dist/bundle-schemas.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +9 -0
- package/dist/cli.js.map +1 -0
- package/dist/codegen-data.d.ts +1 -0
- package/dist/codegen-data.d.ts.map +1 -0
- package/dist/codegen-data.js +2 -0
- package/dist/codegen-data.js.map +1 -0
- package/dist/commands/import.d.ts +1 -0
- package/dist/commands/import.d.ts.map +1 -0
- package/dist/commands/import.js +1 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/translate.d.ts +1 -0
- package/dist/commands/translate.d.ts.map +1 -0
- package/dist/commands/translate.js +10 -4
- package/dist/commands/translate.js.map +1 -0
- package/dist/commands/validate-all.d.ts +1 -0
- package/dist/commands/validate-all.d.ts.map +1 -0
- package/dist/commands/validate-all.js +1 -0
- package/dist/commands/validate-all.js.map +1 -0
- package/dist/commands/validate-core.d.ts +1 -0
- package/dist/commands/validate-core.d.ts.map +1 -0
- package/dist/commands/validate-core.js +1 -0
- package/dist/commands/validate-core.js.map +1 -0
- package/dist/commands/validate-enrichment.d.ts +1 -0
- package/dist/commands/validate-enrichment.d.ts.map +1 -0
- package/dist/commands/validate-enrichment.js +1 -0
- package/dist/commands/validate-enrichment.js.map +1 -0
- package/dist/convert-faction.d.ts +1 -0
- package/dist/convert-faction.d.ts.map +1 -0
- package/dist/convert-faction.js +1 -0
- package/dist/convert-faction.js.map +1 -0
- package/dist/converters/configs/adepta-sororitas.d.ts +1 -0
- package/dist/converters/configs/adepta-sororitas.d.ts.map +1 -0
- package/dist/converters/configs/adepta-sororitas.js +1 -0
- package/dist/converters/configs/adepta-sororitas.js.map +1 -0
- package/dist/converters/configs/adeptus-astartes.d.ts +1 -0
- package/dist/converters/configs/adeptus-astartes.d.ts.map +1 -0
- package/dist/converters/configs/adeptus-astartes.js +1 -0
- package/dist/converters/configs/adeptus-astartes.js.map +1 -0
- package/dist/converters/configs/adeptus-custodes.d.ts +1 -0
- package/dist/converters/configs/adeptus-custodes.d.ts.map +1 -0
- package/dist/converters/configs/adeptus-custodes.js +1 -0
- package/dist/converters/configs/adeptus-custodes.js.map +1 -0
- package/dist/converters/configs/adeptus-mechanicus.d.ts +1 -0
- package/dist/converters/configs/adeptus-mechanicus.d.ts.map +1 -0
- package/dist/converters/configs/adeptus-mechanicus.js +1 -0
- package/dist/converters/configs/adeptus-mechanicus.js.map +1 -0
- package/dist/converters/configs/aeldari.d.ts +1 -0
- package/dist/converters/configs/aeldari.d.ts.map +1 -0
- package/dist/converters/configs/aeldari.js +1 -0
- package/dist/converters/configs/aeldari.js.map +1 -0
- package/dist/converters/configs/agents-of-the-imperium.d.ts +1 -0
- package/dist/converters/configs/agents-of-the-imperium.d.ts.map +1 -0
- package/dist/converters/configs/agents-of-the-imperium.js +1 -0
- package/dist/converters/configs/agents-of-the-imperium.js.map +1 -0
- package/dist/converters/configs/astra-militarum.d.ts +1 -0
- package/dist/converters/configs/astra-militarum.d.ts.map +1 -0
- package/dist/converters/configs/astra-militarum.js +1 -0
- package/dist/converters/configs/astra-militarum.js.map +1 -0
- package/dist/converters/configs/black-templars.d.ts +1 -0
- package/dist/converters/configs/black-templars.d.ts.map +1 -0
- package/dist/converters/configs/black-templars.js +1 -0
- package/dist/converters/configs/black-templars.js.map +1 -0
- package/dist/converters/configs/blood-angels.d.ts +1 -0
- package/dist/converters/configs/blood-angels.d.ts.map +1 -0
- package/dist/converters/configs/blood-angels.js +1 -0
- package/dist/converters/configs/blood-angels.js.map +1 -0
- package/dist/converters/configs/chaos-daemons.d.ts +1 -0
- package/dist/converters/configs/chaos-daemons.d.ts.map +1 -0
- package/dist/converters/configs/chaos-daemons.js +1 -0
- package/dist/converters/configs/chaos-daemons.js.map +1 -0
- package/dist/converters/configs/chaos-knights.d.ts +1 -0
- package/dist/converters/configs/chaos-knights.d.ts.map +1 -0
- package/dist/converters/configs/chaos-knights.js +1 -0
- package/dist/converters/configs/chaos-knights.js.map +1 -0
- package/dist/converters/configs/chaos-space-marines.d.ts +1 -0
- package/dist/converters/configs/chaos-space-marines.d.ts.map +1 -0
- package/dist/converters/configs/chaos-space-marines.js +1 -0
- package/dist/converters/configs/chaos-space-marines.js.map +1 -0
- package/dist/converters/configs/crimson-fists.d.ts +1 -0
- package/dist/converters/configs/crimson-fists.d.ts.map +1 -0
- package/dist/converters/configs/crimson-fists.js +1 -0
- package/dist/converters/configs/crimson-fists.js.map +1 -0
- package/dist/converters/configs/dark-angels.d.ts +1 -0
- package/dist/converters/configs/dark-angels.d.ts.map +1 -0
- package/dist/converters/configs/dark-angels.js +1 -0
- package/dist/converters/configs/dark-angels.js.map +1 -0
- package/dist/converters/configs/death-guard.d.ts +1 -0
- package/dist/converters/configs/death-guard.d.ts.map +1 -0
- package/dist/converters/configs/death-guard.js +1 -0
- package/dist/converters/configs/death-guard.js.map +1 -0
- package/dist/converters/configs/deathwatch.d.ts +1 -0
- package/dist/converters/configs/deathwatch.d.ts.map +1 -0
- package/dist/converters/configs/deathwatch.js +1 -0
- package/dist/converters/configs/deathwatch.js.map +1 -0
- package/dist/converters/configs/drukhari.d.ts +1 -0
- package/dist/converters/configs/drukhari.d.ts.map +1 -0
- package/dist/converters/configs/drukhari.js +1 -0
- package/dist/converters/configs/drukhari.js.map +1 -0
- package/dist/converters/configs/emperors-children.d.ts +1 -0
- package/dist/converters/configs/emperors-children.d.ts.map +1 -0
- package/dist/converters/configs/emperors-children.js +1 -0
- package/dist/converters/configs/emperors-children.js.map +1 -0
- package/dist/converters/configs/genestealer-cults.d.ts +1 -0
- package/dist/converters/configs/genestealer-cults.d.ts.map +1 -0
- package/dist/converters/configs/genestealer-cults.js +1 -0
- package/dist/converters/configs/genestealer-cults.js.map +1 -0
- package/dist/converters/configs/grey-knights.d.ts +1 -0
- package/dist/converters/configs/grey-knights.d.ts.map +1 -0
- package/dist/converters/configs/grey-knights.js +1 -0
- package/dist/converters/configs/grey-knights.js.map +1 -0
- package/dist/converters/configs/imperial-fists.d.ts +1 -0
- package/dist/converters/configs/imperial-fists.d.ts.map +1 -0
- package/dist/converters/configs/imperial-fists.js +1 -0
- package/dist/converters/configs/imperial-fists.js.map +1 -0
- package/dist/converters/configs/imperial-knights.d.ts +1 -0
- package/dist/converters/configs/imperial-knights.d.ts.map +1 -0
- package/dist/converters/configs/imperial-knights.js +1 -0
- package/dist/converters/configs/imperial-knights.js.map +1 -0
- package/dist/converters/configs/iron-hands.d.ts +1 -0
- package/dist/converters/configs/iron-hands.d.ts.map +1 -0
- package/dist/converters/configs/iron-hands.js +1 -0
- package/dist/converters/configs/iron-hands.js.map +1 -0
- package/dist/converters/configs/leagues-of-votann.d.ts +1 -0
- package/dist/converters/configs/leagues-of-votann.d.ts.map +1 -0
- package/dist/converters/configs/leagues-of-votann.js +1 -0
- package/dist/converters/configs/leagues-of-votann.js.map +1 -0
- package/dist/converters/configs/necrons.d.ts +1 -0
- package/dist/converters/configs/necrons.d.ts.map +1 -0
- package/dist/converters/configs/necrons.js +1 -0
- package/dist/converters/configs/necrons.js.map +1 -0
- package/dist/converters/configs/orks.d.ts +1 -0
- package/dist/converters/configs/orks.d.ts.map +1 -0
- package/dist/converters/configs/orks.js +1 -0
- package/dist/converters/configs/orks.js.map +1 -0
- package/dist/converters/configs/raven-guard.d.ts +1 -0
- package/dist/converters/configs/raven-guard.d.ts.map +1 -0
- package/dist/converters/configs/raven-guard.js +1 -0
- package/dist/converters/configs/raven-guard.js.map +1 -0
- package/dist/converters/configs/salamanders.d.ts +1 -0
- package/dist/converters/configs/salamanders.d.ts.map +1 -0
- package/dist/converters/configs/salamanders.js +1 -0
- package/dist/converters/configs/salamanders.js.map +1 -0
- package/dist/converters/configs/space-wolves.d.ts +1 -0
- package/dist/converters/configs/space-wolves.d.ts.map +1 -0
- package/dist/converters/configs/space-wolves.js +1 -0
- package/dist/converters/configs/space-wolves.js.map +1 -0
- package/dist/converters/configs/tau-empire.d.ts +1 -0
- package/dist/converters/configs/tau-empire.d.ts.map +1 -0
- package/dist/converters/configs/tau-empire.js +1 -0
- package/dist/converters/configs/tau-empire.js.map +1 -0
- package/dist/converters/configs/thousand-sons.d.ts +1 -0
- package/dist/converters/configs/thousand-sons.d.ts.map +1 -0
- package/dist/converters/configs/thousand-sons.js +1 -0
- package/dist/converters/configs/thousand-sons.js.map +1 -0
- package/dist/converters/configs/tyranids.d.ts +1 -0
- package/dist/converters/configs/tyranids.d.ts.map +1 -0
- package/dist/converters/configs/tyranids.js +1 -0
- package/dist/converters/configs/tyranids.js.map +1 -0
- package/dist/converters/configs/ultramarines.d.ts +1 -0
- package/dist/converters/configs/ultramarines.d.ts.map +1 -0
- package/dist/converters/configs/ultramarines.js +1 -0
- package/dist/converters/configs/ultramarines.js.map +1 -0
- package/dist/converters/configs/white-scars.d.ts +1 -0
- package/dist/converters/configs/white-scars.d.ts.map +1 -0
- package/dist/converters/configs/white-scars.js +1 -0
- package/dist/converters/configs/white-scars.js.map +1 -0
- package/dist/converters/configs/world-eaters.d.ts +1 -0
- package/dist/converters/configs/world-eaters.d.ts.map +1 -0
- package/dist/converters/configs/world-eaters.js +1 -0
- package/dist/converters/configs/world-eaters.js.map +1 -0
- package/dist/converters/faction-config.d.ts +1 -0
- package/dist/converters/faction-config.d.ts.map +1 -0
- package/dist/converters/faction-config.js +1 -0
- package/dist/converters/faction-config.js.map +1 -0
- package/dist/converters/id-generator.d.ts +1 -0
- package/dist/converters/id-generator.d.ts.map +1 -0
- package/dist/converters/id-generator.js +1 -0
- package/dist/converters/id-generator.js.map +1 -0
- package/dist/converters/keyword-filter.d.ts +1 -0
- package/dist/converters/keyword-filter.d.ts.map +1 -0
- package/dist/converters/keyword-filter.js +1 -0
- package/dist/converters/keyword-filter.js.map +1 -0
- package/dist/converters/stat-parser.d.ts +1 -0
- package/dist/converters/stat-parser.d.ts.map +1 -0
- package/dist/converters/stat-parser.js +1 -0
- package/dist/converters/stat-parser.js.map +1 -0
- package/dist/converters/view-selector.d.ts +1 -0
- package/dist/converters/view-selector.d.ts.map +1 -0
- package/dist/converters/view-selector.js +1 -0
- package/dist/converters/view-selector.js.map +1 -0
- package/dist/converters/weapon-dedup.d.ts +1 -0
- package/dist/converters/weapon-dedup.d.ts.map +1 -0
- package/dist/converters/weapon-dedup.js +1 -0
- package/dist/converters/weapon-dedup.js.map +1 -0
- package/dist/cruncher/attribution.d.ts +66 -0
- package/dist/cruncher/attribution.d.ts.map +1 -0
- package/dist/cruncher/attribution.js +88 -0
- package/dist/cruncher/attribution.js.map +1 -0
- package/dist/cruncher/buffs.d.ts +206 -0
- package/dist/cruncher/buffs.d.ts.map +1 -0
- package/dist/cruncher/buffs.js +150 -0
- package/dist/cruncher/buffs.js.map +1 -0
- package/dist/cruncher/engine.d.ts +50 -0
- package/dist/cruncher/engine.d.ts.map +1 -0
- package/dist/cruncher/engine.js +312 -0
- package/dist/cruncher/engine.js.map +1 -0
- package/dist/cruncher/from-dsl.d.ts +101 -0
- package/dist/cruncher/from-dsl.d.ts.map +1 -0
- package/dist/cruncher/from-dsl.js +968 -0
- package/dist/cruncher/from-dsl.js.map +1 -0
- package/dist/cruncher/from-keyword.d.ts +35 -0
- package/dist/cruncher/from-keyword.d.ts.map +1 -0
- package/dist/cruncher/from-keyword.js +159 -0
- package/dist/cruncher/from-keyword.js.map +1 -0
- package/dist/cruncher/get-buffs.d.ts +12 -0
- package/dist/cruncher/get-buffs.d.ts.map +1 -0
- package/dist/cruncher/get-buffs.js +7 -0
- package/dist/cruncher/get-buffs.js.map +1 -0
- package/dist/cruncher/index.d.ts +12 -0
- package/dist/cruncher/index.d.ts.map +1 -0
- package/dist/cruncher/index.js +12 -0
- package/dist/cruncher/index.js.map +1 -0
- package/dist/data/bundle.generated.d.ts +1 -0
- package/dist/data/bundle.generated.d.ts.map +1 -0
- package/dist/data/bundle.generated.js +2 -1
- package/dist/data/bundle.generated.js.map +1 -0
- package/dist/data/collection.d.ts +10 -0
- package/dist/data/collection.d.ts.map +1 -0
- package/dist/data/collection.js +15 -0
- package/dist/data/collection.js.map +1 -0
- package/dist/data/dataset.d.ts +132 -2
- package/dist/data/dataset.d.ts.map +1 -0
- package/dist/data/dataset.js +248 -1
- package/dist/data/dataset.js.map +1 -0
- package/dist/data/entities.d.ts +67 -2
- package/dist/data/entities.d.ts.map +1 -0
- package/dist/data/entities.js +122 -0
- package/dist/data/entities.js.map +1 -0
- package/dist/data/index.d.ts +10 -1
- package/dist/data/index.d.ts.map +1 -0
- package/dist/data/index.js +14 -1
- package/dist/data/index.js.map +1 -0
- package/dist/data/normalize.d.ts +1 -0
- package/dist/data/normalize.d.ts.map +1 -0
- package/dist/data/normalize.js +1 -0
- package/dist/data/normalize.js.map +1 -0
- package/dist/data/roster-resolve.d.ts +58 -0
- package/dist/data/roster-resolve.d.ts.map +1 -0
- package/dist/data/roster-resolve.js +82 -0
- package/dist/data/roster-resolve.js.map +1 -0
- package/dist/data/types.d.ts +4 -1
- package/dist/data/types.d.ts.map +1 -0
- package/dist/data/types.js +2 -0
- package/dist/data/types.js.map +1 -0
- package/dist/export/helpers.d.ts +33 -0
- package/dist/export/helpers.d.ts.map +1 -0
- package/dist/export/helpers.js +57 -0
- package/dist/export/helpers.js.map +1 -0
- package/dist/export/index.d.ts +22 -0
- package/dist/export/index.d.ts.map +1 -0
- package/dist/export/index.js +28 -0
- package/dist/export/index.js.map +1 -0
- package/dist/export/newrecruit-json.d.ts +3 -0
- package/dist/export/newrecruit-json.d.ts.map +1 -0
- package/dist/export/newrecruit-json.js +140 -0
- package/dist/export/newrecruit-json.js.map +1 -0
- package/dist/export/newrecruit-simple.d.ts +3 -0
- package/dist/export/newrecruit-simple.d.ts.map +1 -0
- package/dist/export/newrecruit-simple.js +76 -0
- package/dist/export/newrecruit-simple.js.map +1 -0
- package/dist/export/newrecruit-wtc.d.ts +4 -0
- package/dist/export/newrecruit-wtc.d.ts.map +1 -0
- package/dist/export/newrecruit-wtc.js +142 -0
- package/dist/export/newrecruit-wtc.js.map +1 -0
- package/dist/export/roster-json.d.ts +3 -0
- package/dist/export/roster-json.d.ts.map +1 -0
- package/dist/export/roster-json.js +8 -0
- package/dist/export/roster-json.js.map +1 -0
- package/dist/export/rosterizer.d.ts +3 -0
- package/dist/export/rosterizer.d.ts.map +1 -0
- package/dist/export/rosterizer.js +144 -0
- package/dist/export/rosterizer.js.map +1 -0
- package/dist/export/serializer.d.ts +27 -0
- package/dist/export/serializer.d.ts.map +1 -0
- package/dist/export/serializer.js +2 -0
- package/dist/export/serializer.js.map +1 -0
- package/dist/gen-conformance.d.ts +1 -0
- package/dist/gen-conformance.d.ts.map +1 -0
- package/dist/gen-conformance.js +274 -12
- package/dist/gen-conformance.js.map +1 -0
- package/dist/generated.d.ts +194 -118
- package/dist/generated.d.ts.map +1 -0
- package/dist/generated.js +1 -0
- package/dist/generated.js.map +1 -0
- package/dist/import/adapter.d.ts +4 -3
- package/dist/import/adapter.d.ts.map +1 -0
- package/dist/import/adapter.js +1 -0
- package/dist/import/adapter.js.map +1 -0
- package/dist/import/decode.d.ts +1 -0
- package/dist/import/decode.d.ts.map +1 -0
- package/dist/import/decode.js +1 -0
- package/dist/import/decode.js.map +1 -0
- package/dist/import/gw.d.ts +69 -0
- package/dist/import/gw.d.ts.map +1 -0
- package/dist/import/gw.js +245 -0
- package/dist/import/gw.js.map +1 -0
- package/dist/import/import-roster.d.ts +84 -0
- package/dist/import/import-roster.d.ts.map +1 -0
- package/dist/import/import-roster.js +207 -0
- package/dist/import/import-roster.js.map +1 -0
- package/dist/import/index.d.ts +7 -3
- package/dist/import/index.d.ts.map +1 -0
- package/dist/import/index.js +5 -1
- package/dist/import/index.js.map +1 -0
- package/dist/import/listforge.d.ts +1 -0
- package/dist/import/listforge.d.ts.map +1 -0
- package/dist/import/listforge.js +22 -2
- package/dist/import/listforge.js.map +1 -0
- package/dist/import/newrecruit-json.d.ts +31 -0
- package/dist/import/newrecruit-json.d.ts.map +1 -0
- package/dist/import/newrecruit-json.js +224 -0
- package/dist/import/newrecruit-json.js.map +1 -0
- package/dist/import/newrecruit-simple.d.ts +29 -0
- package/dist/import/newrecruit-simple.d.ts.map +1 -0
- package/dist/import/newrecruit-simple.js +200 -0
- package/dist/import/newrecruit-simple.js.map +1 -0
- package/dist/import/newrecruit-text.d.ts +51 -0
- package/dist/import/newrecruit-text.d.ts.map +1 -0
- package/dist/import/newrecruit-text.js +102 -0
- package/dist/import/newrecruit-text.js.map +1 -0
- package/dist/import/newrecruit-wtc.d.ts +36 -0
- package/dist/import/newrecruit-wtc.d.ts.map +1 -0
- package/dist/import/newrecruit-wtc.js +337 -0
- package/dist/import/newrecruit-wtc.js.map +1 -0
- package/dist/import/resolve.d.ts +3 -2
- package/dist/import/resolve.d.ts.map +1 -0
- package/dist/import/resolve.js +5 -2
- package/dist/import/resolve.js.map +1 -0
- package/dist/import/rosterizer.d.ts +70 -0
- package/dist/import/rosterizer.d.ts.map +1 -0
- package/dist/import/rosterizer.js +348 -0
- package/dist/import/rosterizer.js.map +1 -0
- package/dist/import/types.d.ts +11 -1
- package/dist/import/types.d.ts.map +1 -0
- package/dist/import/types.js +1 -0
- package/dist/import/types.js.map +1 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -0
- package/dist/known-support-10e.d.ts +1 -0
- package/dist/known-support-10e.d.ts.map +1 -0
- package/dist/known-support-10e.js +1 -0
- package/dist/known-support-10e.js.map +1 -0
- package/dist/link-abilities.d.ts +41 -0
- package/dist/link-abilities.d.ts.map +1 -0
- package/dist/link-abilities.js +159 -0
- package/dist/link-abilities.js.map +1 -0
- package/dist/migrations/2026-weapon-keywords.d.ts +2 -0
- package/dist/migrations/2026-weapon-keywords.d.ts.map +1 -0
- package/dist/migrations/2026-weapon-keywords.js +247 -0
- package/dist/migrations/2026-weapon-keywords.js.map +1 -0
- package/dist/port-10e-faction.d.ts +1 -0
- package/dist/port-10e-faction.d.ts.map +1 -0
- package/dist/port-10e-faction.js +1 -0
- package/dist/port-10e-faction.js.map +1 -0
- package/dist/report.d.ts +1 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +1 -0
- package/dist/report.js.map +1 -0
- package/dist/rube-goldberg.d.ts +3 -0
- package/dist/rube-goldberg.d.ts.map +1 -0
- package/dist/rube-goldberg.js +109 -0
- package/dist/rube-goldberg.js.map +1 -0
- package/dist/runner.d.ts +38 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +492 -0
- package/dist/runner.js.map +1 -0
- package/dist/schema-loader.d.ts +1 -0
- package/dist/schema-loader.d.ts.map +1 -0
- package/dist/schema-loader.js +1 -0
- package/dist/schema-loader.js.map +1 -0
- package/dist/scrub-ip.d.ts +14 -0
- package/dist/scrub-ip.d.ts.map +1 -0
- package/dist/scrub-ip.js +88 -0
- package/dist/scrub-ip.js.map +1 -0
- package/dist/validate.d.ts +1 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +2 -0
- package/dist/validate.js.map +1 -0
- package/package.json +15 -3
- package/schemas/core/roster.schema.json +19 -4
- package/schemas/core/weapon-keyword.schema.json +31 -0
- package/schemas/core/weapon.schema.json +22 -1
- package/schemas/enrichment/ability-dsl/effect.schema.json +23 -1
- package/dist/import/import-listforge.d.ts +0 -23
- package/dist/import/import-listforge.js +0 -32
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raven-guard.d.ts","sourceRoot":"","sources":["../../../src/converters/configs/raven-guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE3E,QAAA,MAAM,UAAU,EAAE,aAYjB,CAAC;AAIF,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raven-guard.js","sourceRoot":"","sources":["../../../src/converters/configs/raven-guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAsB,MAAM,sBAAsB,CAAC;AAE3E,MAAM,UAAU,GAAkB;IAChC,eAAe,EAAE,IAAI;IACrB,SAAS,EAAE,aAAa;IACxB,WAAW,EAAE,aAAa;IAC1B,kBAAkB,EAAE,gBAAgB;IACpC,aAAa,EAAE,gBAAgB;IAC/B,eAAe,EAAE,CAAC,UAAU,EAAE,kBAAkB,EAAE,aAAa,CAAC;IAChE,eAAe,EAAE,kBAAkB;IACnC,OAAO,EAAE,EAAE;IACX,oBAAoB,EAAE,EAAE;IACxB,SAAS,EAAE,IAAI;IACf,gBAAgB,EAAE,CAAC,oBAAoB,CAAC;CACzC,CAAC;AAEF,eAAe,CAAC,UAAU,CAAC,CAAC;AAE5B,eAAe,UAAU,CAAC","sourcesContent":["import { registerFaction, type FactionConfig } from \"../faction-config.js\";\n\nconst ravenGuard: FactionConfig = {\n sourceFactionId: \"SM\",\n factionId: \"raven-guard\",\n factionName: \"Raven Guard\",\n factionAbilityName: \"Oath of Moment\",\n factionRuleId: \"oath-of-moment\",\n factionKeywords: [\"Imperium\", \"Adeptus Astartes\", \"Raven Guard\"],\n parentFactionId: \"adeptus-astartes\",\n aliases: [],\n compositionOverrides: {},\n skipUnits: true,\n detachmentFilter: [\"Company of Hunters\"],\n};\n\nregisterFaction(ravenGuard);\n\nexport default ravenGuard;\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"salamanders.d.ts","sourceRoot":"","sources":["../../../src/converters/configs/salamanders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE3E,QAAA,MAAM,WAAW,EAAE,aAYlB,CAAC;AAIF,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"salamanders.js","sourceRoot":"","sources":["../../../src/converters/configs/salamanders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAsB,MAAM,sBAAsB,CAAC;AAE3E,MAAM,WAAW,GAAkB;IACjC,eAAe,EAAE,IAAI;IACrB,SAAS,EAAE,aAAa;IACxB,WAAW,EAAE,aAAa;IAC1B,kBAAkB,EAAE,gBAAgB;IACpC,aAAa,EAAE,gBAAgB;IAC/B,eAAe,EAAE,CAAC,UAAU,EAAE,kBAAkB,EAAE,aAAa,CAAC;IAChE,eAAe,EAAE,kBAAkB;IACnC,OAAO,EAAE,EAAE;IACX,oBAAoB,EAAE,EAAE;IACxB,SAAS,EAAE,IAAI;IACf,gBAAgB,EAAE,CAAC,4BAA4B,CAAC;CACjD,CAAC;AAEF,eAAe,CAAC,WAAW,CAAC,CAAC;AAE7B,eAAe,WAAW,CAAC","sourcesContent":["import { registerFaction, type FactionConfig } from \"../faction-config.js\";\n\nconst salamanders: FactionConfig = {\n sourceFactionId: \"SM\",\n factionId: \"salamanders\",\n factionName: \"Salamanders\",\n factionAbilityName: \"Oath of Moment\",\n factionRuleId: \"oath-of-moment\",\n factionKeywords: [\"Imperium\", \"Adeptus Astartes\", \"Salamanders\"],\n parentFactionId: \"adeptus-astartes\",\n aliases: [],\n compositionOverrides: {},\n skipUnits: true,\n detachmentFilter: [\"Forgefather\\u2019s Seekers\"],\n};\n\nregisterFaction(salamanders);\n\nexport default salamanders;\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"space-wolves.d.ts","sourceRoot":"","sources":["../../../src/converters/configs/space-wolves.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE3E,QAAA,MAAM,WAAW,EAAE,aAYlB,CAAC;AAIF,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"space-wolves.js","sourceRoot":"","sources":["../../../src/converters/configs/space-wolves.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAsB,MAAM,sBAAsB,CAAC;AAE3E,MAAM,WAAW,GAAkB;IACjC,eAAe,EAAE,IAAI;IACrB,SAAS,EAAE,cAAc;IACzB,WAAW,EAAE,cAAc;IAC3B,kBAAkB,EAAE,gBAAgB;IACpC,aAAa,EAAE,gBAAgB;IAC/B,eAAe,EAAE,CAAC,UAAU,EAAE,kBAAkB,EAAE,cAAc,CAAC;IACjE,eAAe,EAAE,kBAAkB;IACnC,OAAO,EAAE,EAAE;IACX,oBAAoB,EAAE,EAAE;IACxB,SAAS,EAAE,IAAI;IACf,gBAAgB,EAAE,CAAC,qBAAqB,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,oBAAoB,CAAC;CACzI,CAAC;AAEF,eAAe,CAAC,WAAW,CAAC,CAAC;AAE7B,eAAe,WAAW,CAAC","sourcesContent":["import { registerFaction, type FactionConfig } from \"../faction-config.js\";\n\nconst spaceWolves: FactionConfig = {\n sourceFactionId: \"SM\",\n factionId: \"space-wolves\",\n factionName: \"Space Wolves\",\n factionAbilityName: \"Oath of Moment\",\n factionRuleId: \"oath-of-moment\",\n factionKeywords: [\"Imperium\", \"Adeptus Astartes\", \"Space Wolves\"],\n parentFactionId: \"adeptus-astartes\",\n aliases: [],\n compositionOverrides: {},\n skipUnits: true,\n detachmentFilter: [\"Champions of Fenris\", \"Saga of the Beastslayer\", \"Saga of the Bold\", \"Saga of the Great Wolf\", \"Saga of the Hunter\"],\n};\n\nregisterFaction(spaceWolves);\n\nexport default spaceWolves;\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tau-empire.d.ts","sourceRoot":"","sources":["../../../src/converters/configs/tau-empire.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE3E,QAAA,MAAM,SAAS,EAAE,aAwChB,CAAC;AAIF,eAAe,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tau-empire.js","sourceRoot":"","sources":["../../../src/converters/configs/tau-empire.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAsB,MAAM,sBAAsB,CAAC;AAE3E,MAAM,SAAS,GAAkB;IAC/B,eAAe,EAAE,KAAK;IACtB,SAAS,EAAE,YAAY;IACvB,WAAW,EAAE,kBAAkB;IAC/B,kBAAkB,EAAE,sBAAsB;IAC1C,aAAa,EAAE,sBAAsB;IACrC,eAAe,EAAE,CAAC,kBAAkB,CAAC;IACrC,eAAe,EAAE,IAAI;IACrB,OAAO,EAAE,EAAE;IACX,oBAAoB,EAAE;QACpB,eAAe,EAAE;YACf,EAAE,IAAI,EAAE,2BAA2B,EAAE,YAAY,EAAE,cAAc,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,eAAe,EAAE,cAAc,EAAE,qBAAqB,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE;YACxL,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,eAAe,EAAE,cAAc,EAAE,qBAAqB,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE;SAC/I;QACD,aAAa,EAAE;YACb,EAAE,IAAI,EAAE,2BAA2B,EAAE,YAAY,EAAE,cAAc,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,cAAc,EAAE,aAAa,EAAE,qBAAqB,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE;YACtL,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,cAAc,EAAE,aAAa,EAAE,qBAAqB,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE;SAC7I;QACD,iBAAiB,EAAE;YACjB,EAAE,IAAI,EAAE,yBAAyB,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,eAAe,EAAE,qBAAqB,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE;YACpK,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,eAAe,EAAE,qBAAqB,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE;SAC7H;QACD,kBAAkB,EAAE;YAClB,EAAE,IAAI,EAAE,oBAAoB,EAAE,YAAY,EAAE,iBAAiB,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,aAAa,EAAE,qBAAqB,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE;YAClK,EAAE,IAAI,EAAE,iBAAiB,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,kBAAkB,EAAE,CAAC,aAAa,EAAE,qBAAqB,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE;SACjI;QACD,mBAAmB,EAAE;YACnB,EAAE,IAAI,EAAE,aAAa,EAAE,YAAY,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,oBAAoB,EAAE,qBAAqB,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE;YACnK,EAAE,IAAI,EAAE,kBAAkB,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,kBAAkB,EAAE,CAAC,oBAAoB,EAAE,qBAAqB,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE;YACzI,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,eAAe,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE;SACvG;QACD,qBAAqB,EAAE;YACrB,EAAE,IAAI,EAAE,uBAAuB,EAAE,YAAY,EAAE,oBAAoB,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,cAAc,EAAE,kBAAkB,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE;YACtK,EAAE,IAAI,EAAE,oBAAoB,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,cAAc,EAAE,kBAAkB,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE;SACjI;QACD,mBAAmB,EAAE;YACnB,EAAE,IAAI,EAAE,sBAAsB,EAAE,YAAY,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE;YACrK,EAAE,IAAI,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE;SACjI;KACF;CACF,CAAC;AAEF,eAAe,CAAC,SAAS,CAAC,CAAC;AAE3B,eAAe,SAAS,CAAC","sourcesContent":["import { registerFaction, type FactionConfig } from \"../faction-config.js\";\n\nconst tauEmpire: FactionConfig = {\n sourceFactionId: \"TAU\",\n factionId: \"tau-empire\",\n factionName: \"T\\u2019au Empire\",\n factionAbilityName: \"For the Greater Good\",\n factionRuleId: \"for-the-greater-good\",\n factionKeywords: [\"T\\u2019au Empire\"],\n parentFactionId: null,\n aliases: [],\n compositionOverrides: {\n \"breacher-team\": [\n { name: \"Fire Warrior Shas\\u2019ui\", profile_name: \"Fire Warrior\", min: 1, max: 1, default_weapon_ids: [\"pulse-blaster\", \"pulse-pistol\", \"close-combat-weapon\"], is_leader_model: true },\n { name: \"Fire Warrior\", min: 9, max: 9, default_weapon_ids: [\"pulse-blaster\", \"pulse-pistol\", \"close-combat-weapon\"], is_leader_model: false },\n ],\n \"strike-team\": [\n { name: \"Fire Warrior Shas\\u2019ui\", profile_name: \"Fire Warrior\", min: 1, max: 1, default_weapon_ids: [\"pulse-pistol\", \"pulse-rifle\", \"close-combat-weapon\"], is_leader_model: true },\n { name: \"Fire Warrior\", min: 9, max: 9, default_weapon_ids: [\"pulse-pistol\", \"pulse-rifle\", \"close-combat-weapon\"], is_leader_model: false },\n ],\n \"pathfinder-team\": [\n { name: \"Pathfinder Shas\\u2019ui\", profile_name: \"Pathfinder\", min: 1, max: 1, default_weapon_ids: [\"pulse-carbine\", \"close-combat-weapon\"], is_leader_model: true },\n { name: \"Pathfinder\", min: 9, max: 9, default_weapon_ids: [\"pulse-carbine\", \"close-combat-weapon\"], is_leader_model: false },\n ],\n \"kroot-carnivores\": [\n { name: \"Kroot Trail Shaper\", profile_name: \"Kroot Carnivore\", min: 1, max: 1, default_weapon_ids: [\"kroot-rifle\", \"close-combat-weapon\"], is_leader_model: true },\n { name: \"Kroot Carnivore\", min: 9, max: 19, default_weapon_ids: [\"kroot-rifle\", \"close-combat-weapon\"], is_leader_model: false },\n ],\n \"kroot-farstalkers\": [\n { name: \"Kill-Broker\", profile_name: \"Kroot Farstalker\", min: 1, max: 1, default_weapon_ids: [\"farstalker-firearm\", \"close-combat-weapon\"], is_leader_model: true },\n { name: \"Kroot Farstalker\", min: 10, max: 10, default_weapon_ids: [\"farstalker-firearm\", \"close-combat-weapon\"], is_leader_model: false },\n { name: \"Kroot Hound\", min: 1, max: 1, default_weapon_ids: [\"ripping-fangs\"], is_leader_model: false },\n ],\n \"stealth-battlesuits\": [\n { name: \"Stealth Shas\\u2019vre\", profile_name: \"Stealth Battlesuit\", min: 1, max: 1, default_weapon_ids: [\"burst-cannon\", \"battlesuit-fists\"], is_leader_model: true },\n { name: \"Stealth Battlesuit\", min: 4, max: 4, default_weapon_ids: [\"burst-cannon\", \"battlesuit-fists\"], is_leader_model: false },\n ],\n \"vespid-stingwings\": [\n { name: \"Vespid Strain Leader\", profile_name: \"Vespid Stingwing\", min: 1, max: 1, default_weapon_ids: [\"neutron-blaster\", \"stingwing-claws\"], is_leader_model: true },\n { name: \"Vespid Stingwing\", min: 4, max: 9, default_weapon_ids: [\"neutron-blaster\", \"stingwing-claws\"], is_leader_model: false },\n ],\n },\n};\n\nregisterFaction(tauEmpire);\n\nexport default tauEmpire;\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thousand-sons.d.ts","sourceRoot":"","sources":["../../../src/converters/configs/thousand-sons.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE3E,QAAA,MAAM,YAAY,EAAE,aA0BnB,CAAC;AAIF,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thousand-sons.js","sourceRoot":"","sources":["../../../src/converters/configs/thousand-sons.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAsB,MAAM,sBAAsB,CAAC;AAE3E,MAAM,YAAY,GAAkB;IAClC,eAAe,EAAE,IAAI;IACrB,SAAS,EAAE,eAAe;IAC1B,WAAW,EAAE,eAAe;IAC5B,kBAAkB,EAAE,oBAAoB;IACxC,aAAa,EAAE,oBAAoB;IACnC,eAAe,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,eAAe,CAAC;IACvD,eAAe,EAAE,IAAI;IACrB,OAAO,EAAE,EAAE;IACX,oBAAoB,EAAE;QACpB,gBAAgB,EAAE;YAChB,EAAE,IAAI,EAAE,mBAAmB,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,qBAAqB,EAAE,cAAc,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE;YACjI,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,iBAAiB,EAAE,qBAAqB,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE;SAClI;QACD,2BAA2B,EAAE;YAC3B,EAAE,IAAI,EAAE,wBAAwB,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,sBAAsB,EAAE,cAAc,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE;YACvI,EAAE,IAAI,EAAE,0BAA0B,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,sBAAsB,EAAE,oBAAoB,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE;SACjJ;QACD,WAAW,EAAE;YACX,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,YAAY,EAAE,iBAAiB,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE;YAC7I,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,kBAAkB,EAAE,CAAC,YAAY,EAAE,iBAAiB,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE;SACrH;QACD,aAAa,EAAE;YACb,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,mBAAmB,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE;SAC3G;KACF;CACF,CAAC;AAEF,eAAe,CAAC,YAAY,CAAC,CAAC;AAE9B,eAAe,YAAY,CAAC","sourcesContent":["import { registerFaction, type FactionConfig } from \"../faction-config.js\";\n\nconst thousandSons: FactionConfig = {\n sourceFactionId: \"TS\",\n factionId: \"thousand-sons\",\n factionName: \"Thousand Sons\",\n factionAbilityName: \"Cabal of Sorcerers\",\n factionRuleId: \"cabal-of-sorcerers\",\n factionKeywords: [\"Chaos\", \"Tzeentch\", \"Thousand Sons\"],\n parentFactionId: null,\n aliases: [],\n compositionOverrides: {\n \"rubric-marines\": [\n { name: \"Aspiring Sorcerer\", min: 1, max: 1, default_weapon_ids: [\"inferno-bolt-pistol\", \"force-weapon\"], is_leader_model: true },\n { name: \"Rubric Marine\", min: 4, max: 9, default_weapon_ids: [\"inferno-boltgun\", \"close-combat-weapon\"], is_leader_model: false },\n ],\n \"scarab-occult-terminators\": [\n { name: \"Scarab Occult Sorcerer\", min: 1, max: 1, default_weapon_ids: [\"inferno-combi-bolter\", \"force-weapon\"], is_leader_model: true },\n { name: \"Scarab Occult Terminator\", min: 4, max: 9, default_weapon_ids: [\"inferno-combi-bolter\", \"prosperine-khopesh\"], is_leader_model: false },\n ],\n \"tzaangors\": [\n { name: \"Twistbray\", profile_name: \"Tzaangor\", min: 1, max: 1, default_weapon_ids: [\"autopistol\", \"tzaangor-blades\"], is_leader_model: true },\n { name: \"Tzaangor\", min: 9, max: 19, default_weapon_ids: [\"autopistol\", \"tzaangor-blades\"], is_leader_model: false },\n ],\n \"chaos-spawn\": [\n { name: \"Chaos Spawn\", min: 2, max: 2, default_weapon_ids: [\"hideous-mutations\"], is_leader_model: false },\n ],\n },\n};\n\nregisterFaction(thousandSons);\n\nexport default thousandSons;\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tyranids.d.ts","sourceRoot":"","sources":["../../../src/converters/configs/tyranids.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE3E,QAAA,MAAM,QAAQ,EAAE,aAuBf,CAAC;AAIF,eAAe,QAAQ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tyranids.js","sourceRoot":"","sources":["../../../src/converters/configs/tyranids.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAsB,MAAM,sBAAsB,CAAC;AAE3E,MAAM,QAAQ,GAAkB;IAC9B,eAAe,EAAE,KAAK;IACtB,SAAS,EAAE,UAAU;IACrB,WAAW,EAAE,UAAU;IACvB,kBAAkB,EAAE,oBAAoB;IACxC,aAAa,EAAE,oBAAoB;IACnC,eAAe,EAAE,CAAC,UAAU,CAAC;IAC7B,eAAe,EAAE,IAAI;IACrB,OAAO,EAAE,EAAE;IACX,oBAAoB,EAAE;QACpB,uBAAuB,EAAE;YACvB,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,0BAA0B,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE;YAClH,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,0BAA0B,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE;SACxI;QACD,yCAAyC,EAAE;YACzC,EAAE,IAAI,EAAE,eAAe,EAAE,YAAY,EAAE,iBAAiB,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,cAAc,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE;YACvI,EAAE,IAAI,EAAE,iBAAiB,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,iBAAiB,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE;SAC7G;QACD,0CAA0C,EAAE;YAC1C,EAAE,IAAI,EAAE,eAAe,EAAE,YAAY,EAAE,iBAAiB,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,UAAU,EAAE,iBAAiB,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE;YACtJ,EAAE,IAAI,EAAE,iBAAiB,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,UAAU,EAAE,iBAAiB,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE;SACzH;KACF;CACF,CAAC;AAEF,eAAe,CAAC,QAAQ,CAAC,CAAC;AAE1B,eAAe,QAAQ,CAAC","sourcesContent":["import { registerFaction, type FactionConfig } from \"../faction-config.js\";\n\nconst tyranids: FactionConfig = {\n sourceFactionId: \"TYR\",\n factionId: \"tyranids\",\n factionName: \"Tyranids\",\n factionAbilityName: \"Shadow in the Warp\",\n factionRuleId: \"shadow-in-the-warp\",\n factionKeywords: [\"Tyranids\"],\n parentFactionId: null,\n aliases: [],\n compositionOverrides: {\n \"hyperadapted-raveners\": [\n { name: \"Ravener Prime\", min: 1, max: 1, default_weapon_ids: [\"ravener-claws-and-talons\"], is_leader_model: true },\n { name: \"Ravener\", profile_name: \"Raveners\", min: 4, max: 4, default_weapon_ids: [\"ravener-claws-and-talons\"], is_leader_model: false },\n ],\n \"tyranid-warriors-with-melee-bio-weapons\": [\n { name: \"Tyranid Prime\", profile_name: \"Tyranid Warrior\", min: 1, max: 1, default_weapon_ids: [\"prime-talons\"], is_leader_model: true },\n { name: \"Tyranid Warrior\", min: 2, max: 5, default_weapon_ids: [\"dual-boneswords\"], is_leader_model: false },\n ],\n \"tyranid-warriors-with-ranged-bio-weapons\": [\n { name: \"Tyranid Prime\", profile_name: \"Tyranid Warrior\", min: 1, max: 1, default_weapon_ids: [\"devourer\", \"scything-talons\"], is_leader_model: true },\n { name: \"Tyranid Warrior\", min: 2, max: 5, default_weapon_ids: [\"devourer\", \"scything-talons\"], is_leader_model: false },\n ],\n },\n};\n\nregisterFaction(tyranids);\n\nexport default tyranids;\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ultramarines.d.ts","sourceRoot":"","sources":["../../../src/converters/configs/ultramarines.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE3E,QAAA,MAAM,YAAY,EAAE,aAYnB,CAAC;AAIF,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ultramarines.js","sourceRoot":"","sources":["../../../src/converters/configs/ultramarines.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAsB,MAAM,sBAAsB,CAAC;AAE3E,MAAM,YAAY,GAAkB;IAClC,eAAe,EAAE,IAAI;IACrB,SAAS,EAAE,cAAc;IACzB,WAAW,EAAE,cAAc;IAC3B,kBAAkB,EAAE,gBAAgB;IACpC,aAAa,EAAE,gBAAgB;IAC/B,eAAe,EAAE,CAAC,UAAU,EAAE,kBAAkB,EAAE,cAAc,CAAC;IACjE,eAAe,EAAE,kBAAkB;IACnC,OAAO,EAAE,EAAE;IACX,oBAAoB,EAAE,EAAE;IACxB,SAAS,EAAE,IAAI;IACf,gBAAgB,EAAE,CAAC,mBAAmB,CAAC;CACxC,CAAC;AAEF,eAAe,CAAC,YAAY,CAAC,CAAC;AAE9B,eAAe,YAAY,CAAC","sourcesContent":["import { registerFaction, type FactionConfig } from \"../faction-config.js\";\n\nconst ultramarines: FactionConfig = {\n sourceFactionId: \"SM\",\n factionId: \"ultramarines\",\n factionName: \"Ultramarines\",\n factionAbilityName: \"Oath of Moment\",\n factionRuleId: \"oath-of-moment\",\n factionKeywords: [\"Imperium\", \"Adeptus Astartes\", \"Ultramarines\"],\n parentFactionId: \"adeptus-astartes\",\n aliases: [],\n compositionOverrides: {},\n skipUnits: true,\n detachmentFilter: [\"Blade of Ultramar\"],\n};\n\nregisterFaction(ultramarines);\n\nexport default ultramarines;\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"white-scars.d.ts","sourceRoot":"","sources":["../../../src/converters/configs/white-scars.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE3E,QAAA,MAAM,UAAU,EAAE,aAYjB,CAAC;AAIF,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"white-scars.js","sourceRoot":"","sources":["../../../src/converters/configs/white-scars.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAsB,MAAM,sBAAsB,CAAC;AAE3E,MAAM,UAAU,GAAkB;IAChC,eAAe,EAAE,IAAI;IACrB,SAAS,EAAE,aAAa;IACxB,WAAW,EAAE,aAAa;IAC1B,kBAAkB,EAAE,gBAAgB;IACpC,aAAa,EAAE,gBAAgB;IAC/B,eAAe,EAAE,CAAC,UAAU,EAAE,kBAAkB,EAAE,aAAa,CAAC;IAChE,eAAe,EAAE,kBAAkB;IACnC,OAAO,EAAE,EAAE;IACX,oBAAoB,EAAE,EAAE;IACxB,SAAS,EAAE,IAAI;IACf,gBAAgB,EAAE,CAAC,mBAAmB,CAAC;CACxC,CAAC;AAEF,eAAe,CAAC,UAAU,CAAC,CAAC;AAE5B,eAAe,UAAU,CAAC","sourcesContent":["import { registerFaction, type FactionConfig } from \"../faction-config.js\";\n\nconst whiteScars: FactionConfig = {\n sourceFactionId: \"SM\",\n factionId: \"white-scars\",\n factionName: \"White Scars\",\n factionAbilityName: \"Oath of Moment\",\n factionRuleId: \"oath-of-moment\",\n factionKeywords: [\"Imperium\", \"Adeptus Astartes\", \"White Scars\"],\n parentFactionId: \"adeptus-astartes\",\n aliases: [],\n compositionOverrides: {},\n skipUnits: true,\n detachmentFilter: [\"Reclamation Force\"],\n};\n\nregisterFaction(whiteScars);\n\nexport default whiteScars;\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"world-eaters.d.ts","sourceRoot":"","sources":["../../../src/converters/configs/world-eaters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE3E,QAAA,MAAM,WAAW,EAAE,aAuClB,CAAC;AAIF,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"world-eaters.js","sourceRoot":"","sources":["../../../src/converters/configs/world-eaters.ts"],"names":[],"mappings":"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","sourcesContent":["import { registerFaction, type FactionConfig } from \"../faction-config.js\";\n\nconst worldEaters: FactionConfig = {\n sourceFactionId: \"WE\",\n factionId: \"world-eaters\",\n factionName: \"World Eaters\",\n factionAbilityName: \"Blessings of Khorne\",\n factionRuleId: \"blessings-of-khorne\",\n factionKeywords: [\"Chaos\", \"Khorne\", \"World Eaters\"],\n parentFactionId: null,\n aliases: [],\n compositionOverrides: {\n \"khorne-berzerkers\": [\n { name: \"Berzerker Champion\", profile_name: \"Khorne Berzerker\", min: 1, max: 1, default_weapon_ids: [\"bolt-pistol\", \"chainblade\"], is_leader_model: true },\n { name: \"Khorne Berzerker\", min: 9, max: 19, default_weapon_ids: [\"bolt-pistol\", \"chainblade\"], is_leader_model: false },\n ],\n \"jakhals\": [\n { name: \"Jakhal Pack Leader\", profile_name: \"Jakhal\", min: 1, max: 1, default_weapon_ids: [\"autopistol\", \"jakhal-chainblades\"], is_leader_model: true },\n { name: \"Dishonoured\", profile_name: \"Jakhal\", min: 1, max: 2, default_weapon_ids: [\"mauler-chainblade\"], is_leader_model: false },\n { name: \"Jakhal\", min: 8, max: 17, default_weapon_ids: [\"autopistol\", \"jakhal-chainblades\"], is_leader_model: false },\n ],\n \"eightbound\": [\n { name: \"Eightbound Champion\", profile_name: \"Eightbound\", min: 1, max: 1, default_weapon_ids: [\"chainblades\"], is_leader_model: true },\n { name: \"Eightbound\", min: 2, max: 5, default_weapon_ids: [\"chainblades\"], is_leader_model: false },\n ],\n \"exalted-eightbound\": [\n { name: \"Exalted Eightbound Champion\", profile_name: \"Exalted Eightbound\", min: 1, max: 1, default_weapon_ids: [\"chainblades\"], is_leader_model: true },\n { name: \"Exalted Eightbound\", min: 2, max: 5, default_weapon_ids: [\"chainblades\"], is_leader_model: false },\n ],\n \"chaos-terminators\": [\n { name: \"Terminator Champion\", profile_name: \"World Eaters Terminator\", min: 1, max: 1, default_weapon_ids: [\"combi-bolter\", \"accursed-weapon\"], is_leader_model: true },\n { name: \"Chaos Terminator\", profile_name: \"World Eaters Terminator\", min: 4, max: 4, default_weapon_ids: [\"combi-bolter\", \"accursed-weapon\"], is_leader_model: false },\n ],\n \"goremongers\": [\n { name: \"Goremonger Pack Leader\", profile_name: \"Goremongers\", min: 1, max: 1, default_weapon_ids: [\"autopistol\", \"chainblade\", \"close-combat-weapon\"], is_leader_model: true },\n { name: \"Goremonger\", profile_name: \"Goremongers\", min: 7, max: 7, default_weapon_ids: [\"autopistol\", \"chainblade\", \"close-combat-weapon\"], is_leader_model: false },\n ],\n \"chaos-spawn\": [\n { name: \"Chaos Spawn\", min: 2, max: 2, default_weapon_ids: [\"hideous-mutations\"], is_leader_model: false },\n ],\n },\n};\n\nregisterFaction(worldEaters);\n\nexport default worldEaters;\n"]}
|
|
@@ -51,3 +51,4 @@ export interface FactionConfig {
|
|
|
51
51
|
export declare function registerFaction(config: FactionConfig): void;
|
|
52
52
|
export declare function getFactionConfig(factionId: string): FactionConfig;
|
|
53
53
|
export declare function listFactions(): string[];
|
|
54
|
+
//# sourceMappingURL=faction-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"faction-config.d.ts","sourceRoot":"","sources":["../../src/converters/faction-config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,eAAe,EAAE,MAAM,CAAC;IAExB,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAElB,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAC;IAEpB,oEAAoE;IACpE,kBAAkB,EAAE,MAAM,CAAC;IAE3B,2EAA2E;IAC3E,aAAa,EAAE,MAAM,CAAC;IAEtB,8EAA8E;IAC9E,eAAe,EAAE,MAAM,EAAE,CAAC;IAE1B,iEAAiE;IACjE,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAE/B,oCAAoC;IACpC,OAAO,EAAE,MAAM,EAAE,CAAC;IAElB;;;;OAIG;IACH,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;IAEnD;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE5B;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAKD,wBAAgB,eAAe,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAE3D;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,CASjE;AAED,wBAAgB,YAAY,IAAI,MAAM,EAAE,CAEvC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"faction-config.js","sourceRoot":"","sources":["../../src/converters/faction-config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA0DH,wEAAwE;AACxE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAC;AAElD,MAAM,UAAU,eAAe,CAAC,MAAqB;IACnD,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,SAAiB;IAChD,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACvC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,SAAS,GAAG,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClD,MAAM,IAAI,KAAK,CACb,oBAAoB,SAAS,iBAAiB,SAAS,EAAE,CAC1D,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AACrC,CAAC","sourcesContent":["/**\n * Faction-specific configuration for the generic converter.\n *\n * Each faction provides a config that parameterizes the conversion pipeline.\n * Configs are stored in ./configs/ and imported by convert-faction.ts.\n */\n\nexport interface ModelEntry {\n name: string;\n profile_name?: string | null;\n min: number;\n max: number;\n default_weapon_ids?: string[];\n is_leader_model: boolean;\n}\n\nexport interface FactionConfig {\n /** Source faction ID in army-assist data (e.g., \"WE\", \"EC\"). */\n sourceFactionId: string;\n\n /** 40kdc entity ID (e.g., \"world-eaters\", \"emperors-children\"). */\n factionId: string;\n\n /** Display name (e.g., \"World Eaters\", \"Emperor's Children\"). */\n factionName: string;\n\n /** Faction ability name used for view selection on shared units. */\n factionAbilityName: string;\n\n /** 40kdc ID for the faction rule ability (e.g., \"blessings-of-khorne\"). */\n factionRuleId: string;\n\n /** Top-level faction keywords (e.g., [\"Chaos\", \"Khorne\", \"World Eaters\"]). */\n factionKeywords: string[];\n\n /** Parent faction ID if this is a subfaction, null otherwise. */\n parentFactionId: string | null;\n\n /** Aliases for the faction name. */\n aliases: string[];\n\n /**\n * Manual composition overrides for multi-model units.\n * Keyed by 40kdc unit ID (e.g., \"khorne-berzerkers\").\n * Single-model units (vehicles, characters) get auto-generated compositions.\n */\n compositionOverrides: Record<string, ModelEntry[]>;\n\n /**\n * For subfactions that share a source faction (e.g., SM chapters):\n * only include detachments whose names match this list.\n * Stratagems and enhancements are filtered to matching detachments.\n * If undefined, all detachments are included.\n */\n detachmentFilter?: string[];\n\n /**\n * If true, skip unit/weapon/leader-attachment/unit-composition generation.\n * Used by subfactions whose units are inherited from the parent faction.\n */\n skipUnits?: boolean;\n}\n\n/** Registry of all known faction configs, keyed by 40kdc faction ID. */\nconst registry = new Map<string, FactionConfig>();\n\nexport function registerFaction(config: FactionConfig): void {\n registry.set(config.factionId, config);\n}\n\nexport function getFactionConfig(factionId: string): FactionConfig {\n const config = registry.get(factionId);\n if (!config) {\n const available = [...registry.keys()].join(\", \");\n throw new Error(\n `Unknown faction \"${factionId}\". Available: ${available}`\n );\n }\n return config;\n}\n\nexport function listFactions(): string[] {\n return [...registry.keys()].sort();\n}\n"]}
|
|
@@ -12,3 +12,4 @@ export declare function parseStratagemType(typeStr: string): {
|
|
|
12
12
|
export declare function parsePlayerTurn(turn: string): string;
|
|
13
13
|
/** Map source phase names to schema phase enum values. Filters out invalid phases. */
|
|
14
14
|
export declare function mapPhases(phases: string[]): string[];
|
|
15
|
+
//# sourceMappingURL=id-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"id-generator.d.ts","sourceRoot":"","sources":["../../src/converters/id-generator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,wDAAwD;AACxD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAe7C;AAED,kFAAkF;AAClF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;CACxB,CAsBA;AAED,mDAAmD;AACnD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMpD;AAED,sFAAsF;AACtF,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAWpD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"id-generator.js","sourceRoot":"","sources":["../../src/converters/id-generator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,iBAAiB,GAAG,8BAA8B,CAAC;AAEzD,wDAAwD;AACxD,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,MAAM,EAAE,GAAG,IAAI;SACZ,SAAS,CAAC,KAAK,CAAC;SAChB,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC,mBAAmB;SACnD,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAM,iCAAiC;SACjE,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAK,6BAA6B;SAC7D,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAS,gCAAgC;IAEpE,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CACb,iBAAiB,EAAE,gBAAgB,IAAI,oCAAoC,CAC5E,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAIhD,wDAAwD;IACxD,6EAA6E;IAC7E,qEAAqE;IACrE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;IAC/D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,iCAAiC,OAAO,GAAG,CAAC,CAAC;IAC/D,CAAC;IACD,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACvC,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAE9C,MAAM,OAAO,GAA2B;QACtC,eAAe,EAAE,eAAe;QAChC,gBAAgB,EAAE,gBAAgB;QAClC,WAAW,EAAE,WAAW;QACxB,OAAO,EAAE,SAAS;KACnB,CAAC;IACF,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,4BAA4B,OAAO,WAAW,OAAO,GAAG,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;AAClC,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IACxC,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC9C,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,WAAW,CAAC;IAC/C,IAAI,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC;QAAE,OAAO,eAAe,CAAC;IACvD,MAAM,IAAI,KAAK,CAAC,8BAA8B,IAAI,GAAG,CAAC,CAAC;AACzD,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,SAAS,CAAC,MAAgB;IACxC,MAAM,QAAQ,GAA2B;QACvC,OAAO,EAAE,SAAS;QAClB,QAAQ,EAAE,UAAU;QACpB,QAAQ,EAAE,UAAU;QACpB,MAAM,EAAE,QAAQ;QAChB,KAAK,EAAE,OAAO;KACf,CAAC;IACF,OAAO,MAAM;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;SACrC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;AACjD,CAAC","sourcesContent":["/**\n * Generates kebab-case entity IDs from display names.\n */\n\nconst ENTITY_ID_PATTERN = /^[a-z0-9][a-z0-9-]*[a-z0-9]$/;\n\n/** Convert a display name to a kebab-case entity ID. */\nexport function nameToId(name: string): string {\n const id = name\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\") // strip diacritics\n .replace(/[''\\u2019]/g, \"\") // strip apostrophes/right-quotes\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\") // non-alphanumeric → hyphens\n .replace(/^-+|-+$/g, \"\"); // trim leading/trailing hyphens\n\n if (!ENTITY_ID_PATTERN.test(id)) {\n throw new Error(\n `Generated ID \"${id}\" from name \"${name}\" does not match entity-id pattern`\n );\n }\n return id;\n}\n\n/** Convert a stratagem type string to the schema enum value and detachment ID. */\nexport function parseStratagemType(typeStr: string): {\n type: string;\n detachmentName: string;\n} {\n // Format: \"Berzerker Warband - Battle Tactic Stratagem\"\n // Require spaces around the separator to avoid splitting on internal hyphens\n // (e.g., \"Spearhead-at-Arms\" has hyphens but the delimiter is \" - \")\n const match = typeStr.match(/^(.+)\\s+-\\s+(.+?)\\s*Stratagem$/i);\n if (!match) {\n throw new Error(`Cannot parse stratagem type: \"${typeStr}\"`);\n }\n const detachmentName = match[1].trim();\n const rawType = match[2].trim().toLowerCase();\n\n const typeMap: Record<string, string> = {\n \"battle tactic\": \"battle-tactic\",\n \"strategic ploy\": \"strategic-ploy\",\n \"epic deed\": \"epic-deed\",\n wargear: \"wargear\",\n };\n const type = typeMap[rawType];\n if (!type) {\n throw new Error(`Unknown stratagem type: \"${rawType}\" from \"${typeStr}\"`);\n }\n return { type, detachmentName };\n}\n\n/** Convert a player turn string to schema enum. */\nexport function parsePlayerTurn(turn: string): string {\n const lower = turn.toLowerCase().trim();\n if (lower.includes(\"either\")) return \"either\";\n if (lower.includes(\"your\")) return \"your-turn\";\n if (lower.includes(\"opponent\")) return \"opponent-turn\";\n throw new Error(`Cannot parse player turn: \"${turn}\"`);\n}\n\n/** Map source phase names to schema phase enum values. Filters out invalid phases. */\nexport function mapPhases(phases: string[]): string[] {\n const phaseMap: Record<string, string> = {\n command: \"command\",\n movement: \"movement\",\n shooting: \"shooting\",\n charge: \"charge\",\n fight: \"fight\",\n };\n return phases\n .map((p) => phaseMap[p.toLowerCase()])\n .filter((p): p is string => p !== undefined);\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyword-filter.d.ts","sourceRoot":"","sources":["../../src/converters/keyword-filter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,UAAU,aAAa;IACrB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAqCD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,aAAa,EAAE,EACzB,WAAW,EAAE,MAAM,GAClB,aAAa,CAsCf"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyword-filter.js","sourceRoot":"","sources":["../../src/converters/keyword-filter.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Filters keywords for shared units to return only the target faction's view.\n *\n * Source data stores all views' keywords in a flat list, grouped by faction\n * keyword markers (is_faction_keyword === \"true\"). Each group starts with one\n * or more faction keyword entries, followed by regular keywords for that view.\n */\n\nexport interface SourceKeyword {\n datasheet_id: string;\n keyword: string;\n model: string;\n is_faction_keyword: string;\n}\n\ninterface KeywordResult {\n factionKeywords: string[];\n regularKeywords: string[];\n}\n\ninterface KeywordGroup {\n factionKeywords: string[];\n regularKeywords: string[];\n}\n\n/**\n * Split keywords into view groups delimited by faction keyword entries.\n * Each group starts when a faction keyword is encountered after regular keywords\n * (or at the start).\n */\nfunction splitKeywordGroups(keywords: SourceKeyword[]): KeywordGroup[] {\n const groups: KeywordGroup[] = [];\n let current: KeywordGroup | null = null;\n\n for (const kw of keywords) {\n if (kw.is_faction_keyword === \"true\") {\n if (current === null || current.regularKeywords.length > 0) {\n // Start a new group when we see a faction keyword after regular ones\n // (or at the very start)\n if (current !== null) groups.push(current);\n current = { factionKeywords: [], regularKeywords: [] };\n }\n current!.factionKeywords.push(kw.keyword);\n } else {\n if (current === null) {\n current = { factionKeywords: [], regularKeywords: [] };\n }\n current.regularKeywords.push(kw.keyword);\n }\n }\n if (current !== null) groups.push(current);\n\n return groups;\n}\n\n/**\n * Get keywords for a specific faction from a shared unit's keyword list.\n * Finds the group whose faction keywords include `factionName` and returns\n * deduplicated faction + regular keywords for that view.\n *\n * For single-view units (one group), returns all keywords as-is.\n */\nexport function getKeywordsForFaction(\n keywords: SourceKeyword[],\n factionName: string\n): KeywordResult {\n const groups = splitKeywordGroups(keywords);\n\n if (groups.length <= 1) {\n // Single-view unit — return everything\n const group = groups[0] ?? { factionKeywords: [], regularKeywords: [] };\n return {\n factionKeywords: [...new Set(group.factionKeywords)],\n regularKeywords: [...new Set(group.regularKeywords)],\n };\n }\n\n // Multi-view unit — find the group matching the target faction\n for (const group of groups) {\n if (group.factionKeywords.includes(factionName)) {\n return {\n factionKeywords: [...new Set(group.factionKeywords)],\n regularKeywords: [...new Set(group.regularKeywords)],\n };\n }\n }\n\n // Fallback: faction name not found in any group. Return all keywords\n // deduplicated — better than throwing for edge cases.\n const allFaction = new Set<string>();\n const allRegular = new Set<string>();\n for (const group of groups) {\n group.factionKeywords.forEach((k) => allFaction.add(k));\n group.regularKeywords.forEach((k) => allRegular.add(k));\n }\n console.warn(\n `Warning: faction \"${factionName}\" not found in keyword groups for ` +\n `datasheet ${keywords[0]?.datasheet_id}. Returning all keywords.`\n );\n return {\n factionKeywords: [...allFaction],\n regularKeywords: [...allRegular],\n };\n}\n"]}
|
|
@@ -20,3 +20,4 @@ export declare function parseIntStat(s: string): number;
|
|
|
20
20
|
export declare function parseWeaponKeywords(description: string): string[];
|
|
21
21
|
/** Parse AP value. "0" → 0, "-2" → -2 */
|
|
22
22
|
export declare function parseAP(s: string): number;
|
|
23
|
+
//# sourceMappingURL=stat-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stat-parser.d.ts","sourceRoot":"","sources":["../../src/converters/stat-parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,6EAA6E;AAC7E,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAM3C;AAED,8DAA8D;AAC9D,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM1D;AAED,+FAA+F;AAC/F,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAQzD;AAED,wFAAwF;AACxF,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAMtD;AAED,gDAAgD;AAChD,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAElD;AAED,mDAAmD;AACnD,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEpD;AAED,qDAAqD;AACrD,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAM9C;AAED,sGAAsG;AACtG,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAMjE;AAED,yCAAyC;AACzC,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAMzC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stat-parser.js","sourceRoot":"","sources":["../../src/converters/stat-parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,6EAA6E;AAC7E,MAAM,UAAU,SAAS,CAAC,CAAS;IACjC,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,IAAI,OAAO,KAAK,EAAE,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,GAAG;QAAE,OAAO,CAAC,CAAC;IACnE,MAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAChC,IAAI,KAAK,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,GAAG,CAAC,CAAC;IAC/D,OAAO,CAAC,CAAC;AACX,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,iBAAiB,CAAC,CAAS;IACzC,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1C,IAAI,OAAO,KAAK,EAAE,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IACxE,MAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAChC,IAAI,KAAK,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,GAAG,CAAC,CAAC;IACpE,OAAO,CAAC,CAAC;AACX,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,cAAc,CAAC,CAAS;IACtC,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACzB,IAAI,OAAO,KAAK,EAAE,IAAI,OAAO,KAAK,GAAG;QAAE,OAAO,CAAC,CAAC;IAChD,8CAA8C;IAC9C,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC;IAChD,MAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAChC,IAAI,KAAK,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,GAAG,CAAC,CAAC;IACjE,OAAO,CAAC,CAAC;AACX,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,IAAI,OAAO,KAAK,EAAE,IAAI,OAAO,CAAC,WAAW,EAAE,KAAK,OAAO,IAAI,OAAO,KAAK,KAAK;QAAE,OAAO,OAAO,CAAC;IAC7F,MAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAChC,IAAI,KAAK,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,GAAG,CAAC,CAAC;IAC5D,OAAO,CAAC,CAAC;AACX,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,SAAS,CAAC,CAAS;IACjC,OAAO,iBAAiB,CAAC,CAAC,CAAC,CAAC;AAC9B,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,WAAW,CAAC,CAAS;IACnC,OAAO,iBAAiB,CAAC,CAAC,CAAC,CAAC;AAC9B,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,YAAY,CAAC,CAAS;IACpC,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACzB,IAAI,OAAO,KAAK,EAAE,IAAI,OAAO,KAAK,GAAG;QAAE,OAAO,CAAC,CAAC;IAChD,MAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAChC,IAAI,KAAK,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,GAAG,CAAC,CAAC;IAC/D,OAAO,CAAC,CAAC;AACX,CAAC;AAED,sGAAsG;AACtG,MAAM,UAAU,mBAAmB,CAAC,WAAmB;IACrD,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,EAAE,CAAC;IACzD,OAAO,WAAW;SACf,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACjC,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,OAAO,CAAC,CAAS;IAC/B,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACzB,IAAI,OAAO,KAAK,EAAE,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,GAAG;QAAE,OAAO,CAAC,CAAC;IACnE,MAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAChC,IAAI,KAAK,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC;IACzD,OAAO,CAAC,CAAC;AACX,CAAC","sourcesContent":["/**\n * Parses army-assist display-format stat strings into typed values\n * for the 40kdc-data schemas.\n */\n\n/** Strip inch marks and parse to integer. \"8\\\"\" → 8, \"14\\\"\" → 14, \"*\" → 0 */\nexport function parseMove(s: string): number {\n const cleaned = s.replace(/[\"″]/g, \"\").trim();\n if (cleaned === \"\" || cleaned === \"-\" || cleaned === \"*\") return 0;\n const n = parseInt(cleaned, 10);\n if (isNaN(n)) throw new Error(`Cannot parse movement: \"${s}\"`);\n return n;\n}\n\n/** Parse target-number stat. \"3+\" → 3, \"6+\" → 6, \"\" → null */\nexport function parseTargetNumber(s: string): number | null {\n const cleaned = s.replace(\"+\", \"\").trim();\n if (cleaned === \"\" || cleaned === \"-\" || cleaned === \"N/A\") return null;\n const n = parseInt(cleaned, 10);\n if (isNaN(n)) throw new Error(`Cannot parse target number: \"${s}\"`);\n return n;\n}\n\n/** Parse a stat-value field. Returns integer for fixed values, string for dice expressions. */\nexport function parseStatValue(s: string): number | string {\n const cleaned = s.trim();\n if (cleaned === \"\" || cleaned === \"-\") return 0;\n // Dice expressions: D6, 2D6, D6+2, D3+1, etc.\n if (/^\\d*[dD]\\d/i.test(cleaned)) return cleaned;\n const n = parseInt(cleaned, 10);\n if (isNaN(n)) throw new Error(`Cannot parse stat value: \"${s}\"`);\n return n;\n}\n\n/** Parse weapon range. \"36\\\"\" → 36, \"Melee\" → \"Melee\", \"\" → \"Melee\", \"N/A\" → \"Melee\" */\nexport function parseRange(s: string): number | \"Melee\" {\n const cleaned = s.replace(/[\"″]/g, \"\").trim();\n if (cleaned === \"\" || cleaned.toLowerCase() === \"melee\" || cleaned === \"N/A\") return \"Melee\";\n const n = parseInt(cleaned, 10);\n if (isNaN(n)) throw new Error(`Cannot parse range: \"${s}\"`);\n return n;\n}\n\n/** Parse BS/WS. \"3+\" → 3, \"N/A\" or \"\" → null */\nexport function parseBSWS(s: string): number | null {\n return parseTargetNumber(s);\n}\n\n/** Parse invulnerable save. \"4+\" → 4, \"\" → null */\nexport function parseInvuln(s: string): number | null {\n return parseTargetNumber(s);\n}\n\n/** Parse toughness, wounds, OC — always integers. */\nexport function parseIntStat(s: string): number {\n const cleaned = s.trim();\n if (cleaned === \"\" || cleaned === \"-\") return 0;\n const n = parseInt(cleaned, 10);\n if (isNaN(n)) throw new Error(`Cannot parse int stat: \"${s}\"`);\n return n;\n}\n\n/** Parse weapon keywords from the description field. \"Pistol, Hazardous\" → [\"Pistol\", \"Hazardous\"] */\nexport function parseWeaponKeywords(description: string): string[] {\n if (!description || description.trim() === \"\") return [];\n return description\n .split(\",\")\n .map((k) => k.trim())\n .filter((k) => k.length > 0);\n}\n\n/** Parse AP value. \"0\" → 0, \"-2\" → -2 */\nexport function parseAP(s: string): number {\n const cleaned = s.trim();\n if (cleaned === \"\" || cleaned === \"-\" || cleaned === \"0\") return 0;\n const n = parseInt(cleaned, 10);\n if (isNaN(n)) throw new Error(`Cannot parse AP: \"${s}\"`);\n return n;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view-selector.d.ts","sourceRoot":"","sources":["../../src/converters/view-selector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,UAAU,SAAS,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,CAAC,EAAE,CAAC;CACd;AAED,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EACvD,OAAO,EAAE,CAAC,EAAE,GACX,SAAS,CAAC,CAAC,CAAC,EAAE,CAkBhB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,aAAa,EAAE,EAC1B,kBAAkB,EAAE,MAAM,GACzB,MAAM,CA4BR;AAED,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EACvD,OAAO,EAAE,CAAC,EAAE,EACZ,SAAS,EAAE,MAAM,GAChB,CAAC,EAAE,CASL;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,EAC3D,OAAO,EAAE,CAAC,EAAE,EACZ,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,CAAC,EAAE,CAuBL"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view-selector.js","sourceRoot":"","sources":["../../src/converters/view-selector.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Handles multi-view data for shared units.\n *\n * Shared units (e.g., Chaos Land Raider) appear in multiple factions with the\n * same UUID. Their abilities, models, and weapons tables contain repeated entry\n * groups — one per faction \"view\". Views are delimited by the line number\n * resetting to 1.\n *\n * For World Eaters, the correct view is identified by having\n * \"Blessings of Khorne\" as a Faction-type ability.\n */\n\nexport interface SourceAbility {\n datasheet_id: string;\n line: string;\n ability_id: string;\n model: string;\n name: string;\n description: string;\n type: string;\n parameter: string;\n phases: string[];\n}\n\ninterface ViewGroup<T extends { line: string }> {\n index: number;\n entries: T[];\n}\n\n/** Split an array of line-numbered entries into view groups by line-number resets. */\nexport function splitIntoViews<T extends { line: string }>(\n entries: T[]\n): ViewGroup<T>[] {\n const views: ViewGroup<T>[] = [];\n let current: T[] = [];\n let lastLine = Infinity;\n\n for (const entry of entries) {\n const line = parseInt(entry.line, 10);\n if (line <= lastLine && current.length > 0) {\n views.push({ index: views.length, entries: current });\n current = [];\n }\n current.push(entry);\n lastLine = line;\n }\n if (current.length > 0) {\n views.push({ index: views.length, entries: current });\n }\n return views;\n}\n\n/**\n * Find the view index for a faction's shared unit.\n * Identifies the correct view by matching the faction's primary ability name\n * among the Faction-type abilities in each view.\n * Returns 0 for faction-exclusive units (single view).\n */\nexport function findFactionViewIndex(\n abilities: SourceAbility[],\n factionAbilityName: string\n): number {\n if (abilities.length === 0) return 0;\n const views = splitIntoViews(abilities);\n if (views.length === 1) return 0;\n\n for (const view of views) {\n const hasAbility = view.entries.some(\n (a) =>\n a.type === \"Faction\" &&\n a.name === factionAbilityName\n );\n if (hasAbility) return view.index;\n }\n\n // Some shared units (e.g., SM vehicles used by Grey Knights, or units shared\n // with Agents of the Imperium) have views with no Faction-type ability.\n // Use the first such view when no direct match is found.\n const emptyFactionViews = views.filter(\n (v) => !v.entries.some((a) => a.type === \"Faction\")\n );\n if (emptyFactionViews.length > 0) {\n return emptyFactionViews[0].index;\n }\n\n throw new Error(\n `No \"${factionAbilityName}\" faction ability found in ${views.length} views ` +\n `for datasheet ${abilities[0]?.datasheet_id}`\n );\n}\n\n/** Extract entries for a specific view index from a line-numbered array. */\nexport function getViewEntries<T extends { line: string }>(\n entries: T[],\n viewIndex: number\n): T[] {\n if (entries.length === 0) return [];\n const views = splitIntoViews(entries);\n if (viewIndex >= views.length) {\n throw new Error(\n `View index ${viewIndex} out of range (${views.length} views available)`\n );\n }\n return views[viewIndex].entries;\n}\n\n/**\n * Split points entries (no line field) into views for a shared unit.\n *\n * Points entries are ordered by view. For simple cases (1 entry per view),\n * indexing by viewIndex works. For multi-squad-size units, views are\n * delimited by the model count resetting (decreasing from prev entry).\n */\nexport function getPointsForView<T extends { models: string }>(\n entries: T[],\n viewIndex: number,\n numViews: number\n): T[] {\n if (numViews <= 1) return entries;\n\n // Try splitting by model count resets (decrease signals new view)\n const views: T[][] = [[]];\n for (let i = 0; i < entries.length; i++) {\n const cur = parseInt(entries[i].models, 10);\n const prev =\n i > 0 ? parseInt(entries[i - 1].models, 10) : 0;\n if (i > 0 && cur <= prev) {\n views.push([]);\n }\n views[views.length - 1].push(entries[i]);\n }\n\n if (viewIndex < views.length) {\n return views[viewIndex];\n }\n\n // Fallback: evenly divide\n const perView = Math.ceil(entries.length / numViews);\n const start = viewIndex * perView;\n return entries.slice(start, start + perView);\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weapon-dedup.d.ts","sourceRoot":"","sources":["../../src/converters/weapon-dedup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAWH,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,CAAC,EAAE,MAAM,CAAC;IACV,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IACxB,KAAK,EAAE;QACL,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QACnB,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACnB,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACnB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QACnB,EAAE,EAAE,MAAM,CAAC;QACX,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;KACpB,CAAC;IACF,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IACzB,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,YAAY,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CACtD;AAyDD;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC,EAC5C,WAAW,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAClD;IACD,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,kEAAkE;IAClE,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;CACzC,CAoEA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weapon-dedup.js","sourceRoot":"","sources":["../../src/converters/weapon-dedup.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Weapon profile merging and cross-unit deduplication.\n *\n * Source data splits multi-profile weapons into separate rows using an\n * en-dash delimiter: \"Plasma pistol – Standard\" / \"Plasma pistol – Supercharge\".\n * These become a single weapon entity with a profiles array.\n *\n * Cross-unit dedup: weapons with identical (name, type, all profile stats)\n * across different units are the same entity, referenced by a shared ID.\n */\n\nimport { nameToId } from \"./id-generator.js\";\nimport {\n parseRange,\n parseBSWS,\n parseStatValue,\n parseAP,\n parseWeaponKeywords,\n} from \"./stat-parser.js\";\n\nexport interface SourceWargear {\n datasheet_id: string;\n line: string;\n line_in_wargear: string;\n dice: string;\n name: string;\n description: string;\n range: string;\n type: string;\n A: string;\n BS_WS: string;\n S: string;\n AP: string;\n D: string;\n}\n\nexport interface WeaponProfile {\n name: string;\n range: number | \"Melee\";\n stats: {\n A: number | string;\n BS?: number | null;\n WS?: number | null;\n S: number | string;\n AP: number;\n D: number | string;\n };\n keywords: string[];\n}\n\nexport interface WeaponEntity {\n id: string;\n name: string;\n type: \"ranged\" | \"melee\";\n profiles: WeaponProfile[];\n game_version: { edition: string; dataslate: string };\n}\n\n// EN-DASH (U+2013) and regular hyphen used as profile separators\nconst PROFILE_SEPARATOR = /\\s*[\\u2013\\u2014-]\\s+/;\n\n/** Split \"Plasma pistol – Standard\" into { baseName: \"Plasma pistol\", profileName: \"Standard\" } */\nfunction splitProfileName(fullName: string): {\n baseName: string;\n profileName: string;\n} {\n const parts = fullName.split(PROFILE_SEPARATOR);\n if (parts.length >= 2) {\n return {\n baseName: parts[0].trim(),\n profileName: parts.slice(1).join(\" – \").trim(),\n };\n }\n return { baseName: fullName.trim(), profileName: fullName.trim() };\n}\n\n/** Build a single weapon profile from a source wargear row. */\nfunction buildProfile(row: SourceWargear, profileName: string): WeaponProfile {\n const range = parseRange(row.range);\n const isMelee = row.type === \"Melee\" || range === \"Melee\";\n\n const stats: WeaponProfile[\"stats\"] = {\n A: parseStatValue(row.A),\n S: parseStatValue(row.S),\n AP: parseAP(row.AP),\n D: parseStatValue(row.D),\n };\n\n if (isMelee) {\n stats.WS = parseBSWS(row.BS_WS);\n } else {\n stats.BS = parseBSWS(row.BS_WS);\n }\n\n return {\n name: profileName,\n range,\n stats,\n keywords: parseWeaponKeywords(row.description),\n };\n}\n\n/** Hash a weapon entity for cross-unit deduplication. */\nfunction weaponHash(name: string, type: string, profiles: WeaponProfile[]): string {\n const profileParts = profiles\n .map(\n (p) =>\n `${p.name}|${p.range}|${JSON.stringify(p.stats)}|${p.keywords.sort().join(\",\")}`\n )\n .sort();\n return `${name.toLowerCase()}|${type}|${profileParts.join(\";\")}`;\n}\n\n/**\n * Merge wargear rows for a single unit into weapon entities,\n * then deduplicate across all units.\n */\nexport function buildWeaponRegistry(\n allUnitWargear: Map<string, SourceWargear[]>,\n gameVersion: { edition: string; dataslate: string }\n): {\n weapons: WeaponEntity[];\n /** Maps (datasheetId) → Set of weapon entity IDs for that unit */\n unitWeaponIds: Map<string, Set<string>>;\n} {\n // Global dedup registry: hash → WeaponEntity\n const registry = new Map<string, WeaponEntity>();\n const unitWeaponIds = new Map<string, Set<string>>();\n\n for (const [datasheetId, rows] of allUnitWargear) {\n const weaponIds = new Set<string>();\n unitWeaponIds.set(datasheetId, weaponIds);\n\n // Group rows by base weapon name for profile merging\n const groups = new Map<string, { baseName: string; rows: SourceWargear[]; profileNames: string[] }>();\n\n for (const row of rows) {\n const { baseName, profileName } = splitProfileName(row.name);\n const key = baseName.toLowerCase();\n if (!groups.has(key)) {\n groups.set(key, { baseName, rows: [], profileNames: [] });\n }\n const group = groups.get(key)!;\n group.rows.push(row);\n group.profileNames.push(profileName);\n }\n\n for (const [, group] of groups) {\n const { baseName, rows: groupRows, profileNames } = group;\n const type = groupRows[0].type === \"Melee\" ? \"melee\" : \"ranged\";\n\n // Skip rows with obviously corrupt source data (shifted columns)\n const validRows = groupRows.filter((row, i) => {\n const s = parseStatValue(row.S);\n if (typeof s === \"number\" && s < 0) return false;\n const d = parseStatValue(row.D);\n if (type === \"ranged\" && d === 0 && row.D === \"\") return false;\n return true;\n });\n if (validRows.length === 0) continue;\n const validProfileNames = groupRows.map((row, i) => ({ row, name: profileNames[i] }))\n .filter(({ row }) => validRows.includes(row))\n .map(({ name }) => name);\n\n // If there's only one profile and its name matches the base name, use base name as profile name\n const profiles = validRows.map((row, i) => {\n const pName =\n validRows.length === 1 ? baseName : validProfileNames[i];\n return buildProfile(row, pName);\n });\n\n const hash = weaponHash(baseName, type, profiles);\n\n if (!registry.has(hash)) {\n const id = nameToId(baseName);\n registry.set(hash, {\n id,\n name: baseName,\n type: type as \"ranged\" | \"melee\",\n profiles,\n game_version: gameVersion,\n });\n }\n\n weaponIds.add(registry.get(hash)!.id);\n }\n }\n\n return {\n weapons: [...registry.values()],\n unitWeaponIds,\n };\n}\n"]}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-stage buff attribution by leave-one-out (LOO) recompute.
|
|
3
|
+
*
|
|
4
|
+
* The engine is closed-form, so the honest way to answer "how much did this
|
|
5
|
+
* buff lift this stage?" is to re-run {@link crunch} with that buff removed and
|
|
6
|
+
* diff the stage value. LOO is exactly correct through every non-linearity the
|
|
7
|
+
* pipeline has — the ±1 hit/wound caps, the wound-threshold table, save clamps,
|
|
8
|
+
* FNP, the models-killed cap — and it respects the resolver's non-additive
|
|
9
|
+
* rules for free: a buff that grants a keyword the weapon already carries (e.g.
|
|
10
|
+
* a second Sustained Hits 1) is deduped inside `resolveBuffs`, so its LOO delta
|
|
11
|
+
* comes out ≈ 0 rather than double-counting.
|
|
12
|
+
*
|
|
13
|
+
* Only *toggleable* buffs are attributed — abilities (army / detachment /
|
|
14
|
+
* stratagem / unit / attached / support) and manual UI toggles. The weapon's
|
|
15
|
+
* intrinsic keywords are auto-injected inside `crunch`, are not levers, and are
|
|
16
|
+
* never removed; they're reported by id in {@link AttributedStage.intrinsics}
|
|
17
|
+
* so a UI can explain an elevated baseline without splitting them out.
|
|
18
|
+
*
|
|
19
|
+
* @packageDocumentation
|
|
20
|
+
*/
|
|
21
|
+
import type { Dataset } from "../data/dataset.js";
|
|
22
|
+
import type { BuffSource } from "./buffs.js";
|
|
23
|
+
import { type EngineInput, type Stage } from "./engine.js";
|
|
24
|
+
/** One toggleable buff group's marginal effect on a single stage. */
|
|
25
|
+
export type StageLift = {
|
|
26
|
+
/** Representative source of the group (all its `Buff`s share a group key). */
|
|
27
|
+
source: BuffSource;
|
|
28
|
+
/** `stageValue(all buffs) − stageValue(all buffs minus this group)`. */
|
|
29
|
+
delta: number;
|
|
30
|
+
};
|
|
31
|
+
/** A pipeline stage with its value decomposed across the toggleable buffs. */
|
|
32
|
+
export type AttributedStage = {
|
|
33
|
+
name: Stage["name"];
|
|
34
|
+
/** Stage value with every buff on — identical to {@link crunch}'s stage. */
|
|
35
|
+
expected: number;
|
|
36
|
+
/** The engine's stage detail string, unchanged. */
|
|
37
|
+
detail: string;
|
|
38
|
+
/** Stage value with all groupable buffs removed (intrinsics kept). */
|
|
39
|
+
baseline: number;
|
|
40
|
+
/** Per-group marginal effect; groups whose |delta| ≤ epsilon are dropped. */
|
|
41
|
+
lifts: StageLift[];
|
|
42
|
+
/**
|
|
43
|
+
* `expected − baseline − Σ lifts`. Non-zero when buffs collide under a cap
|
|
44
|
+
* (two +1s sharing one ±1 cap each show ≈0 lift; the real +1 lands here),
|
|
45
|
+
* so a UI can surface it honestly as "overlap (capped)".
|
|
46
|
+
*/
|
|
47
|
+
residual: number;
|
|
48
|
+
/** Active weapon-keyword ids (intrinsic, auto-injected); display-only. */
|
|
49
|
+
intrinsics: string[];
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Decompose each pipeline stage of `crunch(input)` into the marginal lift of
|
|
53
|
+
* every toggleable buff group, via leave-one-out recompute.
|
|
54
|
+
*
|
|
55
|
+
* Cost is `groups + 2` `crunch` calls (full + baseline + one per group); the
|
|
56
|
+
* engine is closed-form, so this is cheap to call per weapon line.
|
|
57
|
+
*
|
|
58
|
+
* @param input The same {@link EngineInput} you'd pass to {@link crunch}.
|
|
59
|
+
* @param dataset Optional dataset override (defaults to the embedded one).
|
|
60
|
+
* @param opts `epsilon` — lifts/residuals at or below this magnitude are
|
|
61
|
+
* treated as zero (default 1e-6).
|
|
62
|
+
*/
|
|
63
|
+
export declare function attributeStages(input: EngineInput, dataset?: Dataset, opts?: {
|
|
64
|
+
epsilon?: number;
|
|
65
|
+
}): AttributedStage[];
|
|
66
|
+
//# sourceMappingURL=attribution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attribution.d.ts","sourceRoot":"","sources":["../../src/cruncher/attribution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAU,KAAK,WAAW,EAAqB,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AAEtF,qEAAqE;AACrE,MAAM,MAAM,SAAS,GAAG;IACtB,8EAA8E;IAC9E,MAAM,EAAE,UAAU,CAAC;IACnB,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,8EAA8E;AAC9E,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACpB,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AA4BF;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,WAAW,EAClB,OAAO,CAAC,EAAE,OAAO,EACjB,IAAI,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1B,eAAe,EAAE,CA2DnB"}
|