Python library for parsing BattleScribe/NewRecruit roster JSON. Extracted from Nachmund Tracker's processJSON, ported JS→Python. - parse_roster(json_string) / parse_roster_file(path) → RosterSummary - Extracts: unit name, pts, CP, model count, weapon breakdown per model variant - Handles: variable-model-count units, nested costs, compound upgrades - Unicode apostrophe-safe unit lookup (find_unit) - to_dict() for JSON serialization - 8/8 tests passing on real roster data (27 units, 2815pts)
67 lines
1.9 KiB
Markdown
67 lines
1.9 KiB
Markdown
# bs-roster-parser
|
||
|
||
Python library for parsing BattleScribe/NewRecruit roster JSON into flat unit lists with costs, model counts, and weapon breakdowns.
|
||
|
||
## Install
|
||
|
||
```bash
|
||
pip install git+https://git.homelab.local/kaykayyali/bs-roster-parser.git
|
||
```
|
||
|
||
Or clone and install locally:
|
||
```bash
|
||
git clone https://git.homelab.local/kaykayyali/bs-roster-parser.git
|
||
cd bs-roster-parser
|
||
pip install -e .
|
||
```
|
||
|
||
## Usage
|
||
|
||
```python
|
||
from bs_roster_parser import parse_roster_file
|
||
|
||
# Parse a roster file
|
||
summary = parse_roster_file("roster.json")
|
||
|
||
# Access units
|
||
for unit in summary.units:
|
||
print(f"{unit.name}: {unit.pts}pts, {unit.model_count} models")
|
||
for model in unit.breakdown:
|
||
print(f" {model.name} ×{model.count}")
|
||
if model.weapons:
|
||
print(f" Weapons: {', '.join(model.weapons)}")
|
||
|
||
# Aggregate stats
|
||
print(f"Total: {summary.total_pts}pts, {summary.total_cp} CP")
|
||
print(f"Units: {summary.unit_count}, Models: {summary.total_models}")
|
||
|
||
# Find a specific unit
|
||
gaunt = summary.find_unit("Gaunt's Ghosts")
|
||
|
||
# Export to dict/JSON
|
||
import json
|
||
print(json.dumps(summary.to_dict(), indent=2))
|
||
```
|
||
|
||
## What it extracts
|
||
|
||
Each unit includes:
|
||
- **name** — display name (custom name if set, otherwise catalogue name)
|
||
- **pts** — total points cost (including descendant costs for variable-model-count units)
|
||
- **cp** — crusade points
|
||
- **model_count** — total models (summed from child model nodes)
|
||
- **breakdown** — per-model-variant list with names, counts, and detected weapons
|
||
- **type** — `unit` or `model`
|
||
|
||
The roster summary includes:
|
||
- **roster_name**, **game_system**, **faction** (detected from first force)
|
||
- **points_limit** (from costLimits)
|
||
- **total_pts**, **total_cp**, **unit_count**, **total_models**
|
||
|
||
## Origin
|
||
|
||
Extracted from the [Nachmund Tracker](https://git.homelab.local/kaykayyali/Nachmund-Tracker) project's `processJSON` function, ported from JavaScript to Python and generalized as a reusable library.
|
||
|
||
## License
|
||
|
||
MIT |