79 lines
3 KiB
Python
79 lines
3 KiB
Python
"""
|
|
Production - The Idle Game: Sector & Product Registry Loader
|
|
Parses modular JS sector files into authoritative Python dictionaries.
|
|
Ensures single-source-of-truth between frontend definitions and backend simulation.
|
|
"""
|
|
|
|
import os
|
|
import glob
|
|
import json
|
|
import re
|
|
|
|
def js_to_dict(js_code: str):
|
|
"""Converts a standard JavaScript object/array literal to a Python dict/list."""
|
|
# Remove single-line comments
|
|
clean = re.sub(r'//.*', '', js_code)
|
|
# Quote unquoted property keys: e.g. id: 'wheat' -> "id": "wheat"
|
|
clean = re.sub(r'([{,]\s*)([a-zA-Z0-9_]+)\s*:', r'\1"\2":', clean)
|
|
# Replace single quotes with double quotes
|
|
clean = clean.replace("'", '"')
|
|
# Remove trailing commas before } or ]
|
|
clean = re.sub(r',\s*([}\]])', r'\1', clean)
|
|
return json.loads(clean)
|
|
|
|
def get_sectors_directory() -> str:
|
|
"""Finds the directory containing sector .js files whether in local dev or Docker."""
|
|
candidates = [
|
|
os.path.join(os.path.dirname(__file__), "..", "frontend", "js", "data", "sectors"), # Local repo dev
|
|
os.path.join(os.path.dirname(__file__), "sectors"), # Docker mount /app/sectors
|
|
"/app/sectors", # Standard container mount
|
|
os.path.abspath("frontend/js/data/sectors")
|
|
]
|
|
for c in candidates:
|
|
if os.path.isdir(c) and glob.glob(os.path.join(c, "*.js")):
|
|
return os.path.abspath(c)
|
|
return ""
|
|
|
|
def load_all_sectors_and_products():
|
|
"""
|
|
Scans the sectors directory, parsing all modular JS sector files.
|
|
Returns:
|
|
(sectors_dict, products_dict)
|
|
"""
|
|
sec_dir = get_sectors_directory()
|
|
sectors = {}
|
|
products = {}
|
|
|
|
if not sec_dir:
|
|
print("[WARNING] No sector files directory found! Falling back to empty catalog.")
|
|
return sectors, products
|
|
|
|
for file_path in glob.glob(os.path.join(sec_dir, "*.js")):
|
|
try:
|
|
with open(file_path, "r", encoding="utf-8") as f:
|
|
content = f.read()
|
|
|
|
# Parse Sector Object
|
|
sec_match = re.search(r'export\s+const\s+[A-Z_]+_SECTOR\s*=\s*({[\s\S]*?});', content)
|
|
if sec_match:
|
|
sec_obj = js_to_dict(sec_match.group(1))
|
|
sectors[sec_obj["id"]] = sec_obj
|
|
|
|
# Parse Products Array
|
|
prod_match = re.search(r'export\s+const\s+[A-Z_]+_PRODUCTS\s*=\s*(\[[\s\S]*?\]);', content)
|
|
if prod_match:
|
|
prod_list = js_to_dict(prod_match.group(1))
|
|
for p in prod_list:
|
|
products[p["id"]] = p
|
|
|
|
except Exception as e:
|
|
print(f"[ERROR] Failed to parse sector file {file_path}: {e}")
|
|
|
|
return sectors, products
|
|
|
|
if __name__ == '__main__':
|
|
s, p = load_all_sectors_and_products()
|
|
print(f"Loaded {len(s)} sectors and {len(p)} products.")
|
|
for sid, sobj in s.items():
|
|
count = sum(1 for prod in p.values() if prod.get('sector') == sid)
|
|
print(f" - {sobj['name']} ({sid}): {count} commodities")
|