From 72730291f01967118bdcfde7146e890e5de481e8 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Sat, 27 Feb 2010 09:35:18 +0200 Subject: [PATCH 01/30] Fix HUD-cache updates on Postgres The value in pdata[p]['position'] is a string. Change the 'pos' dictionary keys to strings, and to prevent potential breakage on other databases, always enforce that the looked up key is first converted to string. --- pyfpdb/Database.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 0303aad2..069789f3 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1703,8 +1703,8 @@ class Database: line[55] = gid # gametypeId line[56] = pids[p] # playerId line[57] = len(pids) # activeSeats - pos = {'B':'B', 'S':'S', 0:'D', 1:'C', 2:'M', 3:'M', 4:'M', 5:'E', 6:'E', 7:'E', 8:'E', 9:'E' } - line[58] = pos[pdata[p]['position']] + pos = {'B':'B', 'S':'S', '0':'D', '1':'C', '2':'M', '3':'M', '4':'M', '5':'E', '6':'E', '7':'E', '8':'E', '9':'E' } + line[58] = pos[str(pdata[p]['position'])] line[59] = pdata[p]['tourneyTypeId'] line[60] = styleKey # styleKey inserts.append(line) From 4042fc6c40b9cd4f03f0be9ae9e854662ba114f1 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Sat, 27 Feb 2010 17:41:52 +0200 Subject: [PATCH 02/30] Use sqlcoder's fix for position map The values for pdata[p]['position'] come from DerivedStats.py, where the value was explicitly cast to a string. This way it should work again and use the cleaner code from sqlcoder instead. --- pyfpdb/Database.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index f24a7c33..d0fe733b 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1713,8 +1713,8 @@ class Database: line[55] = gid # gametypeId line[56] = pids[p] # playerId line[57] = len(pids) # activeSeats - pos = {'B':'B', 'S':'S', '0':'D', '1':'C', '2':'M', '3':'M', '4':'M', '5':'E', '6':'E', '7':'E', '8':'E', '9':'E' } - line[58] = pos[str(pdata[p]['position'])] + pos = {'B':'B', 'S':'S', 0:'D', 1:'C', 2:'M', 3:'M', 4:'M', 5:'E', 6:'E', 7:'E', 8:'E', 9:'E' } + line[58] = pos[pdata[p]['position']] line[59] = pdata[p]['tourneyTypeId'] line[60] = styleKey # styleKey inserts.append(line) From dcbb90def66c59daa10631e0a0e74949689968fa Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Fri, 5 Mar 2010 08:39:54 +0200 Subject: [PATCH 03/30] Update changelog and bump version --- packaging/debian/changelog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packaging/debian/changelog b/packaging/debian/changelog index 4bacf635..ebd45a53 100644 --- a/packaging/debian/changelog +++ b/packaging/debian/changelog @@ -1,3 +1,10 @@ +free-poker-tools (0.20~git20100305) unstable; urgency=low + + * New snapshot + * Version bumped to 0.20 + + -- Mika Bostrom Fri, 05 Mar 2010 08:38:52 +0200 + free-poker-tools (0.12~git20100122) unstable; urgency=low * New snapshot release with reworked import code From 6ba7621f2a4a8eb934f02908c8afeef6d6533a88 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 23 Apr 2010 00:28:30 +0800 Subject: [PATCH 04/30] Fix 'errors' stat in importer Instead of: GuiBulkImport done: Stored: 32 Duplicates: 0 Partial: 0 Errors: 32 in 0.530081987381 seconds - 0/sec We have: GuiBulkImport done: Stored: 0 Duplicates: 0 Partial: 0 Errors: 32 in 0.530081987381 seconds - 0/sec --- pyfpdb/fpdb_import.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 689858e0..56c59b77 100755 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -468,6 +468,7 @@ class Importer: errors = getattr(hhc, 'numErrors') stored = getattr(hhc, 'numHands') stored -= duplicates + stored -= errors else: # conversion didn't work # TODO: appropriate response? From 3dd5f92a3c115f9761e6c51ae78bcb32dcd6d00b Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 23 Apr 2010 00:33:24 +0800 Subject: [PATCH 05/30] Add logging for two areas, fix RAZZ v Razz issue Add ERROR conditions for determineGameType failing, and raise a FpdbParseError in each case --- pyfpdb/PokerStarsToFpdb.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 801f17d6..24cf3bb7 100644 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -135,8 +135,10 @@ class PokerStars(HandHistoryConverter): info = {} m = self.re_GameInfo.search(handText) if not m: - print "DEBUG: determineGameType(): did not match" - return None + tmp = handText[0:100] + log.error("determineGameType: Unable to recognise gametype from: '%s'" % tmp) + log.error("determineGameType: Raising FpdbParseError") + raise FpdbParseError mg = m.groupdict() # translations from captured groups to fpdb info strings @@ -154,7 +156,7 @@ class PokerStars(HandHistoryConverter): 'Omaha' : ('hold','omahahi'), 'Omaha Hi/Lo' : ('hold','omahahilo'), 'Razz' : ('stud','razz'), - 'RAZZ' : ('stud','razz'), + 'RAZZ' : ('stud','razz'), '7 Card Stud' : ('stud','studhi'), '7 Card Stud Hi/Lo' : ('stud','studhilo'), 'Badugi' : ('draw','badugi'), @@ -183,8 +185,13 @@ class PokerStars(HandHistoryConverter): info['type'] = 'tour' if info['limitType'] == 'fl' and info['bb'] is not None and info['type'] == 'ring' and info['base'] != 'stud': - info['sb'] = Lim_Blinds[mg['BB']][0] - info['bb'] = Lim_Blinds[mg['BB']][1] + try: + info['sb'] = Lim_Blinds[mg['BB']][0] + info['bb'] = Lim_Blinds[mg['BB']][1] + except KeyError: + log.error("determineGameType: Lim_Blinds has no lookup for '%s'" % mg['BB']) + log.error("determineGameType: Raising FpdbParseError") + raise FpdbParseError # NB: SB, BB must be interpreted as blinds or bets depending on limit type. return info From 5aadf643be07b1fc12887181a0128265508e91d9 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 23 Apr 2010 00:36:12 +0800 Subject: [PATCH 06/30] Add '2' to the Lim_Blinds lookup table Fixes Dogs import issue. --- pyfpdb/PokerStarsToFpdb.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 24cf3bb7..75cf3cbb 100644 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -144,6 +144,7 @@ class PokerStars(HandHistoryConverter): # translations from captured groups to fpdb info strings Lim_Blinds = { '0.04': ('0.01', '0.02'), '0.10': ('0.02', '0.05'), '0.20': ('0.05', '0.10'), '0.50': ('0.10', '0.25'), '1.00': ('0.25', '0.50'), '2.00': ('0.50', '1.00'), + '2': ('0.50', '1.00'), '4.00': ('1.00', '2.00'), '6.00': ('1.00', '3.00'), '10.00': ('2.00', '5.00'), '20.00': ('5.00', '10.00'), '30.00': ('10.00', '15.00'), '60.00': ('15.00', '30.00'), '100.00': ('25.00', '50.00'),'200.00': ('50.00', '100.00'),'400.00': ('100.00', '200.00'), From c0ebc4b7cf4a039418e9eb0f5e6425312d1e3886 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 22 Apr 2010 23:22:28 +0800 Subject: [PATCH 07/30] Update to Session viewer Fix a couple of crashers - Make sure last session in list is displayed correctly - Actually calculate hands/hour (Thanks Socratic) - Make graph display the correct number of sessions --- pyfpdb/GuiSessionViewer.py | 62 +++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/pyfpdb/GuiSessionViewer.py b/pyfpdb/GuiSessionViewer.py index b5ca0867..d11f83d8 100755 --- a/pyfpdb/GuiSessionViewer.py +++ b/pyfpdb/GuiSessionViewer.py @@ -184,7 +184,7 @@ class GuiSessionViewer (threading.Thread): sitenos.append(siteids[site]) _q = self.sql.query['getPlayerId'] _name = Charset.to_utf8(heroes[site]) - print 'DEBUG(_name) :: %s' % _name + #print 'DEBUG(_name) :: %s' % _name self.cursor.execute(_q, (_name,)) # arg = tuple result = self.db.cursor.fetchall() if len(result) == 1: @@ -262,13 +262,20 @@ class GuiSessionViewer (threading.Thread): times = map(lambda x:long(x[0]), hands) handids = map(lambda x:int(x[1]), hands) winnings = map(lambda x:float(x[4]), hands) - print "DEBUG: len(times) %s" %(len(times)) + #print "DEBUG: len(times) %s" %(len(times)) diffs = diff(times) # This array is the difference in starttime between consecutive hands index = nonzero(diff(times) > THRESHOLD) # This array represents the indexes into 'times' for start/end times of sessions # ie. times[index[0][0]] is the end of the first session #print "DEBUG: len(index[0]) %s" %(len(index[0])) - #print "DEBUG: index %s" %(index) - #print "DEBUG: index[0][0] %s" %(index[0][0]) + if len(index[0]) > 0: + #print "DEBUG: index[0][0] %s" %(index[0][0]) + #print "DEBUG: index %s" %(index) + pass + else: + index = [[0]] + #print "DEBUG: index %s" %(index) + #print "DEBUG: index[0][0] %s" %(index[0][0]) + pass total = 0 last_idx = 0 @@ -281,27 +288,57 @@ class GuiSessionViewer (threading.Thread): results = [] cum_sum = cumsum(winnings) cum_sum = cum_sum/100 + sid = 0 # Take all results and format them into a list for feeding into gui model. for i in range(len(index[0])): - sid = i # Session id hds = index[0][i] - last_idx # Number of hands in session if hds > 0: stime = strftime("%d/%m/%Y %H:%M", localtime(times[last_idx])) # Formatted start time etime = strftime("%d/%m/%Y %H:%M", localtime(times[index[0][i]])) # Formatted end time - hph = (times[index[0][i]] - times[last_idx])/60 # Hands per hour + minutesplayed = (times[index[0][i]] - times[last_idx])/60 + if minutesplayed == 0: + minutesplayed = 1 + hph = hds*60/minutesplayed # Hands per hour won = sum(winnings[last_idx:index[0][i]])/100.0 hwm = max(cum_sum[last_idx:index[0][i]]) lwm = min(cum_sum[last_idx:index[0][i]]) - #print "DEBUG: range: (%s, %s) - (min, max): (%s, %s)" %(last_idx, index[0][i], hwm, lwm) + open = (sum(winnings[:last_idx]))/100 + close = (sum(winnings[:index[0][i]]))/100 + #print "DEBUG: range: (%s, %s) - (min, max): (%s, %s) - (open,close): (%s, %s)" %(last_idx, index[0][i], lwm, hwm, open, close) results.append([sid, hds, stime, etime, hph, won]) - opens.append((sum(winnings[:last_idx]))/100) - closes.append((sum(winnings[:index[0][i]]))/100) + opens.append(open) + closes.append(close) highs.append(hwm) lows.append(lwm) - #print "Hands in session %4s: %4s Start: %s End: %s HPH: %s Profit: %s" %(sid, hds, stime, etime, hph, won) + #print "DEBUG: Hands in session %4s: %4s Start: %s End: %s HPH: %s Profit: %s" %(sid, hds, stime, etime, hph, won) total = total + (index[0][i] - last_idx) last_idx = index[0][i] + 1 + sid = sid+1 + else: + print "hds <= 0" + + #The last session is between times[last_idx:-1] + hds = len(times) - last_idx + stime = strftime("%d/%m/%Y %H:%M", localtime(times[last_idx])) # Formatted start time + etime = strftime("%d/%m/%Y %H:%M", localtime(times[index[0][-1]])) # Formatted end time + minutesplayed = (times[-1] - times[last_idx])/60 + if minutesplayed == 0: + minutesplayed = 1 + hph = hds*60/minutesplayed # Hands per hour + won = sum(winnings[last_idx:-1])/100.0 + hwm = max(cum_sum[last_idx:-1]) + lwm = min(cum_sum[last_idx:-1]) + open = (sum(winnings[:last_idx]))/100 + close = (sum(winnings[:-1]))/100 + #print "DEBUG: range: (%s, %s) - (min, max): (%s, %s) - (open,close): (%s, %s)" %(last_idx, index[0][i], lwm, hwm, open, close) + + results.append([sid, hds, stime, etime, hph, won]) + opens.append(open) + closes.append(close) + highs.append(hwm) + lows.append(lwm) + #print "Hands in session %4s: %4s Start: %s End: %s HPH: %s Profit: %s" %(sid, hds, stime, etime, hph, won) return (results, opens, closes, highs, lows) @@ -330,11 +367,6 @@ class GuiSessionViewer (threading.Thread): def generateGraph(self, opens, closes, highs, lows): self.clearGraphData() - #FIXME: Weird - first data entry is crashing this for me - opens = opens[1:] - closes = closes[1:] - highs = highs[1:] - lows = lows[1:] # print "DEBUG:" # print "highs = %s" % highs # print "lows = %s" % lows From d11623c7364b8b7ed06cfd0e1b790093668ebcc0 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 23 Apr 2010 11:39:52 +0800 Subject: [PATCH 08/30] Update Session viewer based on Socratic comments --- pyfpdb/GuiSessionViewer.py | 61 ++++++++++++++------------------------ 1 file changed, 22 insertions(+), 39 deletions(-) diff --git a/pyfpdb/GuiSessionViewer.py b/pyfpdb/GuiSessionViewer.py index d11f83d8..b4f14d95 100755 --- a/pyfpdb/GuiSessionViewer.py +++ b/pyfpdb/GuiSessionViewer.py @@ -33,7 +33,7 @@ try: from matplotlib.backends.backend_gtkagg import NavigationToolbar2GTKAgg as NavigationToolbar from matplotlib.finance import candlestick2 - from numpy import diff, nonzero, sum, cumsum, max, min + from numpy import diff, nonzero, sum, cumsum, max, min, append # from matplotlib.dates import DateFormatter, WeekdayLocator, HourLocator, \ # DayLocator, MONDAY, timezone @@ -241,6 +241,9 @@ class GuiSessionViewer (threading.Thread): #end def fillStatsFrame(self, vbox): def generateDatasets(self, playerids, sitenos, limits, seats): + THRESHOLD = 1800 # Minimum number of seconds between consecutive hands before being considered a new session + PADDING = 5 # Additional time in minutes to add to a session, session startup, shutdown etc (FiXME: user configurable) + # Get a list of all handids and their timestampts #FIXME: Query still need to filter on blind levels @@ -255,7 +258,6 @@ class GuiSessionViewer (threading.Thread): q = q.replace("", "%s") self.db.cursor.execute(q) - THRESHOLD = 1800 hands = self.db.cursor.fetchall() # Take that list and create an array of the time between hands @@ -263,9 +265,11 @@ class GuiSessionViewer (threading.Thread): handids = map(lambda x:int(x[1]), hands) winnings = map(lambda x:float(x[4]), hands) #print "DEBUG: len(times) %s" %(len(times)) - diffs = diff(times) # This array is the difference in starttime between consecutive hands - index = nonzero(diff(times) > THRESHOLD) # This array represents the indexes into 'times' for start/end times of sessions - # ie. times[index[0][0]] is the end of the first session + diffs = diff(times) # This array is the difference in starttime between consecutive hands + diffs2 = append(diffs,THRESHOLD + 1) # Append an additional session to the end of the diffs, so the next line + # includes an index into the last 'session' + index = nonzero(diffs2 > THRESHOLD) # This array represents the indexes into 'times' for start/end times of sessions + # times[index[0][0]] is the end of the first session, #print "DEBUG: len(index[0]) %s" %(len(index[0])) if len(index[0]) > 0: #print "DEBUG: index[0][0] %s" %(index[0][0]) @@ -278,7 +282,7 @@ class GuiSessionViewer (threading.Thread): pass total = 0 - last_idx = 0 + first_idx = 0 lowidx = 0 uppidx = 0 opens = [] @@ -288,23 +292,24 @@ class GuiSessionViewer (threading.Thread): results = [] cum_sum = cumsum(winnings) cum_sum = cum_sum/100 - sid = 0 + sid = 1 # Take all results and format them into a list for feeding into gui model. for i in range(len(index[0])): - hds = index[0][i] - last_idx # Number of hands in session + hds = index[0][i] - first_idx + 1 # Number of hands in session if hds > 0: - stime = strftime("%d/%m/%Y %H:%M", localtime(times[last_idx])) # Formatted start time + stime = strftime("%d/%m/%Y %H:%M", localtime(times[first_idx])) # Formatted start time etime = strftime("%d/%m/%Y %H:%M", localtime(times[index[0][i]])) # Formatted end time - minutesplayed = (times[index[0][i]] - times[last_idx])/60 + minutesplayed = (times[index[0][i]] - times[first_idx])/60 if minutesplayed == 0: minutesplayed = 1 + minutesplayed = minutesplayed + PADDING hph = hds*60/minutesplayed # Hands per hour - won = sum(winnings[last_idx:index[0][i]])/100.0 - hwm = max(cum_sum[last_idx:index[0][i]]) - lwm = min(cum_sum[last_idx:index[0][i]]) - open = (sum(winnings[:last_idx]))/100 + won = sum(winnings[first_idx:index[0][i]])/100.0 + hwm = max(cum_sum[first_idx:index[0][i]]) + lwm = min(cum_sum[first_idx:index[0][i]]) + open = (sum(winnings[:first_idx]))/100 close = (sum(winnings[:index[0][i]]))/100 - #print "DEBUG: range: (%s, %s) - (min, max): (%s, %s) - (open,close): (%s, %s)" %(last_idx, index[0][i], lwm, hwm, open, close) + #print "DEBUG: range: (%s, %s) - (min, max): (%s, %s) - (open,close): (%s, %s)" %(first_idx, index[0][i], lwm, hwm, open, close) results.append([sid, hds, stime, etime, hph, won]) opens.append(open) @@ -312,34 +317,12 @@ class GuiSessionViewer (threading.Thread): highs.append(hwm) lows.append(lwm) #print "DEBUG: Hands in session %4s: %4s Start: %s End: %s HPH: %s Profit: %s" %(sid, hds, stime, etime, hph, won) - total = total + (index[0][i] - last_idx) - last_idx = index[0][i] + 1 + total = total + (index[0][i] - first_idx) + first_idx = index[0][i] + 1 sid = sid+1 else: print "hds <= 0" - #The last session is between times[last_idx:-1] - hds = len(times) - last_idx - stime = strftime("%d/%m/%Y %H:%M", localtime(times[last_idx])) # Formatted start time - etime = strftime("%d/%m/%Y %H:%M", localtime(times[index[0][-1]])) # Formatted end time - minutesplayed = (times[-1] - times[last_idx])/60 - if minutesplayed == 0: - minutesplayed = 1 - hph = hds*60/minutesplayed # Hands per hour - won = sum(winnings[last_idx:-1])/100.0 - hwm = max(cum_sum[last_idx:-1]) - lwm = min(cum_sum[last_idx:-1]) - open = (sum(winnings[:last_idx]))/100 - close = (sum(winnings[:-1]))/100 - #print "DEBUG: range: (%s, %s) - (min, max): (%s, %s) - (open,close): (%s, %s)" %(last_idx, index[0][i], lwm, hwm, open, close) - - results.append([sid, hds, stime, etime, hph, won]) - opens.append(open) - closes.append(close) - highs.append(hwm) - lows.append(lwm) - #print "Hands in session %4s: %4s Start: %s End: %s HPH: %s Profit: %s" %(sid, hds, stime, etime, hph, won) - return (results, opens, closes, highs, lows) def clearGraphData(self): From c871d7fc2fbe15bb7347be6bf685fab96b54ba46 Mon Sep 17 00:00:00 2001 From: gimick Date: Thu, 15 Apr 2010 23:16:26 +0100 Subject: [PATCH 09/30] gimick - Do not set CBChance if there has been a donkbet --- pyfpdb/DerivedStats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 4e55cdfc..f5278b99 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -368,8 +368,8 @@ class DerivedStats(): name = self.lastBetOrRaiser(hand.actionStreets[i+1]) if name: chance = self.noBetsBefore(hand.actionStreets[i+2], name) - self.handsplayers[name]['street%dCBChance' % (i+1)] = True if chance == True: + self.handsplayers[name]['street%dCBChance' % (i+1)] = True self.handsplayers[name]['street%dCBDone' % (i+1)] = self.betStreet(hand.actionStreets[i+2], name) def calcCheckCallRaise(self, hand): From 6e603149267822b07259d84ffa6c52c0590c8e53 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 23 Apr 2010 11:49:57 +0800 Subject: [PATCH 10/30] First part of making FTP archive files work --- pyfpdb/HandHistoryConverter.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 2053eba9..5b65b955 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -62,7 +62,7 @@ class HandHistoryConverter(): codepage = "cp1252" - def __init__(self, config, in_path = '-', out_path = '-', follow=False, index=0, autostart=True, starsArchive=False): + def __init__(self, config, in_path = '-', out_path = '-', follow=False, index=0, autostart=True, starsArchive=False, ftpArchive=False): """\ in_path (default '-' = sys.stdin) out_path (default '-' = sys.stdout) @@ -75,6 +75,7 @@ follow : whether to tail -f the input""" self.index = index self.starsArchive = starsArchive + self.ftpArchive = ftpArchive self.in_path = in_path self.out_path = out_path @@ -247,6 +248,11 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py. m = re.compile('^Hand #\d+', re.MULTILINE) self.obs = m.sub('', self.obs) + if self.ftpArchive == True: + log.debug("Converting ftpArchive format to readable") + m = re.compile('^\*\*\*\*\*\*+\s#\s\d+\s\*\*\*\*\*+$', re.MULTILINE) + self.obs = m.sub('', self.obs) + if self.obs is None or self.obs == "": log.info("Read no hands.") return [] From 9ac46c8c92c1c135e9741bc8812d39f0dd51eb52 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 23 Apr 2010 17:09:08 +0800 Subject: [PATCH 11/30] Add to Stars limit lookup table. --- pyfpdb/PokerStarsToFpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 75cf3cbb..c964faa5 100644 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -144,7 +144,7 @@ class PokerStars(HandHistoryConverter): # translations from captured groups to fpdb info strings Lim_Blinds = { '0.04': ('0.01', '0.02'), '0.10': ('0.02', '0.05'), '0.20': ('0.05', '0.10'), '0.50': ('0.10', '0.25'), '1.00': ('0.25', '0.50'), '2.00': ('0.50', '1.00'), - '2': ('0.50', '1.00'), + '2': ('0.50', '1.00'), '4': ('1.00', '2.00'), '6': ('1.00', '3.00'), '4.00': ('1.00', '2.00'), '6.00': ('1.00', '3.00'), '10.00': ('2.00', '5.00'), '20.00': ('5.00', '10.00'), '30.00': ('10.00', '15.00'), '60.00': ('15.00', '30.00'), '100.00': ('25.00', '50.00'),'200.00': ('50.00', '100.00'),'400.00': ('100.00', '200.00'), From 2503cd1b6c461f4ad6bbbe8e86175ce41403e0d3 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Thu, 13 May 2010 06:57:59 +0300 Subject: [PATCH 12/30] Fix what looks like a thinko The stat 'fold_f' probably should do a "float(foo)/float(bar)" division because there is no function called "fold" --- pyfpdb/Stats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Stats.py b/pyfpdb/Stats.py index 47d8b9f1..264ebd18 100755 --- a/pyfpdb/Stats.py +++ b/pyfpdb/Stats.py @@ -277,7 +277,7 @@ def fold_f(stat_dict, player): """ Folded flop/4th.""" stat = 0.0 try: - stat = float(stat_dict[player]['fold_2'])/fold(stat_dict[player]['saw_f']) + stat = float(stat_dict[player]['fold_2'])/float(stat_dict[player]['saw_f']) return (stat, '%3.1f' % (100*stat) + '%', 'ff=%3.1f' % (100*stat) + '%', From c52767ea4171c7b88eba258e91b271845573e868 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Fri, 28 May 2010 02:31:04 +0200 Subject: [PATCH 13/30] it now records and displays fold stats (not too thoroughly tested) --- pyfpdb/DerivedStats.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index f5278b99..a951d0b7 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -146,6 +146,8 @@ class DerivedStats(): self.aggr(self.hand, i) self.calls(self.hand, i) self.bets(self.hand, i) + if i>0: + self.folds(self.hand, i) # Winnings is a non-negative value of money collected from the pot, which already includes the # rake taken out. hand.collectees is Decimal, database requires cents @@ -408,10 +410,16 @@ class DerivedStats(): def aggr(self, hand, i): aggrers = set() + others = set() # Growl - actionStreets contains 'BLINDSANTES', which isn't actually an action street + + firstAggrMade=False for act in hand.actions[hand.actionStreets[i+1]]: + if firstAggrMade: + others.add(act[0]) if act[1] in ('completes', 'bets', 'raises'): aggrers.add(act[0]) + firstAggrMade=True for player in hand.players: #print "DEBUG: actionStreet[%s]: %s" %(hand.actionStreets[i+1], i) @@ -419,6 +427,11 @@ class DerivedStats(): self.handsplayers[player[1]]['street%sAggr' % i] = True else: self.handsplayers[player[1]]['street%sAggr' % i] = False + + if len(aggrers)>0 and i>0: + for playername in others: + self.handsplayers[playername]['otherRaisedStreet%s' % i] = True + #print "otherRaised detected on handid "+str(hand.handid)+" for "+playername+" on street "+str(i) def calls(self, hand, i): callers = [] @@ -429,11 +442,18 @@ class DerivedStats(): # CG - I'm sure this stat is wrong # Best guess is that raise = 2 bets def bets(self, hand, i): - betters = [] for act in hand.actions[hand.actionStreets[i+1]]: if act[1] in ('bets'): self.handsplayers[act[0]]['street%sBets' % i] = 1 + self.handsplayers[act[0]]['street%sBets' % i] + + def folds(self, hand, i): + for act in hand.actions[hand.actionStreets[i+1]]: + if act[1] in ('folds'): + if self.handsplayers[act[0]]['otherRaisedStreet%s' % i] == True: + self.handsplayers[act[0]]['foldToOtherRaisedStreet%s' % i] = True + #print "fold detected on handid "+str(hand.handid)+" for "+act[0]+" on street "+str(i) + def countPlayers(self, hand): pass From 994f0fdcccb28200f7b6b185d70f57005ed73ae6 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 4 Jun 2010 03:02:07 +0800 Subject: [PATCH 14/30] Modify recent patch from Steffen adding fold stats - Remove added whitespace - Reformatted debug strings in preferred printf style (and starting with DEBUG:) - Swapped len(aggrers)>0 and i>0 for short circuit evaluation, and reformatted spacing for consistent coding style -- (NOTE: for NLHE this will definitely be faster as less hands go to flop - may be slower for limit games) Also added a couple of comments near enumerate() calls about 2.5 to 2.6 syntax --- pyfpdb/DerivedStats.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index a951d0b7..c36201e5 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -139,6 +139,8 @@ class DerivedStats(): self.handsplayers[player[1]]['seatNo'] = player[0] self.handsplayers[player[1]]['startCash'] = int(100 * Decimal(player[2])) + # XXX: enumerate(list, start=x) is python 2.6 syntax; 'start' + #for i, street in enumerate(hand.actionStreets[2:], start=1): for i, street in enumerate(hand.actionStreets[2:]): self.seen(self.hand, i+1) @@ -382,6 +384,7 @@ class DerivedStats(): CG: CheckCall would be a much better name for this. """ + # XXX: enumerate(list, start=x) is python 2.6 syntax; 'start' #for i, street in enumerate(hand.actionStreets[2:], start=1): for i, street in enumerate(hand.actionStreets[2:]): actions = hand.actions[hand.actionStreets[i+1]] @@ -412,7 +415,7 @@ class DerivedStats(): aggrers = set() others = set() # Growl - actionStreets contains 'BLINDSANTES', which isn't actually an action street - + firstAggrMade=False for act in hand.actions[hand.actionStreets[i+1]]: if firstAggrMade: @@ -427,11 +430,12 @@ class DerivedStats(): self.handsplayers[player[1]]['street%sAggr' % i] = True else: self.handsplayers[player[1]]['street%sAggr' % i] = False - - if len(aggrers)>0 and i>0: + + if i > 0 and len(aggrers) > 0: for playername in others: self.handsplayers[playername]['otherRaisedStreet%s' % i] = True - #print "otherRaised detected on handid "+str(hand.handid)+" for "+playername+" on street "+str(i) + #print "DEBUG: otherRaised detected on handid %s for %s on actionStreet[%s]: %s" + # %(hand.handid, playername, hand.actionStreets[i+1], i) def calls(self, hand, i): callers = [] @@ -445,15 +449,16 @@ class DerivedStats(): for act in hand.actions[hand.actionStreets[i+1]]: if act[1] in ('bets'): self.handsplayers[act[0]]['street%sBets' % i] = 1 + self.handsplayers[act[0]]['street%sBets' % i] - + def folds(self, hand, i): for act in hand.actions[hand.actionStreets[i+1]]: if act[1] in ('folds'): if self.handsplayers[act[0]]['otherRaisedStreet%s' % i] == True: self.handsplayers[act[0]]['foldToOtherRaisedStreet%s' % i] = True - #print "fold detected on handid "+str(hand.handid)+" for "+act[0]+" on street "+str(i) - + #print "DEBUG: fold detected on handid %s for %s on actionStreet[%s]: %s" + # %(hand.handid, act[0],hand.actionStreets[i+1], i) + def countPlayers(self, hand): pass From f6fbf0825040f6cf251eb133e89f31a36638bfd3 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Fri, 28 May 2010 19:12:02 +0200 Subject: [PATCH 15/30] moved fold stats so that the file no longer indicates that they're not done --- pyfpdb/DerivedStats.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index c36201e5..b222fc01 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -67,12 +67,12 @@ class DerivedStats(): self.handsplayers[player[1]]['street%dCBDone' %i] = False self.handsplayers[player[1]]['street%dCheckCallRaiseChance' %i] = False 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]]['otherRaisedStreet%d' %i] = False - self.handsplayers[player[1]]['foldToOtherRaisedStreet%d' %i] = False self.handsplayers[player[1]]['foldToStreet%dCBChance' %i] = False self.handsplayers[player[1]]['foldToStreet%dCBDone' %i] = False From 5a13e96b3bababe0dd17332917d0d1461b849c8c Mon Sep 17 00:00:00 2001 From: Gerko de Roo Date: Wed, 17 Mar 2010 22:38:40 +0100 Subject: [PATCH 16/30] Auto close HUD support for closing tourney windows added. Not neat but functional. --- pyfpdb/Hud.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index dcad0865..5dcccf3c 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -448,6 +448,8 @@ class Hud: if os.name == 'nt': if not win32gui.IsWindow(self.table.number): self.parent.kill_hud(self, self.table.name) + self.parent.kill_hud(self, self.table.name.split(" ")[0]) + #table.name is only a valid handle for ring games ! we are not killing tourney tables here. return False # anyone know how to do this in unix, or better yet, trap the X11 error that is triggered when executing the get_origin() for a closed window? if self.table.gdkhandle is not None: From 27e5bf86988177b3403ad23d52b3bf52bf688104 Mon Sep 17 00:00:00 2001 From: Gerko de Roo Date: Mon, 17 May 2010 19:23:17 +0200 Subject: [PATCH 17/30] Moved Codec conversion to Charset The TIP is using a codec conversion that doesn't handle error exeptions. This could lock up the HUD.... --- pyfpdb/Stats.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Stats.py b/pyfpdb/Stats.py index 264ebd18..74d51675 100755 --- a/pyfpdb/Stats.py +++ b/pyfpdb/Stats.py @@ -57,6 +57,7 @@ import re # FreePokerTools modules import Configuration import Database +import Charset re_Places = re.compile("_[0-9]$") @@ -67,7 +68,7 @@ import codecs encoder = codecs.lookup(Configuration.LOCALE_ENCODING) def do_tip(widget, tip): - (_tip, _len) = encoder.encode(tip) + _tip = Charset.to_utf8(tip) widget.set_tooltip_text(_tip) def do_stat(stat_dict, player = 24, stat = 'vpip'): From 23ae26259b5dfc37a73803e6a661b1b993574472 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 4 Jun 2010 04:17:30 +0800 Subject: [PATCH 18/30] Steffen reported a FTP file in UTF-8 format. Added it as the 3rd codec tested --- pyfpdb/FulltiltToFpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/FulltiltToFpdb.py b/pyfpdb/FulltiltToFpdb.py index 10ecb8dd..2c6370e6 100755 --- a/pyfpdb/FulltiltToFpdb.py +++ b/pyfpdb/FulltiltToFpdb.py @@ -27,7 +27,7 @@ class Fulltilt(HandHistoryConverter): sitename = "Fulltilt" filetype = "text" - codepage = ["utf-16", "cp1252"] + codepage = ["utf-16", "cp1252", "utf-8"] siteId = 1 # Needs to match id entry in Sites database # Static regexes From e17058953c320682d462ca2b35b30cc247613e21 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 4 Jun 2010 05:36:59 +0800 Subject: [PATCH 19/30] Add preliminary functions and variables for hex encoding patch Kangaderoo has a patch which potentially fixes storage and display issues for users who do not have their database text storage as utf8. Functions and variables added to Charset to disect the patch --- pyfpdb/Charset.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/pyfpdb/Charset.py b/pyfpdb/Charset.py index 9c49f505..055ca714 100644 --- a/pyfpdb/Charset.py +++ b/pyfpdb/Charset.py @@ -26,7 +26,9 @@ import Configuration encoder_to_utf = codecs.lookup('utf-8') encoder_to_sys = codecs.lookup(Configuration.LOCALE_ENCODING) +coder_hex = codecs.lookup('hex_codec') +hex_coding = False #FIXME: Should only be on if db is not UTF8 - test in Database.py? # I'm saving a few cycles with this one not_needed1, not_needed2, not_needed3 = False, False, False if Configuration.LOCALE_ENCODING == 'UTF8': @@ -75,3 +77,19 @@ def to_gui(s): except UnicodeEncodeError: sys.stderr.write('Could not encode: "%s"\n' % s) raise + +def to_hex(s): + try: + out = coder_hex.encode(s)[0] + return out + except UnicodeDecodeError: + sys.stderr.write('Could not convert: "%s"\n' % s) + return s + +def from_hex(s): + try: + out = coder_hex.decode(s)[0] + return out + except UnicodeDecodeError: + sys.stderr.write('Could not convert: "%s"\n' % s) + return s From bdbcf19b064b1c4f41ae2f685da506bf691f9433 Mon Sep 17 00:00:00 2001 From: Gerko de Roo Date: Thu, 4 Mar 2010 14:11:50 +0100 Subject: [PATCH 20/30] Player stat fix for PartyPoker When placing a uncalled bet (like all-in) the uncalled part is put in a sitepot Therefore the player exist 2* in collected. The uncalled part of the bet was subtracted twice for collected and collectees. --- pyfpdb/PartyPokerToFpdb.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyfpdb/PartyPokerToFpdb.py b/pyfpdb/PartyPokerToFpdb.py index f83c8672..5cb170e6 100755 --- a/pyfpdb/PartyPokerToFpdb.py +++ b/pyfpdb/PartyPokerToFpdb.py @@ -261,6 +261,7 @@ class PartyPoker(HandHistoryConverter): if v[0] in self.pot.returned: self.collected[i][1] = Decimal(v[1]) - self.pot.returned[v[0]] self.collectees[v[0]] -= self.pot.returned[v[0]] + self.pot.returned[v[0]] = 0 return origTotalPot() return totalPot instancemethod = type(hand.totalPot) From e41c63f6ee0fa773494a8b243af3bcc6d5103dca Mon Sep 17 00:00:00 2001 From: Gerko de Roo Date: Thu, 4 Mar 2010 14:32:48 +0100 Subject: [PATCH 21/30] When small blind raises here the addRaiseBy was generating money. One player on small blind with total $2.25, commited $2.27 to the pot. --- pyfpdb/PartyPokerToFpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/PartyPokerToFpdb.py b/pyfpdb/PartyPokerToFpdb.py index 5cb170e6..94acfd3f 100755 --- a/pyfpdb/PartyPokerToFpdb.py +++ b/pyfpdb/PartyPokerToFpdb.py @@ -433,7 +433,7 @@ class PartyPoker(HandHistoryConverter): if street == 'PREFLOP' and \ playerName in [item[0] for item in hand.actions['BLINDSANTES'] if item[2]!='ante']: # preflop raise from blind - hand.addRaiseBy( street, playerName, amount ) + hand.addCallandRaise( street, playerName, amount ) else: hand.addCallandRaise( street, playerName, amount ) elif actionType == 'calls': From 1edf8607609181f5a96aae752fdeb6a63c690d03 Mon Sep 17 00:00:00 2001 From: Gerko de Roo Date: Thu, 4 Mar 2010 19:49:43 +0100 Subject: [PATCH 22/30] Add support for post of dead small blind (PartyPoker) --- pyfpdb/PartyPokerToFpdb.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pyfpdb/PartyPokerToFpdb.py b/pyfpdb/PartyPokerToFpdb.py index 94acfd3f..5c60f179 100755 --- a/pyfpdb/PartyPokerToFpdb.py +++ b/pyfpdb/PartyPokerToFpdb.py @@ -360,8 +360,14 @@ class PartyPoker(HandHistoryConverter): if hand.gametype['type'] == 'ring': try: assert noSmallBlind==False - m = self.re_PostSB.search(hand.handText) - hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB')) + liveBlind = True + for m in self.re_PostSB.finditer(hand.handText): + if liveBlind: + hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB')) + liveBlind = False + else: + # Post dead blinds as ante + hand.addBlind(m.group('PNAME'), 'secondsb', m.group('SB')) except: # no small blind hand.addBlind(None, None, None) From 3716f11f061216a299bd8634b9fca954aee19a53 Mon Sep 17 00:00:00 2001 From: Gerko de Roo Date: Mon, 17 May 2010 20:04:14 +0200 Subject: [PATCH 23/30] 1970-01-01 in mktime generates overflow... --- pyfpdb/Filters.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index 15fccd1c..43f7819d 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -876,7 +876,7 @@ class Filters(threading.Thread): t2 = self.end_date.get_text() if t1 == '': - t1 = '1970-01-01' + t1 = '1970-01-02' if t2 == '': t2 = '2020-12-12' From 6b00311756e7c4d54205ccc1b2d55b00550755c4 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 4 Jun 2010 14:37:46 +0800 Subject: [PATCH 24/30] Make sqlite index deletion and creation work. Also updated the coding style and logging in that area. --- pyfpdb/Database.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 8939d4b3..23fb02fb 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1162,7 +1162,8 @@ class Database: self.connection.set_isolation_level(0) # allow table/index operations to work for idx in self.indexes[self.backend]: if self.backend == self.MYSQL_INNODB: - print "creating mysql index ", idx['tab'], idx['col'] + print "Creating mysql index %s %s" %(idx['tab'], idx['col']) + log.debug("Creating sqlite index %s %s" %(idx['tab'], idx['col'])) try: s = "create index %s on %s(%s)" % (idx['col'],idx['tab'],idx['col']) self.get_cursor().execute(s) @@ -1170,21 +1171,23 @@ class Database: print " create idx failed: " + str(sys.exc_info()) elif self.backend == self.PGSQL: # mod to use tab_col for index name? - print "creating pg index ", idx['tab'], idx['col'] + print "Creating pg index %s %s" %(idx['tab'], idx['col']) + log.debug("Creating sqlite index %s %s" %(idx['tab'], idx['col'])) try: s = "create index %s_%s_idx on %s(%s)" % (idx['tab'], idx['col'], idx['tab'], idx['col']) self.get_cursor().execute(s) except: print " create idx failed: " + str(sys.exc_info()) elif self.backend == self.SQLITE: - log.debug("Creating sqlite index %s %s" % (idx['tab'], idx['col'])) + print "Creating sqlite index %s %s" %(idx['tab'], idx['col']) + log.debug("Creating sqlite index %s %s" %(idx['tab'], idx['col'])) try: s = "create index %s_%s_idx on %s(%s)" % (idx['tab'], idx['col'], idx['tab'], idx['col']) self.get_cursor().execute(s) except: log.debug("Create idx failed: " + str(sys.exc_info())) else: - print "Only MySQL, Postgres and SQLite supported so far" + print "Unknown database: MySQL, Postgres and SQLite supported" return -1 if self.backend == self.PGSQL: self.connection.set_isolation_level(1) # go back to normal isolation level @@ -1215,8 +1218,15 @@ class Database: % (idx['tab'],idx['col']) ) except: print " drop idx failed: " + str(sys.exc_info()) + elif self.backend == self.SQLITE: + print "Dropping sqlite index ", idx['tab'], idx['col'] + try: + self.get_cursor().execute( "drop index %s_%s_idx" + % (idx['tab'],idx['col']) ) + except: + print " drop idx failed: " + str(sys.exc_info()) else: - print "Only MySQL and Postgres supported so far" + print "Only MySQL, Postgres and SQLITE supported, what are you trying to use?" return -1 if self.backend == self.PGSQL: self.connection.set_isolation_level(1) # go back to normal isolation level From 212438a0c60fe78f2cc7dd539ca4b4b296844c50 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 4 Jun 2010 15:25:56 +0800 Subject: [PATCH 25/30] Database.py - Additional logging and comments --- pyfpdb/Database.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 23fb02fb..ce4e3f6f 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -193,7 +193,7 @@ class Database: # alter table t add constraint c foreign key (fkcol) references tab(rcol) # (fkcol is used for foreigh key name) - # mysql to list indexes: + # mysql to list indexes: (CG - "LIST INDEXES" should work too) # SELECT table_name, index_name, non_unique, column_name # FROM INFORMATION_SCHEMA.STATISTICS # WHERE table_name = 'tbl_name' @@ -223,6 +223,7 @@ class Database: # Note: index names must be unique across a schema # CREATE INDEX idx ON tab(col) # DROP INDEX idx + # SELECT * FROM PG_INDEXES # SQLite notes: @@ -1075,7 +1076,7 @@ class Database: c = self.get_cursor() c.execute(self.sql.query['createSettingsTable']) - log.debug(self.sql.query['createSitesTable']) + log.debug("Creating tables") c.execute(self.sql.query['createSitesTable']) c.execute(self.sql.query['createGametypesTable']) c.execute(self.sql.query['createPlayersTable']) @@ -1088,7 +1089,8 @@ class Database: c.execute(self.sql.query['createHandsActionsTable']) c.execute(self.sql.query['createHudCacheTable']) - # create unique indexes: + # Create unique indexes: + log.debug("Creating unique indexes") c.execute(self.sql.query['addTourneyIndex']) c.execute(self.sql.query['addHandsIndex']) c.execute(self.sql.query['addPlayersIndex']) From 12ad272f91f6300d1ed1c875cd5dea78ed6f8d85 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 4 Jun 2010 15:26:50 +0800 Subject: [PATCH 26/30] SQL.py - Add functions for listing indexes. Not used anywhere - may be a good reference at some point --- pyfpdb/SQL.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index deb9d527..37d214ff 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -51,6 +51,18 @@ class Sql: WHERE type='table' ORDER BY name;""" + ################################ + # List indexes + ################################ + if db_server == 'mysql': + self.query['list_tables'] = """SHOW INDEXES""" + elif db_server == 'postgresql': + self.query['list_tables'] = """SELECT tablename, indexname FROM PG_INDEXES""" + elif db_server == 'sqlite': + self.query['list_tables'] = """SELECT name FROM sqlite_master + WHERE type='index' + ORDER BY name;""" + ################################################################## # Drop Tables - MySQL, PostgreSQL and SQLite all share same syntax ################################################################## From 0c3cdb12f8f6ea9f56c4ba29e94b1c8cd751d5c7 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 4 Jun 2010 15:59:47 +0800 Subject: [PATCH 27/30] General cleanup - Exception messages and improved logging. Stars HHC, HHC itself and Hand. Should not get the first 100 characters of an failing hand in the log, which contains the handid for later reference. Played around with the number of characters a while ago - 100 chars is about the sweet spot. --- pyfpdb/Hand.py | 11 ++++++----- pyfpdb/HandHistoryConverter.py | 6 ++---- pyfpdb/PokerStarsToFpdb.py | 4 ++-- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index adb7d3f6..71fc6ced 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -274,15 +274,16 @@ If a player has None chips he won't be added.""" self.streets.update(match.groupdict()) log.debug("markStreets:\n"+ str(self.streets)) else: + tmp = self.handText[0:100] log.error("markstreets didn't match") log.error(" - Assuming hand cancelled") self.cancelled = True - raise FpdbParseError + raise FpdbParseError("FpdbParseError: markStreets appeared to fail: First 100 chars: '%s'" % tmp) def checkPlayerExists(self,player): if player not in [p[1] for p in self.players]: - print "checkPlayerExists", player, "fail" - raise FpdbParseError + print "DEBUG: checkPlayerExists %s fail" % player + raise FpdbParseError("checkPlayerExists: '%s' failed." % player) @@ -1487,9 +1488,9 @@ class Pot(object): if self.sym is None: self.sym = "C" if self.total is None: - print "call Pot.end() before printing pot total" + print "DEBUG: call Pot.end() before printing pot total" # NB if I'm sure end() is idempotent, call it here. - raise FpdbParseError + raise FpdbParseError("FpdbError in printing Hand object") ret = "Total pot %s%.2f" % (self.sym, self.total) if len(self.pots) < 2: diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 5b65b955..3b858f10 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -137,8 +137,7 @@ Otherwise, finish at EOF. self.numHands += 1 except FpdbParseError, e: self.numErrors += 1 - log.warning("Failed to convert hand %s" % e.hid) - log.warning("Exception msg: '%s'" % str(e)) + log.warning("HHC.start(follow): processHand failed: Exception msg: '%s'" % e) log.debug(handText) else: handsList = self.allHandsAsList() @@ -152,8 +151,7 @@ Otherwise, finish at EOF. self.processedHands.append(self.processHand(handText)) except FpdbParseError, e: self.numErrors += 1 - log.warning("Failed to convert hand %s" % e.hid) - log.warning("Exception msg: '%s'" % str(e)) + log.warning("HHC.start(): processHand failed: Exception msg: '%s'" % e) log.debug(handText) self.numHands = len(handsList) endtime = time.time() diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 79bef1ea..17a9b15c 100644 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -140,7 +140,7 @@ class PokerStars(HandHistoryConverter): tmp = handText[0:100] log.error("determineGameType: Unable to recognise gametype from: '%s'" % tmp) log.error("determineGameType: Raising FpdbParseError") - raise FpdbParseError + raise FpdbParseError("Unable to recognise gametype from: '%s'" % tmp) mg = m.groupdict() # translations from captured groups to fpdb info strings @@ -194,7 +194,7 @@ class PokerStars(HandHistoryConverter): except KeyError: log.error("determineGameType: Lim_Blinds has no lookup for '%s'" % mg['BB']) log.error("determineGameType: Raising FpdbParseError") - raise FpdbParseError + raise FpdbParseError("Lim_Blinds has no lookup for '%s'" % mg['BB']) # NB: SB, BB must be interpreted as blinds or bets depending on limit type. return info From 3b823574ab8ceeb4022b7272fbca3bf495f15e37 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 5 Jun 2010 00:44:40 +0800 Subject: [PATCH 28/30] Bump version to 0.20 --- pyfpdb/fpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 768795ab..3d9db3d7 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -110,7 +110,7 @@ import Database import Configuration import Exceptions -VERSION = "0.12" +VERSION = "0.20" class fpdb: From 18a3af2e88066cff10df7322b8b427b723b8db25 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 5 Jun 2010 17:58:00 +0800 Subject: [PATCH 29/30] Fix HHC init and python 2.5 incompatibility --- pyfpdb/Anonymise.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Anonymise.py b/pyfpdb/Anonymise.py index 32036b1e..1eea39db 100644 --- a/pyfpdb/Anonymise.py +++ b/pyfpdb/Anonymise.py @@ -5,6 +5,7 @@ import Options import HandHistoryConverter (options, argv) = Options.fpdb_options() +config = Configuration.Config() filter = options.hhc @@ -13,7 +14,7 @@ filter_name = filter.replace("ToFpdb", "") mod = __import__(filter) obj = getattr(mod, filter_name, None) -hhc = obj(autostart=False) +hhc = obj(config, autostart=False) if os.path.exists(options.infile): in_fh = codecs.open(options.infile, 'r', "utf8") @@ -31,7 +32,7 @@ for a in m: uniq = set(players) -for i, name in enumerate(uniq, 1): +for i, name in enumerate(uniq): filecontents = filecontents.replace(name, 'Player%d' %i) print filecontents From 3d7668bde5985cf4e307f452447e6973fb2c390c Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 5 Jun 2010 18:00:41 +0800 Subject: [PATCH 30/30] Add required import --- pyfpdb/Anonymise.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyfpdb/Anonymise.py b/pyfpdb/Anonymise.py index 1eea39db..512980e0 100644 --- a/pyfpdb/Anonymise.py +++ b/pyfpdb/Anonymise.py @@ -3,6 +3,7 @@ import re import codecs import Options import HandHistoryConverter +import Configuration (options, argv) = Options.fpdb_options() config = Configuration.Config()