From 38824658bf1d18093f5fc47bb8cb5564bdfcfa85 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Tue, 27 Oct 2026 15:37:40 +0100 Subject: [PATCH] feat: show pack probes on the site The Measurements page lists the latest probe of each platform, system, install path and core, and each platform page shows its own under Tested. --- scripts/generate_site.py | 5 +++ scripts/sitemeasurements.py | 76 +++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/scripts/generate_site.py b/scripts/generate_site.py index dd04f5697..f9da8e71b 100644 --- a/scripts/generate_site.py +++ b/scripts/generate_site.py @@ -4247,6 +4247,7 @@ def generate_platform_page( lines.extend(["", *_platform_install_block(name, display, on_card)]) lines.extend(["", _pack_buttons(name, f"Download {display} Pack", display=display)]) lines.append("") + lines.extend(sitemeasurements.pack_tested_section(_PACK_ITEMS.get(name, []))) # The declaration behind each detail, by system and name in declaration # order: keyed by name alone, the last of MiSTer's 23 boot.rom gave its @@ -8439,6 +8440,8 @@ _DATA_MEMBERS: dict[str, dict[str, dict]] = {} _DATA_REVISIONS: dict[str, dict] = {} # The measurement index items of each emulator, for its Tested block. _MEASUREMENT_ITEMS: dict[str, list[dict]] = {} +# Pack probes by platform key, for the Tested block of a platform page. +_PACK_ITEMS: dict[str, list[dict]] = {} # The emulator pages that list each data directory, by ref. _DATA_READERS: dict[str, list[tuple[str, str]]] = {} @@ -11171,6 +11174,8 @@ def _generate(args: argparse.Namespace) -> None: _record(path) _MEASUREMENT_ITEMS.clear() _MEASUREMENT_ITEMS.update(sitemeasurements.by_emulator(measured.index)) + _PACK_ITEMS.clear() + _PACK_ITEMS.update(sitemeasurements.by_platform(measured.index)) print(f" {measured.index['records']} records, {measured.index['count']} tests") write_if_changed(str(docs / sitemeasurements.EXPLORER_PAGE), sitemeasurements.generate_explorer_page(measured.index) + reference_next()) diff --git a/scripts/sitemeasurements.py b/scripts/sitemeasurements.py index ac420682f..c0b502dbc 100644 --- a/scripts/sitemeasurements.py +++ b/scripts/sitemeasurements.py @@ -166,6 +166,80 @@ def campaign_summary(root: Path, stored: list[mr.Stored], source: dict | None) - "open": open_items} +def pack_summary(root: Path, source: dict | None) -> list[dict]: + """The latest pack probe of each platform, install path, system, core + and game, with a link to its line.""" + latest: dict[tuple, tuple[int, dict]] = {} + for number, line in enumerate(mr.read_campaign(root, mr.PACK_PROBES), 1): + key = (line["platform"], line["install"], line["system"], line["core"]["file"], + line["content"]["label"]) + latest[key] = (number, line) + items = [] + for key in sorted(latest): + number, line = latest[key] + url = (permalink(source["repo"], source["commit"], mr.records_path(mr.PACK_PROBES), number) + if source and source.get("commit") else None) + items.append({ + "platform": line["platform"], "platform_version": line["platform_version"], + "install": line["install"], "system": line["system"], "emulator": line["emulator"], + "core": line["core"]["file"].removesuffix("_libretro.so"), + "content": line["content"]["label"], "verdict": line["verdict"], + "date": line["probed_at"], "opened": len(line["files_opened"]), + "findings": len(line["findings"]), "id": line["id"], "record_url": url, + }) + return items + + +def by_platform(index: dict) -> dict[str, list[dict]]: + out: dict[str, list[dict]] = {} + for item in index.get("packs") or (): + out.setdefault(item["platform"], []).append(item) + return out + + +INSTALL_WORDS = {"pack": "pack", "installer": "installer"} + + +def _pack_row(item: dict, platform_column: bool) -> str: + link = f"[line]({item['record_url']})" if item["record_url"] else _code(item["id"]) + cells = ([_plain(item["platform"])] if platform_column else []) + [ + _plain(item["system"]), INSTALL_WORDS[item["install"]], _code(item["core"]), + _plain(item["content"]), f"`{item['verdict']}`", str(item["findings"]), link] + return "| " + " | ".join(cells) + " |" + + +PACKS_INTRO = ("A game started with the platform's BIOS folder as a user gets it, from the " + "pack or from the installer ([how]({prefix}{page}#packs)). A finding is a file " + "the core looked for that the folder lacks or holds under another path.") +PLATFORM_INTRO = "Games started with this BIOS folder as you install it ([how]({prefix}{page}#packs))." + + +def packs_section(items: list[dict], heading: str = "## Packs", platform_column: bool = True, + prefix: str = "", intro: str = PACKS_INTRO) -> list[str]: + """Packs tested the way a user installs them: one row per platform, + system, install path and core.""" + if not items: + return [] + columns = (["Platform"] if platform_column else []) + [ + "System", "Installed by", "Core", "Game", "Verdict", "Findings", "Record"] + return [ + heading, + "", + intro.format(prefix=prefix, page=METHOD_PAGE), + "", + "| " + " | ".join(columns) + " |", + "|" + "|".join("---" for _ in columns) + "|", + *(_pack_row(item, platform_column) for item in + sorted(items, key=lambda i: (i["platform"], i["system"], i["install"], i["core"], i["content"]))), + "", + ] + + +def pack_tested_section(items: list[dict]) -> list[str]: + """The Tested block of a platform page.""" + return packs_section(items, "## Tested", platform_column=False, prefix="../", intro=PLATFORM_INTRO) + + # Characters a campaign value could use to leave its place on the page: HTML # and MDX syntax ({ } opens an expression), code spans, emphasis and links. _UNSAFE = {"&": "&", "<": "<", ">": ">", "{": "{", "}": "}", "`": "`", @@ -460,6 +534,7 @@ def build(public: Path, root: Path = ROOT, emulators_dir: Path = ROOT / "emulato profiles = load_profiles(emulators_dir) index = build_index(stored, source, profiles, system_names) index["campaign"] = campaign_summary(root, stored, source) + index["packs"] = pack_summary(root, source) paths = [public / INDEX_PATH] (public / INDEX_PATH).parent.mkdir(parents=True, exist_ok=True) write_if_changed(str(public / INDEX_PATH), @@ -585,6 +660,7 @@ def generate_explorer_page(index: dict) -> str: "", "", "", + *packs_section(index.get("packs") or []), *campaign_section(index.get("campaign")), ])