iPoker: Update from initial Carbon template

determineGameType: partially functional
readHandInfo: partially functional
readPlayerStacks: Done
compilePlayerRegexes: Skipped
markStreets: done for Stud
readAntes: Needs doing
readBlinds: Needs doing
readBringIn: Needs doing
...
readAction: Partially complete
This commit is contained in:
Worros 2010-09-11 16:11:16 +08:00
parent 5a7c628dba
commit 8911790408

View File

@ -23,16 +23,8 @@
#
# TODO:
#
# -- No siteID assigned
# -- No support for games other than NL hold 'em cash. Hand histories for other
# games required
# -- No support for limit hold 'em yet, though this would be easy to add
# -- No support for tournaments (see also the last item below)
# -- Assumes that the currency of ring games is USD
# -- Only works for 'gametype="2"'. What is 'gametype'?
# -- Only accepts 'realmoney="true"'
# -- A hand's time-stamp does not record seconds past the minute (a
# limitation of the history format)
# -- No support for a bring-in or for antes (is the latter in fact unnecessary
# for hold 'em on Carbon?)
# -- hand.maxseats can only be guessed at
@ -77,23 +69,19 @@ class iPoker(HandHistoryConverter):
re_SplitHands = re.compile(r'</game>\n+(?=<game)')
re_TailSplitHands = re.compile(r'(</game>)')
re_GameInfo = re.compile(r'<gametype>(?P<GAME>[a-zA-Z0-9 ]+) \$(?P<SB>[.0-9]+)/\$(?P<BB>[.0-9]+)</gametype>', re.MULTILINE)
# \$(?P<SB>[.0-9]+)\/\$(?P<BB>[.0-9]+)<\/gametype>', re.MULTILINE)
re_HandInfo = re.compile(r'<game id="(?P<HID1>[0-9]+)-(?P<HID2>[0-9]+)" starttime="(?P<DATETIME>[0-9]+)" numholecards="2" gametype="2" realmoney="true" data="[0-9]+\|(?P<TABLE>[^\(]+)', re.MULTILINE)
re_HandInfo = re.compile(r'gamecode="(?P<HID>[0-9]+)">\s+<general>\s+<startdate>(?P<DATETIME>[-: 0-9]+)</startdate>', re.MULTILINE)
re_Button = re.compile(r'<players dealer="(?P<BUTTON>[0-9]+)">')
re_PlayerInfo = re.compile(r'<player seat="(?P<SEAT>[0-9]+)" nickname="(?P<PNAME>.+)" balance="\$(?P<CASH>[.0-9]+)" dealtin="(?P<DEALTIN>(true|false))" />', re.MULTILINE)
re_PlayerInfo = re.compile(r'<player seat="(?P<SEAT>[0-9]+)" name="(?P<PNAME>[^"]+)" chips="\$(?P<CASH>[.0-9]+)" dealer="(?P<DEALTIN>(0|1))"', re.MULTILINE)
re_Board = re.compile(r'<cards type="COMMUNITY" cards="(?P<CARDS>[^"]+)"', re.MULTILINE)
re_EndOfHand = re.compile(r'<round id="END_OF_GAME"', re.MULTILINE)
# The following are also static regexes: there is no need to call
# compilePlayerRegexes (which does nothing), since players are identified
# not by name but by seat number
re_PostSB = re.compile(r'<event sequence="[0-9]+" type="(SMALL_BLIND|RETURN_BLIND)" player="(?P<PSEAT>[0-9])" amount="(?P<SB>[.0-9]+)"/>', re.MULTILINE)
re_PostBB = re.compile(r'<event sequence="[0-9]+" type="(BIG_BLIND|INITIAL_BLIND)" player="(?P<PSEAT>[0-9])" amount="(?P<BB>[.0-9]+)"/>', re.MULTILINE)
re_PostBoth = re.compile(r'<event sequence="[0-9]+" type="(RETURN_BLIND)" player="(?P<PSEAT>[0-9])" amount="(?P<SBBB>[.0-9]+)"/>', re.MULTILINE)
#re_Antes = ???
#re_BringIn = ???
re_HeroCards = re.compile(r'<cards type="HOLE" cards="(?P<CARDS>.+)" player="(?P<PSEAT>[0-9])"', re.MULTILINE)
re_Action = re.compile(r'<event sequence="[0-9]+" type="(?P<ATYPE>FOLD|CHECK|CALL|BET|RAISE|ALL_IN|SIT_OUT)" (?P<TIMESTAMP>timestamp="[0-9]+" )?player="(?P<PSEAT>[0-9])"( amount="(?P<BET>[.0-9]+)")?/>', re.MULTILINE)
re_Action = re.compile(r'<action no="[0-9]+" player="(?P<PNAME>[^"]+)" type="(?P<ATYPE>0|3|4|16)" sum="\$(?P<BET>[.0-9]+)"', re.MULTILINE)
re_ShowdownAction = re.compile(r'<cards type="SHOWN" cards="(?P<CARDS>..,..)" player="(?P<PSEAT>[0-9])"/>', re.MULTILINE)
re_CollectPot = re.compile(r'<winner amount="(?P<POT>[.0-9]+)" uncalled="(true|false)" potnumber="[0-9]+" player="(?P<PSEAT>[0-9])"', re.MULTILINE)
re_SitsOut = re.compile(r'<event sequence="[0-9]+" type="SIT_OUT" player="(?P<PSEAT>[0-9])"/>', re.MULTILINE)
@ -110,8 +98,11 @@ class iPoker(HandHistoryConverter):
return p[1]
def readSupportedGames(self):
return [["ring", "hold", "nl"],
["tour", "hold", "nl"]]
return [
["ring", "stud", "fl"],
#["ring", "hold", "nl"],
#["tour", "hold", "nl"]
]
def determineGameType(self, handText):
"""return dict with keys/values:
@ -144,6 +135,7 @@ or None if we fail to get the info """
self.info = {}
mg = m.groupdict()
print "DEBUG: m.groupdict(): %s" % mg
limits = { 'No Limit':'nl', 'Limit':'fl' }
games = { # base, category
@ -171,24 +163,21 @@ or None if we fail to get the info """
def readHandInfo(self, hand):
m = self.re_HandInfo.search(hand.handText)
if m is None:
logging.info(_("Didn't match re_HandInfo"))
logging.error(_("Didn't match re_HandInfo"))
logging.info(hand.handText)
return None
logging.debug("HID %s-%s, Table %s" % (m.group('HID1'),
m.group('HID2'), m.group('TABLE')[:-1]))
hand.handid = m.group('HID1') + m.group('HID2')
hand.tablename = m.group('TABLE')[:-1]
hand.maxseats = 2 # This value may be increased as necessary
hand.startTime = datetime.datetime.strptime(m.group('DATETIME')[:12],
'%Y%m%d%H%M')
# Check that the hand is complete up to the awarding of the pot; if
# not, the hand is unparseable
if self.re_EndOfHand.search(hand.handText) is None:
raise FpdbParseError(hid=m.group('HID1') + "-" + m.group('HID2'))
raise FpdbParseError(_("Didn't match re_HandInfo"))
mg = m.groupdict()
print "DEBUG: m.groupdict(): %s" % mg
hand.handid = m.group('HID')
#hand.tablename = m.group('TABLE')[:-1]
hand.maxseats = None
hand.startTime = datetime.datetime.strptime(m.group('DATETIME'), '%Y-%m-%d %H:%M:%S')
def readPlayerStacks(self, hand):
m = self.re_PlayerInfo.finditer(hand.handText)
for a in m:
ag = a.groupdict()
print "DEBUG: ag: %s" %ag
seatno = int(a.group('SEAT'))
# It may be necessary to adjust 'hand.maxseats', which is an
# educated guess, starting with 2 (indicating a heads-up table) and
@ -202,12 +191,18 @@ or None if we fail to get the info """
hand.maxseats = 9
else:
hand.maxseats = 6
if a.group('DEALTIN') == "true":
hand.addPlayer(seatno, a.group('PNAME'), a.group('CASH'))
hand.addPlayer(seatno, a.group('PNAME'), a.group('CASH'))
def markStreets(self, hand):
#if hand.gametype['base'] == 'hold':
m = re.search(r'<round id="PREFLOP" sequence="[0-9]+">(?P<PREFLOP>.+(?=<round id="POSTFLOP")|.+)(<round id="POSTFLOP" sequence="[0-9]+">(?P<FLOP>.+(?=<round id="POSTTURN")|.+))?(<round id="POSTTURN" sequence="[0-9]+">(?P<TURN>.+(?=<round id="POSTRIVER")|.+))?(<round id="POSTRIVER" sequence="[0-9]+">(?P<RIVER>.+))?', hand.handText, re.DOTALL)
if hand.gametype['base'] in ('stud'):
m = re.search(r'(?P<ANTES>.+(?=<round no="2">)|.+)'
r'(<round no="2">(?P<THIRD>.+(?=<round no="3">)|.+))?'
r'(<round no="3">(?P<FOURTH>.+(?=<round no="4">)|.+))?'
r'(<round no="4">(?P<FIFTH>.+(?=<round no="5">)|.+))?'
r'(<round no="5">(?P<SIXTH>.+(?=<round no="6">)|.+))?'
r'(<round no="6">(?P<SEVENTH>.+))?', hand.handText,re.DOTALL)
hand.addStreets(m)
def readCommunityCards(self, hand, street):
@ -224,27 +219,11 @@ or None if we fail to get the info """
pass # ???
def readBlinds(self, hand):
try:
m = self.re_PostSB.search(hand.handText)
hand.addBlind(self.playerNameFromSeatNo(m.group('PSEAT'), hand),
'small blind', m.group('SB'))
except: # no small blind
hand.addBlind(None, None, None)
m = self.re_PostSB.search(hand.handText)
hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB'))
for a in self.re_PostBB.finditer(hand.handText):
hand.addBlind(self.playerNameFromSeatNo(a.group('PSEAT'), hand),
'big blind', a.group('BB'))
for a in self.re_PostBoth.finditer(hand.handText):
bb = Decimal(self.info['bb'])
amount = Decimal(a.group('SBBB'))
if amount < bb:
hand.addBlind(self.playerNameFromSeatNo(a.group('PSEAT'),
hand), 'small blind', a.group('SBBB'))
elif amount == bb:
hand.addBlind(self.playerNameFromSeatNo(a.group('PSEAT'),
hand), 'big blind', a.group('SBBB'))
else:
hand.addBlind(self.playerNameFromSeatNo(a.group('PSEAT'),
hand), 'both', a.group('SBBB'))
hand.addBlind(m.group('PNAME'), 'big blind', a.group('BB'))
#for a in self.re_PostBoth.finditer(hand.handText):
def readButton(self, hand):
hand.buttonpos = int(self.re_Button.search(hand.handText).group('BUTTON'))
@ -261,24 +240,24 @@ or None if we fail to get the info """
logging.debug("readAction (%s)" % street)
m = self.re_Action.finditer(hand.streets[street])
for action in m:
ag = action.groupdict()
print "DEBUG: action.groupdict: %s" % ag
logging.debug("%s %s" % (action.group('ATYPE'),
action.groupdict()))
player = self.playerNameFromSeatNo(action.group('PSEAT'), hand)
if action.group('ATYPE') == 'RAISE':
hand.addCallandRaise(street, player, action.group('BET'))
elif action.group('ATYPE') == 'CALL':
hand.addCall(street, player, action.group('BET'))
elif action.group('ATYPE') == '3': # Believe this is 'call'
hand.addCall(street, action.group('PNAME'), action.group('BET'))
elif action.group('ATYPE') == 'BET':
hand.addBet(street, player, action.group('BET'))
elif action.group('ATYPE') in ('FOLD', 'SIT_OUT'):
hand.addFold(street, player)
elif action.group('ATYPE') == '0': # Belive this is 'fold'
hand.addFold(street, action.group('PNAME'))
elif action.group('ATYPE') == 'CHECK':
hand.addCheck(street, player)
elif action.group('ATYPE') == 'ALL_IN':
hand.addAllIn(street, player, action.group('BET'))
else:
logging.debug(_("Unimplemented readAction: %s %s"
% (action.group('PSEAT'),action.group('ATYPE'),)))
logging.error(_("Unimplemented readAction: %s" % (ag)))
def readShowdownActions(self, hand):
for shows in self.re_ShowdownAction.finditer(hand.handText):