109 lines
3.3 KiB
Python
109 lines
3.3 KiB
Python
from __future__ import annotations
|
|
import csv
|
|
import os
|
|
import json
|
|
from typing import Optional, Dict
|
|
from flask import current_app
|
|
|
|
# Cache: "name in lowercase" -> type_id
|
|
_BP_NAME2ID: Dict[str, int] = {}
|
|
# Cache: product type id -> (product name)
|
|
_ID2NAME: Dict[int, str] = {}
|
|
# Optional benutzerdefinierte Überschreibungen
|
|
# Format: { "Structure Market Network": 123456, ... }
|
|
_USER_MAP: Dict[str, int] = {}
|
|
|
|
|
|
def _data_path(filename: str) -> str:
|
|
return os.path.join(current_app.root_path, "data", filename)
|
|
|
|
|
|
def _ensure_loaded() -> None:
|
|
"""Liest typeIDs.csv einmalig ein und baut schnelle Nachschlage-Maps auf."""
|
|
global _BP_NAME2ID, _ID2NAME, _USER_MAP
|
|
if _BP_NAME2ID and _ID2NAME:
|
|
return
|
|
|
|
# Benutzer-Overrides (optional)
|
|
try:
|
|
override = _data_path("blueprints.json")
|
|
if os.path.isfile(override):
|
|
with open(override, "r", encoding="utf-8") as f:
|
|
_USER_MAP = json.load(f) or {}
|
|
except Exception:
|
|
_USER_MAP = {}
|
|
|
|
csv_path = _data_path("typeIDs.csv")
|
|
if not os.path.isfile(csv_path):
|
|
return
|
|
|
|
try:
|
|
with open(csv_path, "r", encoding="utf-8", newline="") as f:
|
|
# Datei ist ;-separiert: id;name;group_id;iconID;graphicID
|
|
reader = csv.reader(f, delimiter=";")
|
|
header = next(reader, None) # "id;name;group_id;iconID;graphicID"
|
|
for row in reader:
|
|
if not row or len(row) < 2:
|
|
continue
|
|
try:
|
|
tid = int(row[0])
|
|
except Exception:
|
|
continue
|
|
name = (row[1] or "").strip()
|
|
if not name:
|
|
continue
|
|
_ID2NAME[tid] = name
|
|
key = name.lower()
|
|
# Merke auch die Blaupause separat (Name endet exakt auf " Blueprint")
|
|
if key.endswith(" blueprint"):
|
|
_BP_NAME2ID[key] = tid
|
|
except Exception:
|
|
# Map bleibt ggf. leer; Aufrufer bekommen dann None zurück
|
|
pass
|
|
|
|
|
|
def product_name_by_id(type_id: int) -> Optional[str]:
|
|
"""Gibt den Produktnamen zur TypeID zurück (aus typeIDs.csv)."""
|
|
_ensure_loaded()
|
|
return _ID2NAME.get(type_id)
|
|
|
|
|
|
def resolve_blueprint_id(product_name: str) -> Optional[int]:
|
|
"""
|
|
Ermittelt die Blueprint-TypeID zu einem *Produktnamen*.
|
|
Regeln:
|
|
1) Benutzer-Override (blueprints.json)
|
|
2) Exakter Treffer "<Produktname> Blueprint" in typeIDs.csv
|
|
3) Weicher Treffer (enthält Produktname & 'blueprint')
|
|
"""
|
|
if not product_name:
|
|
return None
|
|
|
|
_ensure_loaded()
|
|
|
|
# 1) User-Override
|
|
if product_name in _USER_MAP:
|
|
return int(_USER_MAP[product_name])
|
|
|
|
wanted_exact = f"{product_name} Blueprint".lower()
|
|
|
|
# 2) Exakter Treffer
|
|
if wanted_exact in _BP_NAME2ID:
|
|
return _BP_NAME2ID[wanted_exact]
|
|
|
|
# 3) Weiche Suche
|
|
prod_l = product_name.lower()
|
|
for k, tid in _BP_NAME2ID.items():
|
|
if prod_l in k and "blueprint" in k:
|
|
return tid
|
|
|
|
return None
|
|
|
|
|
|
def resolve_blueprint_id_by_product_id(product_type_id: int) -> Optional[int]:
|
|
"""Ermittelt die Blueprint-TypeID aus der *Produkt*-TypeID."""
|
|
name = product_name_by_id(int(product_type_id))
|
|
if not name:
|
|
return None
|
|
return resolve_blueprint_id(name)
|