1"""Assemble this repository's static site: a manifest of the submissions, the solution files, and the viewer page."""
2from __future__ import annotations
4import argparse
5import json
6import shutil
7from pathlib import Path
9ROOT = Path(__file__).resolve().parents[1]
10LFS_PREFIX = b"version https://git-lfs.github.com/spec/v1"
13def is_lfs_pointer(p: Path) -> bool:
14 try:
15 with open(p, "rb") as f:
16 return f.read(len(LFS_PREFIX)) == LFS_PREFIX
17 except OSError:
18 return False
21def main():
22 ap = argparse.ArgumentParser()
23 ap.add_argument("--out", type=Path, default=ROOT / "site")
24 args = ap.parse_args()
25 out: Path = args.out
26 if out.exists():
27 shutil.rmtree(out)
28 out.mkdir(parents=True)
29 manifest = {"challenges": {}}
30 for p in sorted((ROOT / "solutions").glob("*/*.json")):
31 sub = json.loads(p.read_text())
32 cid = p.parent.name
33 entry = manifest["challenges"].setdefault(cid, {"submissions": []})
34 rel_dir = p.parent.relative_to(ROOT)
35 for sol in sub["solutions"]:
36 sol["output"] = f"{rel_dir.as_posix()}/{sol['output']}"
37 if "fields" in sol and not sol["fields"]["path"].startswith("http"):
38 local = p.parent / sol["fields"]["path"]
39 sol["fields"]["path"] = f"{rel_dir.as_posix()}/{sol['fields']['path']}"
40 sol["fields"]["available"] = local.exists() and not is_lfs_pointer(local)
41 entry["submissions"].append(sub)
42 shutil.copytree(ROOT / "solutions", out / "solutions")
43 shutil.copyfile(ROOT / "web" / "index.html", out / "index.html")
44 shutil.copyfile(ROOT / "web" / "viewer.js", out / "viewer.js")
45 # the shared Web Audio player, from the installed challenge-tools package
46 from challenge_tools.build import player_js
48 (out / "player.js").write_text(player_js())
49 # suggested playback gains, when the challenge repository is checked out beside us (as in the workflow)
50 gains = {}
51 for cj in sorted((ROOT / "challenge-repo" / "challenges").glob("*/challenge.json")) if (ROOT / "challenge-repo").exists() else []:
52 ch = json.loads(cj.read_text())
53 gains[ch["challenge_id"]] = (ch.get("playback") or {}).get("gain_db")
54 manifest["playback_gain_db"] = gains
55 (out / "manifest.json").write_text(json.dumps(manifest, indent=1))
56 print(f"site written to {out}")
59if __name__ == "__main__":
60 main()