Files
psopeeps_site/scripts/import-newserv-drop-tables.py
T
2026-06-13 17:43:19 -04:00

188 lines
5.2 KiB
Python
Executable File

#!/usr/bin/env python3
import json
import re
from pathlib import Path
NEWSERV = Path.home() / ".local/share/github/psopeeps-newserv"
PEEPS_OUT = Path("site/generated/drops/peeps")
HARDCORE_OUT = Path("site/generated/drops/hardcore")
PEEPS_TABLES = {
"v1": NEWSERV / "system/tables/rare-table-v1.json",
"v2": NEWSERV / "system/tables/rare-table-v2.json",
"v3": NEWSERV / "system/tables/rare-table-v3.json",
"bb": NEWSERV / "system/tables/rare-table-v4.json",
}
HARDCORE_TABLES = {
"bb": Path("source-drops/hardcore/rare-table-v4.json"),
}
def strip_json_comments(text):
out = []
in_str = False
esc = False
i = 0
while i < len(text):
c = text[i]
n = text[i + 1] if i + 1 < len(text) else ""
if in_str:
out.append(c)
if esc:
esc = False
elif c == "\\":
esc = True
elif c == '"':
in_str = False
i += 1
continue
if c == '"':
in_str = True
out.append(c)
i += 1
continue
if c == "/" and n == "/":
while i < len(text) and text[i] not in "\r\n":
i += 1
continue
out.append(c)
i += 1
return "".join(out)
def quote_hex_numbers(text):
return re.sub(r'(?<!["\w])0x[0-9A-Fa-f]+', lambda m: f'"{m.group(0)}"', text)
def remove_trailing_commas(text):
out = []
in_str = False
esc = False
i = 0
while i < len(text):
c = text[i]
if in_str:
out.append(c)
if esc:
esc = False
elif c == "\\":
esc = True
elif c == '"':
in_str = False
i += 1
continue
if c == '"':
in_str = True
out.append(c)
i += 1
continue
if c == ",":
j = i + 1
while j < len(text) and text[j] in " \t\r\n":
j += 1
if j < len(text) and text[j] in "}]":
i += 1
continue
out.append(c)
i += 1
return "".join(out)
def load_newserv_jsonish(path):
text = path.read_text(encoding="utf-8", errors="replace")
text = strip_json_comments(text)
text = quote_hex_numbers(text)
text = remove_trailing_commas(text)
return json.loads(text)
def normalize_item_code(value):
if isinstance(value, str) and value.startswith("0x"):
return "0x" + value[2:].upper()
if isinstance(value, int):
return f"0x{value:06X}"
return str(value)
def flatten_table(version, table):
rows = []
for game_mode, episodes in table.items():
if not isinstance(episodes, dict):
continue
for episode, difficulties in episodes.items():
if not isinstance(difficulties, dict):
continue
for difficulty, section_ids in difficulties.items():
if not isinstance(section_ids, dict):
continue
for section_id, sources in section_ids.items():
if not isinstance(sources, dict):
continue
for source, drops in sources.items():
if not isinstance(drops, list):
continue
for drop in drops:
if not isinstance(drop, list) or len(drop) < 2:
continue
rows.append({
"version": version,
"mode": str(game_mode),
"episode": str(episode),
"difficulty": str(difficulty),
"section_id": str(section_id),
"source": str(source),
"rate": str(drop[0]),
"item_code": normalize_item_code(drop[1]),
"item": str(drop[2]) if len(drop) >= 3 and drop[2] else "",
})
return rows
def write_group(mode, label, tables, out_dir):
out_dir.mkdir(parents=True, exist_ok=True)
index = {
"mode": mode,
"label": label,
"tables": [],
}
labels = {"v1": "V1", "v2": "V2", "v3": "V3", "bb": "BB"}
for version, src in tables.items():
table = load_newserv_jsonish(src)
rows = flatten_table(version, table)
out_name = f"{version}.json"
out_path = out_dir / out_name
out_path.write_text(json.dumps(rows, indent=2, sort_keys=True) + "\n")
index["tables"].append({
"version": version,
"label": labels[version],
"path": out_name,
"rows": len(rows),
})
print(f"{mode} {version}: {len(rows)} rows -> {out_path}")
index_path = out_dir / "index.json"
index_path.write_text(json.dumps(index, indent=2, sort_keys=True) + "\n")
print(f"{mode} index -> {index_path}")
def main():
write_group("peeps", "Peeps", PEEPS_TABLES, PEEPS_OUT)
write_group("hardcore", "Hardcore", HARDCORE_TABLES, HARDCORE_OUT)
if __name__ == "__main__":
main()