"""The site's measurement pages, from the index sync_measurements.py writes. Three places read the same index: the Tested block of each emulator page, the Measurements explorer page and the host table of the methodology page. A number is never shown without its method and host beside it. """ from __future__ import annotations import re import sqlite3 from pathlib import Path import sitemarkup as markup from siterender import _escape_tags EXPLORER_PAGE = "measurements.md" METHOD_PAGE = "wiki/measurements.md" HOSTS_MARKER = "" def by_emulator(index: dict) -> dict[str, list[dict]]: out: dict[str, list[dict]] = {} for item in index.get("items", []): out.setdefault(item["emulator"], []).append(item) return out def _text(value: object) -> str: """Record text as the page shows it. A semicolon joining two clauses ends a sentence on the site: the record keeps the words as written.""" text = " ".join(str(value or "").split()) text = re.sub(r";\s+(\w)", lambda m: ". " + m[1].upper(), text) return _escape_tags(text) 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)}**", "", 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']}), [its data]({item['data_url']}), {runs}.", "", ] return lines def tested_section(name: str, items: list[dict]) -> list[str]: """The Tested block of an emulator page, empty when nothing was recorded.""" 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 def hosts_table(index: dict) -> list[str]: hosts: dict[str, int] = {} for item in index.get("items", []): # The load average differs per run: the computer is what comes before it. computer = item["host"].split(", load ")[0] hosts[computer] = hosts.get(computer, 0) + 1 if not hosts: return ["No result is recorded at the pinned commit yet.", ""] return [ "| Computer | Tests |", "|----------|------:|", *(f"| {_text(host)} | {count} |" for host, count in sorted(hosts.items())), "", ] def with_hosts(page: str, index: dict) -> str: """The methodology page with the computers the results ran on.""" return page.replace(HOSTS_MARKER, "\n".join(hosts_table(index)).rstrip("\n")) def generate_explorer_page(index: dict) -> str: commit = index.get("commit") repo = index.get("repo") or "" source = (f"[retrobios-measurements]({repo}/tree/{commit}) at {_short(commit)}" if commit else "the measurements project, not read in this build") return "\n".join([ "# Measurements", "", f"Emulators run in real conditions: {index.get('records', 0)} records, " f"{index.get('count', 0)} tests, read from {source}. " f"[How they are made]({METHOD_PAGE}).", "", " ".join([ markup.button("SQLite of every record", "downloads/measurements.sqlite", primary=True), markup.button("Index as JSON", "data/measurements/index.json"), ]), "", "Each row is the latest record of one test, with its method and the computer it " "ran on. One SQLite file per emulator is linked from its page.", "", "", "", ]) def sqlite_tables(path: Path) -> list[tuple[str, list[str]]]: """Each table of a database with its columns, in the order created.""" connection = sqlite3.connect(f"file:{path}?mode=ro", uri=True) try: names = [row[0] for row in connection.execute( "SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY rowid")] return [(name, [row[1] for row in connection.execute(f"PRAGMA table_info({name})")]) for name in names] finally: connection.close() def data_page_section(path: Path) -> list[str]: """The Data page's description of measurements.sqlite.""" return [ "## Measurements", "", "[`measurements.sqlite`](downloads/measurements.sqlite) holds every core probe " "record at the pinned commit of [retrobios-measurements]" "(https://github.com/Abdess/retrobios-measurements), and " "`downloads/measurements/.sqlite` the records of one emulator, linked " f"from its page. The [Measurements]({EXPLORER_PAGE}) page reads " "[`data/measurements/index.json`](data/measurements/index.json). A record line is " "valid against [`core-probe-record.schema.json`](api/v1/schemas/core-probe-record.schema.json) " "and its data file against [`core-probe-data.schema.json`](api/v1/schemas/core-probe-data.schema.json).", "", "| Table | Columns |", "|-------|---------|", *(f"| `{name}` | {', '.join(f'`{c}`' for c in columns)} |" for name, columns in sqlite_tables(path)), "", "`meta` names the measurements commit and the record version. A list or object " "value is JSON text, an absent one empty. `runs.superseded` is 1 for a record a " "later one corrects.", "", "```sql", "SELECT r.emulator, c.claim, c.status, r.recorded_at, h.cpu_model", "FROM runs r JOIN checks c ON c.run_id = r.id JOIN hosts h ON h.id = r.host_id", "WHERE r.superseded = 0 ORDER BY r.recorded_at;", "```", "", ]