#!/usr/bin/env python3 """All-time kill counter (bots and humans). ./kills show the scoreboard (and save the tally) Counts the " killed " lines in hlds/cstrike/logs. Per-log counts are kept in kills-tally.json, so the totals survive scripts/backup.sh deleting logs older than 30 days (it runs this first).""" import collections, json, os, re D = os.path.dirname(os.path.abspath(__file__)) LOGS = os.path.join(D, "hlds", "cstrike", "logs") STATE = os.path.join(D, "kills-tally.json") KILL = re.compile(r'^L (\d\d/\d\d/\d{4}) - [\d:]+: "(.+?)<\d+><[^>]*><[^>]*>" killed ' r'".+?<\d+><[^>]*><[^>]*>" with "([^"]+)"') try: st = json.load(open(STATE)) except (OSError, ValueError): st = {"files": {}} for f in sorted(os.listdir(LOGS)) if os.path.isdir(LOGS) else []: if not f.endswith(".log"): continue n, who, wpn, days = 0, collections.Counter(), collections.Counter(), set() for line in open(os.path.join(LOGS, f), encoding="utf-8", errors="replace"): m = KILL.match(line) if m: n += 1; days.add(m[1]); who[m[2]] += 1; wpn[m[3]] += 1 if n or f not in st["files"]: st["files"][f] = {"kills": n, "who": who, "wpn": wpn, "days": sorted(days)} tmp = STATE + ".tmp" json.dump(st, open(tmp, "w")) os.replace(tmp, STATE) total, who, wpn, days = 0, collections.Counter(), collections.Counter(), set() for v in st["files"].values(): total += v["kills"]; who.update(v["who"]); wpn.update(v["wpn"]); days.update(v["days"]) print(f"\n ALL-TIME KILLS: {total:,} ({len(days)} days of carnage, {len(st['files'])} maps played)\n") print(" top fraggers:") for i, (n, k) in enumerate(who.most_common(5), 1): print(f" {i}. {n:<18} {k:,}") print("\n weapons of choice:") for n, k in wpn.most_common(5): print(f" {n:<18} {k:,}") print()