diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index 5bfc47c0..cd2b044e 100755 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -36,16 +36,19 @@ class Everleaf(HandHistoryConverter): re_Board = re.compile(ur"\[ (?P.+) \]") - def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True): + def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, debugging=False): """\ in_path (default '-' = sys.stdin) out_path (default '-' = sys.stdout) -follow : whether to tail -f the input""" +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...""" HandHistoryConverter.__init__(self, in_path, out_path, sitename="Everleaf", follow=follow) print "DEBUG: __init__" logging.info("Initialising Everleaf converter class") self.filetype = "text" self.codepage = "cp1252" + self.debugging = debugging if autostart: self.start() @@ -62,7 +65,7 @@ follow : whether to tail -f the input""" 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| complete to)(\s\[?(?:\$| €|)\s?(?P[.\d]+?)\.?\s?(USD|EUR|)\]?)?" % player_re, re.MULTILINE) + self.re_Action = re.compile(ur"^%s(?P: bets| checks| raises| calls| folds| complete to)(\s\[?(?:\$| €|)\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) @@ -104,7 +107,7 @@ or None if we fail to get the info """ m = self.re_GameInfo.search(handText) if not m: return None - + mg = m.groupdict() # translations from captured groups to our info strings @@ -128,6 +131,9 @@ or None if we fail to get the info """ info['currency'] = currencies[mg['CURRENCY']] # NB: SB, BB must be interpreted as blinds or bets depending on limit type. + if not self.debugging and info['base']=='stud': + return None + return info @@ -304,5 +310,5 @@ if __name__ == "__main__": LOG_FILENAME = './logging.out' logging.basicConfig(filename=LOG_FILENAME,level=options.verbosity) - e = Everleaf(in_path = options.ipath, out_path = options.opath, follow = options.follow) + e = Everleaf(in_path = options.ipath, out_path = options.opath, follow = options.follow, autostart=True, debugging=True) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 727656b6..5b29a735 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -733,8 +733,6 @@ class Pot(object): self.pots = [] while len(commitsall) > 0: commitslive = [(v,k) for (v,k) in commitsall if k in self.contenders] - print "all", commitsall - print "live", commitslive v1 = commitslive[0][0] self.pots += [sum([min(v,v1) for (v,k) in commitsall])] commitsall = [((v-v1),k) for (v,k) in commitsall if v-v1 >0] diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 54b6e459..7ed679a4 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -88,6 +88,8 @@ class HandHistoryConverter(threading.Thread): # write to stdout self.out_fh = sys.stdout else: + # TODO: out_path should be sanity checked before opening. Perhaps in fpdb_import? + # I'm not sure what we're looking for, although we don't want out_path==in_path!='-' self.out_fh = open(self.out_path, 'a') #TODO: append may be overly conservative. self.sitename = sitename self.follow = follow @@ -111,16 +113,24 @@ class HandHistoryConverter(threading.Thread): def run(self): """process a hand at a time from the input specified by in_path. If in follow mode, wait for more data to turn up. -Otherwise, finish at eof...""" +Otherwise, finish at eof...""" + starttime = time.time() + if not self.sanityCheck(): + print "Cowardly refusing to continue after failed sanity check" + return if self.follow: + numHands = 0 for handText in self.tailHands(): + numHands+=1 self.processHand(handText) else: handsList = self.allHandsAsList() logging.info("Parsing %d hands" % len(handsList)) for handText in handsList: self.processHand(handText) - + numHands= len(handsList) + endtime = time.time() + print "Processed %d hands in %.3f seconds" % (numHands, endtime - starttime) def tailHands(self): """Generator of handTexts from a tailed file: @@ -180,6 +190,7 @@ Tail the in_path file and yield handTexts separated by re_SplitHands""" def allHandsAsList(self): """Return a list of handtexts in the file at self.in_path""" + #TODO : any need for this to be generator? e.g. stars support can email one huge file of all hands in a year. Better to read bit by bit than all at once. self.readFile() self.obs = self.obs.strip() self.obs = self.obs.replace('\r\n', '\n') @@ -209,20 +220,6 @@ Tail the in_path file and yield handTexts separated by re_SplitHands""" logging.info("Unsupported game type: %s" % gametype) # TODO: pity we don't know the HID at this stage. Log the entire hand? # From the log we can deduce that it is the hand after the one before :) - - - def processFile(self): - starttime = time.time() - if not self.sanityCheck(): - print "Cowardly refusing to continue after failed sanity check" - return - self.readFile(self.file) - if self.obs == "" or self.obs == None: - print "Did not read anything from file." - return - ### alala deleted - endtime = time.time() - print "Processed %d hands in %.3f seconds" % (len(self.hands), endtime - starttime) # These functions are parse actions that may be overridden by the inheriting class # This function should return a list of lists looking like: @@ -292,27 +289,34 @@ or None if we fail to get the info """ def sanityCheck(self): + """Check we aren't going to do some stupid things""" + #TODO: the hhbase stuff needs to be in fpdb_import sane = False base_w = False - #Check if hhbase exists and is writable - #Note: Will not try to create the base HH directory - if not (os.access(self.hhbase, os.W_OK) and os.path.isdir(self.hhbase)): - print "HH Sanity Check: Directory hhbase '" + self.hhbase + "' doesn't exist or is not writable" - else: - #Check if hhdir exists and is writable - if not os.path.isdir(self.hhdir): - # In first pass, dir may not exist. Attempt to create dir - print "Creating directory: '%s'" % (self.hhdir) - os.mkdir(self.hhdir) - sane = True - elif os.access(self.hhdir, os.W_OK): - sane = True - else: - print "HH Sanity Check: Directory hhdir '" + self.hhdir + "' or its parent directory are not writable" + #~ #Check if hhbase exists and is writable + #~ #Note: Will not try to create the base HH directory + #~ if not (os.access(self.hhbase, os.W_OK) and os.path.isdir(self.hhbase)): + #~ print "HH Sanity Check: Directory hhbase '" + self.hhbase + "' doesn't exist or is not writable" + #~ else: + #~ #Check if hhdir exists and is writable + #~ if not os.path.isdir(self.hhdir): + #~ # In first pass, dir may not exist. Attempt to create dir + #~ print "Creating directory: '%s'" % (self.hhdir) + #~ os.mkdir(self.hhdir) + #~ sane = True + #~ elif os.access(self.hhdir, os.W_OK): + #~ sane = True + #~ else: + #~ print "HH Sanity Check: Directory hhdir '" + self.hhdir + "' or its parent directory are not writable" # Make sure input and output files are different or we'll overwrite the source file - if(self.ofile == self.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 + return sane @@ -357,4 +361,4 @@ or None if we fail to get the info """ return True def getProcessedFile(self): - return self.ofile + return self.out_path diff --git a/pyfpdb/test_Everleaf.py b/pyfpdb/test_Everleaf.py index ee77910f..1e568bb7 100644 --- a/pyfpdb/test_Everleaf.py +++ b/pyfpdb/test_Everleaf.py @@ -15,21 +15,36 @@ Blinds €0.50/ €1 NL Hold'em - 2009/01/11 - 16:09:40 Table Casino Lyon Vert 58 Seat 3 is the button Total number of players: 6""", - {'type':'ring', 'base':"hold", 'category':'holdem', 'limitType':'nl', 'sb':'0.50', 'bb':'1', 'currency':'EUR'}), + {'type':'ring', 'base':"hold", 'category':'holdem', 'limitType':'nl', 'sb':'0.50', 'bb':'1', 'currency':'EUR'}), + ("""Everleaf Gaming Game #55198191 ***** Hand history for game #55198191 ***** Blinds $0.50/$1 NL Hold'em - 2008/09/01 - 10:02:11 Table Speed Kuala Seat 8 is the button Total number of players: 10""", - {'type':'ring', 'base':"hold", 'category':'holdem', 'limitType':'nl', 'sb':'0.50', 'bb':'1', 'currency':'USD'}), + {'type':'ring', 'base':"hold", 'category':'holdem', 'limitType':'nl', 'sb':'0.50', 'bb':'1', 'currency':'USD'}), + ("""Everleaf Gaming Game #75065769 ***** Hand history for game #75065769 ***** Blinds 10/20 NL Hold'em - 2009/02/25 - 17:30:32 Table 2 Seat 1 is the button Total number of players: 10""", - {'type':'ring', 'base':"hold", 'category':'holdem', 'limitType':'nl', 'sb':'10', 'bb':'20', 'currency':'T$'}) + {'type':'ring', 'base':"hold", 'category':'holdem', 'limitType':'nl', 'sb':'10', 'bb':'20', 'currency':'T$'}), + + ("""Everleaf Gaming Game #65087798 +***** Hand history for game #65087798 ***** +$0.25/$0.50 7 Card Stud - 2008/12/05 - 21:46:00 +Table Plymouth""", + {'type':'ring', 'base':'stud', 'category':'studhi', 'limitType':'fl', 'sb':'0.25', 'bb':'0.50', 'currency':'USD'}), + + ("""Everleaf Gaming Game #65295370 +***** Hand history for game #65295370 ***** +Blinds $0.50/$1 PL Omaha - 2008/12/07 - 21:59:48 +Table Guanajuato""", + {'type':'ring', 'base':'hold', 'category':'omahahi', 'limitType':'pl', 'sb':'0.50', 'bb':'1','currency':'USD'}) + ) for (header, info) in pairs: yield checkGameInfo, hhc, header, info