"""Cross-pod damage analysis for the #95 cluster-burst change. For each node: what it FIRED (shooter-side projectile impacts) versus what it RECEIVED (zone applications), so a round fired on one node can be seen landing on the other with its burst count intact. """ import re, sys, collections def load(path): return open(path, encoding="latin-1", errors="replace").read() RX_HIT = re.compile(r"\[dmghit\] mech=(\S+) zone=(\d+) vital=(\d) type=(\d+) " r"amt=([0-9.eE+-]+) burst=([0-9.]+) lvl ([0-9.eE+-]+)->([0-9.eE+-]+)") RX_IMP = re.compile(r"\[projectile\] IMPACT damage=([0-9.]+) subsys=(\d+).*?burst=(\d+)") for name, path in [("NODE A (1501)", sys.argv[1]), ("NODE B (1601)", sys.argv[2])]: d = load(path) imps = RX_IMP.findall(d) hits = RX_HIT.findall(d) print("=" * 62) print("%s %s" % (name, path)) print(" FIRED : %d projectile impacts, bursts=%s" % (len(imps), dict(sorted(collections.Counter(int(b) for _, _, b in imps).items())))) byType = collections.defaultdict(list) for mech, zone, vital, ty, amt, burst, a, b in hits: byType[int(ty)].append((float(amt), int(float(burst)), float(b) - float(a))) print(" TOOK : %d zone applications" % len(hits)) for ty in sorted(byType): v = byType[ty] label = {2: "EXPLOSIVE(missile/AC)", 3: "ENERGY(beam)", 0: "COLLISION"}.get(ty, "type%d" % ty) print(" %-22s %3d apps bursts=%-28s dlvl=%.4f" % (label, len(v), dict(sorted(collections.Counter(b for _, b, _ in v).items())), sum(x[2] for x in v))) mult = [b for _, b, _ in byType.get(2, []) if b > 1] print(" >>> multi-burst EXPLOSIVE applications received: %d %s" % (len(mult), "<-- cluster count SURVIVED the wire" if mult else "<-- NONE (burst lost!)")) for tag in ("Unhandled", "assert", "ACCESS_VIOLATION"): n = len(re.findall(tag, d, re.I)) if n: print(" !! %s x%d" % (tag, n))