fix: link systems to the folder of their files

This commit is contained in:
Abdessamad Derraz committed 2026-10-16 14:31:46 +02:00
1 parent 53621fa689
commit 606141a61d
2 files changed
+94 -15

No files matched your search

+34 -15
View File
@@ -39,6 +39,8 @@ from common import (
load_emulator_profiles,
load_provenance_snapshots,
require_yaml,
resolution_is_hash_exact,
resolve_local_file,
resolve_platform_cores,
unique_emulator_profiles,
write_if_changed as _write_artifact,
@@ -121,6 +123,26 @@ CLS_LABELS = {
}
def _system_folder(
files: list[dict], db: dict, name_consoles: dict[str, set[tuple[str, str]]]
) -> tuple[str, str] | None:
"""The bios/<manufacturer>/<console> folder a system's files live in."""
votes: dict[tuple[str, str], int] = {}
for fe in files:
local, status = resolve_local_file(fe, db)
parts = (local or "").split("/")
if len(parts) >= 4 and parts[0] == "bios" and resolution_is_hash_exact(status):
place = (parts[1], parts[2])
votes[place] = votes.get(place, 0) + 1
if votes:
return max(sorted(votes), key=lambda place: votes[place])
for fe in files:
places = name_consoles.get(fe.get("name", ""), set())
if len(places) == 1:
return next(iter(places))
return None
def _build_system_page_map_from_data(
manufacturers: dict,
coverages: dict,
@@ -130,15 +152,14 @@ def _build_system_page_map_from_data(
Uses platform file paths to trace system_id -> bios directory -> manufacturer page.
"""
db.get("files", {})
db.get("indexes", {}).get("by_name", {})
# Build reverse index: filename -> (manufacturer, console) from bios/ structure
file_to_console: dict[str, tuple[str, str]] = {}
# Every console folder a filename sits in. A name in one folder only can
# place a system; a name in several says nothing (MiSTer's boot.rom lives
# under a dozen consoles, and the last one written used to win).
name_consoles: dict[str, set[tuple[str, str]]] = {}
for mfr, consoles in manufacturers.items():
for console, entries in consoles.items():
for entry in entries:
file_to_console[entry["name"]] = (mfr, console)
name_consoles.setdefault(entry["name"], set()).add((mfr, console))
# Build normalized console name index for fuzzy matching
console_norm: dict[str, tuple[str, str]] = {}
@@ -170,15 +191,13 @@ def _build_system_page_map_from_data(
for sys_id, system in config.get("systems", {}).items():
if sys_id in _system_page_map:
continue
# Strategy 1: trace via file paths in DB
for fe in system.get("files", []):
fname = fe.get("name", "")
if fname in file_to_console:
mfr, console = file_to_console[fname]
slug = mfr.lower().replace(" ", "-")
_system_page_map[sys_id] = (slug, console)
break
if sys_id in _system_page_map:
# Strategy 1: the folder holding the files the system declares,
# found by content; most votes win. A bare name stands in only
# where the collection files it in a single console.
place = _system_folder(system.get("files", []), db, name_consoles)
if place is not None:
mfr, console = place
_system_page_map[sys_id] = (mfr.lower().replace(" ", "-"), console)
continue
# Strategy 2: fuzzy match system_id against console directory names
if sys_id in console_norm:
+60
View File
@@ -0,0 +1,60 @@
"""A platform system links to the page of the folder its files live in.
The site mapped each system by the bare name of its first file, the last
console written winning: MiSTer's boot.rom sits under a dozen consoles, so
wonderswan and tiger-game-com linked to VideoBrain, ngpc and tandy-coco to
TI-99. Reads the repository: skips when the database is absent.
"""
from __future__ import annotations
import os
import sys
import unittest
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO_ROOT / "scripts"))
import generate_site as gs # noqa: E402
class LinksFollowContent(unittest.TestCase):
def test_an_ambiguous_name_places_nothing(self):
names = {"boot.rom": {("VideoBrain", "VideoBrain"), ("Bandai", "WonderSwan")}}
files = [{"name": "boot.rom", "sha1": "0" * 40}]
self.assertIsNone(gs._system_folder(files, {"files": {}, "indexes": {}}, names))
names["only.rom"] = {("Bandai", "WonderSwan")}
files.append({"name": "only.rom"})
self.assertEqual(
gs._system_folder(files, {"files": {}, "indexes": {}}, names),
("Bandai", "WonderSwan"),
)
def test_mister_systems(self):
if not (REPO_ROOT / "database.json").exists():
self.skipTest("database.json is not built")
previous = os.getcwd()
os.chdir(REPO_ROOT)
self.addCleanup(os.chdir, previous)
from common import load_database, load_platform_config
db = load_database("database.json")
config = load_platform_config("misterfpga")
names: dict = {}
for mfr, consoles in gs._group_by_manufacturer(db).items():
for console, entries in consoles.items():
for entry in entries:
names.setdefault(entry["name"], set()).add((mfr, console))
expected = {"wonderswan": "WonderSwan", "ngpc": "Neo Geo Pocket"}
for sys_id, console in expected.items():
system = config["systems"].get(sys_id)
if system is None:
continue
with self.subTest(system=sys_id):
place = gs._system_folder(system.get("files", []), db, names)
self.assertEqual(place and place[1], console)
if __name__ == "__main__":
unittest.main()