#!/usr/bin/env python3 from __future__ import annotations import argparse import json from pathlib import Path def crop_icon(icon: str | None) -> list[int | str] | None: if not icon: return None lines = icon.split("\n") xs: list[int] = [] ys: list[int] = [] for y, line in enumerate(lines): for x, char in enumerate(line): if char != " ": xs.append(x) ys.append(y) if not xs: return [0, 0, ""] min_x = min(xs) max_x = max(xs) min_y = min(ys) max_y = max(ys) cropped_lines = [line[min_x : max_x + 1].rstrip() for line in lines[min_y : max_y + 1]] return [min_x, min_y, "\n".join(cropped_lines)] def compact_chains(data: object) -> list[list[object]]: if isinstance(data, dict): chains = data.get("chains") else: chains = data if not isinstance(chains, list): raise ValueError("Input JSON does not contain a valid chains array") compact: list[list[object]] = [] for chain in chains: if isinstance(chain, list): if len(chain) == 2 and isinstance(chain[1], list): compact.append(chain) continue if len(chain) == 3 and isinstance(chain[1], int) and isinstance(chain[2], list): compact.append([chain[0], chain[2]]) continue raise ValueError("Invalid compact chain entry") if not isinstance(chain, dict): raise ValueError("Expected verbose or compact chain entries as input") items = chain.get("items") if not isinstance(items, list) or not items: continue base_id = chain["base_id"] compact_items: list[list[object]] = [] for item in items: compact_items.append([ item["item_id"], crop_icon(item.get("icon_nfp_16x16")), ]) compact.append([base_id, compact_items]) return compact def main() -> int: parser = argparse.ArgumentParser( description="Rewrite atc_chains.json into a compact format used by compcount.lua." ) parser.add_argument("source", nargs="?", default="atc_chains_uncompressed.json") parser.add_argument("destination", nargs="?", default="atc_chains.json") args = parser.parse_args() source_path = Path(args.source) destination_path = Path(args.destination) original_text = source_path.read_text(encoding="utf-8") data = json.loads(original_text) compact = {"chains": compact_chains(data)} compact_text = json.dumps(compact, separators=(",", ":")) destination_path.write_text(compact_text, encoding="utf-8") print(f"Compacted {source_path} -> {destination_path}") print(f"Old size: {len(original_text.encode('utf-8'))} bytes") print(f"New size: {len(compact_text.encode('utf-8'))} bytes") return 0 if __name__ == "__main__": raise SystemExit(main())