diff --git a/scripts/common.py b/scripts/common.py index 760eb815..e4cfc93d 100644 --- a/scripts/common.py +++ b/scripts/common.py @@ -773,6 +773,13 @@ def load_emulator_profiles( return profiles +def unique_emulator_profiles(profiles: dict[str, dict]) -> dict[str, dict]: + """Profiles counting as distinct emulators (aliases and tests excluded).""" + return { + k: v for k, v in profiles.items() if v.get("type") not in ("alias", "test") + } + + def group_identical_platforms( platforms: list[str], platforms_dir: str, diff --git a/scripts/generate_readme.py b/scripts/generate_readme.py index fdc4633a..61bad765 100644 --- a/scripts/generate_readme.py +++ b/scripts/generate_readme.py @@ -15,13 +15,14 @@ import json import os import sys from datetime import datetime, timezone -from pathlib import Path sys.path.insert(0, os.path.dirname(__file__)) from common import ( list_registered_platforms, load_database, + load_emulator_profiles, load_platform_config, + unique_emulator_profiles, write_if_changed, ) from verify import verify_platform @@ -116,37 +117,27 @@ def generate_readme(db: dict, platforms_dir: str) -> str: except FileNotFoundError: pass - emulator_count = ( - sum( - 1 - for f in Path("emulators").glob("*.yml") - if not f.name.endswith(".old.yml") - ) - if Path("emulators").exists() - else 0 + profiles = unique_emulator_profiles( + load_emulator_profiles("emulators", skip_aliases=False) ) + emulator_count = len(profiles) - # Count systems from emulator profiles system_ids: set[str] = set() - emu_dir = Path("emulators") - if emu_dir.exists(): - try: - import yaml - - for f in emu_dir.glob("*.yml"): - if f.name.endswith(".old.yml"): - continue - with open(f) as fh: - p = yaml.safe_load(fh) or {} - system_ids.update(p.get("systems", [])) - except ImportError: - pass + for p in profiles.values(): + system_ids.update(p.get("systems", [])) lines = [ '

', ' RetroBIOS', "

", "", + '

', + ' ' + 'Build', + ' ' + 'Site', + "

", + "", f"Complete BIOS and firmware packs for " f"{', '.join(c['platform'] for c in sorted(coverages.values(), key=lambda x: x[ 'platform' diff --git a/scripts/generate_site.py b/scripts/generate_site.py index 8103bf80..aacd6cff 100644 --- a/scripts/generate_site.py +++ b/scripts/generate_site.py @@ -12,6 +12,7 @@ Usage: from __future__ import annotations import argparse +import json import os import shutil import sys @@ -24,6 +25,7 @@ from common import ( load_database, load_emulator_profiles, require_yaml, + unique_emulator_profiles, write_if_changed, ) @@ -242,9 +244,7 @@ def generate_home( total_size = db.get("total_size", 0) ts = _timestamp() - unique = { - k: v for k, v in profiles.items() if v.get("type") not in ("alias", "test") - } + unique = unique_emulator_profiles(profiles) emulator_count = len(unique) # Classification stats @@ -321,6 +321,16 @@ def generate_home( f"[Pack]({RELEASE_URL}){{ .md-button .md-button--primary }} |" ) + lines.extend( + [ + "", + "Verification is the check each platform runs itself, replicated " + "from its source code. RetroArch only tests that files exist; " + "Batocera compares MD5 checksums. " + "[How each mode works](wiki/verification-modes.md).", + ] + ) + # Quick start (collapsible -- secondary info) lines.extend( [ @@ -393,6 +403,27 @@ def generate_home( return "\n".join(lines) + "\n" +def compute_stats(db: dict, coverages: dict, profiles: dict) -> dict: + unique = unique_emulator_profiles(profiles) + systems: set[str] = set() + for p in unique.values(): + systems.update(p.get("systems", [])) + return { + "generated_at": _timestamp(), + "files": db.get("total_files", 0), + "size_bytes": db.get("total_size", 0), + "platforms": len(coverages), + "emulators": len(unique), + "systems": len(systems), + "source": REPO_URL, + "downloads": RELEASE_URL, + } + + +def generate_stats(stats: dict) -> str: + return json.dumps(stats, indent=2) + "\n" + + # Platform pages @@ -431,6 +462,15 @@ def generate_platform_index(coverages: dict) -> str: f"[Pack]({RELEASE_URL}){{ .md-button .md-button--primary }} |" ) + lines.extend( + [ + "", + "Verification is the check each platform runs itself, replicated " + "from its source code. " + "[How each mode works](../wiki/verification-modes.md).", + ] + ) + return "\n".join(lines) + "\n" @@ -2448,6 +2488,9 @@ def main(): str(docs / "index.md"), generate_home(db, coverages, profiles, registry) ) + stats = compute_stats(db, coverages, profiles) + write_if_changed(str(docs / "stats.json"), generate_stats(stats)) + # Build system_id -> manufacturer page map (needed by all generators) print("Building system cross-reference map...") manufacturers = _group_by_manufacturer(db)