Merge branch 'master' of git://git.assembla.com/free_poker_tools

This commit is contained in:
Mika Bostrom 2009-07-31 08:26:50 +03:00
commit f60416502d
8 changed files with 72 additions and 100 deletions

View File

@ -1620,6 +1620,7 @@ class HandToWrite:
self.maxSeats = None self.maxSeats = None
self.tableName = None self.tableName = None
self.seatNos = None self.seatNos = None
self.payin_amounts = None # tourney import was complaining mightily about this missing
except: except:
print "htw.init error: " + str(sys.exc_info()) print "htw.init error: " + str(sys.exc_info())
raise raise

View File

@ -44,7 +44,7 @@ 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) 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...""" 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) HandHistoryConverter.__init__(self, in_path, out_path, sitename="Everleaf", follow=follow, index=index)
logging.info("Initialising Everleaf converter class") logging.info("Initialising Everleaf converter class")
self.filetype = "text" self.filetype = "text"

View File

@ -118,7 +118,7 @@ follow : whether to tail -f the input"""
if not m: if not m:
return None return None
mg = m.groupdict() mg = m.groupdict()
# translations from captured groups to our info strings # translations from captured groups to our info strings
limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl' } limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl' }
games = { # base, category games = { # base, category
@ -140,8 +140,27 @@ follow : whether to tail -f the input"""
if mg['TOURNO'] == None: info['type'] = "ring" if mg['TOURNO'] == None: info['type'] = "ring"
else: info['type'] = "tour" else: info['type'] = "tour"
# NB: SB, BB must be interpreted as blinds or bets depending on limit type. # 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 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): def readHandInfo(self, hand):
m = self.re_HandInfo.search(hand.handText,re.DOTALL) m = self.re_HandInfo.search(hand.handText,re.DOTALL)
if(m == None): if(m == None):
@ -158,6 +177,12 @@ follow : whether to tail -f the input"""
hand.tourNo = m.group('TOURNO') hand.tourNo = m.group('TOURNO')
if m.group('PLAY') != None: if m.group('PLAY') != None:
hand.gametype['currency'] = 'play' 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. # These work, but the info is already in the Hand class - should be used for tourneys though.
# m.group('SB') # m.group('SB')

View File

@ -56,6 +56,7 @@ class Hand(object):
self.buttonpos = 0 self.buttonpos = 0
self.tourNo = None self.tourNo = None
self.buyin = None self.buyin = None
self.fee = None # the Database code is looking for this one .. ?
self.level = None self.level = None
self.mixed = None self.mixed = None
self.seating = [] self.seating = []
@ -564,7 +565,7 @@ Map the tuple self.gametype onto the pokerstars string describing it
def writeGameLine(self): def writeGameLine(self):
"""Return the first HH line for the current hand.""" """Return the first HH line for the current hand."""
gs = "PokerStars Game #%s: " % self.handid gs = "PokerStars Game #%s: " % self.handid
if self.tourNo != None and self.mixed != None: # mixed tournament 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()) 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 elif self.tourNo != None: # all other tournaments

View File

@ -57,6 +57,10 @@ class HandHistoryConverter():
self.out_fh = sys.stdout self.out_fh = sys.stdout
else: else:
# TODO: out_path should be sanity checked. # 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.out_fh = open(self.out_path, 'w')
self.sitename = sitename self.sitename = sitename

View File

@ -29,18 +29,31 @@ class PokerStars(HandHistoryConverter):
############################################################ ############################################################
# Class Variables # Class Variables
substitutions = {
'LEGAL_ISO' : "USD|EUR|GBP|CAD", # legal ISO currency codes
'LS' : "\$" # legal currency symbols
}
# Static regexes # Static regexes
re_GameInfo = re.compile("""PokerStars\sGame\s\#(?P<HID>[0-9]+):\s+ re_GameInfo = re.compile("""
(Tournament\s\#(?P<TOURNO>\d+),\s(?P<BUYIN>[\$\+\d\.]+)\s)? PokerStars\sGame\s\#(?P<HID>[0-9]+):\s+
(?P<MIXED>HORSE|8\-Game|HOSE)?\s?\(? (Tournament\s\# # open paren of tournament info
(?P<GAME>Hold\'em|Razz|7\sCard\sStud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball)\s (?P<TOURNO>\d+),\s
(?P<LIMIT>No\sLimit|Limit|Pot\sLimit)\)?,?\s (?P<BUYIN>[%(LS)s\+\d\.]+ # here's how I plan to use LS
(-\sLevel\s(?P<LEVEL>[IVXLC]+)\s)?\(? \s?(?P<TOUR_ISO>%(LEGAL_ISO)s)?
(?P<CURRENCY>\$|)? )\s)? # close paren of tournament info
(?P<SB>[.0-9]+)/\$? (?P<MIXED>HORSE|8\-Game|HOSE)?\s?\(?
(?P<BB>[.0-9]+)\)\s-\s (?P<GAME>Hold\'em|Razz|7\sCard\sStud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball)\s
(?P<DATETIME>.*$)""", (?P<LIMIT>No\sLimit|Limit|Pot\sLimit)\)?,?\s
re.MULTILINE|re.VERBOSE) (-\sLevel\s(?P<LEVEL>[IVXLC]+)\s)?
\(? # open paren of the stakes
(?P<CURRENCY>%(LS)s|)?
(?P<SB>[.0-9]+)/%(LS)s?
(?P<BB>[.0-9]+)
\s?(?P<ISO>%(LEGAL_ISO)s)?
\)\s-\s # close paren of the stakes
(?P<DATETIME>.*$)""" % substitutions,
re.MULTILINE|re.VERBOSE)
re_SplitHands = re.compile('\n\n+') re_SplitHands = re.compile('\n\n+')
re_TailSplitHands = re.compile('(\n\n\n+)') re_TailSplitHands = re.compile('(\n\n\n+)')
re_HandInfo = re.compile("""^Table\s\'(?P<TABLE>[-\ a-zA-Z\d]+)\'\s re_HandInfo = re.compile("""^Table\s\'(?P<TABLE>[-\ 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): for a in self.re_PostBoth.finditer(hand.handText):
hand.addBlind(a.group('PNAME'), 'both', a.group('SBBB')) 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): def readHeroCards(self, hand):
# streets PREFLOP, PREDRAW, and THIRD are special cases beacause # streets PREFLOP, PREDRAW, and THIRD are special cases beacause
# we need to grab hero's cards # we need to grab hero's cards
@ -318,62 +318,6 @@ follow : whether to tail -f the input"""
else: else:
hand.addHoleCards(street, player, open=newcards, closed=oldcards, shown=False, mucked=False, dealt=False) 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): def readAction(self, hand, street):
m = self.re_Action.finditer(hand.streets[street]) m = self.re_Action.finditer(hand.streets[street])

View File

@ -268,23 +268,15 @@ class Importer:
if os.path.exists(file): if os.path.exists(file):
stat_info = os.stat(file) stat_info = os.stat(file)
#rulog.writelines("path exists ") #rulog.writelines("path exists ")
try: if file in self.updated:
lastupdate = self.updated[file] if stat_info.st_size > self.updated[file]:
#rulog.writelines("lastupdate = %d, mtime = %d" % (lastupdate,stat_info.st_mtime))
if stat_info.st_mtime > lastupdate:
self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1]) self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1])
self.updated[file] = time() self.updated[file] = stat_info.st_size
except: else:
self.updated[file] = time()
# If modified in the last minute run an immediate import.
# This codepath only runs first time the file is found.
if os.path.isdir(file) or (time() - stat_info.st_mtime) < 60: if os.path.isdir(file) or (time() - stat_info.st_mtime) < 60:
# TODO attach a HHC thread to the file self.updated[file] = 0
# TODO import the output of the HHC thread -- this needs to wait for the HHC to block? else:
self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1]) self.updated[file] = stat_info.st_size
# 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])
else: else:
self.removeFromFileList[file] = True self.removeFromFileList[file] = True
self.addToDirList = filter(lambda x: self.addImportDirectory(x, True, self.addToDirList[x][0], self.addToDirList[x][1]), self.addToDirList) 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() starttime = time()
last_read_hand = 0 last_read_hand = 0
loc = 0 loc = 0
#print "file =", file # print "file =", file
if file == "stdin": if file == "stdin":
inputFile = sys.stdin inputFile = sys.stdin
else: else:

View File

@ -167,7 +167,12 @@ def mainParser(settings, siteID, category, hand, config, db = None):
except: except:
print "parse: error during commit: " + str(sys.exc_value) 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: # save data structures in a HandToWrite instance and then insert into database:
htw = Database.HandToWrite() htw = Database.HandToWrite()
htw.set_all( config, settings, base, category, siteTourneyNo, buyin htw.set_all( config, settings, base, category, siteTourneyNo, buyin