From 88d67dc429b72ee9ed5ec7fa57f033676efb8d83 Mon Sep 17 00:00:00 2001 From: grindi Date: Sat, 8 Aug 2009 12:07:30 +0400 Subject: [PATCH 01/25] Fixed folder couldn't be displayed error in BulkImport --- pyfpdb/Configuration.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index e01a6b43..f7f31167 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +# -*- coding: utf-8 -*- """Configuration.py Handles HUD configuration files. @@ -542,6 +543,13 @@ class Config: if db_server != None: self.supported_databases[db_name].dp_server = db_server if db_type != None: self.supported_databases[db_name].dp_type = db_type return + + def getDefaultSite(self): + "Returns first enabled site or None" + for site_name,site in self.supported_sites.iteritems(): + if site.enabled: + return site_name + return None def get_tv_parameters(self): tv = {} @@ -573,14 +581,15 @@ class Config: except: imp['fastStoreHudCache'] = True return imp - def get_default_paths(self, site = "PokerStars"): + def get_default_paths(self, site = None): + if site is None: site = self.getDefaultSite() paths = {} try: - paths['hud-defaultPath'] = os.path.expanduser(self.supported_sites[site].HH_path) - paths['bulkImport-defaultPath'] = os.path.expanduser(self.supported_sites[site].HH_path) + path = os.path.expanduser(self.supported_sites[site].HH_path) + assert(os.path.isdir(path) or os.path.isfile(path)) # maybe it should try another site? + paths['hud-defaultPath'] = paths['bulkImport-defaultPath'] = path except: - paths['hud-defaultPath'] = "default" - paths['bulkImport-defaultPath'] = "default" + paths['hud-defaultPath'] = paths['bulkImport-defaultPath'] = "default" return paths def get_frames(self, site = "PokerStars"): From 5c468d0a3877fc4ab09344bb9bc6d5221f35dd96 Mon Sep 17 00:00:00 2001 From: grindi Date: Sat, 8 Aug 2009 15:47:58 +0400 Subject: [PATCH 02/25] Added party hh path into HUD_config.xml.example --- pyfpdb/HUD_config.xml.example | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index bd8cb7df..adc8141c 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -252,10 +252,10 @@ From 4074092f322dff53f1ce4bbe619a542e80f83c11 Mon Sep 17 00:00:00 2001 From: grindi Date: Sat, 8 Aug 2009 17:36:48 +0400 Subject: [PATCH 03/25] Removed .gitignore --- .gitignore | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 .gitignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index f3d74a9a..00000000 --- a/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.pyc -*~ From d6529ab42f4a1bc822d96a4ee88b424f0688d0dc Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 9 Aug 2009 01:59:44 +0800 Subject: [PATCH 04/25] Import Hand.insert() work storeHand updated, almost works, just violating some NOT NULL contraints --- pyfpdb/Database.py | 10 ++++++++-- pyfpdb/Hand.py | 6 ++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index d59c879c..6fb96507 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -28,6 +28,7 @@ import sys import traceback from datetime import datetime, date, time, timedelta from time import time, strftime, sleep +from decimal import Decimal import string import re import logging @@ -1127,6 +1128,7 @@ class Database: sitehandno, handstart, importtime, + seats, maxseats, boardcard1, boardcard2, @@ -1135,7 +1137,8 @@ class Database: boardcard5 ) VALUES - (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""" + (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, + %s, %s)""" #--- texture, #-- playersVpi, #-- playersAtStreet1, @@ -1156,14 +1159,17 @@ class Database: #-- seats, q = q.replace('%s', self.sql.query['placeholder']) + print "DEBUG: p: %s" %p + print "DEBUG: gtid: %s" % p['gameTypeId'] self.cursor.execute(q, ( p['tableName'], + p['gameTypeId'], p['siteHandNo'], - p['gametypeid'], p['handStart'], datetime.today(), #importtime # len(p['names']), #seats p['maxSeats'], + p['seats'], p['boardcard1'], p['boardcard2'], p['boardcard3'], diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 8c165bd9..c3bd93f0 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -197,10 +197,10 @@ db: a connected fpdb_db object""" hilo = "s" elif self.gametype['category'] in ['razz','27_3draw','badugi']: hilo = "l" - #FIXME - the two zeros are small_bet and big_bet for limit + gtid = db.insertGameTypes( (self.siteId, self.gametype['type'], self.gametype['base'], self.gametype['category'], self.gametype['limitType'], hilo, - self.gametype['sb'], self.gametype['bb'], 0, 0) ) + int(Decimal(self.gametype['sb'])*100), int(Decimal(self.gametype['bb'])*100), 0, 0) ) # HudCache data to come from DerivedStats class @@ -210,9 +210,11 @@ db: a connected fpdb_db object""" hh = {} hh['siteHandNo'] = self.handid hh['handStart'] = self.starttime + hh['gameTypeId'] = gtid[0] # seats TINYINT NOT NULL, hh['tableName'] = self.tablename hh['maxSeats'] = self.maxseats + hh['seats'] = len(sqlids) # boardcard1 smallint, /* 0=none, 1-13=2-Ah 14-26=2-Ad 27-39=2-Ac 40-52=2-As */ # boardcard2 smallint, # boardcard3 smallint, From f431a6307093d88fb7c19182b998af5eace508e5 Mon Sep 17 00:00:00 2001 From: eblade Date: Sat, 8 Aug 2009 15:58:30 -0400 Subject: [PATCH 05/25] badHangs -> badHands --- pyfpdb/HandHistoryConverter.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index fb7311ab..7d943ada 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -96,14 +96,14 @@ Otherwise, finish at eof. else: handsList = self.allHandsAsList() logging.info("Parsing %d hands" % len(handsList)) - nBadHangs = 0 + nBadHands = 0 for handText in handsList: try: self.processedHands.append(self.processHand(handText)) except Exception, e: # TODO: it's better to replace it with s-t like HhcEception - nBadHangs += 1 + nBadHands += 1 logging.error("Caught exception while parsing hand: %s" % str(e)) - numHands = len(handsList) - nBadHangs + numHands = len(handsList) - nBadHands endtime = time.time() print "read %d hands in %.3f seconds" % (numHands, endtime - starttime) if self.out_fh != sys.stdout: From c042bea1817a99a6639c4ecbd66be20d54e76d28 Mon Sep 17 00:00:00 2001 From: grindi Date: Sun, 9 Aug 2009 16:24:31 +0400 Subject: [PATCH 06/25] Improved table-by-name recognition for non-latin window titles What i mean: u'1464739' in 'Speed #1464739 - \xc1\xcb \xd5\xee\xeb\xe4\xe5\xec' -> Exception u'1464739' in 'Speed #1464739 - \xc1\xcb \xd5\xee\xeb\xe4\xe5\xec'.decode('cp1251') -> True --- pyfpdb/Tables.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Tables.py b/pyfpdb/Tables.py index 97a897ca..9fdc8630 100755 --- a/pyfpdb/Tables.py +++ b/pyfpdb/Tables.py @@ -230,11 +230,20 @@ def discover_nt_by_name(c, tablename): """Finds poker client window with the given table name.""" titles = {} win32gui.EnumWindows(win_enum_handler, titles) + + def getDefaultEncoding(): + # FIXME: if somebody know better place fot this function - move it + # FIXME: it's better to use GetCPInfo for windows http://msdn.microsoft.com/en-us/library/dd318078(VS.85).aspx + # but i have no idea, how to call it + import locale + return locale.getpreferredencoding() + for hwnd in titles: #print "Tables.py: tablename =", tablename, "title =", titles[hwnd] try: + # maybe it's better to make global titles[hwnd] decoding? # this can blow up in XP on some windows, eg firefox displaying http://docs.python.org/tutorial/classes.html - if not tablename.lower() in titles[hwnd].lower(): continue + if not tablename.lower() in titles[hwnd].decode(getDefaultEncoding()).lower(): continue except: continue if 'History for table:' in titles[hwnd]: continue # Everleaf Network HH viewer window From 730c82bc95613030559925cbac30e225ff7c0cc1 Mon Sep 17 00:00:00 2001 From: grindi Date: Sun, 9 Aug 2009 16:38:55 +0400 Subject: [PATCH 07/25] Party hhc: added max seats recognition --- pyfpdb/PartyPokerToFpdb.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pyfpdb/PartyPokerToFpdb.py b/pyfpdb/PartyPokerToFpdb.py index af1081df..81044e78 100644 --- a/pyfpdb/PartyPokerToFpdb.py +++ b/pyfpdb/PartyPokerToFpdb.py @@ -88,6 +88,7 @@ class PartyPoker(HandHistoryConverter): """, re.MULTILINE|re.VERBOSE) + re_TotalPlayers = re.compile("^Total\s+number\s+of\s+players\s*:\s*(?P\d+)", re.MULTILINE) re_SplitHands = re.compile('\x00+') re_TailSplitHands = re.compile('(\x00+)') lineSplitter = '\n' @@ -112,6 +113,8 @@ follow : whether to tail -f the input""" def allHandsAsList(self): list = HandHistoryConverter.allHandsAsList(self) + if list is None: + return None return filter(lambda text: len(text.strip()), list) def compilePlayerRegexs(self, hand): @@ -249,6 +252,9 @@ follow : whether to tail -f the input""" m = self.re_Hid.search(hand.handText) if m: info.update(m.groupdict()) + m = self.re_TotalPlayers.search(hand.handText) + if m: info.update(m.groupdict()) + # FIXME: it's a hack cause party doesn't supply hand.maxseats info #hand.maxseats = ??? hand.mixed = None @@ -281,6 +287,8 @@ follow : whether to tail -f the input""" #FIXME: it's dirty hack T_T cur = info[key][0] if info[key][0] not in '0123456789' else '' hand.buyin = info[key] + '+%s0' % cur + if key == 'MAXSEATS': + hand.maxseats = int(info[key]) if key == 'LEVEL': hand.level = info[key] if key == 'PLAY' and info['PLAY'] != 'Real': From a32d4e053a4df6d1d7a469307e5784d9e6fb3db2 Mon Sep 17 00:00:00 2001 From: Matt Turnbull Date: Sun, 9 Aug 2009 15:19:43 +0100 Subject: [PATCH 08/25] FulltiltToFpdb handles canceled hands Better exception handling during parsing FpdbParseEcxeption takes an optional HID Stripped pointless __init__s from *ToFpdb subclasses Logging now has logging.conf config - default is to log only INFO to file but easily changed to DEBUG for devel work --- pyfpdb/BetfairToFpdb.py | 18 ++--- pyfpdb/EverleafToFpdb.py | 23 ++---- pyfpdb/Exceptions.py | 5 +- pyfpdb/FulltiltToFpdb.py | 35 ++++----- pyfpdb/Hand.py | 51 ++++++------- pyfpdb/HandHistoryConverter.py | 133 +++++++++++++++++++++------------ pyfpdb/PartyPokerToFpdb.py | 19 ++--- pyfpdb/PokerStarsToFpdb.py | 26 ++----- pyfpdb/Win2dayToFpdb.py | 16 ++-- pyfpdb/test_FullTilt.py | 7 +- pyfpdb/test_PokerStars.py | 2 +- 11 files changed, 164 insertions(+), 171 deletions(-) diff --git a/pyfpdb/BetfairToFpdb.py b/pyfpdb/BetfairToFpdb.py index 1ccec5d0..59344991 100755 --- a/pyfpdb/BetfairToFpdb.py +++ b/pyfpdb/BetfairToFpdb.py @@ -26,6 +26,11 @@ from HandHistoryConverter import * class Betfair(HandHistoryConverter): + sitename = 'Betfair' + filetype = "text" + codepage = "cp1252" + siteId = 7 # Needs to match id entry in Sites database + # Static regexes re_GameInfo = re.compile("^(?PNL|PL|) (?P\$|)?(?P[.0-9]+)/\$?(?P[.0-9]+) (?P(Texas Hold\'em|Omaha Hi|Razz))", re.MULTILINE) re_SplitHands = re.compile(r'\n\n+') @@ -34,19 +39,6 @@ class Betfair(HandHistoryConverter): re_PlayerInfo = re.compile("Seat (?P[0-9]+): (?P.*)\s\(\s(\$(?P[.0-9]+)) \)") re_Board = re.compile(ur"\[ (?P.+) \]") - def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, index=0): - """\ -in_path (default '-' = sys.stdin) -out_path (default '-' = sys.stdout) -follow : whether to tail -f the input""" - HandHistoryConverter.__init__(self, in_path, out_path, sitename="Betfair", follow=follow, index) # Call super class init. - logging.info("Initialising Betfair converter class") - self.filetype = "text" - self.codepage = "cp1252" - self.siteId = 7 # Needs to match id entry in Sites database - if autostart: - self.start() - def compilePlayerRegexs(self, hand): players = set([player[1] for player in hand.players]) diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index 9c63bcf0..2835b6ff 100755 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -26,6 +26,11 @@ from HandHistoryConverter import * class Everleaf(HandHistoryConverter): + sitename = 'Everleaf' + filetype = "text" + codepage = "cp1252" + siteId = 3 # Needs to match id entry in Sites database + # Static regexes re_SplitHands = re.compile(r"\n\n\n+") re_TailSplitHands = re.compile(r"(\n\n\n+)") @@ -37,24 +42,6 @@ class Everleaf(HandHistoryConverter): re_Board = re.compile(ur"\[ (?P.+) \]") - def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, debugging=False, index=0): - """\ -in_path (default '-' = sys.stdin) -out_path (default '-' = sys.stdout) -follow : whether to tail -f the input -autostart: whether to run the thread (or you can call start() yourself) -debugging: if False, pass on partially supported game types. If true, have a go and error...""" - #print "DEBUG: XXXXXXXXXXXXXXX" - HandHistoryConverter.__init__(self, in_path, out_path, sitename="Everleaf", follow=follow, index=index) - logging.info("Initialising Everleaf converter class") - self.filetype = "text" - self.codepage = "cp1252" - self.siteId = 3 # Needs to match id entry in Sites database - self.debugging = debugging - if autostart: - self.start() - # otherwise you need to call start yourself. - def compilePlayerRegexs(self, hand): players = set([player[1] for player in hand.players]) if not players <= self.compiledPlayers: # x <= y means 'x is subset of y' diff --git a/pyfpdb/Exceptions.py b/pyfpdb/Exceptions.py index fa76f3cd..8259a484 100644 --- a/pyfpdb/Exceptions.py +++ b/pyfpdb/Exceptions.py @@ -1 +1,4 @@ -class FpdbParseError(Exception): pass +class FpdbParseError(Exception): + def __init__(self,hid=None): + self.hid = hid + diff --git a/pyfpdb/FulltiltToFpdb.py b/pyfpdb/FulltiltToFpdb.py index a68c1cbd..19a666f1 100755 --- a/pyfpdb/FulltiltToFpdb.py +++ b/pyfpdb/FulltiltToFpdb.py @@ -27,6 +27,11 @@ from HandHistoryConverter import * class Fulltilt(HandHistoryConverter): + sitename = "Fulltilt" + filetype = "text" + codepage = "cp1252" + siteId = 1 # Needs to match id entry in Sites database + # Static regexes re_GameInfo = re.compile('''(?:(?P.+)\s\((?P\d+)\),\s)? .+ @@ -39,7 +44,7 @@ class Fulltilt(HandHistoryConverter): ''', re.VERBOSE) re_SplitHands = re.compile(r"\n\n+") re_TailSplitHands = re.compile(r"(\n\n+)") - re_HandInfo = re.compile('''.*\#(?P[0-9]+):\s + re_HandInfo = re.compile(r'''.*\#(?P[0-9]+):\s (?:(?P.+)\s\((?P\d+)\),\s)? Table\s (?PPlay\sChip\s|PC)? @@ -47,8 +52,9 @@ class Fulltilt(HandHistoryConverter): (\((?P.+)\)\s)?-\s \$?(?P[.0-9]+)/\$?(?P[.0-9]+)\s(Ante\s\$?(?P[.0-9]+)\s)?-\s (?P[a-zA-Z\/\'\s]+)\s-\s - (?P.*) - ''', re.VERBOSE) + (?P.*?)\n + (?:.*?\n(?PHand\s\#(?P=HID)\shas\sbeen\scanceled))? + ''', re.VERBOSE|re.DOTALL) re_Button = re.compile('^The button is in seat #(?P