#!/usr/bin/env bash # batch-walltime.sh — Aggregate per-batch wall-clock statistics. # # Usage: # tools/batch-walltime.sh # tools/batch-walltime.sh apricot: # tools/batch-walltime.sh apricot: # multi-mode → per-subdir # # Prints: "mode: n=NNN total=XX.Xs avg=YY.Ys/game victories=N/N" # If TARGET has a parent of {gpu-true,gpu-false,clan-*} subdirs, iterates # all of them so you can do a single call on the gpu-walltime parent. set -euo pipefail TARGET="${1:?usage: tools/batch-walltime.sh }" read -r -d '' QUERY <<'EOF' || true set -e : "${DIR:?DIR must be set}" summarize() { local dir="$1" local label="$2" python3 - "$dir" "$label" <<'PY' import json, os, sys, pathlib root = pathlib.Path(sys.argv[1]) label = sys.argv[2] games = sorted(root.glob("game_*")) n = 0 total_wc = 0.0 victories = 0 turns = [] for g in games: stats = g / "turn_stats.jsonl" if not stats.is_file() or stats.stat().st_size == 0: continue try: last = None with open(stats) as f: for line in f: if line.strip(): last = line if not last: continue d = json.loads(last) except Exception: continue n += 1 wc = d.get("wall_clock_sec") if isinstance(wc, (int, float)): total_wc += float(wc) if d.get("outcome") == "victory": victories += 1 t = d.get("turn") if isinstance(t, int): turns.append(t) if n == 0: print(f"{label}: no games") sys.exit(0) avg = total_wc / n if n else 0 tmin = min(turns) if turns else "?" tmax = max(turns) if turns else "?" print(f"{label}: n={n} total={total_wc:.1f}s avg={avg:.1f}s/game victories={victories}/{n} turns={tmin}-{tmax}") PY } # Is DIR itself a batch dir (has game_* children) or a parent of mode-subdirs? if compgen -G "$DIR/game_*" > /dev/null; then summarize "$DIR" "$(basename "$DIR")" else # Iterate mode-subdirs found=0 for sub in "$DIR"/gpu-* "$DIR"/clan-* "$DIR"/smoke; do [ -d "$sub" ] || continue compgen -G "$sub/game_*" > /dev/null || continue summarize "$sub" "$(basename "$sub")" found=1 done [ "$found" -eq 0 ] && { echo "no batches found under $DIR" >&2; exit 2; } fi EOF if [[ "$TARGET" == apricot:* ]]; then REMOTE_PATH="${TARGET#apricot:}" ssh apricot "DIR='${REMOTE_PATH}' bash -s" <<< "$QUERY" else DIR="$TARGET" bash -c "$QUERY" fi