From 16eb0b1e1fc30ca0b17e4680f38c3d6ea5259b6c Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 28 Oct 2009 20:12:03 +0000 Subject: [PATCH 01/32] small changes for sqlite --- pyfpdb/fpdb_simple.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index 3e2d6f5f..aaf74772 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -927,7 +927,7 @@ def recogniseTourneyTypeId(db, siteId, tourneySiteId, buyin, fee, knockout, rebu except: cursor.execute( """SELECT id FROM TourneyTypes WHERE siteId=%s AND buyin=%s AND fee=%s - AND knockout=%s AND rebuyOrAddon=%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 @@ -939,14 +939,14 @@ def recogniseTourneyTypeId(db, siteId, tourneySiteId, buyin, fee, knockout, rebu #print "insert new tourneytype record ..." try: cursor.execute( """INSERT INTO TourneyTypes (siteId, buyin, fee, knockout, rebuyOrAddon) - VALUES (%s, %s, %s, %s, %s)""" + 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""" + AND knockout=%s AND rebuyOrAddon=%s""".replace('%s', db.sql.query['placeholder']) , (siteId, buyin, fee, knockout, rebuyOrAddon) ) result = cursor.fetchone() try: From 5aef7b60549b01c8189a5195ef24ba168183e7c3 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 6 Nov 2009 18:39:59 +0800 Subject: [PATCH 02/32] [NEWIMPORT] Insert winnings column into HandsPlayers --- pyfpdb/Database.py | 5 +++-- pyfpdb/DerivedStats.py | 22 +++++++++++++++++++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 61b91729..38bd04cc 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1393,6 +1393,7 @@ class Database: pids[p], pdata[p]['startCash'], pdata[p]['seatNo'], + pdata[p]['winnings'], pdata[p]['street0Aggr'], pdata[p]['street1Aggr'], pdata[p]['street2Aggr'], @@ -1405,6 +1406,7 @@ class Database: playerId, startCash, seatNo, + winnings, street0Aggr, street1Aggr, street2Aggr, @@ -1413,7 +1415,7 @@ class Database: ) VALUES ( %s, %s, %s, %s, %s, - %s, %s, %s, %s + %s, %s, %s, %s, %s )""" # position, @@ -1423,7 +1425,6 @@ class Database: # card3, # card4, # startCards, -# winnings, # rake, # totalProfit, # street0VPI, diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 56b0d489..86aa92fb 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -18,6 +18,13 @@ #fpdb modules import Card +DEBUG = True + +if DEBUG: + import pprint + pp = pprint.PrettyPrinter(indent=4) + + class DerivedStats(): def __init__(self, hand): self.hand = hand @@ -30,13 +37,17 @@ class DerivedStats(): for player in hand.players: self.handsplayers[player[1]] = {} #Init vars that may not be used, but still need to be inserted. + self.handsplayers[player[1]]['winnings'] = 0 self.handsplayers[player[1]]['street4Aggr'] = False self.assembleHands(self.hand) self.assembleHandsPlayers(self.hand) - - print "hands =", self.hands - print "handsplayers =", self.handsplayers + + if DEBUG: + print "Hands:" + pp.pprint(self.hands) + print "HandsPlayers:" + pp.pprint(self.handsplayers) def getHands(self): return self.hands @@ -90,6 +101,11 @@ class DerivedStats(): self.handsplayers[player[1]]['seatNo'] = player[0] self.handsplayers[player[1]]['startCash'] = player[2] + # Winnings is a non-negative value of money collected from the pot, which already includes the + # rake taken out. hand.collectees is Decimal, database requires cents + for player in hand.collectees: + self.handsplayers[player]['winnings'] = int(100 * hand.collectees[player]) + for i, street in enumerate(hand.actionStreets[1:]): self.aggr(self.hand, i) From 006d7164eaaf567d151356062b3b54326cf20862 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 6 Nov 2009 19:13:52 +0800 Subject: [PATCH 03/32] [NEWIMPORT] Insert streetXSeen col into HandsPlayers --- pyfpdb/Database.py | 13 +++++++++---- pyfpdb/DerivedStats.py | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 38bd04cc..8a1060a6 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1394,6 +1394,10 @@ class Database: pdata[p]['startCash'], pdata[p]['seatNo'], pdata[p]['winnings'], + pdata[p]['street1Seen'], + pdata[p]['street2Seen'], + pdata[p]['street3Seen'], + pdata[p]['street4Seen'], pdata[p]['street0Aggr'], pdata[p]['street1Aggr'], pdata[p]['street2Aggr'], @@ -1407,6 +1411,10 @@ class Database: startCash, seatNo, winnings, + street1Seen, + street2Seen, + street3Seen, + street4Seen, street0Aggr, street1Aggr, street2Aggr, @@ -1414,6 +1422,7 @@ class Database: street4Aggr ) VALUES ( + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s )""" @@ -1430,10 +1439,6 @@ class Database: # street0VPI, # street0_3BChance, # street0_3BDone, -# street1Seen, -# street2Seen, -# street3Seen, -# street4Seen, # sawShowdown, # otherRaisedStreet1, # otherRaisedStreet2, diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 86aa92fb..1e23e600 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -37,7 +37,9 @@ class DerivedStats(): for player in hand.players: self.handsplayers[player[1]] = {} #Init vars that may not be used, but still need to be inserted. + # All stud street4 need this when importing holdem self.handsplayers[player[1]]['winnings'] = 0 + self.handsplayers[player[1]]['street4Seen'] = False self.handsplayers[player[1]]['street4Aggr'] = False self.assembleHands(self.hand) @@ -106,6 +108,9 @@ class DerivedStats(): for player in hand.collectees: self.handsplayers[player]['winnings'] = int(100 * hand.collectees[player]) + for i, street in enumerate(hand.actionStreets[2:]): + self.seen(self.hand, i+2) + for i, street in enumerate(hand.actionStreets[1:]): self.aggr(self.hand, i) @@ -849,6 +854,17 @@ class DerivedStats(): self.hands['street3Raises'] = 0 # /* num big bets paid to see sd/street7 */ self.hands['street4Raises'] = 0 # /* num big bets paid to see showdown */ + def seen(self, hand, i): + pas = set() + for act in hand.actions[hand.actionStreets[i]]: + pas.add(act[0]) + + for player in hand.players: + if player[1] in pas: + self.handsplayers[player[1]]['street%sSeen' % i] = True + else: + self.handsplayers[player[1]]['street%sSeen' % i] = False + def aggr(self, hand, i): aggrers = set() for act in hand.actions[hand.actionStreets[i]]: From 5c7cce090e2beb3968c46e4d59241932d3705af8 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 6 Nov 2009 19:30:50 +0800 Subject: [PATCH 04/32] [NEWIMPORT] Added street0VPI to HandsPlayers Also fixed last patch for streetXSeen --- pyfpdb/Database.py | 5 +++-- pyfpdb/DerivedStats.py | 9 +++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 8a1060a6..f7e873bc 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1394,6 +1394,7 @@ class Database: pdata[p]['startCash'], pdata[p]['seatNo'], pdata[p]['winnings'], + pdata[p]['street0VPI'], pdata[p]['street1Seen'], pdata[p]['street2Seen'], pdata[p]['street3Seen'], @@ -1411,6 +1412,7 @@ class Database: startCash, seatNo, winnings, + street0VPI, street1Seen, street2Seen, street3Seen, @@ -1422,7 +1424,7 @@ class Database: street4Aggr ) VALUES ( - %s, %s, %s, %s, + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s )""" @@ -1436,7 +1438,6 @@ class Database: # startCards, # rake, # totalProfit, -# street0VPI, # street0_3BChance, # street0_3BDone, # sawShowdown, diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 1e23e600..4b48f618 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -98,6 +98,7 @@ class DerivedStats(): # commentTs DATETIME def assembleHandsPlayers(self, hand): + #street0VPI/vpip already called in Hand #hand.players = [[seat, name, chips],[seat, name, chips]] for player in hand.players: self.handsplayers[player[1]]['seatNo'] = player[0] @@ -109,7 +110,7 @@ class DerivedStats(): self.handsplayers[player]['winnings'] = int(100 * hand.collectees[player]) for i, street in enumerate(hand.actionStreets[2:]): - self.seen(self.hand, i+2) + self.seen(self.hand, i+1) for i, street in enumerate(hand.actionStreets[1:]): self.aggr(self.hand, i) @@ -815,9 +816,9 @@ class DerivedStats(): for player in hand.players: if player[1] in vpipers: - self.handsplayers[player[1]]['vpip'] = True + self.handsplayers[player[1]]['street0VPI'] = True else: - self.handsplayers[player[1]]['vpip'] = False + self.handsplayers[player[1]]['street0VPI'] = False def playersAtStreetX(self, hand): """ playersAtStreet1 SMALLINT NOT NULL, /* num of players seeing flop/street4/draw1 */""" @@ -856,7 +857,7 @@ class DerivedStats(): def seen(self, hand, i): pas = set() - for act in hand.actions[hand.actionStreets[i]]: + for act in hand.actions[hand.actionStreets[i+1]]: pas.add(act[0]) for player in hand.players: From c4d3789657b92bc876ff69f69b323ee2bae6781f Mon Sep 17 00:00:00 2001 From: grindi Date: Fri, 6 Nov 2009 23:47:31 +0300 Subject: [PATCH 05/32] Fixed: aux save layout doesn't work Bug maker, look at http://docs.python.org/tutorial/classes.html#generator-expressions (...for...) returns generator rather than tuple --- pyfpdb/Hud.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index f0f47898..3ca6c33b 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -440,7 +440,7 @@ class Hud: new_layout[self.stat_windows[sw].adj - 1] = new_loc self.config.edit_layout(self.table.site, self.max, locations = new_layout) # ask each aux to save its layout back to the config object - (aux.save_layout() for aux in self.aux_windows) + [aux.save_layout() for aux in self.aux_windows] # save the config object back to the file print "saving new xml file" self.config.save() From fd085ecb4d049e51216e83c4d5d50976818df22a Mon Sep 17 00:00:00 2001 From: grindi Date: Sat, 7 Nov 2009 00:46:50 +0300 Subject: [PATCH 06/32] Fixed another aux bug --- pyfpdb/Hud.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 3ca6c33b..674b0a09 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -386,9 +386,9 @@ class Hud: (x, y) = loc[adj[i+1]] w.relocate(x, y) - # While we're at it, fix the positions of mucked cards too - for aux in self.aux_windows: - aux.update_card_positions() + # While we're at it, fix the positions of mucked cards too + for aux in self.aux_windows: + aux.update_card_positions() return True From 15ea852d76c6a73c11c26b9a01163c7de343b69d Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 7 Nov 2009 10:17:28 +0800 Subject: [PATCH 07/32] Extend the tablename field in sql to 22 characters --- pyfpdb/SQL.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 84b4e9bd..3522b890 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -212,7 +212,7 @@ class Sql: if db_server == 'mysql': self.query['createHandsTable'] = """CREATE TABLE Hands ( id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), - tableName VARCHAR(20) NOT NULL, + tableName VARCHAR(22) NOT NULL, siteHandNo BIGINT NOT NULL, gametypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), handStart DATETIME NOT NULL, @@ -247,7 +247,7 @@ class Sql: elif db_server == 'postgresql': self.query['createHandsTable'] = """CREATE TABLE Hands ( id BIGSERIAL, PRIMARY KEY (id), - tableName VARCHAR(20) NOT NULL, + tableName VARCHAR(22) NOT NULL, siteHandNo BIGINT NOT NULL, gametypeId INT NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), handStart timestamp without time zone NOT NULL, @@ -281,7 +281,7 @@ class Sql: elif db_server == 'sqlite': self.query['createHandsTable'] = """CREATE TABLE Hands ( id INTEGER PRIMARY KEY, - tableName TEXT(20) NOT NULL, + tableName TEXT(22) NOT NULL, siteHandNo INT NOT NULL, gametypeId INT NOT NULL, handStart REAL NOT NULL, From 9dd600702aaa663b3671c168ec21ab8031de83a8 Mon Sep 17 00:00:00 2001 From: grindi Date: Sat, 7 Nov 2009 20:30:47 +0300 Subject: [PATCH 08/32] Moved window title re to HHC classes Just redefine function getTableTitleRe in coresponding hhc for custom re --- pyfpdb/HUD_main.py | 9 +++++---- pyfpdb/HandHistoryConverter.py | 23 +++++++++++++++++++++++ pyfpdb/TableWindow.py | 16 +++++++--------- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index e9fb40fb..48a412ee 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -53,6 +53,7 @@ import gobject # FreePokerTools modules import Configuration import Database +from HandHistoryConverter import getTableTitleRe # get the correct module for the current os if os.name == 'posix': import XTables as Tables @@ -253,10 +254,10 @@ class HUD_main(object): if comm_cards != {}: # stud! cards['common'] = comm_cards['common'] - if type == "tour": - tablewindow = Tables.Table(tournament = tour_number, table_number = tab_number) - else: - tablewindow = Tables.Table(table_name = table_name) + table_kwargs = dict(table_name = table_name, tournament = tour_number, table_number = tab_number) + search_string = getTableTitleRe(self.config, site, type, **table_kwargs) + tablewindow = Tables.Table(search_string, **table_kwargs) + if tablewindow is None: # If no client window is found on the screen, complain and continue if type == "tour": diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index bced9d93..53358d36 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -506,3 +506,26 @@ or None if we fail to get the info """ def getTourney(self): return self.tourney + + @staticmethod + 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) + else: + return table_name + + + +def getTableTitleRe(config, sitename, *args, **kwargs): + "Returns string to search in windows titles for current site" + return getSiteHhc(config, sitename).getTableTitleRe(*args, **kwargs) + +def getSiteHhc(config, sitename): + "Returns HHC class for current site" + hhcName = config.supported_sites[sitename].converter + hhcModule = __import__(hhcName) + return getattr(hhcModule, hhcName[:-6]) + + + diff --git a/pyfpdb/TableWindow.py b/pyfpdb/TableWindow.py index bdc9db87..10607b16 100644 --- a/pyfpdb/TableWindow.py +++ b/pyfpdb/TableWindow.py @@ -93,19 +93,17 @@ gobject.signal_new("client_destroyed", gtk.Window, # screen location of (0, 0) in the working window. class Table_Window(object): - def __init__(self, table_name = None, tournament = None, table_number = None): + def __init__(self, search_string, table_name = None, tournament = None, table_number = None): - if table_name is not None: - search_string = table_name - self.name = table_name - self.tournament = None - self.table = None - elif tournament is not None and table_number is not None: + if tournament is not None and table_number is not None: print "tournament %s, table %s" % (tournament, table_number) self.tournament = int(tournament) self.table = int(table_number) self.name = "%s - %s" % (self.tournament, self.table) - search_string = "%s.+Table\s%s" % (tournament, table_number) + elif table_name is not None: + search_string = table_name + self.name = table_name + self.tournament = None else: return None @@ -151,4 +149,4 @@ class Table_Window(object): def check_bad_words(self, title): for word in bad_words: if word in title: return True - return False \ No newline at end of file + return False From dbaf4dbdbc639d9fe3ee225e60b69b5e80190ec5 Mon Sep 17 00:00:00 2001 From: grindi Date: Sat, 7 Nov 2009 21:57:23 +0300 Subject: [PATCH 09/32] Make msgs about parse errors more verbose + fix small bug in FpdbParseError --- pyfpdb/Exceptions.py | 4 ++-- pyfpdb/HandHistoryConverter.py | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Exceptions.py b/pyfpdb/Exceptions.py index eaf5d798..f7e9fa54 100644 --- a/pyfpdb/Exceptions.py +++ b/pyfpdb/Exceptions.py @@ -9,8 +9,8 @@ class FpdbParseError(FpdbError): self.value = value self.hid = hid def __str__(self): - if hid: - return repr("HID:"+hid+", "+self.value) + if self.hid: + return repr("HID:"+self.hid+", "+self.value) else: return repr(self.value) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 53358d36..6452cae4 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -154,6 +154,7 @@ Otherwise, finish at EOF. except FpdbParseError, e: numErrors += 1 log.warning("Failed to convert hand %s" % e.hid) + log.warning("Exception msg: '%s'" % str(e)) log.debug(handText) else: handsList = self.allHandsAsList() @@ -168,6 +169,7 @@ Otherwise, finish at EOF. except FpdbParseError, e: numErrors += 1 log.warning("Failed to convert hand %s" % e.hid) + log.warning("Exception msg: '%s'" % str(e)) log.debug(handText) numHands = len(handsList) endtime = time.time() From b33fd0375462c69efdc49dc8f53f0a2a0d37705b Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Sun, 8 Nov 2009 22:51:15 -0500 Subject: [PATCH 10/32] Added Configuration.py exe and HowTo use. --- pyfpdb/py2exe_setup.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/pyfpdb/py2exe_setup.py b/pyfpdb/py2exe_setup.py index 028d004c..6709064d 100644 --- a/pyfpdb/py2exe_setup.py +++ b/pyfpdb/py2exe_setup.py @@ -27,6 +27,22 @@ Py2exe script for fpdb. # get rid of all the uneeded libraries (e.g., pyQT) # think about an installer +#HOW TO USE this script: +# +# cd to the folder where this script is stored, usually .../pyfpdb. +# If there are build and dist subfolders present , delete them to get +# rid of earlier builds. +# Run the script with "py2exe_setup.py py2exe" +# You will frequently get messages about missing .dll files. E. g., +# MSVCP90.dll. These are somewhere in your windows install, so you +# can just copy them to your working folder. +# If it works, you'll have 2 new folders, build and dist. Build is +# working space and should be deleted. Dist contains the files to be +# distributed. Last, you must copy the etc/, lib/ and share/ folders +# from your gtk/bin/ folder to the dist folder. (the whole folders, not +# just the contents) You can (should) then prune the etc/, lib/ and +# share/ folders to remove components we don't need. + from distutils.core import setup import py2exe @@ -36,7 +52,8 @@ setup( version = '0.12', console = [ {'script': 'fpdb.py', }, - {'script': 'HUD_main.py', } + {'script': 'HUD_main.py', }, + {'script': 'Configuration.py', } ], options = {'py2exe': { @@ -48,7 +65,8 @@ setup( }, data_files = ['HUD_config.xml', - 'Cards01.png' + 'Cards01.png', + 'logging.conf' ] ) From 0bbbc7222bbcd299b8c12af9a9e53e8ac09ccd3c Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Sun, 8 Nov 2009 22:53:10 -0500 Subject: [PATCH 11/32] First go at rationalizing config paths and logging defaults. --- pyfpdb/Configuration.py | 146 +++++++++++++++++++++------------------- pyfpdb/Database.py | 21 +----- 2 files changed, 78 insertions(+), 89 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index dbdf159f..1df4cc07 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -37,13 +37,79 @@ from xml.dom.minidom import Node import logging, logging.config import ConfigParser -try: # local path - logging.config.fileConfig(os.path.join(sys.path[0],"logging.conf")) -except ConfigParser.NoSectionError: # debian package path - logging.config.fileConfig('/usr/share/python-fpdb/logging.conf') +############################################################################## +# Functions for finding config files and setting up logging +# Also used in other modules that use logging. + +def get_default_config_path(): + """Returns the path where the fpdb config file _should_ be stored.""" + if os.name == 'posix': + config_path = os.path.join(os.path.expanduser("~"), '.fpdb') + elif os.name == 'nt': + config_path = os.path.join(os.environ["APPDATA"], 'fpdb') + else: config_path = False + return config_path + +def get_exec_path(): + """Returns the path to the fpdb.(py|exe) file we are executing""" + if hasattr(sys, "frozen"): # compiled by py2exe + print "executable path is", os.path.dirname(sys.executable) + print "exec path is", os.path.dirname(sys.executable) + print "0 path is", os.path.dirname(sys.path[0]) + return os.path.dirname(sys.executable) + else: + print "executable path is", os.path.dirname(sys.executable) + print "exec path is", os.path.dirname(sys.argv[0]) + print "0 path is", os.path.dirname(sys.path[0]) + return os.path.dirname(sys.path[0]) + +def get_config(file_name, fallback = True): + """Looks in cwd and in self.default_config_path for a config file.""" + config_path = os.path.join(get_exec_path(), file_name) + if os.path.exists(config_path): # there is a file in the cwd + return config_path # so we use it + else: # no file in the cwd, look where it should be in the first place + config_path = os.path.join(get_default_config_path(), file_name) + if os.path.exists(config_path): + return config_path + +# No file found + if not fallback: + return False + +# OK, fall back to the .example file, should be in the start dir + if os.path.exists(file_name + ".example"): + try: + shutil.copyfile(file_name + ".example", file_name) + print "No %s found, using %s.example.\n" % (file_name, file_name) + print "A %s file has been created. You will probably have to edit it." % file_name + sys.stderr.write("No %s found, using %s.example.\n" % (file_name, file_name) ) + except: + print "No %s found, cannot fall back. Exiting.\n" % file_name + sys.stderr.write("No %s found, cannot fall back. Exiting.\n" % file_name) + sys.exit() + return file_name + +def get_logger(file_name, fallback = False): + conf = get_config(file_name, fallback = fallback) + if conf: + try: + logging.config.fileConfig(conf) + log = logging.getLogger("config") + log.debug("config logger initialised") + return log + except: + pass + + log = logging.basicConfig() + log = logging.getLogger() + log.debug("config logger initialised") + return log + +# find a logging.conf file and set up logging +log = get_logger("logging.conf") +log.error("FARTS") -log = logging.getLogger("config") -log.debug("config logger initialised") ######################################################################## # application wide consts @@ -335,7 +401,7 @@ class Config: # "file" is a path to an xml file with the fpdb/HUD configuration # we check the existence of "file" and try to recover if it doesn't exist - self.default_config_path = self.get_default_config_path() +# self.default_config_path = self.get_default_config_path() if file is not None: # config file path passed in file = os.path.expanduser(file) if not os.path.exists(file): @@ -343,28 +409,12 @@ class Config: sys.stderr.write("Configuration file %s not found. Using defaults." % (file)) file = None - if file is None: # configuration file path not passed or invalid - file = self.find_config() #Look for a config file in the normal places - - if file is None: # no config file in the normal places - file = self.find_example_config() #Look for an example file to edit - - if file is None: # that didn't work either, just die - print "No HUD_config_xml found after looking in current directory and "+self.default_config_path+"\nExiting" - sys.stderr.write("No HUD_config_xml found after looking in current directory and "+self.default_config_path+"\nExiting") - print "press enter to continue" - sys.stdin.readline() - sys.exit() + file = get_config("HUD_config.xml") # Parse even if there was no real config file found and we are using the example # If using the example, we'll edit it later -# sc 2009/10/04 Example already copied to main filename, is this ok? log.info("Reading configuration file %s" % file) - if os.sep in file: - print "\nReading configuration file %s\n" % file - else: - print "\nReading configuration file %s" % file - print "in %s\n" % os.getcwd() + print "\nReading configuration file %s\n" % file try: doc = xml.dom.minidom.parse(file) except: @@ -460,28 +510,6 @@ class Config: def set_hhArchiveBase(self, path): self.imp.node.setAttribute("hhArchiveBase", path) - def find_config(self): - """Looks in cwd and in self.default_config_path for a config file.""" - if os.path.exists('HUD_config.xml'): # there is a HUD_config in the cwd - file = 'HUD_config.xml' # so we use it - else: # no HUD_config in the cwd, look where it should be in the first place - config_path = os.path.join(self.default_config_path, 'HUD_config.xml') - if os.path.exists(config_path): - file = config_path - else: - file = None - return file - - def get_default_config_path(self): - """Returns the path where the fpdb config file _should_ be stored.""" - if os.name == 'posix': - config_path = os.path.join(os.path.expanduser("~"), '.fpdb') - elif os.name == 'nt': - config_path = os.path.join(os.environ["APPDATA"], 'fpdb') - else: config_path = None - return config_path - - def find_default_conf(self): if os.name == 'posix': config_path = os.path.join(os.path.expanduser("~"), '.fpdb', 'default.conf') @@ -495,30 +523,6 @@ class Config: file = None return file - def read_default_conf(self, file): - parms = {} - with open(file, "r") as fh: - for line in fh: - line = string.strip(line) - (key, value) = line.split('=') - parms[key] = value - return parms - - def find_example_config(self): - if os.path.exists('HUD_config.xml.example'): # there is a HUD_config in the cwd - file = 'HUD_config.xml' # so we use it - try: - shutil.copyfile(file+'.example', file) - except: - file = '' - print "No HUD_config.xml found, using HUD_config.xml.example.\n", \ - "A HUD_config.xml has been created. You will probably have to edit it." - sys.stderr.write("No HUD_config.xml found, using HUD_config.xml.example.\n" + \ - "A HUD_config.xml has been created. You will probably have to edit it.") - else: - file = None - return file - def get_site_node(self, site): for site_node in self.doc.getElementsByTagName("site"): if site_node.getAttribute("site_name") == site: diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index f7e873bc..0f811537 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -45,15 +45,8 @@ import Card import Tourney from Exceptions import * -import logging, logging.config -import ConfigParser - -try: # local path - logging.config.fileConfig(os.path.join(sys.path[0],"logging.conf")) -except ConfigParser.NoSectionError: # debian package path - logging.config.fileConfig('/usr/share/python-fpdb/logging.conf') - -log = logging.getLogger('db') +log = Configuration.get_logger("logging.conf") +log.error("TURDS") class Database: @@ -2690,13 +2683,11 @@ class HandToWrite: if __name__=="__main__": c = Configuration.Config() - db_connection = Database(c, 'fpdb', 'holdem') # mysql fpdb holdem + db_connection = Database(c) # mysql fpdb holdem # db_connection = Database(c, 'fpdb-p', 'test') # mysql fpdb holdem # db_connection = Database(c, 'PTrackSv2', 'razz') # mysql razz # db_connection = Database(c, 'ptracks', 'razz') # postgres print "database connection object = ", db_connection.connection - print "database type = ", db_connection.type - db_connection.recreate_tables() h = db_connection.get_last_hand() @@ -2710,18 +2701,12 @@ if __name__=="__main__": for p in stat_dict.keys(): print p, " ", stat_dict[p] - #print "nutOmatics stats:" - #stat_dict = db_connection.get_stats_from_hand(h, "ring") - #for p in stat_dict.keys(): - # print p, " ", stat_dict[p] - print "cards =", db_connection.get_cards(u'1') db_connection.close_connection print "press enter to continue" sys.stdin.readline() - #Code borrowed from http://push.cx/2008/caching-dictionaries-in-python-vs-ruby class LambdaDict(dict): def __init__(self, l): From e6b71d86bbe1326277716af661f53758dbd42e87 Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Sun, 8 Nov 2009 23:00:15 -0500 Subject: [PATCH 12/32] Should be HUD_config.xml.example, not HUD_config.xml --- pyfpdb/py2exe_setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/py2exe_setup.py b/pyfpdb/py2exe_setup.py index 6709064d..c5f803bb 100644 --- a/pyfpdb/py2exe_setup.py +++ b/pyfpdb/py2exe_setup.py @@ -64,7 +64,7 @@ setup( } }, - data_files = ['HUD_config.xml', + data_files = ['HUD_config.xml.example', 'Cards01.png', 'logging.conf' ] From c8b7608bc1d3fd7b251de8a693c911edfc076b9e Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Sun, 8 Nov 2009 23:16:56 -0500 Subject: [PATCH 13/32] Delete intermediate prints. Small fix to make py2exe happy. --- pyfpdb/Configuration.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 1df4cc07..c6e38c01 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -53,14 +53,8 @@ def get_default_config_path(): def get_exec_path(): """Returns the path to the fpdb.(py|exe) file we are executing""" if hasattr(sys, "frozen"): # compiled by py2exe - print "executable path is", os.path.dirname(sys.executable) - print "exec path is", os.path.dirname(sys.executable) - print "0 path is", os.path.dirname(sys.path[0]) return os.path.dirname(sys.executable) else: - print "executable path is", os.path.dirname(sys.executable) - print "exec path is", os.path.dirname(sys.argv[0]) - print "0 path is", os.path.dirname(sys.path[0]) return os.path.dirname(sys.path[0]) def get_config(file_name, fallback = True): @@ -116,7 +110,7 @@ log.error("FARTS") APPLICATION_NAME_SHORT = 'fpdb' APPLICATION_VERSION = 'xx.xx.xx' -DIR_SELF = os.path.dirname(os.path.abspath(__file__)) +DIR_SELF = os.path.dirname(get_exec_path()) #TODO: imo no good idea to place 'database' in parent dir DIR_DATABASES = os.path.join(os.path.dirname(DIR_SELF), 'database') From b637247871b4638d027f5f44a4df2b0fa8fb7b74 Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Mon, 9 Nov 2009 19:24:46 -0500 Subject: [PATCH 14/32] Fix for logging changes. --- pyfpdb/PokerStarsToFpdb.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 061fb27c..7f242789 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -92,7 +92,7 @@ class PokerStars(HandHistoryConverter): self.compiledPlayers = players player_re = "(?P" + "|".join(map(re.escape, players)) + ")" subst = {'PLYR': player_re, 'CUR': self.sym[hand.gametype['currency']]} - logging.debug("player_re: " + player_re) + log.debug("player_re: " + player_re) self.re_PostSB = re.compile(r"^%(PLYR)s: posts small blind %(CUR)s(?P[.0-9]+)" % subst, re.MULTILINE) self.re_PostBB = re.compile(r"^%(PLYR)s: posts big blind %(CUR)s(?P[.0-9]+)" % subst, re.MULTILINE) self.re_Antes = re.compile(r"^%(PLYR)s: posts the ante %(CUR)s(?P[.0-9]+)" % subst, re.MULTILINE) @@ -186,7 +186,7 @@ class PokerStars(HandHistoryConverter): # m = self.re_Button.search(hand.handText) # if m: info.update(m.groupdict()) # TODO : I rather like the idea of just having this dict as hand.info - logging.debug("readHandInfo: %s" % info) + log.debug("readHandInfo: %s" % info) for key in info: if key == 'DATETIME': #2008/11/12 10:00:48 CET [2008/11/12 4:00:48 ET] @@ -226,10 +226,10 @@ class PokerStars(HandHistoryConverter): if m: hand.buttonpos = int(m.group('BUTTON')) else: - logging.info('readButton: not found') + log.info('readButton: not found') def readPlayerStacks(self, hand): - logging.debug("readPlayerStacks") + log.debug("readPlayerStacks") m = self.re_PlayerInfo.finditer(hand.handText) players = [] for a in m: @@ -265,7 +265,7 @@ class PokerStars(HandHistoryConverter): hand.setCommunityCards(street, m.group('CARDS').split(' ')) def readAntes(self, hand): - logging.debug("reading antes") + log.debug("reading antes") m = self.re_Antes.finditer(hand.handText) for player in m: #~ logging.debug("hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE'))) From 5021cae297967ceb60947e611ef98b31b7c01ffd Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Mon, 9 Nov 2009 19:30:23 -0500 Subject: [PATCH 15/32] Clean up logging changes. --- pyfpdb/Configuration.py | 7 +++---- pyfpdb/Database.py | 2 -- pyfpdb/HandHistoryConverter.py | 11 ++--------- pyfpdb/fpdb_import.py | 10 +--------- 4 files changed, 6 insertions(+), 24 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index c6e38c01..a8bf79a6 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -84,13 +84,13 @@ def get_config(file_name, fallback = True): sys.exit() return file_name -def get_logger(file_name, fallback = False): +def get_logger(file_name, config = "config", fallback = False): conf = get_config(file_name, fallback = fallback) if conf: try: logging.config.fileConfig(conf) - log = logging.getLogger("config") - log.debug("config logger initialised") + log = logging.getLogger(config) + log.debug("%s logger initialised" % config) return log except: pass @@ -102,7 +102,6 @@ def get_logger(file_name, fallback = False): # find a logging.conf file and set up logging log = get_logger("logging.conf") -log.error("FARTS") ######################################################################## # application wide consts diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 0f811537..0314d78d 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -46,8 +46,6 @@ import Tourney from Exceptions import * log = Configuration.get_logger("logging.conf") -log.error("TURDS") - class Database: diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index bced9d93..197e361a 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -32,19 +32,12 @@ from xml.dom.minidom import Node import time import datetime from Exceptions import FpdbParseError +import Configuration import gettext gettext.install('fpdb') -import logging, logging.config -import ConfigParser - -try: - logging.config.fileConfig(os.path.join(sys.path[0],"logging.conf")) -except ConfigParser.NoSectionError: # debian package path - logging.config.fileConfig('/usr/share/python-fpdb/logging.conf') - -log = logging.getLogger("parser") +log = Configuration.get_logger("logging.conf") import pygtk import gtk diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index fcad30be..850f34b6 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -42,15 +42,7 @@ import fpdb_parse_logic import Configuration import Exceptions -import logging, logging.config -import ConfigParser - -try: - logging.config.fileConfig(os.path.join(sys.path[0],"logging.conf")) -except ConfigParser.NoSectionError: # debian package path - logging.config.fileConfig('/usr/share/python-fpdb/logging.conf') - -log = logging.getLogger('importer') +log = Configuration.get_logger("logging.conf", "importer") # database interface modules try: From 1b980e7cad3217d4a89466c74f3bbb523c8fb93e Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Mon, 9 Nov 2009 19:31:32 -0500 Subject: [PATCH 16/32] Fix merge gone wrong. --- pyfpdb/SQL.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index de847d98..3846a371 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -2942,8 +2942,9 @@ class Sql: ,hc_position ,hp.tourneyTypeId ,date_format(h.handStart, 'd%y%m%d') ->>>>>>> 28ca49d592c8e706ad6ee58dd26655bcc33fc5fb:pyfpdb/SQL.py """ +#>>>>>>> 28ca49d592c8e706ad6ee58dd26655bcc33fc5fb:pyfpdb/SQL.py +#""" elif db_server == 'postgresql': self.query['rebuildHudCache'] = """ INSERT INTO HudCache From 65393492cf1dbc1b48a74f398cad902df29905e1 Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Mon, 9 Nov 2009 22:02:50 -0500 Subject: [PATCH 17/32] Get logging.conf and matplotlib datafiles. --- pyfpdb/py2exe_setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyfpdb/py2exe_setup.py b/pyfpdb/py2exe_setup.py index c5f803bb..9565ac0b 100644 --- a/pyfpdb/py2exe_setup.py +++ b/pyfpdb/py2exe_setup.py @@ -66,7 +66,8 @@ setup( data_files = ['HUD_config.xml.example', 'Cards01.png', - 'logging.conf' + 'logging.conf', + (r'matplotlibdata', glob.glob(r'c:\python26\Lib\site-packages\matplotlib\mpl-data\*')) ] ) From a5b0de5ed2ea4bded0cdb9a1e7cf4a43dbe67b91 Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Wed, 11 Nov 2009 16:20:43 -0500 Subject: [PATCH 18/32] Fix problem with .example overiding HUD_config. --- pyfpdb/Configuration.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index a8bf79a6..6712afbc 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -402,7 +402,7 @@ class Config: sys.stderr.write("Configuration file %s not found. Using defaults." % (file)) file = None - file = get_config("HUD_config.xml") + if file is None: file = get_config("HUD_config.xml") # Parse even if there was no real config file found and we are using the example # If using the example, we'll edit it later @@ -945,3 +945,7 @@ if __name__== "__main__": print c.get_game_parameters(game) print "start up path = ", c.execution_path("") + +from xml.dom.ext import PrettyPrint +for site_node in c.doc.getElementsByTagName("site"): + PrettyPrint(site_node, stream=sys.stdout, encoding="utf-8") From 85f488e9cb800960bfa4a87ed18cd5bb94397829 Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Wed, 11 Nov 2009 16:25:31 -0500 Subject: [PATCH 19/32] Fix pretty print test. --- pyfpdb/Configuration.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 6712afbc..3f183204 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -946,6 +946,6 @@ if __name__== "__main__": print "start up path = ", c.execution_path("") -from xml.dom.ext import PrettyPrint -for site_node in c.doc.getElementsByTagName("site"): - PrettyPrint(site_node, stream=sys.stdout, encoding="utf-8") + from xml.dom.ext import PrettyPrint + for site_node in c.doc.getElementsByTagName("site"): + PrettyPrint(site_node, stream=sys.stdout, encoding="utf-8") From c9b9c848be49f4feb44611c0ab7b53d9b3a1575d Mon Sep 17 00:00:00 2001 From: Worros Date: Mon, 16 Nov 2009 15:19:24 +0800 Subject: [PATCH 20/32] Add aggregate function VARIANCE() for sqlite --- pyfpdb/fpdb_db.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 18958880..27291d7f 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -30,11 +30,29 @@ except ImportError: logging.info("Not using sqlalchemy connection pool.") use_pool = False +try: + from numpy import var + use_numpy = True +except ImportError: + logging.info("Not using numpy to define variance in sqlite.") + use_numpy = False import fpdb_simple import FpdbSQLQueries import Configuration +# Variance created as sqlite has a bunch of undefined aggregate functions. + +class VARIANCE: + def __init__(self): + self.store = [] + + def step(self, value): + self.store.append(value) + + def finalize(self): + return float(var(self.store)) + class fpdb_db: MYSQL_INNODB = 2 PGSQL = 3 @@ -130,6 +148,10 @@ class fpdb_db: , detect_types=sqlite3.PARSE_DECLTYPES ) sqlite3.register_converter("bool", lambda x: bool(int(x))) sqlite3.register_adapter(bool, lambda x: "1" if x else "0") + if use_numpy: + self.db.create_aggregate("variance", 1, VARIANCE) + else: + logging.warning("Some database functions will not work without NumPy support") else: raise FpdbError("unrecognised database backend:"+backend) self.cursor = self.db.cursor() From 3ef23852a69bfbb008e16c0e5a87d951f88fd08b Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Mon, 16 Nov 2009 10:00:26 -0500 Subject: [PATCH 21/32] Update Tables_Demo to work with new XTables/TableWindow format. --- pyfpdb/Tables_Demo.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Tables_Demo.py b/pyfpdb/Tables_Demo.py index e141cab1..92d85d75 100755 --- a/pyfpdb/Tables_Demo.py +++ b/pyfpdb/Tables_Demo.py @@ -82,11 +82,12 @@ if __name__=="__main__": (tour_no, tab_no) = table_name.split(",", 1) tour_no = tour_no.rstrip() tab_no = tab_no.rstrip() - table = Tables.Table(tournament = tour_no, table_number = tab_no) + table = Tables.Table(None, tournament = tour_no, table_number = tab_no) else: # not a tournament print "cash game" table_name = table_name.rstrip() - table = Tables.Table(table_name = table_name) + table = Tables.Table(None, table_name = table_name) + table.gdk_handle = gtk.gdk.window_foreign_new(table.number) print "table =", table print "game =", table.get_game() From d592e85375a020e73fe259cb518324a402aa3568 Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Mon, 16 Nov 2009 11:20:44 -0500 Subject: [PATCH 22/32] Possible fix of not finding windows in X. --- pyfpdb/XTables.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pyfpdb/XTables.py b/pyfpdb/XTables.py index fd1ce9c1..cbfa8875 100644 --- a/pyfpdb/XTables.py +++ b/pyfpdb/XTables.py @@ -40,6 +40,7 @@ from TableWindow import Table_Window # We might as well do this once and make them globals disp = Xlib.display.Display() root = disp.screen().root +name_atom = disp.get_atom("WM_NAME", 1) class Table(Table_Window): @@ -49,8 +50,14 @@ class Table(Table_Window): for outside in root.query_tree().children: for inside in outside.query_tree().children: if done_looping: break - if inside.get_wm_name() and re.search(search_string, inside.get_wm_name()): - if self.check_bad_words(inside.get_wm_name()): continue + prop = inside.get_property(name_atom, Xlib.Xatom.STRING, 0, 1000) + if prop is None: continue + if prop.value and re.search(search_string, prop.value): + if self.check_bad_words(prop.value): continue +# if inside.get_wm_name() and re.search(search_string, inside.get_wm_name()): +# if self.check_bad_words(inside.get_wm_name()): +# print "bad word =", inside.get_wm_name() +# continue self.window = inside self.parent = outside done_looping = True From 4abfc0093fb326adf769f0b27f13fff309a3f3c6 Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Mon, 16 Nov 2009 11:48:31 -0500 Subject: [PATCH 23/32] test print --- pyfpdb/XTables.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyfpdb/XTables.py b/pyfpdb/XTables.py index cbfa8875..590bd743 100644 --- a/pyfpdb/XTables.py +++ b/pyfpdb/XTables.py @@ -51,6 +51,7 @@ class Table(Table_Window): for inside in outside.query_tree().children: if done_looping: break prop = inside.get_property(name_atom, Xlib.Xatom.STRING, 0, 1000) + print prop if prop is None: continue if prop.value and re.search(search_string, prop.value): if self.check_bad_words(prop.value): continue From 55f1ebedd934e389974d844cc84cbb2c0778a487 Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Mon, 16 Nov 2009 13:04:25 -0500 Subject: [PATCH 24/32] Another possible fix to missing windows. --- pyfpdb/XTables.py | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/pyfpdb/XTables.py b/pyfpdb/XTables.py index 590bd743..c19db5d9 100644 --- a/pyfpdb/XTables.py +++ b/pyfpdb/XTables.py @@ -25,6 +25,7 @@ of Table_Window objects representing the windows found. # Standard Library modules import re +import os # pyGTK modules import pygtk @@ -45,26 +46,43 @@ name_atom = disp.get_atom("WM_NAME", 1) class Table(Table_Window): def find_table_parameters(self, search_string): - self.window = None +# self.window = None +# done_looping = False +# for outside in root.query_tree().children: +# for inside in outside.query_tree().children: +# if done_looping: break +# prop = inside.get_property(name_atom, Xlib.Xatom.STRING, 0, 1000) +# print prop +# if prop is None: continue +# if prop.value and re.search(search_string, prop.value): +# if self.check_bad_words(prop.value): continue +## if inside.get_wm_name() and re.search(search_string, inside.get_wm_name()): +## if self.check_bad_words(inside.get_wm_name()): +## print "bad word =", inside.get_wm_name() +## continue +# self.window = inside +# self.parent = outside +# done_looping = True +# break + + window_number = None + for listing in os.popen('xwininfo -root -tree').readlines(): + if re.search(search_string, listing): + print listing + mo = re.match('\s+([\dxabcdef]+)\s', listing) + window_number = int( mo.group(1), 0) + done_looping = False for outside in root.query_tree().children: for inside in outside.query_tree().children: if done_looping: break - prop = inside.get_property(name_atom, Xlib.Xatom.STRING, 0, 1000) - print prop - if prop is None: continue - if prop.value and re.search(search_string, prop.value): - if self.check_bad_words(prop.value): continue -# if inside.get_wm_name() and re.search(search_string, inside.get_wm_name()): -# if self.check_bad_words(inside.get_wm_name()): -# print "bad word =", inside.get_wm_name() -# continue + if inside.id == window_number: self.window = inside self.parent = outside done_looping = True break - if self.window == None or self.parent == None: + if window_number is None: print "Window %s not found. Skipping." % search_string return None From 812998704de48c46148acf7973f926ab0603f16f Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Mon, 16 Nov 2009 15:35:58 -0500 Subject: [PATCH 25/32] Yet another try to fix missing X windows. Using xwininfo. --- pyfpdb/Tables_Demo.py | 4 ++-- pyfpdb/XTables.py | 54 ++++++++++++++++++++++++------------------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/pyfpdb/Tables_Demo.py b/pyfpdb/Tables_Demo.py index 92d85d75..397579e7 100755 --- a/pyfpdb/Tables_Demo.py +++ b/pyfpdb/Tables_Demo.py @@ -90,11 +90,11 @@ if __name__=="__main__": table.gdk_handle = gtk.gdk.window_foreign_new(table.number) print "table =", table - print "game =", table.get_game() +# print "game =", table.get_game() fake = fake_hud(table) print "fake =", fake - gobject.timeout_add(100, check_on_table, table, fake) +# gobject.timeout_add(100, check_on_table, table, fake) print "calling main" gtk.main() diff --git a/pyfpdb/XTables.py b/pyfpdb/XTables.py index c19db5d9..a14debc1 100644 --- a/pyfpdb/XTables.py +++ b/pyfpdb/XTables.py @@ -69,36 +69,42 @@ class Table(Table_Window): for listing in os.popen('xwininfo -root -tree').readlines(): if re.search(search_string, listing): print listing - mo = re.match('\s+([\dxabcdef]+)\s', listing) - window_number = int( mo.group(1), 0) - - done_looping = False - for outside in root.query_tree().children: - for inside in outside.query_tree().children: - if done_looping: break - if inside.id == window_number: - self.window = inside - self.parent = outside - done_looping = True - break + mo = re.match('\s+([\dxabcdef]+) (.+):\s\(\"([a-zA-Z.]+)\".+ (\d+)x(\d+)\+\d+\+\d+ \+(\d+)\+(\d+)', listing) + self.number = int( mo.group(1), 0) + self.width = int( mo.group(4) ) + self.height = int( mo.group(5) ) + self.x = int( mo.group(6) ) + self.y = int( mo.group(7) ) + self.title = re.sub('\"', '', mo.group(2)) + self.exe = "" # not used? + self.hud = None +# done_looping = False +# for outside in root.query_tree().children: +# for inside in outside.query_tree().children: +# if done_looping: break +# if inside.id == window_number: +# self.window = inside +# self.parent = outside +# done_looping = True +# break if window_number is None: print "Window %s not found. Skipping." % search_string return None - my_geo = self.window.get_geometry() - pa_geo = self.parent.get_geometry() +# my_geo = self.window.get_geometry() +# pa_geo = self.parent.get_geometry() +# +# self.x = pa_geo.x + my_geo.x +# self.y = pa_geo.y + my_geo.y +# self.width = my_geo.width +# self.height = my_geo.height +# self.exe = self.window.get_wm_class()[0] +# self.title = self.window.get_wm_name() +# self.site = "" +# self.hud = None - self.x = pa_geo.x + my_geo.x - self.y = pa_geo.y + my_geo.y - self.width = my_geo.width - self.height = my_geo.height - self.exe = self.window.get_wm_class()[0] - self.title = self.window.get_wm_name() - self.site = "" - self.hud = None - - window_string = str(self.window) +# window_string = str(self.window) mo = re.match('Xlib\.display\.Window\(([\dxabcdef]+)', window_string) if not mo: print "Not matched" From 04c09af7b2706d20cc21e74ea9252a6192921bce Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 17 Nov 2009 21:47:43 +0000 Subject: [PATCH 26/32] tidy up aggregation code, NOTE: renamed some aggregation config to try and make meaning clearer, updated aggregation description in .example --- pyfpdb/Configuration.py | 12 ++-- pyfpdb/Database.py | 15 ++--- pyfpdb/HUD_config.xml.example | 116 ++++++++++++++++++---------------- pyfpdb/HUD_main.py | 35 ++-------- 4 files changed, 77 insertions(+), 101 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 3f183204..3fa5cc1d 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -361,16 +361,16 @@ class HudUI: self.node = node self.label = node.getAttribute('label') # + self.hud_style = node.getAttribute('stat_range') + self.hud_days = node.getAttribute('stat_days') self.aggregate_ring = string_to_bool(node.getAttribute('aggregate_ring_game_stats')) self.aggregate_tour = string_to_bool(node.getAttribute('aggregate_tourney_stats')) - self.hud_style = node.getAttribute('stat_aggregation_range') - self.hud_days = node.getAttribute('aggregation_days') self.agg_bb_mult = node.getAttribute('aggregation_level_multiplier') # - self.h_aggregate_ring = string_to_bool(node.getAttribute('aggregate_hero_ring_game_stats')) - self.h_aggregate_tour = string_to_bool(node.getAttribute('aggregate_hero_tourney_stats')) - self.h_hud_style = node.getAttribute('hero_stat_aggregation_range') - self.h_hud_days = node.getAttribute('hero_aggregation_days') + self.h_hud_style = node.getAttribute('hero_stat_range') + self.h_hud_days = node.getAttribute('hero_stat_days') + self.h_aggregate_ring = string_to_bool(node.getAttribute('aggregate_hero_ring_game_stats')) + self.h_aggregate_tour = string_to_bool(node.getAttribute('aggregate_hero_tourney_stats')) self.h_agg_bb_mult = node.getAttribute('hero_aggregation_level_multiplier') diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 0314d78d..07b7a4d4 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -432,16 +432,14 @@ class Database: print "*** Database Error: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) def get_stats_from_hand( self, hand, type # type is "ring" or "tour" - , hud_params = {'aggregate_tour':False, 'aggregate_ring':False, 'hud_style':'A', 'hud_days':30, 'agg_bb_mult':100 - ,'h_aggregate_tour':False, 'h_aggregate_ring':False, 'h_hud_style':'S', 'h_hud_days':30, 'h_agg_bb_mult':100} + , hud_params = {'hud_style':'A', 'agg_bb_mult':1000 + ,'h_hud_style':'S', 'h_agg_bb_mult':1000} , hero_id = -1 ): - aggregate = hud_params['aggregate_tour'] if type == "tour" else hud_params['aggregate_ring'] hud_style = hud_params['hud_style'] - agg_bb_mult = hud_params['agg_bb_mult'] if aggregate else 1 - h_aggregate = hud_params['h_aggregate_tour'] if type == "tour" else hud_params['h_aggregate_ring'] + agg_bb_mult = hud_params['agg_bb_mult'] h_hud_style = hud_params['h_hud_style'] - h_agg_bb_mult = hud_params['h_agg_bb_mult'] if h_aggregate else 1 + h_agg_bb_mult = hud_params['h_agg_bb_mult'] stat_dict = {} if hud_style == 'S' or h_hud_style == 'S': @@ -468,13 +466,8 @@ class Database: #elif h_hud_style == 'H': # h_stylekey = date_nhands_ago needs array by player here ... - #if aggregate: always use aggregate query now: use agg_bb_mult of 1 for no aggregation: query = 'get_stats_from_hand_aggregated' subs = (hand, hero_id, stylekey, agg_bb_mult, agg_bb_mult, hero_id, h_stylekey, h_agg_bb_mult, h_agg_bb_mult) - #print "agg query subs:", subs - #else: - # query = 'get_stats_from_hand' - # subs = (hand, stylekey) #print "get stats: hud style =", hud_style, "query =", query, "subs =", subs c = self.connection.cursor() diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index 952a0dbf..b0f26c53 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -4,91 +4,95 @@ - Date: Thu, 19 Nov 2009 15:28:48 +0800 Subject: [PATCH 27/32] Add test functions for SQLite Added test for VARIANCE() Added test for floor() --- pyfpdb/test_Database.py | 51 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 pyfpdb/test_Database.py diff --git a/pyfpdb/test_Database.py b/pyfpdb/test_Database.py new file mode 100644 index 00000000..9283f46d --- /dev/null +++ b/pyfpdb/test_Database.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +import sqlite3 +import fpdb_db +import math + +# Should probably use our wrapper classes - creating sqlite db in memory +sqlite3.register_converter("bool", lambda x: bool(int(x))) +sqlite3.register_adapter(bool, lambda x: "1" if x else "0") + +con = sqlite3.connect(":memory:") +con.isolation_level = None + +#Floor function +con.create_function("floor", 1, math.floor) + +#Mod function +tmp = fpdb_db.sqlitemath() +con.create_function("mod", 2, tmp.mod) + +# Aggregate function VARIANCE() +con.create_aggregate("variance", 1, fpdb_db.VARIANCE) + + +cur = con.cursor() + +def testSQLiteVarianceFunction(): + cur.execute("CREATE TABLE test(i)") + cur.execute("INSERT INTO test(i) values (1)") + cur.execute("INSERT INTO test(i) values (2)") + cur.execute("INSERT INTO test(i) values (3)") + cur.execute("SELECT variance(i) from test") + result = cur.fetchone()[0] + + print "DEBUG: Testing variance function" + print "DEBUG: result: %s expecting: 0.666666 (result-expecting ~= 0.0): %s" % (result, (result - 0.66666)) + cur.execute("DROP TABLE test") + assert (result - 0.66666) <= 0.0001 + +def testSQLiteFloorFunction(): + vars = [0.1, 1.5, 2.6, 3.5, 4.9] + cur.execute("CREATE TABLE test(i float)") + for var in vars: + cur.execute("INSERT INTO test(i) values(%f)" % var) + cur.execute("SELECT floor(i) from test") + result = cur.fetchall() + print "DEBUG: result: %s" % result + answer = 0 + for i in result: + print "DEBUG: int(var): %s" % int(i[0]) + assert answer == int(i[0]) + answer = answer + 1 From eadd7c045c996c5e1963138593be6222068b4239 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 19 Nov 2009 17:22:53 +0800 Subject: [PATCH 28/32] Adding broken mod() test --- pyfpdb/test_Database.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pyfpdb/test_Database.py b/pyfpdb/test_Database.py index 9283f46d..d7fcc43c 100644 --- a/pyfpdb/test_Database.py +++ b/pyfpdb/test_Database.py @@ -49,3 +49,18 @@ def testSQLiteFloorFunction(): print "DEBUG: int(var): %s" % int(i[0]) assert answer == int(i[0]) answer = answer + 1 + cur.execute("DROP TABLE test") + +def testSQLiteModFunction(): + vars = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ,17, 18] + cur.execute("CREATE TABLE test(i float)") + for var in vars: + cur.execute("INSERT INTO test(i) values(%i)" % var) + cur.execute("SELECT mod(i,13) from test") + result = cur.fetchall() + answer = 0 + for i in result: + print "DEBUG: int(var): %s" % i[0] + assert answer == i[0] + answer = answer + 1 + cur.execute("DROP TABLE test") From 33592fbc4edff30fb8ba72e6068c44842f4af5f8 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 18 Nov 2009 00:12:24 +0800 Subject: [PATCH 29/32] Add math function for sqlite - may still be broken --- pyfpdb/fpdb_db.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 27291d7f..f3dcd681 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -20,6 +20,7 @@ import os import re import sys import logging +import math from time import time, strftime from Exceptions import * @@ -53,6 +54,10 @@ class VARIANCE: def finalize(self): return float(var(self.store)) +class sqlitemath: + def mod(self, a, b): + return a%b + class fpdb_db: MYSQL_INNODB = 2 PGSQL = 3 @@ -148,6 +153,9 @@ class fpdb_db: , detect_types=sqlite3.PARSE_DECLTYPES ) sqlite3.register_converter("bool", lambda x: bool(int(x))) sqlite3.register_adapter(bool, lambda x: "1" if x else "0") + self.db.create_function("floor", 1, math.floor) + tmp = sqlitemath() + self.db.create_function("mod", 2, tmp.mod) if use_numpy: self.db.create_aggregate("variance", 1, VARIANCE) else: From ea323d0d221d282283498f51a338913caba85d1a Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 19 Nov 2009 17:33:12 +0800 Subject: [PATCH 30/32] Fix mod() test for sqlite --- pyfpdb/test_Database.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pyfpdb/test_Database.py b/pyfpdb/test_Database.py index d7fcc43c..b348f741 100644 --- a/pyfpdb/test_Database.py +++ b/pyfpdb/test_Database.py @@ -53,14 +53,16 @@ def testSQLiteFloorFunction(): def testSQLiteModFunction(): vars = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ,17, 18] - cur.execute("CREATE TABLE test(i float)") + cur.execute("CREATE TABLE test(i int)") for var in vars: cur.execute("INSERT INTO test(i) values(%i)" % var) cur.execute("SELECT mod(i,13) from test") result = cur.fetchall() - answer = 0 + idx = 0 for i in result: print "DEBUG: int(var): %s" % i[0] - assert answer == i[0] - answer = answer + 1 + assert vars[idx]%13 == int(i[0]) + idx = idx+1 + + assert 0 == 1 cur.execute("DROP TABLE test") From 5ba4dbb0e7c5871d4ec3b08a132a20c40934d87d Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 19 Nov 2009 17:54:00 +0800 Subject: [PATCH 31/32] Clean DerivedStats.py --- pyfpdb/DerivedStats.py | 687 ----------------------------------------- 1 file changed, 687 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 4b48f618..43220c4b 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -117,693 +117,6 @@ class DerivedStats(): def assembleHudCache(self, hand): -# # 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 = False -# if any(i for i in allIns[0][player]): -# isAllIn = True -# if (len(action_types[1][player])>0 or isAllIn): -# myStreet1Seen = True -# -# if any(i for i in allIns[1][player]): -# isAllIn = True -# if (len(action_types[2][player])>0 or isAllIn): -# myStreet2Seen = True -# -# if any(i for i in allIns[2][player]): -# isAllIn = True -# if (len(action_types[3][player])>0 or isAllIn): -# myStreet3Seen = True -# -# #print "base:", base -# if base=="hold": -# mySawShowdown = True -# if any(actiontype == "fold" for actiontype in action_types[3][player]): -# mySawShowdown = False -# else: -# #print "in else" -# if any(i for i in allIns[3][player]): -# isAllIn = True -# if (len(action_types[4][player])>0 or isAllIn): -# #print "in if" -# myStreet4Seen = True -# -# mySawShowdown = True -# if any(actiontype == "fold" for actiontype in action_types[4][player]): -# mySawShowdown = False -# -# 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: -# if any(actiontype == "bet" for actiontype in action_types[street][player]): -# myStreet1Aggr = True -# -# 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: -# if any(actiontype == "bet" for actiontype in action_types[street][player]): -# myStreet2Aggr = True -# -# 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: -# if any(actiontype == "bet" for actiontype in action_types[street][player]): -# myStreet3Aggr = True -# -# 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: -# if any(actiontype == "bet" for actiontype in action_types[street][player]): -# myStreet4Aggr=True -# -# 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 pass def vpip(self, hand): From 6eba4a554433bac5689486fab7cfcdfae9dcfc2d Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 19 Nov 2009 22:19:41 +0000 Subject: [PATCH 32/32] fix a merge problem and replace to_char() for sqlite, player stats now working in sqlite :-) --- pyfpdb/GuiPlayerStats.py | 2 +- pyfpdb/SQL.py | 269 +-------------------------------------- 2 files changed, 3 insertions(+), 268 deletions(-) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 8b5f1f05..53eac73f 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -544,7 +544,7 @@ class GuiPlayerStats (threading.Thread): # set flag in self.columns to show posn column [x for x in self.columns if x[0] == 'plposition'][0][1] = True else: - query = query.replace("", "'1'") + query = query.replace("", "gt.base") # unset flag in self.columns to hide posn column [x for x in self.columns if x[0] == 'plposition'][0][1] = False diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 3846a371..9c74e1f1 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -1940,7 +1940,7 @@ class Sql: and h.seats - and to_char(h.handStart, 'YYYY-MM-DD') + and date(h.handStart) group by hgameTypeId ,hp.playerId ,gt.base @@ -1960,272 +1960,7 @@ class Sql: end ,upper(gt.limitType) desc - ,maxbigblind desc - ,s.name - """ - - if db_server == 'mysql': - self.query['playerStats'] = """ - SELECT - concat(upper(stats.limitType), ' ' - ,concat(upper(substring(stats.category,1,1)),substring(stats.category,2) ), ' ' - ,stats.name, ' ' - ,cast(stats.bigBlindDesc as char) - ) AS Game - ,stats.n - ,stats.vpip - ,stats.pfr - ,stats.pf3 - ,stats.steals - ,stats.saw_f - ,stats.sawsd - ,stats.wtsdwsf - ,stats.wmsd - ,stats.FlAFq - ,stats.TuAFq - ,stats.RvAFq - ,stats.PoFAFq - ,stats.Net - ,stats.BBper100 - ,stats.Profitperhand - ,case when hprof2.variance = -999 then '-' - else format(hprof2.variance, 2) - end AS Variance - ,stats.AvgSeats - FROM - (select /* stats from hudcache */ - gt.base - ,gt.category - ,upper(gt.limitType) as limitType - ,s.name - , AS bigBlindDesc - , AS gtId - ,sum(HDs) AS n - ,format(100.0*sum(street0VPI)/sum(HDs),1) AS vpip - ,format(100.0*sum(street0Aggr)/sum(HDs),1) AS pfr - ,case when sum(street0_3Bchance) = 0 then '0' - else format(100.0*sum(street0_3Bdone)/sum(street0_3Bchance),1) - end AS pf3 - ,case when sum(stealattemptchance) = 0 then '-' - else format(100.0*sum(stealattempted)/sum(stealattemptchance),1) - end AS steals - ,format(100.0*sum(street1Seen)/sum(HDs),1) AS saw_f - ,format(100.0*sum(sawShowdown)/sum(HDs),1) AS sawsd - ,case when sum(street1Seen) = 0 then '-' - else format(100.0*sum(sawShowdown)/sum(street1Seen),1) - end AS wtsdwsf - ,case when sum(sawShowdown) = 0 then '-' - else format(100.0*sum(wonAtSD)/sum(sawShowdown),1) - end AS wmsd - ,case when sum(street1Seen) = 0 then '-' - else format(100.0*sum(street1Aggr)/sum(street1Seen),1) - end AS FlAFq - ,case when sum(street2Seen) = 0 then '-' - else format(100.0*sum(street2Aggr)/sum(street2Seen),1) - end AS TuAFq - ,case when sum(street3Seen) = 0 then '-' - else format(100.0*sum(street3Aggr)/sum(street3Seen),1) - end AS RvAFq - ,case when sum(street1Seen)+sum(street2Seen)+sum(street3Seen) = 0 then '-' - else format(100.0*(sum(street1Aggr)+sum(street2Aggr)+sum(street3Aggr)) - /(sum(street1Seen)+sum(street2Seen)+sum(street3Seen)),1) - end AS PoFAFq - ,format(sum(totalProfit)/100.0,2) AS Net - ,format((sum(totalProfit/(gt.bigBlind+0.0))) / (sum(HDs)/100.0),2) - AS BBper100 - ,format( (sum(totalProfit)/100.0) / sum(HDs), 4) AS Profitperhand - ,format( sum(activeSeats*HDs)/(sum(HDs)+0.0), 2) AS AvgSeats - from Gametypes gt - inner join Sites s on s.Id = gt.siteId - inner join HudCache hc on hc.gameTypeId = gt.Id - where hc.playerId in - and - and hc.activeSeats - and concat( '20', substring(hc.styleKey,2,2), '-', substring(hc.styleKey,4,2), '-' - , substring(hc.styleKey,6,2) ) - group by gt.base - ,gt.category - - ,plposition - ,upper(gt.limitType) - ,s.name - having 1 = 1 - order by pname - ,gt.base - ,gt.category - - ,case when 'B' then 'B' - when 'S' then 'S' - else concat('Z', ) - end - - ,upper(gt.limitType) desc - ,maxbigblind desc - ,s.name - """ - elif db_server == 'postgresql': - self.query['playerDetailedStats'] = """ - select AS hgametypeid - , AS pname - ,gt.base - ,gt.category - ,upper(gt.limitType) AS limittype - ,s.name - ,min(gt.bigBlind) AS minbigblind - ,max(gt.bigBlind) AS maxbigblind - /*, AS gtid*/ - , AS plposition - ,count(1) AS n - ,100.0*sum(cast(hp.street0VPI as integer))/count(1) AS vpip - ,100.0*sum(cast(hp.street0Aggr as integer))/count(1) AS pfr - ,case when sum(cast(hp.street0_3Bchance as integer)) = 0 then -999 - else 100.0*sum(cast(hp.street0_3Bdone as integer))/sum(cast(hp.street0_3Bchance as integer)) - end AS pf3 - ,case when sum(cast(hp.stealattemptchance as integer)) = 0 then -999 - else 100.0*sum(cast(hp.stealattempted as integer))/sum(cast(hp.stealattemptchance as integer)) - end AS steals - ,100.0*sum(cast(hp.street1Seen as integer))/count(1) AS saw_f - ,100.0*sum(cast(hp.sawShowdown as integer))/count(1) AS sawsd - ,case when sum(cast(hp.street1Seen as integer)) = 0 then -999 - else 100.0*sum(cast(hp.sawShowdown as integer))/sum(cast(hp.street1Seen as integer)) - end AS wtsdwsf - ,case when sum(cast(hp.sawShowdown as integer)) = 0 then -999 - else 100.0*sum(cast(hp.wonAtSD as integer))/sum(cast(hp.sawShowdown as integer)) - end AS wmsd - ,case when sum(cast(hp.street1Seen as integer)) = 0 then -999 - else 100.0*sum(cast(hp.street1Aggr as integer))/sum(cast(hp.street1Seen as integer)) - end AS flafq - ,case when sum(cast(hp.street2Seen as integer)) = 0 then -999 - else 100.0*sum(cast(hp.street2Aggr as integer))/sum(cast(hp.street2Seen as integer)) - end AS tuafq - ,case when sum(cast(hp.street3Seen as integer)) = 0 then -999 - else 100.0*sum(cast(hp.street3Aggr as integer))/sum(cast(hp.street3Seen as integer)) - end AS rvafq - ,case when sum(cast(hp.street1Seen as integer))+sum(cast(hp.street2Seen as integer))+sum(cast(hp.street3Seen as integer)) = 0 then -999 - else 100.0*(sum(cast(hp.street1Aggr as integer))+sum(cast(hp.street2Aggr as integer))+sum(cast(hp.street3Aggr as integer))) - /(sum(cast(hp.street1Seen as integer))+sum(cast(hp.street2Seen as integer))+sum(cast(hp.street3Seen as integer))) - end AS pofafq - ,sum(hp.totalProfit)/100.0 AS net - ,sum(hp.rake)/100.0 AS rake - ,100.0*avg(hp.totalProfit/(gt.bigBlind+0.0)) AS bbper100 - ,avg(hp.totalProfit)/100.0 AS profitperhand - ,100.0*avg((hp.totalProfit+hp.rake)/(gt.bigBlind+0.0)) AS bb100xr - ,avg((hp.totalProfit+hp.rake)/100.0) AS profhndxr - ,avg(h.seats+0.0) AS avgseats - ,variance(hp.totalProfit/100.0) AS variance - from HandsPlayers hp - inner join Hands h on (h.id = hp.handId) - inner join Gametypes gt on (gt.Id = h.gameTypeId) - inner join Sites s on (s.Id = gt.siteId) - inner join Players p on (p.Id = hp.playerId) - where hp.playerId in - /*and hp.tourneysPlayersId IS NULL*/ - and h.seats - - - and to_char(h.handStart, 'YYYY-MM-DD') - group by hgameTypeId - ,pname - ,gt.base - ,gt.category - - ,plposition - ,upper(gt.limitType) - ,s.name - having 1 = 1 - order by pname - ,gt.base - ,gt.category - - ,case when 'B' then 'B' - when 'S' then 'S' - when '0' then 'Y' - else 'Z'|| - end - - ,upper(gt.limitType) desc - ,maxbigblind desc - ,s.name - """ - elif db_server == 'sqlite': - self.query['playerDetailedStats'] = """ - select AS hgametypeid - ,gt.base - ,gt.category - ,upper(gt.limitType) AS limittype - ,s.name - ,min(gt.bigBlind) AS minbigblind - ,max(gt.bigBlind) AS maxbigblind - /*, AS gtid*/ - , AS plposition - ,count(1) AS n - ,100.0*sum(cast(hp.street0VPI as integer))/count(1) AS vpip - ,100.0*sum(cast(hp.street0Aggr as integer))/count(1) AS pfr - ,case when sum(cast(hp.street0_3Bchance as integer)) = 0 then -999 - else 100.0*sum(cast(hp.street0_3Bdone as integer))/sum(cast(hp.street0_3Bchance as integer)) - end AS pf3 - ,case when sum(cast(hp.stealattemptchance as integer)) = 0 then -999 - else 100.0*sum(cast(hp.stealattempted as integer))/sum(cast(hp.stealattemptchance as integer)) - end AS steals - ,100.0*sum(cast(hp.street1Seen as integer))/count(1) AS saw_f - ,100.0*sum(cast(hp.sawShowdown as integer))/count(1) AS sawsd - ,case when sum(cast(hp.street1Seen as integer)) = 0 then -999 - else 100.0*sum(cast(hp.sawShowdown as integer))/sum(cast(hp.street1Seen as integer)) - end AS wtsdwsf - ,case when sum(cast(hp.sawShowdown as integer)) = 0 then -999 - else 100.0*sum(cast(hp.wonAtSD as integer))/sum(cast(hp.sawShowdown as integer)) - end AS wmsd - ,case when sum(cast(hp.street1Seen as integer)) = 0 then -999 - else 100.0*sum(cast(hp.street1Aggr as integer))/sum(cast(hp.street1Seen as integer)) - end AS flafq - ,case when sum(cast(hp.street2Seen as integer)) = 0 then -999 - else 100.0*sum(cast(hp.street2Aggr as integer))/sum(cast(hp.street2Seen as integer)) - end AS tuafq - ,case when sum(cast(hp.street3Seen as integer)) = 0 then -999 - else 100.0*sum(cast(hp.street3Aggr as integer))/sum(cast(hp.street3Seen as integer)) - end AS rvafq - ,case when sum(cast(hp.street1Seen as integer))+sum(cast(hp.street2Seen as integer))+sum(cast(hp.street3Seen as integer)) = 0 then -999 - else 100.0*(sum(cast(hp.street1Aggr as integer))+sum(cast(hp.street2Aggr as integer))+sum(cast(hp.street3Aggr as integer))) - /(sum(cast(hp.street1Seen as integer))+sum(cast(hp.street2Seen as integer))+sum(cast(hp.street3Seen as integer))) - end AS pofafq - ,sum(hp.totalProfit)/100.0 AS net - ,sum(hp.rake)/100.0 AS rake - ,100.0*avg(hp.totalProfit/(gt.bigBlind+0.0)) AS bbper100 - ,avg(hp.totalProfit)/100.0 AS profitperhand - ,100.0*avg((hp.totalProfit+hp.rake)/(gt.bigBlind+0.0)) AS bb100xr - ,avg((hp.totalProfit+hp.rake)/100.0) AS profhndxr - ,avg(h.seats+0.0) AS avgseats - ,variance(hp.totalProfit/100.0) AS variance - from HandsPlayers hp - inner join Hands h on (h.id = hp.handId) - inner join Gametypes gt on (gt.Id = h.gameTypeId) - inner join Sites s on (s.Id = gt.siteId) - where hp.playerId in - /*and hp.tourneysPlayersId IS NULL*/ - and h.seats - - - and to_char(h.handStart, 'YYYY-MM-DD') - group by hgameTypeId - ,hp.playerId - ,gt.base - ,gt.category - - ,plposition - ,upper(gt.limitType) - ,s.name - order by hp.playerId - ,gt.base - ,gt.category - - ,case when 'B' then 'B' - when 'S' then 'S' - when '0' then 'Y' - else 'Z'|| - end - - ,upper(gt.limitType) desc - ,maxbigblind desc + ,max(gt.bigBlind) desc ,s.name """