From 19a32943d833a379ff9ddc1160c0799cf2922c91 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 9 Oct 2010 15:27:58 +0800 Subject: [PATCH 01/24] Hand: Move assemble() function up into select() --- pyfpdb/Hand.py | 276 ++++++++++++++++++++++++------------------------- 1 file changed, 134 insertions(+), 142 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 0909d42d..ce0e4e7a 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -281,9 +281,143 @@ db: a connected Database object""" def select(self, handId): """ Function to create Hand object from database """ + c = cnxn.cursor() + + # We need at least sitename, gametype, handid + # for the Hand.__init__ + c.execute("""SELECT + s.name, + g.category, + g.base, + g.type, + g.limitType, + g.hilo, + round(g.smallBlind / 100.0,2), + round(g.bigBlind / 100.0,2), + round(g.smallBet / 100.0,2), + round(g.bigBet / 100.0,2), + s.currency, + h.boardcard1, + h.boardcard2, + h.boardcard3, + h.boardcard4, + h.boardcard5 + FROM + hands as h, + sites as s, + gametypes as g, + handsplayers as hp, + players as p + WHERE + h.id = %(handid)s + and g.id = h.gametypeid + and hp.handid = h.id + and p.id = hp.playerid + and s.id = p.siteid + limit 1""", {'handid':handid}) + #TODO: siteid should be in hands table - we took the scenic route through players here. + res = c.fetchone() + gametype = {'category':res[1],'base':res[2],'type':res[3],'limitType':res[4],'hilo':res[5],'sb':res[6],'bb':res[7], 'currency':res[10]} + c = Configuration.Config() + h = HoldemOmahaHand(config = c, hhc = None, sitename=res[0], gametype = gametype, handText=None, builtFrom = "DB", handid=handid) + cards = map(Card.valueSuitFromCard, res[11:16] ) + if cards[0]: + h.setCommunityCards('FLOP', cards[0:3]) + if cards[3]: + h.setCommunityCards('TURN', [cards[3]]) + if cards[4]: + h.setCommunityCards('RIVER', [cards[4]]) + #[Card.valueSuitFromCard(x) for x in cards] + + # HandInfo : HID, TABLE + # BUTTON - why is this treated specially in Hand? + # answer: it is written out in hand histories + # still, I think we should record all the active seat positions in a seat_order array + c.execute("""SELECT + h.sitehandno as hid, + h.tablename as table, + h.startTime as startTime + FROM + hands as h + WHERE h.id = %(handid)s + """, {'handid':handid}) + res = c.fetchone() + h.handid = res[0] + h.tablename = res[1] + h.startTime = res[2] # automatically a datetime + + # PlayerStacks + c.execute("""SELECT + hp.seatno, + round(hp.winnings / 100.0,2) as winnings, + p.name, + round(hp.startcash / 100.0,2) as chips, + hp.card1,hp.card2, + hp.position + FROM + handsplayers as hp, + players as p + WHERE + hp.handid = %(handid)s + and p.id = hp.playerid + """, {'handid':handid}) + for (seat, winnings, name, chips, card1,card2, position) in c.fetchall(): + h.addPlayer(seat,name,chips) + if card1 and card2: + h.addHoleCards(map(Card.valueSuitFromCard, (card1,card2)), name, dealt=True) + if winnings > 0: + h.addCollectPot(name, winnings) + if position == 'B': + h.buttonpos = seat + # actions + c.execute("""SELECT + (ha.street,ha.actionno) as actnum, + p.name, + ha.street, + ha.action, + ha.allin, + round(ha.amount / 100.0,2) + FROM + handsplayers as hp, + handsactions as ha, + players as p + WHERE + hp.handid = %(handid)s + and ha.handsplayerid = hp.id + and p.id = hp.playerid + ORDER BY + ha.street,ha.actionno + """, {'handid':handid}) + res = c.fetchall() + for (actnum,player, streetnum, act, allin, amount) in res: + act=act.strip() + street = h.allStreets[streetnum+1] + if act==u'blind': + h.addBlind(player, 'big blind', amount) + # TODO: The type of blind is not recorded in the DB. + # TODO: preflop street name anomalies in Hand + elif act==u'fold': + h.addFold(street,player) + elif act==u'call': + h.addCall(street,player,amount) + elif act==u'bet': + h.addBet(street,player,amount) + elif act==u'check': + h.addCheck(street,player) + elif act==u'unbet': + pass + else: + print act, player, streetnum, allin, amount + # TODO : other actions + #hhc.readShowdownActions(self) + #hc.readShownCards(self) + h.totalPot() + h.rake = h.totalpot - h.totalcollected + + return h def addPlayer(self, seat, name, chips): """\ @@ -1540,146 +1674,4 @@ class Pot(object): return ret + ''.join([ (" Side pot %s%.2f." % (self.sym, self.pots[x]) ) for x in xrange(1, len(self.pots)) ]) -def assemble(cnxn, handid): - c = cnxn.cursor() - # We need at least sitename, gametype, handid - # for the Hand.__init__ - c.execute(""" -select - s.name, - g.category, - g.base, - g.type, - g.limitType, - g.hilo, - round(g.smallBlind / 100.0,2), - round(g.bigBlind / 100.0,2), - round(g.smallBet / 100.0,2), - round(g.bigBet / 100.0,2), - s.currency, - h.boardcard1, - h.boardcard2, - h.boardcard3, - h.boardcard4, - h.boardcard5 -from - hands as h, - sites as s, - gametypes as g, - handsplayers as hp, - players as p -where - h.id = %(handid)s -and g.id = h.gametypeid -and hp.handid = h.id -and p.id = hp.playerid -and s.id = p.siteid -limit 1""", {'handid':handid}) - #TODO: siteid should be in hands table - we took the scenic route through players here. - res = c.fetchone() - gametype = {'category':res[1],'base':res[2],'type':res[3],'limitType':res[4],'hilo':res[5],'sb':res[6],'bb':res[7], 'currency':res[10]} - c = Configuration.Config() - h = HoldemOmahaHand(config = c, hhc = None, sitename=res[0], gametype = gametype, handText=None, builtFrom = "DB", handid=handid) - cards = map(Card.valueSuitFromCard, res[11:16] ) - if cards[0]: - h.setCommunityCards('FLOP', cards[0:3]) - if cards[3]: - h.setCommunityCards('TURN', [cards[3]]) - if cards[4]: - h.setCommunityCards('RIVER', [cards[4]]) - #[Card.valueSuitFromCard(x) for x in cards] - - # HandInfo : HID, TABLE - # BUTTON - why is this treated specially in Hand? - # answer: it is written out in hand histories - # still, I think we should record all the active seat positions in a seat_order array - c.execute(""" -SELECT - h.sitehandno as hid, - h.tablename as table, - h.startTime as startTime -FROM - hands as h -WHERE h.id = %(handid)s -""", {'handid':handid}) - res = c.fetchone() - h.handid = res[0] - h.tablename = res[1] - h.startTime = res[2] # automatically a datetime - - # PlayerStacks - c.execute(""" -SELECT - hp.seatno, - round(hp.winnings / 100.0,2) as winnings, - p.name, - round(hp.startcash / 100.0,2) as chips, - hp.card1,hp.card2, - hp.position -FROM - handsplayers as hp, - players as p -WHERE - hp.handid = %(handid)s -and p.id = hp.playerid -""", {'handid':handid}) - for (seat, winnings, name, chips, card1,card2, position) in c.fetchall(): - h.addPlayer(seat,name,chips) - if card1 and card2: - h.addHoleCards(map(Card.valueSuitFromCard, (card1,card2)), name, dealt=True) - if winnings > 0: - h.addCollectPot(name, winnings) - if position == 'B': - h.buttonpos = seat - - - # actions - c.execute(""" -SELECT - (ha.street,ha.actionno) as actnum, - p.name, - ha.street, - ha.action, - ha.allin, - round(ha.amount / 100.0,2) -FROM - handsplayers as hp, - handsactions as ha, - players as p -WHERE - hp.handid = %(handid)s -and ha.handsplayerid = hp.id -and p.id = hp.playerid -ORDER BY - ha.street,ha.actionno -""", {'handid':handid}) - res = c.fetchall() - for (actnum,player, streetnum, act, allin, amount) in res: - act=act.strip() - street = h.allStreets[streetnum+1] - if act==u'blind': - h.addBlind(player, 'big blind', amount) - # TODO: The type of blind is not recorded in the DB. - # TODO: preflop street name anomalies in Hand - elif act==u'fold': - h.addFold(street,player) - elif act==u'call': - h.addCall(street,player,amount) - elif act==u'bet': - h.addBet(street,player,amount) - elif act==u'check': - h.addCheck(street,player) - elif act==u'unbet': - pass - else: - print act, player, streetnum, allin, amount - # TODO : other actions - - #hhc.readShowdownActions(self) - #hc.readShownCards(self) - h.totalPot() - h.rake = h.totalpot - h.totalcollected - - - return h From 487330fc5787072a6d85e80c1b0b21d6dcb21b47 Mon Sep 17 00:00:00 2001 From: lastpoet Date: Sat, 9 Oct 2010 16:59:01 +0100 Subject: [PATCH 02/24] remove tooltips on headers --- pyfpdb/GuiRingPlayerStats.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/GuiRingPlayerStats.py b/pyfpdb/GuiRingPlayerStats.py index 3d1bcb21..0f374a77 100644 --- a/pyfpdb/GuiRingPlayerStats.py +++ b/pyfpdb/GuiRingPlayerStats.py @@ -85,9 +85,9 @@ class DemoTips(TreeViewTooltips): def get_tooltip(self, view, column, path): model = view.get_model() cards = model[path][0] - title=column.get_title() - display='%s\n%s' % (title,onlinehelp[title]) + if (title == 'Hand' or title == 'Game'): display='' #no tooltips on headers + else: display='%s for %s\n%s' % (title,cards,onlinehelp[title]) return (display) def location(self, x, y, w, h): From 746e4b487190eae6c81d2aa7fbe58edb9cbf6be7 Mon Sep 17 00:00:00 2001 From: Worros Date: Mon, 11 Oct 2010 16:40:15 +0800 Subject: [PATCH 03/24] Stars: Make play money hands parse again --- pyfpdb/PokerStarsToFpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 8b35c525..24719de5 100644 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -39,7 +39,7 @@ class PokerStars(HandHistoryConverter): siteId = 2 # Needs to match id entry in Sites database mixes = { 'HORSE': 'horse', '8-Game': '8game', 'HOSE': 'hose'} # Legal mixed games - sym = {'USD': "\$", 'CAD': "\$", 'T$': "", "EUR": "\xe2\x82\xac", "GBP": "\xa3"} # ADD Euro, Sterling, etc HERE + sym = {'USD': "\$", 'CAD': "\$", 'T$': "", "EUR": "\xe2\x82\xac", "GBP": "\xa3", "play": ""} # ADD Euro, Sterling, etc HERE substitutions = { 'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes 'LS' : "\$|\xe2\x82\xac|" # legal currency symbols - Euro(cp1252, utf-8) From dc215a5d01c80fbe66052f37f22cf2d406cb29b4 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Mon, 11 Oct 2010 18:22:55 -0400 Subject: [PATCH 04/24] reflow get_geometry some, pep8 --- pyfpdb/WinTables.py | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/pyfpdb/WinTables.py b/pyfpdb/WinTables.py index 442aeaa2..80d1a9b5 100644 --- a/pyfpdb/WinTables.py +++ b/pyfpdb/WinTables.py @@ -49,6 +49,7 @@ from TableWindow import Table_Window b_width = 3 tb_height = 29 + class Table(Table_Window): def find_table_parameters(self): @@ -56,39 +57,43 @@ class Table(Table_Window): titles = {} win32gui.EnumWindows(win_enum_handler, titles) for hwnd in titles: - if titles[hwnd] == "": continue + if titles[hwnd] == "": + continue if re.search(self.search_string, titles[hwnd]): - if self.check_bad_words(titles[hwnd]): continue + if self.check_bad_words(titles[hwnd]): + continue self.window = hwnd break try: if self.window == None: - log.error( "Window %s not found. Skipping." % self.search_string ) + log.error("Window %s not found. Skipping." % self.search_string) return None except AttributeError: log.error(_("self.window doesn't exist? why?")) return None - self.title = titles[hwnd] - self.hud = None + self.title = titles[hwnd] + self.hud = None self.number = hwnd def get_geometry(self): - if not win32gui.IsWindow(self.number): # window closed - return None - try: - (x, y, width, height) = win32gui.GetWindowRect(self.number) - #print "x=",x,"y=",y,"width=",width,"height=",height - width = width - x - height = height - y - return {'x' : int(x) + b_width, + if win32gui.IsWindow(self.number): + (x, y, width, height) = win32gui.GetWindowRect(self.number) + # this apparently returns x = far left side of window, width = far right side of window, y = top of window, height = bottom of window + # so apparently we have to subtract x from "width" to get actual width, and y from "height" to get actual height ? + # it definitely gives slightly different results than the GTK code that does the same thing. + #print "x=", x, "y=", y, "width=", width, "height=", height + width = width - x + height = height - y + return { + 'x' : int(x) + b_width, 'y' : int(y) + tb_height, 'height' : int(height) - y, 'width' : int(width) - x - } - except: + } + except AttributeError: return None def get_window_title(self): @@ -145,5 +150,6 @@ class Table(Table_Window): # hud.main_window.set_title(real_name) + def win_enum_handler(hwnd, titles): titles[hwnd] = win32gui.GetWindowText(hwnd) From fb206dfde6e091a826e7a3c1147e2e4bc8a669d0 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Mon, 11 Oct 2010 18:23:22 -0400 Subject: [PATCH 05/24] actually import _mysql_exceptions before trying to test against it --- pyfpdb/fpdb.pyw | 1 + 1 file changed, 1 insertion(+) diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index ec10bd9f..74afc40f 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -962,6 +962,7 @@ class fpdb: if self.db!=None: if self.db.backend==self.db.MYSQL_INNODB: try: + import _mysql_exceptions if self.db is not None and self.db.is_connected(): self.db.disconnect() except _mysql_exceptions.OperationalError: # oh, damn, we're already disconnected From fed287334a5d620da9a18c5a92e50981e6456f91 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Mon, 11 Oct 2010 18:40:58 -0400 Subject: [PATCH 06/24] further fixing in WinTables for dealing with a window that has disappeared --- pyfpdb/WinTables.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyfpdb/WinTables.py b/pyfpdb/WinTables.py index 80d1a9b5..391f70c7 100644 --- a/pyfpdb/WinTables.py +++ b/pyfpdb/WinTables.py @@ -97,7 +97,10 @@ class Table(Table_Window): return None def get_window_title(self): - return win32gui.GetWindowText(self.window) + try: # after window is destroyed, self.window = attribute error + return win32gui.GetWindowText(self.window) + except AttributeError: + return "" # def get_nt_exe(self, hwnd): # """Finds the name of the executable that the given window handle belongs to.""" From 25e03489fe834898c39b9beb45cb46e09440fede Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Mon, 11 Oct 2010 22:23:06 -0400 Subject: [PATCH 07/24] fix error in logging mechanism, remove a debug print --- pyfpdb/Hud.py | 2 +- pyfpdb/TableWindow.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 15a9e6de..94baaa55 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -404,7 +404,7 @@ class Hud: if self.hud_params['agg_bb_mult'] != num \ and getattr(self, 'aggBBmultItem'+str(num)).get_active(): - log.debug('set_opponent_aggregation', num) + log.debug('set_opponent_aggregation %d', num) self.hud_params['agg_bb_mult'] = num for mult in ('1', '2', '3', '10', '10000'): if mult != str(num): diff --git a/pyfpdb/TableWindow.py b/pyfpdb/TableWindow.py index e3ec40de..31a94e3c 100644 --- a/pyfpdb/TableWindow.py +++ b/pyfpdb/TableWindow.py @@ -186,7 +186,7 @@ class Table_Window(object): mo = re.search(self.tableno_re, new_title) if mo is not None: - print "get_table_no: mo=",mo.groups() + #print "get_table_no: mo=",mo.groups() return mo.group(1) return False From 388bec04dddf7710bd33de9e20577305fe34d2c1 Mon Sep 17 00:00:00 2001 From: Chaz Date: Mon, 11 Oct 2010 22:37:59 -0400 Subject: [PATCH 08/24] Removed Partouche from in the config files --- pyfpdb/HUD_config.test.xml | 1 - pyfpdb/HUD_config.xml.example | 1 - 2 files changed, 2 deletions(-) diff --git a/pyfpdb/HUD_config.test.xml b/pyfpdb/HUD_config.test.xml index 6df2a4ea..77f27924 100644 --- a/pyfpdb/HUD_config.test.xml +++ b/pyfpdb/HUD_config.test.xml @@ -574,7 +574,6 @@ Left-Drag to Move" - diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index f650f52b..9afad9dc 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -772,7 +772,6 @@ Left-Drag to Move" - From 5643aeca6215b0d90967041862b5a07d4954065f Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Mon, 11 Oct 2010 23:42:05 -0400 Subject: [PATCH 09/24] fix another bad debug log --- pyfpdb/Hud.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 94baaa55..56d184d5 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -393,7 +393,7 @@ class Hud: if self.hud_params['h_agg_bb_mult'] != num \ and getattr(self, 'h_aggBBmultItem'+str(num)).get_active(): - log.debug('set_player_aggregation', num) + log.debug('set_player_aggregation %d', num) self.hud_params['h_agg_bb_mult'] = num for mult in ('1', '2', '3', '10', '10000'): if mult != str(num): From 6202d02dbcfb4ede4a017f15846937cef9ffb075 Mon Sep 17 00:00:00 2001 From: Chaz Date: Tue, 12 Oct 2010 01:08:32 -0400 Subject: [PATCH 10/24] Module containing a class that identifies the site a particular hand history, or directory of hand histories came from. Includes a main method which id's the regression files. --- pyfpdb/IdentifySite.py | 122 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 pyfpdb/IdentifySite.py diff --git a/pyfpdb/IdentifySite.py b/pyfpdb/IdentifySite.py new file mode 100644 index 00000000..b4f1a8a7 --- /dev/null +++ b/pyfpdb/IdentifySite.py @@ -0,0 +1,122 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +#Copyright 2010 Chaz Littlejohn +#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 L10n +_ = L10n.get_translation() + +import re +import sys +import os +import os.path +from optparse import OptionParser +import codecs +import Configuration +import Database + +__ARCHIVE_PRE_HEADER_REGEX='^Hand #(\d+)\s*$|\*{20}\s#\s\d+\s\*+\s+' +re_SplitArchive = re.compile(__ARCHIVE_PRE_HEADER_REGEX) + + +class IdentifySite: + def __init__(self, config, in_path = '-'): + self.in_path = in_path + self.config = config + self.db = Database.Database(config) + self.sitelist = {} + self.filelist = {} + self.generateSiteList() + self.walkDirectory(self.in_path, self.sitelist) + + def generateSiteList(self): + """Generates a ordered dictionary of site, filter and filter name for each site in hhcs""" + for site, hhc in self.config.hhcs.iteritems(): + filter = hhc.converter + filter_name = filter.replace("ToFpdb", "") + result = self.db.get_site_id(site) + if len(result) == 1: + self.sitelist[result[0][0]] = (site, filter, filter_name) + else: + pass + + def walkDirectory(self, dir, sitelist): + """Walks a directory, and executes a callback on each file""" + dir = os.path.abspath(dir) + for file in [file for file in os.listdir(dir) if not file in [".",".."]]: + nfile = os.path.join(dir,file) + if os.path.isdir(nfile): + self.walkDirectory(nfile, sitelist) + else: + self.idSite(nfile, sitelist) + + def __listof(self, x): + if isinstance(x, list) or isinstance(x, tuple): + return x + else: + return [x] + + def idSite(self, file, sitelist): + """Identifies the site the hh file originated from""" + if file.endswith('.txt'): + self.filelist[file] = '' + archive = False + for site, info in sitelist.iteritems(): + mod = __import__(info[1]) + obj = getattr(mod, info[2], None) + + for kodec in self.__listof(obj.codepage): + try: + in_fh = codecs.open(file, 'r', kodec) + whole_file = in_fh.read() + in_fh.close() + + if info[2] in ('OnGame', 'Winamax'): + m = obj.re_HandInfo.search(whole_file) + elif info[2] in ('PartyPoker'): + m = obj.re_GameInfoRing.search(whole_file) + if not m: + m = obj.re_GameInfoTrny.search(whole_file) + else: + m = obj.re_GameInfo.search(whole_file) + if re_SplitArchive.search(whole_file): + archive = True + if m: + self.filelist[file] = [info[0]] + [info[1]] + [kodec] + [archive] + break + except: + pass + +def main(argv=None): + if argv is None: + argv = sys.argv[1:] + + config = Configuration.Config(file = "HUD_config.test.xml") + in_path = 'regression-test-files/' + IdSite = IdentifySite(config, in_path) + + print "\n----------- SITE LIST -----------" + for site, info in IdSite.sitelist.iteritems(): + print site, info + print "----------- END SITE LIST -----------" + + print "\n----------- ID REGRESSION FILES -----------" + for file, site in IdSite.filelist.iteritems(): + print file, site + print "----------- END ID REGRESSION FILES -----------" + + +if __name__ == '__main__': + sys.exit(main()) From 970b88349b482ec6e321f4bbc9f2fd88981d3482 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Tue, 12 Oct 2010 02:23:56 -0400 Subject: [PATCH 11/24] hud doesn't crash when mixing cash/tourney --- pyfpdb/TableWindow.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyfpdb/TableWindow.py b/pyfpdb/TableWindow.py index 31a94e3c..ec694c73 100644 --- a/pyfpdb/TableWindow.py +++ b/pyfpdb/TableWindow.py @@ -184,7 +184,11 @@ class Table_Window(object): if new_title is None: return False - mo = re.search(self.tableno_re, new_title) + try: + mo = re.search(self.tableno_re, new_title) + except AttributeError: #'Table' object has no attribute 'tableno_re' + return False + if mo is not None: #print "get_table_no: mo=",mo.groups() return mo.group(1) From d517606a599dd6b8b4c80a145e951b2225513e49 Mon Sep 17 00:00:00 2001 From: Chaz Date: Tue, 12 Oct 2010 21:00:08 -0400 Subject: [PATCH 12/24] Added SplitHandHistory module which can be used to split up hand histories (archive & non-archive) into smaller files of n hands each (useful in limitied memory situations). Module contains a SplitHandHistory class and a command line utility. --- pyfpdb/SplitHandHistory.py | 215 +++++++++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 pyfpdb/SplitHandHistory.py diff --git a/pyfpdb/SplitHandHistory.py b/pyfpdb/SplitHandHistory.py new file mode 100644 index 00000000..76760ab0 --- /dev/null +++ b/pyfpdb/SplitHandHistory.py @@ -0,0 +1,215 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +#Copyright 2010 Chaz Littlejohn +#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 L10n +_ = L10n.get_translation() + +# This code is based heavily on stars-support-hh-split.py by Mika Boström + +import os +import sys +import re +import codecs +from optparse import OptionParser +import Configuration +from cStringIO import StringIO + +__ARCHIVE_PRE_HEADER_REGEX='^Hand #(\d+)\s*$|\*{20}\s#\s\d+\s\*+\s+' +re_SplitArchive = re.compile(__ARCHIVE_PRE_HEADER_REGEX) +codepage = ["utf-16", "utf-8", "cp1252"] + + +class SplitHandHistory: + def __init__(self, config, in_path = '-', out_path = None, hands = 100, site = "PokerStars", archive = False): + self.config = config + self.in_path = in_path + self.out_path = out_path + if not self.out_path: + self.out_path = os.path.dirname(self.in_path) + self.hands = hands + self.archive = archive + self.re_SplitHands = None + self.line_delimiter = None + self.filedone = False + + #Acquire re_SplitHands for this hh + filter = self.config.hhcs[site].converter + filter_name = filter.replace("ToFpdb", "") + mod = __import__(filter) + obj = getattr(mod, filter_name, None) + self.re_SplitHands = obj.re_SplitHands + #Determine line delimiter type if any + if self.re_SplitHands.match('\n\n'): + self.line_delimiter = '\n\n' + elif self.re_SplitHands.match('\n\n\n'): + self.line_delimiter = '\n\n\n' + else: + pass + + #Open the gargantuan file + try: + infile = file(self.in_path, 'r') + except: + print 'File is sophisticated' + for kodec in self.__listof(codepage): + try: + infile = codecs.open(self.in_path, 'r', kodec) + except IOError: + print 'File not found' + sys.exit(2) + + if self.archive: + nn = 0 + while True: + nn += 1 + check = self.do_hands_per_file(infile, nn) + if check is None: + print '%s processed' % self.in_path + break + else: + filenum = 0 + while not self.filedone: + filenum += 1 + outfile = self.new_file(filenum) + handnum = 0 + for hand in self.paragraphs(infile): + outfile.write(hand) + if self.line_delimiter: + outfile.write(self.line_delimiter) + handnum += 1 + if handnum >= self.hands: + break + outfile.close() + + def new_file(self, fileno=-1): + if fileno < 1: + print 'Nope, won\'t work (fileno=%d)' % fileno + sys.exit(2) + basename = os.path.splitext(os.path.basename(self.in_path))[0] + name = os.path.join(self.out_path, basename+'-%06d.txt' % fileno) + print '-> %s' % name + newfile = file(name, 'w') + return newfile + + #Archive Hand Splitter + def do_hands_per_file(self, infile, num=-1): + done = False + n = 0 + outfile = self.new_file(num) + while n < self.hands: + try: + infile = self.next_hand(infile) + infile = self.process_hand(infile, outfile) + except: + done = True + break + n += 1 + outfile.close() + if not done: + return infile + else: + return None + + #Non-Archive Hand Splitter + def paragraphs(self, file, separator=None): + if not callable(separator) and self.line_delimiter: + def separator(line): return line == '\n' + else: + def separator(sline): return self.re_SplitHands.search(line) + file_str = StringIO() + print file_str.getvalue() + for line in file: + if separator(line): + if file_str.getvalue(): + if not self.line_delimiter: + file_str.write(line) + yield file_str.getvalue() + file_str = None + file_str = StringIO() + else: + file_str.write(line) + if file_str.getvalue(): yield file_str.getvalue() + self.filedone = True + + + # Finds pre-hand header (Hand #) + def next_hand(self, infile): + m = None + while not m: + l = infile.readline() + #print l, len(l) + # Catch EOF + if len(l) == 0: + raise IOError + m = re_SplitArchive.search(l) + # There is an empty line after pre-hand header and actual HH entry + l = infile.readline() + + return infile + + # Each individual hand is written separately + def process_hand(self, infile=None, outfile=None): + l = infile.readline() + l = l.replace('\r\n', '\n') + outfile.write(l) + l = infile.readline() + + while len(l) < 3: + l = infile.readline() + + while len(l) > 2: + l = l.replace('\r\n', '\n') + outfile.write(l) + l = infile.readline() + outfile.write(self.line_delimiter) + return infile + + def __listof(self, x): + if isinstance(x, list) or isinstance(x, tuple): + return x + else: + return [x] + +def main(argv=None): + if argv is None: + argv = sys.argv[1:] + + parser = OptionParser() + parser.add_option("-f", "--file", dest="filename", metavar="FILE", default=None, + help=_("Input file in quiet mode")) + parser.add_option("-o", "--outpath", dest="outpath", metavar="FILE", default=None, + help=_("Input out path in quiet mode")) + parser.add_option("-c", "--convert", dest="filtername", default="PokerStars", metavar="FILTER", + help=_("Conversion filter (*Full Tilt Poker, PokerStars, Everleaf, Absolute)")) + parser.add_option("-a", "--archive", action="store_true", dest="archive", default=False, + help=_("File to be split is a PokerStars or Full Tilt Poker archive file")) + parser.add_option("-d", "--hands", dest="hands", default="100", type="int", + help=_("How many hands do you want saved to each file. Default is 100")) + (options, argv) = parser.parse_args(args = argv) + + config = Configuration.Config(file = "HUD_config.test.xml") + + print options.archive + + if not options.filename: + pass + else: + SplitHH = SplitHandHistory(config, options.filename, options.outpath, options.hands, + options.filtername, options.archive) + +if __name__ == '__main__': + sys.exit(main()) From 6ce42df7341400d184118cc64c865a27cd8b7915 Mon Sep 17 00:00:00 2001 From: Chaz Date: Tue, 12 Oct 2010 22:47:22 -0400 Subject: [PATCH 13/24] Fixed a re matching problem for sites (OnGame, Carbon) which include char after the newline in re_SplitHands --- pyfpdb/SplitHandHistory.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/pyfpdb/SplitHandHistory.py b/pyfpdb/SplitHandHistory.py index 76760ab0..aa6c2871 100644 --- a/pyfpdb/SplitHandHistory.py +++ b/pyfpdb/SplitHandHistory.py @@ -44,6 +44,7 @@ class SplitHandHistory: self.archive = archive self.re_SplitHands = None self.line_delimiter = None + self.line_addendum = None self.filedone = False #Acquire re_SplitHands for this hh @@ -52,15 +53,20 @@ class SplitHandHistory: mod = __import__(filter) obj = getattr(mod, filter_name, None) self.re_SplitHands = obj.re_SplitHands + #Determine line delimiter type if any if self.re_SplitHands.match('\n\n'): self.line_delimiter = '\n\n' - elif self.re_SplitHands.match('\n\n\n'): + if self.re_SplitHands.match('\n\n\n'): self.line_delimiter = '\n\n\n' - else: - pass - - #Open the gargantuan file + + #Add new line addendum for sites which match SplitHand to next line as well + if site == 'OnGame': + self.line_addendum = '*' + if site == 'Carbon': + self.line_addendum = ' Date: Wed, 13 Oct 2010 01:47:28 -0400 Subject: [PATCH 14/24] Added a FpdbEndOfFile error for use in SplitHandHistory.py --- pyfpdb/Exceptions.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyfpdb/Exceptions.py b/pyfpdb/Exceptions.py index 34b3bade..589f65cc 100644 --- a/pyfpdb/Exceptions.py +++ b/pyfpdb/Exceptions.py @@ -73,3 +73,6 @@ class FpdbHandDuplicate(FpdbHandError): class FpdbHandPartial(FpdbHandError): pass + +class FpdbEndOfFile(FpdbHandError): + pass From f97c1da3b94bc86fd429e019a7c1f5b0b0ae19f8 Mon Sep 17 00:00:00 2001 From: Chaz Date: Wed, 13 Oct 2010 01:48:35 -0400 Subject: [PATCH 15/24] Migrated SplitHandHistory.py commandline options to Options.py --- pyfpdb/Options.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pyfpdb/Options.py b/pyfpdb/Options.py index 98034b50..4646cb6e 100644 --- a/pyfpdb/Options.py +++ b/pyfpdb/Options.py @@ -53,6 +53,15 @@ def fpdb_options(): help = _("Print version information and exit.")) parser.add_option("-u", "--usage", action="store_true", dest="usage", default=False, help=_("Print some useful one liners")) + # The following options are used for SplitHandHistory.py + parser.add_option("-f", "--file", dest="filename", metavar="FILE", default=None, + help=_("Input file in quiet mode")) + parser.add_option("-o", "--outpath", dest="outpath", metavar="FILE", default=None, + help=_("Input out path in quiet mode")) + parser.add_option("-a", "--archive", action="store_true", dest="archive", default=False, + help=_("File to be split is a PokerStars or Full Tilt Poker archive file")) + parser.add_option("-n", "--numhands", dest="hands", default="100", type="int", + help=_("How many hands do you want saved to each file. Default is 100")) (options, argv) = parser.parse_args() From fa3f878c3a7df623513fc1036ac5872fd1afbf64 Mon Sep 17 00:00:00 2001 From: Chaz Date: Wed, 13 Oct 2010 01:51:57 -0400 Subject: [PATCH 16/24] * Migrated commandline options to Options.py * Added a EOF exception * Fixed a few error handling issues --- pyfpdb/SplitHandHistory.py | 63 +++++++++++++++----------------------- 1 file changed, 25 insertions(+), 38 deletions(-) diff --git a/pyfpdb/SplitHandHistory.py b/pyfpdb/SplitHandHistory.py index aa6c2871..8be80e66 100644 --- a/pyfpdb/SplitHandHistory.py +++ b/pyfpdb/SplitHandHistory.py @@ -24,17 +24,20 @@ import os import sys import re import codecs -from optparse import OptionParser +import Options import Configuration +from Exceptions import * from cStringIO import StringIO +(options, argv) = Options.fpdb_options() + __ARCHIVE_PRE_HEADER_REGEX='^Hand #(\d+)\s*$|\*{20}\s#\s\d+\s\*+\s+' re_SplitArchive = re.compile(__ARCHIVE_PRE_HEADER_REGEX) codepage = ["utf-16", "utf-8", "cp1252"] class SplitHandHistory: - def __init__(self, config, in_path = '-', out_path = None, hands = 100, site = "PokerStars", archive = False): + def __init__(self, config, in_path = '-', out_path = None, hands = 100, filter = "PokerStarsToFpdb", archive = False): self.config = config self.in_path = in_path self.out_path = out_path @@ -48,7 +51,6 @@ class SplitHandHistory: self.filedone = False #Acquire re_SplitHands for this hh - filter = self.config.hhcs[site].converter filter_name = filter.replace("ToFpdb", "") mod = __import__(filter) obj = getattr(mod, filter_name, None) @@ -61,22 +63,18 @@ class SplitHandHistory: self.line_delimiter = '\n\n\n' #Add new line addendum for sites which match SplitHand to next line as well - if site == 'OnGame': + if filter_name == 'OnGame': self.line_addendum = '*' - if site == 'Carbon': + if filter_name == 'Carbon': self.line_addendum = ' Date: Tue, 12 Oct 2010 22:20:26 +0100 Subject: [PATCH 17/24] calendar displays current entry value calendar inits from db if empty --- pyfpdb/Filters.py | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index a4660eb2..ac62988f 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -1014,6 +1014,25 @@ class Filters(threading.Thread): vb = gtk.VBox() cal = gtk.Calendar() + + if entry == self.start_date: + cal_date = self.start_date.get_text() + if cal_date == '': + self.cursor.execute(self.sql.query['get_first_date']) + result = self.db.cursor.fetchall() + cal_date = result[0][0].split()[0] + self.start_date.set_text(cal_date) + elif entry == self.end_date: + cal_date = self.end_date.get_text() + if cal_date == '': + self.cursor.execute(self.sql.query['get_last_date']) + result = self.db.cursor.fetchall() + cal_date = result[0][0].split()[0] + self.end_date.set_text(cal_date) + + (year,month,day)=cal_date.split('-') + cal.select_month(int(month)-1, int(year)) + cal.select_day(int(day)) vb.pack_start(cal, expand=False, padding=0) btn = gtk.Button(_('Done')) @@ -1039,9 +1058,15 @@ class Filters(threading.Thread): t2 = self.end_date.get_text() if t1 == '': - t1 = '1970-01-02' + self.cursor.execute(self.sql.query['get_first_date']) + result = self.db.cursor.fetchall() + t1 = result[0][0].split()[0] + self.start_date.set_text(t1) if t2 == '': - t2 = '2020-12-12' + self.cursor.execute(self.sql.query['get_last_date']) + result = self.db.cursor.fetchall() + t2 = result[0][0].split()[0] + self.end_date.set_text(t2) s1 = strptime(t1, "%Y-%m-%d") # make time_struct s2 = strptime(t2, "%Y-%m-%d") From 6e00ba9d78182f8cf21ac0a38c50f2fe50670da5 Mon Sep 17 00:00:00 2001 From: lastpoet Date: Tue, 12 Oct 2010 20:34:06 +0100 Subject: [PATCH 18/24] add date boundaries in filters --- pyfpdb/Filters.py | 1 + pyfpdb/SQL.py | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index ac62988f..1b07a67c 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -1062,6 +1062,7 @@ class Filters(threading.Thread): result = self.db.cursor.fetchall() t1 = result[0][0].split()[0] self.start_date.set_text(t1) + if t2 == '': self.cursor.execute(self.sql.query['get_last_date']) result = self.db.cursor.fetchall() diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index eef9ce04..d45ccd38 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -1396,6 +1396,10 @@ class Sql: , maxSeats, knockout, rebuy, addOn, speed, shootout, matrix, sng)""" self.query['get_last_hand'] = "select max(id) from Hands" + + self.query['get_last_date'] = "SELECT MAX(startTime) FROM Hands" + + self.query['get_first_date'] = "SELECT MIN(startTime) FROM Hands" self.query['get_player_id'] = """ select Players.id AS player_id From a71f68280307bba1750d68804e1b2caa25fd697f Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 13 Oct 2010 17:47:00 +0800 Subject: [PATCH 19/24] DerivedStats: adjust street0VPI for stud Add complete as one of the actions that count as VPIP --- pyfpdb/DerivedStats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 1f5a933e..c76c9f08 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -289,7 +289,7 @@ class DerivedStats(): def vpip(self, hand): vpipers = set() for act in hand.actions[hand.actionStreets[1]]: - if act[1] in ('calls','bets', 'raises'): + if act[1] in ('calls','bets', 'raises', 'completes'): vpipers.add(act[0]) self.hands['playersVpi'] = len(vpipers) From cfc2be559e14a5e5d9df2baf96bd45c709b731e7 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 13 Oct 2010 17:53:23 +0800 Subject: [PATCH 20/24] DerivedStats: Remove incorrect comment from positional calc --- pyfpdb/DerivedStats.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index c76c9f08..2fb055f8 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -243,11 +243,6 @@ class DerivedStats(): first betting round is 0 NOTE: HU, both values are negative for non-stud games NOTE2: I've never seen a HU stud match""" - # The position calculation must be done differently for Stud and other games as - # Stud the 'blind' acts first - in all other games they act last. - # - #This function is going to get it wrong when there in situations where there - # is no small blind. I can live with that. actions = hand.actions[hand.holeStreets[0]] # Note: pfbao list may not include big blind if all others folded players = self.pfbao(actions) From f244f8a37d920ef938898f696edd270aa472ff13 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 13 Oct 2010 18:05:41 +0800 Subject: [PATCH 21/24] DerivedStats: Merge Flop and stud position calculation No regressions using test suite --------------------- Total Errors: 29 --------------------- No position errors in stat listing --- pyfpdb/DerivedStats.py | 43 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 2fb055f8..abbc4234 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -247,35 +247,30 @@ class DerivedStats(): # Note: pfbao list may not include big blind if all others folded players = self.pfbao(actions) + # set blinds first, then others from pfbao list, avoids problem if bb + # is missing from pfbao list or if there is no small blind + sb, bb, bi = False, False, False if hand.gametype['base'] == 'stud': - positions = [7, 6, 5, 4, 3, 2, 1, 0, 'S', 'B'] - seats = len(players) - map = [] - # Could posibly change this to be either -2 or -1 depending if they complete or bring-in - # First player to act is -1, last player is 0 for 6 players it should look like: - # ['S', 4, 3, 2, 1, 0] - map = positions[-seats-1:-1] # Copy required positions from postions array anding in -1 - map = map[-1:] + map[0:-1] # and move the -1 to the start of that array - - for i, player in enumerate(players): - #print "player %s in posn %s" % (player, str(map[i])) - self.handsplayers[player]['position'] = map[i] + # Stud position is determined after cards are dealt + bi = [x[0] for x in hand.actions[hand.actionStreets[1]] if x[1] == 'bringin'] else: - # set blinds first, then others from pfbao list, avoids problem if bb - # is missing from pfbao list or if there is no small blind bb = [x[0] for x in hand.actions[hand.actionStreets[0]] if x[1] == 'big blind'] sb = [x[0] for x in hand.actions[hand.actionStreets[0]] if x[1] == 'small blind'] - # if there are > 1 sb or bb only the first is used! - if bb: - self.handsplayers[bb[0]]['position'] = 'B' - if bb[0] in players: players.remove(bb[0]) - if sb: - self.handsplayers[sb[0]]['position'] = 'S' - if sb[0] in players: players.remove(sb[0]) - #print "bb =", bb, "sb =", sb, "players =", players - for i,player in enumerate(reversed(players)): - self.handsplayers[player]['position'] = i + # if there are > 1 sb or bb only the first is used! + if bb: + self.handsplayers[bb[0]]['position'] = 'B' + if bb[0] in players: players.remove(bb[0]) + if sb: + self.handsplayers[sb[0]]['position'] = 'S' + if sb[0] in players: players.remove(sb[0]) + if bi: + self.handsplayers[bi[0]]['position'] = 'S' + if bi[0] in players: players.remove(bi[0]) + + #print "DEBUG: bb: '%s' sb: '%s' bi: '%s' plyrs: '%s'" %(bb, sb, bi, players) + for i,player in enumerate(reversed(players)): + self.handsplayers[player]['position'] = i def assembleHudCache(self, hand): # No real work to be done - HandsPlayers data already contains the correct info From ccb116cedad535fc0a538a1d251529563c3d2860 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 13 Oct 2010 18:15:14 +0800 Subject: [PATCH 22/24] DerivedStats: Fix raiseFirstInChance and raisedFirstIn for stud The previous calculation didn't correctly deal with the 'complete' and 'bringin' actions, with bringin being markes as raisedFirstIn = True Reduced regression test errors, but triggered some in unverified file. --------------------- Total Errors: 22 --------------------- Likely offenders: ( 2) : regression-test-files/cash/Stars/Stud/7-StudHL-USD-0.04-0.08-200911.Cardtest.txt ( 2) : raiseFirstInChance ( 1) : street1CBChance ( 1) : street1CBDone --- pyfpdb/DerivedStats.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index abbc4234..cd63e871 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -377,9 +377,9 @@ class DerivedStats(): if steal_attempt and act != 'folds': break - if not steal_attempt and not raised: # if posn in steal_positions and not steal_attempt: + if not steal_attempt and not raised and not act in ('bringin'): self.handsplayers[pname]['raiseFirstInChance'] = True - if act in ('bets', 'raises'): + if act in ('bets', 'raises', 'completes'): self.handsplayers[pname]['raisedFirstIn'] = True raised = True if posn in steal_positions: @@ -387,7 +387,7 @@ class DerivedStats(): if act == 'calls': break - if posn not in steal_positions and act != 'folds': + if posn not in steal_positions and act not in ('folds', 'bringin'): break def calc34BetStreet0(self, hand): From 83b1a41c6e5603bd1160580c6f421d129fe8ac0a Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 13 Oct 2010 18:25:18 +0800 Subject: [PATCH 23/24] Regression: Verify and fix Stars.hp file after raisedFirstIn fix denny501 was the bringin - so no opportunity s0rrow was 'utg' and limped (bad s0rrow *smack*) --- .../Stars/Stud/7-StudHL-USD-0.04-0.08-200911.Cardtest.txt.hp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/regression-test-files/cash/Stars/Stud/7-StudHL-USD-0.04-0.08-200911.Cardtest.txt.hp b/pyfpdb/regression-test-files/cash/Stars/Stud/7-StudHL-USD-0.04-0.08-200911.Cardtest.txt.hp index 65bde96e..6bde0900 100644 --- a/pyfpdb/regression-test-files/cash/Stars/Stud/7-StudHL-USD-0.04-0.08-200911.Cardtest.txt.hp +++ b/pyfpdb/regression-test-files/cash/Stars/Stud/7-StudHL-USD-0.04-0.08-200911.Cardtest.txt.hp @@ -312,7 +312,7 @@ 'otherRaisedStreet3': False, 'otherRaisedStreet4': False, 'position': 'S', - 'raiseFirstInChance': True, + 'raiseFirstInChance': False, 'raisedFirstIn': False, 'rake': 0, 'sawShowdown': False, @@ -594,7 +594,7 @@ 'otherRaisedStreet3': True, 'otherRaisedStreet4': True, 'position': 6, - 'raiseFirstInChance': False, + 'raiseFirstInChance': True, 'raisedFirstIn': False, 'rake': 2, 'sawShowdown': True, From 4cb59175f7126ed3c206db481e96517b4cf5c4f0 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Sun, 24 Oct 2010 22:01:40 +0200 Subject: [PATCH 24/24] add missed _() --- pyfpdb/SplitHandHistory.py | 10 +++++----- pyfpdb/WinTables.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pyfpdb/SplitHandHistory.py b/pyfpdb/SplitHandHistory.py index 8be80e66..52c1d340 100644 --- a/pyfpdb/SplitHandHistory.py +++ b/pyfpdb/SplitHandHistory.py @@ -73,7 +73,7 @@ class SplitHandHistory: try: infile = codecs.open(self.in_path, 'r', kodec) except IOError: - print 'File not found' + print _('File not found') sys.exit(2) #Split with do_hands_per_file if archive and paragraphs if a regular hh @@ -83,7 +83,7 @@ class SplitHandHistory: nn += 1 check = self.do_hands_per_file(infile, nn) if check is None: - print '%s processed' % self.in_path + print _('%s processed' % self.in_path) break else: filenum = 0 @@ -102,7 +102,7 @@ class SplitHandHistory: def new_file(self, fileno=-1): if fileno < 1: - print 'Nope, will not work (fileno=%d)' % fileno + print _('Nope, will not work (fileno=%d)' % fileno) sys.exit(2) basename = os.path.splitext(os.path.basename(self.in_path))[0] name = os.path.join(self.out_path, basename+'-%06d.txt' % fileno) @@ -123,7 +123,7 @@ class SplitHandHistory: done = True break except: - print "Unexpected error processing file" + print _("Unexpected error processing file") sys.exit(2) n += 1 outfile.close() @@ -162,7 +162,7 @@ class SplitHandHistory: #print l, len(l) # Catch EOF if len(l) == 0: - raise FpdbEndOfFile("End of file reached") + raise FpdbEndOfFile(_("End of file reached")) m = re_SplitArchive.search(l) # There is an empty line after pre-hand header and actual HH entry l = infile.readline() diff --git a/pyfpdb/WinTables.py b/pyfpdb/WinTables.py index 391f70c7..f6ddd93b 100644 --- a/pyfpdb/WinTables.py +++ b/pyfpdb/WinTables.py @@ -67,7 +67,7 @@ class Table(Table_Window): try: if self.window == None: - log.error("Window %s not found. Skipping." % self.search_string) + log.error(_("Window %s not found. Skipping." % self.search_string)) return None except AttributeError: log.error(_("self.window doesn't exist? why?"))