2008-12-16 15:45:58 +01:00
#!/usr/bin/env python
2009-03-10 00:03:17 +01:00
# -*- coding: utf-8 -*-
#
2008-12-16 15:45:58 +01:00
# Copyright 2008, 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
########################################################################
import sys
2009-03-04 17:46:01 +01:00
import logging
2008-12-16 15:45:58 +01:00
from HandHistoryConverter import *
2009-03-13 21:00:12 +01:00
# Fulltilt HH Format converter
2009-07-19 03:33:00 +02:00
# TODO: cat tourno and table to make table name for tournaments
2008-12-16 15:45:58 +01:00
2009-03-13 21:00:12 +01:00
class Fulltilt ( HandHistoryConverter ) :
2009-02-25 15:35:28 +01:00
2009-08-09 16:19:43 +02:00
sitename = " Fulltilt "
filetype = " text "
codepage = " cp1252 "
siteId = 1 # Needs to match id entry in Sites database
2009-02-25 15:35:28 +01:00
# Static regexes
2009-07-19 03:33:00 +02:00
re_GameInfo = re . compile ( ''' (?:(?P<TOURNAMENT>.+) \ s \ ((?P<TOURNO> \ d+) \ ), \ s)?
. +
- \s ( ? P < CURRENCY > \$ | ) ?
2009-07-17 23:07:53 +02:00
( ? P < SB > [ .0 - 9 ] + ) /
\$ ? ( ? P < BB > [ .0 - 9 ] + ) \s
2009-07-22 14:54:30 +02:00
( Ante \s \$ ? ( ? P < ANTE > [ .0 - 9 ] + ) \s ) ? - \s
2009-07-17 23:07:53 +02:00
( ? P < LIMIT > ( No \sLimit | Pot \sLimit | Limit ) ) ? \s
2009-07-22 14:54:30 +02:00
( ? P < GAME > ( Hold \' em|Omaha \ sHi|Omaha \ sH/L|7 \ sCard \ sStud|Stud \ sH/L|Razz|Stud \ sHi))
2009-07-17 23:07:53 +02:00
''' , re.VERBOSE)
2009-03-31 08:44:19 +02:00
re_SplitHands = re . compile ( r " \ n \ n+ " )
re_TailSplitHands = re . compile ( r " ( \ n \ n+) " )
2009-08-09 16:19:43 +02:00
re_HandInfo = re . compile ( r ''' .* \ #(?P<HID>[0-9]+): \ s
2009-07-19 03:33:00 +02:00
( ? : ( ? P < TOURNAMENT > . + ) \s \( ( ? P < TOURNO > \d + ) \) , \s ) ?
2009-07-22 14:54:30 +02:00
Table \s
2009-07-22 16:24:29 +02:00
( ? P < PLAY > Play \sChip \s | PC ) ?
2009-07-22 14:54:30 +02:00
( ? P < TABLE > [ - \s \da - zA - Z ] + ) \s
2009-07-17 23:07:53 +02:00
( \( ( ? P < TABLEATTRIBUTES > . + ) \) \s ) ? - \s
2009-07-22 14:54:30 +02:00
\$ ? ( ? P < SB > [ .0 - 9 ] + ) / \$ ? ( ? P < BB > [ .0 - 9 ] + ) \s ( Ante \s \$ ? ( ? P < ANTE > [ .0 - 9 ] + ) \s ) ? - \s
2009-07-17 23:07:53 +02:00
( ? P < GAMETYPE > [ a - zA - Z \/ \' \ s]+) \ s- \ s
2009-08-09 16:19:43 +02:00
( ? P < DATETIME > . * ? ) \n
( ? : . * ? \n ( ? P < CANCELLED > Hand \s \#(?P=HID)\shas\sbeen\scanceled))?
''' , re.VERBOSE|re.DOTALL)
2009-02-26 17:26:50 +01:00
re_Button = re . compile ( ' ^The button is in seat #(?P<BUTTON> \ d+) ' , re . MULTILINE )
2009-07-20 16:01:51 +02:00
re_PlayerInfo = re . compile ( ' Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \ ( \ $?(?P<CASH>[,.0-9]+) \ )$ ' , re . MULTILINE )
2009-02-25 15:35:28 +01:00
re_Board = re . compile ( r " \ [(?P<CARDS>.+) \ ] " )
2009-07-22 19:51:48 +02:00
# These regexes are for FTP only
2009-07-22 16:24:29 +02:00
re_Mixed = re . compile ( r ' \ s \ - \ s(?P<MIXED>HA|HORSE|HOSE) \ s \ - \ s ' , re . VERBOSE )
2009-07-22 19:51:48 +02:00
re_Max = re . compile ( " (?P<MAX> \ d+)( max)? " , re . MULTILINE )
2009-04-04 16:12:45 +02:00
# NB: if we ever match "Full Tilt Poker" we should also match "FullTiltPoker", which PT Stud erroneously exports.
2009-02-25 15:35:28 +01:00
2009-07-22 16:24:29 +02:00
mixes = { ' HORSE ' : ' horse ' , ' 7-Game ' : ' 7game ' , ' HOSE ' : ' hose ' , ' HA ' : ' ha ' }
2009-03-10 00:03:17 +01:00
def compilePlayerRegexs ( self , hand ) :
players = set ( [ player [ 1 ] for player in hand . players ] )
2009-03-07 10:06:52 +01:00
if not players < = self . compiledPlayers : # x <= y means 'x is subset of y'
# we need to recompile the player regexs.
self . compiledPlayers = players
player_re = " (?P<PNAME> " + " | " . join ( map ( re . escape , players ) ) + " ) "
logging . debug ( " player_re: " + player_re )
self . re_PostSB = re . compile ( r " ^ %s posts the small blind of \ $?(?P<SB>[.0-9]+) " % player_re , re . MULTILINE )
self . re_PostBB = re . compile ( r " ^ %s posts (the big blind of )? \ $?(?P<BB>[.0-9]+) " % player_re , re . MULTILINE )
self . re_Antes = re . compile ( r " ^ %s antes \ $?(?P<ANTE>[.0-9]+) " % player_re , re . MULTILINE )
self . re_BringIn = re . compile ( r " ^ %s brings in for \ $?(?P<BRINGIN>[.0-9]+) " % player_re , re . MULTILINE )
self . re_PostBoth = re . compile ( r " ^ %s posts small \ & big blinds \ [ \ $? (?P<SBBB>[.0-9]+) " % player_re , re . MULTILINE )
2009-03-02 22:48:30 +01:00
self . re_HeroCards = re . compile ( r " ^Dealt to %s (?: \ [(?P<OLDCARDS>.+?) \ ])?( \ [(?P<NEWCARDS>.+?) \ ]) " % player_re , re . MULTILINE )
2009-07-20 20:27:03 +02:00
self . re_Action = re . compile ( r " ^ %s (?P<ATYPE> bets| checks| raises to| completes it to| calls| folds)( \ $?(?P<BET>[., \ d]+))? " % player_re , re . MULTILINE )
2009-03-07 10:06:52 +01:00
self . re_ShowdownAction = re . compile ( r " ^ %s shows \ [(?P<CARDS>.*) \ ] " % player_re , re . MULTILINE )
self . re_CollectPot = re . compile ( r " ^Seat (?P<SEAT>[0-9]+): %s ( \ (button \ ) | \ (small blind \ ) | \ (big blind \ ) )?(collected|showed \ [.* \ ] and won) \ ( \ $(?P<POT>[. \ d]+) \ )(, mucked| with.*) " % player_re , re . MULTILINE )
self . re_SitsOut = re . compile ( r " ^ %s sits out " % player_re , re . MULTILINE )
self . re_ShownCards = re . compile ( r " ^Seat (?P<SEAT>[0-9]+): %s \ (.* \ ) showed \ [(?P<CARDS>.*) \ ].* " % player_re , re . MULTILINE )
2009-02-22 04:42:16 +01:00
2008-12-16 15:45:58 +01:00
def readSupportedGames ( self ) :
2009-02-22 10:07:11 +01:00
return [ [ " ring " , " hold " , " nl " ] ,
2009-02-23 11:24:21 +01:00
[ " ring " , " hold " , " pl " ] ,
2009-03-12 18:21:31 +01:00
[ " ring " , " hold " , " fl " ] ,
2009-07-19 03:33:00 +02:00
2009-03-12 18:18:34 +01:00
[ " ring " , " stud " , " fl " ] ,
2009-07-19 03:33:00 +02:00
[ " tour " , " hold " , " nl " ] ,
[ " tour " , " hold " , " pl " ] ,
[ " tour " , " hold " , " fl " ] ,
[ " tour " , " stud " , " fl " ] ,
2009-02-22 10:07:11 +01:00
]
2008-12-16 15:45:58 +01:00
2009-03-04 16:10:08 +01:00
def determineGameType ( self , handText ) :
2009-02-22 10:07:11 +01:00
# 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
2009-03-04 15:29:13 +01:00
# Full Tilt Poker Game #10809877615: Table Danville - $0.50/$1 Ante $0.10 - Limit Razz - 21:47:27 ET - 2009/02/23
2009-03-10 00:03:17 +01:00
info = { ' type ' : ' ring ' }
2009-03-04 16:10:08 +01:00
m = self . re_GameInfo . search ( handText )
2009-03-10 00:03:17 +01:00
if not m :
return None
mg = m . groupdict ( )
2009-07-30 06:13:45 +02:00
2009-03-10 00:03:17 +01:00
# translations from captured groups to our info strings
limits = { ' No Limit ' : ' nl ' , ' Pot Limit ' : ' pl ' , ' Limit ' : ' fl ' }
games = { # base, category
" Hold ' em " : ( ' hold ' , ' holdem ' ) ,
' Omaha Hi ' : ( ' hold ' , ' omahahi ' ) ,
2009-07-17 23:07:53 +02:00
' Omaha H/L ' : ( ' hold ' , ' omahahilo ' ) ,
2009-03-10 00:03:17 +01:00
' Razz ' : ( ' stud ' , ' razz ' ) ,
2009-07-22 14:54:30 +02:00
' Stud Hi ' : ( ' stud ' , ' studhi ' ) ,
' Stud H/L ' : ( ' stud ' , ' studhilo ' )
2009-03-10 00:03:17 +01:00
}
currencies = { u ' € ' : ' EUR ' , ' $ ' : ' USD ' , ' ' : ' T$ ' }
2009-07-17 23:07:53 +02:00
info [ ' limitType ' ] = limits [ mg [ ' LIMIT ' ] ]
info [ ' sb ' ] = mg [ ' SB ' ]
info [ ' bb ' ] = mg [ ' BB ' ]
if mg [ ' GAME ' ] != None :
2009-03-10 00:03:17 +01:00
( info [ ' base ' ] , info [ ' category ' ] ) = games [ mg [ ' GAME ' ] ]
2009-07-17 23:07:53 +02:00
if mg [ ' CURRENCY ' ] != None :
2009-03-10 00:03:17 +01:00
info [ ' currency ' ] = currencies [ mg [ ' CURRENCY ' ] ]
2009-07-19 03:33:00 +02:00
if mg [ ' TOURNO ' ] == None : info [ ' type ' ] = " ring "
else : info [ ' type ' ] = " tour "
2009-03-10 00:03:17 +01:00
# NB: SB, BB must be interpreted as blinds or bets depending on limit type.
2009-07-31 03:50:08 +02:00
if info [ ' type ' ] == " tour " : return None # importer is screwed on tournies, pass on those hands so we don't interrupt other autoimporting
2009-03-10 00:03:17 +01:00
return info
2008-12-16 15:45:58 +01:00
2009-07-30 06:13:45 +02:00
#Following function is a hack, we should be dealing with this in readFile (i think correct codepage....)
# Same function as parent class, removing the 2 end characters. - CG
def allHandsAsList ( self ) :
""" Return a list of handtexts in the file at self.in_path """
#TODO : any need for this to be generator? e.g. stars support can email one huge file of all hands in a year. Better to read bit by bit than all at once.
self . readFile ( )
# FIXME: it's a hack
if self . obs [ : 2 ] == u ' \xff \xfe ' :
self . obs = self . obs [ 2 : ] . replace ( ' \x00 ' , ' ' )
self . obs = self . obs . strip ( )
self . obs = self . obs . replace ( ' \r \n ' , ' \n ' )
if self . obs == " " or self . obs == None :
logging . info ( " Read no hands. " )
2009-08-12 10:47:18 +02:00
return [ ]
2009-07-30 06:13:45 +02:00
return re . split ( self . re_SplitHands , self . obs )
2008-12-16 15:45:58 +01:00
def readHandInfo ( self , hand ) :
2009-08-09 16:19:43 +02:00
m = self . re_HandInfo . search ( hand . handText )
2009-03-18 17:52:18 +01:00
if ( m == None ) :
logging . info ( " Didn ' t match re_HandInfo " )
logging . info ( hand . handText )
return None
2008-12-16 15:45:58 +01:00
hand . handid = m . group ( ' HID ' )
hand . tablename = m . group ( ' TABLE ' )
2009-06-09 16:53:09 +02:00
hand . starttime = datetime . datetime . strptime ( m . group ( ' DATETIME ' ) , " % H: % M: % S ET - % Y/ % m/ %d " )
2009-08-09 16:19:43 +02:00
if m . group ( " CANCELLED " ) :
raise FpdbParseError ( hid = m . group ( ' HID ' ) )
2009-03-21 17:31:36 +01:00
if m . group ( ' TABLEATTRIBUTES ' ) :
2009-07-22 19:51:48 +02:00
m2 = self . re_Max . search ( m . group ( ' TABLEATTRIBUTES ' ) )
if m2 : hand . maxseats = int ( m2 . group ( ' MAX ' ) )
2009-07-19 03:33:00 +02:00
hand . tourNo = m . group ( ' TOURNO ' )
2009-07-22 14:54:30 +02:00
if m . group ( ' PLAY ' ) != None :
hand . gametype [ ' currency ' ] = ' play '
2009-07-31 02:56:39 +02:00
# TODO: if there's a way to figure these out, we should.. otherwise we have to stuff it with unknowns
if hand . buyin == None :
hand . buyin = " $0.00+$0.00 "
if hand . level == None :
hand . level = " 0 "
2009-07-19 03:33:00 +02:00
2008-12-16 15:45:58 +01:00
# These work, but the info is already in the Hand class - should be used for tourneys though.
2009-03-04 15:29:13 +01:00
# m.group('SB')
# m.group('BB')
# m.group('GAMETYPE')
2008-12-16 15:45:58 +01:00
# Stars format (Nov 10 2008): 2008/11/07 12:38:49 CET [2008/11/07 7:38:49 ET]
# or : 2008/11/07 12:38:49 ET
# Not getting it in my HH files yet, so using
# 2008/11/10 3:58:52 ET
#TODO: Do conversion from GMT to ET
#TODO: Need some date functions to convert to different timezones (Date::Manip for perl rocked for this)
2008-12-17 00:23:33 +01:00
#hand.starttime = "%d/%02d/%02d %d:%02d:%02d ET" %(int(m.group('YEAR')), int(m.group('MON')), int(m.group('DAY')),
##int(m.group('HR')), int(m.group('MIN')), int(m.group('SEC')))
2008-12-16 15:45:58 +01:00
#FIXME: hand.buttonpos = int(m.group('BUTTON'))
def readPlayerStacks ( self , hand ) :
2009-03-04 16:10:08 +01:00
m = self . re_PlayerInfo . finditer ( hand . handText )
2008-12-16 15:45:58 +01:00
players = [ ]
for a in m :
hand . addPlayer ( int ( a . group ( ' SEAT ' ) ) , a . group ( ' PNAME ' ) , a . group ( ' CASH ' ) )
def markStreets ( self , hand ) :
# PREFLOP = ** Dealing down cards **
2009-03-10 17:17:54 +01:00
if hand . gametype [ ' base ' ] == ' hold ' :
2009-02-24 17:17:25 +01:00
m = re . search ( r " \ * \ * \ * HOLE CARDS \ * \ * \ *(?P<PREFLOP>.+(?= \ * \ * \ * FLOP \ * \ * \ *)|.+) "
2008-12-16 18:26:58 +01:00
r " ( \ * \ * \ * FLOP \ * \ * \ *(?P<FLOP> \ [ \ S \ S \ S \ S \ S \ S \ ].+(?= \ * \ * \ * TURN \ * \ * \ *)|.+))? "
r " ( \ * \ * \ * TURN \ * \ * \ * \ [ \ S \ S \ S \ S \ S \ S] (?P<TURN> \ [ \ S \ S \ ].+(?= \ * \ * \ * RIVER \ * \ * \ *)|.+))? "
2009-03-04 16:10:08 +01:00
r " ( \ * \ * \ * RIVER \ * \ * \ * \ [ \ S \ S \ S \ S \ S \ S \ S \ S] (?P<RIVER> \ [ \ S \ S \ ].+))? " , hand . handText , re . DOTALL )
2009-03-10 17:17:54 +01:00
elif hand . gametype [ ' base ' ] == " stud " : # or should this be gametype['category'] == 'razz'
2009-02-24 18:05:51 +01:00
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 \ * \ * \ *)|.+))? "
2009-03-04 16:10:08 +01:00
r " ( \ * \ * \ * 7TH STREET \ * \ * \ *(?P<SEVENTH>.+))? " , hand . handText , re . DOTALL )
2008-12-16 15:45:58 +01:00
hand . addStreets ( m )
2008-12-16 18:26:58 +01:00
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)
2008-12-16 22:08:10 +01:00
#print "DEBUG readCommunityCards:", street, hand.streets.group(street)
2009-03-10 17:17:54 +01:00
m = self . re_Board . search ( hand . streets [ street ] )
2008-12-16 18:26:58 +01:00
hand . setCommunityCards ( street , m . group ( ' CARDS ' ) . split ( ' ' ) )
2008-12-16 15:45:58 +01:00
def readBlinds ( self , hand ) :
try :
2009-03-04 16:10:08 +01:00
m = self . re_PostSB . search ( hand . handText )
2008-12-16 15:45:58 +01:00
hand . addBlind ( m . group ( ' PNAME ' ) , ' small blind ' , m . group ( ' SB ' ) )
except : # no small blind
hand . addBlind ( None , None , None )
2009-03-04 16:10:08 +01:00
for a in self . re_PostBB . finditer ( hand . handText ) :
2008-12-16 15:45:58 +01:00
hand . addBlind ( a . group ( ' PNAME ' ) , ' big blind ' , a . group ( ' BB ' ) )
2009-03-04 16:10:08 +01:00
for a in self . re_PostBoth . finditer ( hand . handText ) :
2008-12-16 15:45:58 +01:00
hand . addBlind ( a . group ( ' PNAME ' ) , ' small & big blinds ' , a . group ( ' SBBB ' ) )
2009-02-24 17:17:25 +01:00
def readAntes ( self , hand ) :
2009-03-04 17:46:01 +01:00
logging . debug ( " reading antes " )
2009-03-04 16:10:08 +01:00
m = self . re_Antes . finditer ( hand . handText )
2009-02-25 16:45:46 +01:00
for player in m :
2009-03-04 17:46:01 +01:00
logging . debug ( " hand.addAnte( %s , %s ) " % ( player . group ( ' PNAME ' ) , player . group ( ' ANTE ' ) ) )
2009-07-22 14:54:30 +02:00
# if player.group() !=
2009-02-25 16:45:46 +01:00
hand . addAnte ( player . group ( ' PNAME ' ) , player . group ( ' ANTE ' ) )
2009-02-24 17:17:25 +01:00
def readBringIn ( self , hand ) :
2009-03-04 16:10:08 +01:00
m = self . re_BringIn . search ( hand . handText , re . DOTALL )
2009-03-10 18:25:49 +01:00
if m :
logging . debug ( " Player bringing in: %s for %s " % ( m . group ( ' PNAME ' ) , m . group ( ' BRINGIN ' ) ) )
hand . addBringIn ( m . group ( ' PNAME ' ) , m . group ( ' BRINGIN ' ) )
else :
2009-07-23 01:21:00 +02:00
logging . warning ( " No bringin found, handid = %s " % hand . handid )
2009-02-24 17:17:25 +01:00
def readButton ( self , hand ) :
2009-03-04 16:10:08 +01:00
hand . buttonpos = int ( self . re_Button . search ( hand . handText ) . group ( ' BUTTON ' ) )
2009-02-24 17:17:25 +01:00
2008-12-16 15:45:58 +01:00
def readHeroCards ( self , hand ) :
2009-07-17 23:07:53 +02:00
# streets PREFLOP, PREDRAW, and THIRD are special cases beacause
# we need to grab hero's cards
for street in ( ' PREFLOP ' , ' DEAL ' ) :
if street in hand . streets . keys ( ) :
m = self . re_HeroCards . finditer ( hand . streets [ street ] )
for found in m :
# if m == None:
# hand.involved = False
# else:
hand . hero = found . group ( ' PNAME ' )
newcards = found . group ( ' NEWCARDS ' ) . split ( ' ' )
hand . addHoleCards ( street , hand . hero , closed = newcards , shown = False , mucked = False , dealt = True )
for street , text in hand . streets . iteritems ( ) :
if not text or street in ( ' PREFLOP ' , ' DEAL ' ) : continue # already done these
m = self . re_HeroCards . finditer ( hand . streets [ street ] )
for found in m :
player = found . group ( ' PNAME ' )
if found . group ( ' NEWCARDS ' ) == None :
newcards = [ ]
else :
newcards = found . group ( ' NEWCARDS ' ) . split ( ' ' )
if found . group ( ' OLDCARDS ' ) == None :
oldcards = [ ]
else :
oldcards = found . group ( ' OLDCARDS ' ) . split ( ' ' )
2009-07-22 20:06:05 +02:00
if street == ' THIRD ' and len ( oldcards ) == 2 : # hero in stud game
2009-07-17 23:07:53 +02:00
hand . hero = player
hand . dealt . add ( player ) # need this for stud??
2009-07-22 20:06:05 +02:00
hand . addHoleCards ( street , player , closed = oldcards , open = newcards , shown = False , mucked = False , dealt = False )
2009-07-17 23:07:53 +02:00
else :
hand . addHoleCards ( street , player , open = newcards , closed = oldcards , shown = False , mucked = False , dealt = False )
2009-02-25 11:32:12 +01:00
2008-12-16 15:45:58 +01:00
def readAction ( self , hand , street ) :
2009-03-07 15:35:52 +01:00
m = self . re_Action . finditer ( hand . streets [ street ] )
2008-12-16 15:45:58 +01:00
for action in m :
if action . group ( ' ATYPE ' ) == ' raises to ' :
hand . addRaiseTo ( street , action . group ( ' PNAME ' ) , action . group ( ' BET ' ) )
2009-03-12 02:49:16 +01:00
elif action . group ( ' ATYPE ' ) == ' completes it to ' :
2009-03-11 17:51:58 +01:00
hand . addComplete ( street , action . group ( ' PNAME ' ) , action . group ( ' BET ' ) )
2008-12-16 15:45:58 +01:00
elif action . group ( ' ATYPE ' ) == ' calls ' :
hand . addCall ( street , action . group ( ' PNAME ' ) , action . group ( ' BET ' ) )
elif action . group ( ' ATYPE ' ) == ' bets ' :
hand . addBet ( street , action . group ( ' PNAME ' ) , action . group ( ' BET ' ) )
elif action . group ( ' ATYPE ' ) == ' folds ' :
hand . addFold ( street , action . group ( ' PNAME ' ) )
elif action . group ( ' ATYPE ' ) == ' checks ' :
hand . addCheck ( street , action . group ( ' PNAME ' ) )
else :
2009-03-12 02:49:16 +01:00
print " DEBUG: unimplemented readAction: ' %s ' ' %s ' " % ( action . group ( ' PNAME ' ) , action . group ( ' ATYPE ' ) , )
2008-12-16 18:26:58 +01:00
2008-12-16 15:45:58 +01:00
def readShowdownActions ( self , hand ) :
2009-03-04 16:10:08 +01:00
for shows in self . re_ShowdownAction . finditer ( hand . handText ) :
2008-12-16 15:45:58 +01:00
cards = shows . group ( ' CARDS ' )
2009-03-02 16:10:15 +01:00
cards = cards . split ( ' ' )
2008-12-16 15:45:58 +01:00
hand . addShownCards ( cards , shows . group ( ' PNAME ' ) )
def readCollectPot ( self , hand ) :
2009-03-04 16:10:08 +01:00
for m in self . re_CollectPot . finditer ( hand . handText ) :
2008-12-16 18:26:58 +01:00
hand . addCollectPot ( player = m . group ( ' PNAME ' ) , pot = m . group ( ' POT ' ) )
def readShownCards ( self , hand ) :
2009-03-04 16:10:08 +01:00
for m in self . re_ShownCards . finditer ( hand . handText ) :
2008-12-16 15:45:58 +01:00
if m . group ( ' CARDS ' ) is not None :
cards = m . group ( ' CARDS ' )
2009-03-02 16:10:15 +01:00
cards = cards . split ( ' ' )
2008-12-16 18:26:58 +01:00
hand . addShownCards ( cards = cards , player = m . group ( ' PNAME ' ) )
2008-12-16 15:45:58 +01:00
2009-07-20 16:01:51 +02:00
def guessMaxSeats ( self , hand ) :
""" Return a guess at max_seats when not specified in HH. """
mo = self . maxOccSeat ( hand )
if mo == 10 : return 10 #that was easy
if hand . gametype [ ' base ' ] == ' stud ' :
if mo < = 8 : return 8
else : return mo
if hand . gametype [ ' base ' ] == ' draw ' :
if mo < = 6 : return 6
else : return mo
if mo == 2 : return 2
if mo < = 6 : return 6
return 9
2009-07-22 16:24:29 +02:00
def readOther ( self , hand ) :
m = self . re_Mixed . search ( self . in_path )
if m == None : hand . mixed = None
else :
hand . mixed = self . mixes [ m . groupdict ( ) [ ' MIXED ' ] ]
2008-12-16 15:45:58 +01:00
if __name__ == " __main__ " :
2009-03-02 22:48:30 +01:00
parser = OptionParser ( )
parser . add_option ( " -i " , " --input " , dest = " ipath " , help = " parse input hand history " , default = " regression-test-files/fulltilt/razz/FT20090223 Danville - $0.50-$1 Ante $0.10 - Limit Razz.txt " )
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 ( )
2009-03-13 21:00:12 +01:00
e = Fulltilt ( in_path = options . ipath , out_path = options . opath , follow = options . follow )