From cf6e818ae5ae784ee778cdc11b9c204337f70da1 Mon Sep 17 00:00:00 2001 From: Carl Gherardi Date: Mon, 14 Dec 2009 16:45:08 +0800 Subject: [PATCH 01/36] [NEWIMPORT] Enable NEWIMPORT by defaul --- pyfpdb/Configuration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 996ef60c..bf8689a6 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -125,7 +125,7 @@ DATABASE_TYPES = ( DATABASE_TYPE_MYSQL, ) -NEWIMPORT = False +NEWIMPORT = True ######################################################################## def string_to_bool(string, default=True): From f03a9c287fba9398aba1eff20a17e5b398656d99 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 17 Dec 2009 15:53:12 +0800 Subject: [PATCH 02/36] Add some code to kinda detect hand cancellation hhc.readHandInfo(self) hhc.readPlayerStacks(self) hhc.compilePlayerRegexs(self) hhc.markStreets(self) Is the order, the first correctly failing regex is markStreets --- pyfpdb/Hand.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 6901340e..32140256 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -54,6 +54,7 @@ class Hand(object): self.starttime = 0 self.handText = handText self.handid = 0 + self.cancelled = False self.dbid_hands = 0 self.dbid_pids = None self.dbid_gt = 0 @@ -263,6 +264,8 @@ If a player has None chips he won't be added.""" log.debug("markStreets:\n"+ str(self.streets)) else: log.error("markstreets didn't match") + log.error(" - Assuming hand cancelled") + self.cancelled = True def checkPlayerExists(self,player): if player not in [p[1] for p in self.players]: @@ -613,6 +616,8 @@ class HoldemOmahaHand(Hand): hhc.readPlayerStacks(self) hhc.compilePlayerRegexs(self) hhc.markStreets(self) + if self.cancelled: + return hhc.readBlinds(self) hhc.readAntes(self) hhc.readButton(self) From 26fc0b592837765c515277fc1f0b373b9934667b Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 17 Dec 2009 18:42:50 +0800 Subject: [PATCH 03/36] Add ability to import Stars archive files. PokerStars support can provide a HH archive. The format is similar but not the same as a a standard hh format as it contains an additional line "Hand #X" between each hand. Patch adds an option -s to GuiBulkImport, which when specified will strip these lines out and continue parsing. --- pyfpdb/GuiBulkImport.py | 4 ++++ pyfpdb/Hand.py | 1 + pyfpdb/HandHistoryConverter.py | 8 +++++++- pyfpdb/fpdb_import.py | 19 +++++++++++++------ 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/pyfpdb/GuiBulkImport.py b/pyfpdb/GuiBulkImport.py index 7db420c7..16131ab2 100755 --- a/pyfpdb/GuiBulkImport.py +++ b/pyfpdb/GuiBulkImport.py @@ -326,6 +326,8 @@ def main(argv=None): help="How often to print a one-line status report (0 (default) means never)") parser.add_option("-u", "--usage", action="store_true", dest="usage", default=False, help="Print some useful one liners") + parser.add_option("-s", "--starsarchive", action="store_true", dest="starsArchive", default=False, + help="Do the required conversion for Stars Archive format (ie. as provided by support") (options, argv) = parser.parse_args(args = argv) if options.usage == True: @@ -369,6 +371,8 @@ def main(argv=None): importer.setThreads(-1) importer.addBulkImportImportFileOrDir(os.path.expanduser(options.filename), site=options.filtername) importer.setCallHud(False) + if options.starsArchive: + importer.setStarsArchive(True) (stored, dups, partial, errs, ttime) = importer.runImport() importer.clearFileList() print 'GuiBulkImport done: Stored: %d \tDuplicates: %d \tPartial: %d \tErrors: %d in %s seconds - %.0f/sec'\ diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 32140256..3467216a 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -266,6 +266,7 @@ If a player has None chips he won't be added.""" log.error("markstreets didn't match") log.error(" - Assuming hand cancelled") self.cancelled = True + raise FpdbParseError def checkPlayerExists(self,player): if player not in [p[1] for p in self.players]: diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 27bb9b1a..a18797df 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -57,7 +57,7 @@ class HandHistoryConverter(): codepage = "cp1252" - def __init__(self, in_path = '-', out_path = '-', follow=False, index=0, autostart=True): + def __init__(self, in_path = '-', out_path = '-', follow=False, index=0, autostart=True, starsArchive=False): """\ in_path (default '-' = sys.stdin) out_path (default '-' = sys.stdout) @@ -66,6 +66,7 @@ follow : whether to tail -f the input""" log.info("HandHistory init - %s subclass, in_path '%s'; out_path '%s'" % (self.sitename, in_path, out_path) ) self.index = 0 + self.starsArchive = starsArchive self.in_path = in_path self.out_path = out_path @@ -254,6 +255,11 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py. self.readFile() self.obs = self.obs.strip() self.obs = self.obs.replace('\r\n', '\n') + if self.starsArchive == True: + log.debug("Converting starsArchive format to readable") + m = re.compile('^Hand #\d+', re.MULTILINE) + self.obs = m.sub('', self.obs) + if self.obs is None or self.obs == "": log.info("Read no hands.") return [] diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 7b3dd4f1..8921d9d8 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -91,6 +91,7 @@ class Importer: self.settings.setdefault("writeQMaxWait", 10) # not used self.settings.setdefault("dropIndexes", "don't drop") self.settings.setdefault("dropHudCache", "don't drop") + self.settings.setdefault("starsArchive", False) self.writeq = None self.database = Database.Database(self.config, sql = self.sql) @@ -134,6 +135,9 @@ class Importer: def setDropHudCache(self, value): self.settings['dropHudCache'] = value + def setStarsArchive(self, value): + self.settings['starsArchive'] = value + # def setWatchTime(self): # self.updated = time() @@ -425,7 +429,7 @@ class Importer: mod = __import__(filter) obj = getattr(mod, filter_name, None) if callable(obj): - hhc = obj(in_path = file, out_path = out_path, index = 0) # Index into file 0 until changeover + hhc = obj(in_path = file, out_path = out_path, index = 0, starsArchive = self.settings['starsArchive']) # Index into file 0 until changeover if hhc.getStatus() and self.NEWIMPORT == False: (stored, duplicates, partial, errors, ttime) = self.import_fpdb_file(db, out_path, site, q) elif hhc.getStatus() and self.NEWIMPORT == True: @@ -435,11 +439,14 @@ class Importer: to_hud = [] for hand in handlist: - #try, except duplicates here? - hand.prepInsert(self.database) - hand.insert(self.database) - if self.callHud and hand.dbid_hands != 0: - to_hud.append(hand.dbid_hands) + if hand is not None: + #try, except duplicates here? + hand.prepInsert(self.database) + hand.insert(self.database) + if self.callHud and hand.dbid_hands != 0: + to_hud.append(hand.dbid_hands) + else: + log.error("Hand processed but empty") self.database.commit() #pipe the Hands.id out to the HUD From 1093b1e43c3a12af748e0768cd71513e70d6d060 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 18 Dec 2009 10:27:09 +0800 Subject: [PATCH 04/36] Remove dead code --- pyfpdb/fpdb_import.py | 160 +----------------------------------------- 1 file changed, 1 insertion(+), 159 deletions(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 8921d9d8..21aa5d5c 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -430,9 +430,7 @@ class Importer: obj = getattr(mod, filter_name, None) if callable(obj): hhc = obj(in_path = file, out_path = out_path, index = 0, starsArchive = self.settings['starsArchive']) # Index into file 0 until changeover - if hhc.getStatus() and self.NEWIMPORT == False: - (stored, duplicates, partial, errors, ttime) = self.import_fpdb_file(db, out_path, site, q) - elif hhc.getStatus() and self.NEWIMPORT == True: + if hhc.getStatus() and self.NEWIMPORT == True: #This code doesn't do anything yet handlist = hhc.getProcessedHands() self.pos_in_file[file] = hhc.getLastCharacterRead() @@ -468,162 +466,6 @@ class Importer: return (stored, duplicates, partial, errors, ttime) - def import_fpdb_file(self, db, file, site, q): - starttime = time() - last_read_hand = 0 - loc = 0 - (stored, duplicates, partial, errors, ttime) = (0, 0, 0, 0, 0) - # print "file =", file - if file == "stdin": - inputFile = sys.stdin - else: - if os.path.exists(file): - inputFile = open(file, "rU") - else: - self.removeFromFileList[file] = True - return (0, 0, 0, 1, 0) - try: - loc = self.pos_in_file[file] - #size = os.path.getsize(file) - #print "loc =", loc, 'size =', size - except KeyError: - pass - # Read input file into class and close file - inputFile.seek(loc) - #tmplines = inputFile.readlines() - #if tmplines == None or tmplines == []: - # print "tmplines = ", tmplines - #else: - # print "tmplines[0] =", tmplines[0] - self.lines = fpdb_simple.removeTrailingEOL(inputFile.readlines()) - self.pos_in_file[file] = inputFile.tell() - inputFile.close() - - x = clock() - (stored, duplicates, partial, errors, ttime, handsId) = self.import_fpdb_lines(db, self.lines, starttime, file, site, q) - - db.commit() - y = clock() - ttime = y - x - #ttime = time() - starttime - if q is None: - log.info("Total stored: %(stored)d\tduplicates:%(duplicates)d\terrors:%(errors)d\ttime:%(ttime)s" % locals()) - - if not stored: - if duplicates: - for line_no in xrange(len(self.lines)): - if self.lines[line_no].find("Game #") != -1: - final_game_line = self.lines[line_no] - handsId=fpdb_simple.parseSiteHandNo(final_game_line) - else: - print "failed to read a single hand from file:", inputFile - handsId = 0 - #todo: this will cause return of an unstored hand number if the last hand was error - self.handsId = handsId - - return (stored, duplicates, partial, errors, ttime) - # end def import_fpdb_file - - - def import_fpdb_lines(self, db, lines, starttime, file, site, q = None): - """Import an fpdb hand history held in the list lines, could be one hand or many""" - - #db.lock_for_insert() # should be ok when using one thread, but doesn't help?? - while gtk.events_pending(): - gtk.main_iteration(False) - - try: # sometimes we seem to be getting an empty self.lines, in which case, we just want to return. - firstline = lines[0] - except: - # just skip the debug message and return silently: - #print "DEBUG: import_fpdb_file: failed on lines[0]: '%s' '%s' '%s' '%s' " %( file, site, lines, loc) - return (0,0,0,1,0,0) - - if "Tournament Summary" in firstline: - print "TODO: implement importing tournament summaries" - #self.faobs = readfile(inputFile) - #self.parseTourneyHistory() - return (0,0,0,1,0,0) - - category = fpdb_simple.recogniseCategory(firstline) - - startpos = 0 - stored = 0 #counter - duplicates = 0 #counter - partial = 0 #counter - errors = 0 #counter - ttime = 0 - handsId = 0 - - for i in xrange(len(lines)): - if len(lines[i]) < 2: #Wierd way to detect for '\r\n' or '\n' - endpos = i - hand = lines[startpos:endpos] - - if len(hand[0]) < 2: - hand=hand[1:] - - if len(hand) < 3: - pass - #TODO: This is ugly - we didn't actually find the start of the - # hand with the outer loop so we test again... - else: - isTourney = fpdb_simple.isTourney(hand[0]) - if not isTourney: - hand = fpdb_simple.filterAnteBlindFold(hand) - self.hand = hand - - try: - handsId = fpdb_parse_logic.mainParser( self.settings, self.siteIds[site] - , category, hand, self.config - , db, q ) - db.commit() - - stored += 1 - if self.callHud: - #print "call to HUD here. handsId:",handsId - #pipe the Hands.id out to the HUD - # print "fpdb_import: sending hand to hud", handsId, "pipe =", self.caller.pipe_to_hud - try: - self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep) - except IOError: # hud closed - self.callHud = False - pass # continue import without hud - except Exceptions.DuplicateError: - duplicates += 1 - db.rollback() - except (ValueError), fe: - errors += 1 - self.printEmailErrorMessage(errors, file, hand) - - if (self.settings['failOnError']): - db.commit() #dont remove this, in case hand processing was cancelled. - raise - else: - db.rollback() - except (fpdb_simple.FpdbError), fe: - errors += 1 - self.printEmailErrorMessage(errors, file, hand) - db.rollback() - - if self.settings['failOnError']: - db.commit() #dont remove this, in case hand processing was cancelled. - raise - - if self.settings['minPrint']: - if not ((stored+duplicates+errors) % self.settings['minPrint']): - print "stored:", stored, " duplicates:", duplicates, "errors:", errors - - if self.settings['handCount']: - if ((stored+duplicates+errors) >= self.settings['handCount']): - if not self.settings['quiet']: - print "quitting due to reaching the amount of hands to be imported" - print "Total stored:", stored, "duplicates:", duplicates, "errors:", errors, " time:", (time() - starttime) - sys.exit(0) - startpos = endpos - return (stored, duplicates, partial, errors, ttime, handsId) - # end def import_fpdb_lines - def printEmailErrorMessage(self, errors, filename, line): traceback.print_exc(file=sys.stderr) print "Error No.",errors,", please send the hand causing this to steffen@sycamoretest.info so I can fix it." From 975eb360ef96d3f669269117c9fe78f151662379 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 18 Dec 2009 10:27:43 +0800 Subject: [PATCH 05/36] [NEWIMPORT] Add stubbed variable to insert --- pyfpdb/Database.py | 3 ++- pyfpdb/SQL.py | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 9d1f3f85..72b41336 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1651,7 +1651,8 @@ class Database: pdata[p]['street2CheckCallRaiseDone'], pdata[p]['street3CheckCallRaiseChance'], pdata[p]['street3CheckCallRaiseDone'], - pdata[p]['street4CheckCallRaiseChance'] + pdata[p]['street4CheckCallRaiseChance'], + pdata[p]['street4CheckCallRaiseDone'] ) ) q = self.sql.query['store_hands_players'] diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index c0319dfe..56c1f388 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -3404,10 +3404,11 @@ class Sql: street2CheckCallRaiseDone, street3CheckCallRaiseChance, street3CheckCallRaiseDone, - street4CheckCallRaiseChance + street4CheckCallRaiseChance, + street4CheckCallRaiseDone ) VALUES ( - %s, %s, %s, %s, + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, From 2b7d34c4842e40b9d8fdb950eefd23c99068e95d Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 18 Dec 2009 13:32:09 +0800 Subject: [PATCH 06/36] [NEWIMPORT] Fix syntax to be 2.5 compatible. Python 2.6 enumerate() function contains a useful 'start' paramater, apparently this did not exist in 2.5. Patch frim Mika Bostrom --- pyfpdb/DerivedStats.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 1a34db1e..5943a10f 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -168,8 +168,10 @@ class DerivedStats(): for player in hand.players: hcs = hand.join_holecards(player[1], asList=True) hcs = hcs + [u'0x', u'0x', u'0x', u'0x', u'0x'] - for i, card in enumerate(hcs[:7], 1): - self.handsplayers[player[1]]['card%s' % i] = Card.encodeCard(card) + #for i, card in enumerate(hcs[:7], 1): #Python 2.6 syntax + # self.handsplayers[player[1]]['card%s' % i] = Card.encodeCard(card) + for i, card in enumerate(hcs[:7]): + self.handsplayers[player[1]]['card%s' % (i+1)] = Card.encodeCard(card) # position, @@ -266,13 +268,17 @@ class DerivedStats(): # Then no bets before the player with initiatives first action on current street # ie. if player on street-1 had initiative # and no donkbets occurred - for i, street in enumerate(hand.actionStreets[2:], start=1): - name = self.lastBetOrRaiser(hand.actionStreets[i]) + + # XXX: enumerate(list, start=x) is python 2.6 syntax; 'start' + # came there + #for i, street in enumerate(hand.actionStreets[2:], start=1): + for i, street in enumerate(hand.actionStreets[2:]: + name = self.lastBetOrRaiser(hand.actionStreets[i+1]) if name: - chance = self.noBetsBefore(hand.actionStreets[i+1], name) - self.handsplayers[name]['street%dCBChance' %i] = True + chance = self.noBetsBefore(hand.actionStreets[i+2], name) + self.handsplayers[name]['street%dCBChance' % (i+1)] = True if chance == True: - self.handsplayers[name]['street%dCBDone' %i] = self.betStreet(hand.actionStreets[i+1], name) + self.handsplayers[name]['street%dCBDone' % (i+1)] = self.betStreet(hand.actionStreets[i+2], name) def seen(self, hand, i): pas = set() From 02453ce3c09096b50405265b433e29702b0859ec Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 22 Dec 2009 13:47:33 +0800 Subject: [PATCH 07/36] Move locale variable to Configuration --- pyfpdb/fpdb_import.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 21aa5d5c..577562b8 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -409,7 +409,7 @@ class Importer: conv = None (stored, duplicates, partial, errors, ttime) = (0, 0, 0, 0, 0) - file = file.decode(fpdb_simple.LOCALE_ENCODING) + file = file.decode(Configuration.LOCALE_ENCODING) # Load filter, process file, pass returned filename to import_fpdb_file if self.settings['threads'] > 0 and self.writeq is not None: From 262eb5200d85cdc13691a09dab0885a8df11922d Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 22 Dec 2009 13:49:22 +0800 Subject: [PATCH 08/36] Add LOCALE static to Configuration --- pyfpdb/Configuration.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index bf8689a6..174d0673 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -31,6 +31,7 @@ import inspect import string import traceback import shutil +import locale import xml.dom.minidom from xml.dom.minidom import Node @@ -126,6 +127,7 @@ DATABASE_TYPES = ( ) NEWIMPORT = True +LOCALE_ENCODING = locale.getdefaultlocale()[1] ######################################################################## def string_to_bool(string, default=True): From 1b82f20411f02dfcaf3cc57aceebca514ecb5c45 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 22 Dec 2009 14:44:35 +0800 Subject: [PATCH 09/36] [NEWIMPORT] Remove legacy code. --- pyfpdb/CliFpdb.py | 66 -- pyfpdb/Database.py | 350 -------- pyfpdb/GuiBulkImport.py | 1 - pyfpdb/GuiTableViewer.py | 1 - pyfpdb/fpdb_db.py | 1 - pyfpdb/fpdb_import.py | 2 - pyfpdb/fpdb_parse_logic.py | 235 ----- pyfpdb/fpdb_simple.py | 1728 ------------------------------------ 8 files changed, 2384 deletions(-) delete mode 100755 pyfpdb/CliFpdb.py delete mode 100644 pyfpdb/fpdb_parse_logic.py delete mode 100644 pyfpdb/fpdb_simple.py diff --git a/pyfpdb/CliFpdb.py b/pyfpdb/CliFpdb.py deleted file mode 100755 index abdddb45..00000000 --- a/pyfpdb/CliFpdb.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/python - -#Copyright 2008 Steffen Jobbagy-Felso -#This program is free software: you can redistribute it and/or modify -#it under the terms of the GNU Affero General Public License as published by -#the Free Software Foundation, version 3 of the License. -# -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU Affero General Public License -#along with this program. If not, see . -#In the "official" distribution you can find the license in -#agpl-3.0.txt in the docs folder of the package. - -import os -import sys -import fpdb_simple -from optparse import OptionParser - -try: - import MySQLdb -except: - diaSQLLibMissing = gtk.Dialog(title="Fatal Error - SQL interface library missing", parent=None, flags=0, buttons=(gtk.STOCK_QUIT,gtk.RESPONSE_OK)) - - print "Please note that the CLI importer only works with MySQL, if you use PostgreSQL this error is expected." - -import fpdb_import -import fpdb_db - -if __name__ == "__main__": - #process CLI parameters - parser = OptionParser() - parser.add_option("-c", "--handCount", default="0", type="int", - help="Number of hands to import (default 0 means unlimited)") - parser.add_option("-d", "--database", default="fpdb", help="The MySQL database to use (default fpdb)") - parser.add_option("-e", "--errorFile", default="failed.txt", - help="File to store failed hands into. (default: failed.txt) Not implemented.") - parser.add_option("-f", "--inputFile", "--file", "--inputfile", default="stdin", - help="The file you want to import (remember to use quotes if necessary)") - parser.add_option("-m", "--minPrint", "--status", default="50", type="int", - help="How often to print a one-line status report (0 means never, default is 50)") - parser.add_option("-p", "--password", help="The password for the MySQL user") - parser.add_option("-q", "--quiet", action="store_true", - help="If this is passed it doesn't print a total at the end nor the opening line. Note that this purposely does NOT change --minPrint") - parser.add_option("-s", "--server", default="localhost", - help="Hostname/IP of the MySQL server (default localhost)") - parser.add_option("-u", "--user", default="fpdb", help="The MySQL username (default fpdb)") - parser.add_option("-x", "--failOnError", action="store_true", - help="If this option is passed it quits when it encounters any error") - - (options, argv) = parser.parse_args() - - settings={'callFpdbHud':False, 'db-backend':2} - settings['db-host']=options.server - settings['db-user']=options.user - settings['db-password']=options.password - settings['db-databaseName']=options.database - settings['handCount']=options.handCount - settings['failOnError']=options.failOnError - - importer = fpdb_import.Importer(options, settings) - importer.addImportFile(options.inputFile) - importer.runImport() diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 72b41336..412036ab 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -43,7 +43,6 @@ import Queue # FreePokerTools modules import fpdb_db -import fpdb_simple import Configuration import SQL import Card @@ -724,120 +723,6 @@ class Database: return ret - #stores a stud/razz hand into the database - def ring_stud(self, config, settings, base, category, site_hand_no, gametype_id, hand_start_time - ,names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes - ,action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName - ,seatNos): - - fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) - - hands_id = self.storeHands(self.backend, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats, hudImportData - ,(None, None, None, None, None), (None, None, None, None, None)) - - #print "before calling store_hands_players_stud, antes:", antes - hands_players_ids = self.store_hands_players_stud(self.backend, hands_id, player_ids - ,start_cashes, antes, card_values - ,card_suits, winnings, rakes, seatNos) - - if 'dropHudCache' not in settings or settings['dropHudCache'] != 'drop': - self.storeHudCache(self.backend, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - - return hands_id - #end def ring_stud - - def ring_holdem_omaha(self, config, settings, base, category, site_hand_no, gametype_id - ,hand_start_time, names, player_ids, start_cashes, positions, card_values - ,card_suits, board_values, board_suits, winnings, rakes, action_types, allIns - ,action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): - """stores a holdem/omaha hand into the database""" - - t0 = time() - #print "in ring_holdem_omaha" - fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) - t1 = time() - fpdb_simple.fill_board_cards(board_values, board_suits) - t2 = time() - - hands_id = self.storeHands(self.backend, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats - ,hudImportData, board_values, board_suits) - #TEMPORARY CALL! - Just until all functions are migrated - t3 = time() - hands_players_ids = self.store_hands_players_holdem_omaha( - self.backend, category, hands_id, player_ids, start_cashes - , positions, card_values, card_suits, winnings, rakes, seatNos, hudImportData) - t4 = time() - if 'dropHudCache' not in settings or settings['dropHudCache'] != 'drop': - self.storeHudCache(self.backend, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - t5 = time() - #print "fills=(%4.3f) saves=(%4.3f,%4.3f,%4.3f)" % (t2-t0, t3-t2, t4-t3, t5-t4) - return hands_id - #end def ring_holdem_omaha - - def tourney_holdem_omaha(self, config, settings, base, category, siteTourneyNo, buyin, fee, knockout - ,entries, prizepool, tourney_start, payin_amounts, ranks, tourneyTypeId - ,siteId #end of tourney specific params - ,site_hand_no, gametype_id, hand_start_time, names, player_ids - ,start_cashes, positions, card_values, card_suits, board_values - ,board_suits, winnings, rakes, action_types, allIns, action_amounts - ,actionNos, hudImportData, maxSeats, tableName, seatNos): - """stores a tourney holdem/omaha hand into the database""" - - fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) - fpdb_simple.fill_board_cards(board_values, board_suits) - - tourney_id = self.store_tourneys(tourneyTypeId, siteTourneyNo, entries, prizepool, tourney_start) - tourneys_players_ids = self.store_tourneys_players(tourney_id, player_ids, payin_amounts, ranks, winnings) - - hands_id = self.storeHands(self.backend, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats - ,hudImportData, board_values, board_suits) - - hands_players_ids = self.store_hands_players_holdem_omaha_tourney( - self.backend, category, hands_id, player_ids, start_cashes, positions - , card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids - , hudImportData, tourneyTypeId) - - #print "tourney holdem, backend=%d" % backend - if 'dropHudCache' not in settings or settings['dropHudCache'] != 'drop': - self.storeHudCache(self.backend, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - - return hands_id - #end def tourney_holdem_omaha - - def tourney_stud(self, config, settings, base, category, siteTourneyNo, buyin, fee, knockout, entries - ,prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteId - ,siteHandNo, gametypeId, handStartTime, names, playerIds, startCashes, antes - ,cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts - ,actionNos, hudImportData, maxSeats, tableName, seatNos): - #stores a tourney stud/razz hand into the database - - fpdb_simple.fillCardArrays(len(names), base, category, cardValues, cardSuits) - - tourney_id = self.store_tourneys(tourneyTypeId, siteTourneyNo, entries, prizepool, tourneyStartTime) - - tourneys_players_ids = self.store_tourneys_players(tourney_id, playerIds, payin_amounts, ranks, winnings) - - hands_id = self.storeHands( self.backend, siteHandNo, gametypeId - , handStartTime, names, tableName, maxSeats - , hudImportData, (None, None, None, None, None), (None, None, None, None, None) ) - # changed board_values and board_suits to arrays of None, just like the - # cash game version of this function does - i don't believe this to be - # the correct thing to do (tell me if i'm wrong) but it should keep the - # importer from crashing - - hands_players_ids = self.store_hands_players_stud_tourney(self.backend, hands_id - , playerIds, startCashes, antes, cardValues, cardSuits - , winnings, rakes, seatNos, tourneys_players_ids, tourneyTypeId) - - if 'dropHudCache' not in settings or settings['dropHudCache'] != 'drop': - self.storeHudCache(self.backend, base, category, gametypeId, handStartTime, playerIds, hudImportData) - - return hands_id - #end def tourney_stud - def prepareBulkImport(self): """Drop some indexes/foreign keys to prepare for bulk import. Currently keeping the standalone indexes as needed to import quickly""" @@ -1465,64 +1350,6 @@ class Database: print "Error during fdb.lock_for_insert:", str(sys.exc_value) #end def lock_for_insert - def store_the_hand(self, h): - """Take a HandToWrite object and store it in the db""" - - # Following code writes hands to database and commits (or rolls back if there is an error) - try: - result = None - if h.isTourney: - ranks = map(lambda x: 0, h.names) # create an array of 0's equal to the length of names - payin_amounts = fpdb_simple.calcPayin(len(h.names), h.buyin, h.fee) - - if h.base == "hold": - result = self.tourney_holdem_omaha( - h.config, h.settings, h.base, h.category, h.siteTourneyNo, h.buyin - , h.fee, h.knockout, h.entries, h.prizepool, h.tourneyStartTime - , payin_amounts, ranks, h.tourneyTypeId, h.siteID, h.siteHandNo - , h.gametypeID, h.handStartTime, h.names, h.playerIDs, h.startCashes - , h.positions, h.cardValues, h.cardSuits, h.boardValues, h.boardSuits - , h.winnings, h.rakes, h.actionTypes, h.allIns, h.actionAmounts - , h.actionNos, h.hudImportData, h.maxSeats, h.tableName, h.seatNos) - elif h.base == "stud": - result = self.tourney_stud( - h.config, h.settings, h.base, h.category, h.siteTourneyNo - , h.buyin, h.fee, h.knockout, h.entries, h.prizepool, h.tourneyStartTime - , payin_amounts, ranks, h.tourneyTypeId, h.siteID, h.siteHandNo - , h.gametypeID, h.handStartTime, h.names, h.playerIDs, h.startCashes - , h.antes, h.cardValues, h.cardSuits, h.winnings, h.rakes, h.actionTypes - , h.allIns, h.actionAmounts, h.actionNos, h.hudImportData, h.maxSeats - , h.tableName, h.seatNos) - else: - raise FpdbError("unrecognised category") - else: - if h.base == "hold": - result = self.ring_holdem_omaha( - h.config, h.settings, h.base, h.category, h.siteHandNo - , h.gametypeID, h.handStartTime, h.names, h.playerIDs - , h.startCashes, h.positions, h.cardValues, h.cardSuits - , h.boardValues, h.boardSuits, h.winnings, h.rakes - , h.actionTypes, h.allIns, h.actionAmounts, h.actionNos - , h.hudImportData, h.maxSeats, h.tableName, h.seatNos) - elif h.base == "stud": - result = self.ring_stud( - h.config, h.settings, h.base, h.category, h.siteHandNo, h.gametypeID - , h.handStartTime, h.names, h.playerIDs, h.startCashes, h.antes - , h.cardValues, h.cardSuits, h.winnings, h.rakes, h.actionTypes, h.allIns - , h.actionAmounts, h.actionNos, h.hudImportData, h.maxSeats, h.tableName - , h.seatNos) - else: - raise FpdbError("unrecognised category") - except: - print "Error storing hand: " + str(sys.exc_value) - self.rollback() - # re-raise the exception so that the calling routine can decide what to do: - # (e.g. a write thread might try again) - raise - - return result - #end def store_the_hand - ########################### # NEWIMPORT CODE ########################### @@ -2583,183 +2410,6 @@ class Database: #end def tRecogniseTourneyType - def tRecognizeTourney(self, tourney, dbTourneyTypeId): - logging.debug("Database.tRecognizeTourney") - tourneyID = 1 - # Check if tourney exists in db (based on tourney.siteId and tourney.tourNo) - # If so retrieve all data to check for consistency - cursor = self.get_cursor() - cursor.execute (self.sql.query['getTourney'].replace('%s', self.sql.query['placeholder']), - (tourney.tourNo, tourney.siteId) - ) - result=cursor.fetchone() - - expectedValuesDecimal = { 2 : "entries", 3 : "prizepool", 6 : "buyInChips", 9 : "rebuyChips", - 10 : "addOnChips", 11 : "rebuyAmount", 12 : "addOnAmount", 13 : "totalRebuys", - 14 : "totalAddOns", 15 : "koBounty" } - expectedValues = { 7 : "tourneyName", 16 : "tourneyComment" } - - tourneyDataMatch = True - tCommentTs = None - starttime = None - endtime = None - - try: - len(result) - tourneyID = result[0] - logging.debug("Tourney found in db with TourneyID = %d" % tourneyID) - if result[1] <> dbTourneyTypeId: - tourneyDataMatch = False - logging.debug("Tourney has wrong type ID (expected : %s - found : %s)" % (dbTourneyTypeId, result[1])) - if (tourney.starttime is None and result[4] is not None) or ( tourney.starttime is not None and fpdb_simple.parseHandStartTime("- %s" % tourney.starttime) <> result[4]) : - tourneyDataMatch = False - logging.debug("Tourney data mismatch : wrong starttime : Tourney=%s / db=%s" % (tourney.starttime, result[4])) - if (tourney.endtime is None and result[5] is not None) or ( tourney.endtime is not None and fpdb_simple.parseHandStartTime("- %s" % tourney.endtime) <> result[5]) : - tourneyDataMatch = False - logging.debug("Tourney data mismatch : wrong endtime : Tourney=%s / db=%s" % (tourney.endtime, result[5])) - - for ev in expectedValues : - if ( getattr( tourney, expectedValues.get(ev) ) <> result[ev] ): - logging.debug("Tourney data mismatch : wrong %s : Tourney=%s / db=%s" % (expectedValues.get(ev), getattr( tourney, expectedValues.get(ev)), result[ev]) ) - tourneyDataMatch = False - #break - for evD in expectedValuesDecimal : - if ( Decimal(getattr( tourney, expectedValuesDecimal.get(evD)) ) <> result[evD] ): - logging.debug("Tourney data mismatch : wrong %s : Tourney=%s / db=%s" % (expectedValuesDecimal.get(evD), getattr( tourney, expectedValuesDecimal.get(evD)), result[evD]) ) - tourneyDataMatch = False - #break - - # TO DO : Deal with matrix summary mutliple parsings - - except: - # Tourney not found : create - logging.debug("Tourney is not found : create") - if tourney.tourneyComment is not None : - tCommentTs = datetime.today() - if tourney.starttime is not None : - starttime = fpdb_simple.parseHandStartTime("- %s" % tourney.starttime) - if tourney.endtime is not None : - endtime = fpdb_simple.parseHandStartTime("- %s" % tourney.endtime) - # TODO : deal with matrix Id processed - cursor.execute (self.sql.query['insertTourney'].replace('%s', self.sql.query['placeholder']), - (dbTourneyTypeId, tourney.tourNo, tourney.entries, tourney.prizepool, starttime, - endtime, tourney.buyInChips, tourney.tourneyName, 0, tourney.rebuyChips, tourney.addOnChips, - tourney.rebuyAmount, tourney.addOnAmount, tourney.totalRebuys, tourney.totalAddOns, tourney.koBounty, - tourney.tourneyComment, tCommentTs) - ) - tourneyID = self.get_last_insert_id(cursor) - - - # Deal with inconsistent tourney in db - if tourneyDataMatch == False : - # Update Tourney - if result[16] <> tourney.tourneyComment : - tCommentTs = datetime.today() - if tourney.starttime is not None : - starttime = fpdb_simple.parseHandStartTime("- %s" % tourney.starttime) - if tourney.endtime is not None : - endtime = fpdb_simple.parseHandStartTime("- %s" % tourney.endtime) - - cursor.execute (self.sql.query['updateTourney'].replace('%s', self.sql.query['placeholder']), - (dbTourneyTypeId, tourney.entries, tourney.prizepool, starttime, - endtime, tourney.buyInChips, tourney.tourneyName, 0, tourney.rebuyChips, tourney.addOnChips, - tourney.rebuyAmount, tourney.addOnAmount, tourney.totalRebuys, tourney.totalAddOns, tourney.koBounty, - tourney.tourneyComment, tCommentTs, tourneyID) - ) - - return tourneyID - #end def tRecognizeTourney - - def tStoreTourneyPlayers(self, tourney, dbTourneyId): - logging.debug("Database.tStoreTourneyPlayers") - # First, get playerids for the players and specifically the one for hero : - playersIds = self.recognisePlayerIDs(tourney.players, tourney.siteId) - # hero may be None for matrix tourneys summaries -# hero = [ tourney.hero ] -# heroId = self.recognisePlayerIDs(hero , tourney.siteId) -# logging.debug("hero Id = %s - playersId = %s" % (heroId , playersIds)) - - tourneyPlayersIds=[] - try: - cursor = self.get_cursor() - - for i in xrange(len(playersIds)): - cursor.execute(self.sql.query['getTourneysPlayers'].replace('%s', self.sql.query['placeholder']) - ,(dbTourneyId, playersIds[i])) - result=cursor.fetchone() - #print "tried SELECTing tourneys_players.id:",tmp - - try: - len(result) - # checking data - logging.debug("TourneysPlayers found : checking data") - expectedValuesDecimal = { 1 : "payinAmounts", 2 : "finishPositions", 3 : "winnings", 4 : "countRebuys", - 5 : "countAddOns", 6 : "countKO" } - - tourneyPlayersIds.append(result[0]); - - tourneysPlayersDataMatch = True - for evD in expectedValuesDecimal : - if ( Decimal(getattr( tourney, expectedValuesDecimal.get(evD))[tourney.players[i]] ) <> result[evD] ): - logging.debug("TourneysPlayers data mismatch for TourneysPlayer id=%d, name=%s : wrong %s : Tourney=%s / db=%s" % (result[0], tourney.players[i], expectedValuesDecimal.get(evD), getattr( tourney, expectedValuesDecimal.get(evD))[tourney.players[i]], result[evD]) ) - tourneysPlayersDataMatch = False - #break - - if tourneysPlayersDataMatch == False: - logging.debug("TourneysPlayers data update needed") - cursor.execute (self.sql.query['updateTourneysPlayers'].replace('%s', self.sql.query['placeholder']), - (tourney.payinAmounts[tourney.players[i]], tourney.finishPositions[tourney.players[i]], - tourney.winnings[tourney.players[i]] , tourney.countRebuys[tourney.players[i]], - tourney.countAddOns[tourney.players[i]] , tourney.countKO[tourney.players[i]], - result[7], result[8], result[0]) - ) - - except TypeError: - logging.debug("TourneysPlayers not found : need insert") - cursor.execute (self.sql.query['insertTourneysPlayers'].replace('%s', self.sql.query['placeholder']), - (dbTourneyId, playersIds[i], - tourney.payinAmounts[tourney.players[i]], tourney.finishPositions[tourney.players[i]], - tourney.winnings[tourney.players[i]] , tourney.countRebuys[tourney.players[i]], - tourney.countAddOns[tourney.players[i]] , tourney.countKO[tourney.players[i]], - None, None) - ) - tourneyPlayersIds.append(self.get_last_insert_id(cursor)) - - except: - raise fpdb_simple.FpdbError( "tStoreTourneyPlayers error: " + str(sys.exc_value) ) - - return tourneyPlayersIds - #end def tStoreTourneyPlayers - - def tUpdateTourneysHandsPlayers(self, tourney, dbTourneysPlayersIds, dbTourneyTypeId): - logging.debug("Database.tCheckTourneysHandsPlayers") - try: - # Massive update seems to take quite some time ... -# query = self.sql.query['updateHandsPlayersForTTypeId2'] % (dbTourneyTypeId, self.sql.query['handsPlayersTTypeId_joiner'].join([self.sql.query['placeholder'] for id in dbTourneysPlayersIds]) ) -# cursor = self.get_cursor() -# cursor.execute (query, dbTourneysPlayersIds) - - query = self.sql.query['selectHandsPlayersWithWrongTTypeId'] % (dbTourneyTypeId, self.sql.query['handsPlayersTTypeId_joiner'].join([self.sql.query['placeholder'] for id in dbTourneysPlayersIds]) ) - #print "query : %s" % query - cursor = self.get_cursor() - cursor.execute (query, dbTourneysPlayersIds) - result=cursor.fetchall() - - if (len(result) > 0): - logging.debug("%d lines need update : %s" % (len(result), result) ) - listIds = [] - for i in result: - listIds.append(i[0]) - - query2 = self.sql.query['updateHandsPlayersForTTypeId'] % (dbTourneyTypeId, self.sql.query['handsPlayersTTypeId_joiner_id'].join([self.sql.query['placeholder'] for id in listIds]) ) - cursor.execute (query2, listIds) - else: - logging.debug("No need to update, HandsPlayers are correct") - - except: - raise fpdb_simple.FpdbError( "tStoreTourneyPlayers error: " + str(sys.exc_value) ) - #end def tUpdateTourneysHandsPlayers - # Class used to hold all the data needed to write a hand to the db # mainParser() in fpdb_parse_logic.py creates one of these and then passes it to diff --git a/pyfpdb/GuiBulkImport.py b/pyfpdb/GuiBulkImport.py index 16131ab2..a64a9425 100755 --- a/pyfpdb/GuiBulkImport.py +++ b/pyfpdb/GuiBulkImport.py @@ -30,7 +30,6 @@ import gtk import gobject # fpdb/FreePokerTools modules -import fpdb_simple import fpdb_import import Configuration import Exceptions diff --git a/pyfpdb/GuiTableViewer.py b/pyfpdb/GuiTableViewer.py index c730f962..57fc772d 100644 --- a/pyfpdb/GuiTableViewer.py +++ b/pyfpdb/GuiTableViewer.py @@ -20,7 +20,6 @@ import pygtk pygtk.require('2.0') import gtk import os -import fpdb_simple import fpdb_import import fpdb_db diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 2d7f2e0c..9f6993b9 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -38,7 +38,6 @@ except ImportError: logging.info("Not using numpy to define variance in sqlite.") use_numpy = False -import fpdb_simple import FpdbSQLQueries import Configuration diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 577562b8..a7a21831 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -35,10 +35,8 @@ import gtk # fpdb/FreePokerTools modules -import fpdb_simple import fpdb_db import Database -import fpdb_parse_logic import Configuration import Exceptions diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py deleted file mode 100644 index 6fac3669..00000000 --- a/pyfpdb/fpdb_parse_logic.py +++ /dev/null @@ -1,235 +0,0 @@ -#!/usr/bin/python - -#Copyright 2008 Steffen Jobbagy-Felso -#This program is free software: you can redistribute it and/or modify -#it under the terms of the GNU Affero General Public License as published by -#the Free Software Foundation, version 3 of the License. -# -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU Affero General Public License -#along with this program. If not, see . -#In the "official" distribution you can find the license in -#agpl-3.0.txt in the docs folder of the package. - -#parses an in-memory fpdb hand history and calls db routine to store it - -import sys -from time import time, strftime -from Exceptions import * - -import fpdb_simple -import Database - -def mainParser(settings, siteID, category, hand, config, db = None, writeq = None): - """ mainParser for Holdem Hands """ - t0 = time() - backend = settings['db-backend'] - # Ideally db connection is passed in, if not use sql list if passed in, - # otherwise start from scratch - if db is None: - db = Database.Database(c = config, sql = None) - category = fpdb_simple.recogniseCategory(hand[0]) - - base = "hold" if (category == "holdem" or category == "omahahi" or - category == "omahahilo") else "stud" - - #part 0: create the empty arrays - # lineTypes valid values: header, name, cards, action, win, rake, ignore - # lineStreets valid values: predeal, preflop, flop, turn, river - lineTypes = [] - lineStreets = [] - cardValues = [] - cardSuits = [] - boardValues = [] - boardSuits = [] - antes = [] - allIns = [] - actionAmounts = [] - actionNos = [] - actionTypes = [] - actionTypeByNo = [] - seatLines = [] - winnings = [] - rakes = [] - - #part 1: read hand no and check for duplicate - siteHandNo = fpdb_simple.parseSiteHandNo(hand[0]) - handStartTime = fpdb_simple.parseHandStartTime(hand[0]) - isTourney = fpdb_simple.isTourney(hand[0]) - - smallBlindLine = None - for i, line in enumerate(hand): - if 'posts small blind' in line or 'posts the small blind' in line: - if line[-2:] == "$0": continue - smallBlindLine = i - break - else: - smallBlindLine = 0 - # If we did not find a small blind line, what happens? - # if we leave it at None, it errors two lines down. - - gametypeID = fpdb_simple.recogniseGametypeID(backend, db, db.get_cursor(), - hand[0], hand[smallBlindLine], - siteID, category, isTourney) - if isTourney: - siteTourneyNo = fpdb_simple.parseTourneyNo(hand[0]) - buyin = fpdb_simple.parseBuyin(hand[0]) - fee = fpdb_simple.parseFee(hand[0]) - entries = -1 #todo: parse this - prizepool = -1 #todo: parse this - knockout = False - tourneyStartTime= handStartTime #todo: read tourney start time - rebuyOrAddon = fpdb_simple.isRebuyOrAddon(hand[0]) - - # The tourney site id has to be searched because it may already be in - # db with a TourneyTypeId which is different from the one automatically - # calculated (Summary import first) - tourneyTypeId = fpdb_simple.recogniseTourneyTypeId(db, siteID, - siteTourneyNo, - buyin, fee, - knockout, - rebuyOrAddon) - else: - siteTourneyNo = -1 - buyin = -1 - fee = -1 - entries = -1 - prizepool = -1 - knockout = 0 - tourneyStartTime= None - rebuyOrAddon = -1 - - tourneyTypeId = 1 - fpdb_simple.isAlreadyInDB(db, gametypeID, siteHandNo) - - hand = fpdb_simple.filterCrap(hand, isTourney) - - #part 2: classify lines by type (e.g. cards, action, win, sectionchange) and street - fpdb_simple.classifyLines(hand, category, lineTypes, lineStreets) - - #part 3: read basic player info - #3a read player names, startcashes - for i, line in enumerate(hand): - if lineTypes[i] == "name": - seatLines.append(line) - - names = fpdb_simple.parseNames(seatLines) - playerIDs = db.recognisePlayerIDs(names, siteID) # inserts players as needed - tmp = fpdb_simple.parseCashesAndSeatNos(seatLines) - startCashes = tmp['startCashes'] - seatNos = tmp['seatNos'] - - fpdb_simple.createArrays(category, len(names), cardValues, cardSuits, antes, - winnings, rakes, actionTypes, allIns, - actionAmounts, actionNos, actionTypeByNo) - - #3b read positions - if base == "hold": - positions = fpdb_simple.parsePositions(hand, names) - - #part 4: take appropriate action for each line based on linetype - for i, line in enumerate(hand): - if lineTypes[i] == "cards": - fpdb_simple.parseCardLine(category, lineStreets[i], line, names, - cardValues, cardSuits, boardValues, - boardSuits) - #if category=="studhilo": - # print "hand[i]:", hand[i] - # print "cardValues:", cardValues - # print "cardSuits:", cardSuits - elif lineTypes[i] == "action": - fpdb_simple.parseActionLine(base, isTourney, line, lineStreets[i], - playerIDs, names, actionTypes, allIns, - actionAmounts, actionNos, actionTypeByNo) - elif lineTypes[i] == "win": - fpdb_simple.parseWinLine(line, names, winnings, isTourney) - elif lineTypes[i] == "rake": - totalRake = 0 if isTourney else fpdb_simple.parseRake(line) - fpdb_simple.splitRake(winnings, rakes, totalRake) - elif (lineTypes[i] == "header" or lineTypes[i] == "rake" or - lineTypes[i] == "name" or lineTypes[i] == "ignore"): - pass - elif lineTypes[i] == "ante": - fpdb_simple.parseAnteLine(line, isTourney, names, antes) - elif lineTypes[i] == "table": - tableResult=fpdb_simple.parseTableLine(base, line) - else: - raise FpdbError("unrecognised lineType:" + lineTypes[i]) - - maxSeats = tableResult['maxSeats'] - tableName = tableResult['tableName'] - #print "before part5, antes:", antes - - #part 5: final preparations, then call Database.* with - # the arrays as they are - that file will fill them. - fpdb_simple.convertCardValues(cardValues) - if base == "hold": - fpdb_simple.convertCardValuesBoard(boardValues) - fpdb_simple.convertBlindBet(actionTypes, actionAmounts) - fpdb_simple.checkPositions(positions) - - c = db.get_cursor() - c.execute("SELECT limitType FROM Gametypes WHERE id=%s" % (db.sql.query['placeholder'],), (gametypeID, )) - limit_type = c.fetchone()[0] - fpdb_simple.convert3B4B(category, limit_type, actionTypes, actionAmounts) - - totalWinnings = sum(winnings) - - # if hold'em, use positions and not antes, if stud do not use positions, use antes - # this is used for handsplayers inserts, so still needed even if hudcache update is being skipped - if base == "hold": - hudImportData = fpdb_simple.generateHudCacheData(playerIDs, base, - category, actionTypes, - allIns, actionTypeByNo, - winnings, - totalWinnings, - positions, actionTypes, - actionAmounts, None) - else: - hudImportData = fpdb_simple.generateHudCacheData(playerIDs, base, - category, actionTypes, - allIns, actionTypeByNo, - winnings, - totalWinnings, None, - actionTypes, - actionAmounts, antes) - - try: - db.commit() # need to commit new players as different db connection used - # for other writes. maybe this will change maybe not ... - except: # TODO: this really needs to be narrowed down - print "parse: error during commit: " + str(sys.exc_value) - -# HERE's an ugly kludge to keep from failing when positions is undef -# We'll fix this by getting rid of the legacy importer. REB - try: - if positions: - pass - except NameError: - positions = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - # save data structures in a HandToWrite instance and then insert into database: - htw = Database.HandToWrite() - htw.set_all( config, settings, base, category, siteTourneyNo, buyin - , fee, knockout, entries, prizepool, tourneyStartTime - , isTourney, tourneyTypeId, siteID, siteHandNo - , gametypeID, handStartTime, names, playerIDs, startCashes - , positions, antes, cardValues, cardSuits, boardValues, boardSuits - , winnings, rakes, actionTypes, allIns, actionAmounts - , actionNos, hudImportData, maxSeats, tableName, seatNos) - - # save hand in db via direct call or via q if in a thread - if writeq is None: - result = db.store_the_hand(htw) - else: - writeq.put(htw) - result = -999 # meaning unknown - - t9 = time() - #print "parse and save=(%4.3f)" % (t9-t0) - return result -#end def mainParser - diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py deleted file mode 100644 index 5f0c6507..00000000 --- a/pyfpdb/fpdb_simple.py +++ /dev/null @@ -1,1728 +0,0 @@ -#!/usr/bin/python -# -*- coding: iso-8859-15 -*- - -#Copyright 2008 Steffen Jobbagy-Felso -#This program is free software: you can redistribute it and/or modify -#it under the terms of the GNU Affero General Public License as published by -#the Free Software Foundation, version 3 of the License. -# -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU Affero General Public License -#along with this program. If not, see . -#In the "official" distribution you can find the license in -#agpl-3.0.txt in the docs folder of the package. - -#This file contains simple functions for fpdb - -#Aiming to eventually remove this module, functions will move to, eg: -#fpdb_db db create/re-create/management/etc -#Hands or related files for saving hands to db, etc - -import datetime -import time -import re -import sys -from Exceptions import * -import locale - -import Card - -PS = 1 -FTP = 2 - -# TODO: these constants are also used in fpdb_save_to_db and others, is there a way to do like C #define, and #include ? -# answer - yes. These are defined in fpdb_db so are accessible through that class. -MYSQL_INNODB = 2 -PGSQL = 3 -SQLITE = 4 - -LOCALE_ENCODING = locale.getdefaultlocale()[1] - -#returns an array of the total money paid. intending to add rebuys/addons here -def calcPayin(count, buyin, fee): - return [buyin + fee for i in xrange(count)] -#end def calcPayin - -def checkPositions(positions): - """ verify positions are valid """ - if any(not (p == "B" or p == "S" or (p >= 0 and p <= 9)) for p in positions): - raise FpdbError("invalid position '"+p+"' found in checkPositions") - ### RHH modified to allow for "position 9" here (pos==9 is when you're a dead hand before the BB - ### eric - position 8 could be valid - if only one blind is posted, but there's still 10 people, ie a sitout is present, and the small is dead... - -def classifyLines(hand, category, lineTypes, lineStreets): - """ makes a list of classifications for each line for further processing - manipulates passed arrays """ - currentStreet = "predeal" - done = False #set this to true once we reach the last relevant line (the summary, except rake, is all repeats) - for i, line in enumerate(hand): - if done: - if "[" not in line or "mucked [" not in line: - lineTypes.append("ignore") - else: - lineTypes.append("cards") - elif line.startswith("Dealt to"): - lineTypes.append("cards") - elif i == 0: - lineTypes.append("header") - elif line.startswith("Table '"): - lineTypes.append("table") - elif line.startswith("Seat ") and ( ("in chips" in line) or "($" in line): - lineTypes.append("name") - elif isActionLine(line): - lineTypes.append("action") - if " posts " in line or " posts the " in line: - currentStreet="preflop" - elif " antes " in line or " posts the ante " in line: - lineTypes.append("ante") - elif line.startswith("*** FLOP *** ["): - lineTypes.append("cards") - currentStreet="flop" - elif line.startswith("*** TURN *** ["): - lineTypes.append("cards") - currentStreet="turn" - elif line.startswith("*** RIVER *** ["): - lineTypes.append("cards") - currentStreet="river" - elif line.startswith("*** 3"): - lineTypes.append("ignore") - currentStreet=0 - elif line.startswith("*** 4"): - lineTypes.append("ignore") - currentStreet=1 - elif line.startswith("*** 5"): - lineTypes.append("ignore") - currentStreet=2 - elif line.startswith("*** 6"): - lineTypes.append("ignore") - currentStreet=3 - elif line.startswith("*** 7") or line == "*** RIVER ***": - lineTypes.append("ignore") - currentStreet=4 - elif isWinLine(line): - lineTypes.append("win") - elif line.startswith("Total pot ") and "Rake" in line: - lineTypes.append("rake") - done=True - elif "*** SHOW DOWN ***" in line or "*** SUMMARY ***" in line: - lineTypes.append("ignore") - #print "in classifyLine, showdown or summary" - elif " shows [" in line: - lineTypes.append("cards") - else: - raise FpdbError("unrecognised linetype in:"+hand[i]) - lineStreets.append(currentStreet) - -def convert3B4B(category, limit_type, actionTypes, actionAmounts): - """calculates the actual bet amounts in the given amount array and changes it accordingly.""" - for i in xrange(len(actionTypes)): - for j in xrange(len(actionTypes[i])): - bets = [] - for k in xrange(len(actionTypes[i][j])): - if (actionTypes[i][j][k] == "bet"): - bets.append((i,j,k)) - if (len(bets)>=2): - #print "len(bets) 2 or higher, need to correct it. bets:",bets,"len:",len(bets) - for betNo in reversed(xrange (1,len(bets))): - amount2 = actionAmounts[bets[betNo][0]][bets[betNo][1]][bets[betNo][2]] - amount1 = actionAmounts[bets[betNo-1][0]][bets[betNo-1][1]][bets[betNo-1][2]] - actionAmounts[bets[betNo][0]][bets[betNo][1]][bets[betNo][2]] = amount2 - amount1 - -def convertBlindBet(actionTypes, actionAmounts): - """ Corrects the bet amount if the player had to pay blinds """ - i = 0#setting street to pre-flop - for j in xrange(len(actionTypes[i])):#playerloop - blinds = [] - bets = [] - for k in xrange(len(actionTypes[i][j])): - if actionTypes[i][j][k] == "blind": - blinds.append((i,j,k)) - - if blinds and actionTypes[i][j][k] == "bet": - bets.append((i,j,k)) - if len(bets) == 1: - blind_amount=actionAmounts[blinds[0][0]][blinds[0][1]][blinds[0][2]] - bet_amount=actionAmounts[bets[0][0]][bets[0][1]][bets[0][2]] - actionAmounts[bets[0][0]][bets[0][1]][bets[0][2]] = bet_amount - blind_amount - -#converts the strings in the given array to ints (changes the passed array, no returning). see table design for conversion details -#todo: make this use convertCardValuesBoard -def convertCardValues(arr): - map(convertCardValuesBoard, arr) - -# a 0-card is one in a stud game that we did not see or was not shown -card_map = { 0: 0, "2": 2, "3" : 3, "4" : 4, "5" : 5, "6" : 6, "7" : 7, "8" : 8, - "9" : 9, "T" : 10, "J" : 11, "Q" : 12, "K" : 13, "A" : 14} - -def convertCardValuesBoard(arr): - """ converts the strings in the given array to ints - (changes the passed array, no returning). see table design for - conversion details """ - for i in xrange(len(arr)): - arr[i] = card_map[arr[i]] - -def createArrays(category, seats, card_values, card_suits, antes, winnings, - rakes, action_types, allIns, action_amounts, actionNos, - actionTypeByNo): - """ this creates the 2D/3D arrays. manipulates the passed arrays instead of returning. """ - for i in xrange(seats):#create second dimension arrays - card_values.append( [] ) - card_suits.append( [] ) - antes.append(0) - winnings.append(0) - rakes.append(0) - - streetCount = 4 if (category == "holdem" or category == "omahahi" or - category == "omahahilo") else 5 - - for i in xrange(streetCount): #build the first dimension array, for streets - action_types.append([]) - allIns.append([]) - action_amounts.append([]) - actionNos.append([]) - actionTypeByNo.append([]) - for j in xrange(seats): # second dimension arrays: players - action_types[i].append([]) - allIns[i].append([]) - action_amounts[i].append([]) - actionNos[i].append([]) -# if (category=="holdem" or category=="omahahi" or category=="omahahilo"): -# pass - if category == "razz" or category == "studhi" or category == "studhilo": #need to fill card arrays. - for i in xrange(seats): - for j in xrange(7): - card_values[i].append(0) - card_suits[i].append("x") -# else: -# raise FpdbError("invalid category") -#end def createArrays - -def fill_board_cards(board_values, board_suits): - """ fill up the two board card arrays """ - while len(board_values) < 5: - board_values.append(0) - board_suits.append("x") - -def fillCardArrays(player_count, base, category, card_values, card_suits): - """fills up the two card arrays""" - if category == "holdem": - cardCount = 2 - elif category == "omahahi" or category == "omahahilo": - cardCount = 4 - elif base == "stud": - cardCount = 7 - else: - raise FpdbError("invalid category:", category) - - for i in xrange(player_count): - while len(card_values[i]) < cardCount: - card_values[i].append(0) - card_suits[i].append("x") -#end def fillCardArrays - -#filters out a player that folded before paying ante or blinds. This should be called -#before calling the actual hand parser. manipulates hand, no return. -def filterAnteBlindFold(hand): - #todo: this'll only get rid of one ante folder, not multiple ones - #todo: in tourneys this should not be removed but - #print "start of filterAnteBlindFold" - pre3rd = [] - for i, line in enumerate(hand): - if line.startswith("*** 3") or line.startswith("*** HOLE"): - pre3rd = hand[0:i] - - foldeeName = None - for line in pre3rd: - if line.endswith("folds") or line.endswith("is sitting out") or line.endswith(" stands up"): #found ante fold or timeout - pos = line.find(" folds") - foldeeName = line[0:pos] - if pos == -1 and " in chips)" not in line: - pos = line.find(" is sitting out") - foldeeName = line[0:pos] - if pos == -1: - pos = line.find(" stands up") - foldeeName = line[0:pos] - if pos == -1: - pos1 = line.find(": ") + 2 - pos2 = line.find(" (") - foldeeName = line[pos1:pos2] - - if foldeeName is not None: - #print "filterAnteBlindFold, foldeeName:",foldeeName - for i, line in enumerate(hand): - if foldeeName in line: - hand[i] = None - - return [line for line in hand if line] - -def stripEOLspaces(str): - return str.rstrip() - -def filterCrap(hand, isTourney): - """ removes useless lines as well as trailing spaces """ - - #remove trailing spaces at end of line - hand = [line.rstrip() for line in hand] - - #general variable position word filter/string filter - for i in xrange(len(hand)): - if hand[i].startswith("Board ["): - hand[i] = False - elif hand[i].find(" out of hand ")!=-1: - hand[i]=hand[i][:-56] - elif "($0 in chips)" in hand[i]: - hand[i] = False - elif hand[i]=="*** HOLE CARDS ***": - hand[i] = False - elif hand[i].endswith("has been disconnected"): - hand[i] = False - elif hand[i].endswith("has requested TIME"): - hand[i] = False - elif hand[i].endswith("has returned"): - hand[i] = False - elif hand[i].endswith("will be allowed to play after the button"): - hand[i] = False - elif hand[i].endswith("has timed out"): - hand[i] = False - elif hand[i].endswith("has timed out while disconnected"): - hand[i] = False - elif hand[i].endswith("has timed out while being disconnected"): - hand[i] = False - elif hand[i].endswith("is connected"): - hand[i] = False - elif hand[i].endswith("is disconnected"): - hand[i] = False - elif hand[i].find(" is low with [")!=-1: - hand[i] = False - elif hand[i].endswith(" mucks"): - hand[i] = False - elif hand[i].endswith(": mucks hand"): - hand[i] = False - elif hand[i] == "No low hand qualified": - hand[i] = False - elif hand[i] == "Pair on board - a double bet is allowed": - hand[i] = False - elif " shows " in hand[i] and "[" not in hand[i]: - hand[i] = False - elif hand[i].startswith("The button is in seat #"): - hand[i] = False - #above is alphabetic, reorder below if bored - elif hand[i].startswith("Time has expired"): - hand[i] = False - elif hand[i].endswith("has reconnected"): - hand[i] = False - elif hand[i].endswith("seconds left to act"): - hand[i] = False - elif hand[i].endswith("seconds to reconnect"): - hand[i] = False - elif hand[i].endswith("was removed from the table for failing to post"): - hand[i] = False - elif "joins the table at seat " in hand[i]: - hand[i] = False - elif (hand[i].endswith("leaves the table")): - hand[i] = False - elif "is high with " in hand[i]: - hand[i] = False - elif hand[i].endswith("doesn't show hand"): - hand[i] = False - elif hand[i].endswith("is being treated as all-in"): - hand[i] = False - elif " adds $" in hand[i]: - hand[i] = False - elif hand[i] == "Betting is capped": - hand[i] = False - elif (hand[i].find(" said, \"")!=-1): - hand[i] = False - - if isTourney and not hand[i] == False: - if (hand[i].endswith(" is sitting out") and (not hand[i].startswith("Seat "))): - hand[i] = False - elif hand[i]: - if (hand[i].endswith(": sits out")): - hand[i] = False - elif (hand[i].endswith(" is sitting out")): - hand[i] = False - # python docs say this is identical to filter(None, list) - # which removes all false items from the passed list (hand) - hand = [line for line in hand if line] - - return hand - -def float2int(string): - """ takes a poker float (including , for thousand seperator) and - converts it to an int """ - # Note that this automagically assumes US style currency formatters - pos = string.find(",") - if pos != -1: #remove , the thousand seperator - string = "%s%s" % (string[0:pos], string[pos+1:]) - - pos = string.find(".") - if pos != -1: #remove decimal point - string = "%s%s" % (string[0:pos], string[pos+1:]) - - result = int(string) - if pos == -1: #no decimal point - was in full dollars - need to multiply with 100 - result *= 100 - return result - -ActionLines = ( "calls $", ": calls ", "brings in for", "completes it to", - "posts small blind", "posts the small blind", "posts big blind", - "posts the big blind", "posts small & big blinds", "posts $", - "posts a dead", "bets $", ": bets ", " raises") - -def isActionLine(line): - if line.endswith("folds"): - return True - elif line.endswith("checks"): - return True - elif line.startswith("Uncalled bet"): - return True - - # searches for each member of ActionLines being in line, returns true - # on first match .. neat func - return any(x for x in ActionLines if x in line) - -def isAlreadyInDB(db, gametypeID, siteHandNo): - c = db.get_cursor() - c.execute(db.sql.query['isAlreadyInDB'], (gametypeID, siteHandNo)) - result = c.fetchall() - if len(result) >= 1: - raise DuplicateError ("dupl") - -def isRebuyOrAddon(topline): - """isRebuyOrAddon not implemented yet""" - return False - -#returns whether the passed topline indicates a tournament or not -def isTourney(topline): - return "Tournament" in topline - -WinLines = ( "wins the pot", "ties for the ", "wins side pot", "wins the low main pot", "wins the high main pot", - "wins the low", - "wins the high pot", "wins the high side pot", "wins the main pot", "wins the side pot", "collected" ) - -def isWinLine(line): - """ returns boolean whether the passed line is a win line """ - return any(x for x in WinLines if x in line) - -#returns the amount of cash/chips put into the put in the given action line -def parseActionAmount(line, atype, isTourney): - #if (line.endswith(" and is all-in")): - # line=line[:-14] - #elif (line.endswith(", and is all in")): - # line=line[:-15] - - #ideally we should recognise this as an all-in if category is capXl - if line.endswith(", and is capped"): - line=line[:-15] - if line.endswith(" and is capped"): - line=line[:-14] - - if atype == "fold" or atype == "check": - amount = 0 - elif atype == "unbet": - pos1 = line.find("$") + 1 - if pos1 == 0: - pos1 = line.find("(") + 1 - pos2 = line.find(")") - amount = float2int(line[pos1:pos2]) - elif atype == "bet" and ": raises $" in line and "to $" in line: - pos = line.find("to $")+4 - amount = float2int(line[pos:]) - else: - if not isTourney: - pos = line.rfind("$")+1 - #print "parseActionAmount, line:", line, "line[pos:]:", line[pos:] - amount = float2int(line[pos:]) - else: - #print "line:"+line+"EOL" - pos = line.rfind(" ")+1 - #print "pos:",pos - #print "pos of 20:", line.find("20") - amount = int(line[pos:]) - - if atype == "unbet": - amount *= -1 - return amount -#end def parseActionAmount - -#doesnt return anything, simply changes the passed arrays action_types and -# action_amounts. For stud this expects numeric streets (3-7), for -# holdem/omaha it expects predeal, preflop, flop, turn or river -def parseActionLine(base, isTourney, line, street, playerIDs, names, action_types, allIns, action_amounts, actionNos, actionTypeByNo): - if street == "predeal" or street == "preflop": - street = 0 - elif street == "flop": - street = 1 - elif street == "turn": - street = 2 - elif street == "river": - street = 3 - - nextActionNo = 0 - for player in xrange(len(actionNos[street])): - for count in xrange(len(actionNos[street][player])): - if actionNos[street][player][count]>=nextActionNo: - nextActionNo=actionNos[street][player][count]+1 - - (line, allIn) = goesAllInOnThisLine(line) - atype = parseActionType(line) - playerno = recognisePlayerNo(line, names, atype) - amount = parseActionAmount(line, atype, isTourney) - - action_types[street][playerno].append(atype) - allIns[street][playerno].append(allIn) - action_amounts[street][playerno].append(amount) - actionNos[street][playerno].append(nextActionNo) - tmp=(playerIDs[playerno], atype) - actionTypeByNo[street].append(tmp) - -def goesAllInOnThisLine(line): - """returns whether the player went all-in on this line and removes the all-in text from the line.""" - isAllIn = False - if (line.endswith(" and is all-in")): - line = line[:-14] - isAllIn = True - elif (line.endswith(", and is all in")): - line = line[:-15] - isAllIn = True - return (line, isAllIn) - -#returns the action type code (see table design) of the given action line -ActionTypes = { 'brings in for' :"blind", - ' posts $' :"blind", - ' posts a dead ' :"blind", - ' posts the small blind of $' :"blind", - ': posts big blind ' :"blind", - ': posts small blind ' :"blind", - ' posts the big blind of $' :"blind", - ': posts small & big blinds $' :"blind", - ': posts small blind $' :"blind", - 'calls' :"call", - 'completes it to' :"bet", - ' bets' :"bet", - ' raises' :"bet" - } -def parseActionType(line): - if (line.startswith("Uncalled bet")): - return "unbet" - elif (line.endswith(" folds")): - return "fold" - elif (line.endswith(" checks")): - return "check" - else: - for x in ActionTypes: - if x in line: - return ActionTypes[x] - raise FpdbError ("failed to recognise actiontype in parseActionLine in: "+line) - -#parses the ante out of the given line and checks which player paid it, updates antes accordingly. -def parseAnteLine(line, isTourney, names, antes): - for i, name in enumerate(names): - if line.startswith(name.encode(LOCALE_ENCODING)): - pos = line.rfind("$") + 1 - if not isTourney: - antes[i] += float2int(line[pos:]) - else: - if "all-in" not in line: - pos = line.rfind(" ") + 1 - antes[i] += int(line[pos:]) - else: - pos1 = line.rfind("ante") + 5 - pos2 = line.find(" ", pos1) - antes[i] += int(line[pos1:pos2]) - -#returns the buyin of a tourney in cents -def parseBuyin(topline): - pos1 = topline.find("$")+1 - if pos1 != 0: - pos2 = topline.find("+") - else: - pos1 = topline.find("€")+3 - pos2 = topline.find("+") - return float2int(topline[pos1:pos2]) - -#parses a card line and changes the passed arrays accordingly -#todo: reorganise this messy method -def parseCardLine(category, street, line, names, cardValues, cardSuits, boardValues, boardSuits): - if line.startswith("Dealt to") or " shows [" in line or "mucked [" in line: - playerNo = recognisePlayerNo(line, names, "card") #anything but unbet will be ok for that string - - pos = line.rfind("[")+1 - if category == "holdem": - for i in (pos, pos+3): - cardValues[playerNo].append(line[i:i+1]) - cardSuits[playerNo].append(line[i+1:i+2]) - if len(cardValues[playerNo]) != 2: - if (cardValues[playerNo][0] == cardValues[playerNo][2] and - cardSuits[playerNo][1] == cardSuits[playerNo][3]): - cardValues[playerNo]=cardValues[playerNo][0:2] - cardSuits[playerNo]=cardSuits[playerNo][0:2] - else: - print "line:",line,"cardValues[playerNo]:",cardValues[playerNo] - raise FpdbError("read too many/too few holecards in parseCardLine") - elif category == "omahahi" or category == "omahahilo": - for i in (pos, pos+3, pos+6, pos+9): - cardValues[playerNo].append(line[i:i+1]) - cardSuits[playerNo].append(line[i+1:i+2]) - if (len(cardValues[playerNo])!=4): - if (cardValues[playerNo][0] == cardValues[playerNo][4] and - cardSuits[playerNo][3] == cardSuits[playerNo][7]): #two tests will do - cardValues[playerNo] = cardValues[playerNo][0:4] - cardSuits[playerNo] = cardSuits[playerNo][0:4] - else: - print "line:",line,"cardValues[playerNo]:",cardValues[playerNo] - raise FpdbError("read too many/too few holecards in parseCardLine") - elif category == "razz" or category == "studhi" or category == "studhilo": - if "shows" not in line and "mucked" not in line: - #print "parseCardLine(in stud if), street:", street - if line[pos+2]=="]": #-> not (hero and 3rd street) - cardValues[playerNo][street+2]=line[pos:pos+1] - cardSuits[playerNo][street+2]=line[pos+1:pos+2] - else: - #print "hero card1:", line[pos:pos+2], "hero card2:", line[pos+3:pos+5], "hero card3:", line[pos+6:pos+8], - cardValues[playerNo][street]=line[pos:pos+1] - cardSuits[playerNo][street]=line[pos+1:pos+2] - cardValues[playerNo][street+1]=line[pos+3:pos+4] - cardSuits[playerNo][street+1]=line[pos+4:pos+5] - cardValues[playerNo][street+2]=line[pos+6:pos+7] - cardSuits[playerNo][street+2]=line[pos+7:pos+8] - else: - #print "parseCardLine(in stud else), street:", street - cardValues[playerNo][0]=line[pos:pos+1] - cardSuits[playerNo][0]=line[pos+1:pos+2] - pos+=3 - cardValues[playerNo][1]=line[pos:pos+1] - cardSuits[playerNo][1]=line[pos+1:pos+2] - if street==4: - pos=pos=line.rfind("]")-2 - cardValues[playerNo][6]=line[pos:pos+1] - cardSuits[playerNo][6]=line[pos+1:pos+2] - #print "cardValues:", cardValues - #print "cardSuits:", cardSuits - else: - print "line:",line,"street:",street - raise FpdbError("invalid category") - #print "end of parseCardLine/playercards, cardValues:",cardValues - elif (line.startswith("*** FLOP ***")): - pos=line.find("[")+1 - for i in (pos, pos+3, pos+6): - boardValues.append(line[i:i+1]) - boardSuits.append(line[i+1:i+2]) - #print boardValues - elif (line.startswith("*** TURN ***") or line.startswith("*** RIVER ***")): - pos=line.find("[")+1 - pos=line.find("[", pos+1)+1 - boardValues.append(line[pos:pos+1]) - boardSuits.append(line[pos+1:pos+2]) - #print boardValues - else: - raise FpdbError ("unrecognised line:"+line) - -def parseCashesAndSeatNos(lines): - """parses the startCashes and seatNos of each player out of the given lines and returns them as a dictionary of two arrays""" - cashes = [] - seatNos = [] - for i in xrange (len(lines)): - pos2=lines[i].find(":") - seatNos.append(int(lines[i][5:pos2])) - - pos1=lines[i].rfind("($")+2 - if pos1==1: #for tourneys - it's 1 instead of -1 due to adding 2 above - pos1=lines[i].rfind("(")+1 - pos2=lines[i].find(" in chips") - cashes.append(float2int(lines[i][pos1:pos2])) - return {'startCashes':cashes, 'seatNos':seatNos} - -#returns the buyin of a tourney in cents -def parseFee(topline): - pos1 = topline.find("$")+1 - if pos1 != 0: - pos1 = topline.find("$", pos1)+1 - pos2 = topline.find(" ", pos1) - else: - pos1 = topline.find("€")+3 - pos1 = topline.find("€", pos1)+3 - pos2 = topline.find(" ", pos1) - return float2int(topline[pos1:pos2]) - -#returns a datetime object with the starttime indicated in the given topline -def parseHandStartTime(topline): - #convert x:13:35 to 0x:13:35 - counter=0 - while counter < 10: - pos = topline.find(" %d:" % counter) - if pos != -1: - topline = "%s0%s" % (topline[0:pos+1], topline[pos+1:]) - break - counter += 1 - - isUTC=False - if topline.find("UTC")!=-1: - pos1 = topline.find("-")+2 - pos2 = topline.find("UTC") - tmp=topline[pos1:pos2] - isUTC=True - else: - tmp=topline - #print "parsehandStartTime, tmp:", tmp - pos = tmp.find("-")+2 - tmp = tmp[pos:] - #Need to match either - # 2008/09/07 06:23:14 ET or - # 2008/08/17 - 01:14:43 (ET) or - # 2008/11/12 9:33:31 CET [2008/11/12 3:33:31 ET] - rexx = '(?P[0-9]{4})\/(?P[0-9]{2})\/(?P[0-9]{2})[\- ]+(?P
[0-9]+):(?P[0-9]+):(?P[0-9]+)' - m = re.search(rexx,tmp) - result = datetime.datetime(int(m.group('YEAR')), int(m.group('MON')), int(m.group('DAY')), int(m.group('HR')), int(m.group('MIN')), int(m.group('SEC'))) - - if not isUTC: #these use US ET - result += datetime.timedelta(hours=5) - - return result - -#parses the names out of the given lines and returns them as an array -def findName(line): - pos1 = line.find(":") + 2 - pos2 = line.rfind("(") - 1 - return unicode(line[pos1:pos2], LOCALE_ENCODING) - -def parseNames(lines): - return [findName(line) for line in lines] - -def parsePositions(hand, names): - positions = [-1 for i in names] - sb, bb = -1, -1 - - for line in hand: - if sb == -1 and "small blind" in line and "dead small blind" not in line: - sb = line - if bb == -1 and "big blind" in line and "dead big blind" not in line: - bb = line - -#identify blinds -#print "parsePositions before recognising sb/bb. names:",names - sbExists = True - if sb != -1: - sb = recognisePlayerNo(sb, names, "bet") - else: - sbExists = False - if bb != -1: - bb = recognisePlayerNo(bb, names, "bet") - -# print "sb = ", sb, "bb = ", bb - if bb == sb: # if big and small are same, then don't duplicate the small - sbExists = False - sb = -1 - - #write blinds into array - if sbExists: - positions[sb]="S" - positions[bb]="B" - - #fill up rest of array - arraypos = sb - 1 if sbExists else bb - 1 - - distFromBtn=0 - while arraypos >= 0 and arraypos != bb: - #print "parsePositions first while, arraypos:",arraypos,"positions:",positions - positions[arraypos] = distFromBtn - arraypos -= 1 - distFromBtn += 1 - - # eric - this takes into account dead seats between blinds - if sbExists: - i = bb - 1 - while positions[i] < 0 and i != sb: - positions[i] = 9 - i -= 1 - ### RHH - Changed to set the null seats before BB to "9" - i = sb - 1 if sbExists else bb - 1 - - while positions[i] < 0: - positions[i]=9 - i-=1 - - arraypos=len(names)-1 - if (bb!=0 or (bb==0 and sbExists==False) or (bb == 1 and sb != arraypos) ): - while (arraypos > bb and arraypos > sb): - positions[arraypos] = distFromBtn - arraypos -= 1 - distFromBtn += 1 - - if any(p == -1 for p in positions): - print "parsePositions names:",names - print "result:",positions - raise FpdbError ("failed to read positions") -# print str(positions), "\n" - return positions - -#simply parses the rake amount and returns it as an int -def parseRake(line): - pos = line.find("Rake")+6 - rake = float2int(line[pos:]) - return rake - -def parseSiteHandNo(topline): - """returns the hand no assigned by the poker site""" - pos1 = topline.find("#")+1 - pos2 = topline.find(":") - return topline[pos1:pos2] - -def parseTableLine(base, line): - """returns a dictionary with maxSeats and tableName""" - pos1=line.find('\'')+1 - pos2=line.find('\'', pos1) - #print "table:",line[pos1:pos2] - pos3=pos2+2 - pos4=line.find("-max") - #print "seats:",line[pos3:pos4] - return {'maxSeats':int(line[pos3:pos4]), 'tableName':line[pos1:pos2]} -#end def parseTableLine - -#returns the hand no assigned by the poker site -def parseTourneyNo(topline): - pos1 = topline.find("Tournament #")+12 - pos2 = topline.find(",", pos1) - #print "parseTourneyNo pos1:",pos1," pos2:",pos2, " result:",topline[pos1:pos2] - return topline[pos1:pos2] - -#parses a win/collect line. manipulates the passed array winnings, no explicit return -def parseWinLine(line, names, winnings, isTourney): - #print "parseWinLine: line:",line - for i,n in enumerate(names): - n = n.encode(LOCALE_ENCODING) - if line.startswith(n): - if isTourney: - pos1 = line.rfind("collected ") + 10 - pos2 = line.find(" ", pos1) - winnings[i] += int(line[pos1:pos2]) - else: - pos1 = line.rfind("$") + 1 - pos2 = line.find(" ", pos1) - winnings[i] += float2int(line[pos1:pos2]) - -#returns the category (as per database) string for the given line -def recogniseCategory(line): - if "Razz" in line: - return "razz" - elif "Hold'em" in line: - return "holdem" - elif "Omaha" in line: - if "Hi/Lo" not in line and "H/L" not in line: - return "omahahi" - else: - return "omahahilo" - elif "Stud" in line: - if "Hi/Lo" not in line and "H/L" not in line: - return "studhi" - else: - return "studhilo" - else: - raise FpdbError("failed to recognise category, line:"+line) - -#returns the int for the gametype_id for the given line -def recogniseGametypeID(backend, db, cursor, topline, smallBlindLine, site_id, category, isTourney):#todo: this method is messy - #if (topline.find("HORSE")!=-1): - # raise FpdbError("recogniseGametypeID: HORSE is not yet supported.") - - #note: the below variable names small_bet and big_bet are misleading, in NL/PL they mean small/big blind - if isTourney: - type = "tour" - pos1 = topline.find("(")+1 - if(topline[pos1] == "H" or topline[pos1] == "O" or - topline[pos1] == "R" or topline[pos1]=="S" or - topline[pos1+2] == "C"): - pos1 = topline.find("(", pos1)+1 - pos2 = topline.find("/", pos1) - small_bet = int(topline[pos1:pos2]) - else: - type = "ring" - pos1 = topline.find("$")+1 - pos2 = topline.find("/$") - small_bet = float2int(topline[pos1:pos2]) - - pos1 = pos2+2 - if isTourney: - pos1 -= 1 - pos2 = topline.find(")") - - if pos2 <= pos1: - pos2 = topline.find(")", pos1) - - if isTourney: - big_bet = int(topline[pos1:pos2]) - else: - big_bet = float2int(topline[pos1:pos2]) - - if 'No Limit' in topline: - limit_type = "nl" if 'Cap No' not in topline else "cn" - elif 'Pot Limit' in topline: - limit_type = "pl" if 'Cap Pot' not in topline else "cp" - else: - limit_type = "fl" - - #print "recogniseGametypeID small_bet/blind:",small_bet,"big bet/blind:", big_bet,"limit type:",limit_type - if limit_type == "fl": - cursor.execute(db.sql.query['getGametypeFL'], (site_id, type, category, - limit_type, small_bet, - big_bet)) - else: - cursor.execute(db.sql.query['getGametypeNL'], (site_id, type, category, - limit_type, small_bet, - big_bet)) - result = cursor.fetchone() - #print "recgt1 result=",result - #ret=result[0] - #print "recgt1 ret=",ret - #print "tried SELECTing gametypes.id, result:",result - - try: - len(result) - except TypeError: - if category=="holdem" or category=="omahahi" or category=="omahahilo": - base="hold" - else: - base="stud" - - if category=="holdem" or category=="omahahi" or category=="studhi": - hiLo='h' - elif category=="razz": - hiLo='l' - else: - hiLo='s' - - if (limit_type=="fl"): - big_blind=small_bet - if base=="hold": - if smallBlindLine==topline: - raise FpdbError("invalid small blind line") - elif isTourney: - pos=smallBlindLine.rfind(" ")+1 - small_blind=int(smallBlindLine[pos:]) - else: - pos=smallBlindLine.rfind("$")+1 - small_blind=float2int(smallBlindLine[pos:]) - else: - small_blind=0 - result = db.insertGameTypes( (site_id, type, base, category, limit_type, hiLo - ,small_blind, big_blind, small_bet, big_bet) ) - #cursor.execute ("SELECT id FROM Gametypes WHERE siteId=%s AND type=%s AND category=%s - #AND limitType=%s AND smallBet=%s AND bigBet=%s", (site_id, type, category, limit_type, small_bet, big_bet)) - else: - result = db.insertGameTypes( (site_id, type, base, category, limit_type, hiLo - ,small_bet, big_bet, 0, 0) )#remember, for these bet means blind - #cursor.execute ("SELECT id FROM Gametypes WHERE siteId=%s AND type=%s AND category=%s - #AND limitType=%s AND smallBlind=%s AND bigBlind=%s", (site_id, type, category, limit_type, small_bet, big_bet)) - - return result[0] -#end def recogniseGametypeID - -def recogniseTourneyTypeId(db, siteId, tourneySiteId, buyin, fee, knockout, rebuyOrAddon): - ret = -1 - cursor = db.get_cursor() - # First we try to find the tourney itself (by its tourneySiteId) in case it has already been inserted before (by a summary file for instance) - # The reason is that some tourneys may not be identified correctly in the HH toplines (especially Buy-In and Fee which are used to search/create the TourneyTypeId) - #TODO: When the summary file will be dumped to BD, if the tourney is already in, Buy-In/Fee may need an update (e.g. creation of a new type and link to the Tourney) - cursor.execute (db.sql.query['getTourneyTypeIdByTourneyNo'].replace('%s', db.sql.query['placeholder']), (tourneySiteId, siteId)) - result = cursor.fetchone() - - try: - len(result) - ret = result[0] - except: - cursor.execute( """SELECT id FROM TourneyTypes - WHERE siteId=%s AND buyin=%s AND fee=%s - AND knockout=%s AND rebuyOrAddon=%s""".replace('%s', db.sql.query['placeholder']) - , (siteId, buyin, fee, knockout, rebuyOrAddon) ) - result = cursor.fetchone() - #print "tried selecting tourneytypes.id, result:", result - - try: - len(result) - ret = result[0] - except TypeError:#this means we need to create a new entry - #print "insert new tourneytype record ..." - try: - cursor.execute( """INSERT INTO TourneyTypes (siteId, buyin, fee, knockout, rebuyOrAddon) - VALUES (%s, %s, %s, %s, %s)""".replace('%s', db.sql.query['placeholder']) - , (siteId, buyin, fee, knockout, rebuyOrAddon) ) - ret = db.get_last_insert_id(cursor) - except: - #print "maybe tourneytype was created since select, try selecting again ..." - cursor.execute( """SELECT id FROM TourneyTypes - WHERE siteId=%s AND buyin=%s AND fee=%s - AND knockout=%s AND rebuyOrAddon=%s""".replace('%s', db.sql.query['placeholder']) - , (siteId, buyin, fee, knockout, rebuyOrAddon) ) - result = cursor.fetchone() - try: - len(result) - ret = result[0] - except: - print "Failed to find or insert TourneyTypes record" - ret = -1 # failed to find or insert record - #print "tried selecting tourneytypes.id again, result:", result - - #print "recogniseTourneyTypeId: returning", ret - return ret -#end def recogniseTourneyTypeId - - -#recognises the name in the given line and returns its array position in the given array -def recognisePlayerNo(line, names, atype): - #print "recogniseplayerno, names:",names - for i in xrange(len(names)): - encodedName = names[i].encode(LOCALE_ENCODING) - if (atype=="unbet"): - if (line.endswith(encodedName)): - return (i) - elif (line.startswith("Dealt to ")): - #print "recognisePlayerNo, card precut, line:",line - tmp=line[9:] - #print "recognisePlayerNo, card postcut, tmp:",tmp - if (tmp.startswith(encodedName)): - return (i) - elif (line.startswith("Seat ")): - if (line.startswith("Seat 10")): - tmp=line[9:] - else: - tmp=line[8:] - - if (tmp.startswith(encodedName)): - return (i) - else: - if (line.startswith(encodedName)): - return (i) - #if we're here we mustve failed - raise FpdbError ("failed to recognise player in: "+line+" atype:"+atype) -#end def recognisePlayerNo - - -#removes trailing \n from the given array -def removeTrailingEOL(arr): - for i in xrange(len(arr)): - if (arr[i].endswith("\n")): - #print "arr[i] before removetrailingEOL:", arr[i] - arr[i]=arr[i][:-1] - #print "arr[i] after removetrailingEOL:", arr[i] - return arr -#end def removeTrailingEOL - -#splits the rake according to the proportion of pot won. manipulates the second passed array. -def splitRake(winnings, rakes, totalRake): - winnercnt=0 - totalWin=0 - for i in xrange(len(winnings)): - if winnings[i]!=0: - winnercnt+=1 - totalWin+=winnings[i] - firstWinner=i - if winnercnt==1: - rakes[firstWinner]=totalRake - else: - totalWin=float(totalWin) - for i in xrange(len(winnings)): - if winnings[i]!=0: - winPortion=winnings[i]/totalWin - rakes[i]=totalRake*winPortion -#end def splitRake - -def generateHudCacheData(player_ids, base, category, action_types, allIns, actionTypeByNo - ,winnings, totalWinnings, positions, actionTypes, actionAmounts, antes): - """calculates data for the HUD during import. IMPORTANT: if you change this method make -sure to also change the following storage method and table_viewer.prepare_data if necessary -""" - #print "generateHudCacheData, len(player_ids)=", len(player_ids) - #setup subarrays of the result dictionary. - street0VPI=[] - street0Aggr=[] - street0_3BChance=[] - street0_3BDone=[] - street1Seen=[] - street2Seen=[] - street3Seen=[] - street4Seen=[] - sawShowdown=[] - street1Aggr=[] - street2Aggr=[] - street3Aggr=[] - street4Aggr=[] - otherRaisedStreet1=[] - otherRaisedStreet2=[] - otherRaisedStreet3=[] - otherRaisedStreet4=[] - foldToOtherRaisedStreet1=[] - foldToOtherRaisedStreet2=[] - foldToOtherRaisedStreet3=[] - foldToOtherRaisedStreet4=[] - wonWhenSeenStreet1=[] - - wonAtSD=[] - stealAttemptChance=[] - stealAttempted=[] - hudDataPositions=[] - - street0Calls=[] - street1Calls=[] - street2Calls=[] - street3Calls=[] - street4Calls=[] - street0Bets=[] - street1Bets=[] - street2Bets=[] - street3Bets=[] - street4Bets=[] - #street0Raises=[] - #street1Raises=[] - #street2Raises=[] - #street3Raises=[] - #street4Raises=[] - - # Summary figures for hand table: - result={} - result['playersVpi']=0 - result['playersAtStreet1']=0 - result['playersAtStreet2']=0 - result['playersAtStreet3']=0 - result['playersAtStreet4']=0 - result['playersAtShowdown']=0 - result['street0Raises']=0 - result['street1Raises']=0 - result['street2Raises']=0 - result['street3Raises']=0 - result['street4Raises']=0 - result['street1Pot']=0 - result['street2Pot']=0 - result['street3Pot']=0 - result['street4Pot']=0 - result['showdownPot']=0 - - firstPfRaiseByNo=-1 - firstPfRaiserId=-1 - firstPfRaiserNo=-1 - firstPfCallByNo=-1 - firstPfCallerId=-1 - - for i, action in enumerate(actionTypeByNo[0]): - if action[1] == "bet": - firstPfRaiseByNo = i - firstPfRaiserId = action[0] - for j, pid in enumerate(player_ids): - if pid == firstPfRaiserId: - firstPfRaiserNo = j - break - break - for i, action in enumerate(actionTypeByNo[0]): - if action[1] == "call": - firstPfCallByNo = i - firstPfCallerId = action[0] - break - firstPlayId = firstPfCallerId - if firstPfRaiseByNo <> -1: - if firstPfRaiseByNo < firstPfCallByNo or firstPfCallByNo == -1: - firstPlayId = firstPfRaiserId - - - cutoffId=-1 - buttonId=-1 - sbId=-1 - bbId=-1 - if base=="hold": - for player, pos in enumerate(positions): - if pos == 1: - cutoffId = player_ids[player] - if pos == 0: - buttonId = player_ids[player] - if pos == 'S': - sbId = player_ids[player] - if pos == 'B': - bbId = player_ids[player] - - someoneStole=False - - #run a loop for each player preparing the actual values that will be commited to SQL - for player in xrange(len(player_ids)): - #set default values - myStreet0VPI=False - myStreet0Aggr=False - myStreet0_3BChance=False - myStreet0_3BDone=False - myStreet1Seen=False - myStreet2Seen=False - myStreet3Seen=False - myStreet4Seen=False - mySawShowdown=False - myStreet1Aggr=False - myStreet2Aggr=False - myStreet3Aggr=False - myStreet4Aggr=False - myOtherRaisedStreet1=False - myOtherRaisedStreet2=False - myOtherRaisedStreet3=False - myOtherRaisedStreet4=False - myFoldToOtherRaisedStreet1=False - myFoldToOtherRaisedStreet2=False - myFoldToOtherRaisedStreet3=False - myFoldToOtherRaisedStreet4=False - myWonWhenSeenStreet1=0.0 - myWonAtSD=0.0 - myStealAttemptChance=False - myStealAttempted=False - myStreet0Calls=0 - myStreet1Calls=0 - myStreet2Calls=0 - myStreet3Calls=0 - myStreet4Calls=0 - myStreet0Bets=0 - myStreet1Bets=0 - myStreet2Bets=0 - myStreet3Bets=0 - myStreet4Bets=0 - #myStreet0Raises=0 - #myStreet1Raises=0 - #myStreet2Raises=0 - #myStreet3Raises=0 - #myStreet4Raises=0 - - #calculate VPIP and PFR - street=0 - heroPfRaiseCount=0 - for currentAction in action_types[street][player]: # finally individual actions - if currentAction == "bet": - myStreet0Aggr = True - if currentAction == "bet" or currentAction == "call": - myStreet0VPI = True - - if myStreet0VPI: - result['playersVpi'] += 1 - myStreet0Calls = action_types[street][player].count('call') - myStreet0Bets = action_types[street][player].count('bet') - # street0Raises = action_types[street][player].count('raise') bet count includes raises for now - result['street0Raises'] += myStreet0Bets - - #PF3BChance and PF3B - pfFold=-1 - pfRaise=-1 - if firstPfRaiseByNo != -1: - for i, actionType in enumerate(actionTypeByNo[0]): - if actionType[0] == player_ids[player]: - if actionType[1] == "bet" and pfRaise == -1 and i > firstPfRaiseByNo: - pfRaise = i - if actionType[1] == "fold" and pfFold == -1: - pfFold = i - if pfFold == -1 or pfFold > firstPfRaiseByNo: - myStreet0_3BChance = True - if pfRaise > firstPfRaiseByNo: - myStreet0_3BDone = True - - #steal calculations - if base=="hold": - if len(player_ids)>=3: # no point otherwise # was 5, use 3 to match pokertracker definition - if positions[player]==1: - if firstPfRaiserId==player_ids[player] \ - and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo): - myStealAttempted=True - myStealAttemptChance=True - if firstPlayId==cutoffId or firstPlayId==buttonId or firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1: - myStealAttemptChance=True - if positions[player]==0: - if firstPfRaiserId==player_ids[player] \ - and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo): - myStealAttempted=True - myStealAttemptChance=True - if firstPlayId==buttonId or firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1: - myStealAttemptChance=True - if positions[player]=='S': - if firstPfRaiserId==player_ids[player] \ - and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo): - myStealAttempted=True - myStealAttemptChance=True - if firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1: - myStealAttemptChance=True - if positions[player]=='B': - pass - - if myStealAttempted: - someoneStole=True - - - #calculate saw* values - isAllIn = any(i for i in allIns[0][player]) - if isAllIn or len(action_types[1][player]) > 0: - myStreet1Seen = True - - if not isAllIn: - isAllIn = any(i for i in allIns[1][player]) - if isAllIn or len(action_types[2][player]) > 0: - if all(actiontype != "fold" for actiontype in action_types[1][player]): - myStreet2Seen = True - - if not isAllIn: - isAllAin = any(i for i in allIns[2][player]) - if isAllIn or len(action_types[3][player]) > 0: - if all(actiontype != "fold" for actiontype in action_types[2][player]): - myStreet3Seen = True - - #print "base:", base - if base == "hold": - mySawShowdown = not any(actiontype == "fold" for actiontype in action_types[3][player]) - else: - #print "in else" - if not isAllIn: - isAllIn = any(i for i in allIns[3][player]) - if isAllIn or len(action_types[4][player]) > 0: - #print "in if" - myStreet4Seen = True - - mySawShowdown = not any(actiontype == "fold" for actiontype in action_types[4][player]) - - if myStreet1Seen: - result['playersAtStreet1'] += 1 - if myStreet2Seen: - result['playersAtStreet2'] += 1 - if myStreet3Seen: - result['playersAtStreet3'] += 1 - if myStreet4Seen: - result['playersAtStreet4'] += 1 - if mySawShowdown: - result['playersAtShowdown'] += 1 - - #flop stuff - street = 1 - if myStreet1Seen: - myStreet1Aggr = any(actiontype == "bet" for actiontype in action_types[street][player]) - myStreet1Calls = action_types[street][player].count('call') - myStreet1Bets = action_types[street][player].count('bet') - # street1Raises = action_types[street][player].count('raise') bet count includes raises for now - result['street1Raises'] += myStreet1Bets - - for otherPlayer in xrange(len(player_ids)): - if player == otherPlayer: - pass - else: - for countOther in xrange(len(action_types[street][otherPlayer])): - if action_types[street][otherPlayer][countOther] == "bet": - myOtherRaisedStreet1 = True - for countOtherFold in xrange(len(action_types[street][player])): - if action_types[street][player][countOtherFold] == "fold": - myFoldToOtherRaisedStreet1 = True - - #turn stuff - copy of flop with different vars - street = 2 - if myStreet2Seen: - myStreet2Aggr = any(actiontype == "bet" for actiontype in action_types[street][player]) - myStreet2Calls = action_types[street][player].count('call') - myStreet2Bets = action_types[street][player].count('bet') - # street2Raises = action_types[street][player].count('raise') bet count includes raises for now - result['street2Raises'] += myStreet2Bets - - for otherPlayer in xrange(len(player_ids)): - if player == otherPlayer: - pass - else: - for countOther in xrange(len(action_types[street][otherPlayer])): - if action_types[street][otherPlayer][countOther] == "bet": - myOtherRaisedStreet2 = True - for countOtherFold in xrange(len(action_types[street][player])): - if action_types[street][player][countOtherFold] == "fold": - myFoldToOtherRaisedStreet2 = True - - #river stuff - copy of flop with different vars - street = 3 - if myStreet3Seen: - myStreet3Aggr = any(actiontype == "bet" for actiontype in action_types[street][player]) - myStreet3Calls = action_types[street][player].count('call') - myStreet3Bets = action_types[street][player].count('bet') - # street3Raises = action_types[street][player].count('raise') bet count includes raises for now - result['street3Raises'] += myStreet3Bets - - for otherPlayer in xrange(len(player_ids)): - if player == otherPlayer: - pass - else: - for countOther in xrange(len(action_types[street][otherPlayer])): - if action_types[street][otherPlayer][countOther] == "bet": - myOtherRaisedStreet3 = True - for countOtherFold in xrange(len(action_types[street][player])): - if action_types[street][player][countOtherFold] == "fold": - myFoldToOtherRaisedStreet3 = True - - #stud river stuff - copy of flop with different vars - street = 4 - if myStreet4Seen: - myStreet4Aggr = any(actiontype == "bet" for actiontype in action_types[street][player]) - myStreet4Calls = action_types[street][player].count('call') - myStreet4Bets = action_types[street][player].count('bet') - # street4Raises = action_types[street][player].count('raise') bet count includes raises for now - result['street4Raises'] += myStreet4Bets - - for otherPlayer in xrange(len(player_ids)): - if player == otherPlayer: - pass - else: - for countOther in xrange(len(action_types[street][otherPlayer])): - if action_types[street][otherPlayer][countOther] == "bet": - myOtherRaisedStreet4 = True - for countOtherFold in xrange(len(action_types[street][player])): - if action_types[street][player][countOtherFold] == "fold": - myFoldToOtherRaisedStreet4 = True - - if winnings[player] != 0: - if myStreet1Seen: - myWonWhenSeenStreet1 = winnings[player] / float(totalWinnings) - if mySawShowdown: - myWonAtSD = myWonWhenSeenStreet1 - - #add each value to the appropriate array - street0VPI.append(myStreet0VPI) - street0Aggr.append(myStreet0Aggr) - street0_3BChance.append(myStreet0_3BChance) - street0_3BDone.append(myStreet0_3BDone) - street1Seen.append(myStreet1Seen) - street2Seen.append(myStreet2Seen) - street3Seen.append(myStreet3Seen) - street4Seen.append(myStreet4Seen) - sawShowdown.append(mySawShowdown) - street1Aggr.append(myStreet1Aggr) - street2Aggr.append(myStreet2Aggr) - street3Aggr.append(myStreet3Aggr) - street4Aggr.append(myStreet4Aggr) - otherRaisedStreet1.append(myOtherRaisedStreet1) - otherRaisedStreet2.append(myOtherRaisedStreet2) - otherRaisedStreet3.append(myOtherRaisedStreet3) - otherRaisedStreet4.append(myOtherRaisedStreet4) - foldToOtherRaisedStreet1.append(myFoldToOtherRaisedStreet1) - foldToOtherRaisedStreet2.append(myFoldToOtherRaisedStreet2) - foldToOtherRaisedStreet3.append(myFoldToOtherRaisedStreet3) - foldToOtherRaisedStreet4.append(myFoldToOtherRaisedStreet4) - wonWhenSeenStreet1.append(myWonWhenSeenStreet1) - wonAtSD.append(myWonAtSD) - stealAttemptChance.append(myStealAttemptChance) - stealAttempted.append(myStealAttempted) - if base=="hold": - pos=positions[player] - if pos=='B': - hudDataPositions.append('B') - elif pos=='S': - hudDataPositions.append('S') - elif pos==0: - hudDataPositions.append('D') - elif pos==1: - hudDataPositions.append('C') - elif pos>=2 and pos<=4: - hudDataPositions.append('M') - elif pos>=5 and pos<=8: - hudDataPositions.append('E') - ### RHH Added this elif to handle being a dead hand before the BB (pos==9) - elif pos==9: - hudDataPositions.append('X') - else: - raise FpdbError("invalid position") - elif base=="stud": - #todo: stud positions and steals - pass - - street0Calls.append(myStreet0Calls) - street1Calls.append(myStreet1Calls) - street2Calls.append(myStreet2Calls) - street3Calls.append(myStreet3Calls) - street4Calls.append(myStreet4Calls) - street0Bets.append(myStreet0Bets) - street1Bets.append(myStreet1Bets) - street2Bets.append(myStreet2Bets) - street3Bets.append(myStreet3Bets) - street4Bets.append(myStreet4Bets) - #street0Raises.append(myStreet0Raises) - #street1Raises.append(myStreet1Raises) - #street2Raises.append(myStreet2Raises) - #street3Raises.append(myStreet3Raises) - #street4Raises.append(myStreet4Raises) - - #add each array to the to-be-returned dictionary - result['street0VPI']=street0VPI - result['street0Aggr']=street0Aggr - result['street0_3BChance']=street0_3BChance - result['street0_3BDone']=street0_3BDone - result['street1Seen']=street1Seen - result['street2Seen']=street2Seen - result['street3Seen']=street3Seen - result['street4Seen']=street4Seen - result['sawShowdown']=sawShowdown - - result['street1Aggr']=street1Aggr - result['otherRaisedStreet1']=otherRaisedStreet1 - result['foldToOtherRaisedStreet1']=foldToOtherRaisedStreet1 - result['street2Aggr']=street2Aggr - result['otherRaisedStreet2']=otherRaisedStreet2 - result['foldToOtherRaisedStreet2']=foldToOtherRaisedStreet2 - result['street3Aggr']=street3Aggr - result['otherRaisedStreet3']=otherRaisedStreet3 - result['foldToOtherRaisedStreet3']=foldToOtherRaisedStreet3 - result['street4Aggr']=street4Aggr - result['otherRaisedStreet4']=otherRaisedStreet4 - result['foldToOtherRaisedStreet4']=foldToOtherRaisedStreet4 - result['wonWhenSeenStreet1']=wonWhenSeenStreet1 - result['wonAtSD']=wonAtSD - result['stealAttemptChance']=stealAttemptChance - result['stealAttempted']=stealAttempted - result['street0Calls']=street0Calls - result['street1Calls']=street1Calls - result['street2Calls']=street2Calls - result['street3Calls']=street3Calls - result['street4Calls']=street4Calls - result['street0Bets']=street0Bets - result['street1Bets']=street1Bets - result['street2Bets']=street2Bets - result['street3Bets']=street3Bets - result['street4Bets']=street4Bets - #result['street0Raises']=street0Raises - #result['street1Raises']=street1Raises - #result['street2Raises']=street2Raises - #result['street3Raises']=street3Raises - #result['street4Raises']=street4Raises - - #now the various steal values - foldBbToStealChance=[] - foldedBbToSteal=[] - foldSbToStealChance=[] - foldedSbToSteal=[] - for player in xrange(len(player_ids)): - myFoldBbToStealChance=False - myFoldedBbToSteal=False - myFoldSbToStealChance=False - myFoldedSbToSteal=False - - if base=="hold": - if someoneStole and (positions[player]=='B' or positions[player]=='S') and firstPfRaiserId!=player_ids[player]: - street=0 - for count in xrange(len(action_types[street][player])):#individual actions - if positions[player]=='B': - myFoldBbToStealChance=True - if action_types[street][player][count]=="fold": - myFoldedBbToSteal=True - if positions[player]=='S': - myFoldSbToStealChance=True - if action_types[street][player][count]=="fold": - myFoldedSbToSteal=True - - - foldBbToStealChance.append(myFoldBbToStealChance) - foldedBbToSteal.append(myFoldedBbToSteal) - foldSbToStealChance.append(myFoldSbToStealChance) - foldedSbToSteal.append(myFoldedSbToSteal) - result['foldBbToStealChance']=foldBbToStealChance - result['foldedBbToSteal']=foldedBbToSteal - result['foldSbToStealChance']=foldSbToStealChance - result['foldedSbToSteal']=foldedSbToSteal - - #now CB - street1CBChance=[] - street1CBDone=[] - didStreet1CB=[] - for player in xrange(len(player_ids)): - myStreet1CBChance=False - myStreet1CBDone=False - - if street0VPI[player]: - myStreet1CBChance=True - if street1Aggr[player]: - myStreet1CBDone=True - didStreet1CB.append(player_ids[player]) - - street1CBChance.append(myStreet1CBChance) - street1CBDone.append(myStreet1CBDone) - result['street1CBChance']=street1CBChance - result['street1CBDone']=street1CBDone - - #now 2B - street2CBChance=[] - street2CBDone=[] - didStreet2CB=[] - for player in xrange(len(player_ids)): - myStreet2CBChance=False - myStreet2CBDone=False - - if street1CBDone[player]: - myStreet2CBChance=True - if street2Aggr[player]: - myStreet2CBDone=True - didStreet2CB.append(player_ids[player]) - - street2CBChance.append(myStreet2CBChance) - street2CBDone.append(myStreet2CBDone) - result['street2CBChance']=street2CBChance - result['street2CBDone']=street2CBDone - - #now 3B - street3CBChance=[] - street3CBDone=[] - didStreet3CB=[] - for player in xrange(len(player_ids)): - myStreet3CBChance=False - myStreet3CBDone=False - - if street2CBDone[player]: - myStreet3CBChance=True - if street3Aggr[player]: - myStreet3CBDone=True - didStreet3CB.append(player_ids[player]) - - street3CBChance.append(myStreet3CBChance) - street3CBDone.append(myStreet3CBDone) - result['street3CBChance']=street3CBChance - result['street3CBDone']=street3CBDone - - #and 4B - street4CBChance=[] - street4CBDone=[] - didStreet4CB=[] - for player in xrange(len(player_ids)): - myStreet4CBChance=False - myStreet4CBDone=False - - if street3CBDone[player]: - myStreet4CBChance=True - if street4Aggr[player]: - myStreet4CBDone=True - didStreet4CB.append(player_ids[player]) - - street4CBChance.append(myStreet4CBChance) - street4CBDone.append(myStreet4CBDone) - result['street4CBChance']=street4CBChance - result['street4CBDone']=street4CBDone - - - result['position']=hudDataPositions - - foldToStreet1CBChance=[] - foldToStreet1CBDone=[] - foldToStreet2CBChance=[] - foldToStreet2CBDone=[] - foldToStreet3CBChance=[] - foldToStreet3CBDone=[] - foldToStreet4CBChance=[] - foldToStreet4CBDone=[] - - for player in xrange(len(player_ids)): - myFoldToStreet1CBChance=False - myFoldToStreet1CBDone=False - foldToStreet1CBChance.append(myFoldToStreet1CBChance) - foldToStreet1CBDone.append(myFoldToStreet1CBDone) - - myFoldToStreet2CBChance=False - myFoldToStreet2CBDone=False - foldToStreet2CBChance.append(myFoldToStreet2CBChance) - foldToStreet2CBDone.append(myFoldToStreet2CBDone) - - myFoldToStreet3CBChance=False - myFoldToStreet3CBDone=False - foldToStreet3CBChance.append(myFoldToStreet3CBChance) - foldToStreet3CBDone.append(myFoldToStreet3CBDone) - - myFoldToStreet4CBChance=False - myFoldToStreet4CBDone=False - foldToStreet4CBChance.append(myFoldToStreet4CBChance) - foldToStreet4CBDone.append(myFoldToStreet4CBDone) - - if len(didStreet1CB)>=1: - generateFoldToCB(1, player_ids, didStreet1CB, street1CBDone, foldToStreet1CBChance, foldToStreet1CBDone, actionTypeByNo) - - if len(didStreet2CB)>=1: - generateFoldToCB(2, player_ids, didStreet2CB, street2CBDone, foldToStreet2CBChance, foldToStreet2CBDone, actionTypeByNo) - - if len(didStreet3CB)>=1: - generateFoldToCB(3, player_ids, didStreet3CB, street3CBDone, foldToStreet3CBChance, foldToStreet3CBDone, actionTypeByNo) - - if len(didStreet4CB)>=1: - generateFoldToCB(4, player_ids, didStreet4CB, street4CBDone, foldToStreet4CBChance, foldToStreet4CBDone, actionTypeByNo) - - result['foldToStreet1CBChance']=foldToStreet1CBChance - result['foldToStreet1CBDone']=foldToStreet1CBDone - result['foldToStreet2CBChance']=foldToStreet2CBChance - result['foldToStreet2CBDone']=foldToStreet2CBDone - result['foldToStreet3CBChance']=foldToStreet3CBChance - result['foldToStreet3CBDone']=foldToStreet3CBDone - result['foldToStreet4CBChance']=foldToStreet4CBChance - result['foldToStreet4CBDone']=foldToStreet4CBDone - - - totalProfit=[] - - street1CheckCallRaiseChance=[] - street1CheckCallRaiseDone=[] - street2CheckCallRaiseChance=[] - street2CheckCallRaiseDone=[] - street3CheckCallRaiseChance=[] - street3CheckCallRaiseDone=[] - street4CheckCallRaiseChance=[] - street4CheckCallRaiseDone=[] - #print "b4 totprof calc, len(playerIds)=", len(player_ids) - for pl in xrange(len(player_ids)): - #print "pl=", pl - myTotalProfit=winnings[pl] # still need to deduct other costs - if antes: - myTotalProfit=winnings[pl] - antes[pl] - for i in xrange(len(actionTypes)): #iterate through streets - #for j in xrange(len(actionTypes[i])): #iterate through names (using pl loop above) - for k in xrange(len(actionTypes[i][pl])): #iterate through individual actions of that player on that street - myTotalProfit -= actionAmounts[i][pl][k] - - myStreet1CheckCallRaiseChance=False - myStreet1CheckCallRaiseDone=False - myStreet2CheckCallRaiseChance=False - myStreet2CheckCallRaiseDone=False - myStreet3CheckCallRaiseChance=False - myStreet3CheckCallRaiseDone=False - myStreet4CheckCallRaiseChance=False - myStreet4CheckCallRaiseDone=False - - #print "myTotalProfit=", myTotalProfit - totalProfit.append(myTotalProfit) - #print "totalProfit[]=", totalProfit - - street1CheckCallRaiseChance.append(myStreet1CheckCallRaiseChance) - street1CheckCallRaiseDone.append(myStreet1CheckCallRaiseDone) - street2CheckCallRaiseChance.append(myStreet2CheckCallRaiseChance) - street2CheckCallRaiseDone.append(myStreet2CheckCallRaiseDone) - street3CheckCallRaiseChance.append(myStreet3CheckCallRaiseChance) - street3CheckCallRaiseDone.append(myStreet3CheckCallRaiseDone) - street4CheckCallRaiseChance.append(myStreet4CheckCallRaiseChance) - street4CheckCallRaiseDone.append(myStreet4CheckCallRaiseDone) - - result['totalProfit']=totalProfit - #print "res[totalProfit]=", result['totalProfit'] - - result['street1CheckCallRaiseChance']=street1CheckCallRaiseChance - result['street1CheckCallRaiseDone']=street1CheckCallRaiseDone - result['street2CheckCallRaiseChance']=street2CheckCallRaiseChance - result['street2CheckCallRaiseDone']=street2CheckCallRaiseDone - result['street3CheckCallRaiseChance']=street3CheckCallRaiseChance - result['street3CheckCallRaiseDone']=street3CheckCallRaiseDone - result['street4CheckCallRaiseChance']=street4CheckCallRaiseChance - result['street4CheckCallRaiseDone']=street4CheckCallRaiseDone - return result -#end def generateHudCacheData - -def generateFoldToCB(street, playerIDs, didStreetCB, streetCBDone, foldToStreetCBChance, foldToStreetCBDone, actionTypeByNo): - """fills the passed foldToStreetCB* arrays appropriately depending on the given street""" - #print "beginning of generateFoldToCB, street:", street, "len(actionTypeByNo):", len(actionTypeByNo) - #print "len(actionTypeByNo[street]):",len(actionTypeByNo[street]) - firstCBReaction=0 - for action in xrange(len(actionTypeByNo[street])): - if actionTypeByNo[street][action][1]=="bet": - for player in didStreetCB: - if player==actionTypeByNo[street][action][0] and firstCBReaction==0: - firstCBReaction=action+1 - break - - for action in actionTypeByNo[street][firstCBReaction:]: - for player in xrange(len(playerIDs)): - if playerIDs[player]==action[0]: - foldToStreetCBChance[player]=True - if action[1]=="fold": - foldToStreetCBDone[player]=True -#end def generateFoldToCB From 0898ddf8a15700f01cdf43f3ac8d73207daeefcd Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 22 Dec 2009 17:20:07 +0800 Subject: [PATCH 10/36] [NEWIMPORT] HandsPlayers.startCards Dodgy function just to get things kinda working again. --- pyfpdb/Card.py | 21 ++++++++++++++++++++- pyfpdb/DerivedStats.py | 4 ++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/pyfpdb/Card.py b/pyfpdb/Card.py index 287a0f6a..8639fd35 100755 --- a/pyfpdb/Card.py +++ b/pyfpdb/Card.py @@ -16,6 +16,25 @@ #agpl-3.0.txt in the docs folder of the package. +# From fpdb_simple +card_map = { "0": 0, "2": 2, "3" : 3, "4" : 4, "5" : 5, "6" : 6, "7" : 7, "8" : 8, + "9" : 9, "T" : 10, "J" : 11, "Q" : 12, "K" : 13, "A" : 14} + +# FIXME: the following is a workaround until switching to newimport. +# This should be moved into DerivedStats +# I'd also like to change HandsPlayers.startCards to a different datatype +# so we can 'trivially' add different start card classifications + +def calcStartCards(hand, player): + if hand.gametype['category'] == 'holdem': + hcs = hand.join_holecards(player, asList=True) + #print "DEBUG: hcs: %s" % hcs + value1 = card_map[hcs[0][0]] + value2 = card_map[hcs[1][0]] + return twoStartCards(value1, hcs[0][1], value2, hcs[1][1]) + else: + # FIXME: Only do startCards value for holdem at the moment + return 0 def twoStartCards(value1, suit1, value2, suit2): @@ -127,4 +146,4 @@ if __name__ == '__main__': (i, valueSuitFromCard(i), i+13, valueSuitFromCard(i+13), i+26, valueSuitFromCard(i+26), i+39, valueSuitFromCard(i+39)) print - print encodeCard('7c') \ No newline at end of file + print encodeCard('7c') diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index dbd655a3..b65b0d05 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -47,6 +47,7 @@ class DerivedStats(): self.handsplayers[player[1]]['wonWhenSeenStreet1'] = 0.0 self.handsplayers[player[1]]['sawShowdown'] = False self.handsplayers[player[1]]['wonAtSD'] = 0.0 + self.handsplayers[player[1]]['startCards'] = 0 for i in range(5): self.handsplayers[player[1]]['street%dCalls' % i] = 0 self.handsplayers[player[1]]['street%dBets' % i] = 0 @@ -57,7 +58,6 @@ class DerivedStats(): #FIXME - Everything below this point is incomplete. self.handsplayers[player[1]]['position'] = 2 self.handsplayers[player[1]]['tourneyTypeId'] = 1 - self.handsplayers[player[1]]['startCards'] = 0 self.handsplayers[player[1]]['street0_3BChance'] = False self.handsplayers[player[1]]['street0_3BDone'] = False self.handsplayers[player[1]]['stealAttemptChance'] = False @@ -172,7 +172,7 @@ class DerivedStats(): # self.handsplayers[player[1]]['card%s' % i] = Card.encodeCard(card) for i, card in enumerate(hcs[:7]): self.handsplayers[player[1]]['card%s' % (i+1)] = Card.encodeCard(card) - + self.handsplayers[player[1]]['startCards'] = Card.calcStartCards(hand, player[1]) # position, #Stud 3rd street card test From ae55a89d7f16ee918c39372127ccb25de1ec31b7 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 22 Dec 2009 20:22:05 +0800 Subject: [PATCH 11/36] Remove reference to fpdb_simple --- pyfpdb/Tables.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyfpdb/Tables.py b/pyfpdb/Tables.py index ea5dfc4c..75bc574c 100755 --- a/pyfpdb/Tables.py +++ b/pyfpdb/Tables.py @@ -39,7 +39,6 @@ if os.name == 'nt': # FreePokerTools modules import Configuration -from fpdb_simple import LOCALE_ENCODING # Each TableWindow object must have the following attributes correctly populated: # tw.name = the table name from the title bar, which must to match the table name @@ -238,7 +237,7 @@ def discover_nt_by_name(c, tablename): try: # maybe it's better to make global titles[hwnd] decoding? # this can blow up in XP on some windows, eg firefox displaying http://docs.python.org/tutorial/classes.html - if not tablename.lower() in titles[hwnd].decode(LOCALE_ENCODING).lower(): + if not tablename.lower() in titles[hwnd].decode(Configuration.LOCALE_ENCODING).lower(): continue except: continue From 4d8d678d644a1cf7b439c5d4dc2ae8986a6f4656 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 22 Dec 2009 21:40:37 +0800 Subject: [PATCH 12/36] [NEWIMPORT] Make seek into autoimport function Now that the legacy import path is gone, enable the index for HHC --- pyfpdb/HandHistoryConverter.py | 2 +- pyfpdb/fpdb_import.py | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index a18797df..9d4807a2 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -65,7 +65,7 @@ follow : whether to tail -f the input""" log.info("HandHistory init - %s subclass, in_path '%s'; out_path '%s'" % (self.sitename, in_path, out_path) ) - self.index = 0 + self.index = index self.starsArchive = starsArchive self.in_path = in_path diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index a7a21831..2decf6b6 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -427,7 +427,12 @@ class Importer: mod = __import__(filter) obj = getattr(mod, filter_name, None) if callable(obj): - hhc = obj(in_path = file, out_path = out_path, index = 0, starsArchive = self.settings['starsArchive']) # Index into file 0 until changeover + idx = 0 + if file in self.pos_in_file: + idx = self.pos_in_file[file] + else: + self.pos_in_file[file] = 0 + hhc = obj(in_path = file, out_path = out_path, index = idx, starsArchive = self.settings['starsArchive']) # Index into file 0 until changeover if hhc.getStatus() and self.NEWIMPORT == True: #This code doesn't do anything yet handlist = hhc.getProcessedHands() From 284693e95e820e0e8e41428f82f6d93784ec23a7 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 22 Dec 2009 22:02:36 +0800 Subject: [PATCH 13/36] [NEWIMPORT] Rebuild hudcache after hand is committed --- pyfpdb/fpdb_import.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 2decf6b6..a2a466de 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -449,6 +449,7 @@ class Importer: else: log.error("Hand processed but empty") self.database.commit() + self.database.rebuild_hudcache() #pipe the Hands.id out to the HUD for hid in to_hud: From d8a87b92d4101ca406ab0866964737e2d3baba30 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 22 Dec 2009 22:15:27 +0800 Subject: [PATCH 14/36] [NEWIMPORT] Make hudcache rebuild only happen no call to hud --- pyfpdb/fpdb_import.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index a2a466de..24f16000 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -449,7 +449,8 @@ class Importer: else: log.error("Hand processed but empty") self.database.commit() - self.database.rebuild_hudcache() + if self.callHud: + self.database.rebuild_hudcache() #pipe the Hands.id out to the HUD for hid in to_hud: From 355225fc258e26b34e078e8baec5143267f9a0e5 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 22 Dec 2009 23:03:05 +0800 Subject: [PATCH 15/36] [NEWIMPORT] Remove test_fpdb_simple --- pyfpdb/test_fpdb_simple.py | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100755 pyfpdb/test_fpdb_simple.py diff --git a/pyfpdb/test_fpdb_simple.py b/pyfpdb/test_fpdb_simple.py deleted file mode 100755 index 3d9615cb..00000000 --- a/pyfpdb/test_fpdb_simple.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- -import fpdb_simple -import datetime -import py - -def checkDateParse(header, site, result): - assert fpdb_simple.parseHandStartTime(header, site) == result - -def testPokerStarsHHDate(): - tuples = ( - ("PokerStars Game #21969660557: Hold'em No Limit ($0.50/$1.00) - 2008/11/12 10:00:48 CET [2008/11/12 4:00:48 ET]", "ps", - datetime.datetime(2008,11,12,15,00,48)), - ("PokerStars Game #21969660557: Hold'em No Limit ($0.50/$1.00) - 2008/08/17 - 01:14:43 (ET)", "ps", - datetime.datetime(2008,8,17,6,14,43)), - ("PokerStars Game #21969660557: Hold'em No Limit ($0.50/$1.00) - 2008/09/07 06:23:14 ET", "ps", - datetime.datetime(2008,9,7,11,23,14)) - ) - -#def testTableDetection(): -# result = Tables.clean_title("French (deep)") -# assert result == "French" -# result = Tables.clean_title("French (deep) - $0.25/$0.50 - No Limit Hold'em - Logged In As xxxx") -# assert result == "French" -# -# for (header, site, result) in tuples: -# yield checkDateParse, header, site, result - From 6e9153c25c529a608020732bd329376f5692348f Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 23 Dec 2009 13:30:12 +0800 Subject: [PATCH 16/36] [NEWIMPORT] Copy Grigorij's code from Alchemy Copied some of Grigorij's code verbatim for calculating additional stats, still needs adapting. Also reorder some functions so the corresponding files are more mergeable in future. --- pyfpdb/DerivedStats.py | 112 +++++++++++++++++++++++++++++++++++------ 1 file changed, 96 insertions(+), 16 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index b65b0d05..c87e714a 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -262,13 +262,58 @@ class DerivedStats(): for (i, street) in enumerate(hand.actionStreets[1:]): self.hands['street%dRaises' % i] = len(filter( lambda action: action[1] in ('raises','bets'), hand.actions[street])) - def calcCBets(self, hand): - # Continuation Bet chance, action: - # Had the last bet (initiative) on previous street, got called, close street action - # Then no bets before the player with initiatives first action on current street - # ie. if player on street-1 had initiative - # and no donkbets occurred + def calcSteals(self, hand): + """Fills stealAttempt(Chance|ed, fold(Bb|Sb)ToSteal(Chance|) + Steal attemp - open raise on positions 2 1 0 S - i.e. MP3, CO, BU, SB + Fold to steal - folding blind after steal attemp wo any other callers or raisers + """ + if self.gametype_dict['base'] != 'hold': + # FIXME: add support for other games //grindi + return + steal_attemp = False + for action in hand.actions[hand.actionStreets[1]]: + hp, act = self.handplayers_by_name[action[0]], action[1] + #print action[0], hp.position, steal_attemp, act + if hp.position == 'B': + hp.foldBbToStealChance = steal_attemp + hp.foldBbToSteal = hp.foldBbToStealChance and act == 'folds' + break + elif hp.position == 'S': + hp.foldSbToStealChance = steal_attemp + hp.foldSbToSteal = hp.foldSbToStealChance and act == 'folds' + + if steal_attemp and act != 'folds': + break + + if hp.position in ('2', '1', '0', 'S') and not steal_attemp: + hp.stealAttemptChance = True + if act in ('bets', 'raises'): + hp.stealAttempted = True + steal_attemp = True + + def calc34BetStreet0(self, hand): + """Fills street0_(3|4)B(Chance|Done), other(3|4)BStreet0""" + bet_level = 1 # bet_level after 3-bet is equal to 3 + for action in hand.actions[hand.actionStreets[1]]: + # FIXME: fill other(3|4)BStreet0 - i have no idea what does it mean + hp, aggr = self.handplayers_by_name[action[0]], action[1] in ('raises', 'bets') + hp.street0_3BChance = bet_level == 2 + hp.street0_4BChance = bet_level == 3 + hp.street0_3BDone = aggr and (hp.street0_3BChance) + hp.street0_4BDone = aggr and (hp.street0_4BChance) + if aggr: + bet_level += 1 + + + def calcCBets(self, hand): + """Fill streetXCBChance, streetXCBDone, foldToStreetXCBDone, foldToStreetXCBChance + + Continuation Bet chance, action: + Had the last bet (initiative) on previous street, got called, close street action + Then no bets before the player with initiatives first action on current street + ie. if player on street-1 had initiative and no donkbets occurred + """ # XXX: enumerate(list, start=x) is python 2.6 syntax; 'start' # came there #for i, street in enumerate(hand.actionStreets[2:], start=1): @@ -280,6 +325,29 @@ class DerivedStats(): if chance == True: self.handsplayers[name]['street%dCBDone' % (i+1)] = self.betStreet(hand.actionStreets[i+2], name) + def calcCheckCallRaise(self, hand): + """Fill streetXCheckCallRaiseChance, streetXCheckCallRaiseDone + + streetXCheckCallRaiseChance = got raise/bet after check + streetXCheckCallRaiseDone = checked. got raise/bet. didn't fold + + CG: CheckCall would be a much better name for this. + """ + for i, street in enumerate(hand.actionStreets[2:], start=1): + actions = hand.actions[hand.actionStreets[i]] + checkers = set() + initial_raiser = None + for action in actions: + pname, act = action[0], action[1] + if act in ('bets', 'raises') and initial_raiser is None: + initial_raiser = pname + elif act == 'check' and initial_raiser is None: + checkers.add(pname) + elif initial_raiser is not None and pname in checkers: + hp = self.handplayers_by_name[pname] + setattr(hp, 'street%dCheckCallRaiseChance' % i, True) + setattr(hp, 'street%dCheckCallRaiseDone' % i, act!='folds') + def seen(self, hand, i): pas = set() for act in hand.actions[hand.actionStreets[i+1]]: @@ -333,6 +401,27 @@ class DerivedStats(): players.add(action[0]) return players + + def firstsBetOrRaiser(self, actions): + """Returns player name that placed the first bet or raise. + + None if there were no bets or raises on that street + """ + for act in actions: + if act[1] in ('bets', 'raises'): + return act[0] + return None + + def lastBetOrRaiser(self, street): + """Returns player name that placed the last bet or raise for that street. + None if there were no bets or raises on that street""" + lastbet = None + for act in self.hand.actions[street]: + if act[1] in ('bets', 'raises'): + lastbet = act[0] + return lastbet + + def noBetsBefore(self, street, player): """Returns true if there were no bets before the specified players turn, false otherwise""" betOrRaise = False @@ -345,6 +434,7 @@ class DerivedStats(): break return betOrRaise + def betStreet(self, street, player): """Returns true if player bet/raised the street as their first action""" betOrRaise = False @@ -353,14 +443,4 @@ class DerivedStats(): betOrRaise = True else: break - return betOrRaise - - def lastBetOrRaiser(self, street): - """Returns player name that placed the last bet or raise for that street. - None if there were no bets or raises on that street""" - lastbet = None - for act in self.hand.actions[street]: - if act[1] in ('bets', 'raises'): - lastbet = act[0] - return lastbet From a2d0657b3a2d3c2069a1f135d13a969f18852868 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 23 Dec 2009 13:56:18 +0800 Subject: [PATCH 17/36] [NEWIMPORT] Remove unused functions Move old HudCache update over in preparation for fixing --- pyfpdb/Database.py | 679 ++++++++------------------------------------- 1 file changed, 119 insertions(+), 560 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 412036ab..9614084f 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1490,532 +1490,11 @@ class Database: c = self.get_cursor() c.executemany(q, inserts) - def storeHudCacheNew(self, gid, pid, hc): - q = """INSERT INTO HudCache ( - gametypeId, - playerId - ) - VALUES ( - %s, %s - )""" - -# gametypeId, -# playerId, -# activeSeats, -# position, -# tourneyTypeId, -# styleKey, -# HDs, -# street0VPI, -# street0Aggr, -# street0_3BChance, -# street0_3BDone, -# street1Seen, -# street2Seen, -# street3Seen, -# street4Seen, -# sawShowdown, -# street1Aggr, -# street2Aggr, -# street3Aggr, -# street4Aggr, -# otherRaisedStreet1, -# otherRaisedStreet2, -# otherRaisedStreet3, -# otherRaisedStreet4, -# foldToOtherRaisedStreet1, -# foldToOtherRaisedStreet2, -# foldToOtherRaisedStreet3, -# foldToOtherRaisedStreet4, -# wonWhenSeenStreet1, -# wonAtSD, -# stealAttemptChance, -# stealAttempted, -# foldBbToStealChance, -# foldedBbToSteal, -# foldSbToStealChance, -# foldedSbToSteal, -# street1CBChance, -# street1CBDone, -# street2CBChance, -# street2CBDone, -# street3CBChance, -# street3CBDone, -# street4CBChance, -# street4CBDone, -# foldToStreet1CBChance, -# foldToStreet1CBDone, -# foldToStreet2CBChance, -# foldToStreet2CBDone, -# foldToStreet3CBChance, -# foldToStreet3CBDone, -# foldToStreet4CBChance, -# foldToStreet4CBDone, -# totalProfit, -# street1CheckCallRaiseChance, -# street1CheckCallRaiseDone, -# street2CheckCallRaiseChance, -# street2CheckCallRaiseDone, -# street3CheckCallRaiseChance, -# street3CheckCallRaiseDone, -# street4CheckCallRaiseChance, -# street4CheckCallRaiseDone) - - q = q.replace('%s', self.sql.query['placeholder']) - - self.cursor.execute(q, ( - gid, - pid - )) - -# gametypeId, -# playerId, -# activeSeats, -# position, -# tourneyTypeId, -# styleKey, -# HDs, -# street0VPI, -# street0Aggr, -# street0_3BChance, -# street0_3BDone, -# street1Seen, -# street2Seen, -# street3Seen, -# street4Seen, -# sawShowdown, -# street1Aggr, -# street2Aggr, -# street3Aggr, -# street4Aggr, -# otherRaisedStreet1, -# otherRaisedStreet2, -# otherRaisedStreet3, -# otherRaisedStreet4, -# foldToOtherRaisedStreet1, -# foldToOtherRaisedStreet2, -# foldToOtherRaisedStreet3, -# foldToOtherRaisedStreet4, -# wonWhenSeenStreet1, -# wonAtSD, -# stealAttemptChance, -# stealAttempted, -# foldBbToStealChance, -# foldedBbToSteal, -# foldSbToStealChance, -# foldedSbToSteal, -# street1CBChance, -# street1CBDone, -# street2CBChance, -# street2CBDone, -# street3CBChance, -# street3CBDone, -# street4CBChance, -# street4CBDone, -# foldToStreet1CBChance, -# foldToStreet1CBDone, -# foldToStreet2CBChance, -# foldToStreet2CBDone, -# foldToStreet3CBChance, -# foldToStreet3CBDone, -# foldToStreet4CBChance, -# foldToStreet4CBDone, -# totalProfit, -# street1CheckCallRaiseChance, -# street1CheckCallRaiseDone, -# street2CheckCallRaiseChance, -# street2CheckCallRaiseDone, -# street3CheckCallRaiseChance, -# street3CheckCallRaiseDone, -# street4CheckCallRaiseChance, -# street4CheckCallRaiseDone) - - def isDuplicate(self, gametypeID, siteHandNo): - dup = False - c = self.get_cursor() - c.execute(self.sql.query['isAlreadyInDB'], (gametypeID, siteHandNo)) - result = c.fetchall() - if len(result) > 0: - dup = True - return dup - - def getGameTypeId(self, siteid, game): - c = self.get_cursor() - #FIXME: Fixed for NL at the moment - c.execute(self.sql.query['getGametypeNL'], (siteid, game['type'], game['category'], game['limitType'], - int(Decimal(game['sb'])*100), int(Decimal(game['bb'])*100))) - tmp = c.fetchone() - if (tmp == None): - hilo = "h" - if game['category'] in ['studhilo', 'omahahilo']: - hilo = "s" - elif game['category'] in ['razz','27_3draw','badugi']: - hilo = "l" - tmp = self.insertGameTypes( (siteid, game['type'], game['base'], game['category'], game['limitType'], hilo, - int(Decimal(game['sb'])*100), int(Decimal(game['bb'])*100), 0, 0) ) - return tmp[0] - - def getSqlPlayerIDs(self, pnames, siteid): - result = {} - if(self.pcache == None): - self.pcache = LambdaDict(lambda key:self.insertPlayer(key, siteid)) - - for player in pnames: - result[player] = self.pcache[player] - # NOTE: Using the LambdaDict does the same thing as: - #if player in self.pcache: - # #print "DEBUG: cachehit" - # pass - #else: - # self.pcache[player] = self.insertPlayer(player, siteid) - #result[player] = self.pcache[player] - - return result - - def insertPlayer(self, name, site_id): - result = None - c = self.get_cursor() - q = "SELECT name, id FROM Players WHERE siteid=%s and name=%s" - q = q.replace('%s', self.sql.query['placeholder']) - - #NOTE/FIXME?: MySQL has ON DUPLICATE KEY UPDATE - #Usage: - # INSERT INTO `tags` (`tag`, `count`) - # VALUES ($tag, 1) - # ON DUPLICATE KEY UPDATE `count`=`count`+1; - - - #print "DEBUG: name: %s site: %s" %(name, site_id) - - c.execute (q, (site_id, name)) - - tmp = c.fetchone() - if (tmp == None): #new player - c.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)".replace('%s',self.sql.query['placeholder']) - ,(name, site_id)) - #Get last id might be faster here. - #c.execute ("SELECT id FROM Players WHERE name=%s", (name,)) - result = self.get_last_insert_id(c) - else: - result = tmp[1] - return result - - def insertGameTypes(self, row): - c = self.get_cursor() - c.execute( self.sql.query['insertGameTypes'], row ) - return [self.get_last_insert_id(c)] - - - -################################# -# Finish of NEWIMPORT CODE -################################# - - - - def storeHands(self, backend, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats, hudCache - ,board_values, board_suits): - - cards = [Card.cardFromValueSuit(v,s) for v,s in zip(board_values,board_suits)] - #stores into table hands: - try: - c = self.get_cursor() - c.execute ("""INSERT INTO Hands - (siteHandNo, gametypeId, handStart, seats, tableName, importTime, maxSeats - ,boardcard1,boardcard2,boardcard3,boardcard4,boardcard5 - ,playersVpi, playersAtStreet1, playersAtStreet2 - ,playersAtStreet3, playersAtStreet4, playersAtShowdown - ,street0Raises, street1Raises, street2Raises - ,street3Raises, street4Raises, street1Pot - ,street2Pot, street3Pot, street4Pot - ,showdownPot - ) - VALUES - (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) - """.replace('%s', self.sql.query['placeholder']) - , (site_hand_no, gametype_id, hand_start_time, len(names), tableName, datetime.today(), maxSeats - ,cards[0], cards[1], cards[2], cards[3], cards[4] - ,hudCache['playersVpi'], hudCache['playersAtStreet1'], hudCache['playersAtStreet2'] - ,hudCache['playersAtStreet3'], hudCache['playersAtStreet4'], hudCache['playersAtShowdown'] - ,hudCache['street0Raises'], hudCache['street1Raises'], hudCache['street2Raises'] - ,hudCache['street3Raises'], hudCache['street4Raises'], hudCache['street1Pot'] - ,hudCache['street2Pot'], hudCache['street3Pot'], hudCache['street4Pot'] - ,hudCache['showdownPot'] - )) - ret = self.get_last_insert_id(c) - except: - ret = -1 - raise FpdbError( "storeHands error: " + str(sys.exc_value) ) - - return ret - #end def storeHands - - def store_hands_players_holdem_omaha(self, backend, category, hands_id, player_ids, start_cashes - ,positions, card_values, card_suits, winnings, rakes, seatNos, hudCache): - result=[] - - # postgres (and others?) needs the booleans converted to ints before saving: - # (or we could just save them as boolean ... but then we can't sum them so easily in sql ???) - # NO - storing booleans for now so don't need this - #hudCacheInt = {} - #for k,v in hudCache.iteritems(): - # if k in ('wonWhenSeenStreet1', 'wonAtSD', 'totalProfit'): - # hudCacheInt[k] = v - # else: - # hudCacheInt[k] = map(lambda x: 1 if x else 0, v) - - try: - inserts = [] - for i in xrange(len(player_ids)): - card1 = Card.cardFromValueSuit(card_values[i][0], card_suits[i][0]) - card2 = Card.cardFromValueSuit(card_values[i][1], card_suits[i][1]) - - if (category=="holdem"): - startCards = Card.twoStartCards(card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1]) - card3 = None - card4 = None - elif (category=="omahahi" or category=="omahahilo"): - startCards = Card.fourStartCards(card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1] - ,card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3]) - card3 = Card.cardFromValueSuit(card_values[i][2], card_suits[i][2]) - card4 = Card.cardFromValueSuit(card_values[i][3], card_suits[i][3]) - else: - raise FpdbError("invalid category") - - inserts.append( ( - hands_id, player_ids[i], start_cashes[i], positions[i], 1, # tourneytypeid - needed for hudcache - card1, card2, card3, card4, startCards, - winnings[i], rakes[i], seatNos[i], hudCache['totalProfit'][i], - hudCache['street0VPI'][i], hudCache['street0Aggr'][i], - hudCache['street0_3BChance'][i], hudCache['street0_3BDone'][i], - hudCache['street1Seen'][i], hudCache['street2Seen'][i], hudCache['street3Seen'][i], - hudCache['street4Seen'][i], hudCache['sawShowdown'][i], - hudCache['street1Aggr'][i], hudCache['street2Aggr'][i], hudCache['street3Aggr'][i], hudCache['street4Aggr'][i], - hudCache['otherRaisedStreet1'][i], hudCache['otherRaisedStreet2'][i], - hudCache['otherRaisedStreet3'][i], hudCache['otherRaisedStreet4'][i], - hudCache['foldToOtherRaisedStreet1'][i], hudCache['foldToOtherRaisedStreet2'][i], - hudCache['foldToOtherRaisedStreet3'][i], hudCache['foldToOtherRaisedStreet4'][i], - hudCache['wonWhenSeenStreet1'][i], hudCache['wonAtSD'][i], - hudCache['stealAttemptChance'][i], hudCache['stealAttempted'][i], hudCache['foldBbToStealChance'][i], - hudCache['foldedBbToSteal'][i], hudCache['foldSbToStealChance'][i], hudCache['foldedSbToSteal'][i], - hudCache['street1CBChance'][i], hudCache['street1CBDone'][i], hudCache['street2CBChance'][i], hudCache['street2CBDone'][i], - hudCache['street3CBChance'][i], hudCache['street3CBDone'][i], hudCache['street4CBChance'][i], hudCache['street4CBDone'][i], - hudCache['foldToStreet1CBChance'][i], hudCache['foldToStreet1CBDone'][i], - hudCache['foldToStreet2CBChance'][i], hudCache['foldToStreet2CBDone'][i], - hudCache['foldToStreet3CBChance'][i], hudCache['foldToStreet3CBDone'][i], - hudCache['foldToStreet4CBChance'][i], hudCache['foldToStreet4CBDone'][i], - hudCache['street1CheckCallRaiseChance'][i], hudCache['street1CheckCallRaiseDone'][i], - hudCache['street2CheckCallRaiseChance'][i], hudCache['street2CheckCallRaiseDone'][i], - hudCache['street3CheckCallRaiseChance'][i], hudCache['street3CheckCallRaiseDone'][i], - hudCache['street4CheckCallRaiseChance'][i], hudCache['street4CheckCallRaiseDone'][i], - hudCache['street0Calls'][i], hudCache['street1Calls'][i], hudCache['street2Calls'][i], hudCache['street3Calls'][i], hudCache['street4Calls'][i], - hudCache['street0Bets'][i], hudCache['street1Bets'][i], hudCache['street2Bets'][i], hudCache['street3Bets'][i], hudCache['street4Bets'][i] - ) ) - c = self.get_cursor() - c.executemany (""" - INSERT INTO HandsPlayers - (handId, playerId, startCash, position, tourneyTypeId, - card1, card2, card3, card4, startCards, winnings, rake, seatNo, totalProfit, - street0VPI, street0Aggr, street0_3BChance, street0_3BDone, - street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown, - street1Aggr, street2Aggr, street3Aggr, street4Aggr, - otherRaisedStreet1, otherRaisedStreet2, otherRaisedStreet3, otherRaisedStreet4, - foldToOtherRaisedStreet1, foldToOtherRaisedStreet2, foldToOtherRaisedStreet3, foldToOtherRaisedStreet4, - wonWhenSeenStreet1, wonAtSD, - stealAttemptChance, stealAttempted, foldBbToStealChance, foldedBbToSteal, foldSbToStealChance, foldedSbToSteal, - street1CBChance, street1CBDone, street2CBChance, street2CBDone, - street3CBChance, street3CBDone, street4CBChance, street4CBDone, - foldToStreet1CBChance, foldToStreet1CBDone, foldToStreet2CBChance, foldToStreet2CBDone, - foldToStreet3CBChance, foldToStreet3CBDone, foldToStreet4CBChance, foldToStreet4CBDone, - street1CheckCallRaiseChance, street1CheckCallRaiseDone, street2CheckCallRaiseChance, street2CheckCallRaiseDone, - street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone, - street0Calls, street1Calls, street2Calls, street3Calls, street4Calls, - street0Bets, street1Bets, street2Bets, street3Bets, street4Bets - ) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']) - ,inserts ) - result.append( self.get_last_insert_id(c) ) # wrong? not used currently - except: - raise FpdbError( "store_hands_players_holdem_omaha error: " + str(sys.exc_value) ) - - return result - #end def store_hands_players_holdem_omaha - - def store_hands_players_stud(self, backend, hands_id, player_ids, start_cashes, antes, - card_values, card_suits, winnings, rakes, seatNos): - #stores hands_players rows for stud/razz games. returns an array of the resulting IDs - - try: - result=[] - #print "before inserts in store_hands_players_stud, antes:", antes - for i in xrange(len(player_ids)): - card1 = Card.cardFromValueSuit(card_values[i][0], card_suits[i][0]) - card2 = Card.cardFromValueSuit(card_values[i][1], card_suits[i][1]) - card3 = Card.cardFromValueSuit(card_values[i][2], card_suits[i][2]) - card4 = Card.cardFromValueSuit(card_values[i][3], card_suits[i][3]) - card5 = Card.cardFromValueSuit(card_values[i][4], card_suits[i][4]) - card6 = Card.cardFromValueSuit(card_values[i][5], card_suits[i][5]) - card7 = Card.cardFromValueSuit(card_values[i][6], card_suits[i][6]) - - c = self.get_cursor() - c.execute ("""INSERT INTO HandsPlayers - (handId, playerId, startCash, ante, tourneyTypeId, - card1, card2, - card3, card4, - card5, card6, - card7, winnings, rake, seatNo) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']), - (hands_id, player_ids[i], start_cashes[i], antes[i], 1, - card1, card2, - card3, card4, - card5, card6, - card7, winnings[i], rakes[i], seatNos[i])) - #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i])) - #result.append(cursor.fetchall()[0][0]) - result.append( self.get_last_insert_id(c) ) - except: - raise FpdbError( "store_hands_players_stud error: " + str(sys.exc_value) ) - - return result - #end def store_hands_players_stud - - def store_hands_players_holdem_omaha_tourney(self, backend, category, hands_id, player_ids - ,start_cashes, positions, card_values, card_suits - ,winnings, rakes, seatNos, tourneys_players_ids - ,hudCache, tourneyTypeId): - #stores hands_players for tourney holdem/omaha hands - - try: - result=[] - inserts = [] - for i in xrange(len(player_ids)): - card1 = Card.cardFromValueSuit(card_values[i][0], card_suits[i][0]) - card2 = Card.cardFromValueSuit(card_values[i][1], card_suits[i][1]) - - if len(card_values[0])==2: - startCards = Card.twoStartCards(card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1]) - card3 = None - card4 = None - elif len(card_values[0])==4: - startCards = Card.fourStartCards(card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1] - ,card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3]) - card3 = Card.cardFromValueSuit(card_values[i][2], card_suits[i][2]) - card4 = Card.cardFromValueSuit(card_values[i][3], card_suits[i][3]) - else: - raise FpdbError ("invalid card_values length:"+str(len(card_values[0]))) - - inserts.append( (hands_id, player_ids[i], start_cashes[i], positions[i], tourneyTypeId, - card1, card2, card3, card4, startCards, - winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i], hudCache['totalProfit'][i], - hudCache['street0VPI'][i], hudCache['street0Aggr'][i], - hudCache['street0_3BChance'][i], hudCache['street0_3BDone'][i], - hudCache['street1Seen'][i], hudCache['street2Seen'][i], hudCache['street3Seen'][i], - hudCache['street4Seen'][i], hudCache['sawShowdown'][i], - hudCache['street1Aggr'][i], hudCache['street2Aggr'][i], hudCache['street3Aggr'][i], hudCache['street4Aggr'][i], - hudCache['otherRaisedStreet1'][i], hudCache['otherRaisedStreet2'][i], - hudCache['otherRaisedStreet3'][i], hudCache['otherRaisedStreet4'][i], - hudCache['foldToOtherRaisedStreet1'][i], hudCache['foldToOtherRaisedStreet2'][i], - hudCache['foldToOtherRaisedStreet3'][i], hudCache['foldToOtherRaisedStreet4'][i], - hudCache['wonWhenSeenStreet1'][i], hudCache['wonAtSD'][i], - hudCache['stealAttemptChance'][i], hudCache['stealAttempted'][i], hudCache['foldBbToStealChance'][i], - hudCache['foldedBbToSteal'][i], hudCache['foldSbToStealChance'][i], hudCache['foldedSbToSteal'][i], - hudCache['street1CBChance'][i], hudCache['street1CBDone'][i], hudCache['street2CBChance'][i], hudCache['street2CBDone'][i], - hudCache['street3CBChance'][i], hudCache['street3CBDone'][i], hudCache['street4CBChance'][i], hudCache['street4CBDone'][i], - hudCache['foldToStreet1CBChance'][i], hudCache['foldToStreet1CBDone'][i], - hudCache['foldToStreet2CBChance'][i], hudCache['foldToStreet2CBDone'][i], - hudCache['foldToStreet3CBChance'][i], hudCache['foldToStreet3CBDone'][i], - hudCache['foldToStreet4CBChance'][i], hudCache['foldToStreet4CBDone'][i], - hudCache['street1CheckCallRaiseChance'][i], hudCache['street1CheckCallRaiseDone'][i], - hudCache['street2CheckCallRaiseChance'][i], hudCache['street2CheckCallRaiseDone'][i], - hudCache['street3CheckCallRaiseChance'][i], hudCache['street3CheckCallRaiseDone'][i], - hudCache['street4CheckCallRaiseChance'][i], hudCache['street4CheckCallRaiseDone'][i], - hudCache['street0Calls'][i], hudCache['street1Calls'][i], hudCache['street2Calls'][i], - hudCache['street3Calls'][i], hudCache['street4Calls'][i], - hudCache['street0Bets'][i], hudCache['street1Bets'][i], hudCache['street2Bets'][i], - hudCache['street3Bets'][i], hudCache['street4Bets'][i] - ) ) - - c = self.get_cursor() - c.executemany (""" - INSERT INTO HandsPlayers - (handId, playerId, startCash, position, tourneyTypeId, - card1, card2, card3, card4, startCards, winnings, rake, tourneysPlayersId, seatNo, totalProfit, - street0VPI, street0Aggr, street0_3BChance, street0_3BDone, - street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown, - street1Aggr, street2Aggr, street3Aggr, street4Aggr, - otherRaisedStreet1, otherRaisedStreet2, otherRaisedStreet3, otherRaisedStreet4, - foldToOtherRaisedStreet1, foldToOtherRaisedStreet2, foldToOtherRaisedStreet3, foldToOtherRaisedStreet4, - wonWhenSeenStreet1, wonAtSD, - stealAttemptChance, stealAttempted, foldBbToStealChance, foldedBbToSteal, foldSbToStealChance, foldedSbToSteal, - street1CBChance, street1CBDone, street2CBChance, street2CBDone, - street3CBChance, street3CBDone, street4CBChance, street4CBDone, - foldToStreet1CBChance, foldToStreet1CBDone, foldToStreet2CBChance, foldToStreet2CBDone, - foldToStreet3CBChance, foldToStreet3CBDone, foldToStreet4CBChance, foldToStreet4CBDone, - street1CheckCallRaiseChance, street1CheckCallRaiseDone, street2CheckCallRaiseChance, street2CheckCallRaiseDone, - street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone, - street0Calls, street1Calls, street2Calls, street3Calls, street4Calls, - street0Bets, street1Bets, street2Bets, street3Bets, street4Bets - ) - VALUES - (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']) - ,inserts ) - - result.append( self.get_last_insert_id(c) ) - #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i])) - #result.append(cursor.fetchall()[0][0]) - except: - err = traceback.extract_tb(sys.exc_info()[2])[-1] - print "***Error storing hand: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) - raise FpdbError( "store_hands_players_holdem_omaha_tourney error: " + str(sys.exc_value) ) - - return result - #end def store_hands_players_holdem_omaha_tourney - - def store_hands_players_stud_tourney(self, backend, hands_id, player_ids, start_cashes, - antes, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids, tourneyTypeId): - #stores hands_players for tourney stud/razz hands - return # TODO: stubbed out until someone updates it for current database structuring - try: - result=[] - for i in xrange(len(player_ids)): - c = self.get_cursor() - c.execute ("""INSERT INTO HandsPlayers - (handId, playerId, startCash, ante, - card1Value, card1Suit, card2Value, card2Suit, - card3Value, card3Suit, card4Value, card4Suit, - card5Value, card5Suit, card6Value, card6Suit, - card7Value, card7Suit, winnings, rake, tourneysPlayersId, seatNo, tourneyTypeId) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']), - (hands_id, player_ids[i], start_cashes[i], antes[i], - card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], - card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3], - card_values[i][4], card_suits[i][4], card_values[i][5], card_suits[i][5], - card_values[i][6], card_suits[i][6], winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i], tourneyTypeId)) - #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i])) - #result.append(cursor.fetchall()[0][0]) - result.append( self.get_last_insert_id(c) ) - except: - raise FpdbError( "store_hands_players_stud_tourney error: " + str(sys.exc_value) ) - - return result - #end def store_hands_players_stud_tourney - - def storeHudCache(self, backend, base, category, gametypeId, hand_start_time, playerIds, hudImportData): + def storeHudCache(self, gid, pid, hc): """Update cached statistics. If update fails because no record exists, do an insert. Can't use array updates here (not easily anyway) because we need to insert any rows that don't get updated.""" - # if (category=="holdem" or category=="omahahi" or category=="omahahilo"): - try: if self.use_date_in_hudcache: #print "key =", "d%02d%02d%02d " % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day) styleKey = "d%02d%02d%02d" % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day) @@ -2200,48 +1679,128 @@ class Database: # else: # print "todo: implement storeHudCache for stud base" - except: - raise FpdbError( "storeHudCache error: " + str(sys.exc_value) ) - - #end def storeHudCache + def isDuplicate(self, gametypeID, siteHandNo): + dup = False + c = self.get_cursor() + c.execute(self.sql.query['isAlreadyInDB'], (gametypeID, siteHandNo)) + result = c.fetchall() + if len(result) > 0: + dup = True + return dup + + def getGameTypeId(self, siteid, game): + c = self.get_cursor() + #FIXME: Fixed for NL at the moment + c.execute(self.sql.query['getGametypeNL'], (siteid, game['type'], game['category'], game['limitType'], + int(Decimal(game['sb'])*100), int(Decimal(game['bb'])*100))) + tmp = c.fetchone() + if (tmp == None): + hilo = "h" + if game['category'] in ['studhilo', 'omahahilo']: + hilo = "s" + elif game['category'] in ['razz','27_3draw','badugi']: + hilo = "l" + tmp = self.insertGameTypes( (siteid, game['type'], game['base'], game['category'], game['limitType'], hilo, + int(Decimal(game['sb'])*100), int(Decimal(game['bb'])*100), 0, 0) ) + return tmp[0] + + def getSqlPlayerIDs(self, pnames, siteid): + result = {} + if(self.pcache == None): + self.pcache = LambdaDict(lambda key:self.insertPlayer(key, siteid)) - def store_tourneys(self, tourneyTypeId, siteTourneyNo, entries, prizepool, startTime): - ret = -1 - try: - # try and create tourney record, fetch id if it already exists - # avoids race condition when doing the select first - cursor = self.get_cursor() - cursor.execute("savepoint ins_tourney") - cursor.execute("""INSERT INTO Tourneys - (tourneyTypeId, siteTourneyNo, entries, prizepool, startTime) - VALUES (%s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']) - ,(tourneyTypeId, siteTourneyNo, entries, prizepool, startTime)) - ret = self.get_last_insert_id(cursor) - #print "created new tourneys.id:",ret - except: - #if str(sys.exc_value) contains 'sitetourneyno': - # raise FpdbError( "store_tourneys error: " + str(sys.exc_value) ) + for player in pnames: + result[player] = self.pcache[player] + # NOTE: Using the LambdaDict does the same thing as: + #if player in self.pcache: + # #print "DEBUG: cachehit" + # pass #else: - #print "error insert tourney (%s) trying select ..." % (str(sys.exc_value),) - cursor.execute("rollback to savepoint ins_tourney") - try: - cursor.execute( "SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s".replace('%s', self.sql.query['placeholder']) - , (siteTourneyNo, tourneyTypeId) ) - rec = cursor.fetchone() - #print "select tourney result: ", rec - try: - len(rec) - ret = rec[0] - except: - print "Tourney id not found" - except: - print "Error selecting tourney id:", str(sys.exc_info()[1]) + # self.pcache[player] = self.insertPlayer(player, siteid) + #result[player] = self.pcache[player] + + return result + + def insertPlayer(self, name, site_id): + result = None + c = self.get_cursor() + q = "SELECT name, id FROM Players WHERE siteid=%s and name=%s" + q = q.replace('%s', self.sql.query['placeholder']) + + #NOTE/FIXME?: MySQL has ON DUPLICATE KEY UPDATE + #Usage: + # INSERT INTO `tags` (`tag`, `count`) + # VALUES ($tag, 1) + # ON DUPLICATE KEY UPDATE `count`=`count`+1; + + + #print "DEBUG: name: %s site: %s" %(name, site_id) + + c.execute (q, (site_id, name)) + + tmp = c.fetchone() + if (tmp == None): #new player + c.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)".replace('%s',self.sql.query['placeholder']) + ,(name, site_id)) + #Get last id might be faster here. + #c.execute ("SELECT id FROM Players WHERE name=%s", (name,)) + result = self.get_last_insert_id(c) + else: + result = tmp[1] + return result + + def insertGameTypes(self, row): + c = self.get_cursor() + c.execute( self.sql.query['insertGameTypes'], row ) + return [self.get_last_insert_id(c)] + + + +################################# +# Finish of NEWIMPORT CODE +################################# + + + + def storeHands(self, backend, site_hand_no, gametype_id + ,hand_start_time, names, tableName, maxSeats, hudCache + ,board_values, board_suits): + + cards = [Card.cardFromValueSuit(v,s) for v,s in zip(board_values,board_suits)] + #stores into table hands: + try: + c = self.get_cursor() + c.execute ("""INSERT INTO Hands + (siteHandNo, gametypeId, handStart, seats, tableName, importTime, maxSeats + ,boardcard1,boardcard2,boardcard3,boardcard4,boardcard5 + ,playersVpi, playersAtStreet1, playersAtStreet2 + ,playersAtStreet3, playersAtStreet4, playersAtShowdown + ,street0Raises, street1Raises, street2Raises + ,street3Raises, street4Raises, street1Pot + ,street2Pot, street3Pot, street4Pot + ,showdownPot + ) + VALUES + (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) + """.replace('%s', self.sql.query['placeholder']) + , (site_hand_no, gametype_id, hand_start_time, len(names), tableName, datetime.today(), maxSeats + ,cards[0], cards[1], cards[2], cards[3], cards[4] + ,hudCache['playersVpi'], hudCache['playersAtStreet1'], hudCache['playersAtStreet2'] + ,hudCache['playersAtStreet3'], hudCache['playersAtStreet4'], hudCache['playersAtShowdown'] + ,hudCache['street0Raises'], hudCache['street1Raises'], hudCache['street2Raises'] + ,hudCache['street3Raises'], hudCache['street4Raises'], hudCache['street1Pot'] + ,hudCache['street2Pot'], hudCache['street3Pot'], hudCache['street4Pot'] + ,hudCache['showdownPot'] + )) + ret = self.get_last_insert_id(c) + except: + ret = -1 + raise FpdbError( "storeHands error: " + str(sys.exc_value) ) - cursor.execute("release savepoint ins_tourney") - #print "store_tourneys returning", ret return ret - #end def store_tourneys - + #end def storeHands + def store_tourneys_players(self, tourney_id, player_ids, payin_amounts, ranks, winnings): try: result=[] From a0475aa4db5b9688625ef0d1009ec46b0988f8b3 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 23 Dec 2009 23:14:34 +0800 Subject: [PATCH 18/36] [NEWIMPORT] Add function to update hudcache for Hand --- pyfpdb/Database.py | 288 +++++++++++++++-------------------------- pyfpdb/DerivedStats.py | 2 + pyfpdb/Hand.py | 3 + pyfpdb/SQL.py | 141 ++++++++++++++++++++ pyfpdb/fpdb_import.py | 7 +- 5 files changed, 252 insertions(+), 189 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 9614084f..0b9cd32d 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -586,6 +586,7 @@ class Database: elif not name.lower() in stat_dict[playerid]: stat_dict[playerid][name.lower()] = val elif name.lower() not in ('hand_id', 'player_id', 'seat', 'screen_name', 'seats'): + #print "DEBUG: stat_dict[%s][%s]: %s" %(playerid, name.lower(), val) stat_dict[playerid][name.lower()] += val n += 1 if n >= 10000: break # todo: don't think this is needed so set nice and high @@ -1490,194 +1491,109 @@ class Database: c = self.get_cursor() c.executemany(q, inserts) - def storeHudCache(self, gid, pid, hc): - """Update cached statistics. If update fails because no record exists, do an insert. - Can't use array updates here (not easily anyway) because we need to insert any rows - that don't get updated.""" + def storeHudCache(self, gid, pids, starttime, pdata): + """Update cached statistics. If update fails because no record exists, do an insert.""" - if self.use_date_in_hudcache: - #print "key =", "d%02d%02d%02d " % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day) - styleKey = "d%02d%02d%02d" % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day) - else: - # hard-code styleKey as 'A000000' (all-time cache, no key) for now - styleKey = 'A000000' + if self.use_date_in_hudcache: + styleKey = datetime.strftime(starttime, 'd%y%m%d') + #styleKey = "d%02d%02d%02d" % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day) + else: + # hard-code styleKey as 'A000000' (all-time cache, no key) for now + styleKey = 'A000000' + + update_hudcache = self.sql.query['update_hudcache'] + update_hudcache = update_hudcache.replace('%s', self.sql.query['placeholder']) + insert_hudcache = self.sql.query['insert_hudcache'] + insert_hudcache = insert_hudcache.replace('%s', self.sql.query['placeholder']) - #print "storeHudCache, len(playerIds)=", len(playerIds), " len(vpip)=" \ - #, len(hudImportData['street0VPI']), " len(totprof)=", len(hudImportData['totalProfit']) - for player in xrange(len(playerIds)): - - # Set up a clean row - row=[] - row.append(0)#blank for id - row.append(gametypeId) - row.append(playerIds[player]) - row.append(len(playerIds))#seats - for i in xrange(len(hudImportData)+2): - row.append(0) - - if base=="hold": - row[4]=hudImportData['position'][player] - else: - row[4]=0 - row[5]=1 #tourneysGametypeId - row[6]+=1 #HDs - if hudImportData['street0VPI'][player]: row[7]+=1 - if hudImportData['street0Aggr'][player]: row[8]+=1 - if hudImportData['street0_3BChance'][player]: row[9]+=1 - if hudImportData['street0_3BDone'][player]: row[10]+=1 - if hudImportData['street1Seen'][player]: row[11]+=1 - if hudImportData['street2Seen'][player]: row[12]+=1 - if hudImportData['street3Seen'][player]: row[13]+=1 - if hudImportData['street4Seen'][player]: row[14]+=1 - if hudImportData['sawShowdown'][player]: row[15]+=1 - if hudImportData['street1Aggr'][player]: row[16]+=1 - if hudImportData['street2Aggr'][player]: row[17]+=1 - if hudImportData['street3Aggr'][player]: row[18]+=1 - if hudImportData['street4Aggr'][player]: row[19]+=1 - if hudImportData['otherRaisedStreet1'][player]: row[20]+=1 - if hudImportData['otherRaisedStreet2'][player]: row[21]+=1 - if hudImportData['otherRaisedStreet3'][player]: row[22]+=1 - if hudImportData['otherRaisedStreet4'][player]: row[23]+=1 - if hudImportData['foldToOtherRaisedStreet1'][player]: row[24]+=1 - if hudImportData['foldToOtherRaisedStreet2'][player]: row[25]+=1 - if hudImportData['foldToOtherRaisedStreet3'][player]: row[26]+=1 - if hudImportData['foldToOtherRaisedStreet4'][player]: row[27]+=1 - if hudImportData['wonWhenSeenStreet1'][player]!=0.0: row[28]+=hudImportData['wonWhenSeenStreet1'][player] - if hudImportData['wonAtSD'][player]!=0.0: row[29]+=hudImportData['wonAtSD'][player] - if hudImportData['stealAttemptChance'][player]: row[30]+=1 - if hudImportData['stealAttempted'][player]: row[31]+=1 - if hudImportData['foldBbToStealChance'][player]: row[32]+=1 - if hudImportData['foldedBbToSteal'][player]: row[33]+=1 - if hudImportData['foldSbToStealChance'][player]: row[34]+=1 - if hudImportData['foldedSbToSteal'][player]: row[35]+=1 - - if hudImportData['street1CBChance'][player]: row[36]+=1 - if hudImportData['street1CBDone'][player]: row[37]+=1 - if hudImportData['street2CBChance'][player]: row[38]+=1 - if hudImportData['street2CBDone'][player]: row[39]+=1 - if hudImportData['street3CBChance'][player]: row[40]+=1 - if hudImportData['street3CBDone'][player]: row[41]+=1 - if hudImportData['street4CBChance'][player]: row[42]+=1 - if hudImportData['street4CBDone'][player]: row[43]+=1 - - if hudImportData['foldToStreet1CBChance'][player]: row[44]+=1 - if hudImportData['foldToStreet1CBDone'][player]: row[45]+=1 - if hudImportData['foldToStreet2CBChance'][player]: row[46]+=1 - if hudImportData['foldToStreet2CBDone'][player]: row[47]+=1 - if hudImportData['foldToStreet3CBChance'][player]: row[48]+=1 - if hudImportData['foldToStreet3CBDone'][player]: row[49]+=1 - if hudImportData['foldToStreet4CBChance'][player]: row[50]+=1 - if hudImportData['foldToStreet4CBDone'][player]: row[51]+=1 - - #print "player=", player - #print "len(totalProfit)=", len(hudImportData['totalProfit']) - if hudImportData['totalProfit'][player]: - row[52]+=hudImportData['totalProfit'][player] - - if hudImportData['street1CheckCallRaiseChance'][player]: row[53]+=1 - if hudImportData['street1CheckCallRaiseDone'][player]: row[54]+=1 - if hudImportData['street2CheckCallRaiseChance'][player]: row[55]+=1 - if hudImportData['street2CheckCallRaiseDone'][player]: row[56]+=1 - if hudImportData['street3CheckCallRaiseChance'][player]: row[57]+=1 - if hudImportData['street3CheckCallRaiseDone'][player]: row[58]+=1 - if hudImportData['street4CheckCallRaiseChance'][player]: row[59]+=1 - if hudImportData['street4CheckCallRaiseDone'][player]: row[60]+=1 - - # Try to do the update first: - cursor = self.get_cursor() - num = cursor.execute("""UPDATE HudCache - SET HDs=HDs+%s, street0VPI=street0VPI+%s, street0Aggr=street0Aggr+%s, - street0_3BChance=street0_3BChance+%s, street0_3BDone=street0_3BDone+%s, - street1Seen=street1Seen+%s, street2Seen=street2Seen+%s, street3Seen=street3Seen+%s, - street4Seen=street4Seen+%s, sawShowdown=sawShowdown+%s, - street1Aggr=street1Aggr+%s, street2Aggr=street2Aggr+%s, street3Aggr=street3Aggr+%s, - street4Aggr=street4Aggr+%s, otherRaisedStreet1=otherRaisedStreet1+%s, - otherRaisedStreet2=otherRaisedStreet2+%s, otherRaisedStreet3=otherRaisedStreet3+%s, - otherRaisedStreet4=otherRaisedStreet4+%s, - foldToOtherRaisedStreet1=foldToOtherRaisedStreet1+%s, foldToOtherRaisedStreet2=foldToOtherRaisedStreet2+%s, - foldToOtherRaisedStreet3=foldToOtherRaisedStreet3+%s, foldToOtherRaisedStreet4=foldToOtherRaisedStreet4+%s, - wonWhenSeenStreet1=wonWhenSeenStreet1+%s, wonAtSD=wonAtSD+%s, stealAttemptChance=stealAttemptChance+%s, - stealAttempted=stealAttempted+%s, foldBbToStealChance=foldBbToStealChance+%s, - foldedBbToSteal=foldedBbToSteal+%s, - foldSbToStealChance=foldSbToStealChance+%s, foldedSbToSteal=foldedSbToSteal+%s, - street1CBChance=street1CBChance+%s, street1CBDone=street1CBDone+%s, street2CBChance=street2CBChance+%s, - street2CBDone=street2CBDone+%s, street3CBChance=street3CBChance+%s, - street3CBDone=street3CBDone+%s, street4CBChance=street4CBChance+%s, street4CBDone=street4CBDone+%s, - foldToStreet1CBChance=foldToStreet1CBChance+%s, foldToStreet1CBDone=foldToStreet1CBDone+%s, - foldToStreet2CBChance=foldToStreet2CBChance+%s, foldToStreet2CBDone=foldToStreet2CBDone+%s, - foldToStreet3CBChance=foldToStreet3CBChance+%s, - foldToStreet3CBDone=foldToStreet3CBDone+%s, foldToStreet4CBChance=foldToStreet4CBChance+%s, - foldToStreet4CBDone=foldToStreet4CBDone+%s, totalProfit=totalProfit+%s, - street1CheckCallRaiseChance=street1CheckCallRaiseChance+%s, - street1CheckCallRaiseDone=street1CheckCallRaiseDone+%s, street2CheckCallRaiseChance=street2CheckCallRaiseChance+%s, - street2CheckCallRaiseDone=street2CheckCallRaiseDone+%s, street3CheckCallRaiseChance=street3CheckCallRaiseChance+%s, - street3CheckCallRaiseDone=street3CheckCallRaiseDone+%s, street4CheckCallRaiseChance=street4CheckCallRaiseChance+%s, - street4CheckCallRaiseDone=street4CheckCallRaiseDone+%s - WHERE gametypeId+0=%s - AND playerId=%s - AND activeSeats=%s - AND position=%s - AND tourneyTypeId+0=%s - AND styleKey=%s - """.replace('%s', self.sql.query['placeholder']) - ,(row[6], row[7], row[8], row[9], row[10], - row[11], row[12], row[13], row[14], row[15], - row[16], row[17], row[18], row[19], row[20], - row[21], row[22], row[23], row[24], row[25], - row[26], row[27], row[28], row[29], row[30], - row[31], row[32], row[33], row[34], row[35], - row[36], row[37], row[38], row[39], row[40], - row[41], row[42], row[43], row[44], row[45], - row[46], row[47], row[48], row[49], row[50], - row[51], row[52], row[53], row[54], row[55], - row[56], row[57], row[58], row[59], row[60], - row[1], row[2], row[3], str(row[4]), row[5], styleKey)) - # Test statusmessage to see if update worked, do insert if not - #print "storehud2, upd num =", num.rowcount - # num is a cursor in sqlite - if ( (backend == self.PGSQL and cursor.statusmessage != "UPDATE 1") - or (backend == self.MYSQL_INNODB and num == 0) - or (backend == self.SQLITE and num.rowcount == 0) - ): - #print "playerid before insert:",row[2]," num = ", num - num = cursor.execute("""INSERT INTO HudCache - (gametypeId, playerId, activeSeats, position, tourneyTypeId, styleKey, - HDs, street0VPI, street0Aggr, street0_3BChance, street0_3BDone, - street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown, - street1Aggr, street2Aggr, street3Aggr, street4Aggr, otherRaisedStreet1, - otherRaisedStreet2, otherRaisedStreet3, otherRaisedStreet4, foldToOtherRaisedStreet1, foldToOtherRaisedStreet2, - foldToOtherRaisedStreet3, foldToOtherRaisedStreet4, wonWhenSeenStreet1, wonAtSD, stealAttemptChance, - stealAttempted, foldBbToStealChance, foldedBbToSteal, foldSbToStealChance, foldedSbToSteal, - street1CBChance, street1CBDone, street2CBChance, street2CBDone, street3CBChance, - street3CBDone, street4CBChance, street4CBDone, foldToStreet1CBChance, foldToStreet1CBDone, - foldToStreet2CBChance, foldToStreet2CBDone, foldToStreet3CBChance, foldToStreet3CBDone, foldToStreet4CBChance, - foldToStreet4CBDone, totalProfit, street1CheckCallRaiseChance, street1CheckCallRaiseDone, street2CheckCallRaiseChance, - street2CheckCallRaiseDone, street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone) - VALUES (%s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']) - , (row[1], row[2], row[3], row[4], row[5], styleKey, row[6], row[7], row[8], row[9], row[10] - ,row[11], row[12], row[13], row[14], row[15], row[16], row[17], row[18], row[19], row[20] - ,row[21], row[22], row[23], row[24], row[25], row[26], row[27], row[28], row[29], row[30] - ,row[31], row[32], row[33], row[34], row[35], row[36], row[37], row[38], row[39], row[40] - ,row[41], row[42], row[43], row[44], row[45], row[46], row[47], row[48], row[49], row[50] - ,row[51], row[52], row[53], row[54], row[55], row[56], row[57], row[58], row[59], row[60]) ) - #print "hopefully inserted hud data line: ", cursor.rowcount - # message seems to be "INSERT 0 1" - else: - #print "updated(2) hud data line" - pass - # else: - # print "todo: implement storeHudCache for stud base" + #print "DEBUG: %s %s %s" %(hid, pids, pdata) + inserts = [] + for p in pdata: + line = [0]*61 + + line[0] = 1 # HDs + if pdata[p]['street0VPI']: line[1] = 1 + if pdata[p]['street0Aggr']: line[2] = 1 + if pdata[p]['street0_3BChance']: line[3] = 1 + if pdata[p]['street0_3BDone']: line[4] = 1 + if pdata[p]['street1Seen']: line[5] = 1 + if pdata[p]['street2Seen']: line[6] = 1 + if pdata[p]['street3Seen']: line[7] = 1 + if pdata[p]['street4Seen']: line[8] = 1 + if pdata[p]['sawShowdown']: line[9] = 1 + if pdata[p]['street1Aggr']: line[10] = 1 + if pdata[p]['street2Aggr']: line[11] = 1 + if pdata[p]['street3Aggr']: line[12] = 1 + if pdata[p]['street4Aggr']: line[13] = 1 + if pdata[p]['otherRaisedStreet1']: line[14] = 1 + if pdata[p]['otherRaisedStreet2']: line[15] = 1 + if pdata[p]['otherRaisedStreet3']: line[16] = 1 + if pdata[p]['otherRaisedStreet4']: line[17] = 1 + if pdata[p]['foldToOtherRaisedStreet1']: line[18] = 1 + if pdata[p]['foldToOtherRaisedStreet2']: line[19] = 1 + if pdata[p]['foldToOtherRaisedStreet3']: line[20] = 1 + if pdata[p]['foldToOtherRaisedStreet4']: line[21] = 1 + line[22] = pdata[p]['wonWhenSeenStreet1'] + line[23] = pdata[p]['wonAtSD'] + if pdata[p]['stealAttemptChance']: line[24] = 1 + if pdata[p]['stealAttempted']: line[25] = 1 + if pdata[p]['foldBbToStealChance']: line[26] = 1 + if pdata[p]['foldedBbToSteal']: line[27] = 1 + if pdata[p]['foldSbToStealChance']: line[28] = 1 + if pdata[p]['foldedSbToSteal']: line[29] = 1 + if pdata[p]['street1CBChance']: line[30] = 1 + if pdata[p]['street1CBDone']: line[31] = 1 + if pdata[p]['street2CBChance']: line[32] = 1 + if pdata[p]['street2CBDone']: line[33] = 1 + if pdata[p]['street3CBChance']: line[34] = 1 + if pdata[p]['street3CBDone']: line[35] = 1 + if pdata[p]['street4CBChance']: line[36] = 1 + if pdata[p]['street4CBDone']: line[37] = 1 + if pdata[p]['foldToStreet1CBChance']: line[38] = 1 + if pdata[p]['foldToStreet1CBDone']: line[39] = 1 + if pdata[p]['foldToStreet2CBChance']: line[40] = 1 + if pdata[p]['foldToStreet2CBDone']: line[41] = 1 + if pdata[p]['foldToStreet3CBChance']: line[42] = 1 + if pdata[p]['foldToStreet3CBDone']: line[43] = 1 + if pdata[p]['foldToStreet4CBChance']: line[44] = 1 + if pdata[p]['foldToStreet4CBDone']: line[45] = 1 + line[46] = pdata[p]['totalProfit'] + if pdata[p]['street1CheckCallRaiseChance']: line[47] = 1 + if pdata[p]['street1CheckCallRaiseDone']: line[48] = 1 + if pdata[p]['street2CheckCallRaiseChance']: line[49] = 1 + if pdata[p]['street2CheckCallRaiseDone']: line[50] = 1 + if pdata[p]['street3CheckCallRaiseChance']: line[51] = 1 + if pdata[p]['street3CheckCallRaiseDone']: line[52] = 1 + if pdata[p]['street4CheckCallRaiseChance']: line[53] = 1 + if pdata[p]['street4CheckCallRaiseDone']: line[54] = 1 + line[55] = gid # gametypeId + line[56] = pids[p] # playerId + line[57] = len(pids) # activeSeats + line[58] = pdata[p]['position'] + line[59] = pdata[p]['tourneyTypeId'] + line[60] = styleKey # styleKey + inserts.append(line) + + + cursor = self.get_cursor() + + for row in inserts: + # Try to do the update first: + num = cursor.execute(update_hudcache, row) + # Test statusmessage to see if update worked, do insert if not + # num is a cursor in sqlite + if ((self.backend == self.PGSQL and cursor.statusmessage != "UPDATE 1") + or (self.backend == self.MYSQL_INNODB and num == 0) + or (self.backend == self.SQLITE and num.rowcount == 0)): + #move the last 6 items in WHERE clause of row from the end of the array + # to the beginning for the INSERT statement + print "DEBUG: using INSERT: %s" % num + row = row[-6:] + row[:-6] + num = cursor.execute(insert_hudcache, row) + print "DEBUG: Successfully(?: %s) updated HudCacho using INSERT" % num + else: + print "DEBUG: Successfully updated HudCacho using UPDATE" + pass def isDuplicate(self, gametypeID, siteHandNo): dup = False diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index c87e714a..1e81dd8d 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -201,6 +201,7 @@ class DerivedStats(): # 2 Hijack def assembleHudCache(self, hand): + # No real work to be done - HandsPlayers data already contains the correct info pass def vpip(self, hand): @@ -443,4 +444,5 @@ class DerivedStats(): betOrRaise = True else: break + return betOrRaise diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 3467216a..a660b56d 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -232,6 +232,9 @@ db: a connected fpdb_db object""" #Raise Duplicate exception? pass + def updateHudCache(self, db): + db.storeHudCache(self.dbid_gt, self.dbid_pids, self.starttime, self.stats.getHandsPlayers()) + def select(self, handId): """ Function to create Hand object from database """ diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 56c1f388..2b19b04a 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -3088,6 +3088,147 @@ class Sql: ,'d' || substr(strftime('%Y%m%d', h.handStart),3,7) """ + self.query['insert_hudcache'] = """ + INSERT INTO HudCache ( + gametypeId, + playerId, + activeSeats, + position, + tourneyTypeId, + styleKey, + HDs, + street0VPI, + street0Aggr, + street0_3BChance, + street0_3BDone, + street1Seen, + street2Seen, + street3Seen, + street4Seen, + sawShowdown, + street1Aggr, + street2Aggr, + street3Aggr, + street4Aggr, + otherRaisedStreet1, + otherRaisedStreet2, + otherRaisedStreet3, + otherRaisedStreet4, + foldToOtherRaisedStreet1, + foldToOtherRaisedStreet2, + foldToOtherRaisedStreet3, + foldToOtherRaisedStreet4, + wonWhenSeenStreet1, + wonAtSD, + stealAttemptChance, + stealAttempted, + foldBbToStealChance, + foldedBbToSteal, + foldSbToStealChance, + foldedSbToSteal, + street1CBChance, + street1CBDone, + street2CBChance, + street2CBDone, + street3CBChance, + street3CBDone, + street4CBChance, + street4CBDone, + foldToStreet1CBChance, + foldToStreet1CBDone, + foldToStreet2CBChance, + foldToStreet2CBDone, + foldToStreet3CBChance, + foldToStreet3CBDone, + foldToStreet4CBChance, + foldToStreet4CBDone, + totalProfit, + street1CheckCallRaiseChance, + street1CheckCallRaiseDone, + street2CheckCallRaiseChance, + street2CheckCallRaiseDone, + street3CheckCallRaiseChance, + street3CheckCallRaiseDone, + street4CheckCallRaiseChance, + street4CheckCallRaiseDone) + VALUES (%s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s)""" + + self.query['update_hudcache'] = """ + UPDATE HudCache SET + HDs=HDs+%s, + street0VPI=street0VPI+%s, + street0Aggr=street0Aggr+%s, + street0_3BChance=street0_3BChance+%s, + street0_3BDone=street0_3BDone+%s, + street1Seen=street1Seen+%s, + street2Seen=street2Seen+%s, + street3Seen=street3Seen+%s, + street4Seen=street4Seen+%s, + sawShowdown=sawShowdown+%s, + street1Aggr=street1Aggr+%s, + street2Aggr=street2Aggr+%s, + street3Aggr=street3Aggr+%s, + street4Aggr=street4Aggr+%s, + otherRaisedStreet1=otherRaisedStreet1+%s, + otherRaisedStreet2=otherRaisedStreet2+%s, + otherRaisedStreet3=otherRaisedStreet3+%s, + otherRaisedStreet4=otherRaisedStreet4+%s, + foldToOtherRaisedStreet1=foldToOtherRaisedStreet1+%s, + foldToOtherRaisedStreet2=foldToOtherRaisedStreet2+%s, + foldToOtherRaisedStreet3=foldToOtherRaisedStreet3+%s, + foldToOtherRaisedStreet4=foldToOtherRaisedStreet4+%s, + wonWhenSeenStreet1=wonWhenSeenStreet1+%s, + wonAtSD=wonAtSD+%s, + stealAttemptChance=stealAttemptChance+%s, + stealAttempted=stealAttempted+%s, + foldBbToStealChance=foldBbToStealChance+%s, + foldedBbToSteal=foldedBbToSteal+%s, + foldSbToStealChance=foldSbToStealChance+%s, + foldedSbToSteal=foldedSbToSteal+%s, + street1CBChance=street1CBChance+%s, + street1CBDone=street1CBDone+%s, + street2CBChance=street2CBChance+%s, + street2CBDone=street2CBDone+%s, + street3CBChance=street3CBChance+%s, + street3CBDone=street3CBDone+%s, + street4CBChance=street4CBChance+%s, + street4CBDone=street4CBDone+%s, + foldToStreet1CBChance=foldToStreet1CBChance+%s, + foldToStreet1CBDone=foldToStreet1CBDone+%s, + foldToStreet2CBChance=foldToStreet2CBChance+%s, + foldToStreet2CBDone=foldToStreet2CBDone+%s, + foldToStreet3CBChance=foldToStreet3CBChance+%s, + foldToStreet3CBDone=foldToStreet3CBDone+%s, + foldToStreet4CBChance=foldToStreet4CBChance+%s, + foldToStreet4CBDone=foldToStreet4CBDone+%s, + totalProfit=totalProfit+%s, + street1CheckCallRaiseChance=street1CheckCallRaiseChance+%s, + street1CheckCallRaiseDone=street1CheckCallRaiseDone+%s, + street2CheckCallRaiseChance=street2CheckCallRaiseChance+%s, + street2CheckCallRaiseDone=street2CheckCallRaiseDone+%s, + street3CheckCallRaiseChance=street3CheckCallRaiseChance+%s, + street3CheckCallRaiseDone=street3CheckCallRaiseDone+%s, + street4CheckCallRaiseChance=street4CheckCallRaiseChance+%s, + street4CheckCallRaiseDone=street4CheckCallRaiseDone+%s + WHERE gametypeId+0=%s + AND playerId=%s + AND activeSeats=%s + AND position=%s + AND tourneyTypeId+0=%s + AND styleKey=%s""" + self.query['get_hero_hudcache_start'] = """select min(hc.styleKey) from HudCache hc where hc.playerId in diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 24f16000..41d04283 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -432,9 +432,8 @@ class Importer: idx = self.pos_in_file[file] else: self.pos_in_file[file] = 0 - hhc = obj(in_path = file, out_path = out_path, index = idx, starsArchive = self.settings['starsArchive']) # Index into file 0 until changeover + hhc = obj(in_path = file, out_path = out_path, index = idx, starsArchive = self.settings['starsArchive']) if hhc.getStatus() and self.NEWIMPORT == True: - #This code doesn't do anything yet handlist = hhc.getProcessedHands() self.pos_in_file[file] = hhc.getLastCharacterRead() to_hud = [] @@ -449,8 +448,10 @@ class Importer: else: log.error("Hand processed but empty") self.database.commit() + # Call hudcache update if not in bulk import mode + # FIXME: Need to test for bulk import that isn't rebuilding the cache if self.callHud: - self.database.rebuild_hudcache() + hand.updateHudCache(self.database) #pipe the Hands.id out to the HUD for hid in to_hud: From 0adf0a7b18ae44b6a1b5f67b398a1788ea60303d Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 24 Dec 2009 01:12:39 +0800 Subject: [PATCH 19/36] [NEWIMPORT] updateHudCache update. Fix a couple of bugs: position != 2 its = 'M' actually commit changes to hud --- pyfpdb/Database.py | 14 ++++++++------ pyfpdb/fpdb_import.py | 1 + 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 0b9cd32d..fcb0c066 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1569,7 +1569,8 @@ class Database: line[55] = gid # gametypeId line[56] = pids[p] # playerId line[57] = len(pids) # activeSeats - line[58] = pdata[p]['position'] + pos = {-2:'B', -1:'S', 0:'D', 1:'C', 2:'M', 3:'M', 4:'M', 5:'E', 6:'E', 7:'E', 8:'E', 9:'E' } + line[58] = pos[pdata[p]['position']] line[59] = pdata[p]['tourneyTypeId'] line[60] = styleKey # styleKey inserts.append(line) @@ -1580,19 +1581,20 @@ class Database: for row in inserts: # Try to do the update first: num = cursor.execute(update_hudcache, row) - # Test statusmessage to see if update worked, do insert if not - # num is a cursor in sqlite + #print "DEBUG: values: %s" % row[-6:] + # Test statusmessage to see if update worked, do insert if not + # num is a cursor in sqlite if ((self.backend == self.PGSQL and cursor.statusmessage != "UPDATE 1") or (self.backend == self.MYSQL_INNODB and num == 0) or (self.backend == self.SQLITE and num.rowcount == 0)): #move the last 6 items in WHERE clause of row from the end of the array # to the beginning for the INSERT statement - print "DEBUG: using INSERT: %s" % num + #print "DEBUG: using INSERT: %s" % num row = row[-6:] + row[:-6] num = cursor.execute(insert_hudcache, row) - print "DEBUG: Successfully(?: %s) updated HudCacho using INSERT" % num + #print "DEBUG: Successfully(?: %s) updated HudCacho using INSERT" % num else: - print "DEBUG: Successfully updated HudCacho using UPDATE" + #print "DEBUG: Successfully updated HudCacho using UPDATE" pass def isDuplicate(self, gametypeID, siteHandNo): diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 41d04283..7c240cbe 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -452,6 +452,7 @@ class Importer: # FIXME: Need to test for bulk import that isn't rebuilding the cache if self.callHud: hand.updateHudCache(self.database) + self.database.commit() #pipe the Hands.id out to the HUD for hid in to_hud: From 46e91e1a0f687aa25e33924807b554e097a1983b Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 25 Dec 2009 18:55:13 +0800 Subject: [PATCH 20/36] [NEWIMPORT] Remove a couple of unused functions --- pyfpdb/Database.py | 102 --------------------------------------------- 1 file changed, 102 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index fcb0c066..0e67e6b6 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -619,69 +619,6 @@ class Database: rows = c.fetchall() return rows - #returns the SQL ids of the names given in an array - # TODO: if someone gets industrious, they should make the parts that use the output of this function deal with a dict - # { playername: id } instead of depending on it's relation to the positions list - # then this can be reduced in complexity a bit - - #def recognisePlayerIDs(cursor, names, site_id): - # result = [] - # for i in xrange(len(names)): - # cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],)) - # tmp=cursor.fetchall() - # if (len(tmp)==0): #new player - # cursor.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)", (names[i], site_id)) - # #print "Number of players rows inserted: %d" % cursor.rowcount - # cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],)) - # tmp=cursor.fetchall() - # #print "recognisePlayerIDs, names[i]:",names[i],"tmp:",tmp - # result.append(tmp[0][0]) - # return result - - def recognisePlayerIDs(self, names, site_id): - c = self.get_cursor() - q = "SELECT name,id FROM Players WHERE siteid=%d and (name=%s)" %(site_id, " OR name=".join([self.sql.query['placeholder'] for n in names])) - c.execute(q, names) # get all playerids by the names passed in - ids = dict(c.fetchall()) # convert to dict - if len(ids) != len(names): - notfound = [n for n in names if n not in ids] # make list of names not in database - if notfound: # insert them into database - q_ins = "INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")" - q_ins = q_ins.replace('%s', self.sql.query['placeholder']) - c.executemany(q_ins, [(n,) for n in notfound]) - q2 = "SELECT name,id FROM Players WHERE siteid=%d and (name=%s)" % (site_id, " OR name=".join(["%s" for n in notfound])) - q2 = q2.replace('%s', self.sql.query['placeholder']) - c.execute(q2, notfound) # get their new ids - tmp = c.fetchall() - for n,id in tmp: # put them all into the same dict - ids[n] = id - # return them in the SAME ORDER that they came in in the names argument, rather than the order they came out of the DB - return [ids[n] for n in names] - #end def recognisePlayerIDs - - # Here's a version that would work if it wasn't for the fact that it needs to have the output in the same order as input - # this version could also be improved upon using list comprehensions, etc - - #def recognisePlayerIDs(cursor, names, site_id): - # result = [] - # notfound = [] - # cursor.execute("SELECT name,id FROM Players WHERE name='%s'" % "' OR name='".join(names)) - # tmp = dict(cursor.fetchall()) - # for n in names: - # if n not in tmp: - # notfound.append(n) - # else: - # result.append(tmp[n]) - # if notfound: - # cursor.executemany("INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")", (notfound)) - # cursor.execute("SELECT id FROM Players WHERE name='%s'" % "' OR name='".join(notfound)) - # tmp = cursor.fetchall() - # for n in tmp: - # result.append(n[0]) - # - # return result - - def get_site_id(self, site): c = self.get_cursor() c.execute(self.sql.query['getSiteId'], (site,)) @@ -1680,45 +1617,6 @@ class Database: - def storeHands(self, backend, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats, hudCache - ,board_values, board_suits): - - cards = [Card.cardFromValueSuit(v,s) for v,s in zip(board_values,board_suits)] - #stores into table hands: - try: - c = self.get_cursor() - c.execute ("""INSERT INTO Hands - (siteHandNo, gametypeId, handStart, seats, tableName, importTime, maxSeats - ,boardcard1,boardcard2,boardcard3,boardcard4,boardcard5 - ,playersVpi, playersAtStreet1, playersAtStreet2 - ,playersAtStreet3, playersAtStreet4, playersAtShowdown - ,street0Raises, street1Raises, street2Raises - ,street3Raises, street4Raises, street1Pot - ,street2Pot, street3Pot, street4Pot - ,showdownPot - ) - VALUES - (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) - """.replace('%s', self.sql.query['placeholder']) - , (site_hand_no, gametype_id, hand_start_time, len(names), tableName, datetime.today(), maxSeats - ,cards[0], cards[1], cards[2], cards[3], cards[4] - ,hudCache['playersVpi'], hudCache['playersAtStreet1'], hudCache['playersAtStreet2'] - ,hudCache['playersAtStreet3'], hudCache['playersAtStreet4'], hudCache['playersAtShowdown'] - ,hudCache['street0Raises'], hudCache['street1Raises'], hudCache['street2Raises'] - ,hudCache['street3Raises'], hudCache['street4Raises'], hudCache['street1Pot'] - ,hudCache['street2Pot'], hudCache['street3Pot'], hudCache['street4Pot'] - ,hudCache['showdownPot'] - )) - ret = self.get_last_insert_id(c) - except: - ret = -1 - raise FpdbError( "storeHands error: " + str(sys.exc_value) ) - - return ret - #end def storeHands - def store_tourneys_players(self, tourney_id, player_ids, payin_amounts, ranks, winnings): try: result=[] From 1245a0cab3091575f13da4e8a0c5d1aa2fb507ec Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 26 Dec 2009 10:07:33 +0800 Subject: [PATCH 21/36] New test file - All-in pre flop --- ...HE-6max-USD-0.05-0.10-200912.Allin-pre.txt | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt diff --git a/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt b/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt new file mode 100644 index 00000000..b876c42a --- /dev/null +++ b/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt @@ -0,0 +1,41 @@ +PokerStars Game #37165169101: Hold'em No Limit ($0.10/$0.25 USD) - 2009/12/25 9:50:09 ET +Table 'Lucretia IV' 6-max Seat #2 is the button +Seat 1: Blåveis ($55.10 in chips) +Seat 2: Kinewma ($31.40 in chips) +Seat 3: AAALISAAAA ($20.20 in chips) +Seat 4: Arbaz ($25 in chips) +Seat 5: s0rrow ($29.85 in chips) +Seat 6: bys7 ($41.35 in chips) +AAALISAAAA: posts small blind $0.10 +Arbaz: posts big blind $0.25 +*** HOLE CARDS *** +Dealt to s0rrow [Ac As] +s0rrow: raises $0.50 to $0.75 +bys7: calls $0.75 +Blåveis: folds +Kinewma: folds +AAALISAAAA: raises $1.50 to $2.25 +Arbaz: folds +s0rrow: raises $3.50 to $5.75 +bys7: folds +AAALISAAAA: raises $14.45 to $20.20 and is all-in +s0rrow: calls $14.45 +*** FLOP *** [3d 7h Kh] +*** TURN *** [3d 7h Kh] [Ts] +*** RIVER *** [3d 7h Kh Ts] [5c] +*** SHOW DOWN *** +AAALISAAAA: shows [Kd 5d] (two pair, Kings and Fives) +s0rrow: shows [Ac As] (a pair of Aces) +AAALISAAAA collected $39.35 from pot +*** SUMMARY *** +Total pot $41.40 | Rake $2.05 +Board [3d 7h Kh Ts 5c] +Seat 1: Blåveis folded before Flop (didn't bet) +Seat 2: Kinewma (button) folded before Flop (didn't bet) +Seat 3: AAALISAAAA (small blind) showed [Kd 5d] and won ($39.35) with two pair, Kings and Fives +Seat 4: Arbaz (big blind) folded before Flop +Seat 5: s0rrow showed [Ac As] and lost with a pair of Aces +Seat 6: bys7 folded before Flop + + + From 9f2f015fd0e65a6d64973d284b28d50d7a746c71 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 26 Dec 2009 12:23:20 +0800 Subject: [PATCH 22/36] New test for all-in preflop. Test still fails - need to sort out an issue with database placement --- pyfpdb/test_PokerStars.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/pyfpdb/test_PokerStars.py b/pyfpdb/test_PokerStars.py index e3e45c35..18a9f556 100644 --- a/pyfpdb/test_PokerStars.py +++ b/pyfpdb/test_PokerStars.py @@ -82,6 +82,8 @@ def testFlopImport(): # River: hero (continuation bets?) all-in and is not called importer.addBulkImportImportFileOrDir( """regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Stats-comparision.txt""", site="PokerStars") + importer.addBulkImportImportFileOrDir( + """regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt""", site="PokerStars") importer.setCallHud(False) (stored, dups, partial, errs, ttime) = importer.runImport() print "DEBUG: stored: %s dups: %s partial: %s errs: %s ttime: %s" %(stored, dups, partial, errs, ttime) @@ -114,6 +116,32 @@ and s.id = p.siteid""" # Assert if any sawShowdown = True assert result[row][col['sawShowdown']] == 0 + q = """SELECT + s.name, + p.name, + hp.sawShowdown +FROM + Hands as h, + Sites as s, + Gametypes as g, + HandsPlayers as hp, + Players as p +WHERE + h.siteHandNo = 37165169101 +and g.id = h.gametypeid +and hp.handid = h.id +and p.id = hp.playerid +and s.id = p.siteid""" + c = db.get_cursor() + c.execute(q) + result = c.fetchall() + for row, data in enumerate(result): + print "DEBUG: result[%s]: %s" %(row, result[row]) + # Assert if any sawShowdown = True + assert result[row][col['sawShowdown']] == 1 + + assert 0 == 1 + def testStudImport(): db.recreate_tables() importer = fpdb_import.Importer(False, settings, config) From 0e318e6d9f4e0a7b9d7911842e60091d084e172a Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 26 Dec 2009 17:18:05 +0800 Subject: [PATCH 23/36] [NEWIMPORT] Commit currnetly failing test - sawShowdown It would appear that all-in pre-flop doesn't flag sawShowdown. Also modified the query to select street0Aggr, as that appears to be wrong at the moment --- pyfpdb/DerivedStats.py | 2 +- pyfpdb/test_PokerStars.py | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 1e81dd8d..7c50178b 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -363,7 +363,7 @@ class DerivedStats(): def aggr(self, hand, i): aggrers = set() for act in hand.actions[hand.actionStreets[i]]: - if act[1] in ('completes', 'raises'): + if act[1] in ('completes', 'bets', 'raises'): aggrers.add(act[0]) for player in hand.players: diff --git a/pyfpdb/test_PokerStars.py b/pyfpdb/test_PokerStars.py index 18a9f556..72c9049c 100644 --- a/pyfpdb/test_PokerStars.py +++ b/pyfpdb/test_PokerStars.py @@ -89,13 +89,14 @@ def testFlopImport(): print "DEBUG: stored: %s dups: %s partial: %s errs: %s ttime: %s" %(stored, dups, partial, errs, ttime) importer.clearFileList() - col = { 'sawShowdown': 2 + col = { 'sawShowdown': 2, 'street0Aggr':3 } q = """SELECT s.name, p.name, - hp.sawShowdown + hp.sawShowdown, + hp.street0Aggr FROM Hands as h, Sites as s, @@ -119,7 +120,8 @@ and s.id = p.siteid""" q = """SELECT s.name, p.name, - hp.sawShowdown + hp.sawShowdown, + hp.street0Aggr FROM Hands as h, Sites as s, @@ -135,10 +137,10 @@ and s.id = p.siteid""" c = db.get_cursor() c.execute(q) result = c.fetchall() + pstats = { u'Kinewma':0, u'Arbaz':0, u's0rrow':1, u'bys7':0, u'AAALISAAAA':1, u'Bl\xe5veis':0 } for row, data in enumerate(result): - print "DEBUG: result[%s]: %s" %(row, result[row]) - # Assert if any sawShowdown = True - assert result[row][col['sawShowdown']] == 1 + print "DEBUG: result[%s]: %s == %s" %(row, result[row], pstats[data[1]]) + assert result[row][col['sawShowdown']] == pstats[data[1]] assert 0 == 1 From 3553bdaf715575ee4b8e20de97d4062002bac798 Mon Sep 17 00:00:00 2001 From: Gerko de Roo Date: Wed, 23 Dec 2009 21:12:56 +0100 Subject: [PATCH 24/36] search string for table detect changed --- pyfpdb/HandHistoryConverter.py | 2 +- pyfpdb/Tables.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 9d4807a2..47cfd302 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -512,7 +512,7 @@ or None if we fail to get the info """ def getTableTitleRe(type, table_name=None, tournament = None, table_number=None): "Returns string to search in windows titles" if type=="tour": - return "%s.+Table\s%s" % (tournament, table_number) + return "%s.+Table.+%s" % (tournament, table_number) else: return table_name diff --git a/pyfpdb/Tables.py b/pyfpdb/Tables.py index 75bc574c..ce99b274 100755 --- a/pyfpdb/Tables.py +++ b/pyfpdb/Tables.py @@ -160,7 +160,7 @@ def discover_posix_by_name(c, tablename): def discover_posix_tournament(c, t_number, s_number): """Finds the X window for a client, given tournament and table nos.""" - search_string = "%s.+Table\s%s" % (t_number, s_number) + search_string = "%s.+Table.+%s" % (t_number, s_number) for listing in os.popen('xwininfo -root -tree').readlines(): if re.search(search_string, listing): return decode_xwininfo(c, listing) From eb226c002678d2e63bd6f3d568386605c55e5af0 Mon Sep 17 00:00:00 2001 From: Gerko de Roo Date: Wed, 23 Dec 2009 21:15:55 +0100 Subject: [PATCH 25/36] Added color highlight for stats window. high and low threshold and color can be set in the xml file --- pyfpdb/Configuration.py | 4 ++ pyfpdb/HUD_config.xml.example | 97 ++++++++++++++++++----------------- pyfpdb/Hud.py | 10 ++++ 3 files changed, 63 insertions(+), 48 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 174d0673..39bf5921 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -269,6 +269,10 @@ class Game: stat.hudprefix = stat_node.getAttribute("hudprefix") stat.hudsuffix = stat_node.getAttribute("hudsuffix") stat.hudcolor = stat_node.getAttribute("hudcolor") + stat.stat_loth = stat_node.getAttribute("stat_loth") + stat.stat_hith = stat_node.getAttribute("stat_hith") + stat.stat_locolor = stat_node.getAttribute("stat_locolor") + stat.stat_hicolor = stat_node.getAttribute("stat_hicolor") self.stats[stat.stat_name] = stat diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index b1ebd761..a772773e 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -449,59 +449,60 @@ Left-Drag to Move" - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + + diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index b61c17aa..1eb51aea 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -632,6 +632,16 @@ class Hud: self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.hudcolor)) + if this_stat.stat_loth != "": + if number[0] < (float(this_stat.stat_loth)/100): + self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) + window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_locolor)) + + if this_stat.stat_hith != "": + if number[0] > (float(this_stat.stat_hith)/100): + self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) + window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_hicolor)) + window.label[r][c].set_text(statstring) if statstring != "xxx": # is there a way to tell if this particular stat window is visible already, or no? window.window.show_all() From 3f3d8ac54a59d0617d18e212621aa5045676f171 Mon Sep 17 00:00:00 2001 From: Worros Date: Mon, 28 Dec 2009 10:21:31 +0800 Subject: [PATCH 26/36] Fix tab spacing from Gerkos recent patch --- pyfpdb/Hud.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 1eb51aea..e2994de8 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -633,14 +633,14 @@ class Hud: window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.hudcolor)) if this_stat.stat_loth != "": - if number[0] < (float(this_stat.stat_loth)/100): - self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) - window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_locolor)) + if number[0] < (float(this_stat.stat_loth)/100): + self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) + window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_locolor)) if this_stat.stat_hith != "": - if number[0] > (float(this_stat.stat_hith)/100): - self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) - window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_hicolor)) + if number[0] > (float(this_stat.stat_hith)/100): + self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) + window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_hicolor)) window.label[r][c].set_text(statstring) if statstring != "xxx": # is there a way to tell if this particular stat window is visible already, or no? From 1cf464283f15228f6c0d42abd8651bcaf3a4056e Mon Sep 17 00:00:00 2001 From: Gerko de Roo Date: Wed, 23 Dec 2009 21:44:55 +0100 Subject: [PATCH 27/36] Hmm forgot the color reset to default. There must be a better methode --- pyfpdb/Hud.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index e2994de8..2b6d0237 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -631,7 +631,10 @@ class Hud: if this_stat.hudcolor != "": self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.hudcolor)) - + else: + self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) + window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#FFFFFF")) + if this_stat.stat_loth != "": if number[0] < (float(this_stat.stat_loth)/100): self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) From c7aca0a32e9fe6398dfcc3d73ea9ce17cf3257e6 Mon Sep 17 00:00:00 2001 From: Worros Date: Mon, 28 Dec 2009 22:03:26 +0800 Subject: [PATCH 28/36] Update HUD_config.xml - Change default Holdem stat window layout to 3x3, add some more colouring - Fix tab breakage from Gerko. --- pyfpdb/HUD_config.xml.example | 91 ++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 45 deletions(-) diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index a772773e..3acfd812 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -448,61 +448,62 @@ Left-Drag to Move" + + + + + + + + + + + - + - - - - - - + + + + + + - + - - - - - - + + + + + + - + - - - - - - + + + + + + - + - - - - - - + + + + + + - + - - - - - - - - - - - - - - - - + + + + + + From 478b82587dfcf307b6d7e9e907dc89fa8c68e291 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Thu, 24 Dec 2009 09:52:47 +0200 Subject: [PATCH 29/36] Store names as UTF-8 The names should be always in UTF-8 encoding. At least for PostgreSQL the encdoding of the database comes from the time of running 'initdb' (which is different from 'createdb') and if the encoding was selected or set to something else at that time, the following error will occur: File ".../pyfpdb/Database.py", line 1630, in self.pcache = LambdaDict(lambda key:self.insertPlayer(key, siteid)) File ".../pyfpdb/Database.py", line 1661, in insertPlayer c.execute (q, (site_id, _name)) File "/usr/lib/python2.5/encodings/iso8859_15.py", line 12, in encode return codecs.charmap_encode(input,errors,encoding_table) UnicodeEncodeError: 'charmap' codec can't encode character u'\u2122' in position 10: character maps to This happens because 'name' is a regular string as opposed to a valid unicode object. By forcing the string to unicode and encoding it in UTF-8 the error goes away. In my case the database encoding was ISO-8859-15 (latin9) but any other "wrong" encoding would trigger the same problem. This is a relatively common problem in python. --- pyfpdb/Database.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 0e67e6b6..63e9a0a5 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -38,6 +38,7 @@ from decimal import Decimal import string import re import Queue +import codecs # pyGTK modules @@ -50,6 +51,7 @@ import Tourney from Exceptions import * log = Configuration.get_logger("logging.conf") +encoder = codecs.lookup('utf-8') class Database: @@ -1578,6 +1580,7 @@ class Database: def insertPlayer(self, name, site_id): result = None + (_name, _len) = encoder.encode(unicode(name)) c = self.get_cursor() q = "SELECT name, id FROM Players WHERE siteid=%s and name=%s" q = q.replace('%s', self.sql.query['placeholder']) @@ -1591,12 +1594,12 @@ class Database: #print "DEBUG: name: %s site: %s" %(name, site_id) - c.execute (q, (site_id, name)) + c.execute (q, (site_id, _name)) tmp = c.fetchone() if (tmp == None): #new player c.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)".replace('%s',self.sql.query['placeholder']) - ,(name, site_id)) + ,(_name, site_id)) #Get last id might be faster here. #c.execute ("SELECT id FROM Players WHERE name=%s", (name,)) result = self.get_last_insert_id(c) From cd88de7c7e57c334cc87f09126711a2c1dd15c8f Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 30 Dec 2009 15:44:48 +0800 Subject: [PATCH 30/36] [NEWIMPORT] Copy in Alchemy files from Grigorij's alchemy branch --- pyfpdb/AlchemyFacilities.py | 116 +++++++++ pyfpdb/AlchemyMappings.py | 464 ++++++++++++++++++++++++++++++++++++ pyfpdb/AlchemyTables.py | 438 ++++++++++++++++++++++++++++++++++ 3 files changed, 1018 insertions(+) create mode 100644 pyfpdb/AlchemyFacilities.py create mode 100644 pyfpdb/AlchemyMappings.py create mode 100644 pyfpdb/AlchemyTables.py diff --git a/pyfpdb/AlchemyFacilities.py b/pyfpdb/AlchemyFacilities.py new file mode 100644 index 00000000..c8284efb --- /dev/null +++ b/pyfpdb/AlchemyFacilities.py @@ -0,0 +1,116 @@ +# -*- coding: utf-8 -*- +from decimal import Decimal + +from sqlalchemy import types +from sqlalchemy.orm.exc import NoResultFound +from sqlalchemy.exc import IntegrityError + +import Card + +class CardColumn(types.TypeDecorator): + """Stores cards as smallints + + Automatically converts values like '9h' to smallint + + >>> CardColumn().process_bind_param( 'Td', '' ) + 22 + >>> CardColumn().process_bind_param( u'Td', '' ) + 22 + >>> CardColumn().process_bind_param( 22, '' ) + 22 + >>> CardColumn().process_result_value( 22, '' ) + 'Td' + """ + + impl = types.SmallInteger + + def process_bind_param(self, value, dialect): + if value is None or isinstance(value, int): + return value + elif isinstance(value, basestring) and len(value) == 2: + return Card.encodeCard(str(value)) + else: + raise Exception, "Incorrect card value: " + repr(value) + + def process_result_value(self, value, dialect): + return Card.valueSuitFromCard( value ) + + +class MoneyColumn(types.TypeDecorator): + """Stores money: bets, pots, etc + + Understands: + Decimal as real amount + int as amount mupliplied by 100 + string as decimal + Returns Decimal + >>> MoneyColumn().process_bind_param( 230, '' ) + 230 + >>> MoneyColumn().process_bind_param( Decimal('2.30'), '' ) + 230 + >>> MoneyColumn().process_bind_param( '2.30', '' ) + 230 + >>> MoneyColumn().process_result_value( 230, '' ) + Decimal('2.3') + """ + + impl = types.Integer + + def process_bind_param(self, value, dialect): + if value is None or isinstance(value, int): + return value + elif isinstance(value, basestring) or isinstance(value, Decimal): + return int(Decimal(value)*100) + else: + raise Exception, "Incorrect amount:" + repr(value) + + def process_result_value(self, value, dialect): + if value is None: + return None + return Decimal(value)/100 + + +class BigIntColumn(types.TypeDecorator, types.Integer): + """Representing db-independent big integer """ + # Integer inheritance required for auto_increment flag + + impl = types.Integer + + def load_dialect_impl(self, dialect): + from sqlalchemy import databases + if dialect.name == 'mysql': + return databases.mysql.MSBigInteger() + elif dialect.name == 'postgres': + return databases.mysql.PGBigInteger() + return types.Integer() + + +class MappedBase(object): + """Provide dummy contrcutor""" + + def __init__(self, **kwargs): + for k, v in kwargs.iteritems(): + setattr(self, k, v) + + def get_columns_names(self): + return [i.name for i in self._sa_class_manager.mapper.c] + +def get_or_create(klass, session, **kwargs): + """ + Looks up an object with the given kwargs, creating one if necessary. + Returns a tuple of (object, created), where created is a boolean + specifying whether an object was created. + """ + assert kwargs, \ + 'get_or_create() must be passed at least one keyword argument' + try: + return session.query(klass).filter_by(**kwargs).one(), False + except NoResultFound: + try: + obj = klass(**kwargs) + session.add(obj) + session.flush() + return obj, True + except IntegrityError: + return session.query(klass).filter_by(**kwargs).one(), False + diff --git a/pyfpdb/AlchemyMappings.py b/pyfpdb/AlchemyMappings.py new file mode 100644 index 00000000..c2e088a9 --- /dev/null +++ b/pyfpdb/AlchemyMappings.py @@ -0,0 +1,464 @@ +# -*- coding: utf-8 -*- +"""@package AlchemyMappings +This package contains all classes to be mapped and mappers themselves +""" + +import logging +import re +from decimal import Decimal +from sqlalchemy.orm import mapper, relation, reconstructor +from sqlalchemy.sql import select +from collections import defaultdict + + +from AlchemyTables import * +from AlchemyFacilities import get_or_create, MappedBase +from DerivedStats import DerivedStats +from Exceptions import IncompleteHandError, FpdbError + + +class Player(MappedBase): + """Class reflecting Players db table""" + + @staticmethod + def get_or_create(session, siteId, name): + return get_or_create(Player, session, siteId=siteId, name=name)[0] + + def __str__(self): + return '' % (self.name, self.site and self.site.name) + + +class Gametype(MappedBase): + """Class reflecting Gametypes db table""" + + @staticmethod + def get_or_create(session, siteId, gametype): + map = zip( + ['type', 'base', 'category', 'limitType', 'smallBlind', 'bigBlind', 'smallBet', 'bigBet'], + ['type', 'base', 'category', 'limitType', 'sb', 'bb', 'dummy', 'dummy', ]) + gametype = dict([(new, gametype.get(old)) for new, old in map ]) + + hilo = "h" + if gametype['category'] in ('studhilo', 'omahahilo'): + hilo = "s" + elif gametype['category'] in ('razz','27_3draw','badugi'): + hilo = "l" + gametype['hiLo'] = hilo + + for f in ['smallBlind', 'bigBlind', 'smallBet', 'bigBet']: + if gametype[f] is None: + gametype[f] = 0 + gametype[f] = int(Decimal(gametype[f])*100) + + gametype['siteId'] = siteId + return get_or_create(Gametype, session, **gametype)[0] + + +class HandActions(object): + """Class reflecting HandsActions db table""" + def initFromImportedHand(self, hand, actions): + self.hand = hand + self.actions = {} + for street, street_actions in actions.iteritems(): + self.actions[street] = [] + for v in street_actions: + hp = hand.handplayers_by_name[v[0]] + self.actions[street].append({'street': street, 'pid': hp.id, 'seat': hp.seatNo, 'action':v}) + + @property + def flat_actions(self): + actions = [] + for street in self.hand.allStreets: + actions += self.actions[street] + return actions + + + +class HandInternal(DerivedStats): + """Class reflecting Hands db table""" + + def parseImportedHandStep1(self, hand): + """Extracts values to insert into from hand returned by HHC. No db is needed he""" + hand.players = hand.getAlivePlayers() + + # also save some data for step2. Those fields aren't in Hands table + self.siteId = hand.siteId + self.gametype_dict = hand.gametype + + self.attachHandPlayers(hand) + self.attachActions(hand) + + self.assembleHands(hand) + self.assembleHandsPlayers(hand) + + def parseImportedHandStep2(self, session): + """Fetching ids for gametypes and players""" + gametype = Gametype.get_or_create(session, self.siteId, self.gametype_dict) + self.gametypeId = gametype.id + for hp in self.handPlayers: + hp.playerId = Player.get_or_create(session, self.siteId, hp.name).id + + def getPlayerByName(self, name): + if not hasattr(self, 'handplayers_by_name'): + self.handplayers_by_name = {} + for hp in self.handPlayers: + pname = getattr(hp, 'name', None) or hp.player.name + self.handplayers_by_name[pname] = hp + return self.handplayers_by_name[name] + + def attachHandPlayers(self, hand): + """Fill HandInternal.handPlayers list. Create self.handplayers_by_name""" + hand.noSb = getattr(hand, 'noSb', None) + if hand.noSb is None and self.gametype_dict['base']=='hold': + saw_sb = False + for action in hand.actions[hand.actionStreets[0]]: # blindsantes + if action[1] == 'posts' and action[2] == 'small blind' and action[0] is not None: + saw_sb = True + hand.noSb = saw_sb + + self.handplayers_by_name = {} + for seat, name, chips in hand.players: + p = HandPlayer(hand = self, imported_hand=hand, seatNo=seat, + name=name, startCash=chips) + self.handplayers_by_name[name] = p + + def attachActions(self, hand): + """Create HandActions object""" + a = HandActions() + a.initFromImportedHand(self, hand.actions) + + def parseImportedTournament(self, hand, session): + """Fetching tourney, its type and players + + Must be called after Step2 + """ + if self.gametype_dict['type'] != 'tour': return + + # check for consistense + for i in ('buyin', 'tourNo'): + if not hasattr(hand, i): + raise IncompleteHandError( + "Field '%s' required for tournaments" % i, self.id, hand ) + + # repair old-style buyin value + m = re.match('\$(\d+)\+\$(\d+)', hand.buyin) + if m is not None: + hand.buyin, self.fee = m.groups() + + # fetch tourney type + tour_type_hand2db = { + 'buyin': 'buyin', + 'fee': 'fee', + 'speed': 'speed', + 'maxSeats': 'maxseats', + 'knockout': 'isKO', + 'rebuyOrAddon': 'isRebuy', + 'headsUp': 'isHU', + 'shootout': 'isShootout', + 'matrix': 'isMatrix', + 'sng': 'isSNG', + } + tour_type_index = dict([ + ( i_db, getattr(hand, i_hand, None) ) + for i_db, i_hand in tour_type_hand2db.iteritems() + ]) + tour_type_index['siteId'] = self.siteId + tour_type = TourneyType.get_or_create(session, **tour_type_index) + + # fetch and update tourney + tour = Tourney.get_or_create(session, hand.tourNo, tour_type.id) + cols = tour.get_columns_names() + for col in cols: + hand_val = getattr(hand, col, None) + if col in ('id', 'tourneyTypeId', 'comment', 'commentTs') or hand_val is None: + continue + db_val = getattr(tour, col, None) + if db_val is None: + setattr(tour, col, hand_val) + elif col == 'koBounty': + setattr(tour, col, max(db_val, hand_val)) + elif col == 'tourStartTime' and hand.handStart: + setattr(tour, col, min(db_val, hand.handStart)) + + if tour.entries is None and tour_type.sng: + tour.entries = tour_type.maxSeats + + # fetch and update tourney players + for hp in self.handPlayers: + tp = TourneyPlayer.get_or_create(session, tour.id, hp.playerId) + # FIXME: other TourneysPlayers should be added here + + session.flush() + + def isDuplicate(self, session): + """Checks if current hand already exists in db + + siteHandNo ans gameTypeId have to be setted + """ + return session.query(HandInternal).filter_by( + siteHandNo=self.siteHandNo, gametypeId=self.gametypeId).count()!=0 + + def __str__(self): + s = list() + for i in self._sa_class_manager.mapper.c: + s.append('%25s %s' % (i, getattr(self, i.name))) + + s+=['', ''] + for i,p in enumerate(self.handPlayers): + s.append('%d. %s' % (i, p.name or '???')) + s.append(str(p)) + return '\n'.join(s) + + @property + def boardcards(self): + cards = [] + for i in range(5): + cards.append(getattr(self, 'boardcard%d' % (i+1), None)) + return filter(bool, cards) + + @property + def HandClass(self): + """Return HoldemOmahaHand or something like this""" + import Hand + if self.gametype.base == 'hold': + return Hand.HoldemOmahaHand + elif self.gametype.base == 'draw': + return Hand.DrawHand + elif self.gametype.base == 'stud': + return Hand.StudHand + raise Exception("Unknow gametype.base: '%s'" % self.gametype.base) + + @property + def allStreets(self): + return self.HandClass.allStreets + + @property + def actionStreets(self): + return self.HandClass.actionStreets + + + +class HandPlayer(MappedBase): + """Class reflecting HandsPlayers db table""" + def __init__(self, **kwargs): + if 'imported_hand' in kwargs and 'seatNo' in kwargs: + imported_hand = kwargs.pop('imported_hand') + self.position = self.getPosition(imported_hand, kwargs['seatNo']) + super(HandPlayer, self).__init__(**kwargs) + + @reconstructor + def init_on_load(self): + self.name = self.player.name + + @staticmethod + def getPosition(hand, seat): + """Returns position value like 'B', 'S', '0', '1', ... + + >>> class A(object): pass + ... + >>> A.noSb = False + >>> A.maxseats = 6 + >>> A.buttonpos = 2 + >>> A.gametype = {'base': 'hold'} + >>> A.players = [(i, None, None) for i in (2, 4, 5, 6)] + >>> HandPlayer.getPosition(A, 6) # cut off + '1' + >>> HandPlayer.getPosition(A, 2) # button + '0' + >>> HandPlayer.getPosition(A, 4) # SB + 'S' + >>> HandPlayer.getPosition(A, 5) # BB + 'B' + >>> A.noSb = True + >>> HandPlayer.getPosition(A, 5) # MP3 + '2' + >>> HandPlayer.getPosition(A, 6) # cut off + '1' + >>> HandPlayer.getPosition(A, 2) # button + '0' + >>> HandPlayer.getPosition(A, 4) # BB + 'B' + """ + from itertools import chain + if hand.gametype['base'] == 'stud': + # FIXME: i've never played stud so plz check & del comment \\grindi + bringin = None + for action in chain(*[self.actions[street] for street in hand.allStreets]): + if action[1]=='bringin': + bringin = action[0] + break + if bringin is None: + raise Exception, "Cannot find bringin" + # name -> seat + bringin = int(filter(lambda p: p[1]==bringin, bringin)[0]) + seat = (int(seat) - int(bringin))%int(hand.maxseats) + return str(seat) + else: + seats_occupied = sorted([seat_ for seat_, name, chips in hand.players], key=int) + if hand.buttonpos not in seats_occupied: + # i.e. something like + # Seat 3: PlayerX ($0), is sitting out + # The button is in seat #3 + hand.buttonpos = max(seats_occupied, + key = lambda s: int(s) + if int(s) <= int(hand.buttonpos) + else int(s) - int(hand.maxseats) + ) + seats_occupied = sorted(seats_occupied, + key = lambda seat_: ( + - seats_occupied.index(seat_) + + seats_occupied.index(hand.buttonpos) + + 2) % len(seats_occupied) + ) + # now (if SB presents) seats_occupied contains seats in order: BB, SB, BU, CO, MP3, ... + if hand.noSb: + # fix order in the case nosb + seats_occupied = seats_occupied[1:] + seats_occupied[0:1] + seats_occupied.insert(1, -1) + seat = seats_occupied.index(seat) + if seat == 0: + return 'B' + elif seat == 1: + return 'S' + else: + return str(seat-2) + + @property + def cards(self): + cards = [] + for i in range(7): + cards.append(getattr(self, 'card%d' % (i+1), None)) + return filter(bool, cards) + + def __str__(self): + s = list() + for i in self._sa_class_manager.mapper.c: + s.append('%45s %s' % (i, getattr(self, i.name))) + return '\n'.join(s) + + +class Site(object): + """Class reflecting Players db table""" + INITIAL_DATA = [ + (1 , 'Full Tilt Poker','USD'), + (2 , 'PokerStars', 'USD'), + (3 , 'Everleaf', 'USD'), + (4 , 'Win2day', 'USD'), + (5 , 'OnGame', 'USD'), + (6 , 'UltimateBet', 'USD'), + (7 , 'Betfair', 'USD'), + (8 , 'Absolute', 'USD'), + (9 , 'PartyPoker', 'USD'), + (10, 'Partouche', 'EUR'), + ] + INITIAL_DATA_KEYS = ('id', 'name', 'currency') + + INITIAL_DATA_DICTS = [ dict(zip(INITIAL_DATA_KEYS, datum)) for datum in INITIAL_DATA ] + + @classmethod + def insert_initial(cls, connection): + connection.execute(sites_table.insert(), cls.INITIAL_DATA_DICTS) + + +class Tourney(MappedBase): + """Class reflecting Tourneys db table""" + + @classmethod + def get_or_create(cls, session, siteTourneyNo, tourneyTypeId): + """Fetch tourney by index or creates one if none. """ + return get_or_create(cls, session, siteTourneyNo=siteTourneyNo, + tourneyTypeId=tourneyTypeId)[0] + + + +class TourneyType(MappedBase): + """Class reflecting TourneysType db table""" + + @classmethod + def get_or_create(cls, session, **kwargs): + """Fetch tourney type by index or creates one if none + + Required kwargs: + buyin fee speed maxSeats knockout + rebuyOrAddon headsUp shootout matrix sng + """ + return get_or_create(cls, session, **kwargs)[0] + + +class TourneyPlayer(MappedBase): + """Class reflecting TourneysPlayers db table""" + + @classmethod + def get_or_create(cls, session, tourneyId, playerId): + """Fetch tourney player by index or creates one if none """ + return get_or_create(cls, session, tourneyId=tourneyId, playerId=playerId) + + +class Version(object): + """Provides read/write access for version var""" + CURRENT_VERSION = 120 # db version for current release + # 119 - first alchemy version + # 120 - add m_factor + + conn = None + ver = None + def __init__(self, connection=None): + if self.__class__.conn is None: + self.__class__.conn = connection + + @classmethod + def is_wrong(cls): + return cls.get() != cls.CURRENT_VERSION + + @classmethod + def get(cls): + if cls.ver is None: + try: + cls.ver = cls.conn.execute(select(['version'], settings_table)).fetchone()[0] + except: + return None + return cls.ver + + @classmethod + def set(cls, value): + if cls.conn.execute(settings_table.select()).rowcount==0: + cls.conn.execute(settings_table.insert(), version=value) + else: + cls.conn.execute(settings_table.update().values(version=value)) + cls.ver = value + + @classmethod + def set_initial(cls): + cls.set(cls.CURRENT_VERSION) + + +mapper (Gametype, gametypes_table, properties={ + 'hands': relation(HandInternal, backref='gametype'), +}) +mapper (Player, players_table, properties={ + 'playerHands': relation(HandPlayer, backref='player'), + 'playerTourney': relation(TourneyPlayer, backref='player'), +}) +mapper (Site, sites_table, properties={ + 'gametypes': relation(Gametype, backref = 'site'), + 'players': relation(Player, backref = 'site'), + 'tourneyTypes': relation(TourneyType, backref = 'site'), +}) +mapper (HandActions, hands_actions_table, properties={}) +mapper (HandInternal, hands_table, properties={ + 'handPlayers': relation(HandPlayer, backref='hand'), + 'actions_all': relation(HandActions, backref='hand', uselist=False), +}) +mapper (HandPlayer, hands_players_table, properties={}) + +mapper (Tourney, tourneys_table) +mapper (TourneyType, tourney_types_table, properties={ + 'tourneys': relation(Tourney, backref='type'), +}) +mapper (TourneyPlayer, tourneys_players_table) + +class LambdaKeyDict(defaultdict): + """Operates like defaultdict but passes key argument to the factory function""" + def __missing__(key): + return self.default_factory(key) + diff --git a/pyfpdb/AlchemyTables.py b/pyfpdb/AlchemyTables.py new file mode 100644 index 00000000..3165a480 --- /dev/null +++ b/pyfpdb/AlchemyTables.py @@ -0,0 +1,438 @@ +# -*- coding: utf-8 -*- +"""@package AlchemyTables +Contains all sqlalchemy tables +""" + +from sqlalchemy import Table, Float, Column, Integer, String, MetaData, \ + ForeignKey, Boolean, SmallInteger, DateTime, Text, Index, CHAR, \ + PickleType, Unicode + +from AlchemyFacilities import CardColumn, MoneyColumn, BigIntColumn + + +metadata = MetaData() + + +autorates_table = Table('Autorates', metadata, + Column('id', Integer, primary_key=True, nullable=False), + Column('playerId', Integer, ForeignKey("Players.id"), nullable=False), + Column('gametypeId', SmallInteger, ForeignKey("Gametypes.id"), nullable=False), + Column('description', String(50), nullable=False), + Column('shortDesc', CHAR(8), nullable=False), + Column('ratingTime', DateTime, nullable=False), + Column('handCount', Integer, nullable=False), + mysql_charset='utf8', + mysql_engine='InnoDB', +) + + +gametypes_table = Table('Gametypes', metadata, + Column('id', SmallInteger, primary_key=True), + Column('siteId', SmallInteger, ForeignKey("Sites.id"), nullable=False), # SMALLINT + Column('type', String(4), nullable=False), # char(4) NOT NULL + Column('base', String(4), nullable=False), # char(4) NOT NULL + Column('category', String(9), nullable=False), # varchar(9) NOT NULL + Column('limitType', CHAR(2), nullable=False), # char(2) NOT NULL + Column('hiLo', CHAR(1), nullable=False), # char(1) NOT NULL + Column('smallBlind', Integer(3)), # int + Column('bigBlind', Integer(3)), # int + Column('smallBet', Integer(3), nullable=False), # int NOT NULL + Column('bigBet', Integer(3), nullable=False), # int NOT NULL + mysql_charset='utf8', + mysql_engine='InnoDB', +) + + +hands_table = Table('Hands', metadata, + Column('id', BigIntColumn, primary_key=True), + Column('tableName', String(30), nullable=False), + Column('siteHandNo', BigIntColumn, nullable=False), + Column('gametypeId', SmallInteger, ForeignKey('Gametypes.id'), nullable=False), + Column('handStart', DateTime, nullable=False), + Column('importTime', DateTime, nullable=False), + Column('seats', SmallInteger, nullable=False), + Column('maxSeats', SmallInteger, nullable=False), + + Column('boardcard1', CardColumn), + Column('boardcard2', CardColumn), + Column('boardcard3', CardColumn), + Column('boardcard4', CardColumn), + Column('boardcard5', CardColumn), + Column('texture', SmallInteger), + Column('playersVpi', SmallInteger, nullable=False), + Column('playersAtStreet1', SmallInteger, nullable=False, default=0), + Column('playersAtStreet2', SmallInteger, nullable=False, default=0), + Column('playersAtStreet3', SmallInteger, nullable=False, default=0), + Column('playersAtStreet4', SmallInteger, nullable=False, default=0), + Column('playersAtShowdown',SmallInteger, nullable=False), + Column('street0Raises', SmallInteger, nullable=False), + Column('street1Raises', SmallInteger, nullable=False), + Column('street2Raises', SmallInteger, nullable=False), + Column('street3Raises', SmallInteger, nullable=False), + Column('street4Raises', SmallInteger, nullable=False), + Column('street1Pot', MoneyColumn), + Column('street2Pot', MoneyColumn), + Column('street3Pot', MoneyColumn), + Column('street4Pot', MoneyColumn), + Column('showdownPot', MoneyColumn), + Column('comment', Text), + Column('commentTs', DateTime), + mysql_charset='utf8', + mysql_engine='InnoDB', +) +Index('siteHandNo', hands_table.c.siteHandNo, hands_table.c.gametypeId, unique=True) + + +hands_actions_table = Table('HandsActions', metadata, + Column('id', BigIntColumn, primary_key=True, nullable=False), + Column('handId', BigIntColumn, ForeignKey("Hands.id"), nullable=False), + Column('actions', PickleType, nullable=False), + mysql_charset='utf8', + mysql_engine='InnoDB', +) + + +hands_players_table = Table('HandsPlayers', metadata, + Column('id', BigIntColumn, primary_key=True), + Column('handId', BigIntColumn, ForeignKey("Hands.id"), nullable=False), + Column('playerId', Integer, ForeignKey("Players.id"), nullable=False), + Column('startCash', MoneyColumn), + Column('position', CHAR(1)), #CHAR(1) + Column('seatNo', SmallInteger, nullable=False), #SMALLINT NOT NULL + + Column('card1', CardColumn), #smallint NOT NULL, + Column('card2', CardColumn), #smallint NOT NULL + Column('card3', CardColumn), #smallint + Column('card4', CardColumn), #smallint + Column('card5', CardColumn), #smallint + Column('card6', CardColumn), #smallint + Column('card7', CardColumn), #smallint + Column('startCards', SmallInteger), #smallint + + Column('m_factor', Integer), # null for ring games + Column('ante', MoneyColumn), #INT + Column('winnings', MoneyColumn, nullable=False, default=0), #int NOT NULL + Column('rake', MoneyColumn, nullable=False, default=0), #int NOT NULL + Column('totalProfit', MoneyColumn), #INT + Column('comment', Text), #text + Column('commentTs', DateTime), #DATETIME + Column('tourneysPlayersId', BigIntColumn, ForeignKey("TourneysPlayers.id"),), #BIGINT UNSIGNED + Column('tourneyTypeId', Integer, ForeignKey("TourneyTypes.id"),), #SMALLINT UNSIGNED + + Column('wonWhenSeenStreet1',Float), #FLOAT + Column('wonWhenSeenStreet2',Float), #FLOAT + Column('wonWhenSeenStreet3',Float), #FLOAT + Column('wonWhenSeenStreet4',Float), #FLOAT + Column('wonAtSD', Float), #FLOAT + + Column('street0VPI', Boolean), #BOOLEAN + Column('street0Aggr', Boolean), #BOOLEAN + Column('street0_3BChance', Boolean), #BOOLEAN + Column('street0_3BDone', Boolean), #BOOLEAN + Column('street0_4BChance', Boolean), #BOOLEAN + Column('street0_4BDone', Boolean), #BOOLEAN + Column('other3BStreet0', Boolean), #BOOLEAN + Column('other4BStreet0', Boolean), #BOOLEAN + + Column('street1Seen', Boolean), #BOOLEAN + Column('street2Seen', Boolean), #BOOLEAN + Column('street3Seen', Boolean), #BOOLEAN + Column('street4Seen', Boolean), #BOOLEAN + Column('sawShowdown', Boolean), #BOOLEAN + + Column('street1Aggr', Boolean), #BOOLEAN + Column('street2Aggr', Boolean), #BOOLEAN + Column('street3Aggr', Boolean), #BOOLEAN + Column('street4Aggr', Boolean), #BOOLEAN + + Column('otherRaisedStreet0',Boolean), #BOOLEAN + Column('otherRaisedStreet1',Boolean), #BOOLEAN + Column('otherRaisedStreet2',Boolean), #BOOLEAN + Column('otherRaisedStreet3',Boolean), #BOOLEAN + Column('otherRaisedStreet4',Boolean), #BOOLEAN + Column('foldToOtherRaisedStreet0', Boolean), #BOOLEAN + Column('foldToOtherRaisedStreet1', Boolean), #BOOLEAN + Column('foldToOtherRaisedStreet2', Boolean), #BOOLEAN + Column('foldToOtherRaisedStreet3', Boolean), #BOOLEAN + Column('foldToOtherRaisedStreet4', Boolean), #BOOLEAN + + Column('stealAttemptChance', Boolean), #BOOLEAN + Column('stealAttempted', Boolean), #BOOLEAN + Column('foldBbToStealChance', Boolean), #BOOLEAN + Column('foldedBbToSteal', Boolean), #BOOLEAN + Column('foldSbToStealChance', Boolean), #BOOLEAN + Column('foldedSbToSteal', Boolean), #BOOLEAN + + Column('street1CBChance', Boolean), #BOOLEAN + Column('street1CBDone', Boolean), #BOOLEAN + Column('street2CBChance', Boolean), #BOOLEAN + Column('street2CBDone', Boolean), #BOOLEAN + Column('street3CBChance', Boolean), #BOOLEAN + Column('street3CBDone', Boolean), #BOOLEAN + Column('street4CBChance', Boolean), #BOOLEAN + Column('street4CBDone', Boolean), #BOOLEAN + + Column('foldToStreet1CBChance', Boolean), #BOOLEAN + Column('foldToStreet1CBDone', Boolean), #BOOLEAN + Column('foldToStreet2CBChance', Boolean), #BOOLEAN + Column('foldToStreet2CBDone', Boolean), #BOOLEAN + Column('foldToStreet3CBChance', Boolean), #BOOLEAN + Column('foldToStreet3CBDone', Boolean), #BOOLEAN + Column('foldToStreet4CBChance', Boolean), #BOOLEAN + Column('foldToStreet4CBDone', Boolean), #BOOLEAN + + Column('street1CheckCallRaiseChance',Boolean), #BOOLEAN + Column('street1CheckCallRaiseDone', Boolean), #BOOLEAN + Column('street2CheckCallRaiseChance',Boolean), #BOOLEAN + Column('street2CheckCallRaiseDone', Boolean), #BOOLEAN + Column('street3CheckCallRaiseChance',Boolean), #BOOLEAN + Column('street3CheckCallRaiseDone', Boolean), #BOOLEAN + Column('street4CheckCallRaiseChance',Boolean), #BOOLEAN + Column('street4CheckCallRaiseDone', Boolean), #BOOLEAN + + Column('street0Calls', SmallInteger), #TINYINT + Column('street1Calls', SmallInteger), #TINYINT + Column('street2Calls', SmallInteger), #TINYINT + Column('street3Calls', SmallInteger), #TINYINT + Column('street4Calls', SmallInteger), #TINYINT + Column('street0Bets', SmallInteger), #TINYINT + Column('street1Bets', SmallInteger), #TINYINT + Column('street2Bets', SmallInteger), #TINYINT + Column('street3Bets', SmallInteger), #TINYINT + Column('street4Bets', SmallInteger), #TINYINT + Column('street0Raises', SmallInteger), #TINYINT + Column('street1Raises', SmallInteger), #TINYINT + Column('street2Raises', SmallInteger), #TINYINT + Column('street3Raises', SmallInteger), #TINYINT + Column('street4Raises', SmallInteger), #TINYINT + + Column('actionString', String(15)), #VARCHAR(15) + mysql_charset='utf8', + mysql_engine='InnoDB', +) + + +hud_cache_table = Table('HudCache', metadata, + Column('id', BigIntColumn, primary_key=True), + Column('gametypeId', SmallInteger, ForeignKey("Gametypes.id"), nullable=False), # SMALLINT + Column('playerId', Integer, ForeignKey("Players.id"), nullable=False), # SMALLINT + Column('activeSeats', SmallInteger, nullable=False), # SMALLINT NOT NULL + Column('position', CHAR(1)), # CHAR(1) + Column('tourneyTypeId', Integer, ForeignKey("TourneyTypes.id") ), # SMALLINT + Column('styleKey', CHAR(7), nullable=False), # CHAR(7) NOT NULL + Column('m_factor', Integer), + Column('HDs', Integer, nullable=False), # INT NOT NULL + + Column('wonWhenSeenStreet1', Float), # FLOAT + Column('wonWhenSeenStreet2', Float), # FLOAT + Column('wonWhenSeenStreet3', Float), # FLOAT + Column('wonWhenSeenStreet4', Float), # FLOAT + Column('wonAtSD', Float), # FLOAT + + Column('street0VPI', Integer), # INT + Column('street0Aggr', Integer), # INT + Column('street0_3BChance', Integer), # INT + Column('street0_3BDone', Integer), # INT + Column('street0_4BChance', Integer), # INT + Column('street0_4BDone', Integer), # INT + Column('other3BStreet0', Integer), # INT + Column('other4BStreet0', Integer), # INT + + Column('street1Seen', Integer), # INT + Column('street2Seen', Integer), # INT + Column('street3Seen', Integer), # INT + Column('street4Seen', Integer), # INT + Column('sawShowdown', Integer), # INT + + Column('street1Aggr', Integer), # INT + Column('street2Aggr', Integer), # INT + Column('street3Aggr', Integer), # INT + Column('street4Aggr', Integer), # INT + + Column('otherRaisedStreet0', Integer), # INT + Column('otherRaisedStreet1', Integer), # INT + Column('otherRaisedStreet2', Integer), # INT + Column('otherRaisedStreet3', Integer), # INT + Column('otherRaisedStreet4', Integer), # INT + Column('foldToOtherRaisedStreet0', Integer), # INT + Column('foldToOtherRaisedStreet1', Integer), # INT + Column('foldToOtherRaisedStreet2', Integer), # INT + Column('foldToOtherRaisedStreet3', Integer), # INT + Column('foldToOtherRaisedStreet4', Integer), # INT + + Column('stealAttemptChance', Integer), # INT + Column('stealAttempted', Integer), # INT + Column('foldBbToStealChance', Integer), # INT + Column('foldedBbToSteal', Integer), # INT + Column('foldSbToStealChance', Integer), # INT + Column('foldedSbToSteal', Integer), # INT + + Column('street1CBChance', Integer), # INT + Column('street1CBDone', Integer), # INT + Column('street2CBChance', Integer), # INT + Column('street2CBDone', Integer), # INT + Column('street3CBChance', Integer), # INT + Column('street3CBDone', Integer), # INT + Column('street4CBChance', Integer), # INT + Column('street4CBDone', Integer), # INT + + Column('foldToStreet1CBChance', Integer), # INT + Column('foldToStreet1CBDone', Integer), # INT + Column('foldToStreet2CBChance', Integer), # INT + Column('foldToStreet2CBDone', Integer), # INT + Column('foldToStreet3CBChance', Integer), # INT + Column('foldToStreet3CBDone', Integer), # INT + Column('foldToStreet4CBChance', Integer), # INT + Column('foldToStreet4CBDone', Integer), # INT + + Column('totalProfit', Integer), # INT + + Column('street1CheckCallRaiseChance', Integer), # INT + Column('street1CheckCallRaiseDone', Integer), # INT + Column('street2CheckCallRaiseChance', Integer), # INT + Column('street2CheckCallRaiseDone', Integer), # INT + Column('street3CheckCallRaiseChance', Integer), # INT + Column('street3CheckCallRaiseDone', Integer), # INT + Column('street4CheckCallRaiseChance', Integer), # INT + Column('street4CheckCallRaiseDone', Integer), # INT + + Column('street0Calls', Integer), # INT + Column('street1Calls', Integer), # INT + Column('street2Calls', Integer), # INT + Column('street3Calls', Integer), # INT + Column('street4Calls', Integer), # INT + Column('street0Bets', Integer), # INT + Column('street1Bets', Integer), # INT + Column('street2Bets', Integer), # INT + Column('street3Bets', Integer), # INT + Column('street4Bets', Integer), # INT + Column('street0Raises', Integer), # INT + Column('street1Raises', Integer), # INT + Column('street2Raises', Integer), # INT + Column('street3Raises', Integer), # INT + Column('street4Raises', Integer), # INT + mysql_charset='utf8', + mysql_engine='InnoDB', +) + + +players_table = Table('Players', metadata, + Column('id', Integer, primary_key=True), + Column('name', Unicode(32), nullable=False), # VARCHAR(32) CHARACTER SET utf8 NOT NULL + Column('siteId', SmallInteger, ForeignKey("Sites.id"), nullable=False), # SMALLINT + Column('comment', Text), # text + Column('commentTs', DateTime), # DATETIME + mysql_charset='utf8', + mysql_engine='InnoDB', +) +Index('name', players_table.c.name, players_table.c.siteId, unique=True) + + +settings_table = Table('Settings', metadata, + Column('version', SmallInteger, nullable=False), + mysql_charset='utf8', + mysql_engine='InnoDB', +) + + +sites_table = Table('Sites', metadata, + Column('id', SmallInteger, primary_key=True), + Column('name', String(32), nullable=False), # varchar(32) NOT NULL + Column('currency', String(3), nullable=False), # char(3) NOT NULL + mysql_charset='utf8', + mysql_engine='InnoDB', +) + + +tourneys_table = Table('Tourneys', metadata, + Column('id', Integer, primary_key=True), + Column('tourneyTypeId', Integer, ForeignKey("TourneyTypes.id"), nullable=False, default=1), + Column('siteTourneyNo', BigIntColumn, nullable=False), # BIGINT NOT NULL + Column('entries', Integer), # INT NOT NULL + Column('prizepool', Integer), # INT NOT NULL + Column('tourStartTime', DateTime), # DATETIME NOT NULL + Column('tourEndTime', DateTime), # DATETIME + Column('buyinChips', Integer), # INT + Column('tourneyName', String(40)), # varchar(40) + # Mask use : 1=Positionnal Winnings|2=Match1|4=Match2|...|pow(2,n)=Matchn + Column('matrixIdProcessed',SmallInteger, default=0), # TINYINT UNSIGNED DEFAULT 0 + Column('rebuyChips', Integer, default=0), # INT DEFAULT 0 + Column('addonChips', Integer, default=0), # INT DEFAULT 0 + Column('rebuyAmount', MoneyColumn, default=0), # INT DEFAULT 0 + Column('addonAmount', MoneyColumn, default=0), # INT DEFAULT 0 + Column('totalRebuys', Integer, default=0), # INT DEFAULT 0 + Column('totalAddons', Integer, default=0), # INT DEFAULT 0 + Column('koBounty', Integer, default=0), # INT DEFAULT 0 + Column('comment', Text), # TEXT + Column('commentTs', DateTime), # DATETIME + mysql_charset='utf8', + mysql_engine='InnoDB', +) +Index('siteTourneyNo', tourneys_table.c.siteTourneyNo, tourneys_table.c.tourneyTypeId, unique=True) + + +tourney_types_table = Table('TourneyTypes', metadata, + Column('id', Integer, primary_key=True), + Column('siteId', SmallInteger, ForeignKey("Sites.id"), nullable=False), + Column('buyin', Integer, nullable=False), # INT NOT NULL + Column('fee', Integer, nullable=False, default=0), # INT NOT NULL + Column('maxSeats', Boolean, nullable=False, default=-1), # INT NOT NULL DEFAULT -1 + Column('knockout', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False + Column('rebuyOrAddon', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False + Column('speed', String(10)), # varchar(10) + Column('headsUp', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False + Column('shootout', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False + Column('matrix', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False + Column('sng', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False + mysql_charset='utf8', + mysql_engine='InnoDB', +) +Index('tourneyTypes_all', + tourney_types_table.c.siteId, tourney_types_table.c.buyin, tourney_types_table.c.fee, + tourney_types_table.c.maxSeats, tourney_types_table.c.knockout, tourney_types_table.c.rebuyOrAddon, + tourney_types_table.c.speed, tourney_types_table.c.headsUp, tourney_types_table.c.shootout, + tourney_types_table.c.matrix, tourney_types_table.c.sng) + + +tourneys_players_table = Table('TourneysPlayers', metadata, + Column('id', BigIntColumn, primary_key=True), + Column('tourneyId', Integer, ForeignKey("Tourneys.id"), nullable=False), + Column('playerId', Integer, ForeignKey("Players.id"), nullable=False), + Column('payinAmount', Integer), # INT NOT NULL + Column('rank', Integer), # INT NOT NULL + Column('winnings', Integer), # INT NOT NULL + Column('nbRebuys', Integer, default=0), # INT DEFAULT 0 + Column('nbAddons', Integer, default=0), # INT DEFAULT 0 + Column('nbKO', Integer, default=0), # INT DEFAULT 0 + Column('comment', Text), # TEXT + Column('commentTs', DateTime), # DATETIME + mysql_charset='utf8', + mysql_engine='InnoDB', +) +Index('tourneyId', tourneys_players_table.c.tourneyId, tourneys_players_table.c.playerId, unique=True) + + +def sss(): + "Debug function. Returns (config, sql, db)" + + import Configuration, SQL, Database, os + class Dummy(object): + pass + self = Dummy() + self.config = Configuration.Config() + self.settings = {} + if (os.sep=="/"): + self.settings['os']="linuxmac" + else: + self.settings['os']="windows" + + self.settings.update(self.config.get_db_parameters()) + self.settings.update(self.config.get_tv_parameters()) + self.settings.update(self.config.get_import_parameters()) + self.settings.update(self.config.get_default_paths()) + + self.sql = SQL.Sql( db_server = self.settings['db-server']) + self.db = Database.Database(self.config, sql = self.sql) + + return self.config, self.sql, self.db + From 62935664c80099f93d25b5dd4ca0628f9cc56f71 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Fri, 1 Jan 2010 22:57:25 +0000 Subject: [PATCH 31/36] set stats color to fgcolor --- pyfpdb/Hud.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 2b6d0237..1a27b682 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -606,6 +606,7 @@ class Hud: if self.update_table_position() == False: # we got killed by finding our table was gone return + self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) for s in self.stat_dict: try: statd = self.stat_dict[s] @@ -629,20 +630,16 @@ class Hud: window = self.stat_windows[statd['seat']] if this_stat.hudcolor != "": - self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.hudcolor)) else: - self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) - window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#FFFFFF")) + window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) if this_stat.stat_loth != "": if number[0] < (float(this_stat.stat_loth)/100): - self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_locolor)) if this_stat.stat_hith != "": if number[0] > (float(this_stat.stat_hith)/100): - self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_hicolor)) window.label[r][c].set_text(statstring) From bad744fd80ac6092a7d02deda0721157db9e61bf Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 15 Jan 2010 13:50:46 +0800 Subject: [PATCH 32/36] [NEWIMPORT] setPositions(), fix aggr function PFR now actually works --- pyfpdb/DerivedStats.py | 73 +++++++++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 22 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 7c50178b..920d60cf 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -48,6 +48,7 @@ class DerivedStats(): self.handsplayers[player[1]]['sawShowdown'] = False self.handsplayers[player[1]]['wonAtSD'] = 0.0 self.handsplayers[player[1]]['startCards'] = 0 + self.handsplayers[player[1]]['position'] = 2 for i in range(5): self.handsplayers[player[1]]['street%dCalls' % i] = 0 self.handsplayers[player[1]]['street%dBets' % i] = 0 @@ -56,7 +57,6 @@ class DerivedStats(): self.handsplayers[player[1]]['street%dCBDone' %i] = False #FIXME - Everything below this point is incomplete. - self.handsplayers[player[1]]['position'] = 2 self.handsplayers[player[1]]['tourneyTypeId'] = 1 self.handsplayers[player[1]]['street0_3BChance'] = False self.handsplayers[player[1]]['street0_3BDone'] = False @@ -174,31 +174,41 @@ class DerivedStats(): self.handsplayers[player[1]]['card%s' % (i+1)] = Card.encodeCard(card) self.handsplayers[player[1]]['startCards'] = Card.calcStartCards(hand, player[1]) - # position, - #Stud 3rd street card test - # denny501: brings in for $0.02 - # s0rrow: calls $0.02 - # TomSludge: folds - # Soroka69: calls $0.02 - # rdiezchang: calls $0.02 (Seat 8) - # u.pressure: folds (Seat 1) - # 123smoothie: calls $0.02 - # gashpor: calls $0.02 - + self.setPositions(hand) # Additional stats # 3betSB, 3betBB # Squeeze, Ratchet? - def getPosition(hand, seat): - """Returns position value like 'B', 'S', 0, 1, ...""" - # Flop/Draw games with blinds - # Need a better system??? - # -2 BB - B (all) - # -1 SB - S (all) - # 0 Button - # 1 Cutoff - # 2 Hijack + def setPositions(self, hand): + """Sets the position for each player in HandsPlayers + any blinds are negative values, and the last person to act on the + first betting round is 0 + NOTE: HU, both values are negative for non-stud games + NOTE2: I've never seen a HU stud match""" + # The position calculation must be done differently for Stud and other games as + # Stud the 'blind' acts first - in all other games they act last. + # + #This function is going to get it wrong when there in situations where there + # is no small blind. I can live with that. + positions = [7, 6, 5, 4, 3, 2, 1, 0, 'S', 'B'] + actions = hand.actions[hand.holeStreets[0]] + players = self.pfbao(actions) + seats = len(players) + map = [] + if hand.gametype['base'] == 'stud': + # Could posibly change this to be either -2 or -1 depending if they complete or bring-in + # First player to act is -1, last player is 0 for 6 players it should look like: + # ['S', 4, 3, 2, 1, 0] + map = positions[-seats-1:-1] # Copy required positions from postions array anding in -1 + map = map[-1:] + map[0:-1] # and move the -1 to the start of that array + else: + # For 6 players is should look like: + # [3, 2, 1, 0, 'S', 'B'] + map = positions[-seats:] # Copy required positions from array ending in -2 + + for i, player in enumerate(players): + self.handsplayers[player]['position'] = map[i] def assembleHudCache(self, hand): # No real work to be done - HandsPlayers data already contains the correct info @@ -362,11 +372,13 @@ class DerivedStats(): def aggr(self, hand, i): aggrers = set() - for act in hand.actions[hand.actionStreets[i]]: + # Growl - actionStreets contains 'BLINDSANTES', which isn't actually an action street + for act in hand.actions[hand.actionStreets[i+1]]: if act[1] in ('completes', 'bets', 'raises'): aggrers.add(act[0]) for player in hand.players: + #print "DEBUG: actionStreet[%s]: %s" %(hand.actionStreets[i+1], i) if player[1] in aggrers: self.handsplayers[player[1]]['street%sAggr' % i] = True else: @@ -402,6 +414,23 @@ class DerivedStats(): players.add(action[0]) return players + def pfbao(self, actions, f=None, l=None, unique=True): + """Helper method. Returns set of PlayersFilteredByActionsOrdered + + f - forbidden actions + l - limited to actions + """ + # Note, this is an adaptation of function 5 from: + # http://www.peterbe.com/plog/uniqifiers-benchmark + seen = {} + players = [] + for action in actions: + if l is not None and action[1] not in l: continue + if f is not None and action[1] in f: continue + if action[0] in seen and unique: continue + seen[action[0]] = 1 + players.append(action[0]) + return players def firstsBetOrRaiser(self, actions): """Returns player name that placed the first bet or raise. From 700a68bcc803647251dde8ce53c44b151458bd16 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 15 Jan 2010 18:29:16 +0800 Subject: [PATCH 33/36] [NEWIMPORT] calcCheckCallRaise() Modify function from Grigorij to calculate check/call --- pyfpdb/DerivedStats.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 920d60cf..fe857ae4 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -55,6 +55,8 @@ class DerivedStats(): for i in range(1,5): self.handsplayers[player[1]]['street%dCBChance' %i] = False self.handsplayers[player[1]]['street%dCBDone' %i] = False + self.handsplayers[player[1]]['street%dCheckCallRaiseChance' %i] = False + self.handsplayers[player[1]]['street%dCheckCallRaiseDone' %i] = False #FIXME - Everything below this point is incomplete. self.handsplayers[player[1]]['tourneyTypeId'] = 1 @@ -72,8 +74,6 @@ class DerivedStats(): self.handsplayers[player[1]]['foldToOtherRaisedStreet%d' %i] = False self.handsplayers[player[1]]['foldToStreet%dCBChance' %i] = False self.handsplayers[player[1]]['foldToStreet%dCBDone' %i] = False - self.handsplayers[player[1]]['street%dCheckCallRaiseChance' %i] = False - self.handsplayers[player[1]]['street%dCheckCallRaiseDone' %i] = False self.assembleHands(self.hand) self.assembleHandsPlayers(self.hand) @@ -175,6 +175,7 @@ class DerivedStats(): self.handsplayers[player[1]]['startCards'] = Card.calcStartCards(hand, player[1]) self.setPositions(hand) + self.calcCheckCallRaise(hand) # Additional stats # 3betSB, 3betBB # Squeeze, Ratchet? @@ -352,12 +353,11 @@ class DerivedStats(): pname, act = action[0], action[1] if act in ('bets', 'raises') and initial_raiser is None: initial_raiser = pname - elif act == 'check' and initial_raiser is None: + elif act == 'checks' and initial_raiser is None: checkers.add(pname) elif initial_raiser is not None and pname in checkers: - hp = self.handplayers_by_name[pname] - setattr(hp, 'street%dCheckCallRaiseChance' % i, True) - setattr(hp, 'street%dCheckCallRaiseDone' % i, act!='folds') + self.handsplayers[pname]['street%dCheckCallRaiseChance' % i] = True + self.handsplayers[pname]['street%dCheckCallRaiseDone' % i] = act!='folds' def seen(self, hand, i): pas = set() From ecf1c6b878ebcc02f49c751c6c9228014812f316 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 15 Jan 2010 19:42:24 +0800 Subject: [PATCH 34/36] [NEWIMPORT] Almost all remaining stats All conversions from Grigorij street0_3BChance street0_3BDone street0_4BChance street0_4BDone stealAttemptChance stealAttempted foldBbToStealChance foldBbToStealChance foldSbToStealChance foldedSbToSteal foldedBbToSteal 3Bet, 4Bet in Stud does appear to work. Unable to test steal in Stud games, all example hands in micros do not have a chance (I believe) --- pyfpdb/DerivedStats.py | 59 +++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index fe857ae4..8b9af93b 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -49,6 +49,17 @@ class DerivedStats(): self.handsplayers[player[1]]['wonAtSD'] = 0.0 self.handsplayers[player[1]]['startCards'] = 0 self.handsplayers[player[1]]['position'] = 2 + self.handsplayers[player[1]]['street0_3BChance'] = False + self.handsplayers[player[1]]['street0_3BDone'] = False + self.handsplayers[player[1]]['street0_4BChance'] = False + self.handsplayers[player[1]]['street0_4BDone'] = False + self.handsplayers[player[1]]['stealAttemptChance'] = False + self.handsplayers[player[1]]['stealAttempted'] = False + self.handsplayers[player[1]]['foldBbToStealChance'] = False + self.handsplayers[player[1]]['foldBbToStealChance'] = False + self.handsplayers[player[1]]['foldSbToStealChance'] = False + self.handsplayers[player[1]]['foldedSbToSteal'] = False + self.handsplayers[player[1]]['foldedBbToSteal'] = False for i in range(5): self.handsplayers[player[1]]['street%dCalls' % i] = 0 self.handsplayers[player[1]]['street%dBets' % i] = 0 @@ -60,15 +71,6 @@ class DerivedStats(): #FIXME - Everything below this point is incomplete. self.handsplayers[player[1]]['tourneyTypeId'] = 1 - self.handsplayers[player[1]]['street0_3BChance'] = False - self.handsplayers[player[1]]['street0_3BDone'] = False - self.handsplayers[player[1]]['stealAttemptChance'] = False - self.handsplayers[player[1]]['stealAttempted'] = False - self.handsplayers[player[1]]['foldBbToStealChance'] = False - self.handsplayers[player[1]]['foldBbToStealChance'] = False - self.handsplayers[player[1]]['foldSbToStealChance'] = False - self.handsplayers[player[1]]['foldedSbToSteal'] = False - self.handsplayers[player[1]]['foldedBbToSteal'] = False for i in range(1,5): self.handsplayers[player[1]]['otherRaisedStreet%d' %i] = False self.handsplayers[player[1]]['foldToOtherRaisedStreet%d' %i] = False @@ -176,6 +178,8 @@ class DerivedStats(): self.setPositions(hand) self.calcCheckCallRaise(hand) + self.calc34BetStreet0(hand) + self.calcSteals(hand) # Additional stats # 3betSB, 3betBB # Squeeze, Ratchet? @@ -280,28 +284,29 @@ class DerivedStats(): Steal attemp - open raise on positions 2 1 0 S - i.e. MP3, CO, BU, SB Fold to steal - folding blind after steal attemp wo any other callers or raisers """ - if self.gametype_dict['base'] != 'hold': - # FIXME: add support for other games //grindi - return steal_attemp = False + steal_positions = ('2', '1', '0', 'S') + if hand.gametype['base'] == 'stud': + steal_positions = ('2', '1', '0') for action in hand.actions[hand.actionStreets[1]]: - hp, act = self.handplayers_by_name[action[0]], action[1] + pname, act = action[0], action[1] #print action[0], hp.position, steal_attemp, act - if hp.position == 'B': - hp.foldBbToStealChance = steal_attemp - hp.foldBbToSteal = hp.foldBbToStealChance and act == 'folds' + if self.handsplayers[pname]['position'] == 'B': + #NOTE: Stud games will never hit this section + self.handsplayers[pname]['foldBbToStealChance'] = steal_attemp + self.handsplayers[pname]['foldBbToSteal'] = self.handsplayers[pname]['foldBbToStealChance'] and act == 'folds' break - elif hp.position == 'S': - hp.foldSbToStealChance = steal_attemp - hp.foldSbToSteal = hp.foldSbToStealChance and act == 'folds' + elif self.handsplayers[pname]['position'] == 'S': + self.handsplayers[pname]['foldSbToStealChance'] = steal_attemp + self.handsplayers[pname]['foldSbToSteal'] = self.handsplayers[pname]['foldSbToStealChance'] and act == 'folds' if steal_attemp and act != 'folds': break - if hp.position in ('2', '1', '0', 'S') and not steal_attemp: - hp.stealAttemptChance = True + if self.handsplayers[pname]['position'] in steal_positions and not steal_attemp: + self.handsplayers[pname]['stealAttemptChance'] = True if act in ('bets', 'raises'): - hp.stealAttempted = True + self.handsplayers[pname]['stealAttempted'] = True steal_attemp = True def calc34BetStreet0(self, hand): @@ -309,11 +314,11 @@ class DerivedStats(): bet_level = 1 # bet_level after 3-bet is equal to 3 for action in hand.actions[hand.actionStreets[1]]: # FIXME: fill other(3|4)BStreet0 - i have no idea what does it mean - hp, aggr = self.handplayers_by_name[action[0]], action[1] in ('raises', 'bets') - hp.street0_3BChance = bet_level == 2 - hp.street0_4BChance = bet_level == 3 - hp.street0_3BDone = aggr and (hp.street0_3BChance) - hp.street0_4BDone = aggr and (hp.street0_4BChance) + pname, aggr = action[0], action[1] in ('raises', 'bets') + self.handsplayers[pname]['street0_3BChance'] = bet_level == 2 + self.handsplayers[pname]['street0_4BChance'] = bet_level == 3 + self.handsplayers[pname]['street0_3BDone'] = aggr and (self.handsplayers[pname]['street0_3BChance']) + self.handsplayers[pname]['street0_4BDone'] = aggr and (self.handsplayers[pname]['street0_4BChance']) if aggr: bet_level += 1 From 776405982b526f36fbd502ec43da5261ed4624aa Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 15 Jan 2010 21:24:37 +0800 Subject: [PATCH 35/36] Quick fix for hud --- pyfpdb/Database.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 63e9a0a5..c7b3e3b8 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1508,7 +1508,7 @@ class Database: line[55] = gid # gametypeId line[56] = pids[p] # playerId line[57] = len(pids) # activeSeats - pos = {-2:'B', -1:'S', 0:'D', 1:'C', 2:'M', 3:'M', 4:'M', 5:'E', 6:'E', 7:'E', 8:'E', 9:'E' } + pos = {'B':'B', 'S':'S', 0:'D', 1:'C', 2:'M', 3:'M', 4:'M', 5:'E', 6:'E', 7:'E', 8:'E', 9:'E' } line[58] = pos[pdata[p]['position']] line[59] = pdata[p]['tourneyTypeId'] line[60] = styleKey # styleKey From 3f0dfd2b2614ca5de2e807f71f2b3eff9703198a Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 16 Jan 2010 13:55:01 +0800 Subject: [PATCH 36/36] Fix enumerate() --- pyfpdb/DerivedStats.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 8b9af93b..88bb6407 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -350,8 +350,9 @@ class DerivedStats(): CG: CheckCall would be a much better name for this. """ - for i, street in enumerate(hand.actionStreets[2:], start=1): - actions = hand.actions[hand.actionStreets[i]] + #for i, street in enumerate(hand.actionStreets[2:], start=1): + for i, street in enumerate(hand.actionStreets[2:]): + actions = hand.actions[hand.actionStreets[i+1]] checkers = set() initial_raiser = None for action in actions: @@ -361,8 +362,8 @@ class DerivedStats(): elif act == 'checks' and initial_raiser is None: checkers.add(pname) elif initial_raiser is not None and pname in checkers: - self.handsplayers[pname]['street%dCheckCallRaiseChance' % i] = True - self.handsplayers[pname]['street%dCheckCallRaiseDone' % i] = act!='folds' + self.handsplayers[pname]['street%dCheckCallRaiseChance' % (i+1)] = True + self.handsplayers[pname]['street%dCheckCallRaiseDone' % (i+1)] = act!='folds' def seen(self, hand, i): pas = set()