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
# 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_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)
@ -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)
def readSupportedGames(self):
return [["ring", "hold", "nl"]
return [["ring", "hold", "nl"],
["ring", "hold", "pl"]
]
def determineGameType(self, handText):
@ -80,8 +81,10 @@ class Betfair(HandHistoryConverter):
m = self.re_GameInfo.search(handText)
if not m:
logging.info(_('GameInfo regex did not match'))
return 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)
mg = m.groupdict()
@ -90,6 +93,7 @@ class Betfair(HandHistoryConverter):
games = { # base, category
"Texas Hold'em" : ('hold','holdem'),
'Omaha Hi' : ('hold','omahahi'),
'Omaha' : ('hold','omahahi'),
'Razz' : ('stud','razz'),
'7 Card Stud' : ('stud','studhi')
}
@ -104,16 +108,15 @@ class Betfair(HandHistoryConverter):
info['bb'] = mg['BB']
if 'CURRENCY' in mg:
info['currency'] = currencies[mg['CURRENCY']]
# NB: SB, BB must be interpreted as blinds or bets depending on limit type.
return info
def readHandInfo(self, hand):
m = self.re_HandInfo.search(hand.handText)
if(m == None):
logging.info(_("Didn't match re_HandInfo"))
logging.info(hand.handText)
return None
log.error(_("Didn't match re_HandInfo"))
raise FpdbParseError("No match in readHandInfo.")
print "DEBUG: got this far!"
logging.debug("HID %s, Table %s" % (m.group('HID'), m.group('TABLE')))
hand.handid = m.group('HID')
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 ('Carbon', 'CA')")
c.execute("INSERT INTO Sites (name,code) VALUES ('PKR', 'PK')")
c.execute("INSERT INTO Sites (name,code) VALUES ('iPoker', 'IP')")
#end def fillDefaultData
def rebuild_indexes(self, start=None):

View File

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

View File

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

View File

@ -199,6 +199,10 @@ class PartyPoker(HandHistoryConverter):
m = self._getGameType(handText)
m_20BBmin = self.re_20BBmin.search(handText)
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
mg = m.groupdict()

View File

@ -239,6 +239,7 @@ class Pkr(HandHistoryConverter):
if players.has_key(a.group('PNAME')):
pass # Ignore
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'))
players[a.group('PNAME')] = True
@ -335,9 +336,16 @@ class Pkr(HandHistoryConverter):
m = self.re_Action.finditer(hand.streets[street])
for action in m:
acts = action.groupdict()
#print "DEBUG: readAction: acts: %s" % acts
if action.group('ATYPE') == ' raises':
hand.addRaiseTo( street, action.group('PNAME'), action.group('BET') )
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') )
elif action.group('ATYPE') == ' bets':
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)
m2 = self.re_GameInfo.search(hand.handText)
if m is None or m2 is None:
logging.info("Didn't match re_HandInfo")
logging.info(hand.handText)
log.error("Didn't match re_HandInfo")
raise FpdbParseError("No match in readHandInfo.")
info.update(m.groupdict())

View File

@ -145,11 +145,13 @@ def main(argv=None):
EverleafErrors = FpdbError('Everleaf Poker')
CarbonErrors = FpdbError('Carbon')
PKRErrors = FpdbError('PKR')
iPokerErrors = FpdbError('iPoker')
ErrorsList = [
PokerStarsErrors, FTPErrors, PartyPokerErrors,
BetfairErrors, OnGameErrors, AbsoluteErrors,
EverleafErrors, CarbonErrors, PKRErrors
EverleafErrors, CarbonErrors, PKRErrors,
iPokerErrors
]
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/Carbon/", compare, importer, CarbonErrors, "Carbon")
walk_testfiles("regression-test-files/cash/PKR/", compare, importer, PKRErrors, "PKR")
walk_testfiles("regression-test-files/cash/iPoker/", compare, importer, iPokerErrors, "iPoker")
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>