boluopai.
中文 · unavailable
GitHub source

render_wheel.py

#!/usr/bin/env python3
"""Render a portable wheel with an independently sampled initial result."""

import argparse
import json
import math
import secrets
import uuid
from pathlib import Path


def render(options, speed=3, output_format="standalone"):
    if (
        not isinstance(options, list)
        or not 1 <= len(options) <= 100
        or any(not isinstance(x, str) or not x.strip() or len(x) > 200 for x in options)
        or len(set(options)) != len(options)
    ):
        raise ValueError(
            "Expected 1–100 distinct nonempty option strings, at most 200 characters each"
        )
    if not math.isfinite(speed) or not 0.25 <= speed <= 3:
        raise ValueError("Speed must be between 0.25 and 3")
    config = {
        "options": options,
        "speed": speed,
        "runId": str(uuid.uuid4()),
        "drawIndex": secrets.randbelow(len(options)),
    }
    template = (Path(__file__).resolve().parents[1] / "assets/wheel.html").read_text(encoding="utf-8")
    payload = json.dumps(config, ensure_ascii=False).replace("<", "\\u003c")
    fragment = template.replace("__WHEEL_ID__", "wheel-" + config["runId"]).replace(
        "__WHEEL_CONFIG__", payload
    )
    if output_format == "standalone":
        shell = (Path(__file__).resolve().parents[1] / "assets/standalone.html").read_text(encoding="utf-8")
        return shell.replace("__WHEEL_FRAGMENT__", fragment), config
    if output_format != "inline":
        raise ValueError("Format must be standalone or inline")
    return fragment, config


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--options", required=True, type=Path)
    parser.add_argument("--output", required=True, type=Path)
    parser.add_argument("--speed", type=float, default=3)
    parser.add_argument("--format", choices=["standalone", "inline"], default="standalone")
    args = parser.parse_args()
    fragment, config = render(json.loads(args.options.read_text(encoding="utf-8")), args.speed, args.format)
    args.output.parent.mkdir(parents=True, exist_ok=True)
    args.output.write_text(fragment, encoding="utf-8")
    print(
        json.dumps(
            {
                "path": str(args.output.resolve()),
                "runId": config["runId"],
                "selected": config["options"][config["drawIndex"]],
            },
            ensure_ascii=False,
        )
    )


if __name__ == "__main__":
    main()