79 lines
3.0 KiB
Python
79 lines
3.0 KiB
Python
#!/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) |