179 lines
4.9 KiB
Python
Executable File
179 lines
4.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import json
|
|
import re
|
|
from pathlib import Path
|
|
|
|
NEWSERV = Path.home() / ".local/share/github/psopeeps-newserv"
|
|
OUT = Path("site/generated/drops/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",
|
|
}
|
|
|
|
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 main():
|
|
OUT.mkdir(parents=True, exist_ok=True)
|
|
|
|
index = {
|
|
"mode": "peeps",
|
|
"label": "Peeps",
|
|
"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 / 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"{version}: {len(rows)} rows -> {out_path}")
|
|
|
|
index_path = OUT / "index.json"
|
|
index_path.write_text(json.dumps(index, indent=2, sort_keys=True) + "\n")
|
|
print(f"index -> {index_path}")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|