Expanded my entry in contributors.txt.
[fpdb-dooglus.git] / pyfpdb / TestHandsPlayers.py
blob88cc2940c0e6160c218c4e474dc4dd9d821afccd
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
4 # Copyright 2010-2011, Carl Gherardi
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 ########################################################################
21 import sys
22 import os
23 import codecs
24 from Hand import *
25 import Configuration
26 import Database
27 import SQL
28 import fpdb_import
29 import Options
30 import datetime
31 import pytz
32 import pprint
33 pp = pprint.PrettyPrinter(indent=4)
35 DEBUG = False
38 class FpdbError:
39 def __init__(self, sitename):
40 self.site = sitename
41 self.errorcount = 0
42 self.histogram = {}
43 self.statcount = {}
45 def error_report(self, filename, hand, stat, ghash, testhash, player):
46 print "Regression Test Error:"
47 print "\tFile: %s" % filename
48 print "\tStat: %s" % stat
49 print "\tPlayer: %s" % player
50 if filename in self.histogram:
51 self.histogram[filename] += 1
52 else:
53 self.histogram[filename] = 1
55 if stat in self.statcount:
56 self.statcount[stat] += 1
57 else:
58 self.statcount[stat] = 1
59 self.errorcount += 1
61 def print_histogram(self):
62 print "%s:" % self.site
63 for f in self.histogram:
64 idx = f.find('regression')
65 print "(%3d) : %s" %(self.histogram[f], f[idx:])
67 def compare_gametypes_file(filename, importer, errors):
68 hashfilename = filename + '.gt'
70 in_fh = codecs.open(hashfilename, 'r', 'utf8')
71 whole_file = in_fh.read()
72 in_fh.close()
74 testhash = eval(whole_file)
76 hhc = importer.getCachedHHC()
77 handlist = hhc.getProcessedHands()
79 lookup = {
80 0:'Gametype: siteId',
81 1:'Gametype: currency',
82 2:'Gametype: type',
83 3:'Gametype: base',
84 4:'Gametype: game',
85 5:'Gametype: limit',
86 6:'Gametype: hilo',
87 7:'Gametype: Small Blind',
88 8:'Gametype: Big Blind',
89 9:'Gametype: Small Bet',
90 10:'Gametype: Big Bet',
91 11:'Gametype: maxSeats',
92 12:'Gametype: ante'
95 for hand in handlist:
96 ghash = hand.gametyperow
97 for i in range(len(ghash)):
98 #print "DEBUG: about to compare: '%s' and '%s'" %(ghash[i], testhash[i])
99 if ghash[i] == testhash[i]:
100 # The stats match - continue
101 pass
102 else:
103 errors.error_report(filename, hand, lookup[i], ghash, testhash, None)
104 pass
106 def compare_handsplayers_file(filename, importer, errors):
107 hashfilename = filename + '.hp'
109 in_fh = codecs.open(hashfilename, 'r', 'utf8')
110 whole_file = in_fh.read()
111 in_fh.close()
113 testhash = eval(whole_file)
115 hhc = importer.getCachedHHC()
116 handlist = hhc.getProcessedHands()
117 #We _really_ only want to deal with a single hand here.
118 for hand in handlist:
119 ghash = hand.stats.getHandsPlayers()
120 for p in ghash:
121 #print "DEBUG: player: '%s'" % p
122 pstat = ghash[p]
123 teststat = testhash[p]
125 for stat in pstat:
126 #print "pstat[%s][%s]: %s == %s" % (p, stat, pstat[stat], teststat[stat])
127 try:
128 if pstat[stat] == teststat[stat]:
129 # The stats match - continue
130 pass
131 else:
132 if stat == 'tourneyTypeId' or stat == 'tourneysPlayersIds' or stat == 'showed':
133 # Not and error
134 pass
135 else:
136 errors.error_report(filename, hand, stat, ghash, testhash, p)
137 except KeyError, e:
138 errors.error_report(filename, False, "KeyError: '%s'" % stat, False, False, p)
140 def compare_hands_file(filename, importer, errors):
141 hashfilename = filename + '.hands'
143 in_fh = codecs.open(hashfilename, 'r', 'utf8')
144 whole_file = in_fh.read()
145 in_fh.close()
147 testhash = eval(whole_file)
149 hhc = importer.getCachedHHC()
150 handlist = hhc.getProcessedHands()
152 for hand in handlist:
153 ghash = hand.stats.getHands()
154 # Delete unused data from hash
155 try:
156 del ghash['gsc']
157 del ghash['sc']
158 del ghash['id']
159 except KeyError:
160 pass
161 del ghash['boards']
162 for datum in ghash:
163 #print "DEBUG: hand: '%s'" % datum
164 try:
165 if ghash[datum] == testhash[datum]:
166 # The stats match - continue
167 pass
168 else:
169 # Stats don't match.
170 if (datum == "gametypeId"
171 or datum == 'sessionId'
172 or datum == 'tourneyId'
173 or datum == 'gameSessionId'
174 or datum == 'fileId'
175 or datum == 'runItTwice'):
176 # Not an error. gametypeIds are dependent on the order added to the db.
177 #print "DEBUG: Skipping mismatched gamtypeId"
178 pass
179 else:
180 errors.error_report(filename, hand, datum, ghash, testhash, None)
181 except KeyError, e:
182 errors.error_report(filename, False, "KeyError: '%s'" % datum, False, False, None)
185 def compare(leaf, importer, errors, site):
186 filename = leaf
187 #print "DEBUG: fileanme: %s" % filename
189 # Test if this is a hand history file
190 if filename.endswith('.txt'):
191 # test if there is a .hp version of the file
192 if DEBUG: print "Site: %s" % site
193 if DEBUG: print "Filename: %s" % filename
194 importer.addBulkImportImportFileOrDir(filename, site=site)
195 (stored, dups, partial, errs, ttime) = importer.runImport()
197 if errs > 0:
198 errors.error_report(filename, False, "Parse", False, False, False)
199 else:
200 if os.path.isfile(filename + '.hp'):
201 compare_handsplayers_file(filename, importer, errors)
202 if os.path.isfile(filename + '.hands'):
203 compare_hands_file(filename, importer, errors)
204 if os.path.isfile(filename + '.gt'):
205 compare_gametypes_file(filename, importer, errors)
207 importer.clearFileList()
211 def walk_testfiles(dir, function, importer, errors, site):
212 """Walks a directory, and executes a callback on each file """
213 dir = os.path.abspath(dir)
214 try:
215 for file in [file for file in os.listdir(dir) if not file in [".",".."]]:
216 nfile = os.path.join(dir,file)
217 if os.path.isdir(nfile):
218 walk_testfiles(nfile, compare, importer, errors, site)
219 else:
220 function(nfile, importer, errors, site)
221 except OSError as (errno, strerror):
222 if errno == 20:
223 # Error 20 is 'not a directory'
224 function(dir, importer, errors, site)
225 else:
226 raise OSError(errno, strerror)
228 def usage():
229 print "USAGE:"
230 print "Run all tests:"
231 print "\t./TestHandsPlayers.py"
232 print "Run tests for a sinlge site:"
233 print "\t./TestHandsPlayers -s <Sitename>"
234 print "Run tests for a sinlge file in a site:"
235 print "\t./TestHandsPlayers -s <Sitename> -f <filename>"
236 sys.exit(0)
238 def main(argv=None):
239 if argv is None:
240 argv = sys.argv[1:]
242 (options, argv) = Options.fpdb_options()
244 test_all_sites = True
246 if options.usage == True:
247 usage()
249 single_file_test = False
251 if options.sitename:
252 options.sitename = Options.site_alias(options.sitename)
253 if options.sitename == False:
254 usage()
255 if options.filename:
256 print "Testing single hand: '%s'" % options.filename
257 single_file_test = True
258 else:
259 print "Only regression testing '%s' files" % (options.sitename)
260 test_all_sites = False
262 config = Configuration.Config(file = "HUD_config.test.xml")
263 db = Database.Database(config)
264 sql = SQL.Sql(db_server = 'sqlite')
265 settings = {}
266 settings.update(config.get_db_parameters())
267 settings.update(config.get_import_parameters())
268 settings.update(config.get_default_paths())
269 db.recreate_tables()
270 importer = fpdb_import.Importer(False, settings, config, None)
271 importer.setDropIndexes("don't drop")
272 importer.setFailOnError(True)
273 importer.setThreads(-1)
274 importer.setCallHud(False)
275 importer.setFakeCacheHHC(True)
277 PacificPokerErrors= FpdbError('PacificPoker')
278 PokerStarsErrors = FpdbError('PokerStars')
279 FTPErrors = FpdbError('Full Tilt Poker')
280 PartyPokerErrors = FpdbError('Party Poker')
281 BetfairErrors = FpdbError('Betfair')
282 OnGameErrors = FpdbError('OnGame')
283 AbsoluteErrors = FpdbError('Absolute Poker')
284 UltimateBetErrors = FpdbError('Ultimate Bet')
285 EverleafErrors = FpdbError('Everleaf Poker')
286 EverestErrors = FpdbError('Everest Poker')
287 CarbonErrors = FpdbError('Carbon')
288 PKRErrors = FpdbError('PKR')
289 iPokerErrors = FpdbError('iPoker')
290 Win2dayErrors = FpdbError('Win2day')
291 WinamaxErrors = FpdbError('Winamax')
293 ErrorsList = [
294 PacificPokerErrors, PokerStarsErrors, FTPErrors, PartyPokerErrors,
295 BetfairErrors, OnGameErrors, AbsoluteErrors,
296 EverleafErrors, CarbonErrors, PKRErrors,
297 iPokerErrors, WinamaxErrors, UltimateBetErrors,
298 Win2dayErrors, EverestErrors,
301 sites = {
302 'PacificPoker' : False,
303 'PokerStars' : False,
304 'Full Tilt Poker' : False,
305 'PartyPoker' : False,
306 'Betfair' : False,
307 'OnGame' : False,
308 'Absolute' : False,
309 'UltimateBet' : False,
310 'Everleaf' : False,
311 'Carbon' : False,
312 #'PKR' : False,
313 'iPoker' : False,
314 'Win2day' : False,
315 'Winamax' : False,
316 'Everest' : False,
319 if test_all_sites == True:
320 for s in sites:
321 sites[s] = True
322 else:
323 sites[options.sitename] = True
325 if sites['PacificPoker'] == True and not single_file_test:
326 walk_testfiles("regression-test-files/cash/PacificPoker/", compare, importer, PacificPokerErrors, "PacificPoker")
327 elif sites['PacificPoker'] == True and single_file_test:
328 walk_testfiles(options.filename, compare, importer, PacificPokerErrors, "PacificPoker")
330 if sites['PokerStars'] == True and not single_file_test:
331 walk_testfiles("regression-test-files/cash/Stars/", compare, importer, PokerStarsErrors, "PokerStars")
332 walk_testfiles("regression-test-files/tour/Stars/", compare, importer, PokerStarsErrors, "PokerStars")
333 elif sites['PokerStars'] == True and single_file_test:
334 walk_testfiles(options.filename, compare, importer, PokerStarsErrors, "PokerStars")
336 if sites['Full Tilt Poker'] == True and not single_file_test:
337 walk_testfiles("regression-test-files/cash/FTP/", compare, importer, FTPErrors, "Full Tilt Poker")
338 walk_testfiles("regression-test-files/tour/FTP/", compare, importer, FTPErrors, "Full Tilt Poker")
339 elif sites['Full Tilt Poker'] == True and single_file_test:
340 walk_testfiles(options.filename, compare, importer, FTPErrors, "Full Tilt Poker")
341 if sites['PartyPoker'] == True and not single_file_test:
342 walk_testfiles("regression-test-files/cash/PartyPoker/", compare, importer, PartyPokerErrors, "PartyPoker")
343 walk_testfiles("regression-test-files/tour/PartyPoker/", compare, importer, PartyPokerErrors, "PartyPoker")
344 elif sites['PartyPoker'] == True and single_file_test:
345 walk_testfiles(options.filename, compare, importer, PartyPokerErrors, "PartyPoker")
346 if sites['Betfair'] == True and not single_file_test:
347 walk_testfiles("regression-test-files/cash/Betfair/", compare, importer, BetfairErrors, "Betfair")
348 elif sites['Betfair'] == True and single_file_test:
349 walk_testfiles(options.filename, compare, importer, BetfairErrors, "Betfair")
350 if sites['OnGame'] == True and not single_file_test:
351 walk_testfiles("regression-test-files/cash/OnGame/", compare, importer, OnGameErrors, "OnGame")
352 walk_testfiles("regression-test-files/tour/ongame/", compare, importer, OnGameErrors, "OnGame")
353 elif sites['OnGame'] == True and single_file_test:
354 walk_testfiles(options.filename, compare, importer, OnGameErrors, "OnGame")
355 if sites['Absolute'] == True and not single_file_test:
356 walk_testfiles("regression-test-files/cash/Absolute/", compare, importer, AbsoluteErrors, "Absolute")
357 walk_testfiles("regression-test-files/tour/Absolute/", compare, importer, AbsoluteErrors, "Absolute")
358 elif sites['Absolute'] == True and single_file_test:
359 walk_testfiles(options.filename, compare, importer, AbsoluteErrors, "Absolute")
360 if sites['UltimateBet'] == True and not single_file_test:
361 walk_testfiles("regression-test-files/cash/UltimateBet/", compare, importer, UltimateBetErrors, "Absolute")
362 elif sites['UltimateBet'] == True and single_file_test:
363 walk_testfiles(options.filename, compare, importer, UltimateBetErrors, "Absolute")
364 if sites['Everleaf'] == True and not single_file_test:
365 walk_testfiles("regression-test-files/cash/Everleaf/", compare, importer, EverleafErrors, "Everleaf")
366 walk_testfiles("regression-test-files/tour/Everleaf/", compare, importer, EverleafErrors, "Everleaf")
367 elif sites['Everleaf'] == True and single_file_test:
368 walk_testfiles(options.filename, compare, importer, EverleafErrors, "Everleaf")
369 if sites['Everest'] == True and not single_file_test:
370 walk_testfiles("regression-test-files/cash/Everest/", compare, importer, EverestErrors, "Everest")
371 elif sites['Everest'] == True and single_file_test:
372 walk_testfiles(options.filename, compare, importer, EverestErrors, "Everest")
373 if sites['Carbon'] == True and not single_file_test:
374 walk_testfiles("regression-test-files/cash/Carbon/", compare, importer, CarbonErrors, "Carbon")
375 elif sites['Carbon'] == True and single_file_test:
376 walk_testfiles(options.filename, compare, importer, CarbonErrors, "Carbon")
377 #if sites['PKR'] == True and not single_file_test:
378 # walk_testfiles("regression-test-files/cash/PKR/", compare, importer, PKRErrors, "PKR")
379 if sites['iPoker'] == True and not single_file_test:
380 walk_testfiles("regression-test-files/cash/iPoker/", compare, importer, iPokerErrors, "iPoker")
381 elif sites['iPoker'] == True and single_file_test:
382 walk_testfiles(options.filename, compare, importer, iPokerErrors, "iPoker")
383 if sites['Winamax'] == True and not single_file_test:
384 walk_testfiles("regression-test-files/cash/Winamax/", compare, importer, WinamaxErrors, "Winamax")
385 walk_testfiles("regression-test-files/tour/Winamax/", compare, importer, WinamaxErrors, "Winamax")
386 elif sites['Winamax'] == True and single_file_test:
387 walk_testfiles(options.filename, compare, importer, WinamaxErrors, "Winamax")
388 if sites['Win2day'] == True and not single_file_test:
389 walk_testfiles("regression-test-files/cash/Win2day/", compare, importer, Win2dayErrors, "Win2day")
390 elif sites['Win2day'] == True and single_file_test:
391 walk_testfiles(options.filename, compare, importer, Win2dayErrors, "Win2day")
393 totalerrors = 0
395 for i, site in enumerate(ErrorsList):
396 totalerrors += ErrorsList[i].errorcount
398 for i, site in enumerate(ErrorsList):
399 ErrorsList[i].print_histogram()
401 # Merge the dicts of stats from the various error objects
402 statdict = {}
403 for i, site in enumerate(ErrorsList):
404 tmp = ErrorsList[i].statcount
405 for stat in tmp:
406 if stat in statdict:
407 statdict[stat] += tmp[stat]
408 else:
409 statdict[stat] = tmp[stat]
411 print "\n"
412 print "---------------------"
413 print "Errors by stat:"
414 print "---------------------"
415 #for stat in statdict:
416 # print "(%3d) : %s" %(statdict[stat], stat)
418 sortedstats = sorted([(value,key) for (key,value) in statdict.items()])
419 for num, stat in sortedstats:
420 print "(%3d) : %s" %(num, stat)
422 print "---------------------"
423 print "Total Errors: %d" % totalerrors
424 print "---------------------"
426 if __name__ == '__main__':
427 sys.exit(main())