-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathextract_ptnml.py
More file actions
118 lines (90 loc) · 2.75 KB
/
Copy pathextract_ptnml.py
File metadata and controls
118 lines (90 loc) · 2.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#!/usr/bin/env python3
import argparse
import glob
from collections import defaultdict
from itertools import chain
import chess.pgn
# [LL, LD/DL, WL/DD/LW, WD/DW, WW]
PTNML_INDEX = {-2: 0, -1: 1, 0: 2, 1: 3, 2: 4}
def score_from_new(headers):
result = headers["Result"]
if result == "1/2-1/2":
return 0
new_is_white = headers["White"] == "new"
if new_is_white:
return 1 if result == "1-0" else -1
else:
return 1 if result == "0-1" else -1
def main():
parser = argparse.ArgumentParser(
description="Extract WDL and pentanomial statistics from fastchess PGNs"
)
parser.add_argument("pgns", nargs="+")
args = parser.parse_args()
pairs = defaultdict(list)
# WDL = [loss, draw, win]
wdl = [0, 0, 0]
games = 0
for filename in chain.from_iterable(glob.glob(p) for p in args.pgns):
with open(filename, encoding="utf-8") as f:
while (game := chess.pgn.read_game(f)) is not None:
headers = game.headers
score = score_from_new(headers)
games += 1
if score < 0:
wdl[0] += 1
elif score == 0:
wdl[1] += 1
else:
wdl[2] += 1
fen = headers.get("FEN")
round_id = headers.get("Round")
if fen is None or round_id is None:
raise RuntimeError(
f"{filename}: missing FEN or Round tag"
)
# Include filename because each shard starts rounds again
key = (
filename,
round_id,
fen,
)
pairs[key].append(score)
ptnml = [0] * 5
pairs_count = 0
for key, scores in pairs.items():
if len(scores) != 2:
print(
f"Skipping incomplete pair {key}: got {len(scores)} games"
)
continue
# Make sure the two games are the repeat pair
if scores[0] + scores[1] not in PTNML_INDEX:
raise RuntimeError("Invalid pair score")
ptnml[PTNML_INDEX[scores[0] + scores[1]]] += 1
pairs_count += 1
print(f"Games: {games}")
print(f"Pairs: {pairs_count}")
print()
print("WDL:")
print(f" Loss: {wdl[0]}")
print(f" Draw: {wdl[1]}")
print(f" Win : {wdl[2]}")
print()
print(wdl)
print()
print("PTNML:")
names = [
"LL",
"LD",
"WL/DD",
"WD",
"WW",
]
for name, count in zip(names, ptnml):
print(f" {name:10}: {count}")
print()
print(ptnml)
print(" ".join([str(w) for w in ptnml]))
if __name__ == "__main__":
main()