#!/usr/bin/env python3 """扫描 training_data 目录下所有 CSV,按 bot 类型统计胜率""" import sys, os, glob, re from collections import Counter, defaultdict def scan(csv_dir='training_data'): csvs = sorted(glob.glob(os.path.join(csv_dir, 'game_*.csv'))) if not csvs: print("No CSV files found") return total = 0 per_bot = defaultdict(lambda: {'wins': 0, 'games': 0}) per_game = [] # (game_id, winner_pos, bots_str) for fp in csvs: with open(fp) as f: for line in f: if line.startswith('#RESULT'): parts = line.strip().split(',') winner = int(parts[1].split('=')[1]) bots = parts[2].split('=')[1].split(',') game_id = os.path.splitext(os.path.basename(fp))[0] per_game.append((game_id, winner, line.strip())) total += 1 # winner_pos is 1-indexed, bots[winner-1] for i, bt in enumerate(bots): per_bot[bt]['games'] += 1 winner_bt = bots[winner - 1] if 0 < winner <= len(bots) else '?' per_bot[winner_bt]['wins'] += 1 break if total == 0: print("No #RESULT lines found. Run with updated hjha-console.") return print(f"{total} games scanned") print(f"{'Bot':<12} {'Wins':>6} {'Rate':>8} {'Games':>6}") print("-" * 35) for bt in sorted(per_bot.keys()): d = per_bot[bt] rate = d['wins'] / d['games'] * 100 if d['games'] > 0 else 0 print(f"{bt:<12} {d['wins']:>6} {rate:>7.1f}% {d['games']:>6}") # 也统计按 bot 组合 combo_stats = defaultdict(lambda: {'total': 0, 'winners': Counter()}) for gid, winner, line in per_game: m = re.search(r'bots=([^,]+(?:,[^,]+)*)', line) if m: key = m.group(1) combo_stats[key]['total'] += 1 combo_stats[key]['winners'][winner] += 1 if len(combo_stats) > 0: print(f"\nBy bot composition:") for combo in sorted(combo_stats.keys()): d = combo_stats[combo] bots = combo.split(',') print(f" [{combo}] — {d['total']} games:") for pos, count in sorted(d['winners'].items()): bt = bots[pos-1] if 0 < pos <= len(bots) else '?' print(f" pos{pos}({bt}): {count}/{d['total']} ({count/d['total']*100:.0f}%)") if __name__ == '__main__': d = sys.argv[1] if len(sys.argv) > 1 else 'training_data' # 如果指定了目录不存在, 可能是编号的round目录 if not os.path.isdir(d): # 尝试 training_rounds 下最新 rounds = sorted(glob.glob('training_rounds/r*')) if rounds: d = os.path.join(rounds[-1], 'training_data') if not os.path.isdir(d): print(f"No training_data in {rounds[-1]}") sys.exit(1) else: print("No data found") sys.exit(1) scan(d)