-
Notifications
You must be signed in to change notification settings - Fork 0
/
result_checker.py
254 lines (191 loc) · 7.31 KB
/
result_checker.py
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
#!/usr/bin/python
## coding=utf-8
import codecs
import sys
from card import Card
from hand import Hand, TYPE_NAME
class GameLogParser:
def __init__(self, filename):
self.filename = filename
def read_line(self):
self.cline = self.file.readline()
def parse(self, *games):
with codecs.open(self.filename, 'r', encoding='UTF-8') as self.file:
self.read_line()
# read until eof
while self.cline:
game_line = self.cline.strip()
for game in games:
if game.check_title(self.cline):
print game_line
game.process(self)
self.read_line()
for game in games:
game.print_coverage()
def search_until(self, *search):
while True:
for pair in search:
if pair[0] in self.cline:
return pair[1]
self.read_line()
def read_until(self, search):
while search not in self.cline:
self.read_line()
def before(self, end_char):
return self.cline[:self.cline.index(end_char)]
def between(self, start_char, end_char):
return self.cline[self.cline.index(start_char) + 1: self.cline.index(end_char)]
class GameLogic:
game_name = "???"
def __init__(self):
# create two dimensional array (list of lists) to hold counters for different hand comparisons
self.coverage = [[0 for y in range(11)] for x in range(11)]
self.coverage_count = 0
def update_coverage(self, hands):
"""
Combine winning hand with every other hand and increment comparison counters
"""
winner = max(hands)
for hand in hands:
if hand != winner:
self.coverage[winner[0].type][hand[0].type] += 1
self.coverage_count += 1
def print_coverage(self):
"""
Print debug information
"""
print "%s coverage report (%d hands compared)" % (self.game_name, self.coverage_count)
print ' ' * 14, ''.join(map(lambda tn: tn.center(14), TYPE_NAME))
for type_name, counts in zip(TYPE_NAME, self.coverage):
print type_name.rjust(14), ''.join(map(lambda count: str(count).center(14), counts))
def check_title(self, line):
"""
Return True if line starts game-log for accepted type of game
"""
raise NotImplementedError("Please Implement this method")
def process(self, parser):
"""
Process the game-log and return True if log declares correct winner(s)
"""
raise NotImplementedError("Please Implement this method")
def print_error(self, hands, winners, winners_by_log):
"""
Helper method to declare dispute in subclasses process()
"""
print " ERROR"
for hand in hands:
print " {player}: [{hand}] {ipj}{chk}".format(
player=str(hand[1]),
hand=str(hand[0]),
ipj='(ipj)' if hand[1] in winners_by_log else '',
chk='(chk)' if hand[1] in winners else '',
)
class SokoLogic(GameLogic):
game_name = "Sökö"
def __init__(self):
GameLogic.__init__(self)
def check_title(self, line):
return u'GAME #' in line and u'Sökö' in line
def process(self, parser):
# read all hands in showdown
hands = self.parse_showdown(parser)
if not hands:
return True
self.update_coverage(hands)
# collect all players whose hand is equal to the best hand
winners = [hand[1] for hand in hands if hand[0] == max(hands)[0]]
# who is the winner in log?
winners_by_log = self.parse_summary(parser)
if set(winners_by_log) == set(winners):
return True
else:
self.print_error(hands, winners, winners_by_log)
return False
def parse_showdown(self, parser):
# search for showdown title
if not parser.search_until((u'*** SHOW DOWN ***', True), (u'*** SUMMARY ***', False)):
parser.read_line()
return []
# showdown title line processed -> advance to next line
parser.read_line()
hands = []
# read until summary title concludes the showdown
while u'*** SUMMARY ***' not in parser.cline:
# skip mucked hands
# if u'(mucked)' not in parser.cline:
try:
player = parser.before(':')
cards = parser.between('[', ']')
hand = Hand.from_str(cards)
hands.append((hand, player))
except ValueError:
pass
# hand processed -> advance to next line
parser.read_line()
return hands
def parse_summary(self, parser):
winners = []
parser.read_until(u'wins')
while u'wins' in parser.cline:
winners.append(parser.before(':'))
# winner processed -> advance to next line
parser.read_line()
return winners
class HoldemLogic(GameLogic):
game_name = "Holdem"
def __init__(self):
GameLogic.__init__(self)
def check_title(self, line):
return u'GAME #' in line and u'Holdem' in line
def process(self, parser):
# read table cards
river = self.parse_river(parser)
# read all hands in showdown
hands = self.parse_showdown(parser, river)
self.update_coverage(hands)
# collect all players whose hand is equal to the best hand
winners = [hand[1] for hand in hands if hand[0] == max(hands)[0]]
# who is the winner in log?
winners_by_log = self.parse_summary(parser)
if set(winners_by_log) == set(winners):
return True
else:
self.print_error(hands, winners, winners_by_log)
return False
def parse_river(self, parser):
# search for river title
parser.read_until(u'*** RIVER ***')
cards = Card.from_str(parser.between('[', ']'))
parser.read_line()
return cards
def parse_showdown(self, parser, river):
# search for showdown title
parser.read_until(u'*** SHOW DOWN ***')
# showdown title line processed -> advance to next line
parser.read_line()
hands = []
# read until summary title concludes the showdown
while u'*** SUMMARY ***' not in parser.cline:
# skip mucked hands
if u'(mucked)' not in parser.cline:
try:
player = parser.before(':')
cards = Card.from_str(parser.between('[', ']'))
hand = Hand.from_cards(river + cards)
hands.append((hand, player))
except ValueError:
pass
# hand processed -> advance to next line
parser.read_line()
return hands
def parse_summary(self, parser):
winners = []
parser.read_until(u'wins')
while u'wins' in parser.cline:
winners.append(parser.before(':'))
# winner processed -> advance to next line
parser.read_line()
return winners
if __name__ == "__main__":
parser = GameLogParser(sys.argv[1])
parser.parse(SokoLogic(), HoldemLogic())