Merge branch 'master' of git://git.assembla.com/fpdboz.git
This commit is contained in:
commit
701079fe35
|
@ -25,24 +25,29 @@ from time import strftime
|
|||
# Class for converting Everleaf HH format.
|
||||
|
||||
class Everleaf(HandHistoryConverter):
|
||||
|
||||
# Static regexes
|
||||
re_SplitHands = re.compile(r"\n\n+")
|
||||
re_GameInfo = re.compile(r".*Blinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<LTYPE>(NL|PL)) (?P<GAME>(Hold\'em|Omaha|7 Card Stud))")
|
||||
re_HandInfo = re.compile(r".*#(?P<HID>[0-9]+)\n.*\nBlinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<DATETIME>\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P<TABLE>[- a-zA-Z]+)")
|
||||
re_Button = re.compile(r"^Seat (?P<BUTTON>\d+) is the button", re.MULTILINE)
|
||||
re_PlayerInfo = re.compile(r"^Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\s+(\$ (?P<CASH>[.0-9]+) USD|new player|All-in) \)", re.MULTILINE)
|
||||
re_Board = re.compile(r"\[ (?P<CARDS>.+) \]")
|
||||
|
||||
|
||||
def __init__(self, config, file):
|
||||
print "Initialising Everleaf converter class"
|
||||
HandHistoryConverter.__init__(self, config, file, sitename="Everleaf") # Call super class init.
|
||||
self.sitename = "Everleaf"
|
||||
self.setFileType("text", "cp1252")
|
||||
|
||||
self.re_GameInfo = re.compile(r".*Blinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<LTYPE>(NL|PL)) (?P<GAME>(Hold\'em|Omaha|7 Card Stud))")
|
||||
self.re_SplitHands = re.compile(r"\n\n+")
|
||||
self.re_HandInfo = re.compile(r".*#(?P<HID>[0-9]+)\n.*\nBlinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<DATETIME>\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P<TABLE>[- a-zA-Z]+)\nSeat (?P<BUTTON>[0-9]+)")
|
||||
self.re_PlayerInfo = re.compile(r"^Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\s+(\$ (?P<CASH>[.0-9]+) USD|new player|All-in) \)", re.MULTILINE)
|
||||
self.re_Board = re.compile(r"\[ (?P<CARDS>.+) \]")
|
||||
|
||||
try:
|
||||
self.ofile = os.path.join(self.hhdir, file.split(os.path.sep)[-2]+"-"+os.path.basename(file))
|
||||
except:
|
||||
self.ofile = os.path.join(self.hhdir, "x"+strftime("%d-%m-%y")+os.path.basename(file))
|
||||
|
||||
def compile_player_regexs(self):
|
||||
def compilePlayerRegexs(self):
|
||||
player_re = "(?P<PNAME>" + "|".join(map(re.escape, self.players)) + ")"
|
||||
#print "DEBUG player_re: " + player_re
|
||||
self.re_PostSB = re.compile(r"^%s: posts small blind \[\$? (?P<SB>[.0-9]+)" % player_re, re.MULTILINE)
|
||||
|
@ -116,7 +121,6 @@ class Everleaf(HandHistoryConverter):
|
|||
#TODO: Do conversion from GMT to ET
|
||||
#TODO: Need some date functions to convert to different timezones (Date::Manip for perl rocked for this)
|
||||
hand.starttime = time.strptime(m.group('DATETIME'), "%Y/%m/%d - %H:%M:%S")
|
||||
hand.buttonpos = int(m.group('BUTTON'))
|
||||
|
||||
def readPlayerStacks(self, hand):
|
||||
m = self.re_PlayerInfo.finditer(hand.string)
|
||||
|
@ -160,6 +164,9 @@ class Everleaf(HandHistoryConverter):
|
|||
for a in self.re_PostBoth.finditer(hand.string):
|
||||
hand.addBlind(a.group('PNAME'), 'both', a.group('SBBB'))
|
||||
|
||||
def readButton(self, hand):
|
||||
hand.buttonpos = int(self.re_Button.search(hand.string).group('BUTTON'))
|
||||
|
||||
def readHeroCards(self, hand):
|
||||
m = self.re_HeroCards.search(hand.string)
|
||||
if(m == None):
|
||||
|
|
|
@ -23,36 +23,41 @@ from HandHistoryConverter import *
|
|||
# FullTilt HH Format converter
|
||||
|
||||
class FullTilt(HandHistoryConverter):
|
||||
|
||||
# Static regexes
|
||||
re_GameInfo = re.compile('- \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (Ante \$(?P<ANTE>[.0-9]+) )?- (?P<LTYPE>(No|Pot)? )?Limit (?P<GAME>(Hold\'em|Omaha|Razz))')
|
||||
re_SplitHands = re.compile(r"\n\n+")
|
||||
re_HandInfo = re.compile('.*#(?P<HID>[0-9]+): Table (?P<TABLE>[- a-zA-Z]+) (\((?P<TABLEATTRIBUTES>.+)\) )?- \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (Ante \$(?P<ANTE>[.0-9]+) )?- (?P<GAMETYPE>[a-zA-Z\' ]+) - (?P<DATETIME>.*)')
|
||||
re_Button = re.compile('^The button is in seat #(?P<BUTTON>\d+)', re.MULTILINE)
|
||||
re_PlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$(?P<CASH>[.0-9]+)\)\n')
|
||||
re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
|
||||
|
||||
def __init__(self, config, file):
|
||||
print "Initialising FullTilt converter class"
|
||||
HandHistoryConverter.__init__(self, config, file, sitename="FullTilt") # Call super class init.
|
||||
self.sitename = "FullTilt"
|
||||
self.setFileType("text", "cp1252")
|
||||
|
||||
self.re_GameInfo = re.compile('- \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) - (?P<LTYPE>(No|Pot)) Limit (?P<GAME>(Hold\'em|Omaha))')
|
||||
self.re_SplitHands = re.compile(r"\n\n+")
|
||||
self.re_HandInfo = re.compile('.*#(?P<HID>[0-9]+): Table (?P<TABLE>[- a-zA-Z]+) (\((?P<TABLEATTRIBUTES>.+)\) )?- \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) - (?P<GAMETYPE>[a-zA-Z\' ]+) - (?P<DATETIME>.*)')
|
||||
self.re_Button = re.compile('The button is in seat #(?P<BUTTON>\d+)')
|
||||
self.re_PlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$(?P<CASH>[.0-9]+)\)\n')
|
||||
self.re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
|
||||
|
||||
def compile_player_regexs(self):
|
||||
def compilePlayerRegexs(self):
|
||||
player_re = "(?P<PNAME>" + "|".join(map(re.escape, self.players)) + ")"
|
||||
#print "DEBUG player_re: " + player_re
|
||||
self.re_PostSB = re.compile('.*\n(?P<PNAME>.*) posts the small blind of \$?(?P<SB>[.0-9]+)')
|
||||
self.re_PostBB = re.compile('.*\n(?P<PNAME>.*) posts (the big blind of )?\$?(?P<BB>[.0-9]+)')
|
||||
self.re_PostBoth = re.compile('.*\n(?P<PNAME>.*) posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)')
|
||||
self.re_HeroCards = re.compile('.*\nDealt\sto\s(?P<PNAME>.*)\s\[(?P<CARDS>.*)\]')
|
||||
self.re_Action = re.compile('.*\n(?P<PNAME>.*)(?P<ATYPE> bets| checks| raises to| calls| folds)(\s\$(?P<BET>[.\d]+))?')
|
||||
self.re_ShowdownAction = re.compile('.*\n(?P<PNAME>.*) shows \[(?P<CARDS>.*)\]')
|
||||
self.re_CollectPot = re.compile(r"Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*?) (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(\$(?P<POT>[.\d]+)\)(, mucked| with.*)")
|
||||
self.re_SitsOut = re.compile('(?P<PNAME>.*) sits out')
|
||||
self.re_ShownCards = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(.*\) showed \[(?P<CARDS>.*)\].*')
|
||||
print "DEBUG player_re: " + player_re
|
||||
self.re_PostSB = re.compile(r"^%s posts the small blind of \$?(?P<SB>[.0-9]+)" % player_re, re.MULTILINE)
|
||||
self.re_PostBB = re.compile(r"^%s posts (the big blind of )?\$?(?P<BB>[.0-9]+)" % player_re, re.MULTILINE)
|
||||
self.re_Antes = re.compile(r"^%s antes \$?(?P<ANTE>[.0-9]+)" % player_re, re.MULTILINE)
|
||||
self.re_BringIn = re.compile(r"^%s brings in for \$?(?P<BRINGIN>[.0-9]+)" % player_re, re.MULTILINE)
|
||||
self.re_PostBoth = re.compile(r"^%s posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)" % player_re, re.MULTILINE)
|
||||
self.re_HeroCards = re.compile(r"^Dealt to %s \[(?P<CARDS>[AKQJT0-9hcsd ]+)\]( \[(?P<NEWCARD>[AKQJT0-9hcsd ]+)\])?" % player_re, re.MULTILINE)
|
||||
self.re_Action = re.compile(r"^%s(?P<ATYPE> bets| checks| raises to| calls| folds)(\s\$(?P<BET>[.\d]+))?" % player_re, re.MULTILINE)
|
||||
self.re_ShowdownAction = re.compile(r"^%s shows \[(?P<CARDS>.*)\]" % player_re, re.MULTILINE)
|
||||
self.re_CollectPot = re.compile(r"^Seat (?P<SEAT>[0-9]+): %s (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(\$(?P<POT>[.\d]+)\)(, mucked| with.*)" % player_re, re.MULTILINE)
|
||||
self.re_SitsOut = re.compile(r"^%s sits out" % player_re, re.MULTILINE)
|
||||
self.re_ShownCards = re.compile(r"^Seat (?P<SEAT>[0-9]+): %s \(.*\) showed \[(?P<CARDS>.*)\].*" % player_re, re.MULTILINE)
|
||||
|
||||
|
||||
def readSupportedGames(self):
|
||||
return [["ring", "hold", "nl"],
|
||||
["ring", "hold", "pl"],
|
||||
["ring", "razz", "fl"],
|
||||
["ring", "omaha", "pl"]
|
||||
]
|
||||
|
||||
|
@ -66,15 +71,21 @@ class FullTilt(HandHistoryConverter):
|
|||
|
||||
|
||||
m = self.re_GameInfo.search(self.obs)
|
||||
if m.group('LTYPE') == "No":
|
||||
if m.group('LTYPE') == "No ":
|
||||
structure = "nl"
|
||||
elif m.group('LTYPE') == "Pot":
|
||||
elif m.group('LTYPE') == "Pot ":
|
||||
structure = "pl"
|
||||
elif m.group('LTYPE') == None:
|
||||
structure = "fl"
|
||||
|
||||
if m.group('GAME') == "Hold\'em":
|
||||
game = "hold"
|
||||
if m.group('GAME') == "Omaha":
|
||||
elif m.group('GAME') == "Omaha":
|
||||
game = "omahahi"
|
||||
elif m.group('GAME') == "Razz":
|
||||
game = "razz"
|
||||
|
||||
print m.groups()
|
||||
|
||||
gametype = ["ring", game, structure, m.group('SB'), m.group('BB')]
|
||||
|
||||
|
@ -85,7 +96,6 @@ class FullTilt(HandHistoryConverter):
|
|||
#print m.groups()
|
||||
hand.handid = m.group('HID')
|
||||
hand.tablename = m.group('TABLE')
|
||||
hand.buttonpos = int(self.re_Button.search(hand.string).group('BUTTON'))
|
||||
hand.starttime = time.strptime(m.group('DATETIME'), "%H:%M:%S ET - %Y/%m/%d")
|
||||
# These work, but the info is already in the Hand class - should be used for tourneys though.
|
||||
# m.group('SB')
|
||||
|
@ -112,11 +122,18 @@ class FullTilt(HandHistoryConverter):
|
|||
# PREFLOP = ** Dealing down cards **
|
||||
# This re fails if, say, river is missing; then we don't get the ** that starts the river.
|
||||
|
||||
if self.gametype[1] == "hold" or self.gametype[1] == "omaha":
|
||||
m = re.search(r"\*\*\* HOLE CARDS \*\*\*(?P<PREFLOP>.+(?=\*\*\* FLOP \*\*\*)|.+)"
|
||||
r"(\*\*\* FLOP \*\*\*(?P<FLOP> \[\S\S \S\S \S\S\].+(?=\*\*\* TURN \*\*\*)|.+))?"
|
||||
r"(\*\*\* TURN \*\*\* \[\S\S \S\S \S\S] (?P<TURN>\[\S\S\].+(?=\*\*\* RIVER \*\*\*)|.+))?"
|
||||
r"(\*\*\* RIVER \*\*\* \[\S\S \S\S \S\S \S\S] (?P<RIVER>\[\S\S\].+))?", hand.string,re.DOTALL)
|
||||
|
||||
elif self.gametype[1] == "razz":
|
||||
m = re.search(r"(?P<ANTES>.+(?=\*\*\* 3RD STREET \*\*\*)|.+)"
|
||||
r"(\*\*\* 3RD STREET \*\*\*(?P<THIRD>.+(?=\*\*\* 4TH STREET \*\*\*)|.+))?"
|
||||
r"(\*\*\* 4TH STREET \*\*\*(?P<FOURTH>.+(?=\*\*\* 5TH STREET \*\*\*)|.+))?"
|
||||
r"(\*\*\* 5TH STREET \*\*\*(?P<FIFTH>.+(?=\*\*\* 6TH STREET \*\*\*)|.+))?"
|
||||
r"(\*\*\* 6TH STREET \*\*\*(?P<SIXTH>.+(?=\*\*\* 7TH STREET \*\*\*)|.+))?"
|
||||
r"(\*\*\* 7TH STREET \*\*\*(?P<SEVENTH>.+))?", hand.string,re.DOTALL)
|
||||
hand.addStreets(m)
|
||||
|
||||
def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand
|
||||
|
@ -137,6 +154,23 @@ class FullTilt(HandHistoryConverter):
|
|||
for a in self.re_PostBoth.finditer(hand.string):
|
||||
hand.addBlind(a.group('PNAME'), 'small & big blinds', a.group('SBBB'))
|
||||
|
||||
def readAntes(self, hand):
|
||||
print "DEBUG: reading antes"
|
||||
m = self.re_Antes.finditer(hand.string)
|
||||
for player in m:
|
||||
print "DEBUG: hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE'))
|
||||
hand.addAnte(player.group('PNAME'), player.group('ANTE'))
|
||||
|
||||
def readBringIn(self, hand):
|
||||
print "DEBUG: reading bring in"
|
||||
# print hand.string
|
||||
m = self.re_BringIn.search(hand.string,re.DOTALL)
|
||||
print "DEBUG: Player bringing in: %s for %s" %(m.group('PNAME'), m.group('BRINGIN'))
|
||||
hand.addBringIn(m.group('PNAME'), m.group('BRINGIN'))
|
||||
|
||||
def readButton(self, hand):
|
||||
hand.buttonpos = int(self.re_Button.search(hand.string).group('BUTTON'))
|
||||
|
||||
def readHeroCards(self, hand):
|
||||
m = self.re_HeroCards.search(hand.string)
|
||||
if(m == None):
|
||||
|
@ -150,6 +184,20 @@ class FullTilt(HandHistoryConverter):
|
|||
cards = set(cards.split(' '))
|
||||
hand.addHoleCards(cards, m.group('PNAME'))
|
||||
|
||||
def readPlayerCards(self, hand, street):
|
||||
#Used for stud hands - borrows the HeroCards regex for now.
|
||||
m = self.re_HeroCards.finditer(hand.streets.group(street))
|
||||
print "DEBUG: razz/stud readPlayerCards"
|
||||
print hand.streets.group(street)
|
||||
for player in m:
|
||||
print player.groups()
|
||||
cards = player.group('CARDS')
|
||||
if player.group('NEWCARD') != None:
|
||||
print cards
|
||||
cards = cards + " " + player.group('NEWCARD')
|
||||
cards = set(cards.split(' '))
|
||||
hand.addPlayerCards(cards, player.group('PNAME'))
|
||||
|
||||
def readAction(self, hand, street):
|
||||
m = self.re_Action.finditer(hand.streets.group(street))
|
||||
for action in m:
|
||||
|
@ -188,7 +236,7 @@ class FullTilt(HandHistoryConverter):
|
|||
if __name__ == "__main__":
|
||||
c = Configuration.Config()
|
||||
if len(sys.argv) == 1:
|
||||
testfile = "regression-test-files/fulltilt/FT20081209 CR - tay - $0.05-$0.10 - No Limit Hold'em.txt"
|
||||
testfile = "regression-test-files/fulltilt/razz/FT20090223 Danville - $0.50-$1 Ante $0.10 - Limit Razz.txt"
|
||||
else:
|
||||
testfile = sys.argv[1]
|
||||
print "Converting: ", testfile
|
||||
|
|
|
@ -106,7 +106,8 @@ class GuiAutoImport (threading.Thread):
|
|||
"""Callback for timer to do an import iteration."""
|
||||
if self.doAutoImportBool:
|
||||
self.importer.runUpdated()
|
||||
print "GuiAutoImport.import_dir done"
|
||||
sys.stdout.write(".")
|
||||
sys.stdout.flush()
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
|
|
@ -35,17 +35,6 @@ import Configuration
|
|||
|
||||
class GuiBulkImport():
|
||||
|
||||
def import_dir(self):
|
||||
"""imports a directory, non-recursive. todo: move this to fpdb_import so CLI can use it"""
|
||||
|
||||
self.path = self.inputFile
|
||||
self.importer.addImportDirectory(self.path)
|
||||
self.importer.setCallHud(False)
|
||||
starttime = time()
|
||||
(stored, dups, partial, errs, ttime) = self.importer.runImport()
|
||||
print 'GuiBulkImport.import_dir done: Stored: %d Duplicates: %d Partial: %d Errors: %d in %s seconds - %d/sec'\
|
||||
% (stored, dups, partial, errs, ttime, stored / ttime)
|
||||
|
||||
def load_clicked(self, widget, data=None):
|
||||
# get the dir to import from the chooser
|
||||
self.inputFile = self.chooser.get_filename()
|
||||
|
@ -63,18 +52,22 @@ class GuiBulkImport():
|
|||
self.importer.setDropIndexes(cb_model[cb_index][0])
|
||||
else:
|
||||
self.importer.setDropIndexes("auto")
|
||||
|
||||
hhc=self.cbfilter.get_model()[self.cbfilter.get_active()][0]
|
||||
self.lab_info.set_text("Importing")
|
||||
if os.path.isdir(self.inputFile):
|
||||
self.import_dir()
|
||||
else:
|
||||
self.importer.addImportFile(self.inputFile)
|
||||
|
||||
self.importer.addBulkImportImportFileOrDir(self.inputFile,filter=hhc)
|
||||
self.importer.setCallHud(False)
|
||||
self.importer.runImport()
|
||||
starttime = time()
|
||||
(stored, dups, partial, errs, ttime) = self.importer.runImport()
|
||||
print 'GuiBulkImport.import_dir done: Stored: %d Duplicates: %d Partial: %d Errors: %d in %s seconds - %d/sec'\
|
||||
% (stored, dups, partial, errs, ttime, stored / ttime)
|
||||
self.importer.clearFileList()
|
||||
|
||||
self.lab_info.set_text("Import finished")
|
||||
|
||||
def get_vbox(self):
|
||||
return self.vbox
|
||||
|
||||
def __init__(self, db, settings, config):
|
||||
self.db = db # this is an instance of fpdb_db
|
||||
self.settings = settings
|
||||
|
@ -159,6 +152,20 @@ class GuiBulkImport():
|
|||
self.table.attach(self.cb, 4, 5, 1, 2, xpadding = 10, ypadding = 0, yoptions=gtk.SHRINK)
|
||||
self.cb.show()
|
||||
|
||||
# label - filter
|
||||
self.lab_filter = gtk.Label("Site filter:")
|
||||
self.table.attach(self.lab_filter, 2, 3, 2, 3, xpadding = 0, ypadding = 0, yoptions=gtk.SHRINK)
|
||||
self.lab_filter.show()
|
||||
self.lab_filter.set_justify(gtk.JUSTIFY_RIGHT)
|
||||
|
||||
# ComboBox - filter
|
||||
self.cbfilter = gtk.combo_box_new_text()
|
||||
self.cbfilter.append_text("passthrough")
|
||||
self.cbfilter.append_text("Everleaf")
|
||||
self.cbfilter.set_active(0)
|
||||
self.table.attach(self.cbfilter, 3, 4, 2, 3, xpadding = 10, ypadding = 0, yoptions=gtk.SHRINK)
|
||||
self.cbfilter.show()
|
||||
|
||||
# label - info
|
||||
self.lab_info = gtk.Label()
|
||||
self.table.attach(self.lab_info, 0, 4, 2, 3, xpadding = 0, ypadding = 0, yoptions=gtk.SHRINK)
|
||||
|
|
149
pyfpdb/Hand.py
149
pyfpdb/Hand.py
|
@ -39,7 +39,10 @@ class Hand:
|
|||
self.gametype = gametype
|
||||
self.string = string
|
||||
|
||||
if gametype[1] == "hold" or self.gametype[1] == "omaha":
|
||||
self.streetList = ['PREFLOP','FLOP','TURN','RIVER'] # a list of the observed street names in order
|
||||
elif self.gametype[1] == "razz" or self.gametype[1] == "stud" or self.gametype[1] == "stud8":
|
||||
self.streetList = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] # a list of the observed street names in order
|
||||
|
||||
self.handid = 0
|
||||
self.sb = gametype[3]
|
||||
|
@ -143,6 +146,22 @@ player (string) name of player
|
|||
except FpdbParseError, e:
|
||||
print "[ERROR] Tried to add holecards for unknown player: %s" % (player,)
|
||||
|
||||
def addPlayerCards(self, cards, player):
|
||||
"""\
|
||||
Assigns observed cards to a player.
|
||||
cards set of card bigrams e.g. set(['2h','Jc'])
|
||||
player (string) name of player
|
||||
|
||||
Should probably be merged with addHoleCards
|
||||
"""
|
||||
print "DEBUG: addPlayerCards", cards,player
|
||||
try:
|
||||
self.checkPlayerExists(player)
|
||||
cards = set([self.card(c) for c in cards])
|
||||
self.holecards[player].update(cards)
|
||||
except FpdbParseError, e:
|
||||
print "[ERROR] Tried to add holecards for unknown player: %s" % (player,)
|
||||
|
||||
def addShownCards(self, cards, player, holeandboard=None):
|
||||
"""\
|
||||
For when a player shows cards for any reason (for showdown or out of choice).
|
||||
|
@ -182,6 +201,14 @@ Card ranks will be uppercased
|
|||
c = c.replace(k,v)
|
||||
return c
|
||||
|
||||
def addAnte(self, player, ante):
|
||||
if player is not None:
|
||||
self.bets['ANTES'][player].append(Decimal(ante))
|
||||
self.stacks[player] -= Decimal(ante)
|
||||
act = (player, 'posts', "ante", ante, self.stacks[player]==0)
|
||||
self.actions['ANTES'].append(act)
|
||||
self.pot.addMoney(player, Decimal(ante))
|
||||
|
||||
def addBlind(self, player, blindtype, amount):
|
||||
# if player is None, it's a missing small blind.
|
||||
# TODO:
|
||||
|
@ -210,6 +237,14 @@ Card ranks will be uppercased
|
|||
self.posted = self.posted + [[player,blindtype]]
|
||||
#print "DEBUG: self.posted: %s" %(self.posted)
|
||||
|
||||
def addBringIn(self, player, ante):
|
||||
if player is not None:
|
||||
self.bets['THIRD'][player].append(Decimal(ante))
|
||||
self.stacks[player] -= Decimal(ante)
|
||||
act = (player, 'bringin', "bringin", ante, self.stacks[player]==0)
|
||||
self.actions['THIRD'].append(act)
|
||||
self.pot.addMoney(player, Decimal(ante))
|
||||
|
||||
|
||||
def addCall(self, street, player=None, amount=None):
|
||||
# Potentially calculate the amount of the call if not supplied
|
||||
|
@ -362,11 +397,19 @@ Map the tuple self.gametype onto the pokerstars string describing it
|
|||
"cp" : "Cap Pot Limit"
|
||||
}
|
||||
|
||||
print "DEBUG: self.gametype: %s" %(self.gametype)
|
||||
string = "%s %s" %(gs[self.gametype[1]], ls[self.gametype[2]])
|
||||
|
||||
return string
|
||||
|
||||
def writeHand(self, fh=sys.__stdout__):
|
||||
if self.gametype[1] == "hold" or self.gametype[1] == "omaha":
|
||||
self.writeHoldemHand(fh)
|
||||
else:
|
||||
self.writeStudHand(fh)
|
||||
|
||||
|
||||
def writeHoldemHand(self, fh=sys.__stdout__):
|
||||
# PokerStars format.
|
||||
#print "\n### Pseudo stars format ###"
|
||||
#print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %(self.sitename, self.handid, self.getGameTypeAsString(), self.sb, self.bb, self.starttime))
|
||||
|
@ -413,6 +456,110 @@ Map the tuple self.gametype onto the pokerstars string describing it
|
|||
self.printActionLine(act, fh)
|
||||
|
||||
|
||||
#Some sites don't have a showdown section so we have to figure out if there should be one
|
||||
# The logic for a showdown is: at the end of river action there are at least two players in the hand
|
||||
# we probably don't need a showdown section in pseudo stars format for our filtering purposes
|
||||
if 'SHOWDOWN' in self.actions:
|
||||
print >>fh, _("*** SHOW DOWN ***")
|
||||
#TODO: Complete SHOWDOWN
|
||||
|
||||
# Current PS format has the lines:
|
||||
# Uncalled bet ($111.25) returned to s0rrow
|
||||
# s0rrow collected $5.15 from side pot
|
||||
# stervels: shows [Ks Qs] (two pair, Kings and Queens)
|
||||
# stervels collected $45.35 from main pot
|
||||
# Immediately before the summary.
|
||||
# The current importer uses those lines for importing winning rather than the summary
|
||||
for name in self.pot.returned:
|
||||
print >>fh, _("Uncalled bet ($%s) returned to %s" %(self.pot.returned[name],name))
|
||||
for entry in self.collected:
|
||||
print >>fh, _("%s collected $%s from x pot" %(entry[0], entry[1]))
|
||||
|
||||
print >>fh, _("*** SUMMARY ***")
|
||||
print >>fh, "%s | Rake $%.2f" % (self.pot, self.rake)
|
||||
|
||||
board = []
|
||||
for s in self.board.values():
|
||||
board += s
|
||||
if board: # sometimes hand ends preflop without a board
|
||||
print >>fh, _("Board [%s]" % (" ".join(board)))
|
||||
|
||||
for player in [x for x in self.players if x[1] in players_who_act_preflop]:
|
||||
seatnum = player[0]
|
||||
name = player[1]
|
||||
if name in self.collectees and name in self.shown:
|
||||
print >>fh, _("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards[name]), self.collectees[name]))
|
||||
elif name in self.collectees:
|
||||
print >>fh, _("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name]))
|
||||
elif name in self.shown:
|
||||
print >>fh, _("Seat %d: %s showed [%s]" % (seatnum, name, " ".join(self.holecards[name])))
|
||||
elif name in self.folded:
|
||||
print >>fh, _("Seat %d: %s folded" % (seatnum, name))
|
||||
else:
|
||||
print >>fh, _("Seat %d: %s mucked" % (seatnum, name))
|
||||
|
||||
print >>fh, "\n\n"
|
||||
# TODO:
|
||||
# logic for side pots
|
||||
# logic for which players get to showdown
|
||||
# I'm just not sure we need to do this so heavily.. and if we do, it's probably better to use pokerlib
|
||||
#if self.holecards[player[1]]: # empty list default is false
|
||||
#hole = self.holecards[player[1]]
|
||||
##board = []
|
||||
##for s in self.board.values():
|
||||
##board += s
|
||||
##playerhand = self.bestHand('hi', board+hole)
|
||||
##print "Seat %d: %s showed %s and won/lost with %s" % (player[0], player[1], hole, playerhand)
|
||||
#print "Seat %d: %s showed %s" % (player[0], player[1], hole)
|
||||
#else:
|
||||
#print "Seat %d: %s mucked or folded" % (player[0], player[1])
|
||||
|
||||
|
||||
def writeStudHand(self, fh=sys.__stdout__):
|
||||
# PokerStars format.
|
||||
#print "\n### Pseudo stars format ###"
|
||||
#print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %(self.sitename, self.handid, self.getGameTypeAsString(), self.sb, self.bb, self.starttime))
|
||||
print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d - %H:%M:%S (ET)', self.starttime)))
|
||||
print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos))
|
||||
|
||||
players_who_post_antes = set([x[0] for x in self.actions['ANTES']])
|
||||
|
||||
for player in [x for x in self.players if x[1] in players_who_post_antes]:
|
||||
#Only print stacks of players who do something preflop
|
||||
print >>fh, _("Seat %s: %s ($%s)" %(player[0], player[1], player[2]))
|
||||
|
||||
if 'ANTES' in self.actions:
|
||||
for act in self.actions['ANTES']:
|
||||
print >>fh, _("%s: posts the ante $%s" %(act[0], act[3]))
|
||||
|
||||
if 'THIRD' in self.actions:
|
||||
print >>fh, _("*** 3RD STREET ***")
|
||||
for player in [x for x in self.players if x[1] in players_who_post_antes]:
|
||||
print >>fh, _("Dealt to ")
|
||||
for act in self.actions['THIRD']:
|
||||
#FIXME: Need some logic here for bringin vs completes
|
||||
self.printActionLine(act, fh)
|
||||
|
||||
if 'FOURTH' in self.actions:
|
||||
print >>fh, _("*** 4TH STREET ***")
|
||||
for act in self.actions['FOURTH']:
|
||||
self.printActionLine(act, fh)
|
||||
|
||||
if 'FIFTH' in self.actions:
|
||||
print >>fh, _("*** 5TH STREET ***")
|
||||
for act in self.actions['FIFTH']:
|
||||
self.printActionLine(act, fh)
|
||||
|
||||
if 'SIXTH' in self.actions:
|
||||
print >>fh, _("*** 6TH STREET ***")
|
||||
for act in self.actions['SIXTH']:
|
||||
self.printActionLine(act, fh)
|
||||
|
||||
if 'SEVENTH' in self.actions:
|
||||
print >>fh, _("*** 7TH STREET ***")
|
||||
for act in self.actions['SEVENTH']:
|
||||
self.printActionLine(act, fh)
|
||||
|
||||
#Some sites don't have a showdown section so we have to figure out if there should be one
|
||||
# The logic for a showdown is: at the end of river action there are at least two players in the hand
|
||||
# we probably don't need a showdown section in pseudo stars format for our filtering purposes
|
||||
|
@ -442,7 +589,7 @@ Map the tuple self.gametype onto the pokerstars string describing it
|
|||
if board: # sometimes hand ends preflop without a board
|
||||
print >>fh, _("Board [%s]" % (" ".join(board)))
|
||||
|
||||
for player in [x for x in self.players if x[1] in players_who_act_preflop]:
|
||||
for player in [x for x in self.players if x[1] in players_who_post_antes]:
|
||||
seatnum = player[0]
|
||||
name = player[1]
|
||||
if name in self.collectees and name in self.shown:
|
||||
|
|
|
@ -91,6 +91,7 @@ class HandHistoryConverter:
|
|||
self.ofile = os.path.join(self.hhdir, os.path.basename(file))
|
||||
self.rexx = FpdbRegex.FpdbRegex()
|
||||
self.players = set()
|
||||
self.maxseats = 10
|
||||
|
||||
def __str__(self):
|
||||
tmp = "HandHistoryConverter: '%s'\n" % (self.sitename)
|
||||
|
@ -136,18 +137,29 @@ class HandHistoryConverter:
|
|||
else:
|
||||
# we need to recompile the player regexs.
|
||||
self.players = playersThisHand
|
||||
self.compile_player_regexs()
|
||||
self.compilePlayerRegexs()
|
||||
|
||||
self.markStreets(hand)
|
||||
# Different calls if stud or holdem like
|
||||
if self.gametype[1] == "hold" or self.gametype[1] == "omaha":
|
||||
self.readBlinds(hand)
|
||||
self.readButton(hand)
|
||||
self.readHeroCards(hand) # want to generalise to draw games
|
||||
elif self.gametype[1] == "razz" or self.gametype[1] == "stud" or self.gametype[1] == "stud8":
|
||||
self.readAntes(hand)
|
||||
self.readBringIn(hand)
|
||||
|
||||
self.readShowdownActions(hand)
|
||||
|
||||
# Read actions in street order
|
||||
for street in hand.streetList: # go through them in order
|
||||
print "DEBUG: ", street
|
||||
if hand.streets.group(street) is not None:
|
||||
if self.gametype[1] == "hold" or self.gametype[1] == "omaha":
|
||||
self.readCommunityCards(hand, street) # read community cards
|
||||
elif self.gametype[1] == "razz" or self.gametype[1] == "stud" or self.gametype[1] == "stud8":
|
||||
self.readPlayerCards(hand, street)
|
||||
|
||||
self.readAction(hand, street)
|
||||
|
||||
|
||||
|
@ -197,9 +209,8 @@ class HandHistoryConverter:
|
|||
# [['seat#', 'player1name', 'stacksize'] ['seat#', 'player2name', 'stacksize'] [...]]
|
||||
def readPlayerStacks(self, hand): abstract
|
||||
|
||||
# Given
|
||||
#
|
||||
def compile_player_regexs(self): 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
|
||||
|
@ -210,7 +221,11 @@ class HandHistoryConverter:
|
|||
# ['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
|
||||
def readBringIn(self, hand): abstract
|
||||
def readButton(self, hand): abstract
|
||||
def readHeroCards(self, hand): abstract
|
||||
def readPlayerCards(self, hand, street): abstract
|
||||
def readAction(self, hand, street): abstract
|
||||
def readCollectPot(self, hand): abstract
|
||||
def readShownCards(self, hand): abstract
|
||||
|
|
|
@ -114,11 +114,27 @@ class Importer:
|
|||
#TODO: test it is a valid file -> put that in config!!
|
||||
self.filelist[filename] = [site] + [filter]
|
||||
|
||||
# Called from GuiBulkImport to add a file or directory.
|
||||
def addBulkImportImportFileOrDir(self, inputPath,filter = "passthrough"):
|
||||
"""Add a file or directory for bulk import"""
|
||||
# Bulk import never monitors
|
||||
|
||||
# if directory, add all files in it. Otherwise add single file.
|
||||
# TODO: only add sane files?
|
||||
if os.path.isdir(inputPath):
|
||||
for subdir in os.walk(inputPath):
|
||||
for file in subdir[2]:
|
||||
self.addImportFile(os.path.join(inputPath, subdir[0], file), site="default", filter=filter)
|
||||
else:
|
||||
self.addImportFile(inputPath, site="default", filter=filter)
|
||||
|
||||
#Add a directory of files to filelist
|
||||
#Only one import directory per site supported.
|
||||
#dirlist is a hash of lists:
|
||||
#dirlist{ 'PokerStars' => ["/path/to/import/", "filtername"] }
|
||||
def addImportDirectory(self,dir,monitor = False, site = "default", filter = "passthrough"):
|
||||
#This should really be using os.walk
|
||||
#http://docs.python.org/library/os.html
|
||||
if os.path.isdir(dir):
|
||||
if monitor == True:
|
||||
self.monitor = True
|
||||
|
@ -370,7 +386,7 @@ class Importer:
|
|||
sys.exit(0)
|
||||
startpos=endpos
|
||||
ttime = time() - starttime
|
||||
print "Total stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors, " time:", ttime
|
||||
print "\rTotal stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors, " time:", ttime
|
||||
|
||||
if stored==0:
|
||||
if duplicates>0:
|
||||
|
|
Loading…
Reference in New Issue
Block a user