From 9cf75f7303c4fe73fc3647a1198d5f4aac2cf1a1 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Mon, 1 Feb 2010 08:47:55 -0500 Subject: [PATCH 01/24] fix getTableTitleRe calling in HUD_main:read_stdin, to use site_name (currently processing site name) instead of "site" which was always last site_name on list (this may break some people's HHC's, now that it works right) --- pyfpdb/HUD_main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index df144e92..71b7c03e 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -268,7 +268,7 @@ class HUD_main(object): cards['common'] = comm_cards['common'] table_kwargs = dict(table_name = table_name, tournament = tour_number, table_number = tab_number) - search_string = getTableTitleRe(self.config, site, type, **table_kwargs) + search_string = getTableTitleRe(self.config, site_name, type, **table_kwargs) tablewindow = Tables.Table(search_string, **table_kwargs) if tablewindow is None: From 27f95c51b2670f42767a4d469e36d1dda4ce97e9 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Mon, 1 Feb 2010 08:48:28 -0500 Subject: [PATCH 02/24] whitespace --- pyfpdb/HandHistoryConverter.py | 47 ++++++++++++++++------------------ 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index bec2ebae..9047af50 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -64,7 +64,7 @@ out_path (default '-' = sys.stdout) follow : whether to tail -f the input""" log.info("HandHistory init - %s subclass, in_path '%s'; out_path '%s'" % (self.sitename, in_path, out_path) ) - + self.index = index self.starsArchive = starsArchive @@ -77,7 +77,7 @@ follow : whether to tail -f the input""" # Tourney object used to store TourneyInfo when called to deal with a Summary file self.tourney = None - + if in_path == '-': self.in_fh = sys.stdin @@ -106,7 +106,7 @@ follow : whether to tail -f the input""" self.follow = follow self.compiledPlayers = set() self.maxseats = 10 - + self.status = True self.parsedObjectType = "HH" #default behaviour : parsing HH files, can be "Summary" if the parsing encounters a Summary File @@ -121,7 +121,7 @@ HandHistoryConverter: '%(sitename)s' in_path '%(in_path)s' out_path '%(out_path)s' follow '%(follow)s' - """ % locals() + """ % locals() def start(self): """Process a hand at a time from the input specified by in_path. @@ -141,7 +141,7 @@ Otherwise, finish at EOF. self.numHands = 0 self.numErrors = 0 if self.follow: - #TODO: See how summary files can be handled on the fly (here they should be rejected as before) + #TODO: See how summary files can be handled on the fly (here they should be rejected as before) log.info("Tailing '%s'" % self.in_path) for handText in self.tailHands(): try: @@ -176,7 +176,7 @@ Otherwise, finish at EOF. endtime = time.time() if summaryParsingStatus : log.info("Summary file '%s' correctly parsed (took %.3f seconds)" % (self.in_path, endtime - starttime)) - else : + else : log.warning("Error converting summary file '%s' (took %.3f seconds)" % (self.in_path, endtime - starttime)) except IOError, ioe: @@ -230,7 +230,7 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py. # x-- [x,--,] x,-- # x--x [x,--,x] x,x # x--x-- [x,--,x,--,] x,x,-- - + # The length is always odd. # 'odd' indices are always splitters. # 'even' indices are always paragraphs or '' @@ -264,13 +264,13 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py. log.info("Read no hands.") return [] return re.split(self.re_SplitHands, self.obs) - + def processHand(self, handText): gametype = self.determineGameType(handText) log.debug("gametype %s" % gametype) hand = None l = None - if gametype is None: + if gametype is None: gametype = "unmatched" # TODO: not ideal, just trying to not error. # TODO: Need to count failed hands. @@ -304,7 +304,7 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py. # This function should return a list of lists looking like: # return [["ring", "hold", "nl"], ["tour", "hold", "nl"]] # Showing all supported games limits and types - + def readSupportedGames(self): abstract # should return a list @@ -339,17 +339,17 @@ or None if we fail to get the info """ # Needs to return a list of lists in the format # [['seat#', 'player1name', 'stacksize'] ['seat#', 'player2name', 'stacksize'] [...]] def readPlayerStacks(self, hand): abstract - + def compilePlayerRegexs(self): abstract """Compile dynamic regexes -- these explicitly match known player names and must be updated if a new player joins""" - + # Needs to return a MatchObject with group names identifying the streets into the Hand object # so groups are called by street names 'PREFLOP', 'FLOP', 'STREET2' etc # blinds are done seperately def markStreets(self, hand): abstract #Needs to return a list in the format - # ['player1name', 'player2name', ...] where player1name is the sb and player2name is bb, + # ['player1name', 'player2name', ...] where player1name is the sb and player2name is bb, # addtional players are assumed to post a bb oop def readBlinds(self, hand): abstract def readAntes(self, hand): abstract @@ -362,16 +362,16 @@ or None if we fail to get the info """ def readShownCards(self, hand): abstract # Some sites do odd stuff that doesn't fall in to the normal HH parsing. - # e.g., FTP doesn't put mixed game info in the HH, but puts in in the + # e.g., FTP doesn't put mixed game info in the HH, but puts in in the # file name. Use readOther() to clean up those messes. def readOther(self, hand): pass - + # Some sites don't report the rake. This will be called at the end of the hand after the pot total has been calculated # an inheriting class can calculate it for the specific site if need be. def getRake(self, hand): hand.rake = hand.totalpot - hand.totalcollected # * Decimal('0.05') # probably not quite right - - + + def sanityCheck(self): """Check we aren't going to do some stupid things""" #TODO: the hhbase stuff needs to be in fpdb_import @@ -396,7 +396,7 @@ or None if we fail to get the info """ # Make sure input and output files are different or we'll overwrite the source file if True: # basically.. I don't know sane = True - + if self.in_path != '-' and self.out_path == self.in_path: print "HH Sanity Check: output and input files are the same, check config" sane = False @@ -429,7 +429,7 @@ or None if we fail to get the info """ def readFile(self): """Open in_path according to self.codepage. Exceptions caught further up""" - + if self.filetype == "text": if self.in_path == '-': # read from stdin @@ -464,7 +464,7 @@ or None if we fail to get the info """ if hand.gametype['base'] == 'stud': if mo <= 8: return 8 - else: return mo + else: return mo if hand.gametype['base'] == 'draw': if mo <= 6: return 6 @@ -500,9 +500,9 @@ or None if we fail to get the info """ def getParsedObjectType(self): return self.parsedObjectType - #returns a status (True/False) indicating wether the parsing could be done correctly or not + #returns a status (True/False) indicating wether the parsing could be done correctly or not def readSummaryInfo(self, summaryInfoList): abstract - + def getTourney(self): return self.tourney @@ -525,6 +525,3 @@ def getSiteHhc(config, sitename): hhcName = config.supported_sites[sitename].converter hhcModule = __import__(hhcName) return getattr(hhcModule, hhcName[:-6]) - - - From 1656a0e6d1933b72198bc5bdfadd7d4275036f54 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Mon, 1 Feb 2010 08:51:06 -0500 Subject: [PATCH 03/24] Everleaf: adjust Everleaf regexs to support tournaments, add error printing on failure of compilePlayerRegexs, add ring omahahilo pl and tour hold nl to supported games list, determine tournament number/table number from processing filename, fix getTableTitleRe --- pyfpdb/EverleafToFpdb.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index ad9d0524..c9206ea5 100755 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -38,8 +38,9 @@ class Everleaf(HandHistoryConverter): #re.compile(ur"^(Blinds )?(?P\$| €|)(?P[.0-9]+)/(?:\$| €)?(?P[.0-9]+) (?PNL|PL|) (?P(Hold\'em|Omaha|7 Card Stud))", re.MULTILINE) re_HandInfo = re.compile(ur".*#(?P[0-9]+)\n.*\n(Blinds )?(?:\$| €|)(?P[.0-9]+)/(?:\$| €|)(?P[.0-9]+) (?P.*) - (?P\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P.+$)", re.MULTILINE) re_Button = re.compile(ur"^Seat (?P
[0-9]+)\.txt") def compilePlayerRegexs(self, hand): @@ -55,18 +56,25 @@ class Everleaf(HandHistoryConverter): self.re_Antes = re.compile(ur"^%s: posts ante \[(?:\$| €|) (?P[.0-9]+)" % player_re, re.MULTILINE) self.re_BringIn = re.compile(ur"^%s posts bring-in (?:\$| €|)(?P[.0-9]+)\." % player_re, re.MULTILINE) self.re_HeroCards = re.compile(ur"^Dealt to %s \[ (?P.*) \]" % player_re, re.MULTILINE) - self.re_Action = re.compile(ur"^%s(?P: bets| checks| raises| calls| folds)(\s\[(?:\$| €|) (?P[.\d]+) (USD|EUR|)\])?" % player_re, re.MULTILINE) + self.re_Action = re.compile(ur"^%s(?P: bets| checks| raises| calls| folds)(\s\[(?:\$| €|) (?P[.,\d]+) (USD|EUR|Chips)\])?" % player_re, re.MULTILINE) #self.re_Action = re.compile(ur"^%s(?P: bets| checks| raises| calls| folds| complete to)(\s\[?(?:\$| €|) ?(?P\d+\.?\d*)\.?\s?(USD|EUR|)\]?)?" % player_re, re.MULTILINE) self.re_ShowdownAction = re.compile(ur"^%s shows \[ (?P.*) \]" % player_re, re.MULTILINE) self.re_CollectPot = re.compile(ur"^%s wins (?:\$| €|) (?P[.\d]+) (USD|EUR|chips)(.*?\[ (?P.*?) \])?" % player_re, re.MULTILINE) self.re_SitsOut = re.compile(ur"^%s sits out" % player_re, re.MULTILINE) + else: + print "*** EverleafToFpdb: compilePlayerRegexs failed" + print players + print self.compiledPlayers + def readSupportedGames(self): return [["ring", "hold", "nl"], ["ring", "hold", "pl"], ["ring", "hold", "fl"], ["ring", "studhi", "fl"], - ["ring", "omahahi", "pl"] + ["ring", "omahahi", "pl"], + ["ring", "omahahilo", "pl"], + ["tour", "hold", "nl"] ] def determineGameType(self, handText): @@ -138,6 +146,13 @@ or None if we fail to get the info """ hand.tablename = m.group('TABLE') hand.maxseats = 6 # assume 6-max unless we have proof it's a larger/smaller game, since everleaf doesn't give seat max info + t = self.re_TourneyInfoFromFilename.search(self.in_path) + if t: + tourno = t.group('TOURNO') + if tourno: # we're a tourney, yay + hand.tourNo = tourno + hand.tablename = t.group('TABLE') + # Believe Everleaf time is GMT/UTC, no transation necessary # Stars format (Nov 10 2008): 2008/11/07 12:38:49 CET [2008/11/07 7:38:49 ET] # or : 2008/11/07 12:38:49 ET @@ -287,7 +302,9 @@ or None if we fail to get the info """ @staticmethod def getTableTitleRe(type, table_name=None, tournament = None, table_number=None): - return "^%s -" % (table_name) + if tournament: + return "%s - Tournament ID: %s -" % (table_number, tournament) + return "%s -" % (table_name) From e3be7db2a0631d875188b6ee22855535b8694f18 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Mon, 1 Feb 2010 09:17:42 -0500 Subject: [PATCH 04/24] fix bug i introduced that caused everleaf cash hands to fail --- pyfpdb/EverleafToFpdb.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index c9206ea5..fe17f158 100755 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -149,7 +149,6 @@ or None if we fail to get the info """ t = self.re_TourneyInfoFromFilename.search(self.in_path) if t: tourno = t.group('TOURNO') - if tourno: # we're a tourney, yay hand.tourNo = tourno hand.tablename = t.group('TABLE') From 81ff8e632cc483b0cc53678dd0c818734c8d7e7e Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Mon, 1 Feb 2010 09:41:33 -0500 Subject: [PATCH 05/24] remove my misunderstanding of how compileplayerregexs worked --- pyfpdb/EverleafToFpdb.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index fe17f158..fdc35bf6 100755 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -62,11 +62,6 @@ class Everleaf(HandHistoryConverter): self.re_CollectPot = re.compile(ur"^%s wins (?:\$| €|) (?P[.\d]+) (USD|EUR|chips)(.*?\[ (?P.*?) \])?" % player_re, re.MULTILINE) self.re_SitsOut = re.compile(ur"^%s sits out" % player_re, re.MULTILINE) - else: - print "*** EverleafToFpdb: compilePlayerRegexs failed" - print players - print self.compiledPlayers - def readSupportedGames(self): return [["ring", "hold", "nl"], ["ring", "hold", "pl"], From eff216919dd7ad03bdfe9a7500438c1c46ac6a80 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Mon, 1 Feb 2010 09:57:28 -0500 Subject: [PATCH 06/24] Everleaf: Change "EUR"(old) to "EURO"(new), still doesn't seem to allow eur import (is that because my site config is set for usd ?) --- pyfpdb/EverleafToFpdb.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index fdc35bf6..5dd8d041 100755 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -38,7 +38,7 @@ class Everleaf(HandHistoryConverter): #re.compile(ur"^(Blinds )?(?P\$| €|)(?P[.0-9]+)/(?:\$| €)?(?P[.0-9]+) (?PNL|PL|) (?P(Hold\'em|Omaha|7 Card Stud))", re.MULTILINE) re_HandInfo = re.compile(ur".*#(?P[0-9]+)\n.*\n(Blinds )?(?:\$| €|)(?P[.0-9]+)/(?:\$| €|)(?P[.0-9]+) (?P.*) - (?P\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P
.+$)", re.MULTILINE) re_Button = re.compile(ur"^Seat (?P
[0-9]+)\.txt") @@ -56,10 +56,10 @@ class Everleaf(HandHistoryConverter): self.re_Antes = re.compile(ur"^%s: posts ante \[(?:\$| €|) (?P[.0-9]+)" % player_re, re.MULTILINE) self.re_BringIn = re.compile(ur"^%s posts bring-in (?:\$| €|)(?P[.0-9]+)\." % player_re, re.MULTILINE) self.re_HeroCards = re.compile(ur"^Dealt to %s \[ (?P.*) \]" % player_re, re.MULTILINE) - self.re_Action = re.compile(ur"^%s(?P: bets| checks| raises| calls| folds)(\s\[(?:\$| €|) (?P[.,\d]+) (USD|EUR|Chips)\])?" % player_re, re.MULTILINE) + self.re_Action = re.compile(ur"^%s(?P: bets| checks| raises| calls| folds)(\s\[(?:\$| €|) (?P[.,\d]+) (USD|EURO|Chips)\])?" % player_re, re.MULTILINE) #self.re_Action = re.compile(ur"^%s(?P: bets| checks| raises| calls| folds| complete to)(\s\[?(?:\$| €|) ?(?P\d+\.?\d*)\.?\s?(USD|EUR|)\]?)?" % player_re, re.MULTILINE) self.re_ShowdownAction = re.compile(ur"^%s shows \[ (?P.*) \]" % player_re, re.MULTILINE) - self.re_CollectPot = re.compile(ur"^%s wins (?:\$| €|) (?P[.\d]+) (USD|EUR|chips)(.*?\[ (?P.*?) \])?" % player_re, re.MULTILINE) + self.re_CollectPot = re.compile(ur"^%s wins (?:\$| €|) (?P[.\d]+) (USD|EURO|chips)(.*?\[ (?P.*?) \])?" % player_re, re.MULTILINE) self.re_SitsOut = re.compile(ur"^%s sits out" % player_re, re.MULTILINE) def readSupportedGames(self): From aea7db22e367bee92eda58ebc72e2ef3808333d0 Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Mon, 1 Feb 2010 18:37:36 -0500 Subject: [PATCH 07/24] Options for logging level and version. Not connected yet. --- pyfpdb/Options.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Options.py b/pyfpdb/Options.py index ab226124..6570dbe4 100644 --- a/pyfpdb/Options.py +++ b/pyfpdb/Options.py @@ -15,9 +15,9 @@ #In the "official" distribution you can find the license in #agpl-3.0.txt in the docs folder of the package. -import os import sys from optparse import OptionParser +# http://docs.python.org/library/optparse.html def fpdb_options(): @@ -41,6 +41,14 @@ def fpdb_options(): parser.add_option("-k", "--konverter", dest="hhc", default="PokerStarsToFpdb", help="Module name for Hand History Converter") + parser.add_option("-l", "--logging", + dest = "log_level", + choices = ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL', 'EMPTY'), + help = "Error logging level. (DEBUG, INFO, WARNING, ERROR, CRITICAL, EMPTY)", + default = 'EMPTY') + parser.add_option("-v", "--version", action = "store_true", + help = "Print version information and exit.") + (options, argv) = parser.parse_args() return (options, argv) From 76f9517655da8881aaabef57996f80254d1a60c2 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Tue, 2 Feb 2010 14:54:27 -0500 Subject: [PATCH 08/24] WinTables will no longer accept trying to attach to "FPDBHUD" titled windows --- pyfpdb/WinTables.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyfpdb/WinTables.py b/pyfpdb/WinTables.py index f834eac9..5bca9e41 100644 --- a/pyfpdb/WinTables.py +++ b/pyfpdb/WinTables.py @@ -50,10 +50,12 @@ class Table(Table_Window): titles = {} win32gui.EnumWindows(win_enum_handler, titles) for hwnd in titles: + # print "searching ", search_string, " in ", titles[hwnd] if re.search(search_string, titles[hwnd]): if 'History for table:' in titles[hwnd]: continue # Everleaf Network HH viewer window if 'HUD:' in titles[hwnd]: continue # FPDB HUD window if 'Chat:' in titles[hwnd]: continue # Some sites (FTP? PS? Others?) have seperable or seperately constructed chat windows + if 'FPDBHUD' in titles[hwnd]: continue # can't attach to ourselves! self.window = hwnd break From 9dfa0967b8fc571650ab2241a496720f281085fe Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Thu, 4 Feb 2010 13:08:26 -0500 Subject: [PATCH 09/24] Correct data files. --- pyfpdb/py2exe_setup.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pyfpdb/py2exe_setup.py b/pyfpdb/py2exe_setup.py index 9565ac0b..1e1ddc6b 100644 --- a/pyfpdb/py2exe_setup.py +++ b/pyfpdb/py2exe_setup.py @@ -58,8 +58,8 @@ setup( options = {'py2exe': { 'packages' :'encodings', - 'includes' : 'cairo, pango, pangocairo, atk, gobject, PokerStarsToFpdb', - 'excludes' : '_tkagg, _agg2, cocoaagg, fltkagg', + 'includes' : 'cairo, pango, pangocairo, atk, gobject, PokerStarsToFpdb, FulltiltToFpdb', + 'excludes' : '_tkagg, _agg2, cocoaagg, fltkagg', 'dll_excludes': 'libglade-2.0-0.dll', } }, @@ -67,7 +67,9 @@ setup( data_files = ['HUD_config.xml.example', 'Cards01.png', 'logging.conf', - (r'matplotlibdata', glob.glob(r'c:\python26\Lib\site-packages\matplotlib\mpl-data\*')) + (r'mpl-data', [r'C:\Python25\Lib\site-packages\matplotlib\mpl-data\matplotlibrc']), + (r'mpl-data\images', glob.glob(r'C:\Python25\Lib\site-packages\matplotlib\mpl-data\images\*.*')), + (r'mpl-data\fonts', glob.glob(r'C:\Python25\Lib\site-packages\matplotlib\mpl-data\fonts\*.*')),) ] ) From c10665935fba50b1844cddda23f3dd7bde2beff4 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Thu, 4 Feb 2010 16:33:21 -0500 Subject: [PATCH 10/24] stop clobbering search_string in TableWindow::__init__ . Thanks Ray! --- pyfpdb/HUD_main.py | 1 + pyfpdb/TableWindow.py | 22 +++++++++++----------- pyfpdb/WinTables.py | 1 + 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index 1251c2f0..0a365850 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -273,6 +273,7 @@ class HUD_main(object): table_kwargs = dict(table_name = table_name, tournament = tour_number, table_number = tab_number) search_string = getTableTitleRe(self.config, site_name, type, **table_kwargs) + # print "getTableTitleRe ", self.config, site_name, type, "=", search_string tablewindow = Tables.Table(search_string, **table_kwargs) if tablewindow is None: diff --git a/pyfpdb/TableWindow.py b/pyfpdb/TableWindow.py index 10607b16..aa994bfe 100644 --- a/pyfpdb/TableWindow.py +++ b/pyfpdb/TableWindow.py @@ -11,12 +11,12 @@ of Table_Window objects representing the windows found. # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. -# +# # 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 General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -58,7 +58,7 @@ bad_words = ('History for table:', 'HUD:', 'Chat:') # Here are the custom signals we define for allowing the 'client watcher' # thread to communicate with the gui thread. Any time a poker client is -# is moved, resized, or closed on of these signals is emitted to the +# is moved, resized, or closed on of these signals is emitted to the # HUD main window. gobject.signal_new("client_moved", gtk.Window, gobject.SIGNAL_RUN_LAST, @@ -80,16 +80,16 @@ gobject.signal_new("client_destroyed", gtk.Window, # from the corresponding hand history. # tw.site = the site name, e.g. PokerStars, FullTilt. This must match the site # name specified in the config file. -# tw.number = This is the system id number for the client table window in the +# tw.number = This is the system id number for the client table window in the # format that the system presents it. This is Xid in Xwindows and # hwnd in Microsoft Windows. # tw.title = The full title from the window title bar. -# tw.width, tw.height = The width and height of the window in pixels. This is -# the internal width and height, not including the title bar and +# tw.width, tw.height = The width and height of the window in pixels. This is +# the internal width and height, not including the title bar and # window borders. -# tw.x, tw.y = The x, y (horizontal, vertical) location of the window relative +# tw.x, tw.y = The x, y (horizontal, vertical) location of the window relative # to the top left of the display screen. This also does not include the -# title bar and window borders. To put it another way, this is the +# title bar and window borders. To put it another way, this is the # screen location of (0, 0) in the working window. class Table_Window(object): @@ -101,7 +101,7 @@ class Table_Window(object): self.table = int(table_number) self.name = "%s - %s" % (self.tournament, self.table) elif table_name is not None: - search_string = table_name + # search_string = table_name self.name = table_name self.tournament = None else: @@ -111,7 +111,7 @@ class Table_Window(object): def __str__(self): # __str__ method for testing - likely_attrs = ("site", "number", "title", "width", "height", "x", "y", + likely_attrs = ("site", "number", "title", "width", "height", "x", "y", "tournament", "table", "gdkhandle") temp = 'TableWindow object\n' for a in likely_attrs: @@ -125,7 +125,7 @@ class Table_Window(object): for game, names in game_names.iteritems(): for name in names: if name in title: - return game + return game return None def check_geometry(self): diff --git a/pyfpdb/WinTables.py b/pyfpdb/WinTables.py index 5bca9e41..255238f4 100644 --- a/pyfpdb/WinTables.py +++ b/pyfpdb/WinTables.py @@ -50,6 +50,7 @@ class Table(Table_Window): titles = {} win32gui.EnumWindows(win_enum_handler, titles) for hwnd in titles: + if titles[hwnd] == "": continue # print "searching ", search_string, " in ", titles[hwnd] if re.search(search_string, titles[hwnd]): if 'History for table:' in titles[hwnd]: continue # Everleaf Network HH viewer window From fde72003f7ec49021623c00f076cdbd3104e7cde Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 5 Feb 2010 11:44:27 +0800 Subject: [PATCH 11/24] test2.py - Add more tests Added most imports, and printed some formatted output for assiting diagnosis of new user installs --- pyfpdb/test2.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/pyfpdb/test2.py b/pyfpdb/test2.py index 74ce1e72..8acdb089 100755 --- a/pyfpdb/test2.py +++ b/pyfpdb/test2.py @@ -22,12 +22,36 @@ Test if gtk is working. ######################################################################## import sys +import os try: + import gobject as _gobject + print "Import of gobject:\tSuccess" import pygtk + print "Import of pygtk:\tSuccess" pygtk.require('2.0') import gtk + print "Import of gtk:\t\tSuccess" + import pango + print "Import of pango:\tSuccess" + if os.name == 'nt': + import win32 + import win32api + print "Import of win32:\tSuccess" + + try: + import matplotlib + matplotlib.use('GTK') + print "Import of matplotlib:\tSuccess" + import numpy + print "Import of numpy:\tSuccess" + import pylab + print "Import of pylab:\tSuccess" + except: + print "\nError:", sys.exc_info() + print "\npress return to finish" + sys.stdin.readline() win = gtk.Window(gtk.WINDOW_TOPLEVEL) win.set_title("Test GTK") From ab693e3b3c0010b966a8d3ab9bb0fc5639ab16d3 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 5 Feb 2010 11:51:12 +0800 Subject: [PATCH 12/24] test_PokerStars.py - Fix calls to HHC. sqlcoder added config as a parameter to HHC and Hand --- pyfpdb/test_PokerStars.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/test_PokerStars.py b/pyfpdb/test_PokerStars.py index 4244f532..588368ab 100755 --- a/pyfpdb/test_PokerStars.py +++ b/pyfpdb/test_PokerStars.py @@ -27,9 +27,9 @@ settings.update(config.get_default_paths()) gametype = {'type':'ring', 'base':'draw', 'category':'badugi', 'limitType':'fl', 'sb':'0.25', 'bb':'0.50','currency':'USD'} text = "" -hhc = PokerStarsToFpdb.PokerStars(autostart=False) +hhc = PokerStarsToFpdb.PokerStars(config, autostart=False) -h = HoldemOmahaHand(None, "PokerStars", gametype, text, builtFrom = "Test") +h = HoldemOmahaHand(config, None, "PokerStars", gametype, text, builtFrom = "Test") h.addPlayer("1", "s0rrow", "100000") hhc.compilePlayerRegexs(h) @@ -39,7 +39,7 @@ def checkGameInfo(hhc, header, info): assert hhc.determineGameType(header) == info def testGameInfo(): - hhc = PokerStarsToFpdb.PokerStars(autostart=False) + hhc = PokerStarsToFpdb.PokerStars(config, autostart=False) pairs = ( (u"PokerStars Game #20461877044: Hold'em No Limit ($1/$2) - 2008/09/16 18:58:01 ET", {'type':'ring', 'base':"hold", 'category':'holdem', 'limitType':'nl', 'sb':'1', 'bb':'2', 'currency':'USD'}), From ac458386da2291de86eaee97cade229ecda45167 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 5 Feb 2010 21:29:07 +0800 Subject: [PATCH 13/24] Add config path to test2.py display --- pyfpdb/test2.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyfpdb/test2.py b/pyfpdb/test2.py index 8acdb089..7dea96f6 100755 --- a/pyfpdb/test2.py +++ b/pyfpdb/test2.py @@ -23,6 +23,9 @@ Test if gtk is working. import sys import os +import Configuration + +config_path = Configuration.get_default_config_path() try: import gobject as _gobject @@ -66,7 +69,7 @@ try: (gtk.STOCK_CLOSE, gtk.RESPONSE_OK)) dia.set_default_size(500, 300) - l = gtk.Label("GTK is working!") + l = gtk.Label("GTK is working!\nConfig location: %s" %config_path) dia.vbox.add(l) l.show() From 5c26fee853dd96a071d86d42765a3e6445a94a4a Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Fri, 5 Feb 2010 08:58:47 -0500 Subject: [PATCH 14/24] handle mysql error on close if connection was timed out --- pyfpdb/fpdb.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 5bef3503..7a000981 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -802,8 +802,11 @@ class fpdb: # TODO: can we get some / all of the stuff done in this function to execute on any kind of abort? print "Quitting normally" # TODO: check if current settings differ from profile, if so offer to save or abort - if self.db is not None and self.db.connected: - self.db.disconnect() + try: + if self.db is not None and self.db.connected: + self.db.disconnect() + except _mysql_exceptions.OperationalError: # oh, damn, we're already disconnected + pass self.statusIcon.set_visible(False) gtk.main_quit() From 08078cfee4dd50e84a92e71b0d92725695e18eb0 Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Fri, 5 Feb 2010 23:03:55 -0500 Subject: [PATCH 15/24] Configure for python 2.5. Add icon for fpdb.exe. --- pyfpdb/py2exe_setup.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyfpdb/py2exe_setup.py b/pyfpdb/py2exe_setup.py index 1e1ddc6b..6391194f 100644 --- a/pyfpdb/py2exe_setup.py +++ b/pyfpdb/py2exe_setup.py @@ -45,13 +45,14 @@ Py2exe script for fpdb. from distutils.core import setup import py2exe +import glob setup( name = 'fpdb', description = 'Free Poker DataBase', version = '0.12', - console = [ {'script': 'fpdb.py', }, + console = [ {'script': 'fpdb.py', "icon_resources": [(1, "../gfx/fpdb_large_icon.ico")]}, {'script': 'HUD_main.py', }, {'script': 'Configuration.py', } ], @@ -69,7 +70,7 @@ setup( 'logging.conf', (r'mpl-data', [r'C:\Python25\Lib\site-packages\matplotlib\mpl-data\matplotlibrc']), (r'mpl-data\images', glob.glob(r'C:\Python25\Lib\site-packages\matplotlib\mpl-data\images\*.*')), - (r'mpl-data\fonts', glob.glob(r'C:\Python25\Lib\site-packages\matplotlib\mpl-data\fonts\*.*')),) + (r'mpl-data\fonts', glob.glob(r'C:\Python25\Lib\site-packages\matplotlib\mpl-data\fonts\*.*')), ] ) From 4df991517e0fdd22e1013438ece31f7dc4624294 Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Fri, 5 Feb 2010 23:13:53 -0500 Subject: [PATCH 16/24] Changes to make the py2exe exe happy. --- pyfpdb/Configuration.py | 13 ++++++++++++- pyfpdb/GuiAutoImport.py | 7 ++++++- 2 files changed, 18 insertions(+), 2 deletions(-) mode change 100755 => 100644 pyfpdb/Configuration.py mode change 100755 => 100644 pyfpdb/GuiAutoImport.py diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py old mode 100755 new mode 100644 index ec4c621e..f87cd049 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -166,6 +166,10 @@ if LOCALE_ENCODING == "US-ASCII": # needs LOCALE_ENCODING (above), imported for sqlite setup in Config class below + +FROZEN = hasattr(sys, "frozen") +EXEC_PATH = get_exec_path() + import Charset @@ -613,7 +617,8 @@ class Config: def save(self, file = None): if file is None: file = self.file - shutil.move(file, file+".backup") + shutil.move(file, file+".backup", ignore_errors = True) + with open(file, 'w') as f: self.doc.writexml(f) @@ -1030,3 +1035,9 @@ if __name__== "__main__": PrettyPrint(site_node, stream=sys.stdout, encoding="utf-8") except: print "xml.dom.ext needs PyXML to be installed!" + + print "FROZEN =", FROZEN + print "EXEC_PATH =", EXEC_PATH + + print "press enter to end" + sys.stdin.readline() diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py old mode 100755 new mode 100644 index 339ce968..f8150500 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -193,7 +193,11 @@ class GuiAutoImport (threading.Thread): self.doAutoImportBool = True widget.set_label(u' _Stop Autoimport ') if self.pipe_to_hud is None: - if os.name == 'nt': + if Configuration.FROZEN: + path = Configuration.EXEC_PATH + command = "HUD_main.exe" + bs = 0 + elif os.name == 'nt': path = sys.path[0].replace('\\','\\\\') command = 'python "'+path+'\\HUD_main.py" ' + self.settings['cl_options'] bs = 0 @@ -203,6 +207,7 @@ class GuiAutoImport (threading.Thread): bs = 1 try: + print "opening pipe to HUD" self.pipe_to_hud = subprocess.Popen(command, bufsize=bs, stdin=subprocess.PIPE, universal_newlines=True) From 8aa18b95d829781091eb585a27afd8291238a9cd Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Fri, 5 Feb 2010 23:19:58 -0500 Subject: [PATCH 17/24] Changes to make running py2exe exe happy. --- pyfpdb/Configuration.py | 13 +------------ pyfpdb/GuiAutoImport.py | 7 +------ 2 files changed, 2 insertions(+), 18 deletions(-) mode change 100644 => 100755 pyfpdb/Configuration.py mode change 100644 => 100755 pyfpdb/GuiAutoImport.py diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py old mode 100644 new mode 100755 index f87cd049..ec4c621e --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -166,10 +166,6 @@ if LOCALE_ENCODING == "US-ASCII": # needs LOCALE_ENCODING (above), imported for sqlite setup in Config class below - -FROZEN = hasattr(sys, "frozen") -EXEC_PATH = get_exec_path() - import Charset @@ -617,8 +613,7 @@ class Config: def save(self, file = None): if file is None: file = self.file - shutil.move(file, file+".backup", ignore_errors = True) - + shutil.move(file, file+".backup") with open(file, 'w') as f: self.doc.writexml(f) @@ -1035,9 +1030,3 @@ if __name__== "__main__": PrettyPrint(site_node, stream=sys.stdout, encoding="utf-8") except: print "xml.dom.ext needs PyXML to be installed!" - - print "FROZEN =", FROZEN - print "EXEC_PATH =", EXEC_PATH - - print "press enter to end" - sys.stdin.readline() diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py old mode 100644 new mode 100755 index f8150500..339ce968 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -193,11 +193,7 @@ class GuiAutoImport (threading.Thread): self.doAutoImportBool = True widget.set_label(u' _Stop Autoimport ') if self.pipe_to_hud is None: - if Configuration.FROZEN: - path = Configuration.EXEC_PATH - command = "HUD_main.exe" - bs = 0 - elif os.name == 'nt': + if os.name == 'nt': path = sys.path[0].replace('\\','\\\\') command = 'python "'+path+'\\HUD_main.py" ' + self.settings['cl_options'] bs = 0 @@ -207,7 +203,6 @@ class GuiAutoImport (threading.Thread): bs = 1 try: - print "opening pipe to HUD" self.pipe_to_hud = subprocess.Popen(command, bufsize=bs, stdin=subprocess.PIPE, universal_newlines=True) From 120d05f9cde9f0159b89f84807af36c4f91f6184 Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Sat, 6 Feb 2010 14:55:48 -0500 Subject: [PATCH 18/24] Changes for py2exe exe. --- pyfpdb/GuiAutoImport.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py index 339ce968..f8150500 100755 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -193,7 +193,11 @@ class GuiAutoImport (threading.Thread): self.doAutoImportBool = True widget.set_label(u' _Stop Autoimport ') if self.pipe_to_hud is None: - if os.name == 'nt': + if Configuration.FROZEN: + path = Configuration.EXEC_PATH + command = "HUD_main.exe" + bs = 0 + elif os.name == 'nt': path = sys.path[0].replace('\\','\\\\') command = 'python "'+path+'\\HUD_main.py" ' + self.settings['cl_options'] bs = 0 @@ -203,6 +207,7 @@ class GuiAutoImport (threading.Thread): bs = 1 try: + print "opening pipe to HUD" self.pipe_to_hud = subprocess.Popen(command, bufsize=bs, stdin=subprocess.PIPE, universal_newlines=True) From ac51876200743ea58f0af8c5d74cb7e01801b731 Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 7 Feb 2010 19:08:23 +0800 Subject: [PATCH 19/24] PokerStarsTo Fpdb: Fix subtle bug in re_Action The bet action could become multiline greedy if there was a playername starting with 'card' in the next line. """ danny purse: bets $0.50 cardjunkie25: calls $0.50 """ Would match "danny purse: bets $0.50\ncard", and the rest of that line would be ignored. Added '$' to the end of the regex to make sure that it is limited to 1 line, and wrap 'cards' as a group. --- pyfpdb/PokerStarsToFpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index c2a92881..fc63be91 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -103,7 +103,7 @@ class PokerStars(HandHistoryConverter): self.re_Action = re.compile(r""" ^%(PLYR)s:(?P\sbets|\schecks|\sraises|\scalls|\sfolds|\sdiscards|\sstands\spat) (\s(%(CUR)s)?(?P[.\d]+))?(\sto\s%(CUR)s(?P[.\d]+))? # the number discarded goes in - (\scards?(\s\[(?P.+?)\])?)?""" + (\s(cards)?(\s\[(?P.+?)\])?)?$""" % subst, re.MULTILINE|re.VERBOSE) self.re_ShowdownAction = re.compile(r"^%s: shows \[(?P.*)\]" % player_re, re.MULTILINE) self.re_CollectPot = re.compile(r"Seat (?P[0-9]+): %(PLYR)s (\(button\) |\(small blind\) |\(big blind\) |\(button\) \(small blind\) )?(collected|showed \[.*\] and won) \(%(CUR)s(?P[.\d]+)\)(, mucked| with.*|)" % subst, re.MULTILINE) From ee66abfecc1bce5b59748b31f73cd856ef739c39 Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 7 Feb 2010 19:19:00 +0800 Subject: [PATCH 20/24] Revert "PokerStarsTo Fpdb: Fix subtle bug in re_Action" This reverts commit ac51876200743ea58f0af8c5d74cb7e01801b731. --- pyfpdb/PokerStarsToFpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index fc63be91..c2a92881 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -103,7 +103,7 @@ class PokerStars(HandHistoryConverter): self.re_Action = re.compile(r""" ^%(PLYR)s:(?P\sbets|\schecks|\sraises|\scalls|\sfolds|\sdiscards|\sstands\spat) (\s(%(CUR)s)?(?P[.\d]+))?(\sto\s%(CUR)s(?P[.\d]+))? # the number discarded goes in - (\s(cards)?(\s\[(?P.+?)\])?)?$""" + (\scards?(\s\[(?P.+?)\])?)?""" % subst, re.MULTILINE|re.VERBOSE) self.re_ShowdownAction = re.compile(r"^%s: shows \[(?P.*)\]" % player_re, re.MULTILINE) self.re_CollectPot = re.compile(r"Seat (?P[0-9]+): %(PLYR)s (\(button\) |\(small blind\) |\(big blind\) |\(button\) \(small blind\) )?(collected|showed \[.*\] and won) \(%(CUR)s(?P[.\d]+)\)(, mucked| with.*|)" % subst, re.MULTILINE) From b996a884debdc0568e78ed9312ce14ad099a746c Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 7 Feb 2010 19:21:32 +0800 Subject: [PATCH 21/24] PokerStarsTo? Fpdb: Fix subtle bug in re_Action The bet action could become multiline greedy if there was a playername starting with 'card' in the next line. """ danny purse: bets $0.50 cardjunkie25: calls $0.50 """ Would match "danny purse: bets $0.50\ncard", and the rest of that line would be ignored. Added '$' to the end of the regex to make sure that it is limited to 1 line --- pyfpdb/PokerStarsToFpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index c2a92881..90a8bfd0 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -103,7 +103,7 @@ class PokerStars(HandHistoryConverter): self.re_Action = re.compile(r""" ^%(PLYR)s:(?P\sbets|\schecks|\sraises|\scalls|\sfolds|\sdiscards|\sstands\spat) (\s(%(CUR)s)?(?P[.\d]+))?(\sto\s%(CUR)s(?P[.\d]+))? # the number discarded goes in - (\scards?(\s\[(?P.+?)\])?)?""" + (\scards?(\s\[(?P.+?)\])?)?$""" % subst, re.MULTILINE|re.VERBOSE) self.re_ShowdownAction = re.compile(r"^%s: shows \[(?P.*)\]" % player_re, re.MULTILINE) self.re_CollectPot = re.compile(r"Seat (?P[0-9]+): %(PLYR)s (\(button\) |\(small blind\) |\(big blind\) |\(button\) \(small blind\) )?(collected|showed \[.*\] and won) \(%(CUR)s(?P[.\d]+)\)(, mucked| with.*|)" % subst, re.MULTILINE) From e0777d6f0d110aabf4e3b34ee38f1ffe121dfaad Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Sun, 7 Feb 2010 12:36:41 -0500 Subject: [PATCH 22/24] Add windows icon file. --- gfx/fpdb_large_icon.ico | Bin 0 -> 4286 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 gfx/fpdb_large_icon.ico diff --git a/gfx/fpdb_large_icon.ico b/gfx/fpdb_large_icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..6be85f1ca732d527e4c63c29812295f762ec392c GIT binary patch literal 4286 zcmc&%2~bm67LC$^<=CUsMKd*J&1fr3Yqx9RD58j{xZ*ZUgBHq?AOZpbT0sz5TnL*A z0TK~qvjIUC7j|qw2p|}?ga9HU%Dzaz011-+?z|r>X{P{-vhA9mI=MIZzIV=j+y6fl z$}Id@vV=l@Q|>OLP}C?C%5n@GqHMz;VTr3T4d?YRWrwH0H|dFfraOcmFW^ zgNCY%dy(3_ul2OQOFr?F)-&pf-7DmRTQ{$kyI&LX}A;V z$-nIFxK^J0BkVsGEs)dB*5A4`+`)1?L|nH)1sS2JydV}r{OM8OtA9IR-snqOHPt^U z=yq)R&d;8vH^IJo3LZZUM%>c7kQC!R=xB4$SWR{QY(>K_uSp9}RNS0#SAOJ;+K86kD0? za{pW*0GLtNE&p1)+4QH4!@<7hkd@+($Z_YSU44I=w$Gm=m?_W4V)8zTiHU#B%gbNf z(o(6;;gqOnWo7@}$;s)f`1ts5-wNL?+pe=x%fxVf=haK5kde$lRh+wc+*i>VyCZ?0 zqphT*^l=%=Jv}{lM4~}XR#qeD?b}{%dwY9MbaeCvk!X|^9vWP1YOLKE;B5jA?_NP% zP6A}41c9f^F@~H(dCpgI_mfsbLt|22U0r>}(9mEnk2gjfIRcW5jPb#Vi4jR|-s7Y7 z_59k?wEe*FJcjq!MVWS1+I6^c!JM3P6_RY>g5S=?B=U~}78VwYUj_zyO$-j~dZ52+ zTeH?Ct#*BV{Ryp2+llX&pOS9a5cxbI;YCUOFSnd+Ec6Aw9!DYVjwgCnk^s36nBePa z5v8U&Z)T!cksPypoed2Q_n4ZVczyiXNvZL_*%Owg$?t#7EhpZzzJ!vZLfE%+=PS*% znxkvhtQ|8pGLCd}KH7FK<~&qB`2~t|BjH|r2t0jS;VK`9#`{O%pZ1O-JGrKH5rZEc0CR<4AzXI!{f(;XEE`+f3qGEn1fN?0SN+?NhuaWQS@sfZj{_l= zAVMMmkx&RJY&Ls<&kt_q^Sg=*3ShmaCeR(7UR*p+&A|KdEQiCP$Hm3{^Aoa@Qg(KB z`>tHNG}KU6hnE3B*gptyw*>(2M*$`#uzfGHBOml{bX8Y})K^t?lWm_oeheDw%S86} z*CLyndt%$$U&nE|Rof?tOcOZg=Jt*2*|U#gBO~EuQ`7j%h6Z5^pWn|ddD8QO$LnsY zsp)DYQCr(lU0&WD-b-w^P4hIU!T~=8-1~)x+c6?5?e44>vYm7d1Cu z@2RW1N#+Ixg4m}yIfdGrwn#NKlX&Uref52PZ8Oq$cXwCv^z`&%1_lzvnVB!kva_p7 z?%(GWr>8$DN=+>&NJ+_moSdASlaP>|6(67ZC^j~ur>2G_tgjC*N={C~zaM1B#oaG2 zD0pr~rAbz-FcWxqNN!YCKBZ3@=oA58217Y0Fz_L{hU7Z)xLl$*Kc6Vd%R_~^x$tXF z4m`=vhrym6*&ZNmL1JP89(!Cvb#))v2a$UNUxk=sAP}h$5gH16ckF;2 zIy%VK(h_9aWO4ZX3442?Bt1RrZA(l3i-v|_S z+SH*CCUac`iv?5@6WFPv1AF!K;K1(P=$N4)VR7OFVQp!NFo=?(BDwy67(a-+yE>&3 z@d!jky#v=X{fKIDlGwk0uin%u(?|US0v6tkh)8sGa)Lux_df>@qT@zJNTyArA$wa} z!pYtqb$4{Y*vJSp^7%tpf4IN5OIlka1Yh6x$lm%k&}h`E=~brA;OUbkZbn9KWrcMcjMT->C+fh+=VId(S4mLJmWnn?sT3Hc4)9HxCWTJlZ{3C?M z#bSKU8pd!P;+ig9S#n5CrK>_2ZxzTPHK1Y;zdOauf>)d zY<5f-lR2K0kN_NfHu2tGc2k@ANrqE-#W?SbWuBFff$xGOJ)L0FW*QkYEhyLYuc2 w20kf1Af+h5kPHi;4cnrR;EnwcP{CFO=SVD&p^dT__tOOl#S3%52Q_T|3&nkXv;Y7A literal 0 HcmV?d00001 From 94ab5849fa165b39d110beb6b7b0d2bb592deacd Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Sun, 7 Feb 2010 14:23:29 +0200 Subject: [PATCH 23/24] Modify display of 'n' in HUD for large numbers When sample size grows to larger than 1000, use "X.Yk" notation to show the approximate value. --- pyfpdb/Stats.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Stats.py b/pyfpdb/Stats.py index 18913eed..ab92c99f 100755 --- a/pyfpdb/Stats.py +++ b/pyfpdb/Stats.py @@ -245,8 +245,20 @@ def saw_f(stat_dict, player): def n(stat_dict, player): """ Number of hands played.""" try: + # If sample is large enough, use X.Yk notation instead + _n = stat_dict[player]['n'] + fmt = '%d' % _n + if _n >= 1000: + k = _n / 1000 + c = _n % 1000 + _c = float(c) / 100.0 + d = int(round(_c)) + if d == 10: + k += 1 + d = 0 + fmt = '%d.%dk' % (k, d) return (stat_dict[player]['n'], - '%d' % (stat_dict[player]['n']), + '%s' % fmt, 'n=%d' % (stat_dict[player]['n']), 'n=%d' % (stat_dict[player]['n']), '(%d)' % (stat_dict[player]['n']), From 965adc7b2760747368ae05236ad07fcc9f2e56ef Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Tue, 9 Feb 2010 18:51:37 -0500 Subject: [PATCH 24/24] Add EXEC_PATH to constants. --- pyfpdb/Configuration.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index ec4c621e..c3c93293 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -166,6 +166,10 @@ if LOCALE_ENCODING == "US-ASCII": # needs LOCALE_ENCODING (above), imported for sqlite setup in Config class below + +FROZEN = hasattr(sys, "frozen") +EXEC_PATH = get_exec_path() + import Charset @@ -613,7 +617,11 @@ class Config: def save(self, file = None): if file is None: file = self.file - shutil.move(file, file+".backup") + try: + shutil.move(file, file+".backup") + except: + pass + with open(file, 'w') as f: self.doc.writexml(f) @@ -1030,3 +1038,9 @@ if __name__== "__main__": PrettyPrint(site_node, stream=sys.stdout, encoding="utf-8") except: print "xml.dom.ext needs PyXML to be installed!" + + print "FROZEN =", FROZEN + print "EXEC_PATH =", EXEC_PATH + + print "press enter to end" + sys.stdin.readline()