diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 8d58da50..9e0007a3 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1620,6 +1620,7 @@ class HandToWrite: self.maxSeats = None self.tableName = None self.seatNos = None + self.payin_amounts = None # tourney import was complaining mightily about this missing except: print "htw.init error: " + str(sys.exc_info()) raise diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index a7685f90..9c63bcf0 100755 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -44,7 +44,7 @@ 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" + #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" diff --git a/pyfpdb/FulltiltToFpdb.py b/pyfpdb/FulltiltToFpdb.py index 4fb0e8b3..a68c1cbd 100755 --- a/pyfpdb/FulltiltToFpdb.py +++ b/pyfpdb/FulltiltToFpdb.py @@ -118,7 +118,7 @@ follow : whether to tail -f the input""" if not m: return None mg = m.groupdict() - + # translations from captured groups to our info strings limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl' } games = { # base, category @@ -140,8 +140,27 @@ follow : whether to tail -f the input""" if mg['TOURNO'] == None: info['type'] = "ring" else: info['type'] = "tour" # NB: SB, BB must be interpreted as blinds or bets depending on limit type. + if info['type'] == "tour": return None # importer is screwed on tournies, pass on those hands so we don't interrupt other autoimporting return info + #Following function is a hack, we should be dealing with this in readFile (i think correct codepage....) + # Same function as parent class, removing the 2 end characters. - CG + 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() + + # FIXME: it's a hack + if self.obs[:2] == u'\xff\xfe': + self.obs = self.obs[2:].replace('\x00', '') + + self.obs = self.obs.strip() + self.obs = self.obs.replace('\r\n', '\n') + if self.obs == "" or self.obs == None: + logging.info("Read no hands.") + return + return re.split(self.re_SplitHands, self.obs) + def readHandInfo(self, hand): m = self.re_HandInfo.search(hand.handText,re.DOTALL) if(m == None): @@ -158,6 +177,12 @@ follow : whether to tail -f the input""" hand.tourNo = m.group('TOURNO') if m.group('PLAY') != None: hand.gametype['currency'] = 'play' + + # TODO: if there's a way to figure these out, we should.. otherwise we have to stuff it with unknowns + if hand.buyin == None: + hand.buyin = "$0.00+$0.00" + if hand.level == None: + hand.level = "0" # These work, but the info is already in the Hand class - should be used for tourneys though. # m.group('SB') diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 4e7d4bdf..0dbb9674 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -56,6 +56,7 @@ class Hand(object): self.buttonpos = 0 self.tourNo = None self.buyin = None + self.fee = None # the Database code is looking for this one .. ? self.level = None self.mixed = None self.seating = [] @@ -564,7 +565,7 @@ Map the tuple self.gametype onto the pokerstars string describing it def writeGameLine(self): """Return the first HH line for the current hand.""" gs = "PokerStars Game #%s: " % self.handid - + if self.tourNo != None and self.mixed != None: # mixed tournament gs = gs + "Tournament #%s, %s %s (%s) - Level %s (%s) - " % (self.tourNo, self.buyin, self.MS[self.mixed], self.getGameTypeAsString(), self.level, self.getStakesAsString()) elif self.tourNo != None: # all other tournaments diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index f5d46034..2ded2c50 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -57,6 +57,10 @@ class HandHistoryConverter(): self.out_fh = sys.stdout else: # TODO: out_path should be sanity checked. + out_dir = os.path.dirname(self.out_path) + if not os.path.isdir(out_dir): + logging.info("Creatin directory '%s'" % out_dir) + os.makedirs(out_dir) self.out_fh = open(self.out_path, 'w') self.sitename = sitename diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 61d4df4c..20ba4319 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -29,18 +29,31 @@ class PokerStars(HandHistoryConverter): ############################################################ # Class Variables + substitutions = { + 'LEGAL_ISO' : "USD|EUR|GBP|CAD", # legal ISO currency codes + 'LS' : "\$" # legal currency symbols + } + # Static regexes - re_GameInfo = re.compile("""PokerStars\sGame\s\#(?P[0-9]+):\s+ - (Tournament\s\#(?P\d+),\s(?P[\$\+\d\.]+)\s)? - (?PHORSE|8\-Game|HOSE)?\s?\(? - (?PHold\'em|Razz|7\sCard\sStud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball)\s - (?PNo\sLimit|Limit|Pot\sLimit)\)?,?\s - (-\sLevel\s(?P[IVXLC]+)\s)?\(? - (?P\$|)? - (?P[.0-9]+)/\$? - (?P[.0-9]+)\)\s-\s - (?P.*$)""", - re.MULTILINE|re.VERBOSE) + re_GameInfo = re.compile(""" + PokerStars\sGame\s\#(?P[0-9]+):\s+ + (Tournament\s\# # open paren of tournament info + (?P\d+),\s + (?P[%(LS)s\+\d\.]+ # here's how I plan to use LS + \s?(?P%(LEGAL_ISO)s)? + )\s)? # close paren of tournament info + (?PHORSE|8\-Game|HOSE)?\s?\(? + (?PHold\'em|Razz|7\sCard\sStud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball)\s + (?PNo\sLimit|Limit|Pot\sLimit)\)?,?\s + (-\sLevel\s(?P[IVXLC]+)\s)? + \(? # open paren of the stakes + (?P%(LS)s|)? + (?P[.0-9]+)/%(LS)s? + (?P[.0-9]+) + \s?(?P%(LEGAL_ISO)s)? + \)\s-\s # close paren of the stakes + (?P.*$)""" % substitutions, + re.MULTILINE|re.VERBOSE) re_SplitHands = re.compile('\n\n+') re_TailSplitHands = re.compile('(\n\n\n+)') re_HandInfo = re.compile("""^Table\s\'(?P[-\ a-zA-Z\d]+)\'\s @@ -270,19 +283,6 @@ follow : whether to tail -f the input""" for a in self.re_PostBoth.finditer(hand.handText): hand.addBlind(a.group('PNAME'), 'both', a.group('SBBB')) -# def readHeroCards(self, hand): -# m = self.re_HeroCards.search(hand.handText) -# if(m == None): -# #Not involved in hand -# hand.involved = False -# else: -# hand.hero = m.group('PNAME') -# # "2c, qh" -> set(["2c","qc"]) -# # Also works with Omaha hands. -# cards = m.group('NEWCARDS') -# cards = set(cards.split(' ')) -# hand.addHoleCards(cards, m.group('PNAME'), shown=False, mucked=False, dealt=True) - def readHeroCards(self, hand): # streets PREFLOP, PREDRAW, and THIRD are special cases beacause # we need to grab hero's cards @@ -318,62 +318,6 @@ follow : whether to tail -f the input""" else: hand.addHoleCards(street, player, open=newcards, closed=oldcards, shown=False, mucked=False, dealt=False) - -# def readDrawCards(self, hand, street): -# logging.debug("readDrawCards") -# m = self.re_HeroCards.finditer(hand.streets[street]) -# if m == None: -# hand.involved = False -# else: -# for player in m: -# hand.hero = player.group('PNAME') # Only really need to do this once -# newcards = player.group('NEWCARDS') -# oldcards = player.group('OLDCARDS') -# if newcards == None: -# newcards = set() -# else: -# newcards = set(newcards.split(' ')) -# if oldcards == None: -# oldcards = set() -# else: -# oldcards = set(oldcards.split(' ')) -# hand.addDrawHoleCards(newcards, oldcards, player.group('PNAME'), street) - - -# def readStudPlayerCards(self, hand, street): -# # See comments of reference implementation in FullTiltToFpdb.py -# logging.debug("readStudPlayerCards") -# m = self.re_HeroCards.finditer(hand.streets[street]) -# for player in m: -# #~ logging.debug(player.groupdict()) -# (pname, oldcards, newcards) = (player.group('PNAME'), player.group('OLDCARDS'), player.group('NEWCARDS')) -# if oldcards: -# oldcards = [c.strip() for c in oldcards.split(' ')] -# if newcards: -# newcards = [c.strip() for c in newcards.split(' ')] -# if street=='ANTES': -# return -# elif street=='THIRD': -# # we'll have observed hero holecards in CARDS and thirdstreet open cards in 'NEWCARDS' -# # hero: [xx][o] -# # others: [o] -# hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = oldcards, open = newcards) -# elif street in ('FOURTH', 'FIFTH', 'SIXTH'): -# # 4th: -# # hero: [xxo] [o] -# # others: [o] [o] -# # 5th: -# # hero: [xxoo] [o] -# # others: [oo] [o] -# # 6th: -# # hero: [xxooo] [o] -# # others: [ooo] [o] -# hand.addPlayerCards(player = player.group('PNAME'), street = street, open = newcards) -# # we may additionally want to check the earlier streets tally with what we have but lets trust it for now. -# elif street=='SEVENTH' and newcards: -# # hero: [xxoooo] [x] -# # others: not reported. -# hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = newcards) def readAction(self, hand, street): m = self.re_Action.finditer(hand.streets[street]) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index ed87731b..76b483ba 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -268,23 +268,15 @@ class Importer: if os.path.exists(file): stat_info = os.stat(file) #rulog.writelines("path exists ") - try: - lastupdate = self.updated[file] - #rulog.writelines("lastupdate = %d, mtime = %d" % (lastupdate,stat_info.st_mtime)) - if stat_info.st_mtime > lastupdate: + if file in self.updated: + if stat_info.st_size > self.updated[file]: self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1]) - self.updated[file] = time() - except: - self.updated[file] = time() - # If modified in the last minute run an immediate import. - # This codepath only runs first time the file is found. + self.updated[file] = stat_info.st_size + else: if os.path.isdir(file) or (time() - stat_info.st_mtime) < 60: - # TODO attach a HHC thread to the file - # TODO import the output of the HHC thread -- this needs to wait for the HHC to block? - self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1]) - # TODO we also test if directory, why? - #if os.path.isdir(file): - #self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1]) + self.updated[file] = 0 + else: + self.updated[file] = stat_info.st_size else: self.removeFromFileList[file] = True self.addToDirList = filter(lambda x: self.addImportDirectory(x, True, self.addToDirList[x][0], self.addToDirList[x][1]), self.addToDirList) @@ -351,7 +343,7 @@ class Importer: starttime = time() last_read_hand = 0 loc = 0 - #print "file =", file + # print "file =", file if file == "stdin": inputFile = sys.stdin else: diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py index fd2d6796..673254d0 100644 --- a/pyfpdb/fpdb_parse_logic.py +++ b/pyfpdb/fpdb_parse_logic.py @@ -167,7 +167,12 @@ def mainParser(settings, siteID, category, hand, config, db = None): except: print "parse: error during commit: " + str(sys.exc_value) - +# HERE's an ugly kludge to keep from failing when positions is undef +# We'll fix this by getting rid of the legacy importer. REB + try: + if positions: pass + except: + positions = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] # save data structures in a HandToWrite instance and then insert into database: htw = Database.HandToWrite() htw.set_all( config, settings, base, category, siteTourneyNo, buyin