From 6a999f4232b2066021fb46770f7b33fbcb5058bf Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 20 Jun 2010 17:47:23 +0100 Subject: [PATCH 01/63] change shortcut key for import button so that it still works when button label is 'I M P O R T I N G' --- pyfpdb/GuiAutoImport.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py index 6dd67ba5..5ff28703 100755 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -100,7 +100,7 @@ class GuiAutoImport (threading.Thread): hbox.pack_start(lbl1, expand=True, fill=False) self.doAutoImportBool = False - self.startButton = gtk.ToggleButton(" _Start Autoimport ") + self.startButton = gtk.ToggleButton(" Start Autoimpor_t ") self.startButton.connect("clicked", self.startClicked, "start clicked") hbox.pack_start(self.startButton, expand=False, fill=False) @@ -153,7 +153,7 @@ class GuiAutoImport (threading.Thread): def do_import(self): """Callback for timer to do an import iteration.""" if self.doAutoImportBool: - self.startButton.set_label(u' I M P O R T I N G ') + self.startButton.set_label(u' I M P O R _T I N G ') self.importer.runUpdated() self.addText(".") #sys.stdout.write(".") @@ -164,9 +164,9 @@ class GuiAutoImport (threading.Thread): def reset_startbutton(self): if self.pipe_to_hud is not None: - self.startButton.set_label(u' _Stop Autoimport ') + self.startButton.set_label(u' Stop Autoimpor_t ') else: - self.startButton.set_label(u' _Start Autoimport ') + self.startButton.set_label(u' Start Autoimpor_t ') return False @@ -243,7 +243,7 @@ class GuiAutoImport (threading.Thread): #print >>self.pipe_to_hud.stdin, "\n" self.pipe_to_hud.communicate('\n') # waits for process to terminate self.pipe_to_hud = None - self.startButton.set_label(u' _Start Autoimport ') + self.startButton.set_label(u' Start Autoimpor_t ') #end def GuiAutoImport.startClicked From 1d263c81393ab780c5d1a82914ce4250060c63cf Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 11 Jul 2010 18:36:45 +0100 Subject: [PATCH 02/63] fix call to db.connected() --- pyfpdb/fpdb.pyw | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index 4554827c..e4d48cf1 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -66,6 +66,7 @@ cl_options = string.join(sys.argv[1:]) (options, argv) = Options.fpdb_options() import logging, logging.config +log = logging.getLogger("fpdb") try: import pygtk @@ -854,9 +855,10 @@ class fpdb: print "Quitting normally" # TODO: check if current settings differ from profile, if so offer to save or abort try: - if self.db is not None and self.db.connected: + if self.db is not None and self.db.connected(): self.db.disconnect() except _mysql_exceptions.OperationalError: # oh, damn, we're already disconnected + log.info("fpdb.quit disconnect error being ignored: "+str(sys.exc_info())) pass self.statusIcon.set_visible(False) From 45fa170758dd72409349bf44803730594b4386d7 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 11 Jul 2010 18:53:26 +0100 Subject: [PATCH 03/63] comment out close of fpdb after db recreate, I don't see how it helps --- pyfpdb/fpdb.pyw | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index e4d48cf1..473c4641 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -424,12 +424,18 @@ class fpdb: # TODO: figure out why this seems to be necessary dia_restart = gtk.MessageDialog(parent=self.window, flags=0, type=gtk.MESSAGE_WARNING, buttons=(gtk.BUTTONS_OK), message_format="Restart fpdb") - diastring = "Fpdb now needs to close. Please restart it." - dia_restart.format_secondary_text(diastring) - - dia_restart.run() - dia_restart.destroy() - self.quit(None, None) + + # sc: I don't see the need for this closedown - if it is a problem let me know + # and I will look into it .... (if there is a problem with db re-create I + # would expect it to be before here, i.e. maybe user needs to restart before + # the re-create. Once here everything should be ok.) + # The recreate will not work if autoimport is running! Other than that it + # should work. + #diastring = "Fpdb now needs to close. Please restart it." + #dia_restart.format_secondary_text(diastring) + #dia_restart.run() + #dia_restart.destroy() + #self.quit(None, None) elif response == gtk.RESPONSE_NO: self.release_global_lock() print 'User cancelled recreating tables' From b52110d45f94ac725a374c9cb34162739298d5df Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 11 Jul 2010 19:00:27 +0100 Subject: [PATCH 04/63] change tabs to spaces --- pyfpdb/fpdb.pyw | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index 473c4641..3c42ae1c 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -36,9 +36,9 @@ if os.name == 'nt' and sys.version[0:3] not in ('2.5', '2.6') and '-r' not in sy print "Python " + sys.version[0:3] + ' - press return to continue\n' sys.stdin.readline() if os.name=='nt': - os.execvpe('pythonw.exe', ('pythonw.exe', 'fpdb.pyw', '-r'), os.environ) # first arg is ignored (name of program being run) - else: - os.execvpe('python', ('python', 'fpdb.pyw', '-r'), os.environ) # first arg is ignored (name of program being run) + os.execvpe('pythonw.exe', ('pythonw.exe', 'fpdb.pyw', '-r'), os.environ) # first arg is ignored (name of program being run) + else: + os.execvpe('python', ('python', 'fpdb.pyw', '-r'), os.environ) # first arg is ignored (name of program being run) else: print "\npython 2.5 not found, please install python 2.5 or 2.6 for fpdb\n" raw_input("Press ENTER to continue.") @@ -437,7 +437,7 @@ class fpdb: #dia_restart.destroy() #self.quit(None, None) elif response == gtk.RESPONSE_NO: - self.release_global_lock() + self.release_global_lock() print 'User cancelled recreating tables' #if not lock_released: #end def dia_recreate_tables From 32e1cb7b7f06eed5bc7ad9991695bde322f1887b Mon Sep 17 00:00:00 2001 From: steffen123 Date: Mon, 12 Jul 2010 10:20:53 +0200 Subject: [PATCH 05/63] another fix for the introduction of TT.limitType --- pyfpdb/SQL.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index a1eec221..6228ab24 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -1992,7 +1992,7 @@ class Sql: end as bb_or_buyin from Gametypes gt cross join TourneyTypes tt - order by type, limitType DESC, bb_or_buyin DESC""" + order by type, gt.limitType DESC, bb_or_buyin DESC""" if db_server == 'mysql': self.query['playerDetailedStats'] = """ From 04ec51d7c16ab76842a74333d2e47524a9392e97 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Mon, 12 Jul 2010 11:00:50 +0200 Subject: [PATCH 06/63] DB: Fix capitalisation of Gametypes table in SQLite --- pyfpdb/Database.py | 2 +- pyfpdb/SQL.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 513c4ee9..bf0ed73b 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -74,7 +74,7 @@ except ImportError: use_numpy = False -DB_VERSION = 131 +DB_VERSION = 132 # Variance created as sqlite has a bunch of undefined aggregate functions. diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 6228ab24..818a2d0e 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -190,7 +190,7 @@ class Sql: smallBet int, bigBet int)""" elif db_server == 'sqlite': - self.query['createGametypesTable'] = """CREATE TABLE GameTypes ( + self.query['createGametypesTable'] = """CREATE TABLE Gametypes ( id INTEGER PRIMARY KEY, siteId INTEGER, currency TEXT, From d208d627a472e8815a93870d72bf1e718e1eaa3b Mon Sep 17 00:00:00 2001 From: steffen123 Date: Mon, 12 Jul 2010 16:48:12 +0200 Subject: [PATCH 07/63] stop sqlite&postgres from doing except _mysql.... sqlite gives another error on quit unfortunately --- pyfpdb/fpdb.pyw | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index 763d3ef1..4ba3bb4a 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -844,11 +844,16 @@ class fpdb: #FIXME get two "quitting normally" messages, following the addition of the self.window.destroy() call print "Quitting normally" # TODO: check if current settings differ from profile, if so offer to save or abort - try: + + if self.db.backend==self.db.MYSQL_INNODB: + try: + if self.db is not None and self.db.connected: + self.db.disconnect() + except _mysql_exceptions.OperationalError: # oh, damn, we're already disconnected + pass + else: if self.db is not None and self.db.connected: self.db.disconnect() - except _mysql_exceptions.OperationalError: # oh, damn, we're already disconnected - pass self.statusIcon.set_visible(False) self.window.destroy() # explicitly destroy to allow child windows to close cleanly From 1d571cabee94434aad96059b2e7f26d82e2f83ce Mon Sep 17 00:00:00 2001 From: steffen123 Date: Mon, 12 Jul 2010 18:04:30 +0200 Subject: [PATCH 08/63] windows: by sqlcoder, fixes importing files with greek characters --- pyfpdb/fpdb_import.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index e8455c01..ac569c95 100755 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -152,7 +152,7 @@ class Importer: #Add an individual file to filelist def addImportFile(self, filename, site = "default", filter = "passthrough"): #TODO: test it is a valid file -> put that in config!! - if filename in self.filelist or not os.path.exists(filename): + if filename in self.filelist or not os.path.exists(unicode(filename,'utf-8')): return self.filelist[filename] = [site] + [filter] if site not in self.siteIds: @@ -406,7 +406,7 @@ class Importer: conv = None (stored, duplicates, partial, errors, ttime) = (0, 0, 0, 0, time()) - file = file.decode(Configuration.LOCALE_ENCODING) + file = file.decode("utf-8") #(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 d4e54e6aaee424055a4c0e39c87b57711147e0ca Mon Sep 17 00:00:00 2001 From: steffen123 Date: Tue, 13 Jul 2010 18:04:26 +0200 Subject: [PATCH 09/63] POLISH: it can now quit when it wasn't able to connect to DB --- pyfpdb/fpdb.pyw | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index 4ba3bb4a..1afec904 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -845,15 +845,18 @@ class fpdb: print "Quitting normally" # TODO: check if current settings differ from profile, if so offer to save or abort - if self.db.backend==self.db.MYSQL_INNODB: - try: + if self.db!=None: + if self.db.backend==self.db.MYSQL_INNODB: + try: + if self.db is not None and self.db.connected: + self.db.disconnect() + except _mysql_exceptions.OperationalError: # oh, damn, we're already disconnected + pass + else: if self.db is not None and self.db.connected: self.db.disconnect() - except _mysql_exceptions.OperationalError: # oh, damn, we're already disconnected - pass else: - if self.db is not None and self.db.connected: - self.db.disconnect() + pass self.statusIcon.set_visible(False) self.window.destroy() # explicitly destroy to allow child windows to close cleanly From 8db0445d7104d0805bc42fbfe8e6f54c36108229 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Tue, 13 Jul 2010 18:04:53 +0200 Subject: [PATCH 10/63] IMAP: close server connection when done --- pyfpdb/ImapSummaries.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/ImapSummaries.py b/pyfpdb/ImapSummaries.py index 4f8813dd..f2874725 100755 --- a/pyfpdb/ImapSummaries.py +++ b/pyfpdb/ImapSummaries.py @@ -74,8 +74,8 @@ def run(config, db): print "completed running Imap import, closing server connection" #finally: # try: - # server.close() + server.close() # finally: # pass - #server.logout() + server.logout() \ No newline at end of file From 8ebea1a5ce7d205500bf48912db9a4ad7fb75ad1 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Tue, 13 Jul 2010 20:17:15 +0200 Subject: [PATCH 11/63] PSS: now records game category and limit type Not for mixed games - again, I need examples --- pyfpdb/PokerStarsSummary.py | 24 +++++++++++++++++++++--- pyfpdb/TourneySummary.py | 1 + 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/pyfpdb/PokerStarsSummary.py b/pyfpdb/PokerStarsSummary.py index e652a95c..99e4633d 100644 --- a/pyfpdb/PokerStarsSummary.py +++ b/pyfpdb/PokerStarsSummary.py @@ -25,22 +25,40 @@ import PokerStarsToFpdb from TourneySummary import * class PokerStarsSummary(TourneySummary): + limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl', 'LIMIT':'fl' } + games = { # base, category + "Hold'em" : ('hold','holdem'), + 'Omaha' : ('hold','omahahi'), + 'Omaha Hi/Lo' : ('hold','omahahilo'), + 'Razz' : ('stud','razz'), + 'RAZZ' : ('stud','razz'), + '7 Card Stud' : ('stud','studhi'), + '7 Card Stud Hi/Lo' : ('stud','studhilo'), + 'Badugi' : ('draw','badugi'), + 'Triple Draw 2-7 Lowball' : ('draw','27_3draw'), + '5 Card Draw' : ('draw','fivedraw') + } + re_TourNo = re.compile("\#[0-9]+,") re_Entries = re.compile("[0-9]+") re_Prizepool = re.compile("\$[0-9]+\.[0-9]+") - re_Player = re.compile("""(?P[0-9]+):\s(?P.*)\s\(.*\),(\s)?(\$(?P[0-9]+\.[0-9]+))?(?Pstill\splaying)?""") + re_Player = re.compile(u"""(?P[0-9]+):\s(?P.*)\s\(.*\),(\s)?(\$(?P[0-9]+\.[0-9]+))?(?Pstill\splaying)?""") re_BuyInFee = re.compile("(?P[0-9]+\.[0-9]+).*(?P[0-9]+\.[0-9]+)") re_FPP = re.compile("(?P[0-9]+)\sFPP") #note: the dollar and cent in the below line are currency-agnostic re_Added = re.compile("(?P[0-9]+)\.(?P[0-9]+)\s(?P[A-Z]+)(\sadded\sto\sthe\sprize\spool\sby\sPokerStars)") re_DateTime = re.compile("(?P[0-9]{4})\/(?P[0-9]{2})\/(?P[0-9]{2})[\- ]+(?P[0-9]+):(?P[0-9]+):(?P[0-9]+)") - # = re.compile("") + re_GameInfo = re.compile(u""".+(?PNo\sLimit|Limit|LIMIT|Pot\sLimit)\s(?PHold\'em|Razz|RAZZ|7\sCard\sStud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball|5\sCard\sDraw)""") def parseSummary(self): lines=self.summaryText.splitlines() self.tourNo = self.re_TourNo.findall(lines[0])[0][1:-1] #ignore game and limit type as thats not recorded - #print "tourNo:",self.tourNo + + result=self.re_GameInfo.search(lines[0]) + result=result.groupdict() + self.gametype['limitType']=self.limits[result['LIMIT']] + self.gametype['category']=self.games[result['GAME']][0] if lines[1].find("$")!=-1: #TODO: move this into a method and call that from PokerStarsToFpdb.py:269 if hand.buyinCurrency=="USD" etc. self.currency="USD" diff --git a/pyfpdb/TourneySummary.py b/pyfpdb/TourneySummary.py index 75d4bcde..89d7388f 100644 --- a/pyfpdb/TourneySummary.py +++ b/pyfpdb/TourneySummary.py @@ -92,6 +92,7 @@ class TourneySummary(object): self.isSatellite = False self.isDoubleOrNothing = False self.guarantee = 0 + self.gametype = {'category':None, 'limitType':None} # Collections indexed by player names self.playerIds = {} From b8968591c595d7751b54710fdb089deffb2eaa0c Mon Sep 17 00:00:00 2001 From: steffen123 Date: Tue, 13 Jul 2010 20:21:05 +0200 Subject: [PATCH 12/63] TPS: display limitType and category --- pyfpdb/GuiTourneyPlayerStats.py | 2 ++ pyfpdb/SQL.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/pyfpdb/GuiTourneyPlayerStats.py b/pyfpdb/GuiTourneyPlayerStats.py index 2ce1e2bb..7523f594 100644 --- a/pyfpdb/GuiTourneyPlayerStats.py +++ b/pyfpdb/GuiTourneyPlayerStats.py @@ -78,6 +78,8 @@ class GuiTourneyPlayerStats (GuiPlayerStats.GuiPlayerStats): # is column displayed, column heading, xalignment, formatting, celltype self.columns = [ ["siteName", True, "Site", 0.0, "%s", "str"] #,["tourney", False, "Tourney", 0.0, "%s", "str"] # true not allowed for this line + , ["category", True, "Cat.", 0.0, "%s", "str"] + , ["limitType", True, "Limit", 0.0, "%s", "str"] , ["currency", True, "Curr.", 0.0, "%s", "str"] , ["buyIn", True, "BuyIn", 1.0, "%3.2f", "str"] , ["fee", True, "Fee", 1.0, "%3.2f", "str"] diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index e6a39f2f..96a45d2c 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -2300,6 +2300,8 @@ class Sql: ,tt.currency AS currency ,(CASE WHEN tt.currency = "USD" THEN tt.buyIn/100.0 ELSE tt.buyIn END) AS buyIn ,tt.fee/100.0 AS fee + ,tt.category AS category + ,tt.limitType AS limitType ,p.name AS playerName ,COUNT(1) AS tourneyCount ,SUM(CASE WHEN tp.rank > 0 THEN 0 ELSE 1 END) AS unknownRank From 522a745eadc47c30756016f8789ad2d929190b59 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Tue, 13 Jul 2010 20:37:06 +0200 Subject: [PATCH 13/63] REFACTOR: move timezone changing method to HHC so it can used by other parsers --- pyfpdb/HandHistoryConverter.py | 17 +++++++++++++++++ pyfpdb/PokerStarsSummary.py | 3 ++- pyfpdb/PokerStarsToFpdb.py | 17 +---------------- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index acabbd8b..4554c2e8 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -494,6 +494,23 @@ or None if we fail to get the info """ def getTourney(self): return self.tourney + + @staticmethod + def changeTimezone(time, givenTimezone, wantedTimezone): + if givenTimezone=="ET" and wantedTimezone=="UTC": + # approximate rules for ET daylight savings time: + if ( time.month == 12 # all of Dec + or (time.month == 11 and time.day > 4) # and most of November + or time.month < 3 # and all of Jan/Feb + or (time.month == 3 and time.day < 11) ): # and 1st 10 days of March + offset = datetime.timedelta(hours=5) # are EST: assume 5 hour offset (ET without daylight saving) + else: + offset = datetime.timedelta(hours=4) # rest is EDT: assume 4 hour offset (ET with daylight saving) + # adjust time into UTC: + time = time + offset + #print " tz = %s start = %s" % (tz, str(hand.starttime)) + return time + #end @staticmethod def changeTimezone @staticmethod def getTableTitleRe(type, table_name=None, tournament = None, table_number=None): diff --git a/pyfpdb/PokerStarsSummary.py b/pyfpdb/PokerStarsSummary.py index 99e4633d..73844e57 100644 --- a/pyfpdb/PokerStarsSummary.py +++ b/pyfpdb/PokerStarsSummary.py @@ -21,6 +21,7 @@ from decimal import Decimal import datetime from Exceptions import FpdbParseError +from HandHistoryConverter import * import PokerStarsToFpdb from TourneySummary import * @@ -106,7 +107,7 @@ class PokerStarsSummary(TourneySummary): result=result.groupdict() datetimestr = "%s/%s/%s %s:%s:%s" % (result['Y'], result['M'],result['D'],result['H'],result['MIN'],result['S']) self.startTime= datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S") # also timezone at end, e.g. " ET" - self.startTime = PokerStarsToFpdb.removeET(self.startTime) + self.startTime = HandHistoryConverter.changeTimezone(self.startTime, "ET", "UTC") currentLine+=1 result=self.re_DateTime.search(lines[currentLine]) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index d7386e23..0a9e47fc 100644 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -26,21 +26,6 @@ from decimal import Decimal # PokerStars HH Format -def removeET(time): - # approximate rules for ET daylight savings time: - if ( time.month == 12 # all of Dec - or (time.month == 11 and time.day > 4) # and most of November - or time.month < 3 # and all of Jan/Feb - or (time.month == 3 and time.day < 11) ): # and 1st 10 days of March - offset = datetime.timedelta(hours=5) # are EST: assume 5 hour offset (ET without daylight saving) - else: - offset = datetime.timedelta(hours=4) # rest is EDT: assume 4 hour offset (ET with daylight saving) - # adjust time into UTC: - time = time + offset - #print " tz = %s start = %s" % (tz, str(hand.starttime)) - return time -#end def removeET - class PokerStars(HandHistoryConverter): # Class Variables @@ -244,7 +229,7 @@ class PokerStars(HandHistoryConverter): #tz = a.group('TZ') # just assume ET?? #print " tz = ", tz, " datetime =", datetimestr hand.startTime = datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S") # also timezone at end, e.g. " ET" - hand.startTime = removeET(hand.startTime) + hand.startTime = HandHistoryConverter.changeTimezone(hand.startTime, "ET", "UTC") if key == 'HID': hand.handid = info[key] if key == 'TOURNO': From 256d027ecabb8e38264a6e804bbfa39cf4ee8373 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Tue, 13 Jul 2010 21:17:40 +0200 Subject: [PATCH 14/63] PSS: calculates timezone out of start and end time now --- pyfpdb/PokerStarsSummary.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/pyfpdb/PokerStarsSummary.py b/pyfpdb/PokerStarsSummary.py index 73844e57..a384056a 100644 --- a/pyfpdb/PokerStarsSummary.py +++ b/pyfpdb/PokerStarsSummary.py @@ -48,7 +48,8 @@ class PokerStarsSummary(TourneySummary): re_FPP = re.compile("(?P[0-9]+)\sFPP") #note: the dollar and cent in the below line are currency-agnostic re_Added = re.compile("(?P[0-9]+)\.(?P[0-9]+)\s(?P[A-Z]+)(\sadded\sto\sthe\sprize\spool\sby\sPokerStars)") - re_DateTime = re.compile("(?P[0-9]{4})\/(?P[0-9]{2})\/(?P[0-9]{2})[\- ]+(?P[0-9]+):(?P[0-9]+):(?P[0-9]+)") + re_DateTime = re.compile("\[(?P[0-9]{4})\/(?P[0-9]{2})\/(?P[0-9]{2})[\- ]+(?P[0-9]+):(?P[0-9]+):(?P[0-9]+)") + re_DateTimeET = re.compile("(?P[0-9]{4})\/(?P[0-9]{2})\/(?P[0-9]{2})[\- ]+(?P[0-9]+):(?P[0-9]+):(?P[0-9]+)") re_GameInfo = re.compile(u""".+(?PNo\sLimit|Limit|LIMIT|Pot\sLimit)\s(?PHold\'em|Razz|RAZZ|7\sCard\sStud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball|5\sCard\sDraw)""") def parseSummary(self): @@ -103,19 +104,28 @@ class PokerStarsSummary(TourneySummary): currentLine+=1 #print "after prizepool lines[currentLine]", lines[currentLine] + useET=False result=self.re_DateTime.search(lines[currentLine]) + if not result: + print "in not result starttime" + useET=True + result=self.re_DateTimeET.search(lines[currentLine]) result=result.groupdict() datetimestr = "%s/%s/%s %s:%s:%s" % (result['Y'], result['M'],result['D'],result['H'],result['MIN'],result['S']) self.startTime= datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S") # also timezone at end, e.g. " ET" self.startTime = HandHistoryConverter.changeTimezone(self.startTime, "ET", "UTC") currentLine+=1 - result=self.re_DateTime.search(lines[currentLine]) + if useET: + result=self.re_DateTimeET.search(lines[currentLine]) + else: + result=self.re_DateTime.search(lines[currentLine]) if result: result=result.groupdict() datetimestr = "%s/%s/%s %s:%s:%s" % (result['Y'], result['M'],result['D'],result['H'],result['MIN'],result['S']) self.endTime= datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S") # also timezone at end, e.g. " ET" - currentLine+=1 + self.endTime = HandHistoryConverter.changeTimezone(self.endTime, "ET", "UTC") + currentLine+=1 if lines[currentLine].find("Tournament is still in progress")!=-1: currentLine+=1 From 02e1a7159202cb0e87daa865cb1394a1c8cf8e8e Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 13 Jul 2010 20:21:34 +0100 Subject: [PATCH 15/63] fix broken graphing --- pyfpdb/SQL.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 96a45d2c..ed74e9d2 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -2828,7 +2828,7 @@ class Sql: AND h.startTime < '' - AND gt.type is 'ring' + AND gt.type = 'ring' GROUP BY h.startTime, hp.handId, hp.sawShowdown, hp.totalProfit ORDER BY h.startTime""" From d78d69e9f4f8dce057db4721468d79bd8a3ffc53 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 13 Jul 2010 21:19:18 +0100 Subject: [PATCH 16/63] miss out fl/pl/nl checkbox if no relevant hands --- pyfpdb/RingFilters.py | 49 ++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/pyfpdb/RingFilters.py b/pyfpdb/RingFilters.py index db7ed4de..5a057937 100644 --- a/pyfpdb/RingFilters.py +++ b/pyfpdb/RingFilters.py @@ -66,6 +66,7 @@ class RingFilters(Filters.Filters): # Outer Packing box self.mainVBox = gtk.VBox(False, 0) + self.found = {'nl':False, 'fl':False, 'pl':False, 'ring':False, 'tour':False} self.label = {} self.callback = {} @@ -364,7 +365,7 @@ class RingFilters(Filters.Filters): #end def __set_game_select def __set_limit_select(self, w, limit): - #print w.get_active() + #print "__set_limit_select: limit =", limit, w.get_active() self.limits[limit] = w.get_active() log.debug("self.limit[%s] set to %s" %(limit, self.limits[limit])) if limit.isdigit() or (len(limit) > 2 and (limit[-2:] == 'nl' or limit[-2:] == 'fl' or limit[-2:] == 'pl')): @@ -488,7 +489,7 @@ class RingFilters(Filters.Filters): if self.limits[limit]: self.type = "ring" for cb in self.cbLimits.values(): - #print "cb label: ", cb.children()[0].get_text() + print "ring: cb label: ", cb.children()[0].get_text() if self.types[cb.get_children()[0].get_text()] == 'tour': cb.set_active(False) elif limit == "tour": @@ -627,7 +628,7 @@ class RingFilters(Filters.Filters): self.cursor.execute(self.sql.query['getCashLimits']) # selects limitType, bigBlind result = self.db.cursor.fetchall() - found = {'nl':False, 'fl':False, 'pl':False, 'ring':False, 'tour':False} + self.found = {'nl':False, 'fl':False, 'pl':False, 'ring':False, 'tour':False} if len(result) >= 1: hbox = gtk.HBox(True, 0) @@ -648,16 +649,16 @@ class RingFilters(Filters.Filters): if True: #line[0] == 'ring': if line[1] == 'fl': name = str(line[2]) - found['fl'] = True + self.found['fl'] = True elif line[1] == 'pl': name = str(line[2])+line[1] - found['pl'] = True + self.found['pl'] = True else: name = str(line[2])+line[1] - found['nl'] = True + self.found['nl'] = True self.cbLimits[name] = self.createLimitLine(hbox, name, name) self.types[name] = line[0] - found[line[0]] = True # type is ring/tour + self.found[line[0]] = True # type is ring/tour self.type = line[0] # if only one type, set it now if "LimitSep" in display and display["LimitSep"] == True and len(result) >= 2: hbox = gtk.HBox(True, 0) @@ -675,24 +676,30 @@ class RingFilters(Filters.Filters): self.cbNoLimits = self.createLimitLine(hbox, 'none', self.filterText['limitsnone']) dest = vbox3 # for ring/tour buttons - if "LimitType" in display and display["LimitType"] == True and found['nl'] and found['fl']: - #if found['fl']: - hbox = gtk.HBox(False, 0) - vbox3.pack_start(hbox, False, False, 0) - self.cbFL = self.createLimitLine(hbox, 'fl', self.filterText['limitsFL']) - #if found['nl']: - hbox = gtk.HBox(False, 0) - vbox3.pack_start(hbox, False, False, 0) - self.cbNL = self.createLimitLine(hbox, 'nl', self.filterText['limitsNL']) - hbox = gtk.HBox(False, 0) - vbox3.pack_start(hbox, False, False, 0) - self.cbPL = self.createLimitLine(hbox, 'pl', self.filterText['limitsPL']) - dest = vbox2 # for ring/tour buttons + if "LimitType" in display and display["LimitType"] == True: + num_limit_types = 0 + if self.found['fl']: num_limit_types = num_limit_types + 1 + if self.found['pl']: num_limit_types = num_limit_types + 1 + if self.found['nl']: num_limit_types = num_limit_types + 1 + if num_limit_types > 1: + if self.found['fl']: + hbox = gtk.HBox(False, 0) + vbox3.pack_start(hbox, False, False, 0) + self.cbFL = self.createLimitLine(hbox, 'fl', self.filterText['limitsFL']) + if self.found['nl']: + hbox = gtk.HBox(False, 0) + vbox3.pack_start(hbox, False, False, 0) + self.cbNL = self.createLimitLine(hbox, 'nl', self.filterText['limitsNL']) + if self.found['pl']: + hbox = gtk.HBox(False, 0) + vbox3.pack_start(hbox, False, False, 0) + self.cbPL = self.createLimitLine(hbox, 'pl', self.filterText['limitsPL']) + dest = vbox2 # for ring/tour buttons else: print "INFO: No games returned from database" log.info("No games returned from database") - if "Type" in display and display["Type"] == True and found['ring'] and found['tour']: + if "Type" in display and display["Type"] == True and self.found['ring'] and self.found['tour']: rb1 = gtk.RadioButton(None, self.filterText['ring']) rb1.connect('clicked', self.__set_limit_select, 'ring') rb2 = gtk.RadioButton(rb1, self.filterText['tour']) From 666161042950f90beaca088fad8fa0ff925224d4 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 13 Jul 2010 21:22:40 +0100 Subject: [PATCH 17/63] comment out debug msg --- pyfpdb/RingFilters.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/RingFilters.py b/pyfpdb/RingFilters.py index 5a057937..47bd5d6f 100644 --- a/pyfpdb/RingFilters.py +++ b/pyfpdb/RingFilters.py @@ -489,7 +489,7 @@ class RingFilters(Filters.Filters): if self.limits[limit]: self.type = "ring" for cb in self.cbLimits.values(): - print "ring: cb label: ", cb.children()[0].get_text() + #print "cb label: ", cb.children()[0].get_text() if self.types[cb.get_children()[0].get_text()] == 'tour': cb.set_active(False) elif limit == "tour": From b07505d3672c5dfcd71f093bc5fc21abe9f3e487 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 13 Jul 2010 21:23:32 +0100 Subject: [PATCH 18/63] tidy up closedown --- pyfpdb/Database.py | 1 + pyfpdb/fpdb.pyw | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index bf0ed73b..e6b72c1e 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -521,6 +521,7 @@ class Database: self.connection.commit() self.cursor.close() self.connection.close() + self.__connected = False def reconnect(self, due_to_error=False): """Reconnects the DB""" diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index 1203246f..27c5fd6d 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -849,18 +849,21 @@ class fpdb: def quit(self, widget, data=None): # TODO: can we get some / all of the stuff done in this function to execute on any kind of abort? #FIXME get two "quitting normally" messages, following the addition of the self.window.destroy() call - print "Quitting normally" + # ... because self.window.destroy() leads to self.destroy() which calls this! + if not self.quitting: + print "Quitting normally" + self.quitting = True # TODO: check if current settings differ from profile, if so offer to save or abort if self.db!=None: if self.db.backend==self.db.MYSQL_INNODB: try: - if self.db is not None and self.db.connected: + if self.db is not None and self.db.connected(): self.db.disconnect() except _mysql_exceptions.OperationalError: # oh, damn, we're already disconnected pass else: - if self.db is not None and self.db.connected: + if self.db is not None and self.db.connected(): self.db.disconnect() else: pass @@ -945,6 +948,7 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt and gpl-3.0.txt self.lock = interlocks.InterProcessLock(name="fpdb_global_lock") self.db = None self.status_bar = None + self.quitting = False self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.connect("delete_event", self.delete_event) From 397e87b8009852105c10b4483405aebebacf1fa2 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 13 Jul 2010 23:12:50 +0100 Subject: [PATCH 19/63] autoimport passes filenames to fpdb_import as unicode, so make bulk import do this as well so that add_import_file() always gets same type --- pyfpdb/fpdb_import.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index ac569c95..eeaa63ac 100755 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -152,7 +152,9 @@ class Importer: #Add an individual file to filelist def addImportFile(self, filename, site = "default", filter = "passthrough"): #TODO: test it is a valid file -> put that in config!! - if filename in self.filelist or not os.path.exists(unicode(filename,'utf-8')): + #print "addimportfile: filename is a", filename.__class__ + # filename now comes in as unicode + if filename in self.filelist or not os.path.exists(filename): return self.filelist[filename] = [site] + [filter] if site not in self.siteIds: @@ -177,10 +179,11 @@ class Importer: if os.path.isdir(inputPath): for subdir in os.walk(inputPath): for file in subdir[2]: - self.addImportFile(os.path.join(subdir[0], file), site=site, - filter=filter) + self.addImportFile(unicode(os.path.join(subdir[0], file),'utf-8'), + site=site, filter=filter) else: - self.addImportFile(inputPath, site=site, filter=filter) + + self.addImportFile(unicode(inputPath,'utf-8'), site=site, filter=filter) #Add a directory of files to filelist #Only one import directory per site supported. #dirlist is a hash of lists: @@ -406,7 +409,8 @@ class Importer: conv = None (stored, duplicates, partial, errors, ttime) = (0, 0, 0, 0, time()) - file = file.decode("utf-8") #(Configuration.LOCALE_ENCODING) + # sc: is there any need to decode this? maybe easier to skip it than guess at the encoding? + #file = file.decode("utf-8") #(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 1329101794b26e3a626a87685a8ba3728992b9a8 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Wed, 14 Jul 2010 01:46:32 +0200 Subject: [PATCH 20/63] POLISH: add notice about long time to recreate dialogue --- pyfpdb/fpdb.pyw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index 1afec904..6482a8c1 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -393,7 +393,7 @@ class fpdb: dia_confirm = gtk.MessageDialog(parent=self.window, flags=gtk.DIALOG_DESTROY_WITH_PARENT, type=gtk.MESSAGE_WARNING, buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm deleting and recreating tables") diastring = "Please confirm that you want to (re-)create the tables. If there already are tables in the database " \ - +self.db.database+" on "+self.db.host+" they will be deleted." + +self.db.database+" on "+self.db.host+" they will be deleted.\nThis may take a while." dia_confirm.format_secondary_text(diastring)#todo: make above string with bold for db, host and deleted # disable windowclose, do not want the the underlying processing interrupted mid-process dia_confirm.set_deletable(False) From 35bb8a449099e8822ceb3c2ea4fd548faa4a188d Mon Sep 17 00:00:00 2001 From: steffen123 Date: Wed, 14 Jul 2010 01:48:08 +0200 Subject: [PATCH 21/63] POLISH: add notice about time to dump DB --- pyfpdb/fpdb.pyw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index 6482a8c1..9996a105 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -703,7 +703,7 @@ class fpdb: ('rebuildhudcache', None, 'Rebuild HUD Cache', None, 'Rebuild HUD Cache', self.dia_recreate_hudcache), ('rebuildindexes', None, 'Rebuild DB Indexes', None, 'Rebuild DB Indexes', self.dia_rebuild_indexes), ('databasestats', None, '_Statistics', None, 'View Database Statistics', self.dia_database_stats), - ('dumptofile', None, 'Dump Database to Textfile', None, 'Dump Database to Textfile (takes much time, RAM, HD)', self.dia_dump_db), + ('dumptofile', None, 'Dump Database to Textfile (takes ALOT of time)', None, 'Dump Database to Textfile (takes ALOT of time)', self.dia_dump_db), ('help', None, '_Help'), ('Logs', None, '_Log Messages', None, 'Log and Debug Messages', self.dia_logs), ('About', None, 'A_bout', None, 'About the program', self.dia_about), From 5cd78b608b8a87f85d3fea9571b9a3ccec121028 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Wed, 14 Jul 2010 01:49:55 +0200 Subject: [PATCH 22/63] DB: add TourneyTypes.rebuyFee and addOnFee --- pyfpdb/Database.py | 2 +- pyfpdb/SQL.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index bf0ed73b..fb00566a 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -74,7 +74,7 @@ except ImportError: use_numpy = False -DB_VERSION = 132 +DB_VERSION = 133 # Variance created as sqlite has a bunch of undefined aggregate functions. diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 96a45d2c..75461152 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -401,9 +401,11 @@ class Sql: maxSeats INT, rebuy BOOLEAN, rebuyCost INT, + rebuyFee INT, rebuyChips INT, addOn BOOLEAN, addOnCost INT, + addOnFee INT, addOnChips INT, knockout BOOLEAN, koBounty INT, @@ -428,9 +430,11 @@ class Sql: maxSeats INT, rebuy BOOLEAN, rebuyCost INT, + rebuyFee INT, rebuyChips INT, addOn BOOLEAN, addOnCost INT, + addOnFee INT, addOnChips INT, knockout BOOLEAN, koBounty INT, @@ -454,9 +458,11 @@ class Sql: maxSeats INT, rebuy BOOLEAN, rebuyCost INT, + rebuyFee INT, rebuyChips INT, addOn BOOLEAN, addOnCost INT, + addOnFee INT, addOnChips INT, knockout BOOLEAN, koBounty INT, From 2bd11661e3d771caee92b1b106a8c9eb740c5823 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Wed, 14 Jul 2010 18:54:31 +0200 Subject: [PATCH 23/63] for now revert "comment out close of fpdb after db recreate, I don't see how it helps" I could reproduce the bug so until its fixed I want to keep the quit-on-recreate This reverts commit 45fa170758dd72409349bf44803730594b4386d7. --- pyfpdb/fpdb.pyw | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index cce592e2..4efaaa64 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -416,18 +416,12 @@ class fpdb: # TODO: figure out why this seems to be necessary dia_restart = gtk.MessageDialog(parent=self.window, flags=0, type=gtk.MESSAGE_WARNING, buttons=(gtk.BUTTONS_OK), message_format="Restart fpdb") - - # sc: I don't see the need for this closedown - if it is a problem let me know - # and I will look into it .... (if there is a problem with db re-create I - # would expect it to be before here, i.e. maybe user needs to restart before - # the re-create. Once here everything should be ok.) - # The recreate will not work if autoimport is running! Other than that it - # should work. - #diastring = "Fpdb now needs to close. Please restart it." - #dia_restart.format_secondary_text(diastring) - #dia_restart.run() - #dia_restart.destroy() - #self.quit(None, None) + diastring = "Fpdb now needs to close. Please restart it." + dia_restart.format_secondary_text(diastring) + + dia_restart.run() + dia_restart.destroy() + self.quit(None, None) elif response == gtk.RESPONSE_NO: self.release_global_lock() print 'User cancelled recreating tables' From 2734dcb85a0ed9115dc8a100baf692ec1b7bef52 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Wed, 14 Jul 2010 20:58:37 +0200 Subject: [PATCH 24/63] GUI: mention mailing lists on start page --- pyfpdb/fpdb.pyw | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index 4efaaa64..c0c72cb5 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -912,6 +912,9 @@ class fpdb: def tab_main_help(self, widget, data=None): """Displays a tab with the main fpdb help screen""" mh_tab=gtk.Label("""Welcome to Fpdb! +To be notified of new snapshots and releases go to https://lists.sourceforge.net/lists/listinfo/fpdb-announce and subscribe. +If you want to follow development more closely go to https://lists.sourceforge.net/lists/listinfo/fpdb-main and subscribe. + This program is currently in an alpha-state, so our database format is still sometimes changed. You should therefore always keep your hand history files so that you can re-import after an update, if necessary. From 40088d6cf316f2080e943c1289f37f8a78139784 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Wed, 14 Jul 2010 21:07:19 +0200 Subject: [PATCH 25/63] rename DB.createOrUpdateTourneyType to createTourneyType since TTs are static --- pyfpdb/Database.py | 4 ++-- pyfpdb/Hand.py | 2 +- pyfpdb/TourneySummary.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index bf9396f2..460d381a 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1985,7 +1985,7 @@ class Database: print "***Error sending finish: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) # end def send_finish_msg(): - def createOrUpdateTourneyType(self, hand):#note: this method is used on Hand and TourneySummary objects + def createTourneyType(self, hand):#note: this method is used on Hand and TourneySummary objects tourneyTypeId = 1 # Check if Tourney exists, and if so retrieve TTypeId : in that case, check values of the ttype @@ -2029,7 +2029,7 @@ class Database: ) tourneyTypeId = self.get_last_insert_id(cursor) return tourneyTypeId - #end def createOrUpdateTourneyType + #end def createTourneyType def createOrUpdateTourney(self, hand, source):#note: this method is used on Hand and TourneySummary objects cursor = self.get_cursor() diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 49553f85..c1520b16 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -227,7 +227,7 @@ dealt whether they were seen in a 'dealt to' line self.dbid_gt = db.getGameTypeId(self.siteId, self.gametype) if self.tourNo!=None: - self.tourneyTypeId = db.createOrUpdateTourneyType(self) + self.tourneyTypeId = db.createTourneyType(self) db.commit() self.tourneyId = db.createOrUpdateTourney(self, "HHC") db.commit() diff --git a/pyfpdb/TourneySummary.py b/pyfpdb/TourneySummary.py index 89d7388f..f10d3993 100644 --- a/pyfpdb/TourneySummary.py +++ b/pyfpdb/TourneySummary.py @@ -202,7 +202,7 @@ class TourneySummary(object): self.dbid_pids=self.playerIds #TODO:rename this field in Hand so this silly renaming can be removed #print "TS.self before starting insert",self - self.tourneyTypeId = self.db.createOrUpdateTourneyType(self) + self.tourneyTypeId = self.db.createTourneyType(self) self.db.commit() self.tourneyId = self.db.createOrUpdateTourney(self, "TS") self.db.commit() From 3657327566c43c0c4e96dc972dcb4bdcc08931e1 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 14 Jul 2010 21:07:20 +0100 Subject: [PATCH 26/63] clear player cache when recreating database --- pyfpdb/Database.py | 4 ++++ pyfpdb/fpdb.pyw | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index e6b72c1e..385e61a7 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1114,6 +1114,7 @@ class Database: """(Re-)creates the tables of the current DB""" self.drop_tables() + self.resetPlayerIDs() self.create_tables() self.createAllIndexes() self.commit() @@ -1853,6 +1854,9 @@ class Database: #FIXME: recognise currency return tmp[0] + def resetPlayerIDs(self): + self.pcache = None + def getSqlPlayerIDs(self, pnames, siteid): result = {} if(self.pcache == None): diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index 27c5fd6d..ae05e171 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -409,6 +409,10 @@ class fpdb: # self.release_global_lock() # lock_released = True self.db.recreate_tables() + # find any guibulkimport windows and clear player cache: + for t in self.threads: + if isinstance(t, GuiBulkImport.GuiBulkImport): + t.importer.database.resetPlayerIDs() self.release_global_lock() #else: # for other dbs use same connection as holds global lock From 85cc5a5471ed07b7dd45c72380d20d0f8b3384b0 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Wed, 14 Jul 2010 22:36:07 +0200 Subject: [PATCH 27/63] TOURNEY: DB.createOrUpdateTourney fills in missing fields now --- pyfpdb/Database.py | 31 +++++++++++++++++++++++++------ pyfpdb/SQL.py | 5 ++--- pyfpdb/TourneySummary.py | 6 +++++- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 460d381a..3b5d32e2 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -2033,12 +2033,31 @@ class Database: def createOrUpdateTourney(self, hand, source):#note: this method is used on Hand and TourneySummary objects cursor = self.get_cursor() - cursor.execute (self.sql.query['getTourneyIdByTourneyNo'].replace('%s', self.sql.query['placeholder']), + cursor.execute (self.sql.query['getTourneyByTourneyNo'].replace('%s', self.sql.query['placeholder']), (hand.siteId, hand.tourNo)) + columnNames=[desc[0] for desc in cursor.description] result=cursor.fetchone() - - if result != None and len(result)==1: - tourneyId = result[0] + + if result != None: + expectedValues = ('comment', 'tourneyName', 'matrixIdProcessed', 'totalRebuyCount', 'totalAddOnCount', + 'prizepool', 'startTime', 'entries', 'commentTs', 'endTime') + updateDb=False + resultDict = dict(zip(columnNames, result)) + + tourneyId = resultDict["id"] + if source=="TS": + for ev in expectedValues : + if getattr(hand, ev)==None and resultDict[ev]!=None:#DB has this value but object doesnt, so update object + setattr(hand, ev, resultDict[ev]) + elif getattr(hand, ev)!=None and resultDict[ev]==None:#object has this value but DB doesnt, so update DB + updateDb=True + elif ev=="startTime": + if (resultDict[ev] < hand.startTime): + hand.startTime=resultDict[ev] + if updateDb: + cursor.execute (self.sql.query['updateTourney'].replace('%s', self.sql.query['placeholder']), + (hand.entries, hand.prizepool, hand.startTime, hand.endTime, hand.tourneyName, + hand.matrixIdProcessed, hand.totalRebuyCount, hand.totalAddOnCount, hand.comment, hand.commentTs, tourneyId)) else: if source=="HHC": cursor.execute (self.sql.query['insertTourney'].replace('%s', self.sql.query['placeholder']), @@ -2046,8 +2065,8 @@ class Database: hand.startTime, None, None, None, None, None)) elif source=="TS": cursor.execute (self.sql.query['insertTourney'].replace('%s', self.sql.query['placeholder']), - (hand.tourneyTypeId, hand.tourNo, hand.entries, hand.prizepool, - hand.startTime, hand.endTime, hand.tourneyName, hand.matrixIdProcessed, hand.totalRebuyCount, hand.totalAddOnCount)) + (hand.tourneyTypeId, hand.tourNo, hand.entries, hand.prizepool, hand.startTime, + hand.endTime, hand.tourneyName, hand.matrixIdProcessed, hand.totalRebuyCount, hand.totalAddOnCount)) else: raise FpdbParseError("invalid source in Database.createOrUpdateTourney") tourneyId = self.get_last_insert_id(cursor) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index cf4bb1ee..a3204bea 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -3700,7 +3700,7 @@ class Sql: VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) """ - self.query['getTourneyIdByTourneyNo'] = """SELECT t.id + self.query['getTourneyByTourneyNo'] = """SELECT t.* FROM Tourneys t INNER JOIN TourneyTypes tt ON (t.tourneyTypeId = tt.id) WHERE tt.siteId=%s AND t.siteTourneyNo=%s @@ -3714,8 +3714,7 @@ class Sql: """ self.query['updateTourney'] = """UPDATE Tourneys - SET tourneyTypeId = %s, - entries = %s, + SET entries = %s, prizepool = %s, startTime = %s, endTime = %s, diff --git a/pyfpdb/TourneySummary.py b/pyfpdb/TourneySummary.py index f10d3993..b8045104 100644 --- a/pyfpdb/TourneySummary.py +++ b/pyfpdb/TourneySummary.py @@ -93,6 +93,8 @@ class TourneySummary(object): self.isDoubleOrNothing = False self.guarantee = 0 self.gametype = {'category':None, 'limitType':None} + self.comment = None + self.commentTs = None # Collections indexed by player names self.playerIds = {} @@ -151,7 +153,9 @@ class TourneySummary(object): ("SNG", self.isSng), ("SATELLITE", self.isSatellite), ("DOUBLE OR NOTHING", self.isDoubleOrNothing), - ("GUARANTEE", self.guarantee) + ("GUARANTEE", self.guarantee), + ("COMMENT", self.comment), + ("COMMENT TIMESTAMP", self.commentTs) ) structs = ( ("PLAYER IDS", self.playerIds), From ced3e8ac729910974625c7d10bf152a39e9828e0 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Wed, 14 Jul 2010 22:44:10 +0200 Subject: [PATCH 28/63] TOURNEY: rename a query --- pyfpdb/Database.py | 2 +- pyfpdb/SQL.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 3b5d32e2..358aed8b 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -2084,7 +2084,7 @@ class Database: raise FpdbParseError("invalid source in Database.createOrUpdateTourneysPlayers") cursor = self.get_cursor() - cursor.execute (self.sql.query['getTourneysPlayersId'].replace('%s', self.sql.query['placeholder']), + cursor.execute (self.sql.query['getTourneysPlayersIdByIds'].replace('%s', self.sql.query['placeholder']), (hand.tourneyId, playerId)) result=cursor.fetchone() diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index a3204bea..afac2d90 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -3727,7 +3727,7 @@ class Sql: WHERE id=%s """ - self.query['getTourneysPlayersId'] = """SELECT id + self.query['getTourneysPlayersIdByIds'] = """SELECT id FROM TourneysPlayers WHERE tourneyId=%s AND playerId+0=%s """ From 6a8f3ff68b20e9dbf49aa1c63adf9be76ba2279c Mon Sep 17 00:00:00 2001 From: steffen123 Date: Wed, 14 Jul 2010 23:05:37 +0200 Subject: [PATCH 29/63] TOURNEY: createOrUpdateTourneysPlayers now updates fields as needed --- pyfpdb/Database.py | 24 ++++++++++++++++++++++-- pyfpdb/SQL.py | 8 +++----- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 358aed8b..d176bd87 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -2084,12 +2084,32 @@ class Database: raise FpdbParseError("invalid source in Database.createOrUpdateTourneysPlayers") cursor = self.get_cursor() - cursor.execute (self.sql.query['getTourneysPlayersIdByIds'].replace('%s', self.sql.query['placeholder']), + cursor.execute (self.sql.query['getTourneysPlayersByIds'].replace('%s', self.sql.query['placeholder']), (hand.tourneyId, playerId)) + columnNames=[desc[0] for desc in cursor.description] result=cursor.fetchone() - if result != None and len(result)==1: + if result != None: + expectedValues = ('rank', 'winnings', 'winningsCurrency', 'rebuyCount', 'addOnCount', 'koCount') + updateDb=False + resultDict = dict(zip(columnNames, result)) + tourneysPlayersIds.append(result[0]) + if source=="TS": + tourneysPlayersId=result[0] + for ev in expectedValues : + handAttribute=ev + if ev!="winnings" and ev!="winningsCurrency": + handAttribute+="s" + + if getattr(hand, handAttribute)[player]==None and resultDict[ev]!=None:#DB has this value but object doesnt, so update object + setattr(hand, handAttribute, resultDict[ev][player]) + elif getattr(hand, handAttribute)[player]!=None and resultDict[ev]==None:#object has this value but DB doesnt, so update DB + updateDb=True + if updateDb: + cursor.execute (self.sql.query['updateTourneysPlayer'].replace('%s', self.sql.query['placeholder']), + (hand.ranks[player], hand.winnings[player], hand.winningsCurrency[player], + hand.rebuyCounts[player], hand.addOnCounts[player], hand.koCounts[player], tourneysPlayersId)) else: if source=="HHC": cursor.execute (self.sql.query['insertTourneysPlayer'].replace('%s', self.sql.query['placeholder']), diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index afac2d90..5041ae35 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -3727,20 +3727,18 @@ class Sql: WHERE id=%s """ - self.query['getTourneysPlayersIdByIds'] = """SELECT id + self.query['getTourneysPlayersByIds'] = """SELECT * FROM TourneysPlayers WHERE tourneyId=%s AND playerId+0=%s """ - self.query['updateTourneysPlayers'] = """UPDATE TourneysPlayers + self.query['updateTourneysPlayer'] = """UPDATE TourneysPlayers SET rank = %s, winnings = %s, winningsCurrency = %s, rebuyCount = %s, addOnCount = %s, - koCount = %s, - comment = %s, - commentTs = %s + koCount = %s WHERE id=%s """ From ebf16c6aa9459cbc16cc57109493a8b6ffdd7c7d Mon Sep 17 00:00:00 2001 From: steffen123 Date: Thu, 15 Jul 2010 00:27:57 +0200 Subject: [PATCH 30/63] TOURNEY: store HandsPlayers.tourneysPlayersId --- pyfpdb/Database.py | 8 ++++---- pyfpdb/DerivedStats.py | 4 ++++ pyfpdb/SQL.py | 3 ++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index d176bd87..f35fe19a 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1657,6 +1657,7 @@ class Database: pdata[p]['street4Bets'], pdata[p]['position'], pdata[p]['tourneyTypeId'], + pdata[p]['tourneysPlayersIds'], pdata[p]['startCards'], pdata[p]['street0_3BChance'], pdata[p]['street0_3BDone'], @@ -2074,7 +2075,7 @@ class Database: #end def createOrUpdateTourney def createOrUpdateTourneysPlayers(self, hand, source):#note: this method is used on Hand and TourneySummary objects - tourneysPlayersIds=[] + tourneysPlayersIds={} for player in hand.players: if source=="TS": #TODO remove this horrible hack playerId = hand.dbid_pids[player] @@ -2094,9 +2095,8 @@ class Database: updateDb=False resultDict = dict(zip(columnNames, result)) - tourneysPlayersIds.append(result[0]) + tourneysPlayersIds[player[1]]=result[0] if source=="TS": - tourneysPlayersId=result[0] for ev in expectedValues : handAttribute=ev if ev!="winnings" and ev!="winningsCurrency": @@ -2124,7 +2124,7 @@ class Database: cursor.execute (self.sql.query['insertTourneysPlayer'].replace('%s', self.sql.query['placeholder']), (hand.tourneyId, playerId, None, None, None, hand.rebuyCounts[player], hand.addOnCounts[player], hand.koCounts[player])) - tourneysPlayersIds.append(self.get_last_insert_id(cursor)) + tourneysPlayersIds[player[1]]=self.get_last_insert_id(cursor) return tourneysPlayersIds #end def createOrUpdateTourneysPlayers diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 96928486..f34a8673 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -140,6 +140,10 @@ class DerivedStats(): self.handsplayers[player[1]]['seatNo'] = player[0] self.handsplayers[player[1]]['startCash'] = int(100 * Decimal(player[2])) self.handsplayers[player[1]]['sitout'] = False #TODO: implement actual sitout detection + if hand.gametype["type"]=="tour": + self.handsplayers[player[1]]['tourneysPlayersIds'] = hand.tourneysPlayersIds[player[1]] + else: + self.handsplayers[player[1]]['tourneysPlayersIds'] = None # XXX: enumerate(list, start=x) is python 2.6 syntax; 'start' #for i, street in enumerate(hand.actionStreets[2:], start=1): diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 5041ae35..515c8a24 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -3853,6 +3853,7 @@ class Sql: street4Bets, position, tourneyTypeId, + tourneysPlayersId, startCards, street0_3BChance, street0_3BDone, @@ -3910,7 +3911,7 @@ class Sql: %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s + %s, %s )""" ################################ From 9e004e896211c1fee65f817c7f6e50d7055a5596 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Thu, 15 Jul 2010 01:18:36 +0200 Subject: [PATCH 31/63] DB: remove default row for TT, allow HP.ttId to be NULL and remove default --- pyfpdb/Database.py | 14 +------------- pyfpdb/DerivedStats.py | 6 ++++-- pyfpdb/SQL.py | 12 ++++++------ 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index f35fe19a..329c3da9 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -74,7 +74,7 @@ except ImportError: use_numpy = False -DB_VERSION = 133 +DB_VERSION = 134 # Variance created as sqlite has a bunch of undefined aggregate functions. @@ -1408,18 +1408,6 @@ class Database: c.execute("INSERT INTO Sites (name,code) VALUES ('Partouche', 'PA')") c.execute("INSERT INTO Sites (name,code) VALUES ('Carbon', 'CA')") c.execute("INSERT INTO Sites (name,code) VALUES ('PKR', 'PK')") - if self.backend == self.SQLITE: - c.execute("""INSERT INTO TourneyTypes (id, siteId, currency, buyin, fee, category, limitType, - buyInChips, maxSeats, knockout, rebuy, addOn, speed, shootout, matrix) - VALUES (NULL, 1, 'USD', 0, 0, "NA", "NA", 0, 0, 0, 0, 0, NULL, 0, 0);""") - elif self.backend == self.PGSQL: - c.execute("""insert into TourneyTypes(siteId, currency, buyin, fee, category, limitType, - buyInChips, maxSeats, knockout, rebuy, addOn, speed, shootout, matrix) - values (1, 'USD', 0, 0, "NA", "NA", 0, 0, False, False, False, null, False, False);""") - elif self.backend == self.MYSQL_INNODB: - c.execute("""insert into TourneyTypes(id, siteId, currency, buyin, fee, category, limitType, - buyInChips, maxSeats, knockout, rebuy, addOn, speed, shootout, matrix) - values (DEFAULT, 1, 'USD', 0, 0, "NA", "NA", 0, 0, False, False, False, null, False, False);""") #end def fillDefaultData def rebuild_indexes(self, start=None): diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index f34a8673..9bd8bbd2 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -59,6 +59,8 @@ class DerivedStats(): self.handsplayers[player[1]]['foldSbToStealChance'] = False self.handsplayers[player[1]]['foldedSbToSteal'] = False self.handsplayers[player[1]]['foldedBbToSteal'] = False + self.handsplayers[player[1]]['tourneyTypeId'] = None + for i in range(5): self.handsplayers[player[1]]['street%dCalls' % i] = 0 self.handsplayers[player[1]]['street%dBets' % i] = 0 @@ -70,9 +72,8 @@ class DerivedStats(): self.handsplayers[player[1]]['street%dCheckCallRaiseDone' %i] = False self.handsplayers[player[1]]['otherRaisedStreet%d' %i] = False self.handsplayers[player[1]]['foldToOtherRaisedStreet%d' %i] = False - + #FIXME - Everything below this point is incomplete. - self.handsplayers[player[1]]['tourneyTypeId'] = 1 for i in range(1,5): self.handsplayers[player[1]]['foldToStreet%dCBChance' %i] = False self.handsplayers[player[1]]['foldToStreet%dCBDone' %i] = False @@ -141,6 +142,7 @@ class DerivedStats(): self.handsplayers[player[1]]['startCash'] = int(100 * Decimal(player[2])) self.handsplayers[player[1]]['sitout'] = False #TODO: implement actual sitout detection if hand.gametype["type"]=="tour": + self.handsplayers[player[1]]['tourneyTypeId']=hand.tourneyTypeId self.handsplayers[player[1]]['tourneysPlayersIds'] = hand.tourneysPlayersIds[player[1]] else: self.handsplayers[player[1]]['tourneysPlayersIds'] = None diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 515c8a24..1cd25bd3 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -554,7 +554,7 @@ class Sql: comment text, commentTs DATETIME, tourneysPlayersId BIGINT UNSIGNED, FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id), - tourneyTypeId SMALLINT UNSIGNED NOT NULL DEFAULT 1, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), + tourneyTypeId SMALLINT UNSIGNED, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), wonWhenSeenStreet1 FLOAT, wonWhenSeenStreet2 FLOAT, @@ -671,7 +671,7 @@ class Sql: comment text, commentTs timestamp without time zone, tourneysPlayersId BIGINT, FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id), - tourneyTypeId INT NOT NULL DEFAULT 1, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), + tourneyTypeId INT, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), wonWhenSeenStreet1 FLOAT, wonWhenSeenStreet2 FLOAT, @@ -787,7 +787,7 @@ class Sql: comment TEXT, commentTs REAL, tourneysPlayersId INT, - tourneyTypeId INT NOT NULL DEFAULT 1, + tourneyTypeId INT, wonWhenSeenStreet1 REAL, wonWhenSeenStreet2 REAL, @@ -981,7 +981,7 @@ class Sql: playerId INT UNSIGNED NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id), activeSeats SMALLINT NOT NULL, position CHAR(1), - tourneyTypeId SMALLINT UNSIGNED NOT NULL DEFAULT 1, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), + tourneyTypeId SMALLINT UNSIGNED, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), styleKey CHAR(7) NOT NULL, /* 1st char is style (A/T/H/S), other 6 are the key */ HDs INT NOT NULL, @@ -1082,7 +1082,7 @@ class Sql: playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id), activeSeats SMALLINT, position CHAR(1), - tourneyTypeId INT DEFAULT 1, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), + tourneyTypeId INT, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), styleKey CHAR(7) NOT NULL, /* 1st char is style (A/T/H/S), other 6 are the key */ HDs INT, @@ -1181,7 +1181,7 @@ class Sql: playerId INT, activeSeats INT, position TEXT, - tourneyTypeId INT DEFAULT 1, + tourneyTypeId INT, styleKey TEXT NOT NULL, /* 1st char is style (A/T/H/S), other 6 are the key */ HDs INT, From 32ae817a2a64a9c5e985a992ab4e170e94a95dd0 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Thu, 15 Jul 2010 01:49:04 +0200 Subject: [PATCH 32/63] remove IMAPEmailFetcher as ImapSummaries has a superset of features --- pyfpdb/IMAPEmailFetcher.py | 61 -------------------------------------- 1 file changed, 61 deletions(-) delete mode 100644 pyfpdb/IMAPEmailFetcher.py diff --git a/pyfpdb/IMAPEmailFetcher.py b/pyfpdb/IMAPEmailFetcher.py deleted file mode 100644 index 840ccd2d..00000000 --- a/pyfpdb/IMAPEmailFetcher.py +++ /dev/null @@ -1,61 +0,0 @@ -import imaplib -import Configuration -import os -import pprint - -pp = pprint.PrettyPrinter(indent=4) - -def open_imap_connection(verbose=False): - # Read the config file - # FIXME - hostname = 'imap.gmail.com' - port = 993 - username = 'slartibartfast' - password = '42' - - # Connect - if verbose: print "Connecting to %s" % hostname - connection = imaplib.IMAP4_SSL(hostname) - - # Login to our account - if verbose: print "Logging in as %s" % username - connection.login(username, password) - return connection - -if __name__ == '__main__': - # Read the config file - # FIXME - folder = "INBOX" - c = open_imap_connection(verbose=True) - - try: - typ, data = c.list(directory=folder) - print typ, data - - c.select('INBOX', readonly=True) - - typ, msg_ids = c.search(None, '(SUBJECT "Results for PokerStars Tournament *")') - print typ, msg_ids - msgidlist = msg_ids[0].split(' ') - print msgidlist - - for msg in msgidlist: - print 'HEADER:' - typ, msg_data = c.fetch(msg, '(BODY.PEEK[HEADER])') - for response_part in msg_data: - if isinstance(response_part, tuple): - print response_part[1] - - print 'BODY TEXT:' - typ, msg_data = c.fetch(msg, '(BODY.PEEK[TEXT])') - for response_part in msg_data: - if isinstance(response_part, tuple): - print response_part[1] - - - finally: - try: - c.close() - except: - pass - c.logout() From 3d37006bbc6cb80fcf6484dd325c24959e31275b Mon Sep 17 00:00:00 2001 From: steffen123 Date: Thu, 15 Jul 2010 01:53:22 +0200 Subject: [PATCH 33/63] rename ImapSummaries to ImapFetcher to better reflect its scope --- pyfpdb/{ImapSummaries.py => ImapFetcher.py} | 2 +- pyfpdb/fpdb.pyw | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename pyfpdb/{ImapSummaries.py => ImapFetcher.py} (98%) diff --git a/pyfpdb/ImapSummaries.py b/pyfpdb/ImapFetcher.py similarity index 98% rename from pyfpdb/ImapSummaries.py rename to pyfpdb/ImapFetcher.py index f2874725..da13698c 100755 --- a/pyfpdb/ImapSummaries.py +++ b/pyfpdb/ImapFetcher.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -#Copyright 2008-2010 Steffen Schaumburg +#Copyright 2010 Steffen Schaumburg #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. diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index c0c72cb5..898b6ec5 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -103,7 +103,7 @@ import GuiPrefs import GuiLogView import GuiDatabase import GuiBulkImport -import ImapSummaries +import ImapFetcher import GuiRingPlayerStats import GuiTourneyPlayerStats import GuiPositionalStats @@ -722,7 +722,7 @@ class fpdb: #end def get_menu def import_imap_summaries(self, widget, data=None): - result=ImapSummaries.run(self.config, self.db) + result=ImapFetcher.run(self.config, self.db) #print "import imap summaries result:", result #end def import_imap_summaries From 10a94fa4413de9afd2ef8ada5f676c1315fa85cd Mon Sep 17 00:00:00 2001 From: steffen123 Date: Thu, 15 Jul 2010 01:53:46 +0200 Subject: [PATCH 34/63] IMAP: fix a silly mistake I made earlier --- pyfpdb/Database.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 329c3da9..59d6a884 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -2097,7 +2097,7 @@ class Database: if updateDb: cursor.execute (self.sql.query['updateTourneysPlayer'].replace('%s', self.sql.query['placeholder']), (hand.ranks[player], hand.winnings[player], hand.winningsCurrency[player], - hand.rebuyCounts[player], hand.addOnCounts[player], hand.koCounts[player], tourneysPlayersId)) + hand.rebuyCounts[player], hand.addOnCounts[player], hand.koCounts[player], tourneysPlayersIds[player[1]])) else: if source=="HHC": cursor.execute (self.sql.query['insertTourneysPlayer'].replace('%s', self.sql.query['placeholder']), From 18dc3f29ff716ec27644715f87786e253d71e374 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Thu, 15 Jul 2010 01:58:54 +0200 Subject: [PATCH 35/63] TOURNEY: fix category recording for PS summary import --- pyfpdb/PokerStarsSummary.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/PokerStarsSummary.py b/pyfpdb/PokerStarsSummary.py index a384056a..764e072f 100644 --- a/pyfpdb/PokerStarsSummary.py +++ b/pyfpdb/PokerStarsSummary.py @@ -60,7 +60,7 @@ class PokerStarsSummary(TourneySummary): result=self.re_GameInfo.search(lines[0]) result=result.groupdict() self.gametype['limitType']=self.limits[result['LIMIT']] - self.gametype['category']=self.games[result['GAME']][0] + self.gametype['category']=self.games[result['GAME']][1] if lines[1].find("$")!=-1: #TODO: move this into a method and call that from PokerStarsToFpdb.py:269 if hand.buyinCurrency=="USD" etc. self.currency="USD" From d65b6e55c82e18bee30ff8517d108a0125308ba8 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Thu, 15 Jul 2010 02:08:59 +0200 Subject: [PATCH 36/63] TOURNEY: fix recording of Hands.tourneyId, allow it to be NULL --- pyfpdb/Database.py | 4 ++-- pyfpdb/DerivedStats.py | 1 + pyfpdb/SQL.py | 6 +++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 59d6a884..9a5606f6 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -74,7 +74,7 @@ except ImportError: use_numpy = False -DB_VERSION = 134 +DB_VERSION = 135 # Variance created as sqlite has a bunch of undefined aggregate functions. @@ -1562,7 +1562,7 @@ class Database: p['tableName'], p['gameTypeId'], p['siteHandNo'], - 0, # tourneyId: 0 means not a tourney hand + p['tourneyId'], p['startTime'], datetime.today(), #importtime p['seats'], diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 9bd8bbd2..7aab6c98 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -103,6 +103,7 @@ class DerivedStats(): self.hands['seats'] = self.countPlayers(hand) self.hands['maxSeats'] = hand.maxseats self.hands['texture'] = None # No calculation done for this yet. + self.hands['tourneyId'] = hand.tourneyId # This (i think...) is correct for both stud and flop games, as hand.board['street'] disappears, and # those values remain default in stud. diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 1cd25bd3..7e509e85 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -278,7 +278,7 @@ class Sql: id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), tableName VARCHAR(22) NOT NULL, siteHandNo BIGINT NOT NULL, - tourneyId INT UNSIGNED NOT NULL, + tourneyId INT UNSIGNED, gametypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), startTime DATETIME NOT NULL, importTime DATETIME NOT NULL, @@ -315,7 +315,7 @@ class Sql: id BIGSERIAL, PRIMARY KEY (id), tableName VARCHAR(22) NOT NULL, siteHandNo BIGINT NOT NULL, - tourneyId INT NOT NULL, + tourneyId INT, gametypeId INT NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), startTime timestamp without time zone NOT NULL, importTime timestamp without time zone NOT NULL, @@ -351,7 +351,7 @@ class Sql: id INTEGER PRIMARY KEY, tableName TEXT(22) NOT NULL, siteHandNo INT NOT NULL, - tourneyId INT NOT NULL, + tourneyId INT, gametypeId INT NOT NULL, startTime REAL NOT NULL, importTime REAL NOT NULL, From a8edb976f8cf34749c09ce4db69e7a76cc39ad91 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Thu, 15 Jul 2010 02:19:58 +0200 Subject: [PATCH 37/63] FTP: fix to make it store Hand.startTime as UTC rather than ET --- pyfpdb/FulltiltToFpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/FulltiltToFpdb.py b/pyfpdb/FulltiltToFpdb.py index d9e924f0..c1954140 100755 --- a/pyfpdb/FulltiltToFpdb.py +++ b/pyfpdb/FulltiltToFpdb.py @@ -201,7 +201,7 @@ class Fulltilt(HandHistoryConverter): return None hand.handid = m.group('HID') hand.tablename = m.group('TABLE') - hand.startTime = datetime.datetime.strptime(m.group('DATETIME'), "%H:%M:%S ET - %Y/%m/%d") + hand.startTime = HandHistoryConverter.changeTimezone(datetime.datetime.strptime(m.group('DATETIME'), "%H:%M:%S ET - %Y/%m/%d"), "ET", "UTC") if m.group("CANCELLED") or m.group("PARTIAL"): raise FpdbParseError(hid=m.group('HID')) From f56a003242455d0b064e2c4e9709e0a5db5402b3 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Thu, 15 Jul 2010 03:32:10 +0200 Subject: [PATCH 38/63] GUI: start of HUD stat configurator: select parameters --- pyfpdb/Configuration.py | 4 +-- pyfpdb/fpdb.pyw | 59 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index ea2a8a78..7af32d03 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -1069,8 +1069,8 @@ class Config: def get_supported_games(self): """Get the list of supported games.""" sg = [] - for game in c.supported_games.keys(): - sg.append(c.supported_games[game].game_name) + for game in self.supported_games.keys(): + sg.append(self.supported_games[game].game_name) return sg def execution_path(self, filename): diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index 898b6ec5..24df913b 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -337,6 +337,62 @@ class fpdb: diatitle="Database Statistics") #end def dia_database_stats + def diaHudConfigurator(self, widget, data=None): + self.obtain_global_lock("diaHudConfigurator") + diaSelections = gtk.Dialog("HUD Configurator - choose category", + self.window, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, + (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT, + gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT)) + + label=gtk.Label("Please select the game category for which you want to configure HUD stats:") + diaSelections.vbox.add(label) + label.show() + + #combo=gtk.ComboBox() + + comboGame = gtk.combo_box_new_text() + comboGame.connect("changed", self.hudConfiguratorComboSelection) + diaSelections.vbox.add(comboGame) + games=self.config.get_supported_games() + for game in games: + comboGame.append_text(game) + comboGame.show() + + comboRows = gtk.combo_box_new_text() + comboRows.connect("changed", self.hudConfiguratorComboSelection) + diaSelections.vbox.add(comboRows) + for i in range(1,8): + comboRows.append_text(str(i)+" rows") + comboRows.show() + + comboColumns = gtk.combo_box_new_text() + comboColumns.connect("changed", self.hudConfiguratorComboSelection) + diaSelections.vbox.add(comboColumns) + for i in range(1,8): + comboColumns.append_text(str(i)+" columns") + comboColumns.show() + + response=diaSelections.run() + if response == gtk.RESPONSE_ACCEPT: + print "clicked ok and selected:", self.hudConfiguratorGame,"with", str(self.hudConfiguratorRows), "rows and", str(self.hudConfiguratorColumns), "columns" + diaSelections.destroy() + + #TODO: bring up dialogue to actually select stats + #TODO: show explanation of what each stat means + self.release_global_lock() + #end def diaHudConfigurator + + def hudConfiguratorComboSelection(self, widget): + result=widget.get_active_text() + if result.endswith(" rows"): + self.hudConfiguratorRows=int(result[0]) + elif result.endswith(" columns"): + self.hudConfiguratorColumns=int(result[0]) + else: + self.hudConfiguratorGame=result + #end def hudConfiguratorComboSelection + def dia_dump_db(self, widget, data=None): self.db.dumpDatabase("database-dump.sql") #end def dia_database_stats @@ -640,6 +696,7 @@ class fpdb: + @@ -652,6 +709,7 @@ class fpdb: + @@ -692,6 +750,7 @@ class fpdb: ('imapsummaries', None, '_Import Tourney Summaries through eMail/IMAP', 'I', 'Auto Import and HUD', self.import_imap_summaries), ('viewers', None, '_Viewers'), ('autoimp', None, '_Auto Import and HUD', 'A', 'Auto Import and HUD', self.tab_auto_import), + ('hudConfigurator', None, '_HUD Configurator', 'H', 'HUD Configurator', self.diaHudConfigurator), ('graphs', None, '_Graphs', 'G', 'Graphs', self.tabGraphViewer), ('ringplayerstats', None, 'Ring _Player Stats (tabulated view)', 'P', 'Ring Player Stats (tabulated view)', self.tab_ring_player_stats), ('tourneyplayerstats', None, '_Tourney Player Stats (tabulated view)', 'T', 'Tourney Player Stats (tabulated view)', self.tab_tourney_player_stats), From bda435ec34c00b406bcb06b471824e6fe11bcf6e Mon Sep 17 00:00:00 2001 From: steffen123 Date: Fri, 16 Jul 2010 05:07:30 +0200 Subject: [PATCH 39/63] EBUILD: add lots of improvements from ferki to ebuild --- packaging/gentoo/fpdb-0.20-r2.ebuild | 59 ++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 packaging/gentoo/fpdb-0.20-r2.ebuild diff --git a/packaging/gentoo/fpdb-0.20-r2.ebuild b/packaging/gentoo/fpdb-0.20-r2.ebuild new file mode 100644 index 00000000..2e04719e --- /dev/null +++ b/packaging/gentoo/fpdb-0.20-r2.ebuild @@ -0,0 +1,59 @@ +# Copyright 1999-2010 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# created by Steffen Schaumburg, steffen@schaumburger.info + +EAPI="2" +NEED_PYTHON=2.5 + +DESCRIPTION="Fpdb is a free/open source tracker/HUD for use with online poker" +HOMEPAGE="http://fpdb.wiki.sourceforge.net/" +SRC_URI="mirror://sourceforge/${PN}/${PV}/${P}.tar.gz" + +LICENSE="AGPL-3" +SLOT="0" +KEYWORDS="~amd64 ~x86" +#note: this should work on other architectures too, please send me your experiences + +IUSE="graphing mysql postgres sqlite" +RDEPEND=" + mysql? ( virtual/mysql + dev-python/mysql-python ) + postgres? ( dev-db/postgresql-server + dev-python/psycopg ) + sqlite? ( dev-lang/python[sqlite] + dev-python/numpy ) + >=x11-libs/gtk+-2.10 + dev-python/pygtk + graphing? ( dev-python/numpy + dev-python/matplotlib[gtk] ) + dev-python/python-xlib" +DEPEND="${RDEPEND}" + +src_install() { + dodir /usr/share/games/fpdb + + exeinto /usr/share/games/fpdb + doexe run_fpdb.py + dosym /usr/share/games/fpdb/run_fpdb.py /usr/bin/fpdb + + insinto /usr/share/games/fpdb + doins readme.txt + + insinto /usr/share/games/fpdb/files + doins files/* + + insinto /usr/share/games/fpdb/gfx + doins gfx/* + + insinto /usr/share/games/fpdb/pyfpdb + doins pyfpdb/* + +# pyfpdb/regression-test-files dir is missing for now; cp -r ?? + +} + +pkg_postinst() { + elog "Note that if you really want to use mysql or postgresql you will have to create" + elog "the database and user yourself and enter it into the fpdb config." + elog "You can find the instructions on the project's website." +} From a1f422cbe45933a2e601bb28a5651bb797525eee Mon Sep 17 00:00:00 2001 From: steffen123 Date: Fri, 16 Jul 2010 20:27:43 +0200 Subject: [PATCH 40/63] GUI: second HudConfigurator dia with grid for comboboxes --- pyfpdb/fpdb.pyw | 60 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index 24df913b..b463258a 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -338,7 +338,10 @@ class fpdb: #end def dia_database_stats def diaHudConfigurator(self, widget, data=None): - self.obtain_global_lock("diaHudConfigurator") + self.hudConfiguratorRows=None + self.hudConfiguratorColumns=None + self.hudConfiguratorGame=None + diaSelections = gtk.Dialog("HUD Configurator - choose category", self.window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, @@ -374,13 +377,11 @@ class fpdb: comboColumns.show() response=diaSelections.run() - if response == gtk.RESPONSE_ACCEPT: - print "clicked ok and selected:", self.hudConfiguratorGame,"with", str(self.hudConfiguratorRows), "rows and", str(self.hudConfiguratorColumns), "columns" diaSelections.destroy() - #TODO: bring up dialogue to actually select stats - #TODO: show explanation of what each stat means - self.release_global_lock() + if response == gtk.RESPONSE_ACCEPT and self.hudConfiguratorRows!=None and self.hudConfiguratorColumns!=None and self.hudConfiguratorGame!=None: + print "clicked ok and selected:", self.hudConfiguratorGame,"with", str(self.hudConfiguratorRows), "rows and", str(self.hudConfiguratorColumns), "columns" + self.diaHudConfiguratorTable() #end def diaHudConfigurator def hudConfiguratorComboSelection(self, widget): @@ -393,6 +394,53 @@ class fpdb: self.hudConfiguratorGame=result #end def hudConfiguratorComboSelection + def diaHudConfiguratorTable(self): + #TODO: show explanation of what each stat means + self.obtain_global_lock("diaHudConfiguratorTable") + diaHudTable = gtk.Dialog("HUD Configurator - please choose your stats", + self.window, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, + (gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT, + gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT)) + + label=gtk.Label("Please choose the stats you wish to use") + diaHudTable.vbox.add(label) + label.show() + + self.hudConfiguratorTableContents=[] + table= gtk.Table(rows=self.hudConfiguratorRows+1, columns=self.hudConfiguratorColumns+1, homogeneous=True) + + for rowNumber in range(self.hudConfiguratorRows+1): + newRow=[] + + for columnNumber in range(self.hudConfiguratorColumns+1): + if rowNumber==0: + if columnNumber==0: + pass + else: + label=gtk.Label("column "+str(columnNumber)) + table.attach(child=label, left_attach=columnNumber, right_attach=columnNumber+1, top_attach=rowNumber, bottom_attach=rowNumber+1) + label.show() + else: + if columnNumber==0: + label=gtk.Label("row "+str(rowNumber)) + table.attach(child=label, left_attach=columnNumber, right_attach=columnNumber+1, top_attach=rowNumber, bottom_attach=rowNumber+1) + label.show() + self.hudConfiguratorTableContents.append(newRow) + diaHudTable.vbox.add(table) + table.show() + + response=diaHudTable.run() + diaHudTable.destroy() + + if response == gtk.RESPONSE_ACCEPT: + self.storeNewHudStatConfig() + #end def diaHudConfiguratorTable + + def storeNewHudStatConfig(self): + print "storeNewHudStatConfig" + #end def storeNewHudStatConfig + def dia_dump_db(self, widget, data=None): self.db.dumpDatabase("database-dump.sql") #end def dia_database_stats From 71f8fb5ef194062b665ee9b327afd2073ffccf7e Mon Sep 17 00:00:00 2001 From: steffen123 Date: Fri, 16 Jul 2010 20:32:01 +0200 Subject: [PATCH 41/63] GUI: have default selections and fix locking in HudConfigurator --- pyfpdb/fpdb.pyw | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index b463258a..cb24efb7 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -360,6 +360,7 @@ class fpdb: games=self.config.get_supported_games() for game in games: comboGame.append_text(game) + comboGame.set_active(0) comboGame.show() comboRows = gtk.combo_box_new_text() @@ -367,6 +368,7 @@ class fpdb: diaSelections.vbox.add(comboRows) for i in range(1,8): comboRows.append_text(str(i)+" rows") + comboRows.set_active(0) comboRows.show() comboColumns = gtk.combo_box_new_text() @@ -374,6 +376,7 @@ class fpdb: diaSelections.vbox.add(comboColumns) for i in range(1,8): comboColumns.append_text(str(i)+" columns") + comboColumns.set_active(0) comboColumns.show() response=diaSelections.run() @@ -396,7 +399,6 @@ class fpdb: def diaHudConfiguratorTable(self): #TODO: show explanation of what each stat means - self.obtain_global_lock("diaHudConfiguratorTable") diaHudTable = gtk.Dialog("HUD Configurator - please choose your stats", self.window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, @@ -438,7 +440,9 @@ class fpdb: #end def diaHudConfiguratorTable def storeNewHudStatConfig(self): + self.obtain_global_lock("diaHudConfiguratorTable") print "storeNewHudStatConfig" + self.release_global_lock() #end def storeNewHudStatConfig def dia_dump_db(self, widget, data=None): From f6232004ad64bafecbe0d17bdd7ef7117e111ea2 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Fri, 16 Jul 2010 20:37:53 +0200 Subject: [PATCH 42/63] PSS: PS summary import now supports non-ascii playernames in sqlite --- pyfpdb/Database.py | 8 ++++---- pyfpdb/TourneySummary.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 9a5606f6..177938b2 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -856,7 +856,7 @@ class Database: def get_player_id(self, config, siteName, playerName): c = self.connection.cursor() siteNameUtf = Charset.to_utf8(siteName) - playerNameUtf = Charset.to_utf8(playerName) + playerNameUtf = unicode(playerName) #print "db.get_player_id siteName",siteName,"playerName",playerName c.execute(self.sql.query['get_player_id'], (playerNameUtf, siteNameUtf)) row = c.fetchone() @@ -2040,9 +2040,9 @@ class Database: setattr(hand, ev, resultDict[ev]) elif getattr(hand, ev)!=None and resultDict[ev]==None:#object has this value but DB doesnt, so update DB updateDb=True - elif ev=="startTime": - if (resultDict[ev] < hand.startTime): - hand.startTime=resultDict[ev] + #elif ev=="startTime": + # if (resultDict[ev] < hand.startTime): + # hand.startTime=resultDict[ev] if updateDb: cursor.execute (self.sql.query['updateTourney'].replace('%s', self.sql.query['placeholder']), (hand.entries, hand.prizepool, hand.startTime, hand.endTime, hand.tourneyName, diff --git a/pyfpdb/TourneySummary.py b/pyfpdb/TourneySummary.py index b8045104..4e02ace8 100644 --- a/pyfpdb/TourneySummary.py +++ b/pyfpdb/TourneySummary.py @@ -197,7 +197,7 @@ class TourneySummary(object): for player in self.players: id=self.db.get_player_id(self.config, self.siteName, player) if not id: - id=self.db.insertPlayer(player, self.siteId) + id=self.db.insertPlayer(unicode(player), self.siteId) self.playerIds.update({player:id}) #print "TS.insert players",self.players,"playerIds",self.playerIds From d95fcfe5d0776d039dbfe86d43b183ac8f0a6f88 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Fri, 16 Jul 2010 21:00:29 +0200 Subject: [PATCH 43/63] GUI: HudConfigurator shows combo boxes for stats --- pyfpdb/fpdb.pyw | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index cb24efb7..428cb3ed 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -423,11 +423,20 @@ class fpdb: label=gtk.Label("column "+str(columnNumber)) table.attach(child=label, left_attach=columnNumber, right_attach=columnNumber+1, top_attach=rowNumber, bottom_attach=rowNumber+1) label.show() + elif columnNumber==0: + label=gtk.Label("row "+str(rowNumber)) + table.attach(child=label, left_attach=columnNumber, right_attach=columnNumber+1, top_attach=rowNumber, bottom_attach=rowNumber+1) + label.show() else: - if columnNumber==0: - label=gtk.Label("row "+str(rowNumber)) - table.attach(child=label, left_attach=columnNumber, right_attach=columnNumber+1, top_attach=rowNumber, bottom_attach=rowNumber+1) - label.show() + comboBox = gtk.combo_box_new_text() + for i in ("vpip", "pfr", "wtsd"): + comboBox.append_text(i) + comboBox.set_active(0) + + newRow.append(comboBox) + table.attach(child=comboBox, left_attach=columnNumber, right_attach=columnNumber+1, top_attach=rowNumber, bottom_attach=rowNumber+1) + + comboBox.show() self.hudConfiguratorTableContents.append(newRow) diaHudTable.vbox.add(table) table.show() From 66ac9b27d6f84e6fcfec4c86b6216b04d6d4fe6f Mon Sep 17 00:00:00 2001 From: steffen123 Date: Fri, 16 Jul 2010 21:33:36 +0200 Subject: [PATCH 44/63] comment out some broken code, add TODO for it --- pyfpdb/Stats.py | 65 +++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/pyfpdb/Stats.py b/pyfpdb/Stats.py index ea3d33bb..72af0bb0 100755 --- a/pyfpdb/Stats.py +++ b/pyfpdb/Stats.py @@ -760,38 +760,39 @@ def ffreq4(stat_dict, player): if __name__== "__main__": c = Configuration.Config() - db_connection = Database.Database(c) - h = db_connection.get_last_hand() - stat_dict = db_connection.get_stats_from_hand(h, "ring") + #TODO: restore the below code. somehow it creates a version 119 DB but commenting this out makes it print a stat list + #db_connection = Database.Database(c) + #h = db_connection.get_last_hand() + #stat_dict = db_connection.get_stats_from_hand(h, "ring") - for player in stat_dict.keys(): - print "player = ", player, do_stat(stat_dict, player = player, stat = 'vpip') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'pfr') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'wtsd') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'profit100') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'saw_f') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'n') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'fold_f') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'wmsd') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'steal') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'f_SB_steal') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'f_BB_steal') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'three_B') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'WMsF') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq1') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq2') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq3') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq4') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_123') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'cb1') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'cb2') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'cb3') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'cb4') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq1') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq2') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq3') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq4') - print "\n" + #for player in stat_dict.keys(): + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'vpip') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'pfr') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'wtsd') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'profit100') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'saw_f') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'n') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'fold_f') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'wmsd') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'steal') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'f_SB_steal') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'f_BB_steal') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'three_B') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'WMsF') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq1') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq2') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq3') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq4') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_123') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'cb1') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'cb2') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'cb3') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'cb4') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq1') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq2') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq3') + #print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq4') + #print "\n" print "\n\nLegal stats:" print "(add _0 to name to display with 0 decimal places, _1 to display with 1, etc)\n" @@ -804,5 +805,5 @@ if __name__== "__main__": # print " " % (attr) print - db_connection.close_connection + #db_connection.close_connection From ef91cb5ad1568a796ced8a03f586aadde55cc4ed Mon Sep 17 00:00:00 2001 From: steffen123 Date: Fri, 16 Jul 2010 21:56:44 +0200 Subject: [PATCH 45/63] GUI: HudConfigurator displays all stats now and reads selections --- pyfpdb/fpdb.pyw | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index 428cb3ed..6107ab76 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -115,6 +115,7 @@ import SQL import Database import Configuration import Exceptions +import Stats VERSION = "0.20 plus git" @@ -412,6 +413,16 @@ class fpdb: self.hudConfiguratorTableContents=[] table= gtk.Table(rows=self.hudConfiguratorRows+1, columns=self.hudConfiguratorColumns+1, homogeneous=True) + statDir=dir(Stats) + statDict={} + for attr in statDir: + if attr.startswith('__'): continue + if attr in ("Charset", "Configuration", "Database", "GInitiallyUnowned", "gtk", "pygtk", + "player", "c", "db_connection", "do_stat", "do_tip", "stat_dict", + "h", "re", "re_Percent", "re_Places", ): continue + statDict[attr]=eval("Stats.%s.__doc__" % (attr)) + #print "statDict:",statDict + for rowNumber in range(self.hudConfiguratorRows+1): newRow=[] @@ -429,8 +440,9 @@ class fpdb: label.show() else: comboBox = gtk.combo_box_new_text() - for i in ("vpip", "pfr", "wtsd"): - comboBox.append_text(i) + + for stat in statDict.keys(): + comboBox.append_text(stat) comboBox.set_active(0) newRow.append(comboBox) @@ -449,8 +461,12 @@ class fpdb: #end def diaHudConfiguratorTable def storeNewHudStatConfig(self): + print "start of storeNewHudStatConfig" self.obtain_global_lock("diaHudConfiguratorTable") - print "storeNewHudStatConfig" + for row in self.hudConfiguratorTableContents: + for column in row: + print column.get_active_text() + self.release_global_lock() #end def storeNewHudStatConfig From 5bf7937f9e2b423d0eb06409856326ab62b22f26 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Fri, 16 Jul 2010 21:57:32 +0200 Subject: [PATCH 46/63] CLEANUP: remove trivial commented out method --- pyfpdb/fpdb.pyw | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index 6107ab76..69e64924 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -474,25 +474,6 @@ class fpdb: self.db.dumpDatabase("database-dump.sql") #end def dia_database_stats - -# def dia_get_db_root_credentials(self): -# """obtains db root credentials from user""" -# user, pw=None, None -# -# dialog=gtk.Dialog(title="DB Credentials needed", parent=None, flags=0, -# buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,"Connect and recreate",gtk.RESPONSE_OK)) -# -# label_warning1=gtk.Label("Please enter credentials for a database user for "+self.host+" that has permissions to create a database.") -# -# -# label_user=gtk.Label("Username") -# dialog.vbox.add(label_user) -# label_user.show() -# -# response=dialog.run() -# dialog.destroy() -# return (user, pw, response) - def dia_licensing(self, widget, data=None): self.warning_box("Unimplemented: Licensing") From c23a1388fc5240377815c64a16a7803a385c5e9f Mon Sep 17 00:00:00 2001 From: steffen123 Date: Sat, 17 Jul 2010 00:23:48 +0200 Subject: [PATCH 47/63] GUI: HUD configurator fully working, dont even need to restart fpdb --- pyfpdb/Configuration.py | 51 +++++++++++++++++++++++++++++++++++++++++ pyfpdb/fpdb.pyw | 25 ++++++++++++-------- 2 files changed, 67 insertions(+), 9 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 7af32d03..faeb5e23 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -655,6 +655,14 @@ class Config: if site_node.getAttribute("site_name") == site: return site_node + def getGameNode(self,gameName): + """returns DOM game node for a given game""" + for gameNode in self.doc.getElementsByTagName("game"): + #print "getGameNode gameNode:",gameNode + if gameNode.getAttribute("game_name") == gameName: + return gameNode + #end def getGameNode + def get_aux_node(self, aux): for aux_node in self.doc.getElementsByTagName("aw"): if aux_node.getAttribute("name") == aux: @@ -734,6 +742,49 @@ class Config: location_node.setAttribute("y", str( locations[i-1][1] )) self.supported_sites[site_name].layout[max].location[i] = ( locations[i-1][0], locations[i-1][1] ) + def editStats(self, gameName, statArray): + """replaces stat selection for the given gameName with the given statArray""" + gameNode = self.getGameNode(gameName) + statNodes = gameNode.getElementsByTagName("stat") + + for node in statNodes: + gameNode.removeChild(node) + + gameNode.setAttribute("rows", str(len(statArray))) + gameNode.setAttribute("cols", str(len(statArray[0]))) + + for rowNumber in range(len(statArray)): + for columnNumber in range(len(statArray[rowNumber])): + newStat=self.doc.createElement("stat") + + newAttrStatName=self.doc.createAttribute("stat_name") + newStat.setAttributeNode(newAttrStatName) + newStat.setAttribute("stat_name", statArray[rowNumber][columnNumber]) + + newAttrStatName=self.doc.createAttribute("row") + newStat.setAttributeNode(newAttrStatName) + newStat.setAttribute("row", str(rowNumber)) + + newAttrStatName=self.doc.createAttribute("col") + newStat.setAttributeNode(newAttrStatName) + newStat.setAttribute("col", str(columnNumber)) + + newAttrStatName=self.doc.createAttribute("click") + newStat.setAttributeNode(newAttrStatName) + newStat.setAttribute("click", "tog_decorate") + + newAttrStatName=self.doc.createAttribute("popup") + newStat.setAttributeNode(newAttrStatName) + newStat.setAttribute("popup", "default") + + newAttrStatName=self.doc.createAttribute("tip") + newStat.setAttributeNode(newAttrStatName) + newStat.setAttribute("tip", "tip1") + + gameNode.appendChild(newStat) + statNodes = gameNode.getElementsByTagName("stat") + #end def editStats + def edit_aux_layout(self, aux_name, max, width = None, height = None, locations = None): aux_node = self.get_aux_node(aux_name) layout_node = self.get_layout_node(aux_node, max) diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index 69e64924..d2f06f35 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -339,6 +339,7 @@ class fpdb: #end def dia_database_stats def diaHudConfigurator(self, widget, data=None): + """Opens dialog to set parameters (game category, row count, column count for HUD stat configurator""" self.hudConfiguratorRows=None self.hudConfiguratorColumns=None self.hudConfiguratorGame=None @@ -353,8 +354,6 @@ class fpdb: diaSelections.vbox.add(label) label.show() - #combo=gtk.ComboBox() - comboGame = gtk.combo_box_new_text() comboGame.connect("changed", self.hudConfiguratorComboSelection) diaSelections.vbox.add(comboGame) @@ -384,11 +383,12 @@ class fpdb: diaSelections.destroy() if response == gtk.RESPONSE_ACCEPT and self.hudConfiguratorRows!=None and self.hudConfiguratorColumns!=None and self.hudConfiguratorGame!=None: - print "clicked ok and selected:", self.hudConfiguratorGame,"with", str(self.hudConfiguratorRows), "rows and", str(self.hudConfiguratorColumns), "columns" + #print "clicked ok and selected:", self.hudConfiguratorGame,"with", str(self.hudConfiguratorRows), "rows and", str(self.hudConfiguratorColumns), "columns" self.diaHudConfiguratorTable() #end def diaHudConfigurator def hudConfiguratorComboSelection(self, widget): + #TODO: remove this and handle it directly in diaHudConfigurator result=widget.get_active_text() if result.endswith(" rows"): self.hudConfiguratorRows=int(result[0]) @@ -399,6 +399,8 @@ class fpdb: #end def hudConfiguratorComboSelection def diaHudConfiguratorTable(self): + """shows dialogue with Table of ComboBoxes to allow choosing of HUD stats""" + #TODO: add notices to hud configurator: no duplicates, no empties, display options #TODO: show explanation of what each stat means diaHudTable = gtk.Dialog("HUD Configurator - please choose your stats", self.window, @@ -421,11 +423,9 @@ class fpdb: "player", "c", "db_connection", "do_stat", "do_tip", "stat_dict", "h", "re", "re_Percent", "re_Places", ): continue statDict[attr]=eval("Stats.%s.__doc__" % (attr)) - #print "statDict:",statDict for rowNumber in range(self.hudConfiguratorRows+1): newRow=[] - for columnNumber in range(self.hudConfiguratorColumns+1): if rowNumber==0: if columnNumber==0: @@ -449,7 +449,8 @@ class fpdb: table.attach(child=comboBox, left_attach=columnNumber, right_attach=columnNumber+1, top_attach=rowNumber, bottom_attach=rowNumber+1) comboBox.show() - self.hudConfiguratorTableContents.append(newRow) + if rowNumber!=0: + self.hudConfiguratorTableContents.append(newRow) diaHudTable.vbox.add(table) table.show() @@ -461,12 +462,18 @@ class fpdb: #end def diaHudConfiguratorTable def storeNewHudStatConfig(self): - print "start of storeNewHudStatConfig" + """stores selections made in diaHudConfiguratorTable""" self.obtain_global_lock("diaHudConfiguratorTable") + statTable=[] for row in self.hudConfiguratorTableContents: + newRow=[] for column in row: - print column.get_active_text() - + newField = column.get_active_text() + newRow.append(newField) + statTable.append(newRow) + + self.config.editStats(self.hudConfiguratorGame,statTable) + self.config.save() #TODO: make it not store in horrible formatting self.release_global_lock() #end def storeNewHudStatConfig From 90ceafda6d9b67945f9dc150f6cd99198b561897 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Sat, 17 Jul 2010 02:19:12 +0200 Subject: [PATCH 48/63] DB: Added TT.added, addedCurrency --- pyfpdb/Database.py | 2 +- pyfpdb/Hand.py | 2 ++ pyfpdb/PokerStarsSummary.py | 1 - pyfpdb/SQL.py | 12 +++++++++--- pyfpdb/TourneySummary.py | 20 ++++++++++++-------- 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 177938b2..5ad52916 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -74,7 +74,7 @@ except ImportError: use_numpy = False -DB_VERSION = 135 +DB_VERSION = 136 # Variance created as sqlite has a bunch of undefined aggregate functions. diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index c1520b16..a1a6c5d8 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -85,6 +85,8 @@ class Hand(object): self.isKO = False self.isMatrix = False self.isShootout = False + self.added = None + self.addedCurrency = None self.tourneyComment = None self.seating = [] diff --git a/pyfpdb/PokerStarsSummary.py b/pyfpdb/PokerStarsSummary.py index 764e072f..477d7996 100644 --- a/pyfpdb/PokerStarsSummary.py +++ b/pyfpdb/PokerStarsSummary.py @@ -93,7 +93,6 @@ class PokerStarsSummary(TourneySummary): result=result.groupdict() self.added=100*int(Decimal(result['DOLLAR']))+int(Decimal(result['CENT'])) self.addedCurrency=result['CURRENCY'] - #print "TODO: implement added:",self.added,self.addedCurrency currentLine+=1 #print "after added/entries lines[currentLine]", lines[currentLine] diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 7e509e85..b6542bac 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -415,7 +415,9 @@ class Sql: sng BOOLEAN, satellite BOOLEAN, doubleOrNothing BOOLEAN, - guarantee INT) + guarantee INT, + added INT, + addedCurrency VARCHAR(4)) ENGINE=INNODB""" elif db_server == 'postgresql': self.query['createTourneyTypesTable'] = """CREATE TABLE TourneyTypes ( @@ -444,7 +446,9 @@ class Sql: sng BOOLEAN, satellite BOOLEAN, doubleOrNothing BOOLEAN, - guarantee INT)""" + guarantee INT, + added INT, + addedCurrency VARCHAR(4))""" elif db_server == 'sqlite': self.query['createTourneyTypesTable'] = """CREATE TABLE TourneyTypes ( id INTEGER PRIMARY KEY, @@ -472,7 +476,9 @@ class Sql: sng BOOLEAN, satellite BOOLEAN, doubleOrNothing BOOLEAN, - guarantee INT)""" + guarantee INT, + added INT, + addedCurrency VARCHAR(4))""" ################################ # Create Tourneys diff --git a/pyfpdb/TourneySummary.py b/pyfpdb/TourneySummary.py index 4e02ace8..737f6aca 100644 --- a/pyfpdb/TourneySummary.py +++ b/pyfpdb/TourneySummary.py @@ -79,19 +79,21 @@ class TourneySummary(object): self.matrixIdProcessed = None self.subTourneyBuyin = None self.subTourneyFee = None - self.rebuyChips = 0 - self.addOnChips = 0 - self.rebuyCost = 0 - self.addOnCost = 0 - self.totalRebuyCount = 0 - self.totalAddOnCount = 0 - self.koBounty = 0 + self.rebuyChips = None + self.addOnChips = None + self.rebuyCost = None + self.addOnCost = None + self.totalRebuyCount = None + self.totalAddOnCount = None + self.koBounty = None self.tourneyComment = None self.players = [] self.isSng = False self.isSatellite = False self.isDoubleOrNothing = False - self.guarantee = 0 + self.guarantee = None + self.added = None + self.addedCurrency = None self.gametype = {'category':None, 'limitType':None} self.comment = None self.commentTs = None @@ -154,6 +156,8 @@ class TourneySummary(object): ("SATELLITE", self.isSatellite), ("DOUBLE OR NOTHING", self.isDoubleOrNothing), ("GUARANTEE", self.guarantee), + ("ADDED", self.added), + ("ADDED CURRENCY", self.addedCurrency), ("COMMENT", self.comment), ("COMMENT TIMESTAMP", self.commentTs) ) From 656986826f3094f998b1b85ee89f4b89ce8d789b Mon Sep 17 00:00:00 2001 From: steffen123 Date: Sat, 17 Jul 2010 02:35:02 +0200 Subject: [PATCH 49/63] TOURNEY: record added/addedCurrency --- pyfpdb/Database.py | 22 ++++------------------ pyfpdb/SQL.py | 6 ++++-- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 5ad52916..7354624a 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1984,27 +1984,13 @@ class Database: ) result=cursor.fetchone() - expectedValues = { 1 : "buyin", 2 : "fee", 4 : "isKO", 5 : "isRebuy", 6 : "speed", - 7 : "isShootout", 8 : "isMatrix" } - tourneyTypeIdMatch = True - - try: + if result: tourneyTypeId = result[0] - log.debug("Tourney found in db with Tourney_Type_ID = %d" % tourneyTypeId) - for ev in expectedValues : - if ( getattr( hand, expectedValues.get(ev) ) <> result[ev] ): - log.debug("TypeId mismatch : wrong %s : Tourney=%s / db=%s" % (expectedValues.get(ev), getattr( hand, expectedValues.get(ev)), result[ev]) ) - tourneyTypeIdMatch = False - #break - except: - # Tourney not found : a TourneyTypeId has to be found or created for that specific tourney - tourneyTypeIdMatch = False - - if tourneyTypeIdMatch == False : + else: # Check for an existing TTypeId that matches tourney info, if not found create it cursor.execute (self.sql.query['getTourneyTypeId'].replace('%s', self.sql.query['placeholder']), (hand.siteId, hand.buyinCurrency, hand.buyin, hand.fee, hand.gametype['category'], hand.gametype['limitType'], hand.isKO, - hand.isRebuy, hand.isRebuy, hand.speed, hand.isShootout, hand.isMatrix) + hand.isRebuy, hand.isRebuy, hand.speed, hand.isShootout, hand.isMatrix, hand.added, hand.addedCurrency) ) result=cursor.fetchone() @@ -2014,7 +2000,7 @@ class Database: cursor.execute (self.sql.query['insertTourneyType'].replace('%s', self.sql.query['placeholder']), (hand.siteId, hand.buyinCurrency, hand.buyin, hand.fee, hand.gametype['category'], hand.gametype['limitType'], hand.buyInChips, hand.isKO, hand.isRebuy, - hand.isAddOn, hand.speed, hand.isShootout, hand.isMatrix) + hand.isAddOn, hand.speed, hand.isShootout, hand.isMatrix, hand.added, hand.addedCurrency) ) tourneyTypeId = self.get_last_insert_id(cursor) return tourneyTypeId diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index b6542bac..a3dfd5e5 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -3698,12 +3698,14 @@ class Sql: AND speed=%s AND shootout=%s AND matrix=%s + AND added=%s + AND addedCurrency=%s """ self.query['insertTourneyType'] = """INSERT INTO TourneyTypes (siteId, currency, buyin, fee, category, limitType, buyInChips, knockout, rebuy, - addOn ,speed, shootout, matrix) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) + addOn ,speed, shootout, matrix, added, addedCurrency) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) """ self.query['getTourneyByTourneyNo'] = """SELECT t.* From 794f0a0374ce2da55691ebbd0f4266ad2f9f487e Mon Sep 17 00:00:00 2001 From: steffen123 Date: Sat, 17 Jul 2010 02:45:52 +0200 Subject: [PATCH 50/63] GUI: change hotkey to start/stop autoimport to alt+a --- pyfpdb/GuiAutoImport.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py index 518ab647..ddc47f57 100755 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -101,7 +101,7 @@ class GuiAutoImport (threading.Thread): hbox.pack_start(lbl1, expand=True, fill=False) self.doAutoImportBool = False - self.startButton = gtk.ToggleButton(" Start Autoimpor_t ") + self.startButton = gtk.ToggleButton(" Start _Autoimport ") self.startButton.connect("clicked", self.startClicked, "start clicked") hbox.pack_start(self.startButton, expand=False, fill=False) @@ -156,7 +156,7 @@ class GuiAutoImport (threading.Thread): def do_import(self): """Callback for timer to do an import iteration.""" if self.doAutoImportBool: - self.startButton.set_label(u' I M P O R _T I N G ') + self.startButton.set_label(u' _Auto Import Running ') self.importer.runUpdated() self.addText(".") #sys.stdout.write(".") @@ -167,9 +167,9 @@ class GuiAutoImport (threading.Thread): def reset_startbutton(self): if self.pipe_to_hud is not None: - self.startButton.set_label(u' Stop Autoimpor_t ') + self.startButton.set_label(u' Stop _Autoimport ') else: - self.startButton.set_label(u' Start Autoimpor_t ') + self.startButton.set_label(u' Start _Autoimport ') return False @@ -246,7 +246,7 @@ class GuiAutoImport (threading.Thread): #print >>self.pipe_to_hud.stdin, "\n" self.pipe_to_hud.communicate('\n') # waits for process to terminate self.pipe_to_hud = None - self.startButton.set_label(u' Start Autoimpor_t ') + self.startButton.set_label(u' Start _Autoimport ') #end def GuiAutoImport.startClicked From 59294a7b94db1231688f831544c4a766fe39aff5 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Sat, 17 Jul 2010 03:01:09 +0200 Subject: [PATCH 51/63] TIMES: record Hands.importTime as UTC instead of localtime --- pyfpdb/Database.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 7354624a..cdfac060 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1564,7 +1564,7 @@ class Database: p['siteHandNo'], p['tourneyId'], p['startTime'], - datetime.today(), #importtime + datetime.utcnow(), #importtime p['seats'], p['maxSeats'], p['texture'], From 7f2f6301864b96141a7b1b716140d3134b5d4e93 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Sat, 17 Jul 2010 03:09:55 +0200 Subject: [PATCH 52/63] GUI: add some warnings and further info to HUD configurator --- pyfpdb/fpdb.pyw | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index d2f06f35..b122d86e 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -408,7 +408,19 @@ class fpdb: (gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT, gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT)) - label=gtk.Label("Please choose the stats you wish to use") + label=gtk.Label("Please choose the stats you wish to use in the below table.") + diaHudTable.vbox.add(label) + label.show() + + label=gtk.Label("Note that you may not select any stat more than once or it will crash.") + diaHudTable.vbox.add(label) + label.show() + + label=gtk.Label("It is not currently possible to select \"empty\" or anything else to that end.") + diaHudTable.vbox.add(label) + label.show() + + label=gtk.Label("To configure things like colouring you will still have to manually edit your HUD_config.xml.") diaHudTable.vbox.add(label) label.show() From 337fc353c8543eb5524d6b6f735b4431437f9577 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Sat, 17 Jul 2010 03:39:31 +0200 Subject: [PATCH 53/63] rename RingFilters back to Filters --- pyfpdb/Filters.py | 939 +++++++++++++++++++++++++++++++++- pyfpdb/GuiGraphViewer.py | 4 +- pyfpdb/GuiPositionalStats.py | 4 +- pyfpdb/GuiRingPlayerStats.py | 4 +- pyfpdb/GuiSessionViewer.py | 4 +- pyfpdb/RingFilters.py | 955 ----------------------------------- 6 files changed, 944 insertions(+), 966 deletions(-) delete mode 100644 pyfpdb/RingFilters.py diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index b211b698..06f43610 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -#Copyright 2010 Steffen Schaumburg +#Copyright 2008-2010 Steffen Schaumburg #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. @@ -16,7 +16,940 @@ #In the "official" distribution you can find the license in agpl-3.0.txt. import threading +import pygtk +pygtk.require('2.0') +import gtk +import os +import sys +from optparse import OptionParser +from time import gmtime, mktime, strftime, strptime +import gobject +#import pokereval + +import logging +# logging has been set up in fpdb.py or HUD_main.py, use their settings: +log = logging.getLogger("filter") + + +import Configuration +import Database +import SQL +import Charset +import Filters class Filters(threading.Thread): - pass -#end class Filters + def __init__(self, db, config, qdict, display = {}, debug=True): + # config and qdict are now redundant + self.debug = debug + self.db = db + self.cursor = db.cursor + self.sql = db.sql + self.conf = db.config + self.display = display + + # text used on screen stored here so that it can be configured + self.filterText = {'limitsall':'All', 'limitsnone':'None', 'limitsshow':'Show _Limits' + ,'seatsbetween':'Between:', 'seatsand':'And:', 'seatsshow':'Show Number of _Players' + ,'playerstitle':'Hero:', 'sitestitle':'Sites:', 'gamestitle':'Games:' + ,'limitstitle':'Limits:', 'seatstitle':'Number of Players:' + ,'groupstitle':'Grouping:', 'posnshow':'Show Position Stats:' + ,'datestitle':'Date:' + ,'groupsall':'All Players' + ,'limitsFL':'FL', 'limitsNL':'NL', 'limitsPL':'PL', 'ring':'Ring', 'tour':'Tourney' + } + + gen = self.conf.get_general_params() + self.day_start = 0 + if 'day_start' in gen: + self.day_start = float(gen['day_start']) + + # Outer Packing box + self.mainVBox = gtk.VBox(False, 0) + + self.found = {'nl':False, 'fl':False, 'pl':False, 'ring':False, 'tour':False} + self.label = {} + self.callback = {} + + self.make_filter() + + def make_filter(self): + self.sites = {} + self.games = {} + self.limits = {} + self.seats = {} + self.groups = {} + self.siteid = {} + self.heroes = {} + self.boxes = {} + + for site in self.conf.get_supported_sites(): + #Get db site id for filtering later + self.cursor.execute(self.sql.query['getSiteId'], (site,)) + result = self.db.cursor.fetchall() + if len(result) == 1: + self.siteid[site] = result[0][0] + else: + print "Either 0 or more than one site matched (%s) - EEK" % site + + # For use in date ranges. + self.start_date = gtk.Entry(max=12) + self.end_date = gtk.Entry(max=12) + self.start_date.set_property('editable', False) + self.end_date.set_property('editable', False) + + # For use in groups etc + self.sbGroups = {} + self.numHands = 0 + + playerFrame = gtk.Frame() + playerFrame.set_label_align(0.0, 0.0) + vbox = gtk.VBox(False, 0) + + self.fillPlayerFrame(vbox, self.display) + playerFrame.add(vbox) + + sitesFrame = gtk.Frame() + sitesFrame.set_label_align(0.0, 0.0) + vbox = gtk.VBox(False, 0) + + self.fillSitesFrame(vbox) + sitesFrame.add(vbox) + + # Game types + gamesFrame = gtk.Frame() + gamesFrame.set_label_align(0.0, 0.0) + gamesFrame.show() + vbox = gtk.VBox(False, 0) + + self.fillGamesFrame(vbox) + gamesFrame.add(vbox) + + # Limits + limitsFrame = gtk.Frame() + limitsFrame.show() + vbox = gtk.VBox(False, 0) + self.cbLimits = {} + self.cbNoLimits = None + self.cbAllLimits = None + self.cbFL = None + self.cbNL = None + self.cbPL = None + self.rb = {} # radio buttons for ring/tour + self.type = None # ring/tour + self.types = {} # list of all ring/tour values + + self.fillLimitsFrame(vbox, self.display) + limitsFrame.add(vbox) + + # Seats + seatsFrame = gtk.Frame() + seatsFrame.show() + vbox = gtk.VBox(False, 0) + self.sbSeats = {} + + self.fillSeatsFrame(vbox, self.display) + seatsFrame.add(vbox) + + # Groups + groupsFrame = gtk.Frame() + groupsFrame.show() + vbox = gtk.VBox(False, 0) + + self.fillGroupsFrame(vbox, self.display) + groupsFrame.add(vbox) + + # Date + dateFrame = gtk.Frame() + dateFrame.set_label_align(0.0, 0.0) + dateFrame.show() + vbox = gtk.VBox(False, 0) + + self.fillDateFrame(vbox) + dateFrame.add(vbox) + + # Buttons + self.Button1=gtk.Button("Unnamed 1") + self.Button1.set_sensitive(False) + + self.Button2=gtk.Button("Unnamed 2") + self.Button2.set_sensitive(False) + + self.mainVBox.add(playerFrame) + self.mainVBox.add(sitesFrame) + self.mainVBox.add(gamesFrame) + self.mainVBox.add(limitsFrame) + self.mainVBox.add(seatsFrame) + self.mainVBox.add(groupsFrame) + self.mainVBox.add(dateFrame) + self.mainVBox.add(self.Button1) + self.mainVBox.add(self.Button2) + + self.mainVBox.show_all() + + # Should do this cleaner + if "Heroes" not in self.display or self.display["Heroes"] == False: + playerFrame.hide() + if "Sites" not in self.display or self.display["Sites"] == False: + sitesFrame.hide() + if "Games" not in self.display or self.display["Games"] == False: + gamesFrame.hide() + if "Limits" not in self.display or self.display["Limits"] == False: + limitsFrame.hide() + if "Seats" not in self.display or self.display["Seats"] == False: + seatsFrame.hide() + if "Groups" not in self.display or self.display["Groups"] == False: + groupsFrame.hide() + if "Dates" not in self.display or self.display["Dates"] == False: + dateFrame.hide() + if "Button1" not in self.display or self.display["Button1"] == False: + self.Button1.hide() + if "Button2" not in self.display or self.display["Button2"] == False: + self.Button2.hide() + + if 'button1' in self.label and self.label['button1']: + self.Button1.set_label( self.label['button1'] ) + if 'button2' in self.label and self.label['button2']: + self.Button2.set_label( self.label['button2'] ) + if 'button1' in self.callback and self.callback['button1']: + self.Button1.connect("clicked", self.callback['button1'], "clicked") + self.Button1.set_sensitive(True) + if 'button2' in self.callback and self.callback['button2']: + self.Button2.connect("clicked", self.callback['button2'], "clicked") + self.Button2.set_sensitive(True) + + # make sure any locks on db are released: + self.db.rollback() + + def get_vbox(self): + """returns the vbox of this thread""" + return self.mainVBox + #end def get_vbox + + def getNumHands(self): + return self.numHands + #end def getNumHands + + def getSites(self): + return self.sites + #end def getSites + + def getGames(self): + return self.games + + def getSiteIds(self): + return self.siteid + #end def getSiteIds + + def getHeroes(self): + return self.heroes + #end def getHeroes + + def getLimits(self): + ltuple = [] + for l in self.limits: + if self.limits[l] == True: + ltuple.append(l) + return ltuple + + def getType(self): + return(self.type) + + def getSeats(self): + if 'from' in self.sbSeats: + self.seats['from'] = self.sbSeats['from'].get_value_as_int() + if 'to' in self.sbSeats: + self.seats['to'] = self.sbSeats['to'].get_value_as_int() + return self.seats + #end def getSeats + + def getGroups(self): + return self.groups + + def getDates(self): + return self.__get_dates() + #end def getDates + + def registerButton1Name(self, title): + self.Button1.set_label(title) + self.label['button1'] = title + + def registerButton1Callback(self, callback): + self.Button1.connect("clicked", callback, "clicked") + self.Button1.set_sensitive(True) + self.callback['button1'] = callback + + def registerButton2Name(self, title): + self.Button2.set_label(title) + self.label['button2'] = title + #end def registerButton2Name + + def registerButton2Callback(self, callback): + self.Button2.connect("clicked", callback, "clicked") + self.Button2.set_sensitive(True) + self.callback['button2'] = callback + #end def registerButton2Callback + + def cardCallback(self, widget, data=None): + log.debug( "%s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()]) ) + + def createPlayerLine(self, hbox, site, player): + log.debug('add:"%s"' % player) + label = gtk.Label(site +" id:") + hbox.pack_start(label, False, False, 3) + + pname = gtk.Entry() + pname.set_text(player) + pname.set_width_chars(20) + hbox.pack_start(pname, False, True, 0) + pname.connect("changed", self.__set_hero_name, site) + + # Added EntryCompletion but maybe comboBoxEntry is more flexible? (e.g. multiple choices) + completion = gtk.EntryCompletion() + pname.set_completion(completion) + liststore = gtk.ListStore(gobject.TYPE_STRING) + completion.set_model(liststore) + completion.set_text_column(0) + names = self.db.get_player_names(self.conf, self.siteid[site]) # (config=self.conf, site_id=None, like_player_name="%") + for n in names: # list of single-element "tuples" + _n = Charset.to_gui(n[0]) + _nt = (_n, ) + liststore.append(_nt) + + self.__set_hero_name(pname, site) + + def __set_hero_name(self, w, site): + _name = w.get_text() + # get_text() returns a str but we want internal variables to be unicode: + _guiname = unicode(_name) + self.heroes[site] = _guiname + #log.debug("setting heroes[%s]: %s"%(site, self.heroes[site])) + #end def __set_hero_name + + def __set_num_hands(self, w, val): + try: + self.numHands = int(w.get_text()) + except: + self.numHands = 0 + #log.debug("setting numHands:", self.numHands) + #end def __set_num_hands + + def createSiteLine(self, hbox, site): + cb = gtk.CheckButton(site) + cb.connect('clicked', self.__set_site_select, site) + cb.set_active(True) + hbox.pack_start(cb, False, False, 0) + + def createGameLine(self, hbox, game): + cb = gtk.CheckButton(game) + cb.connect('clicked', self.__set_game_select, game) + hbox.pack_start(cb, False, False, 0) + cb.set_active(True) + + def createLimitLine(self, hbox, limit, ltext): + cb = gtk.CheckButton(str(ltext)) + cb.connect('clicked', self.__set_limit_select, limit) + hbox.pack_start(cb, False, False, 0) + if limit != "none": + cb.set_active(True) + return(cb) + + def __set_site_select(self, w, site): + #print w.get_active() + self.sites[site] = w.get_active() + log.debug("self.sites[%s] set to %s" %(site, self.sites[site])) + + def __set_game_select(self, w, game): + #print w.get_active() + self.games[game] = w.get_active() + log.debug("self.games[%s] set to %s" %(game, self.games[game])) + #end def __set_game_select + + def __set_limit_select(self, w, limit): + #print "__set_limit_select: limit =", limit, w.get_active() + self.limits[limit] = w.get_active() + log.debug("self.limit[%s] set to %s" %(limit, self.limits[limit])) + if limit.isdigit() or (len(limit) > 2 and (limit[-2:] == 'nl' or limit[-2:] == 'fl' or limit[-2:] == 'pl')): + if self.limits[limit]: + if self.cbNoLimits is not None: + self.cbNoLimits.set_active(False) + else: + if self.cbAllLimits is not None: + self.cbAllLimits.set_active(False) + if not self.limits[limit]: + if limit.isdigit(): + if self.cbFL is not None: + self.cbFL.set_active(False) + elif (len(limit) > 2 and (limit[-2:] == 'nl')): + if self.cbNL is not None: + self.cbNL.set_active(False) + else: + if self.cbPL is not None: + self.cbPL.set_active(False) + elif limit == "all": + if self.limits[limit]: + #for cb in self.cbLimits.values(): + # cb.set_active(True) + if self.cbFL is not None: + self.cbFL.set_active(True) + if self.cbNL is not None: + self.cbNL.set_active(True) + if self.cbPL is not None: + self.cbPL.set_active(True) + elif limit == "none": + if self.limits[limit]: + for cb in self.cbLimits.values(): + cb.set_active(False) + if self.cbNL is not None: + self.cbNL.set_active(False) + if self.cbFL is not None: + self.cbFL.set_active(False) + if self.cbPL is not None: + self.cbPL.set_active(False) + elif limit == "fl": + if not self.limits[limit]: + # only toggle all fl limits off if they are all currently on + # this stops turning one off from cascading into 'fl' box off + # and then all fl limits being turned off + all_fl_on = True + for cb in self.cbLimits.values(): + t = cb.get_children()[0].get_text() + if t.isdigit(): + if not cb.get_active(): + all_fl_on = False + found = {'ring':False, 'tour':False} + for cb in self.cbLimits.values(): + #print "cb label: ", cb.children()[0].get_text() + t = cb.get_children()[0].get_text() + if t.isdigit(): + if self.limits[limit] or all_fl_on: + cb.set_active(self.limits[limit]) + found[self.types[t]] = True + if self.limits[limit]: + if not found[self.type]: + if self.type == 'ring': + if 'tour' in self.rb: + self.rb['tour'].set_active(True) + elif self.type == 'tour': + if 'ring' in self.rb: + self.rb['ring'].set_active(True) + elif limit == "nl": + if not self.limits[limit]: + # only toggle all nl limits off if they are all currently on + # this stops turning one off from cascading into 'nl' box off + # and then all nl limits being turned off + all_nl_on = True + for cb in self.cbLimits.values(): + t = cb.get_children()[0].get_text() + if "nl" in t and len(t) > 2: + if not cb.get_active(): + all_nl_on = False + found = {'ring':False, 'tour':False} + for cb in self.cbLimits.values(): + t = cb.get_children()[0].get_text() + if "nl" in t and len(t) > 2: + if self.limits[limit] or all_nl_on: + cb.set_active(self.limits[limit]) + found[self.types[t]] = True + if self.limits[limit]: + if not found[self.type]: + if self.type == 'ring': + if 'tour' in self.rb: + self.rb['tour'].set_active(True) + elif self.type == 'tour': + if 'ring' in self.rb: + self.rb['ring'].set_active(True) + elif limit == "pl": + if not self.limits[limit]: + # only toggle all nl limits off if they are all currently on + # this stops turning one off from cascading into 'nl' box off + # and then all nl limits being turned off + all_nl_on = True + for cb in self.cbLimits.values(): + t = cb.get_children()[0].get_text() + if "pl" in t and len(t) > 2: + if not cb.get_active(): + all_nl_on = False + found = {'ring':False, 'tour':False} + for cb in self.cbLimits.values(): + t = cb.get_children()[0].get_text() + if "pl" in t and len(t) > 2: + if self.limits[limit] or all_nl_on: + cb.set_active(self.limits[limit]) + found[self.types[t]] = True + if self.limits[limit]: + if not found[self.type]: + if self.type == 'ring': + if 'tour' in self.rb: + self.rb['tour'].set_active(True) + elif self.type == 'tour': + if 'ring' in self.rb: + self.rb['ring'].set_active(True) + elif limit == "ring": + log.debug("set", limit, "to", self.limits[limit]) + if self.limits[limit]: + self.type = "ring" + for cb in self.cbLimits.values(): + #print "cb label: ", cb.children()[0].get_text() + if self.types[cb.get_children()[0].get_text()] == 'tour': + cb.set_active(False) + elif limit == "tour": + log.debug( "set", limit, "to", self.limits[limit] ) + if self.limits[limit]: + self.type = "tour" + for cb in self.cbLimits.values(): + #print "cb label: ", cb.children()[0].get_text() + if self.types[cb.get_children()[0].get_text()] == 'ring': + cb.set_active(False) + + def __set_seat_select(self, w, seat): + #print "__set_seat_select: seat =", seat, "active =", w.get_active() + self.seats[seat] = w.get_active() + log.debug( "self.seats[%s] set to %s" %(seat, self.seats[seat]) ) + + def __set_group_select(self, w, group): + #print "__set_seat_select: seat =", seat, "active =", w.get_active() + self.groups[group] = w.get_active() + log.debug( "self.groups[%s] set to %s" %(group, self.groups[group]) ) + + def fillPlayerFrame(self, vbox, display): + top_hbox = gtk.HBox(False, 0) + vbox.pack_start(top_hbox, False, False, 0) + lbl_title = gtk.Label(self.filterText['playerstitle']) + lbl_title.set_alignment(xalign=0.0, yalign=0.5) + top_hbox.pack_start(lbl_title, expand=True, padding=3) + showb = gtk.Button(label="refresh", stock=None, use_underline=True) + showb.set_alignment(xalign=1.0, yalign=0.5) + showb.connect('clicked', self.__refresh, 'players') + + vbox1 = gtk.VBox(False, 0) + vbox.pack_start(vbox1, False, False, 0) + self.boxes['players'] = vbox1 + + for site in self.conf.get_supported_sites(): + hBox = gtk.HBox(False, 0) + vbox1.pack_start(hBox, False, True, 0) + + player = self.conf.supported_sites[site].screen_name + _pname = Charset.to_gui(player) + self.createPlayerLine(hBox, site, _pname) + + if "GroupsAll" in display and display["GroupsAll"] == True: + hbox = gtk.HBox(False, 0) + vbox1.pack_start(hbox, False, False, 0) + cb = gtk.CheckButton(self.filterText['groupsall']) + cb.connect('clicked', self.__set_group_select, 'allplayers') + hbox.pack_start(cb, False, False, 0) + self.sbGroups['allplayers'] = cb + self.groups['allplayers'] = False + + lbl = gtk.Label('Min # Hands:') + lbl.set_alignment(xalign=1.0, yalign=0.5) + hbox.pack_start(lbl, expand=True, padding=3) + + phands = gtk.Entry() + phands.set_text('0') + phands.set_width_chars(8) + hbox.pack_start(phands, False, False, 0) + phands.connect("changed", self.__set_num_hands, site) + top_hbox.pack_start(showb, expand=False, padding=1) + + def fillSitesFrame(self, vbox): + top_hbox = gtk.HBox(False, 0) + top_hbox.show() + vbox.pack_start(top_hbox, False, False, 0) + + lbl_title = gtk.Label(self.filterText['sitestitle']) + lbl_title.set_alignment(xalign=0.0, yalign=0.5) + top_hbox.pack_start(lbl_title, expand=True, padding=3) + + showb = gtk.Button(label="hide", stock=None, use_underline=True) + showb.set_alignment(xalign=1.0, yalign=0.5) + showb.connect('clicked', self.__toggle_box, 'sites') + showb.show() + top_hbox.pack_start(showb, expand=False, padding=1) + + vbox1 = gtk.VBox(False, 0) + self.boxes['sites'] = vbox1 + vbox.pack_start(vbox1, False, False, 0) + + for site in self.conf.get_supported_sites(): + hbox = gtk.HBox(False, 0) + vbox1.pack_start(hbox, False, True, 0) + self.createSiteLine(hbox, site) + #Get db site id for filtering later + #self.cursor.execute(self.sql.query['getSiteId'], (site,)) + #result = self.db.cursor.fetchall() + #if len(result) == 1: + # self.siteid[site] = result[0][0] + #else: + # print "Either 0 or more than one site matched - EEK" + + def fillGamesFrame(self, vbox): + top_hbox = gtk.HBox(False, 0) + vbox.pack_start(top_hbox, False, False, 0) + lbl_title = gtk.Label(self.filterText['gamestitle']) + lbl_title.set_alignment(xalign=0.0, yalign=0.5) + top_hbox.pack_start(lbl_title, expand=True, padding=3) + showb = gtk.Button(label="hide", stock=None, use_underline=True) + showb.set_alignment(xalign=1.0, yalign=0.5) + showb.connect('clicked', self.__toggle_box, 'games') + top_hbox.pack_start(showb, expand=False, padding=1) + + vbox1 = gtk.VBox(False, 0) + vbox.pack_start(vbox1, False, False, 0) + self.boxes['games'] = vbox1 + + self.cursor.execute(self.sql.query['getGames']) + result = self.db.cursor.fetchall() + if len(result) >= 1: + for line in result: + hbox = gtk.HBox(False, 0) + vbox1.pack_start(hbox, False, True, 0) + self.createGameLine(hbox, line[0]) + else: + print "INFO: No games returned from database" + log.info("No games returned from database") + #end def fillGamesFrame + + def fillLimitsFrame(self, vbox, display): + top_hbox = gtk.HBox(False, 0) + vbox.pack_start(top_hbox, False, False, 0) + lbl_title = gtk.Label(self.filterText['limitstitle']) + lbl_title.set_alignment(xalign=0.0, yalign=0.5) + top_hbox.pack_start(lbl_title, expand=True, padding=3) + showb = gtk.Button(label="hide", stock=None, use_underline=True) + showb.set_alignment(xalign=1.0, yalign=0.5) + showb.connect('clicked', self.__toggle_box, 'limits') + + vbox1 = gtk.VBox(False, 0) + vbox.pack_start(vbox1, False, False, 0) + self.boxes['limits'] = vbox1 + + self.cursor.execute(self.sql.query['getCashLimits']) + # selects limitType, bigBlind + result = self.db.cursor.fetchall() + self.found = {'nl':False, 'fl':False, 'pl':False, 'ring':False, 'tour':False} + + if len(result) >= 1: + hbox = gtk.HBox(True, 0) + vbox1.pack_start(hbox, False, False, 0) + vbox2 = gtk.VBox(False, 0) + hbox.pack_start(vbox2, False, False, 0) + vbox3 = gtk.VBox(False, 0) + hbox.pack_start(vbox3, False, False, 0) + for i, line in enumerate(result): + if "UseType" in self.display: + if line[0] != self.display["UseType"]: + continue + hbox = gtk.HBox(False, 0) + if i <= len(result)/2: + vbox2.pack_start(hbox, False, False, 0) + else: + vbox3.pack_start(hbox, False, False, 0) + if True: #line[0] == 'ring': + if line[1] == 'fl': + name = str(line[2]) + self.found['fl'] = True + elif line[1] == 'pl': + name = str(line[2])+line[1] + self.found['pl'] = True + else: + name = str(line[2])+line[1] + self.found['nl'] = True + self.cbLimits[name] = self.createLimitLine(hbox, name, name) + self.types[name] = line[0] + self.found[line[0]] = True # type is ring/tour + self.type = line[0] # if only one type, set it now + if "LimitSep" in display and display["LimitSep"] == True and len(result) >= 2: + hbox = gtk.HBox(True, 0) + vbox1.pack_start(hbox, False, False, 0) + vbox2 = gtk.VBox(False, 0) + hbox.pack_start(vbox2, False, False, 0) + vbox3 = gtk.VBox(False, 0) + hbox.pack_start(vbox3, False, False, 0) + + hbox = gtk.HBox(False, 0) + vbox2.pack_start(hbox, False, False, 0) + self.cbAllLimits = self.createLimitLine(hbox, 'all', self.filterText['limitsall']) + hbox = gtk.HBox(False, 0) + vbox2.pack_start(hbox, False, False, 0) + self.cbNoLimits = self.createLimitLine(hbox, 'none', self.filterText['limitsnone']) + + dest = vbox3 # for ring/tour buttons + if "LimitType" in display and display["LimitType"] == True: + num_limit_types = 0 + if self.found['fl']: num_limit_types = num_limit_types + 1 + if self.found['pl']: num_limit_types = num_limit_types + 1 + if self.found['nl']: num_limit_types = num_limit_types + 1 + if num_limit_types > 1: + if self.found['fl']: + hbox = gtk.HBox(False, 0) + vbox3.pack_start(hbox, False, False, 0) + self.cbFL = self.createLimitLine(hbox, 'fl', self.filterText['limitsFL']) + if self.found['nl']: + hbox = gtk.HBox(False, 0) + vbox3.pack_start(hbox, False, False, 0) + self.cbNL = self.createLimitLine(hbox, 'nl', self.filterText['limitsNL']) + if self.found['pl']: + hbox = gtk.HBox(False, 0) + vbox3.pack_start(hbox, False, False, 0) + self.cbPL = self.createLimitLine(hbox, 'pl', self.filterText['limitsPL']) + dest = vbox2 # for ring/tour buttons + else: + print "INFO: No games returned from database" + log.info("No games returned from database") + + if "Type" in display and display["Type"] == True and self.found['ring'] and self.found['tour']: + rb1 = gtk.RadioButton(None, self.filterText['ring']) + rb1.connect('clicked', self.__set_limit_select, 'ring') + rb2 = gtk.RadioButton(rb1, self.filterText['tour']) + rb2.connect('clicked', self.__set_limit_select, 'tour') + top_hbox.pack_start(rb1, False, False, 0) # (child, expand, fill, padding) + top_hbox.pack_start(rb2, True, True, 0) # child uses expand space if fill is true + + self.rb['ring'] = rb1 + self.rb['tour'] = rb2 + #print "about to set ring to true" + rb1.set_active(True) + # set_active doesn't seem to call this for some reason so call manually: + self.__set_limit_select(rb1, 'ring') + self.type = 'ring' + top_hbox.pack_start(showb, expand=False, padding=1) + + def fillSeatsFrame(self, vbox, display): + hbox = gtk.HBox(False, 0) + vbox.pack_start(hbox, False, False, 0) + lbl_title = gtk.Label(self.filterText['seatstitle']) + lbl_title.set_alignment(xalign=0.0, yalign=0.5) + hbox.pack_start(lbl_title, expand=True, padding=3) + showb = gtk.Button(label="hide", stock=None, use_underline=True) + showb.set_alignment(xalign=1.0, yalign=0.5) + showb.connect('clicked', self.__toggle_box, 'seats') + hbox.pack_start(showb, expand=False, padding=1) + + vbox1 = gtk.VBox(False, 0) + vbox.pack_start(vbox1, False, False, 0) + self.boxes['seats'] = vbox1 + + hbox = gtk.HBox(False, 0) + vbox1.pack_start(hbox, False, True, 0) + + lbl_from = gtk.Label(self.filterText['seatsbetween']) + lbl_to = gtk.Label(self.filterText['seatsand']) + adj1 = gtk.Adjustment(value=2, lower=2, upper=10, step_incr=1, page_incr=1, page_size=0) + sb1 = gtk.SpinButton(adjustment=adj1, climb_rate=0.0, digits=0) + adj2 = gtk.Adjustment(value=10, lower=2, upper=10, step_incr=1, page_incr=1, page_size=0) + sb2 = gtk.SpinButton(adjustment=adj2, climb_rate=0.0, digits=0) + + hbox.pack_start(lbl_from, expand=False, padding=3) + hbox.pack_start(sb1, False, False, 0) + hbox.pack_start(lbl_to, expand=False, padding=3) + hbox.pack_start(sb2, False, False, 0) + + self.sbSeats['from'] = sb1 + self.sbSeats['to'] = sb2 + #end def fillSeatsFrame + + def fillGroupsFrame(self, vbox, display): + hbox = gtk.HBox(False, 0) + vbox.pack_start(hbox, False, False, 0) + lbl_title = gtk.Label(self.filterText['groupstitle']) + lbl_title.set_alignment(xalign=0.0, yalign=0.5) + hbox.pack_start(lbl_title, expand=True, padding=3) + showb = gtk.Button(label="hide", stock=None, use_underline=True) + showb.set_alignment(xalign=1.0, yalign=0.5) + showb.connect('clicked', self.__toggle_box, 'groups') + hbox.pack_start(showb, expand=False, padding=1) + + vbox1 = gtk.VBox(False, 0) + vbox.pack_start(vbox1, False, False, 0) + self.boxes['groups'] = vbox1 + + hbox = gtk.HBox(False, 0) + vbox1.pack_start(hbox, False, False, 0) + cb = self.createLimitLine(hbox, 'show', self.filterText['limitsshow']) + + hbox = gtk.HBox(False, 0) + vbox1.pack_start(hbox, False, True, 0) + cb = gtk.CheckButton(self.filterText['posnshow']) + cb.connect('clicked', self.__set_group_select, 'posn') + hbox.pack_start(cb, False, False, 0) + self.sbGroups['posn'] = cb + self.groups['posn'] = False + + if "SeatSep" in display and display["SeatSep"] == True: + hbox = gtk.HBox(False, 0) + vbox1.pack_start(hbox, False, True, 0) + cb = gtk.CheckButton(self.filterText['seatsshow']) + cb.connect('clicked', self.__set_seat_select, 'show') + hbox.pack_start(cb, False, False, 0) + self.sbSeats['show'] = cb + self.seats['show'] = False + + def fillCardsFrame(self, vbox): + hbox1 = gtk.HBox(True,0) + hbox1.show() + vbox.pack_start(hbox1, True, True, 0) + + cards = [ "A", "K","Q","J","T","9","8","7","6","5","4","3","2" ] + + for j in range(0, len(cards)): + hbox1 = gtk.HBox(True,0) + hbox1.show() + vbox.pack_start(hbox1, True, True, 0) + for i in range(0, len(cards)): + if i < (j + 1): + suit = "o" + else: + suit = "s" + button = gtk.ToggleButton("%s%s%s" %(cards[i], cards[j], suit)) + button.connect("toggled", self.cardCallback, "%s%s%s" %(cards[i], cards[j], suit)) + hbox1.pack_start(button, True, True, 0) + button.show() + + def fillDateFrame(self, vbox): + # Hat tip to Mika Bostrom - calendar code comes from PokerStats + top_hbox = gtk.HBox(False, 0) + vbox.pack_start(top_hbox, False, False, 0) + lbl_title = gtk.Label(self.filterText['datestitle']) + lbl_title.set_alignment(xalign=0.0, yalign=0.5) + top_hbox.pack_start(lbl_title, expand=True, padding=3) + showb = gtk.Button(label="hide", stock=None, use_underline=True) + showb.set_alignment(xalign=1.0, yalign=0.5) + showb.connect('clicked', self.__toggle_box, 'dates') + top_hbox.pack_start(showb, expand=False, padding=1) + + vbox1 = gtk.VBox(False, 0) + vbox.pack_start(vbox1, False, False, 0) + self.boxes['dates'] = vbox1 + + hbox = gtk.HBox() + vbox1.pack_start(hbox, False, True, 0) + + lbl_start = gtk.Label('From:') + + btn_start = gtk.Button() + btn_start.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)) + btn_start.connect('clicked', self.__calendar_dialog, self.start_date) + + hbox.pack_start(lbl_start, expand=False, padding=3) + hbox.pack_start(btn_start, expand=False, padding=3) + hbox.pack_start(self.start_date, expand=False, padding=2) + + #New row for end date + hbox = gtk.HBox() + vbox1.pack_start(hbox, False, True, 0) + + lbl_end = gtk.Label(' To:') + btn_end = gtk.Button() + btn_end.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)) + btn_end.connect('clicked', self.__calendar_dialog, self.end_date) + + btn_clear = gtk.Button(label=' Clear Dates ') + btn_clear.connect('clicked', self.__clear_dates) + + hbox.pack_start(lbl_end, expand=False, padding=3) + hbox.pack_start(btn_end, expand=False, padding=3) + hbox.pack_start(self.end_date, expand=False, padding=2) + + hbox.pack_start(btn_clear, expand=False, padding=15) + #end def fillDateFrame + + def __refresh(self, widget, entry): + for w in self.mainVBox.get_children(): + w.destroy() + self.make_filter() + + def __toggle_box(self, widget, entry): + if self.boxes[entry].props.visible: + self.boxes[entry].hide() + widget.set_label("show") + else: + self.boxes[entry].show() + widget.set_label("hide") + #end def __toggle_box + + def __calendar_dialog(self, widget, entry): + d = gtk.Window(gtk.WINDOW_TOPLEVEL) + d.set_title('Pick a date') + + vb = gtk.VBox() + cal = gtk.Calendar() + vb.pack_start(cal, expand=False, padding=0) + + btn = gtk.Button('Done') + btn.connect('clicked', self.__get_date, cal, entry, d) + + vb.pack_start(btn, expand=False, padding=4) + + d.add(vb) + d.set_position(gtk.WIN_POS_MOUSE) + d.show_all() + #end def __calendar_dialog + + def __clear_dates(self, w): + self.start_date.set_text('') + self.end_date.set_text('') + #end def __clear_dates + + def __get_dates(self): + # self.day_start gives user's start of day in hours + offset = int(self.day_start * 3600) # calc day_start in seconds + + t1 = self.start_date.get_text() + t2 = self.end_date.get_text() + + if t1 == '': + t1 = '1970-01-02' + if t2 == '': + t2 = '2020-12-12' + + s1 = strptime(t1, "%Y-%m-%d") # make time_struct + s2 = strptime(t2, "%Y-%m-%d") + e1 = mktime(s1) + offset # s1 is localtime, but returned time since epoch is UTC, then add the + e2 = mktime(s2) + offset # s2 is localtime, but returned time since epoch is UTC + e2 = e2 + 24 * 3600 - 1 # date test is inclusive, so add 23h 59m 59s to e2 + + adj_t1 = strftime("%Y-%m-%d %H:%M:%S", gmtime(e1)) # make adjusted string including time + adj_t2 = strftime("%Y-%m-%d %H:%M:%S", gmtime(e2)) + log.info("t1="+t1+" adj_t1="+adj_t1+'.') + + return (adj_t1, adj_t2) + #end def __get_dates + + def __get_date(self, widget, calendar, entry, win): + # year and day are correct, month is 0..11 + (year, month, day) = calendar.get_date() + month += 1 + ds = '%04d-%02d-%02d' % (year, month, day) + entry.set_text(ds) + win.destroy() + +def main(argv=None): + """main can also be called in the python interpreter, by supplying the command line as the argument.""" + if argv is None: + argv = sys.argv[1:] + + def destroy(*args): # call back for terminating the main eventloop + gtk.main_quit() + + parser = OptionParser() + (options, argv) = parser.parse_args(args = argv) + + config = Configuration.Config() + db = None + + db = Database.Database() + db.do_connect(config) + + qdict = SQL.SQL(db.get_backend_name()) + + i = Filters(db, config, qdict) + main_window = gtk.Window() + main_window.connect('destroy', destroy) + main_window.add(i.get_vbox()) + main_window.show() + gtk.main() + +if __name__ == '__main__': + sys.exit(main()) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index 68cbacc7..96026864 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -44,7 +44,7 @@ except ImportError, inst: import fpdb_import import Database -import RingFilters +import Filters import Charset class GuiGraphViewer (threading.Thread): @@ -75,7 +75,7 @@ class GuiGraphViewer (threading.Thread): "Button2" : True } - self.filters = RingFilters.RingFilters(self.db, self.conf, self.sql, display = filters_display) + self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display) self.filters.registerButton1Name("Refresh _Graph") self.filters.registerButton1Callback(self.generateGraph) self.filters.registerButton2Name("_Export to File") diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index b114e892..6b4e0703 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -24,7 +24,7 @@ from time import time, strftime import fpdb_import import Database -import RingFilters +import Filters class GuiPositionalStats (threading.Thread): def __init__(self, config, querylist, debug=True): @@ -57,7 +57,7 @@ class GuiPositionalStats (threading.Thread): "Button2" : False } - self.filters = RingFilters.RingFilters(self.db, self.conf, self.sql, display = filters_display) + self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display) self.filters.registerButton1Name("Refresh") self.filters.registerButton1Callback(self.refreshStats) diff --git a/pyfpdb/GuiRingPlayerStats.py b/pyfpdb/GuiRingPlayerStats.py index 29aaf44c..f7d32355 100644 --- a/pyfpdb/GuiRingPlayerStats.py +++ b/pyfpdb/GuiRingPlayerStats.py @@ -27,7 +27,7 @@ from time import time, strftime import Card import fpdb_import import Database -import RingFilters +import Filters import Charset import GuiPlayerStats @@ -79,7 +79,7 @@ class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats): "Button2" : True } - self.filters = RingFilters.RingFilters(self.db, self.conf, self.sql, display = filters_display) + self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display) self.filters.registerButton1Name("_Filters") self.filters.registerButton1Callback(self.showDetailFilter) self.filters.registerButton2Name("_Refresh Stats") diff --git a/pyfpdb/GuiSessionViewer.py b/pyfpdb/GuiSessionViewer.py index f8c0d4cc..a04248a3 100755 --- a/pyfpdb/GuiSessionViewer.py +++ b/pyfpdb/GuiSessionViewer.py @@ -45,7 +45,7 @@ except ImportError, inst: import Card import fpdb_import import Database -import RingFilters +import Filters import Charset class GuiSessionViewer (threading.Thread): @@ -95,7 +95,7 @@ class GuiSessionViewer (threading.Thread): "Button2" : False } - self.filters = RingFilters.RingFilters(self.db, self.conf, self.sql, display = filters_display) + self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display) self.filters.registerButton1Name("_Refresh") self.filters.registerButton1Callback(self.refreshStats) diff --git a/pyfpdb/RingFilters.py b/pyfpdb/RingFilters.py deleted file mode 100644 index 47bd5d6f..00000000 --- a/pyfpdb/RingFilters.py +++ /dev/null @@ -1,955 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -#Copyright 2008-2010 Steffen Schaumburg -#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. - -import threading -import pygtk -pygtk.require('2.0') -import gtk -import os -import sys -from optparse import OptionParser -from time import gmtime, mktime, strftime, strptime -import gobject -#import pokereval - -import logging -# logging has been set up in fpdb.py or HUD_main.py, use their settings: -log = logging.getLogger("filter") - - -import Configuration -import Database -import SQL -import Charset -import Filters - -class RingFilters(Filters.Filters): - def __init__(self, db, config, qdict, display = {}, debug=True): - # config and qdict are now redundant - self.debug = debug - self.db = db - self.cursor = db.cursor - self.sql = db.sql - self.conf = db.config - self.display = display - - # text used on screen stored here so that it can be configured - self.filterText = {'limitsall':'All', 'limitsnone':'None', 'limitsshow':'Show _Limits' - ,'seatsbetween':'Between:', 'seatsand':'And:', 'seatsshow':'Show Number of _Players' - ,'playerstitle':'Hero:', 'sitestitle':'Sites:', 'gamestitle':'Games:' - ,'limitstitle':'Limits:', 'seatstitle':'Number of Players:' - ,'groupstitle':'Grouping:', 'posnshow':'Show Position Stats:' - ,'datestitle':'Date:' - ,'groupsall':'All Players' - ,'limitsFL':'FL', 'limitsNL':'NL', 'limitsPL':'PL', 'ring':'Ring', 'tour':'Tourney' - } - - gen = self.conf.get_general_params() - self.day_start = 0 - if 'day_start' in gen: - self.day_start = float(gen['day_start']) - - # Outer Packing box - self.mainVBox = gtk.VBox(False, 0) - - self.found = {'nl':False, 'fl':False, 'pl':False, 'ring':False, 'tour':False} - self.label = {} - self.callback = {} - - self.make_filter() - - def make_filter(self): - self.sites = {} - self.games = {} - self.limits = {} - self.seats = {} - self.groups = {} - self.siteid = {} - self.heroes = {} - self.boxes = {} - - for site in self.conf.get_supported_sites(): - #Get db site id for filtering later - self.cursor.execute(self.sql.query['getSiteId'], (site,)) - result = self.db.cursor.fetchall() - if len(result) == 1: - self.siteid[site] = result[0][0] - else: - print "Either 0 or more than one site matched (%s) - EEK" % site - - # For use in date ranges. - self.start_date = gtk.Entry(max=12) - self.end_date = gtk.Entry(max=12) - self.start_date.set_property('editable', False) - self.end_date.set_property('editable', False) - - # For use in groups etc - self.sbGroups = {} - self.numHands = 0 - - playerFrame = gtk.Frame() - playerFrame.set_label_align(0.0, 0.0) - vbox = gtk.VBox(False, 0) - - self.fillPlayerFrame(vbox, self.display) - playerFrame.add(vbox) - - sitesFrame = gtk.Frame() - sitesFrame.set_label_align(0.0, 0.0) - vbox = gtk.VBox(False, 0) - - self.fillSitesFrame(vbox) - sitesFrame.add(vbox) - - # Game types - gamesFrame = gtk.Frame() - gamesFrame.set_label_align(0.0, 0.0) - gamesFrame.show() - vbox = gtk.VBox(False, 0) - - self.fillGamesFrame(vbox) - gamesFrame.add(vbox) - - # Limits - limitsFrame = gtk.Frame() - limitsFrame.show() - vbox = gtk.VBox(False, 0) - self.cbLimits = {} - self.cbNoLimits = None - self.cbAllLimits = None - self.cbFL = None - self.cbNL = None - self.cbPL = None - self.rb = {} # radio buttons for ring/tour - self.type = None # ring/tour - self.types = {} # list of all ring/tour values - - self.fillLimitsFrame(vbox, self.display) - limitsFrame.add(vbox) - - # Seats - seatsFrame = gtk.Frame() - seatsFrame.show() - vbox = gtk.VBox(False, 0) - self.sbSeats = {} - - self.fillSeatsFrame(vbox, self.display) - seatsFrame.add(vbox) - - # Groups - groupsFrame = gtk.Frame() - groupsFrame.show() - vbox = gtk.VBox(False, 0) - - self.fillGroupsFrame(vbox, self.display) - groupsFrame.add(vbox) - - # Date - dateFrame = gtk.Frame() - dateFrame.set_label_align(0.0, 0.0) - dateFrame.show() - vbox = gtk.VBox(False, 0) - - self.fillDateFrame(vbox) - dateFrame.add(vbox) - - # Buttons - self.Button1=gtk.Button("Unnamed 1") - self.Button1.set_sensitive(False) - - self.Button2=gtk.Button("Unnamed 2") - self.Button2.set_sensitive(False) - - self.mainVBox.add(playerFrame) - self.mainVBox.add(sitesFrame) - self.mainVBox.add(gamesFrame) - self.mainVBox.add(limitsFrame) - self.mainVBox.add(seatsFrame) - self.mainVBox.add(groupsFrame) - self.mainVBox.add(dateFrame) - self.mainVBox.add(self.Button1) - self.mainVBox.add(self.Button2) - - self.mainVBox.show_all() - - # Should do this cleaner - if "Heroes" not in self.display or self.display["Heroes"] == False: - playerFrame.hide() - if "Sites" not in self.display or self.display["Sites"] == False: - sitesFrame.hide() - if "Games" not in self.display or self.display["Games"] == False: - gamesFrame.hide() - if "Limits" not in self.display or self.display["Limits"] == False: - limitsFrame.hide() - if "Seats" not in self.display or self.display["Seats"] == False: - seatsFrame.hide() - if "Groups" not in self.display or self.display["Groups"] == False: - groupsFrame.hide() - if "Dates" not in self.display or self.display["Dates"] == False: - dateFrame.hide() - if "Button1" not in self.display or self.display["Button1"] == False: - self.Button1.hide() - if "Button2" not in self.display or self.display["Button2"] == False: - self.Button2.hide() - - if 'button1' in self.label and self.label['button1']: - self.Button1.set_label( self.label['button1'] ) - if 'button2' in self.label and self.label['button2']: - self.Button2.set_label( self.label['button2'] ) - if 'button1' in self.callback and self.callback['button1']: - self.Button1.connect("clicked", self.callback['button1'], "clicked") - self.Button1.set_sensitive(True) - if 'button2' in self.callback and self.callback['button2']: - self.Button2.connect("clicked", self.callback['button2'], "clicked") - self.Button2.set_sensitive(True) - - # make sure any locks on db are released: - self.db.rollback() - - def get_vbox(self): - """returns the vbox of this thread""" - return self.mainVBox - #end def get_vbox - - def getNumHands(self): - return self.numHands - #end def getNumHands - - def getSites(self): - return self.sites - #end def getSites - - def getGames(self): - return self.games - - def getSiteIds(self): - return self.siteid - #end def getSiteIds - - def getHeroes(self): - return self.heroes - #end def getHeroes - - def getLimits(self): - ltuple = [] - for l in self.limits: - if self.limits[l] == True: - ltuple.append(l) - return ltuple - - def getType(self): - return(self.type) - - def getSeats(self): - if 'from' in self.sbSeats: - self.seats['from'] = self.sbSeats['from'].get_value_as_int() - if 'to' in self.sbSeats: - self.seats['to'] = self.sbSeats['to'].get_value_as_int() - return self.seats - #end def getSeats - - def getGroups(self): - return self.groups - - def getDates(self): - return self.__get_dates() - #end def getDates - - def registerButton1Name(self, title): - self.Button1.set_label(title) - self.label['button1'] = title - - def registerButton1Callback(self, callback): - self.Button1.connect("clicked", callback, "clicked") - self.Button1.set_sensitive(True) - self.callback['button1'] = callback - - def registerButton2Name(self, title): - self.Button2.set_label(title) - self.label['button2'] = title - #end def registerButton2Name - - def registerButton2Callback(self, callback): - self.Button2.connect("clicked", callback, "clicked") - self.Button2.set_sensitive(True) - self.callback['button2'] = callback - #end def registerButton2Callback - - def cardCallback(self, widget, data=None): - log.debug( "%s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()]) ) - - def createPlayerLine(self, hbox, site, player): - log.debug('add:"%s"' % player) - label = gtk.Label(site +" id:") - hbox.pack_start(label, False, False, 3) - - pname = gtk.Entry() - pname.set_text(player) - pname.set_width_chars(20) - hbox.pack_start(pname, False, True, 0) - pname.connect("changed", self.__set_hero_name, site) - - # Added EntryCompletion but maybe comboBoxEntry is more flexible? (e.g. multiple choices) - completion = gtk.EntryCompletion() - pname.set_completion(completion) - liststore = gtk.ListStore(gobject.TYPE_STRING) - completion.set_model(liststore) - completion.set_text_column(0) - names = self.db.get_player_names(self.conf, self.siteid[site]) # (config=self.conf, site_id=None, like_player_name="%") - for n in names: # list of single-element "tuples" - _n = Charset.to_gui(n[0]) - _nt = (_n, ) - liststore.append(_nt) - - self.__set_hero_name(pname, site) - - def __set_hero_name(self, w, site): - _name = w.get_text() - # get_text() returns a str but we want internal variables to be unicode: - _guiname = unicode(_name) - self.heroes[site] = _guiname - #log.debug("setting heroes[%s]: %s"%(site, self.heroes[site])) - #end def __set_hero_name - - def __set_num_hands(self, w, val): - try: - self.numHands = int(w.get_text()) - except: - self.numHands = 0 - #log.debug("setting numHands:", self.numHands) - #end def __set_num_hands - - def createSiteLine(self, hbox, site): - cb = gtk.CheckButton(site) - cb.connect('clicked', self.__set_site_select, site) - cb.set_active(True) - hbox.pack_start(cb, False, False, 0) - - def createGameLine(self, hbox, game): - cb = gtk.CheckButton(game) - cb.connect('clicked', self.__set_game_select, game) - hbox.pack_start(cb, False, False, 0) - cb.set_active(True) - - def createLimitLine(self, hbox, limit, ltext): - cb = gtk.CheckButton(str(ltext)) - cb.connect('clicked', self.__set_limit_select, limit) - hbox.pack_start(cb, False, False, 0) - if limit != "none": - cb.set_active(True) - return(cb) - - def __set_site_select(self, w, site): - #print w.get_active() - self.sites[site] = w.get_active() - log.debug("self.sites[%s] set to %s" %(site, self.sites[site])) - - def __set_game_select(self, w, game): - #print w.get_active() - self.games[game] = w.get_active() - log.debug("self.games[%s] set to %s" %(game, self.games[game])) - #end def __set_game_select - - def __set_limit_select(self, w, limit): - #print "__set_limit_select: limit =", limit, w.get_active() - self.limits[limit] = w.get_active() - log.debug("self.limit[%s] set to %s" %(limit, self.limits[limit])) - if limit.isdigit() or (len(limit) > 2 and (limit[-2:] == 'nl' or limit[-2:] == 'fl' or limit[-2:] == 'pl')): - if self.limits[limit]: - if self.cbNoLimits is not None: - self.cbNoLimits.set_active(False) - else: - if self.cbAllLimits is not None: - self.cbAllLimits.set_active(False) - if not self.limits[limit]: - if limit.isdigit(): - if self.cbFL is not None: - self.cbFL.set_active(False) - elif (len(limit) > 2 and (limit[-2:] == 'nl')): - if self.cbNL is not None: - self.cbNL.set_active(False) - else: - if self.cbPL is not None: - self.cbPL.set_active(False) - elif limit == "all": - if self.limits[limit]: - #for cb in self.cbLimits.values(): - # cb.set_active(True) - if self.cbFL is not None: - self.cbFL.set_active(True) - if self.cbNL is not None: - self.cbNL.set_active(True) - if self.cbPL is not None: - self.cbPL.set_active(True) - elif limit == "none": - if self.limits[limit]: - for cb in self.cbLimits.values(): - cb.set_active(False) - if self.cbNL is not None: - self.cbNL.set_active(False) - if self.cbFL is not None: - self.cbFL.set_active(False) - if self.cbPL is not None: - self.cbPL.set_active(False) - elif limit == "fl": - if not self.limits[limit]: - # only toggle all fl limits off if they are all currently on - # this stops turning one off from cascading into 'fl' box off - # and then all fl limits being turned off - all_fl_on = True - for cb in self.cbLimits.values(): - t = cb.get_children()[0].get_text() - if t.isdigit(): - if not cb.get_active(): - all_fl_on = False - found = {'ring':False, 'tour':False} - for cb in self.cbLimits.values(): - #print "cb label: ", cb.children()[0].get_text() - t = cb.get_children()[0].get_text() - if t.isdigit(): - if self.limits[limit] or all_fl_on: - cb.set_active(self.limits[limit]) - found[self.types[t]] = True - if self.limits[limit]: - if not found[self.type]: - if self.type == 'ring': - if 'tour' in self.rb: - self.rb['tour'].set_active(True) - elif self.type == 'tour': - if 'ring' in self.rb: - self.rb['ring'].set_active(True) - elif limit == "nl": - if not self.limits[limit]: - # only toggle all nl limits off if they are all currently on - # this stops turning one off from cascading into 'nl' box off - # and then all nl limits being turned off - all_nl_on = True - for cb in self.cbLimits.values(): - t = cb.get_children()[0].get_text() - if "nl" in t and len(t) > 2: - if not cb.get_active(): - all_nl_on = False - found = {'ring':False, 'tour':False} - for cb in self.cbLimits.values(): - t = cb.get_children()[0].get_text() - if "nl" in t and len(t) > 2: - if self.limits[limit] or all_nl_on: - cb.set_active(self.limits[limit]) - found[self.types[t]] = True - if self.limits[limit]: - if not found[self.type]: - if self.type == 'ring': - if 'tour' in self.rb: - self.rb['tour'].set_active(True) - elif self.type == 'tour': - if 'ring' in self.rb: - self.rb['ring'].set_active(True) - elif limit == "pl": - if not self.limits[limit]: - # only toggle all nl limits off if they are all currently on - # this stops turning one off from cascading into 'nl' box off - # and then all nl limits being turned off - all_nl_on = True - for cb in self.cbLimits.values(): - t = cb.get_children()[0].get_text() - if "pl" in t and len(t) > 2: - if not cb.get_active(): - all_nl_on = False - found = {'ring':False, 'tour':False} - for cb in self.cbLimits.values(): - t = cb.get_children()[0].get_text() - if "pl" in t and len(t) > 2: - if self.limits[limit] or all_nl_on: - cb.set_active(self.limits[limit]) - found[self.types[t]] = True - if self.limits[limit]: - if not found[self.type]: - if self.type == 'ring': - if 'tour' in self.rb: - self.rb['tour'].set_active(True) - elif self.type == 'tour': - if 'ring' in self.rb: - self.rb['ring'].set_active(True) - elif limit == "ring": - log.debug("set", limit, "to", self.limits[limit]) - if self.limits[limit]: - self.type = "ring" - for cb in self.cbLimits.values(): - #print "cb label: ", cb.children()[0].get_text() - if self.types[cb.get_children()[0].get_text()] == 'tour': - cb.set_active(False) - elif limit == "tour": - log.debug( "set", limit, "to", self.limits[limit] ) - if self.limits[limit]: - self.type = "tour" - for cb in self.cbLimits.values(): - #print "cb label: ", cb.children()[0].get_text() - if self.types[cb.get_children()[0].get_text()] == 'ring': - cb.set_active(False) - - def __set_seat_select(self, w, seat): - #print "__set_seat_select: seat =", seat, "active =", w.get_active() - self.seats[seat] = w.get_active() - log.debug( "self.seats[%s] set to %s" %(seat, self.seats[seat]) ) - - def __set_group_select(self, w, group): - #print "__set_seat_select: seat =", seat, "active =", w.get_active() - self.groups[group] = w.get_active() - log.debug( "self.groups[%s] set to %s" %(group, self.groups[group]) ) - - def fillPlayerFrame(self, vbox, display): - top_hbox = gtk.HBox(False, 0) - vbox.pack_start(top_hbox, False, False, 0) - lbl_title = gtk.Label(self.filterText['playerstitle']) - lbl_title.set_alignment(xalign=0.0, yalign=0.5) - top_hbox.pack_start(lbl_title, expand=True, padding=3) - showb = gtk.Button(label="refresh", stock=None, use_underline=True) - showb.set_alignment(xalign=1.0, yalign=0.5) - showb.connect('clicked', self.__refresh, 'players') - - vbox1 = gtk.VBox(False, 0) - vbox.pack_start(vbox1, False, False, 0) - self.boxes['players'] = vbox1 - - for site in self.conf.get_supported_sites(): - hBox = gtk.HBox(False, 0) - vbox1.pack_start(hBox, False, True, 0) - - player = self.conf.supported_sites[site].screen_name - _pname = Charset.to_gui(player) - self.createPlayerLine(hBox, site, _pname) - - if "GroupsAll" in display and display["GroupsAll"] == True: - hbox = gtk.HBox(False, 0) - vbox1.pack_start(hbox, False, False, 0) - cb = gtk.CheckButton(self.filterText['groupsall']) - cb.connect('clicked', self.__set_group_select, 'allplayers') - hbox.pack_start(cb, False, False, 0) - self.sbGroups['allplayers'] = cb - self.groups['allplayers'] = False - - lbl = gtk.Label('Min # Hands:') - lbl.set_alignment(xalign=1.0, yalign=0.5) - hbox.pack_start(lbl, expand=True, padding=3) - - phands = gtk.Entry() - phands.set_text('0') - phands.set_width_chars(8) - hbox.pack_start(phands, False, False, 0) - phands.connect("changed", self.__set_num_hands, site) - top_hbox.pack_start(showb, expand=False, padding=1) - - def fillSitesFrame(self, vbox): - top_hbox = gtk.HBox(False, 0) - top_hbox.show() - vbox.pack_start(top_hbox, False, False, 0) - - lbl_title = gtk.Label(self.filterText['sitestitle']) - lbl_title.set_alignment(xalign=0.0, yalign=0.5) - top_hbox.pack_start(lbl_title, expand=True, padding=3) - - showb = gtk.Button(label="hide", stock=None, use_underline=True) - showb.set_alignment(xalign=1.0, yalign=0.5) - showb.connect('clicked', self.__toggle_box, 'sites') - showb.show() - top_hbox.pack_start(showb, expand=False, padding=1) - - vbox1 = gtk.VBox(False, 0) - self.boxes['sites'] = vbox1 - vbox.pack_start(vbox1, False, False, 0) - - for site in self.conf.get_supported_sites(): - hbox = gtk.HBox(False, 0) - vbox1.pack_start(hbox, False, True, 0) - self.createSiteLine(hbox, site) - #Get db site id for filtering later - #self.cursor.execute(self.sql.query['getSiteId'], (site,)) - #result = self.db.cursor.fetchall() - #if len(result) == 1: - # self.siteid[site] = result[0][0] - #else: - # print "Either 0 or more than one site matched - EEK" - - def fillGamesFrame(self, vbox): - top_hbox = gtk.HBox(False, 0) - vbox.pack_start(top_hbox, False, False, 0) - lbl_title = gtk.Label(self.filterText['gamestitle']) - lbl_title.set_alignment(xalign=0.0, yalign=0.5) - top_hbox.pack_start(lbl_title, expand=True, padding=3) - showb = gtk.Button(label="hide", stock=None, use_underline=True) - showb.set_alignment(xalign=1.0, yalign=0.5) - showb.connect('clicked', self.__toggle_box, 'games') - top_hbox.pack_start(showb, expand=False, padding=1) - - vbox1 = gtk.VBox(False, 0) - vbox.pack_start(vbox1, False, False, 0) - self.boxes['games'] = vbox1 - - self.cursor.execute(self.sql.query['getGames']) - result = self.db.cursor.fetchall() - if len(result) >= 1: - for line in result: - hbox = gtk.HBox(False, 0) - vbox1.pack_start(hbox, False, True, 0) - self.createGameLine(hbox, line[0]) - else: - print "INFO: No games returned from database" - log.info("No games returned from database") - #end def fillGamesFrame - - def fillLimitsFrame(self, vbox, display): - top_hbox = gtk.HBox(False, 0) - vbox.pack_start(top_hbox, False, False, 0) - lbl_title = gtk.Label(self.filterText['limitstitle']) - lbl_title.set_alignment(xalign=0.0, yalign=0.5) - top_hbox.pack_start(lbl_title, expand=True, padding=3) - showb = gtk.Button(label="hide", stock=None, use_underline=True) - showb.set_alignment(xalign=1.0, yalign=0.5) - showb.connect('clicked', self.__toggle_box, 'limits') - - vbox1 = gtk.VBox(False, 0) - vbox.pack_start(vbox1, False, False, 0) - self.boxes['limits'] = vbox1 - - self.cursor.execute(self.sql.query['getCashLimits']) - # selects limitType, bigBlind - result = self.db.cursor.fetchall() - self.found = {'nl':False, 'fl':False, 'pl':False, 'ring':False, 'tour':False} - - if len(result) >= 1: - hbox = gtk.HBox(True, 0) - vbox1.pack_start(hbox, False, False, 0) - vbox2 = gtk.VBox(False, 0) - hbox.pack_start(vbox2, False, False, 0) - vbox3 = gtk.VBox(False, 0) - hbox.pack_start(vbox3, False, False, 0) - for i, line in enumerate(result): - if "UseType" in self.display: - if line[0] != self.display["UseType"]: - continue - hbox = gtk.HBox(False, 0) - if i <= len(result)/2: - vbox2.pack_start(hbox, False, False, 0) - else: - vbox3.pack_start(hbox, False, False, 0) - if True: #line[0] == 'ring': - if line[1] == 'fl': - name = str(line[2]) - self.found['fl'] = True - elif line[1] == 'pl': - name = str(line[2])+line[1] - self.found['pl'] = True - else: - name = str(line[2])+line[1] - self.found['nl'] = True - self.cbLimits[name] = self.createLimitLine(hbox, name, name) - self.types[name] = line[0] - self.found[line[0]] = True # type is ring/tour - self.type = line[0] # if only one type, set it now - if "LimitSep" in display and display["LimitSep"] == True and len(result) >= 2: - hbox = gtk.HBox(True, 0) - vbox1.pack_start(hbox, False, False, 0) - vbox2 = gtk.VBox(False, 0) - hbox.pack_start(vbox2, False, False, 0) - vbox3 = gtk.VBox(False, 0) - hbox.pack_start(vbox3, False, False, 0) - - hbox = gtk.HBox(False, 0) - vbox2.pack_start(hbox, False, False, 0) - self.cbAllLimits = self.createLimitLine(hbox, 'all', self.filterText['limitsall']) - hbox = gtk.HBox(False, 0) - vbox2.pack_start(hbox, False, False, 0) - self.cbNoLimits = self.createLimitLine(hbox, 'none', self.filterText['limitsnone']) - - dest = vbox3 # for ring/tour buttons - if "LimitType" in display and display["LimitType"] == True: - num_limit_types = 0 - if self.found['fl']: num_limit_types = num_limit_types + 1 - if self.found['pl']: num_limit_types = num_limit_types + 1 - if self.found['nl']: num_limit_types = num_limit_types + 1 - if num_limit_types > 1: - if self.found['fl']: - hbox = gtk.HBox(False, 0) - vbox3.pack_start(hbox, False, False, 0) - self.cbFL = self.createLimitLine(hbox, 'fl', self.filterText['limitsFL']) - if self.found['nl']: - hbox = gtk.HBox(False, 0) - vbox3.pack_start(hbox, False, False, 0) - self.cbNL = self.createLimitLine(hbox, 'nl', self.filterText['limitsNL']) - if self.found['pl']: - hbox = gtk.HBox(False, 0) - vbox3.pack_start(hbox, False, False, 0) - self.cbPL = self.createLimitLine(hbox, 'pl', self.filterText['limitsPL']) - dest = vbox2 # for ring/tour buttons - else: - print "INFO: No games returned from database" - log.info("No games returned from database") - - if "Type" in display and display["Type"] == True and self.found['ring'] and self.found['tour']: - rb1 = gtk.RadioButton(None, self.filterText['ring']) - rb1.connect('clicked', self.__set_limit_select, 'ring') - rb2 = gtk.RadioButton(rb1, self.filterText['tour']) - rb2.connect('clicked', self.__set_limit_select, 'tour') - top_hbox.pack_start(rb1, False, False, 0) # (child, expand, fill, padding) - top_hbox.pack_start(rb2, True, True, 0) # child uses expand space if fill is true - - self.rb['ring'] = rb1 - self.rb['tour'] = rb2 - #print "about to set ring to true" - rb1.set_active(True) - # set_active doesn't seem to call this for some reason so call manually: - self.__set_limit_select(rb1, 'ring') - self.type = 'ring' - top_hbox.pack_start(showb, expand=False, padding=1) - - def fillSeatsFrame(self, vbox, display): - hbox = gtk.HBox(False, 0) - vbox.pack_start(hbox, False, False, 0) - lbl_title = gtk.Label(self.filterText['seatstitle']) - lbl_title.set_alignment(xalign=0.0, yalign=0.5) - hbox.pack_start(lbl_title, expand=True, padding=3) - showb = gtk.Button(label="hide", stock=None, use_underline=True) - showb.set_alignment(xalign=1.0, yalign=0.5) - showb.connect('clicked', self.__toggle_box, 'seats') - hbox.pack_start(showb, expand=False, padding=1) - - vbox1 = gtk.VBox(False, 0) - vbox.pack_start(vbox1, False, False, 0) - self.boxes['seats'] = vbox1 - - hbox = gtk.HBox(False, 0) - vbox1.pack_start(hbox, False, True, 0) - - lbl_from = gtk.Label(self.filterText['seatsbetween']) - lbl_to = gtk.Label(self.filterText['seatsand']) - adj1 = gtk.Adjustment(value=2, lower=2, upper=10, step_incr=1, page_incr=1, page_size=0) - sb1 = gtk.SpinButton(adjustment=adj1, climb_rate=0.0, digits=0) - adj2 = gtk.Adjustment(value=10, lower=2, upper=10, step_incr=1, page_incr=1, page_size=0) - sb2 = gtk.SpinButton(adjustment=adj2, climb_rate=0.0, digits=0) - - hbox.pack_start(lbl_from, expand=False, padding=3) - hbox.pack_start(sb1, False, False, 0) - hbox.pack_start(lbl_to, expand=False, padding=3) - hbox.pack_start(sb2, False, False, 0) - - self.sbSeats['from'] = sb1 - self.sbSeats['to'] = sb2 - #end def fillSeatsFrame - - def fillGroupsFrame(self, vbox, display): - hbox = gtk.HBox(False, 0) - vbox.pack_start(hbox, False, False, 0) - lbl_title = gtk.Label(self.filterText['groupstitle']) - lbl_title.set_alignment(xalign=0.0, yalign=0.5) - hbox.pack_start(lbl_title, expand=True, padding=3) - showb = gtk.Button(label="hide", stock=None, use_underline=True) - showb.set_alignment(xalign=1.0, yalign=0.5) - showb.connect('clicked', self.__toggle_box, 'groups') - hbox.pack_start(showb, expand=False, padding=1) - - vbox1 = gtk.VBox(False, 0) - vbox.pack_start(vbox1, False, False, 0) - self.boxes['groups'] = vbox1 - - hbox = gtk.HBox(False, 0) - vbox1.pack_start(hbox, False, False, 0) - cb = self.createLimitLine(hbox, 'show', self.filterText['limitsshow']) - - hbox = gtk.HBox(False, 0) - vbox1.pack_start(hbox, False, True, 0) - cb = gtk.CheckButton(self.filterText['posnshow']) - cb.connect('clicked', self.__set_group_select, 'posn') - hbox.pack_start(cb, False, False, 0) - self.sbGroups['posn'] = cb - self.groups['posn'] = False - - if "SeatSep" in display and display["SeatSep"] == True: - hbox = gtk.HBox(False, 0) - vbox1.pack_start(hbox, False, True, 0) - cb = gtk.CheckButton(self.filterText['seatsshow']) - cb.connect('clicked', self.__set_seat_select, 'show') - hbox.pack_start(cb, False, False, 0) - self.sbSeats['show'] = cb - self.seats['show'] = False - - def fillCardsFrame(self, vbox): - hbox1 = gtk.HBox(True,0) - hbox1.show() - vbox.pack_start(hbox1, True, True, 0) - - cards = [ "A", "K","Q","J","T","9","8","7","6","5","4","3","2" ] - - for j in range(0, len(cards)): - hbox1 = gtk.HBox(True,0) - hbox1.show() - vbox.pack_start(hbox1, True, True, 0) - for i in range(0, len(cards)): - if i < (j + 1): - suit = "o" - else: - suit = "s" - button = gtk.ToggleButton("%s%s%s" %(cards[i], cards[j], suit)) - button.connect("toggled", self.cardCallback, "%s%s%s" %(cards[i], cards[j], suit)) - hbox1.pack_start(button, True, True, 0) - button.show() - - def fillDateFrame(self, vbox): - # Hat tip to Mika Bostrom - calendar code comes from PokerStats - top_hbox = gtk.HBox(False, 0) - vbox.pack_start(top_hbox, False, False, 0) - lbl_title = gtk.Label(self.filterText['datestitle']) - lbl_title.set_alignment(xalign=0.0, yalign=0.5) - top_hbox.pack_start(lbl_title, expand=True, padding=3) - showb = gtk.Button(label="hide", stock=None, use_underline=True) - showb.set_alignment(xalign=1.0, yalign=0.5) - showb.connect('clicked', self.__toggle_box, 'dates') - top_hbox.pack_start(showb, expand=False, padding=1) - - vbox1 = gtk.VBox(False, 0) - vbox.pack_start(vbox1, False, False, 0) - self.boxes['dates'] = vbox1 - - hbox = gtk.HBox() - vbox1.pack_start(hbox, False, True, 0) - - lbl_start = gtk.Label('From:') - - btn_start = gtk.Button() - btn_start.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)) - btn_start.connect('clicked', self.__calendar_dialog, self.start_date) - - hbox.pack_start(lbl_start, expand=False, padding=3) - hbox.pack_start(btn_start, expand=False, padding=3) - hbox.pack_start(self.start_date, expand=False, padding=2) - - #New row for end date - hbox = gtk.HBox() - vbox1.pack_start(hbox, False, True, 0) - - lbl_end = gtk.Label(' To:') - btn_end = gtk.Button() - btn_end.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)) - btn_end.connect('clicked', self.__calendar_dialog, self.end_date) - - btn_clear = gtk.Button(label=' Clear Dates ') - btn_clear.connect('clicked', self.__clear_dates) - - hbox.pack_start(lbl_end, expand=False, padding=3) - hbox.pack_start(btn_end, expand=False, padding=3) - hbox.pack_start(self.end_date, expand=False, padding=2) - - hbox.pack_start(btn_clear, expand=False, padding=15) - #end def fillDateFrame - - def __refresh(self, widget, entry): - for w in self.mainVBox.get_children(): - w.destroy() - self.make_filter() - - def __toggle_box(self, widget, entry): - if self.boxes[entry].props.visible: - self.boxes[entry].hide() - widget.set_label("show") - else: - self.boxes[entry].show() - widget.set_label("hide") - #end def __toggle_box - - def __calendar_dialog(self, widget, entry): - d = gtk.Window(gtk.WINDOW_TOPLEVEL) - d.set_title('Pick a date') - - vb = gtk.VBox() - cal = gtk.Calendar() - vb.pack_start(cal, expand=False, padding=0) - - btn = gtk.Button('Done') - btn.connect('clicked', self.__get_date, cal, entry, d) - - vb.pack_start(btn, expand=False, padding=4) - - d.add(vb) - d.set_position(gtk.WIN_POS_MOUSE) - d.show_all() - #end def __calendar_dialog - - def __clear_dates(self, w): - self.start_date.set_text('') - self.end_date.set_text('') - #end def __clear_dates - - def __get_dates(self): - # self.day_start gives user's start of day in hours - offset = int(self.day_start * 3600) # calc day_start in seconds - - t1 = self.start_date.get_text() - t2 = self.end_date.get_text() - - if t1 == '': - t1 = '1970-01-02' - if t2 == '': - t2 = '2020-12-12' - - s1 = strptime(t1, "%Y-%m-%d") # make time_struct - s2 = strptime(t2, "%Y-%m-%d") - e1 = mktime(s1) + offset # s1 is localtime, but returned time since epoch is UTC, then add the - e2 = mktime(s2) + offset # s2 is localtime, but returned time since epoch is UTC - e2 = e2 + 24 * 3600 - 1 # date test is inclusive, so add 23h 59m 59s to e2 - - adj_t1 = strftime("%Y-%m-%d %H:%M:%S", gmtime(e1)) # make adjusted string including time - adj_t2 = strftime("%Y-%m-%d %H:%M:%S", gmtime(e2)) - log.info("t1="+t1+" adj_t1="+adj_t1+'.') - - return (adj_t1, adj_t2) - #end def __get_dates - - def __get_date(self, widget, calendar, entry, win): - # year and day are correct, month is 0..11 - (year, month, day) = calendar.get_date() - month += 1 - ds = '%04d-%02d-%02d' % (year, month, day) - entry.set_text(ds) - win.destroy() - -def main(argv=None): - """main can also be called in the python interpreter, by supplying the command line as the argument.""" - if argv is None: - argv = sys.argv[1:] - - def destroy(*args): # call back for terminating the main eventloop - gtk.main_quit() - - parser = OptionParser() - (options, argv) = parser.parse_args(args = argv) - - config = Configuration.Config() - db = None - - db = Database.Database() - db.do_connect(config) - - qdict = SQL.SQL(db.get_backend_name()) - - i = Filters(db, config, qdict) - main_window = gtk.Window() - main_window.connect('destroy', destroy) - main_window.add(i.get_vbox()) - main_window.show() - gtk.main() - -if __name__ == '__main__': - sys.exit(main()) From a463d82f5ba2cf71d741f98d226bc6ffa972bc68 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Sat, 17 Jul 2010 03:48:21 +0200 Subject: [PATCH 54/63] IMAP: add two more fields to config --- pyfpdb/Configuration.py | 2 ++ pyfpdb/HUD_config.xml.example | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index faeb5e23..b5e3e76f 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -442,6 +442,8 @@ class Email: self.password = node.getAttribute("password") self.useSsl = node.getAttribute("useSsl") self.folder = node.getAttribute("folder") + self.siteName = node.getAttribute("siteName") + self.fetchType = node.getAttribute("fetchType") def __str__(self): return " host = %s\n username = %s\n password = %s\n useSsl = %s\n folder = %s\n" \ diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index c1d1f644..9ee17c1c 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -645,7 +645,7 @@ Left-Drag to Move" - +