#!/usr/bin/env python3 """依頼157:確かめの回のまとめ(依頼143・147・149・154・155 の check と並べる)。 python3 agg157.py <回のフォルダ> [<回のフォルダ> ...]""" import csv, json, os, sys, statistics from collections import Counter, defaultdict HOSP = "/Volumes/KIOXIA/r2r2r-data/service_sim/unity/hospital" R143 = {"hall": HOSP + "/20261110_floor143/runs/check143a_v06_hall_s0", "switch": HOSP + "/20261110_floor143/runs/check143c_v06_switch_s0"} R147 = {"hall": HOSP + "/20261110_people147/runs/check147a_v06_hall_s0", "switch": HOSP + "/20261110_people147/runs/check147c_v06_switch_s0"} R149 = {"hall": HOSP + "/20261111_flow149/runs/check149a_v06_hall_s0", "switch": HOSP + "/20261111_flow149/runs/check149c_v06_switch_s0"} R154 = {"hall": HOSP + "/20261111_flow154/runs/check154a_v06_hall_s0", "switch": HOSP + "/20261111_flow154/runs/check154c_v06_switch_s0"} R155 = {"hall": HOSP + "/20261112_flow155/runs/check155a_v06_hall_s0", "switch": HOSP + "/20261112_flow155/runs/check155c_v06_switch_s0"} EST = {"busy": (2, 8), "quiet": (1, 3)} # assumptions.json crowd_people.flow_estimate H1 = "/Users/shimazueiichi/Robotics_UX/ServiceSim/Assets/ServiceSim/Hospital/Data/hospital_h1-155.json" TN = {1: "急に止まった", 2: "ひやり", 3: "人がよけさせられた", 4: "立ち往生", 5: "横切り", 6: "止まりきれなかった"} LAY = json.load(open(H1, encoding="utf-8")) COR = {c["name"]: c["rect"] for c in LAY["layout"]["corridors"]} STAFF_COR = ["職員の中廊下", "西の縦廊下", "東の縦廊下", "外来の奥の職員通路", "東の縦廊下(北)"] WAIT = ["総合受付・会計の待合", "お薬の窓口の待合", "生理検査の待合", "化学療法の受付・待合", "救急の待合"] MIDW = ["内科の中待合", "ほかの外来の中待合"] SCOR = ["職員の中廊下", "西の縦廊下", "東の縦廊下", "外来の奥の職員通路"] ENT = ["正面玄関", "玄関の通り"] ELV = ["エレベーターホール", "エレベーター"] TOI = ["トイレ(西)", "トイレ(東)", "化学療法のトイレ"] ROLES = ("外来の患者", "化学療法の患者", "救急の患者", "看護師", "医師", "薬剤師", "検査技師", "事務") def inr(r, x, z, e=1e-4): return r[0] - e <= x <= r[2] + e and r[1] - e <= z <= r[3] + e def area3(x, z): if inr(COR["外来の大廊下"], x, z): return "外来の大廊下" if any(inr(COR[n], x, z) for n in STAFF_COR): return "職員の廊下" if inr(COR["玄関の通り"], x, z): return "玄関の通り" return "部屋の中" def rd(run, f): return list(csv.DictReader(open(os.path.join(run, f), encoding="utf-8"))) def one(run): s = json.load(open(os.path.join(run, "summary.json"), encoding="utf-8")) ev = rd(run, "events.csv") legs = {l["leg_id"]: l for l in rd(run, "legs.csv")} run_c, wait_c, ar = Counter(), Counter(), defaultdict(Counter) fast = 0 kinds = defaultdict(Counter) for e in ev: k = int(e["type"]) d = legs[e["leg_id"]]["dir"] if e["leg_id"] in legs else "" if d == "待ち": wait_c[k] += 1 continue run_c[k] += 1 kinds[k][e["partner_kind"] or "なし"] += 1 if k == 2 and e["note"] == "速いまま": fast += 1 ar[area3(float(e["robot_x"]), float(e["robot_z"]))][k] += 1 return dict(s=s, ev=ev, legs=legs, run=run_c, wait=wait_c, area=ar, fast=fast, kinds=kinds, trips=rd(run, "trips.csv"), moves=rd(run, "moves.csv"), resc=rd(run, "rescues.csv")) def line(c, ks=range(1, 7)): return "/".join("%d" % c[k] for k in ks) def hm(t): t = int(round(t)) + 7 * 3600 + 1800 return "%d:%02d" % (t // 3600, (t % 3600) // 60) def halls(run): return {float(r["t_s"]): int(r["hall_people"]) for r in rd(run, "crowd.csv")} def zones_table(run, s, run149): # run149 = 比べる相手(依頼155) zl = rd(run, "zones147.csv") byt = defaultdict(lambda: Counter()) for r in zl: t = float(r["t_s"]); n = int(r["patients"]) + int(r["staff"]) z = r["zone"] if z in WAIT: c = "待合" elif z in MIDW: c = "中待合" elif z in SCOR: c = "職員の廊下" elif z == "外来の大廊下": c = None elif z in ENT: c = "玄関" elif z in ELV: c = "エレベーターホール" # ホールと中(かご)を合わせる elif z in TOI: c = "トイレ" else: c = "部屋の中" if c: byt[t][c] += n byt[t]["all"] += n crowd = rd(run, "crowd.csv") hall = {float(r["t_s"]): (int(r["hall_people"]), int(r["hall_target"]), int(r["east_people"])) for r in crowd} h147 = halls(run149) e149 = {float(r["t_s"]): int(r["east_people"]) for r in rd(run149, "crowd.csv")} end = s["sim_s"] print("時刻ごと(30分ごとの平均。1分ごとに数えた人数。患者・付き添い・職員・エレベーターから来た人の全部)") print("時刻 大廊下x0〜70 依頼155 目安(flow_estimate) 大廊下x70〜120 依頼155 待合 中待合 部屋の中 職員の廊下 玄関・玄関の通り エレベーターホール トイレ 全部") t0 = 0.0 while t0 < end - 1: ts = [t for t in hall if t0 <= t < t0 + 1800] if not ts: break avg = lambda f: sum(f(t) for t in ts) / len(ts) hh = avg(lambda t: hall[t][0]); ee = avg(lambda t: hall[t][2]) tg = "%d〜%d" % (EST["busy"] if 1800 <= t0 < 12600 else EST["quiet"]) x49 = [e149[t] for t in e149 if t0 <= t < t0 + 1800] e49 = sum(x49) / len(x49) if x49 else float("nan") t47 = [h147[t] for t in h147 if t0 <= t < t0 + 1800] h47 = sum(t47) / len(t47) if t47 else float("nan") cs = {c: avg(lambda t: byt[t][c]) for c in ("待合", "中待合", "部屋の中", "職員の廊下", "玄関", "エレベーターホール", "トイレ", "all")} print("%s〜%s %6.1f %6.1f %8s %6.1f %6.1f %6.1f %6.1f %7.1f %7.1f %7.1f %7.1f %6.1f %6.1f" % ( hm(t0), hm(t0 + 1800), hh, h47, tg, ee, e49, cs["待合"], cs["中待合"], cs["部屋の中"], cs["職員の廊下"], cs["玄関"], cs["エレベーターホール"], cs["トイレ"], cs["all"])) t0 += 1800 busy = [hall[t][0] for t in hall if 1800 <= t < 12600] quiet = [hall[t][0] for t in hall if t < 1800 or t >= 12600] b47 = [h147[t] for t in h147 if 1800 <= t < 12600]; q47 = [h147[t] for t in h147 if t < 1800 or t >= 12600] allh = list(hall.values()) print("外来の大廊下 x0〜70:混んでいる時間帯(8:00〜11:00)平均 %.1f 人・最大 %d 人(依頼155 %.1f・%d/目安 2〜8)/空いている時間帯 平均 %.1f 人・最大 %d 人(依頼155 %.1f・%d/目安 1〜3)" % ( sum(busy) / len(busy), max(busy), sum(b47) / len(b47), max(b47), sum(quiet) / len(quiet), max(quiet), sum(q47) / len(q47), max(q47))) print("1日の平均 %.2f 人(依頼155 %.2f 人)" % (sum(h[0] for h in allh) / len(allh), sum(h147.values()) / len(h147))) pm = [hall[t][0] for t in hall if t >= 19800] # 13:00 から(午後) pm49 = [h147[t] for t in h147 if t >= 19800] print("午後(13:00〜)平均 %.1f 人・最大 %d 人(依頼155 %.1f・%d/目安 1〜3)" % (sum(pm) / len(pm), max(pm), sum(pm49) / len(pm49), max(pm49))) ea = [hall[t][2] for t in hall]; e49a = list(e149.values()) print("大廊下 x70〜120:1日の平均 %.2f 人・最大 %d 人(依頼155 %.2f 人・%d 人)" % (sum(ea) / len(ea), max(ea), sum(e49a) / len(e49a), max(e49a))) sc = [byt[t]["職員の廊下"] for t in byt] print("職員の廊下の人数:平均 %.2f 人・最大 %d 人" % (sum(sc) / len(sc), max(sc))) # 依頼155 の職員の廊下 zb = rd(run149, "zones147.csv"); bt = defaultdict(int) for r in zb: if r["zone"] in SCOR: bt[float(r["t_s"])] += int(r["patients"]) + int(r["staff"]) print(" (依頼155 平均 %.2f 人・最大 %d 人)" % (sum(bt.values()) / max(1, len(bt)), max(bt.values()) if bt else 0)) # 7:30〜8:00(清掃の間) cl = [hall[t][0] for t in hall if t < 1800]; ce = [hall[t][2] for t in hall if t < 1800] cl5 = [h147[t] for t in h147 if t < 1800] print("7:30〜8:00(清掃の間):大廊下 x0〜70 平均 %.2f 人・最大 %d 人(依頼155 %.2f 人・%d 人)/x70〜120 平均 %.2f 人・最大 %d 人" % ( sum(cl) / len(cl), max(cl), sum(cl5) / len(cl5), max(cl5), sum(ce) / len(ce), max(ce))) def people(run, s): rows = rd(run, "people147.csv") for what in ("外来の患者", "付き添い", "化学療法の患者", "救急の患者", "病棟の患者", "病棟の看護師", "見舞いの人", "ほかの階の職員"): rs = [r for r in rows if r["what"] == what] st = sorted(float(r["stay_s"]) / 60 for r in rs if r["stay_s"]) inside = sum(1 for r in rs if r["spawn_s"] and not r["exit_s"]) never = sum(1 for r in rs if not r["spawn_s"]) if len(st) >= 2: q = statistics.quantiles(st, n=10) print("%s %d 人:出た %d・回の終わりに中にいた %d・入らなかった %d/いた時間 中央値 %.1f 分・最短 %.1f・最長 %.1f(10〜90%%:%.1f〜%.1f)" % ( what, len(rs), len(st), inside, never, statistics.median(st), st[0], st[-1], q[0], q[-1])) else: print("%s %d 人:出た %d・回の終わりに中にいた %d・入らなかった %d" % (what, len(rs), len(st), inside, never)) pat = [r for r in rows if r["what"] in ("外来の患者",)] sk = Counter() for r in rows: for x in r["skipped"].split("|"): if x: sk[r["what"] + " " + x] += 1 print("飛ばした行き先(人):", "・".join("%s %d 人" % kv for kv in sk.most_common()) or "なし") print("初診・紹介 %d 人(外来の患者 %d 人)" % (sum(1 for r in pat if r["first_visit"] == "1"), len(pat))) # トイレ tw = Counter(r["what"] for r in rows if r["toilet_want"] == "1") td = Counter((r["what"], r["toilet"]) for r in rows if r["toilet"]) tl = rd(run, "toilet149.csv") print("トイレ:行くと決めた人 %s/行った人 %s" % ("・".join("%s %d" % kv for kv in tw.items()), "・".join("%s→%s %d" % (k[0], k[1], v) for k, v in sorted(td.items())))) if tl: dur = [float(r["back_s"]) - float(r["leave_seat_s"]) for r in tl] walk = [float(r["arrive_s"]) - float(r["leave_seat_s"]) for r in tl] print(" 席を立ってから戻るまで 中央値 %.1f 分(最短 %.1f・最長 %.1f)/席からトイレまで歩いた時間 中央値 %.0f 秒・最長 %.0f 秒" % ( statistics.median(dur) / 60, min(dur) / 60, max(dur) / 60, statistics.median(walk), max(walk))) st = Counter(r["step"] for r in tl) print(" どこで待っている間に行ったか:", "・".join("%s %d" % kv for kv in st.most_common())) print(" 行く時が来ないまま回が終わった %d・行けるトイレがない %d・戻るのを待って次へ行くのが遅れた %d 回(計 %.0f 秒)" % ( s["flow_toilet_not_due"], s["flow_toilet_no_way"], s["flow_toilet_extend_n"], s["flow_toilet_extend_s"])) # エレベーター el = rd(run, "elevator149.csv") ec = Counter((r["what"], r["dir"]) for r in el) print("エレベーター(種類ごと):", "・".join("%s %s %d" % (k[0], k[1], v) for k, v in sorted(ec.items()))) wk = Counter(r["kind"] for r in el if r["what"] == "病棟の患者" and r["dir"] == "エレベーターから出る") print(" 病棟の患者の形:", "・".join("%s %d" % kv for kv in wk.items())) print("出さなかった人(行き先へ歩いて行けない):", s.get("flow_not_spawned"), "/救急の患者 %d 人(正面玄関から行ける %d)" % (s["flow_er_not_spawned"], s["flow_er_reach_from_main"])) xl = rd(run, "er_cross154.csv") for z in ("救急の待合", "救急の処置の場所"): rs = [r for r in xl if r["zone"] == z] byw = Counter(r["what"] for r in rs) sec = sorted(float(r["seconds"]) for r in rs) if sec: print("%s を通り抜けた外来の患者の役割の人 %d 人(%s)/そこにいた時間 合計 %.0f 秒・1人 中央値 %.1f 秒・最長 %.1f 秒" % ( z, len(rs), "・".join("%s %d" % kv for kv in byw.items()), sum(sec), statistics.median(sec), sec[-1])) else: print("%s を通り抜けた外来の患者の役割の人 0 人" % z) print("病棟の看護師:検査の所の中のそばに立った %d・所の中の点 %d・大廊下の端で待った %d/化学療法のトイレへ行けず西・東にした %d" % ( s.get("flow_ward_nurse_inside", -1), s.get("flow_ward_nurse_inside_random", -1), s["flow_ward_nurse_hall_waits"], s.get("flow_chemo_toilet_fallback", -1))) print("案A:付き添いを呼んだ %d・付き添った %d・間に合わない %d・時間切れ %d/付き添いなしで裏の通路にいた患者 %.1f 秒" % ( s["flow_escort_calls"], s["flow_escorts"], s["flow_escort_late"], s["flow_escort_timeouts"], s["flow_back_no_escort_s"])) pr = [r for r in pat if "処置・検査室" in r["steps"]] went = sum(1 for r in pr if any(x.startswith("処置・検査室:") and x.split(":")[3] for x in r["steps"].split("|"))) print(" 処置・検査室・内視鏡室の行き先がある外来の患者 %d 人・着いた %d 人" % (len(pr), went)) def east_end(a): return sum(1 for e in a["ev"] if (a["legs"][e["leg_id"]]["dir"] if e["leg_id"] in a["legs"] else "") != "待ち" and float(e["robot_x"]) >= 95 and float(e["robot_z"]) >= 27) def prob(a, b143, b147, b149, b154, b155): L = [a, b155, b154, b149, b147, b143] f = lambda g: " / ".join(g(x) for x in L) print("問題の数(1 急に止まった/2 ひやり/3 人がよけさせられた/4 立ち往生/5 横切り/止まりきれなかった) 依頼157 / 依頼155 / 依頼154 / 依頼149 / 依頼147 / 依頼143") print(" 走っている間 全部: " + f(lambda x: line(x["run"])) + " (合計 " + f(lambda x: "%d" % sum(x["run"].values())) + ")") for ar in ("外来の大廊下", "職員の廊下", "部屋の中", "玄関の通り"): print(" %s: " % ar + f(lambda x: line(x["area"][ar]))) print(" 台の前で待っている間: " + f(lambda x: line(x["wait"]))) print(" 速いままのひやり: " + f(lambda x: "%d" % x["fast"])) print(" 助け: " + f(lambda x: "%d" % len(x["resc"]))) print(" 大廊下の東の端(走っている間・ロボットの中心 x95 以上・z27 以上): " + f(lambda x: "%d" % east_end(x))) def chemo155(run, s): rows = rd(run, "people147.csv") ch = [r for r in rows if r["what"] == "化学療法の患者"] want = [r for r in ch if r["toilet_want"] == "1"] td = Counter(r["toilet"] or "(まだ・行く時が来ない)" for r in want) print("化学療法の患者 %d 人のうちトイレに行くと決まった %d 人:行き先 %s/化学療法のトイレへ行けず西・東にした %d 人" % ( len(ch), len(want), "・".join("%s %d" % (k, td.get(k, 0)) for k in ("化学療法のトイレ", "トイレ(西)", "トイレ(東)", "行けない", "(まだ・行く時が来ない)")), s.get("flow_chemo_toilet_fallback", -1))) ids = set(r["id"] for r in ch) tl = [r for r in rd(run, "toilet149.csv") if r["what"] == "化学療法の患者"] for r in tl: print(" id %s %s 席を立つ %s 秒・着く %s 秒(歩き %.1f 秒)・戻る %s 秒(帰り %.1f 秒)" % (r["id"], r["toilet"], r["leave_seat_s"], r["arrive_s"], float(r["arrive_s"]) - float(r["leave_seat_s"]), r["back_s"], float(r["back_s"]) - float(r["stay_end_s"]))) wy = rd(run, "chemo_way155.csv") bw = defaultdict(list) for r in wy: bw[r["what"]].append(r) print("トイレの前の通り道(x114〜115.5・z53〜60)にいた人 %d 人:" % len(wy)) for w, rs in bw.items(): print(" %s %d 人・いた時間 合計 %.0f 秒(1人 最長 %.1f 秒)・歩いている途中で止まっていた 合計 %.2f 秒・続けて止まった最長 %.2f 秒" % ( w, len(rs), sum(float(r["seconds"]) for r in rs), max(float(r["seconds"]) for r in rs), sum(float(r["stopped_s"]) for r in rs), max(float(r["longest_stop_s"]) for r in rs))) print(" 続けて止まった最長(全員)%.2f 秒" % s.get("flow_chemo_way_longest_stop_s", -1)) def staff155(run): st = rd(run, "staff147.csv") posts = defaultdict(set); own = {} for r in st: posts[r["role"]].add(r["zone"]); own[r["staff_id"] if "staff_id" in r else r["id"]] = r["zone"] mv = rd(run, "staff_moves147.csv") w = Counter(m["what"] for m in mv) print("職員の動き(終わったもの):", "・".join("%s %d" % kv for kv in w.items())) c = Counter(); non = 0; ownn = 0 for m in mv: if m["what"] != "持ち場から動く": continue c[(m["role"], m["dest"])] += 1 if m["dest"] not in posts[m["role"]]: non += 1 if m["dest"] == own[m["staff_id"]]: ownn += 1 print("ふだんの行き来(持ち場から動く)の行き先:役割ごと・所ごとの回数(*=その役割の持ち場がある所)") for role in ("医師", "看護師", "薬剤師", "検査技師", "事務"): ks = sorted(k for k in c if k[0] == role) print(" %s 計 %d:%s" % (role, sum(c[k] for k in ks), "・".join("%s%s %d" % (k[1], "*" if k[1] in posts[role] else "(持ち場でない)", c[k]) for k in ks))) print(" 持ち場がある所:" + "・".join(sorted(posts[role]))) print(" 持ち場でない所へ行った回数 %d/自分の持ち場の所が行き先 %d" % (non, ownn)) def staff157(run, s, a): st = rd(run, "staff157.csv") er = rd(run, "errands157.csv") trips = a["trips"] ran = [t for t in trips if t["start_s"]] arrived = [t for t in trips if t["arrive_b_s"]] exp = {6: sum(1 for t in ran if t["from"].startswith("内科外来の処置室")), 8: sum(1 for t in ran if t["from"] == "救急室の処置室"), 10: sum(1 for t in ran if t["from"] == "薬剤部の払い出し口"), 7: sum(1 for t in arrived if t["to"] == "外来化学療法室の受付"), 13: sum(1 for t in arrived if t["to"] == "検査部の検体受付"), 9: s.get("flow_staff_walks_scheduled", 0)} by = defaultdict(lambda: dict(n=0, type=0, out=0.0, outr=0.0, oute=0.0, et=0, ew=0, eo=0, mx=0.0)) for r in st: b = by[int(r["no"])] b["n"] += 1; b["type"] = int(r["type"]); o = float(r["outside_s"]); b["out"] += o; b["outr"] += float(r["outside_rescue_s"]); b["oute"] += float(r["outside_errand_s"]) b["et"] += int(r["errands_trip"]); b["ew"] += int(r["errands_walk"]); b["eo"] += int(r["errands_other"]); b["mx"] = max(b["mx"], o) print("職員の番号ごと(型・人数・持ち場の所の外にいた秒 合計(1人 最長)/そのうち助け・用事の間/用事の回数 便・人が運ぶ回・ほか/便の数・人が運ぶ回の数)") rows = s.get("flow_staff_by_no", {}) for no in sorted(by): b = by[no] e = exp.get(no) ok = "" if no in (6, 7, 8, 10, 13): ok = " 便の数 %d → %s" % (e, "合う" if b["et"] == e else "合わない") if no == 9: ok = " staff_walks_all %d 回 → %s" % (e, "合う" if b["ew"] == e else "合わない") print(" %2d 型%d %3d 人 外 %8.1f 秒(最長 %7.1f)/助け %.1f・用事 %.1f/便 %d・人が運ぶ回 %d・ほか %d%s" % (no, b["type"], b["n"], b["out"], b["mx"], b["outr"], b["oute"], b["et"], b["ew"], b["eo"], ok)) t1 = [no for no in by if by[no]["type"] == 1 and by[no]["out"] > 0] print(" 型1 で持ち場の所の外にいた番号:", t1 or "なし(全部 0 秒)") w = Counter(re_what(r["what"]) for r in er) print("用事(errands157):", "・".join("%s %d" % kv for kv in w.items()), "/出すのが遅れた(空いている人がいなかった)最大 %.1f 秒・終わりに出せていない %d・扉の内側に来る人がいない %d" % ( s.get("flow_errand_max_delay_s", 0), s.get("flow_errands_pending_at_end", 0), s.get("flow_errand_partner_missing", 0))) for r in er: if int(r["walk_no"]) > 0: print(" %s 番号 %s 職員 %s:%s 出す %s 秒・着く %s 秒・終わる %s 秒 %s" % (r["what"], r["no"], r["staff_id"], r["dest"], r["start_s"], r["arrive_s"], r["end_s"], r["note"])) mv = rd(run, "staff_moves147.csv") print("職員の動き(staff_moves147 の種類):", "・".join("%s %d" % kv for kv in Counter(re_what(m["what"]) for m in mv).items())) print("ほかの階の職員の3つ:", s.get("flow_other_floor_split")) print("清掃・警備の人:", s.get("flow_extra")) ex = rd(run, "extra157.csv") for r in ex: if "入る" in r["what"] or "出た" in r["what"] or "見回りに出る" in r["what"]: pass ses = [(r["t_s"], r["who"] + r["idx"], r["what"]) for r in ex if "入る" in r["what"] or "出た" in r["what"]] print(" 入る・出る:", "/".join("%s %s %s" % (hm(float(t)), w2, x.replace("正面玄関から", "")) for t, w2, x in ses)) print(" 見回り:", "・".join(hm(float(r["t_s"])) for r in ex if "見回りに出る" in r["what"])) def re_what(w): i = w.find("(") return w[:i] if i >= 0 else w def partners157(run, a, b): pa = {r["event_id"]: r for r in rd(run, "partners157.csv")} def run_ev(x): return [e for e in x["ev"] if (x["legs"][e["leg_id"]]["dir"] if e["leg_id"] in x["legs"] else "") != "待ち"] ra, rb = run_ev(a), run_ev(b) for lab, evs, base in (("依頼157", ra, False), ("依頼155", rb, True)): tot = sum(1 for e in evs if e["type"] in ("2", "3", "6")) stf = sum(1 for e in evs if e["type"] in ("2", "3", "6") and e["partner_kind"] in ("スタッフ", "ストレッチャー", "清掃のカート")) stf2 = sum(1 for e in evs if e["type"] in ("2", "3", "6") and e["partner_kind"] == "スタッフ") print("相手(%s・走っている間・ひやり+よけさせられた+止まりきれなかった %d 件):職員の形(スタッフ)%d 件(%.0f%%)・ストレッチャーと清掃のカートを足すと %d 件(%.0f%%)" % ( lab, tot, stf2, 100.0 * stf2 / max(1, tot), stf, 100.0 * stf / max(1, tot))) for k in (1, 2, 3, 5, 6): c = Counter() for e in ra: if e["type"] != str(k): continue p = pa.get(e["event_id"]) c[(p["cat"] + " " + p["no"]).strip() if p else "?"] += 1 if c: print(" 相手 %d %s(番号ごと): %s" % (k, TN[k], "・".join("%s %d" % kv for kv in c.most_common()))) c = Counter() for e in ra: if e["type"] in ("2", "3", "6"): p = pa.get(e["event_id"]) if p and p["cat"] in ("職員", "ほかの階の職員", "病棟の看護師", "清掃の人", "警備の人"): c[(p["cat"] + " " + p["no"]).strip() + ":" + re_what(p["doing"])] += 1 print(" 職員の形の相手が何をしていたか(2・3・6):", "・".join("%s %d" % kv for kv in c.most_common())) cw = Counter() for e in a["ev"]: if (a["legs"][e["leg_id"]]["dir"] if e["leg_id"] in a["legs"] else "") != "待ち": continue p = pa.get(e["event_id"]) cw[(p["cat"] + " " + p["no"]).strip() + (":" + re_what(p["doing"]) if p and p["cat"] == "職員" else "") if p else "?"] += 1 print(" 台の前で待っている間の相手:", "・".join("%s %d" % kv for kv in cw.most_common())) def stall157(run): st = rd(run, "stall157.csv"); nr = rd(run, "stall_near157.csv") near = defaultdict(list) for r in nr: near[r["stall_id"]].append(r) print("歩いている途中で 60 秒以上動けなかった人 %d 件:" % len(st)) for r in st: print(" #%s %s %s(%s・%s)%s 〜 %s(%s 秒)(%s,%s) %s/%s/終わり:%s" % (r["stall_id"], r["cat"], r["no"], r["kind"], r["walker_id"], hm(float(r["start_s"])), hm(float(r["end_s"])), r["dur_s"], r["x"], r["z"], r["zone"], r["doing"], r["end"])) for n in sorted(near[r["stall_id"]], key=lambda n: -float(n["near_s"])): print(" まわり:%s %s(%s・id %s)%s 秒(止まっていた %s・動いていた %s)最も近い %s m/%s" % (n["cat"], n["no"], n["kind"], n["near_id"], n["near_s"], n["stopped_s"], n["moving_s"], n["min_d_m"], n["doing"])) # 病棟の患者(救急室のまわり) xl = [r for r in rd(run, "er_cross154.csv") if r["what"] == "病棟の患者"] for z in ("救急の待合", "救急の処置の場所"): sec = sorted(float(r["seconds"]) for r in xl if r["zone"] == z) if sec: print("病棟の患者が %s にいた時間:%d 人・中央値 %.1f 秒・最長 %.1f 秒" % (z, len(sec), statistics.median(sec), sec[-1])) def green_early(run, a): # 7:30〜8:00 の緑の便(走っている間)の問題 legs = a["legs"]; c = Counter(); n = 0 for t in a["trips"]: if t["route"] != "green" or not t["start_s"] or float(t["start_s"]) >= 1800: continue n += 1 ids = {t["go_leg"], t["back_leg"]} for e in a["ev"]: if e["leg_id"] in ids: c[int(e["type"])] += 1 print("7:30〜8:00 に出た緑の便 %d 便の問題(走っている間):%s(合計 %d)" % (n, line(c), sum(c.values()))) def main(): b143 = {k: one(v) for k, v in R143.items()} b147 = {k: one(v) for k, v in R147.items()} b149 = {k: one(v) for k, v in R149.items()} b154 = {k: one(v) for k, v in R154.items()} b155 = {k: one(v) for k, v in R155.items()} for run in sys.argv[1:]: a = one(run) s = a["s"] key = "switch" if s["plan_key"] == "switch" else "hall" print() print("== %s(%s)status %s/回の終わり %.1f 秒(%s)/最後の便が戻った %.1f 秒/実時間 %.1f 分" % ( os.path.basename(run), s["plan"], s["status"], s["sim_s"], hm(s["sim_s"]), s["last_trip_end_s"], s["wall_s"] / 60)) print("便 %d(走った %d・途中 %d・走れなかった %d)/移る %d(終えた %d)/出るのが遅れた 平均 %.1f 秒・最大 %.1f 秒" % ( s["trips_scheduled"], s["trips_done"], s["trips_unfinished_at_end"], s["trips_not_run_after_end"] + s["trips_not_run_other"], s["moves"], s["moves_done"], s["delay_mean_s"], s["delay_max_s"])) print("瞬間移動 ロボット %d(1コマ最大 %.3f m)・人 %d(最大 %.3f m)/人の引き直し(180秒動けない)%d/行き先の近くで止まって待った %d" % ( s["robot_jumps"], s["robot_max_step_m"], s["person_jumps"], s["person_max_step_m"], s.get("flow_stuck_regoes", 0), s.get("flow_near_stops", 0))) st = [e for e in a["ev"] if e["type"] == "4"] print("立ち往生 %d: %s" % (len(st), "/".join("%s〜%s秒 %s秒 (%s,%s) %s" % (e["t_s"], e["end_s"], e["value"], e["robot_x"], e["robot_z"], e["note"]) for e in st))) print("助け %d: %s" % (len(a["resc"]), "/".join("%s秒 (%s,%s) %s・%s" % (r["call_s"], r["x"], r["z"], r["partner"], r["outcome"]) for r in a["resc"]))) print("ロボットの入らない所に中心が入った時間 %.2f 秒/どの所にも入っていない時間 %.2f 秒" % (s["robot_forbidden_s"], s["robot_no_zone_s"])) if s.get("people_mode") == "flow": print("人が access で入れない所に入った時間(役割ごと):", "・".join("%s %.2f 秒" % (r, s["flow_forbidden_s_" + r]) for r in ROLES)) print("どの所にも入っていない時間(役割ごと):", "・".join("%s %.2f 秒" % (r, s["flow_no_zone_s_" + r]) for r in ROLES)) print("職員 %d 人/持ち場から動いた %d 回・看護師が呼びに出た %d 回(看護師なし %d・間に合わない %d)" % ( s["flow_staff_total"], s["flow_staff_moves"], s["flow_nurse_calls"], s["flow_nurse_calls_no_nurse"], s["flow_nurse_late"])) print("席 %d(使えない %d)・机などの横の点 %d・診察室 %d/所 %d 枚・区画 %d/壁の箱 %d・家具の箱 %d" % ( s["flow_seats"], s["flow_seats_dropped"], s["flow_spots"], s["flow_consult_rooms"], s["flow_pieces"], s["flow_areas"], s["flow_wall_boxes"], s["flow_furniture_boxes"])) print("飛ばした行き先(理由):", s["flow_skips"]) people(run, s) chemo155(run, s) staff157(run, s, a) zones_table(run, s, R155[key]) prob(a, b143[key], b147[key], b149[key], b154[key], b155[key]) partners157(run, a, b155[key]) stall157(run) green_early(run, a) lc = Counter() for e in a["ev"]: d = a["legs"][e["leg_id"]]["dir"] if e["leg_id"] in a["legs"] else "" lc[d] += 1 print(" 区間ごとの数(全部の種類):", "・".join("%s %d" % kv for kv in lc.items())) for k in range(1, 7): if a["kinds"][k]: print(" 相手 %d %s: %s" % (k, TN[k], "・".join("%s %d" % kv for kv in a["kinds"][k].most_common()))) if __name__ == "__main__": main()