"""Figures 16-18 for paper_safety 4.9b (abstain trilogy, intent inference, predicate
factorial). Values read from the run artifacts (env_substrates/multiagent/results)."""
import json, os
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np

R = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                 "..", "..", "..", "env_substrates", "multiagent", "results")
R = os.path.normpath(R)
OUT = os.path.dirname(os.path.abspath(__file__))

def load(name): return json.load(open(os.path.join(R, name)))

# ---------------- Figure 16: the abstain trilogy ----------------
arms = ["A0", "AR99", "AR99t", "AR99g", "AR99g4", "AR99g5"]
labels = ["A0\n(ref)", "AR99\none-tier", "AR99t\ntwo-tier", "AR99g\ngrown",
          "AR99g4\ngame-th.", "AR99g5\ntask-cons."]
walls = [483, 1500, 808, 232, 0, 1500]
cert  = [0, 0, 0, 0, 4, 0]
prog  = [16.47, -3.20, -3.20, -47.92, -88.02, -3.20]
fig, ax = plt.subplots(1, 3, figsize=(13, 3.8))
ax[0].bar(labels, walls, color="#4477aa"); ax[0].set_title("wall events"); ax[0].axhline(0, c="k", lw=.6)
ax[1].bar(labels, cert, color="#cc6677"); ax[1].set_title("certified contacts"); ax[1].axhline(0, c="k", lw=.6)
for i, v in enumerate(cert): ax[1].text(i, v+.08, str(v), ha="center", fontsize=9)
ax[2].bar(labels, prog, color="#228833"); ax[2].set_title("progress"); ax[2].axhline(0, c="k", lw=.6)
ax[2].axhline(8.24, ls="--", c="gray", lw=.8); ax[2].text(0.1, 8.6, "bar +8.24", fontsize=8, color="gray")
for a in ax: a.tick_params(axis="x", labelsize=8); a.grid(axis="y", alpha=.3)
fig.suptitle("Figure 16 — the abstain trilogy: each fix isolates one defect "
             "(availability → soundness → objective → feasibility)", fontsize=11)
fig.tight_layout(rect=[0, 0, 1, .93]); fig.savefig(os.path.join(OUT, "fig16_abstain_trilogy.png"), dpi=140); plt.close(fig)

# ---------------- Figure 17: privilege-free intent inference ----------------
t83 = load("t83.json"); st = t83["stats"]
names = ["CV\n(rung 1)", "responder\nprivileged", "responder\ninferred"]
vals = [st["cv"]["m95"], st["priv"]["m95"], st["inf"]["m95"]]
fig, ax = plt.subplots(figsize=(5.2, 3.6))
b = ax.bar(names, vals, color=["#888888", "#4477aa", "#228833"])
for r, v in zip(b, vals): ax.text(r.get_x()+r.get_width()/2, v+.03, f"{v:.3f}", ha="center", fontsize=10)
ax.set_ylabel("ε m95 (world units)"); ax.set_title("Figure 17 — intent read from motion alone", fontsize=11)
ax.text(.02, .96, f"classifier acc = {t83['cls_acc']:.3f}\nrecovery = {t83['recovery_fraction']:.2f}× "
        f"(bar 0.5×)", transform=ax.transAxes, va="top", fontsize=9)
ax.grid(axis="y", alpha=.3); fig.tight_layout()
fig.savefig(os.path.join(OUT, "fig17_intent_inference.png"), dpi=140); plt.close(fig)

# ---------------- Figure 18: predicate factorial ----------------
t84 = load("t84.json"); grid = t84["grid"]
scens = ["adversary", "spread", "tag"]; preds = ["P1_contact_free", "P2_separation", "P3_bounded_contact_time"]
short = {"P1_contact_free": "P1 contact-free", "P2_separation": "P2 separation", "P3_bounded_contact_time": "P3 bounded-contact-time"}
x = np.arange(len(scens)); w = .26
fig, ax = plt.subplots(figsize=(8.4, 3.8))
for i, p in enumerate(preds):
    v = [grid[s][p]["violations"] for s in scens]
    bars = ax.bar(x + (i-1)*w, v, w, label=short[p])
    for r, s in zip(bars, scens):
        if t84["best_per_scenario"][s] == p:
            ax.text(r.get_x()+r.get_width()/2, r.get_height()+8, "best", ha="center",
                    fontsize=8, color="#aa2222", fontweight="bold")
ax.set_xticks(x); ax.set_xticklabels(scens); ax.set_ylabel("predicate violations")
ax.set_title("Figure 18 — predicate factorial: the best spec is regime-relative (P2 dominated)", fontsize=11)
ax.legend(fontsize=8); ax.grid(axis="y", alpha=.3); fig.tight_layout()
fig.savefig(os.path.join(OUT, "fig18_predicate_factorial.png"), dpi=140); plt.close(fig)
print("wrote fig16, fig17, fig18 to", OUT)
