"""②の夜(20261105_p0)のロボット2台・種10個の30秒以上の止まり192回を、直した②の図面(版 08db8a0d067c)に重ねる。 使い方: python3 draw_night_stops.py <出力.png>""" import json, sys, math import matplotlib; matplotlib.use("Agg") import matplotlib.pyplot as plt from matplotlib.patches import Rectangle, Circle from matplotlib import font_manager as fm FONT = "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc" fm.fontManager.addfont(FONT) plt.rcParams["font.family"] = fm.FontProperties(fname=FONT).get_name() U = json.load(open(sys.argv[1])); P = json.load(open(sys.argv[2])) SB = [12.2, 5.1, 14.6, 5.9]; FP = (10.9, 5.45) def area(x, y): if SB[0] <= x <= SB[2] and SB[1] <= y <= SB[3]: return "待機場所の中" if math.hypot(x - FP[0], y - FP[1]) <= 2.5: return "受け渡し口から2.5m以内" if 4.75 <= x <= 6.85 and 11.3 <= y <= 14.0: return "丸テーブルのまわり" if 7.5 <= x <= 9.5 and 8.0 <= y <= 9.6: return "仕切りの右端のすき間" if x < 9.5 and y > 9.0: return "奥の区画のそのほか" if 13.0 <= x <= 21.5 and 2.6 <= y <= 4.5: return "ドリンクバーのまわり" if 9.0 <= x <= 14.0 and y < 3.8: return "入口・レジのまわり" return "そのほか" COL = {"待機場所の中": "#d6336c", "受け渡し口から2.5m以内": "#f08c00", "入口・レジのまわり": "#1971c2", "仕切りの右端のすき間": "#2f9e44", "丸テーブルのまわり": "#7048e8", "奥の区画のそのほか": "#7048e8", "ドリンクバーのまわり": "#868e96", "そのほか": "#495057"} fig, ax = plt.subplots(figsize=(13, 11)) for r in U["rooms"]: x0, y0, x1, y1 = r["rect"]; ax.add_patch(Rectangle((x0, y0), x1 - x0, y1 - y0, fc="#eceef2", ec="#999", lw=0.6)) ax.text((x0 + x1) / 2, (y0 + y1) / 2, r["label"], ha="center", va="center", fontsize=8, color="#666") for w in U["walls"] + [dict(rect=r) for r in U["outer_walls"]]: x0, y0, x1, y1 = w["rect"]; ax.add_patch(Rectangle((x0, y0), x1 - x0, y1 - y0, fc="#7d8590", ec="none")) for t in U["tables"]: p = t["parts"] for b in p["benches"]: ax.add_patch(Rectangle((b[0], b[1]), b[2] - b[0], b[3] - b[1], fc="#d6d9df", ec="#555", lw=0.5)) tp = p["top"] if p.get("top_shape") == "circle": ax.add_patch(Circle(((tp[0] + tp[2]) / 2, (tp[1] + tp[3]) / 2), (tp[2] - tp[0]) / 2, fc="white", ec="#222", lw=0.9)) else: ax.add_patch(Rectangle((tp[0], tp[1]), tp[2] - tp[0], tp[3] - tp[1], fc="white", ec="#222", lw=0.9)) for c in p["chairs"]: r = c["rect"]; ax.add_patch(Circle(((r[0] + r[2]) / 2, (r[1] + r[3]) / 2), (r[2] - r[0]) / 2, fc="#ced4da", ec="#555", lw=0.4)) x0, y0, x1, y1 = t["footprint"]; ax.text(x0, y1 + 0.06, t["id"], fontsize=7, color="#333") for pl in U["places"]: if pl["kind"] == "RobotStandby": r = pl["rect"]; ax.add_patch(Rectangle((r[0], r[1]), r[2] - r[0], r[3] - r[1], fc="none", ec="#d6336c", lw=1.2, ls="--")) if pl["kind"] == "Waiting": r = pl["rect"]; ax.add_patch(Rectangle((r[0], r[1]), r[2] - r[0], r[3] - r[1], fc="#e7f5ff", ec="#1971c2", lw=1)) ax.add_patch(Circle(FP, 0.15, fc="white", ec="#e8590c", lw=1.5, zorder=6)) cnt = {} for x, y, cause, res, dur, seed in P: a = area(x, y); cnt[a] = cnt.get(a, 0) + 1 ax.add_patch(Circle((x, y), 0.13, fc=COL[a], ec="white", lw=0.3, alpha=0.75, zorder=7)) ax.set_xlim(-0.5, 24.5); ax.set_ylim(-1.2, 19.6); ax.set_aspect("equal"); ax.axis("off") order = ["入口・レジのまわり", "待機場所の中", "受け渡し口から2.5m以内", "仕切りの右端のすき間", "丸テーブルのまわり", "奥の区画のそのほか", "ドリンクバーのまわり", "そのほか"] txt = " ".join(f"{k} {cnt.get(k, 0)}" for k in order if cnt.get(k)) ax.set_title(f"② 定番の郊外型(直した版):ロボット2台・種10個の30秒以上の止まり {len(P)}回\n{txt}", fontsize=11) print(cnt) plt.tight_layout(); plt.savefig(sys.argv[3], dpi=110)