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

This commit is contained in:
Eric Blade 2010-09-06 15:52:43 -04:00
commit 27c6250be9
10 changed files with 427 additions and 11 deletions

View File

@ -44,7 +44,7 @@ class Betfair(HandHistoryConverter):
siteId = 7 # Needs to match id entry in Sites database siteId = 7 # Needs to match id entry in Sites database
# Static regexes # Static regexes
re_GameInfo = re.compile("^(?P<LIMIT>NL|PL|) (?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAME>(Texas Hold\'em|Omaha Hi|Razz))", re.MULTILINE) re_GameInfo = re.compile("^(?P<LIMIT>NL|PL|) (?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAME>(Texas Hold\'em|Omaha Hi|Omaha|Razz))", re.MULTILINE)
re_SplitHands = re.compile(r'\n\n+') re_SplitHands = re.compile(r'\n\n+')
re_HandInfo = re.compile("\*\*\*\*\* Betfair Poker Hand History for Game (?P<HID>[0-9]+) \*\*\*\*\*\n(?P<LIMIT>NL|PL|) (?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAMETYPE>(Texas Hold\'em|Omaha Hi|Razz)) - (?P<DATETIME>[a-zA-Z]+, [a-zA-Z]+ \d+, \d\d:\d\d:\d\d GMT \d\d\d\d)\nTable (?P<TABLE>[ a-zA-Z0-9]+) \d-max \(Real Money\)\nSeat (?P<BUTTON>[0-9]+)", re.MULTILINE) re_HandInfo = re.compile("\*\*\*\*\* Betfair Poker Hand History for Game (?P<HID>[0-9]+) \*\*\*\*\*\n(?P<LIMIT>NL|PL|) (?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAMETYPE>(Texas Hold\'em|Omaha Hi|Razz)) - (?P<DATETIME>[a-zA-Z]+, [a-zA-Z]+ \d+, \d\d:\d\d:\d\d GMT \d\d\d\d)\nTable (?P<TABLE>[ a-zA-Z0-9]+) \d-max \(Real Money\)\nSeat (?P<BUTTON>[0-9]+)", re.MULTILINE)
re_Button = re.compile(ur"^Seat (?P<BUTTON>\d+) is the button", re.MULTILINE) re_Button = re.compile(ur"^Seat (?P<BUTTON>\d+) is the button", re.MULTILINE)
@ -72,7 +72,8 @@ class Betfair(HandHistoryConverter):
self.re_ShownCards = re.compile(r"%s (?P<SEAT>[0-9]+) (?P<CARDS>adsfasdf)" % player_re, re.MULTILINE) self.re_ShownCards = re.compile(r"%s (?P<SEAT>[0-9]+) (?P<CARDS>adsfasdf)" % player_re, re.MULTILINE)
def readSupportedGames(self): def readSupportedGames(self):
return [["ring", "hold", "nl"] return [["ring", "hold", "nl"],
["ring", "hold", "pl"]
] ]
def determineGameType(self, handText): def determineGameType(self, handText):
@ -80,8 +81,10 @@ class Betfair(HandHistoryConverter):
m = self.re_GameInfo.search(handText) m = self.re_GameInfo.search(handText)
if not m: if not m:
logging.info(_('GameInfo regex did not match')) tmp = handText[0:100]
return None log.error(_("determineGameType: Unable to recognise gametype from: '%s'") % tmp)
log.error(_("determineGameType: Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
mg = m.groupdict() mg = m.groupdict()
@ -90,6 +93,7 @@ class Betfair(HandHistoryConverter):
games = { # base, category games = { # base, category
"Texas Hold'em" : ('hold','holdem'), "Texas Hold'em" : ('hold','holdem'),
'Omaha Hi' : ('hold','omahahi'), 'Omaha Hi' : ('hold','omahahi'),
'Omaha' : ('hold','omahahi'),
'Razz' : ('stud','razz'), 'Razz' : ('stud','razz'),
'7 Card Stud' : ('stud','studhi') '7 Card Stud' : ('stud','studhi')
} }
@ -104,16 +108,15 @@ class Betfair(HandHistoryConverter):
info['bb'] = mg['BB'] info['bb'] = mg['BB']
if 'CURRENCY' in mg: if 'CURRENCY' in mg:
info['currency'] = currencies[mg['CURRENCY']] info['currency'] = currencies[mg['CURRENCY']]
# NB: SB, BB must be interpreted as blinds or bets depending on limit type.
return info return info
def readHandInfo(self, hand): def readHandInfo(self, hand):
m = self.re_HandInfo.search(hand.handText) m = self.re_HandInfo.search(hand.handText)
if(m == None): if(m == None):
logging.info(_("Didn't match re_HandInfo")) log.error(_("Didn't match re_HandInfo"))
logging.info(hand.handText) raise FpdbParseError("No match in readHandInfo.")
return None print "DEBUG: got this far!"
logging.debug("HID %s, Table %s" % (m.group('HID'), m.group('TABLE'))) logging.debug("HID %s, Table %s" % (m.group('HID'), m.group('TABLE')))
hand.handid = m.group('HID') hand.handid = m.group('HID')
hand.tablename = m.group('TABLE') hand.tablename = m.group('TABLE')

View File

@ -1443,6 +1443,7 @@ class Database:
c.execute("INSERT INTO Sites (name,code) VALUES ('Partouche', 'PA')") c.execute("INSERT INTO Sites (name,code) VALUES ('Partouche', 'PA')")
c.execute("INSERT INTO Sites (name,code) VALUES ('Carbon', 'CA')") c.execute("INSERT INTO Sites (name,code) VALUES ('Carbon', 'CA')")
c.execute("INSERT INTO Sites (name,code) VALUES ('PKR', 'PK')") c.execute("INSERT INTO Sites (name,code) VALUES ('PKR', 'PK')")
c.execute("INSERT INTO Sites (name,code) VALUES ('iPoker', 'IP')")
#end def fillDefaultData #end def fillDefaultData
def rebuild_indexes(self, start=None): def rebuild_indexes(self, start=None):

View File

@ -577,6 +577,7 @@ Left-Drag to Move"
<hhc site="Partouche" converter="PartoucheToFpdb"/> <hhc site="Partouche" converter="PartoucheToFpdb"/>
<hhc site="Carbon" converter="CarbonToFpdb"/> <hhc site="Carbon" converter="CarbonToFpdb"/>
<hhc site="PKR" converter="PkrToFpdb"/> <hhc site="PKR" converter="PkrToFpdb"/>
<hhc site="iPoker" converter="iPokerToFpdb"/>
</hhcs> </hhcs>
<supported_databases> <supported_databases>

View File

@ -702,6 +702,7 @@ Left-Drag to Move"
<hhc site="Carbon" converter="CarbonToFpdb"/> <hhc site="Carbon" converter="CarbonToFpdb"/>
<hhc site="OnGame" converter="OnGameToFpdb"/> <hhc site="OnGame" converter="OnGameToFpdb"/>
<hhc site="PKR" converter="PkrToFpdb"/> <hhc site="PKR" converter="PkrToFpdb"/>
<hhc site="iPoker" converter="iPokerToFpdb"/>
</hhcs> </hhcs>
<raw_hands save="none" compression="none"/> <raw_hands save="none" compression="none"/>

View File

@ -199,6 +199,10 @@ class PartyPoker(HandHistoryConverter):
m = self._getGameType(handText) m = self._getGameType(handText)
m_20BBmin = self.re_20BBmin.search(handText) m_20BBmin = self.re_20BBmin.search(handText)
if m is None: if m is None:
tmp = handText[0:100]
log.error(_("determineGameType: Unable to recognise gametype from: '%s'") % tmp)
log.error(_("determineGameType: Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
return None return None
mg = m.groupdict() mg = m.groupdict()

View File

@ -239,6 +239,7 @@ class Pkr(HandHistoryConverter):
if players.has_key(a.group('PNAME')): if players.has_key(a.group('PNAME')):
pass # Ignore pass # Ignore
else: else:
#print "DEBUG: addPlayer(%s, %s, %s)" % (a.group('SEAT'), a.group('PNAME'), a.group('CASH'))
hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH')) hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH'))
players[a.group('PNAME')] = True players[a.group('PNAME')] = True
@ -335,9 +336,16 @@ class Pkr(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()
#print "DEBUG: readAction: acts: %s" % acts
if action.group('ATYPE') == ' raises': if action.group('ATYPE') == ' raises':
hand.addRaiseTo( street, action.group('PNAME'), action.group('BET') ) hand.addRaiseTo( street, action.group('PNAME'), action.group('BET') )
elif action.group('ATYPE') == ' calls': elif action.group('ATYPE') == ' calls':
# Amount in hand history is not cumulative
# ie. Player3 calls 0.08
# Player5 raises to 0.16
# Player3 calls 0.16 (Doh! he's only calling 0.08
# TODO: Going to have to write an addCallStoopid()
#print "DEBUG: addCall( %s, %s, None)" %(street,action.group('PNAME'))
hand.addCall( street, action.group('PNAME'), action.group('BET') ) hand.addCall( street, action.group('PNAME'), action.group('BET') )
elif action.group('ATYPE') == ' bets': elif action.group('ATYPE') == ' bets':
hand.addBet( street, action.group('PNAME'), action.group('BET') ) hand.addBet( street, action.group('PNAME'), action.group('BET') )

View File

@ -221,8 +221,7 @@ class PokerStars(HandHistoryConverter):
m = self.re_HandInfo.search(hand.handText,re.DOTALL) m = self.re_HandInfo.search(hand.handText,re.DOTALL)
m2 = self.re_GameInfo.search(hand.handText) m2 = self.re_GameInfo.search(hand.handText)
if m is None or m2 is None: if m is None or m2 is None:
logging.info("Didn't match re_HandInfo") log.error("Didn't match re_HandInfo")
logging.info(hand.handText)
raise FpdbParseError("No match in readHandInfo.") raise FpdbParseError("No match in readHandInfo.")
info.update(m.groupdict()) info.update(m.groupdict())

View File

@ -145,11 +145,13 @@ def main(argv=None):
EverleafErrors = FpdbError('Everleaf Poker') EverleafErrors = FpdbError('Everleaf Poker')
CarbonErrors = FpdbError('Carbon') CarbonErrors = FpdbError('Carbon')
PKRErrors = FpdbError('PKR') PKRErrors = FpdbError('PKR')
iPokerErrors = FpdbError('iPoker')
ErrorsList = [ ErrorsList = [
PokerStarsErrors, FTPErrors, PartyPokerErrors, PokerStarsErrors, FTPErrors, PartyPokerErrors,
BetfairErrors, OnGameErrors, AbsoluteErrors, BetfairErrors, OnGameErrors, AbsoluteErrors,
EverleafErrors, CarbonErrors, PKRErrors EverleafErrors, CarbonErrors, PKRErrors,
iPokerErrors
] ]
walk_testfiles("regression-test-files/cash/Stars/", compare, importer, PokerStarsErrors, "PokerStars") walk_testfiles("regression-test-files/cash/Stars/", compare, importer, PokerStarsErrors, "PokerStars")
@ -164,6 +166,7 @@ def main(argv=None):
walk_testfiles("regression-test-files/cash/Everleaf/", compare, importer, EverleafErrors, "Everleaf") walk_testfiles("regression-test-files/cash/Everleaf/", compare, importer, EverleafErrors, "Everleaf")
walk_testfiles("regression-test-files/cash/Carbon/", compare, importer, CarbonErrors, "Carbon") walk_testfiles("regression-test-files/cash/Carbon/", compare, importer, CarbonErrors, "Carbon")
walk_testfiles("regression-test-files/cash/PKR/", compare, importer, PKRErrors, "PKR") walk_testfiles("regression-test-files/cash/PKR/", compare, importer, PKRErrors, "PKR")
walk_testfiles("regression-test-files/cash/iPoker/", compare, importer, iPokerErrors, "iPoker")
totalerrors = 0 totalerrors = 0

325
pyfpdb/iPokerToFpdb.py Normal file
View File

@ -0,0 +1,325 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2010, Carl Gherardi
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
########################################################################
# This code is based on CarbonToFpdb.py by Matthew Boss
#
# 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
# -- The last hand in a history file will often be incomplete and is therefore
# rejected
# -- Is behaviour currently correct when someone shows an uncalled hand?
# -- Information may be lost when the hand ID is converted from the native form
# xxxxxxxx-yyy(y*) to xxxxxxxxyyy(y*) (in principle this should be stored as
# a string, but the database does not support this). Is there a possibility
# of collision between hand IDs that ought to be distinct?
# -- Cannot parse tables that run it twice (nor is this likely ever to be
# possible)
# -- Cannot parse hands in which someone is all in in one of the blinds. Until
# this is corrected tournaments will be unparseable
import sys
import logging
from HandHistoryConverter import *
from decimal import Decimal
import locale
lang=locale.getdefaultlocale()[0][0:2]
if lang=="en":
def _(string): return string
else:
import gettext
try:
trans = gettext.translation("fpdb", localedir="locale", languages=[lang])
trans.install()
except IOError:
def _(string): return string
class iPoker(HandHistoryConverter):
sitename = "iPoker"
filetype = "text"
codepage = "cp1252"
siteID = 11
# Static regexes
re_SplitHands = re.compile(r'</game>\n+(?=<game)')
re_TailSplitHands = re.compile(r'(</game>)')
re_GameInfo = re.compile(r'<description type="(?P<GAME>[a-zA-Z ]+)" stakes="(?P<LIMIT>[a-zA-Z ]+) \(\$(?P<SB>[.0-9]+)/\$(?P<BB>[.0-9]+)\)"/>', 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_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_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_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)
re_ShownCards = re.compile(r'<cards type="(SHOWN|MUCKED)" cards="(?P<CARDS>..,..)" player="(?P<PSEAT>[0-9])"/>', re.MULTILINE)
def compilePlayerRegexs(self, hand):
pass
def playerNameFromSeatNo(self, seatNo, hand):
# This special function is required because Carbon Poker records
# actions by seat number, not by the player's name
for p in hand.players:
if p[0] == int(seatNo):
return p[1]
def readSupportedGames(self):
return [["ring", "hold", "nl"],
["tour", "hold", "nl"]]
def determineGameType(self, handText):
"""return dict with keys/values:
'type' in ('ring', 'tour')
'limitType' in ('nl', 'cn', 'pl', 'cp', 'fl')
'base' in ('hold', 'stud', 'draw')
'category' in ('holdem', 'omahahi', omahahilo', 'razz', 'studhi', 'studhilo', 'fivedraw', '27_1draw', '27_3draw', 'badugi')
'hilo' in ('h','l','s')
'smallBlind' int?
'bigBlind' int?
'smallBet'
'bigBet'
'currency' in ('USD', 'EUR', 'T$', <countrycode>)
or None if we fail to get the info """
m = self.re_GameInfo.search(handText)
if not m:
# Information about the game type appears only at the beginning of
# a hand history file; hence it is not supplied with the second
# and subsequent hands. In these cases we use the value previously
# stored.
try:
self.info
return self.info
except AttributeError:
tmp = handText[0:100]
log.error(_("determineGameType: Unable to recognise gametype from: '%s'") % tmp)
log.error(_("determineGameType: Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
self.info = {}
mg = m.groupdict()
limits = { 'No Limit':'nl', 'Limit':'fl' }
games = { # base, category
'Holdem' : ('hold','holdem'),
'Holdem Tournament' : ('hold','holdem') }
if 'LIMIT' in mg:
self.info['limitType'] = limits[mg['LIMIT']]
if 'GAME' in mg:
(self.info['base'], self.info['category']) = games[mg['GAME']]
if 'SB' in mg:
self.info['sb'] = mg['SB']
if 'BB' in mg:
self.info['bb'] = mg['BB']
if mg['GAME'] == 'Holdem Tournament':
self.info['type'] = 'tour'
self.info['currency'] = 'T$'
else:
self.info['type'] = 'ring'
self.info['currency'] = 'USD'
return self.info
def readHandInfo(self, hand):
m = self.re_HandInfo.search(hand.handText)
if m is None:
logging.info(_("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'))
def readPlayerStacks(self, hand):
m = self.re_PlayerInfo.finditer(hand.handText)
for a in m:
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
# adjusted upwards in steps to 6, then 9, then 10. An adjustment is
# made whenever a player is discovered whose seat number is
# currently above the maximum allowable for the table.
if seatno >= hand.maxseats:
if seatno > 8:
hand.maxseats = 10
elif seatno > 5:
hand.maxseats = 9
else:
hand.maxseats = 6
if a.group('DEALTIN') == "true":
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)
hand.addStreets(m)
def readCommunityCards(self, hand, street):
m = self.re_Board.search(hand.streets[street])
if street == 'FLOP':
hand.setCommunityCards(street, m.group('CARDS').split(','))
elif street in ('TURN','RIVER'):
hand.setCommunityCards(street, [m.group('CARDS').split(',')[-1]])
def readAntes(self, hand):
pass # ???
def readBringIn(self, hand):
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)
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'))
def readButton(self, hand):
hand.buttonpos = int(self.re_Button.search(hand.handText).group('BUTTON'))
def readHeroCards(self, hand):
m = self.re_HeroCards.search(hand.handText)
if m:
hand.hero = self.playerNameFromSeatNo(m.group('PSEAT'), hand)
cards = m.group('CARDS').split(',')
hand.addHoleCards('PREFLOP', hand.hero, closed=cards, shown=False,
mucked=False, dealt=True)
def readAction(self, hand, street):
logging.debug("readAction (%s)" % street)
m = self.re_Action.finditer(hand.streets[street])
for action in m:
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') == 'BET':
hand.addBet(street, player, action.group('BET'))
elif action.group('ATYPE') in ('FOLD', 'SIT_OUT'):
hand.addFold(street, player)
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'),)))
def readShowdownActions(self, hand):
for shows in self.re_ShowdownAction.finditer(hand.handText):
cards = shows.group('CARDS').split(',')
hand.addShownCards(cards,
self.playerNameFromSeatNo(shows.group('PSEAT'),
hand))
def readCollectPot(self, hand):
pots = [Decimal(0) for n in range(hand.maxseats)]
for m in self.re_CollectPot.finditer(hand.handText):
pots[int(m.group('PSEAT'))] += Decimal(m.group('POT'))
# Regarding the processing logic for "committed", see Pot.end() in
# Hand.py
committed = sorted([(v,k) for (k,v) in hand.pot.committed.items()])
for p in range(hand.maxseats):
pname = self.playerNameFromSeatNo(p, hand)
if committed[-1][1] == pname:
pots[p] -= committed[-1][0] - committed[-2][0]
if pots[p] > 0:
hand.addCollectPot(player=pname, pot=pots[p])
def readShownCards(self, hand):
for m in self.re_ShownCards.finditer(hand.handText):
cards = m.group('CARDS').split(',')
hand.addShownCards(cards=cards, player=self.playerNameFromSeatNo(m.group('PSEAT'), hand))
if __name__ == "__main__":
parser = OptionParser()
parser.add_option("-i", "--input", dest="ipath", help=_("parse input hand history"), default="-")
parser.add_option("-o", "--output", dest="opath", help=_("output translation to"), default="-")
parser.add_option("-f", "--follow", dest="follow", help=_("follow (tail -f) the input"), action="store_true", default=False)
parser.add_option("-q", "--quiet", action="store_const", const=logging.CRITICAL, dest="verbosity", default=logging.INFO)
parser.add_option("-v", "--verbose", action="store_const", const=logging.INFO, dest="verbosity")
parser.add_option("--vv", action="store_const", const=logging.DEBUG, dest="verbosity")
(options, args) = parser.parse_args()
LOG_FILENAME = './logging.out'
logging.basicConfig(filename=LOG_FILENAME, level=options.verbosity)
e = Carbon(in_path = options.ipath,
out_path = options.opath,
follow = options.follow,
autostart = True)

View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?><session sessioncode="2752856781">
<general>
<mode>real</mode>
<gametype>7 Card Stud L $0.05/$0.10</gametype>
<tablename>Labyrinth</tablename>
<duration>00:04</duration>
<gamecount>2</gamecount>
<startdate>2010-09-05 13:00:46</startdate>
<currency>USD</currency>
<nickname>exStingray</nickname>
<bets>$0.04</bets>
<wins>$0</wins>
<chipsin>1</chipsin>
<chipsout>0.88</chipsout>
<ipoints>0.08</ipoints>
</general>
<game gamecode="2418629537">
<general>
<startdate>2010-09-05 13:00:46</startdate>
<players>
<player seat="1" name="exStingray" chips="$1" dealer="1" win="$0" bet="$0.01" /><player seat="2" name="Binghai" chips="$0.73" dealer="0" win="$0.13" bet="$0.03" /><player seat="3" name="" chips="$0" dealer="0" win="$0" bet="$0" /><player seat="4" name="FENGLIUDUSHENG" chips="$1.23" dealer="0" win="$0" bet="$0.01" /><player seat="5" name="komanchi7" chips="$0.59" dealer="0" win="$0" bet="$0.01" /><player seat="6" name="Qekz406" chips="$2.20" dealer="0" win="$0" bet="$0.03" /><player seat="7" name="axi0matic" chips="$3" dealer="0" win="$0" bet="$0.01" /><player seat="8" name="" chips="$0" dealer="0" win="$0" bet="$0" /><player seat="9" name="ad1028" chips="$3.58" dealer="0" win="$0" bet="$0" /><player seat="10" name="Zsuzsanna" chips="$0.83" dealer="0" win="$0" bet="$0.03" />
</players>
</general>
<round no="0">
<action no="1" player="exStingray" type="15" sum="$0.01" cards="[cards]"/><action no="2" player="Binghai" type="15" sum="$0.01" cards="[cards]"/><action no="3" player="FENGLIUDUSHENG" type="15" sum="$0.01" cards="[cards]"/><action no="4" player="komanchi7" type="15" sum="$0.01" cards="[cards]"/><action no="5" player="Qekz406" type="15" sum="$0.01" cards="[cards]"/><action no="6" player="axi0matic" type="15" sum="$0.01" cards="[cards]"/><action no="7" player="Zsuzsanna" type="15" sum="$0.01" cards="[cards]"/>
</round>
<round no="1">
</round>
<round no="2">
<cards type="Third Street" player="exStingray">X X H6</cards><action no="14" player="exStingray" type="0" sum="$0" cards=""/><cards type="Third Street" player="Binghai">H8 D7 C2</cards><action no="8" player="Binghai" type="16" sum="$0.02" cards=""/><cards type="Third Street" player="FENGLIUDUSHENG">X X HA</cards><action no="9" player="FENGLIUDUSHENG" type="0" sum="$0" cards=""/><cards type="Third Street" player="komanchi7">X X CQ</cards><action no="10" player="komanchi7" type="0" sum="$0" cards=""/><cards type="Third Street" player="Qekz406">H9 S6 C7</cards><action no="11" player="Qekz406" type="3" sum="$0.02" cards=""/><cards type="Third Street" player="axi0matic">X X CK</cards><action no="12" player="axi0matic" type="0" sum="$0" cards=""/><cards type="Third Street" player="Zsuzsanna">D8 HJ HK</cards><action no="13" player="Zsuzsanna" type="3" sum="$0.02" cards=""/>
</round>
<round no="3">
<cards type="Fourth Street" player="Binghai">C5</cards><action no="16" player="Binghai" type="4" sum="$0" cards=""/><cards type="Fourth Street" player="Qekz406">S10</cards><action no="17" player="Qekz406" type="4" sum="$0" cards=""/><cards type="Fourth Street" player="Zsuzsanna">C10</cards><action no="15" player="Zsuzsanna" type="4" sum="$0" cards=""/>
</round>
<round no="4">
<cards type="Fifth Street" player="Binghai">H2</cards><action no="20" player="Binghai" type="4" sum="$0" cards=""/><cards type="Fifth Street" player="Qekz406">D10</cards><action no="18" player="Qekz406" type="4" sum="$0" cards=""/><cards type="Fifth Street" player="Zsuzsanna">H7</cards><action no="19" player="Zsuzsanna" type="4" sum="$0" cards=""/>
</round>
<round no="5">
<cards type="Sixth Street" player="Binghai">H4</cards><action no="23" player="Binghai" type="4" sum="$0" cards=""/><cards type="Sixth Street" player="Qekz406">D2</cards><action no="21" player="Qekz406" type="4" sum="$0" cards=""/><cards type="Sixth Street" player="Zsuzsanna">H3</cards><action no="22" player="Zsuzsanna" type="4" sum="$0" cards=""/>
</round>
<round no="6">
<cards type="River" player="Binghai">C4</cards><action no="26" player="Binghai" type="4" sum="$0" cards=""/><cards type="River" player="Qekz406">DQ</cards><action no="24" player="Qekz406" type="4" sum="$0" cards=""/><cards type="River" player="Zsuzsanna">DK</cards><action no="25" player="Zsuzsanna" type="4" sum="$0" cards=""/>
</round>
</game><game gamecode="2418630592">
<general>
<startdate>2010-09-05 13:01:58</startdate>
<players>
<player seat="1" name="exStingray" chips="$0.99" dealer="1" win="$0" bet="$0.03" /><player seat="2" name="Binghai" chips="$0.83" dealer="0" win="$0" bet="$0.03" /><player seat="3" name="" chips="$0" dealer="0" win="$0" bet="$0" /><player seat="4" name="FENGLIUDUSHENG" chips="$1.22" dealer="0" win="$0" bet="$0.03" /><player seat="5" name="komanchi7" chips="$0.58" dealer="0" win="$0.43" bet="$0.18" /><player seat="6" name="Qekz406" chips="$2.17" dealer="0" win="$0" bet="$0.01" /><player seat="7" name="axi0matic" chips="$2.99" dealer="0" win="$0" bet="$0.08" /><player seat="8" name="" chips="$0" dealer="0" win="$0" bet="$0" /><player seat="9" name="ad1028" chips="$3.58" dealer="0" win="$0" bet="$0" /><player seat="10" name="Zsuzsanna" chips="$0.80" dealer="0" win="$0" bet="$0.08" />
</players>
</general>
<round no="0">
<action no="1" player="exStingray" type="15" sum="$0.01" cards="[cards]"/><action no="2" player="Binghai" type="15" sum="$0.01" cards="[cards]"/><action no="3" player="FENGLIUDUSHENG" type="15" sum="$0.01" cards="[cards]"/><action no="4" player="komanchi7" type="15" sum="$0.01" cards="[cards]"/><action no="5" player="Qekz406" type="15" sum="$0.01" cards="[cards]"/><action no="6" player="axi0matic" type="15" sum="$0.01" cards="[cards]"/><action no="7" player="Zsuzsanna" type="15" sum="$0.01" cards="[cards]"/>
</round>
<round no="1">
</round>
<round no="2">
<cards type="Third Street" player="exStingray">D4 S7 C8</cards><action no="13" player="exStingray" type="3" sum="$0.02" cards=""/><cards type="Third Street" player="Binghai">X X D5</cards><action no="14" player="Binghai" type="3" sum="$0.02" cards=""/><cards type="Third Street" player="FENGLIUDUSHENG">X X S2</cards><action no="8" player="FENGLIUDUSHENG" type="16" sum="$0.02" cards=""/><cards type="Third Street" player="komanchi7">X X H9</cards><action no="9" player="komanchi7" type="3" sum="$0.02" cards=""/><cards type="Third Street" player="Qekz406">X X CJ</cards><action no="10" player="Qekz406" type="0" sum="$0" cards=""/><cards type="Third Street" player="axi0matic">X X H10</cards><action no="11" player="axi0matic" type="3" sum="$0.02" cards=""/><cards type="Third Street" player="Zsuzsanna">X X H5</cards><action no="12" player="Zsuzsanna" type="3" sum="$0.02" cards=""/>
</round>
<round no="3">
<cards type="Fourth Street" player="exStingray">H2</cards><action no="18" player="exStingray" type="0" sum="$0" cards=""/><cards type="Fourth Street" player="Binghai">H7</cards><action no="19" player="Binghai" type="0" sum="$0" cards=""/><cards type="Fourth Street" player="FENGLIUDUSHENG">H6</cards><action no="20" player="FENGLIUDUSHENG" type="0" sum="$0" cards=""/><cards type="Fourth Street" player="komanchi7">HQ</cards><action no="15" player="komanchi7" type="5" sum="$0.05" cards=""/><cards type="Fourth Street" player="axi0matic">D9</cards><action no="16" player="axi0matic" type="3" sum="$0.05" cards=""/><cards type="Fourth Street" player="Zsuzsanna">C6</cards><action no="17" player="Zsuzsanna" type="3" sum="$0.05" cards=""/>
</round>
<round no="4">
<cards type="Fifth Street" player="komanchi7">HA</cards><action no="21" player="komanchi7" type="5" sum="$0.10" cards=""/><cards type="Fifth Street" player="axi0matic">S8</cards><action no="22" player="axi0matic" type="0" sum="$0" cards=""/><cards type="Fifth Street" player="Zsuzsanna">D2</cards><action no="23" player="Zsuzsanna" type="0" sum="$0" cards=""/>
</round>
</game>
</session>