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

This commit is contained in:
Matt Turnbull 2009-02-25 10:26:25 +00:00
commit baa5b2e8b5
5 changed files with 159 additions and 166 deletions

View File

@ -22,48 +22,7 @@ import Configuration
from HandHistoryConverter import * from HandHistoryConverter import *
from time import strftime from time import strftime
# Everleaf HH format # Class for converting Everleaf HH format.
# Everleaf Gaming Game #55208539
# ***** Hand history for game #55208539 *****
# Blinds $0.50/$1 NL Hold'em - 2008/09/01 - 13:35:01
# Table Speed Kuala
# Seat 1 is the button
# Total number of players: 9
# Seat 1: BadBeatBox ( $ 98.97 USD )
# Seat 3: EricBlade ( $ 73.96 USD )
# Seat 4: randy888 ( $ 196.50 USD )
# Seat 5: BaronSengir ( $ 182.80 USD )
# Seat 6: dogge ( $ 186.06 USD )
# Seat 7: wings ( $ 50 USD )
# Seat 8: schoffeltje ( $ 282.05 USD )
# Seat 9: harrydebeng ( $ 109.45 USD )
# Seat 10: smaragdar ( $ 96.50 USD )
# EricBlade: posts small blind [$ 0.50 USD]
# randy888: posts big blind [$ 1 USD]
# wings: posts big blind [$ 1 USD]
# ** Dealing down cards **
# Dealt to EricBlade [ qc, 3c ]
# BaronSengir folds
# dogge folds
# wings raises [$ 2.50 USD]
# schoffeltje folds
# harrydebeng calls [$ 3.50 USD]
# smaragdar raises [$ 15.50 USD]
# BadBeatBox folds
# EricBlade folds
# randy888 folds
# wings calls [$ 12 USD]
# harrydebeng folds
# ** Dealing Flop ** [ qs, 3d, 8h ]
# wings: bets [$ 34.50 USD]
# smaragdar calls [$ 34.50 USD]
# ** Dealing Turn ** [ 2d ]
# ** Dealing River ** [ 6c ]
# dogge shows [ 9h, 9c ]a pair of nines
# spicybum shows [ 5d, 6d ]a straight, eight high
# harrydebeng does not show cards
# smaragdar wins $ 102 USD from main pot with a pair of aces [ ad, ah, qs, 8h, 6c ]
class Everleaf(HandHistoryConverter): class Everleaf(HandHistoryConverter):
def __init__(self, config, file): def __init__(self, config, file):
@ -72,7 +31,7 @@ class Everleaf(HandHistoryConverter):
self.sitename = "Everleaf" self.sitename = "Everleaf"
self.setFileType("text", "cp1252") self.setFileType("text", "cp1252")
self.re_GameInfo = re.compile(r".*Blinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)") self.re_GameInfo = re.compile(r".*Blinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<LTYPE>(NL|PL)) (?P<GAME>(Hold\'em|Omaha))")
self.re_SplitHands = re.compile(r"\n\n+") 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_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_PlayerInfo = re.compile(r"^Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\s+(\$ (?P<CASH>[.0-9]+) USD|new player|All-in) \)", re.MULTILINE)
@ -85,7 +44,7 @@ class Everleaf(HandHistoryConverter):
def compile_player_regexs(self): def compile_player_regexs(self):
player_re = "(?P<PNAME>" + "|".join(map(re.escape, self.players)) + ")" player_re = "(?P<PNAME>" + "|".join(map(re.escape, self.players)) + ")"
print "DEBUG player_re: " + player_re #print "DEBUG player_re: " + player_re
self.re_PostSB = re.compile(r"^%s: posts small blind \[\$? (?P<SB>[.0-9]+)" % player_re, re.MULTILINE) self.re_PostSB = re.compile(r"^%s: posts small blind \[\$? (?P<SB>[.0-9]+)" % player_re, re.MULTILINE)
self.re_PostBB = re.compile(r"^%s: posts big blind \[\$? (?P<BB>[.0-9]+)" % player_re, re.MULTILINE) self.re_PostBB = re.compile(r"^%s: posts big blind \[\$? (?P<BB>[.0-9]+)" % player_re, re.MULTILINE)
self.re_PostBoth = re.compile(r"^%s: posts both blinds \[\$? (?P<SBBB>[.0-9]+)" % player_re, re.MULTILINE) self.re_PostBoth = re.compile(r"^%s: posts both blinds \[\$? (?P<SBBB>[.0-9]+)" % player_re, re.MULTILINE)
@ -96,14 +55,32 @@ class Everleaf(HandHistoryConverter):
self.re_SitsOut = re.compile(r"^%s sits out" % player_re, re.MULTILINE) self.re_SitsOut = re.compile(r"^%s sits out" % player_re, re.MULTILINE)
def readSupportedGames(self): def readSupportedGames(self):
return [["ring", "hold", "nl"]] return [["ring", "hold", "nl"],
["ring", "hold", "pl"],
["ring", "omaha", "pl"]
]
def determineGameType(self): def determineGameType(self):
# Cheating with this regex, only support nlhe at the moment # Cheating with this regex, only support nlhe at the moment
gametype = ["ring", "hold", "nl"] # Blinds $0.50/$1 PL Omaha - 2008/12/07 - 21:59:48
# Blinds $0.05/$0.10 NL Hold'em - 2009/02/21 - 11:21:57
# $0.25/$0.50 7 Card Stud - 2008/12/05 - 21:43:59
structure = "" # nl, pl, cn, cp, fl
game = ""
m = self.re_GameInfo.search(self.obs) m = self.re_GameInfo.search(self.obs)
gametype = gametype + [m.group('SB')] if m.group('LTYPE') == "NL":
gametype = gametype + [m.group('BB')] structure = "nl"
elif m.group('LTYPE') == "PL":
structure = "pl"
if m.group('GAME') == "Hold\'em":
game = "hold"
if m.group('GAME') == "Omaha":
game = "omahahi"
gametype = ["ring", game, structure, m.group('SB'), m.group('BB')]
return gametype return gametype
def readHandInfo(self, hand): def readHandInfo(self, hand):
@ -148,8 +125,8 @@ class Everleaf(HandHistoryConverter):
def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand
print "DEBUG " + street + ":" #print "DEBUG " + street + ":"
print hand.streets.group(street) + "\n" #print hand.streets.group(street) + "\n"
if street in ('FLOP','TURN','RIVER'): # a list of streets which get dealt community cards (i.e. all but PREFLOP) if street in ('FLOP','TURN','RIVER'): # a list of streets which get dealt community cards (i.e. all but PREFLOP)
m = self.re_Board.search(hand.streets.group(street)) m = self.re_Board.search(hand.streets.group(street))
hand.setCommunityCards(street, m.group('CARDS').split(', ')) hand.setCommunityCards(street, m.group('CARDS').split(', '))
@ -159,7 +136,7 @@ class Everleaf(HandHistoryConverter):
m = self.re_PostSB.search(hand.string) m = self.re_PostSB.search(hand.string)
hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB')) hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB'))
except Exception, e: # no small blind except Exception, e: # no small blind
print e #print e
hand.addBlind(None, None, None) hand.addBlind(None, None, None)
for a in self.re_PostBB.finditer(hand.string): for a in self.re_PostBB.finditer(hand.string):
hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB')) hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB'))

View File

@ -20,51 +20,7 @@ import sys
import Configuration import Configuration
from HandHistoryConverter import * from HandHistoryConverter import *
# FullTilt HH Format # FullTilt HH Format converter
#Full Tilt Poker Game #9403951181: Table CR - tay - $0.05/$0.10 - No Limit Hold'em - 9:40:20 ET - 2008/12/09
#Seat 1: rigoise ($15.95)
#Seat 2: K2dream ($6.70)
#Seat 4: ravens2216 ($10)
#Seat 5: rizkouner ($4)
#Seat 6: Sorrowful ($8.35)
#rigoise posts the small blind of $0.05
#K2dream posts the big blind of $0.10
#5 seconds left to act
#rizkouner posts $0.10
#The button is in seat #6
#*** HOLE CARDS ***
#Dealt to Sorrowful [8h Qc]
#ravens2216 folds
#rizkouner checks
#Sorrowful has 15 seconds left to act
#Sorrowful folds
#rigoise folds
#K2dream checks
#*** FLOP *** [9d Kc 5c]
#K2dream checks
#rizkouner checks
#*** TURN *** [9d Kc 5c] [5h]
#K2dream has 15 seconds left to act
#K2dream bets $0.20
#rizkouner calls $0.20
#*** RIVER *** [9d Kc 5c 5h] [6h]
#K2dream checks
#rizkouner has 15 seconds left to act
#rizkouner bets $0.20
#K2dream folds
#Uncalled bet of $0.20 returned to rizkouner
#rizkouner mucks
#rizkouner wins the pot ($0.60)
#*** SUMMARY ***
#Total pot $0.65 | Rake $0.05
#Board: [9d Kc 5c 5h 6h]
#Seat 1: rigoise (small blind) folded before the Flop
#Seat 2: K2dream (big blind) folded on the River
#Seat 4: ravens2216 didn't bet (folded)
#Seat 5: rizkouner collected ($0.60), mucked
#Seat 6: Sorrowful (button) didn't bet (folded)
#Seat N: rizkouner (button) showed [Jh Ah] and won ($0.70) with a pair of Threes
class FullTilt(HandHistoryConverter): class FullTilt(HandHistoryConverter):
def __init__(self, config, file): def __init__(self, config, file):
@ -72,42 +28,68 @@ class FullTilt(HandHistoryConverter):
HandHistoryConverter.__init__(self, config, file, sitename="FullTilt") # Call super class init. HandHistoryConverter.__init__(self, config, file, sitename="FullTilt") # Call super class init.
self.sitename = "FullTilt" self.sitename = "FullTilt"
self.setFileType("text", "cp1252") self.setFileType("text", "cp1252")
self.rexx.setGameInfoRegex('- \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) -') self.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))')
self.rexx.setSplitHandRegex('\n\n+') self.re_SplitHands = re.compile(r"\n\n+")
self.rexx.setHandInfoRegex('.*#(?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_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>.*)')
# self.rexx.setHandInfoRegex('.*#(?P<HID>[0-9]+): Table (?P<TABLE>[ a-zA-Z]+) - \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) - (?P<GAMETYPE>.*) - (?P<HR>[0-9]+):(?P<MIN>[0-9]+) ET - (?P<YEAR>[0-9]+)/(?P<MON>[0-9]+)/(?P<DAY>[0-9]+)Table (?P<TABLE>[ a-zA-Z]+)\nSeat (?P<BUTTON>[0-9]+)') self.re_Button = re.compile('The button is in seat #(?P<BUTTON>\d+)')
self.rexx.button_re = 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.rexx.setPlayerInfoRegex('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$(?P<CASH>[.0-9]+)\)\n') self.re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
self.rexx.setPostSbRegex('.*\n(?P<PNAME>.*) posts the small blind of \$?(?P<SB>[.0-9]+)')
self.rexx.setPostBbRegex('.*\n(?P<PNAME>.*) posts (the big blind of )?\$?(?P<BB>[.0-9]+)') def compile_player_regexs(self):
self.rexx.setPostBothRegex('.*\n(?P<PNAME>.*) posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)') player_re = "(?P<PNAME>" + "|".join(map(re.escape, self.players)) + ")"
self.rexx.setHeroCardsRegex('.*\nDealt\sto\s(?P<PNAME>.*)\s\[(?P<CARDS>.*)\]') #print "DEBUG player_re: " + player_re
self.rexx.setActionStepRegex('.*\n(?P<PNAME>.*)(?P<ATYPE> bets| checks| raises to| calls| folds)(\s\$(?P<BET>[.\d]+))?') self.re_PostSB = re.compile('.*\n(?P<PNAME>.*) posts the small blind of \$?(?P<SB>[.0-9]+)')
self.rexx.setShowdownActionRegex('.*\n(?P<PNAME>.*) shows \[(?P<CARDS>.*)\]') self.re_PostBB = re.compile('.*\n(?P<PNAME>.*) posts (the big blind of )?\$?(?P<BB>[.0-9]+)')
self.rexx.setCollectPotRegex(r"Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*?) (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(\$(?P<POT>[.\d]+)\)(, mucked| with.*)") self.re_BringIn = re.compile('.*\n(?P<PNAME>.*) brings in for \$?(?P<BRINGIN>[.0-9]+)')
self.rexx.shown_cards_re = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(.*\) showed \[(?P<CARDS>.*)\].*') self.re_PostBoth = re.compile('.*\n(?P<PNAME>.*) posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)')
self.rexx.sits_out_re = re.compile('(?P<PNAME>.*) sits out') self.re_HeroCards = re.compile('.*\nDealt\sto\s(?P<PNAME>.*)\s\[(?P<CARDS>.*)\]')
self.rexx.compileRegexes() 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>.*)\].*')
def readSupportedGames(self): def readSupportedGames(self):
pass return [["ring", "hold", "nl"],
["ring", "hold", "pl"],
["ring", "razz", "fl"],
["ring", "omaha", "pl"]
]
def determineGameType(self): def determineGameType(self):
# Cheating with this regex, only support nlhe at the moment # Cheating with this regex, only support nlhe at the moment
gametype = ["ring", "hold", "nl"] # Full Tilt Poker Game #10777181585: Table Deerfly (deep 6) - $0.01/$0.02 - Pot Limit Omaha Hi - 2:24:44 ET - 2009/02/22
# Full Tilt Poker Game #10773265574: Table Butte (6 max) - $0.01/$0.02 - Pot Limit Hold'em - 21:33:46 ET - 2009/02/21
# Full Tilt Poker Game #9403951181: Table CR - tay - $0.05/$0.10 - No Limit Hold'em - 9:40:20 ET - 2008/12/09
structure = "" # nl, pl, cn, cp, fl
game = ""
m = self.rexx.game_info_re.search(self.obs)
gametype = gametype + [m.group('SB')] m = self.re_GameInfo.search(self.obs)
gametype = gametype + [m.group('BB')] if m.group('LTYPE') == "No ":
structure = "nl"
elif m.group('LTYPE') == "Pot ":
structure = "pl"
elif m.group('LTYPE') == "None":
structure = "fl"
if m.group('GAME') == "Hold\'em":
game = "hold"
elif m.group('GAME') == "Omaha":
game = "omahahi"
elif m.group('GAME') == "Razz":
game = "razz"
gametype = ["ring", game, structure, m.group('SB'), m.group('BB')]
return gametype return gametype
def readHandInfo(self, hand): def readHandInfo(self, hand):
m = self.rexx.hand_info_re.search(hand.string,re.DOTALL) m = self.re_HandInfo.search(hand.string,re.DOTALL)
#print m.groups() #print m.groups()
hand.handid = m.group('HID') hand.handid = m.group('HID')
hand.tablename = m.group('TABLE') hand.tablename = m.group('TABLE')
hand.buttonpos = int(self.rexx.button_re.search(hand.string).group('BUTTON'))
hand.starttime = time.strptime(m.group('DATETIME'), "%H:%M:%S ET - %Y/%m/%d") 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. # These work, but the info is already in the Hand class - should be used for tourneys though.
# m.group('SB') # m.group('SB')
@ -125,7 +107,7 @@ class FullTilt(HandHistoryConverter):
#FIXME: hand.buttonpos = int(m.group('BUTTON')) #FIXME: hand.buttonpos = int(m.group('BUTTON'))
def readPlayerStacks(self, hand): def readPlayerStacks(self, hand):
m = self.rexx.player_info_re.finditer(hand.string) m = self.re_PlayerInfo.finditer(hand.string)
players = [] players = []
for a in m: for a in m:
hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH')) hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH'))
@ -134,34 +116,53 @@ class FullTilt(HandHistoryConverter):
# PREFLOP = ** Dealing down cards ** # PREFLOP = ** Dealing down cards **
# This re fails if, say, river is missing; then we don't get the ** that starts the river. # 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 \*\*\*)|.+)" m = re.search(r"\*\*\* HOLE CARDS \*\*\*(?P<PREFLOP>.+(?=\*\*\* FLOP \*\*\*)|.+)"
r"(\*\*\* FLOP \*\*\*(?P<FLOP> \[\S\S \S\S \S\S\].+(?=\*\*\* TURN \*\*\*)|.+))?" 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"(\*\*\* 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) 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) hand.addStreets(m)
def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand
if street in ('FLOP','TURN','RIVER'): # a list of streets which get dealt community cards (i.e. all but PREFLOP) if street in ('FLOP','TURN','RIVER'): # a list of streets which get dealt community cards (i.e. all but PREFLOP)
self.rexx.board_re = re.compile(r"\[(?P<CARDS>.+)\]")
#print "DEBUG readCommunityCards:", street, hand.streets.group(street) #print "DEBUG readCommunityCards:", street, hand.streets.group(street)
m = self.rexx.board_re.search(hand.streets.group(street)) m = self.re_Board.search(hand.streets.group(street))
hand.setCommunityCards(street, m.group('CARDS').split(' ')) hand.setCommunityCards(street, m.group('CARDS').split(' '))
def readBlinds(self, hand): def readBlinds(self, hand):
try: try:
m = self.rexx.small_blind_re.search(hand.string) m = self.re_PostSB.search(hand.string)
hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB')) hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB'))
except: # no small blind except: # no small blind
hand.addBlind(None, None, None) hand.addBlind(None, None, None)
for a in self.rexx.big_blind_re.finditer(hand.string): for a in self.re_PostBB.finditer(hand.string):
hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB')) hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB'))
for a in self.rexx.both_blinds_re.finditer(hand.string): for a in self.re_PostBoth.finditer(hand.string):
hand.addBlind(a.group('PNAME'), 'small & big blinds', a.group('SBBB')) hand.addBlind(a.group('PNAME'), 'small & big blinds', a.group('SBBB'))
def readAntes(self, hand):
print "DEBUG: reading antes"
print "DEBUG: FIXME reading antes"
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'))
def readButton(self, hand):
hand.buttonpos = int(self.re_Button.search(hand.string).group('BUTTON'))
def readHeroCards(self, hand): def readHeroCards(self, hand):
m = self.rexx.hero_cards_re.search(hand.string) m = self.re_HeroCards.search(hand.string)
if(m == None): if(m == None):
#Not involved in hand #Not involved in hand
hand.involved = False hand.involved = False
@ -174,7 +175,7 @@ class FullTilt(HandHistoryConverter):
hand.addHoleCards(cards, m.group('PNAME')) hand.addHoleCards(cards, m.group('PNAME'))
def readAction(self, hand, street): def readAction(self, hand, street):
m = self.rexx.action_re.finditer(hand.streets.group(street)) m = self.re_Action.finditer(hand.streets.group(street))
for action in m: for action in m:
if action.group('ATYPE') == ' raises to': if action.group('ATYPE') == ' raises to':
hand.addRaiseTo( street, action.group('PNAME'), action.group('BET') ) hand.addRaiseTo( street, action.group('PNAME'), action.group('BET') )
@ -191,17 +192,17 @@ class FullTilt(HandHistoryConverter):
def readShowdownActions(self, hand): def readShowdownActions(self, hand):
for shows in self.rexx.showdown_action_re.finditer(hand.string): for shows in self.re_ShowdownAction.finditer(hand.string):
cards = shows.group('CARDS') cards = shows.group('CARDS')
cards = set(cards.split(' ')) cards = set(cards.split(' '))
hand.addShownCards(cards, shows.group('PNAME')) hand.addShownCards(cards, shows.group('PNAME'))
def readCollectPot(self,hand): def readCollectPot(self,hand):
for m in self.rexx.collect_pot_re.finditer(hand.string): for m in self.re_CollectPot.finditer(hand.string):
hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT')) hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT'))
def readShownCards(self,hand): def readShownCards(self,hand):
for m in self.rexx.shown_cards_re.finditer(hand.string): for m in self.re_ShownCards.finditer(hand.string):
if m.group('CARDS') is not None: if m.group('CARDS') is not None:
cards = m.group('CARDS') cards = m.group('CARDS')
cards = set(cards.split(' ')) cards = set(cards.split(' '))
@ -211,7 +212,7 @@ class FullTilt(HandHistoryConverter):
if __name__ == "__main__": if __name__ == "__main__":
c = Configuration.Config() c = Configuration.Config()
if len(sys.argv) == 1: if len(sys.argv) == 1:
testfile = "regression-test-files/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: else:
testfile = sys.argv[1] testfile = sys.argv[1]
print "Converting: ", testfile print "Converting: ", testfile

View File

@ -39,7 +39,10 @@ class Hand:
self.gametype = gametype self.gametype = gametype
self.string = string 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 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','FORTH','FIFTH','SIXTH','SEVENTH'] # a list of the observed street names in order
self.handid = 0 self.handid = 0
self.sb = gametype[3] self.sb = gametype[3]
@ -135,7 +138,7 @@ Assigns observed holecards to a player.
cards set of card bigrams e.g. set(['2h','Jc']) cards set of card bigrams e.g. set(['2h','Jc'])
player (string) name of player player (string) name of player
""" """
print "DEBUG: addHoleCards", cards,player #print "DEBUG: addHoleCards", cards,player
try: try:
self.checkPlayerExists(player) self.checkPlayerExists(player)
cards = set([self.card(c) for c in cards]) cards = set([self.card(c) for c in cards])
@ -148,7 +151,7 @@ player (string) name of player
For when a player shows cards for any reason (for showdown or out of choice). For when a player shows cards for any reason (for showdown or out of choice).
Card ranks will be uppercased Card ranks will be uppercased
""" """
print "DEBUG: addShownCards", cards,player,holeandboard #print "DEBUG: addShownCards", cards,player,holeandboard
if cards is not None: if cards is not None:
self.shown.add(player) self.shown.add(player)
self.addHoleCards(cards,player) self.addHoleCards(cards,player)
@ -194,7 +197,7 @@ Card ranks will be uppercased
# If a player posts a big & small blind # If a player posts a big & small blind
# - FIXME: We dont record this for later printing yet # - FIXME: We dont record this for later printing yet
print "DEBUG addBlind: %s posts %s, %s" % (player, blindtype, amount) #print "DEBUG addBlind: %s posts %s, %s" % (player, blindtype, amount)
if player is not None: if player is not None:
self.bets['PREFLOP'][player].append(Decimal(amount)) self.bets['PREFLOP'][player].append(Decimal(amount))
self.stacks[player] -= Decimal(amount) self.stacks[player] -= Decimal(amount)
@ -208,7 +211,7 @@ Card ranks will be uppercased
# extra small blind is 'dead' # extra small blind is 'dead'
self.lastBet['PREFLOP'] = Decimal(self.bb) self.lastBet['PREFLOP'] = Decimal(self.bb)
self.posted = self.posted + [[player,blindtype]] self.posted = self.posted + [[player,blindtype]]
print "DEBUG: self.posted: %s" %(self.posted) #print "DEBUG: self.posted: %s" %(self.posted)
def addCall(self, street, player=None, amount=None): def addCall(self, street, player=None, amount=None):
@ -218,7 +221,7 @@ Card ranks will be uppercased
self.bets[street][player].append(Decimal(amount)) self.bets[street][player].append(Decimal(amount))
#self.lastBet[street] = Decimal(amount) #self.lastBet[street] = Decimal(amount)
self.stacks[player] -= Decimal(amount) self.stacks[player] -= Decimal(amount)
print "DEBUG %s calls %s, stack %s" % (player, amount, self.stacks[player]) #print "DEBUG %s calls %s, stack %s" % (player, amount, self.stacks[player])
act = (player, 'calls', amount, self.stacks[player]==0) act = (player, 'calls', amount, self.stacks[player]==0)
self.actions[street].append(act) self.actions[street].append(act)
self.pot.addMoney(player, Decimal(amount)) self.pot.addMoney(player, Decimal(amount))
@ -290,7 +293,7 @@ Add a raise on [street] by [player] to [amountTo]
self.checkPlayerExists(player) self.checkPlayerExists(player)
self.bets[street][player].append(Decimal(amount)) self.bets[street][player].append(Decimal(amount))
self.stacks[player] -= Decimal(amount) self.stacks[player] -= Decimal(amount)
print "DEBUG %s bets %s, stack %s" % (player, amount, self.stacks[player]) #print "DEBUG %s bets %s, stack %s" % (player, amount, self.stacks[player])
act = (player, 'bets', amount, self.stacks[player]==0) act = (player, 'bets', amount, self.stacks[player]==0)
self.actions[street].append(act) self.actions[street].append(act)
self.lastBet[street] = Decimal(amount) self.lastBet[street] = Decimal(amount)
@ -298,7 +301,7 @@ Add a raise on [street] by [player] to [amountTo]
def addFold(self, street, player): def addFold(self, street, player):
print "DEBUG: %s %s folded" % (street, player) #print "DEBUG: %s %s folded" % (street, player)
self.checkPlayerExists(player) self.checkPlayerExists(player)
self.folded.add(player) self.folded.add(player)
self.pot.addFold(player) self.pot.addFold(player)
@ -306,19 +309,13 @@ Add a raise on [street] by [player] to [amountTo]
def addCheck(self, street, player): def addCheck(self, street, player):
print "DEBUG: %s %s checked" % (street, player) #print "DEBUG: %s %s checked" % (street, player)
self.checkPlayerExists(player) self.checkPlayerExists(player)
self.actions[street].append((player, 'checks')) self.actions[street].append((player, 'checks'))
# dart1 wins $ 51.09 USD from main pot with a full house, queens full of threes [ Qh, Qc, Qd, 3c, 3s ]
# dart1 wins $ 41.07 USD from side pot with a full house, queens full of threes [ Qh, Qc, Qd, 3c, 3s ]
# DEBUG: dart1 collected 51.09
# DEBUG: dart1 collected 41.07
# [WARNING] %s collected pot more than once; avoidable by reading winnings only from summary lines?
# TODO: Should we just add the pots together??
def addCollectPot(self,player, pot): def addCollectPot(self,player, pot):
print "DEBUG: %s collected %s" % (player, pot) #print "DEBUG: %s collected %s" % (player, pot)
self.checkPlayerExists(player) self.checkPlayerExists(player)
self.collected = self.collected + [[player, pot]] self.collected = self.collected + [[player, pot]]
if player not in self.collectees: if player not in self.collectees:
@ -351,7 +348,7 @@ Map the tuple self.gametype onto the pokerstars string describing it
""" """
# currently it appears to be something like ["ring", "hold", "nl", sb, bb]: # currently it appears to be something like ["ring", "hold", "nl", sb, bb]:
gs = {"hold" : "Hold'em", gs = {"hold" : "Hold'em",
"omahahi" : "FIXME", "omahahi" : "Omaha",
"omahahilo" : "FIXME", "omahahilo" : "FIXME",
"razz" : "Razz", "razz" : "Razz",
"studhi" : "FIXME", "studhi" : "FIXME",
@ -424,7 +421,7 @@ Map the tuple self.gametype onto the pokerstars string describing it
# we probably don't need a showdown section in pseudo stars format for our filtering purposes # we probably don't need a showdown section in pseudo stars format for our filtering purposes
if 'SHOWDOWN' in self.actions: if 'SHOWDOWN' in self.actions:
print >>fh, _("*** SHOW DOWN ***") print >>fh, _("*** SHOW DOWN ***")
print >>fh, "DEBUG: what do they show" # print >>fh, "DEBUG: what do they show"
# Current PS format has the lines: # Current PS format has the lines:
# Uncalled bet ($111.25) returned to s0rrow # Uncalled bet ($111.25) returned to s0rrow

View File

@ -91,6 +91,7 @@ class HandHistoryConverter:
self.ofile = os.path.join(self.hhdir, os.path.basename(file)) self.ofile = os.path.join(self.hhdir, os.path.basename(file))
self.rexx = FpdbRegex.FpdbRegex() self.rexx = FpdbRegex.FpdbRegex()
self.players = set() self.players = set()
self.maxseats = 10
def __str__(self): def __str__(self):
tmp = "HandHistoryConverter: '%s'\n" % (self.sitename) tmp = "HandHistoryConverter: '%s'\n" % (self.sitename)
@ -98,11 +99,11 @@ class HandHistoryConverter:
tmp = tmp + "\thhdir: '%s'\n" % (self.hhdir) tmp = tmp + "\thhdir: '%s'\n" % (self.hhdir)
tmp = tmp + "\tfiletype: '%s'\n" % (self.filetype) tmp = tmp + "\tfiletype: '%s'\n" % (self.filetype)
tmp = tmp + "\tinfile: '%s'\n" % (self.file) tmp = tmp + "\tinfile: '%s'\n" % (self.file)
# tmp = tmp + "\toutfile: '%s'\n" % (self.ofile) tmp = tmp + "\toutfile: '%s'\n" % (self.ofile)
# tmp = tmp + "\tgametype: '%s'\n" % (self.gametype[0]) #tmp = tmp + "\tgametype: '%s'\n" % (self.gametype[0])
# tmp = tmp + "\tgamebase: '%s'\n" % (self.gametype[1]) #tmp = tmp + "\tgamebase: '%s'\n" % (self.gametype[1])
# tmp = tmp + "\tlimit: '%s'\n" % (self.gametype[2]) #tmp = tmp + "\tlimit: '%s'\n" % (self.gametype[2])
# tmp = tmp + "\tsb/bb: '%s/%s'\n" % (self.gametype[3], self.gametype[4]) #tmp = tmp + "\tsb/bb: '%s/%s'\n" % (self.gametype[3], self.gametype[4])
return tmp return tmp
def processFile(self): def processFile(self):
@ -114,17 +115,17 @@ class HandHistoryConverter:
if self.obs == "" or self.obs == None: if self.obs == "" or self.obs == None:
print "Did not read anything from file." print "Did not read anything from file."
return return
# Ugh
self.obs = self.obs.replace('\r\n', '\n') self.obs = self.obs.replace('\r\n', '\n')
outfile = open(self.ofile, 'w') outfile = open(self.ofile, 'w')
self.gametype = self.determineGameType() self.gametype = self.determineGameType()
self.hands = self.splitFileIntoHands() self.hands = self.splitFileIntoHands()
for hand in self.hands: for hand in self.hands:
# print "\nInput:\n"+hand.string #print "\nDEBUG: Input:\n"+hand.string
self.readHandInfo(hand) self.readHandInfo(hand)
self.readPlayerStacks(hand) self.readPlayerStacks(hand)
print "DEBUG stacks:", hand.stacks #print "DEBUG stacks:", hand.stacks
# at this point we know the player names, they are in hand.players # at this point we know the player names, they are in hand.players
playersThisHand = set([player[1] for player in hand.players]) playersThisHand = set([player[1] for player in hand.players])
if playersThisHand <= self.players: # x <= y means 'x is subset of y' if playersThisHand <= self.players: # x <= y means 'x is subset of y'
@ -135,16 +136,27 @@ class HandHistoryConverter:
self.players = playersThisHand self.players = playersThisHand
self.compile_player_regexs() self.compile_player_regexs()
# Different calls if stud or holdem like
if self.gametype[1] == "hold" or self.gametype[1] == "omaha":
self.markStreets(hand) self.markStreets(hand)
self.readBlinds(hand) self.readBlinds(hand)
self.readButton(hand)
self.readHeroCards(hand) # want to generalise to draw games 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.markStreets(hand) # <--- Different streets
self.readAntes(hand)
self.readBringIn(hand)
self.readShowdownActions(hand) self.readShowdownActions(hand)
# Read actions in street order # Read actions in street order
for street in hand.streetList: # go through them in order for street in hand.streetList: # go through them in order
if hand.streets.group(street) is not None: 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 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) self.readAction(hand, street)
@ -164,7 +176,7 @@ class HandHistoryConverter:
outfile.close() outfile.close()
endtime = time.time() endtime = time.time()
print "Processed %d hands in %d seconds" % (len(self.hands), endtime-starttime) 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 # These functions are parse actions that may be overridden by the inheriting class
@ -207,6 +219,9 @@ class HandHistoryConverter:
# ['player1name', 'player2name', ...] where player1name is the sb and player2name is bb, # ['player1name', 'player2name', ...] where player1name is the sb and player2name is bb,
# addtional players are assumed to post a bb oop # addtional players are assumed to post a bb oop
def readBlinds(self, hand): abstract 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 readHeroCards(self, hand): abstract
def readAction(self, hand, street): abstract def readAction(self, hand, street): abstract
def readCollectPot(self, hand): abstract def readCollectPot(self, hand): abstract

View File

@ -34,6 +34,7 @@ import fpdb_db
import fpdb_parse_logic import fpdb_parse_logic
import Configuration import Configuration
import EverleafToFpdb import EverleafToFpdb
import FulltiltToFpdb
# database interface modules # database interface modules
try: try:
@ -117,6 +118,8 @@ class Importer:
#dirlist is a hash of lists: #dirlist is a hash of lists:
#dirlist{ 'PokerStars' => ["/path/to/import/", "filtername"] } #dirlist{ 'PokerStars' => ["/path/to/import/", "filtername"] }
def addImportDirectory(self,dir,monitor = False, site = "default", filter = "passthrough"): 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 os.path.isdir(dir):
if monitor == True: if monitor == True:
self.monitor = True self.monitor = True
@ -207,7 +210,7 @@ class Importer:
conv = EverleafToFpdb.Everleaf(self.config, file) conv = EverleafToFpdb.Everleaf(self.config, file)
elif filter == "FulltiltToFpdb": elif filter == "FulltiltToFpdb":
print "converting ", file print "converting ", file
conv = FulltiltToFpdb.Fulltilt(self.config, file) conv = FulltiltToFpdb.FullTilt(self.config, file)
else: else:
print "Unknown filter ", filter print "Unknown filter ", filter
return return