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): diff --git a/pyfpdb/GuiSessionViewer.py b/pyfpdb/GuiSessionViewer.py index b5ca0867..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 @@ -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: @@ -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,23 +258,31 @@ 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 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)) - 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(times) %s" %(len(times)) + 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])) - #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 + first_idx = 0 lowidx = 0 uppidx = 0 opens = [] @@ -281,27 +292,36 @@ class GuiSessionViewer (threading.Thread): results = [] cum_sum = cumsum(winnings) cum_sum = cum_sum/100 + sid = 1 # 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 + 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 - hph = (times[index[0][i]] - times[last_idx])/60 # 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) + 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[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)" %(first_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) - total = total + (index[0][i] - last_idx) - last_idx = index[0][i] + 1 + #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] - first_idx) + first_idx = index[0][i] + 1 + sid = sid+1 + else: + print "hds <= 0" return (results, opens, closes, highs, lows) @@ -330,11 +350,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 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 [] diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 801f17d6..c964faa5 100644 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -135,13 +135,16 @@ 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 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': ('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'), @@ -154,7 +157,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 +186,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 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?