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

This commit is contained in:
Eratosthenes 2010-12-05 12:53:28 -05:00
commit 78fdb37f38
17 changed files with 684 additions and 120 deletions

View File

@ -479,12 +479,13 @@ class Import:
self.hhArchiveBase = node.getAttribute("hhArchiveBase")
self.hhBulkPath = node.getAttribute("hhBulkPath")
self.saveActions = string_to_bool(node.getAttribute("saveActions"), default=False)
self.cacheSessions = string_to_bool(node.getAttribute("cacheSessions"), default=False)
self.fastStoreHudCache = string_to_bool(node.getAttribute("fastStoreHudCache"), default=False)
self.saveStarsHH = string_to_bool(node.getAttribute("saveStarsHH"), default=False)
def __str__(self):
return " interval = %s\n callFpdbHud = %s\n hhArchiveBase = %s\n saveActions = %s\n fastStoreHudCache = %s\n" \
% (self.interval, self.callFpdbHud, self.hhArchiveBase, self.saveActions, self.fastStoreHudCache)
% (self.interval, self.callFpdbHud, self.hhArchiveBase, self.saveActions, self.cacheSessions, self.fastStoreHudCache)
class HudUI:
def __init__(self, node):
@ -1259,6 +1260,9 @@ class Config:
try: imp['saveActions'] = self.imp.saveActions
except: imp['saveActions'] = False
try: imp['cacheSessions'] = self.imp.cacheSessions
except: imp['cacheSessions'] = False
try: imp['saveStarsHH'] = self.imp.saveStarsHH
except: imp['saveStarsHH'] = False

View File

@ -73,7 +73,7 @@ except ImportError:
use_numpy = False
DB_VERSION = 145
DB_VERSION = 146
# Variance created as sqlite has a bunch of undefined aggregate functions.
@ -296,8 +296,8 @@ class Database:
# vars for hand ids or dates fetched according to above config:
self.hand_1day_ago = 0 # max hand id more than 24 hrs earlier than now
self.date_ndays_ago = 'd00000000' # date N days ago ('d' + YYMMDD)
self.h_date_ndays_ago = 'd00000000' # date N days ago ('d' + YYMMDD) for hero
self.date_ndays_ago = 'd000000' # date N days ago ('d' + YYMMDD)
self.h_date_ndays_ago = 'd000000' # date N days ago ('d' + YYMMDD) for hero
self.date_nhands_ago = {} # dates N hands ago per player - not used yet
self.saveActions = False if self.import_options['saveActions'] == False else True
@ -701,18 +701,18 @@ class Database:
d = timedelta(days=hud_days, hours=tz_day_start_offset)
now = datetime.utcnow() - d
self.date_ndays_ago = "d%02d%02d%02d%02d" % (now.year - 2000, now.month, now.day, tz_day_start_offset)
self.date_ndays_ago = "d%02d%02d%02d" % (now.year - 2000, now.month, now.day)
d = timedelta(days=h_hud_days, hours=tz_day_start_offset)
now = datetime.utcnow() - d
self.h_date_ndays_ago = "d%02d%02d%02d%02d" % (now.year - 2000, now.month, now.day, tz_day_start_offset)
self.h_date_ndays_ago = "d%02d%02d%02d" % (now.year - 2000, now.month, now.day)
def init_player_hud_stat_vars(self, playerid):
# not sure if this is workable, to be continued ...
try:
# self.date_nhands_ago is used for fetching stats for last n hands (hud_style = 'H')
# This option not used yet - needs to be called for each player :-(
self.date_nhands_ago[str(playerid)] = 'd00000000'
self.date_nhands_ago[str(playerid)] = 'd000000'
# should use aggregated version of query if appropriate
c.execute(self.sql.query['get_date_nhands_ago'], (self.hud_hands, playerid))
@ -780,11 +780,11 @@ class Database:
if hud_style == 'T':
stylekey = self.date_ndays_ago
elif hud_style == 'A':
stylekey = '000000000' # all stylekey values should be higher than this
stylekey = '0000000' # all stylekey values should be higher than this
elif hud_style == 'S':
stylekey = 'zzzzzzzzz' # all stylekey values should be lower than this
stylekey = 'zzzzzzz' # all stylekey values should be lower than this
else:
stylekey = '000000000'
stylekey = '0000000'
log.info('hud_style: %s' % hud_style)
#elif hud_style == 'H':
@ -793,9 +793,9 @@ class Database:
if h_hud_style == 'T':
h_stylekey = self.h_date_ndays_ago
elif h_hud_style == 'A':
h_stylekey = '000000000' # all stylekey values should be higher than this
h_stylekey = '0000000' # all stylekey values should be higher than this
elif h_hud_style == 'S':
h_stylekey = 'zzzzzzzzz' # all stylekey values should be lower than this
h_stylekey = 'zzzzzzz' # all stylekey values should be lower than this
else:
h_stylekey = '00000000'
log.info('h_hud_style: %s' % h_hud_style)
@ -1832,12 +1832,19 @@ class Database:
def storeHudCache(self, gid, pids, starttime, pdata):
"""Update cached statistics. If update fails because no record exists, do an insert."""
tz = datetime.utcnow() - datetime.today()
tz_offset = tz.seconds/3600
tz_day_start_offset = self.day_start + tz_offset
d = timedelta(hours=tz_day_start_offset)
starttime_offset = starttime - d
if self.use_date_in_hudcache:
styleKey = datetime.strftime(starttime, 'd%y%m%d%H')
#styleKey = "d%02d%02d%02d%02d" % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day, hand_start_time.hour)
styleKey = datetime.strftime(starttime_offset, 'd%y%m%d')
#styleKey = "d%02d%02d%02d" % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day)
else:
# hard-code styleKey as 'A00000000' (all-time cache, no key) for now
styleKey = 'A00000000'
# hard-code styleKey as 'A000000' (all-time cache, no key) for now
styleKey = 'A000000'
update_hudcache = self.sql.query['update_hudcache']
update_hudcache = update_hudcache.replace('%s', self.sql.query['placeholder'])
@ -1959,6 +1966,53 @@ class Database:
else:
#print "DEBUG: Successfully updated HudCacho using UPDATE"
pass
def storeSessionsCache(self, pids, starttime, pdata):
"""Update cached sessions. If update fails because no record exists, do an insert."""
#In development
pass
#update_sessionscache = self.sql.query['update_sessionscache']
#update_sessionscache = update_sessionscache.replace('%s', self.sql.query['placeholder'])
#insert_sessionscache = self.sql.query['insert_sessionscache']
#insert_sessionscache = insert_sessionscache.replace('%s', self.sql.query['placeholder'])
#merge_sessionscache = self.sql.query['merge_sessionscache']
#merge_sessionscache = merge_sessionscache.replace('%s', self.sql.query['placeholder'])
#print "DEBUG: %s %s %s" %(hid, pids, pdata)
#inserts = []
#for p in pdata:
#line = [0]*5
#line[0] = 1 # HDs
#line[1] = pdata[p]['totalProfit']
#line[2] = pids[p] # playerId
#line[3] = sessionStart
#line[4] = sessionEnd
#inserts.append(line)
#cursor = self.get_cursor()
#for row in inserts:
# Try to do the update first:
#num = cursor.execute(update_sessionscache, row)
#print "DEBUG: values: %s" % row[-3:]
# Test statusmessage to see if update worked, do insert if not
# num is a cursor in sqlite
#if ((self.backend == self.PGSQL and cursor.statusmessage != "UPDATE 1")
#or (self.backend == self.MYSQL_INNODB and num == 0)
#or (self.backend == self.SQLITE and num.rowcount == 0)):
#move the last 6 items in WHERE clause of row from the end of the array
# to the beginning for the INSERT statement
#print "DEBUG: using INSERT: %s" % num
#row = row[-3:] + row[:-3]
#num = cursor.execute(insert_sessionscache, row)
#print "DEBUG: Successfully(?: %s) updated HudCacho using INSERT" % num
#else:
#print "DEBUG: Successfully updated HudCacho using UPDATE"
#pass
def isDuplicate(self, gametypeID, siteHandNo):
dup = False

View File

@ -33,6 +33,7 @@ class FullTiltPokerSummary(TourneySummary):
games = { # base, category
"Hold'em" : ('hold','holdem'),
'Omaha' : ('hold','omahahi'),
'Omahai Hi' : ('hold','omahahi'),
'Omaha Hi/Lo' : ('hold','omahahilo'),
'Razz' : ('stud','razz'),
'RAZZ' : ('stud','razz'),
@ -55,7 +56,7 @@ class FullTiltPokerSummary(TourneySummary):
re_TourneyInfo = re.compile(u"""
\s.*
(?P<TYPE>Tournament|Sit\s\&\sGo)\s\((?P<TOURNO>[0-9]+)\)(\s+)?
(?P<GAME>Hold\'em|Razz|RAZZ|7\sCard\sStud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball|5\sCard\sDraw)\s+
(?P<GAME>Hold\'em|Razz|RAZZ|7\sCard\sStud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball|5\sCard\sDraw)\s+
(?P<LIMIT>No\sLimit|Limit|LIMIT|Pot\sLimit)\s+
(Buy-In:\s\$(?P<BUYIN>[.\d]+)(\s\+\s\$(?P<FEE>[.\d]+))?\s+)?
(Buy-In\sChips:\s(?P<CHIPS>\d+)\s+)?

274
pyfpdb/GuiReplayer.py Normal file
View File

@ -0,0 +1,274 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#Copyright 2010 Maxime Grandchamp
#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU Affero General Public License as published by
#the Free Software Foundation, version 3 of the License.
#
#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 Affero General Public License
#along with this program. If not, see <http://www.gnu.org/licenses/>.
#In the "official" distribution you can find the license in agpl-3.0.txt.
import L10n
_ = L10n.get_translation()
from Hand import *
import Configuration
import Database
import SQL
import fpdb_import
import Filters
import pygtk
pygtk.require('2.0')
import gtk
import math
import gobject
class GuiReplayer:
def __init__(self, config, querylist, mainwin, debug=True):
self.debug = debug
self.conf = config
self.main_window = mainwin
self.sql = querylist
self.db = Database.Database(self.conf, sql=self.sql)
filters_display = { "Heroes" : True,
"Sites" : True,
"Games" : True,
"Limits" : True,
"LimitSep" : True,
"LimitType" : True,
"Type" : True,
"Seats" : True,
"SeatSep" : True,
"Dates" : True,
"Groups" : True,
"GroupsAll" : True,
"Button1" : True,
"Button2" : True
}
self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display)
#self.filters.registerButton1Name(_("Import Hand"))
#self.filters.registerButton1Callback(self.importhand)
#self.filters.registerButton2Name(_("temp"))
#self.filters.registerButton2Callback(self.temp())
# hierarchy: self.mainHBox / self.hpane / self.replayBox / self.area
self.mainHBox = gtk.HBox(False, 0)
self.mainHBox.show()
self.leftPanelBox = self.filters.get_vbox()
self.hpane = gtk.HPaned()
self.hpane.pack1(self.leftPanelBox)
self.mainHBox.add(self.hpane)
self.replayBox = gtk.VBox(False, 0)
self.replayBox.show()
self.hpane.pack2(self.replayBox)
self.hpane.show()
self.area=gtk.DrawingArea()
self.pangolayout = self.area.create_pango_layout("")
self.area.connect("expose-event", self.area_expose)
self.style = self.area.get_style()
self.gc = self.style.fg_gc[gtk.STATE_NORMAL]
self.area.show()
self.replayBox.pack_start(self.area)
self.MyHand = self.importhand()
self.maxseats=self.MyHand.maxseats
if self.MyHand.gametype['currency']=="USD": #TODO: check if there are others ..
self.currency="$"
elif self.MyHand.gametype['currency']=="EUR":
self.currency=""
self.table={} #create table with positions, player names, status (live/folded), stacks and chips on table
for i in range(0,self.maxseats): # radius: 200, center: 250,250
x= int (round(250+200*math.cos(2*i*math.pi/self.maxseats)))
y= int (round(250+200*math.sin(2*i*math.pi/self.maxseats)))
try:
self.table[i]={"name":self.MyHand.players[i][1],"stack":Decimal(self.MyHand.players[i][2]),"x":x,"y":y,"chips":0,"status":"live"} #save coordinates of each player
try:
self.table[i]['holecards']=self.MyHand.holecards["PREFLOP"][self.MyHand.players[i][1]][1]+' '+self.MyHand.holecards["PREFLOP"][self.MyHand.players[i][1]][2]
print "holecards",self.table[i]['holecards']
except:
self.table[i]['holecards']=''
except IndexError: #if seat is empty
print "seat",i+1,"out of",self.maxseats,"empty"
self.actions=[] #create list with all actions
if isinstance(self.MyHand, HoldemOmahaHand):
if self.MyHand.gametype['category'] == 'holdem':
self.play_holdem()
self.action_number=0
self.action_level=0
self.pot=0
gobject.timeout_add(1000,self.draw_action)
def area_expose(self, area, event):
self.style = self.area.get_style()
self.gc = self.style.fg_gc[gtk.STATE_NORMAL]
playerid='999' #makes sure we have an error if player is not recognised
for i in range(0,len(self.table)): #surely there must be a better way to find the player id in the table...
if self.table[i]['name']==self.actions[self.action_number][1]:
playerid=i
if self.actions[self.action_number][2]=="folds":
self.table[playerid]["status"]="folded"
if self.actions[self.action_number][3]:
self.table[playerid]["stack"] -= Decimal(self.actions[self.action_number][3]) #decreases stack if player bets
self.pot += Decimal(self.actions[self.action_number][3]) #increase pot
self.table[playerid]["chips"] += Decimal(self.actions[self.action_number][3]) #increase player's chips on table
cm = self.gc.get_colormap() #create colormap toi be able to play with colours
color = cm.alloc_color("black") #defaults to black
self.gc.set_foreground(color)
self.area.window.draw_arc(self.gc, 0, 125, 125, 300, 300, 0, 360*64) #table
for i in self.table:
if self.table[i]["status"]=="folded":
color = cm.alloc_color("grey") #player has folded => greyed out
self.gc.set_foreground(color)
else:
color = cm.alloc_color("black") #player is live
self.gc.set_foreground(color)
self.pangolayout.set_text(self.table[i]["name"]+self.table[i]["holecards"]) #player names + holecards
self.area.window.draw_layout(self.gc, self.table[i]["x"],self.table[i]["y"], self.pangolayout)
self.pangolayout.set_text('$'+str(self.table[i]["stack"])) #player stacks
self.area.window.draw_layout(self.gc, self.table[i]["x"]+10,self.table[i]["y"]+20, self.pangolayout)
color = cm.alloc_color("green")
self.gc.set_foreground(color)
self.pangolayout.set_text(self.currency+str(self.pot)) #displays pot
self.area.window.draw_layout(self.gc,270,270, self.pangolayout)
if self.actions[self.action_number][0]>1: #displays flop
self.pangolayout.set_text(self.MyHand.board['FLOP'][0]+" "+self.MyHand.board['FLOP'][1]+" "+self.MyHand.board['FLOP'][2])
self.area.window.draw_layout(self.gc,210,240, self.pangolayout)
if self.actions[self.action_number][0]>2: #displays turn
self.pangolayout.set_text(self.MyHand.board['TURN'][0])
self.area.window.draw_layout(self.gc,270,240, self.pangolayout)
if self.actions[self.action_number][0]>3: #displays river
self.pangolayout.set_text(self.MyHand.board['RIVER'][0])
self.area.window.draw_layout(self.gc,290,240, self.pangolayout)
color = cm.alloc_color("red") #highlights the action
self.gc.set_foreground(color)
self.pangolayout.set_text(self.actions[self.action_number][2]) #displays action
self.area.window.draw_layout(self.gc, self.table[playerid]["x"]+10,self.table[playerid]["y"]+35, self.pangolayout)
if self.actions[self.action_number][3]: #displays amount
self.pangolayout.set_text(self.currency+self.actions[self.action_number][3])
self.area.window.draw_layout(self.gc, self.table[playerid]["x"]+10,self.table[playerid]["y"]+55, self.pangolayout)
color = cm.alloc_color("black") #we don't want to draw the filters and others in red
self.gc.set_foreground(color)
def play_holdem(self):
actions=('BLINDSANTES','PREFLOP','FLOP','TURN','RIVER')
for action in actions:
for i in range(0,len(self.MyHand.actions[action])):
player=self.MyHand.actions[action][i][0]
act=self.MyHand.actions[action][i][1]
try:
amount=str(self.MyHand.actions[action][i][2])
except:
amount='' #no amount
self.actions.append([actions.index(action),player,act,amount]) #create table with all actions
def draw_action(self):
if self.action_number==len(self.actions)-1: #no more actions, we exit the loop
return False
if self.actions[self.action_number][0]!=self.action_level: #have we changed street ?
self.action_level=self.actions[self.action_number][0] #record the new street
if self.action_level>1: #we don't want to refresh if simply moving from antes/blinds to preflop action
alloc = self.area.get_allocation()
rect = gtk.gdk.Rectangle(0, 0, alloc.width, alloc.height)
self.area.window.invalidate_rect(rect, True) #make sure we refresh the whole screen
self.action_number+=1
if self.area.window:
playerid='999' #makes sure we have an error if player is not recognised
for i in range(0,len(self.table)): #surely there must be a better way to find the player id in the table...
if self.table[i]['name']==self.actions[self.action_number][1]:
playerid=i
rect = gtk.gdk.Rectangle(self.table[playerid]["x"],self.table[playerid]["y"],100,100)
self.area.window.invalidate_rect(rect, True) #refresh player area of the screen
rect = gtk.gdk.Rectangle(270,270,100,50)
self.area.window.invalidate_rect(rect, True) #refresh pot area
self.area.window.process_updates(True)
print "draw action",self.action_number,self.actions[self.action_number][1],self.actions[self.action_number][2],self.actions[self.action_number][3]
return True
def get_vbox(self):
"""returns the vbox of this thread"""
return self.mainHBox
def importhand(self, handnumber=1):
"""Temporary function that grabs a Hand object from a specified file. Obviously this will
be replaced by a function to select a hand from the db in the not so distant future.
This code has been shamelessly stolen from Carl
"""
config = Configuration.Config(file = "HUD_config.test.xml")
db = Database.Database(config)
sql = SQL.Sql(db_server = 'sqlite')
settings = {}
settings.update(config.get_db_parameters())
settings.update(config.get_import_parameters())
settings.update(config.get_default_paths())
#db.recreate_tables()
importer = fpdb_import.Importer(False, settings, config, None)
importer.setDropIndexes("don't drop")
importer.setFailOnError(True)
importer.setThreads(-1)
importer.setCallHud(False)
importer.setFakeCacheHHC(True)
#Get a simple regression file with a few hands of Hold'em
filename="regression-test-files/cash/Stars/Flop/NLHE-FR-USD-0.01-0.02-201005.microgrind.txt"
site="PokerStars"
importer.addBulkImportImportFileOrDir(filename, site=site)
(stored, dups, partial, errs, ttime) = importer.runImport()
hhc = importer.getCachedHHC()
handlist = hhc.getProcessedHands()
return handlist[0]
def temp(self):
pass

View File

@ -75,10 +75,6 @@ onlinehelp = {'Game':_('Type of Game'),
class DemoTips(TreeViewTooltips):
def __init__(self, customer_column):
# customer_column is an instance of gtk.TreeViewColumn and
# is being used in the gtk.TreeView to show customer names.
# self.cust_col = customer_column
# call base class init
TreeViewTooltips.__init__(self)
@ -91,11 +87,6 @@ class DemoTips(TreeViewTooltips):
return (display)
def location(self, x, y, w, h):
# rename me to "location" so I override the base class
# method. This will demonstrate being able to change
# where the tooltip window popups, relative to the
# pointer.
# this will place the tooltip above and to the right
return x + 30, y - (h + 10)

View File

@ -2,7 +2,7 @@
<FreePokerToolsConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FreePokerToolsConfig.xsd">
<import callFpdbHud = "True" interval = "10" fastStoreHudCache="False" hhArchiveBase="~/.fpdb/HandHistories/" saveActions="True"></import>
<import callFpdbHud = "True" interval = "10" fastStoreHudCache="False" hhArchiveBase="~/.fpdb/HandHistories/" saveActions="True" cacheSessions="False"></import>
<!-- These values determine what stats are displayed in the HUD

View File

@ -12,7 +12,7 @@
config_difficulty="expert"
/>
<import callFpdbHud = "True" interval = "10" fastStoreHudCache="False" hhArchiveBase="~/.fpdb/HandHistories/" saveActions="True"></import>
<import callFpdbHud = "True" interval = "10" fastStoreHudCache="False" hhArchiveBase="~/.fpdb/HandHistories/" saveActions="True" cacheSessions="False"></import>
<gui_cash_stats>
<col col_name="game" disp_all="True" disp_posn="True" col_title="Game" xalignment="0.0" field_format="%s" field_type="str" />

View File

@ -278,6 +278,9 @@ db: a connected Database object"""
def updateHudCache(self, db):
db.storeHudCache(self.dbid_gt, self.dbid_pids, self.startTime, self.stats.getHandsPlayers())
def updateSessionsCache(self, db):
db.storeSessionsCache(self.dbid_pids, self.startTime, self.stats.getHandsPlayers())
def select(self, handId):
""" Function to create Hand object from database """

View File

@ -45,22 +45,27 @@ class PartyPoker(HandHistoryConverter):
codepage = "utf8"
siteId = 9
filetype = "text"
sym = {'USD': "\$", }
sym = {'USD': "\$", 'EUR': u"\u20ac", 'T$': ""}
currencies = {"\$": "USD", "$": "USD", u"\xe2\x82\xac": "EUR", u"\u20ac": "EUR", '': "T$"}
substitutions = {
'LEGAL_ISO' : "USD|EUR", # legal ISO currency codes
'LS' : "\$|\u20AC|\xe2\x82\xac|" # legal currency symbols - Euro(cp1252, utf-8)
}
# Static regexes
# $5 USD NL Texas Hold'em - Saturday, July 25, 07:53:52 EDT 2009
# NL Texas Hold'em $1 USD Buy-in Trny:45685440 Level:8 Blinds-Antes(600/1 200 -50) - Sunday, May 17, 11:25:07 MSKS 2009
re_GameInfoRing = re.compile("""
(?P<CURRENCY>\$|)\s*(?P<RINGLIMIT>[.,0-9]+)([.,0-9/$]+)?\s*(?:USD)?\s*
re_GameInfoRing = re.compile(u"""
(?P<CURRENCY>[%(LS)s])\s*(?P<RINGLIMIT>[.,0-9]+)([.,0-9/$]+)?\s*(?:%(LEGAL_ISO)s)?\s*
(?P<LIMIT>(NL|PL|))\s*
(?P<GAME>(Texas\ Hold\'em|Omaha|7 Card Stud Hi-Lo))
(?P<GAME>(Texas\ Hold\'em|Omaha|7\ Card\ Stud\ Hi-Lo))
\s*\-\s*
(?P<DATETIME>.+)
""", re.VERBOSE | re.UNICODE)
""" % substitutions, re.VERBOSE | re.UNICODE)
re_GameInfoTrny = re.compile("""
(?P<LIMIT>(NL|PL|))\s*
(?P<GAME>(Texas\ Hold\'em|Omaha))\s+
(?:(?P<BUYIN>\$?[.,0-9]+)\s*(?P<BUYIN_CURRENCY>USD)?\s*Buy-in\s+)?
(?:(?P<BUYIN>\$?[.,0-9]+)\s*(?P<BUYIN_CURRENCY>%(LEGAL_ISO)s)?\s*Buy-in\s+)?
Trny:\s?(?P<TOURNO>\d+)\s+
Level:\s*(?P<LEVEL>\d+)\s+
((Blinds|Stakes)(?:-Antes)?)\(
@ -70,15 +75,14 @@ class PartyPoker(HandHistoryConverter):
\)
\s*\-\s*
(?P<DATETIME>.+)
""", re.VERBOSE | re.UNICODE)
re_Hid = re.compile("^Game \#(?P<HID>\d+) starts.")
""" % substitutions, re.VERBOSE | re.UNICODE)
re_Hid = re.compile("Game \#(?P<HID>\d+) starts.")
re_PlayerInfo = re.compile("""
re_PlayerInfo = re.compile(u"""
Seat\s(?P<SEAT>\d+):\s
(?P<PNAME>.*)\s
\(\s*\$?(?P<CASH>[0-9,.]+)\s*(?:USD|)\s*\)
""" ,
re.VERBOSE)
\(\s*[%(LS)s]?(?P<CASH>[0-9,.]+)\s*(?:%(LEGAL_ISO)s|)\s*\)
""" % substitutions, re.VERBOSE| re.UNICODE)
re_HandInfo = re.compile("""
^Table\s+(?P<TTYPE>[$a-zA-Z0-9 ]+)?\s+
@ -123,18 +127,16 @@ class PartyPoker(HandHistoryConverter):
self.compiledPlayers = players
player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")"
subst = {'PLYR': player_re, 'CUR_SYM': hand.SYMBOL[hand.gametype['currency']],
subst = {'PLYR': player_re, 'CUR_SYM': self.sym[hand.gametype['currency']],
'CUR': hand.gametype['currency'] if hand.gametype['currency']!='T$' else ''}
for key in ('CUR_SYM', 'CUR'):
subst[key] = re.escape(subst[key])
self.re_PostSB = re.compile(
r"^%(PLYR)s posts small blind \[%(CUR_SYM)s(?P<SB>[.,0-9]+) ?%(CUR)s\]\." % subst,
re.MULTILINE)
r"^%(PLYR)s posts small blind \[%(CUR_SYM)s(?P<SB>[.,0-9]+) ?%(CUR)s\]\."
% subst, re.MULTILINE)
self.re_PostBB = re.compile(
r"^%(PLYR)s posts big blind \[%(CUR_SYM)s(?P<BB>[.,0-9]+) ?%(CUR)s\]\." % subst,
re.MULTILINE)
u"%(PLYR)s posts big blind \[%(CUR_SYM)s(?P<BB>[.,0-9]+) ?%(CUR)s\]\."
% subst, re.MULTILINE)
self.re_PostDead = re.compile(
r"^%(PLYR)s posts big blind \+ dead \[(?P<BBNDEAD>[.,0-9]+) ?%(CUR_SYM)s\]\." % subst,
r"^%(PLYR)s posts big blind + dead \[(?P<BBNDEAD>[.,0-9]+) ?%(CUR_SYM)s\]\." % subst,
re.MULTILINE)
self.re_Antes = re.compile(
r"^%(PLYR)s posts ante \[%(CUR_SYM)s(?P<ANTE>[.,0-9]+) ?%(CUR)s\]" % subst,
@ -142,11 +144,10 @@ class PartyPoker(HandHistoryConverter):
self.re_HeroCards = re.compile(
r"^Dealt to %(PLYR)s \[\s*(?P<NEWCARDS>.+)\s*\]" % subst,
re.MULTILINE)
self.re_Action = re.compile(r"""
self.re_Action = re.compile(u"""
^%(PLYR)s\s+(?P<ATYPE>bets|checks|raises|calls|folds|is\sall-In)
(?:\s+\[%(CUR_SYM)s(?P<BET>[.,\d]+)\s*%(CUR)s\])?
""" % subst,
re.MULTILINE|re.VERBOSE)
""" % subst, re.MULTILINE|re.VERBOSE)
self.re_ShownCards = re.compile(
r"^%s (?P<SHOWED>(?:doesn\'t )?shows?) " % player_re +
r"\[ *(?P<CARDS>.+) *\](?P<COMBINATION>.+)\.",
@ -181,10 +182,6 @@ class PartyPoker(HandHistoryConverter):
return self._gameType
return self._gameType
@staticmethod
def decode_hand_text(handText):
return handText.encode("latin1").decode(LOCALE_ENCODING)
def determineGameType(self, handText):
"""inspect the handText and return the gametype dict
@ -192,7 +189,6 @@ class PartyPoker(HandHistoryConverter):
{'limitType': xxx, 'base': xxx, 'category': xxx}"""
info = {}
handText = self.decode_hand_text(handText)
m = self._getGameType(handText)
m_20BBmin = self.re_20BBmin.search(handText)
if m is None:
@ -210,7 +206,6 @@ class PartyPoker(HandHistoryConverter):
'Omaha' : ('hold','omahahi'),
"7 Card Stud Hi-Lo" : ('stud','studhi'),
}
currencies = { '$':'USD', '':'T$' }
for expectedField in ['LIMIT', 'GAME']:
if mg[expectedField] is None:
@ -243,7 +238,7 @@ class PartyPoker(HandHistoryConverter):
info['bb'] = "%.2f" % (bb)
info['sb'] = "%.2f" % (sb)
info['currency'] = currencies[mg['CURRENCY']]
info['currency'] = self.currencies[mg['CURRENCY']]
else:
info['sb'] = clearMoneyString(mg['SB'])
info['bb'] = clearMoneyString(mg['BB'])
@ -253,15 +248,11 @@ class PartyPoker(HandHistoryConverter):
def readHandInfo(self, hand):
# we should redecode handtext here (as it imposible to it above)
# if you know more accurate way to do it - tell me
hand.handText = self.decode_hand_text(hand.handText)
info = {}
try:
info.update(self.re_Hid.search(hand.handText).groupdict())
except:
raise FpdbParseError(_("Cannot read HID for current hand"))
except AttributeError, e:
raise FpdbParseError(_("Cannot read HID for current hand: %s" % e))
try:
info.update(self.re_HandInfo.search(hand.handText,re.DOTALL).groupdict())
@ -374,7 +365,6 @@ class PartyPoker(HandHistoryConverter):
else:
#zero stacked players are added later
zeroStackPlayers.append([int(a.group('SEAT')), a.group('PNAME'), clearMoneyString(a.group('CASH'))])
if hand.gametype['type'] == 'ring':
#finds first vacant seat after an exact seat
def findFirstEmptySeat(startSeat):

View File

@ -264,7 +264,7 @@ class PokerStars(HandHistoryConverter):
hand.buyinCurrency="PSFP"
else:
#FIXME: handle other currencies, FPP, play money
raise FpdbParseError(_("failed to detect currency"))
raise FpdbParseError(_("Failed to detect currency: '%s'" % info[key]))
info['BIAMT'] = info['BIAMT'].strip(u'$€FPP')

View File

@ -1064,7 +1064,7 @@ class Sql:
activeSeats SMALLINT NOT NULL,
position CHAR(1),
tourneyTypeId SMALLINT UNSIGNED, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
styleKey CHAR(9) NOT NULL, /* 1st char is style (A/T/H/S), other 8 are the key */
styleKey CHAR(7) NOT NULL, /* 1st char is style (A/T/H/S), other 6 are the key */
HDs INT NOT NULL,
wonWhenSeenStreet1 FLOAT,
@ -1165,7 +1165,7 @@ class Sql:
activeSeats SMALLINT,
position CHAR(1),
tourneyTypeId INT, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
styleKey CHAR(9) NOT NULL, /* 1st char is style (A/T/H/S), other 8 are the key */
styleKey CHAR(7) NOT NULL, /* 1st char is style (A/T/H/S), other 6 are the key */
HDs INT,
wonWhenSeenStreet1 FLOAT,
@ -2047,7 +2047,7 @@ class Sql:
# gets a date, would need to use handsplayers (not hudcache) to get exact hand Id
if db_server == 'mysql':
self.query['get_date_nhands_ago'] = """
select concat( 'd', date_format(max(h.startTime), '%Y%m%d%H') )
select concat( 'd', date_format(max(h.startTime), '%Y%m%d') )
from (select hp.playerId
,coalesce(greatest(max(hp.handId)-%s,1),1) as maxminusx
from HandsPlayers hp
@ -2059,7 +2059,7 @@ class Sql:
"""
elif db_server == 'postgresql':
self.query['get_date_nhands_ago'] = """
select 'd' || to_char(max(h3.startTime), 'YYMMDDHH')
select 'd' || to_char(max(h3.startTime), 'YYMMDD')
from (select hp.playerId
,coalesce(greatest(max(hp.handId)-%s,1),1) as maxminusx
from HandsPlayers hp
@ -2071,7 +2071,7 @@ class Sql:
"""
elif db_server == 'sqlite': # untested guess at query:
self.query['get_date_nhands_ago'] = """
select 'd' || strftime(max(h3.startTime), 'YYMMDDHH')
select 'd' || strftime(max(h3.startTime), 'YYMMDD')
from (select hp.playerId
,coalesce(greatest(max(hp.handId)-%s,1),1) as maxminusx
from HandsPlayers hp
@ -2479,7 +2479,11 @@ class Sql:
select s.name AS siteName
,t.tourneyTypeId AS tourneyTypeId
,tt.currency AS currency
,(CASE WHEN tt.currency = 'USD' THEN tt.buyIn/100.0 ELSE tt.buyIn END) AS buyIn
,(CASE
WHEN tt.currency = 'USD' THEN tt.buyIn/100.0
WHEN tt.currency = 'EUR' THEN tt.buyIn/100.0
ELSE tt.buyIn
END) AS buyIn
,tt.fee/100.0 AS fee
,tt.category AS category
,tt.limitType AS limitType
@ -2512,7 +2516,11 @@ class Sql:
select s.name AS siteName
,t.tourneyTypeId AS tourneyTypeId
,tt.currency AS currency
,(CASE WHEN tt.currency = 'USD' THEN tt.buyIn/100.0 ELSE tt.buyIn END) AS buyIn
,(CASE
WHEN tt.currency = 'USD' THEN tt.buyIn/100.0
WHEN tt.currency = 'EUR' THEN tt.buyIn/100.0
ELSE tt.buyIn
END) AS buyIn
,tt.fee/100.0 AS fee
,tt.category AS category
,tt.limitType AS limitType
@ -2546,7 +2554,11 @@ class Sql:
select s.name AS siteName
,t.tourneyTypeId AS tourneyTypeId
,tt.currency AS currency
,(CASE WHEN tt.currency = 'USD' THEN tt.buyIn/100.0 ELSE tt.buyIn END) AS buyIn
,(CASE
WHEN tt.currency = 'USD' THEN tt.buyIn/100.0
WHEN tt.currency = 'EUR' THEN tt.buyIn/100.0
ELSE tt.buyIn
END) AS buyIn
,tt.fee/100.0 AS fee
,tt.category AS category
,tt.limitType AS limitType
@ -3290,7 +3302,7 @@ class Sql:
else 'E'
end AS hc_position
<tourney_select_clause>
,date_format(h.startTime, 'd%y%m%d%H')
,date_format(h.startTime, 'd%y%m%d')
,count(1)
,sum(wonWhenSeenStreet1)
,sum(wonWhenSeenStreet2)
@ -3379,7 +3391,7 @@ class Sql:
,h.seats
,hc_position
<tourney_group_clause>
,date_format(h.startTime, 'd%y%m%d%H')
,date_format(h.startTime, 'd%y%m%d')
"""
elif db_server == 'postgresql':
self.query['rebuildHudCache'] = """
@ -3488,7 +3500,7 @@ class Sql:
else 'E'
end AS hc_position
<tourney_select_clause>
,'d' || to_char(h.startTime, 'YYMMDDHH')
,'d' || to_char(h.startTime, 'YYMMDD')
,count(1)
,sum(wonWhenSeenStreet1)
,sum(wonWhenSeenStreet2)
@ -3577,7 +3589,7 @@ class Sql:
,h.seats
,hc_position
<tourney_group_clause>
,to_char(h.startTime, 'YYMMDDHH')
,to_char(h.startTime, 'YYMMDD')
"""
else: # assume sqlite
self.query['rebuildHudCache'] = """
@ -3686,7 +3698,7 @@ class Sql:
else 'E'
end AS hc_position
<tourney_select_clause>
,'d' || substr(strftime('%Y%m%d%H', h.startTime),3,9)
,'d' || substr(strftime('%Y%m%d', h.startTime),3,7)
,count(1)
,sum(wonWhenSeenStreet1)
,sum(wonWhenSeenStreet2)
@ -3775,7 +3787,7 @@ class Sql:
,h.seats
,hc_position
<tourney_group_clause>
,'d' || substr(strftime('%Y%m%d%H', h.startTime),3,9)
,'d' || substr(strftime('%Y%m%d', h.startTime),3,7)
"""
self.query['insert_hudcache'] = """
@ -3968,7 +3980,8 @@ class Sql:
AND playerId=%s
AND activeSeats=%s
AND position=%s
AND tourneyTypeId+0=%s
AND (case when tourneyTypeId is NULL then 1 else
(case when tourneyTypeId+0=%s then 1 else 0 end) end)=1
AND styleKey=%s"""
self.query['get_hero_hudcache_start'] = """select min(hc.styleKey)

View File

@ -27,7 +27,7 @@ class Stove:
def __init__(self):
self.hand = None
self.board = None
self.range = None
self.h_range = None
def set_board_with_list(self, board):
pass
@ -58,7 +58,7 @@ class Stove:
def set_villain_range_string(self, string):
# Villain's range
range = Range()
h_range = Range()
hands_in_range = string.strip().split(',')
for h in hands_in_range:
_h = h.strip()
@ -67,11 +67,11 @@ class Stove:
r1 = cc[0]
r2 = cc[1]
vp = Cards(r1, r2)
range.add(vp)
h_range.add(vp)
else:
range.expand(expand_hands(_h, pocket_cards, board))
h_range.expand(expand_hands(_h, self.hand, self.board))
self.range = range
self.h_range = h_range
class Cards:
@ -147,37 +147,17 @@ class SumEV:
self.n_ties += ev.n_ties
self.n_losses += ev.n_losses
def show(self, hand, range):
def show(self, hand, h_range):
win_pct = 100 * (float(self.n_wins) / float(self.n_hands))
lose_pct = 100 * (float(self.n_losses) / float(self.n_hands))
tie_pct = 100 * (float(self.n_ties) / float(self.n_hands))
print 'Enumerated %d possible plays.' % self.n_hands
print 'Your hand: (%s %s)' % (hand.c1, hand.c2)
print 'Against the range: %s\n' % cards_from_range(range)
print 'Against the range: %s\n' % cards_from_range(h_range)
print ' Win Lose Tie'
print ' %5.2f%% %5.2f%% %5.2f%%' % (win_pct, lose_pct, tie_pct)
def usage(me):
print """Texas Hold'Em odds calculator
Calculates odds against a range of hands.
To use: %s '<board cards>' '<your hand>' '<opponent's range>' [...]
Separate cards with space.
Separate hands in range with commas.
""" % me
def cards_from_range(range):
s = '{'
for h in range:
if h.c1 == '__' and h.c2 == '__':
s += 'random, '
else:
s += '%s%s, ' % (h.c1, h.c2)
s = s.rstrip(', ')
s += '}'
return s
# Expands hand abbreviations such as JJ and AK to full hand ranges.
@ -202,7 +182,7 @@ def expand_hands(abbrev, hand, board):
else:
selection = ANY
range = []
h_range = []
considered = set()
for s1 in SUITS:
c1 = r1 + s1
@ -216,8 +196,8 @@ def expand_hands(abbrev, hand, board):
elif selection == OFFSUIT and s1 == s2:
continue
if c2 not in considered and c2 not in known_cards:
range.append(Cards(c1, c2))
return range
h_range.append(Cards(c1, c2))
return h_range
def parse_args(args, container):
@ -229,7 +209,6 @@ def parse_args(args, container):
container.set_hero_cards_string(args[2])
container.set_villain_range_string(args[3])
return True
@ -281,7 +260,7 @@ def odds_for_range(holder):
iters = random.randint(25000, 125000)
else:
iters = -1
for h in holder.range.get():
for h in holder.h_range.get():
e = odds_for_hand(
[holder.hand.c1, holder.hand.c2],
[h.c1, h.c2],
@ -290,7 +269,28 @@ def odds_for_range(holder):
)
sev.add(e)
sev.show(holder.hand, holder.range.get())
sev.show(holder.hand, holder.h_range.get())
def usage(me):
print """Texas Hold'Em odds calculator
Calculates odds against a range of hands.
To use: %s '<board cards>' '<your hand>' '<opponent's range>' [...]
Separate cards with space.
Separate hands in range with commas.
""" % me
def cards_from_range(h_range):
s = '{'
for h in h_range:
if h.c1 == '__' and h.c2 == '__':
s += 'random, '
else:
s += '%s%s, ' % (h.c1, h.c2)
s = s.rstrip(', ')
s += '}'
return s
def main(argv=None):
stove = Stove()

View File

@ -116,6 +116,7 @@ import GuiAutoImport
import GuiGraphViewer
import GuiTourneyGraphViewer
import GuiSessionViewer
import GuiReplayer
import GuiStove
import SQL
import Database
@ -779,6 +780,7 @@ class fpdb:
<menuitem action="tourneyviewer"/>
<menuitem action="posnstats"/>
<menuitem action="sessionstats"/>
<menuitem action="replayer"/>
<menuitem action="stove"/>
</menu>
<menu action="database">
@ -822,6 +824,7 @@ class fpdb:
('tourneyviewer', None, _('Tourney _Viewer'), None, 'Tourney Viewer)', self.tab_tourney_viewer_stats),
('posnstats', None, _('P_ositional Stats (tabulated view, not on sqlite)'), _('<control>O'), 'Positional Stats (tabulated view, not on sqlite)', self.tab_positional_stats),
('sessionstats', None, _('Session Stats'), None, 'Session Stats', self.tab_session_stats),
('replayer', None, _('Hand _Replayer'), None, 'Hand Replayer', self.tab_replayer),
('database', None, _('_Database')),
('maintaindbs', None, _('_Maintain Databases'), None, 'Maintain Databases', self.dia_maintain_dbs),
('createtabs', None, _('Create or Recreate _Tables'), None, 'Create or Recreate Tables ', self.dia_recreate_tables),
@ -1046,6 +1049,12 @@ class fpdb:
ps_tab=new_ps_thread.get_vbox()
self.add_and_display_tab(ps_tab, _("Session Stats"))
def tab_replayer(self, widget, data=None):
new_ps_thread = GuiReplayer.GuiReplayer(self.config, self.sql, self.window)
self.threads.append(new_ps_thread)
ps_tab=new_ps_thread.get_vbox()
self.add_and_display_tab(ps_tab, _("Hand Replayer"))
def tab_main_help(self, widget, data=None):
"""Displays a tab with the main fpdb help screen"""
mh_tab=gtk.Label(_("""Fpdb needs translators!

24
pyfpdb/fpdb_import.py Executable file → Normal file
View File

@ -83,6 +83,7 @@ class Importer:
self.pos_in_file = {} # dict to remember how far we have read in the file
#Set defaults
self.callHud = self.config.get_import_parameters().get("callFpdbHud")
self.cacheSessions = self.config.get_import_parameters().get("cacheSessions")
# CONFIGURATION OPTIONS
self.settings.setdefault("minPrint", 30)
@ -110,6 +111,9 @@ class Importer:
#Set functions
def setCallHud(self, value):
self.callHud = value
def setCacheSessions(self, value):
self.cacheSessions = value
def setMinPrint(self, value):
self.settings['minPrint'] = int(value)
@ -491,14 +495,22 @@ class Importer:
if hand is not None and not hand.is_duplicate:
hand.updateHudCache(self.database)
self.database.commit()
# Call sessionsCache update
if self.cacheSessions:
for hand in handlist:
if hand is not None and not hand.is_duplicate:
hand.updateSessionsCache(self.database)
self.database.commit()
#pipe the Hands.id out to the HUD
for hid in to_hud:
try:
print _("fpdb_import: sending hand to hud"), hand.dbid_hands, "pipe =", self.caller.pipe_to_hud
self.caller.pipe_to_hud.stdin.write("%s" % (hid) + os.linesep)
except IOError, e:
log.error(_("Failed to send hand to HUD: %s") % e)
if self.caller:
for hid in to_hud:
try:
print _("fpdb_import: sending hand to hud"), hand.dbid_hands, "pipe =", self.caller.pipe_to_hud
self.caller.pipe_to_hud.stdin.write("%s" % (hid) + os.linesep)
except IOError, e:
log.error(_("Failed to send hand to HUD: %s") % e)
errors = getattr(hhc, 'numErrors')
stored = getattr(hhc, 'numHands')

View File

@ -0,0 +1,32 @@
Game #9864152000 starts.
#Game No : 9864152000
***** Hand History for Game 9864152000 *****
€10 EUR NL Texas Hold'em - Sunday, November 21, 19:00:00 CET 2010
Table Table 183347 (Real Money)
Seat 1 is the button
Total number of players : 5/6
Seat 3: Hero ( €10 EUR )
Seat 6: Player6 ( €16.49 EUR )
Seat 4: Player4 ( €10.73 EUR )
Seat 1: Player1 ( €8.56 EUR )
Seat 2: Player2 ( €4.90 EUR )
Player2 posts small blind [€0.05 EUR].
Hero posts big blind [€0.10 EUR].
** Dealing down cards **
Dealt to Hero [ Ah Kc ]
Player4 calls [€0.10 EUR]
Player6 calls [€0.10 EUR]
Player1 calls [€0.10 EUR]
Player2 calls [€0.05 EUR]
Hero raises [€0.56 EUR]
Player4 folds
Player6 folds
Player1 folds
Player2 calls [€0.56 EUR]
** Dealing Flop ** [ 5s, 9d, Ad ]
Player2 checks
Hero bets [€1.52 EUR]
Player2 folds
Hero does not show cards.
Hero wins €3.04 EUR

View File

@ -1,3 +1,6 @@
Game #9423586142 starts.
#Game No : 9423586142
***** Hand History For Game 9423586142 *****
0.01/0.02 Texas Hold'em Game Table (NL) - Mon Jul 12 13:38:32 EDT 2010
Table 20BB Min Speed #1775757 (Real Money) -- Seat 1 is the button

178
utils/pypokertest.py Normal file
View File

@ -0,0 +1,178 @@
#
# Copyright (C) 2007, 2008 Loic Dachary <loic@dachary.org>
# Copyright (C) 2004, 2005, 2006 Mekensleep
#
# Mekensleep
# 24 rue vieille du temple
# 75004 Paris
# licensing@mekensleep.com
#
# 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 3 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
#
# Authors:
# Loic Dachary <loic@dachary.org>
#
#
import sys
sys.path.insert(0, ".")
sys.path.insert(0, ".libs")
from pokereval import PokerEval
iterations_low = 100000
iterations_high = 200000
pokereval = PokerEval()
if pokereval.best_hand_value("hi", ["Ah", "Ad", "As", "Kh", "Ks" ]) != 101494784:
sys.exit(1)
if pokereval.string2card("2h") != 0:
sys.exit(1)
print ""
pockets = [ ["As", "Ad", "Ac", "Tc", "Ts", "2d", "5c" ],
["Js", "Jc", "7s", "8c", "8d", "3c", "3h" ],
[255, 255 ] ]
print "stud7 (1) result = %s\n" % pokereval.winners(game = "7stud", pockets = pockets, dead = [], board = [])
pockets = [[22, 18, 21, 3, 41, 1, 30], [39, 255, 255, 15, 13, 17, 255]]
print "stud7 (2) result = %s\n" % pokereval.winners(game = "7stud", pockets = pockets, dead = [], board = [])
print [ j + i + "/%d" % pokereval.string2card(j + i) for i in "hdcs" for j in "23456789TJQKA" ]
print "deck = %s\n" % pokereval.deck()
print "result = %s\n" % pokereval.poker_eval(game = "holdem", pockets = [ ["tc", "ac"], ["3h", "ah"], ["8c", "6h"]], dead = [], board = ["7h", "3s", "2c"])
print "winners = %s\n" % pokereval.winners(game = "holdem", pockets = [ ["tc", "ac"], ["3h", "ah"], ["8c", "6h"]], dead = [], board = ["7h", "3s", "2c"])
print "result = %s\n" % pokereval.poker_eval(game = "holdem", pockets = [ ["tc", "ac"], ["th", "ah"], ["8c", "6h"]], dead = [], board = ["7h", "3s", "2c", "7s", "7d"])
print "winners = %s\n" % pokereval.winners(game = "holdem", pockets = [ ["tc", "ac"], ["th", "ah"], ["8c", "6h"]], dead = [], board = ["7h", "3s", "2c", "7s", "7d"])
print "winners (filthy pockets) = %s\n" % pokereval.winners(game = "holdem", pockets = [ ["tc", "ac", 255], [], [255, 255], ["th", "ah"], ["8c", "6h"]], dead = [], board = ["7h", "3s", "2c", "7s", "7d"])
print "winners omaha = %s\n" % pokereval.winners(game = "omaha", pockets = [ ["tc", "ac", "ks", "kc" ], ["th", "ah", "qs", "qc" ], ["8c", "6h", "js", "jc" ]], dead = [], board = ["7h", "3s", "2c", "7s", "7d"])
print "winners omaha8 = %s\n" % pokereval.winners(game = "omaha8", pockets = [ ["tc", "ac", "ks", "kc" ], ["th", "ah", "qs", "qc" ], ["8c", "6h", "js", "jc" ]], dead = [], board = ["7h", "3s", "2c", "7s", "7d"])
hand = ["Ac", "As", "Td", "7s", "7h", "3s", "2c"]
best_hand = pokereval.best_hand("hi", hand)
print "best hand from %s = %s" % ( hand, pokereval.best_hand("hi", hand) )
print "best hand from %s = (%s) %s " % (hand, best_hand[0], [ pokereval.card2string(i) for i in best_hand[1:] ])
print ""
hand = ["Ah", "Ts", "Kh", "Qs", "Js" ]
best_hand = pokereval.best_hand("hi", hand)
print "best hand from %s = %s" % ( hand, pokereval.best_hand("hi", hand) )
print "best hand from %s = (%s) %s " % (hand, best_hand[0], [ pokereval.card2string(i) for i in best_hand[1:] ])
print ""
hand = ["2h", "Kh", "Qh", "Jh", "Th" ]
best_hand = pokereval.best_hand("hi", hand)
print "best hand from %s = %s" % ( hand, pokereval.best_hand("hi", hand) )
print "best hand from %s = (%s) %s " % (hand, best_hand[0], [ pokereval.card2string(i) for i in best_hand[1:] ])
print ""
hand = ['2s', '3s', 'Jd', 'Ks', 'As', '4d', '5h', '7d', '9c']
best_hand = pokereval.best_hand("hi", hand)
print "best hand from %s = %s" % ( hand, pokereval.best_hand("hi", hand) )
print "best hand from %s = (%s) %s " % (hand, best_hand[0], [ pokereval.card2string(i) for i in best_hand[1:] ])
print ""
hand = ['As', '2s', '4d', '4s', '5c', '5d', '7s']
best_hand = pokereval.best_hand("low", hand)
print "1/ low hand from %s = %s" % ( hand, pokereval.best("low", hand) )
print "best low hand from %s = (%s) %s " % (hand, best_hand[0], [ pokereval.card2string(i) for i in best_hand[1:] ])
print ""
hand = ['As', '2s', '4d', '4s', '5c', '5d', '8s']
best_hand = pokereval.best_hand("low", hand)
print "2/ low hand from %s = %s" % ( hand, pokereval.best("low", hand) )
print "best low hand from %s = (%s) %s " % (hand, best_hand[0], [ pokereval.card2string(i) for i in best_hand[1:] ])
print ""
hand = ['7d', '6c', '5h', '4d', 'As']
best_hand = pokereval.best_hand("low", hand)
print "3/ low hand from %s = %s" % ( hand, pokereval.best("low", hand) )
print "best low hand from %s = (%s) %s " % (hand, best_hand[0], [ pokereval.card2string(i) for i in best_hand[1:] ])
print ""
board = [ 'As', '4d', '5h', '7d', '9c' ]
hand = [ '2s', 'Ts', 'Jd', 'Ks' ]
best_hand = pokereval.best_hand("low", hand, board)
print "4/ low hand from %s / %s = %s" % ( hand, board, pokereval.best("low", hand, board) )
print "best low hand from %s / %s = (%s) %s " % (hand, board, best_hand[0], [ pokereval.card2string(i) for i in best_hand[1:] ])
print ""
board = [ 'As', '4d', '6h', '7d', '3c' ]
hand = [ '2s', '5s', 'Jd', 'Ks' ]
best_hand = pokereval.best_hand("low", hand, board)
print "low hand from %s / %s = %s" % ( hand, board, pokereval.best("low", hand, board) )
print "best low hand from %s / %s = (%s) %s " % (hand, board, best_hand[0], [ pokereval.card2string(i) for i in best_hand[1:] ])
print ""
board = [ 'Jc', '4c', '3c', '5c', '9c' ]
hand = [ '2c', 'Ac', '5h', '9d' ]
best_hand = pokereval.best_hand("hi", hand, board)
print "hi hand from %s / %s = %s" % ( hand, board, pokereval.best("hi", hand, board) )
print "best hi hand from %s / %s = (%s) %s " % (hand, board, best_hand[0], pokereval.card2string(best_hand[1:]))
print ""
board = [ 'Jd', '9c', 'Jc', 'Tc', '2h' ]
hand = [ '2c', '4c', 'Th', '6s' ]
best_hand = pokereval.best_hand("low", hand, board)
print "5/ low hand from %s / %s = %s" % ( hand, board, pokereval.best("low", hand, board) )
print "best low hand from %s / %s = (%s) %s " % (hand, board, best_hand[0], [ pokereval.card2string(i) for i in best_hand[1:] ])
print ""
board = [ 'Ks', 'Jd', '7s', '4d', 'Js' ]
hand = [ '2d', '6c', 'Ac', '5c' ]
best_hand = pokereval.best_hand("low", hand, board)
print "6/ low hand from %s / %s = %s" % ( hand, board, pokereval.best("low", hand, board) )
print "best low hand from %s / %s = (%s) %s " % (hand, board, best_hand[0], [ pokereval.card2string(i) for i in best_hand[1:] ])
if len(sys.argv) > 2:
print "f0 result = %s\n" % pokereval.poker_eval(game = "holdem", fill_pockets = 1, pockets = [ ["As", "3s"], ["__", "__"], ["__", "__"]], dead = [], board = ["__", "Qs", "2c", "Ac", "Kc"])
print ""
print "f1 result = %s\n" % pokereval.poker_eval(game = "holdem", fill_pockets = 1, pockets = [ ["As", "3s"], ["__", "__"], ["__", "__"]], dead = [], board = ["7s", "Qs", "2c", "Ac", "Kc"])
print ""
print "f2 result = %s\n" % pokereval.poker_eval(game = "holdem", fill_pockets = 1, iterations = iterations_low, pockets = [ ["As", "3s"], ["__", "__"], ["__", "__"]], dead = [], board = ["__", "__", "__", "__", "__"])
print ""
print "f3 result = %s\n" % pokereval.poker_eval(game = "holdem", fill_pockets = 1, iterations = iterations_high, pockets = [ ["As", "Ac"], ["__", "__"], ["__", "__"]], dead = [], board = ["__", "__", "__", "__", "__"])
print ""
print "f4 result = %s\n" % pokereval.poker_eval(game = "holdem", fill_pockets = 1, iterations = iterations_high, pockets = [ ["As", "Ks"], ["__", "__"], ["__", "__"]], dead = [], board = ["__", "__", "__", "__", "__"])
print ""
print "f5 result = %s\n" % pokereval.poker_eval(game = "holdem", fill_pockets = 1, iterations = iterations_high, pockets = [ ["2s", "2c"], ["__", "__"], ["__", "__"]], dead = [], board = ["__", "__", "__", "__", "__"])
print ""
print "f6 result = %s\n" % pokereval.poker_eval(game = "holdem", fill_pockets = 1, iterations = iterations_high, pockets = [ ["Js", "Jc"], ["__", "__"], ["__", "__"]], dead = [], board = ["__", "__", "__", "__", "__"])
print ""
print "f7 result = %s\n" % pokereval.poker_eval(game = "omaha", fill_pockets = 1, iterations = iterations_high, pockets = [ ["Js", "Jc", "7s", "8c"], ["__", "__", "__", "__"], ["__", "__", "__", "__"]], dead = [], board = ["__", "__", "__", "__", "__"])
print ""
hand = ['As', 'Ad']
print "handval %s = %d " % (hand, pokereval.evaln(hand))
print ""
hand = ['Qc', '7d']
print "handval %s = %d " % (hand, pokereval.evaln(hand))
pokereval = None