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 diff --git a/pyfpdb/Anonymise.py b/pyfpdb/Anonymise.py index 32036b1e..512980e0 100644 --- a/pyfpdb/Anonymise.py +++ b/pyfpdb/Anonymise.py @@ -3,8 +3,10 @@ import re import codecs import Options import HandHistoryConverter +import Configuration (options, argv) = Options.fpdb_options() +config = Configuration.Config() filter = options.hhc @@ -13,7 +15,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 +33,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 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 diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 8939d4b3..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']) @@ -1162,7 +1164,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 +1173,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 +1220,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 diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 4e55cdfc..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 @@ -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) @@ -146,6 +148,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 @@ -368,8 +372,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): @@ -380,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]] @@ -408,10 +413,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) @@ -420,6 +431,12 @@ class DerivedStats(): else: self.handsplayers[player[1]]['street%sAggr' % i] = False + if i > 0 and len(aggrers) > 0: + for playername in others: + self.handsplayers[playername]['otherRaisedStreet%s' % i] = True + #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 = [] for act in hand.actions[hand.actionStreets[i+1]]: @@ -429,11 +446,19 @@ 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 "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 diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index a5022508..be8f681f 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' 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 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/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 2053eba9..3b858f10 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 @@ -136,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() @@ -151,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() @@ -247,6 +246,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/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: diff --git a/pyfpdb/PartyPokerToFpdb.py b/pyfpdb/PartyPokerToFpdb.py index f83c8672..5c60f179 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) @@ -359,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) @@ -432,7 +439,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': diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 76a58b93..17a9b15c 100644 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -137,13 +137,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("Unable to recognise gametype from: '%s'" % tmp) 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'), @@ -156,7 +159,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'), @@ -185,8 +188,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("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 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 ################################################################## diff --git a/pyfpdb/Stats.py b/pyfpdb/Stats.py index 47d8b9f1..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'): @@ -277,7 +278,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) + '%', 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: 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?