feat: show each test as one row with its proof

The Tested block opens on one summary line, then a row per test: a short title, a result chip, a dot per variant and the date. Method, claim, computer, core build and the record wait in the row's details. Tests from before the boot oracle fold under one line, benchmarks get their own table. beetle_saturn shows under 120 words before anything is opened.
This commit is contained in:
Abdessamad Derraz committed 2026-10-27 19:40:16 +01:00
1 parent 70c3bbd853
commit e7d0c0183c
4 files changed
+449 -68

No files matched your search

+269 -41
View File
@@ -18,6 +18,7 @@ its line at the last commit that touched measurements/.
from __future__ import annotations
import html
import json
import os
import re
@@ -146,9 +147,20 @@ def index_item(entry: mr.Stored, runs: int, source: dict, profiles: dict,
"runs": runs,
"record_url": permalink(source["repo"], source["commit"], mr.records_path(entry.emulator), entry.line),
"sqlite": f"downloads/measurements/{entry.emulator}.sqlite",
"host_short": short_host(record["host"]),
"groups": variant_groups(record),
"proves": proves(record["id"], profile),
"timing": ({"ms_per_frame": record["timing"]["ms_per_frame"]["median"],
"fps": record["timing"]["fps"]["median"],
"stdev": record["timing"]["ms_per_frame"]["stdev"]}
if record.get("timing") else None),
}
def with_title(item: dict) -> dict:
return {**item, "title": short_title(item)}
def build_index(stored: list[mr.Stored], source: dict | None, profiles: dict,
system_names: dict[str, str] | None = None) -> dict:
"""One item per (emulator, subject): its latest record not superseded."""
@@ -161,7 +173,8 @@ def build_index(stored: list[mr.Stored], source: dict | None, profiles: dict,
for key in sorted(by_subject):
entries = by_subject[key]
latest = max(entries, key=lambda s: (s.record["recorded_at"], s.line))
items.append(index_item(latest, len(entries), source or {}, profiles, system_names or {}))
items.append(with_title(index_item(latest, len(entries), source or {}, profiles,
system_names or {})))
items.sort(key=lambda item: (item["emulator"], item["date"], item["subject"]))
return {
"schema_version": INDEX_SCHEMA_VERSION,
@@ -514,9 +527,14 @@ def build(public: Path, root: Path = ROOT, emulators_dir: Path = ROOT / "emulato
# --------------------------------------------------------------------------
def by_emulator(index: dict) -> dict[str, list[dict]]:
"""Each emulator's items, with the count of its findings still open."""
opened: dict[str, int] = {}
for line in (index.get("campaign") or {}).get("open") or ():
opened[line["emulator"]] = opened.get(line["emulator"], 0) + 1
out: dict[str, list[dict]] = {}
for item in index.get("items", []):
out.setdefault(item["emulator"], []).append(item)
out.setdefault(item["emulator"], []).append(
{**item, "open_findings": opened.get(item["emulator"], 0)})
return out
@@ -532,52 +550,262 @@ def _short(commit: str | None) -> str:
return f"`{commit[:12]}`" if commit else "unknown"
def tested_item(item: dict) -> list[str]:
"""One test: what ran, the result, the method and host beside it, the record."""
title = item["claim"] or f"Benchmark of {item['content'] or 'the core alone'}"
runs = "1 run" if item["runs"] == 1 else f"{item['runs']} runs, the latest shown"
core = item["core"]
build = f"{_text(core['library'])} at {_short(core['commit'])}" if core.get("commit") \
else _text(core["library"])
lines = [f"- **{_text(title)}**", ""]
if len(item.get("verdicts") or ()) > 1:
lines += [f" **Result:** `{item['status']}`.", ""]
lines += [f" - {_text(v['variant'])}: `{v['verdict']}`. {_text(v['detail'])}."
for v in item["verdicts"]]
lines.append("")
# A verdict or a comparison, as the block says it: words and a chip kind.
RESULT_WORDS = {
"boots": ("works", "success"),
"bios_error": ("BIOS error", "danger"),
"crash": ("crash", "danger"),
"hang": ("hang", "warning"),
"unknown": ("unknown", "muted"),
"mixed": ("differs", "info"),
"same": ("no difference", "muted"),
"differs": ("differs", "info"),
"inconclusive": ("inconclusive", "warning"),
"no verdict": ("no verdict", "muted"),
"ran": ("ran", "muted"),
}
# Words a subject slug spells that read as one term.
TERMS = {"bios": "BIOS", "vcd": "Video CD", "cd": "CD", "jp": "JP", "us": "US", "eu": "EU",
"cr2": "CR2", "mpeg": "MPEG", "psx": "PSX", "hle": "HLE", "usa": "USA"}
# The campaign's own check names, as the block says them.
CHECK_NAMES = {"files": "full set", "none": "no BIOS", "negative": "wrong files",
"references": "reference run", "variants": "copies", "alias": "other name",
"path": "other path", "bench": "benchmark"}
TITLE_AXIS_WORDS = 4
def _words(text: str) -> list[str]:
return re.findall(r"[a-z0-9]+", str(text or "").lower())
def short_content(label: str | None) -> str:
"""A content label cut to the game's name: no source prefix, no
edition, region or identity detail."""
text = str(label or "").strip()
if ":" in text.split("(")[0]:
text = text.split(":", 1)[1].strip()
for cut in (" - ", " (", ", "):
text = text.split(cut, 1)[0]
return text.strip()
def short_title(item: dict) -> str:
"""A test's name in a few words: the file it varies, the game, and what
the subject adds to them (a build, a region, a check of the campaign)."""
thing = Path(str(item.get("variable") or "")).name
game = short_content(item.get("content"))
known = set(_words(thing)) | set(_words(item.get("content"))) | set(_words(game))
known |= set(_words(Path(str((item.get("core") or {}).get("file") or "")).name.split("_libretro")[0]))
axis = []
for word in _words(item.get("subject")):
if word in known or re.fullmatch(r"[0-9a-f]{8}", word):
continue
issue = re.fullmatch(r"issue(\d+)", word)
word = f"issue {issue[1]}" if issue else CHECK_NAMES.get(word, TERMS.get(word, word))
if word not in axis:
axis.append(word)
if len(axis) > TITLE_AXIS_WORDS:
axis = [*axis[:TITLE_AXIS_WORDS], "..."]
head = ", ".join(part for part in (f"`{thing}`" if thing else "", game) if part)
title = f"{head} ({' '.join(axis)})" if axis and head else head or " ".join(axis)
return title or str(item.get("subject") or "")
def short_host(host: dict) -> str:
"""The computer as a reader names it: the CPU model and the OS."""
cpu = str(host.get("cpu_model") or "unknown CPU")
cpu = re.sub(r"\(R\)|\(TM\)|\bCPU\b|@.*$|^\d+(?:st|nd|rd|th) Gen ", "", cpu)
cpu = " ".join(cpu.split())
system = str(host.get("os") or "")
name = "Linux" if "Linux" in system else system.split("-")[0] or "unknown OS"
if "microsoft" in system.lower():
name += " (WSL2)"
return f"{cpu}, {name}"
def variant_groups(record: dict) -> list[dict]:
"""One entry per variant: the result group it falls in, and whether it
staged no file. A run that carries verdicts is grouped by verdict, a
comparison by the value its observable took."""
check = record.get("check") or {}
position: dict[str, int] = {}
result: dict[str, str] = {}
if all("verdict" in v for v in record["variants"]) and (
record["kind"] == "run" or check.get("observable") == "frame_hashes"):
for variant in record["variants"]:
position.setdefault(variant["verdict"], len(position))
result[variant["label"]] = RESULT_WORDS[variant["verdict"]][0]
groups = {v["label"]: position[v["verdict"]] for v in record["variants"]}
else:
lines += [f" **Result:** `{item['status']}`. {_text(item['statement'])}.", ""]
if item.get("method"):
lines += [f" **Method:** {_text(item['method'])}", ""]
lines += [
f" **Ran on:** {_text(item['host'])}, {item['date'][:10]}. Core build: {build}. "
f"{item['variants']} variant{'s' if item['variants'] != 1 else ''}, "
f"{item['repetitions']} repetition{'s' if item['repetitions'] != 1 else ''} each"
+ (f", {item['flags']} flag{'s' if item['flags'] != 1 else ''} raised" if item["flags"] else "")
+ ".",
"",
f" [Full record]({item['record_url']}), {runs}.",
"",
groups = {}
for number, group in enumerate((check.get("result") or {}).get("groups") or ()):
for label in group["variants"]:
groups[label] = number
result[label] = f"result {chr(ord('A') + number % 26)}"
varied = check.get("variable")
return [{"variant": v["label"], "group": groups.get(v["label"], 0),
"result": result.get(v["label"], ""),
"absent": bool(varied) and varied in v["system_files"] and v["system_files"][varied] is None}
for v in record["variants"]]
def proves(record_id: str, profile: dict) -> list[str]:
"""The profile fields this record is evidence for, as `field of file`."""
out = []
for entry in profile.get("files") or ():
for name, ids in sorted((entry.get("evidence") or {}).items()):
if record_id in ids:
out.append(f"{name} of {entry.get('name')}")
return out
# An MDX page reads a brace as the start of an expression, in text and in
# an attribute alike.
_BRACES = str.maketrans({"{": "{", "}": "}"})
def _attr(value: object) -> str:
return html.escape(" ".join(str(value or "").split()), quote=True).translate(_BRACES)
def _cell(value: object) -> str:
"""Record text placed in raw HTML: escaped, code spans kept, a semicolon
joining two clauses ending a sentence as on the rest of the site."""
text = " ".join(str(value or "").split())
text = re.sub(r";\s+(\w)", lambda m: ". " + m[1].upper(), text)
return markup.inline_html(text).translate(_BRACES)
def _dots(item: dict) -> str:
groups = item.get("groups") or []
names = "; ".join(f"{g['variant']}: {g['result']}" for g in groups)
dots = "".join(
f'<span class="rb-dot rb-dot-{g["group"] % 5}{" rb-dot-empty" if g["absent"] else ""}" '
f'title="{_attr(g["variant"] + ": " + g["result"])}"></span>' for g in groups)
return (f'<span class="rb-dots" role="img" aria-label="{_attr(f"{len(groups)} variants. {names}")}">'
f"{dots}</span>")
def _chip(item: dict) -> str:
words, kind = RESULT_WORDS.get(item["status"], (item["status"], "muted"))
return f'<span class="rb-badge rb-badge-{kind}">{html.escape(words)}</span>'
def _sentence_html(label: str, value: object, markup_ready: bool = False) -> str:
"""One line of the details, or nothing: an empty value is never printed."""
text = (str(value or "") if markup_ready else _cell(value)).strip().rstrip(".")
return f"<p><strong>{label}:</strong> {text}.</p>" if text else ""
def _details(item: dict) -> list[str]:
core = item["core"]
build = _cell(core["library"]) + (f" at <code>{html.escape(core['commit'][:12])}</code>"
if core.get("commit") else "")
reps = f"{item['variants']} variant{'s' if item['variants'] != 1 else ''}, " \
f"{item['repetitions']} repetition{'s' if item['repetitions'] != 1 else ''} each"
if item["flags"]:
reps += f", {item['flags']} flag{'s' if item['flags'] != 1 else ''} raised"
runs = "1 run" if item["runs"] == 1 else f"{item['runs']} runs, the latest shown"
lines = [
_sentence_html("Claim", item.get("claim")),
_sentence_html("Result", item.get("statement")),
_sentence_html("Method", item.get("method")),
_sentence_html("Proves", ", ".join(item.get("proves") or [])),
_sentence_html("Ran on", item["host"]),
_sentence_html("Core build", build and f"{build}. {reps}", markup_ready=True),
f'<p><a href="{_attr(item["record_url"])}">Full record</a>, {runs}.</p>',
]
return [line for line in lines if line]
def tested_counts(items: list[dict]) -> dict:
tests = [i for i in items if i["kind"] != "bench"]
return {"tests": len(items), "confirmed": sum(1 for i in items if i.get("proves")),
"open": max((i.get("open_findings", 0) for i in items), default=0),
"benchmarks": len(items) - len(tests),
"last": max((i["date"][:10] for i in items), default="")}
def core_label(item: dict) -> str:
return Path(str(item["core"].get("file") or "")).name.split("_libretro")[0]
def _row(item: dict, page_host: str, main_core: str) -> list[str]:
elsewhere = (item.get("host_short") or item["host"]) != page_host
title = _cell(item.get("title") or short_title(item))
if core_label(item) != main_core:
title += f' <small>{html.escape(core_label(item))}</small>'
return [
'<details class="rb-tested-row">',
("<summary>"
f'<span class="rb-tested-test">{title}</span>'
f'<span class="rb-tested-result">{_chip(item)}</span>'
f'<span class="rb-tested-variants">{_dots(item)}</span>'
f'<span class="rb-tested-date">{item["date"][:10]}'
+ (f' <small>{_attr(item.get("host_short"))}</small>' if elsewhere else "")
+ "</span></summary>"),
'<div class="rb-tested-more">',
*_details(item),
"</div>",
"</details>",
]
return lines
def tested_section(name: str, items: list[dict]) -> list[str]:
"""The Tested block of an emulator page, empty when nothing was recorded."""
"""The Tested block of an emulator page, empty when nothing was recorded.
The answer first: one summary line, then one row per test with its
result chip, a dot per variant and its date. What proves it (method,
claim, computer, core build, record) waits in each row's details. Tests
recorded before the boot oracle fold under one line, and benchmarks get
their own table at the end.
"""
if not items:
return []
lines = [
"## Tested",
"",
f"This emulator was run in real conditions by the [core probe](../{METHOD_PAGE}). "
f"Each test below is the latest of its kind. "
f"[All measurements](../{EXPLORER_PAGE}), "
f"[these records as SQLite](../downloads/measurements/{name}.sqlite).",
"",
]
for item in sorted(items, key=lambda i: (i["date"], i["subject"]), reverse=True):
lines += tested_item(item)
return lines
counts = tested_counts(items)
hosts = [i.get("host_short") or i["host"] for i in items]
page_host = max(sorted(set(hosts)), key=hosts.count)
cores = [core_label(i) for i in items]
main_core = max(sorted(set(cores)), key=cores.count)
tests = f"{counts['tests']} test{'s' if counts['tests'] != 1 else ''}"
summary = (f"{tests} · {counts['confirmed']} confirmed · {counts['open']} open · "
f"last run {counts['last']} on {page_host}.")
links = (f'<a href="{markup.site_href(METHOD_PAGE.removesuffix(".md") + "/")}">How</a> · '
f'<a href="{markup.site_href(EXPLORER_PAGE.removesuffix(".md") + "/")}">All tests</a> · '
f'<a href="{markup.site_href(f"downloads/measurements/{name}.sqlite")}">SQLite</a>')
ordered = sorted(items, key=lambda i: (i["date"], i["subject"], core_label(i)), reverse=True)
benches = [i for i in ordered if i["kind"] == "bench"]
earlier = [i for i in ordered if i["kind"] != "bench" and i["status"] == "no verdict"]
current = [i for i in ordered if i["kind"] != "bench" and i["status"] != "no verdict"]
lines = ["## Tested", "", '<div class="rb-tested">',
f'<p class="rb-tested-summary">{html.escape(summary)} {links}</p>']
if current or earlier:
lines.append('<div class="rb-tested-head" aria-hidden="true"><span>Test</span>'
"<span>Result</span><span>Variants</span><span>Date</span></div>")
for item in current:
lines += _row(item, page_host, main_core)
if earlier:
lines += ['<details class="rb-tested-earlier">',
f"<summary>{len(earlier)} earlier test{'s' if len(earlier) != 1 else ''}, "
"before the boot oracle</summary>"]
for item in earlier:
lines += _row(item, page_host, main_core)
lines.append("</details>")
if benches:
# One line: MDX reads a table split over lines as paragraphs.
table = ['<table class="rb-tested-bench"><thead><tr><th>Benchmark</th><th>ms per frame</th>'
"<th>fps</th><th>stdev</th><th>runs</th></tr></thead><tbody>"]
for item in benches:
timing = item.get("timing") or {}
title = _cell(item.get("title") or short_title(item))
if core_label(item) != main_core:
title += f' <small>{html.escape(core_label(item))}</small>'
table.append(
f'<tr><td><a href="{_attr(item["record_url"])}">{title}</a></td>'
f'<td>{timing.get("ms_per_frame", 0):.3f}</td><td>{timing.get("fps", 0):.1f}</td>'
f'<td>{timing.get("stdev", 0):.3f}</td><td>{item["repetitions"]}</td></tr>')
lines.append("".join([*table, "</tbody></table>"]))
return [*lines, "</div>", ""]
def hosts_table(index: dict) -> list[str]: