Merge branch 'master' of git://github.com/grindi/fpdb-grindi

This commit is contained in:
Worros 2009-08-11 20:56:43 +08:00
commit 836cba6594
2 changed files with 85 additions and 60 deletions

View File

@ -74,11 +74,17 @@ class Layout:
class Site: class Site:
def __init__(self, node): def __init__(self, node):
def normalizePath(path):
"Normalized existing pathes"
if os.path.exists(path):
return os.path.abspath(path)
return path
self.site_name = node.getAttribute("site_name") self.site_name = node.getAttribute("site_name")
self.table_finder = node.getAttribute("table_finder") self.table_finder = node.getAttribute("table_finder")
self.screen_name = node.getAttribute("screen_name") self.screen_name = node.getAttribute("screen_name")
self.site_path = node.getAttribute("site_path") self.site_path = normalizePath(node.getAttribute("site_path"))
self.HH_path = node.getAttribute("HH_path") self.HH_path = normalizePath(node.getAttribute("HH_path"))
self.decoder = node.getAttribute("decoder") self.decoder = node.getAttribute("decoder")
self.hudopacity = node.getAttribute("hudopacity") self.hudopacity = node.getAttribute("hudopacity")
self.hudbgcolor = node.getAttribute("bgcolor") self.hudbgcolor = node.getAttribute("bgcolor")
@ -92,6 +98,8 @@ class Site:
self.xpad = node.getAttribute("xpad") self.xpad = node.getAttribute("xpad")
self.ypad = node.getAttribute("ypad") self.ypad = node.getAttribute("ypad")
self.layout = {} self.layout = {}
print self.site_name, self.HH_path
for layout_node in node.getElementsByTagName('layout'): for layout_node in node.getElementsByTagName('layout'):
lo = Layout(layout_node) lo = Layout(layout_node)

View File

@ -21,24 +21,23 @@
import sys import sys
from collections import defaultdict from collections import defaultdict
from Exceptions import FpdbParseError
from HandHistoryConverter import * from HandHistoryConverter import *
# PartyPoker HH Format # PartyPoker HH Format
class PartyPokerParseError(FpdbParseError):
"Usage: raise PartyPokerParseError(<msg>[, hh=<hh>][, hid=<hid>])"
def __init__(self, msg='', hh=None, hid=None):
if hh is not None:
msg += "\n\nHand history attached below:\n" + self.wrapHh(hh)
return super(PartyPokerParseError, self).__init__(hid=hid)
#return super(PartyPokerParseError, self).__init__(msg, hid=hid)
def wrapHh(self, hh):
return ("%(DELIMETER)s\n%(HH)s\n%(DELIMETER)s") % \
{'DELIMETER': '#'*50, 'HH': hh}
class PartyPoker(HandHistoryConverter): class PartyPoker(HandHistoryConverter):
class ParsingException(Exception):
"Usage: raise ParsingException(<msg>[, hh=<hh>])"
def __init__(self, *args, **kwargs):
if len(args)==0: args=[''] + list(args)
msg, args = args[0], args[1:]
if 'hh' in kwargs:
msg += self.wrapHh(kwargs['hh'])
del kwargs['hh']
return Exception.__init__(self, msg, *args, **kwargs)
def wrapHh(self, hh):
return ("\n\nHand history attached below:\n"
"%(DELIMETER)s\n%(HH)s\n%(DELIMETER)s") % \
{'DELIMETER': '#'*50, 'HH': hh}
############################################################ ############################################################
# Class Variables # Class Variables
@ -116,6 +115,7 @@ class PartyPoker(HandHistoryConverter):
if mo == 10: return mo if mo == 10: return mo
if mo == 2: return 2 if mo == 2: return 2
if mo <= 6: return 6 if mo <= 6: return 6
# there are 9-max tables for cash and 10-max for tournaments
return 9 if hand.gametype['type']=='ring' else 10 return 9 if hand.gametype['type']=='ring' else 10
def compilePlayerRegexs(self, hand): def compilePlayerRegexs(self, hand):
@ -152,7 +152,7 @@ class PartyPoker(HandHistoryConverter):
r"\[ *(?P<CARDS>.+) *\](?P<COMBINATION>.+)\.", r"\[ *(?P<CARDS>.+) *\](?P<COMBINATION>.+)\.",
re.MULTILINE) re.MULTILINE)
self.re_CollectPot = re.compile( self.re_CollectPot = re.compile(
r""""^%(PLYR)s \s+ wins \s+ r"""^%(PLYR)s \s+ wins \s+
%(CUR_SYM)s(?P<POT>[.\d]+)\s*%(CUR)s""" % subst, %(CUR_SYM)s(?P<POT>[.\d]+)\s*%(CUR)s""" % subst,
re.MULTILINE|re.VERBOSE) re.MULTILINE|re.VERBOSE)
@ -187,7 +187,7 @@ class PartyPoker(HandHistoryConverter):
gametype dict is: gametype dict is:
{'limitType': xxx, 'base': xxx, 'category': xxx}""" {'limitType': xxx, 'base': xxx, 'category': xxx}"""
log.debug(self.ParsingException().wrapHh( handText )) log.debug(PartyPokerParseError().wrapHh( handText ))
info = {} info = {}
m = self._getGameType(handText) m = self._getGameType(handText)
@ -205,20 +205,20 @@ class PartyPoker(HandHistoryConverter):
for expectedField in ['LIMIT', 'GAME']: for expectedField in ['LIMIT', 'GAME']:
if mg[expectedField] is None: if mg[expectedField] is None:
raise self.ParsingException( raise PartyPokerParseError(
"Cannot fetch field '%s'" % expectedField, "Cannot fetch field '%s'" % expectedField,
hh = handText) hh = handText)
try: try:
info['limitType'] = limits[mg['LIMIT'].strip()] info['limitType'] = limits[mg['LIMIT'].strip()]
except: except:
raise self.ParsingException( raise PartyPokerParseError(
"Unknown limit '%s'" % mg['LIMIT'], "Unknown limit '%s'" % mg['LIMIT'],
hh = handText) hh = handText)
try: try:
(info['base'], info['category']) = games[mg['GAME']] (info['base'], info['category']) = games[mg['GAME']]
except: except:
raise self.ParsingException( raise PartyPokerParseError(
"Unknown game type '%s'" % mg['GAME'], "Unknown game type '%s'" % mg['GAME'],
hh = handText) hh = handText)
@ -231,6 +231,7 @@ class PartyPoker(HandHistoryConverter):
if info['type'] == 'ring': if info['type'] == 'ring':
info['sb'], info['bb'] = ringBlinds(mg['RINGLIMIT']) info['sb'], info['bb'] = ringBlinds(mg['RINGLIMIT'])
# FIXME: there are only $ and play money availible for cash # FIXME: there are only $ and play money availible for cash
# to be honest, party doesn't save play money hh
info['currency'] = currencies[mg['CURRENCY']] info['currency'] = currencies[mg['CURRENCY']]
else: else:
info['sb'] = clearMoneyString(mg['SB']) info['sb'] = clearMoneyString(mg['SB'])
@ -243,21 +244,27 @@ class PartyPoker(HandHistoryConverter):
def readHandInfo(self, hand): def readHandInfo(self, hand):
info = {} info = {}
m = self.re_HandInfo.search(hand.handText,re.DOTALL) try:
if m: info.update(self.re_Hid.search(hand.handText).groupdict())
info.update(m.groupdict()) except:
else: raise PartyPokerParseError("Cannot read HID for current hand", hh=hand.handText)
raise self.ParsingException("Cannot read Handinfo for current hand", hh=hand.handText)
m = self._getGameType(hand.handText) try:
if m: info.update(m.groupdict()) info.update(self.re_HandInfo.search(hand.handText,re.DOTALL).groupdict())
m = self.re_Hid.search(hand.handText) except:
if m: info.update(m.groupdict()) raise PartyPokerParseError("Cannot read Handinfo for current hand",
hh=hand.handText, hid = info['HID'])
try:
info.update(self._getGameType(hand.handText).groupdict())
except:
raise PartyPokerParseError("Cannot read GameType for current hand",
hh=hand.handText, hid = info['HID'])
m = self.re_TotalPlayers.search(hand.handText) m = self.re_TotalPlayers.search(hand.handText)
if m: info.update(m.groupdict()) if m: info.update(m.groupdict())
# FIXME: it's a hack cause party doesn't supply hand.maxseats info
#hand.maxseats = ???
hand.mixed = None hand.mixed = None
log.debug("readHandInfo: %s" % info) log.debug("readHandInfo: %s" % info)
@ -285,16 +292,14 @@ class PartyPoker(HandHistoryConverter):
if key == 'TOURNO': if key == 'TOURNO':
hand.tourNo = info[key] hand.tourNo = info[key]
if key == 'BUYIN': if key == 'BUYIN':
#FIXME: it's dirty hack T_T # FIXME: it's dirty hack T_T
# code below assumes that rake is equal to zero
cur = info[key][0] if info[key][0] not in '0123456789' else '' cur = info[key][0] if info[key][0] not in '0123456789' else ''
hand.buyin = info[key] + '+%s0' % cur hand.buyin = info[key] + '+%s0' % cur
#if key == 'MAXSEATS':
#hand.maxseats = int(info[key])
if key == 'LEVEL': if key == 'LEVEL':
hand.level = info[key] hand.level = info[key]
if key == 'PLAY' and info['PLAY'] != 'Real': if key == 'PLAY' and info['PLAY'] != 'Real':
# TODO: play money wasn't tested # if realy there's no play money hh on party
# hand.currency = 'play' # overrides previously set value
hand.gametype['currency'] = 'play' hand.gametype['currency'] = 'play'
def readButton(self, hand): def readButton(self, hand):
@ -313,10 +318,6 @@ class PartyPoker(HandHistoryConverter):
clearMoneyString(a.group('CASH'))) clearMoneyString(a.group('CASH')))
def markStreets(self, hand): def markStreets(self, hand):
# PREFLOP = ** Dealing down cards **
# This re fails if, say, river is missing; then we don't get the ** that starts the river.
assert hand.gametype['base'] == "hold", \
"wtf! There're no %s games on party" % hand.gametype['base']
m = re.search( m = re.search(
r"\*{2} Dealing down cards \*{2}" r"\*{2} Dealing down cards \*{2}"
r"(?P<PREFLOP>.+?)" r"(?P<PREFLOP>.+?)"
@ -337,11 +338,6 @@ class PartyPoker(HandHistoryConverter):
for player in m: for player in m:
hand.addAnte(player.group('PNAME'), player.group('ANTE')) hand.addAnte(player.group('PNAME'), player.group('ANTE'))
def readBringIn(self, hand):
m = self.re_BringIn.search(hand.handText,re.DOTALL)
if m:
hand.addBringIn(m.group('PNAME'), m.group('BRINGIN'))
def readBlinds(self, hand): def readBlinds(self, hand):
noSmallBlind = bool(self.re_NoSmallBlind.search(hand.handText)) noSmallBlind = bool(self.re_NoSmallBlind.search(hand.handText))
if hand.gametype['type'] == 'ring': if hand.gametype['type'] == 'ring':
@ -381,7 +377,7 @@ class PartyPoker(HandHistoryConverter):
bigBlindSeat = findFirstNonEmptySeat(smallBlindSeat + 1) bigBlindSeat = findFirstNonEmptySeat(smallBlindSeat + 1)
blind = smartMin(hand.bb, playersMap[bigBlindSeat][1]) blind = smartMin(hand.bb, playersMap[bigBlindSeat][1])
hand.addBlind(playersMap[bigBlindSeat][0], 'small blind', blind) hand.addBlind(playersMap[bigBlindSeat][0], 'big blind', blind)
@ -400,18 +396,39 @@ class PartyPoker(HandHistoryConverter):
m = self.re_Action.finditer(hand.streets[street]) m = self.re_Action.finditer(hand.streets[street])
for action in m: for action in m:
acts = action.groupdict() acts = action.groupdict()
if action.group('ATYPE') in ('raises','is all-In'): playerName = action.group('PNAME')
hand.addRaiseBy( street, action.group('PNAME'), action.group('BET') ) amount = clearMoneyString(action.group('BET')) if action.group('BET') else None
elif action.group('ATYPE') == 'calls': actionType = action.group('ATYPE')
hand.addCall( street, action.group('PNAME'), action.group('BET') )
elif action.group('ATYPE') == 'bets': if actionType == 'is all-In':
hand.addBet( street, action.group('PNAME'), action.group('BET') ) # party's allin can mean either raise or bet or call
elif action.group('ATYPE') == 'folds': Bp = hand.lastBet[street]
hand.addFold( street, action.group('PNAME')) if Bp == 0:
elif action.group('ATYPE') == 'checks': actionType = 'bets'
hand.addCheck( street, action.group('PNAME')) elif Bp < Decimal(amount):
actionType = 'raises'
else:
actionType = 'calls'
if actionType == 'raises':
if street == 'PREFLOP' and \
playerName in [item[0] for item in hand.actions['BLINDSANTES']]:
# preflop raise from blind
hand.addRaiseBy( street, playerName, amount )
else:
hand.addCallandRaise( street, playerName, amount )
elif actionType == 'calls':
hand.addCall( street, playerName, amount )
elif actionType == 'bets':
hand.addBet( street, playerName, amount )
elif actionType == 'folds':
hand.addFold( street, playerName )
elif actionType == 'checks':
hand.addCheck( street, playerName )
else: else:
print "DEBUG: unimplemented readAction: '%s' '%s'" %(action.group('PNAME'),action.group('ATYPE'),) raise PartyPokerParseError(
"Unimplemented readAction: '%s' '%s'" % (playerName,actionType,),
hid = hand.hid, hh = hand.handText )
def readShowdownActions(self, hand): def readShowdownActions(self, hand):
@ -434,17 +451,17 @@ class PartyPoker(HandHistoryConverter):
hand.addShownCards(cards=cards, player=m.group('PNAME'), shown=shown, mucked=mucked) hand.addShownCards(cards=cards, player=m.group('PNAME'), shown=shown, mucked=mucked)
def ringBlinds(ringLimit): def ringBlinds(ringLimit):
"Returns blinds for current limit" "Returns blinds for current limit in cash games"
ringLimit = float(clearMoneyString(ringLimit)) ringLimit = float(clearMoneyString(ringLimit))
if ringLimit == 5.: ringLimit = 4. if ringLimit == 5.: ringLimit = 4.
return ('%.2f' % (ringLimit/200.), '%.2f' % (ringLimit/100.) ) return ('%.2f' % (ringLimit/200.), '%.2f' % (ringLimit/100.) )
def clearMoneyString(money): def clearMoneyString(money):
"renders 'numbers' like '1 200' and '2,000'" "Renders 'numbers' like '1 200' and '2,000'"
return money.replace(' ', '').replace(',', '') return money.replace(' ', '').replace(',', '')
def renderCards(string): def renderCards(string):
"splits strings like ' Js, 4d '" "Splits strings like ' Js, 4d '"
cards = string.strip().split(' ') cards = string.strip().split(' ')
return filter(len, map(lambda x: x.strip(' ,'), cards)) return filter(len, map(lambda x: x.strip(' ,'), cards))