mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-04-13 12:22:33 -05:00
115 lines
4.1 KiB
Python
115 lines
4.1 KiB
Python
"""Exporter for RetroBat batocera-systems.json format.
|
|
|
|
Produces JSON matching the exact format of
|
|
RetroBat-Official/emulatorlauncher/batocera-systems/Resources/batocera-systems.json:
|
|
- System keys with "name" and "biosFiles" fields
|
|
- Each biosFile has "md5" before "file" (matching original key order)
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from collections import OrderedDict
|
|
from pathlib import Path
|
|
|
|
from .base_exporter import BaseExporter
|
|
|
|
|
|
|
|
|
|
class Exporter(BaseExporter):
|
|
"""Export truth data to RetroBat batocera-systems.json format."""
|
|
|
|
@staticmethod
|
|
def platform_name() -> str:
|
|
return "retrobat"
|
|
|
|
def export(
|
|
self,
|
|
truth_data: dict,
|
|
output_path: str,
|
|
scraped_data: dict | None = None,
|
|
) -> None:
|
|
native_map: dict[str, str] = {}
|
|
if scraped_data:
|
|
for sys_id, sys_data in scraped_data.get("systems", {}).items():
|
|
nid = sys_data.get("native_id")
|
|
if nid:
|
|
native_map[sys_id] = nid
|
|
|
|
output: OrderedDict[str, dict] = OrderedDict()
|
|
|
|
systems = truth_data.get("systems", {})
|
|
for sys_id in sorted(systems):
|
|
sys_data = systems[sys_id]
|
|
files = sys_data.get("files", [])
|
|
if not files:
|
|
continue
|
|
|
|
native_id = native_map.get(sys_id, sys_id)
|
|
scraped_sys = scraped_data.get("systems", {}).get(sys_id) if scraped_data else None
|
|
display_name = self._display_name(sys_id, scraped_sys)
|
|
bios_files: list[OrderedDict] = []
|
|
|
|
for fe in files:
|
|
name = fe.get("name", "")
|
|
if name.startswith("_") or self._is_pattern(name):
|
|
continue
|
|
dest = self._dest(fe)
|
|
md5 = fe.get("md5", "")
|
|
if isinstance(md5, list):
|
|
md5 = md5[0] if md5 else ""
|
|
|
|
# Original format requires md5 for every entry
|
|
if not md5:
|
|
continue
|
|
entry: OrderedDict[str, str] = OrderedDict()
|
|
entry["md5"] = md5
|
|
entry["file"] = f"bios/{dest}"
|
|
bios_files.append(entry)
|
|
|
|
if bios_files:
|
|
if native_id in output:
|
|
existing_files = {e.get("file") for e in output[native_id]["biosFiles"]}
|
|
for entry in bios_files:
|
|
if entry.get("file") not in existing_files:
|
|
output[native_id]["biosFiles"].append(entry)
|
|
else:
|
|
sys_entry: OrderedDict[str, object] = OrderedDict()
|
|
sys_entry["name"] = display_name
|
|
sys_entry["biosFiles"] = bios_files
|
|
output[native_id] = sys_entry
|
|
|
|
Path(output_path).write_text(
|
|
json.dumps(output, indent=2, ensure_ascii=False) + "\n",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
def validate(self, truth_data: dict, output_path: str) -> list[str]:
|
|
data = json.loads(Path(output_path).read_text(encoding="utf-8"))
|
|
|
|
exported_files: set[str] = set()
|
|
for sys_data in data.values():
|
|
for bf in sys_data.get("biosFiles", []):
|
|
path = bf.get("file", "")
|
|
stripped = path.removeprefix("bios/")
|
|
exported_files.add(stripped)
|
|
basename = path.split("/")[-1] if "/" in path else path
|
|
exported_files.add(basename)
|
|
|
|
issues: list[str] = []
|
|
for sys_data in truth_data.get("systems", {}).values():
|
|
for fe in sys_data.get("files", []):
|
|
name = fe.get("name", "")
|
|
if name.startswith("_") or self._is_pattern(name):
|
|
continue
|
|
md5 = fe.get("md5", "")
|
|
if isinstance(md5, list):
|
|
md5 = md5[0] if md5 else ""
|
|
if not md5:
|
|
continue
|
|
dest = self._dest(fe)
|
|
if name not in exported_files and dest not in exported_files:
|
|
issues.append(f"missing: {name}")
|
|
return issues
|