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

This commit is contained in:
gimick 2010-12-05 16:55:26 +00:00
commit ed7abda1b7
129 changed files with 39093 additions and 15240 deletions

BIN
gfx/Table.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

@ -2,12 +2,12 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Copyright 2008-2010, Carl Gherardi # Copyright 2008-2010, Carl Gherardi
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or # the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
@ -18,23 +18,16 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
######################################################################## ########################################################################
#Note that this filter also supports UltimateBet, they are both owned by the same company and form the Cereus Network
import L10n
_ = L10n.get_translation()
# TODO: I have no idea if AP has multi-currency options, i just copied the regex out of Everleaf converter for the currency symbols.. weeeeee - Eric # TODO: I have no idea if AP has multi-currency options, i just copied the regex out of Everleaf converter for the currency symbols.. weeeeee - Eric
import sys import sys
import logging import logging
from HandHistoryConverter import * from HandHistoryConverter import *
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 for converting Absolute HH format. # Class for converting Absolute HH format.
class Absolute(HandHistoryConverter): class Absolute(HandHistoryConverter):
@ -45,31 +38,55 @@ class Absolute(HandHistoryConverter):
codepage = "cp1252" codepage = "cp1252"
siteid = 8 siteid = 8
HORSEHand = False HORSEHand = False
# Static regexes
re_SplitHands = re.compile(r"\n\n\n+")
re_TailSplitHands = re.compile(r"(\n\n\n+)")
#Stage #1571362962: Holdem No Limit $0.02 - 2009-08-05 15:24:06 (ET)
#Table: TORONTO AVE (Real Money) Seat #6 is the dealer
#Seat 6 - FETS63 ($0.75 in chips)
#Board [10s 5d Kh Qh 8c]
re_GameInfo = re.compile(ur"""^Stage #(C?[0-9]+):\s+ # Static regexes
(?P<GAME>Holdem|Seven\sCard\sHi\/L|HORSE) re_SplitHands = re.compile(r"\n\n+")
(?:\s\(1\son\s1\)|)?\s+? re_TailSplitHands = re.compile(r"(\nn\n+)")
(?P<LIMIT>No Limit|Pot\sLimit|Normal|)?\s? #Stage #1571362962: Holdem No Limit $0.02 - 2009-08-05 15:24:06 (ET)
(?P<CURRENCY>\$|\s|) #Table: TORONTO AVE (Real Money) Seat #6 is the dealer
(?P<SB>[.0-9]+)/?(?:\$|\s|)(?P<BB>[.0-9]+)? #Seat 6 - FETS63 ($0.75 in chips)
""", re.MULTILINE|re.VERBOSE) #Board [10s 5d Kh Qh 8c]
re_HorseGameInfo = re.compile(ur"^Game Type: (?P<LIMIT>Limit) (?P<GAME>Holdem)", re.MULTILINE)
# TODO: can set max seats via (1 on 1) to a known 2 .. re_GameInfo = re.compile( ur"""
re_HandInfo = re.compile(ur"^Stage #C?(?P<HID>[0-9]+): .*(?P<DATETIME>\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d).*\n(Table: (?P<TABLE>.*) \(Real Money\))?", re.MULTILINE) ^Stage\s+\#C?(?P<HID>[0-9]+):?\s+
re_TableFromFilename = re.compile(ur".*IHH([0-9]+) (?P<TABLE>.*) -") # on HORSE STUD games, the table name isn't in the hand info! (?:Tourney\ ID\ (?P<TRNY_ID>\d+)\s+)?
re_Button = re.compile(ur"Seat #(?P<BUTTON>[0-9]) is the ?[dead]* dealer$", re.MULTILINE) # TODO: that's not the right way to match for "dead" dealer is it? (?P<GAME>Holdem|Seven\ Card\ Hi\/L|HORSE)\s+
re_PlayerInfo = re.compile(ur"^Seat (?P<SEAT>[0-9]) - (?P<PNAME>.*) \((?:\$| €|)(?P<CASH>[0-9]*[.0-9]+) in chips\)", re.MULTILINE) (?P<TRNY_TYPE>\(1\son\s1\)|Single\ Tournament|Multi\ Normal\ Tournament|)\s*
re_Board = re.compile(ur"\[(?P<CARDS>[^\]]*)\]? *$", re.MULTILINE) (?P<LIMIT>No\ Limit|Pot\ Limit|Normal|)\s?
(?P<CURRENCY>\$|\s|)
(?P<SB>[.,0-9]+)/?(?:\$|\s|)(?P<BB>[.,0-9]+)?
\s+-\s+
(?P<DATETIME>\d\d\d\d-\d\d-\d\d\ \d\d:\d\d:\d\d)\s+
(?: \( (?P<TZ>[A-Z]+) \)\s+ )?
.*?
(Table:\ (?P<TABLE>.*?)\ \(Real\ Money\))?
""", re.MULTILINE|re.VERBOSE|re.DOTALL)
re_HorseGameInfo = re.compile(
ur"^Game Type: (?P<LIMIT>Limit) (?P<GAME>Holdem)",
re.MULTILINE)
re_HandInfo = re_GameInfo
# on HORSE STUD games, the table name isn't in the hand info!
re_RingInfoFromFilename = re.compile(ur".*IHH([0-9]+) (?P<TABLE>.*) -")
re_TrnyInfoFromFilename = re.compile(
ur"IHH\s?([0-9]+) (?P<TRNY_NAME>.*) "\
ur"ID (?P<TRNY_ID>\d+)\s?(\((?P<TABLE>\d+)\))? .* "\
ur"(?:\$|\s€|)(?P<BUYIN>[0-9.]+)\s*\+\s*(?:\$|\s€|)(?P<FEE>[0-9.]+)"
)
# TODO: that's not the right way to match for "dead" dealer is it?
re_Button = re.compile(ur"Seat #(?P<BUTTON>[0-9]) is the ?[dead]* dealer$", re.MULTILINE)
re_PlayerInfo = re.compile(
ur"^Seat (?P<SEAT>[0-9]) - (?P<PNAME>.*) "\
ur"\((?:\$| €|)(?P<CASH>[0-9]*[.,0-9]+) in chips\)",
re.MULTILINE)
re_Board = re.compile(ur"\[(?P<CARDS>[^\]]*)\]? *$", re.MULTILINE)
def compilePlayerRegexs(self, hand): def compilePlayerRegexs(self, hand):
players = set([player[1] for player in hand.players]) players = set([player[1] for player in hand.players])
if not players <= self.compiledPlayers: # x <= y means 'x is subset of y' if not players <= self.compiledPlayers: # x <= y means 'x is subset of y'
@ -78,32 +95,24 @@ class Absolute(HandHistoryConverter):
player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")" player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")"
logging.debug("player_re: "+ player_re) logging.debug("player_re: "+ player_re)
#(?P<CURRENCY>\$| €|)(?P<BB>[0-9]*[.0-9]+) #(?P<CURRENCY>\$| €|)(?P<BB>[0-9]*[.0-9]+)
self.re_PostSB = re.compile(ur"^%s - Posts small blind (?:\$| €|)(?P<SB>[0-9]*[.0-9]+)" % player_re, re.MULTILINE) self.re_PostSB = re.compile(ur"^%s - Posts small blind (?:\$| €|)(?P<SB>[,.0-9]+)" % player_re, re.MULTILINE)
self.re_PostBB = re.compile(ur"^%s - Posts big blind (?:\$| €|)(?P<BB>[0-9]*[.0-9]+)" % player_re, re.MULTILINE) self.re_PostBB = re.compile(ur"^%s - Posts big blind (?:\$| €|)(?P<BB>[.,0-9]+)" % player_re, re.MULTILINE)
# TODO: Absolute posting when coming in new: %s - Posts $0.02 .. should that be a new Post line? where do we need to add support for that? *confused* # TODO: Absolute posting when coming in new: %s - Posts $0.02 .. should that be a new Post line? where do we need to add support for that? *confused*
self.re_PostBoth = re.compile(ur"^%s - Posts dead (?:\$| €|)(?P<SBBB>[0-9]*[.0-9]+)" % player_re, re.MULTILINE) self.re_PostBoth = re.compile(ur"^%s - Posts dead (?:\$| €|)(?P<SBBB>[,.0-9]+)" % player_re, re.MULTILINE)
self.re_Action = re.compile(ur"^%s - (?P<ATYPE>Bets |Raises |All-In |All-In\(Raise\) |Calls |Folds|Checks)?\$?(?P<BET>[0-9]*[.0-9]+)?" % player_re, re.MULTILINE) self.re_Action = re.compile(ur"^%s - (?P<ATYPE>Bets |Raises |All-In |All-In\(Raise\) |Calls |Folds|Checks)?\$?(?P<BET>[,.0-9]+)?" % player_re, re.MULTILINE)
# print "^%s - (?P<ATYPE>Bets |Raises |All-In |All-In\(Raise\) |Calls |Folds|Checks)?\$?(?P<BET>[0-9]*[.0-9]+)?" % player_re
self.re_ShowdownAction = re.compile(ur"^%s - Shows \[(?P<CARDS>.*)\]" % player_re, re.MULTILINE) self.re_ShowdownAction = re.compile(ur"^%s - Shows \[(?P<CARDS>.*)\]" % player_re, re.MULTILINE)
self.re_CollectPot = re.compile(ur"^Seat [0-9]: %s(?: \(dealer\)|)(?: \(big blind\)| \(small blind\)|) (?:won|collected) Total \((?:\$| €|)(?P<POT>[0-9]*[.0-9]+)\)" % player_re, re.MULTILINE) self.re_CollectPot = re.compile(ur"^Seat [0-9]: %s(?: \(dealer\)|)(?: \(big blind\)| \(small blind\)|) (?:won|collected) Total \((?:\$| €|)(?P<POT>[,.0-9]+)\)" % player_re, re.MULTILINE)
#self.re_PostSB = re.compile(ur"^%s: posts small blind \[(?:\$| €|) (?P<SB>[.0-9]+)" % player_re, re.MULTILINE) self.re_Antes = re.compile(ur"^%s - Ante \[(?:\$| €|)(?P<ANTE>[,.0-9]+)" % player_re, re.MULTILINE)
#self.re_PostBB = re.compile(ur"^%s: posts big blind \[(?:\$| €|) (?P<BB>[.0-9]+)" % player_re, re.MULTILINE)
#self.re_PostBoth = re.compile(ur"^%s: posts both blinds \[(?:\$| €|) (?P<SBBB>[.0-9]+)" % player_re, re.MULTILINE)
self.re_Antes = re.compile(ur"^%s - Ante \[(?:\$| €|)(?P<ANTE>[.0-9]+)" % player_re, re.MULTILINE)
#self.re_BringIn = re.compile(ur"^%s posts bring-in (?:\$| €|)(?P<BRINGIN>[.0-9]+)\." % player_re, re.MULTILINE) #self.re_BringIn = re.compile(ur"^%s posts bring-in (?:\$| €|)(?P<BRINGIN>[.0-9]+)\." % player_re, re.MULTILINE)
self.re_HeroCards = re.compile(ur"^Dealt to %s \[(?P<CARDS>.*)\]" % player_re, re.MULTILINE) self.re_HeroCards = re.compile(ur"^Dealt to %s \[(?P<CARDS>.*)\]" % player_re, re.MULTILINE)
#self.re_Action = re.compile(ur"^%s(?P<ATYPE>: bets| checks| raises| calls| folds)(\s\[(?:\$| €|) (?P<BET>[.\d]+) (USD|EUR|)\])?" % player_re, re.MULTILINE)
#self.re_Action = re.compile(ur"^%s(?P<ATYPE>: bets| checks| raises| calls| folds| complete to)(\s\[?(?:\$| €|) ?(?P<BET>\d+\.?\d*)\.?\s?(USD|EUR|)\]?)?" % player_re, re.MULTILINE)
#self.re_ShowdownAction = re.compile(ur"^%s shows \[ (?P<CARDS>.*) \]" % player_re, re.MULTILINE)
#self.re_CollectPot = re.compile(ur"^%s wins (?:\$| €|) (?P<POT>[.\d]+) (USD|EUR|chips)(.*?\[ (?P<CARDS>.*?) \])?" % player_re, re.MULTILINE)
#self.re_SitsOut = re.compile(ur"^%s sits out" % player_re, re.MULTILINE)
def readSupportedGames(self): def readSupportedGames(self):
return [["ring", "hold", "nl"], return [["ring", "hold", "nl"],
["ring", "hold", "pl"], ["ring", "hold", "pl"],
["ring", "hold", "fl"], ["ring", "hold", "fl"],
["ring", "studhi", "fl"], ["ring", "studhi", "fl"],
["ring", "omahahi", "pl"] ["ring", "omahahi", "pl"],
["tour", "hold", "nl"],
] ]
def determineGameType(self, handText): def determineGameType(self, handText):
@ -111,7 +120,9 @@ class Absolute(HandHistoryConverter):
'type' in ('ring', 'tour') 'type' in ('ring', 'tour')
'limitType' in ('nl', 'cn', 'pl', 'cp', 'fl') 'limitType' in ('nl', 'cn', 'pl', 'cp', 'fl')
'base' in ('hold', 'stud', 'draw') 'base' in ('hold', 'stud', 'draw')
'category' in ('holdem', 'omahahi', omahahilo', 'razz', 'studhi', 'studhilo', 'fivedraw', '27_1draw', '27_3draw', 'badugi') 'category' in ('holdem', 'omahahi', omahahilo', 'razz',
'studhi', 'studhilo', 'fivedraw', '27_1draw',
'27_3draw', 'badugi')
'hilo' in ('h','l','s') 'hilo' in ('h','l','s')
'smallBlind' int? 'smallBlind' int?
'bigBlind' int? 'bigBlind' int?
@ -121,7 +132,7 @@ class Absolute(HandHistoryConverter):
or None if we fail to get the info """ or None if we fail to get the info """
info = {'type':'ring'} info = {'type':'ring'}
m = self.re_GameInfo.search(handText) m = self.re_GameInfo.search(handText)
if not m: if not m:
tmp = handText[0:100] tmp = handText[0:100]
@ -129,15 +140,16 @@ class Absolute(HandHistoryConverter):
log.error(_("determineGameType: Raising FpdbParseError")) log.error(_("determineGameType: Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp) raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
mg = m.groupdict() mg = m.groupdict()
#print "DEBUG: mg: %s" % mg
# translations from captured groups to our info strings # translations from captured groups to our info strings
limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Normal':'fl', 'Limit':'fl'} limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Normal':'fl', 'Limit':'fl'}
games = { # base, category games = { # base, category
"Holdem" : ('hold','holdem'), "Holdem" : ('hold','holdem'),
'Omaha' : ('hold','omahahi'), 'Omaha' : ('hold','omahahi'),
'Razz' : ('stud','razz'), 'Razz' : ('stud','razz'),
'Seven Card Hi/L' : ('stud','studhilo'), 'Seven Card Hi/L' : ('stud','studhilo'),
'7 Card Stud' : ('stud','studhi') '7 Card Stud' : ('stud','studhi')
} }
@ -157,45 +169,67 @@ class Absolute(HandHistoryConverter):
if 'GAME' in mg: if 'GAME' in mg:
(info['base'], info['category']) = games[mg['GAME']] (info['base'], info['category']) = games[mg['GAME']]
if 'LIMIT' in mg: if 'LIMIT' in mg:
info['limitType'] = limits[mg['LIMIT']] info['limitType'] = limits[mg['LIMIT']]
if 'SB' in mg:
info['sb'] = mg['SB']
else:
info['sb'] = str(float(mg['BB']) * 0.5) # TODO: Apparently AP doesn't provide small blind info!? must search to see if it's posted, I guess
if 'BB' in mg:
info['bb'] = mg['BB']
if 'CURRENCY' in mg: if 'CURRENCY' in mg:
info['currency'] = currencies[mg['CURRENCY']] info['currency'] = currencies[mg['CURRENCY']]
if info['currency'] == 'T$': if info['currency'] == 'T$':
info['type'] = 'tour' info['type'] = 'tour'
if 'SB' in mg:
mg['SB'] = mg['SB'].replace(',', '')
info['sb'] = mg['SB']
if 'BB' in mg:
info['bb'] = mg['BB']
# NB: SB, BB must be interpreted as blinds or bets depending on limit type. # NB: SB, BB must be interpreted as blinds or bets depending on limit type.
if info['bb'] is None: if info['bb'] is None:
mg['SB'] = mg['SB'].replace(',', '')
info['bb'] = mg['SB'] info['bb'] = mg['SB']
info['sb'] = str(float(mg['SB']) * 0.5) # TODO: AP does provide Small BET for Limit .. I think? at least 1-on-1 limit they do.. sigh info['sb'] = str(float(mg['SB']) * 0.5) # TODO: AP does provide Small BET for Limit .. I think? at least 1-on-1 limit they do.. sigh
#print info;
return info return info
def readHandInfo(self, hand): def readHandInfo(self, hand):
is_trny = hand.gametype['type']=='tour'
m = self.re_HandInfo.search(hand.handText) m = self.re_HandInfo.search(hand.handText)
if(m == None): fname_re = self.re_TrnyInfoFromFilename if is_trny \
logging.info(_("Didn't match re_HandInfo")) else self.re_RingInfoFromFilename
logging.info(hand.handText) fname_info = fname_re.search(self.in_path)
return None
#print "DEBUG: fname_info.groupdict(): %s" %(fname_info.groupdict())
if m is None or fname_info is None:
if m is None:
tmp = hand.handText[0:100]
logging.error(_("readHandInfo: Didn't match: '%s'") % tmp)
raise FpdbParseError(_("Absolute: Didn't match re_HandInfo: '%s'") % tmp)
elif fname_info is None:
logging.error(_("readHandInfo: File name didn't match re_*InfoFromFilename"))
logging.error(_("File name: %s") % self.in_path)
raise FpdbParseError(_("Absolute: Didn't match re_*InfoFromFilename: '%s'") % self.in_path)
logging.debug("HID %s, Table %s" % (m.group('HID'), m.group('TABLE'))) logging.debug("HID %s, Table %s" % (m.group('HID'), m.group('TABLE')))
hand.handid = m.group('HID') hand.handid = m.group('HID')
if m.group('TABLE'): if m.group('TABLE'):
hand.tablename = m.group('TABLE') hand.tablename = m.group('TABLE')
else: else:
t = self.re_TableFromFilename.search(self.in_path) hand.tablename = fname_info.group('TABLE')
hand.tablename = t.group('TABLE')
hand.maxseats = 6 # assume 6-max unless we have proof it's a larger/smaller game, since absolute doesn't give seat max info
# TODO: (1-on-1) does have that info in the game type line
if self.HORSEHand:
hand.maxseats = 8
hand.startTime = datetime.datetime.strptime(m.group('DATETIME'), "%Y-%m-%d %H:%M:%S") hand.startTime = datetime.datetime.strptime(m.group('DATETIME'), "%Y-%m-%d %H:%M:%S")
if is_trny:
hand.fee = fname_info.group('FEE')
hand.buyin = fname_info.group('BUYIN')
hand.tourNo = m.group('TRNY_ID')
hand.tourneyComment = fname_info.group('TRNY_NAME')
# assume 6-max unless we have proof it's a larger/smaller game,
#since absolute doesn't give seat max info
# TODO: (1-on-1) does have that info in the game type line
hand.maxseats = 6
if self.HORSEHand:
hand.maxseats = 8 # todo : unless it's heads up!!?
return return
def readPlayerStacks(self, hand): def readPlayerStacks(self, hand):
@ -204,10 +238,11 @@ class Absolute(HandHistoryConverter):
seatnum = int(a.group('SEAT')) seatnum = int(a.group('SEAT'))
hand.addPlayer(seatnum, a.group('PNAME'), a.group('CASH')) hand.addPlayer(seatnum, a.group('PNAME'), a.group('CASH'))
if seatnum > 6: if seatnum > 6:
hand.maxseats = 10 # absolute does 2/4/6/8/10 games hand.maxseats = 9 # absolute does 2/4/6/9 games
# TODO: implement lookup list by table-name to determine maxes, then fall back to 6 default/10 here, if there's no entry in the list? # TODO: implement lookup list by table-name to determine maxes,
# then fall back to 6 default/10 here, if there's no entry in the list?
def markStreets(self, hand): def markStreets(self, hand):
# PREFLOP = ** Dealing down cards ** # PREFLOP = ** Dealing down cards **
# This re fails if, say, river is missing; then we don't get the ** that starts the river. # This re fails if, say, river is missing; then we don't get the ** that starts the river.
@ -217,7 +252,7 @@ class Absolute(HandHistoryConverter):
r"(\*\*\* FLOP \*\*\*(?P<FLOP>.+(?=\*\*\* TURN \*\*\*)|.+))?" r"(\*\*\* FLOP \*\*\*(?P<FLOP>.+(?=\*\*\* TURN \*\*\*)|.+))?"
r"(\*\*\* TURN \*\*\*(?P<TURN>.+(?=\*\*\* RIVER \*\*\*)|.+))?" r"(\*\*\* TURN \*\*\*(?P<TURN>.+(?=\*\*\* RIVER \*\*\*)|.+))?"
r"(\*\*\* RIVER \*\*\*(?P<RIVER>.+))?", hand.handText, re.DOTALL) r"(\*\*\* RIVER \*\*\*(?P<RIVER>.+))?", hand.handText, re.DOTALL)
elif hand.gametype['base'] == 'stud': # TODO: Not implemented yet elif hand.gametype['base'] == 'stud': # TODO: Not implemented yet
m = re.search(r"(?P<ANTES>.+(?=\*\* Dealing down cards \*\*)|.+)" m = re.search(r"(?P<ANTES>.+(?=\*\* Dealing down cards \*\*)|.+)"
r"(\*\* Dealing down cards \*\*(?P<THIRD>.+(?=\*\*\*\* dealing 4th street \*\*\*\*)|.+))?" r"(\*\* Dealing down cards \*\*(?P<THIRD>.+(?=\*\*\*\* dealing 4th street \*\*\*\*)|.+))?"
@ -227,10 +262,12 @@ class Absolute(HandHistoryConverter):
r"(\*\*\*\* dealing river \*\*\*\*(?P<SEVENTH>.+))?", hand.handText,re.DOTALL) r"(\*\*\*\* dealing river \*\*\*\*(?P<SEVENTH>.+))?", hand.handText,re.DOTALL)
hand.addStreets(m) hand.addStreets(m)
def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand def readCommunityCards(self, hand, street):
# If this has been called, street is a street which gets dealt community cards by type hand # street has been matched by markStreets, so exists in this hand
# but it might be worth checking somehow. # If this has been called, street is a street which gets dealt
# if street in ('FLOP','TURN','RIVER'): # a list of streets which get dealt community cards (i.e. all but PREFLOP) # community cards by type hand but it might be worth checking somehow.
# if street in ('FLOP','TURN','RIVER'):
# a list of streets which get dealt community cards (i.e. all but PREFLOP)
logging.debug("readCommunityCards (%s)" % street) logging.debug("readCommunityCards (%s)" % street)
m = self.re_Board.search(hand.streets[street]) m = self.re_Board.search(hand.streets[street])
cards = m.group('CARDS') cards = m.group('CARDS')
@ -281,7 +318,7 @@ class Absolute(HandHistoryConverter):
else: else:
#Not involved in hand #Not involved in hand
hand.involved = False hand.involved = False
def readStudPlayerCards(self, hand, street): def readStudPlayerCards(self, hand, street):
# lol. see Plymouth.txt # lol. see Plymouth.txt
logging.warning(_("Absolute readStudPlayerCards is only a stub.")) logging.warning(_("Absolute readStudPlayerCards is only a stub."))
@ -295,17 +332,21 @@ class Absolute(HandHistoryConverter):
for action in m: for action in m:
logging.debug("%s %s" % (action.group('ATYPE'), action.groupdict())) logging.debug("%s %s" % (action.group('ATYPE'), action.groupdict()))
if action.group('ATYPE') == 'Raises ' or action.group('ATYPE') == 'All-In(Raise) ': if action.group('ATYPE') == 'Raises ' or action.group('ATYPE') == 'All-In(Raise) ':
hand.addCallandRaise( street, action.group('PNAME'), action.group('BET') ) bet = action.group('BET').replace(',', '')
hand.addCallandRaise( street, action.group('PNAME'), bet)
elif action.group('ATYPE') == 'Calls ': elif action.group('ATYPE') == 'Calls ':
hand.addCall( street, action.group('PNAME'), action.group('BET') ) bet = action.group('BET').replace(',', '')
hand.addCall( street, action.group('PNAME'), bet)
elif action.group('ATYPE') == 'Bets ' or action.group('ATYPE') == 'All-In ': elif action.group('ATYPE') == 'Bets ' or action.group('ATYPE') == 'All-In ':
hand.addBet( street, action.group('PNAME'), action.group('BET') ) bet = action.group('BET').replace(',', '')
hand.addBet( street, action.group('PNAME'), bet)
elif action.group('ATYPE') == 'Folds': elif action.group('ATYPE') == 'Folds':
hand.addFold( street, action.group('PNAME')) hand.addFold( street, action.group('PNAME'))
elif action.group('ATYPE') == 'Checks': elif action.group('ATYPE') == 'Checks':
hand.addCheck( street, action.group('PNAME')) hand.addCheck( street, action.group('PNAME'))
elif action.group('ATYPE') == ' complete to': # TODO: not supported yet ? elif action.group('ATYPE') == ' complete to': # TODO: not supported yet ?
hand.addComplete( street, action.group('PNAME'), action.group('BET')) bet = action.group('BET').replace(',', '')
hand.addComplete( street, action.group('PNAME'), bet)
else: else:
logging.debug(_("Unimplemented readAction: %s %s" %(action.group('PNAME'),action.group('ATYPE'),))) logging.debug(_("Unimplemented readAction: %s %s" %(action.group('PNAME'),action.group('ATYPE'),)))
@ -315,14 +356,15 @@ class Absolute(HandHistoryConverter):
logging.debug("readShowdownActions") logging.debug("readShowdownActions")
for shows in self.re_ShowdownAction.finditer(hand.handText): for shows in self.re_ShowdownAction.finditer(hand.handText):
cards = shows.group('CARDS') cards = shows.group('CARDS')
cards = [validCard(card) for card in cards.split(' ')] cards = [validCard(card) for card in cards.split(' ')]
logging.debug("readShowdownActions %s %s" %(cards, shows.group('PNAME'))) logging.debug("readShowdownActions %s %s" %(cards, shows.group('PNAME')))
hand.addShownCards(cards, shows.group('PNAME')) hand.addShownCards(cards, shows.group('PNAME'))
def readCollectPot(self,hand): def readCollectPot(self,hand):
for m in self.re_CollectPot.finditer(hand.handText): for m in self.re_CollectPot.finditer(hand.handText):
hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT')) pot = m.group('POT').replace(',','')
hand.addCollectPot(player=m.group('PNAME'),pot=pot)
def readShownCards(self,hand): def readShownCards(self,hand):
"""Reads lines where hole & board cards are mixed to form a hand (summary lines)""" """Reads lines where hole & board cards are mixed to form a hand (summary lines)"""
@ -348,7 +390,12 @@ def validCard(card):
if __name__ == "__main__": if __name__ == "__main__":
import Configuration import Configuration
import Database
config = Configuration.Config(None) config = Configuration.Config(None)
# line below this is required
# because config.site_ids (site_name to site_id map) is required
# and one is stored and db.
db = Database.Database(config)
parser = OptionParser() parser = OptionParser()
parser.add_option("-i", "--input", dest="ipath", help=_("parse input hand history"), default="-") parser.add_option("-i", "--input", dest="ipath", help=_("parse input hand history"), default="-")
@ -366,5 +413,5 @@ if __name__ == "__main__":
LOG_FILENAME = './logging.out' LOG_FILENAME = './logging.out'
logging.basicConfig(filename=LOG_FILENAME,level=options.verbosity) logging.basicConfig(filename=LOG_FILENAME,level=options.verbosity)
e = Absolute(config, in_path = options.ipath, out_path = options.opath, follow = options.follow, autostart=True) e = Absolute(config, in_path = options.ipath, out_path = options.opath, follow = options.follow, autostart=True, sitename="Absolute")

22
pyfpdb/Anonymise.py Executable file → Normal file
View File

@ -15,6 +15,9 @@
#along with this program. If not, see <http://www.gnu.org/licenses/>. #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. #In the "official" distribution you can find the license in agpl-3.0.txt.
import L10n
_ = L10n.get_translation()
import os import os
import re import re
import codecs import codecs
@ -23,17 +26,6 @@ import HandHistoryConverter
import Configuration import Configuration
import sys import sys
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
(options, argv) = Options.fpdb_options() (options, argv) = Options.fpdb_options()
config = Configuration.Config() config = Configuration.Config()
@ -47,17 +39,17 @@ obj = getattr(mod, filter_name, None)
hhc = obj(config, autostart=False) hhc = obj(config, autostart=False)
if os.path.exists(options.infile): if os.path.exists(options.filename):
in_fh = codecs.open(options.infile, 'r', "utf8") in_fh = codecs.open(options.filename, 'r', "utf8")
filecontents = in_fh.read() filecontents = in_fh.read()
in_fh.close() in_fh.close()
else: else:
print _("Could not find file %s") % options.infile print _("Could not find file %s") % options.filename
exit(1) exit(1)
m = hhc.re_PlayerInfo.finditer(filecontents) m = hhc.re_PlayerInfo.finditer(filecontents)
outfile = options.infile+".anon" outfile = options.filename+".anon"
print _("Output being written to"), outfile print _("Output being written to"), outfile
savestdout = sys.stdout savestdout = sys.stdout

View File

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

View File

@ -19,11 +19,13 @@
######################################################################## ########################################################################
import L10n
_ = L10n.get_translation()
# This code is based heavily on EverleafToFpdb.py, by Carl Gherardi # This code is based heavily on EverleafToFpdb.py, by Carl Gherardi
# #
# TODO: # TODO:
# #
# -- No siteID assigned
# -- No support for games other than NL hold 'em cash. Hand histories for other # -- No support for games other than NL hold 'em cash. Hand histories for other
# games required # games required
# -- No support for limit hold 'em yet, though this would be easy to add # -- No support for limit hold 'em yet, though this would be easy to add
@ -53,18 +55,6 @@ import logging
from HandHistoryConverter import * from HandHistoryConverter import *
from decimal import Decimal 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 Carbon(HandHistoryConverter): class Carbon(HandHistoryConverter):
@ -76,7 +66,7 @@ class Carbon(HandHistoryConverter):
# Static regexes # Static regexes
re_SplitHands = re.compile(r'</game>\n+(?=<game)') re_SplitHands = re.compile(r'</game>\n+(?=<game)')
re_TailSplitHands = re.compile(r'(</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_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_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_Button = re.compile(r'<players dealer="(?P<BUTTON>[0-9]+)">')
re_PlayerInfo = re.compile(r'<player seat="(?P<SEAT>[0-9]+)" nickname="(?P<PNAME>.+)" balance="\$(?P<CASH>[.0-9]+)" dealtin="(?P<DEALTIN>(true|false))" />', re.MULTILINE) re_PlayerInfo = re.compile(r'<player seat="(?P<SEAT>[0-9]+)" nickname="(?P<PNAME>.+)" balance="\$(?P<CASH>[.0-9]+)" dealtin="(?P<DEALTIN>(true|false))" />', re.MULTILINE)
@ -86,8 +76,8 @@ class Carbon(HandHistoryConverter):
# The following are also static regexes: there is no need to call # The following are also static regexes: there is no need to call
# compilePlayerRegexes (which does nothing), since players are identified # compilePlayerRegexes (which does nothing), since players are identified
# not by name but by seat number # 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_PostSB = re.compile(r'<event sequence="[0-9]+" type="(SMALL_BLIND|RETURN_BLIND)" (?P<TIMESTAMP>timestamp="[0-9]+" )?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_PostBB = re.compile(r'<event sequence="[0-9]+" type="(BIG_BLIND|INITIAL_BLIND)" (?P<TIMESTAMP>timestamp="[0-9]+" )?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_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_Antes = ???
#re_BringIn = ??? #re_BringIn = ???
@ -143,8 +133,9 @@ or None if we fail to get the info """
self.info = {} self.info = {}
mg = m.groupdict() mg = m.groupdict()
print mg
limits = { 'No Limit':'nl', 'Limit':'fl' } limits = { 'No Limit':'nl', 'No Limit ':'nl', 'Limit':'fl' }
games = { # base, category games = { # base, category
'Holdem' : ('hold','holdem'), 'Holdem' : ('hold','holdem'),
'Holdem Tournament' : ('hold','holdem') } 'Holdem Tournament' : ('hold','holdem') }
@ -171,7 +162,7 @@ or None if we fail to get the info """
if m is None: if m is None:
logging.info(_("Didn't match re_HandInfo")) logging.info(_("Didn't match re_HandInfo"))
logging.info(hand.handText) logging.info(hand.handText)
return None raise FpdbParseError(_("No match in readHandInfo."))
logging.debug("HID %s-%s, Table %s" % (m.group('HID1'), logging.debug("HID %s-%s, Table %s" % (m.group('HID1'),
m.group('HID2'), m.group('TABLE')[:-1])) m.group('HID2'), m.group('TABLE')[:-1]))
hand.handid = m.group('HID1') + m.group('HID2') hand.handid = m.group('HID1') + m.group('HID2')
@ -182,7 +173,7 @@ or None if we fail to get the info """
# Check that the hand is complete up to the awarding of the pot; if # Check that the hand is complete up to the awarding of the pot; if
# not, the hand is unparseable # not, the hand is unparseable
if self.re_EndOfHand.search(hand.handText) is None: if self.re_EndOfHand.search(hand.handText) is None:
raise FpdbParseError(hid=m.group('HID1') + "-" + m.group('HID2')) raise FpdbParseError("readHandInfo failed: HID: '%s' HID2: '%s'" %(m.group('HID1'), m.group('HID2')))
def readPlayerStacks(self, hand): def readPlayerStacks(self, hand):
m = self.re_PlayerInfo.finditer(hand.handText) m = self.re_PlayerInfo.finditer(hand.handText)
@ -222,15 +213,13 @@ or None if we fail to get the info """
pass # ??? pass # ???
def readBlinds(self, hand): def readBlinds(self, hand):
try: for a in self.re_PostSB.finditer(hand.handText):
m = self.re_PostSB.search(hand.handText) #print "DEBUG: found sb: '%s' '%s'" %(self.playerNameFromSeatNo(a.group('PSEAT'), hand), a.group('SB'))
hand.addBlind(self.playerNameFromSeatNo(m.group('PSEAT'), hand), hand.addBlind(self.playerNameFromSeatNo(a.group('PSEAT'), hand),'small blind', a.group('SB'))
'small blind', m.group('SB'))
except: # no small blind
hand.addBlind(None, None, None)
for a in self.re_PostBB.finditer(hand.handText): for a in self.re_PostBB.finditer(hand.handText):
hand.addBlind(self.playerNameFromSeatNo(a.group('PSEAT'), hand), #print "DEBUG: found bb: '%s' '%s'" %(self.playerNameFromSeatNo(a.group('PSEAT'), hand), a.group('BB'))
'big blind', a.group('BB')) hand.addBlind(self.playerNameFromSeatNo(a.group('PSEAT'), hand), 'big blind', a.group('BB'))
for a in self.re_PostBoth.finditer(hand.handText): for a in self.re_PostBoth.finditer(hand.handText):
bb = Decimal(self.info['bb']) bb = Decimal(self.info['bb'])
amount = Decimal(a.group('SBBB')) amount = Decimal(a.group('SBBB'))

View File

@ -15,34 +15,37 @@
#along with this program. If not, see <http://www.gnu.org/licenses/>. #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. #In the "official" distribution you can find the license in agpl-3.0.txt.
import locale import L10n
lang=locale.getdefaultlocale()[0][0:2] _ = L10n.get_translation()
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
# From fpdb_simple
card_map = { "0": 0, "2": 2, "3" : 3, "4" : 4, "5" : 5, "6" : 6, "7" : 7, "8" : 8, card_map = { "0": 0, "2": 2, "3" : 3, "4" : 4, "5" : 5, "6" : 6, "7" : 7, "8" : 8,
"9" : 9, "T" : 10, "J" : 11, "Q" : 12, "K" : 13, "A" : 14} "9" : 9, "T" : 10, "J" : 11, "Q" : 12, "K" : 13, "A" : 14}
card_map_low = { "0": 0, "A":1, "2": 2, "3" : 3, "4" : 4, "5" : 5, "6" : 6, "7" : 7, "8" : 8,
"9" : 9, "T" : 10, "J" : 11, "Q" : 12, "K" : 13}
def decodeStartHandValue(game, value):
if game == "holdem":
return twoStartCardString(value)
elif game == "razz":
return decodeRazzStartHand(value)
else:
return "xx"
# FIXME: the following is a workaround until switching to newimport. # FIXME: the following is a workaround until switching to newimport.
# This should be moved into DerivedStats # This should be moved into DerivedStats
# I'd also like to change HandsPlayers.startCards to a different datatype # I'd also like to change HandsPlayers.startCards to a different datatype
# so we can 'trivially' add different start card classifications # so we can 'trivially' add different start card classifications
def calcStartCards(hand, player): def calcStartCards(hand, player):
hcs = hand.join_holecards(player, asList=True)
if hand.gametype['category'] == 'holdem': if hand.gametype['category'] == 'holdem':
hcs = hand.join_holecards(player, asList=True)
#print "DEBUG: hcs: %s" % hcs
value1 = card_map[hcs[0][0]] value1 = card_map[hcs[0][0]]
value2 = card_map[hcs[1][0]] value2 = card_map[hcs[1][0]]
return twoStartCards(value1, hcs[0][1], value2, hcs[1][1]) return twoStartCards(value1, hcs[0][1], value2, hcs[1][1])
elif hand.gametype['category'] == 'razz':
return encodeRazzStartHand(hcs)
else: else:
# FIXME: Only do startCards value for holdem at the moment # FIXME: Only do startCards value for holdem at the moment
return 0 return 0
@ -95,7 +98,7 @@ def twoStartCardString(card):
if x == y: ret = s[x] + s[y] if x == y: ret = s[x] + s[y]
elif x > y: ret = s[x] + s[y] + 's' elif x > y: ret = s[x] + s[y] + 's'
else: ret = s[y] + s[x] + 'o' else: ret = s[y] + s[x] + 'o'
# print "twoStartCardString(", card ,") = " + ret print "twoStartCardString(", card ,") = " + ret
return ret return ret
def fourStartCards(value1, suit1, value2, suit2, value3, suit3, value4, suit4): def fourStartCards(value1, suit1, value2, suit2, value3, suit3, value4, suit4):
@ -163,6 +166,266 @@ def encodeCard(cardString):
if cardString not in encodeCardList: return 0 if cardString not in encodeCardList: return 0
return encodeCardList[cardString] return encodeCardList[cardString]
def decodeRazzStartHand(idx):
decodeRazzList = {
-13:'(00)A',-12:'(00)2',-11:'(00)3',-10:'(00)4',-9:'(00)5',-8:'(00)6',-7:'(00)7',-6:'(00)8',-5:'(00)9',-4:'(00)T',
-3:'(00)J',-2:'(00)Q',-1:'(00)K',0:'xxx',
1:'(32)A',2:'(3A)2',3:'(2A)3',4:'(42)A',5:'(4A)2',6:'(2A)4',7:'(43)A',8:'(4A)3',9:'(3A)4',
10:'(43)2',11:'(42)3',12:'(32)4',13:'(52)A',14:'(5A)2',15:'(2A)5',16:'(53)A',17:'(5A)3',18:'(3A)5',19:'(53)2',
20:'(52)3',21:'(32)5',22:'(54)A',23:'(5A)4',24:'(4A)5',25:'(54)2',26:'(52)4',27:'(42)5',28:'(54)3',29:'(53)4',
30:'(43)5',31:'(62)A',32:'(6A)2',33:'(2A)6',34:'(63)A',35:'(6A)3',36:'(3A)6',37:'(63)2',38:'(62)3',39:'(32)6',
40:'(64)A',41:'(6A)4',42:'(4A)6',43:'(64)2',44:'(62)4',45:'(42)6',46:'(64)3',47:'(63)4',48:'(43)6',49:'(65)A',
50:'(6A)5',51:'(5A)6',52:'(65)2',53:'(62)5',54:'(52)6',55:'(65)3',56:'(63)5',57:'(53)6',58:'(65)4',59:'(64)5',
60:'(54)6',61:'(72)A',62:'(7A)2',63:'(2A)7',64:'(73)A',65:'(7A)3',66:'(3A)7',67:'(73)2',68:'(72)3',69:'(32)7',
70:'(74)A',71:'(7A)4',72:'(4A)7',73:'(74)2',74:'(72)4',75:'(42)7',76:'(74)3',77:'(73)4',78:'(43)7',79:'(75)A',
80:'(7A)5',81:'(5A)7',82:'(75)2',83:'(72)5',84:'(52)7',85:'(75)3',86:'(73)5',87:'(53)7',88:'(75)4',89:'(74)5',
90:'(54)7',91:'(76)A',92:'(7A)6',93:'(6A)7',94:'(76)2',95:'(72)6',96:'(62)7',97:'(76)3',98:'(73)6',99:'(63)7',
100:'(76)4',101:'(74)6',102:'(64)7',103:'(76)5',104:'(75)6',105:'(65)7',106:'(82)A',107:'(8A)2',108:'(2A)8',109:'(83)A',
110:'(8A)3',111:'(3A)8',112:'(83)2',113:'(82)3',114:'(32)8',115:'(84)A',116:'(8A)4',117:'(4A)8',118:'(84)2',119:'(82)4',
120:'(42)8',121:'(84)3',122:'(83)4',123:'(43)8',124:'(85)A',125:'(8A)5',126:'(5A)8',127:'(85)2',128:'(82)5',129:'(52)8',
130:'(85)3',131:'(83)5',132:'(53)8',133:'(85)4',134:'(84)5',135:'(54)8',136:'(86)A',137:'(8A)6',138:'(6A)8',139:'(86)2',
140:'(82)6',141:'(62)8',142:'(86)3',143:'(83)6',144:'(63)8',145:'(86)4',146:'(84)6',147:'(64)8',148:'(86)5',149:'(85)6',
150:'(65)8',151:'(87)A',152:'(8A)7',153:'(7A)8',154:'(87)2',155:'(82)7',156:'(72)8',157:'(87)3',158:'(83)7',159:'(73)8',
160:'(87)4',161:'(84)7',162:'(74)8',163:'(87)5',164:'(85)7',165:'(75)8',166:'(87)6',167:'(86)7',168:'(76)8',169:'(92)A',
170:'(9A)2',171:'(2A)9',172:'(93)A',173:'(9A)3',174:'(3A)9',175:'(93)2',176:'(92)3',177:'(32)9',178:'(94)A',179:'(9A)4',
180:'(4A)9',181:'(94)2',182:'(92)4',183:'(42)9',184:'(94)3',185:'(93)4',186:'(43)9',187:'(95)A',188:'(9A)5',189:'(5A)9',
190:'(95)2',191:'(92)5',192:'(52)9',193:'(95)3',194:'(93)5',195:'(53)9',196:'(95)4',197:'(94)5',198:'(54)9',199:'(96)A',
200:'(9A)6',201:'(6A)9',202:'(96)2',203:'(92)6',204:'(62)9',205:'(96)3',206:'(93)6',207:'(63)9',208:'(96)4',209:'(94)6',
210:'(64)9',211:'(96)5',212:'(95)6',213:'(65)9',214:'(97)A',215:'(9A)7',216:'(7A)9',217:'(97)2',218:'(92)7',219:'(72)9',
220:'(97)3',221:'(93)7',222:'(73)9',223:'(97)4',224:'(94)7',225:'(74)9',226:'(97)5',227:'(95)7',228:'(75)9',229:'(97)6',
230:'(96)7',231:'(76)9',232:'(98)A',233:'(9A)8',234:'(8A)9',235:'(98)2',236:'(92)8',237:'(82)9',238:'(98)3',239:'(93)8',
240:'(83)9',241:'(98)4',242:'(94)8',243:'(84)9',244:'(98)5',245:'(95)8',246:'(85)9',247:'(98)6',248:'(96)8',249:'(86)9',
250:'(98)7',251:'(97)8',252:'(87)9',253:'(T2)A',254:'(TA)2',255:'(2A)T',256:'(T3)A',257:'(TA)3',258:'(3A)T',259:'(T3)2',
260:'(T2)3',261:'(32)T',262:'(T4)A',263:'(TA)4',264:'(4A)T',265:'(T4)2',266:'(T2)4',267:'(42)T',268:'(T4)3',269:'(T3)4',
270:'(43)T',271:'(T5)A',272:'(TA)5',273:'(5A)T',274:'(T5)2',275:'(T2)5',276:'(52)T',277:'(T5)3',278:'(T3)5',279:'(53)T',
280:'(T5)4',281:'(T4)5',282:'(54)T',283:'(T6)A',284:'(TA)6',285:'(6A)T',286:'(T6)2',287:'(T2)6',288:'(62)T',289:'(T6)3',
290:'(T3)6',291:'(63)T',292:'(T6)4',293:'(T4)6',294:'(64)T',295:'(T6)5',296:'(T5)6',297:'(65)T',298:'(T7)A',299:'(TA)7',
300:'(7A)T',301:'(T7)2',302:'(T2)7',303:'(72)T',304:'(T7)3',305:'(T3)7',306:'(73)T',307:'(T7)4',308:'(T4)7',309:'(74)T',
310:'(T7)5',311:'(T5)7',312:'(75)T',313:'(T7)6',314:'(T6)7',315:'(76)T',316:'(T8)A',317:'(TA)8',318:'(8A)T',319:'(T8)2',
320:'(T2)8',321:'(82)T',322:'(T8)3',323:'(T3)8',324:'(83)T',325:'(T8)4',326:'(T4)8',327:'(84)T',328:'(T8)5',329:'(T5)8',
330:'(85)T',331:'(T8)6',332:'(T6)8',333:'(86)T',334:'(T8)7',335:'(T7)8',336:'(87)T',337:'(T9)A',338:'(TA)9',339:'(9A)T',
340:'(T9)2',341:'(T2)9',342:'(92)T',343:'(T9)3',344:'(T3)9',345:'(93)T',346:'(T9)4',347:'(T4)9',348:'(94)T',349:'(T9)5',
350:'(T5)9',351:'(95)T',352:'(T9)6',353:'(T6)9',354:'(96)T',355:'(T9)7',356:'(T7)9',357:'(97)T',358:'(T9)8',359:'(T8)9',
360:'(98)T',361:'(J2)A',362:'(JA)2',363:'(2A)J',364:'(J3)A',365:'(JA)3',366:'(3A)J',367:'(J3)2',368:'(J2)3',369:'(32)J',
370:'(J4)A',371:'(JA)4',372:'(4A)J',373:'(J4)2',374:'(J2)4',375:'(42)J',376:'(J4)3',377:'(J3)4',378:'(43)J',379:'(J5)A',
380:'(JA)5',381:'(5A)J',382:'(J5)2',383:'(J2)5',384:'(52)J',385:'(J5)3',386:'(J3)5',387:'(53)J',388:'(J5)4',389:'(J4)5',
390:'(54)J',391:'(J6)A',392:'(JA)6',393:'(6A)J',394:'(J6)2',395:'(J2)6',396:'(62)J',397:'(J6)3',398:'(J3)6',399:'(63)J',
400:'(J6)4',401:'(J4)6',402:'(64)J',403:'(J6)5',404:'(J5)6',405:'(65)J',406:'(J7)A',407:'(JA)7',408:'(7A)J',409:'(J7)2',
410:'(J2)7',411:'(72)J',412:'(J7)3',413:'(J3)7',414:'(73)J',415:'(J7)4',416:'(J4)7',417:'(74)J',418:'(J7)5',419:'(J5)7',
420:'(75)J',421:'(J7)6',422:'(J6)7',423:'(76)J',424:'(J8)A',425:'(JA)8',426:'(8A)J',427:'(J8)2',428:'(J2)8',429:'(82)J',
430:'(J8)3',431:'(J3)8',432:'(83)J',433:'(J8)4',434:'(J4)8',435:'(84)J',436:'(J8)5',437:'(J5)8',438:'(85)J',439:'(J8)6',
440:'(J6)8',441:'(86)J',442:'(J8)7',443:'(J7)8',444:'(87)J',445:'(J9)A',446:'(JA)9',447:'(9A)J',448:'(J9)2',449:'(J2)9',
450:'(92)J',451:'(J9)3',452:'(J3)9',453:'(93)J',454:'(J9)4',455:'(J4)9',456:'(94)J',457:'(J9)5',458:'(J5)9',459:'(95)J',
460:'(J9)6',461:'(J6)9',462:'(96)J',463:'(J9)7',464:'(J7)9',465:'(97)J',466:'(J9)8',467:'(J8)9',468:'(98)J',469:'(JT)A',
470:'(JA)T',471:'(TA)J',472:'(JT)2',473:'(J2)T',474:'(T2)J',475:'(JT)3',476:'(J3)T',477:'(T3)J',478:'(JT)4',479:'(J4)T',
480:'(T4)J',481:'(JT)5',482:'(J5)T',483:'(T5)J',484:'(JT)6',485:'(J6)T',486:'(T6)J',487:'(JT)7',488:'(J7)T',489:'(T7)J',
490:'(JT)8',491:'(J8)T',492:'(T8)J',493:'(JT)9',494:'(J9)T',495:'(T9)J',496:'(Q2)A',497:'(QA)2',498:'(2A)Q',499:'(Q3)A',
500:'(QA)3',501:'(3A)Q',502:'(Q3)2',503:'(Q2)3',504:'(32)Q',505:'(Q4)A',506:'(QA)4',507:'(4A)Q',508:'(Q4)2',509:'(Q2)4',
510:'(42)Q',511:'(Q4)3',512:'(Q3)4',513:'(43)Q',514:'(Q5)A',515:'(QA)5',516:'(5A)Q',517:'(Q5)2',518:'(Q2)5',519:'(52)Q',
520:'(Q5)3',521:'(Q3)5',522:'(53)Q',523:'(Q5)4',524:'(Q4)5',525:'(54)Q',526:'(Q6)A',527:'(QA)6',528:'(6A)Q',529:'(Q6)2',
530:'(Q2)6',531:'(62)Q',532:'(Q6)3',533:'(Q3)6',534:'(63)Q',535:'(Q6)4',536:'(Q4)6',537:'(64)Q',538:'(Q6)5',539:'(Q5)6',
540:'(65)Q',541:'(Q7)A',542:'(QA)7',543:'(7A)Q',544:'(Q7)2',545:'(Q2)7',546:'(72)Q',547:'(Q7)3',548:'(Q3)7',549:'(73)Q',
550:'(Q7)4',551:'(Q4)7',552:'(74)Q',553:'(Q7)5',554:'(Q5)7',555:'(75)Q',556:'(Q7)6',557:'(Q6)7',558:'(76)Q',559:'(Q8)A',
560:'(QA)8',561:'(8A)Q',562:'(Q8)2',563:'(Q2)8',564:'(82)Q',565:'(Q8)3',566:'(Q3)8',567:'(83)Q',568:'(Q8)4',569:'(Q4)8',
570:'(84)Q',571:'(Q8)5',572:'(Q5)8',573:'(85)Q',574:'(Q8)6',575:'(Q6)8',576:'(86)Q',577:'(Q8)7',578:'(Q7)8',579:'(87)Q',
580:'(Q9)A',581:'(QA)9',582:'(9A)Q',583:'(Q9)2',584:'(Q2)9',585:'(92)Q',586:'(Q9)3',587:'(Q3)9',588:'(93)Q',589:'(Q9)4',
590:'(Q4)9',591:'(94)Q',592:'(Q9)5',593:'(Q5)9',594:'(95)Q',595:'(Q9)6',596:'(Q6)9',597:'(96)Q',598:'(Q9)7',599:'(Q7)9',
600:'(97)Q',601:'(Q9)8',602:'(Q8)9',603:'(98)Q',604:'(QT)A',605:'(QA)T',606:'(TA)Q',607:'(QT)2',608:'(Q2)T',609:'(T2)Q',
610:'(QT)3',611:'(Q3)T',612:'(T3)Q',613:'(QT)4',614:'(Q4)T',615:'(T4)Q',616:'(QT)5',617:'(Q5)T',618:'(T5)Q',619:'(QT)6',
620:'(Q6)T',621:'(T6)Q',622:'(QT)7',623:'(Q7)T',624:'(T7)Q',625:'(QT)8',626:'(Q8)T',627:'(T8)Q',628:'(QT)9',629:'(Q9)T',
630:'(T9)Q',631:'(QJ)A',632:'(QA)J',633:'(JA)Q',634:'(QJ)2',635:'(Q2)J',636:'(J2)Q',637:'(QJ)3',638:'(Q3)J',639:'(J3)Q',
640:'(QJ)4',641:'(Q4)J',642:'(J4)Q',643:'(QJ)5',644:'(Q5)J',645:'(J5)Q',646:'(QJ)6',647:'(Q6)J',648:'(J6)Q',649:'(QJ)7',
650:'(Q7)J',651:'(J7)Q',652:'(QJ)8',653:'(Q8)J',654:'(J8)Q',655:'(QJ)9',656:'(Q9)J',657:'(J9)Q',658:'(QJ)T',659:'(QT)J',
660:'(JT)Q',661:'(K2)A',662:'(KA)2',663:'(2A)K',664:'(K3)A',665:'(KA)3',666:'(3A)K',667:'(K3)2',668:'(K2)3',669:'(32)K',
670:'(K4)A',671:'(KA)4',672:'(4A)K',673:'(K4)2',674:'(K2)4',675:'(42)K',676:'(K4)3',677:'(K3)4',678:'(43)K',679:'(K5)A',
680:'(KA)5',681:'(5A)K',682:'(K5)2',683:'(K2)5',684:'(52)K',685:'(K5)3',686:'(K3)5',687:'(53)K',688:'(K5)4',689:'(K4)5',
690:'(54)K',691:'(K6)A',692:'(KA)6',693:'(6A)K',694:'(K6)2',695:'(K2)6',696:'(62)K',697:'(K6)3',698:'(K3)6',699:'(63)K',
700:'(K6)4',701:'(K4)6',702:'(64)K',703:'(K6)5',704:'(K5)6',705:'(65)K',706:'(K7)A',707:'(KA)7',708:'(7A)K',709:'(K7)2',
710:'(K2)7',711:'(72)K',712:'(K7)3',713:'(K3)7',714:'(73)K',715:'(K7)4',716:'(K4)7',717:'(74)K',718:'(K7)5',719:'(K5)7',
720:'(75)K',721:'(K7)6',722:'(K6)7',723:'(76)K',724:'(K8)A',725:'(KA)8',726:'(8A)K',727:'(K8)2',728:'(K2)8',729:'(82)K',
730:'(K8)3',731:'(K3)8',732:'(83)K',733:'(K8)4',734:'(K4)8',735:'(84)K',736:'(K8)5',737:'(K5)8',738:'(85)K',739:'(K8)6',
740:'(K6)8',741:'(86)K',742:'(K8)7',743:'(K7)8',744:'(87)K',745:'(K9)A',746:'(KA)9',747:'(9A)K',748:'(K9)2',749:'(K2)9',
750:'(92)K',751:'(K9)3',752:'(K3)9',753:'(93)K',754:'(K9)4',755:'(K4)9',756:'(94)K',757:'(K9)5',758:'(K5)9',759:'(95)K',
760:'(K9)6',761:'(K6)9',762:'(96)K',763:'(K9)7',764:'(K7)9',765:'(97)K',766:'(K9)8',767:'(K8)9',768:'(98)K',769:'(KT)A',
770:'(KA)T',771:'(TA)K',772:'(KT)2',773:'(K2)T',774:'(T2)K',775:'(KT)3',776:'(K3)T',777:'(T3)K',778:'(KT)4',779:'(K4)T',
780:'(T4)K',781:'(KT)5',782:'(K5)T',783:'(T5)K',784:'(KT)6',785:'(K6)T',786:'(T6)K',787:'(KT)7',788:'(K7)T',789:'(T7)K',
790:'(KT)8',791:'(K8)T',792:'(T8)K',793:'(KT)9',794:'(K9)T',795:'(T9)K',796:'(KJ)A',797:'(KA)J',798:'(JA)K',799:'(KJ)2',
800:'(K2)J',801:'(J2)K',802:'(KJ)3',803:'(K3)J',804:'(J3)K',805:'(KJ)4',806:'(K4)J',807:'(J4)K',808:'(KJ)5',809:'(K5)J',
810:'(J5)K',811:'(KJ)6',812:'(K6)J',813:'(J6)K',814:'(KJ)7',815:'(K7)J',816:'(J7)K',817:'(KJ)8',818:'(K8)J',819:'(J8)K',
820:'(KJ)9',821:'(K9)J',822:'(J9)K',823:'(KJ)T',824:'(KT)J',825:'(JT)K',826:'(KQ)A',827:'(KA)Q',828:'(QA)K',829:'(KQ)2',
830:'(K2)Q',831:'(Q2)K',832:'(KQ)3',833:'(K3)Q',834:'(Q3)K',835:'(KQ)4',836:'(K4)Q',837:'(Q4)K',838:'(KQ)5',839:'(K5)Q',
840:'(Q5)K',841:'(KQ)6',842:'(K6)Q',843:'(Q6)K',844:'(KQ)7',845:'(K7)Q',846:'(Q7)K',847:'(KQ)8',848:'(K8)Q',849:'(Q8)K',
850:'(KQ)9',851:'(K9)Q',852:'(Q9)K',853:'(KQ)T',854:'(KT)Q',855:'(QT)K',856:'(KQ)J',857:'(KJ)Q',858:'(QJ)K',859:'(2A)A',
860:'(22)A',861:'(AA)2',862:'(2A)2',863:'(3A)A',864:'(33)A',865:'(AA)3',866:'(3A)3',867:'(32)2',868:'(33)2',869:'(22)3',
870:'(32)3',871:'(4A)A',872:'(44)A',873:'(AA)4',874:'(4A)4',875:'(42)2',876:'(44)2',877:'(22)4',878:'(42)4',879:'(43)3',
880:'(44)3',881:'(33)4',882:'(43)4',883:'(5A)A',884:'(55)A',885:'(AA)5',886:'(5A)5',887:'(52)2',888:'(55)2',889:'(22)5',
890:'(52)5',891:'(53)3',892:'(55)3',893:'(33)5',894:'(53)5',895:'(54)4',896:'(55)4',897:'(44)5',898:'(54)5',899:'(6A)A',
900:'(66)A',901:'(AA)6',902:'(6A)6',903:'(62)2',904:'(66)2',905:'(22)6',906:'(62)6',907:'(63)3',908:'(66)3',909:'(33)6',
910:'(63)6',911:'(64)4',912:'(66)4',913:'(44)6',914:'(64)6',915:'(65)5',916:'(66)5',917:'(55)6',918:'(65)6',919:'(7A)A',
920:'(77)A',921:'(AA)7',922:'(7A)7',923:'(72)2',924:'(77)2',925:'(22)7',926:'(72)7',927:'(73)3',928:'(77)3',929:'(33)7',
930:'(73)7',931:'(74)4',932:'(77)4',933:'(44)7',934:'(74)7',935:'(75)5',936:'(77)5',937:'(55)7',938:'(75)7',939:'(76)6',
940:'(77)6',941:'(66)7',942:'(76)7',943:'(8A)A',944:'(88)A',945:'(AA)8',946:'(8A)8',947:'(82)2',948:'(88)2',949:'(22)8',
950:'(82)8',951:'(83)3',952:'(88)3',953:'(33)8',954:'(83)8',955:'(84)4',956:'(88)4',957:'(44)8',958:'(84)8',959:'(85)5',
960:'(88)5',961:'(55)8',962:'(85)8',963:'(86)6',964:'(88)6',965:'(66)8',966:'(86)8',967:'(87)7',968:'(88)7',969:'(77)8',
970:'(87)8',971:'(9A)A',972:'(99)A',973:'(AA)9',974:'(9A)9',975:'(92)2',976:'(99)2',977:'(22)9',978:'(92)9',979:'(93)3',
980:'(99)3',981:'(33)9',982:'(93)9',983:'(94)4',984:'(99)4',985:'(44)9',986:'(94)9',987:'(95)5',988:'(99)5',989:'(55)9',
990:'(95)9',991:'(96)6',992:'(99)6',993:'(66)9',994:'(96)9',995:'(97)7',996:'(99)7',997:'(77)9',998:'(97)9',999:'(98)8',
1000:'(99)8',1001:'(88)9',1002:'(98)9',1003:'(TA)A',1004:'(TT)A',1005:'(AA)T',1006:'(TA)T',1007:'(T2)2',1008:'(TT)2',1009:'(22)T',
1010:'(T2)T',1011:'(T3)3',1012:'(TT)3',1013:'(33)T',1014:'(T3)T',1015:'(T4)4',1016:'(TT)4',1017:'(44)T',1018:'(T4)T',1019:'(T5)5',
1020:'(TT)5',1021:'(55)T',1022:'(T5)T',1023:'(T6)6',1024:'(TT)6',1025:'(66)T',1026:'(T6)T',1027:'(T7)7',1028:'(TT)7',1029:'(77)T',
1030:'(T7)T',1031:'(T8)8',1032:'(TT)8',1033:'(88)T',1034:'(T8)T',1035:'(T9)9',1036:'(TT)9',1037:'(99)T',1038:'(T9)T',1039:'(JA)A',
1040:'(JJ)A',1041:'(AA)J',1042:'(JA)J',1043:'(J2)2',1044:'(JJ)2',1045:'(22)J',1046:'(J2)J',1047:'(J3)3',1048:'(JJ)3',1049:'(33)J',
1050:'(J3)J',1051:'(J4)4',1052:'(JJ)4',1053:'(44)J',1054:'(J4)J',1055:'(J5)5',1056:'(JJ)5',1057:'(55)J',1058:'(J5)J',1059:'(J6)6',
1060:'(JJ)6',1061:'(66)J',1062:'(J6)J',1063:'(J7)7',1064:'(JJ)7',1065:'(77)J',1066:'(J7)J',1067:'(J8)8',1068:'(JJ)8',1069:'(88)J',
1070:'(J8)J',1071:'(J9)9',1072:'(JJ)9',1073:'(99)J',1074:'(J9)J',1075:'(JT)T',1076:'(JJ)T',1077:'(TT)J',1078:'(JT)J',1079:'(QA)A',
1080:'(QQ)A',1081:'(AA)Q',1082:'(QA)Q',1083:'(Q2)2',1084:'(QQ)2',1085:'(22)Q',1086:'(Q2)Q',1087:'(Q3)3',1088:'(QQ)3',1089:'(33)Q',
1090:'(Q3)Q',1091:'(Q4)4',1092:'(QQ)4',1093:'(44)Q',1094:'(Q4)Q',1095:'(Q5)5',1096:'(QQ)5',1097:'(55)Q',1098:'(Q5)Q',1099:'(Q6)6',
1100:'(QQ)6',1101:'(66)Q',1102:'(Q6)Q',1103:'(Q7)7',1104:'(QQ)7',1105:'(77)Q',1106:'(Q7)Q',1107:'(Q8)8',1108:'(QQ)8',1109:'(88)Q',
1110:'(Q8)Q',1111:'(Q9)9',1112:'(QQ)9',1113:'(99)Q',1114:'(Q9)Q',1115:'(QT)T',1116:'(QQ)T',1117:'(TT)Q',1118:'(QT)Q',1119:'(QJ)J',
1120:'(QQ)J',1121:'(JJ)Q',1122:'(QJ)Q',1123:'(KA)A',1124:'(KK)A',1125:'(AA)K',1126:'(KA)K',1127:'(K2)2',1128:'(KK)2',1129:'(22)K',
1130:'(K2)K',1131:'(K3)3',1132:'(KK)3',1133:'(33)K',1134:'(K3)K',1135:'(K4)4',1136:'(KK)4',1137:'(44)K',1138:'(K4)K',1139:'(K5)5',
1140:'(KK)5',1141:'(55)K',1142:'(K5)K',1143:'(K6)6',1144:'(KK)6',1145:'(66)K',1146:'(K6)K',1147:'(K7)7',1148:'(KK)7',1149:'(77)K',
1150:'(K7)K',1151:'(K8)8',1152:'(KK)8',1153:'(88)K',1154:'(K8)K',1155:'(K9)9',1156:'(KK)9',1157:'(99)K',1158:'(K9)K',1159:'(KT)T',
1160:'(KK)T',1161:'(TT)K',1162:'(KT)K',1163:'(KJ)J',1164:'(KK)J',1165:'(JJ)K',1166:'(KJ)K',1167:'(KQ)Q',1168:'(KK)Q',1169:'(QQ)K',
1170:'(KQ)K',1171:'(AA)A',1172:'(22)2',1173:'(33)3',1174:'(44)4',1175:'(55)5',1176:'(66)6',1177:'(77)7',1178:'(88)8',1179:'(99)9',
1180:'(TT)T',1181:'(JJ)J',1182:'(QQ)Q',1183:'(KK)K',
}
return decodeRazzList[idx]
def encodeRazzStartHand(cards):
"""Take Razz starting hand and return an integer index for storing in db"""
startHand = ""
if card_map_low[cards[0][0]] > card_map_low[cards[1][0]]:
startHand = "(%s%s)%s" %(cards[0][0], cards[1][0], cards[2][0])
else:
startHand = "(%s%s)%s" %(cards[1][0], cards[0][0], cards[2][0])
#print "DEBUG: startHand: %s" % startHand
encodeRazzList = {
'(00)A':-13,'(00)2':-12,'(00)3':-11,'(00)4':-10,'(00)5':-9,'(00)6':-8,'(00)7':-7,'(00)8':-6,'(00)9':-5,'(00)T':-4,
'(00)J':-3,'(00)Q':-2,'(00)K':-1,
'(32)A':1,'(3A)2':2,'(2A)3':3,'(42)A':4,'(4A)2':5,'(2A)4':6,'(43)A':7,'(4A)3':8,'(3A)4':9,
'(43)2':10,'(42)3':11,'(32)4':12,'(52)A':13,'(5A)2':14,'(2A)5':15,'(53)A':16,'(5A)3':17,'(3A)5':18,'(53)2':19,
'(52)3':20,'(32)5':21,'(54)A':22,'(5A)4':23,'(4A)5':24,'(54)2':25,'(52)4':26,'(42)5':27,'(54)3':28,'(53)4':29,
'(43)5':30,'(62)A':31,'(6A)2':32,'(2A)6':33,'(63)A':34,'(6A)3':35,'(3A)6':36,'(63)2':37,'(62)3':38,'(32)6':39,
'(64)A':40,'(6A)4':41,'(4A)6':42,'(64)2':43,'(62)4':44,'(42)6':45,'(64)3':46,'(63)4':47,'(43)6':48,'(65)A':49,
'(6A)5':50,'(5A)6':51,'(65)2':52,'(62)5':53,'(52)6':54,'(65)3':55,'(63)5':56,'(53)6':57,'(65)4':58,'(64)5':59,
'(54)6':60,'(72)A':61,'(7A)2':62,'(2A)7':63,'(73)A':64,'(7A)3':65,'(3A)7':66,'(73)2':67,'(72)3':68,'(32)7':69,
'(74)A':70,'(7A)4':71,'(4A)7':72,'(74)2':73,'(72)4':74,'(42)7':75,'(74)3':76,'(73)4':77,'(43)7':78,'(75)A':79,
'(7A)5':80,'(5A)7':81,'(75)2':82,'(72)5':83,'(52)7':84,'(75)3':85,'(73)5':86,'(53)7':87,'(75)4':88,'(74)5':89,
'(54)7':90,'(76)A':91,'(7A)6':92,'(6A)7':93,'(76)2':94,'(72)6':95,'(62)7':96,'(76)3':97,'(73)6':98,'(63)7':99,
'(76)4':100,'(74)6':101,'(64)7':102,'(76)5':103,'(75)6':104,'(65)7':105,'(82)A':106,'(8A)2':107,'(2A)8':108,'(83)A':109,
'(8A)3':110,'(3A)8':111,'(83)2':112,'(82)3':113,'(32)8':114,'(84)A':115,'(8A)4':116,'(4A)8':117,'(84)2':118,'(82)4':119,
'(42)8':120,'(84)3':121,'(83)4':122,'(43)8':123,'(85)A':124,'(8A)5':125,'(5A)8':126,'(85)2':127,'(82)5':128,'(52)8':129,
'(85)3':130,'(83)5':131,'(53)8':132,'(85)4':133,'(84)5':134,'(54)8':135,'(86)A':136,'(8A)6':137,'(6A)8':138,'(86)2':139,
'(82)6':140,'(62)8':141,'(86)3':142,'(83)6':143,'(63)8':144,'(86)4':145,'(84)6':146,'(64)8':147,'(86)5':148,'(85)6':149,
'(65)8':150,'(87)A':151,'(8A)7':152,'(7A)8':153,'(87)2':154,'(82)7':155,'(72)8':156,'(87)3':157,'(83)7':158,'(73)8':159,
'(87)4':160,'(84)7':161,'(74)8':162,'(87)5':163,'(85)7':164,'(75)8':165,'(87)6':166,'(86)7':167,'(76)8':168,'(92)A':169,
'(9A)2':170,'(2A)9':171,'(93)A':172,'(9A)3':173,'(3A)9':174,'(93)2':175,'(92)3':176,'(32)9':177,'(94)A':178,'(9A)4':179,
'(4A)9':180,'(94)2':181,'(92)4':182,'(42)9':183,'(94)3':184,'(93)4':185,'(43)9':186,'(95)A':187,'(9A)5':188,'(5A)9':189,
'(95)2':190,'(92)5':191,'(52)9':192,'(95)3':193,'(93)5':194,'(53)9':195,'(95)4':196,'(94)5':197,'(54)9':198,'(96)A':199,
'(9A)6':200,'(6A)9':201,'(96)2':202,'(92)6':203,'(62)9':204,'(96)3':205,'(93)6':206,'(63)9':207,'(96)4':208,'(94)6':209,
'(64)9':210,'(96)5':211,'(95)6':212,'(65)9':213,'(97)A':214,'(9A)7':215,'(7A)9':216,'(97)2':217,'(92)7':218,'(72)9':219,
'(97)3':220,'(93)7':221,'(73)9':222,'(97)4':223,'(94)7':224,'(74)9':225,'(97)5':226,'(95)7':227,'(75)9':228,'(97)6':229,
'(96)7':230,'(76)9':231,'(98)A':232,'(9A)8':233,'(8A)9':234,'(98)2':235,'(92)8':236,'(82)9':237,'(98)3':238,'(93)8':239,
'(83)9':240,'(98)4':241,'(94)8':242,'(84)9':243,'(98)5':244,'(95)8':245,'(85)9':246,'(98)6':247,'(96)8':248,'(86)9':249,
'(98)7':250,'(97)8':251,'(87)9':252,'(T2)A':253,'(TA)2':254,'(2A)T':255,'(T3)A':256,'(TA)3':257,'(3A)T':258,'(T3)2':259,
'(T2)3':260,'(32)T':261,'(T4)A':262,'(TA)4':263,'(4A)T':264,'(T4)2':265,'(T2)4':266,'(42)T':267,'(T4)3':268,'(T3)4':269,
'(43)T':270,'(T5)A':271,'(TA)5':272,'(5A)T':273,'(T5)2':274,'(T2)5':275,'(52)T':276,'(T5)3':277,'(T3)5':278,'(53)T':279,
'(T5)4':280,'(T4)5':281,'(54)T':282,'(T6)A':283,'(TA)6':284,'(6A)T':285,'(T6)2':286,'(T2)6':287,'(62)T':288,'(T6)3':289,
'(T3)6':290,'(63)T':291,'(T6)4':292,'(T4)6':293,'(64)T':294,'(T6)5':295,'(T5)6':296,'(65)T':297,'(T7)A':298,'(TA)7':299,
'(7A)T':300,'(T7)2':301,'(T2)7':302,'(72)T':303,'(T7)3':304,'(T3)7':305,'(73)T':306,'(T7)4':307,'(T4)7':308,'(74)T':309,
'(T7)5':310,'(T5)7':311,'(75)T':312,'(T7)6':313,'(T6)7':314,'(76)T':315,'(T8)A':316,'(TA)8':317,'(8A)T':318,'(T8)2':319,
'(T2)8':320,'(82)T':321,'(T8)3':322,'(T3)8':323,'(83)T':324,'(T8)4':325,'(T4)8':326,'(84)T':327,'(T8)5':328,'(T5)8':329,
'(85)T':330,'(T8)6':331,'(T6)8':332,'(86)T':333,'(T8)7':334,'(T7)8':335,'(87)T':336,'(T9)A':337,'(TA)9':338,'(9A)T':339,
'(T9)2':340,'(T2)9':341,'(92)T':342,'(T9)3':343,'(T3)9':344,'(93)T':345,'(T9)4':346,'(T4)9':347,'(94)T':348,'(T9)5':349,
'(T5)9':350,'(95)T':351,'(T9)6':352,'(T6)9':353,'(96)T':354,'(T9)7':355,'(T7)9':356,'(97)T':357,'(T9)8':358,'(T8)9':359,
'(98)T':360,'(J2)A':361,'(JA)2':362,'(2A)J':363,'(J3)A':364,'(JA)3':365,'(3A)J':366,'(J3)2':367,'(J2)3':368,'(32)J':369,
'(J4)A':370,'(JA)4':371,'(4A)J':372,'(J4)2':373,'(J2)4':374,'(42)J':375,'(J4)3':376,'(J3)4':377,'(43)J':378,'(J5)A':379,
'(JA)5':380,'(5A)J':381,'(J5)2':382,'(J2)5':383,'(52)J':384,'(J5)3':385,'(J3)5':386,'(53)J':387,'(J5)4':388,'(J4)5':389,
'(54)J':390,'(J6)A':391,'(JA)6':392,'(6A)J':393,'(J6)2':394,'(J2)6':395,'(62)J':396,'(J6)3':397,'(J3)6':398,'(63)J':399,
'(J6)4':400,'(J4)6':401,'(64)J':402,'(J6)5':403,'(J5)6':404,'(65)J':405,'(J7)A':406,'(JA)7':407,'(7A)J':408,'(J7)2':409,
'(J2)7':410,'(72)J':411,'(J7)3':412,'(J3)7':413,'(73)J':414,'(J7)4':415,'(J4)7':416,'(74)J':417,'(J7)5':418,'(J5)7':419,
'(75)J':420,'(J7)6':421,'(J6)7':422,'(76)J':423,'(J8)A':424,'(JA)8':425,'(8A)J':426,'(J8)2':427,'(J2)8':428,'(82)J':429,
'(J8)3':430,'(J3)8':431,'(83)J':432,'(J8)4':433,'(J4)8':434,'(84)J':435,'(J8)5':436,'(J5)8':437,'(85)J':438,'(J8)6':439,
'(J6)8':440,'(86)J':441,'(J8)7':442,'(J7)8':443,'(87)J':444,'(J9)A':445,'(JA)9':446,'(9A)J':447,'(J9)2':448,'(J2)9':449,
'(92)J':450,'(J9)3':451,'(J3)9':452,'(93)J':453,'(J9)4':454,'(J4)9':455,'(94)J':456,'(J9)5':457,'(J5)9':458,'(95)J':459,
'(J9)6':460,'(J6)9':461,'(96)J':462,'(J9)7':463,'(J7)9':464,'(97)J':465,'(J9)8':466,'(J8)9':467,'(98)J':468,'(JT)A':469,
'(JA)T':470,'(TA)J':471,'(JT)2':472,'(J2)T':473,'(T2)J':474,'(JT)3':475,'(J3)T':476,'(T3)J':477,'(JT)4':478,'(J4)T':479,
'(T4)J':480,'(JT)5':481,'(J5)T':482,'(T5)J':483,'(JT)6':484,'(J6)T':485,'(T6)J':486,'(JT)7':487,'(J7)T':488,'(T7)J':489,
'(JT)8':490,'(J8)T':491,'(T8)J':492,'(JT)9':493,'(J9)T':494,'(T9)J':495,'(Q2)A':496,'(QA)2':497,'(2A)Q':498,'(Q3)A':499,
'(QA)3':500,'(3A)Q':501,'(Q3)2':502,'(Q2)3':503,'(32)Q':504,'(Q4)A':505,'(QA)4':506,'(4A)Q':507,'(Q4)2':508,'(Q2)4':509,
'(42)Q':510,'(Q4)3':511,'(Q3)4':512,'(43)Q':513,'(Q5)A':514,'(QA)5':515,'(5A)Q':516,'(Q5)2':517,'(Q2)5':518,'(52)Q':519,
'(Q5)3':520,'(Q3)5':521,'(53)Q':522,'(Q5)4':523,'(Q4)5':524,'(54)Q':525,'(Q6)A':526,'(QA)6':527,'(6A)Q':528,'(Q6)2':529,
'(Q2)6':530,'(62)Q':531,'(Q6)3':532,'(Q3)6':533,'(63)Q':534,'(Q6)4':535,'(Q4)6':536,'(64)Q':537,'(Q6)5':538,'(Q5)6':539,
'(65)Q':540,'(Q7)A':541,'(QA)7':542,'(7A)Q':543,'(Q7)2':544,'(Q2)7':545,'(72)Q':546,'(Q7)3':547,'(Q3)7':548,'(73)Q':549,
'(Q7)4':550,'(Q4)7':551,'(74)Q':552,'(Q7)5':553,'(Q5)7':554,'(75)Q':555,'(Q7)6':556,'(Q6)7':557,'(76)Q':558,'(Q8)A':559,
'(QA)8':560,'(8A)Q':561,'(Q8)2':562,'(Q2)8':563,'(82)Q':564,'(Q8)3':565,'(Q3)8':566,'(83)Q':567,'(Q8)4':568,'(Q4)8':569,
'(84)Q':570,'(Q8)5':571,'(Q5)8':572,'(85)Q':573,'(Q8)6':574,'(Q6)8':575,'(86)Q':576,'(Q8)7':577,'(Q7)8':578,'(87)Q':579,
'(Q9)A':580,'(QA)9':581,'(9A)Q':582,'(Q9)2':583,'(Q2)9':584,'(92)Q':585,'(Q9)3':586,'(Q3)9':587,'(93)Q':588,'(Q9)4':589,
'(Q4)9':590,'(94)Q':591,'(Q9)5':592,'(Q5)9':593,'(95)Q':594,'(Q9)6':595,'(Q6)9':596,'(96)Q':597,'(Q9)7':598,'(Q7)9':599,
'(97)Q':600,'(Q9)8':601,'(Q8)9':602,'(98)Q':603,'(QT)A':604,'(QA)T':605,'(TA)Q':606,'(QT)2':607,'(Q2)T':608,'(T2)Q':609,
'(QT)3':610,'(Q3)T':611,'(T3)Q':612,'(QT)4':613,'(Q4)T':614,'(T4)Q':615,'(QT)5':616,'(Q5)T':617,'(T5)Q':618,'(QT)6':619,
'(Q6)T':620,'(T6)Q':621,'(QT)7':622,'(Q7)T':623,'(T7)Q':624,'(QT)8':625,'(Q8)T':626,'(T8)Q':627,'(QT)9':628,'(Q9)T':629,
'(T9)Q':630,'(QJ)A':631,'(QA)J':632,'(JA)Q':633,'(QJ)2':634,'(Q2)J':635,'(J2)Q':636,'(QJ)3':637,'(Q3)J':638,'(J3)Q':639,
'(QJ)4':640,'(Q4)J':641,'(J4)Q':642,'(QJ)5':643,'(Q5)J':644,'(J5)Q':645,'(QJ)6':646,'(Q6)J':647,'(J6)Q':648,'(QJ)7':649,
'(Q7)J':650,'(J7)Q':651,'(QJ)8':652,'(Q8)J':653,'(J8)Q':654,'(QJ)9':655,'(Q9)J':656,'(J9)Q':657,'(QJ)T':658,'(QT)J':659,
'(JT)Q':660,'(K2)A':661,'(KA)2':662,'(2A)K':663,'(K3)A':664,'(KA)3':665,'(3A)K':666,'(K3)2':667,'(K2)3':668,'(32)K':669,
'(K4)A':670,'(KA)4':671,'(4A)K':672,'(K4)2':673,'(K2)4':674,'(42)K':675,'(K4)3':676,'(K3)4':677,'(43)K':678,'(K5)A':679,
'(KA)5':680,'(5A)K':681,'(K5)2':682,'(K2)5':683,'(52)K':684,'(K5)3':685,'(K3)5':686,'(53)K':687,'(K5)4':688,'(K4)5':689,
'(54)K':690,'(K6)A':691,'(KA)6':692,'(6A)K':693,'(K6)2':694,'(K2)6':695,'(62)K':696,'(K6)3':697,'(K3)6':698,'(63)K':699,
'(K6)4':700,'(K4)6':701,'(64)K':702,'(K6)5':703,'(K5)6':704,'(65)K':705,'(K7)A':706,'(KA)7':707,'(7A)K':708,'(K7)2':709,
'(K2)7':710,'(72)K':711,'(K7)3':712,'(K3)7':713,'(73)K':714,'(K7)4':715,'(K4)7':716,'(74)K':717,'(K7)5':718,'(K5)7':719,
'(75)K':720,'(K7)6':721,'(K6)7':722,'(76)K':723,'(K8)A':724,'(KA)8':725,'(8A)K':726,'(K8)2':727,'(K2)8':728,'(82)K':729,
'(K8)3':730,'(K3)8':731,'(83)K':732,'(K8)4':733,'(K4)8':734,'(84)K':735,'(K8)5':736,'(K5)8':737,'(85)K':738,'(K8)6':739,
'(K6)8':740,'(86)K':741,'(K8)7':742,'(K7)8':743,'(87)K':744,'(K9)A':745,'(KA)9':746,'(9A)K':747,'(K9)2':748,'(K2)9':749,
'(92)K':750,'(K9)3':751,'(K3)9':752,'(93)K':753,'(K9)4':754,'(K4)9':755,'(94)K':756,'(K9)5':757,'(K5)9':758,'(95)K':759,
'(K9)6':760,'(K6)9':761,'(96)K':762,'(K9)7':763,'(K7)9':764,'(97)K':765,'(K9)8':766,'(K8)9':767,'(98)K':768,'(KT)A':769,
'(KA)T':770,'(TA)K':771,'(KT)2':772,'(K2)T':773,'(T2)K':774,'(KT)3':775,'(K3)T':776,'(T3)K':777,'(KT)4':778,'(K4)T':779,
'(T4)K':780,'(KT)5':781,'(K5)T':782,'(T5)K':783,'(KT)6':784,'(K6)T':785,'(T6)K':786,'(KT)7':787,'(K7)T':788,'(T7)K':789,
'(KT)8':790,'(K8)T':791,'(T8)K':792,'(KT)9':793,'(K9)T':794,'(T9)K':795,'(KJ)A':796,'(KA)J':797,'(JA)K':798,'(KJ)2':799,
'(K2)J':800,'(J2)K':801,'(KJ)3':802,'(K3)J':803,'(J3)K':804,'(KJ)4':805,'(K4)J':806,'(J4)K':807,'(KJ)5':808,'(K5)J':809,
'(J5)K':810,'(KJ)6':811,'(K6)J':812,'(J6)K':813,'(KJ)7':814,'(K7)J':815,'(J7)K':816,'(KJ)8':817,'(K8)J':818,'(J8)K':819,
'(KJ)9':820,'(K9)J':821,'(J9)K':822,'(KJ)T':823,'(KT)J':824,'(JT)K':825,'(KQ)A':826,'(KA)Q':827,'(QA)K':828,'(KQ)2':829,
'(K2)Q':830,'(Q2)K':831,'(KQ)3':832,'(K3)Q':833,'(Q3)K':834,'(KQ)4':835,'(K4)Q':836,'(Q4)K':837,'(KQ)5':838,'(K5)Q':839,
'(Q5)K':840,'(KQ)6':841,'(K6)Q':842,'(Q6)K':843,'(KQ)7':844,'(K7)Q':845,'(Q7)K':846,'(KQ)8':847,'(K8)Q':848,'(Q8)K':849,
'(KQ)9':850,'(K9)Q':851,'(Q9)K':852,'(KQ)T':853,'(KT)Q':854,'(QT)K':855,'(KQ)J':856,'(KJ)Q':857,'(QJ)K':858,'(2A)A':859,
'(22)A':860,'(AA)2':861,'(2A)2':862,'(3A)A':863,'(33)A':864,'(AA)3':865,'(3A)3':866,'(32)2':867,'(33)2':868,'(22)3':869,
'(32)3':870,'(4A)A':871,'(44)A':872,'(AA)4':873,'(4A)4':874,'(42)2':875,'(44)2':876,'(22)4':877,'(42)4':878,'(43)3':879,
'(44)3':880,'(33)4':881,'(43)4':882,'(5A)A':883,'(55)A':884,'(AA)5':885,'(5A)5':886,'(52)2':887,'(55)2':888,'(22)5':889,
'(52)5':890,'(53)3':891,'(55)3':892,'(33)5':893,'(53)5':894,'(54)4':895,'(55)4':896,'(44)5':897,'(54)5':898,'(6A)A':899,
'(66)A':900,'(AA)6':901,'(6A)6':902,'(62)2':903,'(66)2':904,'(22)6':905,'(62)6':906,'(63)3':907,'(66)3':908,'(33)6':909,
'(63)6':910,'(64)4':911,'(66)4':912,'(44)6':913,'(64)6':914,'(65)5':915,'(66)5':916,'(55)6':917,'(65)6':918,'(7A)A':919,
'(77)A':920,'(AA)7':921,'(7A)7':922,'(72)2':923,'(77)2':924,'(22)7':925,'(72)7':926,'(73)3':927,'(77)3':928,'(33)7':929,
'(73)7':930,'(74)4':931,'(77)4':932,'(44)7':933,'(74)7':934,'(75)5':935,'(77)5':936,'(55)7':937,'(75)7':938,'(76)6':939,
'(77)6':940,'(66)7':941,'(76)7':942,'(8A)A':943,'(88)A':944,'(AA)8':945,'(8A)8':946,'(82)2':947,'(88)2':948,'(22)8':949,
'(82)8':950,'(83)3':951,'(88)3':952,'(33)8':953,'(83)8':954,'(84)4':955,'(88)4':956,'(44)8':957,'(84)8':958,'(85)5':959,
'(88)5':960,'(55)8':961,'(85)8':962,'(86)6':963,'(88)6':964,'(66)8':965,'(86)8':966,'(87)7':967,'(88)7':968,'(77)8':969,
'(87)8':970,'(9A)A':971,'(99)A':972,'(AA)9':973,'(9A)9':974,'(92)2':975,'(99)2':976,'(22)9':977,'(92)9':978,'(93)3':979,
'(99)3':980,'(33)9':981,'(93)9':982,'(94)4':983,'(99)4':984,'(44)9':985,'(94)9':986,'(95)5':987,'(99)5':988,'(55)9':989,
'(95)9':990,'(96)6':991,'(99)6':992,'(66)9':993,'(96)9':994,'(97)7':995,'(99)7':996,'(77)9':997,'(97)9':998,'(98)8':999,
'(99)8':1000,'(88)9':1001,'(98)9':1002,'(TA)A':1003,'(TT)A':1004,'(AA)T':1005,'(TA)T':1006,'(T2)2':1007,'(TT)2':1008,'(22)T':1009,
'(T2)T':1010,'(T3)3':1011,'(TT)3':1012,'(33)T':1013,'(T3)T':1014,'(T4)4':1015,'(TT)4':1016,'(44)T':1017,'(T4)T':1018,'(T5)5':1019,
'(TT)5':1020,'(55)T':1021,'(T5)T':1022,'(T6)6':1023,'(TT)6':1024,'(66)T':1025,'(T6)T':1026,'(T7)7':1027,'(TT)7':1028,'(77)T':1029,
'(T7)T':1030,'(T8)8':1031,'(TT)8':1032,'(88)T':1033,'(T8)T':1034,'(T9)9':1035,'(TT)9':1036,'(99)T':1037,'(T9)T':1038,'(JA)A':1039,
'(JJ)A':1040,'(AA)J':1041,'(JA)J':1042,'(J2)2':1043,'(JJ)2':1044,'(22)J':1045,'(J2)J':1046,'(J3)3':1047,'(JJ)3':1048,'(33)J':1049,
'(J3)J':1050,'(J4)4':1051,'(JJ)4':1052,'(44)J':1053,'(J4)J':1054,'(J5)5':1055,'(JJ)5':1056,'(55)J':1057,'(J5)J':1058,'(J6)6':1059,
'(JJ)6':1060,'(66)J':1061,'(J6)J':1062,'(J7)7':1063,'(JJ)7':1064,'(77)J':1065,'(J7)J':1066,'(J8)8':1067,'(JJ)8':1068,'(88)J':1069,
'(J8)J':1070,'(J9)9':1071,'(JJ)9':1072,'(99)J':1073,'(J9)J':1074,'(JT)T':1075,'(JJ)T':1076,'(TT)J':1077,'(JT)J':1078,'(QA)A':1079,
'(QQ)A':1080,'(AA)Q':1081,'(QA)Q':1082,'(Q2)2':1083,'(QQ)2':1084,'(22)Q':1085,'(Q2)Q':1086,'(Q3)3':1087,'(QQ)3':1088,'(33)Q':1089,
'(Q3)Q':1090,'(Q4)4':1091,'(QQ)4':1092,'(44)Q':1093,'(Q4)Q':1094,'(Q5)5':1095,'(QQ)5':1096,'(55)Q':1097,'(Q5)Q':1098,'(Q6)6':1099,
'(QQ)6':1100,'(66)Q':1101,'(Q6)Q':1102,'(Q7)7':1103,'(QQ)7':1104,'(77)Q':1105,'(Q7)Q':1106,'(Q8)8':1107,'(QQ)8':1108,'(88)Q':1109,
'(Q8)Q':1110,'(Q9)9':1111,'(QQ)9':1112,'(99)Q':1113,'(Q9)Q':1114,'(QT)T':1115,'(QQ)T':1116,'(TT)Q':1117,'(QT)Q':1118,'(QJ)J':1119,
'(QQ)J':1120,'(JJ)Q':1121,'(QJ)Q':1122,'(KA)A':1123,'(KK)A':1124,'(AA)K':1125,'(KA)K':1126,'(K2)2':1127,'(KK)2':1128,'(22)K':1129,
'(K2)K':1130,'(K3)3':1131,'(KK)3':1132,'(33)K':1133,'(K3)K':1134,'(K4)4':1135,'(KK)4':1136,'(44)K':1137,'(K4)K':1138,'(K5)5':1139,
'(KK)5':1140,'(55)K':1141,'(K5)K':1142,'(K6)6':1143,'(KK)6':1144,'(66)K':1145,'(K6)K':1146,'(K7)7':1147,'(KK)7':1148,'(77)K':1149,
'(K7)K':1150,'(K8)8':1151,'(KK)8':1152,'(88)K':1153,'(K8)K':1154,'(K9)9':1155,'(KK)9':1156,'(99)K':1157,'(K9)K':1158,'(KT)T':1159,
'(KK)T':1160,'(TT)K':1161,'(KT)K':1162,'(KJ)J':1163,'(KK)J':1164,'(JJ)K':1165,'(KJ)K':1166,'(KQ)Q':1167,'(KK)Q':1168,'(QQ)K':1169,
'(KQ)K':1170,'(AA)A':1171,'(22)2':1172,'(33)3':1173,'(44)4':1174,'(55)5':1175,'(66)6':1176,'(77)7':1177,'(88)8':1178,'(99)9':1179,
'(TT)T':1180,'(JJ)J':1181,'(QQ)Q':1182,'(KK)K':1183,
}
#print "DEBUG: encodeRazzList['%s']: %s" % (startHand, encodeRazzList[startHand])
return encodeRazzList[startHand]
if __name__ == '__main__': if __name__ == '__main__':
print _("fpdb card encoding(same as pokersource)") print _("fpdb card encoding(same as pokersource)")
for i in xrange(1, 14): for i in xrange(1, 14):

31
pyfpdb/Configuration.py Executable file → Normal file
View File

@ -23,8 +23,13 @@ Handles HUD configuration files.
######################################################################## ########################################################################
# Standard Library modules # Standard Library modules
from __future__ import with_statement from __future__ import with_statement
import L10n
_ = L10n.get_translation()
import os import os
import sys import sys
import inspect import inspect
@ -36,18 +41,6 @@ import re
import xml.dom.minidom import xml.dom.minidom
from xml.dom.minidom import Node from xml.dom.minidom import Node
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
import logging, logging.config import logging, logging.config
import ConfigParser import ConfigParser
@ -457,11 +450,12 @@ class Aux_window:
class HHC: class HHC:
def __init__(self, node): def __init__(self, node):
self.site = node.getAttribute("site") self.site = node.getAttribute("site")
self.converter = node.getAttribute("converter") self.converter = node.getAttribute("converter")
self.summaryImporter = node.getAttribute("summaryImporter")
def __str__(self): def __str__(self):
return "%s:\t%s" % (self.site, self.converter) return "%s:\tconverter: '%s' summaryImporter: '%s'" % (self.site, self.converter, self.summaryImporter)
class Popup: class Popup:
@ -484,7 +478,7 @@ class Import:
self.callFpdbHud = node.getAttribute("callFpdbHud") self.callFpdbHud = node.getAttribute("callFpdbHud")
self.hhArchiveBase = node.getAttribute("hhArchiveBase") self.hhArchiveBase = node.getAttribute("hhArchiveBase")
self.hhBulkPath = node.getAttribute("hhBulkPath") self.hhBulkPath = node.getAttribute("hhBulkPath")
self.saveActions = string_to_bool(node.getAttribute("saveActions"), default=True) self.saveActions = string_to_bool(node.getAttribute("saveActions"), default=False)
self.fastStoreHudCache = string_to_bool(node.getAttribute("fastStoreHudCache"), default=False) self.fastStoreHudCache = string_to_bool(node.getAttribute("fastStoreHudCache"), default=False)
self.saveStarsHH = string_to_bool(node.getAttribute("saveStarsHH"), default=False) self.saveStarsHH = string_to_bool(node.getAttribute("saveStarsHH"), default=False)
@ -577,7 +571,8 @@ class GUICashStats(list):
def get_defaults(self): def get_defaults(self):
"""A list of defaults to be called, should there be no entry in config""" """A list of defaults to be called, should there be no entry in config"""
defaults = [ [u'game', u'Game', True, True, u'%s', u'str', 0.0], # SQL column name, display title, display all, display positional, format, type, alignment
defaults = [ [u'game', u'Game', True, True, u'%s', u'str', 0.0],
[u'hand', u'Hand', False, False, u'%s', u'str', 0.0], [u'hand', u'Hand', False, False, u'%s', u'str', 0.0],
[u'plposition', u'Posn', False, False, u'%s', u'str', 1.0], [u'plposition', u'Posn', False, False, u'%s', u'str', 1.0],
[u'pname', u'Name', False, False, u'%s', u'str', 0.0], [u'pname', u'Name', False, False, u'%s', u'str', 0.0],
@ -1263,7 +1258,7 @@ class Config:
except: imp['hhBulkPath'] = "" except: imp['hhBulkPath'] = ""
try: imp['saveActions'] = self.imp.saveActions try: imp['saveActions'] = self.imp.saveActions
except: imp['saveActions'] = True except: imp['saveActions'] = False
try: imp['saveStarsHH'] = self.imp.saveStarsHH try: imp['saveStarsHH'] = self.imp.saveStarsHH
except: imp['saveStarsHH'] = False except: imp['saveStarsHH'] = False

View File

@ -5,21 +5,24 @@
Create and manage the database objects. Create and manage the database objects.
""" """
# Copyright 2008-2010, Ray E. Barker # Copyright 2008-2010, Ray E. Barker
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or # the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import L10n
_ = L10n.get_translation()
######################################################################## ########################################################################
# TODO: - rebuild indexes / vacuum option # TODO: - rebuild indexes / vacuum option
@ -46,18 +49,6 @@ import logging
# logging has been set up in fpdb.py or HUD_main.py, use their settings: # logging has been set up in fpdb.py or HUD_main.py, use their settings:
log = logging.getLogger("db") log = logging.getLogger("db")
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
# FreePokerTools modules # FreePokerTools modules
import SQL import SQL
import Card import Card
@ -82,7 +73,7 @@ except ImportError:
use_numpy = False use_numpy = False
DB_VERSION = 143 DB_VERSION = 144
# Variance created as sqlite has a bunch of undefined aggregate functions. # Variance created as sqlite has a bunch of undefined aggregate functions.
@ -114,7 +105,7 @@ class Database:
# Data Structures for index and foreign key creation # Data Structures for index and foreign key creation
# drop_code is an int with possible values: 0 - don't drop for bulk import # drop_code is an int with possible values: 0 - don't drop for bulk import
# 1 - drop during bulk import # 1 - drop during bulk import
# db differences: # db differences:
# - note that mysql automatically creates indexes on constrained columns when # - note that mysql automatically creates indexes on constrained columns when
# foreign keys are created, while postgres does not. Hence the much longer list # foreign keys are created, while postgres does not. Hence the much longer list
# of indexes is required for postgres. # of indexes is required for postgres.
@ -135,6 +126,7 @@ class Database:
, {'tab':'Hands', 'col':'gametypeId', 'drop':0} # mct 22/3/09 , {'tab':'Hands', 'col':'gametypeId', 'drop':0} # mct 22/3/09
#, {'tab':'Hands', 'col':'siteHandNo', 'drop':0} unique indexes not dropped #, {'tab':'Hands', 'col':'siteHandNo', 'drop':0} unique indexes not dropped
, {'tab':'HandsActions', 'col':'handsPlayerId', 'drop':0} , {'tab':'HandsActions', 'col':'handsPlayerId', 'drop':0}
, {'tab':'HandsActions', 'col':'actionId', 'drop':1}
, {'tab':'HandsPlayers', 'col':'handId', 'drop':1} , {'tab':'HandsPlayers', 'col':'handId', 'drop':1}
, {'tab':'HandsPlayers', 'col':'playerId', 'drop':1} , {'tab':'HandsPlayers', 'col':'playerId', 'drop':1}
, {'tab':'HandsPlayers', 'col':'tourneysPlayersId', 'drop':0} , {'tab':'HandsPlayers', 'col':'tourneysPlayersId', 'drop':0}
@ -155,9 +147,11 @@ class Database:
] ]
, [ # indexes for sqlite (list index 4) , [ # indexes for sqlite (list index 4)
{'tab':'Hands', 'col':'gametypeId', 'drop':0} {'tab':'Hands', 'col':'gametypeId', 'drop':0}
, {'tab':'HandsPlayers', 'col':'handId', 'drop':0} , {'tab':'HandsPlayers', 'col':'handId', 'drop':0}
, {'tab':'HandsPlayers', 'col':'playerId', 'drop':0} , {'tab':'HandsPlayers', 'col':'playerId', 'drop':0}
, {'tab':'HandsPlayers', 'col':'tourneysPlayersId', 'drop':0} , {'tab':'HandsPlayers', 'col':'tourneysPlayersId', 'drop':0}
, {'tab':'HandsActions', 'col':'handsPlayerId', 'drop':0}
, {'tab':'HandsActions', 'col':'actionId', 'drop':1}
, {'tab':'HudCache', 'col':'gametypeId', 'drop':1} , {'tab':'HudCache', 'col':'gametypeId', 'drop':1}
, {'tab':'HudCache', 'col':'playerId', 'drop':0} , {'tab':'HudCache', 'col':'playerId', 'drop':0}
, {'tab':'HudCache', 'col':'tourneyTypeId', 'drop':0} , {'tab':'HudCache', 'col':'tourneyTypeId', 'drop':0}
@ -181,6 +175,7 @@ class Database:
, {'fktab':'HandsPlayers', 'fkcol':'playerId', 'rtab':'Players', 'rcol':'id', 'drop':1} , {'fktab':'HandsPlayers', 'fkcol':'playerId', 'rtab':'Players', 'rcol':'id', 'drop':1}
, {'fktab':'HandsPlayers', 'fkcol':'tourneysPlayersId','rtab':'TourneysPlayers','rcol':'id', 'drop':1} , {'fktab':'HandsPlayers', 'fkcol':'tourneysPlayersId','rtab':'TourneysPlayers','rcol':'id', 'drop':1}
, {'fktab':'HandsActions', 'fkcol':'handsPlayerId', 'rtab':'HandsPlayers', 'rcol':'id', 'drop':1} , {'fktab':'HandsActions', 'fkcol':'handsPlayerId', 'rtab':'HandsPlayers', 'rcol':'id', 'drop':1}
, {'fktab':'HandsActions', 'fkcol':'actionId', 'rtab':'Actions', 'rcol':'id', 'drop':1}
, {'fktab':'HudCache', 'fkcol':'gametypeId', 'rtab':'Gametypes', 'rcol':'id', 'drop':1} , {'fktab':'HudCache', 'fkcol':'gametypeId', 'rtab':'Gametypes', 'rcol':'id', 'drop':1}
, {'fktab':'HudCache', 'fkcol':'playerId', 'rtab':'Players', 'rcol':'id', 'drop':0} , {'fktab':'HudCache', 'fkcol':'playerId', 'rtab':'Players', 'rcol':'id', 'drop':0}
, {'fktab':'HudCache', 'fkcol':'tourneyTypeId', 'rtab':'TourneyTypes', 'rcol':'id', 'drop':1} , {'fktab':'HudCache', 'fkcol':'tourneyTypeId', 'rtab':'TourneyTypes', 'rcol':'id', 'drop':1}
@ -190,6 +185,7 @@ class Database:
, {'fktab':'HandsPlayers', 'fkcol':'handId', 'rtab':'Hands', 'rcol':'id', 'drop':1} , {'fktab':'HandsPlayers', 'fkcol':'handId', 'rtab':'Hands', 'rcol':'id', 'drop':1}
, {'fktab':'HandsPlayers', 'fkcol':'playerId', 'rtab':'Players', 'rcol':'id', 'drop':1} , {'fktab':'HandsPlayers', 'fkcol':'playerId', 'rtab':'Players', 'rcol':'id', 'drop':1}
, {'fktab':'HandsActions', 'fkcol':'handsPlayerId', 'rtab':'HandsPlayers', 'rcol':'id', 'drop':1} , {'fktab':'HandsActions', 'fkcol':'handsPlayerId', 'rtab':'HandsPlayers', 'rcol':'id', 'drop':1}
, {'fktab':'HandsActions', 'fkcol':'actionId', 'rtab':'Actions', 'rcol':'id', 'drop':1}
, {'fktab':'HudCache', 'fkcol':'gametypeId', 'rtab':'Gametypes', 'rcol':'id', 'drop':1} , {'fktab':'HudCache', 'fkcol':'gametypeId', 'rtab':'Gametypes', 'rcol':'id', 'drop':1}
, {'fktab':'HudCache', 'fkcol':'playerId', 'rtab':'Players', 'rcol':'id', 'drop':0} , {'fktab':'HudCache', 'fkcol':'playerId', 'rtab':'Players', 'rcol':'id', 'drop':0}
, {'fktab':'HudCache', 'fkcol':'tourneyTypeId', 'rtab':'TourneyTypes', 'rcol':'id', 'drop':1} , {'fktab':'HudCache', 'fkcol':'tourneyTypeId', 'rtab':'TourneyTypes', 'rcol':'id', 'drop':1}
@ -208,7 +204,7 @@ class Database:
# (fkcol is used for foreigh key name) # (fkcol is used for foreigh key name)
# mysql to list indexes: (CG - "LIST INDEXES" should work too) # mysql to list indexes: (CG - "LIST INDEXES" should work too)
# SELECT table_name, index_name, non_unique, column_name # SELECT table_name, index_name, non_unique, column_name
# FROM INFORMATION_SCHEMA.STATISTICS # FROM INFORMATION_SCHEMA.STATISTICS
# WHERE table_name = 'tbl_name' # WHERE table_name = 'tbl_name'
# AND table_schema = 'db_name' # AND table_schema = 'db_name'
@ -245,7 +241,7 @@ class Database:
# create index indexname on tablename (col); # create index indexname on tablename (col);
def __init__(self, c, sql = None, autoconnect = True): def __init__(self, c, sql = None, autoconnect = True):
#log = Configuration.get_logger("logging.conf", "db", log_dir=c.dir_log) #log = Configuration.get_logger("logging.conf", "db", log_dir=c.dir_log)
log.debug(_("Creating Database instance, sql = %s") % sql) log.debug(_("Creating Database instance, sql = %s") % sql)
self.config = c self.config = c
@ -269,11 +265,11 @@ class Database:
if autoconnect: if autoconnect:
# connect to db # connect to db
self.do_connect(c) self.do_connect(c)
if self.backend == self.PGSQL: if self.backend == self.PGSQL:
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT, ISOLATION_LEVEL_READ_COMMITTED, ISOLATION_LEVEL_SERIALIZABLE from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT, ISOLATION_LEVEL_READ_COMMITTED, ISOLATION_LEVEL_SERIALIZABLE
#ISOLATION_LEVEL_AUTOCOMMIT = 0 #ISOLATION_LEVEL_AUTOCOMMIT = 0
#ISOLATION_LEVEL_READ_COMMITTED = 1 #ISOLATION_LEVEL_READ_COMMITTED = 1
#ISOLATION_LEVEL_SERIALIZABLE = 2 #ISOLATION_LEVEL_SERIALIZABLE = 2
@ -308,10 +304,10 @@ class Database:
def dumpDatabase(self): def dumpDatabase(self):
result="fpdb database dump\nDB version=" + str(DB_VERSION)+"\n\n" result="fpdb database dump\nDB version=" + str(DB_VERSION)+"\n\n"
tables=self.cursor.execute(self.sql.query['list_tables']) tables=self.cursor.execute(self.sql.query['list_tables'])
tables=self.cursor.fetchall() tables=self.cursor.fetchall()
for table in (u'Autorates', u'Backings', u'Gametypes', u'Hands', u'HandsActions', u'HandsPlayers', u'HudCache', u'Players', u'RawHands', u'RawTourneys', u'Settings', u'Sites', u'TourneyTypes', u'Tourneys', u'TourneysPlayers'): for table in (u'Actions', u'Autorates', u'Backings', u'Gametypes', u'Hands', u'HandsActions', u'HandsPlayers', u'HudCache', u'Players', u'RawHands', u'RawTourneys', u'Settings', u'Sites', u'TourneyTypes', u'Tourneys', u'TourneysPlayers'):
print "table:", table print "table:", table
result+="###################\nTable "+table+"\n###################\n" result+="###################\nTable "+table+"\n###################\n"
rows=self.cursor.execute(self.sql.query['get'+table]) rows=self.cursor.execute(self.sql.query['get'+table])
@ -332,7 +328,7 @@ class Database:
result+="\n" result+="\n"
return result return result
#end def dumpDatabase #end def dumpDatabase
# could be used by hud to change hud style # could be used by hud to change hud style
def set_hud_style(self, style): def set_hud_style(self, style):
self.hud_style = style self.hud_style = style
@ -372,7 +368,7 @@ class Database:
self.database = database self.database = database
self.connection = None self.connection = None
self.cursor = None self.cursor = None
if backend == Database.MYSQL_INNODB: if backend == Database.MYSQL_INNODB:
import MySQLdb import MySQLdb
if use_pool: if use_pool:
@ -548,13 +544,13 @@ class Database:
self.cursor.close() self.cursor.close()
self.connection.close() self.connection.close()
self.__connected = False self.__connected = False
def reconnect(self, due_to_error=False): def reconnect(self, due_to_error=False):
"""Reconnects the DB""" """Reconnects the DB"""
#print "started reconnect" #print "started reconnect"
self.disconnect(due_to_error) self.disconnect(due_to_error)
self.connect(self.backend, self.host, self.database, self.user, self.password) self.connect(self.backend, self.host, self.database, self.user, self.password)
def get_backend_name(self): def get_backend_name(self):
"""Returns the name of the currently used backend""" """Returns the name of the currently used backend"""
if self.backend==2: if self.backend==2:
@ -574,7 +570,7 @@ class Database:
c.execute(self.sql.query['get_table_name'], (hand_id, )) c.execute(self.sql.query['get_table_name'], (hand_id, ))
row = c.fetchone() row = c.fetchone()
return row return row
def get_table_info(self, hand_id): def get_table_info(self, hand_id):
c = self.connection.cursor() c = self.connection.cursor()
c.execute(self.sql.query['get_table_name'], (hand_id, )) c.execute(self.sql.query['get_table_name'], (hand_id, ))
@ -595,18 +591,18 @@ class Database:
c.execute(self.sql.query['get_last_hand']) c.execute(self.sql.query['get_last_hand'])
row = c.fetchone() row = c.fetchone()
return row[0] return row[0]
def get_xml(self, hand_id): def get_xml(self, hand_id):
c = self.connection.cursor() c = self.connection.cursor()
c.execute(self.sql.query['get_xml'], (hand_id)) c.execute(self.sql.query['get_xml'], (hand_id))
row = c.fetchone() row = c.fetchone()
return row[0] return row[0]
def get_recent_hands(self, last_hand): def get_recent_hands(self, last_hand):
c = self.connection.cursor() c = self.connection.cursor()
c.execute(self.sql.query['get_recent_hands'], {'last_hand': last_hand}) c.execute(self.sql.query['get_recent_hands'], {'last_hand': last_hand})
return c.fetchall() return c.fetchall()
def get_hand_info(self, new_hand_id): def get_hand_info(self, new_hand_id):
c = self.connection.cursor() c = self.connection.cursor()
c.execute(self.sql.query['get_hand_info'], new_hand_id) c.execute(self.sql.query['get_hand_info'], new_hand_id)
@ -839,7 +835,7 @@ class Database:
query = query.replace("<signed>", 'signed ') query = query.replace("<signed>", 'signed ')
else: else:
query = query.replace("<signed>", '') query = query.replace("<signed>", '')
subs = (self.hand_1day_ago, hand, hero_id, seats_min, seats_max subs = (self.hand_1day_ago, hand, hero_id, seats_min, seats_max
, hero_id, h_seats_min, h_seats_max) , hero_id, h_seats_min, h_seats_max)
c = self.get_cursor() c = self.get_cursor()
@ -868,7 +864,7 @@ class Database:
#print "DEBUG: stat_dict[%s][%s]: %s" %(playerid, name.lower(), val) #print "DEBUG: stat_dict[%s][%s]: %s" %(playerid, name.lower(), val)
stat_dict[playerid][name.lower()] += val stat_dict[playerid][name.lower()] += val
n += 1 n += 1
if n >= 10000: break # todo: don't think this is needed so set nice and high if n >= 10000: break # todo: don't think this is needed so set nice and high
# prevents infinite loop so leave for now - comment out or remove? # prevents infinite loop so leave for now - comment out or remove?
row = c.fetchone() row = c.fetchone()
else: else:
@ -878,7 +874,7 @@ class Database:
#print "session stat_dict =", stat_dict #print "session stat_dict =", stat_dict
#return stat_dict #return stat_dict
def get_player_id(self, config, siteName, playerName): def get_player_id(self, config, siteName, playerName):
c = self.connection.cursor() c = self.connection.cursor()
siteNameUtf = Charset.to_utf8(siteName) siteNameUtf = Charset.to_utf8(siteName)
@ -890,7 +886,7 @@ class Database:
return row[0] return row[0]
else: else:
return None return None
def get_player_names(self, config, site_id=None, like_player_name="%"): def get_player_names(self, config, site_id=None, like_player_name="%"):
"""Fetch player names from players. Use site_id and like_player_name if provided""" """Fetch player names from players. Use site_id and like_player_name if provided"""
@ -901,7 +897,7 @@ class Database:
c.execute(self.sql.query['get_player_names'], (p_name, site_id, site_id)) c.execute(self.sql.query['get_player_names'], (p_name, site_id, site_id))
rows = c.fetchall() rows = c.fetchall()
return rows return rows
def get_site_id(self, site): def get_site_id(self, site):
c = self.get_cursor() c = self.get_cursor()
c.execute(self.sql.query['getSiteId'], (site,)) c.execute(self.sql.query['getSiteId'], (site,))
@ -945,7 +941,7 @@ class Database:
def prepareBulkImport(self): def prepareBulkImport(self):
"""Drop some indexes/foreign keys to prepare for bulk import. """Drop some indexes/foreign keys to prepare for bulk import.
Currently keeping the standalone indexes as needed to import quickly""" Currently keeping the standalone indexes as needed to import quickly"""
stime = time() stime = time()
c = self.get_cursor() c = self.get_cursor()
@ -963,7 +959,7 @@ class Database:
"FROM information_schema.KEY_COLUMN_USAGE " + "FROM information_schema.KEY_COLUMN_USAGE " +
#"WHERE REFERENCED_TABLE_SCHEMA = 'fpdb' #"WHERE REFERENCED_TABLE_SCHEMA = 'fpdb'
"WHERE 1=1 " + "WHERE 1=1 " +
"AND table_name = %s AND column_name = %s " + "AND table_name = %s AND column_name = %s " +
"AND referenced_table_name = %s " + "AND referenced_table_name = %s " +
"AND referenced_column_name = %s ", "AND referenced_column_name = %s ",
(fk['fktab'], fk['fkcol'], fk['rtab'], fk['rcol']) ) (fk['fktab'], fk['fkcol'], fk['rtab'], fk['rcol']) )
@ -980,7 +976,7 @@ class Database:
print "dropping pg fk", fk['fktab'], fk['fkcol'] print "dropping pg fk", fk['fktab'], fk['fkcol']
try: try:
# try to lock table to see if index drop will work: # try to lock table to see if index drop will work:
# hmmm, tested by commenting out rollback in grapher. lock seems to work but # hmmm, tested by commenting out rollback in grapher. lock seems to work but
# then drop still hangs :-( does work in some tests though?? # then drop still hangs :-( does work in some tests though??
# will leave code here for now pending further tests/enhancement ... # will leave code here for now pending further tests/enhancement ...
c.execute("BEGIN TRANSACTION") c.execute("BEGIN TRANSACTION")
@ -1000,13 +996,13 @@ class Database:
% (fk['fktab'],fk['fkcol'], str(sys.exc_value).rstrip('\n')) % (fk['fktab'],fk['fkcol'], str(sys.exc_value).rstrip('\n'))
else: else:
return -1 return -1
for idx in self.indexes[self.backend]: for idx in self.indexes[self.backend]:
if idx['drop'] == 1: if idx['drop'] == 1:
if self.backend == self.MYSQL_INNODB: if self.backend == self.MYSQL_INNODB:
print _("dropping mysql index "), idx['tab'], idx['col'] print _("dropping mysql index "), idx['tab'], idx['col']
try: try:
# apparently nowait is not implemented in mysql so this just hangs if there are locks # apparently nowait is not implemented in mysql so this just hangs if there are locks
# preventing the index drop :-( # preventing the index drop :-(
c.execute( "alter table %s drop index %s;", (idx['tab'],idx['col']) ) c.execute( "alter table %s drop index %s;", (idx['tab'],idx['col']) )
except: except:
@ -1023,13 +1019,13 @@ class Database:
#print "after lock, status:", c.statusmessage #print "after lock, status:", c.statusmessage
try: try:
# table locked ok so index drop should work: # table locked ok so index drop should work:
#print "drop index %s_%s_idx" % (idx['tab'],idx['col']) #print "drop index %s_%s_idx" % (idx['tab'],idx['col'])
c.execute( "drop index if exists %s_%s_idx" % (idx['tab'],idx['col']) ) c.execute( "drop index if exists %s_%s_idx" % (idx['tab'],idx['col']) )
#print "dropped pg index ", idx['tab'], idx['col'] #print "dropped pg index ", idx['tab'], idx['col']
except: except:
if "does not exist" not in str(sys.exc_value): if "does not exist" not in str(sys.exc_value):
print _("warning: drop index %s_%s_idx failed: %s, continuing ...") \ print _("warning: drop index %s_%s_idx failed: %s, continuing ...") \
% (idx['tab'],idx['col'], str(sys.exc_value).rstrip('\n')) % (idx['tab'],idx['col'], str(sys.exc_value).rstrip('\n'))
c.execute("END TRANSACTION") c.execute("END TRANSACTION")
except: except:
print _("warning: index %s_%s_idx not dropped %s, continuing ...") \ print _("warning: index %s_%s_idx not dropped %s, continuing ...") \
@ -1047,7 +1043,7 @@ class Database:
def afterBulkImport(self): def afterBulkImport(self):
"""Re-create any dropped indexes/foreign keys after bulk import""" """Re-create any dropped indexes/foreign keys after bulk import"""
stime = time() stime = time()
c = self.get_cursor() c = self.get_cursor()
if self.backend == self.MYSQL_INNODB: if self.backend == self.MYSQL_INNODB:
c.execute("SET foreign_key_checks=1") c.execute("SET foreign_key_checks=1")
@ -1063,7 +1059,7 @@ class Database:
"FROM information_schema.KEY_COLUMN_USAGE " + "FROM information_schema.KEY_COLUMN_USAGE " +
#"WHERE REFERENCED_TABLE_SCHEMA = 'fpdb' #"WHERE REFERENCED_TABLE_SCHEMA = 'fpdb'
"WHERE 1=1 " + "WHERE 1=1 " +
"AND table_name = %s AND column_name = %s " + "AND table_name = %s AND column_name = %s " +
"AND referenced_table_name = %s " + "AND referenced_table_name = %s " +
"AND referenced_column_name = %s ", "AND referenced_column_name = %s ",
(fk['fktab'], fk['fkcol'], fk['rtab'], fk['rcol']) ) (fk['fktab'], fk['fkcol'], fk['rtab'], fk['rcol']) )
@ -1072,43 +1068,43 @@ class Database:
if cons: if cons:
pass pass
else: else:
print _("creating foreign key "), fk['fktab'], fk['fkcol'], "->", fk['rtab'], fk['rcol'] print _("Creating foreign key "), fk['fktab'], fk['fkcol'], "->", fk['rtab'], fk['rcol']
try: try:
c.execute("alter table " + fk['fktab'] + " add foreign key (" c.execute("alter table " + fk['fktab'] + " add foreign key ("
+ fk['fkcol'] + ") references " + fk['rtab'] + "(" + fk['fkcol'] + ") references " + fk['rtab'] + "("
+ fk['rcol'] + ")") + fk['rcol'] + ")")
except: except:
print _(" create foreign key failed: ") + str(sys.exc_info()) print _("Create foreign key failed: ") + str(sys.exc_info())
elif self.backend == self.PGSQL: elif self.backend == self.PGSQL:
print _("creating foreign key "), fk['fktab'], fk['fkcol'], "->", fk['rtab'], fk['rcol'] print _("Creating foreign key "), fk['fktab'], fk['fkcol'], "->", fk['rtab'], fk['rcol']
try: try:
c.execute("alter table " + fk['fktab'] + " add constraint " c.execute("alter table " + fk['fktab'] + " add constraint "
+ fk['fktab'] + '_' + fk['fkcol'] + '_fkey' + fk['fktab'] + '_' + fk['fkcol'] + '_fkey'
+ " foreign key (" + fk['fkcol'] + " foreign key (" + fk['fkcol']
+ ") references " + fk['rtab'] + "(" + fk['rcol'] + ")") + ") references " + fk['rtab'] + "(" + fk['rcol'] + ")")
except: except:
print _(" create foreign key failed: ") + str(sys.exc_info()) print _("Create foreign key failed: ") + str(sys.exc_info())
else: else:
return -1 return -1
for idx in self.indexes[self.backend]: for idx in self.indexes[self.backend]:
if idx['drop'] == 1: if idx['drop'] == 1:
if self.backend == self.MYSQL_INNODB: if self.backend == self.MYSQL_INNODB:
print _("creating mysql index "), idx['tab'], idx['col'] print _("Creating mysql index %s %s") % (idx['tab'], idx['col'])
try: try:
s = "alter table %s add index %s(%s)" % (idx['tab'],idx['col'],idx['col']) s = "alter table %s add index %s(%s)" % (idx['tab'],idx['col'],idx['col'])
c.execute(s) c.execute(s)
except: except:
print _(" create foreign key failed: ") + str(sys.exc_info()) print _("Create foreign key failed: ") + str(sys.exc_info())
elif self.backend == self.PGSQL: elif self.backend == self.PGSQL:
# pass # pass
# mod to use tab_col for index name? # mod to use tab_col for index name?
print _("creating pg index "), idx['tab'], idx['col'] print _("Creating pg index "), idx['tab'], idx['col']
try: try:
s = "create index %s_%s_idx on %s(%s)" % (idx['tab'], idx['col'], idx['tab'], idx['col']) s = "create index %s_%s_idx on %s(%s)" % (idx['tab'], idx['col'], idx['tab'], idx['col'])
c.execute(s) c.execute(s)
except: except:
print _(" create index failed: ") + str(sys.exc_info()) print _("Create index failed: ") + str(sys.exc_info())
else: else:
return -1 return -1
@ -1139,10 +1135,10 @@ class Database:
c.execute("ALTER TABLE " + inner[j][0] + " DROP FOREIGN KEY " + key) c.execute("ALTER TABLE " + inner[j][0] + " DROP FOREIGN KEY " + key)
self.commit() self.commit()
#end drop_referential_inegrity #end drop_referential_inegrity
def recreate_tables(self): def recreate_tables(self):
"""(Re-)creates the tables of the current DB""" """(Re-)creates the tables of the current DB"""
self.drop_tables() self.drop_tables()
self.resetPlayerIDs() self.resetPlayerIDs()
self.create_tables() self.create_tables()
@ -1160,6 +1156,7 @@ class Database:
c.execute(self.sql.query['createSettingsTable']) c.execute(self.sql.query['createSettingsTable'])
log.debug("Creating tables") log.debug("Creating tables")
c.execute(self.sql.query['createActionsTable'])
c.execute(self.sql.query['createSitesTable']) c.execute(self.sql.query['createSitesTable'])
c.execute(self.sql.query['createGametypesTable']) c.execute(self.sql.query['createGametypesTable'])
c.execute(self.sql.query['createPlayersTable']) c.execute(self.sql.query['createPlayersTable'])
@ -1192,7 +1189,7 @@ class Database:
self.rollback() self.rollback()
raise raise
#end def disconnect #end def disconnect
def drop_tables(self): def drop_tables(self):
"""Drops the fpdb tables from the current db""" """Drops the fpdb tables from the current db"""
try: try:
@ -1256,7 +1253,7 @@ class Database:
s = "create index %s on %s(%s)" % (idx['col'],idx['tab'],idx['col']) s = "create index %s on %s(%s)" % (idx['col'],idx['tab'],idx['col'])
self.get_cursor().execute(s) self.get_cursor().execute(s)
except: except:
print _(" create index failed: ") + str(sys.exc_info()) print _("Create index failed: ") + str(sys.exc_info())
elif self.backend == self.PGSQL: elif self.backend == self.PGSQL:
# mod to use tab_col for index name? # mod to use tab_col for index name?
print _("Creating pgsql index %s %s") %(idx['tab'], idx['col']) print _("Creating pgsql index %s %s") %(idx['tab'], idx['col'])
@ -1265,7 +1262,7 @@ class Database:
s = "create index %s_%s_idx on %s(%s)" % (idx['tab'], idx['col'], idx['tab'], idx['col']) s = "create index %s_%s_idx on %s(%s)" % (idx['tab'], idx['col'], idx['tab'], idx['col'])
self.get_cursor().execute(s) self.get_cursor().execute(s)
except: except:
print _(" create index failed: ") + str(sys.exc_info()) print _("Create index failed: ") + str(sys.exc_info())
elif self.backend == self.SQLITE: elif self.backend == self.SQLITE:
print _("Creating sqlite index %s %s") %(idx['tab'], idx['col']) print _("Creating sqlite index %s %s") %(idx['tab'], idx['col'])
log.debug(_("Creating sqlite index %s %s") %(idx['tab'], idx['col'])) log.debug(_("Creating sqlite index %s %s") %(idx['tab'], idx['col']))
@ -1281,7 +1278,7 @@ class Database:
self.connection.set_isolation_level(1) # go back to normal isolation level self.connection.set_isolation_level(1) # go back to normal isolation level
except: except:
print _("Error creating indexes: ") + str(sys.exc_value) print _("Error creating indexes: ") + str(sys.exc_value)
raise FpdbError( "Error creating indexes " + str(sys.exc_value) ) raise FpdbError("Error creating indexes: " + str(sys.exc_value) )
#end def createAllIndexes #end def createAllIndexes
def dropAllIndexes(self): def dropAllIndexes(self):
@ -1336,7 +1333,7 @@ class Database:
"FROM information_schema.KEY_COLUMN_USAGE " + "FROM information_schema.KEY_COLUMN_USAGE " +
#"WHERE REFERENCED_TABLE_SCHEMA = 'fpdb' #"WHERE REFERENCED_TABLE_SCHEMA = 'fpdb'
"WHERE 1=1 " + "WHERE 1=1 " +
"AND table_name = %s AND column_name = %s " + "AND table_name = %s AND column_name = %s " +
"AND referenced_table_name = %s " + "AND referenced_table_name = %s " +
"AND referenced_column_name = %s ", "AND referenced_column_name = %s ",
(fk['fktab'], fk['fkcol'], fk['rtab'], fk['rcol']) ) (fk['fktab'], fk['fkcol'], fk['rtab'], fk['rcol']) )
@ -1347,8 +1344,8 @@ class Database:
else: else:
print _("creating foreign key "), fk['fktab'], fk['fkcol'], "->", fk['rtab'], fk['rcol'] print _("creating foreign key "), fk['fktab'], fk['fkcol'], "->", fk['rtab'], fk['rcol']
try: try:
c.execute("alter table " + fk['fktab'] + " add foreign key (" c.execute("alter table " + fk['fktab'] + " add foreign key ("
+ fk['fkcol'] + ") references " + fk['rtab'] + "(" + fk['fkcol'] + ") references " + fk['rtab'] + "("
+ fk['rcol'] + ")") + fk['rcol'] + ")")
except: except:
print _(" create foreign key failed: ") + str(sys.exc_info()) print _(" create foreign key failed: ") + str(sys.exc_info())
@ -1385,7 +1382,7 @@ class Database:
"FROM information_schema.KEY_COLUMN_USAGE " + "FROM information_schema.KEY_COLUMN_USAGE " +
#"WHERE REFERENCED_TABLE_SCHEMA = 'fpdb' #"WHERE REFERENCED_TABLE_SCHEMA = 'fpdb'
"WHERE 1=1 " + "WHERE 1=1 " +
"AND table_name = %s AND column_name = %s " + "AND table_name = %s AND column_name = %s " +
"AND referenced_table_name = %s " + "AND referenced_table_name = %s " +
"AND referenced_column_name = %s ", "AND referenced_column_name = %s ",
(fk['fktab'], fk['fkcol'], fk['rtab'], fk['rcol']) ) (fk['fktab'], fk['fkcol'], fk['rtab'], fk['rcol']) )
@ -1402,7 +1399,7 @@ class Database:
print _("dropping pg foreign key"), fk['fktab'], fk['fkcol'] print _("dropping pg foreign key"), fk['fktab'], fk['fkcol']
try: try:
# try to lock table to see if index drop will work: # try to lock table to see if index drop will work:
# hmmm, tested by commenting out rollback in grapher. lock seems to work but # hmmm, tested by commenting out rollback in grapher. lock seems to work but
# then drop still hangs :-( does work in some tests though?? # then drop still hangs :-( does work in some tests though??
# will leave code here for now pending further tests/enhancement ... # will leave code here for now pending further tests/enhancement ...
c.execute("BEGIN TRANSACTION") c.execute("BEGIN TRANSACTION")
@ -1422,15 +1419,16 @@ class Database:
% (fk['fktab'],fk['fkcol'], str(sys.exc_value).rstrip('\n')) % (fk['fktab'],fk['fkcol'], str(sys.exc_value).rstrip('\n'))
else: else:
print _("Only MySQL and Postgres supported so far") print _("Only MySQL and Postgres supported so far")
if self.backend == self.PGSQL: if self.backend == self.PGSQL:
self.connection.set_isolation_level(1) # go back to normal isolation level self.connection.set_isolation_level(1) # go back to normal isolation level
#end def dropAllForeignKeys #end def dropAllForeignKeys
def fillDefaultData(self): def fillDefaultData(self):
c = self.get_cursor() c = self.get_cursor()
c.execute("INSERT INTO Settings (version) VALUES (%s);" % (DB_VERSION)) c.execute("INSERT INTO Settings (version) VALUES (%s);" % (DB_VERSION))
#Fill Sites
c.execute("INSERT INTO Sites (name,code) VALUES ('Full Tilt Poker', 'FT')") c.execute("INSERT INTO Sites (name,code) VALUES ('Full Tilt Poker', 'FT')")
c.execute("INSERT INTO Sites (name,code) VALUES ('PokerStars', 'PS')") c.execute("INSERT INTO Sites (name,code) VALUES ('PokerStars', 'PS')")
c.execute("INSERT INTO Sites (name,code) VALUES ('Everleaf', 'EV')") c.execute("INSERT INTO Sites (name,code) VALUES ('Everleaf', 'EV')")
@ -1443,6 +1441,24 @@ class Database:
c.execute("INSERT INTO Sites (name,code) VALUES ('Partouche', 'PA')") c.execute("INSERT INTO Sites (name,code) VALUES ('Partouche', 'PA')")
c.execute("INSERT INTO Sites (name,code) VALUES ('Carbon', 'CA')") c.execute("INSERT INTO Sites (name,code) VALUES ('Carbon', 'CA')")
c.execute("INSERT INTO Sites (name,code) VALUES ('PKR', 'PK')") c.execute("INSERT INTO Sites (name,code) VALUES ('PKR', 'PK')")
c.execute("INSERT INTO Sites (name,code) VALUES ('iPoker', 'IP')")
c.execute("INSERT INTO Sites (name,code) VALUES ('Winamax', 'WM')")
#Fill Actions
c.execute("INSERT INTO Actions (name,code) VALUES ('ante', 'A')")
c.execute("INSERT INTO Actions (name,code) VALUES ('small blind', 'SB')")
c.execute("INSERT INTO Actions (name,code) VALUES ('secondsb', 'SSB')")
c.execute("INSERT INTO Actions (name,code) VALUES ('big blind', 'BB')")
c.execute("INSERT INTO Actions (name,code) VALUES ('both', 'SBBB')")
c.execute("INSERT INTO Actions (name,code) VALUES ('calls', 'C')")
c.execute("INSERT INTO Actions (name,code) VALUES ('raises', 'R')")
c.execute("INSERT INTO Actions (name,code) VALUES ('bets', 'B')")
c.execute("INSERT INTO Actions (name,code) VALUES ('stands pat', 'S')")
c.execute("INSERT INTO Actions (name,code) VALUES ('folds', 'F')")
c.execute("INSERT INTO Actions (name,code) VALUES ('checks', 'K')")
c.execute("INSERT INTO Actions (name,code) VALUES ('discards', 'D')")
c.execute("INSERT INTO Actions (name,code) VALUES ('bringin', 'I')")
c.execute("INSERT INTO Actions (name,code) VALUES ('completes', 'P')")
#end def fillDefaultData #end def fillDefaultData
def rebuild_indexes(self, start=None): def rebuild_indexes(self, start=None):
@ -1471,12 +1487,12 @@ class Database:
p_id = self.get_player_id(self.config, site, self.hero[site_id]) p_id = self.get_player_id(self.config, site, self.hero[site_id])
if p_id: if p_id:
self.hero_ids[site_id] = int(p_id) self.hero_ids[site_id] = int(p_id)
if h_start is None: if h_start is None:
h_start = self.hero_hudstart_def h_start = self.hero_hudstart_def
if v_start is None: if v_start is None:
v_start = self.villain_hudstart_def v_start = self.villain_hudstart_def
if self.hero_ids == {}: if self.hero_ids == {}:
where = "WHERE hp.tourneysPlayersId IS NULL" where = "WHERE hp.tourneysPlayersId IS NULL"
else: else:
@ -1493,7 +1509,7 @@ class Database:
#print "rebuild_sql_cash:",rebuild_sql_cash #print "rebuild_sql_cash:",rebuild_sql_cash
self.get_cursor().execute(self.sql.query['clearHudCache']) self.get_cursor().execute(self.sql.query['clearHudCache'])
self.get_cursor().execute(rebuild_sql_cash) self.get_cursor().execute(rebuild_sql_cash)
if self.hero_ids == {}: if self.hero_ids == {}:
where = "WHERE hp.tourneysPlayersId >= 0" where = "WHERE hp.tourneysPlayersId >= 0"
else: else:
@ -1509,7 +1525,7 @@ class Database:
rebuild_sql_tourney = rebuild_sql_tourney.replace('<tourney_group_clause>', ",t.tourneyTypeId") rebuild_sql_tourney = rebuild_sql_tourney.replace('<tourney_group_clause>', ",t.tourneyTypeId")
rebuild_sql_tourney = rebuild_sql_tourney.replace('<where_clause>', where) rebuild_sql_tourney = rebuild_sql_tourney.replace('<where_clause>', where)
#print "rebuild_sql_tourney:",rebuild_sql_tourney #print "rebuild_sql_tourney:",rebuild_sql_tourney
self.get_cursor().execute(rebuild_sql_tourney) self.get_cursor().execute(rebuild_sql_tourney)
self.commit() self.commit()
print _("Rebuild hudcache took %.1f seconds") % (time() - stime,) print _("Rebuild hudcache took %.1f seconds") % (time() - stime,)
@ -1537,7 +1553,7 @@ class Database:
p_id = self.get_player_id(self.config, site, self.hero[site_id]) p_id = self.get_player_id(self.config, site, self.hero[site_id])
if p_id: if p_id:
self.hero_ids[site_id] = int(p_id) self.hero_ids[site_id] = int(p_id)
q = self.sql.query['get_hero_hudcache_start'].replace("<playerid_list>", str(tuple(self.hero_ids.values()))) q = self.sql.query['get_hero_hudcache_start'].replace("<playerid_list>", str(tuple(self.hero_ids.values())))
c = self.get_cursor() c = self.get_cursor()
c.execute(q) c.execute(q)
@ -1570,7 +1586,7 @@ class Database:
self.connection.set_isolation_level(1) # go back to normal isolation level self.connection.set_isolation_level(1) # go back to normal isolation level
self.commit() self.commit()
atime = time() - stime atime = time() - stime
print _("Analyze took %.1f seconds") % (atime,) log.info(_("Analyze took %.1f seconds") % (atime,))
#end def analyzeDB #end def analyzeDB
def vacuumDB(self): def vacuumDB(self):
@ -1618,20 +1634,20 @@ class Database:
c = self.get_cursor() c = self.get_cursor()
c.execute(q, ( c.execute(q, (
p['tableName'], p['tableName'],
p['gameTypeId'], p['gameTypeId'],
p['siteHandNo'], p['siteHandNo'],
p['tourneyId'], p['tourneyId'],
p['startTime'], p['startTime'],
datetime.utcnow(), #importtime datetime.utcnow(), #importtime
p['seats'], p['seats'],
p['maxSeats'], p['maxSeats'],
p['texture'], p['texture'],
p['playersVpi'], p['playersVpi'],
p['boardcard1'], p['boardcard1'],
p['boardcard2'], p['boardcard2'],
p['boardcard3'], p['boardcard3'],
p['boardcard4'], p['boardcard4'],
p['boardcard5'], p['boardcard5'],
p['playersAtStreet1'], p['playersAtStreet1'],
p['playersAtStreet2'], p['playersAtStreet2'],
@ -1660,6 +1676,7 @@ class Database:
pp.pprint(pdata) pp.pprint(pdata)
inserts = [] inserts = []
hpid = {}
for p in pdata: for p in pdata:
inserts.append( (hid, inserts.append( (hid,
pids[p], pids[p],
@ -1764,39 +1781,44 @@ class Database:
#print "DEBUG: inserts: %s" %inserts #print "DEBUG: inserts: %s" %inserts
#print "DEBUG: q: %s" % q #print "DEBUG: q: %s" % q
c = self.get_cursor() c = self.get_cursor()
c.executemany(q, inserts)
def storeHandsActions(self, hid, pids, adata, printdata = False): if self.import_options['saveActions']:
for r in inserts:
c.execute(q, r)
hpid[(r[0], r[1])] = self.get_last_insert_id(c)
else:
c.executemany(q, inserts)
return hpid
def storeHandsActions(self, hid, pids, hpid, adata, printdata = False):
#print "DEBUG: %s %s %s" %(hid, pids, adata) #print "DEBUG: %s %s %s" %(hid, pids, adata)
if printdata: if printdata:
import pprint import pprint
pp = pprint.PrettyPrinter(indent=4) pp = pprint.PrettyPrinter(indent=4)
pp.pprint(adata) pp.pprint(adata)
#inserts = [] inserts = []
#for p in pdata: for a in adata:
# inserts.append( (hid, inserts.append( (hpid[(hid, pids[adata[a]['player']])],
# pids[p], #self.getHandsPlayerId(self.hid, pids[adata[a]['player']]),
# adata[p]['startCash'], adata[a]['street'],
# adata[p]['seatNo'], adata[a]['actionNo'],
# adata[p]['sitout'], adata[a]['streetActionNo'],
# adata[p]['card1'], adata[a]['actionId'],
adata[a]['amount'],
#handsPlayerId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handsPlayerId) REFERENCES HandsPlayers(id), adata[a]['raiseTo'],
#street SMALLINT NOT NULL, adata[a]['amountCalled'],
#actionNo SMALLINT NOT NULL, adata[a]['numDiscarded'],
#action CHAR(5) NOT NULL, adata[a]['cardsDiscarded'],
#allIn BOOLEAN NOT NULL, adata[a]['allIn']
#amount INT NOT NULL, ) )
q = self.sql.query['store_hands_actions'] q = self.sql.query['store_hands_actions']
#q = q.replace('%s', self.sql.query['placeholder']) q = q.replace('%s', self.sql.query['placeholder'])
#print "DEBUG: inserts: %s" %inserts c = self.get_cursor()
#print "DEBUG: q: %s" % q c.executemany(q, inserts)
#c = self.get_cursor()
#c.executemany(q, inserts)
def storeHudCache(self, gid, pids, starttime, pdata): def storeHudCache(self, gid, pids, starttime, pdata):
"""Update cached statistics. If update fails because no record exists, do an insert.""" """Update cached statistics. If update fails because no record exists, do an insert."""
@ -1812,12 +1834,12 @@ class Database:
update_hudcache = update_hudcache.replace('%s', self.sql.query['placeholder']) update_hudcache = update_hudcache.replace('%s', self.sql.query['placeholder'])
insert_hudcache = self.sql.query['insert_hudcache'] insert_hudcache = self.sql.query['insert_hudcache']
insert_hudcache = insert_hudcache.replace('%s', self.sql.query['placeholder']) insert_hudcache = insert_hudcache.replace('%s', self.sql.query['placeholder'])
#print "DEBUG: %s %s %s" %(hid, pids, pdata) #print "DEBUG: %s %s %s" %(hid, pids, pdata)
inserts = [] inserts = []
for p in pdata: for p in pdata:
line = [0]*85 line = [0]*85
line[0] = 1 # HDs line[0] = 1 # HDs
if pdata[p]['street0VPI']: line[1] = 1 if pdata[p]['street0VPI']: line[1] = 1
if pdata[p]['street0Aggr']: line[2] = 1 if pdata[p]['street0Aggr']: line[2] = 1
@ -1917,7 +1939,7 @@ class Database:
# Test statusmessage to see if update worked, do insert if not # Test statusmessage to see if update worked, do insert if not
# num is a cursor in sqlite # num is a cursor in sqlite
if ((self.backend == self.PGSQL and cursor.statusmessage != "UPDATE 1") if ((self.backend == self.PGSQL and cursor.statusmessage != "UPDATE 1")
or (self.backend == self.MYSQL_INNODB and num == 0) or (self.backend == self.MYSQL_INNODB and num == 0)
or (self.backend == self.SQLITE and num.rowcount == 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 #move the last 6 items in WHERE clause of row from the end of the array
# to the beginning for the INSERT statement # to the beginning for the INSERT statement
@ -1941,14 +1963,14 @@ class Database:
def getGameTypeId(self, siteid, game): def getGameTypeId(self, siteid, game):
c = self.get_cursor() c = self.get_cursor()
#FIXME: Fixed for NL at the moment #FIXME: Fixed for NL at the moment
c.execute(self.sql.query['getGametypeNL'], (siteid, game['type'], game['category'], game['limitType'], game['currency'], c.execute(self.sql.query['getGametypeNL'], (siteid, game['type'], game['category'], game['limitType'], game['currency'],
int(Decimal(game['sb'])*100), int(Decimal(game['bb'])*100))) int(Decimal(game['sb'])*100), int(Decimal(game['bb'])*100)))
tmp = c.fetchone() tmp = c.fetchone()
if (tmp == None): if (tmp == None):
hilo = "h" hilo = "h"
if game['category'] in ['studhilo', 'omahahilo']: if game['category'] in ['studhilo', 'omahahilo']:
hilo = "s" hilo = "s"
elif game['category'] in ['razz','27_3draw','badugi']: elif game['category'] in ['razz','27_3draw','badugi', '27_1draw']:
hilo = "l" hilo = "l"
tmp = self.insertGameTypes( (siteid, game['currency'], game['type'], game['base'], game['category'], game['limitType'], hilo, tmp = self.insertGameTypes( (siteid, game['currency'], game['type'], game['base'], game['category'], game['limitType'], hilo,
int(Decimal(game['sb'])*100), int(Decimal(game['bb'])*100), int(Decimal(game['sb'])*100), int(Decimal(game['bb'])*100),
@ -1963,7 +1985,7 @@ class Database:
result = {} result = {}
if(self.pcache == None): if(self.pcache == None):
self.pcache = LambdaDict(lambda key:self.insertPlayer(key[0], key[1])) self.pcache = LambdaDict(lambda key:self.insertPlayer(key[0], key[1]))
for player in pnames: for player in pnames:
result[player] = self.pcache[(player,siteid)] result[player] = self.pcache[(player,siteid)]
# NOTE: Using the LambdaDict does the same thing as: # NOTE: Using the LambdaDict does the same thing as:
@ -2047,7 +2069,7 @@ class Database:
sendFinal = True sendFinal = True
else: else:
self.store_the_hand(h) self.store_the_hand(h)
# optional commit, could be every hand / every N hands / every time a # optional commit, could be every hand / every N hands / every time a
# commit message received?? mark flag to indicate if commits outstanding # commit message received?? mark flag to indicate if commits outstanding
if commitEachHand: if commitEachHand:
self.commit() self.commit()
@ -2093,7 +2115,7 @@ class Database:
def createTourneyType(self, hand):#note: this method is used on Hand and TourneySummary objects def createTourneyType(self, hand):#note: this method is used on Hand and TourneySummary objects
tourneyTypeId = 1 tourneyTypeId = 1
# Check if Tourney exists, and if so retrieve TTypeId : in that case, check values of the ttype # Check if Tourney exists, and if so retrieve TTypeId : in that case, check values of the ttype
cursor = self.get_cursor() cursor = self.get_cursor()
cursor.execute (self.sql.query['getTourneyTypeIdByTourneyNo'].replace('%s', self.sql.query['placeholder']), cursor.execute (self.sql.query['getTourneyTypeIdByTourneyNo'].replace('%s', self.sql.query['placeholder']),
@ -2108,14 +2130,14 @@ class Database:
# Check for an existing TTypeId that matches tourney info, if not found create it # Check for an existing TTypeId that matches tourney info, if not found create it
#print "info that we use to get TT by detail:", hand.siteId, hand.buyinCurrency, hand.buyin, hand.fee, hand.gametype['category'], hand.gametype['limitType'], hand.isKO, hand.isRebuy, hand.isAddOn, hand.speed, hand.isShootout, hand.isMatrix #print "info that we use to get TT by detail:", hand.siteId, hand.buyinCurrency, hand.buyin, hand.fee, hand.gametype['category'], hand.gametype['limitType'], hand.isKO, hand.isRebuy, hand.isAddOn, hand.speed, hand.isShootout, hand.isMatrix
#print "the query:",self.sql.query['getTourneyTypeId'].replace('%s', self.sql.query['placeholder']) #print "the query:",self.sql.query['getTourneyTypeId'].replace('%s', self.sql.query['placeholder'])
cursor.execute (self.sql.query['getTourneyTypeId'].replace('%s', self.sql.query['placeholder']), cursor.execute (self.sql.query['getTourneyTypeId'].replace('%s', self.sql.query['placeholder']),
(hand.siteId, hand.buyinCurrency, hand.buyin, hand.fee, hand.gametype['category'], (hand.siteId, hand.buyinCurrency, hand.buyin, hand.fee, hand.gametype['category'],
hand.gametype['limitType'], hand.maxseats, hand.isKO, hand.gametype['limitType'], hand.maxseats, hand.isKO,
hand.isRebuy, hand.isAddOn, hand.speed, hand.isShootout, hand.isMatrix) hand.isRebuy, hand.isAddOn, hand.speed, hand.isShootout, hand.isMatrix)
) )
result=cursor.fetchone() result=cursor.fetchone()
#print "result of fetching TT by details:",result #print "result of fetching TT by details:",result
try: try:
tourneyTypeId = result[0] tourneyTypeId = result[0]
except TypeError: #this means we need to create a new entry except TypeError: #this means we need to create a new entry
@ -2128,14 +2150,14 @@ class Database:
tourneyTypeId = self.get_last_insert_id(cursor) tourneyTypeId = self.get_last_insert_id(cursor)
return tourneyTypeId return tourneyTypeId
#end def createTourneyType #end def createTourneyType
def createOrUpdateTourney(self, hand, source):#note: this method is used on Hand and TourneySummary objects def createOrUpdateTourney(self, hand, source):#note: this method is used on Hand and TourneySummary objects
cursor = self.get_cursor() cursor = self.get_cursor()
cursor.execute (self.sql.query['getTourneyByTourneyNo'].replace('%s', self.sql.query['placeholder']), cursor.execute (self.sql.query['getTourneyByTourneyNo'].replace('%s', self.sql.query['placeholder']),
(hand.siteId, hand.tourNo)) (hand.siteId, hand.tourNo))
columnNames=[desc[0] for desc in cursor.description] columnNames=[desc[0] for desc in cursor.description]
result=cursor.fetchone() result=cursor.fetchone()
if result != None: if result != None:
if self.backend == Database.PGSQL: if self.backend == Database.PGSQL:
expectedValues = ('comment', 'tourneyname', 'matrixIdProcessed', 'totalRebuyCount', 'totalAddOnCount', expectedValues = ('comment', 'tourneyname', 'matrixIdProcessed', 'totalRebuyCount', 'totalAddOnCount',
@ -2145,7 +2167,7 @@ class Database:
'prizepool', 'startTime', 'entries', 'commentTs', 'endTime') 'prizepool', 'startTime', 'entries', 'commentTs', 'endTime')
updateDb=False updateDb=False
resultDict = dict(zip(columnNames, result)) resultDict = dict(zip(columnNames, result))
tourneyId = resultDict["id"] tourneyId = resultDict["id"]
if source=="TS": if source=="TS":
for ev in expectedValues : for ev in expectedValues :
@ -2174,7 +2196,7 @@ class Database:
tourneyId = self.get_last_insert_id(cursor) tourneyId = self.get_last_insert_id(cursor)
return tourneyId return tourneyId
#end def createOrUpdateTourney #end def createOrUpdateTourney
def createOrUpdateTourneysPlayers(self, hand, source):#note: this method is used on Hand and TourneySummary objects def createOrUpdateTourneysPlayers(self, hand, source):#note: this method is used on Hand and TourneySummary objects
tourneysPlayersIds={} tourneysPlayersIds={}
for player in hand.players: for player in hand.players:
@ -2184,7 +2206,7 @@ class Database:
playerId = hand.dbid_pids[player[1]] playerId = hand.dbid_pids[player[1]]
else: else:
raise FpdbParseError(_("invalid source in Database.createOrUpdateTourneysPlayers")) raise FpdbParseError(_("invalid source in Database.createOrUpdateTourneysPlayers"))
cursor = self.get_cursor() cursor = self.get_cursor()
cursor.execute (self.sql.query['getTourneysPlayersByIds'].replace('%s', self.sql.query['placeholder']), cursor.execute (self.sql.query['getTourneysPlayersByIds'].replace('%s', self.sql.query['placeholder']),
(hand.tourneyId, playerId)) (hand.tourneyId, playerId))
@ -2195,14 +2217,14 @@ class Database:
expectedValues = ('rank', 'winnings', 'winningsCurrency', 'rebuyCount', 'addOnCount', 'koCount') expectedValues = ('rank', 'winnings', 'winningsCurrency', 'rebuyCount', 'addOnCount', 'koCount')
updateDb=False updateDb=False
resultDict = dict(zip(columnNames, result)) resultDict = dict(zip(columnNames, result))
tourneysPlayersIds[player[1]]=result[0] tourneysPlayersIds[player[1]]=result[0]
if source=="TS": if source=="TS":
for ev in expectedValues : for ev in expectedValues :
handAttribute=ev handAttribute=ev
if ev!="winnings" and ev!="winningsCurrency": if ev!="winnings" and ev!="winningsCurrency":
handAttribute+="s" handAttribute+="s"
if getattr(hand, handAttribute)[player]==None and resultDict[ev]!=None:#DB has this value but object doesnt, so update object if getattr(hand, handAttribute)[player]==None and resultDict[ev]!=None:#DB has this value but object doesnt, so update object
setattr(hand, handAttribute, resultDict[ev][player]) setattr(hand, handAttribute, resultDict[ev][player])
elif getattr(hand, handAttribute)[player]!=None and resultDict[ev]==None:#object has this value but DB doesnt, so update DB elif getattr(hand, handAttribute)[player]!=None and resultDict[ev]==None:#object has this value but DB doesnt, so update DB
@ -2228,7 +2250,7 @@ class Database:
tourneysPlayersIds[player[1]]=self.get_last_insert_id(cursor) tourneysPlayersIds[player[1]]=self.get_last_insert_id(cursor)
return tourneysPlayersIds return tourneysPlayersIds
#end def createOrUpdateTourneysPlayers #end def createOrUpdateTourneysPlayers
def getTourneyTypesIds(self): def getTourneyTypesIds(self):
c = self.connection.cursor() c = self.connection.cursor()
c.execute(self.sql.query['getTourneyTypesIds']) c.execute(self.sql.query['getTourneyTypesIds'])
@ -2240,31 +2262,31 @@ class Database:
c = self.get_cursor() c = self.get_cursor()
c.execute(self.sql.query['getTourneyInfo'], (siteName, tourneyNo)) c.execute(self.sql.query['getTourneyInfo'], (siteName, tourneyNo))
columnNames=c.description columnNames=c.description
names=[] names=[]
for column in columnNames: for column in columnNames:
names.append(column[0]) names.append(column[0])
data=c.fetchone() data=c.fetchone()
return (names,data) return (names,data)
#end def getTourneyInfo #end def getTourneyInfo
def getTourneyPlayerInfo(self, siteName, tourneyNo, playerName): def getTourneyPlayerInfo(self, siteName, tourneyNo, playerName):
c = self.get_cursor() c = self.get_cursor()
c.execute(self.sql.query['getTourneyPlayerInfo'], (siteName, tourneyNo, playerName)) c.execute(self.sql.query['getTourneyPlayerInfo'], (siteName, tourneyNo, playerName))
columnNames=c.description columnNames=c.description
names=[] names=[]
for column in columnNames: for column in columnNames:
names.append(column[0]) names.append(column[0])
data=c.fetchone() data=c.fetchone()
return (names,data) return (names,data)
#end def getTourneyPlayerInfo #end def getTourneyPlayerInfo
#end class Database #end class Database
# Class used to hold all the data needed to write a hand to the db # Class used to hold all the data needed to write a hand to the db
# mainParser() in fpdb_parse_logic.py creates one of these and then passes it to # mainParser() in fpdb_parse_logic.py creates one of these and then passes it to
# self.insert_queue_hands() # self.insert_queue_hands()
class HandToWrite: class HandToWrite:
@ -2312,7 +2334,7 @@ class HandToWrite:
print _("HandToWrite.init error: ") + str(sys.exc_info()) print _("HandToWrite.init error: ") + str(sys.exc_info())
raise raise
# end def __init__ # end def __init__
def set_all( self, config, settings, base, category, siteTourneyNo, buyin def set_all( self, config, settings, base, category, siteTourneyNo, buyin
, fee, knockout, entries, prizepool, tourneyStartTime , fee, knockout, entries, prizepool, tourneyStartTime
, isTourney, tourneyTypeId, siteID, siteHandNo , isTourney, tourneyTypeId, siteID, siteHandNo
@ -2320,7 +2342,7 @@ class HandToWrite:
, positions, antes, cardValues, cardSuits, boardValues, boardSuits , positions, antes, cardValues, cardSuits, boardValues, boardSuits
, winnings, rakes, actionTypes, allIns, actionAmounts , winnings, rakes, actionTypes, allIns, actionAmounts
, actionNos, hudImportData, maxSeats, tableName, seatNos): , actionNos, hudImportData, maxSeats, tableName, seatNos):
try: try:
self.config = config self.config = config
self.settings = settings self.settings = settings
@ -2366,7 +2388,7 @@ class HandToWrite:
def get_finished(self): def get_finished(self):
return( self.finished ) return( self.finished )
# end def get_finished # end def get_finished
def get_siteHandNo(self): def get_siteHandNo(self):
return( self.siteHandNo ) return( self.siteHandNo )
# end def get_siteHandNo # end def get_siteHandNo
@ -2384,14 +2406,14 @@ if __name__=="__main__":
# db_connection.recreate_tables() # db_connection.recreate_tables()
db_connection.dropAllIndexes() db_connection.dropAllIndexes()
db_connection.createAllIndexes() db_connection.createAllIndexes()
h = db_connection.get_last_hand() h = db_connection.get_last_hand()
print "last hand = ", h print "last hand = ", h
hero = db_connection.get_player_id(c, 'PokerStars', 'nutOmatic') hero = db_connection.get_player_id(c, 'PokerStars', 'nutOmatic')
if hero: if hero:
print _("nutOmatic is id_player = %d") % hero print _("nutOmatic is id_player = %d") % hero
# example of displaying query plan in sqlite: # example of displaying query plan in sqlite:
if db_connection.backend == 4: if db_connection.backend == 4:
print print
@ -2400,16 +2422,16 @@ if __name__=="__main__":
for row in c.fetchall(): for row in c.fetchall():
print _("query plan: "), row print _("query plan: "), row
print print
t0 = time() t0 = time()
stat_dict = db_connection.get_stats_from_hand(h, "ring") stat_dict = db_connection.get_stats_from_hand(h, "ring")
t1 = time() t1 = time()
for p in stat_dict.keys(): for p in stat_dict.keys():
print p, " ", stat_dict[p] print p, " ", stat_dict[p]
print _("cards ="), db_connection.get_cards(u'1') print _("cards ="), db_connection.get_cards(u'1')
db_connection.close_connection db_connection.close_connection
print _("get_stats took: %4.3f seconds") % (t1-t0) print _("get_stats took: %4.3f seconds") % (t1-t0)
print _("press enter to continue") print _("press enter to continue")

View File

@ -23,13 +23,6 @@ import logging
# logging has been set up in fpdb.py or HUD_main.py, use their settings: # logging has been set up in fpdb.py or HUD_main.py, use their settings:
log = logging.getLogger("parser") log = logging.getLogger("parser")
DEBUG = False
if DEBUG:
import pprint
pp = pprint.PrettyPrinter(indent=4)
class DerivedStats(): class DerivedStats():
def __init__(self, hand): def __init__(self, hand):
self.hand = hand self.hand = hand
@ -93,17 +86,9 @@ class DerivedStats():
self.assembleHands(self.hand) self.assembleHands(self.hand)
self.assembleHandsPlayers(self.hand) self.assembleHandsPlayers(self.hand)
if DEBUG: if self.hand.saveActions:
self.assembleHandsActions(self.hand) self.assembleHandsActions(self.hand)
if DEBUG:
#print "Hands:"
#pp.pprint(self.hands)
#print "HandsPlayers:"
#pp.pprint(self.handsplayers)
print "HandsActions:"
pp.pprint(self.handsactions)
def getHands(self): def getHands(self):
return self.hands return self.hands
@ -190,6 +175,12 @@ class DerivedStats():
self.handsplayers[player]['rake'] = int(100* hand.rake)/len(hand.collectees) self.handsplayers[player]['rake'] = int(100* hand.rake)/len(hand.collectees)
if self.handsplayers[player]['street1Seen'] == True: if self.handsplayers[player]['street1Seen'] == True:
self.handsplayers[player]['wonWhenSeenStreet1'] = 1.0 self.handsplayers[player]['wonWhenSeenStreet1'] = 1.0
if self.handsplayers[player]['street2Seen'] == True:
self.handsplayers[player]['wonWhenSeenStreet2'] = 1.0
if self.handsplayers[player]['street3Seen'] == True:
self.handsplayers[player]['wonWhenSeenStreet3'] = 1.0
if self.handsplayers[player]['street4Seen'] == True:
self.handsplayers[player]['wonWhenSeenStreet4'] = 1.0
if self.handsplayers[player]['sawShowdown'] == True: if self.handsplayers[player]['sawShowdown'] == True:
self.handsplayers[player]['wonAtSD'] = 1.0 self.handsplayers[player]['wonAtSD'] = 1.0
@ -216,9 +207,35 @@ class DerivedStats():
# Squeeze, Ratchet? # Squeeze, Ratchet?
def assembleHandsActions(self, hand): def assembleHandsActions(self, hand):
print "DEBUG: hand.actions" k = 0
pp.pprint(hand.actions) for i, street in enumerate(hand.actionStreets):
pass for j, act in enumerate(hand.actions[street]):
k += 1
self.handsactions[k] = {}
#default values
self.handsactions[k]['amount'] = 0
self.handsactions[k]['raiseTo'] = 0
self.handsactions[k]['amountCalled'] = 0
self.handsactions[k]['numDiscarded'] = 0
self.handsactions[k]['cardsDiscarded'] = None
self.handsactions[k]['allIn'] = False
#Insert values from hand.actions
self.handsactions[k]['player'] = act[0]
self.handsactions[k]['street'] = i-1
self.handsactions[k]['actionNo'] = k
self.handsactions[k]['streetActionNo'] = (j+1)
self.handsactions[k]['actionId'] = hand.ACTION[act[1]]
if act[1] not in ('discards') and len(act) > 2:
self.handsactions[k]['amount'] = int(100 * act[2])
if act[1] in ('raises', 'completes'):
self.handsactions[k]['raiseTo'] = int(100 * act[3])
self.handsactions[k]['amountCalled'] = int(100 * act[4])
if act[1] in ('discards'):
self.handsactions[k]['numDiscarded'] = int(act[2])
if act[1] in ('discards') and len(act) > 3:
self.handsactions[k]['cardsDiscarded'] = act[3]
if len(act) > 3 and act[1] not in ('discards'):
self.handsactions[k]['allIn'] = act[-1]
def setPositions(self, hand): def setPositions(self, hand):
"""Sets the position for each player in HandsPlayers """Sets the position for each player in HandsPlayers
@ -226,44 +243,34 @@ class DerivedStats():
first betting round is 0 first betting round is 0
NOTE: HU, both values are negative for non-stud games NOTE: HU, both values are negative for non-stud games
NOTE2: I've never seen a HU stud match""" NOTE2: I've never seen a HU stud match"""
# The position calculation must be done differently for Stud and other games as
# Stud the 'blind' acts first - in all other games they act last.
#
#This function is going to get it wrong when there in situations where there
# is no small blind. I can live with that.
actions = hand.actions[hand.holeStreets[0]] actions = hand.actions[hand.holeStreets[0]]
# Note: pfbao list may not include big blind if all others folded # Note: pfbao list may not include big blind if all others folded
players = self.pfbao(actions) players = self.pfbao(actions)
# set blinds first, then others from pfbao list, avoids problem if bb
# is missing from pfbao list or if there is no small blind
sb, bb, bi = False, False, False
if hand.gametype['base'] == 'stud': if hand.gametype['base'] == 'stud':
positions = [7, 6, 5, 4, 3, 2, 1, 0, 'S', 'B'] # Stud position is determined after cards are dealt
seats = len(players) bi = [x[0] for x in hand.actions[hand.actionStreets[1]] if x[1] == 'bringin']
map = []
# Could posibly change this to be either -2 or -1 depending if they complete or bring-in
# First player to act is -1, last player is 0 for 6 players it should look like:
# ['S', 4, 3, 2, 1, 0]
map = positions[-seats-1:-1] # Copy required positions from postions array anding in -1
map = map[-1:] + map[0:-1] # and move the -1 to the start of that array
for i, player in enumerate(players):
#print "player %s in posn %s" % (player, str(map[i]))
self.handsplayers[player]['position'] = map[i]
else: else:
# set blinds first, then others from pfbao list, avoids problem if bb bb = [x[0] for x in hand.actions[hand.actionStreets[0]] if x[1] == 'big blind']
# is missing from pfbao list or if there is no small blind sb = [x[0] for x in hand.actions[hand.actionStreets[0]] if x[1] == 'small blind']
bb = [x[0] for x in hand.actions[hand.actionStreets[0]] if x[2] == 'big blind']
sb = [x[0] for x in hand.actions[hand.actionStreets[0]] if x[2] == 'small blind']
# if there are > 1 sb or bb only the first is used!
if bb:
self.handsplayers[bb[0]]['position'] = 'B'
if bb[0] in players: players.remove(bb[0])
if sb:
self.handsplayers[sb[0]]['position'] = 'S'
if sb[0] in players: players.remove(sb[0])
#print "bb =", bb, "sb =", sb, "players =", players # if there are > 1 sb or bb only the first is used!
for i,player in enumerate(reversed(players)): if bb:
self.handsplayers[player]['position'] = i self.handsplayers[bb[0]]['position'] = 'B'
if bb[0] in players: players.remove(bb[0])
if sb:
self.handsplayers[sb[0]]['position'] = 'S'
if sb[0] in players: players.remove(sb[0])
if bi:
self.handsplayers[bi[0]]['position'] = 'S'
if bi[0] in players: players.remove(bi[0])
#print "DEBUG: bb: '%s' sb: '%s' bi: '%s' plyrs: '%s'" %(bb, sb, bi, players)
for i,player in enumerate(reversed(players)):
self.handsplayers[player]['position'] = i
def assembleHudCache(self, hand): def assembleHudCache(self, hand):
# No real work to be done - HandsPlayers data already contains the correct info # No real work to be done - HandsPlayers data already contains the correct info
@ -272,7 +279,7 @@ class DerivedStats():
def vpip(self, hand): def vpip(self, hand):
vpipers = set() vpipers = set()
for act in hand.actions[hand.actionStreets[1]]: for act in hand.actions[hand.actionStreets[1]]:
if act[1] in ('calls','bets', 'raises'): if act[1] in ('calls','bets', 'raises', 'completes'):
vpipers.add(act[0]) vpipers.add(act[0])
self.hands['playersVpi'] = len(vpipers) self.hands['playersVpi'] = len(vpipers)
@ -370,9 +377,9 @@ class DerivedStats():
if steal_attempt and act != 'folds': if steal_attempt and act != 'folds':
break break
if not steal_attempt and not raised: # if posn in steal_positions and not steal_attempt: if not steal_attempt and not raised and not act in ('bringin'):
self.handsplayers[pname]['raiseFirstInChance'] = True self.handsplayers[pname]['raiseFirstInChance'] = True
if act in ('bets', 'raises'): if act in ('bets', 'raises', 'completes'):
self.handsplayers[pname]['raisedFirstIn'] = True self.handsplayers[pname]['raisedFirstIn'] = True
raised = True raised = True
if posn in steal_positions: if posn in steal_positions:
@ -380,7 +387,7 @@ class DerivedStats():
if act == 'calls': if act == 'calls':
break break
if posn not in steal_positions and act != 'folds': if posn not in steal_positions and act not in ('folds', 'bringin'):
break break
def calc34BetStreet0(self, hand): def calc34BetStreet0(self, hand):

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Copyright 2008-2010, Carl Gherardi # Copyright 2008-2010, Carl Gherardi
@ -18,22 +18,13 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
######################################################################## ########################################################################
import L10n
_ = L10n.get_translation()
import sys import sys
import logging import logging
from HandHistoryConverter import * from HandHistoryConverter import *
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 for converting Everleaf HH format. # Class for converting Everleaf HH format.
class Everleaf(HandHistoryConverter): class Everleaf(HandHistoryConverter):
@ -75,13 +66,16 @@ class Everleaf(HandHistoryConverter):
self.re_SitsOut = re.compile(ur"^%s sits out" % player_re, re.MULTILINE) self.re_SitsOut = re.compile(ur"^%s sits out" % player_re, re.MULTILINE)
def readSupportedGames(self): def readSupportedGames(self):
return [["ring", "hold", "nl"], return [
["ring", "hold", "nl"],
["ring", "hold", "pl"], ["ring", "hold", "pl"],
["ring", "hold", "fl"], ["ring", "hold", "fl"],
["ring", "studhi", "fl"], ["ring", "stud", "fl"],
["ring", "omahahi", "pl"], #["ring", "omahahi", "pl"],
["ring", "omahahilo", "pl"], #["ring", "omahahilo", "pl"],
["tour", "hold", "nl"] ["tour", "hold", "nl"],
["tour", "hold", "fl"],
["tour", "hold", "pl"]
] ]
def determineGameType(self, handText): def determineGameType(self, handText):
@ -151,7 +145,7 @@ or None if we fail to get the info """
logging.debug("HID %s, Table %s" % (m.group('HID'), m.group('TABLE'))) logging.debug("HID %s, Table %s" % (m.group('HID'), m.group('TABLE')))
hand.handid = m.group('HID') hand.handid = m.group('HID')
hand.tablename = m.group('TABLE') hand.tablename = m.group('TABLE')
hand.maxseats = 6 # assume 6-max unless we have proof it's a larger/smaller game, since everleaf doesn't give seat max info hand.maxseats = 4 # assume 4-max unless we have proof it's a larger/smaller game, since everleaf doesn't give seat max info
currencies = { u'':'EUR', '$':'USD', '':'T$', None:'T$' } currencies = { u'':'EUR', '$':'USD', '':'T$', None:'T$' }
mg = m.groupdict() mg = m.groupdict()
@ -180,9 +174,13 @@ or None if we fail to get the info """
for a in m: for a in m:
seatnum = int(a.group('SEAT')) seatnum = int(a.group('SEAT'))
hand.addPlayer(seatnum, a.group('PNAME'), a.group('CASH')) hand.addPlayer(seatnum, a.group('PNAME'), a.group('CASH'))
if seatnum > 6: if seatnum > 8:
hand.maxseats = 10 # everleaf currently does 2/6/10 games, so if seats > 6 are in use, it must be 10-max. hand.maxseats = 10 # they added 8-seat games now
elif seatnum > 6:
hand.maxseats = 8 # everleaf currently does 2/6/10 games, so if seats > 6 are in use, it must be 10-max.
# TODO: implement lookup list by table-name to determine maxes, then fall back to 6 default/10 here, if there's no entry in the list? # TODO: implement lookup list by table-name to determine maxes, then fall back to 6 default/10 here, if there's no entry in the list?
elif seatnum > 4:
hand.maxseats = 6 # they added 4-seat games too!
def markStreets(self, hand): def markStreets(self, hand):

View File

@ -73,3 +73,6 @@ class FpdbHandDuplicate(FpdbHandError):
class FpdbHandPartial(FpdbHandError): class FpdbHandPartial(FpdbHandError):
pass pass
class FpdbEndOfFile(FpdbHandError):
pass

View File

@ -15,6 +15,9 @@
#along with this program. If not, see <http://www.gnu.org/licenses/>. #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. #In the "official" distribution you can find the license in agpl-3.0.txt.
import L10n
_ = L10n.get_translation()
import threading import threading
import pygtk import pygtk
pygtk.require('2.0') pygtk.require('2.0')
@ -30,18 +33,6 @@ import logging
# logging has been set up in fpdb.py or HUD_main.py, use their settings: # logging has been set up in fpdb.py or HUD_main.py, use their settings:
log = logging.getLogger("filter") log = logging.getLogger("filter")
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
import Configuration import Configuration
import Database import Database
import SQL import SQL
@ -71,6 +62,7 @@ class Filters(threading.Thread):
gen = self.conf.get_general_params() gen = self.conf.get_general_params()
self.day_start = 0 self.day_start = 0
if 'day_start' in gen: if 'day_start' in gen:
self.day_start = float(gen['day_start']) self.day_start = float(gen['day_start'])
@ -92,6 +84,7 @@ class Filters(threading.Thread):
self.siteid = {} self.siteid = {}
self.heroes = {} self.heroes = {}
self.boxes = {} self.boxes = {}
self.graphops = {}
for site in self.conf.get_supported_sites(): for site in self.conf.get_supported_sites():
#Get db site id for filtering later #Get db site id for filtering later
@ -112,6 +105,12 @@ class Filters(threading.Thread):
self.sbGroups = {} self.sbGroups = {}
self.numHands = 0 self.numHands = 0
# for use in graphops
# dspin = display in '$' or 'B'
self.graphops['dspin'] = "$"
self.graphops['showdown'] = 'OFF'
self.graphops['nonshowdown'] = 'OFF'
playerFrame = gtk.Frame() playerFrame = gtk.Frame()
playerFrame.set_label_align(0.0, 0.0) playerFrame.set_label_align(0.0, 0.0)
vbox = gtk.VBox(False, 0) vbox = gtk.VBox(False, 0)
@ -152,6 +151,16 @@ class Filters(threading.Thread):
self.fillLimitsFrame(vbox, self.display) self.fillLimitsFrame(vbox, self.display)
limitsFrame.add(vbox) limitsFrame.add(vbox)
# GraphOps
graphopsFrame = gtk.Frame()
#graphops.set_label_align(0,0, 0.0)
graphopsFrame.show()
vbox = gtk.VBox(False, 0)
self.fillGraphOpsFrame(vbox)
graphopsFrame.add(vbox)
# Seats # Seats
seatsFrame = gtk.Frame() seatsFrame = gtk.Frame()
seatsFrame.show() seatsFrame.show()
@ -192,6 +201,7 @@ class Filters(threading.Thread):
self.mainVBox.add(seatsFrame) self.mainVBox.add(seatsFrame)
self.mainVBox.add(groupsFrame) self.mainVBox.add(groupsFrame)
self.mainVBox.add(dateFrame) self.mainVBox.add(dateFrame)
self.mainVBox.add(graphopsFrame)
self.mainVBox.add(self.Button1) self.mainVBox.add(self.Button1)
self.mainVBox.add(self.Button2) self.mainVBox.add(self.Button2)
@ -212,6 +222,8 @@ class Filters(threading.Thread):
groupsFrame.hide() groupsFrame.hide()
if "Dates" not in self.display or self.display["Dates"] == False: if "Dates" not in self.display or self.display["Dates"] == False:
dateFrame.hide() dateFrame.hide()
if "GraphOps" not in self.display or self.display["GraphOps"] == False:
graphopsFrame.hide()
if "Button1" not in self.display or self.display["Button1"] == False: if "Button1" not in self.display or self.display["Button1"] == False:
self.Button1.hide() self.Button1.hide()
if "Button2" not in self.display or self.display["Button2"] == False: if "Button2" not in self.display or self.display["Button2"] == False:
@ -264,6 +276,9 @@ class Filters(threading.Thread):
return self.heroes return self.heroes
#end def getHeroes #end def getHeroes
def getGraphOps(self):
return self.graphops
def getLimits(self): def getLimits(self):
ltuple = [] ltuple = []
for l in self.limits: for l in self.limits:
@ -548,6 +563,14 @@ class Filters(threading.Thread):
self.groups[group] = w.get_active() self.groups[group] = w.get_active()
log.debug( _("self.groups[%s] set to %s") %(group, self.groups[group]) ) log.debug( _("self.groups[%s] set to %s") %(group, self.groups[group]) )
def __set_displayin_select(self, w, ops):
self.graphops['dspin'] = ops
def __set_graphopscheck_select(self, w, data):
#print "%s was toggled %s" % (data, ("OFF", "ON")[w.get_active()])
self.graphops[data] = ("OFF", "ON")[w.get_active()]
def fillPlayerFrame(self, vbox, display): def fillPlayerFrame(self, vbox, display):
top_hbox = gtk.HBox(False, 0) top_hbox = gtk.HBox(False, 0)
vbox.pack_start(top_hbox, False, False, 0) vbox.pack_start(top_hbox, False, False, 0)
@ -779,8 +802,58 @@ class Filters(threading.Thread):
# set_active doesn't seem to call this for some reason so call manually: # set_active doesn't seem to call this for some reason so call manually:
self.__set_limit_select(rb1, 'ring') self.__set_limit_select(rb1, 'ring')
self.type = 'ring' self.type = 'ring'
top_hbox.pack_start(showb, expand=False, padding=1)
def fillGraphOpsFrame(self, vbox):
top_hbox = gtk.HBox(False, 0)
vbox.pack_start(top_hbox, False, False, 0)
title = gtk.Label("Graphing Options:")
title.set_alignment(xalign=0.0, yalign=0.5)
top_hbox.pack_start(title, expand=True, padding=3)
showb = gtk.Button(label="hide", stock=None, use_underline=True)
showb.set_alignment(xalign=1.0, yalign=0.5)
showb.connect('clicked', self.__toggle_box, 'games')
top_hbox.pack_start(showb, expand=False, padding=1) top_hbox.pack_start(showb, expand=False, padding=1)
hbox1 = gtk.HBox(False, 0)
vbox.pack_start(hbox1, False, False, 0)
hbox1.show()
label = gtk.Label("Show Graph In:")
label.set_alignment(xalign=0.0, yalign=0.5)
hbox1.pack_start(label, True, True, 0)
label.show()
button = gtk.RadioButton(None, "$$")
hbox1.pack_start(button, True, True, 0)
button.connect("toggled", self.__set_displayin_select, "$")
button.set_active(True)
button.show()
button = gtk.RadioButton(button, "BB")
hbox1.pack_start(button, True, True, 0)
button.connect("toggled", self.__set_displayin_select, "BB")
button.show()
vbox1 = gtk.VBox(False, 0)
vbox.pack_start(vbox1, False, False, 0)
vbox1.show()
button = gtk.CheckButton("Showdown Winnings", False)
vbox1.pack_start(button, True, True, 0)
# wouldn't it be awesome if there was a way to remember the state of things like
# this and be able to set it to what it was last time?
#button.set_active(True)
button.connect("toggled", self.__set_graphopscheck_select, "showdown")
button.show()
button = gtk.CheckButton("Non-Showdown Winnings", False)
vbox1.pack_start(button, True, True, 0)
# ditto as 8 lines up :)
#button.set_active(True)
button.connect("toggled", self.__set_graphopscheck_select, "nonshowdown");
button.show()
def fillSeatsFrame(self, vbox, display): def fillSeatsFrame(self, vbox, display):
hbox = gtk.HBox(False, 0) hbox = gtk.HBox(False, 0)
vbox.pack_start(hbox, False, False, 0) vbox.pack_start(hbox, False, False, 0)

View File

@ -0,0 +1,129 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#Copyright 2008-2010 Steffen Schaumburg
#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.
"""pokerstars-specific summary parsing code"""
import L10n
_ = L10n.get_translation()
from decimal import Decimal
import datetime
from Exceptions import FpdbParseError
from HandHistoryConverter import *
import PokerStarsToFpdb
from TourneySummary import *
class FullTiltPokerSummary(TourneySummary):
limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl', 'LIMIT':'fl' }
games = { # base, category
"Hold'em" : ('hold','holdem'),
'Omaha' : ('hold','omahahi'),
'Omaha Hi/Lo' : ('hold','omahahilo'),
'Razz' : ('stud','razz'),
'RAZZ' : ('stud','razz'),
'7 Card Stud' : ('stud','studhi'),
'7 Card Stud Hi/Lo' : ('stud','studhilo'),
'Badugi' : ('draw','badugi'),
'Triple Draw 2-7 Lowball' : ('draw','27_3draw'),
'5 Card Draw' : ('draw','fivedraw')
}
substitutions = {
'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
'LS' : "\$|\xe2\x82\xac|" # legal currency symbols - Euro(cp1252, utf-8)
}
re_SplitTourneys = re.compile("^Full Tilt Poker Tournament Summary")
re_TourNo = re.compile("\#(?P<TOURNO>[0-9]+),")
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<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+)?
(?P<ENTRIES>[0-9]+)\sEntries\s+
(\$?(?P<ADDED>[.\d]+)\sadded\sto\sthe\sprize\spool\sby\sPokerStars\.com\s+)?
(Total\sPrize\sPool:\s\$?(?P<PRIZEPOOL>[.0-9]+)\s+)?
(Target\sTournament\s.*)?
Tournament\sstarted:\s
(?P<Y>[\d]{4})\/(?P<M>[\d]{2})\/(?P<D>[\d]+)\s+(?P<H>[\d]+):(?P<MIN>[\d]+):(?P<S>[\d]+)\s??(?P<TZ>[A-Z]+)\s
""" % substitutions ,re.VERBOSE|re.MULTILINE|re.DOTALL)
re_Currency = re.compile(u"""(?P<CURRENCY>[%(LS)s]|FPP)""" % substitutions)
re_Player = re.compile(u"""(?P<RANK>[\d]+):\s(?P<NAME>[^,\r\n]{2,15})(,(\s)?\$(?P<WINNINGS>[.\d]+))?""")
re_DateTime = re.compile("\[(?P<Y>[0-9]{4})\/(?P<M>[0-9]{2})\/(?P<D>[0-9]{2})[\- ]+(?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)")
codepage = ["utf-16", "cp1252", "utf-8"]
def parseSummary(self):
m = self.re_TourneyInfo.search(self.summaryText)
if m == None:
tmp = self.summaryText[0:200]
log.error(_("parseSummary: Unable to recognise Tourney Info: '%s'") % tmp)
log.error(_("parseSummary: Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise Tourney Info: '%s'") % tmp)
print "DEBUG: m.groupdict(): %s" % m.groupdict()
mg = m.groupdict()
if 'TOURNO' in mg: self.tourNo = mg['TOURNO']
if 'LIMIT' in mg: self.gametype['limitType'] = self.limits[mg['LIMIT']]
if 'GAME' in mg: self.gametype['category'] = self.games[mg['GAME']][1]
if mg['BUYIN'] != None:
self.buyin = int(100*Decimal(mg['BUYIN']))
if mg['FEE'] != None:
self.fee = int(100*Decimal(mg['FEE']))
if 'PRIZEPOOL' in mg: self.prizepool = mg['PRIZEPOOL']
if 'ENTRIES' in mg: self.entries = mg['ENTRIES']
datetimestr = "%s/%s/%s %s:%s:%s" % (mg['Y'], mg['M'], mg['D'], mg['H'], mg['MIN'], mg['S'])
self.startTime = datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S")
if 'TZ' in mg:
self.startTime = HandHistoryConverter.changeTimezone(self.startTime, mg['TZ'], "UTC")
m = self.re_Currency.search(self.summaryText)
if m == None:
log.error(_("parseSummary: Unable to locate currency"))
log.error(_("parseSummary: Raising FpdbParseError"))
raise FpdbParseError(_("Unable to locate currency"))
#print "DEBUG: m.groupdict(): %s" % m.groupdict()
mg = m.groupdict()
if mg['CURRENCY'] == "$": self.currency = "USD"
elif mg['CURRENCY'] == u"": self.currency="EUR"
elif mg['CURRENCY'] == "FPP": self.currency="PSFP"
m = self.re_Player.finditer(self.summaryText)
for a in m:
mg = a.groupdict()
print "DEBUG: a.groupdict(): %s" % mg
name = mg['NAME']
rank = mg['RANK']
winnings = 0
if 'WINNINGS' in mg and mg['WINNINGS'] != None:
winnings = int(100*Decimal(mg['WINNINGS']))
self.addPlayer(rank, name, winnings, self.currency, None, None, None)

View File

@ -18,17 +18,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
######################################################################## ########################################################################
import locale import L10n
lang=locale.getdefaultlocale()[0][0:2] _ = L10n.get_translation()
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
import logging import logging
from HandHistoryConverter import * from HandHistoryConverter import *
@ -59,9 +50,9 @@ class Fulltilt(HandHistoryConverter):
(Ante\s\$?(?P<ANTE>[.0-9]+)\s)?-\s (Ante\s\$?(?P<ANTE>[.0-9]+)\s)?-\s
[%(LS)s]?(?P<CAP>[.0-9]+\sCap\s)? [%(LS)s]?(?P<CAP>[.0-9]+\sCap\s)?
(?P<LIMIT>(No\sLimit|Pot\sLimit|Limit))?\s (?P<LIMIT>(No\sLimit|Pot\sLimit|Limit))?\s
(?P<GAME>(Hold\'em|Omaha\sHi|Omaha\sH/L|7\sCard\sStud|Stud\sH/L|Razz|Stud\sHi)) (?P<GAME>(Hold\'em|Omaha\sHi|Omaha\sH/L|7\sCard\sStud|Stud\sH/L|Razz|Stud\sHi|2-7\sTriple\sDraw|5\sCard\sDraw|Badugi))
''' % substitutions, re.VERBOSE) ''' % substitutions, re.VERBOSE)
re_SplitHands = re.compile(r"\n\n+") re_SplitHands = re.compile(r"\n\n\n+")
re_TailSplitHands = re.compile(r"(\n\n+)") re_TailSplitHands = re.compile(r"(\n\n+)")
re_HandInfo = re.compile(r'''.*\#(?P<HID>[0-9]+):\s re_HandInfo = re.compile(r'''.*\#(?P<HID>[0-9]+):\s
(?:(?P<TOURNAMENT>.+)\s\((?P<TOURNO>\d+)\),\s)? (?:(?P<TOURNAMENT>.+)\s\((?P<TOURNO>\d+)\),\s)?
@ -71,7 +62,7 @@ class Fulltilt(HandHistoryConverter):
(\((?P<TABLEATTRIBUTES>.+)\)\s)?-\s (\((?P<TABLEATTRIBUTES>.+)\)\s)?-\s
[%(LS)s]?(?P<SB>[.0-9]+)/[%(LS)s]?(?P<BB>[.0-9]+)\s(Ante\s[%(LS)s]?(?P<ANTE>[.0-9]+)\s)?-\s [%(LS)s]?(?P<SB>[.0-9]+)/[%(LS)s]?(?P<BB>[.0-9]+)\s(Ante\s[%(LS)s]?(?P<ANTE>[.0-9]+)\s)?-\s
[%(LS)s]?(?P<CAP>[.0-9]+\sCap\s)? [%(LS)s]?(?P<CAP>[.0-9]+\sCap\s)?
(?P<GAMETYPE>[a-zA-Z\/\'\s]+)\s-\s (?P<GAMETYPE>[-\da-zA-Z\/\'\s]+)\s-\s
(?P<DATETIME>\d+:\d+:\d+\s(?P<TZ1>\w+)\s-\s\d+/\d+/\d+|\d+:\d+\s(?P<TZ2>\w+)\s-\s\w+\,\s\w+\s\d+\,\s\d+) (?P<DATETIME>\d+:\d+:\d+\s(?P<TZ1>\w+)\s-\s\d+/\d+/\d+|\d+:\d+\s(?P<TZ2>\w+)\s-\s\w+\,\s\w+\s\d+\,\s\d+)
(?P<PARTIAL>\(partial\))?\n (?P<PARTIAL>\(partial\))?\n
(?:.*?\n(?P<CANCELLED>Hand\s\#(?P=HID)\shas\sbeen\scanceled))? (?:.*?\n(?P<CANCELLED>Hand\s\#(?P=HID)\shas\sbeen\scanceled))?
@ -169,6 +160,10 @@ class Fulltilt(HandHistoryConverter):
["ring", "stud", "fl"], ["ring", "stud", "fl"],
["ring", "draw", "fl"],
["ring", "draw", "pl"],
["ring", "draw", "nl"],
["tour", "hold", "nl"], ["tour", "hold", "nl"],
["tour", "hold", "pl"], ["tour", "hold", "pl"],
["tour", "hold", "fl"], ["tour", "hold", "fl"],
@ -186,7 +181,10 @@ class Fulltilt(HandHistoryConverter):
m = self.re_GameInfo.search(handText) m = self.re_GameInfo.search(handText)
if not m: if not m:
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() mg = m.groupdict()
# translations from captured groups to our info strings # translations from captured groups to our info strings
@ -197,7 +195,10 @@ class Fulltilt(HandHistoryConverter):
'Omaha H/L' : ('hold','omahahilo'), 'Omaha H/L' : ('hold','omahahilo'),
'Razz' : ('stud','razz'), 'Razz' : ('stud','razz'),
'Stud Hi' : ('stud','studhi'), 'Stud Hi' : ('stud','studhi'),
'Stud H/L' : ('stud','studhilo') 'Stud H/L' : ('stud','studhilo'),
'2-7 Triple Draw' : ('draw','27_3draw'),
'5 Card Draw' : ('draw','fivedraw'),
'Badugi' : ('draw','badugi'),
} }
currencies = { u'':'EUR', '$':'USD', '':'T$' } currencies = { u'':'EUR', '$':'USD', '':'T$' }
if mg['CAP']: if mg['CAP']:
@ -218,9 +219,9 @@ class Fulltilt(HandHistoryConverter):
def readHandInfo(self, hand): def readHandInfo(self, hand):
m = self.re_HandInfo.search(hand.handText) m = self.re_HandInfo.search(hand.handText)
if m is None: if m is None:
logging.info(_("Didn't match re_HandInfo")) tmp = hand.handText[0:100]
logging.info(hand.handText) log.error(_("readHandInfo: Unable to recognise handinfo from: '%s'") % tmp)
raise FpdbParseError("No match in readHandInfo.") raise FpdbParseError(_("No match in readHandInfo."))
hand.handid = m.group('HID') hand.handid = m.group('HID')
hand.tablename = m.group('TABLE') hand.tablename = m.group('TABLE')
@ -277,27 +278,14 @@ class Fulltilt(HandHistoryConverter):
hand.isMatrix = True hand.isMatrix = True
if special == "Shootout": if special == "Shootout":
hand.isShootout = True hand.isShootout = True
if hand.buyin is None:
hand.buyin = 0
hand.fee=0
hand.buyinCurrency="NA"
if hand.buyin is None:
hand.buyin = "$0.00+$0.00"
if hand.level is None: if hand.level is None:
hand.level = "0" hand.level = "0"
# These work, but the info is already in the Hand class - should be used for tourneys though.
# m.group('SB')
# m.group('BB')
# m.group('GAMETYPE')
# 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)
#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')))
def readPlayerStacks(self, hand): def readPlayerStacks(self, hand):
# Split hand text for FTP, as the regex matches the player names incorrectly # Split hand text for FTP, as the regex matches the player names incorrectly
# in the summary section # in the summary section
@ -310,21 +298,28 @@ class Fulltilt(HandHistoryConverter):
for a in m: for a in m:
hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH')) hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH'))
def markStreets(self, hand): def markStreets(self, hand):
# PREFLOP = ** Dealing down cards **
if hand.gametype['base'] == 'hold': if hand.gametype['base'] == 'hold':
m = re.search(r"\*\*\* HOLE CARDS \*\*\*(?P<PREFLOP>.+(?=\*\*\* FLOP \*\*\*)|.+)" m = re.search(r"\*\*\* HOLE CARDS \*\*\*(?P<PREFLOP>.+(?=\*\*\* FLOP \*\*\*)|.+)"
r"(\*\*\* FLOP \*\*\*(?P<FLOP> \[\S\S \S\S \S\S\].+(?=\*\*\* TURN \*\*\*)|.+))?" r"(\*\*\* FLOP \*\*\*(?P<FLOP> \[\S\S \S\S \S\S\].+(?=\*\*\* TURN \*\*\*)|.+))?"
r"(\*\*\* TURN \*\*\* \[\S\S \S\S \S\S] (?P<TURN>\[\S\S\].+(?=\*\*\* RIVER \*\*\*)|.+))?" r"(\*\*\* TURN \*\*\* \[\S\S \S\S \S\S] (?P<TURN>\[\S\S\].+(?=\*\*\* RIVER \*\*\*)|.+))?"
r"(\*\*\* RIVER \*\*\* \[\S\S \S\S \S\S \S\S] (?P<RIVER>\[\S\S\].+))?", hand.handText,re.DOTALL) r"(\*\*\* RIVER \*\*\* \[\S\S \S\S \S\S \S\S] (?P<RIVER>\[\S\S\].+))?", hand.handText,re.DOTALL)
elif hand.gametype['base'] == "stud": # or should this be gametype['category'] == 'razz' elif hand.gametype['base'] == "stud":
m = re.search(r"(?P<ANTES>.+(?=\*\*\* 3RD STREET \*\*\*)|.+)" m = re.search(r"(?P<ANTES>.+(?=\*\*\* 3RD STREET \*\*\*)|.+)"
r"(\*\*\* 3RD STREET \*\*\*(?P<THIRD>.+(?=\*\*\* 4TH STREET \*\*\*)|.+))?" r"(\*\*\* 3RD STREET \*\*\*(?P<THIRD>.+(?=\*\*\* 4TH STREET \*\*\*)|.+))?"
r"(\*\*\* 4TH STREET \*\*\*(?P<FOURTH>.+(?=\*\*\* 5TH STREET \*\*\*)|.+))?" r"(\*\*\* 4TH STREET \*\*\*(?P<FOURTH>.+(?=\*\*\* 5TH STREET \*\*\*)|.+))?"
r"(\*\*\* 5TH STREET \*\*\*(?P<FIFTH>.+(?=\*\*\* 6TH STREET \*\*\*)|.+))?" r"(\*\*\* 5TH STREET \*\*\*(?P<FIFTH>.+(?=\*\*\* 6TH STREET \*\*\*)|.+))?"
r"(\*\*\* 6TH STREET \*\*\*(?P<SIXTH>.+(?=\*\*\* 7TH STREET \*\*\*)|.+))?" r"(\*\*\* 6TH STREET \*\*\*(?P<SIXTH>.+(?=\*\*\* 7TH STREET \*\*\*)|.+))?"
r"(\*\*\* 7TH STREET \*\*\*(?P<SEVENTH>.+))?", hand.handText,re.DOTALL) r"(\*\*\* 7TH STREET \*\*\*(?P<SEVENTH>.+))?", hand.handText,re.DOTALL)
elif hand.gametype['base'] in ("draw"):
m = re.search(r"(?P<PREDEAL>.+(?=\*\*\* HOLE CARDS \*\*\*)|.+)"
r"(\*\*\* HOLE CARDS \*\*\*(?P<DEAL>.+(?=\*\*\* FIRST DRAW \*\*\*)|.+))?"
r"(\*\*\* FIRST DRAW \*\*\*(?P<DRAWONE>.+(?=\*\*\* SECOND DRAW \*\*\*)|.+))?"
r"(\*\*\* SECOND DRAW \*\*\*(?P<DRAWTWO>.+(?=\*\*\* THIRD DRAW \*\*\*)|.+))?"
r"(\*\*\* THIRD DRAW \*\*\*(?P<DRAWTHREE>.+))?", hand.handText,re.DOTALL)
hand.addStreets(m) hand.addStreets(m)
def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand

View File

@ -15,6 +15,9 @@
#along with this program. If not, see <http://www.gnu.org/licenses/>. #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. #In the "official" distribution you can find the license in agpl-3.0.txt.
import L10n
_ = L10n.get_translation()
import threading import threading
import subprocess import subprocess
import traceback import traceback
@ -37,20 +40,12 @@ from optparse import OptionParser
import Configuration import Configuration
import string import string
import locale if os.name == "nt":
lang=locale.getdefaultlocale()[0][0:2] import win32console
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 GuiAutoImport (threading.Thread): class GuiAutoImport (threading.Thread):
def __init__(self, settings, config, sql, parent): def __init__(self, settings, config, sql = None, parent = None, cli = False):
self.importtimer = 0 self.importtimer = 0
self.settings = settings self.settings = settings
self.config = config self.config = config
@ -59,9 +54,6 @@ class GuiAutoImport (threading.Thread):
imp = self.config.get_import_parameters() imp = self.config.get_import_parameters()
# print "Import parameters"
# print imp
self.input_settings = {} self.input_settings = {}
self.pipe_to_hud = None self.pipe_to_hud = None
@ -71,13 +63,21 @@ class GuiAutoImport (threading.Thread):
self.importer.setQuiet(False) self.importer.setQuiet(False)
self.importer.setFailOnError(False) self.importer.setFailOnError(False)
self.importer.setHandCount(0) self.importer.setHandCount(0)
# self.importer.setWatchTime()
self.server = settings['db-host'] self.server = settings['db-host']
self.user = settings['db-user'] self.user = settings['db-user']
self.password = settings['db-password'] self.password = settings['db-password']
self.database = settings['db-databaseName'] self.database = settings['db-databaseName']
if cli == False:
self.setupGui()
else:
# TODO: Separate the code that grabs the directories from config
# Separate the calls to the Importer API
# Create a timer interface that doesn't rely on GTK
pass
def setupGui(self):
self.mainVBox = gtk.VBox(False,1) self.mainVBox = gtk.VBox(False,1)
hbox = gtk.HBox(True, 0) # contains 2 equal vboxes hbox = gtk.HBox(True, 0) # contains 2 equal vboxes
@ -214,13 +214,17 @@ class GuiAutoImport (threading.Thread):
self.doAutoImportBool = True self.doAutoImportBool = True
widget.set_label(_(u' _Stop Auto Import ')) widget.set_label(_(u' _Stop Auto Import '))
if self.pipe_to_hud is None: if self.pipe_to_hud is None:
if Configuration.FROZEN: if Configuration.FROZEN: # if py2exe, run hud_main.exe
path = Configuration.EXEC_PATH path = Configuration.EXEC_PATH
command = "HUD_main.exe" command = "HUD_main.exe"
bs = 0 bs = 0
elif os.name == 'nt': elif os.name == 'nt':
path = sys.path[0].replace('\\','\\\\') path = sys.path[0].replace('\\','\\\\')
command = 'pythonw "'+path+'\\HUD_main.pyw" ' + self.settings['cl_options'] if win32console.GetConsoleWindow() == 0:
command = 'pythonw "'+path+'\\HUD_main.pyw" ' + self.settings['cl_options']
else:
command = 'python "'+path+'\\HUD_main.pyw" ' + self.settings['cl_options']
# uncomment above line if you want hud_main stdout to work ... and make sure you are running fpdb.py using python.exe not pythonw.exe
bs = 0 bs = 0
else: else:
command = os.path.join(sys.path[0], 'HUD_main.pyw') command = os.path.join(sys.path[0], 'HUD_main.pyw')
@ -229,12 +233,15 @@ class GuiAutoImport (threading.Thread):
try: try:
print _("opening pipe to HUD") print _("opening pipe to HUD")
self.pipe_to_hud = subprocess.Popen(command, bufsize=bs, if Configuration.FROZEN or (os.name == "nt" and win32console.GetConsoleWindow()) == 0:
stdin=subprocess.PIPE, self.pipe_to_hud = subprocess.Popen(command, bufsize=bs,
stdout=subprocess.PIPE, # only needed for py2exe stdin=subprocess.PIPE,
stderr=subprocess.PIPE, # only needed for py2exe stdout=subprocess.PIPE, # needed for pythonw / py2exe
universal_newlines=True stderr=subprocess.PIPE, # needed for pythonw / py2exe
) universal_newlines=True
)
else:
self.pipe_to_hud = subprocess.Popen(command, bufsize=bs, stdin=subprocess.PIPE, universal_newlines=True)
#self.pipe_to_hud.stdout.close() #self.pipe_to_hud.stdout.close()
#self.pipe_to_hud.stderr.close() #self.pipe_to_hud.stderr.close()
except: except:
@ -341,16 +348,16 @@ if __name__== "__main__":
if os.name == 'nt': settings['os'] = 'windows' if os.name == 'nt': settings['os'] = 'windows'
else: settings['os'] = 'linuxmac' else: settings['os'] = 'linuxmac'
settings.update(config.get_db_parameters('fpdb')) settings.update(config.get_db_parameters())
settings.update(config.get_import_parameters()) settings.update(config.get_import_parameters())
settings.update(config.get_default_paths()) settings.update(config.get_default_paths())
if(options.gui == True): if(options.gui == True):
i = GuiAutoImport(settings, config) i = GuiAutoImport(settings, config, None, None)
main_window = gtk.Window() main_window = gtk.Window()
main_window.connect('destroy', destroy) main_window.connect('destroy', destroy)
main_window.add(i.mainVBox) main_window.add(i.mainVBox)
main_window.show() main_window.show()
gtk.main() gtk.main()
else: else:
pass i = GuiAutoImport(settings, config, cli = True)

View File

@ -15,6 +15,9 @@
#along with this program. If not, see <http://www.gnu.org/licenses/>. #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. #In the "official" distribution you can find the license in agpl-3.0.txt.
import L10n
_ = L10n.get_translation()
# Standard Library modules # Standard Library modules
import os import os
import sys import sys
@ -33,17 +36,6 @@ import fpdb_import
import Configuration import Configuration
import Exceptions import Exceptions
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 GuiBulkImport(): class GuiBulkImport():
@ -358,6 +350,8 @@ def main(argv=None):
help=_("Print some useful one liners")) help=_("Print some useful one liners"))
parser.add_option("-s", "--starsarchive", action="store_true", dest="starsArchive", default=False, parser.add_option("-s", "--starsarchive", action="store_true", dest="starsArchive", default=False,
help=_("Do the required conversion for Stars Archive format (ie. as provided by support")) help=_("Do the required conversion for Stars Archive format (ie. as provided by support"))
parser.add_option("-F", "--ftparchive", action="store_true", dest="ftpArchive", default=False,
help=_("Do the required conversion for FTP Archive format (ie. as provided by support"))
parser.add_option("-t", "--testdata", action="store_true", dest="testData", default=False, parser.add_option("-t", "--testdata", action="store_true", dest="testData", default=False,
help=_("Output the pprinted version of the HandsPlayer hash for regresion testing")) help=_("Output the pprinted version of the HandsPlayer hash for regresion testing"))
(options, argv) = parser.parse_args(args = argv) (options, argv) = parser.parse_args(args = argv)
@ -395,7 +389,7 @@ def main(argv=None):
gtk.main() gtk.main()
else: else:
#Do something useful #Do something useful
importer = fpdb_import.Importer(False,settings, config, self.parent) importer = fpdb_import.Importer(False,settings, config, None)
# importer.setDropIndexes("auto") # importer.setDropIndexes("auto")
importer.setDropIndexes(_("don't drop")) importer.setDropIndexes(_("don't drop"))
importer.setFailOnError(options.failOnError) importer.setFailOnError(options.failOnError)
@ -404,6 +398,8 @@ def main(argv=None):
importer.setCallHud(False) importer.setCallHud(False)
if options.starsArchive: if options.starsArchive:
importer.setStarsArchive(True) importer.setStarsArchive(True)
if options.ftpArchive:
importer.setFTPArchive(True)
if options.testData: if options.testData:
importer.setPrintTestData(True) importer.setPrintTestData(True)
(stored, dups, partial, errs, ttime) = importer.runImport() (stored, dups, partial, errs, ttime) = importer.runImport()

View File

@ -15,6 +15,9 @@
#along with this program. If not, see <http://www.gnu.org/licenses/>. #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. #In the "official" distribution you can find the license in agpl-3.0.txt.
import L10n
_ = L10n.get_translation()
import os import os
import sys import sys
import traceback import traceback
@ -31,24 +34,11 @@ import logging
# logging has been set up in fpdb.py or HUD_main.py, use their settings: # logging has been set up in fpdb.py or HUD_main.py, use their settings:
log = logging.getLogger("maintdbs") log = logging.getLogger("maintdbs")
import Exceptions import Exceptions
import Configuration import Configuration
import Database import Database
import SQL import SQL
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 GuiDatabase: class GuiDatabase:
# columns in liststore: # columns in liststore:

View File

@ -15,6 +15,9 @@
#along with this program. If not, see <http://www.gnu.org/licenses/>. #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. #In the "official" distribution you can find the license in agpl-3.0.txt.
import L10n
_ = L10n.get_translation()
import threading import threading
import pygtk import pygtk
pygtk.require('2.0') pygtk.require('2.0')
@ -26,26 +29,16 @@ from time import *
from datetime import datetime from datetime import datetime
#import pokereval #import pokereval
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
import fpdb_import import fpdb_import
import Database import Database
import Filters import Filters
import Charset import Charset
try: try:
calluse = not 'matplotlib' in sys.modules
import matplotlib import matplotlib
matplotlib.use('GTKCairo') if calluse:
matplotlib.use('GTKCairo')
from matplotlib.figure import Figure from matplotlib.figure import Figure
from matplotlib.backends.backend_gtk import FigureCanvasGTK as FigureCanvas from matplotlib.backends.backend_gtk import FigureCanvasGTK as FigureCanvas
from matplotlib.backends.backend_gtkagg import NavigationToolbar2GTKAgg as NavigationToolbar from matplotlib.backends.backend_gtkagg import NavigationToolbar2GTKAgg as NavigationToolbar
@ -82,15 +75,16 @@ class GuiGraphViewer (threading.Thread):
"Seats" : False, "Seats" : False,
"SeatSep" : False, "SeatSep" : False,
"Dates" : True, "Dates" : True,
"GraphOps" : True,
"Groups" : False, "Groups" : False,
"Button1" : True, "Button1" : True,
"Button2" : True "Button2" : True
} }
self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display) self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display)
self.filters.registerButton1Name("Refresh _Graph") self.filters.registerButton1Name(_("Refresh _Graph"))
self.filters.registerButton1Callback(self.generateGraph) self.filters.registerButton1Callback(self.generateGraph)
self.filters.registerButton2Name("_Export to File") self.filters.registerButton2Name(_("_Export to File"))
self.filters.registerButton2Callback(self.exportGraph) self.filters.registerButton2Callback(self.exportGraph)
self.mainHBox = gtk.HBox(False, 0) self.mainHBox = gtk.HBox(False, 0)
@ -153,11 +147,8 @@ class GuiGraphViewer (threading.Thread):
siteids = self.filters.getSiteIds() siteids = self.filters.getSiteIds()
limits = self.filters.getLimits() limits = self.filters.getLimits()
games = self.filters.getGames() games = self.filters.getGames()
graphs = { graphops = self.filters.getGraphOps()
"profit" : True, names = ""
"sawShowdown" : True,
"nonShowdown" : True
}
for i in ('show', 'none'): for i in ('show', 'none'):
if i in limits: if i in limits:
@ -170,6 +161,7 @@ class GuiGraphViewer (threading.Thread):
result = self.db.get_player_id(self.conf, site, _hname) result = self.db.get_player_id(self.conf, site, _hname)
if result is not None: if result is not None:
playerids.append(int(result)) playerids.append(int(result))
names = names + "\n"+_hname + " on "+site
if not sitenos: if not sitenos:
#Should probably pop up here. #Should probably pop up here.
@ -192,13 +184,15 @@ class GuiGraphViewer (threading.Thread):
#Get graph data from DB #Get graph data from DB
starttime = time() starttime = time()
(green, blue, red) = self.getRingProfitGraph(playerids, sitenos, limits, games) (green, blue, red) = self.getRingProfitGraph(playerids, sitenos, limits, games, graphops['dspin'])
print _("Graph generated in: %s") %(time() - starttime) print _("Graph generated in: %s") %(time() - starttime)
#Set axis labels and grid overlay properites #Set axis labels and grid overlay properites
self.ax.set_xlabel(_("Hands"), fontsize = 12) self.ax.set_xlabel(_("Hands"), fontsize = 12)
self.ax.set_ylabel("$", fontsize = 12) # SET LABEL FOR X AXIS
self.ax.set_ylabel(graphops['dspin'], fontsize = 12)
self.ax.grid(color='g', linestyle=':', linewidth=0.2) self.ax.grid(color='g', linestyle=':', linewidth=0.2)
if green == None or green == []: if green == None or green == []:
self.ax.set_title(_("No Data for Player(s) Found")) self.ax.set_title(_("No Data for Player(s) Found"))
@ -234,15 +228,15 @@ class GuiGraphViewer (threading.Thread):
#TODO: Do something useful like alert user #TODO: Do something useful like alert user
#print "No hands returned by graph query" #print "No hands returned by graph query"
else: else:
self.ax.set_title(_("Profit graph for ring games")) self.ax.set_title(_("Profit graph for ring games"+names),fontsize=12)
#Draw plot #Draw plot
if graphs['profit'] == True: self.ax.plot(green, color='green', label=_('Hands: %d\nProfit (%s): %.2f') %(len(green),graphops['dspin'], green[-1]))
self.ax.plot(green, color='green', label=_('Hands: %d\nProfit: $%.2f') %(len(green), green[-1])) if graphops['showdown'] == 'ON':
if graphs['sawShowdown'] == True: self.ax.plot(blue, color='blue', label=_('Showdown (%s): %.2f') %(graphops['dspin'], blue[-1]))
self.ax.plot(blue, color='blue', label=_('Showdown: $%.2f') %(blue[-1])) if graphops['nonshowdown'] == 'ON':
if graphs['nonShowdown'] == True: self.ax.plot(red, color='red', label=_('Non-showdown (%s): %.2f') %(graphops['dspin'], red[-1]))
self.ax.plot(red, color='red', label=_('Non-showdown: $%.2f') %(red[-1]))
if sys.version[0:3] == '2.5': if sys.version[0:3] == '2.5':
self.ax.legend(loc='upper left', shadow=True, prop=FontProperties(size='smaller')) self.ax.legend(loc='upper left', shadow=True, prop=FontProperties(size='smaller'))
else: else:
@ -258,9 +252,17 @@ class GuiGraphViewer (threading.Thread):
#end of def showClicked #end of def showClicked
def getRingProfitGraph(self, names, sites, limits, games):
tmp = self.sql.query['getRingProfitAllHandsPlayerIdSite'] def getRingProfitGraph(self, names, sites, limits, games, units):
# tmp = self.sql.query['getRingProfitAllHandsPlayerIdSite']
# print "DEBUG: getRingProfitGraph" # print "DEBUG: getRingProfitGraph"
if units == '$':
tmp = self.sql.query['getRingProfitAllHandsPlayerIdSiteInDollars']
elif units == 'BB':
tmp = self.sql.query['getRingProfitAllHandsPlayerIdSiteInBB']
start_date, end_date = self.filters.getDates() start_date, end_date = self.filters.getDates()
#Buggered if I can find a way to do this 'nicely' take a list of integers and longs #Buggered if I can find a way to do this 'nicely' take a list of integers and longs

View File

@ -15,6 +15,9 @@
#along with this program. If not, see <http://www.gnu.org/licenses/>. #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. #In the "official" distribution you can find the license in agpl-3.0.txt.
import L10n
_ = L10n.get_translation()
import threading import threading
import pygtk import pygtk
pygtk.require('2.0') pygtk.require('2.0')
@ -22,18 +25,6 @@ import gtk
from imaplib import IMAP4 from imaplib import IMAP4
from socket import gaierror from socket import gaierror
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
import ImapFetcher import ImapFetcher
class GuiImapFetcher (threading.Thread): class GuiImapFetcher (threading.Thread):

View File

@ -15,6 +15,9 @@
#along with this program. If not, see <http://www.gnu.org/licenses/>. #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. #In the "official" distribution you can find the license in agpl-3.0.txt.
import L10n
_ = L10n.get_translation()
import os import os
import Queue import Queue
@ -30,18 +33,6 @@ import logging
# logging has been set up in fpdb.py or HUD_main.py, use their settings: # logging has been set up in fpdb.py or HUD_main.py, use their settings:
log = logging.getLogger("logview") log = logging.getLogger("logview")
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
MAX_LINES = 100000 # max lines to display in window MAX_LINES = 100000 # max lines to display in window
EST_CHARS_PER_LINE = 150 # used to guesstimate number of lines in log file EST_CHARS_PER_LINE = 150 # used to guesstimate number of lines in log file
LOGFILES = [ [ 'Fpdb Errors', 'fpdb-errors.txt', False ] # label, filename, start value LOGFILES = [ [ 'Fpdb Errors', 'fpdb-errors.txt', False ] # label, filename, start value

View File

@ -15,6 +15,9 @@
#along with this program. If not, see <http://www.gnu.org/licenses/>. #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. #In the "official" distribution you can find the license in agpl-3.0.txt.
import L10n
_ = L10n.get_translation()
import traceback import traceback
import threading import threading
import pygtk import pygtk
@ -24,18 +27,6 @@ import os
import sys import sys
from time import time, strftime from time import time, strftime
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
import Card import Card
import fpdb_import import fpdb_import
import Database import Database
@ -43,10 +34,72 @@ import Filters
import Charset import Charset
import GuiPlayerStats import GuiPlayerStats
from TreeViewTooltips import TreeViewTooltips
#colalias,colshowsumm,colshowposn,colheading,colxalign,colformat,coltype = 0,1,2,3,4,5,6 #colalias,colshowsumm,colshowposn,colheading,colxalign,colformat,coltype = 0,1,2,3,4,5,6
#new order in config file: #new order in config file:
colalias,colheading,colshowsumm,colshowposn,colformat,coltype,colxalign = 0,1,2,3,4,5,6 colalias,colheading,colshowsumm,colshowposn,colformat,coltype,colxalign = 0,1,2,3,4,5,6
ranks = {'x':0, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9, 'T':10, 'J':11, 'Q':12, 'K':13, 'A':14} ranks = {'x':0, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9, 'T':10, 'J':11, 'Q':12, 'K':13, 'A':14}
onlinehelp = {'Game':_('Type of Game'),
'Hand':_('Hole cards'),
'Posn':_('Position'),
'Name':_('Name of the player'),
'Hds':_('Number of hands played'),
'Seats':_('Number of Seats'),
'VPIP':_('Voluntarily Putting In the pot\n(blinds excluded)'),
'PFR':_('% Pre Flop Raise'),
'PF3':_('% Pre Flop Re-Raise / 3Bet'),
'AggFac':_('Aggression Factor\n'),
'AggFreq':_('Aggression Frequency\nBet or Raise vs Fold'),
'ContBet':_('Continuation Bet on the flop'),
'RFI':_('% Raise First In\% Raise when first to bet'),
'Steals':_('% First to raise pre-flop\nand steal blinds'),
'Saw_F':_('% Saw Flop vs hands dealt'),
'SawSD':_('Saw Show Down / River'),
'WtSDwsF':_('Went To Show Down When Saw Flop'),
'W$SD':_('Amount Won when Show Down seen'),
'FlAFq':_('Flop Aggression\n% Bet or Raise after seeing Flop'),
'TuAFq':_('Turn Aggression\n% Bet or Raise after seeing Turn'),
'RvAFq':_('River Aggression\n% Bet or Raise after seeing River'),
'PoFAFq':_('Coming Soon\nTotal % agression'),
'Net($)':_('Amount won'),
'bb/100':_('Number of Big Blinds won\nor lost per 100 hands'),
'Rake($)':_('Amount of rake paid'),
'bbxr/100':_('Number of Big Blinds won\nor lost per 100 hands\nwhen excluding rake'),
'Variance':_('Measure of uncertainty\nThe lower, the more stable the amounts won')
}
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)
def get_tooltip(self, view, column, path):
model = view.get_model()
cards = model[path][0]
title=column.get_title()
if (title == 'Hand' or title == 'Game'): display='' #no tooltips on headers
else: display='<big>%s for %s</big>\n<i>%s</i>' % (title,cards,onlinehelp[title])
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)
class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats): class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats):
@ -103,34 +156,6 @@ class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats):
# columns to display, keys match column name returned by sql, values in tuple are: # columns to display, keys match column name returned by sql, values in tuple are:
# is column displayed(summary then position), column heading, xalignment, formatting, celltype # is column displayed(summary then position), column heading, xalignment, formatting, celltype
self.columns = self.conf.get_gui_cash_stat_params() self.columns = self.conf.get_gui_cash_stat_params()
# self.columns = [ ["game", True, True, "Game", 0.0, "%s", "str"]
# , ["hand", False, False, "Hand", 0.0, "%s", "str"] # initial setting ignored for this line (set in code)
# , ["plposition", False, False, "Posn", 1.0, "%s", "str"] # initial setting ignored for this line (set in code)
# , ["pname", False, False, "Name", 0.0, "%s", "str"] # initial setting ignored for this line (set in code)
# , ["n", True, True, "Hds", 1.0, "%1.0f", "str"]
# , ["avgseats", False, False, "Seats", 1.0, "%3.1f", "str"]
# , ["vpip", True, True, "VPIP", 1.0, "%3.1f", "str"]
# , ["pfr", True, True, "PFR", 1.0, "%3.1f", "str"]
# , ["pf3", True, True, "PF3", 1.0, "%3.1f", "str"]
# , ["aggfac", True, True, "AggFac", 1.0, "%2.2f", "str"]
# , ["aggfrq", True, True, "AggFreq", 1.0, "%3.1f", "str"]
# , ["conbet", True, True, "ContBet", 1.0, "%3.1f", "str"]
# , ["rfi", True, True, "RFI", 1.0, "%3.1f", "str"]
# , ["steals", True, True, "Steals", 1.0, "%3.1f", "str"]
# , ["saw_f", True, True, "Saw_F", 1.0, "%3.1f", "str"]
# , ["sawsd", True, True, "SawSD", 1.0, "%3.1f", "str"]
# , ["wtsdwsf", True, True, "WtSDwsF", 1.0, "%3.1f", "str"]
# , ["wmsd", True, True, "W$SD", 1.0, "%3.1f", "str"]
# , ["flafq", True, True, "FlAFq", 1.0, "%3.1f", "str"]
# , ["tuafq", True, True, "TuAFq", 1.0, "%3.1f", "str"]
# , ["rvafq", True, True, "RvAFq", 1.0, "%3.1f", "str"]
# , ["pofafq", False, False, "PoFAFq", 1.0, "%3.1f", "str"]
# , ["net", True, True, "Net($)", 1.0, "%6.2f", "cash"]
# , ["bbper100", True, True, "bb/100", 1.0, "%4.2f", "str"]
# , ["rake", True, True, "Rake($)", 1.0, "%6.2f", "cash"]
# , ["bb100xr", True, True, "bbxr/100", 1.0, "%4.2f", "str"]
# , ["variance", True, True, "Variance", 1.0, "%5.2f", "str"]
# ]
# Detail filters: This holds the data used in the popup window, extra values are # Detail filters: This holds the data used in the popup window, extra values are
# added at the end of these lists during processing # added at the end of these lists during processing
@ -391,6 +416,7 @@ class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats):
print _("***sortcols error: ") + str(sys.exc_info()[1]) print _("***sortcols error: ") + str(sys.exc_info()[1])
print "\n".join( [e[0]+':'+str(e[1])+" "+e[2] for e in err] ) print "\n".join( [e[0]+':'+str(e[1])+" "+e[2] for e in err] )
#end def sortcols #end def sortcols
def addGrid(self, vbox, query, flags, playerids, sitenos, limits, type, seats, groups, dates, games): def addGrid(self, vbox, query, flags, playerids, sitenos, limits, type, seats, groups, dates, games):
counter = 0 counter = 0
@ -401,6 +427,7 @@ class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats):
tmp = self.sql.query[query] tmp = self.sql.query[query]
tmp = self.refineQuery(tmp, flags, playerids, sitenos, limits, type, seats, groups, dates, games) tmp = self.refineQuery(tmp, flags, playerids, sitenos, limits, type, seats, groups, dates, games)
#print "DEBUG: query: %s" % tmp
self.cursor.execute(tmp) self.cursor.execute(tmp)
result = self.cursor.fetchall() result = self.cursor.fetchall()
colnames = [desc[0].lower() for desc in self.cursor.description] colnames = [desc[0].lower() for desc in self.cursor.description]
@ -476,7 +503,7 @@ class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats):
else: else:
if column[colalias] == 'game': if column[colalias] == 'game':
if holecards: if holecards:
value = Card.twoStartCardString( result[sqlrow][hgametypeid_idx] ) value = Card.decodeStartHandValue(result[sqlrow][colnames.index('category')], result[sqlrow][hgametypeid_idx] )
else: else:
minbb = result[sqlrow][colnames.index('minbigblind')] minbb = result[sqlrow][colnames.index('minbigblind')]
maxbb = result[sqlrow][colnames.index('maxbigblind')] maxbb = result[sqlrow][colnames.index('maxbigblind')]
@ -502,6 +529,9 @@ class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats):
#print treerow #print treerow
sqlrow += 1 sqlrow += 1
row += 1 row += 1
tips = DemoTips(column[colformat])
tips.add_view(view)
vbox.show_all() vbox.show_all()
view.show() view.show()
if len(self.liststore) == 1: if len(self.liststore) == 1:

42
pyfpdb/GuiSessionViewer.py Executable file → Normal file
View File

@ -15,6 +15,9 @@
#along with this program. If not, see <http://www.gnu.org/licenses/>. #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. #In the "official" distribution you can find the license in agpl-3.0.txt.
import L10n
_ = L10n.get_translation()
import sys import sys
import threading import threading
import pygtk import pygtk
@ -27,7 +30,7 @@ try:
calluse = not 'matplotlib' in sys.modules calluse = not 'matplotlib' in sys.modules
import matplotlib import matplotlib
if calluse: if calluse:
matplotlib.use('GTK') matplotlib.use('GTKCairo')
from matplotlib.figure import Figure from matplotlib.figure import Figure
from matplotlib.backends.backend_gtk import FigureCanvasGTK as FigureCanvas from matplotlib.backends.backend_gtk import FigureCanvasGTK as FigureCanvas
from matplotlib.backends.backend_gtkagg import NavigationToolbar2GTKAgg as NavigationToolbar from matplotlib.backends.backend_gtkagg import NavigationToolbar2GTKAgg as NavigationToolbar
@ -41,29 +44,20 @@ except ImportError, inst:
print _("""Failed to load numpy and/or matplotlib in Session Viewer""") print _("""Failed to load numpy and/or matplotlib in Session Viewer""")
print _("ImportError: %s") % inst.args print _("ImportError: %s") % inst.args
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
import Card import Card
import fpdb_import import fpdb_import
import Database import Database
import Filters import Filters
import Charset import Charset
DEBUG = False
class GuiSessionViewer (threading.Thread): class GuiSessionViewer (threading.Thread):
def __init__(self, config, querylist, mainwin, debug=True): def __init__(self, config, querylist, mainwin, debug=True):
self.debug = debug self.debug = debug
self.conf = config self.conf = config
self.sql = querylist self.sql = querylist
self.window = mainwin
self.liststore = None self.liststore = None
@ -162,6 +156,28 @@ class GuiSessionViewer (threading.Thread):
# make sure Hand column is not displayed # make sure Hand column is not displayed
#[x for x in self.columns if x[0] == 'hand'][0][1] = False #[x for x in self.columns if x[0] == 'hand'][0][1] = False
if DEBUG == False:
warning_string = """
Session Viewer is proof of concept code only, and contains many bugs.
Feel free to use the viewer, but there is no guarantee that the data is accurate.
If you are interested in developing the code further please contact us via the usual channels.
Thankyou
"""
self.warning_box(warning_string)
def warning_box(self, str, diatitle=_("FPDB WARNING")):
diaWarning = gtk.Dialog(title=diatitle, parent=self.window, flags=gtk.DIALOG_DESTROY_WITH_PARENT, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK))
label = gtk.Label(str)
diaWarning.vbox.add(label)
label.show()
response = diaWarning.run()
diaWarning.destroy()
return response
def get_vbox(self): def get_vbox(self):
"""returns the vbox of this thread""" """returns the vbox of this thread"""

View File

@ -15,6 +15,9 @@
#along with this program. If not, see <http://www.gnu.org/licenses/>. #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. #In the "official" distribution you can find the license in agpl-3.0.txt.
import L10n
_ = L10n.get_translation()
import threading import threading
import pygtk import pygtk
pygtk.require('2.0') pygtk.require('2.0')
@ -26,26 +29,16 @@ from time import *
from datetime import datetime from datetime import datetime
#import pokereval #import pokereval
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
import fpdb_import import fpdb_import
import Database import Database
import Filters import Filters
import Charset import Charset
try: try:
calluse = not 'matplotlib' in sys.modules
import matplotlib import matplotlib
matplotlib.use('GTKCairo') if calluse:
matplotlib.use('GTKCairo')
from matplotlib.figure import Figure from matplotlib.figure import Figure
from matplotlib.backends.backend_gtk import FigureCanvasGTK as FigureCanvas from matplotlib.backends.backend_gtk import FigureCanvasGTK as FigureCanvas
from matplotlib.backends.backend_gtkagg import NavigationToolbar2GTKAgg as NavigationToolbar from matplotlib.backends.backend_gtkagg import NavigationToolbar2GTKAgg as NavigationToolbar
@ -88,9 +81,9 @@ class GuiTourneyGraphViewer (threading.Thread):
} }
self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display) self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display)
self.filters.registerButton1Name("Refresh _Graph") self.filters.registerButton1Name(_("Refresh _Graph"))
self.filters.registerButton1Callback(self.generateGraph) self.filters.registerButton1Callback(self.generateGraph)
self.filters.registerButton2Name("_Export to File") self.filters.registerButton2Name(_("_Export to File"))
self.filters.registerButton2Callback(self.exportGraph) self.filters.registerButton2Callback(self.exportGraph)
self.mainHBox = gtk.HBox(False, 0) self.mainHBox = gtk.HBox(False, 0)

298
pyfpdb/GuiTourneyImport.py Executable file
View File

@ -0,0 +1,298 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#Copyright 2008-2010 Carl Gherardi
#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()
# Standard Library modules
import os
import sys
from time import time
import traceback
import datetime
import codecs
import re
# pyGTK modules
import pygtk
pygtk.require('2.0')
import gtk
import gobject
# fpdb/FreePokerTools modules
import Configuration
import Options
from Exceptions import FpdbParseError
import logging
# logging has been set up in fpdb.py or HUD_main.py, use their settings:
log = logging.getLogger("importer")
class GuiTourneyImport():
def load_clicked(self, widget, data=None):
print "DEBUG: load_clicked"
stored = None
dups = None
partial = None
errs = None
ttime = None
if self.settings['global_lock'].acquire(wait=False, source="GuiTourneyImport"):
print "DEBUG: got global lock"
# get the dir to import from the chooser
selected = self.chooser.get_filenames()
print "DEBUG: Files selected: %s" % selected
sitename = self.cbfilter.get_model()[self.cbfilter.get_active()][0]
for selection in selected:
self.importer.addImportFileOrDir(selection, site = sitename)
starttime = time()
(stored, errs) = self.importer.runImport()
ttime = time() - starttime
if ttime == 0:
ttime = 1
print _('GuiTourneyImport.load done: Stored: %d\tErrors: %d in %s seconds - %.0f/sec')\
% (stored, errs, ttime, (stored+0.0) / ttime)
self.importer.clearFileList()
self.settings['global_lock'].release()
else:
print _("bulk import aborted - global lock not available")
def get_vbox(self):
"""returns the vbox of this thread"""
return self.vbox
def __init__(self, settings, config, sql = None, parent = None):
self.settings = settings
self.config = config
self.parent = parent
self.importer = SummaryImporter(config, sql, parent)
self.vbox = gtk.VBox(False, 0)
self.vbox.show()
self.chooser = gtk.FileChooserWidget()
self.chooser.set_filename(self.settings['bulkImport-defaultPath'])
self.chooser.set_select_multiple(True)
self.vbox.add(self.chooser)
self.chooser.show()
# Table widget to hold the settings
self.table = gtk.Table(rows=5, columns=5, homogeneous=False)
self.vbox.add(self.table)
self.table.show()
# label - tsc
self.lab_filter = gtk.Label(_("Site filter:"))
self.table.attach(self.lab_filter, 1, 2, 2, 3, xpadding=0, ypadding=0,
yoptions=gtk.SHRINK)
self.lab_filter.show()
self.lab_filter.set_justify(gtk.JUSTIFY_RIGHT)
self.lab_filter.set_alignment(1.0, 0.5)
# ComboBox - filter
self.cbfilter = gtk.combo_box_new_text()
disabled_sites = [] # move disabled sites to bottom of list
for w in self.config.hhcs:
print "%s = '%s'" %(w, self.config.hhcs[w].summaryImporter)
try:
# Include sites with a tourney summary importer, and enabled
if self.config.supported_sites[w].enabled and self.config.hhcs[w].summaryImporter != '':
self.cbfilter.append_text(w)
else:
disabled_sites.append(w)
except: # self.supported_sites[w] may not exist if hud_config is bad
disabled_sites.append(w)
for w in disabled_sites:
if self.config.hhcs[w].summaryImporter != '':
self.cbfilter.append_text(w)
self.cbfilter.set_active(0)
self.table.attach(self.cbfilter, 2, 3, 2, 3, xpadding=10, ypadding=1,
yoptions=gtk.SHRINK)
self.cbfilter.show()
# button - Import
self.load_button = gtk.Button(_('_Bulk Import')) # todo: rename variables to import too
self.load_button.connect('clicked', self.load_clicked,
_('Import clicked'))
self.table.attach(self.load_button, 2, 3, 4, 5, xpadding=0, ypadding=0,
yoptions=gtk.SHRINK)
self.load_button.show()
# label - spacer (keeps rows 3 & 5 apart)
self.lab_spacer = gtk.Label()
self.table.attach(self.lab_spacer, 3, 5, 3, 4, xpadding=0, ypadding=0,
yoptions=gtk.SHRINK)
self.lab_spacer.show()
class SummaryImporter:
def __init__(self, config, sql = None, parent = None):
self.config = config
self.sql = sql
self.parent = parent
self.filelist = {}
self.dirlist = {}
self.updatedsize = {}
self.updatedtime = {}
def addImportFile(self, filename, site = "default", tsc = "passthrough"):
if filename in self.filelist or not os.path.exists(filename):
print "DEBUG: addImportFile: File exists, or path non-existent"
return
self.filelist[filename] = [site] + [tsc]
def addImportDirectory(self,dir,monitor=False, site="default", tsc="passthrough"):
if os.path.isdir(dir):
if monitor == True:
self.monitor = True
self.dirlist[site] = [dir] + [tsc]
for file in os.listdir(dir):
self.addImportFile(os.path.join(dir, file), site, tsc)
else:
log.warning(_("Attempted to add non-directory '%s' as an import directory") % str(dir))
def addImportFileOrDir(self, inputPath, site = "PokerStars"):
tsc = self.config.hhcs[site].summaryImporter
if os.path.isdir(inputPath):
for subdir in os.walk(inputPath):
for file in subdir[2]:
self.addImportFile(unicode(os.path.join(subdir[0], file),'utf-8'),
site=site, tsc=tsc)
else:
self.addImportFile(unicode(inputPath,'utf-8'), site=site, tsc=tsc)
pass
def runImport(self):
start = datetime.datetime.now()
starttime = time()
log.info(_("Tourney Summary Import started at %s - %d files to import.") % (start, len(self.filelist)))
total_errors = 0
total_imported = 0
for f in self.filelist:
(site, tsc) = self.filelist[f]
imported, errs = self.importFile(f, tsc, site)
total_errors += errs
total_imported += imported
return (total_imported, total_errors)
def runUpdated(self):
pass
def importFile(self, filename, tsc = "PokerStarsSummary", site = "PokerStars"):
mod = __import__(tsc)
obj = getattr(mod, tsc, None)
if callable(obj):
foabs = self.readFile(obj, filename)
summaryTexts = re.split(obj.re_SplitTourneys, foabs)
# The summary files tend to have a header or footer
# Remove the first and/or last entry if it has < 100 characters
if len(summaryTexts[-1]) <= 100:
summaryTexts.pop()
log.warn(_("TourneyImport: Removing text < 100 characters from end of file"))
if len(summaryTexts[0]) <= 130:
del summaryTexts[0]
log.warn(_("TourneyImport: Removing text < 100 characters from start of file"))
print "Found %s summaries" %(len(summaryTexts))
errors = 0
imported = 0
for j, summaryText in enumerate(summaryTexts, start=1):
try:
conv = obj(db=None, config=self.config, siteName=site, summaryText=summaryText, builtFrom = "IMAP")
except FpdbParseError, e:
errors += 1
print _("Finished importing %s/%s tournament summaries") %(j, len(summaryTexts))
imported = j
return (imported - errors, errors)
def clearFileList(self):
self.updatedsize = {}
self.updatetime = {}
self.filelist = {}
def readFile(self, tsc, filename):
codepage = ["utf8", "utf16"]
whole_file = None
tsc.codepage
for kodec in codepage:
try:
in_fh = codecs.open(filename, 'r', kodec)
whole_file = in_fh.read()
in_fh.close()
break
except UnicodeDecodeError, e:
log.warn(_("GTI.readFile: '%s'") % e)
pass
return whole_file
def main(argv=None):
"""main can also be called in the python interpreter, by supplying the command line as the argument."""
import SQL
if argv is None:
argv = sys.argv[1:]
(options, argv) = Options.fpdb_options()
if options.usage == True:
#Print usage examples and exit
print _("USAGE:")
sys.exit(0)
if options.hhc == "PokerStarsToFpdb":
print _("Need to define a converter")
exit(0)
config = Configuration.Config("HUD_config.test.xml")
sql = SQL.Sql(db_server = 'sqlite')
if options.filename == None:
print _("Need a filename to import")
exit(0)
importer = SummaryImporter(config, sql, None)
importer.addImportFileOrDir(options.filename, site = options.hhc)
starttime = time()
(stored, errs) = importer.runImport()
ttime = time() - starttime
if ttime == 0:
ttime = 1
print _('GuiTourneyImport.load done: Stored: %d\tErrors: %d in %s seconds - %.0f/sec')\
% (stored, errs, ttime, (stored+0.0) / ttime)
importer.clearFileList()
if __name__ == '__main__':
sys.exit(main())

View File

@ -15,6 +15,9 @@
#along with this program. If not, see <http://www.gnu.org/licenses/>. #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. #In the "official" distribution you can find the license in agpl-3.0.txt.
import L10n
_ = L10n.get_translation()
#import traceback #import traceback
import threading import threading
import pygtk import pygtk
@ -24,18 +27,6 @@ import gtk
#import sys #import sys
from time import time, strftime from time import time, strftime
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
#import Card #import Card
#import fpdb_import #import fpdb_import
#import Database #import Database

View File

@ -15,23 +15,14 @@
#along with this program. If not, see <http://www.gnu.org/licenses/>. #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. #In the "official" distribution you can find the license in agpl-3.0.txt.
import L10n
_ = L10n.get_translation()
import threading import threading
import pygtk import pygtk
pygtk.require('2.0') pygtk.require('2.0')
import gtk import gtk
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 GuiTourneyViewer (threading.Thread): class GuiTourneyViewer (threading.Thread):
def __init__(self, config, db, sql, mainwin, debug=True): def __init__(self, config, db, sql, mainwin, debug=True):
self.db = db self.db = db

83
pyfpdb/HHReplayer.py Normal file
View File

@ -0,0 +1,83 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#Copyright 2008-2010 Carl Gherardi
#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 os, pygame
import time
from pygame.locals import *
from pygame.compat import geterror
main_dir = os.path.split(os.path.abspath(__file__))[0]
data_dir = os.path.join(main_dir, '.')
def load_image(name, colorkey=None):
fullname = os.path.join(data_dir, name)
try:
image = pygame.image.load(fullname)
except pygame.error:
print ('Cannot load image:', fullname)
print "data_dir: '%s' name: '%s'" %( data_dir, name)
raise SystemExit(str(geterror()))
image = image.convert()
if colorkey is not None:
if colorkey is -1:
colorkey = image.get_at((0,0))
image.set_colorkey(colorkey, RLEACCEL)
return image, image.get_rect()
def main():
#Initialize Everything
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((640, 480))
table_string = "Tournament 2010090009 Table %s - Blinds $600/$1200 Anto $150"
table_no = 1
table_title = "Nongoma V - $200/$400 USD - Limit Holdem"
pygame.display.set_caption(table_title)
pygame.mouse.set_visible(0)
# Load background image
bgimage, rect = load_image('../gfx/Table.png')
background = pygame.Surface(screen.get_size())
background.blit(bgimage, (0, 0))
#Put Text On The Background, Centered
if pygame.font:
font = pygame.font.Font(None, 24)
text = font.render("FPDB Replayer Table", 1, (10, 10, 10))
textpos = text.get_rect(centerx=background.get_width()/2)
background.blit(text, textpos)
#Display The Background
screen.blit(background, (0, 0))
pygame.display.flip()
going = True
while going:
clock.tick(6000)
# Draw
screen.blit(background, (0, 0))
# Change table #
#table_no += 1
#table_title = "Tournament 2010090009 Table %s - Blinds $600/$1200 Anto $150" % table_no
#pygame.display.set_caption(table_title)
time.sleep(10)
if __name__ == '__main__':
main()

View File

@ -566,17 +566,18 @@ Left-Drag to Move"
</aux_windows> </aux_windows>
<hhcs> <hhcs>
<hhc site="PokerStars" converter="PokerStarsToFpdb"/> <hhc site="PokerStars" converter="PokerStarsToFpdb" summaryImporter="PokerStarsSummary"/>
<hhc site="Full Tilt Poker" converter="FulltiltToFpdb"/> <hhc site="Full Tilt Poker" converter="FulltiltToFpdb" summaryImporter="FullTiltPokerSummary"/>
<hhc site="Everleaf" converter="EverleafToFpdb"/> <hhc site="Everleaf" converter="EverleafToFpdb"/>
<hhc site="Win2day" converter="Win2dayToFpdb"/> <hhc site="Win2day" converter="Win2dayToFpdb"/>
<hhc site="Absolute" converter="AbsoluteToFpdb"/> <hhc site="Absolute" converter="AbsoluteToFpdb"/>
<hhc site="PartyPoker" converter="PartyPokerToFpdb"/> <hhc site="PartyPoker" converter="PartyPokerToFpdb"/>
<hhc site="Betfair" converter="BetfairToFpdb"/> <hhc site="Betfair" converter="BetfairToFpdb"/>
<hhc site="OnGame" converter="OnGameToFpdb"/> <hhc site="OnGame" converter="OnGameToFpdb"/>
<hhc site="Partouche" converter="PartoucheToFpdb"/>
<hhc site="Carbon" converter="CarbonToFpdb"/> <hhc site="Carbon" converter="CarbonToFpdb"/>
<hhc site="PKR" converter="PkrToFpdb"/> <hhc site="PKR" converter="PkrToFpdb"/>
<hhc site="iPoker" converter="iPokerToFpdb"/>
<hhc site="Winamax" converter="WinamaxToFpdb"/>
</hhcs> </hhcs>
<supported_databases> <supported_databases>

View File

@ -290,6 +290,18 @@ Left-Drag to Move"
<location seat="9" x="7" y="88"> </location> <location seat="9" x="7" y="88"> </location>
<location seat="10" x="196" y="69"> </location> <location seat="10" x="196" y="69"> </location>
</layout> </layout>
<layout fav_seat="0" height="546" max="8" width="792">
<location seat="0" x="182" y="69"> </location>
<location seat="1" x="456" y="74"> </location>
<location seat="2" x="630" y="81"> </location>
<location seat="3" x="618" y="352"> </location>
<location seat="4" x="426" y="380"> </location>
<location seat="5" x="243" y="382"> </location>
<location seat="6" x="34" y="351"> </location>
<location seat="7" x="22" y="82"> </location>
<location seat="8" x="213" y="74"> </location>
</layout>
<layout fav_seat="0" height="546" max="2" width="792"> <layout fav_seat="0" height="546" max="2" width="792">
<location seat="1" x="651" y="288"> </location> <location seat="1" x="651" y="288"> </location>
<location seat="2" x="10" y="288"> </location> <location seat="2" x="10" y="288"> </location>
@ -550,6 +562,43 @@ Left-Drag to Move"
<location seat="9" x="70" y="53"> </location> <location seat="9" x="70" y="53"> </location>
</layout> </layout>
</site> </site>
<site HH_path="C:/Program Files/Winamax/HandHistory/YOUR SCREEN NAME HERE/" converter="WinamaxToFpdb" decoder="everleaf_decode_table" enabled="False" screen_name="YOUR SCREEN NAME HERE" site_name="Winamax" site_path="C:/Program Files/Winamax/" supported_games="holdem" table_finder="Winamax.exe">
<layout fav_seat="0" height="547" max="8" width="794">
<location seat="1" x="640" y="64"> </location>
<location seat="2" x="650" y="230"> </location>
<location seat="3" x="650" y="385"> </location>
<location seat="4" x="588" y="425"> </location>
<location seat="5" x="92" y="425"> </location>
<location seat="6" x="0" y="373"> </location>
<location seat="7" x="0" y="223"> </location>
<location seat="8" x="25" y="50"> </location>
</layout>
<layout fav_seat="0" height="547" max="6" width="794">
<location seat="1" x="640" y="58"> </location>
<location seat="2" x="654" y="288"> </location>
<location seat="3" x="615" y="424"> </location>
<location seat="4" x="70" y="421"> </location>
<location seat="5" x="0" y="280"> </location>
<location seat="6" x="70" y="58"> </location>
</layout>
<layout fav_seat="0" height="547" max="2" width="794">
<location seat="1" x="651" y="288"> </location>
<location seat="2" x="10" y="288"> </location>
</layout>
<layout fav_seat="0" height="547" max="9" width="794">
<location seat="1" x="634" y="38"> </location>
<location seat="2" x="667" y="184"> </location>
<location seat="3" x="667" y="321"> </location>
<location seat="4" x="667" y="445"> </location>
<location seat="5" x="337" y="459"> </location>
<location seat="6" x="0" y="400"> </location>
<location seat="7" x="0" y="322"> </location>
<location seat="8" x="0" y="181"> </location>
<location seat="9" x="70" y="53"> </location>
</layout>
</site>
</supported_sites> </supported_sites>
<supported_games> <supported_games>
@ -609,6 +658,43 @@ Left-Drag to Move"
<stat click="tog_decorate" col="0" popup="default" row="2" stat_name="saw_f" tip="tip1"> </stat> <stat click="tog_decorate" col="0" popup="default" row="2" stat_name="saw_f" tip="tip1"> </stat>
<stat click="tog_decorate" col="1" popup="default" row="2" stat_name="ffreq1" tip="tip1"> </stat> <stat click="tog_decorate" col="1" popup="default" row="2" stat_name="ffreq1" tip="tip1"> </stat>
</game> </game>
<game cols="3" db="fpdb" game_name="27_3draw" rows="2">
<stat click="tog_decorate" col="0" popup="default" row="0" stat_name="vpip" tip="tip1"> </stat>
<stat click="tog_decorate" col="1" popup="default" row="0" stat_name="pfr" tip="tip1"> </stat>
<stat click="tog_decorate" col="2" popup="default" row="0" stat_name="ffreq1" tip="tip1"> </stat>
<stat click="tog_decorate" col="0" popup="default" row="1" stat_name="n" tip="tip1"> </stat>
<stat click="tog_decorate" col="1" popup="default" row="1" stat_name="wtsd" tip="tip1"> </stat>
<stat click="tog_decorate" col="2" popup="default" row="1" stat_name="wmsd" tip="tip1"> </stat>
</game>
<game cols="3" db="fpdb" game_name="27_1draw" rows="2">
<stat click="tog_decorate" col="0" popup="default" row="0" stat_name="vpip" tip="tip1"> </stat>
<stat click="tog_decorate" col="1" popup="default" row="0" stat_name="pfr" tip="tip1"> </stat>
<stat click="tog_decorate" col="2" popup="default" row="0" stat_name="ffreq1" tip="tip1"> </stat>
<stat click="tog_decorate" col="0" popup="default" row="1" stat_name="n" tip="tip1"> </stat>
<stat click="tog_decorate" col="1" popup="default" row="1" stat_name="wtsd" tip="tip1"> </stat>
<stat click="tog_decorate" col="2" popup="default" row="1" stat_name="wmsd" tip="tip1"> </stat>
</game>
<game cols="3" db="fpdb" game_name="badugi" rows="2">
<stat click="tog_decorate" col="0" popup="default" row="0" stat_name="vpip" tip="tip1"> </stat>
<stat click="tog_decorate" col="1" popup="default" row="0" stat_name="pfr" tip="tip1"> </stat>
<stat click="tog_decorate" col="2" popup="default" row="0" stat_name="ffreq1" tip="tip1"> </stat>
<stat click="tog_decorate" col="0" popup="default" row="1" stat_name="n" tip="tip1"> </stat>
<stat click="tog_decorate" col="1" popup="default" row="1" stat_name="wtsd" tip="tip1"> </stat>
<stat click="tog_decorate" col="2" popup="default" row="1" stat_name="wmsd" tip="tip1"> </stat>
</game>
<game cols="3" db="fpdb" game_name="fivedraw" rows="2">
<stat click="tog_decorate" col="0" popup="default" row="0" stat_name="vpip" tip="tip1"> </stat>
<stat click="tog_decorate" col="1" popup="default" row="0" stat_name="pfr" tip="tip1"> </stat>
<stat click="tog_decorate" col="2" popup="default" row="0" stat_name="ffreq1" tip="tip1"> </stat>
<stat click="tog_decorate" col="0" popup="default" row="1" stat_name="n" tip="tip1"> </stat>
<stat click="tog_decorate" col="1" popup="default" row="1" stat_name="wtsd" tip="tip1"> </stat>
<stat click="tog_decorate" col="2" popup="default" row="1" stat_name="wmsd" tip="tip1"> </stat>
</game>
</supported_games> </supported_games>
<popup_windows> <popup_windows>
@ -691,17 +777,18 @@ Left-Drag to Move"
</aux_windows> </aux_windows>
<hhcs> <hhcs>
<hhc site="PokerStars" converter="PokerStarsToFpdb"/> <hhc site="PokerStars" converter="PokerStarsToFpdb" summaryImporter="PokerStarsSummary"/>
<hhc site="Full Tilt Poker" converter="FulltiltToFpdb"/> <hhc site="Full Tilt Poker" converter="FulltiltToFpdb" summaryImporter="FullTiltPokerSummary"/>
<hhc site="Everleaf" converter="EverleafToFpdb"/> <hhc site="Everleaf" converter="EverleafToFpdb"/>
<hhc site="Win2day" converter="Win2dayToFpdb"/> <hhc site="Win2day" converter="Win2dayToFpdb"/>
<hhc site="Absolute" converter="AbsoluteToFpdb"/> <hhc site="Absolute" converter="AbsoluteToFpdb"/>
<hhc site="PartyPoker" converter="PartyPokerToFpdb"/> <hhc site="PartyPoker" converter="PartyPokerToFpdb"/>
<hhc site="Betfair" converter="BetfairToFpdb"/> <hhc site="Betfair" converter="BetfairToFpdb"/>
<hhc site="Partouche" converter="PartoucheToFpdb"/>
<hhc site="Carbon" converter="CarbonToFpdb"/> <hhc site="Carbon" converter="CarbonToFpdb"/>
<hhc site="OnGame" converter="OnGameToFpdb"/> <hhc site="OnGame" converter="OnGameToFpdb"/>
<hhc site="PKR" converter="PkrToFpdb"/> <hhc site="PKR" converter="PkrToFpdb"/>
<hhc site="iPoker" converter="iPokerToFpdb"/>
<hhc site="Winamax" converter="WinamaxToFpdb"/>
</hhcs> </hhcs>
<raw_hands save="none" compression="none"/> <raw_hands save="none" compression="none"/>

View File

@ -61,17 +61,19 @@ elif os.name == 'nt':
import Hud import Hud
import locale import locale
lang=locale.getdefaultlocale()[0][0:2] lang = locale.getdefaultlocale()[0][0:2]
print "lang:", lang print "lang:", lang
if lang=="en": if lang == "en":
def _(string): return string def _(string):
return string
else: else:
import gettext import gettext
try: try:
trans = gettext.translation("fpdb", localedir="locale", languages=[lang]) trans = gettext.translation("fpdb", localedir="locale", languages=[lang])
trans.install() trans.install()
except IOError: except IOError:
def _(string): return string def _(string):
return string
# get config and set up logger # get config and set up logger
c = Configuration.Config(file=options.config, dbname=options.dbname) c = Configuration.Config(file=options.config, dbname=options.dbname)
@ -82,7 +84,7 @@ class HUD_main(object):
"""A main() object to own both the read_stdin thread and the gui.""" """A main() object to own both the read_stdin thread and the gui."""
# This class mainly provides state for controlling the multiple HUDs. # This class mainly provides state for controlling the multiple HUDs.
def __init__(self, db_name = 'fpdb'): def __init__(self, db_name='fpdb'):
print _("\nHUD_main: starting ...") print _("\nHUD_main: starting ...")
self.db_name = db_name self.db_name = db_name
self.config = c self.config = c
@ -92,9 +94,9 @@ class HUD_main(object):
try: try:
if not options.errorsToConsole: if not options.errorsToConsole:
fileName = os.path.join(self.config.dir_log, 'HUD-errors.txt') fileName = os.path.join(self.config.dir_log, 'HUD-errors.txt')
print _("Note: error output is being diverted to:\n")+fileName \ print _("Note: error output is being diverted to:\n") + fileName \
+ _("\nAny major error will be reported there _only_.\n") + _("\nAny major error will be reported there _only_.\n")
log.info(_("Note: error output is being diverted to:")+fileName) log.info(_("Note: error output is being diverted to:") + fileName)
log.info(_("Any major error will be reported there _only_.")) log.info(_("Any major error will be reported there _only_."))
errorFile = open(fileName, 'w', 0) errorFile = open(fileName, 'w', 0)
sys.stderr = errorFile sys.stderr = errorFile
@ -104,23 +106,52 @@ class HUD_main(object):
self.hud_params = self.config.get_hud_ui_parameters() self.hud_params = self.config.get_hud_ui_parameters()
# a thread to read stdin # a thread to read stdin
gobject.threads_init() # this is required gobject.threads_init() # this is required
thread.start_new_thread(self.read_stdin, ()) # starts the thread thread.start_new_thread(self.read_stdin, ()) # starts the thread
# a main window # a main window
self.main_window = gtk.Window() self.main_window = gtk.Window()
self.main_window.connect("client_moved", self.client_moved)
self.main_window.connect("client_resized", self.client_resized)
self.main_window.connect("client_destroyed", self.client_destroyed)
self.main_window.connect("game_changed", self.game_changed)
self.main_window.connect("table_changed", self.table_changed)
self.main_window.connect("destroy", self.destroy) self.main_window.connect("destroy", self.destroy)
self.vb = gtk.VBox() self.vb = gtk.VBox()
self.label = gtk.Label(_('Closing this window will exit from the HUD.')) self.label = gtk.Label(_('Closing this window will exit from the HUD.'))
self.vb.add(self.label) self.vb.add(self.label)
self.main_window.add(self.vb) self.main_window.add(self.vb)
self.main_window.set_title(_("HUD Main Window")) self.main_window.set_title(_("HUD Main Window"))
cards = os.path.join(os.getcwd(), '..','gfx','fpdb-cards.png')
if os.path.exists(cards):
self.main_window.set_icon_from_file(cards)
elif os.path.exists('/usr/share/pixmaps/fpdb-cards.png'):
self.main_window.set_icon_from_file('/usr/share/pixmaps/fpdb-cards.png')
else:
self.main_window.set_icon_stock(gtk.STOCK_HOME)
self.main_window.show_all() self.main_window.show_all()
gobject.timeout_add(100, self.check_tables)
except: except:
log.error( "*** Exception in HUD_main.init() *** " ) log.error("*** Exception in HUD_main.init() *** ")
for e in traceback.format_tb(sys.exc_info()[2]): for e in traceback.format_tb(sys.exc_info()[2]):
log.error(e) log.error(e)
def client_moved(self, widget, hud):
hud.up_update_table_position()
def client_resized(self, widget, hud):
pass
def client_destroyed(self, widget, hud): # call back for terminating the main eventloop
self.kill_hud(None, hud.table.name)
def game_changed(self, widget, hud):
print _("hud_main: Game changed.")
def table_changed(self, widget, hud):
print _("hud_main: Table changed.")
self.kill_hud(None, hud.table.name)
def destroy(self, *args): # call back for terminating the main eventloop def destroy(self, *args): # call back for terminating the main eventloop
log.info(_("Terminating normally.")) log.info(_("Terminating normally."))
@ -133,7 +164,12 @@ class HUD_main(object):
self.hud_dict[table].main_window.destroy() self.hud_dict[table].main_window.destroy()
self.vb.remove(self.hud_dict[table].tablehudlabel) self.vb.remove(self.hud_dict[table].tablehudlabel)
del(self.hud_dict[table]) del(self.hud_dict[table])
self.main_window.resize(1,1) self.main_window.resize(1, 1)
def check_tables(self):
for hud in self.hud_dict.keys():
self.hud_dict[hud].table.check_table(self.hud_dict[hud])
return True
def create_HUD(self, new_hand_id, table, table_name, max, poker_game, type, stat_dict, cards): def create_HUD(self, new_hand_id, table, table_name, max, poker_game, type, stat_dict, cards):
"""type is "ring" or "tour" used to set hud_params""" """type is "ring" or "tour" used to set hud_params"""
@ -156,7 +192,7 @@ class HUD_main(object):
self.hud_dict[table_name].update(new_hand_id, self.config) self.hud_dict[table_name].update(new_hand_id, self.config)
self.hud_dict[table_name].reposition_windows() self.hud_dict[table_name].reposition_windows()
except: except:
log.error( "*** Exception in HUD_main::idle_func() *** " + str(sys.exc_info()) ) log.error("*** Exception in HUD_main::idle_func() *** " + str(sys.exc_info()))
for e in traceback.format_tb(sys.exc_info()[2]): for e in traceback.format_tb(sys.exc_info()[2]):
log.error(e) log.error(e)
finally: finally:
@ -222,7 +258,7 @@ class HUD_main(object):
self.hero, self.hero_ids = {}, {} self.hero, self.hero_ids = {}, {}
found = False found = False
while 1: # wait for a new hand number on stdin while 1: # wait for a new hand number on stdin
new_hand_id = sys.stdin.readline() new_hand_id = sys.stdin.readline()
t0 = time.time() t0 = time.time()
t1 = t2 = t3 = t4 = t5 = t6 = t0 t1 = t2 = t3 = t4 = t5 = t6 = t0
@ -266,9 +302,10 @@ class HUD_main(object):
self.db_connection.init_hud_stat_vars( self.hud_dict[temp_key].hud_params['hud_days'] self.db_connection.init_hud_stat_vars( self.hud_dict[temp_key].hud_params['hud_days']
, self.hud_dict[temp_key].hud_params['h_hud_days']) , self.hud_dict[temp_key].hud_params['h_hud_days'])
t2 = time.time() t2 = time.time()
stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_dict[temp_key].hud_params stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_dict[temp_key].hud_params,
,self.hero_ids[site_id], num_seats) self.hero_ids[site_id], num_seats)
t3 = time.time() t3 = time.time()
try: try:
self.hud_dict[temp_key].stat_dict = stat_dict self.hud_dict[temp_key].stat_dict = stat_dict
except KeyError: # HUD instance has been killed off, key is stale except KeyError: # HUD instance has been killed off, key is stale
@ -277,7 +314,7 @@ class HUD_main(object):
# Unlocks table, copied from end of function # Unlocks table, copied from end of function
self.db_connection.connection.rollback() self.db_connection.connection.rollback()
return return
cards = self.db_connection.get_cards(new_hand_id) cards = self.db_connection.get_cards(new_hand_id)
t4 = time.time() t4 = time.time()
comm_cards = self.db_connection.get_common_cards(new_hand_id) comm_cards = self.db_connection.get_common_cards(new_hand_id)
t5 = time.time() t5 = time.time()
@ -291,18 +328,15 @@ class HUD_main(object):
else: else:
# get stats using default params--also get cards # get stats using default params--also get cards
self.db_connection.init_hud_stat_vars( self.hud_params['hud_days'], self.hud_params['h_hud_days'] ) self.db_connection.init_hud_stat_vars( self.hud_params['hud_days'], self.hud_params['h_hud_days'] )
stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_params stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_params,
,self.hero_ids[site_id], num_seats) self.hero_ids[site_id], num_seats)
cards = self.db_connection.get_cards(new_hand_id) cards = self.db_connection.get_cards(new_hand_id)
comm_cards = self.db_connection.get_common_cards(new_hand_id) comm_cards = self.db_connection.get_common_cards(new_hand_id)
if comm_cards != {}: # stud! if comm_cards != {}: # stud!
cards['common'] = comm_cards['common'] cards['common'] = comm_cards['common']
table_kwargs = dict(table_name = table_name, tournament = tour_number, table_number = tab_number) table_kwargs = dict(table_name=table_name, tournament=tour_number, table_number=tab_number)
search_string = getTableTitleRe(self.config, site_name, type, **table_kwargs) tablewindow = Tables.Table(self.config, site_name, **table_kwargs)
# print "getTableTitleRe ", self.config, site_name, type, "=", search_string
tablewindow = Tables.Table(search_string, **table_kwargs)
if tablewindow is None: if tablewindow is None:
# If no client window is found on the screen, complain and continue # If no client window is found on the screen, complain and continue
if type == "tour": if type == "tour":
@ -319,9 +353,11 @@ class HUD_main(object):
t6 = time.time() t6 = time.time()
log.info(_("HUD_main.read_stdin: hand read in %4.3f seconds (%4.3f,%4.3f,%4.3f,%4.3f,%4.3f,%4.3f)") log.info(_("HUD_main.read_stdin: hand read in %4.3f seconds (%4.3f,%4.3f,%4.3f,%4.3f,%4.3f,%4.3f)")
% (t6-t0,t1-t0,t2-t0,t3-t0,t4-t0,t5-t0,t6-t0)) % (t6 - t0,t1 - t0,t2 - t0,t3 - t0,t4 - t0,t5 - t0,t6 - t0))
self.db_connection.connection.rollback() self.db_connection.connection.rollback()
# if type == "tour":
# tablewindow.check_table_no(None)
# # Ray!! tablewindow::check_table_no expects a HUD as an argument!
if __name__== "__main__": if __name__== "__main__":
# start the HUD_main object # start the HUD_main object

View File

@ -15,6 +15,9 @@
#along with this program. If not, see <http://www.gnu.org/licenses/>. #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. #In the "official" distribution you can find the license in agpl-3.0.txt.
import L10n
_ = L10n.get_translation()
# TODO: get writehand() encoding correct # TODO: get writehand() encoding correct
import re import re
@ -28,18 +31,6 @@ import time,datetime
from copy import deepcopy from copy import deepcopy
import pprint import pprint
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
import logging import logging
# logging has been set up in fpdb.py or HUD_main.py, use their settings: # logging has been set up in fpdb.py or HUD_main.py, use their settings:
log = logging.getLogger("parser") log = logging.getLogger("parser")
@ -56,13 +47,16 @@ class Hand(object):
# Class Variables # Class Variables
UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K', 'S':'s', 'C':'c', 'H':'h', 'D':'d'} UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K', 'S':'s', 'C':'c', 'H':'h', 'D':'d'}
LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'} LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'}
SYMBOL = {'USD': '$', 'EUR': u'$', 'T$': '', 'play': ''} SYMBOL = {'USD': '$', 'EUR': u'$', 'GBP': '$', 'T$': '', 'play': ''}
MS = {'horse' : 'HORSE', '8game' : '8-Game', 'hose' : 'HOSE', 'ha': 'HA'} MS = {'horse' : 'HORSE', '8game' : '8-Game', 'hose' : 'HOSE', 'ha': 'HA'}
ACTION = {'ante': 1, 'small blind': 2, 'secondsb': 3, 'big blind': 4, 'both': 5, 'calls': 6, 'raises': 7,
'bets': 8, 'stands pat': 9, 'folds': 10, 'checks': 11, 'discards': 12, 'bringin': 13, 'completes': 14}
def __init__(self, config, sitename, gametype, handText, builtFrom = "HHC"): def __init__(self, config, sitename, gametype, handText, builtFrom = "HHC"):
#log.debug( _("Hand.init(): handText is ") + str(handText) ) #log.debug( _("Hand.init(): handText is ") + str(handText) )
self.config = config self.config = config
self.saveActions = self.config.get_import_parameters().get('saveActions')
#log = Configuration.get_logger("logging.conf", "db", log_dir=self.config.dir_log) #log = Configuration.get_logger("logging.conf", "db", log_dir=self.config.dir_log)
self.sitename = sitename self.sitename = sitename
self.siteId = self.config.get_site_id(sitename) self.siteId = self.config.get_site_id(sitename)
@ -74,13 +68,14 @@ class Hand(object):
self.cancelled = False self.cancelled = False
self.dbid_hands = 0 self.dbid_hands = 0
self.dbid_pids = None self.dbid_pids = None
self.dbid_hpid = None
self.dbid_gt = 0 self.dbid_gt = 0
self.tablename = "" self.tablename = ""
self.hero = "" self.hero = ""
self.maxseats = None self.maxseats = None
self.counted_seats = 0 self.counted_seats = 0
self.buttonpos = 0 self.buttonpos = 0
#tourney stuff #tourney stuff
self.tourNo = None self.tourNo = None
self.tourneyId = None self.tourneyId = None
@ -106,7 +101,7 @@ class Hand(object):
self.players = [] self.players = []
self.posted = [] self.posted = []
self.tourneysPlayersIds = [] self.tourneysPlayersIds = []
# Collections indexed by street names # Collections indexed by street names
self.bets = {} self.bets = {}
self.lastBet = {} self.lastBet = {}
@ -241,7 +236,7 @@ dealt whether they were seen in a 'dealt to' line
#Gametypes #Gametypes
self.dbid_gt = db.getGameTypeId(self.siteId, self.gametype) self.dbid_gt = db.getGameTypeId(self.siteId, self.gametype)
if self.tourNo!=None: if self.tourNo!=None:
self.tourneyTypeId = db.createTourneyType(self) self.tourneyTypeId = db.createTourneyType(self)
db.commit() db.commit()
@ -271,10 +266,11 @@ db: a connected Database object"""
hh['seats'] = len(self.dbid_pids) hh['seats'] = len(self.dbid_pids)
self.dbid_hands = db.storeHand(hh) self.dbid_hands = db.storeHand(hh)
db.storeHandsPlayers(self.dbid_hands, self.dbid_pids, self.stats.getHandsPlayers(), printdata = printtest) self.dbid_hpid = db.storeHandsPlayers(self.dbid_hands, self.dbid_pids,
# TODO HandsActions - all actions for all players for all streets - self.actions self.stats.getHandsPlayers(), printdata = printtest)
# HudCache data can be generated from HandsActions (HandsPlayers?) if self.saveActions:
#db.storeHandsActions(self.dbid_hands, self.dbid_pids, self.stats.getHandsActions(), printdata = printtest) db.storeHandsActions(self.dbid_hands, self.dbid_pids, self.dbid_hpid,
self.stats.getHandsActions(), printdata = printtest)
else: else:
log.info(_("Hand.insert(): hid #: %s is a duplicate") % hh['siteHandNo']) log.info(_("Hand.insert(): hid #: %s is a duplicate") % hh['siteHandNo'])
self.is_duplicate = True # i.e. don't update hudcache self.is_duplicate = True # i.e. don't update hudcache
@ -285,9 +281,143 @@ db: a connected Database object"""
def select(self, handId): def select(self, handId):
""" Function to create Hand object from database """ """ Function to create Hand object from database """
c = cnxn.cursor()
# We need at least sitename, gametype, handid
# for the Hand.__init__
c.execute("""SELECT
s.name,
g.category,
g.base,
g.type,
g.limitType,
g.hilo,
round(g.smallBlind / 100.0,2),
round(g.bigBlind / 100.0,2),
round(g.smallBet / 100.0,2),
round(g.bigBet / 100.0,2),
s.currency,
h.boardcard1,
h.boardcard2,
h.boardcard3,
h.boardcard4,
h.boardcard5
FROM
hands as h,
sites as s,
gametypes as g,
handsplayers as hp,
players as p
WHERE
h.id = %(handid)s
and g.id = h.gametypeid
and hp.handid = h.id
and p.id = hp.playerid
and s.id = p.siteid
limit 1""", {'handid':handid})
#TODO: siteid should be in hands table - we took the scenic route through players here.
res = c.fetchone()
gametype = {'category':res[1],'base':res[2],'type':res[3],'limitType':res[4],'hilo':res[5],'sb':res[6],'bb':res[7], 'currency':res[10]}
c = Configuration.Config()
h = HoldemOmahaHand(config = c, hhc = None, sitename=res[0], gametype = gametype, handText=None, builtFrom = "DB", handid=handid)
cards = map(Card.valueSuitFromCard, res[11:16] )
if cards[0]:
h.setCommunityCards('FLOP', cards[0:3])
if cards[3]:
h.setCommunityCards('TURN', [cards[3]])
if cards[4]:
h.setCommunityCards('RIVER', [cards[4]])
#[Card.valueSuitFromCard(x) for x in cards]
# HandInfo : HID, TABLE
# BUTTON - why is this treated specially in Hand?
# answer: it is written out in hand histories
# still, I think we should record all the active seat positions in a seat_order array
c.execute("""SELECT
h.sitehandno as hid,
h.tablename as table,
h.startTime as startTime
FROM
hands as h
WHERE h.id = %(handid)s
""", {'handid':handid})
res = c.fetchone()
h.handid = res[0]
h.tablename = res[1]
h.startTime = res[2] # automatically a datetime
# PlayerStacks
c.execute("""SELECT
hp.seatno,
round(hp.winnings / 100.0,2) as winnings,
p.name,
round(hp.startcash / 100.0,2) as chips,
hp.card1,hp.card2,
hp.position
FROM
handsplayers as hp,
players as p
WHERE
hp.handid = %(handid)s
and p.id = hp.playerid
""", {'handid':handid})
for (seat, winnings, name, chips, card1,card2, position) in c.fetchall():
h.addPlayer(seat,name,chips)
if card1 and card2:
h.addHoleCards(map(Card.valueSuitFromCard, (card1,card2)), name, dealt=True)
if winnings > 0:
h.addCollectPot(name, winnings)
if position == 'B':
h.buttonpos = seat
# actions
c.execute("""SELECT
(ha.street,ha.actionno) as actnum,
p.name,
ha.street,
ha.action,
ha.allin,
round(ha.amount / 100.0,2)
FROM
handsplayers as hp,
handsactions as ha,
players as p
WHERE
hp.handid = %(handid)s
and ha.handsplayerid = hp.id
and p.id = hp.playerid
ORDER BY
ha.street,ha.actionno
""", {'handid':handid})
res = c.fetchall()
for (actnum,player, streetnum, act, allin, amount) in res:
act=act.strip()
street = h.allStreets[streetnum+1]
if act==u'blind':
h.addBlind(player, 'big blind', amount)
# TODO: The type of blind is not recorded in the DB.
# TODO: preflop street name anomalies in Hand
elif act==u'fold':
h.addFold(street,player)
elif act==u'call':
h.addCall(street,player,amount)
elif act==u'bet':
h.addBet(street,player,amount)
elif act==u'check':
h.addCheck(street,player)
elif act==u'unbet':
pass
else:
print act, player, streetnum, allin, amount
# TODO : other actions
#hhc.readShowdownActions(self)
#hc.readShownCards(self)
h.totalPot()
h.rake = h.totalpot - h.totalcollected
return h
def addPlayer(self, seat, name, chips): def addPlayer(self, seat, name, chips):
"""\ """\
@ -359,12 +489,12 @@ For sites (currently only Carbon Poker) which record "all in" as a special actio
ante = re.sub(u',', u'', ante) #some sites have commas ante = re.sub(u',', u'', ante) #some sites have commas
self.bets['BLINDSANTES'][player].append(Decimal(ante)) self.bets['BLINDSANTES'][player].append(Decimal(ante))
self.stacks[player] -= Decimal(ante) self.stacks[player] -= Decimal(ante)
act = (player, 'posts', "ante", ante, self.stacks[player]==0) act = (player, 'ante', Decimal(ante), self.stacks[player]==0)
self.actions['BLINDSANTES'].append(act) self.actions['BLINDSANTES'].append(act)
# self.pot.addMoney(player, Decimal(ante)) # self.pot.addMoney(player, Decimal(ante))
self.pot.addCommonMoney(player, Decimal(ante)) self.pot.addCommonMoney(player, Decimal(ante))
#I think the antes should be common money, don't have enough hand history to check #I think the antes should be common money, don't have enough hand history to check
def addBlind(self, player, blindtype, amount): def addBlind(self, player, blindtype, amount):
# if player is None, it's a missing small blind. # if player is None, it's a missing small blind.
# The situation we need to cover are: # The situation we need to cover are:
@ -378,13 +508,13 @@ For sites (currently only Carbon Poker) which record "all in" as a special actio
if player is not None: if player is not None:
amount = re.sub(u',', u'', amount) #some sites have commas amount = re.sub(u',', u'', amount) #some sites have commas
self.stacks[player] -= Decimal(amount) self.stacks[player] -= Decimal(amount)
act = (player, 'posts', blindtype, amount, self.stacks[player]==0) act = (player, blindtype, Decimal(amount), self.stacks[player]==0)
self.actions['BLINDSANTES'].append(act) self.actions['BLINDSANTES'].append(act)
if blindtype == 'both': if blindtype == 'both':
# work with the real amount. limit games are listed as $1, $2, where # work with the real amount. limit games are listed as $1, $2, where
# the SB 0.50 and the BB is $1, after the turn the minimum bet amount is $2.... # the SB 0.50 and the BB is $1, after the turn the minimum bet amount is $2....
amount = self.bb amount = self.bb
self.bets['BLINDSANTES'][player].append(Decimal(self.sb)) self.bets['BLINDSANTES'][player].append(Decimal(self.sb))
self.pot.addCommonMoney(player, Decimal(self.sb)) self.pot.addCommonMoney(player, Decimal(self.sb))
@ -411,7 +541,7 @@ For sites (currently only Carbon Poker) which record "all in" as a special actio
#self.lastBet[street] = Decimal(amount) #self.lastBet[street] = Decimal(amount)
self.stacks[player] -= Decimal(amount) self.stacks[player] -= Decimal(amount)
#print "DEBUG %s calls %s, stack %s" % (player, amount, self.stacks[player]) #print "DEBUG %s calls %s, stack %s" % (player, amount, self.stacks[player])
act = (player, 'calls', amount, self.stacks[player]==0) act = (player, 'calls', Decimal(amount), self.stacks[player]==0)
self.actions[street].append(act) self.actions[street].append(act)
self.pot.addMoney(player, Decimal(amount)) self.pot.addMoney(player, Decimal(amount))
@ -472,11 +602,11 @@ Add a raise on [street] by [player] to [amountTo]
Rb = Rt - C - Bc Rb = Rt - C - Bc
self._addRaise(street, player, C, Rb, Rt) self._addRaise(street, player, C, Rb, Rt)
def _addRaise(self, street, player, C, Rb, Rt): def _addRaise(self, street, player, C, Rb, Rt, action = 'raises'):
log.debug(_("%s %s raise %s") %(street, player, Rt)) log.debug(_("%s %s raise %s") %(street, player, Rt))
self.bets[street][player].append(C + Rb) self.bets[street][player].append(C + Rb)
self.stacks[player] -= (C + Rb) self.stacks[player] -= (C + Rb)
act = (player, 'raises', Rb, Rt, C, self.stacks[player]==0) act = (player, action, Rb, Rt, C, self.stacks[player]==0)
self.actions[street].append(act) self.actions[street].append(act)
self.lastBet[street] = Rt # TODO check this is correct self.lastBet[street] = Rt # TODO check this is correct
self.pot.addMoney(player, C+Rb) self.pot.addMoney(player, C+Rb)
@ -490,7 +620,7 @@ Add a raise on [street] by [player] to [amountTo]
self.bets[street][player].append(Decimal(amount)) self.bets[street][player].append(Decimal(amount))
self.stacks[player] -= Decimal(amount) self.stacks[player] -= Decimal(amount)
#print "DEBUG %s bets %s, stack %s" % (player, amount, self.stacks[player]) #print "DEBUG %s bets %s, stack %s" % (player, amount, self.stacks[player])
act = (player, 'bets', amount, self.stacks[player]==0) act = (player, 'bets', Decimal(amount), self.stacks[player]==0)
self.actions[street].append(act) self.actions[street].append(act)
self.lastBet[street] = Decimal(amount) self.lastBet[street] = Decimal(amount)
self.pot.addMoney(player, Decimal(amount)) self.pot.addMoney(player, Decimal(amount))
@ -553,7 +683,7 @@ Card ranks will be uppercased
self.totalcollected = 0; self.totalcollected = 0;
#self.collected looks like [[p1,amount][px,amount]] #self.collected looks like [[p1,amount][px,amount]]
for entry in self.collected: for entry in self.collected:
self.totalcollected += Decimal(entry[1]) self.totalcollected += Decimal(entry[1])
def getGameTypeAsString(self): def getGameTypeAsString(self):
"""\ """\
@ -693,15 +823,12 @@ class HoldemOmahaHand(Hand):
hhc.readPlayerStacks(self) hhc.readPlayerStacks(self)
hhc.compilePlayerRegexs(self) hhc.compilePlayerRegexs(self)
hhc.markStreets(self) hhc.markStreets(self)
if self.cancelled: if self.cancelled:
return return
try: hhc.readBlinds(self) hhc.readBlinds(self)
except:
print _("*** Parse error reading blinds (check compilePlayerRegexs as a likely culprit)"), self
return
hhc.readAntes(self) hhc.readAntes(self)
hhc.readButton(self) hhc.readButton(self)
hhc.readHeroCards(self) hhc.readHeroCards(self)
@ -1032,7 +1159,7 @@ class DrawHand(Hand):
self.bets['DEAL'][player].append(Decimal(amount)) self.bets['DEAL'][player].append(Decimal(amount))
self.stacks[player] -= Decimal(amount) self.stacks[player] -= Decimal(amount)
#print "DEBUG %s posts, stack %s" % (player, self.stacks[player]) #print "DEBUG %s posts, stack %s" % (player, self.stacks[player])
act = (player, 'posts', blindtype, amount, self.stacks[player]==0) act = (player, blindtype, Decimal(amount), self.stacks[player]==0)
self.actions['BLINDSANTES'].append(act) self.actions['BLINDSANTES'].append(act)
self.pot.addMoney(player, Decimal(amount)) self.pot.addMoney(player, Decimal(amount))
if blindtype == 'big blind': if blindtype == 'big blind':
@ -1062,10 +1189,10 @@ class DrawHand(Hand):
def addDiscard(self, street, player, num, cards): def addDiscard(self, street, player, num, cards):
self.checkPlayerExists(player) self.checkPlayerExists(player)
if cards: if cards:
act = (player, 'discards', num, cards) act = (player, 'discards', Decimal(num), cards)
self.discardDrawHoleCards(cards, player, street) self.discardDrawHoleCards(cards, player, street)
else: else:
act = (player, 'discards', num) act = (player, 'discards', Decimal(num))
self.actions[street].append(act) self.actions[street].append(act)
def holecardsAsSet(self, street, player): def holecardsAsSet(self, street, player):
@ -1224,7 +1351,8 @@ class StudHand(Hand):
self.addHoleCards('FOURTH', player, open=[cards[3]], closed=[cards[2]], shown=shown, mucked=mucked) self.addHoleCards('FOURTH', player, open=[cards[3]], closed=[cards[2]], shown=shown, mucked=mucked)
self.addHoleCards('FIFTH', player, open=[cards[4]], closed=cards[2:4], shown=shown, mucked=mucked) self.addHoleCards('FIFTH', player, open=[cards[4]], closed=cards[2:4], shown=shown, mucked=mucked)
self.addHoleCards('SIXTH', player, open=[cards[5]], closed=cards[2:5], shown=shown, mucked=mucked) self.addHoleCards('SIXTH', player, open=[cards[5]], closed=cards[2:5], shown=shown, mucked=mucked)
self.addHoleCards('SEVENTH', player, open=[], closed=[cards[6]], shown=shown, mucked=mucked) if len(cards) > 6:
self.addHoleCards('SEVENTH', player, open=[], closed=[cards[6]], shown=shown, mucked=mucked)
def addPlayerCards(self, player, street, open=[], closed=[]): def addPlayerCards(self, player, street, open=[], closed=[]):
@ -1257,7 +1385,7 @@ Add a complete on [street] by [player] to [amountTo]
Rt = Decimal(amountTo) Rt = Decimal(amountTo)
C = Bp - Bc C = Bp - Bc
Rb = Rt - C Rb = Rt - C
self._addRaise(street, player, C, Rb, Rt) self._addRaise(street, player, C, Rb, Rt, 'completes')
#~ self.bets[street][player].append(C + Rb) #~ self.bets[street][player].append(C + Rb)
#~ self.stacks[player] -= (C + Rb) #~ self.stacks[player] -= (C + Rb)
#~ act = (player, 'raises', Rb, Rt, C, self.stacks[player]==0) #~ act = (player, 'raises', Rb, Rt, C, self.stacks[player]==0)
@ -1270,7 +1398,7 @@ Add a complete on [street] by [player] to [amountTo]
log.debug(_("Bringin: %s, %s") % (player , bringin)) log.debug(_("Bringin: %s, %s") % (player , bringin))
self.bets['THIRD'][player].append(Decimal(bringin)) self.bets['THIRD'][player].append(Decimal(bringin))
self.stacks[player] -= Decimal(bringin) self.stacks[player] -= Decimal(bringin)
act = (player, 'bringin', bringin, self.stacks[player]==0) act = (player, 'bringin', Decimal(bringin), self.stacks[player]==0)
self.actions['THIRD'].append(act) self.actions['THIRD'].append(act)
self.lastBet['THIRD'] = Decimal(bringin) self.lastBet['THIRD'] = Decimal(bringin)
self.pot.addMoney(player, Decimal(bringin)) self.pot.addMoney(player, Decimal(bringin))
@ -1497,7 +1625,7 @@ class Pot(object):
# Return any uncalled bet. # Return any uncalled bet.
committed = sorted([ (v,k) for (k,v) in self.committed.items()]) committed = sorted([ (v,k) for (k,v) in self.committed.items()])
#print "DEBUG: committed: %s" % committed #print "DEBUG: committed: %s" % committed
#ERROR below. lastbet is correct in most cases, but wrong when #ERROR below. lastbet is correct in most cases, but wrong when
# additional money is committed to the pot in cash games # additional money is committed to the pot in cash games
# due to an additional sb being posted. (Speculate that # due to an additional sb being posted. (Speculate that
# posting sb+bb is also potentially wrong) # posting sb+bb is also potentially wrong)
@ -1546,146 +1674,4 @@ class Pot(object):
return ret + ''.join([ (" Side pot %s%.2f." % (self.sym, self.pots[x]) ) for x in xrange(1, len(self.pots)) ]) return ret + ''.join([ (" Side pot %s%.2f." % (self.sym, self.pots[x]) ) for x in xrange(1, len(self.pots)) ])
def assemble(cnxn, handid):
c = cnxn.cursor()
# We need at least sitename, gametype, handid
# for the Hand.__init__
c.execute("""
select
s.name,
g.category,
g.base,
g.type,
g.limitType,
g.hilo,
round(g.smallBlind / 100.0,2),
round(g.bigBlind / 100.0,2),
round(g.smallBet / 100.0,2),
round(g.bigBet / 100.0,2),
s.currency,
h.boardcard1,
h.boardcard2,
h.boardcard3,
h.boardcard4,
h.boardcard5
from
hands as h,
sites as s,
gametypes as g,
handsplayers as hp,
players as p
where
h.id = %(handid)s
and g.id = h.gametypeid
and hp.handid = h.id
and p.id = hp.playerid
and s.id = p.siteid
limit 1""", {'handid':handid})
#TODO: siteid should be in hands table - we took the scenic route through players here.
res = c.fetchone()
gametype = {'category':res[1],'base':res[2],'type':res[3],'limitType':res[4],'hilo':res[5],'sb':res[6],'bb':res[7], 'currency':res[10]}
c = Configuration.Config()
h = HoldemOmahaHand(config = c, hhc = None, sitename=res[0], gametype = gametype, handText=None, builtFrom = "DB", handid=handid)
cards = map(Card.valueSuitFromCard, res[11:16] )
if cards[0]:
h.setCommunityCards('FLOP', cards[0:3])
if cards[3]:
h.setCommunityCards('TURN', [cards[3]])
if cards[4]:
h.setCommunityCards('RIVER', [cards[4]])
#[Card.valueSuitFromCard(x) for x in cards]
# HandInfo : HID, TABLE
# BUTTON - why is this treated specially in Hand?
# answer: it is written out in hand histories
# still, I think we should record all the active seat positions in a seat_order array
c.execute("""
SELECT
h.sitehandno as hid,
h.tablename as table,
h.startTime as startTime
FROM
hands as h
WHERE h.id = %(handid)s
""", {'handid':handid})
res = c.fetchone()
h.handid = res[0]
h.tablename = res[1]
h.startTime = res[2] # automatically a datetime
# PlayerStacks
c.execute("""
SELECT
hp.seatno,
round(hp.winnings / 100.0,2) as winnings,
p.name,
round(hp.startcash / 100.0,2) as chips,
hp.card1,hp.card2,
hp.position
FROM
handsplayers as hp,
players as p
WHERE
hp.handid = %(handid)s
and p.id = hp.playerid
""", {'handid':handid})
for (seat, winnings, name, chips, card1,card2, position) in c.fetchall():
h.addPlayer(seat,name,chips)
if card1 and card2:
h.addHoleCards(map(Card.valueSuitFromCard, (card1,card2)), name, dealt=True)
if winnings > 0:
h.addCollectPot(name, winnings)
if position == 'B':
h.buttonpos = seat
# actions
c.execute("""
SELECT
(ha.street,ha.actionno) as actnum,
p.name,
ha.street,
ha.action,
ha.allin,
round(ha.amount / 100.0,2)
FROM
handsplayers as hp,
handsactions as ha,
players as p
WHERE
hp.handid = %(handid)s
and ha.handsplayerid = hp.id
and p.id = hp.playerid
ORDER BY
ha.street,ha.actionno
""", {'handid':handid})
res = c.fetchall()
for (actnum,player, streetnum, act, allin, amount) in res:
act=act.strip()
street = h.allStreets[streetnum+1]
if act==u'blind':
h.addBlind(player, 'big blind', amount)
# TODO: The type of blind is not recorded in the DB.
# TODO: preflop street name anomalies in Hand
elif act==u'fold':
h.addFold(street,player)
elif act==u'call':
h.addCall(street,player,amount)
elif act==u'bet':
h.addBet(street,player,amount)
elif act==u'check':
h.addCheck(street,player)
elif act==u'unbet':
pass
else:
print act, player, streetnum, allin, amount
# TODO : other actions
#hhc.readShowdownActions(self)
#hc.readShownCards(self)
h.totalPot()
h.rake = h.totalpot - h.totalcollected
return h

View File

@ -15,6 +15,9 @@
#along with this program. If not, see <http://www.gnu.org/licenses/>. #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. #In the "official" distribution you can find the license in agpl-3.0.txt.
import L10n
_ = L10n.get_translation()
import re import re
import sys import sys
import traceback import traceback
@ -41,18 +44,6 @@ import Hand
from Exceptions import FpdbParseError from Exceptions import FpdbParseError
import Configuration import Configuration
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
import pygtk import pygtk
import gtk import gtk
@ -266,13 +257,21 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py.
if self.ftpArchive == True: if self.ftpArchive == True:
log.debug(_("Converting ftpArchive format to readable")) log.debug(_("Converting ftpArchive format to readable"))
m = re.compile('^\*\*\*\*\*\*+\s#\s\d+\s\*\*\*\*\*+$', re.MULTILINE) # Remove ******************** # 1 *************************
m = re.compile('\*{20}\s#\s\d+\s\*{25}\s+', re.MULTILINE)
self.obs = m.sub('', self.obs) self.obs = m.sub('', self.obs)
if self.obs is None or self.obs == "": if self.obs is None or self.obs == "":
log.info(_("Read no hands.")) log.error(_("Read no hands."))
return [] return []
return re.split(self.re_SplitHands, self.obs) handlist = re.split(self.re_SplitHands, self.obs)
# Some HH formats leave dangling text after the split
# ie. </game> (split) </session>EOL
# Remove this dangler if less than 50 characters and warn in the log
if len(handlist[-1]) <= 50:
handlist.pop()
log.warn(_("Removing text < 50 characters"))
return handlist
def processHand(self, handText): def processHand(self, handText):
gametype = self.determineGameType(handText) gametype = self.determineGameType(handText)
@ -289,6 +288,7 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py.
base = gametype['base'] base = gametype['base']
limit = gametype['limitType'] limit = gametype['limitType']
l = [type] + [base] + [limit] l = [type] + [base] + [limit]
if l in self.readSupportedGames(): if l in self.readSupportedGames():
if gametype['base'] == 'hold': if gametype['base'] == 'hold':
log.debug("hand = Hand.HoldemOmahaHand(self, self.sitename, gametype, handtext)") log.debug("hand = Hand.HoldemOmahaHand(self, self.sitename, gametype, handtext)")
@ -298,15 +298,15 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py.
elif gametype['base'] == 'draw': elif gametype['base'] == 'draw':
hand = Hand.DrawHand(self.config, self, self.sitename, gametype, handText) hand = Hand.DrawHand(self.config, self, self.sitename, gametype, handText)
else: else:
log.info(_("Unsupported game type: %s" % gametype)) log.error(_("Unsupported game type: %s" % gametype))
raise FpdbParseError(_("Unsupported game type: %s" % gametype))
if hand: if hand:
#hand.writeHand(self.out_fh) #hand.writeHand(self.out_fh)
return hand return hand
else: else:
log.info(_("Unsupported game type: %s" % gametype)) log.error(_("Unsupported game type: %s" % gametype))
# TODO: pity we don't know the HID at this stage. Log the entire hand? # TODO: pity we don't know the HID at this stage. Log the entire hand?
# From the log we can deduce that it is the hand after the one before :)
# These functions are parse actions that may be overridden by the inheriting class # These functions are parse actions that may be overridden by the inheriting class
@ -668,12 +668,23 @@ or None if we fail to get the info """
else: else:
return table_name return table_name
@staticmethod
def getTableNoRe(tournament):
"Returns string to search window title for tournament table no."
# Full Tilt: $30 + $3 Tournament (181398949), Table 1 - 600/1200 Ante 100 - Limit Razz
# PokerStars: WCOOP 2nd Chance 02: $1,050 NLHE - Tournament 307521826 Table 1 - Blinds $30/$60
return "%s.+Table (\d+)" % (tournament, )
def getTableTitleRe(config, sitename, *args, **kwargs): def getTableTitleRe(config, sitename, *args, **kwargs):
"Returns string to search in windows titles for current site" "Returns string to search in windows titles for current site"
return getSiteHhc(config, sitename).getTableTitleRe(*args, **kwargs) return getSiteHhc(config, sitename).getTableTitleRe(*args, **kwargs)
def getTableNoRe(config, sitename, *args, **kwargs):
"Returns string to search window titles for tournament table no."
return getSiteHhc(config, sitename).getTableNoRe(*args, **kwargs)
def getSiteHhc(config, sitename): def getSiteHhc(config, sitename):
"Returns HHC class for current site" "Returns HHC class for current site"
hhcName = config.supported_sites[sitename].converter hhcName = config.supported_sites[sitename].converter

View File

@ -22,6 +22,10 @@ Create and manage the hud overlays.
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
######################################################################## ########################################################################
import L10n
_ = L10n.get_translation()
# Standard Library modules # Standard Library modules
import os import os
import sys import sys
@ -42,18 +46,6 @@ if os.name == 'nt':
import win32con import win32con
import win32api import win32api
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
# FreePokerTools modules # FreePokerTools modules
import Configuration import Configuration
import Stats import Stats
@ -61,6 +53,7 @@ import Mucked
import Database import Database
#import HUD_main #import HUD_main
def importName(module_name, name): def importName(module_name, name):
"""Import a named object 'name' from module 'module_name'.""" """Import a named object 'name' from module 'module_name'."""
# Recipe 16.3 in the Python Cookbook, 2nd ed. Thanks!!!! # Recipe 16.3 in the Python Cookbook, 2nd ed. Thanks!!!!
@ -71,14 +64,15 @@ def importName(module_name, name):
return None return None
return(getattr(module, name)) return(getattr(module, name))
class Hud:
class Hud:
def __init__(self, parent, table, max, poker_game, config, db_connection): def __init__(self, parent, table, max, poker_game, config, db_connection):
# __init__ is (now) intended to be called from the stdin thread, so it # __init__ is (now) intended to be called from the stdin thread, so it
# cannot touch the gui # cannot touch the gui
if parent is None: # running from cli .. if parent is None: # running from cli ..
self.parent = self self.parent = self
self.parent = parent else:
self.parent = parent
self.table = table self.table = table
self.config = config self.config = config
self.poker_game = poker_game self.poker_game = poker_game
@ -90,11 +84,11 @@ class Hud:
self.mw_created = False self.mw_created = False
self.hud_params = parent.hud_params self.hud_params = parent.hud_params
self.stat_windows = {} self.stat_windows = {}
self.popup_windows = {} self.popup_windows = {}
self.aux_windows = [] self.aux_windows = []
# configure default font and colors from the configuration
(font, font_size) = config.get_default_font(self.table.site) (font, font_size) = config.get_default_font(self.table.site)
self.colors = config.get_default_colors(self.table.site) self.colors = config.get_default_colors(self.table.site)
self.hud_ui = config.get_hud_ui_parameters() self.hud_ui = config.get_hud_ui_parameters()
@ -107,6 +101,7 @@ class Hud:
# do we need to add some sort of condition here for dealing with a request for a font that doesn't exist? # do we need to add some sort of condition here for dealing with a request for a font that doesn't exist?
game_params = config.get_game_parameters(self.poker_game) game_params = config.get_game_parameters(self.poker_game)
# if there are AUX windows configured, set them up (Ray knows how this works, if anyone needs info)
if not game_params['aux'] == [""]: if not game_params['aux'] == [""]:
for aux in game_params['aux']: for aux in game_params['aux']:
aux_params = config.get_aux_parameters(aux) aux_params = config.get_aux_parameters(aux)
@ -118,14 +113,16 @@ class Hud:
self.creation_attrs = None self.creation_attrs = None
def create_mw(self): def create_mw(self):
# Set up a main window for this this instance of the HUD # Set up a main window for this this instance of the HUD
win = gtk.Window() win = gtk.Window()
win.set_skip_taskbar_hint(True) # invisible to taskbar
win.set_gravity(gtk.gdk.GRAVITY_STATIC) win.set_gravity(gtk.gdk.GRAVITY_STATIC)
win.set_title("%s FPDBHUD" % (self.table.name)) win.set_title("%s FPDBHUD" % (self.table.name)) # give it a title that we can easily filter out in the window list when Table search code is looking
win.set_skip_taskbar_hint(True) win.set_decorated(False) # kill titlebars
win.set_decorated(False) win.set_opacity(self.colors["hudopacity"]) # set it to configured hud opacity
win.set_opacity(self.colors["hudopacity"]) win.set_focus(None)
win.set_focus_on_map(False)
win.set_accept_focus(False)
eventbox = gtk.EventBox() eventbox = gtk.EventBox()
label = gtk.Label(self.hud_ui['label']) label = gtk.Label(self.hud_ui['label'])
@ -133,6 +130,7 @@ class Hud:
win.add(eventbox) win.add(eventbox)
eventbox.add(label) eventbox.add(label)
# set it to the desired color of the HUD for this site
label.modify_bg(gtk.STATE_NORMAL, self.backgroundcolor) label.modify_bg(gtk.STATE_NORMAL, self.backgroundcolor)
label.modify_fg(gtk.STATE_NORMAL, self.foregroundcolor) label.modify_fg(gtk.STATE_NORMAL, self.foregroundcolor)
@ -140,9 +138,11 @@ class Hud:
eventbox.modify_fg(gtk.STATE_NORMAL, self.foregroundcolor) eventbox.modify_fg(gtk.STATE_NORMAL, self.foregroundcolor)
self.main_window = win self.main_window = win
# move it to the table window's X/Y position (0,0 on the table window usually)
self.main_window.move(self.table.x, self.table.y) self.main_window.move(self.table.x, self.table.y)
# A popup menu for the main window # A popup menu for the main window
# This menu code has become extremely long - is there a better way to do this?
menu = gtk.Menu() menu = gtk.Menu()
killitem = gtk.MenuItem(_('Kill This HUD')) killitem = gtk.MenuItem(_('Kill This HUD'))
@ -165,9 +165,9 @@ class Hud:
# set agg_bb_mult to 1 to stop aggregation # set agg_bb_mult to 1 to stop aggregation
item = gtk.CheckMenuItem(_('For This Blind Level Only')) item = gtk.CheckMenuItem(_('For This Blind Level Only'))
self.aggMenu.append(item) self.aggMenu.append(item)
item.connect("activate", self.set_aggregation, ('P',1)) item.connect("activate", self.set_aggregation, ('P', 1))
setattr(self, 'h_aggBBmultItem1', item) setattr(self, 'h_aggBBmultItem1', item)
item = gtk.MenuItem(_('For Multiple Blind Levels:')) item = gtk.MenuItem(_('For Multiple Blind Levels:'))
self.aggMenu.append(item) self.aggMenu.append(item)
@ -362,7 +362,7 @@ class Hud:
item.ms = i item.ms = i
maxSeatsMenu.append(item) maxSeatsMenu.append(item)
item.connect("activate", self.change_max_seats) item.connect("activate", self.change_max_seats)
setattr(self, 'maxSeatsMenuItem%d' % (i-1), item) setattr(self, 'maxSeatsMenuItem%d' % (i - 1), item)
eventbox.connect_object("button-press-event", self.on_button_press, menu) eventbox.connect_object("button-press-event", self.on_button_press, menu)
@ -393,7 +393,7 @@ class Hud:
if self.hud_params['h_agg_bb_mult'] != num \ if self.hud_params['h_agg_bb_mult'] != num \
and getattr(self, 'h_aggBBmultItem'+str(num)).get_active(): and getattr(self, 'h_aggBBmultItem'+str(num)).get_active():
log.debug('set_player_aggregation', num) log.debug('set_player_aggregation %d', num)
self.hud_params['h_agg_bb_mult'] = num self.hud_params['h_agg_bb_mult'] = num
for mult in ('1', '2', '3', '10', '10000'): for mult in ('1', '2', '3', '10', '10000'):
if mult != str(num): if mult != str(num):
@ -404,7 +404,7 @@ class Hud:
if self.hud_params['agg_bb_mult'] != num \ if self.hud_params['agg_bb_mult'] != num \
and getattr(self, 'aggBBmultItem'+str(num)).get_active(): and getattr(self, 'aggBBmultItem'+str(num)).get_active():
log.debug('set_opponent_aggregation', num) log.debug('set_opponent_aggregation %d', num)
self.hud_params['agg_bb_mult'] = num self.hud_params['agg_bb_mult'] = num
for mult in ('1', '2', '3', '10', '10000'): for mult in ('1', '2', '3', '10', '10000'):
if mult != str(num): if mult != str(num):
@ -457,6 +457,13 @@ class Hud:
log.debug("setting self.hud_params[%s] = %s" % (param, style)) log.debug("setting self.hud_params[%s] = %s" % (param, style))
def update_table_position(self): def update_table_position(self):
# get table's X/Y position on the desktop, and relocate all of our child windows to accomodate
# In Windows, we can verify the existence of a Window, with win32gui.IsWindow(). In Linux, there doesn't seem to be a
# way to verify the existence of a Window, without trying to access it, which if it doesn't exist anymore, results in a
# big giant X trap and crash.
# People tell me this is a bad idea, because theoretically, IsWindow() could return true now, but not be true when we actually
# use it, but accessing a dead window doesn't result in a complete windowing system shutdown in Windows, whereas it does
# in X. - Eric
if os.name == 'nt': if os.name == 'nt':
if not win32gui.IsWindow(self.table.number): if not win32gui.IsWindow(self.table.number):
self.parent.kill_hud(self, self.table.name) self.parent.kill_hud(self, self.table.name)
@ -465,17 +472,19 @@ class Hud:
return False return False
# anyone know how to do this in unix, or better yet, trap the X11 error that is triggered when executing the get_origin() for a closed window? # anyone know how to do this in unix, or better yet, trap the X11 error that is triggered when executing the get_origin() for a closed window?
if self.table.gdkhandle is not None: if self.table.gdkhandle is not None:
(x, y) = self.table.gdkhandle.get_origin() (oldx, oldy) = self.table.gdkhandle.get_origin() # In Windows, this call returns (0,0) if it's an invalid window. In X, the X server is immediately killed.
if self.table.x != x or self.table.y != y: #(x, y, width, height) = self.table.get_geometry()
self.table.x = x #print "self.table.get_geometry=",x,y,width,height
self.table.y = y if self.table.oldx != oldx or self.table.oldy != oldy: # If the current position does not equal the stored position, save the new position, and then move all the sub windows.
self.main_window.move(x + self.site_params['xshift'], y + self.site_params['yshift']) self.table.oldx = oldx
self.table.oldy = oldy
self.main_window.move(oldx + self.site_params['xshift'], oldy + self.site_params['yshift'])
adj = self.adj_seats(self.hand, self.config) adj = self.adj_seats(self.hand, self.config)
loc = self.config.get_locations(self.table.site, self.max) loc = self.config.get_locations(self.table.site, self.max)
# TODO: is stat_windows getting converted somewhere from a list to a dict, for no good reason? # TODO: is stat_windows getting converted somewhere from a list to a dict, for no good reason?
for i, w in enumerate(self.stat_windows.itervalues()): for i, w in enumerate(self.stat_windows.itervalues()):
(x, y) = loc[adj[i+1]] (oldx, oldy) = loc[adj[i+1]]
w.relocate(x, y) w.relocate(oldx, oldy)
# While we're at it, fix the positions of mucked cards too # While we're at it, fix the positions of mucked cards too
for aux in self.aux_windows: for aux in self.aux_windows:
@ -486,11 +495,27 @@ class Hud:
return True return True
def up_update_table_position(self):
# callback for table moved
# move the stat windows
adj = self.adj_seats(self.hand, self.config)
loc = self.config.get_locations(self.table.site, self.max)
for i, w in enumerate(self.stat_windows.itervalues()):
(x, y) = loc[adj[i+1]]
w.relocate(x, y)
# move the main window
self.main_window.move(self.table.x + self.site_params['xshift'], self.table.y + self.site_params['yshift'])
# and move any auxs
for aux in self.aux_windows:
aux.update_card_positions()
return True
def on_button_press(self, widget, event): def on_button_press(self, widget, event):
if event.button == 1: if event.button == 1: # if primary button, start movement
self.main_window.begin_move_drag(event.button, int(event.x_root), int(event.y_root), event.time) self.main_window.begin_move_drag(event.button, int(event.x_root), int(event.y_root), event.time)
return True return True
if event.button == 3: if event.button == 3: # if secondary button, popup our main popup window
widget.popup(None, None, None, event.button, event.time) widget.popup(None, None, None, event.button, event.time)
return True return True
return False return False
@ -535,7 +560,7 @@ class Hud:
loc = self.stat_windows[sw].window.get_position() loc = self.stat_windows[sw].window.get_position()
new_loc = (loc[0] - self.table.x, loc[1] - self.table.y) new_loc = (loc[0] - self.table.x, loc[1] - self.table.y)
new_layout[self.stat_windows[sw].adj - 1] = new_loc new_layout[self.stat_windows[sw].adj - 1] = new_loc
self.config.edit_layout(self.table.site, self.max, locations = new_layout) self.config.edit_layout(self.table.site, self.max, locations=new_layout)
# ask each aux to save its layout back to the config object # ask each aux to save its layout back to the config object
[aux.save_layout() for aux in self.aux_windows] [aux.save_layout() for aux in self.aux_windows]
# save the config object back to the file # save the config object back to the file
@ -543,12 +568,12 @@ class Hud:
self.config.save() self.config.save()
def adj_seats(self, hand, config): def adj_seats(self, hand, config):
# determine how to adjust seating arrangements, if a "preferred seat" is set in the hud layout configuration
# Need range here, not xrange -> need the actual list # Need range here, not xrange -> need the actual list
adj = range(0, self.max + 1) # default seat adjustments = no adjustment adj = range(0, self.max + 1) # default seat adjustments = no adjustment
# does the user have a fav_seat? # does the user have a fav_seat?
if self.max not in config.supported_sites[self.table.site].layout: if self.max not in config.supported_sites[self.table.site].layout:
sys.stderr.write(_("No layout found for %d-max games for site %s\n") % (self.max, self.table.site) ) sys.stderr.write(_("No layout found for %d-max games for site %s\n") % (self.max, self.table.site))
return adj return adj
if self.table.site != None and int(config.supported_sites[self.table.site].layout[self.max].fav_seat) > 0: if self.table.site != None and int(config.supported_sites[self.table.site].layout[self.max].fav_seat) > 0:
try: try:
@ -621,8 +646,8 @@ class Hud:
[config.supported_games[self.poker_game].stats[stat].col] = \ [config.supported_games[self.poker_game].stats[stat].col] = \
config.supported_games[self.poker_game].stats[stat].stat_name config.supported_games[self.poker_game].stats[stat].stat_name
if os.name == "nt": # if os.name == "nt": # we call update_table_position() regularly in Windows to see if we're moving around. See comments on that function for why this isn't done in X.
gobject.timeout_add(500, self.update_table_position) # gobject.timeout_add(500, self.update_table_position)
def update(self, hand, config): def update(self, hand, config):
self.hand = hand # this is the last hand, so it is available later self.hand = hand # this is the last hand, so it is available later
@ -656,8 +681,8 @@ class Hud:
if this_stat.hudcolor != "": if this_stat.hudcolor != "":
window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.hudcolor)) window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.hudcolor))
else: else:
window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor']))
if this_stat.stat_loth != "": if this_stat.stat_loth != "":
if number[0] < (float(this_stat.stat_loth)/100): if number[0] < (float(this_stat.stat_loth)/100):
window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_locolor)) window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_locolor))
@ -668,9 +693,12 @@ class Hud:
window.label[r][c].set_text(statstring) window.label[r][c].set_text(statstring)
if statstring != "xxx": # is there a way to tell if this particular stat window is visible already, or no? if statstring != "xxx": # is there a way to tell if this particular stat window is visible already, or no?
window.window.show_all() unhidewindow = True
tip = "%s\n%s\n%s, %s" % (statd['screen_name'], number[5], number[3], number[4]) tip = "%s\n%s\n%s, %s" % (statd['screen_name'], number[5], number[3], number[4])
Stats.do_tip(window.e_box[r][c], tip) Stats.do_tip(window.e_box[r][c], tip)
if unhidewindow: #and not window.window.visible: # there is no "visible" attribute in gtk.Window, although the docs seem to indicate there should be
window.window.show_all()
unhidewindow = False
def topify_window(self, window): def topify_window(self, window):
window.set_focus_on_map(False) window.set_focus_on_map(False)
@ -686,7 +714,7 @@ class Stat_Window:
# This handles all callbacks from button presses on the event boxes in # This handles all callbacks from button presses on the event boxes in
# the stat windows. There is a bit of an ugly kludge to separate single- # the stat windows. There is a bit of an ugly kludge to separate single-
# and double-clicks. # and double-clicks.
self.window.show_all() self.window.show() #_all()
if event.button == 3: # right button event if event.button == 3: # right button event
newpopup = Popup_window(self.window, self) newpopup = Popup_window(self.window, self)
@ -745,11 +773,13 @@ class Stat_Window:
self.window = gtk.Window() self.window = gtk.Window()
self.window.set_decorated(0) self.window.set_decorated(0)
self.window.set_property("skip-taskbar-hint", True)
self.window.set_gravity(gtk.gdk.GRAVITY_STATIC) self.window.set_gravity(gtk.gdk.GRAVITY_STATIC)
self.window.set_title("%s" % seat) self.window.set_title("%s" % seat)
self.window.set_property("skip-taskbar-hint", True) self.window.set_focus(None) # set gtk default focus widget for this window to None
self.window.set_focus_on_map(False) self.window.set_focus_on_map(False)
self.window.set_accept_focus(False)
grid = gtk.Table(rows = game.rows, columns = game.cols, homogeneous = False) grid = gtk.Table(rows = game.rows, columns = game.cols, homogeneous = False)
self.grid = grid self.grid = grid

122
pyfpdb/IdentifySite.py Normal file
View File

@ -0,0 +1,122 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#Copyright 2010 Chaz Littlejohn
#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()
import re
import sys
import os
import os.path
from optparse import OptionParser
import codecs
import Configuration
import Database
__ARCHIVE_PRE_HEADER_REGEX='^Hand #(\d+)\s*$|\*{20}\s#\s\d+\s\*+\s+'
re_SplitArchive = re.compile(__ARCHIVE_PRE_HEADER_REGEX)
class IdentifySite:
def __init__(self, config, in_path = '-'):
self.in_path = in_path
self.config = config
self.db = Database.Database(config)
self.sitelist = {}
self.filelist = {}
self.generateSiteList()
self.walkDirectory(self.in_path, self.sitelist)
def generateSiteList(self):
"""Generates a ordered dictionary of site, filter and filter name for each site in hhcs"""
for site, hhc in self.config.hhcs.iteritems():
filter = hhc.converter
filter_name = filter.replace("ToFpdb", "")
result = self.db.get_site_id(site)
if len(result) == 1:
self.sitelist[result[0][0]] = (site, filter, filter_name)
else:
pass
def walkDirectory(self, dir, sitelist):
"""Walks a directory, and executes a callback on each file"""
dir = os.path.abspath(dir)
for file in [file for file in os.listdir(dir) if not file in [".",".."]]:
nfile = os.path.join(dir,file)
if os.path.isdir(nfile):
self.walkDirectory(nfile, sitelist)
else:
self.idSite(nfile, sitelist)
def __listof(self, x):
if isinstance(x, list) or isinstance(x, tuple):
return x
else:
return [x]
def idSite(self, file, sitelist):
"""Identifies the site the hh file originated from"""
if file.endswith('.txt'):
self.filelist[file] = ''
archive = False
for site, info in sitelist.iteritems():
mod = __import__(info[1])
obj = getattr(mod, info[2], None)
for kodec in self.__listof(obj.codepage):
try:
in_fh = codecs.open(file, 'r', kodec)
whole_file = in_fh.read()
in_fh.close()
if info[2] in ('OnGame', 'Winamax'):
m = obj.re_HandInfo.search(whole_file)
elif info[2] in ('PartyPoker'):
m = obj.re_GameInfoRing.search(whole_file)
if not m:
m = obj.re_GameInfoTrny.search(whole_file)
else:
m = obj.re_GameInfo.search(whole_file)
if re_SplitArchive.search(whole_file):
archive = True
if m:
self.filelist[file] = [info[0]] + [info[1]] + [kodec] + [archive]
break
except:
pass
def main(argv=None):
if argv is None:
argv = sys.argv[1:]
config = Configuration.Config(file = "HUD_config.test.xml")
in_path = 'regression-test-files/'
IdSite = IdentifySite(config, in_path)
print "\n----------- SITE LIST -----------"
for site, info in IdSite.sitelist.iteritems():
print site, info
print "----------- END SITE LIST -----------"
print "\n----------- ID REGRESSION FILES -----------"
for file, site in IdSite.filelist.iteritems():
print file, site
print "----------- END ID REGRESSION FILES -----------"
if __name__ == '__main__':
sys.exit(main())

132
pyfpdb/ImapFetcher.py Executable file → Normal file
View File

@ -19,6 +19,9 @@
#see http://docs.python.org/library/imaplib.html for the python interface #see http://docs.python.org/library/imaplib.html for the python interface
#see http://tools.ietf.org/html/rfc2060#section-6.4.4 for IMAP4 search criteria #see http://tools.ietf.org/html/rfc2060#section-6.4.4 for IMAP4 search criteria
import L10n
_ = L10n.get_translation()
from imaplib import IMAP4, IMAP4_SSL from imaplib import IMAP4, IMAP4_SSL
import sys import sys
import codecs import codecs
@ -26,29 +29,30 @@ import re
import Configuration import Configuration
import Database import Database
from Exceptions import FpdbParseError
import SQL import SQL
import Options import Options
import PokerStarsSummary import PokerStarsSummary
import FullTiltPokerSummary
import locale def splitPokerStarsSummaries(summaryText): #TODO: this needs to go to PSS.py
lang=locale.getdefaultlocale()[0][0:2] re_SplitTourneys = PokerStarsSummary.PokerStarsSummary.re_SplitTourneys
if lang=="en": splitSummaries = re.split(re_SplitTourneys, summaryText)
def _(string): return string
else: if len(splitSummaries) <= 1:
import gettext print _("DEBUG: re_SplitTourneys isn't matching")
try:
trans = gettext.translation("fpdb", localedir="locale", languages=[lang]) return splitSummaries
trans.install()
except IOError: def splitFullTiltSummaries(summaryText):#TODO: this needs to go to FTPS.py
def _(string): return string re_SplitTourneys = FullTiltPokerSummary.FullTiltPokerSummary.re_SplitTourneys
splitSummaries = re.split(re_SplitTourneys, summaryText)
if len(splitSummaries) <= 1:
print _("DEBUG: re_SplitTourneys isn't matching")
def splitPokerStarsSummaries(emailText):
splitSummaries=emailText.split("\nPokerStars Tournament #")[1:]
for i in range(len(splitSummaries)):
splitSummaries[i]="PokerStars Tournament #"+splitSummaries[i]
return splitSummaries return splitSummaries
#end def emailText
def run(config, db): def run(config, db):
#print "start of IS.run" #print "start of IS.run"
@ -72,57 +76,89 @@ def run(config, db):
response, searchData = server.search(None, "SUBJECT", "PokerStars Tournament History Request") response, searchData = server.search(None, "SUBJECT", "PokerStars Tournament History Request")
for messageNumber in searchData[0].split(" "): for messageNumber in searchData[0].split(" "):
response, headerData = server.fetch(messageNumber, "(BODY[HEADER.FIELDS (SUBJECT)])") response, headerData = server.fetch(messageNumber, "(BODY[HEADER.FIELDS (SUBJECT)])")
#print "response to fetch subject:",response
if response!="OK": if response!="OK":
raise error #TODO: show error message raise error #TODO: show error message
neededMessages.append(("PS", messageNumber)) neededMessages.append(("PS", messageNumber))
print _("ImapFetcher: Found %s messages to fetch") %(len(neededMessages))
if (len(neededMessages)==0): if (len(neededMessages)==0):
raise error #TODO: show error message raise error #TODO: show error message
for messageData in neededMessages:
email_bodies = []
for i, messageData in enumerate(neededMessages, start=1):
print "Retrieving message %s" % i
response, bodyData = server.fetch(messageData[1], "(UID BODY[TEXT])") response, bodyData = server.fetch(messageData[1], "(UID BODY[TEXT])")
bodyData=bodyData[0][1] bodyData=bodyData[0][1]
if response!="OK": if response!="OK":
raise error #TODO: show error message raise error #TODO: show error message
if messageData[0]=="PS": if messageData[0]=="PS":
summaryTexts=(splitPokerStarsSummaries(bodyData)) email_bodies.append(bodyData)
for summaryText in summaryTexts:
result=PokerStarsSummary.PokerStarsSummary(db=db, config=config, siteName=u"PokerStars", summaryText=summaryText, builtFrom = "IMAP")
#print "finished importing a PS summary with result:",result
#TODO: count results and output to shell like hand importer does
print _("completed running Imap import, closing server connection")
#finally: #finally:
# try: # try:
server.close() server.close()
# finally: # finally:
# pass # pass
server.logout() server.logout()
print _("Completed retrieving IMAP messages, closing server connection")
errors = 0
if len(email_bodies) > 0:
errors = importSummaries(db, config, email_bodies, options = None)
else:
print _("No Tournament summaries found.")
print _("Errors: %s" % errors)
def readFile(filename, options):
codepage = ["utf8"]
whole_file = None
if options.hhc == "PokerStars":
codepage = PokerStarsSummary.PokerStarsSummary.codepage
elif options.hhc == "Full Tilt Poker":
codepage = FullTiltPokerSummary.FullTiltPokerSummary.codepage
for kodec in codepage:
#print "trying", kodec
try:
in_fh = codecs.open(filename, 'r', kodec)
whole_file = in_fh.read()
in_fh.close()
break
except:
pass
def readFile(filename):
kodec = "utf8"
in_fh = codecs.open(filename, 'r', kodec)
whole_file = in_fh.read()
in_fh.close()
return whole_file return whole_file
def runFake(db, config, options):
summaryText = readFile(options.filename, options)
importSummaries(db, config,[summaryText], options=options)
def importSummaries(db, config, summaries, options = None):
# TODO: At this point we should have:
# - list of strings to process
# - The sitename OR specialised TourneySummary object
# Using options is pretty ugly
errors = 0
for summaryText in summaries:
# And we should def be using a 'Split' from the site object
if options == None or options.hhc == "PokerStars":
summaryTexts=(splitPokerStarsSummaries(summaryText))
elif options.hhc == "Full Tilt Poker":
summaryTexts=(splitFullTiltSummaries(summaryText))
def runFake(db, config, infile): print "Found %s summaries in email" %(len(summaryTexts))
summaryText = readFile(infile) for j, summaryText in enumerate(summaryTexts, start=1):
# This regex should be part of PokerStarsSummary try:
re_SplitGames = re.compile("PokerStars Tournament ") if options == None or options.hhc == "PokerStars":
summaryList = re.split(re_SplitGames, summaryText) PokerStarsSummary.PokerStarsSummary(db=db, config=config, siteName=u"PokerStars", summaryText=summaryText, builtFrom = "IMAP")
elif options.hhc == "Full Tilt Poker":
FullTiltPokerSummary.FullTiltPokerSummary(db=db, config=config, siteName=u"Fulltilt", summaryText=summaryText, builtFrom = "IMAP")
except FpdbParseError, e:
errors += 1
print _("Finished importing %s/%s PS summaries") %(j, len(summaryTexts))
if len(summaryList) <= 1: return errors
print "DEBUG: re_SplitGames isn't matching"
for summary in summaryList[1:]:
result = PokerStarsSummary.PokerStarsSummary(db=db, config=config, siteName=u"PokerStars", summaryText=summary, builtFrom = "file")
print "DEBUG: Processed: %s: tournNo: %s" % (result.tourneyId, result.tourNo)
def splitPokerStarsSummaries(emailText):
splitSummaries=emailText.split("\nPokerStars Tournament #")[1:]
def main(argv=None): def main(argv=None):
@ -136,6 +172,10 @@ def main(argv=None):
print _("USAGE:") print _("USAGE:")
sys.exit(0) sys.exit(0)
if options.hhc == "PokerStarsToFpdb":
print _("Need to define a converter")
exit(0)
# These options should really come from the OptionsParser # These options should really come from the OptionsParser
config = Configuration.Config() config = Configuration.Config()
db = Database.Database(config) db = Database.Database(config)
@ -146,7 +186,7 @@ def main(argv=None):
settings.update(config.get_default_paths()) settings.update(config.get_default_paths())
db.recreate_tables() db.recreate_tables()
runFake(db, config, options.infile) runFake(db, config, options)
if __name__ == '__main__': if __name__ == '__main__':
sys.exit(main()) sys.exit(main())

37
pyfpdb/L10n.py Normal file
View File

@ -0,0 +1,37 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#Copyright 2010 Steffen Schaumburg
#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 locale
def pass_through(to_translate): return to_translate
(lang, charset) = locale.getdefaultlocale()
if lang==None or lang[:2]=="en":
translation=pass_through
else:
import gettext
try:
trans = gettext.translation("fpdb", localedir="locale", languages=[lang])
trans.install()
translation=_
except IOError:
translation=pass_through
#def translate(to_translate):
# return _(to_translate)
def get_translation():
return translation

View File

@ -18,6 +18,9 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
######################################################################## ########################################################################
import L10n
_ = L10n.get_translation()
import sys import sys
import exceptions import exceptions
@ -30,18 +33,6 @@ import Configuration
from HandHistoryConverter import * from HandHistoryConverter import *
from decimal import Decimal 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
# OnGame HH Format # OnGame HH Format
class OnGame(HandHistoryConverter): class OnGame(HandHistoryConverter):
@ -61,15 +52,15 @@ class OnGame(HandHistoryConverter):
games = { # base, category games = { # base, category
"TEXAS_HOLDEM" : ('hold','holdem'), "TEXAS_HOLDEM" : ('hold','holdem'),
# 'Omaha' : ('hold','omahahi'), 'OMAHA_HI' : ('hold','omahahi'),
# 'Omaha Hi/Lo' : ('hold','omahahilo'), # 'Omaha Hi/Lo' : ('hold','omahahilo'),
# 'Razz' : ('stud','razz'), # 'Razz' : ('stud','razz'),
# 'RAZZ' : ('stud','razz'), # 'RAZZ' : ('stud','razz'),
# '7 Card Stud' : ('stud','studhi'), 'SEVEN_CARD_STUD' : ('stud','studhi'),
# '7 Card Stud Hi/Lo' : ('stud','studhilo'), 'SEVEN_CARD_STUD_HI_LO' : ('stud','studhilo'),
# 'Badugi' : ('draw','badugi'), # 'Badugi' : ('draw','badugi'),
# 'Triple Draw 2-7 Lowball' : ('draw','27_3draw'), # 'Triple Draw 2-7 Lowball' : ('draw','27_3draw'),
# '5 Card Draw' : ('draw','fivedraw') 'FIVE_CARD_DRAW' : ('draw','fivedraw')
} }
# Static regexes # Static regexes
@ -97,7 +88,7 @@ class OnGame(HandHistoryConverter):
Table:\s(?P<TABLE>[\'\w\s]+)\s\[\d+\]\s\( Table:\s(?P<TABLE>[\'\w\s]+)\s\[\d+\]\s\(
( (
(?P<LIMIT>NO_LIMIT|Limit|LIMIT|Pot\sLimit)\s (?P<LIMIT>NO_LIMIT|Limit|LIMIT|Pot\sLimit)\s
(?P<GAME>TEXAS_HOLDEM|RAZZ)\s (?P<GAME>TEXAS_HOLDEM|OMAHA_HI|SEVEN_CARD_STUD|SEVEN_CARD_STUD_HI_LO|RAZZ|FIVE_CARD_DRAW)\s
(%(LS)s)?(?P<SB>[.0-9]+)/ (%(LS)s)?(?P<SB>[.0-9]+)/
(%(LS)s)?(?P<BB>[.0-9]+) (%(LS)s)?(?P<BB>[.0-9]+)
)? )?
@ -111,14 +102,12 @@ class OnGame(HandHistoryConverter):
re_DateTime = re.compile(""" re_DateTime = re.compile("""
[a-zA-Z]{3}\s [a-zA-Z]{3}\s
(?P<M>[a-zA-Z]{3})\s (?P<M>[a-zA-Z]{3})\s
(?P<D>[0-9]{2})\s (?P<D>[0-9]+)\s
(?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)\s (?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)\s
(?P<OFFSET>\w+[-+]\d+)\s (?P<OFFSET>\w+[-+]\d+)\s
(?P<Y>[0-9]{4}) (?P<Y>[0-9]{4})
""", re.MULTILINE|re.VERBOSE) """, re.MULTILINE|re.VERBOSE)
# self.rexx.button_re = re.compile('#SUMMARY\nDealer: (?P<BUTTONPNAME>.*)\n')
#Seat 1: .Lucchess ($4.17 in chips) #Seat 1: .Lucchess ($4.17 in chips)
#Seat 1: phantomaas ($27.11) #Seat 1: phantomaas ($27.11)
#Seat 5: mleo17 ($9.37) #Seat 5: mleo17 ($9.37)
@ -138,10 +127,11 @@ class OnGame(HandHistoryConverter):
player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")" player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")"
subst = {'PLYR': player_re, 'CUR': self.sym[hand.gametype['currency']]} subst = {'PLYR': player_re, 'CUR': self.sym[hand.gametype['currency']]}
self.re_PostSB = re.compile('(?P<PNAME>.*) posts small blind \((%(CUR)s)?(?P<SB>[\.0-9]+)\)' % subst, re.MULTILINE) self.re_PostSB = re.compile('(?P<PNAME>.*) posts small blind \((%(CUR)s)?(?P<SB>[\.0-9]+)\)' % subst, re.MULTILINE)
self.re_PostBB = re.compile('\), (?P<PNAME>.*) posts big blind \((%(CUR)s)?(?P<BB>[\.0-9]+)\)' % subst, re.MULTILINE) self.re_PostBB = re.compile('(?P<PNAME>.*) posts big blind \((%(CUR)s)?(?P<BB>[\.0-9]+)\)' % subst, re.MULTILINE)
self.re_Antes = re.compile(r"^%(PLYR)s: posts the ante (%(CUR)s)?(?P<ANTE>[\.0-9]+)" % subst, re.MULTILINE) self.re_Antes = re.compile(r"^%(PLYR)s: posts the ante (%(CUR)s)?(?P<ANTE>[\.0-9]+)" % subst, re.MULTILINE)
self.re_BringIn = re.compile(r"^%(PLYR)s: brings[- ]in( low|) for (%(CUR)s)?(?P<BRINGIN>[\.0-9]+)" % subst, re.MULTILINE) self.re_BringIn = re.compile(r"^%(PLYR)s: brings[- ]in( low|) for (%(CUR)s)?(?P<BRINGIN>[\.0-9]+)" % subst, re.MULTILINE)
self.re_PostBoth = re.compile('.*\n(?P<PNAME>.*): posts small \& big blinds \( (%(CUR)s)?(?P<SBBB>[\.0-9]+)\)' % subst) self.re_PostBoth = re.compile('(?P<PNAME>.*): posts small \& big blind \( (%(CUR)s)?(?P<SBBB>[\.0-9]+)\)' % subst)
self.re_PostDead = re.compile('(?P<PNAME>.*) posts dead blind \((%(CUR)s)?(?P<DEAD>[\.0-9]+)\)' % subst, re.MULTILINE)
self.re_HeroCards = re.compile('Dealing\sto\s%(PLYR)s:\s\[(?P<CARDS>.*)\]' % subst) self.re_HeroCards = re.compile('Dealing\sto\s%(PLYR)s:\s\[(?P<CARDS>.*)\]' % subst)
#lopllopl checks, Eurolll checks, .Lucchess checks. #lopllopl checks, Eurolll checks, .Lucchess checks.
@ -165,6 +155,8 @@ class OnGame(HandHistoryConverter):
return [ return [
["ring", "hold", "fl"], ["ring", "hold", "fl"],
["ring", "hold", "nl"], ["ring", "hold", "nl"],
["ring", "stud", "fl"],
["ring", "draw", "fl"],
] ]
def determineGameType(self, handText): def determineGameType(self, handText):
@ -217,21 +209,28 @@ class OnGame(HandHistoryConverter):
#hand.startTime = time.strptime(m.group('DATETIME'), "%a %b %d %H:%M:%S GMT%z %Y") #hand.startTime = time.strptime(m.group('DATETIME'), "%a %b %d %H:%M:%S GMT%z %Y")
# Stupid library doesn't seem to support %z (http://docs.python.org/library/time.html?highlight=strptime#time.strptime) # Stupid library doesn't seem to support %z (http://docs.python.org/library/time.html?highlight=strptime#time.strptime)
# So we need to re-interpret te string to be useful # So we need to re-interpret te string to be useful
m1 = self.re_DateTime.finditer(info[key]) a = self.re_DateTime.search(info[key])
for a in m1: if a:
datetimestr = "%s/%s/%s %s:%s:%s" % (a.group('Y'),a.group('M'), a.group('D'), a.group('H'),a.group('MIN'),a.group('S')) datetimestr = "%s/%s/%s %s:%s:%s" % (a.group('Y'),a.group('M'), a.group('D'), a.group('H'),a.group('MIN'),a.group('S'))
tzoffset = a.group('OFFSET') tzoffset = a.group('OFFSET')
# TODO: Manually adjust time against OFFSET else:
datetimestr = "2010/Jan/01 01:01:01"
log.error(_("readHandInfo: DATETIME not matched: '%s'" % info[key]))
print "DEBUG: readHandInfo: DATETIME not matched: '%s'" % info[key]
# TODO: Manually adjust time against OFFSET
hand.startTime = datetime.datetime.strptime(datetimestr, "%Y/%b/%d %H:%M:%S") # also timezone at end, e.g. " ET" hand.startTime = datetime.datetime.strptime(datetimestr, "%Y/%b/%d %H:%M:%S") # also timezone at end, e.g. " ET"
hand.startTime = HandHistoryConverter.changeTimezone(hand.startTime, tzoffset, "UTC") hand.startTime = HandHistoryConverter.changeTimezone(hand.startTime, tzoffset, "UTC")
if key == 'HID': if key == 'HID':
hand.handid = info[key] hand.handid = info[key]
# Need to remove non-alphanumerics for MySQL
hand.handid = hand.handid.replace('R','')
hand.handid = hand.handid.replace('-','')
if key == 'TABLE': if key == 'TABLE':
hand.tablename = info[key] hand.tablename = info[key]
# TODO: These # TODO: These
hand.buttonpos = 1 hand.buttonpos = 1
hand.maxseats = 10 hand.maxseats = None # Set to None - Hand.py will guessMaxSeats()
hand.mixed = None hand.mixed = None
def readPlayerStacks(self, hand): def readPlayerStacks(self, hand):
@ -241,18 +240,24 @@ class OnGame(HandHistoryConverter):
hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH')) hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH'))
def markStreets(self, hand): def markStreets(self, hand):
# PREFLOP = ** Dealing down cards ** if hand.gametype['base'] in ("hold"):
# This re fails if, say, river is missing; then we don't get the ** that starts the river. m = re.search(r"pocket cards(?P<PREFLOP>.+(?= Dealing flop )|.+(?=Summary))"
#m = re.search('(\*\* Dealing down cards \*\*\n)(?P<PREFLOP>.*?\n\*\*)?( Dealing Flop \*\* \[ (?P<FLOP1>\S\S), (?P<FLOP2>\S\S), (?P<FLOP3>\S\S) \])?(?P<FLOP>.*?\*\*)?( Dealing Turn \*\* \[ (?P<TURN1>\S\S) \])?(?P<TURN>.*?\*\*)?( Dealing River \*\* \[ (?P<RIVER1>\S\S) \])?(?P<RIVER>.*)', hand.string,re.DOTALL)
#if hand.gametype['base'] in ("hold"):
#elif hand.gametype['base'] in ("stud"):
#elif hand.gametype['base'] in ("draw"):
# only holdem so far:
m = re.search(r"pocket cards(?P<PREFLOP>.+(?= Dealing flop )|.+(?=Summary))"
r"( Dealing flop (?P<FLOP>\[\S\S, \S\S, \S\S\].+(?= Dealing turn)|.+(?=Summary)))?" r"( Dealing flop (?P<FLOP>\[\S\S, \S\S, \S\S\].+(?= Dealing turn)|.+(?=Summary)))?"
r"( Dealing turn (?P<TURN>\[\S\S\].+(?= Dealing river)|.+(?=Summary)))?" r"( Dealing turn (?P<TURN>\[\S\S\].+(?= Dealing river)|.+(?=Summary)))?"
r"( Dealing river (?P<RIVER>\[\S\S\].+(?=Summary)))?", hand.handText, re.DOTALL) r"( Dealing river (?P<RIVER>\[\S\S\].+(?=Summary)))?", hand.handText, re.DOTALL)
elif hand.gametype['base'] in ("stud"):
m = re.search(r"(?P<ANTES>.+(?=Dealing pocket cards)|.+)"
r"(Dealing pocket cards(?P<THIRD>.+(?=Dealing 4th street)|.+))?"
r"(Dealing 4th street(?P<FOURTH>.+(?=Dealing 5th street)|.+))?"
r"(Dealing 5th street(?P<FIFTH>.+(?=Dealing 6th street)|.+))?"
r"(Dealing 6th street(?P<SIXTH>.+(?=Dealing river)|.+))?"
r"(Dealing river(?P<SEVENTH>.+))?", hand.handText,re.DOTALL)
elif hand.gametype['base'] in ("draw"):
m = re.search(r"(?P<PREDEAL>.+(?=Dealing pocket cards)|.+)"
r"(Dealing pocket cards(?P<DEAL>.+(?=\*\*\* FIRST DRAW \*\*\*)|.+))?"
r"(\*\*\* FIRST DRAW \*\*\*(?P<DRAWONE>.+(?=\*\*\* SECOND DRAW \*\*\*)|.+))?"
r"(\*\*\* SECOND DRAW \*\*\*(?P<DRAWTWO>.+(?=\*\*\* THIRD DRAW \*\*\*)|.+))?"
r"(\*\*\* THIRD DRAW \*\*\*(?P<DRAWTHREE>.+))?", hand.handText,re.DOTALL)
hand.addStreets(m) hand.addStreets(m)
@ -280,7 +285,6 @@ class OnGame(HandHistoryConverter):
hand.setCommunityCards(street, m.group('CARDS').split(', ')) hand.setCommunityCards(street, m.group('CARDS').split(', '))
def readBlinds(self, hand): def readBlinds(self, hand):
#log.debug( _("readBlinds starting, hand=") + "\n["+hand.handText+"]" )
try: try:
m = self.re_PostSB.search(hand.handText) m = self.re_PostSB.search(hand.handText)
hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB')) hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB'))
@ -289,6 +293,9 @@ class OnGame(HandHistoryConverter):
#hand.addBlind(None, None, None) #hand.addBlind(None, None, None)
for a in self.re_PostBB.finditer(hand.handText): for a in self.re_PostBB.finditer(hand.handText):
hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB')) hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB'))
for a in self.re_PostDead.finditer(hand.handText):
#print "DEBUG: Found dead blind: addBlind(%s, 'secondsb', %s)" %(a.group('PNAME'), a.group('DEAD'))
hand.addBlind(a.group('PNAME'), 'secondsb', a.group('DEAD'))
for a in self.re_PostBoth.finditer(hand.handText): for a in self.re_PostBoth.finditer(hand.handText):
hand.addBlind(a.group('PNAME'), 'small & big blinds', a.group('SBBB')) hand.addBlind(a.group('PNAME'), 'small & big blinds', a.group('SBBB'))
@ -311,10 +318,10 @@ class OnGame(HandHistoryConverter):
for street in ('PREFLOP', 'DEAL'): for street in ('PREFLOP', 'DEAL'):
if street in hand.streets.keys(): if street in hand.streets.keys():
m = self.re_HeroCards.finditer(hand.streets[street]) m = self.re_HeroCards.finditer(hand.streets[street])
for found in m: for found in m:
hand.hero = found.group('PNAME') hand.hero = found.group('PNAME')
newcards = found.group('CARDS').split(', ') newcards = found.group('CARDS').split(', ')
hand.addHoleCards(street, hand.hero, closed=newcards, shown=False, mucked=False, dealt=True) hand.addHoleCards(street, hand.hero, closed=newcards, shown=False, mucked=False, dealt=True)
def readAction(self, hand, street): def readAction(self, hand, street):
m = self.re_Action.finditer(hand.streets[street]) m = self.re_Action.finditer(hand.streets[street])

View File

@ -15,22 +15,13 @@
#along with this program. If not, see <http://www.gnu.org/licenses/>. #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. #In the "official" distribution you can find the license in agpl-3.0.txt.
import L10n
_ = L10n.get_translation()
import sys import sys
from optparse import OptionParser from optparse import OptionParser
# http://docs.python.org/library/optparse.html # http://docs.python.org/library/optparse.html
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
def fpdb_options(): def fpdb_options():
"""Process command line options for fpdb and HUD_main.""" """Process command line options for fpdb and HUD_main."""
@ -47,9 +38,6 @@ def fpdb_options():
parser.add_option("-r", "--rerunPython", parser.add_option("-r", "--rerunPython",
action="store_true", action="store_true",
help=_("Indicates program was restarted with a different path (only allowed once).")) help=_("Indicates program was restarted with a different path (only allowed once)."))
parser.add_option("-i", "--infile",
dest="infile", default="Slartibartfast",
help=_("Input file"))
parser.add_option("-k", "--konverter", parser.add_option("-k", "--konverter",
dest="hhc", default="PokerStarsToFpdb", dest="hhc", default="PokerStarsToFpdb",
help=_("Module name for Hand History Converter")) help=_("Module name for Hand History Converter"))
@ -62,6 +50,15 @@ def fpdb_options():
help = _("Print version information and exit.")) help = _("Print version information and exit."))
parser.add_option("-u", "--usage", action="store_true", dest="usage", default=False, parser.add_option("-u", "--usage", action="store_true", dest="usage", default=False,
help=_("Print some useful one liners")) help=_("Print some useful one liners"))
# The following options are used for SplitHandHistory.py
parser.add_option("-f", "--file", dest="filename", metavar="FILE", default=None,
help=_("Input file in quiet mode"))
parser.add_option("-o", "--outpath", dest="outpath", metavar="FILE", default=None,
help=_("Input out path in quiet mode"))
parser.add_option("-a", "--archive", action="store_true", dest="archive", default=False,
help=_("File to be split is a PokerStars or Full Tilt Poker archive file"))
parser.add_option("-n", "--numhands", dest="hands", default="100", type="int",
help=_("How many hands do you want saved to each file. Default is 100"))
(options, argv) = parser.parse_args() (options, argv) = parser.parse_args()

View File

@ -18,21 +18,13 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
######################################################################## ########################################################################
import L10n
_ = L10n.get_translation()
import sys import sys
from collections import defaultdict from collections import defaultdict
import locale from Configuration import LOCALE_ENCODING
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
from Exceptions import FpdbParseError from Exceptions import FpdbParseError
from HandHistoryConverter import * from HandHistoryConverter import *
@ -50,7 +42,7 @@ class FpdbParseError(FpdbParseError):
class PartyPoker(HandHistoryConverter): class PartyPoker(HandHistoryConverter):
sitename = "PartyPoker" sitename = "PartyPoker"
codepage = "cp1252" codepage = "utf8"
siteId = 9 siteId = 9
filetype = "text" filetype = "text"
sym = {'USD': "\$", } sym = {'USD': "\$", }
@ -61,10 +53,10 @@ class PartyPoker(HandHistoryConverter):
re_GameInfoRing = re.compile(""" re_GameInfoRing = re.compile("""
(?P<CURRENCY>\$|)\s*(?P<RINGLIMIT>[.,0-9]+)([.,0-9/$]+)?\s*(?:USD)?\s* (?P<CURRENCY>\$|)\s*(?P<RINGLIMIT>[.,0-9]+)([.,0-9/$]+)?\s*(?:USD)?\s*
(?P<LIMIT>(NL|PL|))\s* (?P<LIMIT>(NL|PL|))\s*
(?P<GAME>(Texas\ Hold\'em|Omaha)) (?P<GAME>(Texas\ Hold\'em|Omaha|7 Card Stud Hi-Lo))
\s*\-\s* \s*\-\s*
(?P<DATETIME>.+) (?P<DATETIME>.+)
""", re.VERBOSE) """, re.VERBOSE | re.UNICODE)
re_GameInfoTrny = re.compile(""" re_GameInfoTrny = re.compile("""
(?P<LIMIT>(NL|PL|))\s* (?P<LIMIT>(NL|PL|))\s*
(?P<GAME>(Texas\ Hold\'em|Omaha))\s+ (?P<GAME>(Texas\ Hold\'em|Omaha))\s+
@ -78,7 +70,7 @@ class PartyPoker(HandHistoryConverter):
\) \)
\s*\-\s* \s*\-\s*
(?P<DATETIME>.+) (?P<DATETIME>.+)
""", re.VERBOSE) """, re.VERBOSE | re.UNICODE)
re_Hid = re.compile("^Game \#(?P<HID>\d+) starts.") re_Hid = re.compile("^Game \#(?P<HID>\d+) starts.")
re_PlayerInfo = re.compile(""" re_PlayerInfo = re.compile("""
@ -189,6 +181,10 @@ class PartyPoker(HandHistoryConverter):
return self._gameType return self._gameType
return self._gameType return self._gameType
@staticmethod
def decode_hand_text(handText):
return handText.encode("latin1").decode(LOCALE_ENCODING)
def determineGameType(self, handText): def determineGameType(self, handText):
"""inspect the handText and return the gametype dict """inspect the handText and return the gametype dict
@ -196,9 +192,14 @@ class PartyPoker(HandHistoryConverter):
{'limitType': xxx, 'base': xxx, 'category': xxx}""" {'limitType': xxx, 'base': xxx, 'category': xxx}"""
info = {} info = {}
handText = self.decode_hand_text(handText)
m = self._getGameType(handText) m = self._getGameType(handText)
m_20BBmin = self.re_20BBmin.search(handText) m_20BBmin = self.re_20BBmin.search(handText)
if m is None: if m is None:
tmp = handText[0:100]
log.error(_("determineGameType: Unable to recognise gametype from: '%s'") % tmp)
log.error(_("determineGameType: Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
return None return None
mg = m.groupdict() mg = m.groupdict()
@ -207,6 +208,7 @@ class PartyPoker(HandHistoryConverter):
games = { # base, category games = { # base, category
"Texas Hold'em" : ('hold','holdem'), "Texas Hold'em" : ('hold','holdem'),
'Omaha' : ('hold','omahahi'), 'Omaha' : ('hold','omahahi'),
"7 Card Stud Hi-Lo" : ('stud','studhi'),
} }
currencies = { '$':'USD', '':'T$' } currencies = { '$':'USD', '':'T$' }
@ -251,6 +253,10 @@ class PartyPoker(HandHistoryConverter):
def readHandInfo(self, hand): 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 = {} info = {}
try: try:
info.update(self.re_Hid.search(hand.handText).groupdict()) info.update(self.re_Hid.search(hand.handText).groupdict())
@ -299,10 +305,15 @@ class PartyPoker(HandHistoryConverter):
#Saturday, July 25, 07:53:52 EDT 2009 #Saturday, July 25, 07:53:52 EDT 2009
#Thursday, July 30, 21:40:41 MSKS 2009 #Thursday, July 30, 21:40:41 MSKS 2009
#Sunday, October 25, 13:39:07 MSK 2009 #Sunday, October 25, 13:39:07 MSK 2009
m2 = re.search("\w+, (?P<M>\w+) (?P<D>\d+), (?P<H>\d+):(?P<MIN>\d+):(?P<S>\d+) (?P<TZ>[A-Z]+) (?P<Y>\d+)", info[key]) m2 = re.search(
# we cant use '%B' due to locale problems r"\w+,\s+(?P<M>\w+)\s+(?P<D>\d+),\s+(?P<H>\d+):(?P<MIN>\d+):(?P<S>\d+)\s+(?P<TZ>[A-Z]+)\s+(?P<Y>\d+)",
info[key],
re.UNICODE
)
months = ['January', 'February', 'March', 'April','May', 'June', months = ['January', 'February', 'March', 'April','May', 'June',
'July','August','September','October','November','December'] 'July','August','September','October','November','December']
if m2.group('M') not in months:
raise FpdbParseError("Only english hh is supported", hid=info["HID"])
month = months.index(m2.group('M')) + 1 month = months.index(m2.group('M')) + 1
datetimestr = "%s/%s/%s %s:%s:%s" % (m2.group('Y'), month,m2.group('D'),m2.group('H'),m2.group('MIN'),m2.group('S')) datetimestr = "%s/%s/%s %s:%s:%s" % (m2.group('Y'), month,m2.group('D'),m2.group('H'),m2.group('MIN'),m2.group('S'))
hand.startTime = datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S") hand.startTime = datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S")
@ -353,10 +364,54 @@ class PartyPoker(HandHistoryConverter):
def readPlayerStacks(self, hand): def readPlayerStacks(self, hand):
log.debug("readPlayerStacks") log.debug("readPlayerStacks")
m = self.re_PlayerInfo.finditer(hand.handText) m = self.re_PlayerInfo.finditer(hand.handText)
players = [] maxKnownStack = 0
zeroStackPlayers = []
for a in m: for a in m:
hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), if a.group('CASH') > '0':
clearMoneyString(a.group('CASH'))) #record max known stack for use with players with unknown stack
maxKnownStack = max(a.group('CASH'),maxKnownStack)
hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), clearMoneyString(a.group('CASH')))
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):
while startSeat in occupiedSeats:
if startSeat >= hand.maxseats:
startSeat = 0
startSeat += 1
return startSeat
re_JoiningPlayers = re.compile(r"(?P<PLAYERNAME>.*) has joined the table")
re_BBPostingPlayers = re.compile(r"(?P<PLAYERNAME>.*) posts big blind")
match_JoiningPlayers = re_JoiningPlayers.findall(hand.handText)
match_BBPostingPlayers = re_BBPostingPlayers.findall(hand.handText)
#add every player with zero stack, but:
#if a zero stacked player is just joined the table in this very hand then set his stack to maxKnownStack
for p in zeroStackPlayers:
if p[1] in match_JoiningPlayers:
p[2] = clearMoneyString(maxKnownStack)
hand.addPlayer(p[0],p[1],p[2])
seatedPlayers = list([(f[1]) for f in hand.players])
#it works for all known cases as of 2010-09-28
#should be refined with using match_ActivePlayers instead of match_BBPostingPlayers
#as a leaving and rejoining player could be active without posting a BB (sample HH needed)
unseatedActivePlayers = list(set(match_BBPostingPlayers) - set(seatedPlayers))
if unseatedActivePlayers:
for player in unseatedActivePlayers:
previousBBPoster = match_BBPostingPlayers[match_BBPostingPlayers.index(player)-1]
previousBBPosterSeat = dict([(f[1], f[0]) for f in hand.players])[previousBBPoster]
occupiedSeats = list([(f[0]) for f in hand.players])
occupiedSeats.sort()
newPlayerSeat = findFirstEmptySeat(previousBBPosterSeat)
hand.addPlayer(newPlayerSeat,player,clearMoneyString(maxKnownStack))
def markStreets(self, hand): def markStreets(self, hand):
m = re.search( m = re.search(
@ -507,7 +562,6 @@ class PartyPoker(HandHistoryConverter):
else: else:
return "%s.+Table\s#%s" % (TableName[0], table_number) return "%s.+Table\s#%s" % (TableName[0], table_number)
else: else:
print 'party', 'getTableTitleRe', table_number
return table_name return table_name
def clearMoneyString(money): def clearMoneyString(money):

View File

@ -18,22 +18,12 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
######################################################################## ########################################################################
import L10n
_ = L10n.get_translation()
import sys import sys
from HandHistoryConverter import * from HandHistoryConverter import *
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 Pkr(HandHistoryConverter): class Pkr(HandHistoryConverter):
@ -115,7 +105,7 @@ class Pkr(HandHistoryConverter):
^%(PLYR)s(?P<ATYPE>\sbets|\schecks|\sraises|\scalls|\sfolds)(\sto)? ^%(PLYR)s(?P<ATYPE>\sbets|\schecks|\sraises|\scalls|\sfolds)(\sto)?
(\s(%(CUR)s)?(?P<BET>[.\d]+))? (\s(%(CUR)s)?(?P<BET>[.\d]+))?
""" % subst, re.MULTILINE|re.VERBOSE) """ % subst, re.MULTILINE|re.VERBOSE)
self.re_ShowdownAction = re.compile(r"^%s: shows \[(?P<CARDS>.*)\]" % player_re, re.MULTILINE) self.re_ShowdownAction = re.compile(r"^%(PLYR)s shows \[(?P<CARDS>.*)\]" % subst, re.MULTILINE)
self.re_CollectPot = re.compile(r"^%(PLYR)s wins %(CUR)s(?P<POT>[.\d]+)" % subst, re.MULTILINE) self.re_CollectPot = re.compile(r"^%(PLYR)s wins %(CUR)s(?P<POT>[.\d]+)" % subst, re.MULTILINE)
self.re_sitsOut = re.compile("^%s sits out" % player_re, re.MULTILINE) self.re_sitsOut = re.compile("^%s sits out" % player_re, re.MULTILINE)
self.re_ShownCards = re.compile("^Seat (?P<SEAT>[0-9]+): %s (\(.*\) )?(?P<SHOWED>showed|mucked) \[(?P<CARDS>.*)\].*" % player_re, re.MULTILINE) self.re_ShownCards = re.compile("^Seat (?P<SEAT>[0-9]+): %s (\(.*\) )?(?P<SHOWED>showed|mucked) \[(?P<CARDS>.*)\].*" % player_re, re.MULTILINE)
@ -239,6 +229,7 @@ class Pkr(HandHistoryConverter):
if players.has_key(a.group('PNAME')): if players.has_key(a.group('PNAME')):
pass # Ignore pass # Ignore
else: else:
#print "DEBUG: addPlayer(%s, %s, %s)" % (a.group('SEAT'), a.group('PNAME'), a.group('CASH'))
hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH')) hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH'))
players[a.group('PNAME')] = True players[a.group('PNAME')] = True
@ -335,9 +326,16 @@ class Pkr(HandHistoryConverter):
m = self.re_Action.finditer(hand.streets[street]) m = self.re_Action.finditer(hand.streets[street])
for action in m: for action in m:
acts = action.groupdict() acts = action.groupdict()
#print "DEBUG: readAction: acts: %s" % acts
if action.group('ATYPE') == ' raises': if action.group('ATYPE') == ' raises':
hand.addRaiseTo( street, action.group('PNAME'), action.group('BET') ) hand.addRaiseTo( street, action.group('PNAME'), action.group('BET') )
elif action.group('ATYPE') == ' calls': elif action.group('ATYPE') == ' calls':
# Amount in hand history is not cumulative
# ie. Player3 calls 0.08
# Player5 raises to 0.16
# Player3 calls 0.16 (Doh! he's only calling 0.08
# TODO: Going to have to write an addCallStoopid()
#print "DEBUG: addCall( %s, %s, None)" %(street,action.group('PNAME'))
hand.addCall( street, action.group('PNAME'), action.group('BET') ) hand.addCall( street, action.group('PNAME'), action.group('BET') )
elif action.group('ATYPE') == ' bets': elif action.group('ATYPE') == ' bets':
hand.addBet( street, action.group('PNAME'), action.group('BET') ) hand.addBet( street, action.group('PNAME'), action.group('BET') )
@ -354,9 +352,10 @@ class Pkr(HandHistoryConverter):
def readShowdownActions(self, hand): def readShowdownActions(self, hand):
# TODO: pick up mucks also?? # TODO: pick up mucks also??
for shows in self.re_ShowdownAction.finditer(hand.handText): for shows in self.re_ShowdownAction.finditer(hand.handText):
cards = shows.group('CARDS').split(' ') cards = shows.group('CARDS').split(' ')
#print "DEBUG: addShownCards(%s, %s)" %(cards, shows.group('PNAME'))
hand.addShownCards(cards, shows.group('PNAME')) hand.addShownCards(cards, shows.group('PNAME'))
def readCollectPot(self,hand): def readCollectPot(self,hand):

View File

@ -17,6 +17,9 @@
"""pokerstars-specific summary parsing code""" """pokerstars-specific summary parsing code"""
import L10n
_ = L10n.get_translation()
from decimal import Decimal from decimal import Decimal
import datetime import datetime
@ -25,18 +28,6 @@ from HandHistoryConverter import *
import PokerStarsToFpdb import PokerStarsToFpdb
from TourneySummary import * from TourneySummary import *
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 PokerStarsSummary(TourneySummary): class PokerStarsSummary(TourneySummary):
limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl', 'LIMIT':'fl' } limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl', 'LIMIT':'fl' }
games = { # base, category games = { # base, category
@ -57,147 +48,38 @@ class PokerStarsSummary(TourneySummary):
'LS' : "\$|\xe2\x82\xac|" # legal currency symbols - Euro(cp1252, utf-8) 'LS' : "\$|\xe2\x82\xac|" # legal currency symbols - Euro(cp1252, utf-8)
} }
re_SplitGames = re.compile("^PokerStars") re_SplitTourneys = re.compile("PokerStars Tournament ")
re_TourNo = re.compile("\#(?P<TOURNO>[0-9]+),") re_TourNo = re.compile("\#(?P<TOURNO>[0-9]+),")
re_TourneyInfo = re.compile(u""" re_TourneyInfo = re.compile(u"""
\#(?P<TOURNO>[0-9]+),\s \#(?P<TOURNO>[0-9]+),\s
(?P<LIMIT>No\sLimit|Limit|LIMIT|Pot\sLimit)\s (?P<LIMIT>No\sLimit|Limit|LIMIT|Pot\sLimit)\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/Lo|Badugi|Triple\sDraw\s2\-7\sLowball|5\sCard\sDraw)\s+
(?P<DESC>[ a-zA-Z]+\s)? (?P<DESC>[ a-zA-Z]+\s+)?
(Buy-In:\s\$(?P<BUYIN>[.0-9]+)(\/\$(?P<FEE>[.0-9]+))?\s)? (Buy-In:\s\$(?P<BUYIN>[.0-9]+)(\/\$(?P<FEE>[.0-9]+))?(?P<CUR>\s%(LEGAL_ISO)s)?\s+)?
(?P<ENTRIES>[0-9]+)\splayers\s (?P<ENTRIES>[0-9]+)\splayers\s+
(\$?(?P<ADDED>[.\d]+)\sadded\sto\sthe\sprize\spool\sby\sPokerStars\.com\s)? (\$?(?P<ADDED>[.\d]+)\sadded\sto\sthe\sprize\spool\sby\sPokerStars\.com\s+)?
(Total\sPrize\sPool:\s\$?(?P<PRIZEPOOL>[.0-9]+)\s)? (Total\sPrize\sPool:\s\$?(?P<PRIZEPOOL>[.0-9]+)(\s%(LEGAL_ISO)s)?\s+)?
(Target\sTournament\s.*)? (Target\sTournament\s.*)?
Tournament\sstarted\s-\s Tournament\sstarted\s+(-\s)?
(?P<Y>[0-9]{4})\/(?P<M>[0-9]{2})\/(?P<D>[0-9]{2})[\-\s]+(?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)\s?\(?(?P<TZ>[A-Z]+)\)\s (?P<Y>[0-9]{4})\/(?P<M>[0-9]{2})\/(?P<D>[0-9]{2})[\-\s]+(?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)\s?\(?(?P<TZ>[A-Z]+)\)?\s
""" % substitutions ,re.VERBOSE|re.MULTILINE|re.DOTALL) """ % substitutions ,re.VERBOSE|re.MULTILINE|re.DOTALL)
re_Currency = re.compile(u"""(?P<CURRENCY>[%(LS)s]|FPP)""" % substitutions) re_Currency = re.compile(u"""(?P<CURRENCY>[%(LS)s]|FPP)""" % substitutions)
re_Player = re.compile(u"""(?P<RANK>[0-9]+):\s(?P<NAME>.*)\s\(.*\),(\s)?(\$(?P<WINNINGS>[0-9]+\.[0-9]+))?(?P<STILLPLAYING>still\splaying)?""") re_Player = re.compile(u"""(?P<RANK>[0-9]+):\s(?P<NAME>.*)\s\(.*\),(\s)?(\$(?P<WINNINGS>[0-9]+\.[0-9]+))?(?P<STILLPLAYING>still\splaying)?((?P<TICKET>Tournament\sTicket)\s\(WSOP\sStep\s(?P<LEVEL>\d)\))?(\s+)?""")
re_DateTime = re.compile("\[(?P<Y>[0-9]{4})\/(?P<M>[0-9]{2})\/(?P<D>[0-9]{2})[\- ]+(?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)") re_DateTime = re.compile("\[(?P<Y>[0-9]{4})\/(?P<M>[0-9]{2})\/(?P<D>[0-9]{2})[\- ]+(?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)")
re_Entries = re.compile("[0-9]+") codepage = ["utf-8"]
re_Prizepool = re.compile("\$[0-9]+\.[0-9]+")
re_BuyInFee = re.compile("(?P<BUYIN>[0-9]+\.[0-9]+).*(?P<FEE>[0-9]+\.[0-9]+)")
re_FPP = re.compile("(?P<FPP>[0-9]+)\sFPP")
#note: the dollar and cent in the below line are currency-agnostic
re_Added = re.compile("(?P<DOLLAR>[0-9]+)\.(?P<CENT>[0-9]+)\s(?P<CURRENCY>[A-Z]+)(\sadded\sto\sthe\sprize\spool\sby\sPokerStars)")
re_DateTimeET = re.compile("(?P<Y>[0-9]{4})\/(?P<M>[0-9]{2})\/(?P<D>[0-9]{2})[\- ]+(?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)")
re_GameInfo = re.compile(u""".+(?P<LIMIT>No\sLimit|Limit|LIMIT|Pot\sLimit)\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)""")
def parseSummary(self): def parseSummary(self):
lines=self.summaryText.splitlines()
self.tourNo = self.re_TourNo.findall(lines[0])[0][1:-1] #ignore game and limit type as thats not recorded
result=self.re_GameInfo.search(lines[0])
result=result.groupdict()
self.gametype['limitType']=self.limits[result['LIMIT']]
self.gametype['category']=self.games[result['GAME']][1]
if lines[1].find("$")!=-1: #TODO: move this into a method and call that from PokerStarsToFpdb.py:269 if hand.buyinCurrency=="USD" etc.
self.currency="USD"
elif lines[1].find(u"")!=-1:
self.currency="EUR"
elif lines[1].find("FPP")!=-1:
self.currency="PSFP"
else:
raise FpdbParseError(_("didn't recognise buyin currency in:")+lines[1])
if self.currency=="USD" or self.currency=="EUR":
result=self.re_BuyInFee.search(lines[1])
result=result.groupdict()
self.buyin=int(100*Decimal(result['BUYIN']))
self.fee=int(100*Decimal(result['FEE']))
elif self.currency=="PSFP":
result=self.re_FPP.search(lines[1])
result=result.groupdict()
self.buyin=int(Decimal(result['FPP']))
self.fee=0
currentLine=2
self.entries = self.re_Entries.findall(lines[currentLine])[0]
currentLine+=1 #note that I chose to make the code keep state (the current line number)
#as that means it'll fail rather than silently skip potentially valuable information
#print "after entries lines[currentLine]", lines[currentLine]
result=self.re_Added.search(lines[currentLine])
if result:
result=result.groupdict()
self.added=100*int(Decimal(result['DOLLAR']))+int(Decimal(result['CENT']))
self.addedCurrency=result['CURRENCY']
currentLine+=1
else:
self.added=0
self.addedCurrency="NA"
#print "after added/entries lines[currentLine]", lines[currentLine]
result=self.re_Prizepool.findall(lines[currentLine])
if result:
self.prizepool = result[0]
self.prizepool = self.prizepool[1:-3]+self.prizepool[-2:]
currentLine+=1
#print "after prizepool lines[currentLine]", lines[currentLine]
useET=False
result=self.re_DateTime.search(lines[currentLine])
if not result:
print _("in not result starttime")
useET=True
result=self.re_DateTimeET.search(lines[currentLine])
result=result.groupdict()
datetimestr = "%s/%s/%s %s:%s:%s" % (result['Y'], result['M'],result['D'],result['H'],result['MIN'],result['S'])
self.startTime= datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S") # also timezone at end, e.g. " ET"
self.startTime = HandHistoryConverter.changeTimezone(self.startTime, "ET", "UTC")
currentLine+=1
if useET:
result=self.re_DateTimeET.search(lines[currentLine])
else:
result=self.re_DateTime.search(lines[currentLine])
if result:
result=result.groupdict()
datetimestr = "%s/%s/%s %s:%s:%s" % (result['Y'], result['M'],result['D'],result['H'],result['MIN'],result['S'])
self.endTime= datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S") # also timezone at end, e.g. " ET"
self.endTime = HandHistoryConverter.changeTimezone(self.endTime, "ET", "UTC")
currentLine+=1
if lines[currentLine].find("Tournament is still in progress")!=-1:
currentLine+=1
for i in range(currentLine,len(lines)-2): #lines with rank and winnings info
if lines[i].find(":")==-1:
break
result=self.re_Player.search(lines[i])
result=result.groupdict()
rank=result['RANK']
name=result['NAME']
winnings=result['WINNINGS']
if winnings:
winnings=int(100*Decimal(winnings))
else:
winnings=0
if result['STILLPLAYING']:
#print "stillplaying"
rank=None
winnings=None
self.addPlayer(rank, name, winnings, self.currency, None, None, None)#TODO: currency, ko/addon/rebuy count -> need examples!
#end def parseSummary
def parseSummaryFile(self):
m = self.re_TourneyInfo.search(self.summaryText) m = self.re_TourneyInfo.search(self.summaryText)
if m == None: if m == None:
tmp = self.summaryText[0:200] tmp = self.summaryText[0:200]
log.error(_("parseSummaryFile: Unable to recognise Tourney Info: '%s'") % tmp) log.error(_("parseSummary: Unable to recognise Tourney Info: '%s'") % tmp)
log.error(_("parseSummaryFile: Raising FpdbParseError")) log.error(_("parseSummary: Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise Tourney Info: '%s'") % tmp) raise FpdbParseError(_("Unable to recognise Tourney Info: '%s'") % tmp)
#print "DEBUG: m.groupdict(): %s" % m.groupdict() #print "DEBUG: m.groupdict(): %s" % m.groupdict()
@ -222,8 +104,8 @@ class PokerStarsSummary(TourneySummary):
m = self.re_Currency.search(self.summaryText) m = self.re_Currency.search(self.summaryText)
if m == None: if m == None:
log.error(_("parseSummaryFile: Unable to locate currency")) log.error(_("parseSummary: Unable to locate currency"))
log.error(_("parseSummaryFile: Raising FpdbParseError")) log.error(_("parseSummary: Raising FpdbParseError"))
raise FpdbParseError(_("Unable to locate currency")) raise FpdbParseError(_("Unable to locate currency"))
#print "DEBUG: m.groupdict(): %s" % m.groupdict() #print "DEBUG: m.groupdict(): %s" % m.groupdict()
@ -248,6 +130,18 @@ class PokerStarsSummary(TourneySummary):
rank=None rank=None
winnings=None winnings=None
if 'TICKET' and mg['TICKET'] != None:
#print "Tournament Ticket Level %s" % mg['LEVEL']
step_values = {
'1' : '750', # Step 1 - $7.50 USD
'2' : '2750', # Step 2 - $27.00 USD
'3' : '8200', # Step 3 - $82.00 USD
'4' : '21500', # Step 4 - $215.00 USD
'5' : '70000', # Step 5 - $700.00 USD
'6' : '210000', # Step 6 - $2100.00 USD
}
winnings = step_values[mg['LEVEL']]
#TODO: currency, ko/addon/rebuy count -> need examples! #TODO: currency, ko/addon/rebuy count -> need examples!
#print "DEBUG: addPlayer(%s, %s, %s, %s, None, None, None)" %(rank, name, winnings, self.currency) #print "DEBUG: addPlayer(%s, %s, %s, %s, None, None, None)" %(rank, name, winnings, self.currency)
#print "DEBUG: self.buyin: %s self.fee %s" %(self.buyin, self.fee) #print "DEBUG: self.buyin: %s self.fee %s" %(self.buyin, self.fee)

View File

@ -18,24 +18,15 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
######################################################################## ########################################################################
import L10n
_ = L10n.get_translation()
# TODO: straighten out discards for draw games # TODO: straighten out discards for draw games
import sys import sys
from HandHistoryConverter import * from HandHistoryConverter import *
from decimal import Decimal 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
# PokerStars HH Format # PokerStars HH Format
class PokerStars(HandHistoryConverter): class PokerStars(HandHistoryConverter):
@ -48,7 +39,7 @@ class PokerStars(HandHistoryConverter):
siteId = 2 # Needs to match id entry in Sites database siteId = 2 # Needs to match id entry in Sites database
mixes = { 'HORSE': 'horse', '8-Game': '8game', 'HOSE': 'hose'} # Legal mixed games mixes = { 'HORSE': 'horse', '8-Game': '8game', 'HOSE': 'hose'} # Legal mixed games
sym = {'USD': "\$", 'CAD': "\$", 'T$': "", "EUR": "\xe2\x82\xac", "GBP": "\xa3"} # ADD Euro, Sterling, etc HERE sym = {'USD': "\$", 'CAD': "\$", 'T$': "", "EUR": "\xe2\x82\xac", "GBP": "\xa3", "play": ""} # ADD Euro, Sterling, etc HERE
substitutions = { substitutions = {
'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes 'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
'LS' : "\$|\xe2\x82\xac|" # legal currency symbols - Euro(cp1252, utf-8) 'LS' : "\$|\xe2\x82\xac|" # legal currency symbols - Euro(cp1252, utf-8)
@ -106,10 +97,13 @@ class PokerStars(HandHistoryConverter):
(?P<CURRENCY>%(LS)s|)? (?P<CURRENCY>%(LS)s|)?
(?P<SB>[.0-9]+)/(%(LS)s)? (?P<SB>[.0-9]+)/(%(LS)s)?
(?P<BB>[.0-9]+) (?P<BB>[.0-9]+)
(?P<BLAH>\s-\s[%(LS)s\d\.]+\sCap\s-\s)? # Optional Cap part
\s?(?P<ISO>%(LEGAL_ISO)s)? \s?(?P<ISO>%(LEGAL_ISO)s)?
\)\s-\s # close paren of the stakes \) # close paren of the stakes
(?P<DATETIME>.*$)""" % substitutions, (?P<BLAH2>\s\[AAMS\sID:\s[A-Z0-9]+\])? # AAMS ID: in .it HH's
re.MULTILINE|re.VERBOSE) \s-\s
(?P<DATETIME>.*$)
""" % substitutions, re.MULTILINE|re.VERBOSE)
re_PlayerInfo = re.compile(u""" re_PlayerInfo = re.compile(u"""
^Seat\s(?P<SEAT>[0-9]+):\s ^Seat\s(?P<SEAT>[0-9]+):\s
@ -155,6 +149,7 @@ class PokerStars(HandHistoryConverter):
^%(PLYR)s:(?P<ATYPE>\sbets|\schecks|\sraises|\scalls|\sfolds|\sdiscards|\sstands\spat) ^%(PLYR)s:(?P<ATYPE>\sbets|\schecks|\sraises|\scalls|\sfolds|\sdiscards|\sstands\spat)
(\s(%(CUR)s)?(?P<BET>[.\d]+))?(\sto\s%(CUR)s(?P<BETTO>[.\d]+))? # the number discarded goes in <BET> (\s(%(CUR)s)?(?P<BET>[.\d]+))?(\sto\s%(CUR)s(?P<BETTO>[.\d]+))? # the number discarded goes in <BET>
\s*(and\sis\sall.in)? \s*(and\sis\sall.in)?
(and\shas\sreached\sthe\s[%(CUR)s\d\.]+\scap)?
(\scards?(\s\[(?P<DISCARDED>.+?)\])?)?\s*$""" (\scards?(\s\[(?P<DISCARDED>.+?)\])?)?\s*$"""
% subst, re.MULTILINE|re.VERBOSE) % subst, re.MULTILINE|re.VERBOSE)
self.re_ShowdownAction = re.compile(r"^%s: shows \[(?P<CARDS>.*)\]" % player_re, re.MULTILINE) self.re_ShowdownAction = re.compile(r"^%s: shows \[(?P<CARDS>.*)\]" % player_re, re.MULTILINE)
@ -170,6 +165,7 @@ class PokerStars(HandHistoryConverter):
["ring", "stud", "fl"], ["ring", "stud", "fl"],
["ring", "draw", "fl"], ["ring", "draw", "fl"],
["ring", "draw", "pl"],
["ring", "draw", "nl"], ["ring", "draw", "nl"],
["tour", "hold", "nl"], ["tour", "hold", "nl"],
@ -177,7 +173,11 @@ class PokerStars(HandHistoryConverter):
["tour", "hold", "fl"], ["tour", "hold", "fl"],
["tour", "stud", "fl"], ["tour", "stud", "fl"],
]
["tour", "draw", "fl"],
["tour", "draw", "pl"],
["tour", "draw", "nl"],
]
def determineGameType(self, handText): def determineGameType(self, handText):
info = {} info = {}
@ -221,9 +221,8 @@ class PokerStars(HandHistoryConverter):
m = self.re_HandInfo.search(hand.handText,re.DOTALL) m = self.re_HandInfo.search(hand.handText,re.DOTALL)
m2 = self.re_GameInfo.search(hand.handText) m2 = self.re_GameInfo.search(hand.handText)
if m is None or m2 is None: if m is None or m2 is None:
logging.info("Didn't match re_HandInfo") log.error("Didn't match re_HandInfo")
logging.info(hand.handText) raise FpdbParseError(_("No match in readHandInfo."))
raise FpdbParseError("No match in readHandInfo.")
info.update(m.groupdict()) info.update(m.groupdict())
info.update(m2.groupdict()) info.update(m2.groupdict())
@ -455,6 +454,7 @@ class PokerStars(HandHistoryConverter):
if m.group('SHOWED') == "showed": shown = True if m.group('SHOWED') == "showed": shown = True
elif m.group('SHOWED') == "mucked": mucked = True elif m.group('SHOWED') == "mucked": mucked = True
#print "DEBUG: hand.addShownCards(%s, %s, %s, %s)" %(cards, m.group('PNAME'), shown, mucked)
hand.addShownCards(cards=cards, player=m.group('PNAME'), shown=shown, mucked=mucked) hand.addShownCards(cards=cards, player=m.group('PNAME'), shown=shown, mucked=mucked)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -0,0 +1,158 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Generate Razz startCards encoding and decoding for Card.py"""
import re
re_space = re.compile("([\(\)AKQJT0-9]+)\s+", re.MULTILINE)
razzlist = """(32)A (3A)2 (2A)3 (42)A (4A)2 (2A)4 (43)A (4A)3 (3A)4 (43)2
(42)3 (32)4 (52)A (5A)2 (2A)5 (53)A (5A)3 (3A)5 (53)2 (52)3
(32)5 (54)A (5A)4 (4A)5 (54)2 (52)4 (42)5 (54)3 (53)4 (43)5
(62)A (6A)2 (2A)6 (63)A (6A)3 (3A)6 (63)2 (62)3 (32)6 (64)A
(6A)4 (4A)6 (64)2 (62)4 (42)6 (64)3 (63)4 (43)6 (65)A (6A)5
(5A)6 (65)2 (62)5 (52)6 (65)3 (63)5 (53)6 (65)4 (64)5 (54)6
(72)A (7A)2 (2A)7 (73)A (7A)3 (3A)7 (73)2 (72)3 (32)7 (74)A
(7A)4 (4A)7 (74)2 (72)4 (42)7 (74)3 (73)4 (43)7 (75)A (7A)5
(5A)7 (75)2 (72)5 (52)7 (75)3 (73)5 (53)7 (75)4 (74)5 (54)7
(76)A (7A)6 (6A)7 (76)2 (72)6 (62)7 (76)3 (73)6 (63)7 (76)4
(74)6 (64)7 (76)5 (75)6 (65)7 (82)A (8A)2 (2A)8 (83)A (8A)3
(3A)8 (83)2 (82)3 (32)8 (84)A (8A)4 (4A)8 (84)2 (82)4 (42)8
(84)3 (83)4 (43)8 (85)A (8A)5 (5A)8 (85)2 (82)5 (52)8 (85)3
(83)5 (53)8 (85)4 (84)5 (54)8 (86)A (8A)6 (6A)8 (86)2 (82)6
(62)8 (86)3 (83)6 (63)8 (86)4 (84)6 (64)8 (86)5 (85)6 (65)8
(87)A (8A)7 (7A)8 (87)2 (82)7 (72)8 (87)3 (83)7 (73)8 (87)4
(84)7 (74)8 (87)5 (85)7 (75)8 (87)6 (86)7 (76)8 (92)A (9A)2
(2A)9 (93)A (9A)3 (3A)9 (93)2 (92)3 (32)9 (94)A (9A)4 (4A)9
(94)2 (92)4 (42)9 (94)3 (93)4 (43)9 (95)A (9A)5 (5A)9 (95)2
(92)5 (52)9 (95)3 (93)5 (53)9 (95)4 (94)5 (54)9 (96)A (9A)6
(6A)9 (96)2 (92)6 (62)9 (96)3 (93)6 (63)9 (96)4 (94)6 (64)9
(96)5 (95)6 (65)9 (97)A (9A)7 (7A)9 (97)2 (92)7 (72)9 (97)3
(93)7 (73)9 (97)4 (94)7 (74)9 (97)5 (95)7 (75)9 (97)6 (96)7
(76)9 (98)A (9A)8 (8A)9 (98)2 (92)8 (82)9 (98)3 (93)8 (83)9
(98)4 (94)8 (84)9 (98)5 (95)8 (85)9 (98)6 (96)8 (86)9 (98)7
(97)8 (87)9 (T2)A (TA)2 (2A)T (T3)A (TA)3 (3A)T (T3)2 (T2)3
(32)T (T4)A (TA)4 (4A)T (T4)2 (T2)4 (42)T (T4)3 (T3)4 (43)T
(T5)A (TA)5 (5A)T (T5)2 (T2)5 (52)T (T5)3 (T3)5 (53)T (T5)4
(T4)5 (54)T (T6)A (TA)6 (6A)T (T6)2 (T2)6 (62)T (T6)3 (T3)6
(63)T (T6)4 (T4)6 (64)T (T6)5 (T5)6 (65)T (T7)A (TA)7 (7A)T
(T7)2 (T2)7 (72)T (T7)3 (T3)7 (73)T (T7)4 (T4)7 (74)T (T7)5
(T5)7 (75)T (T7)6 (T6)7 (76)T (T8)A (TA)8 (8A)T (T8)2 (T2)8
(82)T (T8)3 (T3)8 (83)T (T8)4 (T4)8 (84)T (T8)5 (T5)8 (85)T
(T8)6 (T6)8 (86)T (T8)7 (T7)8 (87)T (T9)A (TA)9 (9A)T (T9)2
(T2)9 (92)T (T9)3 (T3)9 (93)T (T9)4 (T4)9 (94)T (T9)5 (T5)9
(95)T (T9)6 (T6)9 (96)T (T9)7 (T7)9 (97)T (T9)8 (T8)9 (98)T
(J2)A (JA)2 (2A)J (J3)A (JA)3 (3A)J (J3)2 (J2)3 (32)J (J4)A
(JA)4 (4A)J (J4)2 (J2)4 (42)J (J4)3 (J3)4 (43)J (J5)A (JA)5
(5A)J (J5)2 (J2)5 (52)J (J5)3 (J3)5 (53)J (J5)4 (J4)5 (54)J
(J6)A (JA)6 (6A)J (J6)2 (J2)6 (62)J (J6)3 (J3)6 (63)J (J6)4
(J4)6 (64)J (J6)5 (J5)6 (65)J (J7)A (JA)7 (7A)J (J7)2 (J2)7
(72)J (J7)3 (J3)7 (73)J (J7)4 (J4)7 (74)J (J7)5 (J5)7 (75)J
(J7)6 (J6)7 (76)J (J8)A (JA)8 (8A)J (J8)2 (J2)8 (82)J (J8)3
(J3)8 (83)J (J8)4 (J4)8 (84)J (J8)5 (J5)8 (85)J (J8)6 (J6)8
(86)J (J8)7 (J7)8 (87)J (J9)A (JA)9 (9A)J (J9)2 (J2)9 (92)J
(J9)3 (J3)9 (93)J (J9)4 (J4)9 (94)J (J9)5 (J5)9 (95)J (J9)6
(J6)9 (96)J (J9)7 (J7)9 (97)J (J9)8 (J8)9 (98)J (JT)A (JA)T
(TA)J (JT)2 (J2)T (T2)J (JT)3 (J3)T (T3)J (JT)4 (J4)T (T4)J
(JT)5 (J5)T (T5)J (JT)6 (J6)T (T6)J (JT)7 (J7)T (T7)J (JT)8
(J8)T (T8)J (JT)9 (J9)T (T9)J (Q2)A (QA)2 (2A)Q (Q3)A (QA)3
(3A)Q (Q3)2 (Q2)3 (32)Q (Q4)A (QA)4 (4A)Q (Q4)2 (Q2)4 (42)Q
(Q4)3 (Q3)4 (43)Q (Q5)A (QA)5 (5A)Q (Q5)2 (Q2)5 (52)Q (Q5)3
(Q3)5 (53)Q (Q5)4 (Q4)5 (54)Q (Q6)A (QA)6 (6A)Q (Q6)2 (Q2)6
(62)Q (Q6)3 (Q3)6 (63)Q (Q6)4 (Q4)6 (64)Q (Q6)5 (Q5)6 (65)Q
(Q7)A (QA)7 (7A)Q (Q7)2 (Q2)7 (72)Q (Q7)3 (Q3)7 (73)Q (Q7)4
(Q4)7 (74)Q (Q7)5 (Q5)7 (75)Q (Q7)6 (Q6)7 (76)Q (Q8)A (QA)8
(8A)Q (Q8)2 (Q2)8 (82)Q (Q8)3 (Q3)8 (83)Q (Q8)4 (Q4)8 (84)Q
(Q8)5 (Q5)8 (85)Q (Q8)6 (Q6)8 (86)Q (Q8)7 (Q7)8 (87)Q (Q9)A
(QA)9 (9A)Q (Q9)2 (Q2)9 (92)Q (Q9)3 (Q3)9 (93)Q (Q9)4 (Q4)9
(94)Q (Q9)5 (Q5)9 (95)Q (Q9)6 (Q6)9 (96)Q (Q9)7 (Q7)9 (97)Q
(Q9)8 (Q8)9 (98)Q (QT)A (QA)T (TA)Q (QT)2 (Q2)T (T2)Q (QT)3
(Q3)T (T3)Q (QT)4 (Q4)T (T4)Q (QT)5 (Q5)T (T5)Q (QT)6 (Q6)T
(T6)Q (QT)7 (Q7)T (T7)Q (QT)8 (Q8)T (T8)Q (QT)9 (Q9)T (T9)Q
(QJ)A (QA)J (JA)Q (QJ)2 (Q2)J (J2)Q (QJ)3 (Q3)J (J3)Q (QJ)4
(Q4)J (J4)Q (QJ)5 (Q5)J (J5)Q (QJ)6 (Q6)J (J6)Q (QJ)7 (Q7)J
(J7)Q (QJ)8 (Q8)J (J8)Q (QJ)9 (Q9)J (J9)Q (QJ)T (QT)J (JT)Q
(K2)A (KA)2 (2A)K (K3)A (KA)3 (3A)K (K3)2 (K2)3 (32)K (K4)A
(KA)4 (4A)K (K4)2 (K2)4 (42)K (K4)3 (K3)4 (43)K (K5)A (KA)5
(5A)K (K5)2 (K2)5 (52)K (K5)3 (K3)5 (53)K (K5)4 (K4)5 (54)K
(K6)A (KA)6 (6A)K (K6)2 (K2)6 (62)K (K6)3 (K3)6 (63)K (K6)4
(K4)6 (64)K (K6)5 (K5)6 (65)K (K7)A (KA)7 (7A)K (K7)2 (K2)7
(72)K (K7)3 (K3)7 (73)K (K7)4 (K4)7 (74)K (K7)5 (K5)7 (75)K
(K7)6 (K6)7 (76)K (K8)A (KA)8 (8A)K (K8)2 (K2)8 (82)K (K8)3
(K3)8 (83)K (K8)4 (K4)8 (84)K (K8)5 (K5)8 (85)K (K8)6 (K6)8
(86)K (K8)7 (K7)8 (87)K (K9)A (KA)9 (9A)K (K9)2 (K2)9 (92)K
(K9)3 (K3)9 (93)K (K9)4 (K4)9 (94)K (K9)5 (K5)9 (95)K (K9)6
(K6)9 (96)K (K9)7 (K7)9 (97)K (K9)8 (K8)9 (98)K (KT)A (KA)T
(TA)K (KT)2 (K2)T (T2)K (KT)3 (K3)T (T3)K (KT)4 (K4)T (T4)K
(KT)5 (K5)T (T5)K (KT)6 (K6)T (T6)K (KT)7 (K7)T (T7)K (KT)8
(K8)T (T8)K (KT)9 (K9)T (T9)K (KJ)A (KA)J (JA)K (KJ)2 (K2)J
(J2)K (KJ)3 (K3)J (J3)K (KJ)4 (K4)J (J4)K (KJ)5 (K5)J (J5)K
(KJ)6 (K6)J (J6)K (KJ)7 (K7)J (J7)K (KJ)8 (K8)J (J8)K (KJ)9
(K9)J (J9)K (KJ)T (KT)J (JT)K (KQ)A (KA)Q (QA)K (KQ)2 (K2)Q
(Q2)K (KQ)3 (K3)Q (Q3)K (KQ)4 (K4)Q (Q4)K (KQ)5 (K5)Q (Q5)K
(KQ)6 (K6)Q (Q6)K (KQ)7 (K7)Q (Q7)K (KQ)8 (K8)Q (Q8)K (KQ)9
(K9)Q (Q9)K (KQ)T (KT)Q (QT)K (KQ)J (KJ)Q (QJ)K (2A)A (22)A
(AA)2 (2A)2 (3A)A (33)A (AA)3 (3A)3 (32)2 (33)2 (22)3 (32)3
(4A)A (44)A (AA)4 (4A)4 (42)2 (44)2 (22)4 (42)4 (43)3 (44)3
(33)4 (43)4 (5A)A (55)A (AA)5 (5A)5 (52)2 (55)2 (22)5 (52)5
(53)3 (55)3 (33)5 (53)5 (54)4 (55)4 (44)5 (54)5 (6A)A (66)A
(AA)6 (6A)6 (62)2 (66)2 (22)6 (62)6 (63)3 (66)3 (33)6 (63)6
(64)4 (66)4 (44)6 (64)6 (65)5 (66)5 (55)6 (65)6 (7A)A (77)A
(AA)7 (7A)7 (72)2 (77)2 (22)7 (72)7 (73)3 (77)3 (33)7 (73)7
(74)4 (77)4 (44)7 (74)7 (75)5 (77)5 (55)7 (75)7 (76)6 (77)6
(66)7 (76)7 (8A)A (88)A (AA)8 (8A)8 (82)2 (88)2 (22)8 (82)8
(83)3 (88)3 (33)8 (83)8 (84)4 (88)4 (44)8 (84)8 (85)5 (88)5
(55)8 (85)8 (86)6 (88)6 (66)8 (86)8 (87)7 (88)7 (77)8 (87)8
(9A)A (99)A (AA)9 (9A)9 (92)2 (99)2 (22)9 (92)9 (93)3 (99)3
(33)9 (93)9 (94)4 (99)4 (44)9 (94)9 (95)5 (99)5 (55)9 (95)9
(96)6 (99)6 (66)9 (96)9 (97)7 (99)7 (77)9 (97)9 (98)8 (99)8
(88)9 (98)9 (TA)A (TT)A (AA)T (TA)T (T2)2 (TT)2 (22)T (T2)T
(T3)3 (TT)3 (33)T (T3)T (T4)4 (TT)4 (44)T (T4)T (T5)5 (TT)5
(55)T (T5)T (T6)6 (TT)6 (66)T (T6)T (T7)7 (TT)7 (77)T (T7)T
(T8)8 (TT)8 (88)T (T8)T (T9)9 (TT)9 (99)T (T9)T (JA)A (JJ)A
(AA)J (JA)J (J2)2 (JJ)2 (22)J (J2)J (J3)3 (JJ)3 (33)J (J3)J
(J4)4 (JJ)4 (44)J (J4)J (J5)5 (JJ)5 (55)J (J5)J (J6)6 (JJ)6
(66)J (J6)J (J7)7 (JJ)7 (77)J (J7)J (J8)8 (JJ)8 (88)J (J8)J
(J9)9 (JJ)9 (99)J (J9)J (JT)T (JJ)T (TT)J (JT)J (QA)A (QQ)A
(AA)Q (QA)Q (Q2)2 (QQ)2 (22)Q (Q2)Q (Q3)3 (QQ)3 (33)Q (Q3)Q
(Q4)4 (QQ)4 (44)Q (Q4)Q (Q5)5 (QQ)5 (55)Q (Q5)Q (Q6)6 (QQ)6
(66)Q (Q6)Q (Q7)7 (QQ)7 (77)Q (Q7)Q (Q8)8 (QQ)8 (88)Q (Q8)Q
(Q9)9 (QQ)9 (99)Q (Q9)Q (QT)T (QQ)T (TT)Q (QT)Q (QJ)J (QQ)J
(JJ)Q (QJ)Q (KA)A (KK)A (AA)K (KA)K (K2)2 (KK)2 (22)K (K2)K
(K3)3 (KK)3 (33)K (K3)K (K4)4 (KK)4 (44)K (K4)K (K5)5 (KK)5
(55)K (K5)K (K6)6 (KK)6 (66)K (K6)K (K7)7 (KK)7 (77)K (K7)K
(K8)8 (KK)8 (88)K (K8)K (K9)9 (KK)9 (99)K (K9)K (KT)T (KK)T
(TT)K (KT)K (KJ)J (KK)J (JJ)K (KJ)K (KQ)Q (KK)Q (QQ)K (KQ)K
(AA)A (22)2 (33)3 (44)4 (55)5 (66)6 (77)7 (88)8 (99)9 (TT)T
(JJ)J (QQ)Q (KK)K
"""
count = 1
string = ""
for a in re_space.finditer(razzlist):
string = string + ("'%s':%s," %(a.group(1), count))
count+=1
if count%10 == 0:
string = string + "\n"
print "-------------------------"
print "Razz encode list"
print "------------------------ "
print string
string = ""
count = 1
for a in re_space.finditer(razzlist):
string = string + ("%s:'%s'," %(count, a.group(1)))
count+=1
if count%10 == 0:
string = string + "\n"
print "-------------------------"
print "Razz decode list"
print "------------------------ "
print string

View File

@ -153,7 +153,28 @@ class Sql:
tourneyId BIGINT NOT NULL, tourneyId BIGINT NOT NULL,
rawTourney TEXT NOT NULL, rawTourney TEXT NOT NULL,
complain BOOLEAN NOT NULL DEFAULT FALSE)""" complain BOOLEAN NOT NULL DEFAULT FALSE)"""
################################
# Create Actions
################################
if db_server == 'mysql':
self.query['createActionsTable'] = """CREATE TABLE Actions (
id SMALLINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
name varchar(32) NOT NULL,
code char(4) NOT NULL)
ENGINE=INNODB"""
elif db_server == 'postgresql':
self.query['createActionsTable'] = """CREATE TABLE Actions (
id SERIAL, PRIMARY KEY (id),
name varchar(32),
code char(4))"""
elif db_server == 'sqlite':
self.query['createActionsTable'] = """CREATE TABLE Actions (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
code TEXT NOT NULL)"""
################################ ################################
# Create Sites # Create Sites
################################ ################################
@ -989,11 +1010,14 @@ class Sql:
handsPlayerId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handsPlayerId) REFERENCES HandsPlayers(id), handsPlayerId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handsPlayerId) REFERENCES HandsPlayers(id),
street SMALLINT NOT NULL, street SMALLINT NOT NULL,
actionNo SMALLINT NOT NULL, actionNo SMALLINT NOT NULL,
action CHAR(5) NOT NULL, streetActionNo SMALLINT NOT NULL,
allIn BOOLEAN NOT NULL, actionId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (actionId) REFERENCES Actions(id),
amount INT NOT NULL, amount INT NOT NULL,
comment TEXT, raiseTo INT NOT NULL,
commentTs DATETIME) amountCalled INT NOT NULL,
numDiscarded SMALLINT NOT NULL,
cardsDiscarded varchar(14),
allIn BOOLEAN NOT NULL)
ENGINE=INNODB""" ENGINE=INNODB"""
elif db_server == 'postgresql': elif db_server == 'postgresql':
self.query['createHandsActionsTable'] = """CREATE TABLE HandsActions ( self.query['createHandsActionsTable'] = """CREATE TABLE HandsActions (
@ -1001,24 +1025,31 @@ class Sql:
handsPlayerId BIGINT, FOREIGN KEY (handsPlayerId) REFERENCES HandsPlayers(id), handsPlayerId BIGINT, FOREIGN KEY (handsPlayerId) REFERENCES HandsPlayers(id),
street SMALLINT, street SMALLINT,
actionNo SMALLINT, actionNo SMALLINT,
action CHAR(5), streetActionNo SMALLINT,
allIn BOOLEAN, actionId SMALLINT, FOREIGN KEY (actionId) REFERENCES Actions(id),
amount INT, amount INT,
comment TEXT, raiseTo INT,
commentTs timestamp without time zone)""" amountCalled INT,
numDiscarded SMALLINT,
cardsDiscarded varchar(14),
allIn BOOLEAN)"""
elif db_server == 'sqlite': elif db_server == 'sqlite':
self.query['createHandsActionsTable'] = """CREATE TABLE HandsActions ( self.query['createHandsActionsTable'] = """CREATE TABLE HandsActions (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
handsPlayerId BIGINT, handsPlayerId BIGINT,
street SMALLINT, street SMALLINT,
actionNo SMALLINT, actionNo SMALLINT,
action CHAR(5), streetActionNo SMALLINT,
allIn INT, actionId SMALLINT,
amount INT, amount INT,
comment TEXT, raiseTo INT,
commentTs timestamp without time zone, amountCalled INT,
FOREIGN KEY (handsPlayerId) REFERENCES HandsPlayers(id) numDiscarded SMALLINT,
)""" cardsDiscarded TEXT,
allIn BOOLEAN,
FOREIGN KEY (handsPlayerId) REFERENCES HandsPlayers(id),
FOREIGN KEY (actionId) REFERENCES Actions(id) ON DELETE CASCADE
)"""
################################ ################################
@ -1365,6 +1396,10 @@ class Sql:
, maxSeats, knockout, rebuy, addOn, speed, shootout, matrix, sng)""" , maxSeats, knockout, rebuy, addOn, speed, shootout, matrix, sng)"""
self.query['get_last_hand'] = "select max(id) from Hands" self.query['get_last_hand'] = "select max(id) from Hands"
self.query['get_last_date'] = "SELECT MAX(startTime) FROM Hands"
self.query['get_first_date'] = "SELECT MIN(startTime) FROM Hands"
self.query['get_player_id'] = """ self.query['get_player_id'] = """
select Players.id AS player_id select Players.id AS player_id
@ -3024,8 +3059,6 @@ class Sql:
order by stats.category, stats.limitType, stats.bigBlindDesc desc order by stats.category, stats.limitType, stats.bigBlindDesc desc
<orderbyseats>, cast(stats.PlPosition as smallint) <orderbyseats>, cast(stats.PlPosition as smallint)
""" """
#elif db_server == 'sqlite':
# self.query['playerStatsByPosition'] = """ """
#################################### ####################################
# Cash Game Graph query # Cash Game Graph query
@ -3046,11 +3079,45 @@ class Sql:
GROUP BY h.startTime, hp.handId, hp.sawShowdown, hp.totalProfit GROUP BY h.startTime, hp.handId, hp.sawShowdown, hp.totalProfit
ORDER BY h.startTime""" ORDER BY h.startTime"""
self.query['getRingProfitAllHandsPlayerIdSiteInBB'] = """
SELECT hp.handId, ( hp.totalProfit / ( gt.bigBlind * 2 ) ) * 100 , hp.sawShowdown
FROM HandsPlayers hp
INNER JOIN Players pl ON (pl.id = hp.playerId)
INNER JOIN Hands h ON (h.id = hp.handId)
INNER JOIN Gametypes gt ON (gt.id = h.gametypeId)
WHERE pl.id in <player_test>
AND pl.siteId in <site_test>
AND h.startTime > '<startdate_test>'
AND h.startTime < '<enddate_test>'
<limit_test>
<game_test>
AND hp.tourneysPlayersId IS NULL
GROUP BY h.startTime, hp.handId, hp.sawShowdown, hp.totalProfit
ORDER BY h.startTime"""
self.query['getRingProfitAllHandsPlayerIdSiteInDollars'] = """
SELECT hp.handId, hp.totalProfit, hp.sawShowdown
FROM HandsPlayers hp
INNER JOIN Players pl ON (pl.id = hp.playerId)
INNER JOIN Hands h ON (h.id = hp.handId)
INNER JOIN Gametypes gt ON (gt.id = h.gametypeId)
WHERE pl.id in <player_test>
AND pl.siteId in <site_test>
AND h.startTime > '<startdate_test>'
AND h.startTime < '<enddate_test>'
<limit_test>
<game_test>
AND hp.tourneysPlayersId IS NULL
GROUP BY h.startTime, hp.handId, hp.sawShowdown, hp.totalProfit
ORDER BY h.startTime"""
#################################### ####################################
# Tourney Results query # Tourney Results query
#################################### ####################################
self.query['tourneyResults'] = """ self.query['tourneyResults'] = """
SELECT tp.tourneyId, (tp.winnings - tt.buyIn - tt.fee) as profit, tp.koCount, tp.rebuyCount, tp.addOnCount, tt.buyIn, tt.fee, t.siteTourneyNo SELECT tp.tourneyId, (coalesce(tp.winnings,0) - coalesce(tt.buyIn,0) - coalesce(tt.fee,0)) as profit, tp.koCount, tp.rebuyCount, tp.addOnCount, tt.buyIn, tt.fee, t.siteTourneyNo
FROM TourneysPlayers tp FROM TourneysPlayers tp
INNER JOIN Players pl ON (pl.id = tp.playerId) INNER JOIN Players pl ON (pl.id = tp.playerId)
INNER JOIN Tourneys t ON (t.id = tp.tourneyId) INNER JOIN Tourneys t ON (t.id = tp.tourneyId)
@ -4251,11 +4318,17 @@ class Sql:
handsPlayerId, handsPlayerId,
street, street,
actionNo, actionNo,
action, streetActionNo,
allIn, actionId,
amount amount,
raiseTo,
amountCalled,
numDiscarded,
cardsDiscarded,
allIn
) )
VALUES ( VALUES (
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
%s %s
)""" )"""
@ -4263,9 +4336,9 @@ class Sql:
################################ ################################
# Counts for DB stats window # Counts for DB stats window
################################ ################################
self.query['getHandCount'] = "SELECT COUNT(id) FROM Hands" self.query['getHandCount'] = "SELECT COUNT(*) FROM Hands"
self.query['getTourneyCount'] = "SELECT COUNT(id) FROM Tourneys" self.query['getTourneyCount'] = "SELECT COUNT(*) FROM Tourneys"
self.query['getTourneyTypeCount'] = "SELECT COUNT(id) FROM TourneyTypes" self.query['getTourneyTypeCount'] = "SELECT COUNT(*) FROM TourneyTypes"
################################ ################################
# queries for dumpDatabase # queries for dumpDatabase

207
pyfpdb/SplitHandHistory.py Normal file
View File

@ -0,0 +1,207 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#Copyright 2010 Chaz Littlejohn
#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()
# This code is based heavily on stars-support-hh-split.py by Mika Boström
import os
import sys
import re
import codecs
import Options
import Configuration
from Exceptions import *
from cStringIO import StringIO
(options, argv) = Options.fpdb_options()
__ARCHIVE_PRE_HEADER_REGEX='^Hand #(\d+)\s*$|\*{20}\s#\s\d+\s\*+\s+'
re_SplitArchive = re.compile(__ARCHIVE_PRE_HEADER_REGEX)
codepage = ["utf-16", "utf-8", "cp1252"]
class SplitHandHistory:
def __init__(self, config, in_path = '-', out_path = None, hands = 100, filter = "PokerStarsToFpdb", archive = False):
self.config = config
self.in_path = in_path
self.out_path = out_path
if not self.out_path:
self.out_path = os.path.dirname(self.in_path)
self.hands = hands
self.archive = archive
self.re_SplitHands = None
self.line_delimiter = None
self.line_addendum = None
self.filedone = False
#Acquire re_SplitHands for this hh
filter_name = filter.replace("ToFpdb", "")
mod = __import__(filter)
obj = getattr(mod, filter_name, None)
self.re_SplitHands = obj.re_SplitHands
#Determine line delimiter type if any
if self.re_SplitHands.match('\n\n'):
self.line_delimiter = '\n\n'
if self.re_SplitHands.match('\n\n\n'):
self.line_delimiter = '\n\n\n'
#Add new line addendum for sites which match SplitHand to next line as well
if filter_name == 'OnGame':
self.line_addendum = '*'
if filter_name == 'Carbon':
self.line_addendum = '<game'
#Open the gargantuan file
for kodec in self.__listof(codepage):
try:
infile = codecs.open(self.in_path, 'r', kodec)
except IOError:
print _('File not found')
sys.exit(2)
#Split with do_hands_per_file if archive and paragraphs if a regular hh
if self.archive:
nn = 0
while True:
nn += 1
check = self.do_hands_per_file(infile, nn)
if check is None:
print _('%s processed' % self.in_path)
break
else:
filenum = 0
while not self.filedone:
filenum += 1
outfile = self.new_file(filenum)
handnum = 0
for hand in self.paragraphs(infile, None, self.line_addendum):
outfile.write(hand)
if self.line_delimiter:
outfile.write(self.line_delimiter)
handnum += 1
if handnum >= self.hands:
break
outfile.close()
def new_file(self, fileno=-1):
if fileno < 1:
print _('Nope, will not work (fileno=%d)' % fileno)
sys.exit(2)
basename = os.path.splitext(os.path.basename(self.in_path))[0]
name = os.path.join(self.out_path, basename+'-%06d.txt' % fileno)
print '-> %s' % name
newfile = file(name, 'w')
return newfile
#Archive Hand Splitter
def do_hands_per_file(self, infile, num=-1):
done = False
n = 0
outfile = self.new_file(num)
while n < self.hands:
try:
infile = self.next_hand(infile)
infile = self.process_hand(infile, outfile)
except FpdbEndOfFile:
done = True
break
except:
print _("Unexpected error processing file")
sys.exit(2)
n += 1
outfile.close()
if not done:
return infile
else:
return None
#Non-Archive Hand Splitter
def paragraphs(self, file, separator=None, addendum=None):
if not callable(separator) and self.line_delimiter:
def separator(line): return line == '\n'
else:
def separator(line): return self.re_SplitHands.search(line)
file_str = StringIO()
print file_str.getvalue()
for line in file:
if separator(line+addendum):
if file_str.getvalue():
if not self.line_delimiter:
file_str.write(line)
yield file_str.getvalue()
file_str = None
file_str = StringIO()
else:
file_str.write(line)
if file_str.getvalue(): yield file_str.getvalue()
self.filedone = True
# Finds pre-hand header (Hand #<num>)
def next_hand(self, infile):
m = None
while not m:
l = infile.readline()
#print l, len(l)
# Catch EOF
if len(l) == 0:
raise FpdbEndOfFile(_("End of file reached"))
m = re_SplitArchive.search(l)
# There is an empty line after pre-hand header and actual HH entry
l = infile.readline()
return infile
# Each individual hand is written separately
def process_hand(self, infile=None, outfile=None):
l = infile.readline()
l = l.replace('\r\n', '\n')
outfile.write(l)
l = infile.readline()
while len(l) < 3:
l = infile.readline()
while len(l) > 2:
l = l.replace('\r\n', '\n')
outfile.write(l)
l = infile.readline()
outfile.write(self.line_delimiter)
return infile
def __listof(self, x):
if isinstance(x, list) or isinstance(x, tuple):
return x
else:
return [x]
def main(argv=None):
if argv is None:
argv = sys.argv[1:]
if not options.config:
options.config = Configuration.Config(file = "HUD_config.test.xml")
if options.filename:
SplitHH = SplitHandHistory(options.config, options.filename, options.outpath, options.hands,
options.hhc, options.archive)
if __name__ == '__main__':
sys.exit(main())

15
pyfpdb/Stats.py Executable file → Normal file
View File

@ -47,6 +47,9 @@
# other stuff. # other stuff.
# 6 For each stat you make add a line to the __main__ function to test it. # 6 For each stat you make add a line to the __main__ function to test it.
import L10n
_ = L10n.get_translation()
# Standard Library modules # Standard Library modules
import sys import sys
@ -55,18 +58,6 @@ import pygtk
import gtk import gtk
import re import re
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
# FreePokerTools modules # FreePokerTools modules
import Configuration import Configuration
import Database import Database

309
pyfpdb/Stove.py Executable file
View File

@ -0,0 +1,309 @@
#!/usr/bin/python
# -*- coding: iso-8859-15
#
# stove.py
# Simple Hold'em equity calculator
# Copyright (C) 2007-2008 Mika Boström <bostik@iki.fi>
#
# 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, version 3 of the License.
#
#TODO: gettextify
import sys, random
import pokereval
SUITS = ['h', 'd', 's', 'c']
ANY = 0
SUITED = 1
OFFSUIT = 2
ev = pokereval.PokerEval()
holder = None
class Holder:
def __init__(self):
self.hand = None
self.board = None
self.range = None
class Cards:
def __init__(self, c1, c2):
self.c1 = c1
self.c2 = c2
def get(self):
return [c1, c2]
class Board:
def __init__(self, b1=None, b2=None, b3=None, b4=None, b5=None):
self.b1 = b1
self.b2 = b2
self.b3 = b3
self.b4 = b4
self.b5 = b5
def get(self):
b = []
if self.b3 is not None:
b.append(self.b1)
b.append(self.b2)
b.append(self.b3)
else:
b.extend(["__", "__", "__"])
if self.b4 is not None:
b.append(self.b4)
else:
b.append("__")
if self.b5 is not None:
b.append(self.b5)
else:
b.append("__")
return b
class Range:
def __init__(self):
self.__hands = set()
def add(self, hand):
self.__hands.add(hand)
def expand(self, hands):
self.__hands.update(set(hands))
def get(self):
return sorted(self.__hands)
class EV:
def __init__(self, plays, win, tie, lose):
self.n_hands = plays
self.n_wins = win
self.n_ties = tie
self.n_losses = lose
class SumEV:
def __init__(self):
self.n_hands = 0
self.n_wins = 0
self.n_ties = 0
self.n_losses = 0
def add(self, ev):
self.n_hands += ev.n_hands
self.n_wins += ev.n_wins
self.n_ties += ev.n_ties
self.n_losses += ev.n_losses
def show(self, hand, 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 ' 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.
# Takes into account cards already known to be in player's hand and/or
# board.
def expand_hands(abbrev, hand, board):
selection = -1
known_cards = set()
known_cards.update(set([hand.c2, hand.c2]))
known_cards.update(set([board.b1, board.b2, board.b3, board.b4, board.b5]))
# Card ranks may be different
r1 = abbrev[0]
r2 = abbrev[1]
# There may be a specifier: 's' for 'suited'; 'o' for 'off-suit'
if len(abbrev) == 3:
ltr = abbrev[2]
if ltr == 'o':
selection = OFFSUIT
elif ltr == 's':
selection = SUITED
else:
selection = ANY
range = []
considered = set()
for s1 in SUITS:
c1 = r1 + s1
if c1 in known_cards:
continue
considered.add(c1)
for s2 in SUITS:
c2 = r2 + s2
if selection == SUITED and s1 != s2:
continue
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
def parse_args(args, container):
# args[0] is the path being executed; need 3 more args
if len(args) < 4:
return False
board = Board()
# Board
b = args[1].strip().split()
if len(b) > 4:
board.b5 = b[4]
if len(b) > 3:
board.b4 = b[3]
if len(b) > 2:
board.b1 = b[0]
board.b2 = b[1]
board.b3 = b[2]
# Our pocket cards
cc = args[2].strip().split()
c1 = cc[0]
c2 = cc[1]
pocket_cards = Cards(c1, c2)
# Villain's range
range = Range()
hands_in_range = args[3].strip().split(',')
for h in hands_in_range:
_h = h.strip()
if len(_h) > 3:
cc = _h.split()
r1 = cc[0]
r2 = cc[1]
vp = Cards(r1, r2)
range.add(vp)
else:
range.expand(expand_hands(_h, pocket_cards, board))
holder.hand = pocket_cards
holder.range = range
holder.board = board
return True
def odds_for_hand(hand1, hand2, board, iterations):
res = ev.poker_eval(game='holdem',
pockets = [
hand1,
hand2
],
dead = [],
board = board,
iterations = iterations
)
plays = int(res['info'][0])
eval = res['eval'][0]
win = int(eval['winhi'])
lose = int(eval['losehi'])
tie = int(eval['tiehi'])
_ev = EV(plays, win, tie, lose)
return _ev
def odds_for_range(holder):
sev = SumEV()
monte_carlo = False
# Construct board list
b = []
board = holder.board
if board.b3 is not None:
b.extend([board.b1, board.b2, board.b3])
else:
b.extend(['__', '__', '__'])
monte_carlo = True
if board.b4 is not None:
b.append(board.b4)
else:
b.append("__")
if board.b5 is not None:
b.append(board.b5)
else:
b.append("__")
if monte_carlo:
print 'No board given. Using Monte-Carlo simulation...'
iters = random.randint(25000, 125000)
else:
iters = -1
for h in holder.range.get():
e = odds_for_hand(
[holder.hand.c1, holder.hand.c2],
[h.c1, h.c2],
b,
iterations=iters
)
sev.add(e)
sev.show(holder.hand, holder.range.get())
holder = Holder()
if not parse_args(sys.argv, holder):
usage(sys.argv[0])
sys.exit(2)
odds_for_range(holder)
# debugs
#print '%s, %s' % ( holder.hand.c1, holder.hand.c2)
#print '%s %s %s %s %s' % (holder.board.b1, holder.board.b2,
# holder.board.b3, holder.board.b4, holder.board.b5)
#while True:
# try:
# vl = holder.range.get()
# v = vl.pop()
# print '\t%s %s' % (v.c1, v.c2)
# except IndexError:
# break

View File

@ -1,12 +1,14 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""Discover_TableWindow.py """Base class for interacting with poker client windows.
Inspects the currently open windows and finds those of interest to us--that is There are currently subclasses for X and Windows.
poker table windows from supported sites. Returns a list
of Table_Window objects representing the windows found. The class queries the poker client window for data of interest, such as
size and location. It also controls the signals to alert the HUD when the
client has been resized, destroyed, etc.
""" """
# Copyright 2008-2010, Ray E. Barker # Copyright 2008 - 2010, Ray E. Barker
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -25,37 +27,38 @@ of Table_Window objects representing the windows found.
######################################################################## ########################################################################
# Standard Library modules # Standard Library modules
import os import re
import sys
# pyGTK modules # pyGTK modules
import pygtk
import gtk import gtk
import gobject import gobject
# FreePokerTools modules # FreePokerTools modules
import Configuration from HandHistoryConverter import getTableTitleRe
#if os.name == "posix": from HandHistoryConverter import getTableNoRe
# import XTables
#elif os.name == "nt":
# import WinTables
# Global used for figuring out the current game being played from the title # Global used for figuring out the current game being played from the title.
# The dict key is the fpdb name for the game # The dict key is a tuple of (limit type, category) for the game.
# The list is the names for those games used by the supported poker sites # The list is the names for those games used by the supported poker sites
# This is currently only used for HORSE, so it only needs to support those # This is currently only used for mixed games, so it only needs to support those
# games on PokerStars and Full Tilt. # games on PokerStars and Full Tilt.
game_names = { #fpdb name Stars Name FTP Name nlpl_game_names = { #fpdb name Stars Name FTP Name (if different)
"holdem" : ("Hold\'em" , ), ("nl", "holdem" ) : ("No Limit Hold\'em" , ),
"omahahilo" : ("Omaha H/L" , ), ("pl", "holdem" ) : ("Pot Limit Hold\'em" , ),
"studhilo" : ("Stud H/L" , ), ("pl", "omahahi" ) : ("Pot Limit Omaha" ,"Pot Limit Omaha Hi" ),
"razz" : ("Razz" , ), }
"studhi" : ("Stud" , "Stud Hi") limit_game_names = { #fpdb name Stars Name FTP Name
("fl", "holdem" ) : ("Limit Hold\'em" , ),
("fl", "omahahilo" ) : ("Limit Omaha H/L" , ),
("fl", "studhilo" ) : ("Limit Stud H/L" , ),
("fl", "razz" ) : ("Limit Razz" , ),
("fl", "studhi" ) : ("Limit Stud" , "Stud Hi"),
("fl", "27_3draw" ) : ("Limit Triple Draw 2-7 Lowball", )
} }
# A window title might have our table name + one of theses words/ # A window title might have our table name + one of these words/
# phrases. If it has this word in the title, it is not a table. # phrases. If it has this word in the title, it is not a table.
bad_words = ('History for table:', 'HUD:', 'Chat:') bad_words = ('History for table:', 'HUD:', 'Chat:', 'FPDBHUD')
# Here are the custom signals we define for allowing the 'client watcher' # Here are the custom signals we define for allowing the 'client watcher'
# thread to communicate with the gui thread. Any time a poker client is # thread to communicate with the gui thread. Any time a poker client is
@ -76,11 +79,19 @@ gobject.signal_new("client_destroyed", gtk.Window,
gobject.TYPE_NONE, gobject.TYPE_NONE,
(gobject.TYPE_PYOBJECT,)) (gobject.TYPE_PYOBJECT,))
gobject.signal_new("game_changed", gtk.Window,
gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
(gobject.TYPE_PYOBJECT,))
gobject.signal_new("table_changed", gtk.Window,
gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
(gobject.TYPE_PYOBJECT,))
# Each TableWindow object must have the following attributes correctly populated: # Each TableWindow object must have the following attributes correctly populated:
# tw.name = the table name from the title bar, which must to match the table name # tw.name = the table name from the title bar, which must to match the table name
# from the corresponding hand history. # from the corresponding hand record in the db.
# tw.site = the site name, e.g. PokerStars, FullTilt. This must match the site
# name specified in the config file.
# tw.number = This is the system id number for the client table window in the # tw.number = This is the system id number for the client table window in the
# format that the system presents it. This is Xid in Xwindows and # format that the system presents it. This is Xid in Xwindows and
# hwnd in Microsoft Windows. # hwnd in Microsoft Windows.
@ -92,60 +103,161 @@ gobject.signal_new("client_destroyed", gtk.Window,
# to the top left of the display screen. This also does not include the # to the top left of the display screen. This also does not include the
# title bar and window borders. To put it another way, this is the # title bar and window borders. To put it another way, this is the
# screen location of (0, 0) in the working window. # screen location of (0, 0) in the working window.
# tournament = Tournament number for a tournament or None for a cash game.
# table = Table number for a tournament.
# gdkhandle =
# window =
# parent =
# game =
# search_string =
class Table_Window(object): class Table_Window(object):
def __init__(self, search_string, table_name = None, tournament = None, table_number = None): def __init__(self, config, site, table_name = None, tournament = None, table_number = None):
self.config = config
self.site = site
if tournament is not None and table_number is not None: if tournament is not None and table_number is not None:
print "tournament %s, table %s" % (tournament, table_number)
self.tournament = int(tournament) self.tournament = int(tournament)
self.table = int(table_number) self.table = int(table_number)
self.name = "%s - %s" % (self.tournament, self.table) self.name = "%s - %s" % (self.tournament, self.table)
self.type = "tour"
table_kwargs = dict(tournament = self.tournament, table_number = self.table)
self.tableno_re = getTableNoRe(self.config, self.site, tournament = self.tournament)
elif table_name is not None: elif table_name is not None:
# search_string = table_name
self.name = table_name self.name = table_name
self.type = "cash"
self.tournament = None self.tournament = None
table_kwargs = dict(table_name = table_name)
else: else:
return None return None
self.find_table_parameters(search_string) self.search_string = getTableTitleRe(self.config, self.site, self.type, **table_kwargs)
self.find_table_parameters()
geo = self.get_geometry()
if geo is None: return None
self.width = geo['width']
self.height = geo['height']
self.x = geo['x']
self.y = geo['y']
self.oldx = self.x # attn ray: remove these two lines and update Hud.py::update_table_position()
self.oldy = self.y
self.game = self.get_game()
def __str__(self): def __str__(self):
# __str__ method for testing # __str__ method for testing
likely_attrs = ("site", "number", "title", "width", "height", "x", "y", likely_attrs = ("number", "title", "site", "width", "height", "x", "y",
"tournament", "table", "gdkhandle") "tournament", "table", "gdkhandle", "window", "parent",
"game", "search_string", "tableno_re")
temp = 'TableWindow object\n' temp = 'TableWindow object\n'
for a in likely_attrs: for a in likely_attrs:
if getattr(self, a, 0): if getattr(self, a, 0):
temp += " %s = %s\n" % (a, getattr(self, a)) temp += " %s = %s\n" % (a, getattr(self, a))
return temp return temp
####################################################################
# "get" methods. These query the table and return the info to get.
# They don't change the data in the table and are generally used
# by the "check" methods. Most of the get methods are in the
# subclass because they are specific to X, Windows, etc.
def get_game(self): def get_game(self):
title = self.get_window_title() # title = self.get_window_title()
print title # if title is None:
for game, names in game_names.iteritems(): # return False
title = self.title
# check for nl and pl games first, to avoid bad matches
for game, names in nlpl_game_names.iteritems():
for name in names: for name in names:
if name in title: if name in title:
return game return game
return None for game, names in limit_game_names.iteritems():
for name in names:
if name in title:
return game
return False
def check_geometry(self): def get_table_no(self):
new_title = self.get_window_title()
if new_title is None:
return False
try:
mo = re.search(self.tableno_re, new_title)
except AttributeError: #'Table' object has no attribute 'tableno_re'
return False
if mo is not None:
#print "get_table_no: mo=",mo.groups()
return mo.group(1)
return False
####################################################################
# check_table() is meant to be called by the hud periodically to
# determine if the client has been moved or resized. check_table()
# also checks and signals if the client has been closed.
def check_table(self, hud):
result = self.check_size()
if result != False:
hud.parent.main_window.emit(result, hud)
if result == "client_destroyed":
return True
result = self.check_loc()
if result != False:
hud.parent.main_window.emit(result, hud)
if result == "client_destroyed":
return True
return True
####################################################################
# "check" methods. They use the corresponding get method, update the
# table object and return the name of the signal to be emitted or
# False if unchanged. These do not signal for destroyed
# clients to prevent a race condition.
# These might be called by a Window.timeout, so they must not
# return False, or the timeout will be cancelled.
def check_game(self, hud):
new_game = self.get_game()
if new_game is not None and self.game != new_game:
self.game = new_game
hud.main_window.emit("game_changed", hud)
return "game_changed"
return True
def check_size(self):
new_geo = self.get_geometry() new_geo = self.get_geometry()
if new_geo is None: # window destroyed if new_geo is None: # window destroyed
return "client_destroyed" return "client_destroyed"
elif self.x != new_geo['x'] or self.y != new_geo['y']: # window moved
self.x = new_geo['x']
self.y = new_geo['y']
return "client_moved"
elif self.width != new_geo['width'] or self.height != new_geo['height']: # window resized elif self.width != new_geo['width'] or self.height != new_geo['height']: # window resized
self.width = new_geo['width'] self.width = new_geo['width']
self.height = new_geo['height'] self.height = new_geo['height']
return "client_resized" return "client_resized"
return False # no change
else: return False # window not changed def check_loc(self):
new_geo = self.get_geometry()
if new_geo is None: # window destroyed
return "client_destroyed"
if self.x != new_geo['x'] or self.y != new_geo['y']: # window moved
# print self.x, self.y, new_geo['x'], new_geo['y']
self.x = new_geo['x']
self.y = new_geo['y']
return "client_moved"
return False # no change
def check_table_no(self, hud):
result = self.get_table_no()
if result != False and result != self.table:
self.table = result
if hud is not None:
hud.main_window.emit("table_changed", hud)
return True
def check_bad_words(self, title): def check_bad_words(self, title):
for word in bad_words: for word in bad_words:

View File

@ -22,31 +22,19 @@ Main program module to test/demo the Tables subclasses.
######################################################################## ########################################################################
import L10n
_ = L10n.get_translation()
# Standard Library modules # Standard Library modules
import sys import sys
import os import os
import re
# pyGTK modules # pyGTK modules
import pygtk
import gtk import gtk
import gobject import gobject
# fpdb/free poker tools modules # fpdb/free poker tools modules
import Configuration import Configuration
from HandHistoryConverter import getTableTitleRe
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
# get the correct module for the current os # get the correct module for the current os
if os.name == 'posix': if os.name == 'posix':
@ -73,24 +61,31 @@ if __name__=="__main__":
self.main_window.move(table.x + dx, table.y + dy) self.main_window.move(table.x + dx, table.y + dy)
self.main_window.show_all() self.main_window.show_all()
table.topify(self) table.topify(self)
# These are the currently defined signals. Do this in the HUD.
self.main_window.connect("client_moved", self.client_moved) self.main_window.connect("client_moved", self.client_moved)
self.main_window.connect("client_resized", self.client_resized) self.main_window.connect("client_resized", self.client_resized)
self.main_window.connect("client_destroyed", self.client_destroyed) self.main_window.connect("client_destroyed", self.client_destroyed)
self.main_window.connect("game_changed", self.game_changed)
self.main_window.connect("table_changed", self.table_changed)
# And these of the handlers that go with those signals.
# These would live inside the HUD code.
def client_moved(self, widget, hud): def client_moved(self, widget, hud):
self.main_window.move(self.table.x + self.dx, self.table.y + self.dy) self.main_window.move(self.table.x + self.dx, self.table.y + self.dy)
def client_resized(self, *args): def client_resized(self, *args):
print "client resized" print "Client resized"
def client_destroyed(self, *args): # call back for terminating the main eventloop def client_destroyed(self, *args): # call back for terminating the main eventloop
print "Client destroyed."
gtk.main_quit() gtk.main_quit()
def check_on_table(table, hud): def game_changed(self, *args):
result = table.check_geometry() print "Game Changed."
if result != False:
hud.main_window.emit(result, hud) def table_changed(self, *args):
return True print "Table Changed."
print _("enter table name to find: "), print _("enter table name to find: "),
table_name = sys.stdin.readline() table_name = sys.stdin.readline()
@ -107,16 +102,12 @@ if __name__=="__main__":
type = "cash" type = "cash"
table_kwargs = dict(table_name = table_name) table_kwargs = dict(table_name = table_name)
search_string = getTableTitleRe(config, "Full Tilt Poker", type, **table_kwargs) table = Tables.Table(config, "Full Tilt Poker", **table_kwargs)
table = Tables.Table(search_string, **table_kwargs) print table
table.gdk_handle = gtk.gdk.window_foreign_new(table.number)
print "table =", table
# print "game =", table.get_game()
fake = fake_hud(table) fake = fake_hud(table)
print "fake =", fake gobject.timeout_add(1000, table.check_game, fake)
# gobject.timeout_add(100, check_on_table, table, fake) gobject.timeout_add(100, table.check_table, fake)
print _("calling main") print "calling main"
gtk.main() gtk.main()

View File

@ -129,7 +129,7 @@ def main(argv=None):
settings.update(config.get_import_parameters()) settings.update(config.get_import_parameters())
settings.update(config.get_default_paths()) settings.update(config.get_default_paths())
db.recreate_tables() db.recreate_tables()
importer = fpdb_import.Importer(False, settings, config) importer = fpdb_import.Importer(False, settings, config, None)
importer.setDropIndexes("don't drop") importer.setDropIndexes("don't drop")
importer.setFailOnError(True) importer.setFailOnError(True)
importer.setThreads(-1) importer.setThreads(-1)
@ -142,28 +142,67 @@ def main(argv=None):
BetfairErrors = FpdbError('Betfair') BetfairErrors = FpdbError('Betfair')
OnGameErrors = FpdbError('OnGame') OnGameErrors = FpdbError('OnGame')
AbsoluteErrors = FpdbError('Absolute Poker') AbsoluteErrors = FpdbError('Absolute Poker')
UltimateBetErrors = FpdbError('Ultimate Bet')
EverleafErrors = FpdbError('Everleaf Poker') EverleafErrors = FpdbError('Everleaf Poker')
CarbonErrors = FpdbError('Carbon') CarbonErrors = FpdbError('Carbon')
PKRErrors = FpdbError('PKR') PKRErrors = FpdbError('PKR')
iPokerErrors = FpdbError('iPoker')
Win2dayErrors = FpdbError('Win2day')
WinamaxErrors = FpdbError('Winamax')
ErrorsList = [ ErrorsList = [
PokerStarsErrors, FTPErrors, PartyPokerErrors, PokerStarsErrors, FTPErrors, PartyPokerErrors,
BetfairErrors, OnGameErrors, AbsoluteErrors, BetfairErrors, OnGameErrors, AbsoluteErrors,
EverleafErrors, CarbonErrors, PKRErrors EverleafErrors, CarbonErrors, PKRErrors,
iPokerErrors, WinamaxErrors, UltimateBetErrors,
Win2dayErrors,
] ]
walk_testfiles("regression-test-files/cash/Stars/", compare, importer, PokerStarsErrors, "PokerStars") sites = {
walk_testfiles("regression-test-files/tour/Stars/", compare, importer, PokerStarsErrors, "PokerStars") 'PokerStars' : True,
walk_testfiles("regression-test-files/cash/FTP/", compare, importer, FTPErrors, "Full Tilt Poker") 'Full Tilt Poker' : True,
walk_testfiles("regression-test-files/tour/FTP/", compare, importer, FTPErrors, "Full Tilt Poker") 'PartyPoker' : True,
walk_testfiles("regression-test-files/cash/PartyPoker/", compare, importer, PartyPokerErrors, "PartyPoker") 'Betfair' : True,
walk_testfiles("regression-test-files/tour/PartyPoker/", compare, importer, PartyPokerErrors, "PartyPoker") 'OnGame' : True,
walk_testfiles("regression-test-files/cash/Betfair/", compare, importer, BetfairErrors, "Betfair") 'Absolute' : True,
walk_testfiles("regression-test-files/cash/OnGame/", compare, importer, OnGameErrors, "OnGame") 'UltimateBet' : True,
walk_testfiles("regression-test-files/cash/Absolute/", compare, importer, AbsoluteErrors, "Absolute") 'Everleaf' : True,
walk_testfiles("regression-test-files/cash/Everleaf/", compare, importer, EverleafErrors, "Everleaf") 'Carbon' : True,
walk_testfiles("regression-test-files/cash/Carbon/", compare, importer, CarbonErrors, "Carbon") 'PKR' : False,
walk_testfiles("regression-test-files/cash/PKR/", compare, importer, PKRErrors, "PKR") 'iPoker' : True,
'Win2day' : True,
'Winamax' : True,
}
if sites['PokerStars'] == True:
walk_testfiles("regression-test-files/cash/Stars/", compare, importer, PokerStarsErrors, "PokerStars")
walk_testfiles("regression-test-files/tour/Stars/", compare, importer, PokerStarsErrors, "PokerStars")
if sites['Full Tilt Poker'] == True:
walk_testfiles("regression-test-files/cash/FTP/", compare, importer, FTPErrors, "Full Tilt Poker")
walk_testfiles("regression-test-files/tour/FTP/", compare, importer, FTPErrors, "Full Tilt Poker")
if sites['PartyPoker'] == True:
walk_testfiles("regression-test-files/cash/PartyPoker/", compare, importer, PartyPokerErrors, "PartyPoker")
walk_testfiles("regression-test-files/tour/PartyPoker/", compare, importer, PartyPokerErrors, "PartyPoker")
if sites['Betfair'] == True:
walk_testfiles("regression-test-files/cash/Betfair/", compare, importer, BetfairErrors, "Betfair")
if sites['OnGame'] == True:
walk_testfiles("regression-test-files/cash/OnGame/", compare, importer, OnGameErrors, "OnGame")
if sites['Absolute'] == True:
walk_testfiles("regression-test-files/cash/Absolute/", compare, importer, AbsoluteErrors, "Absolute")
if sites['UltimateBet'] == True:
walk_testfiles("regression-test-files/cash/UltimateBet/", compare, importer, UltimateBetErrors, "Absolute")
if sites['Everleaf'] == True:
walk_testfiles("regression-test-files/cash/Everleaf/", compare, importer, EverleafErrors, "Everleaf")
if sites['Carbon'] == True:
walk_testfiles("regression-test-files/cash/Carbon/", compare, importer, CarbonErrors, "Carbon")
if sites['PKR'] == True:
walk_testfiles("regression-test-files/cash/PKR/", compare, importer, PKRErrors, "PKR")
if sites['iPoker'] == True:
walk_testfiles("regression-test-files/cash/iPoker/", compare, importer, iPokerErrors, "iPoker")
if sites['Winamax'] == True:
walk_testfiles("regression-test-files/cash/Winamax/", compare, importer, WinamaxErrors, "Winamax")
if sites['Win2day'] == True:
walk_testfiles("regression-test-files/cash/Win2day/", compare, importer, Win2dayErrors, "Win2day")
totalerrors = 0 totalerrors = 0

228
pyfpdb/TestSummaryImport.py Executable file
View File

@ -0,0 +1,228 @@
#!/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
########################################################################
import sys
import os
import codecs
import pprint
import Configuration
import Database
import SQL
from GuiTourneyImport import SummaryImporter
class FpdbError:
def __init__(self, sitename):
self.site = sitename
self.errorcount = 0
self.histogram = {}
self.statcount = {}
def error_report(self, filename, hand, stat, ghash, testhash, player):
print "Regression Test Error:"
print "\tFile: %s" % filename
print "\tStat: %s" % stat
print "\tPlayer: %s" % player
if filename in self.histogram:
self.histogram[filename] += 1
else:
self.histogram[filename] = 1
if stat in self.statcount:
self.statcount[stat] += 1
else:
self.statcount[stat] = 1
self.errorcount += 1
def print_histogram(self):
print "%s:" % self.site
for f in self.histogram:
idx = f.find('regression')
print "(%3d) : %s" %(self.histogram[f], f[idx:])
def compare(leaf, importer, errors, site):
filename = leaf
#print "DEBUG: fileanme: %s" % filename
if filename.endswith('.txt'):
# test if there is a .hp version of the file
importer.addImportFileOrDir(filename, site = site)
(stored, errs) = importer.runImport()
# if os.path.isfile(filename + '.hp') and errs < 1:
# # Compare them
# hashfilename = filename + '.hp'
#
# in_fh = codecs.open(hashfilename, 'r', 'utf8')
# whole_file = in_fh.read()
# in_fh.close()
#
# testhash = eval(whole_file)
#
# hhc = importer.getCachedHHC()
# handlist = hhc.getProcessedHands()
# #We _really_ only want to deal with a single hand here.
# for hand in handlist:
# ghash = hand.stats.getHandsPlayers()
# for p in ghash:
# #print "DEBUG: player: '%s'" % p
# pstat = ghash[p]
# teststat = testhash[p]
#
# for stat in pstat:
# #print "pstat[%s][%s]: %s == %s" % (p, stat, pstat[stat], teststat[stat])
# try:
# if pstat[stat] == teststat[stat]:
# # The stats match - continue
# pass
# else:
# # Stats don't match - Doh!
# errors.error_report(filename, hand, stat, ghash, testhash, p)
# except KeyError, e:
# errors.error_report(filename, False, "KeyError: '%s'" % stat, False, False, p)
if errs > 0:
errors.error_report(filename, False, "Parse", False, False, False)
importer.clearFileList()
def walk_testfiles(dir, function, importer, errors, site):
"""Walks a directory, and executes a callback on each file """
dir = os.path.abspath(dir)
for file in [file for file in os.listdir(dir) if not file in [".",".."]]:
nfile = os.path.join(dir,file)
if os.path.isdir(nfile):
walk_testfiles(nfile, compare, importer, errors, site)
else:
print "***********************************"
compare(nfile, importer, errors, site)
print "***********************************"
def main(argv=None):
if argv is None:
argv = sys.argv[1:]
config = Configuration.Config(file = "HUD_config.test.xml")
db = Database.Database(config)
sql = SQL.Sql(db_server = 'sqlite')
db.recreate_tables()
importer = SummaryImporter(config, sql, None)
PokerStarsErrors = FpdbError('PokerStars')
FTPErrors = FpdbError('Full Tilt Poker')
#PartyPokerErrors = FpdbError('Party Poker')
#BetfairErrors = FpdbError('Betfair')
#OnGameErrors = FpdbError('OnGame')
#AbsoluteErrors = FpdbError('Absolute Poker')
#UltimateBetErrors = FpdbError('Ultimate Bet')
#EverleafErrors = FpdbError('Everleaf Poker')
#CarbonErrors = FpdbError('Carbon')
#PKRErrors = FpdbError('PKR')
#iPokerErrors = FpdbError('iPoker')
#WinamaxErrors = FpdbError('Winamax')
ErrorsList = [
PokerStarsErrors,
FTPErrors, #PartyPokerErrors,
#BetfairErrors, OnGameErrors, AbsoluteErrors,
#EverleafErrors, CarbonErrors, PKRErrors,
#iPokerErrors, WinamaxErrors, UltimateBetErrors,
]
sites = {
'PokerStars' : True,
'Full Tilt Poker' : True,
#'PartyPoker' : True,
#'Betfair' : True,
#'OnGame' : True,
#'Absolute' : True,
#'UltimateBet' : True,
#'Everleaf' : True,
#'Carbon' : True,
#'PKR' : False,
#'iPoker' : True,
#'Winamax' : True,
}
if sites['PokerStars'] == True:
walk_testfiles("regression-test-files/summaries/Stars/", compare, importer, PokerStarsErrors, "PokerStars")
if sites['Full Tilt Poker'] == True:
walk_testfiles("regression-test-files/summaries/FTP/", compare, importer, FTPErrors, "Full Tilt Poker")
# walk_testfiles("regression-test-files/tour/FTP/", compare, importer, FTPErrors, "Full Tilt Poker")
#if sites['PartyPoker'] == True:
# walk_testfiles("regression-test-files/cash/PartyPoker/", compare, importer, PartyPokerErrors, "PartyPoker")
# walk_testfiles("regression-test-files/tour/PartyPoker/", compare, importer, PartyPokerErrors, "PartyPoker")
#if sites['Betfair'] == True:
# walk_testfiles("regression-test-files/cash/Betfair/", compare, importer, BetfairErrors, "Betfair")
#if sites['OnGame'] == True:
# walk_testfiles("regression-test-files/cash/OnGame/", compare, importer, OnGameErrors, "OnGame")
#if sites['Absolute'] == True:
# walk_testfiles("regression-test-files/cash/Absolute/", compare, importer, AbsoluteErrors, "Absolute")
#if sites['UltimateBet'] == True:
# walk_testfiles("regression-test-files/cash/UltimateBet/", compare, importer, UltimateBetErrors, "Absolute")
#if sites['Everleaf'] == True:
# walk_testfiles("regression-test-files/cash/Everleaf/", compare, importer, EverleafErrors, "Everleaf")
#if sites['Carbon'] == True:
# walk_testfiles("regression-test-files/cash/Carbon/", compare, importer, CarbonErrors, "Carbon")
#if sites['PKR'] == True:
# walk_testfiles("regression-test-files/cash/PKR/", compare, importer, PKRErrors, "PKR")
#if sites['iPoker'] == True:
# walk_testfiles("regression-test-files/cash/iPoker/", compare, importer, iPokerErrors, "iPoker")
#if sites['Winamax'] == True:
# walk_testfiles("regression-test-files/cash/Winamax/", compare, importer, WinamaxErrors, "Winamax")
totalerrors = 0
for i, site in enumerate(ErrorsList):
totalerrors += ErrorsList[i].errorcount
print "---------------------"
print "Total Errors: %d" % totalerrors
print "---------------------"
for i, site in enumerate(ErrorsList):
ErrorsList[i].print_histogram()
# Merge the dicts of stats from the various error objects
statdict = {}
for i, site in enumerate(ErrorsList):
tmp = ErrorsList[i].statcount
for stat in tmp:
if stat in statdict:
statdict[stat] += tmp[stat]
else:
statdict[stat] = tmp[stat]
print "\n"
print "---------------------"
print "Errors by stat:"
print "---------------------"
#for stat in statdict:
# print "(%3d) : %s" %(statdict[stat], stat)
sortedstats = sorted([(value,key) for (key,value) in statdict.items()])
for num, stat in sortedstats:
print "(%3d) : %s" %(num, stat)
if __name__ == '__main__':
sys.exit(main())

View File

@ -21,6 +21,9 @@
######################################################################## ########################################################################
import L10n
_ = L10n.get_translation()
# to do allow window resizing # to do allow window resizing
# to do hud to echo, but ignore non numbers # to do hud to echo, but ignore non numbers
# to do no stat window for hero # to do no stat window for hero
@ -34,18 +37,6 @@ import traceback
(options, argv) = Options.fpdb_options() (options, argv) = Options.fpdb_options()
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
if not options.errorsToConsole: if not options.errorsToConsole:
print _("Note: error output is being diverted to fpdb-error-log.txt and HUD-error.txt. Any major error will be reported there _only_.") print _("Note: error output is being diverted to fpdb-error-log.txt and HUD-error.txt. Any major error will be reported there _only_.")
errorFile = open('tourneyerror.txt', 'w', 0) errorFile = open('tourneyerror.txt', 'w', 0)

View File

@ -15,6 +15,9 @@
#along with this program. If not, see <http://www.gnu.org/licenses/>. #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. #In the "official" distribution you can find the license in agpl-3.0.txt.
import L10n
_ = L10n.get_translation()
import threading import threading
import pygtk import pygtk
pygtk.require('2.0') pygtk.require('2.0')
@ -29,18 +32,6 @@ from time import gmtime, mktime, strftime, strptime
import logging #logging has been set up in fpdb.py or HUD_main.py, use their settings: import logging #logging has been set up in fpdb.py or HUD_main.py, use their settings:
log = logging.getLogger("filter") log = logging.getLogger("filter")
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
#import Configuration #import Configuration
#import Database #import Database
#import SQL #import SQL

View File

@ -17,6 +17,9 @@
"""parses and stores summary sections from e.g. eMail or summary files""" """parses and stores summary sections from e.g. eMail or summary files"""
import L10n
_ = L10n.get_translation()
# TODO: check to keep only the needed modules # TODO: check to keep only the needed modules
import re import re
@ -31,21 +34,10 @@ import time,datetime
from copy import deepcopy from copy import deepcopy
from Exceptions import * from Exceptions import *
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
import pprint import pprint
import DerivedStats import DerivedStats
import Card import Card
import Database
log = logging.getLogger("parser") log = logging.getLogger("parser")
@ -57,7 +49,7 @@ class TourneySummary(object):
LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'} # SAL- TO KEEP ?? LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'} # SAL- TO KEEP ??
SYMBOL = {'USD': '$', 'EUR': u'$', 'T$': '', 'play': ''} SYMBOL = {'USD': '$', 'EUR': u'$', 'T$': '', 'play': ''}
MS = {'horse' : 'HORSE', '8game' : '8-Game', 'hose' : 'HOSE', 'ha': 'HA'} MS = {'horse' : 'HORSE', '8game' : '8-Game', 'hose' : 'HOSE', 'ha': 'HA'}
SITEIDS = {'Fulltilt':1, 'PokerStars':2, 'Everleaf':3, 'Win2day':4, 'OnGame':5, 'UltimateBet':6, 'Betfair':7, 'Absolute':8, 'PartyPoker':9 } SITEIDS = {'Fulltilt':1, 'Full Tilt Poker':1, 'PokerStars':2, 'Everleaf':3, 'Win2day':4, 'OnGame':5, 'UltimateBet':6, 'Betfair':7, 'Absolute':8, 'PartyPoker':9 }
def __init__(self, db, config, siteName, summaryText, builtFrom = "HHC"): def __init__(self, db, config, siteName, summaryText, builtFrom = "HHC"):
@ -125,11 +117,13 @@ class TourneySummary(object):
self.sym = None self.sym = None
if builtFrom=="IMAP": if builtFrom=="IMAP":
self.parseSummary() # Fix line endings?
self.insertOrUpdate() pass
elif builtFrom == "file": if self.db == None:
self.parseSummaryFile() self.db = Database.Database(config)
self.insertOrUpdate()
self.parseSummary()
self.insertOrUpdate()
#end def __init__ #end def __init__
def __str__(self): def __str__(self):
@ -300,148 +294,3 @@ winnings (decimal) the money the player ended the tourney with (can be 0, or
def printSummary(self): def printSummary(self):
self.writeSummary(sys.stdout) self.writeSummary(sys.stdout)
def assemble(cnxn, tourneyId): #TODO: move this method to Hand or Database
# TODO !!
c = cnxn.cursor()
# We need at least siteName, gametype, handid
# for the Hand.__init__
c.execute("""
select
s.name,
g.category,
g.base,
g.type,
g.limitType,
g.hilo,
round(g.smallBlind / 100.0,2),
round(g.bigBlind / 100.0,2),
round(g.smallBet / 100.0,2),
round(g.bigBet / 100.0,2),
s.currency,
h.boardcard1,
h.boardcard2,
h.boardcard3,
h.boardcard4,
h.boardcard5
from
hands as h,
sites as s,
gametypes as g,
handsplayers as hp,
players as p
where
h.id = %(handid)s
and g.id = h.gametypeid
and hp.handid = h.id
and p.id = hp.playerid
and s.id = p.siteid
limit 1""", {'handid':handid})
#TODO: siteid should be in hands table - we took the scenic route through players here.
res = c.fetchone()
gametype = {'category':res[1],'base':res[2],'type':res[3],'limitType':res[4],'hilo':res[5],'sb':res[6],'bb':res[7], 'currency':res[10]}
h = HoldemOmahaHand(hhc = None, siteName=res[0], gametype = gametype, handText=None, builtFrom = "DB", handid=handid)
cards = map(Card.valueSuitFromCard, res[11:16] )
if cards[0]:
h.setCommunityCards('FLOP', cards[0:3])
if cards[3]:
h.setCommunityCards('TURN', [cards[3]])
if cards[4]:
h.setCommunityCards('RIVER', [cards[4]])
#[Card.valueSuitFromCard(x) for x in cards]
# HandInfo : HID, TABLE
# BUTTON - why is this treated specially in Hand?
# answer: it is written out in hand histories
# still, I think we should record all the active seat positions in a seat_order array
c.execute("""
SELECT
h.sitehandno as hid,
h.tablename as table,
h.startTime as startTime
FROM
Hands as h
WHERE h.id = %(handid)s
""", {'handid':handid})
res = c.fetchone()
h.handid = res[0]
h.tablename = res[1]
h.startTime = res[2] # automatically a datetime
# PlayerStacks
c.execute("""
SELECT
hp.seatno,
round(hp.winnings / 100.0,2) as winnings,
p.name,
round(hp.startcash / 100.0,2) as chips,
hp.card1,hp.card2,
hp.position
FROM
handsplayers as hp,
players as p
WHERE
hp.handid = %(handid)s
and p.id = hp.playerid
""", {'handid':handid})
for (seat, winnings, name, chips, card1,card2, position) in c.fetchall():
h.addPlayer(seat,name,chips)
if card1 and card2:
h.addHoleCards(map(Card.valueSuitFromCard, (card1,card2)), name, dealt=True)
if winnings > 0:
h.addCollectPot(name, winnings)
if position == 'B':
h.buttonpos = seat
# actions
c.execute("""
SELECT
(ha.street,ha.actionno) as actnum,
p.name,
ha.street,
ha.action,
ha.allin,
round(ha.amount / 100.0,2)
FROM
handsplayers as hp,
handsactions as ha,
players as p
WHERE
hp.handid = %(handid)s
and ha.handsplayerid = hp.id
and p.id = hp.playerid
ORDER BY
ha.street,ha.actionno
""", {'handid':handid})
res = c.fetchall()
for (actnum,player, streetnum, act, allin, amount) in res:
act=act.strip()
street = h.allStreets[streetnum+1]
if act==u'blind':
h.addBlind(player, 'big blind', amount)
# TODO: The type of blind is not recorded in the DB.
# TODO: preflop street name anomalies in Hand
elif act==u'fold':
h.addFold(street,player)
elif act==u'call':
h.addCall(street,player,amount)
elif act==u'bet':
h.addBet(street,player,amount)
elif act==u'check':
h.addCheck(street,player)
elif act==u'unbet':
pass
else:
print act, player, streetnum, allin, amount
# TODO : other actions
#hhc.readShowdownActions(self)
#hc.readShownCards(self)
h.totalPot()
h.rake = h.totalpot - h.totalcollected
return h

424
pyfpdb/TreeViewTooltips.py Normal file
View File

@ -0,0 +1,424 @@
# Copyright (c) 2006, Daniel J. Popowich
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Send bug reports and contributions to:
#
# dpopowich AT astro dot umass dot edu
#
# This version of the file is part of fpdb, contact: fpdb-main@lists.sourceforge.net
'''
TreeViewTooltips.py
Provides TreeViewTooltips, a class which presents tooltips for cells,
columns and rows in a gtk.TreeView.
------------------------------------------------------------
This file includes a demo. Just execute the file:
python TreeViewTooltips.py
------------------------------------------------------------
To use, first subclass TreeViewTooltips and implement the get_tooltip()
method; see below. Then add any number of gtk.TreeVew widgets to a
TreeViewTooltips instance by calling the add_view() method. Overview
of the steps:
# 1. subclass TreeViewTooltips
class MyTooltips(TreeViewTooltips):
# 2. overriding get_tooltip()
def get_tooltip(...):
...
# 3. create an instance
mytips = MyTooltips()
# 4. Build up your gtk.TreeView.
myview = gtk.TreeView()
...# create columns, set the model, etc.
# 5. Add the view to the tooltips
mytips.add_view(myview)
How it works: the add_view() method connects the TreeView to the
"motion-notify" event with the callback set to a private method.
Whenever the mouse moves across the TreeView the callback will call
get_tooltip() with the following arguments:
get_tooltip(view, column, path)
where,
view: the gtk.TreeView instance.
column: the gtk.TreeViewColumn instance that the mouse is
currently over.
path: the path to the row that the mouse is currently over.
Based on whether or not column and path are checked for specific
values, get_tooltip can return tooltips for a cell, column, row or the
whole view:
Column Checked Path Checked Tooltip For...
Y Y cell
Y N column
N Y row
N N view
get_tooltip() should return None if no tooltip should be displayed.
Otherwise the return value will be coerced to a string (with the str()
builtin) and stripped; if non-empty, the result will be displayed as
the tooltip. By default, the tooltip popup window will be displayed
centered and just below the pointer and will remain shown until the
pointer leaves the cell (or column, or row, or view, depending on how
get_tooltip() is implemented).
'''
import pygtk
pygtk.require('2.0')
import gtk
import gtk.gdk
import gobject
if gtk.gtk_version < (2, 8):
import warnings
msg = (_('''This module was developed and tested with version 2.8.18 of gtk. You are using version %d.%d.%d. Your milage may vary.''')
% gtk.gtk_version)
warnings.warn(msg)
# major, minor, patch
version = 1, 0, 0
class TreeViewTooltips:
def __init__(self):
'''
Initialize the tooltip. After initialization there are two
attributes available for advanced control:
window: the popup window that holds the tooltip text, an
instance of gtk.Window.
label: a gtk.Label that is packed into the window. The
tooltip text is set in the label with the
set_label() method, so the text can be plain or
markup text.
Be default, the tooltip is enabled. See the enabled/disabled
methods.
'''
# create the window
self.window = window = gtk.Window(gtk.WINDOW_POPUP)
window.set_name('gtk-tooltips')
window.set_resizable(False)
window.set_border_width(4)
window.set_app_paintable(True)
window.connect("expose-event", self.__on_expose_event)
# create the label
self.label = label = gtk.Label()
label.set_line_wrap(True)
label.set_alignment(0.5, 0.5)
label.set_use_markup(True)
label.show()
window.add(label)
# by default, the tooltip is enabled
self.__enabled = True
# saves the current cell
self.__save = None
# the timer id for the next tooltip to be shown
self.__next = None
# flag on whether the tooltip window is shown
self.__shown = False
def enable(self):
'Enable the tooltip'
self.__enabled = True
def disable(self):
'Disable the tooltip'
self.__enabled = False
def __show(self, tooltip, x, y):
'''show the tooltip popup with the text/markup given by
tooltip.
tooltip: the text/markup for the tooltip.
x, y: the coord. (root window based) of the pointer.
'''
window = self.window
# set label
self.label.set_label(tooltip)
# resize window
w, h = window.size_request()
# move the window
window.move(*self.location(x,y,w,h))
# show it
window.show()
self.__shown = True
def __hide(self):
'hide the tooltip'
self.__queue_next()
self.window.hide()
self.__shown = False
def __leave_handler(self, view, event):
'when the pointer leaves the view, hide the tooltip'
self.__hide()
def __motion_handler(self, view, event):
'As the pointer moves across the view, show a tooltip.'
path = view.get_path_at_pos(int(event.x), int(event.y))
if self.__enabled and path:
path, col, x, y = path
tooltip = self.get_tooltip(view, col, path)
if tooltip is not None:
tooltip = str(tooltip).strip()
if tooltip:
self.__queue_next((path, col), tooltip,
int(event.x_root),
int(event.y_root))
return
self.__hide()
def __queue_next(self, *args):
'queue next request to show a tooltip'
# if args is non-empty it means a request was made to show a
# tooltip. if empty, no request is being made, but any
# pending requests should be cancelled anyway.
cell = None
# if called with args, break them out
if args:
cell, tooltip, x, y = args
# if it's the same cell as previously shown, just return
if self.__save == cell:
return
# if we have something queued up, cancel it
if self.__next:
gobject.source_remove(self.__next)
self.__next = None
# if there was a request...
if cell:
# if the tooltip is already shown, show the new one
# immediately
if self.__shown:
self.__show(tooltip, x, y)
# else queue it up in 1/2 second
else:
self.__next = gobject.timeout_add(500, self.__show,
tooltip, x, y)
# save this cell
self.__save = cell
def __on_expose_event(self, window, event):
# this magic is required so the window appears with a 1-pixel
# black border (default gtk Style). This code is a
# transliteration of the C implementation of gtk.Tooltips.
w, h = window.size_request()
window.style.paint_flat_box(window.window, gtk.STATE_NORMAL,
gtk.SHADOW_OUT, None, window,
'tooltip', 0, 0, w, h)
def location(self, x, y, w, h):
'''Given the x,y coordinates of the pointer and the width and
height (w,h) demensions of the tooltip window, return the x, y
coordinates of the tooltip window.
The default location is to center the window on the pointer
and 4 pixels below it.
'''
return x - w/2, y + 4
def add_view(self, view):
'add a gtk.TreeView to the tooltip'
assert isinstance(view, gtk.TreeView), \
('This handler should only be connected to '
'instances of gtk.TreeView')
view.connect("motion-notify-event", self.__motion_handler)
view.connect("leave-notify-event", self.__leave_handler)
def get_tooltip(self, view, column, path):
'See the module doc string for a description of this method'
raise NotImplemented, 'Subclass must implement get_tooltip()'
if __name__ == '__main__':
############################################################
# DEMO
############################################################
# First, subclass TreeViewTooltips
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)
def get_tooltip(self, view, column, path):
# we have a two column view: customer, phone; we'll make
# tooltips cell-based for the customer column, but generic
# column-based for the phone column.
# customer
if column is self.cust_col:
# By checking both column and path we have a
# cell-based tooltip.
model = view.get_model()
customer = model[path][2]
return '<big>%s %s</big>\n<i>%s</i>' % (customer.fname,
customer.lname,
customer.notes)
# phone
else:
return ('<big><u>Generic Column Tooltip</u></big>\n'
'Unless otherwise noted, all\narea codes are 888')
def XX_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 + 10, y - (h + 10)
# Here's our customer
class Customer:
def __init__(self, fname, lname, phone, notes):
self.fname = fname
self.lname = lname
self.phone = phone
self.notes = notes
# create a bunch of customers
customers = []
for fname, lname, phone, notes in [
('Joe', 'Schmoe', '555-1212', 'Likes to Morris dance.'),
('Jane', 'Doe', '555-2323',
'Wonders what the hell\nMorris dancing is.'),
('Phred', 'Phantastic', '900-555-1212', 'Dreams of Betty.'),
('Betty', 'Boop', '555-3434', 'Dreams in b&amp;w.'),
('Red Sox', 'Fan', '555-4545',
"Still livin' 2004!\nEspecially after 2006.")]:
customers.append(Customer(fname, lname, phone, notes))
# Build our model and view
model = gtk.ListStore(str, str, object)
for c in customers:
model.append(['%s %s' % (c.fname, c.lname), c.phone, c])
view = gtk.TreeView(model)
view.get_selection().set_mode(gtk.SELECTION_NONE)
# two columns, name and phone
cell = gtk.CellRendererText()
cell.set_property('xpad', 20)
namecol = gtk.TreeViewColumn('Customer Name', cell, text=0)
namecol.set_min_width(200)
view.append_column(namecol)
cell = gtk.CellRendererText()
phonecol = gtk.TreeViewColumn('Phone', cell, text=1)
view.append_column(phonecol)
# finally, connect the tooltip, specifying the name column as the
# column we want the tooltip to popup over.
tips = DemoTips(namecol)
tips.add_view(view)
# We're going to demonstrate enable/disable. First we need a
# callback function to connect to the toggled signal.
def toggle(button):
if button.get_active():
tips.disable()
else:
tips.enable()
# create a checkbutton and connect our handler
check = gtk.CheckButton('Check to disable view tooltips')
check.connect('toggled', toggle)
# a standard gtk.Tooltips to compare to
tt = gtk.Tooltips()
tt.set_tip(check, ('This is a standard gtk tooltip.\n'
'Compare me to the tooltips above.'))
# create a VBox to pack the view and checkbutton
vbox = gtk.VBox()
vbox.pack_start(view)
vbox.pack_start(check, False)
vbox.show_all()
# pack the vbox into a simple dialog and run it
dialog = gtk.Dialog('TreeViewTooltips Demo')
close = dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_NONE)
# add a tooltip for the close button
tt.set_tip(close, 'Click to end the demo.')
dialog.set_default_size(400,400)
dialog.vbox.pack_start(vbox)
dialog.run()

View File

@ -1,330 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2008-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
########################################################################
import sys
from HandHistoryConverter import *
class UltimateBet(HandHistoryConverter):
# Static regexes
re_GameInfo = re.compile("Stage #(?P<HID>[0-9]+):\s+\(?(?P<GAME>Hold\'em|Razz|Seven Card|Omaha|Omaha Hi/Lo|Badugi) (?P<LIMIT>No Limit|Normal|Pot Limit),? \(?(?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)\) - (?P<DATETIME>.*$)", re.MULTILINE)
re_SplitHands = re.compile('(\n\n\n+)')
re_HandInfo = re.compile("^Table \'(?P<TABLE>[- a-zA-Z]+)\'(?P<TABLEATTRIBUTES>.+?$)?", re.MULTILINE)
re_Button = re.compile('Seat #(?P<BUTTON>\d+) is the button', re.MULTILINE)
re_PlayerInfo = re.compile('^Seat (?P<SEAT>[0-9]+) - (?P<PNAME>.*) \(\$?(?P<CASH>[.0-9]+) in chips\)', re.MULTILINE)
re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
# self.re_setHandInfoRegex('.*#(?P<HID>[0-9]+): Table (?P<TABLE>[ a-zA-Z]+) - \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) - (?P<GAMETYPE>.*) - (?P<HR>[0-9]+):(?P<MIN>[0-9]+) ET - (?P<YEAR>[0-9]+)/(?P<MON>[0-9]+)/(?P<DAY>[0-9]+)Table (?P<TABLE>[ a-zA-Z]+)\nSeat (?P<BUTTON>[0-9]+)')
def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, index=0):
"""\
in_path (default '-' = sys.stdin)
out_path (default '-' = sys.stdout)
follow : whether to tail -f the input"""
HandHistoryConverter.__init__(self, in_path, out_path, sitename="UltimateBet", follow=follow, index=index)
logging.info(_("Initialising UltimateBetconverter class"))
self.filetype = "text"
self.codepage = "cp1252"
self.siteId = 6 # Needs to match id entry in Sites database
if autostart:
self.start()
def compilePlayerRegexs(self, hand):
players = set([player[1] for player in hand.players])
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 small blind \$?(?P<SB>[.0-9]+)" % player_re, re.MULTILINE)
self.re_PostBB = re.compile(r"^%s: posts big blind \$?(?P<BB>[.0-9]+)" % player_re, re.MULTILINE)
self.re_Antes = re.compile(r"^%s - Ante \$?(?P<ANTE>[.0-9]+)" % player_re, re.MULTILINE)
self.re_BringIn = re.compile(r"^%s - Bring-In \$?(?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)
self.re_HeroCards = re.compile(r"^Dealt to %s - Pocket (\[(?P<OLDCARDS>.+?)\])?( \[(?P<NEWCARDS>.+?)\])" % player_re, re.MULTILINE)
self.re_Action = re.compile(r"^%s -(?P<ATYPE> Bets| Checks| raises| Calls| Folds)( \$(?P<BET>[.\d]+))?( to \$(?P<BETTO>[.\d]+))?( (?P<NODISCARDED>\d) cards?( \[(?P<DISCARDED>.+?)\])?)?" % player_re, re.MULTILINE)
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("^%s sits out" % player_re, re.MULTILINE)
self.re_ShownCards = re.compile("^Seat (?P<SEAT>[0-9]+): %s \(.*\) showed \[(?P<CARDS>.*)\].*" % player_re, re.MULTILINE)
def readSupportedGames(self):
return [ ["ring", "stud", "fl"]
]
def determineGameType(self, handText):
info = {'type':'ring'}
m = self.re_GameInfo.search(handText)
if not m:
return None
mg = m.groupdict()
# 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' : ('hold','omahahi'),
'Omaha Hi/Lo' : ('hold','omahahilo'),
'Razz' : ('stud','razz'),
'7 Card Stud' : ('stud','studhi'),
'Badugi' : ('draw','badugi')
}
currencies = { u'':'EUR', '$':'USD', '':'T$' }
if 'LIMIT' in mg:
info['limitType'] = limits[mg['LIMIT']]
if 'GAME' in mg:
(info['base'], info['category']) = games[mg['GAME']]
if 'SB' in mg:
info['sb'] = mg['SB']
if 'BB' in mg:
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):
info = {}
m = self.re_HandInfo.search(hand.handText,re.DOTALL)
if m:
info.update(m.groupdict())
# TODO: Be less lazy and parse maxseats from the HandInfo regex
if m.group('TABLEATTRIBUTES'):
m2 = re.search("\s*(\d+)-max", m.group('TABLEATTRIBUTES'))
hand.maxseats = int(m2.group(1))
m = self.re_GameInfo.search(hand.handText)
if m: info.update(m.groupdict())
m = self.re_Button.search(hand.handText)
if m: info.update(m.groupdict())
# TODO : I rather like the idea of just having this dict as hand.info
logging.debug("readHandInfo: %s" % info)
for key in info:
if key == 'DATETIME':
#2008/11/12 10:00:48 CET [2008/11/12 4:00:48 ET]
#2008/08/17 - 01:14:43 (ET)
#2008/09/07 06:23:14 ET
m2 = re.search("(?P<Y>[0-9]{4})\/(?P<M>[0-9]{2})\/(?P<D>[0-9]{2})[\- ]+(?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)", info[key])
datetime = "%s/%s/%s %s:%s:%s" % (m2.group('Y'), m2.group('M'),m2.group('D'),m2.group('H'),m2.group('MIN'),m2.group('S'))
hand.startTime = time.strptime(datetime, "%Y/%m/%d %H:%M:%S")
if key == 'HID':
hand.handid = info[key]
if key == 'TABLE':
hand.tablename = info[key]
if key == 'BUTTON':
hand.buttonpos = info[key]
def readButton(self, hand):
m = self.re_Button.search(hand.handText)
if m:
hand.buttonpos = int(m.group('BUTTON'))
else:
logging.info(_('readButton: not found'))
def readPlayerStacks(self, hand):
logging.debug("readPlayerStacks")
m = self.re_PlayerInfo.finditer(hand.handText)
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 **
# This re fails if, say, river is missing; then we don't get the ** that starts the river.
if hand.gametype['base'] in ("hold"):
m = re.search(r"\*\*\* HOLE CARDS \*\*\*(?P<PREFLOP>.+(?=\*\*\* FLOP \*\*\*)|.+)"
r"(\*\*\* FLOP \*\*\*(?P<FLOP> \[\S\S \S\S \S\S\].+(?=\*\*\* TURN \*\*\*)|.+))?"
r"(\*\*\* TURN \*\*\* \[\S\S \S\S \S\S] (?P<TURN>\[\S\S\].+(?=\*\*\* RIVER \*\*\*)|.+))?"
r"(\*\*\* RIVER \*\*\* \[\S\S \S\S \S\S \S\S] (?P<RIVER>\[\S\S\].+))?", hand.handText,re.DOTALL)
elif hand.gametype['base'] in ("stud"):
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>.+(?=\*\*\* RIVER \*\*\*)|.+))?"
r"(\*\*\* RIVER \*\*\*(?P<SEVENTH>.+))?", hand.handText,re.DOTALL)
elif hand.gametype['base'] in ("draw"):
m = re.search(r"(?P<PREDEAL>.+(?=\*\*\* DEALING HANDS \*\*\*)|.+)"
r"(\*\*\* DEALING HANDS \*\*\*(?P<DEAL>.+(?=\*\*\* FIRST DRAW \*\*\*)|.+))?"
r"(\*\*\* FIRST DRAW \*\*\*(?P<DRAWONE>.+(?=\*\*\* SECOND DRAW \*\*\*)|.+))?"
r"(\*\*\* SECOND DRAW \*\*\*(?P<DRAWTWO>.+(?=\*\*\* THIRD DRAW \*\*\*)|.+))?"
r"(\*\*\* THIRD DRAW \*\*\*(?P<DRAWTHREE>.+))?", hand.handText,re.DOTALL)
hand.addStreets(m)
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)
#print "DEBUG readCommunityCards:", street, hand.streets.group(street)
m = self.re_Board.search(hand.streets[street])
hand.setCommunityCards(street, m.group('CARDS').split(' '))
def readAntes(self, hand):
logging.debug(_("reading antes"))
m = self.re_Antes.finditer(hand.handText)
for player in m:
#~ logging.debug("hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE')))
hand.addAnte(player.group('PNAME'), player.group('ANTE'))
def readBringIn(self, hand):
m = self.re_BringIn.search(hand.handText,re.DOTALL)
if m:
#~ logging.debug("readBringIn: %s for %s" %(m.group('PNAME'), m.group('BRINGIN')))
hand.addBringIn(m.group('PNAME'), m.group('BRINGIN'))
def readBlinds(self, hand):
try:
m = self.re_PostSB.search(hand.handText)
hand.addBlind(m.group('PNAME'), '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(a.group('PNAME'), 'big blind', a.group('BB'))
for a in self.re_PostBoth.finditer(hand.handText):
hand.addBlind(a.group('PNAME'), 'small & big blinds', a.group('SBBB'))
def readHeroCards(self, hand):
m = self.re_HeroCards.search(hand.handText)
if(m == None):
#Not involved in hand
hand.involved = False
else:
hand.hero = m.group('PNAME')
# "2c, qh" -> set(["2c","qc"])
# Also works with Omaha hands.
cards = m.group('NEWCARDS')
cards = set(cards.split(' '))
hand.addHoleCards(cards, m.group('PNAME'))
def readDrawCards(self, hand, street):
logging.debug("readDrawCards")
m = self.re_HeroCards.finditer(hand.streets[street])
if m == None:
hand.involved = False
else:
for player in m:
hand.hero = player.group('PNAME') # Only really need to do this once
newcards = player.group('NEWCARDS')
oldcards = player.group('OLDCARDS')
if newcards == None:
newcards = set()
else:
newcards = set(newcards.split(' '))
if oldcards == None:
oldcards = set()
else:
oldcards = set(oldcards.split(' '))
hand.addDrawHoleCards(newcards, oldcards, player.group('PNAME'), street)
def readStudPlayerCards(self, hand, street):
# See comments of reference implementation in FullTiltToFpdb.py
logging.debug("readStudPlayerCards")
m = self.re_HeroCards.finditer(hand.streets[street])
for player in m:
#~ logging.debug(player.groupdict())
(pname, oldcards, newcards) = (player.group('PNAME'), player.group('OLDCARDS'), player.group('NEWCARDS'))
if oldcards:
oldcards = [c.strip() for c in oldcards.split(' ')]
if newcards:
newcards = [c.strip() for c in newcards.split(' ')]
if street=='ANTES':
return
elif street=='THIRD':
# we'll have observed hero holecards in CARDS and thirdstreet open cards in 'NEWCARDS'
# hero: [xx][o]
# others: [o]
hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = oldcards, open = newcards)
elif street in ('FOURTH', 'FIFTH', 'SIXTH'):
# 4th:
# hero: [xxo] [o]
# others: [o] [o]
# 5th:
# hero: [xxoo] [o]
# others: [oo] [o]
# 6th:
# hero: [xxooo] [o]
# others: [ooo] [o]
hand.addPlayerCards(player = player.group('PNAME'), street = street, open = newcards)
# we may additionally want to check the earlier streets tally with what we have but lets trust it for now.
elif street=='SEVENTH' and newcards:
# hero: [xxoooo] [x]
# others: not reported.
hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = newcards)
def readAction(self, hand, street):
m = self.re_Action.finditer(hand.streets[street])
for action in m:
if action.group('ATYPE') == ' Raises':
hand.addRaiseBy( street, action.group('PNAME'), action.group('BET') )
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'))
#elif action.group('ATYPE') == ' discards':
# hand.addDiscard(street, action.group('PNAME'), action.group('NODISCARDED'), action.group('DISCARDED'))
#elif action.group('ATYPE') == ' stands pat':
# hand.addStandsPat( street, action.group('PNAME'))
else:
print _("DEBUG: unimplemented readAction: '%s' '%s'" %(action.group('PNAME'),action.group('ATYPE'),))
def readShowdownActions(self, hand):
for shows in self.re_ShowdownAction.finditer(hand.handText):
cards = shows.group('CARDS')
cards = set(cards.split(' '))
hand.addShownCards(cards, shows.group('PNAME'))
def readCollectPot(self,hand):
for m in self.re_CollectPot.finditer(hand.handText):
hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT'))
def readShownCards(self,hand):
for m in self.re_ShownCards.finditer(hand.handText):
if m.group('CARDS') is not None:
cards = m.group('CARDS')
cards = set(cards.split(' '))
hand.addShownCards(cards=cards, player=m.group('PNAME'))
if __name__ == "__main__":
parser = OptionParser()
parser.add_option("-i", "--input", dest="ipath", help=_("parse input hand history"), default="regression-test-files/pokerstars/HH20090226 Natalie V - $0.10-$0.20 - HORSE.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()
LOG_FILENAME = './logging.out'
logging.basicConfig(filename=LOG_FILENAME,level=options.verbosity)
e = UltimateBet(in_path = options.ipath, out_path = options.opath, follow = options.follow)

View File

@ -18,6 +18,9 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
######################################################################## ########################################################################
import L10n
_ = L10n.get_translation()
import sys import sys
import datetime import datetime
from HandHistoryConverter import * from HandHistoryConverter import *
@ -88,8 +91,10 @@ class Win2day(HandHistoryConverter):
m = self.re_GameInfo.search(handText) m = self.re_GameInfo.search(handText)
if not m: if not m:
print "determineGameType:", handText tmp = handText[0:100]
return None log.error(_("determineGameType: Unable to recognise gametype from: '%s'") % tmp)
log.error(_("determineGameType: Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
mg = m.groupdict() mg = m.groupdict()
@ -98,7 +103,8 @@ class Win2day(HandHistoryConverter):
limits = { 'NL':'nl', 'PL':'pl'} limits = { 'NL':'nl', 'PL':'pl'}
games = { # base, category games = { # base, category
"GAME_THM" : ('hold','holdem'), "GAME_THM" : ('hold','holdem'),
# 'Omaha' : ('hold','omahahi'), "GAME_OMA" : ('hold','omahahi'),
#'Omaha Hi/Lo' : ('hold','omahahilo'), #'Omaha Hi/Lo' : ('hold','omahahilo'),
# 'Razz' : ('stud','razz'), # 'Razz' : ('stud','razz'),
#'7 Card Stud' : ('stud','studhi'), #'7 Card Stud' : ('stud','studhi'),
@ -182,15 +188,15 @@ class Win2day(HandHistoryConverter):
if street in ('FLOP','TURN','RIVER'): # a list of streets which get dealt community cards (i.e. all but PREFLOP) if street in ('FLOP','TURN','RIVER'): # a list of streets which get dealt community cards (i.e. all but PREFLOP)
#print "DEBUG readCommunityCards:", street, hand.streets.group(street) #print "DEBUG readCommunityCards:", street, hand.streets.group(street)
boardCards = set([]) boardCards = []
if street == 'FLOP': if street == 'FLOP':
m = self.re_Card.findall(hand.streets[street]) m = self.re_Card.findall(hand.streets[street])
for card in m: for card in m:
boardCards.add(self.convertWin2dayCards(card)) boardCards.append(self.convertWin2dayCards(card))
else: else:
m = self.re_BoardLast.search(hand.streets[street]) m = self.re_BoardLast.search(hand.streets[street])
boardCards.add(self.convertWin2dayCards(m.group('CARD'))) boardCards.append(self.convertWin2dayCards(m.group('CARD')))
hand.setCommunityCards(street, boardCards) hand.setCommunityCards(street, boardCards)
def readAntes(self, hand): def readAntes(self, hand):
@ -225,7 +231,7 @@ class Win2day(HandHistoryConverter):
for found in m: for found in m:
hand.hero = found.group('PNAME') hand.hero = found.group('PNAME')
for card in self.re_Card.finditer(found.group('CARDS')): for card in self.re_Card.finditer(found.group('CARDS')):
print self.convertWin2dayCards(card.group('CARD')) #print self.convertWin2dayCards(card.group('CARD'))
newcards.append(self.convertWin2dayCards(card.group('CARD'))) newcards.append(self.convertWin2dayCards(card.group('CARD')))
#hand.addHoleCards(holeCards, m.group('PNAME')) #hand.addHoleCards(holeCards, m.group('PNAME'))
@ -267,13 +273,13 @@ class Win2day(HandHistoryConverter):
newcards = player.group('NEWCARDS') newcards = player.group('NEWCARDS')
oldcards = player.group('OLDCARDS') oldcards = player.group('OLDCARDS')
if newcards == None: if newcards == None:
newcards = set() newcards = []
else: else:
newcards = set(newcards.split(' ')) newcards = newcards.split(' ')
if oldcards == None: if oldcards == None:
oldcards = set() oldcards = []
else: else:
oldcards = set(oldcards.split(' ')) oldcards = oldcards.split(' ')
hand.addDrawHoleCards(newcards, oldcards, player.group('PNAME'), street) hand.addDrawHoleCards(newcards, oldcards, player.group('PNAME'), street)
@ -337,10 +343,10 @@ class Win2day(HandHistoryConverter):
def readShowdownActions(self, hand): def readShowdownActions(self, hand):
for shows in self.re_ShowdownAction.finditer(hand.handText): for shows in self.re_ShowdownAction.finditer(hand.handText):
showdownCards = set([]) showdownCards = []
for card in self.re_Card.finditer(shows.group('CARDS')): for card in self.re_Card.finditer(shows.group('CARDS')):
#print "DEBUG:", card, card.group('CARD'), self.convertWin2dayCards(card.group('CARD')) #print "DEBUG:", card, card.group('CARD'), self.convertWin2dayCards(card.group('CARD'))
showdownCards.add(self.convertWin2dayCards(card.group('CARD'))) showdownCards.append(self.convertWin2dayCards(card.group('CARD')))
hand.addShownCards(showdownCards, shows.group('PNAME')) hand.addShownCards(showdownCards, shows.group('PNAME'))
@ -354,7 +360,7 @@ class Win2day(HandHistoryConverter):
for m in self.re_ShownCards.finditer(hand.handText): for m in self.re_ShownCards.finditer(hand.handText):
if m.group('CARDS') is not None: if m.group('CARDS') is not None:
cards = m.group('CARDS') cards = m.group('CARDS')
cards = set(cards.split(' ')) cards = cards.split(' ')
hand.addShownCards(cards=cards, player=m.group('PNAME')) hand.addShownCards(cards=cards, player=m.group('PNAME'))
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,10 +1,8 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""WinTables.py """Routines for detecting and handling poker client windows for MS Windows.
Routines for detecting and handling poker client windows for MS Windows.
""" """
# Copyright 2008-2010, Ray E. Barker # Copyright 2008 - 2010, Ray E. Barker
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -22,6 +20,9 @@ Routines for detecting and handling poker client windows for MS Windows.
######################################################################## ########################################################################
import L10n
_ = L10n.get_translation()
# Standard Library modules # Standard Library modules
import re import re
@ -40,18 +41,6 @@ import win32api
import win32con import win32con
import win32security import win32security
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
# FreePokerTools modules # FreePokerTools modules
from TableWindow import Table_Window from TableWindow import Table_Window
@ -60,87 +49,80 @@ from TableWindow import Table_Window
b_width = 3 b_width = 3
tb_height = 29 tb_height = 29
class Table(Table_Window): class Table(Table_Window):
def find_table_parameters(self, search_string): def find_table_parameters(self):
"""Finds poker client window with the given table name.""" """Finds poker client window with the given table name."""
titles = {} titles = {}
win32gui.EnumWindows(win_enum_handler, titles) win32gui.EnumWindows(win_enum_handler, titles)
for hwnd in titles: for hwnd in titles:
if titles[hwnd] == "": continue if titles[hwnd] == "":
# print "searching ", search_string, " in ", titles[hwnd] continue
if re.search(search_string, titles[hwnd]): if re.search(self.search_string, titles[hwnd], re.I):
if 'History for table:' in titles[hwnd]: continue # Everleaf Network HH viewer window if self.check_bad_words(titles[hwnd]):
if 'HUD:' in titles[hwnd]: continue # FPDB HUD window continue
if 'Chat:' in titles[hwnd]: continue # Some sites (FTP? PS? Others?) have seperable or seperately constructed chat windows
if 'FPDBHUD' in titles[hwnd]: continue # can't attach to ourselves!
self.window = hwnd self.window = hwnd
break break
try: try:
if self.window == None: if self.window == None:
log.error(_("Window %s not found. Skipping.") % search_string ) log.error(_("Window %s not found. Skipping." % self.search_string))
return None return None
except AttributeError: except AttributeError:
log.error(_("self.window doesn't exist? why?")) log.error(_("self.window doesn't exist? why?"))
return None return None
(x, y, width, height) = win32gui.GetWindowRect(hwnd) self.title = titles[hwnd]
log.debug("x = %s y = %s width = %s height = %s" % (x, y, width, height)) self.hud = None
self.x = int(x) + b_width
self.y = int(y) + tb_height
self.width = width - x
self.height = height - y
log.debug("x = %s y = %s width = %s height = %s" % (self.x, self.y, self.width, self.height))
#self.height = int(height) - b_width - tb_height
#self.width = int(width) - 2*b_width
self.exe = self.get_nt_exe(hwnd)
self.title = titles[hwnd]
self.site = ""
self.hud = None
self.number = hwnd self.number = hwnd
self.gdkhandle = gtk.gdk.window_foreign_new(long(self.window))
def get_geometry(self): def get_geometry(self):
if not win32gui.IsWindow(self.number): # window closed
return None
try: try:
(x, y, width, height) = win32gui.GetWindowRect(self.number) if win32gui.IsWindow(self.number):
width = width - x (x, y, width, height) = win32gui.GetWindowRect(self.number)
height = height - y # this apparently returns x = far left side of window, width = far right side of window, y = top of window, height = bottom of window
return {'x' : int(x) + b_width, # so apparently we have to subtract x from "width" to get actual width, and y from "height" to get actual height ?
# it definitely gives slightly different results than the GTK code that does the same thing.
#print "x=", x, "y=", y, "width=", width, "height=", height
width = width - x
height = height - y
return {
'x' : int(x) + b_width,
'y' : int(y) + tb_height, 'y' : int(y) + tb_height,
'width' : int(height) - b_width - tb_height, 'height' : int(height) - y,
'height' : int(width) - 2*b_width 'width' : int(width) - x
} }
except: except AttributeError:
return None return None
def get_window_title(self): def get_window_title(self):
return win32gui.GetWindowText(self.window) try: # after window is destroyed, self.window = attribute error
return win32gui.GetWindowText(self.window)
except AttributeError:
return ""
def get_nt_exe(self, hwnd): # def get_nt_exe(self, hwnd):
"""Finds the name of the executable that the given window handle belongs to.""" # """Finds the name of the executable that the given window handle belongs to."""
#
# # Request privileges to enable "debug process", so we can later use PROCESS_VM_READ, retardedly required to GetModuleFileNameEx()
# priv_flags = win32security.TOKEN_ADJUST_PRIVILEGES | win32security.TOKEN_QUERY
# hToken = win32security.OpenProcessToken (win32api.GetCurrentProcess(), priv_flags)
# # enable "debug process"
# privilege_id = win32security.LookupPrivilegeValue (None, win32security.SE_DEBUG_NAME)
# old_privs = win32security.AdjustTokenPrivileges (hToken, 0, [(privilege_id, win32security.SE_PRIVILEGE_ENABLED)])
#
# # Open the process, and query it's filename
# processid = win32process.GetWindowThreadProcessId(hwnd)
# pshandle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ, False, processid[1])
# exename = win32process.GetModuleFileNameEx(pshandle, 0)
#
# # clean up
# win32api.CloseHandle(pshandle)
# win32api.CloseHandle(hToken)
#
# return exename
# Request privileges to enable "debug process", so we can later use PROCESS_VM_READ, retardedly required to GetModuleFileNameEx()
priv_flags = win32security.TOKEN_ADJUST_PRIVILEGES | win32security.TOKEN_QUERY
hToken = win32security.OpenProcessToken (win32api.GetCurrentProcess(), priv_flags)
# enable "debug process"
privilege_id = win32security.LookupPrivilegeValue (None, win32security.SE_DEBUG_NAME)
old_privs = win32security.AdjustTokenPrivileges (hToken, 0, [(privilege_id, win32security.SE_PRIVILEGE_ENABLED)])
# Open the process, and query it's filename
processid = win32process.GetWindowThreadProcessId(hwnd)
pshandle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ, False, processid[1])
exename = win32process.GetModuleFileNameEx(pshandle, 0)
# clean up
win32api.CloseHandle(pshandle)
win32api.CloseHandle(hToken)
return exename
def topify(self, hud): def topify(self, hud):
"""Set the specified gtk window to stayontop in MS Windows.""" """Set the specified gtk window to stayontop in MS Windows."""
@ -159,10 +141,10 @@ class Table(Table_Window):
# hud.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0]) # hud.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0])
hud.main_window.gdkhandle = hud.main_window.window hud.main_window.gdkhandle = hud.main_window.window
hud.main_window.gdkhandle.set_transient_for(self.gdkhandle) hud.main_window.gdkhandle.set_transient_for(self.gdkhandle)
rect = self.gdkhandle.get_frame_extents() # rect = self.gdkhandle.get_frame_extents()
(innerx, innery) = self.gdkhandle.get_origin() # (innerx, innery) = self.gdkhandle.get_origin()
b_width = rect.x - innerx # b_width = rect.x - innerx
tb_height = rect.y - innery # tb_height = rect.y - innery
# #
# style = win32gui.GetWindowLong(self.number, win32con.GWL_EXSTYLE) # style = win32gui.GetWindowLong(self.number, win32con.GWL_EXSTYLE)
# style |= win32con.WS_CLIPCHILDREN # style |= win32con.WS_CLIPCHILDREN
@ -171,5 +153,6 @@ class Table(Table_Window):
# hud.main_window.set_title(real_name) # hud.main_window.set_title(real_name)
def win_enum_handler(hwnd, titles): def win_enum_handler(hwnd, titles):
titles[hwnd] = win32gui.GetWindowText(hwnd) titles[hwnd] = win32gui.GetWindowText(hwnd)

388
pyfpdb/WinamaxToFpdb.py Normal file
View File

@ -0,0 +1,388 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright 2008-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
########################################################################
import L10n
_ = L10n.get_translation()
import sys
import exceptions
import logging
# logging has been set up in fpdb.py or HUD_main.py, use their settings:
import Configuration
from HandHistoryConverter import *
from decimal import Decimal
import time
# Winamax HH Format
class Winamax(HandHistoryConverter):
def Trace(f):
def my_f(*args, **kwds):
print ( "entering " + f.__name__)
result= f(*args, **kwds)
print ( "exiting " + f.__name__)
return result
my_f.__name = f.__name__
my_f.__doc__ = f.__doc__
return my_f
filter = "Winamax"
siteName = "Winamax"
filetype = "text"
codepage = ("utf8", "cp1252")
siteId = 14 # Needs to match id entry in Sites database
mixes = { } # Legal mixed games
sym = {'USD': "\$", 'CAD': "\$", 'T$': "", "EUR": "\xe2\x82\xac", "GBP": "\xa3"} # ADD Euro, Sterling, etc HERE
substitutions = {
'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
'LS' : "\$|\xe2\x82\xac|" # legal currency symbols - Euro(cp1252, utf-8)
}
limits = { 'no limit':'nl', 'pot limit' : 'pl','LIMIT':'fl'}
games = { # base, category
"Holdem" : ('hold','holdem'),
'Omaha' : ('hold','omahahi'),
# 'Omaha Hi/Lo' : ('hold','omahahilo'),
# 'Razz' : ('stud','razz'),
# 'RAZZ' : ('stud','razz'),
# '7 Card Stud' : ('stud','studhi'),
# 'SEVEN_CARD_STUD_HI_LO' : ('stud','studhilo'),
# 'Badugi' : ('draw','badugi'),
# 'Triple Draw 2-7 Lowball' : ('draw','27_3draw'),
# '5 Card Draw' : ('draw','fivedraw')
}
# Static regexes
# ***** End of hand R5-75443872-57 *****
re_SplitHands = re.compile(r'\n\n')
# Winamax Poker - CashGame - HandId: #279823-223-1285031451 - Holdem no limit (0.02€/0.05€) - 2010/09/21 03:10:51 UTC
# Table: 'Charenton-le-Pont' 9-max (real money) Seat #5 is the button
re_HandInfo = re.compile(u"""
\s*Winamax\sPoker\s-\sCashGame\s-\sHandId:\s\#(?P<HID1>\d+)-(?P<HID2>\d+)-(?P<HID3>\d+).*\s
(?P<GAME>Holdem|Omaha)\s
(?P<LIMIT>no\slimit|pot\slimit)\s
\(
((%(LS)s)?(?P<SB>[.0-9]+)(%(LS)s)?)/
((%(LS)s)?(?P<BB>[.0-9]+)(%(LS)s)?)
\)\s-\s
(?P<DATETIME>.*)
Table:\s\'(?P<TABLE>[^']+)\'\s(?P<MAXPLAYER>\d+)\-max
""" % substitutions, re.MULTILINE|re.DOTALL|re.VERBOSE)
re_TailSplitHands = re.compile(r'\n\s*\n')
re_Button = re.compile(r'Seat\s#(?P<BUTTON>\d+)\sis\sthe\sbutton')
re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
# 2010/09/21 03:10:51 UTC
re_DateTime = re.compile("""
(?P<Y>[0-9]{4})/
(?P<M>[0-9]+)/
(?P<D>[0-9]+)\s
(?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)\s
UTC
""", re.MULTILINE|re.VERBOSE)
# Seat 1: some_player (5€)
# Seat 2: some_other_player21 (6.33€)
re_PlayerInfo = re.compile(u'Seat\s(?P<SEAT>[0-9]+):\s(?P<PNAME>.*)\s\((%(LS)s)?(?P<CASH>[.0-9]+)(%(LS)s)?\)' % substitutions)
def compilePlayerRegexs(self, hand):
players = set([player[1] for player in hand.players])
if not players <= self.compiledPlayers: # x <= y means 'x is subset of y'
# we need to recompile the player regexs.
# TODO: should probably rename re_HeroCards and corresponding method,
# since they are used to find all cards on lines starting with "Dealt to:"
# They still identify the hero.
self.compiledPlayers = players
#ANTES/BLINDS
#helander2222 posts blind ($0.25), lopllopl posts blind ($0.50).
player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")"
subst = {'PLYR': player_re, 'CUR': self.sym[hand.gametype['currency']]}
self.re_PostSB = re.compile('%(PLYR)s posts small blind (%(CUR)s)?(?P<SB>[\.0-9]+)(%(CUR)s)?' % subst, re.MULTILINE)
self.re_PostBB = re.compile('%(PLYR)s posts big blind (%(CUR)s)?(?P<BB>[\.0-9]+)(%(CUR)s)?' % subst, re.MULTILINE)
self.re_DenySB = re.compile('(?P<PNAME>.*) deny SB' % subst, re.MULTILINE)
self.re_Antes = re.compile(r"^%(PLYR)s: posts the ante (%(CUR)s)?(?P<ANTE>[\.0-9]+)(%(CUR)s)?" % subst, re.MULTILINE)
self.re_BringIn = re.compile(r"^%(PLYR)s: brings[- ]in( low|) for (%(CUR)s)?(?P<BRINGIN>[\.0-9]+(%(CUR)s)?)" % subst, re.MULTILINE)
self.re_PostBoth = re.compile('(?P<PNAME>.*): posts small \& big blind \( (%(CUR)s)?(?P<SBBB>[\.0-9]+)(%(CUR)s)?\)' % subst)
self.re_PostDead = re.compile('(?P<PNAME>.*) posts dead blind \((%(CUR)s)?(?P<DEAD>[\.0-9]+)(%(CUR)s)?\)' % subst, re.MULTILINE)
self.re_HeroCards = re.compile('Dealt\sto\s%(PLYR)s\s\[(?P<CARDS>.*)\]' % subst)
self.re_Action = re.compile('(, )?(?P<PNAME>.*?)(?P<ATYPE> bets| checks| raises| calls| folds)( (%(CUR)s)?(?P<BET>[\d\.]+)(%(CUR)s)?)?( and is all-in)?' % subst)
self.re_ShowdownAction = re.compile('(?P<PNAME>[^\(\)\n]*) (\((small blind|big blind|button)\) )?shows \[(?P<CARDS>.+)\]')
self.re_CollectPot = re.compile('\s*(?P<PNAME>.*)\scollected\s(%(CUR)s)?(?P<POT>[\.\d]+)(%(CUR)s)?.*' % subst)
self.re_ShownCards = re.compile("^Seat (?P<SEAT>[0-9]+): %(PLYR)s showed \[(?P<CARDS>.*)\].*" % subst, re.MULTILINE)
self.re_sitsOut = re.compile('(?P<PNAME>.*) sits out')
def readSupportedGames(self):
return [
["ring", "hold", "fl"],
["ring", "hold", "nl"],
["ring", "hold", "pl"],
]
def determineGameType(self, handText):
# Inspect the handText and return the gametype dict
# gametype dict is: {'limitType': xxx, 'base': xxx, 'category': xxx}
info = {}
m = self.re_HandInfo.search(handText)
if not m:
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()
info['type'] = 'ring'
info['currency'] = 'EUR'
if 'LIMIT' in mg:
if mg['LIMIT'] in self.limits:
info['limitType'] = self.limits[mg['LIMIT']]
else:
tmp = handText[0:100]
log.error(_("determineGameType: limit not found in self.limits(%s). hand: '%s'") % (str(mg),tmp))
log.error(_("determineGameType: Raising FpdbParseError"))
raise FpdbParseError(_("limit not found in self.limits(%s). hand: '%s'") % (str(mg),tmp))
if 'GAME' in mg:
(info['base'], info['category']) = self.games[mg['GAME']]
if 'SB' in mg:
info['sb'] = mg['SB']
if 'BB' in mg:
info['bb'] = mg['BB']
return info
def readHandInfo(self, hand):
info = {}
m = self.re_HandInfo.search(hand.handText)
if m:
info.update(m.groupdict())
#log.debug("readHandInfo: %s" % info)
for key in info:
if key == 'DATETIME':
a = self.re_DateTime.search(info[key])
if a:
datetimestr = "%s/%s/%s %s:%s:%s" % (a.group('Y'),a.group('M'), a.group('D'), a.group('H'),a.group('MIN'),a.group('S'))
tzoffset = str(-time.timezone/3600)
else:
datetimestr = "2010/Jan/01 01:01:01"
log.error(_("readHandInfo: DATETIME not matched: '%s'" % info[key]))
# print "DEBUG: readHandInfo: DATETIME not matched: '%s'" % info[key]
# TODO: Manually adjust time against OFFSET
hand.startTime = datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S") # also timezone at end, e.g. " ET"
hand.startTime = HandHistoryConverter.changeTimezone(hand.startTime, "CET", "UTC")
if key == 'HID1':
hand.handid = "1%.4d%s%s"%(int(info['HID2']),info['HID1'],info['HID3'])
# Need to remove non-alphanumerics for MySQL
if key == 'TABLE':
hand.tablename = info[key]
# TODO: These
hand.buttonpos = 1
hand.maxseats = 10 # Set to None - Hand.py will guessMaxSeats()
hand.mixed = None
def readPlayerStacks(self, hand):
log.debug(_("readplayerstacks: re is '%s'" % self.re_PlayerInfo))
m = self.re_PlayerInfo.finditer(hand.handText)
for a in m:
hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH'))
def markStreets(self, hand):
m = re.search(r"\*\*\* ANTE\/BLINDS \*\*\*(?P<PREFLOP>.+(?=\*\*\* FLOP \*\*\*)|.+)"
r"(\*\*\* FLOP \*\*\*(?P<FLOP> \[\S\S \S\S \S\S\].+(?=\*\*\* TURN \*\*\*)|.+))?"
r"(\*\*\* TURN \*\*\* \[\S\S \S\S \S\S](?P<TURN>\[\S\S\].+(?=\*\*\* RIVER \*\*\*)|.+))?"
r"(\*\*\* RIVER \*\*\* \[\S\S \S\S \S\S \S\S](?P<RIVER>\[\S\S\].+))?", hand.handText,re.DOTALL)
try:
hand.addStreets(m)
# print "adding street", m.group(0)
# print "---"
except:
print (_("Failed to add streets. handtext=%s"))
#Needs to return a list in the format
# ['player1name', 'player2name', ...] where player1name is the sb and player2name is bb,
# addtional players are assumed to post a bb oop
def readButton(self, hand):
m = self.re_Button.search(hand.handText)
if m:
hand.buttonpos = int(m.group('BUTTON'))
log.debug(_('readButton: button on pos %d'%hand.buttonpos))
else:
log.warning(_('readButton: not found'))
# def readCommunityCards(self, hand, street):
# #print hand.streets.group(street)
# if street in ('FLOP','TURN','RIVER'): # a list of streets which get dealt community cards (i.e. all but PREFLOP)
# m = self.re_Board.search(hand.streets.group(street))
# hand.setCommunityCards(street, m.group('CARDS').split(','))
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)
#print "DEBUG readCommunityCards:", street, hand.streets.group(street)
m = self.re_Board.search(hand.streets[street])
hand.setCommunityCards(street, m.group('CARDS').split(' '))
def readBlinds(self, hand):
if not self.re_DenySB.search(hand.handText):
try:
m = self.re_PostSB.search(hand.handText)
hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB'))
except exceptions.AttributeError: # no small blind
log.warning( _("readBlinds in noSB exception - no SB created")+str(sys.exc_info()) )
#hand.addBlind(None, None, None)
for a in self.re_PostBB.finditer(hand.handText):
hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB'))
for a in self.re_PostDead.finditer(hand.handText):
#print "DEBUG: Found dead blind: addBlind(%s, 'secondsb', %s)" %(a.group('PNAME'), a.group('DEAD'))
hand.addBlind(a.group('PNAME'), 'secondsb', a.group('DEAD'))
for a in self.re_PostBoth.finditer(hand.handText):
hand.addBlind(a.group('PNAME'), 'small & big blinds', a.group('SBBB'))
def readAntes(self, hand):
log.debug(_("reading antes"))
m = self.re_Antes.finditer(hand.handText)
for player in m:
#~ logging.debug("hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE')))
hand.addAnte(player.group('PNAME'), player.group('ANTE'))
def readBringIn(self, hand):
m = self.re_BringIn.search(hand.handText,re.DOTALL)
if m:
#~ logging.debug("readBringIn: %s for %s" %(m.group('PNAME'), m.group('BRINGIN')))
hand.addBringIn(m.group('PNAME'), m.group('BRINGIN'))
def readHeroCards(self, hand):
# streets PREFLOP, PREDRAW, and THIRD are special cases beacause
# we need to grab hero's cards
for street in ('PREFLOP', 'DEAL', 'BLINDSANTES'):
if street in hand.streets.keys():
m = self.re_HeroCards.finditer(hand.streets[street])
if m == []:
log.debug(_("No hole cards found for %s"%street))
for found in m:
hand.hero = found.group('PNAME')
newcards = found.group('CARDS').split(' ')
# print "DEBUG: addHoleCards(%s, %s, %s)" %(street, hand.hero, newcards)
hand.addHoleCards(street, hand.hero, closed=newcards, shown=False, mucked=False, dealt=True)
log.debug(_("Hero cards %s: %s"%(hand.hero, newcards)))
def readAction(self, hand, street):
m = self.re_Action.finditer(hand.streets[street])
for action in m:
acts = action.groupdict()
if action.group('ATYPE') == ' raises':
hand.addRaiseBy( street, action.group('PNAME'), action.group('BET') )
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'))
elif action.group('ATYPE') == ' discards':
hand.addDiscard(street, action.group('PNAME'), action.group('BET'), action.group('DISCARDED'))
elif action.group('ATYPE') == ' stands pat':
hand.addStandsPat( street, action.group('PNAME'))
else:
log.fatal(_("DEBUG: unimplemented readAction: '%s' '%s'")) %(action.group('PNAME'),action.group('ATYPE'),)
# print "Processed %s"%acts
# print "committed=",hand.pot.committed
def readShowdownActions(self, hand):
for shows in self.re_ShowdownAction.finditer(hand.handText):
log.debug(_("add show actions %s"%shows))
cards = shows.group('CARDS')
cards = cards.split(' ')
# print "DEBUG: addShownCards(%s, %s)" %(cards, shows.group('PNAME'))
hand.addShownCards(cards, shows.group('PNAME'))
def readCollectPot(self,hand):
# Winamax has unfortunately thinks that a sidepot is created
# when there is uncalled money in the pot - something that can
# only happen when a player is all-in
# Becuase of this, we need to do the same calculations as class Pot()
# and determine if the amount returned is the same as the amount collected
# if so then the collected line is invalid
total = sum(hand.pot.committed.values()) + sum(hand.pot.common.values())
# Return any uncalled bet.
committed = sorted([ (v,k) for (k,v) in hand.pot.committed.items()])
#print "DEBUG: committed: %s" % committed
#ERROR below. lastbet is correct in most cases, but wrong when
# additional money is committed to the pot in cash games
# due to an additional sb being posted. (Speculate that
# posting sb+bb is also potentially wrong)
returned = {}
lastbet = committed[-1][0] - committed[-2][0]
if lastbet > 0: # uncalled
returnto = committed[-1][1]
#print "DEBUG: returning %f to %s" % (lastbet, returnto)
total -= lastbet
returned[returnto] = lastbet
collectees = []
for m in self.re_CollectPot.finditer(hand.handText):
collectees.append([m.group('PNAME'), m.group('POT')])
for plyr, p in collectees:
if plyr in returned.keys() and Decimal(p) - returned[plyr] == 0:
p = Decimal(p) - returned[plyr]
if p > 0:
print "DEBUG: addCollectPot(%s,%s)" %(plyr, p)
hand.addCollectPot(player=plyr,pot=p)
def readShownCards(self,hand):
for m in self.re_ShownCards.finditer(hand.handText):
log.debug(_("Read shown cards: %s"%m.group(0)))
cards = m.group('CARDS')
cards = cards.split(' ') # needs to be a list, not a set--stud needs the order
(shown, mucked) = (False, False)
if m.group('CARDS') is not None:
shown = True
hand.addShownCards(cards=cards, player=m.group('PNAME'), shown=shown, mucked=mucked)
if __name__ == "__main__":
c = Configuration.Config()
if len(sys.argv) == 1:
testfile = "regression-test-files/ongame/nlhe/ong NLH handhq_0.txt"
else:
testfile = sys.argv[1]
e = Winamax(c, testfile)

View File

@ -1,12 +1,8 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""Discover_Tables.py """XWindows specific methods for TableWindows Class.
Inspects the currently open windows and finds those of interest to us--that is
poker table windows from supported sites. Returns a list
of Table_Window objects representing the windows found.
""" """
# Copyright 2008-2010, Ray E. Barker # Copyright 2008 - 2010, Ray E. Barker
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -24,102 +20,68 @@ of Table_Window objects representing the windows found.
######################################################################## ########################################################################
import L10n
_ = L10n.get_translation()
# Standard Library modules # Standard Library modules
import re import re
import os import os
# pyGTK modules # pyGTK modules
import pygtk
import gtk import gtk
# Other Library modules # Other Library modules
import Xlib
import Xlib.display import Xlib.display
# FreePokerTools modules # FPDB modules
from TableWindow import Table_Window from TableWindow import Table_Window
# We might as well do this once and make them globals # We might as well do this once and make them globals
disp = Xlib.display.Display() disp = Xlib.display.Display()
root = disp.screen().root root = disp.screen().root
name_atom = disp.get_atom("WM_NAME", 1)
class Table(Table_Window): class Table(Table_Window):
def find_table_parameters(self, search_string): def find_table_parameters(self):
# self.window = None
# done_looping = False
# for outside in root.query_tree().children:
# for inside in outside.query_tree().children:
# if done_looping: break
# prop = inside.get_property(name_atom, Xlib.Xatom.STRING, 0, 1000)
# print prop
# if prop is None: continue
# if prop.value and re.search(search_string, prop.value):
# if self.check_bad_words(prop.value): continue
## if inside.get_wm_name() and re.search(search_string, inside.get_wm_name()):
## if self.check_bad_words(inside.get_wm_name()):
## print "bad word =", inside.get_wm_name()
## continue
# self.window = inside
# self.parent = outside
# done_looping = True
# break
window_number = None reg = '''
\s+(?P<XID>[\dxabcdef]+) # XID in hex
\s(?P<TITLE>.+): # window title
'''
self.number = None
for listing in os.popen('xwininfo -root -tree').readlines(): for listing in os.popen('xwininfo -root -tree').readlines():
if re.search(search_string, listing): if re.search(self.search_string, listing, re.I):
# print listing mo = re.match(reg, listing, re.VERBOSE)
mo = re.match('\s+([\dxabcdef]+) (.+):\s\(\"([a-zA-Z0-9\-.]+)\".+ (\d+)x(\d+)\+\d+\+\d+ \+(\d+)\+(\d+)', listing) # mo = re.match('\s+([\dxabcdef]+) (.+):\s\(\"([a-zA-Z0-9\-.]+)\".+ (\d+)x(\d+)\+\d+\+\d+ \+(\d+)\+(\d+)', listing)
self.number = int( mo.group(1), 0) title = re.sub('\"', '', mo.groupdict()["TITLE"])
self.width = int( mo.group(4) ) if self.check_bad_words(title): continue
self.height = int( mo.group(5) ) self.number = int( mo.groupdict()["XID"], 0 )
self.x = int( mo.group(6) ) self.title = title
self.y = int( mo.group(7) ) self.hud = None # specified later
self.title = re.sub('\"', '', mo.group(2)) break
self.exe = "" # not used?
self.hud = None
# done_looping = False
# for outside in root.query_tree().children:
# for inside in outside.query_tree().children:
# if done_looping: break
# if inside.id == window_number:
# self.window = inside
# self.parent = outside
# done_looping = True
# break
if window_number is None: if self.number is None:
return None return None
self.window = self.get_window_from_xid(self.number)
self.parent = self.window.query_tree().parent
# my_geo = self.window.get_geometry() def get_window_from_xid(self, id):
# pa_geo = self.parent.get_geometry() for outside in root.query_tree().children:
# if outside.id == id:
# self.x = pa_geo.x + my_geo.x return outside
# self.y = pa_geo.y + my_geo.y for inside in outside.query_tree().children:
# self.width = my_geo.width if inside.id == id:
# self.height = my_geo.height return inside
# self.exe = self.window.get_wm_class()[0] return None
# self.title = self.window.get_wm_name()
# self.site = ""
# self.hud = None
# window_string = str(self.window)
mo = re.match('Xlib\.display\.Window\(([\dxabcdef]+)', window_string)
if not mo:
print "Not matched"
self.gdk_handle = None
else:
self.number = int( mo.group(1), 0)
print "number =", self.number
# self.gdk_handle = gtk.gdk.window_foreign_new(int(self.number))
def get_geometry(self): def get_geometry(self):
try: try:
my_geo = self.window.get_geometry() my_geo = self.window.get_geometry()
pa_geo = self.parent.get_geometry() pa_geo = self.parent.get_geometry()
return {'x' : pa_geo.x + my_geo.x, return {'x' : my_geo.x + pa_geo.x,
'y' : pa_geo.y + my_geo.y, 'y' : my_geo.y + pa_geo.y,
'width' : my_geo.width, 'width' : my_geo.width,
'height' : my_geo.height 'height' : my_geo.height
} }
@ -127,8 +89,14 @@ class Table(Table_Window):
return None return None
def get_window_title(self): def get_window_title(self):
return self.window.get_wm_name() s = os.popen("xwininfo -wm -id %d" % self.number).read()
mo = re.search('"(.+)"', s)
try:
return mo.group(1)
except AttributeError:
return None
def topify(self, hud): def topify(self, hud):
hud.main_window.gdkhandle = gtk.gdk.window_foreign_new(hud.main_window.window.xid) hud.main_window.gdkhandle = gtk.gdk.window_foreign_new(hud.main_window.window.xid)
hud.main_window.gdkhandle.set_transient_for(self.gdk_handle) hud.main_window.gdkhandle.set_transient_for(self.gdk_handle)

View File

@ -15,23 +15,14 @@
#along with this program. If not, see <http://www.gnu.org/licenses/>. #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. #In the "official" distribution you can find the license in agpl-3.0.txt.
import L10n
_ = L10n.get_translation()
import os import os
import sys import sys
import re import re
import Queue import Queue
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
# if path is set to use an old version of python look for a new one: # if path is set to use an old version of python look for a new one:
# (does this work in linux?) # (does this work in linux?)
if os.name == 'nt' and sys.version[0:3] not in ('2.5', '2.6', '2.7') and '-r' not in sys.argv: if os.name == 'nt' and sys.version[0:3] not in ('2.5', '2.6', '2.7') and '-r' not in sys.argv:
@ -115,6 +106,7 @@ import GuiPrefs
import GuiLogView import GuiLogView
import GuiDatabase import GuiDatabase
import GuiBulkImport import GuiBulkImport
import GuiTourneyImport
import GuiImapFetcher import GuiImapFetcher
import GuiRingPlayerStats import GuiRingPlayerStats
import GuiTourneyPlayerStats import GuiTourneyPlayerStats
@ -130,7 +122,7 @@ import Configuration
import Exceptions import Exceptions
import Stats import Stats
VERSION = "0.20.906 plus git" VERSION = "0.21-rc1"
class fpdb: class fpdb:
@ -772,6 +764,7 @@ class fpdb:
</menu> </menu>
<menu action="import"> <menu action="import">
<menuitem action="bulkimp"/> <menuitem action="bulkimp"/>
<menuitem action="tourneyimp"/>
<menuitem action="imapimport"/> <menuitem action="imapimport"/>
<menuitem action="autoimp"/> <menuitem action="autoimp"/>
</menu> </menu>
@ -814,16 +807,17 @@ class fpdb:
('Preferences', None, _('Pre_ferences'), _('<control>F'), 'Edit your preferences', self.dia_preferences), ('Preferences', None, _('Pre_ferences'), _('<control>F'), 'Edit your preferences', self.dia_preferences),
('import', None, _('_Import')), ('import', None, _('_Import')),
('bulkimp', None, _('_Bulk Import'), _('<control>B'), 'Bulk Import', self.tab_bulk_import), ('bulkimp', None, _('_Bulk Import'), _('<control>B'), 'Bulk Import', self.tab_bulk_import),
('tourneyimp', None, _('Tournament _Results Import'), _('<control>R'), 'Tournament Results Import', self.tab_tourney_import),
('imapimport', None, _('_Import through eMail/IMAP'), _('<control>I'), 'Import through eMail/IMAP', self.tab_imap_import), ('imapimport', None, _('_Import through eMail/IMAP'), _('<control>I'), 'Import through eMail/IMAP', self.tab_imap_import),
('viewers', None, _('_Viewers')), ('viewers', None, _('_Viewers')),
('autoimp', None, _('_Auto Import and HUD'), _('<control>A'), 'Auto Import and HUD', self.tab_auto_import), ('autoimp', None, _('_Auto Import and HUD'), _('<control>A'), 'Auto Import and HUD', self.tab_auto_import),
('hudConfigurator', None, _('_HUD Configurator'), _('<control>H'), 'HUD Configurator', self.diaHudConfigurator), ('hudConfigurator', None, _('_HUD Configurator'), _('<control>H'), 'HUD Configurator', self.diaHudConfigurator),
('graphs', None, _('_Graphs'), _('<control>G'), 'Graphs', self.tabGraphViewer), ('graphs', None, _('_Graphs'), _('<control>G'), 'Graphs', self.tabGraphViewer),
('tourneygraphs', None, _('Tourney Graphs'), None, 'TourneyGraphs', self.tabTourneyGraphViewer), ('tourneygraphs', None, _('Tourney Graphs'), None, 'TourneyGraphs', self.tabTourneyGraphViewer),
('ringplayerstats', None, _('Ring _Player Stats (tabulated view, not on pgsql)'), _('<control>P'), 'Ring Player Stats (tabulated view)', self.tab_ring_player_stats), ('ringplayerstats', None, _('Ring _Player Stats (tabulated view, not on pgsql)'), _('<control>P'), 'Ring Player Stats (tabulated view, not on pgsql)', self.tab_ring_player_stats),
('tourneyplayerstats', None, _('_Tourney Player Stats (tabulated view, not on pgsql)'), _('<control>T'), 'Tourney Player Stats (tabulated view, mysql only)', self.tab_tourney_player_stats), ('tourneyplayerstats', None, _('_Tourney Stats (tabulated view, not on pgsql)'), _('<control>T'), 'Tourney Stats (tabulated view, not on pgsql)', self.tab_tourney_player_stats),
('tourneyviewer', None, _('Tourney _Viewer'), None, 'Tourney Viewer)', self.tab_tourney_viewer_stats), ('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)', self.tab_positional_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), ('sessionstats', None, _('Session Stats'), None, 'Session Stats', self.tab_session_stats),
('database', None, _('_Database')), ('database', None, _('_Database')),
('maintaindbs', None, _('_Maintain Databases'), None, 'Maintain Databases', self.dia_maintain_dbs), ('maintaindbs', None, _('_Maintain Databases'), None, 'Maintain Databases', self.dia_maintain_dbs),
@ -971,6 +965,7 @@ class fpdb:
if self.db!=None: if self.db!=None:
if self.db.backend==self.db.MYSQL_INNODB: if self.db.backend==self.db.MYSQL_INNODB:
try: try:
import _mysql_exceptions
if self.db is not None and self.db.is_connected(): if self.db is not None and self.db.is_connected():
self.db.disconnect() self.db.disconnect()
except _mysql_exceptions.OperationalError: # oh, damn, we're already disconnected except _mysql_exceptions.OperationalError: # oh, damn, we're already disconnected
@ -1004,6 +999,13 @@ class fpdb:
bulk_tab=new_import_thread.get_vbox() bulk_tab=new_import_thread.get_vbox()
self.add_and_display_tab(bulk_tab, _("Bulk Import")) self.add_and_display_tab(bulk_tab, _("Bulk Import"))
def tab_tourney_import(self, widget, data=None):
"""opens a tab for bulk importing"""
new_import_thread = GuiTourneyImport.GuiTourneyImport(self.settings, self.config, self.sql, self.window)
self.threads.append(new_import_thread)
bulk_tab=new_import_thread.get_vbox()
self.add_and_display_tab(bulk_tab, _("Tournament Results Import"))
def tab_imap_import(self, widget, data=None): def tab_imap_import(self, widget, data=None):
new_thread = GuiImapFetcher.GuiImapFetcher(self.config, self.db, self.sql, self.window) new_thread = GuiImapFetcher.GuiImapFetcher(self.config, self.db, self.sql, self.window)
self.threads.append(new_thread) self.threads.append(new_thread)
@ -1021,7 +1023,7 @@ class fpdb:
new_ps_thread = GuiTourneyPlayerStats.GuiTourneyPlayerStats(self.config, self.db, self.sql, self.window) new_ps_thread = GuiTourneyPlayerStats.GuiTourneyPlayerStats(self.config, self.db, self.sql, self.window)
self.threads.append(new_ps_thread) self.threads.append(new_ps_thread)
ps_tab=new_ps_thread.get_vbox() ps_tab=new_ps_thread.get_vbox()
self.add_and_display_tab(ps_tab, _("Tourney Player Stats")) self.add_and_display_tab(ps_tab, _("Tourney Stats"))
def tab_tourney_viewer_stats(self, widget, data=None): def tab_tourney_viewer_stats(self, widget, data=None):
new_thread = GuiTourneyViewer.GuiTourneyViewer(self.config, self.db, self.sql, self.window) new_thread = GuiTourneyViewer.GuiTourneyViewer(self.config, self.db, self.sql, self.window)
@ -1136,10 +1138,13 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an
cards = os.path.join(os.getcwd(), '..','gfx','fpdb-cards.png') cards = os.path.join(os.getcwd(), '..','gfx','fpdb-cards.png')
if os.path.exists(cards): if os.path.exists(cards):
self.statusIcon.set_from_file(cards) self.statusIcon.set_from_file(cards)
self.window.set_icon_from_file(cards)
elif os.path.exists('/usr/share/pixmaps/fpdb-cards.png'): elif os.path.exists('/usr/share/pixmaps/fpdb-cards.png'):
self.statusIcon.set_from_file('/usr/share/pixmaps/fpdb-cards.png') self.statusIcon.set_from_file('/usr/share/pixmaps/fpdb-cards.png')
self.window.set_icon_from_file('/usr/share/pixmaps/fpdb-cards.png')
else: else:
self.statusIcon.set_from_stock(gtk.STOCK_HOME) self.statusIcon.set_from_stock(gtk.STOCK_HOME)
self.window.set_icon_stock(gtk.STOCK_HOME)
self.statusIcon.set_tooltip("Free Poker Database") self.statusIcon.set_tooltip("Free Poker Database")
self.statusIcon.connect('activate', self.statusicon_activate) self.statusIcon.connect('activate', self.statusicon_activate)
self.statusMenu = gtk.Menu() self.statusMenu = gtk.Menu()
@ -1248,7 +1253,7 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an
for site in self.config.get_supported_sites(True): # get site names from config file for site in self.config.get_supported_sites(True): # get site names from config file
try: try:
self.config.get_site_id(site) # and check against list from db self.config.get_site_id(site) # and check against list from db
except KeyError as exc: except KeyError , exc:
log.warning("site %s missing from db" % site) log.warning("site %s missing from db" % site)
dia = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, buttons=(gtk.BUTTONS_YES_NO), message_format="Unknown Site") dia = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, buttons=(gtk.BUTTONS_YES_NO), message_format="Unknown Site")
diastring = _("WARNING: Unable to find site '%s'\n\nPress YES to add this site to the database.") % site diastring = _("WARNING: Unable to find site '%s'\n\nPress YES to add this site to the database.") % site

View File

@ -15,6 +15,9 @@
#along with this program. If not, see <http://www.gnu.org/licenses/>. #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. #In the "official" distribution you can find the license in agpl-3.0.txt.
import L10n
_ = L10n.get_translation()
# Standard Library modules # Standard Library modules
import os # todo: remove this once import_dir is in fpdb_import import os # todo: remove this once import_dir is in fpdb_import
@ -35,18 +38,6 @@ log = logging.getLogger("importer")
import pygtk import pygtk
import gtk import gtk
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
# fpdb/FreePokerTools modules # fpdb/FreePokerTools modules
import Database import Database
import Configuration import Configuration
@ -103,6 +94,7 @@ class Importer:
self.settings.setdefault("dropIndexes", "don't drop") self.settings.setdefault("dropIndexes", "don't drop")
self.settings.setdefault("dropHudCache", "don't drop") self.settings.setdefault("dropHudCache", "don't drop")
self.settings.setdefault("starsArchive", False) self.settings.setdefault("starsArchive", False)
self.settings.setdefault("ftpArchive", False)
self.settings.setdefault("testData", False) self.settings.setdefault("testData", False)
self.settings.setdefault("cacheHHC", False) self.settings.setdefault("cacheHHC", False)
@ -149,6 +141,9 @@ class Importer:
def setStarsArchive(self, value): def setStarsArchive(self, value):
self.settings['starsArchive'] = value self.settings['starsArchive'] = value
def setFTPArchive(self, value):
self.settings['ftpArchive'] = value
def setPrintTestData(self, value): def setPrintTestData(self, value):
self.settings['testData'] = value self.settings['testData'] = value
@ -244,7 +239,7 @@ class Importer:
if self.settings['dropIndexes'] == 'drop': if self.settings['dropIndexes'] == 'drop':
self.database.prepareBulkImport() self.database.prepareBulkImport()
else: else:
log.debug(_("No need to drop indexes.")) log.info(_("No need to drop indexes."))
#print "dropInd =", self.settings['dropIndexes'], " dropHudCache =", self.settings['dropHudCache'] #print "dropInd =", self.settings['dropIndexes'], " dropHudCache =", self.settings['dropHudCache']
if self.settings['threads'] <= 0: if self.settings['threads'] <= 0:
@ -282,11 +277,11 @@ class Importer:
if self.settings['dropIndexes'] == 'drop': if self.settings['dropIndexes'] == 'drop':
self.database.afterBulkImport() self.database.afterBulkImport()
else: else:
print _("No need to rebuild indexes.") log.info (_("No need to rebuild indexes."))
if 'dropHudCache' in self.settings and self.settings['dropHudCache'] == 'drop': if 'dropHudCache' in self.settings and self.settings['dropHudCache'] == 'drop':
self.database.rebuild_hudcache() self.database.rebuild_hudcache()
else: else:
print _("No need to rebuild hudcache.") log.info (_("No need to rebuild hudcache."))
self.database.analyzeDB() self.database.analyzeDB()
endtime = time() endtime = time()
return (totstored, totdups, totpartial, toterrors, endtime-starttime) return (totstored, totdups, totpartial, toterrors, endtime-starttime)
@ -469,7 +464,8 @@ class Importer:
else: else:
self.pos_in_file[file] = 0 self.pos_in_file[file] = 0
hhc = obj( self.config, in_path = file, out_path = out_path, index = idx hhc = obj( self.config, in_path = file, out_path = out_path, index = idx
, starsArchive = self.settings['starsArchive'], sitename = site ) , starsArchive = self.settings['starsArchive'], ftpArchive = self.settings['ftpArchive'],
sitename = site )
if hhc.getStatus(): if hhc.getStatus():
handlist = hhc.getProcessedHands() handlist = hhc.getProcessedHands()
self.pos_in_file[file] = hhc.getLastCharacterRead() self.pos_in_file[file] = hhc.getLastCharacterRead()

307
pyfpdb/iPokerToFpdb.py Normal file
View File

@ -0,0 +1,307 @@
#!/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
########################################################################
import L10n
_ = L10n.get_translation()
# This code is based on CarbonToFpdb.py by Matthew Boss
#
# TODO:
#
# -- No support for tournaments (see also the last item below)
# -- Assumes that the currency of ring games is USD
# -- 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
class iPoker(HandHistoryConverter):
sitename = "iPoker"
filetype = "text"
codepage = "cp1252"
siteID = 13
# Static regexes
re_SplitHands = re.compile(r'</game>')
re_TailSplitHands = re.compile(r'(</game>)')
re_GameInfo = re.compile(r'<gametype>(?P<GAME>[a-zA-Z0-9 ]+) \$(?P<SB>[.0-9]+)/\$(?P<BB>[.0-9]+)</gametype>', re.MULTILINE)
re_HandInfo = re.compile(r'gamecode="(?P<HID>[0-9]+)">\s+<general>\s+<startdate>(?P<DATETIME>[-: 0-9]+)</startdate>', re.MULTILINE)
re_Button = re.compile(r'<players dealer="(?P<BUTTON>[0-9]+)">')
re_PlayerInfo = re.compile(r'<player seat="(?P<SEAT>[0-9]+)" name="(?P<PNAME>[^"]+)" chips="\$(?P<CASH>[.0-9]+)" dealer="(?P<DEALTIN>(0|1))" (?P<WIN>win="\$[^"]+") (bet="\$(?P<BET>[^"]+))?', 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)
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_HeroCards = re.compile(r'<cards type="HOLE" cards="(?P<CARDS>.+)" player="(?P<PSEAT>[0-9])"', re.MULTILINE)
re_Action = re.compile(r'<action no="[0-9]+" player="(?P<PNAME>[^"]+)" type="(?P<ATYPE>\d+)" sum="\$(?P<BET>[.0-9]+)"', re.MULTILINE)
re_Ante = re.compile(r'<action no="[0-9]+" player="(?P<PNAME>[^"]+)" type="(?P<ATYPE>15)" sum="\$(?P<BET>[.0-9]+)" cards="', 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", "stud", "fl"],
#["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()
#print "DEBUG: m.groupdict(): %s" % mg
limits = { 'No Limit':'nl', 'Limit':'fl' }
games = { # base, category
'7 Card Stud L' : ('stud','studhilo'),
}
if 'LIMIT' in mg:
self.info['limitType'] = limits[mg['LIMIT']]
self.info['limitType'] = 'fl'
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.error(_("Didn't match re_HandInfo"))
logging.info(hand.handText)
raise FpdbParseError(_("Didn't match re_HandInfo"))
mg = m.groupdict()
#print "DEBUG: m.groupdict(): %s" % mg
hand.handid = m.group('HID')
#hand.tablename = m.group('TABLE')[:-1]
hand.maxseats = None
hand.startTime = datetime.datetime.strptime(m.group('DATETIME'), '%Y-%m-%d %H:%M:%S')
def readPlayerStacks(self, hand):
print "DEBUG: readPlayerStacks"
m = self.re_PlayerInfo.finditer(hand.handText)
for a in m:
ag = a.groupdict()
#print "DEBUG: re_PlayerInfo: %s" %ag
seatno = int(a.group('SEAT'))
# It may be necessary to adjust 'hand.maxseats', which is an
# educated guess, starting with 2 (indicating a heads-up table) and
# 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
hand.addPlayer(seatno, a.group('PNAME'), a.group('CASH'))
def markStreets(self, hand):
if hand.gametype['base'] in ('stud'):
m = re.search(r'(?P<ANTES>.+(?=<round no="2">)|.+)'
r'(<round no="2">(?P<THIRD>.+(?=<round no="3">)|.+))?'
r'(<round no="3">(?P<FOURTH>.+(?=<round no="4">)|.+))?'
r'(<round no="4">(?P<FIFTH>.+(?=<round no="5">)|.+))?'
r'(<round no="5">(?P<SIXTH>.+(?=<round no="6">)|.+))?'
r'(<round no="6">(?P<SEVENTH>.+))?', hand.handText,re.DOTALL)
hand.addStreets(m)
def readCommunityCards(self, hand, street):
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):
m = self.re_Ante.finditer(hand.handText)
for a in m:
#print "DEBUG: addAnte(%s, %s)" %(a.group('PNAME'), a.group('BET'))
hand.addAnte(a.group('PNAME'), a.group('BET'))
def readBringIn(self, hand):
pass
def readBlinds(self, hand):
m = self.re_PostSB.search(hand.handText)
hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB'))
for a in self.re_PostBB.finditer(hand.handText):
hand.addBlind(m.group('PNAME'), 'big blind', a.group('BB'))
#for a in self.re_PostBoth.finditer(hand.handText):
def readButton(self, hand):
hand.buttonpos = int(self.re_Button.search(hand.handText).group('BUTTON'))
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:
ag = action.groupdict()
#print "DEBUG: action.groupdict: %s" % ag
logging.debug("%s %s" % (action.group('ATYPE'),
action.groupdict()))
if action.group('ATYPE') == 'RAISE': # Still no example for raise (i think?)
hand.addCallandRaise(street, player, action.group('BET'))
elif action.group('ATYPE') == '3': # Believe this is 'call'
#print "DEBUG: addCall(%s, %s, %s)" %(street, action.group('PNAME'), action.group('BET'))
hand.addCall(street, action.group('PNAME'), action.group('BET'))
elif action.group('ATYPE') == '5':
#print "DEBUG: addBet(%s, %s, %s)" %(street, action.group('PNAME'), action.group('BET'))
hand.addBet(street, action.group('PNAME'), action.group('BET'))
elif action.group('ATYPE') == '0': # Belive this is 'fold'
#print "DEBUG: addFold(%s, %s)" %(street, action.group('PNAME'))
hand.addFold(street, action.group('PNAME'))
elif action.group('ATYPE') == '4':
#print "DEBUG: addCheck(%s, %s)" %(street, action.group('PNAME'))
hand.addCheck(street, action.group('PNAME'))
#elif action.group('ATYPE') == 'ALL_IN':
# hand.addAllIn(street, player, action.group('BET'))
elif action.group('ATYPE') == '16': #BringIn
#print "DEBUG: addBringIn(%s, %s)" %(action.group('PNAME'), action.group('BET'))
hand.addBringIn(action.group('PNAME'), action.group('BET'))
else:
logging.error(_("Unimplemented readAction: %s" % (ag)))
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

@ -3,6 +3,9 @@
# Code from http://ender.snowburst.org:4747/~jjohns/interlocks.py # Code from http://ender.snowburst.org:4747/~jjohns/interlocks.py
# Thanks JJ! # Thanks JJ!
import L10n
_ = L10n.get_translation()
import sys import sys
import os, os.path import os, os.path
import subprocess import subprocess
@ -10,18 +13,6 @@ import time
import signal import signal
import base64 import base64
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
InterProcessLock = None InterProcessLock = None
""" """

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3718
pyfpdb/locale/fpdb-fr_FR.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View File

@ -2,7 +2,7 @@ cd ..
rm *.pyc rm *.pyc
echo "creating template po file" echo "creating template po file"
python /usr/share/doc/python-2.7/examples/Tools/i18n/pygettext.py --output-dir=locale --default-domain=fpdb --output=fpdb-en_GB.pot *.py* python /usr/share/doc/python-2.6*/examples/Tools/i18n/pygettext.py --output-dir=locale --default-domain=fpdb --output=fpdb-en_GB.pot *.py*
echo "merging template with existing translations" echo "merging template with existing translations"
msgmerge --update locale/fpdb-de_DE.po locale/fpdb-en_GB.pot msgmerge --update locale/fpdb-de_DE.po locale/fpdb-en_GB.pot
@ -10,7 +10,8 @@ msgmerge --update locale/fpdb-fr_FR.po locale/fpdb-en_GB.pot
msgmerge --update locale/fpdb-hu_HU.po locale/fpdb-en_GB.pot msgmerge --update locale/fpdb-hu_HU.po locale/fpdb-en_GB.pot
echo "compiling mo files" echo "compiling mo files"
python /usr/share/doc/python-2.7/examples/Tools/i18n/msgfmt.py --output-file=locale/de/LC_MESSAGES/fpdb.mo locale/fpdb-de_DE.po python /usr/share/doc/python-2.6*/examples/Tools/i18n/msgfmt.py --output-file=locale/de/LC_MESSAGES/fpdb.mo locale/fpdb-de_DE.po
python /usr/share/doc/python-2.7/examples/Tools/i18n/msgfmt.py --output-file=locale/hu/LC_MESSAGES/fpdb.mo locale/fpdb-hu_HU.po python /usr/share/doc/python-2.6*/examples/Tools/i18n/msgfmt.py --output-file=locale/fr/LC_MESSAGES/fpdb.mo locale/fpdb-fr_FR.po
python /usr/share/doc/python-2.6*/examples/Tools/i18n/msgfmt.py --output-file=locale/hu/LC_MESSAGES/fpdb.mo locale/fpdb-hu_HU.po
pocount locale/*.po pocount locale/*.po

View File

@ -0,0 +1,55 @@
Stage #1483940000: Holdem No Limit $0.02 - 2009-06-10 03:10:00 (ET)
Table: CHILE HWY (Real Money) Seat #7 is the dealer
Seat 7 - PLAYER7 ($2.13 in chips)
Seat 9 - Hero ($2.48 in chips)
Seat 1 - PLAYER1 ($3.98 in chips)
Seat 2 - PLAYER2 ($0.76 in chips)
Seat 3 - PLAYER3 ($2.24 in chips)
Seat 4 - PLAYER4 ($1.94 in chips)
Seat 5 - PLAYER5 ($0.41 in chips)
Seat 6 - PLAYER6 ($0.02 in chips)
Hero - Posts small blind $0.01
PLAYER1 - Posts big blind $0.02
*** POCKET CARDS ***
Dealt to Hero [9c 7c]
PLAYER2 - Calls $0.02
PLAYER3 - Folds
PLAYER4 - Folds
PLAYER5 - Folds
PLAYER6 - Folds
PLAYER7 - Folds
Hero - Calls $0.01
PLAYER1 - Checks
*** FLOP *** [Qh 8h 7h]
Hero - Checks
PLAYER1 - Checks
PLAYER2 - Checks
*** TURN *** [Qh 8h 7h] [Ah]
Hero - Checks
PLAYER1 - Checks
PLAYER2 - Checks
*** RIVER *** [Qh 8h 7h Ah] [Kc]
Hero - Checks
PLAYER1 - Checks
PLAYER2 - Bets $0.06
Hero - Folds
PLAYER1 - Folds
PLAYER2 - returned ($0.06) : not called
*** SHOW DOWN ***
PLAYER2 - Does not show
PLAYER2 Collects $0.06 from main pot
*** SUMMARY ***
Total Pot($0.06)
Board [Qh 8h 7h Ah Kc]
Seat 1: PLAYER1 (big blind) Folded on the RIVER
Seat 2: PLAYER2 collected Total ($0.06) HI:($0.06) [Does not show]
Seat 3: PLAYER3 Folded on the POCKET CARDS
Seat 4: PLAYER4 Folded on the POCKET CARDS
Seat 5: PLAYER5 Folded on the POCKET CARDS
Seat 6: PLAYER6 Folded on the POCKET CARDS
Seat 7: PLAYER7 (dealer) Folded on the POCKET CARDS
Seat 9: Hero (small blind) Folded on the RIVER

View File

@ -0,0 +1,752 @@
{ u'Hero': { 'card1': 34,
'card2': 32,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': True,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': True,
'otherRaisedStreet4': False,
'position': 'S',
'raiseFirstInChance': False,
'raisedFirstIn': False,
'rake': 0,
'sawShowdown': False,
'seatNo': 9,
'sitout': False,
'startCards': 97,
'startCash': 248,
'street0Aggr': False,
'street0Bets': 0,
'street0Calls': 1,
'street0Raises': 0,
'street0VPI': True,
'street0_3BChance': False,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': True,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': True,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': True,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': -2,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 0,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'PLAYER1': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': True,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': True,
'otherRaisedStreet4': False,
'position': 'B',
'raiseFirstInChance': False,
'raisedFirstIn': False,
'rake': 0,
'sawShowdown': False,
'seatNo': 1,
'sitout': False,
'startCards': 0,
'startCash': 398,
'street0Aggr': False,
'street0Bets': 0,
'street0Calls': 0,
'street0Raises': 0,
'street0VPI': False,
'street0_3BChance': False,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': True,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': True,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': True,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': -2,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 0,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'PLAYER2': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 5,
'raiseFirstInChance': True,
'raisedFirstIn': False,
'rake': 0,
'sawShowdown': False,
'seatNo': 2,
'sitout': False,
'startCards': 0,
'startCash': 76,
'street0Aggr': False,
'street0Bets': 0,
'street0Calls': 1,
'street0Raises': 0,
'street0VPI': True,
'street0_3BChance': False,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': True,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': True,
'street3Aggr': True,
'street3Bets': 1,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': True,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': 4,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 6,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 1.0,
'wonWhenSeenStreet2': 1.0,
'wonWhenSeenStreet3': 1.0,
'wonWhenSeenStreet4': 0.0},
u'PLAYER3': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 4,
'raiseFirstInChance': False,
'raisedFirstIn': False,
'rake': 0,
'sawShowdown': False,
'seatNo': 3,
'sitout': False,
'startCards': 0,
'startCash': 224,
'street0Aggr': False,
'street0Bets': 0,
'street0Calls': 0,
'street0Raises': 0,
'street0VPI': False,
'street0_3BChance': False,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': False,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': False,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': False,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': 0,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 0,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'PLAYER4': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 3,
'raiseFirstInChance': False,
'raisedFirstIn': False,
'rake': 0,
'sawShowdown': False,
'seatNo': 4,
'sitout': False,
'startCards': 0,
'startCash': 194,
'street0Aggr': False,
'street0Bets': 0,
'street0Calls': 0,
'street0Raises': 0,
'street0VPI': False,
'street0_3BChance': False,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': False,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': False,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': False,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': 0,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 0,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'PLAYER5': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 2,
'raiseFirstInChance': False,
'raisedFirstIn': False,
'rake': 0,
'sawShowdown': False,
'seatNo': 5,
'sitout': False,
'startCards': 0,
'startCash': 41,
'street0Aggr': False,
'street0Bets': 0,
'street0Calls': 0,
'street0Raises': 0,
'street0VPI': False,
'street0_3BChance': False,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': False,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': False,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': False,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': 0,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 0,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'PLAYER6': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 1,
'raiseFirstInChance': False,
'raisedFirstIn': False,
'rake': 0,
'sawShowdown': False,
'seatNo': 6,
'sitout': False,
'startCards': 0,
'startCash': 2,
'street0Aggr': False,
'street0Bets': 0,
'street0Calls': 0,
'street0Raises': 0,
'street0VPI': False,
'street0_3BChance': False,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': False,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': False,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': False,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': 0,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 0,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'PLAYER7': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 0,
'raiseFirstInChance': False,
'raisedFirstIn': False,
'rake': 0,
'sawShowdown': False,
'seatNo': 7,
'sitout': False,
'startCards': 0,
'startCash': 213,
'street0Aggr': False,
'street0Bets': 0,
'street0Calls': 0,
'street0Raises': 0,
'street0VPI': False,
'street0_3BChance': False,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': False,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': False,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': False,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': 0,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 0,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0}}

View File

@ -1,91 +1,91 @@
Stage #1300000000: Seven Card Hi/Lo Normal $0.02/$0.04 - 2009-03-18 19:10:00 (ET) Stage #1300000000: Seven Card Hi/Lo Normal $0.02/$0.04 - 2009-03-18 19:10:00 (ET)
Seat 1 - PLAYER1 ($0.17 in chips) Seat 1 - PLAYER1 ($0.17 in chips)
Seat 2 - PLAYER2 ($0.36 in chips) Seat 2 - PLAYER2 ($0.36 in chips)
Seat 3 - PLAYER3 ($3.46 in chips) Seat 3 - PLAYER3 ($3.46 in chips)
Seat 5 - PLAYER4 ($1 in chips) Seat 5 - PLAYER4 ($1 in chips)
Seat 6 - PLAYER5 ($1.07 in chips) Seat 6 - PLAYER5 ($1.07 in chips)
Seat 7 - PLAYER6 ($2.31 in chips) Seat 7 - PLAYER6 ($2.31 in chips)
Seat 8 - PLAYER7 ($0.93 in chips) Seat 8 - PLAYER7 ($0.93 in chips)
Player1 - Ante $0.01 Player1 - Ante $0.01
PLAYER5 - Ante $0.01 PLAYER5 - Ante $0.01
PLAYER6 - Ante $0.01 PLAYER6 - Ante $0.01
PLAYER3 - Ante $0.01 PLAYER3 - Ante $0.01
PLAYER7 - Ante $0.01 PLAYER7 - Ante $0.01
PLAYER2 - Ante $0.01 PLAYER2 - Ante $0.01
PLAYER4 - Ante $0.01 PLAYER4 - Ante $0.01
*** 3rd STREET *** *** 3rd STREET ***
Player1 - Pocket [H H Js] Player1 - Pocket [H H Js]
PLAYER2 - Pocket [H H 7h] PLAYER2 - Pocket [H H 7h]
PLAYER3 - Pocket [H H 6s] PLAYER3 - Pocket [H H 6s]
PLAYER4 - Pocket [10c 5c 7s] PLAYER4 - Pocket [10c 5c 7s]
PLAYER5 - Pocket [H H Qh] PLAYER5 - Pocket [H H Qh]
PLAYER6 - Pocket [H H 9c] PLAYER6 - Pocket [H H 9c]
PLAYER7 - Pocket [H H 3s] PLAYER7 - Pocket [H H 3s]
PLAYER7 - Bring-In $0.01 PLAYER7 - Bring-In $0.01
Player1 - Calls $0.01 Player1 - Calls $0.01
PLAYER2 - Folds PLAYER2 - Folds
PLAYER3 - Calls $0.01 PLAYER3 - Calls $0.01
PLAYER4 - Folds PLAYER4 - Folds
PLAYER5 - Folds PLAYER5 - Folds
PLAYER6 - Calls $0.01 PLAYER6 - Calls $0.01
*** 4TH STREET *** *** 4TH STREET ***
Player1 - Pocket [H H Js 10d] Player1 - Pocket [H H Js 10d]
PLAYER3 - Pocket [H H 6s Ah] PLAYER3 - Pocket [H H 6s Ah]
PLAYER4 - Pocket [10c 5c 7s] PLAYER4 - Pocket [10c 5c 7s]
PLAYER6 - Pocket [H H 9c Ks] PLAYER6 - Pocket [H H 9c Ks]
PLAYER7 - Pocket [H H 3s Qc] PLAYER7 - Pocket [H H 3s Qc]
PLAYER3 - Checks PLAYER3 - Checks
PLAYER6 - Checks PLAYER6 - Checks
PLAYER7 - Checks PLAYER7 - Checks
Player1 - Checks Player1 - Checks
*** 5TH STREET *** *** 5TH STREET ***
Player1 - Pocket [H H Js 10d Kh] Player1 - Pocket [H H Js 10d Kh]
PLAYER3 - Pocket [H H 6s Ah 8c] PLAYER3 - Pocket [H H 6s Ah 8c]
PLAYER4 - Pocket [10c 5c 7s] PLAYER4 - Pocket [10c 5c 7s]
PLAYER6 - Pocket [H H 9c Ks 10s] PLAYER6 - Pocket [H H 9c Ks 10s]
PLAYER7 - Pocket [H H 3s Qc 6c] PLAYER7 - Pocket [H H 3s Qc 6c]
PLAYER3 - Bets $0.04 PLAYER3 - Bets $0.04
PLAYER6 - Calls $0.04 PLAYER6 - Calls $0.04
PLAYER7 - Calls $0.04 PLAYER7 - Calls $0.04
Player1 - Calls $0.04 Player1 - Calls $0.04
*** 6TH STREET *** *** 6TH STREET ***
Player1 - Pocket [H H Js 10d Kh 2c] Player1 - Pocket [H H Js 10d Kh 2c]
PLAYER3 - Pocket [H H 6s Ah 8c Jc] PLAYER3 - Pocket [H H 6s Ah 8c Jc]
PLAYER4 - Pocket [10c 5c 7s] PLAYER4 - Pocket [10c 5c 7s]
PLAYER6 - Pocket [H H 9c Ks 10s 8h] PLAYER6 - Pocket [H H 9c Ks 10s 8h]
PLAYER7 - Pocket [H H 3s Qc 6c Qs] PLAYER7 - Pocket [H H 3s Qc 6c Qs]
PLAYER7 - Checks PLAYER7 - Checks
Player1 - Checks Player1 - Checks
PLAYER3 - Bets $0.04 PLAYER3 - Bets $0.04
PLAYER6 - Calls $0.04 PLAYER6 - Calls $0.04
PLAYER7 - Calls $0.04 PLAYER7 - Calls $0.04
Player1 - Calls $0.04 Player1 - Calls $0.04
*** RIVER *** *** RIVER ***
Player1 - Pocket [H H Js 10d Kh 2c H] Player1 - Pocket [H H Js 10d Kh 2c H]
PLAYER3 - Pocket [H H 6s Ah 8c Jc H] PLAYER3 - Pocket [H H 6s Ah 8c Jc H]
PLAYER4 - Pocket [10c 5c 7s] PLAYER4 - Pocket [10c 5c 7s]
PLAYER6 - Pocket [H H 9c Ks 10s 8h H] PLAYER6 - Pocket [H H 9c Ks 10s 8h H]
PLAYER7 - Pocket [H H 3s Qc 6c Qs H] PLAYER7 - Pocket [H H 3s Qc 6c Qs H]
PLAYER7 - Checks PLAYER7 - Checks
Player1 - Checks Player1 - Checks
PLAYER3 - Checks PLAYER3 - Checks
PLAYER6 - Checks PLAYER6 - Checks
*** SHOW DOWN *** *** SHOW DOWN ***
PLAYER7 - Shows [5s 8d 3s Qc 6c Qs 9s] (One pair, queens) PLAYER7 - Shows [5s 8d 3s Qc 6c Qs 9s] (One pair, queens)
Player1 - Shows [Jh 3h Js 10d Kh 2c 2h] (Two Pair, jacks and twos) Player1 - Shows [Jh 3h Js 10d Kh 2c 2h] (Two Pair, jacks and twos)
PLAYER3 - Shows [3d 5d 6s Ah 8c Jc As] (One pair, aces) PLAYER3 - Shows [3d 5d 6s Ah 8c Jc As] (One pair, aces)
PLAYER6 - Shows [Kc 10h 9c Ks 10s 8h 2s] (Two Pair, kings and tens) PLAYER6 - Shows [Kc 10h 9c Ks 10s 8h 2s] (Two Pair, kings and tens)
PLAYER3 Collects $0.19 from main pot PLAYER3 Collects $0.19 from main pot
PLAYER6 Collects $0.20 from main pot PLAYER6 Collects $0.20 from main pot
*** SUMMARY *** *** SUMMARY ***
Total Pot($0.43) | Rake ($0.04) Total Pot($0.43) | Rake ($0.04)
Seat 1: Player1 HI:lost with Two Pair, jacks and twos [Jh 3h Js 10d Kh 2c 2h - B:Js,P:Jh,P:2h,B:2c,B:Kh] Seat 1: Player1 HI:lost with Two Pair, jacks and twos [Jh 3h Js 10d Kh 2c 2h - B:Js,P:Jh,P:2h,B:2c,B:Kh]
Seat 2: PLAYER2 Folded on the 3rd STREET Seat 2: PLAYER2 Folded on the 3rd STREET
Seat 3: PLAYER3 won Total ($0.19) HI:with One pair, aces [3d 5d 6s Ah 8c Jc As - P:As,B:Ah,B:Jc,B:8c,B:6s] LO:($0.19) [B:Ah,P:3d,P:5d,B:6s,B:8c] Seat 3: PLAYER3 won Total ($0.19) HI:with One pair, aces [3d 5d 6s Ah 8c Jc As - P:As,B:Ah,B:Jc,B:8c,B:6s] LO:($0.19) [B:Ah,P:3d,P:5d,B:6s,B:8c]
Seat 5: PLAYER4 Folded on the 3rd STREET Seat 5: PLAYER4 Folded on the 3rd STREET
Seat 6: PLAYER5 Folded on the 3rd STREET Seat 6: PLAYER5 Folded on the 3rd STREET
Seat 7: PLAYER6 won Total ($0.20) HI:($0.20) with Two Pair, kings and tens [Kc 10h 9c Ks 10s 8h 2s - B:Ks,P:Kc,B:10s,P:10h,B:9c] Seat 7: PLAYER6 won Total ($0.20) HI:($0.20) with Two Pair, kings and tens [Kc 10h 9c Ks 10s 8h 2s - B:Ks,P:Kc,B:10s,P:10h,B:9c]
Seat 8: PLAYER7 HI:lost with One pair, queens [5s 8d 3s Qc 6c Qs 9s - B:Qs,B:Qc,P:9s,P:8d,B:6c] Seat 8: PLAYER7 HI:lost with One pair, queens [5s 8d 3s Qc 6c Qs 9s - B:Qs,B:Qc,P:9s,P:8d,B:6c]

View File

@ -1,53 +1,53 @@
<description type="Holdem" stakes="No Limit ($0.25/$0.50)"/> <description type="Holdem" stakes="No Limit ($0.25/$0.50)"/>
<game id="15245216-1000" starttime="20081013150000" numholecards="2" gametype="2" realmoney="true" data="20081013|Niagara Falls (15245216)|15245216|15245216-1000|false"> <game id="15245216-1000" starttime="20081013150000" numholecards="2" gametype="2" realmoney="true" data="20081013|Niagara Falls (15245216)|15245216|15245216-1000|false">
<players dealer="8"> <players dealer="8">
<player seat="3" nickname="Player1" balance="$34.13" dealtin="true" /> <player seat="3" nickname="Player1" balance="$34.13" dealtin="true" />
<player seat="2" nickname="Player2" balance="$49.25" dealtin="true" /> <player seat="2" nickname="Player2" balance="$49.25" dealtin="true" />
<player seat="1" nickname="Player3" balance="$55.64" dealtin="true" /> <player seat="1" nickname="Player3" balance="$55.64" dealtin="true" />
<player seat="0" nickname="Player4" balance="$19.72" dealtin="true" /> <player seat="0" nickname="Player4" balance="$19.72" dealtin="true" />
<player seat="7" nickname="Player5" balance="$25.16" dealtin="true" /> <player seat="7" nickname="Player5" balance="$25.16" dealtin="true" />
<player seat="6" nickname="Player6" balance="$56.44" dealtin="false" /> <player seat="6" nickname="Player6" balance="$56.44" dealtin="false" />
<player seat="5" nickname="Player7" balance="$43.52" dealtin="true" /> <player seat="5" nickname="Player7" balance="$43.52" dealtin="true" />
<player seat="4" nickname="Player8" balance="$28.67" dealtin="true" /> <player seat="4" nickname="Player8" balance="$28.67" dealtin="true" />
<player seat="8" nickname="Player9" balance="$9.25" dealtin="true" /> <player seat="8" nickname="Player9" balance="$9.25" dealtin="true" />
</players> </players>
<round id="BLINDS" sequence="1"> <round id="BLINDS" sequence="1">
<event sequence="1" type="SMALL_BLIND" player="0" amount="0.25"/> <event sequence="1" type="SMALL_BLIND" player="0" amount="0.25"/>
<event sequence="2" type="BIG_BLIND" player="1" amount="0.50"/> <event sequence="2" type="BIG_BLIND" player="1" amount="0.50"/>
</round> </round>
<round id="PREFLOP" sequence="2"> <round id="PREFLOP" sequence="2">
<event sequence="3" type="FOLD" player="2"/> <event sequence="3" type="FOLD" player="2"/>
<event sequence="4" type="FOLD" player="3"/> <event sequence="4" type="FOLD" player="3"/>
<event sequence="5" type="RAISE" player="4" amount="1.00"/> <event sequence="5" type="RAISE" player="4" amount="1.00"/>
<event sequence="6" type="FOLD" player="5"/> <event sequence="6" type="FOLD" player="5"/>
<event sequence="7" type="CALL" player="7" amount="1.00"/> <event sequence="7" type="CALL" player="7" amount="1.00"/>
<event sequence="8" type="FOLD" player="8"/> <event sequence="8" type="FOLD" player="8"/>
<event sequence="9" type="FOLD" player="0"/> <event sequence="9" type="FOLD" player="0"/>
<event sequence="10" type="RAISE" player="1" amount="5.00"/> <event sequence="10" type="RAISE" player="1" amount="5.00"/>
<event sequence="11" type="CALL" player="4" amount="4.50"/> <event sequence="11" type="CALL" player="4" amount="4.50"/>
<event sequence="12" type="FOLD" player="7"/> <event sequence="12" type="FOLD" player="7"/>
<cards type="HOLE" cards="Ah,8s" player="2" hand="Ace High"/> <cards type="HOLE" cards="Ah,8s" player="2" hand="Ace High"/>
</round> </round>
<round id="POSTFLOP" sequence="3"> <round id="POSTFLOP" sequence="3">
<event sequence="13" type="BET" player="1" amount="7.00"/> <event sequence="13" type="BET" player="1" amount="7.00"/>
<event sequence="14" type="CALL" player="4" amount="7.00"/> <event sequence="14" type="CALL" player="4" amount="7.00"/>
<cards type="COMMUNITY" cards="5h,3c,Kd" hand="Ace High"/> <cards type="COMMUNITY" cards="5h,3c,Kd" hand="Ace High"/>
</round> </round>
<round id="POSTTURN" sequence="4"> <round id="POSTTURN" sequence="4">
<event sequence="15" type="BET" player="1" amount="18.00"/> <event sequence="15" type="BET" player="1" amount="18.00"/>
<event sequence="16" type="ALL_IN" player="4" amount="16.17"/> <event sequence="16" type="ALL_IN" player="4" amount="16.17"/>
<event sequence="17" type="SHOW" player="1"/> <event sequence="17" type="SHOW" player="1"/>
<event sequence="18" type="SHOW" player="4"/> <event sequence="18" type="SHOW" player="4"/>
<cards type="COMMUNITY" cards="5h,3c,Kd,3d" hand="Pair of Threes"/> <cards type="COMMUNITY" cards="5h,3c,Kd,3d" hand="Pair of Threes"/>
<cards type="SHOWN" cards="Ad,3s" player="1"/> <cards type="SHOWN" cards="Ad,3s" player="1"/>
<cards type="SHOWN" cards="Qd,Qs" player="4"/> <cards type="SHOWN" cards="Qd,Qs" player="4"/>
</round> </round>
<round id="POSTRIVER" sequence="5"> <round id="POSTRIVER" sequence="5">
<cards type="COMMUNITY" cards="5h,3c,Kd,3d,Ks" hand="Two Pair Kings and Threes"/> <cards type="COMMUNITY" cards="5h,3c,Kd,3d,Ks" hand="Two Pair Kings and Threes"/>
</round> </round>
<round id="END_OF_GAME" sequence="6"> <round id="END_OF_GAME" sequence="6">
<winner amount="55.67" uncalled="false" potnumber="1" player="1" hand="Full House - Threes over Kings" pottype="n"/> <winner amount="55.67" uncalled="false" potnumber="1" player="1" hand="Full House - Threes over Kings" pottype="n"/>
<winner amount="1.83" uncalled="true" potnumber="2" player="1" hand="Full House - Threes over Kings" pottype="n"/> <winner amount="1.83" uncalled="true" potnumber="2" player="1" hand="Full House - Threes over Kings" pottype="n"/>
</round> </round>
</game> </game>

View File

@ -277,8 +277,8 @@
'winnings': 5567, 'winnings': 5567,
'wonAtSD': 1.0, 'wonAtSD': 1.0,
'wonWhenSeenStreet1': 1.0, 'wonWhenSeenStreet1': 1.0,
'wonWhenSeenStreet2': 0.0, 'wonWhenSeenStreet2': 1.0,
'wonWhenSeenStreet3': 0.0, 'wonWhenSeenStreet3': 1.0,
'wonWhenSeenStreet4': 0.0}, 'wonWhenSeenStreet4': 0.0},
u'Player4': { 'card1': 0, u'Player4': { 'card1': 0,
'card2': 0, 'card2': 0,
@ -692,6 +692,7 @@
'raisedFirstIn': False, 'raisedFirstIn': False,
'rake': 0, 'rake': 0,
'sawShowdown': False, 'sawShowdown': False,
'seatNo': 8,
'sitout': False, 'sitout': False,
'startCards': 0, 'startCards': 0,
'startCash': 925, 'startCash': 925,

View File

@ -0,0 +1,416 @@
Everleaf Gaming Game #196321235
***** Hand history for game #196321235 *****
Blinds $0.05/$0.10 NL Hold'em - 2010/08/29 - 20:34:15
Table Cortland XIV
Seat 6 is the button
Total number of players: 6
Seat 1: zlodeu123 ( $ 12.40 USD )
Seat 2: EricBlade ( $ 5 USD )
Seat 3: gabitzatoade ( $ 5.45 USD )
Seat 5: N0pr3s3n7 ( $ 10.29 USD )
Seat 6: Coolcatcool ( $ 8.30 USD )
zlodeu123: posts small blind [$ 0.05 USD]
EricBlade: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to EricBlade [ 9h, Qd ]
gabitzatoade folds
N0pr3s3n7 raises [$ 0.35 USD]
Coolcatcool folds
zlodeu123 folds
EricBlade folds
N0pr3s3n7 does not show cards
N0pr3s3n7 wins $ 0.25 USD from main pot
Everleaf Gaming Game #196321319
***** Hand history for game #196321319 *****
Blinds $0.05/$0.10 NL Hold'em - 2010/08/29 - 20:34:38
Table Cortland XIV
Seat 1 is the button
Total number of players: 5
Seat 1: zlodeu123 ( $ 12.35 USD )
Seat 2: EricBlade ( $ 4.90 USD )
Seat 3: gabitzatoade ( $ 5.45 USD )
Seat 5: N0pr3s3n7 ( $ 10.44 USD )
Seat 6: Coolcatcool ( $ 8.30 USD )
EricBlade: posts small blind [$ 0.05 USD]
gabitzatoade: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to EricBlade [ Qd, 9d ]
N0pr3s3n7 folds
Coolcatcool folds
zlodeu123 folds
EricBlade raises [$ 0.25 USD]
gabitzatoade folds
EricBlade does not show cards
EricBlade wins $ 0.20 USD from main pot
Everleaf Gaming Game #196321394
***** Hand history for game #196321394 *****
Blinds $0.05/$0.10 NL Hold'em - 2010/08/29 - 20:34:57
Table Cortland XIV
Seat 2 is the button
Total number of players: 5
Seat 1: zlodeu123 ( $ 12.35 USD )
Seat 2: EricBlade ( $ 5 USD )
Seat 3: gabitzatoade ( $ 5.35 USD )
Seat 4: Miazza ( new player )
Seat 5: N0pr3s3n7 ( $ 10.44 USD )
Seat 6: Coolcatcool ( $ 8.30 USD )
gabitzatoade: posts small blind [$ 0.05 USD]
N0pr3s3n7: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to EricBlade [ 9c, Ac ]
Coolcatcool folds
zlodeu123 folds
EricBlade raises [$ 0.35 USD]
gabitzatoade calls [$ 0.30 USD]
N0pr3s3n7 folds
** Dealing Flop ** [ 4c, Kh, 6h ]
gabitzatoade checks
EricBlade: bets [$ 0.40 USD]
gabitzatoade calls [$ 0.40 USD]
** Dealing Turn ** [ Qh ]
gabitzatoade checks
Miazza has joined the table
EricBlade checks
** Dealing River ** [ Qd ]
gabitzatoade checks
EricBlade checks
EricBlade shows [ 9c, Ac ] a pair of queens
gabitzatoade shows [ 4s, 4d ] a full house, fours full of queens
gabitzatoade wins $ 1.52 USD from main pot with a full house, fours full of queens [ Qh, Qd, 4s, 4d, 4c ]
Everleaf Gaming Game #196321538
***** Hand history for game #196321538 *****
Blinds $0.05/$0.10 NL Hold'em - 2010/08/29 - 20:35:34
Table Cortland XIV
Seat 3 is the button
Total number of players: 6
Seat 1: zlodeu123 ( $ 12.35 USD )
Seat 2: EricBlade ( $ 4.25 USD )
Seat 3: gabitzatoade ( $ 6.12 USD )
Seat 4: Miazza ( $ 5 USD )
Seat 5: N0pr3s3n7 ( $ 10.34 USD )
Seat 6: Coolcatcool ( $ 8.30 USD )
N0pr3s3n7: posts small blind [$ 0.05 USD]
Coolcatcool: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to EricBlade [ Kc, Jd ]
zlodeu123 raises [$ 0.35 USD]
EricBlade calls [$ 0.35 USD]
gabitzatoade folds
N0pr3s3n7 folds
Coolcatcool folds
** Dealing Flop ** [ 9s, 3c, Jc ]
zlodeu123: bets [$ 0.60 USD]
EricBlade raises [$ 1.80 USD]
zlodeu123 folds
EricBlade does not show cards
EricBlade wins $ 1.95 USD from main pot
Everleaf Gaming Game #196321707
***** Hand history for game #196321707 *****
Blinds $0.05/$0.10 NL Hold'em - 2010/08/29 - 20:36:15
Table Cortland XIV
Seat 5 is the button
Total number of players: 6
Seat 1: zlodeu123 ( $ 11.40 USD )
Seat 2: EricBlade ( $ 5.25 USD )
Seat 3: gabitzatoade ( $ 6.12 USD )
Seat 4: Miazza ( $ 5 USD )
Seat 5: N0pr3s3n7 ( $ 10.29 USD )
Seat 6: Coolcatcool ( $ 8.20 USD )
Coolcatcool: posts small blind [$ 0.05 USD]
zlodeu123: posts big blind [$ 0.10 USD]
Miazza sits out
** Dealing down cards **
Dealt to EricBlade [ 6d, 3d ]
EricBlade folds
gabitzatoade calls [$ 0.10 USD]
N0pr3s3n7 raises [$ 0.30 USD]
Coolcatcool folds
zlodeu123 folds
gabitzatoade calls [$ 0.20 USD]
** Dealing Flop ** [ 8d, 4d, Td ]
gabitzatoade checks
N0pr3s3n7: bets [$ 0.50 USD]
gabitzatoade folds
N0pr3s3n7 does not show cards
N0pr3s3n7 wins $ 0.72 USD from main pot
Everleaf Gaming Game #196321850
***** Hand history for game #196321850 *****
Blinds $0.05/$0.10 NL Hold'em - 2010/08/29 - 20:36:52
Table Cortland XIV
Seat 6 is the button
Total number of players: 6
Seat 1: zlodeu123 ( $ 11.30 USD )
Seat 2: EricBlade ( $ 5.25 USD )
Seat 3: gabitzatoade ( $ 5.82 USD )
Seat 4: Miazza ( $ 5 USD )
Seat 5: N0pr3s3n7 ( $ 10.71 USD )
Seat 6: Coolcatcool ( $ 8.15 USD )
zlodeu123: posts small blind [$ 0.05 USD]
EricBlade: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to EricBlade [ Qh, Qd ]
gabitzatoade folds
N0pr3s3n7 folds
Coolcatcool folds
zlodeu123 folds
EricBlade does not show cards
EricBlade wins $ 0.10 USD from main pot
Everleaf Gaming Game #196321947
***** Hand history for game #196321947 *****
Blinds $0.05/$0.10 NL Hold'em - 2010/08/29 - 20:37:15
Table Cortland XIV
Seat 1 is the button
Total number of players: 6
Seat 1: zlodeu123 ( $ 11.25 USD )
Seat 2: EricBlade ( $ 5.30 USD )
Seat 3: gabitzatoade ( $ 5.82 USD )
Seat 4: Miazza ( $ 5 USD )
Seat 5: N0pr3s3n7 ( $ 10.71 USD )
Seat 6: Coolcatcool ( $ 8.15 USD )
EricBlade: posts small blind [$ 0.05 USD]
gabitzatoade: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to EricBlade [ Ts, Ks ]
N0pr3s3n7 folds
Coolcatcool folds
zlodeu123 folds
EricBlade raises [$ 0.25 USD]
gabitzatoade folds
EricBlade does not show cards
EricBlade wins $ 0.20 USD from main pot
Everleaf Gaming Game #196322013
***** Hand history for game #196322013 *****
Blinds $0.05/$0.10 NL Hold'em - 2010/08/29 - 20:37:32
Table Cortland XIV
Seat 2 is the button
Total number of players: 6
Seat 1: zlodeu123 ( $ 11.25 USD )
Seat 2: EricBlade ( $ 5.40 USD )
Seat 3: gabitzatoade ( $ 5.72 USD )
Seat 4: Miazza ( $ 5 USD )
Seat 5: N0pr3s3n7 ( $ 10.71 USD )
Seat 6: Coolcatcool ( $ 8.15 USD )
gabitzatoade: posts small blind [$ 0.05 USD]
Miazza: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to EricBlade [ 2c, 4s ]
N0pr3s3n7 folds
Coolcatcool folds
zlodeu123 raises [$ 0.35 USD]
EricBlade folds
gabitzatoade calls [$ 0.30 USD]
Miazza folds
** Dealing Flop ** [ Ad, 6d, 6s ]
gabitzatoade checks
zlodeu123: bets [$ 0.60 USD]
gabitzatoade calls [$ 0.60 USD]
** Dealing Turn ** [ Jc ]
gabitzatoade checks
zlodeu123 checks
** Dealing River ** [ Th ]
gabitzatoade checks
zlodeu123 checks
zlodeu123 shows [ Ah, 8d ] two pairs, aces and sixes
gabitzatoade shows [ Ac, 9c ] two pairs, aces and sixes
gabitzatoade wins $ 0.95 USD from main pot with two pairs, aces and sixes [ Ac, Ad, Jc, 6d, 6s ]
zlodeu123 wins $ 0.95 USD from main pot with two pairs, aces and sixes [ Ah, Ad, Jc, 6d, 6s ]
Everleaf Gaming Game #196322188
***** Hand history for game #196322188 *****
Blinds $0.05/$0.10 NL Hold'em - 2010/08/29 - 20:38:16
Table Cortland XIV
Seat 3 is the button
Total number of players: 6
Seat 1: zlodeu123 ( $ 11.25 USD )
Seat 2: EricBlade ( $ 5.40 USD )
Seat 3: gabitzatoade ( $ 5.72 USD )
Seat 4: Miazza ( $ 4.90 USD )
Seat 5: N0pr3s3n7 ( $ 10.71 USD )
Seat 6: Coolcatcool ( $ 8.15 USD )
Miazza: posts small blind [$ 0.05 USD]
N0pr3s3n7: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to EricBlade [ 7d, Kd ]
Coolcatcool folds
zlodeu123 folds
EricBlade raises [$ 0.35 USD]
gabitzatoade folds
Miazza folds
N0pr3s3n7 folds
EricBlade does not show cards
EricBlade wins $ 0.25 USD from main pot
Everleaf Gaming Game #196322268
***** Hand history for game #196322268 *****
Blinds $0.05/$0.10 NL Hold'em - 2010/08/29 - 20:38:34
Table Cortland XIV
Seat 4 is the button
Total number of players: 6
Seat 1: zlodeu123 ( $ 11.25 USD )
Seat 2: EricBlade ( $ 5.55 USD )
Seat 3: gabitzatoade ( $ 5.72 USD )
Seat 4: Miazza ( $ 4.85 USD )
Seat 5: N0pr3s3n7 ( $ 10.61 USD )
Seat 6: Coolcatcool ( $ 8.15 USD )
N0pr3s3n7: posts small blind [$ 0.05 USD]
Coolcatcool: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to EricBlade [ 6d, Kc ]
zlodeu123 folds
EricBlade folds
gabitzatoade folds
Miazza raises [$ 0.35 USD]
N0pr3s3n7 folds
Coolcatcool raises [$ 0.50 USD]
Miazza folds
Coolcatcool does not show cards
Coolcatcool wins $ 0.75 USD from main pot
Everleaf Gaming Game #196322353
***** Hand history for game #196322353 *****
Blinds $0.05/$0.10 NL Hold'em - 2010/08/29 - 20:38:57
Table Cortland XIV
Seat 5 is the button
Total number of players: 6
Seat 1: zlodeu123 ( $ 11.25 USD )
Seat 2: EricBlade ( $ 5.55 USD )
Seat 3: gabitzatoade ( $ 5.72 USD )
Seat 4: Miazza ( $ 4.50 USD )
Seat 5: N0pr3s3n7 ( $ 10.56 USD )
Seat 6: Coolcatcool ( $ 8.55 USD )
Coolcatcool: posts small blind [$ 0.05 USD]
zlodeu123: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to EricBlade [ 3h, 9s ]
EricBlade folds
gabitzatoade folds
Miazza folds
N0pr3s3n7 folds
Coolcatcool folds
zlodeu123 does not show cards
zlodeu123 wins $ 0.10 USD from main pot
Everleaf Gaming Game #196322422
***** Hand history for game #196322422 *****
Blinds $0.05/$0.10 NL Hold'em - 2010/08/29 - 20:39:15
Table Cortland XIV
Seat 6 is the button
Total number of players: 6
Seat 1: zlodeu123 ( $ 11.30 USD )
Seat 2: EricBlade ( $ 5.55 USD )
Seat 3: gabitzatoade ( $ 5.72 USD )
Seat 4: Miazza ( $ 4.50 USD )
Seat 5: N0pr3s3n7 ( $ 10.56 USD )
Seat 6: Coolcatcool ( $ 8.50 USD )
zlodeu123: posts small blind [$ 0.05 USD]
EricBlade: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to EricBlade [ Kd, 4h ]
gabitzatoade folds
Miazza folds
N0pr3s3n7 folds
Coolcatcool folds
zlodeu123 folds
EricBlade does not show cards
EricBlade wins $ 0.10 USD from main pot
Everleaf Gaming Game #196322487
***** Hand history for game #196322487 *****
Blinds $0.05/$0.10 NL Hold'em - 2010/08/29 - 20:39:32
Table Cortland XIV
Seat 1 is the button
Total number of players: 6
Seat 1: zlodeu123 ( $ 11.25 USD )
Seat 2: EricBlade ( $ 5.60 USD )
Seat 3: gabitzatoade ( $ 5.72 USD )
Seat 4: Miazza ( $ 4.50 USD )
Seat 5: N0pr3s3n7 ( $ 10.56 USD )
Seat 6: Coolcatcool ( $ 8.50 USD )
EricBlade: posts small blind [$ 0.05 USD]
gabitzatoade: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to EricBlade [ 9h, Th ]
Miazza folds
N0pr3s3n7 folds
Coolcatcool folds
zlodeu123 folds
EricBlade raises [$ 0.25 USD]
gabitzatoade calls [$ 0.20 USD]
** Dealing Flop ** [ 3d, 5d, 6c ]
EricBlade checks
gabitzatoade: bets [$ 0.40 USD]
EricBlade folds
gabitzatoade does not show cards
gabitzatoade wins $ 0.57 USD from main pot
Everleaf Gaming Game #196322581
***** Hand history for game #196322581 *****
Blinds $0.05/$0.10 NL Hold'em - 2010/08/29 - 20:39:58
Table Cortland XIV
Seat 2 is the button
Total number of players: 5
Seat 1: zlodeu123 ( $ 11.25 USD )
Seat 2: EricBlade ( $ 5.30 USD )
Seat 3: gabitzatoade ( $ 5.99 USD )
Seat 4: Miazza ( $ 4.50 USD )
Seat 5: N0pr3s3n7 ( $ 10.56 USD )
Seat 6: SAVCOMP ( new player )
gabitzatoade: posts small blind [$ 0.05 USD]
Miazza: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to EricBlade [ As, 4d ]
N0pr3s3n7 folds
zlodeu123 raises [$ 0.35 USD]
EricBlade folds
gabitzatoade calls [$ 0.30 USD]
SAVCOMP has joined the table
Miazza folds
** Dealing Flop ** [ 3h, 7h, Tc ]
gabitzatoade checks
zlodeu123 checks
** Dealing Turn ** [ Ks ]
gabitzatoade: bets [$ 0.30 USD]
zlodeu123 raises [$ 0.80 USD]
gabitzatoade calls [$ 0.50 USD]
** Dealing River ** [ Ts ]
gabitzatoade: bets [$ 2 USD]
zlodeu123 calls [$ 2 USD]
gabitzatoade shows [ 8s, 7s ] two pairs, tens and sevens
zlodeu123 shows [ Kd, Ad ] two pairs, kings and tens
zlodeu123 wins $ 6.08 USD from main pot with two pairs, kings and tens [ Ad, Kd, Ks, Tc, Ts ]

View File

@ -0,0 +1,588 @@
Everleaf Gaming Game #149107406
***** Hand history for game #149107406 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:35:19
Table Old Market I
Seat 5 is the button
Total number of players: 2
Seat 5: Villain ( $ 10 USD )
Seat 10: Hero ( $ 10 USD )
Villain has disconnected and has been given a further 20 seconds to react
Villain has disconnected and has been given a further 20 seconds to react
Villain: posts small blind [$ 0.05 USD]
Hero: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ Qc, Qh, 7s, Jd ]
Villain calls [$ 0.05 USD]
Hero raises [$ 0.20 USD]
Villain calls [$ 0.20 USD]
** Dealing Flop ** [ Tc, Kc, 3s ]
Hero: bets [$ 0.60 USD]
Villain calls [$ 0.60 USD]
** Dealing Turn ** [ 6d ]
Hero checks
Villain: bets [$ 1.80 USD]
Hero folds
Villain does not show cards
Villain wins high ($ 1.71 USD) from main pot
Everleaf Gaming Game #149107627
***** Hand history for game #149107627 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:36:09
Table Old Market I
Seat 10 is the button
Total number of players: 2
Seat 5: Villain ( $ 10.81 USD )
Seat 10: Hero ( $ 9.10 USD )
Hero: posts small blind [$ 0.05 USD]
Villain: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ Jd, 9h, 3h, 3c ]
Hero calls [$ 0.05 USD]
Villain checks
** Dealing Flop ** [ 8c, 8h, Qs ]
Villain checks
Hero checks
** Dealing Turn ** [ 7h ]
Villain: bets [$ 0.10 USD]
Hero folds
Villain does not show cards
Villain wins high ($ 0.19 USD) from main pot
Everleaf Gaming Game #149107795
***** Hand history for game #149107795 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:36:48
Table Old Market I
Seat 5 is the button
Total number of players: 2
Seat 5: Villain ( $ 10.90 USD )
Seat 10: Hero ( $ 9 USD )
Villain: posts small blind [$ 0.05 USD]
Hero: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ Qc, As, 4s, Qh ]
Villain calls [$ 0.05 USD]
Hero raises [$ 0.20 USD]
Villain calls [$ 0.20 USD]
** Dealing Flop ** [ 8d, 6h, 3c ]
Hero: bets [$ 0.60 USD]
Villain calls [$ 0.60 USD]
** Dealing Turn ** [ Qd ]
Hero: bets [$ 1.80 USD]
Villain calls [$ 1.80 USD]
** Dealing River ** [ 7h ]
Hero checks
Villain checks
Hero shows [ Qc, As, 4s, Qh ] three of a kind, queens
Villain does not show cards
Hero wins high ($ 2.57 USD) from main pot with three of a kind, queens [ Qc, Qh, Qd, 8d, 7h ]
Hero wins low ($2.56) from main pot with 7, 6, 4, 3, A [ As, 7h, 6h, 4s, 3c ]
Everleaf Gaming Game #149108010
***** Hand history for game #149108010 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:37:35
Table Old Market I
Seat 10 is the button
Total number of players: 2
Seat 5: Villain ( $ 8.20 USD )
Seat 10: Hero ( $ 11.43 USD )
Hero: posts small blind [$ 0.05 USD]
Villain: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ 4s, Ts, 3h, 5s ]
Hero folds
Villain does not show cards
Villain wins high ($ 0.10 USD) from main pot
Everleaf Gaming Game #149108038
***** Hand history for game #149108038 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:37:43
Table Old Market I
Seat 5 is the button
Total number of players: 2
Seat 5: Villain ( $ 8.25 USD )
Seat 10: Hero ( $ 11.38 USD )
Villain: posts small blind [$ 0.05 USD]
Hero: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ 9d, Qc, 9s, Tc ]
Villain raises [$ 0.25 USD]
Hero calls [$ 0.20 USD]
** Dealing Flop ** [ 3d, 4d, 2h ]
Hero checks
Villain: bets [$ 0.60 USD]
Hero folds
Villain does not show cards
Villain wins high ($ 0.57 USD) from main pot
Everleaf Gaming Game #149108121
***** Hand history for game #149108121 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:38:02
Table Old Market I
Seat 10 is the button
Total number of players: 2
Seat 5: Villain ( $ 8.52 USD )
Seat 10: Hero ( $ 11.08 USD )
Hero: posts small blind [$ 0.05 USD]
Villain: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ 4d, Ks, 7h, As ]
Hero raises [$ 0.25 USD]
Villain calls [$ 0.20 USD]
** Dealing Flop ** [ 7d, Qc, 6s ]
Villain checks
Hero checks
** Dealing Turn ** [ Kh ]
Villain: bets [$ 0.60 USD]
Hero calls [$ 0.60 USD]
** Dealing River ** [ Qh ]
Villain: bets [$ 1.80 USD]
Hero folds
Villain does not show cards
Villain wins high ($ 1.71 USD) from main pot
Everleaf Gaming Game #149108259
***** Hand history for game #149108259 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:38:32
Table Old Market I
Seat 5 is the button
Total number of players: 2
Seat 5: Villain ( $ 9.33 USD )
Seat 10: Hero ( $ 10.18 USD )
Villain: posts small blind [$ 0.05 USD]
Hero: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ 7d, 2h, Ad, Jh ]
Villain calls [$ 0.05 USD]
Hero raises [$ 0.20 USD]
Villain has disconnected and has been given a further 20 seconds to react
Villain has disconnected and has been given a further 20 seconds to react
Villain folds
Hero does not show cards
Hero wins $ 0.20 USD from main pot
Everleaf Gaming Game #149108411
***** Hand history for game #149108411 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:39:07
Table Old Market I
Seat 10 is the button
Total number of players: 2
Seat 5: Villain ( $ 9.23 USD )
Seat 10: Hero ( $ 10.28 USD )
Hero: posts small blind [$ 0.05 USD]
Villain: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ Ks, Kd, 7c, 7s ]
Hero raises [$ 0.25 USD]
Villain calls [$ 0.20 USD]
** Dealing Flop ** [ 7d, Ac, 9h ]
Villain checks
Hero checks
** Dealing Turn ** [ 2d ]
Villain: bets [$ 0.60 USD]
Hero calls [$ 0.60 USD]
** Dealing River ** [ 9s ]
Villain checks
Hero: bets [$ 1.80 USD]
Villain folds
Hero does not show cards
Hero wins $ 1.71 USD from main pot
Everleaf Gaming Game #149108717
***** Hand history for game #149108717 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:40:22
Table Old Market I
Seat 5 is the button
Total number of players: 2
Seat 5: Villain ( $ 8.33 USD )
Seat 10: Hero ( $ 11.09 USD )
Villain: posts small blind [$ 0.05 USD]
Hero: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ 5s, 3s, Js, 9d ]
Villain calls [$ 0.05 USD]
Hero checks
** Dealing Flop ** [ 6c, 4s, 4d ]
Hero checks
Villain checks
** Dealing Turn ** [ 7c ]
Hero: bets [$ 0.20 USD]
Villain calls [$ 0.20 USD]
** Dealing River ** [ Qd ]
Hero: bets [$ 0.60 USD]
Villain folds
Hero does not show cards
Hero wins $ 0.29 USD from main pot
Hero wins $ 0.28 USD from main pot
Everleaf Gaming Game #149108874
***** Hand history for game #149108874 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:40:58
Table Old Market I
Seat 10 is the button
Total number of players: 2
Seat 5: Villain ( $ 8.03 USD )
Seat 10: Hero ( $ 11.36 USD )
Hero: posts small blind [$ 0.05 USD]
Villain: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ Qd, Jh, 2h, 5s ]
Hero calls [$ 0.05 USD]
Villain checks
** Dealing Flop ** [ 7d, 2c, 9c ]
Villain: bets [$ 0.20 USD]
Hero folds
Villain does not show cards
Villain wins $ 0.19 USD from main pot
Everleaf Gaming Game #149109021
***** Hand history for game #149109021 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:41:31
Table Old Market I
Seat 5 is the button
Total number of players: 2
Seat 5: Villain ( $ 8.12 USD )
Seat 10: Hero ( $ 11.26 USD )
Villain: posts small blind [$ 0.05 USD]
Hero: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ 4c, 6h, 8s, 5c ]
Villain calls [$ 0.05 USD]
Hero checks
** Dealing Flop ** [ 3d, 8h, Qd ]
Hero checks
Villain: bets [$ 0.20 USD]
Hero folds
Villain does not show cards
Villain wins $ 0.19 USD from main pot
Everleaf Gaming Game #149109123
***** Hand history for game #149109123 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:41:54
Table Old Market I
Seat 10 is the button
Total number of players: 2
Seat 5: Villain ( $ 8.21 USD )
Seat 10: Hero ( $ 11.16 USD )
Hero: posts small blind [$ 0.05 USD]
Villain: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ 7s, 3d, Tc, 5s ]
Hero folds
Villain does not show cards
Villain wins $ 0.10 USD from main pot
Everleaf Gaming Game #149109165
***** Hand history for game #149109165 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:42:04
Table Old Market I
Seat 5 is the button
Total number of players: 2
Seat 5: Villain ( $ 8.26 USD )
Seat 10: Hero ( $ 11.11 USD )
Villain: posts small blind [$ 0.05 USD]
Hero: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ Kh, 3c, 6d, 6s ]
Villain calls [$ 0.05 USD]
Hero checks
** Dealing Flop ** [ 2d, 6c, Th ]
Hero checks
Villain checks
** Dealing Turn ** [ 9d ]
Hero checks
Villain: bets [$ 0.20 USD]
Hero folds
Villain does not show cards
Villain wins $ 0.19 USD from main pot
Everleaf Gaming Game #149109398
***** Hand history for game #149109398 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:42:55
Table Old Market I
Seat 10 is the button
Total number of players: 2
Seat 5: Villain ( $ 8.35 USD )
Seat 10: Hero ( $ 11.01 USD )
Hero: posts small blind [$ 0.05 USD]
Villain: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ 5c, Qd, 6d, 7d ]
Hero calls [$ 0.05 USD]
Villain raises [$ 0.20 USD]
Hero folds
Villain does not show cards
Villain wins $ 0.20 USD from main pot
Everleaf Gaming Game #149109482
***** Hand history for game #149109482 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:43:15
Table Old Market I
Seat 5 is the button
Total number of players: 2
Seat 5: Villain ( $ 8.45 USD )
Seat 10: Hero ( $ 10.91 USD )
Villain: posts small blind [$ 0.05 USD]
Hero: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ 7s, 8d, 5c, Qc ]
Villain calls [$ 0.05 USD]
Hero checks
** Dealing Flop ** [ 5s, Js, 7h ]
Hero: bets [$ 0.20 USD]
Villain calls [$ 0.20 USD]
** Dealing Turn ** [ Ac ]
Hero checks
Villain checks
** Dealing River ** [ 8h ]
Hero checks
Villain checks
Hero shows [ 7s, 8d, 5c, Qc ] two pairs, eights and sevens
Villain does not show cards
Hero wins high ($ 0.57 USD) from main pot with two pairs, eights and sevens [ Ac, 8d, 8h, 7s, 7h ]
Everleaf Gaming Game #149109706
***** Hand history for game #149109706 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:44:04
Table Old Market I
Seat 10 is the button
Total number of players: 2
Seat 5: Villain ( $ 8.15 USD )
Seat 10: Hero ( $ 11.18 USD )
Hero: posts small blind [$ 0.05 USD]
Villain: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ 5s, 8c, 7s, Td ]
Hero calls [$ 0.05 USD]
Villain raises [$ 0.20 USD]
Hero folds
Villain does not show cards
Villain wins high ($ 0.20 USD) from main pot
Everleaf Gaming Game #149109783
***** Hand history for game #149109783 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:44:23
Table Old Market I
Seat 5 is the button
Total number of players: 2
Seat 5: Villain ( $ 8.25 USD )
Seat 10: Hero ( $ 11.08 USD )
Villain: posts small blind [$ 0.05 USD]
Hero: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ 5d, 4c, 8c, Th ]
Villain calls [$ 0.05 USD]
Hero checks
** Dealing Flop ** [ 7h, As, 7s ]
Hero checks
Villain checks
** Dealing Turn ** [ Jc ]
Hero checks
Villain checks
** Dealing River ** [ 3h ]
Hero checks
Villain checks
Hero shows [ 5d, 4c, 8c, Th ] a pair of sevens
Villain shows [ 2h, Kd, 8d, Ts ] a pair of sevens
Villain wins high ($ 0.10 USD) from main pot with a pair of sevens [ As, Kd, Ts, 7h, 7s ] with kicker [ Kh ]
Hero wins low ($0.09) from main pot with 7, 5, 4, 3, A [ As, 7h, 5d, 4c, 3h ]
Everleaf Gaming Game #149109887
***** Hand history for game #149109887 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:44:48
Table Old Market I
Seat 10 is the button
Total number of players: 2
Seat 5: Villain ( $ 8.25 USD )
Seat 10: Hero ( $ 11.07 USD )
Hero: posts small blind [$ 0.05 USD]
Villain: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ Js, Jc, 3d, 7d ]
Hero raises [$ 0.25 USD]
Villain calls [$ 0.20 USD]
** Dealing Flop ** [ 9s, 5d, Qh ]
Villain checks
Hero checks
** Dealing Turn ** [ 6d ]
Villain: bets [$ 0.60 USD]
Hero folds
Villain does not show cards
Villain wins high ($ 0.57 USD) from main pot
Everleaf Gaming Game #149110044
***** Hand history for game #149110044 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:45:23
Table Old Market I
Seat 5 is the button
Total number of players: 2
Seat 5: Villain ( $ 8.52 USD )
Seat 10: Hero ( $ 10.77 USD )
Villain: posts small blind [$ 0.05 USD]
Hero: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ Ah, 2d, 6d, Qh ]
Villain calls [$ 0.05 USD]
Hero raises [$ 0.20 USD]
Villain calls [$ 0.20 USD]
** Dealing Flop ** [ 5c, Td, 9h ]
Hero checks
Villain checks
** Dealing Turn ** [ Ks ]
Hero checks
Villain checks
** Dealing River ** [ 8s ]
Hero checks
Villain: bets [$ 0.30 USD]
Hero folds
Villain does not show cards
Villain wins high ($ 0.57 USD) from main pot
Everleaf Gaming Game #149110335
***** Hand history for game #149110335 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:46:33
Table Old Market I
Seat 10 is the button
Total number of players: 2
Seat 5: Villain ( $ 8.79 USD )
Seat 10: Hero ( $ 10.47 USD )
Hero: posts small blind [$ 0.05 USD]
Villain: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ Th, 5d, Qd, 7s ]
Hero calls [$ 0.05 USD]
Villain checks
** Dealing Flop ** [ 8s, 9c, 3s ]
Villain checks
Hero checks
** Dealing Turn ** [ Tc ]
Villain checks
Hero checks
** Dealing River ** [ Qc ]
Villain checks
Hero checks
Villain shows [ 8d, Kc, 6c, 4s ] a flush, king high
Hero does not show cards
Villain wins high ($ 0.19 USD) from main pot with a flush, king high [ Kc, Qc, Tc, 9c, 6c ]
Everleaf Gaming Game #149110588
***** Hand history for game #149110588 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:47:30
Table Old Market I
Seat 5 is the button
Total number of players: 2
Seat 5: Villain ( $ 8.88 USD )
Seat 10: Hero ( $ 10.37 USD )
Villain: posts small blind [$ 0.05 USD]
Hero: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ 2h, 2s, Qs, Ah ]
Villain calls [$ 0.05 USD]
Hero raises [$ 0.20 USD]
Villain calls [$ 0.20 USD]
** Dealing Flop ** [ Td, Qh, 8h ]
Hero: bets [$ 0.60 USD]
Villain calls [$ 0.60 USD]
** Dealing Turn ** [ 9s ]
Hero checks
Villain: bets [$ 1.80 USD]
Hero calls [$ 1.80 USD]
** Dealing River ** [ 8s ]
Hero checks
Villain checks
Villain shows [ Js, 5h, Tc, 7d ] a straight, queen high
Hero does not show cards
Villain wins high ($ 5.13 USD) from main pot with a straight, queen high [ Qh, Js, Tc, 9s, 8h ]
Everleaf Gaming Game #149110838
***** Hand history for game #149110838 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:48:31
Table Old Market I
Seat 10 is the button
Total number of players: 2
Seat 5: Villain ( $ 11.31 USD )
Seat 10: Hero ( $ 7.67 USD )
Hero: posts small blind [$ 0.05 USD]
Villain: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ Ts, 3d, 8s, 9h ]
Hero calls [$ 0.05 USD]
Villain raises [$ 0.20 USD]
Hero folds
Villain has disconnected and has been given a further 20 seconds to react
Villain does not show cards
Villain wins high ($ 0.20 USD) from main pot
Everleaf Gaming Game #149111070
***** Hand history for game #149111070 *****
Blinds $0.05/$0.10 PL Omaha Hi/Lo - 2010/03/02 - 19:49:28
Table Old Market I
Seat 5 is the button
Total number of players: 2
Seat 5: Villain ( $ 11.41 USD )
Seat 10: Hero ( $ 7.57 USD )
Villain: posts small blind [$ 0.05 USD]
Hero: posts big blind [$ 0.10 USD]
** Dealing down cards **
Dealt to Hero [ 9c, 4d, 8h, Th ]
Villain calls [$ 0.05 USD]
Hero checks
** Dealing Flop ** [ Ad, Qs, 4s ]
Hero checks
Villain checks
** Dealing Turn ** [ Td ]
Hero checks
Villain checks
** Dealing River ** [ 6d ]
Hero checks
Villain: bets [$ 0.10 USD]
Hero folds
Villain does not show cards
Villain wins high ($ 0.10 USD) from main pot
Villain wins low ($0.09) from main pot

View File

@ -0,0 +1,564 @@
{ u'Hero': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 'S',
'raiseFirstInChance': False,
'raisedFirstIn': False,
'rake': 0,
'sawShowdown': False,
'seatNo': 6,
'sitout': False,
'startCards': 0,
'startCash': 645,
'street0Aggr': False,
'street0Bets': 0,
'street0Calls': 0,
'street0Raises': 0,
'street0VPI': False,
'street0_3BChance': False,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': False,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': False,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': False,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': -5,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 0,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player1': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 'B',
'raiseFirstInChance': False,
'raisedFirstIn': False,
'rake': 5,
'sawShowdown': True,
'seatNo': 1,
'sitout': False,
'startCards': 0,
'startCash': 200,
'street0Aggr': True,
'street0Bets': 0,
'street0Calls': 0,
'street0Raises': 0,
'street0VPI': True,
'street0_3BChance': False,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': True,
'street1Bets': 1,
'street1CBChance': True,
'street1CBDone': True,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': True,
'street2Aggr': True,
'street2Bets': 1,
'street2CBChance': True,
'street2CBDone': True,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': True,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': False,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': 50,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 100,
'wonAtSD': 1.0,
'wonWhenSeenStreet1': 1.0,
'wonWhenSeenStreet2': 1.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player2': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 2,
'raiseFirstInChance': False,
'raisedFirstIn': False,
'rake': 0,
'sawShowdown': False,
'seatNo': 2,
'sitout': False,
'startCards': 0,
'startCash': 400,
'street0Aggr': False,
'street0Bets': 0,
'street0Calls': 0,
'street0Raises': 0,
'street0VPI': False,
'street0_3BChance': False,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': False,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': False,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': False,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': 0,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 0,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player3': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': True,
'otherRaisedStreet2': True,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 0,
'raiseFirstInChance': True,
'raisedFirstIn': False,
'rake': 0,
'sawShowdown': True,
'seatNo': 3,
'sitout': False,
'startCards': 0,
'startCash': 50,
'street0Aggr': False,
'street0Bets': 0,
'street0Calls': 2,
'street0Raises': 0,
'street0VPI': True,
'street0_3BChance': True,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 1,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': True,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 1,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': True,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': False,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': -50,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 0,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player4': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 2,
'raiseFirstInChance': False,
'raisedFirstIn': False,
'rake': 0,
'sawShowdown': False,
'seatNo': 4,
'sitout': False,
'startCards': 0,
'startCash': 200,
'street0Aggr': False,
'street0Bets': 0,
'street0Calls': 0,
'street0Raises': 0,
'street0VPI': False,
'street0_3BChance': False,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': False,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': False,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': False,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': 0,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 0,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player5': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 2,
'raiseFirstInChance': False,
'raisedFirstIn': False,
'rake': 0,
'sawShowdown': False,
'seatNo': 5,
'sitout': False,
'startCards': 0,
'startCash': 200,
'street0Aggr': False,
'street0Bets': 0,
'street0Calls': 0,
'street0Raises': 0,
'street0VPI': False,
'street0_3BChance': False,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': False,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': False,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': False,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': 0,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 0,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0}}

View File

@ -465,8 +465,8 @@
'winnings': 94, 'winnings': 94,
'wonAtSD': 1.0, 'wonAtSD': 1.0,
'wonWhenSeenStreet1': 1.0, 'wonWhenSeenStreet1': 1.0,
'wonWhenSeenStreet2': 0.0, 'wonWhenSeenStreet2': 1.0,
'wonWhenSeenStreet3': 0.0, 'wonWhenSeenStreet3': 1.0,
'wonWhenSeenStreet4': 0.0}, 'wonWhenSeenStreet4': 0.0},
u'rockinalex': { 'card1': 49, u'rockinalex': { 'card1': 49,
'card2': 31, 'card2': 31,

View File

@ -0,0 +1,153 @@
***** History for hand R5-81962116-232 *****
Start hand: Mon Sep 13 00:21:02 GMT+0100 2010
Table: Suez [81962116] (LIMIT FIVE_CARD_DRAW $0.05/$0.10, Real money)
User: tchazx
Button: seat 3
Players in round: 4
Seat 8: DamonV2 ($0.07)
Seat 10: tchazx ($1)
Seat 1: x Diabolo666 ($11.23)
Seat 3: velabianca ($0.51)
DamonV2 posts small blind ($0.02)
tchazx posts big blind ($0.05)
---
Dealing pocket cards
Dealing to tchazx: [Tc, 9h, 7c, Ah, Jh]
x Diabolo666 raises $0.10 to $0.10
velabianca folds
DamonV2 folds
tchazx calls $0.05
---
tchazx changed 2 cards
New hand for tchazx: [8h, 9h, 6s, Ah, Jh]
x Diabolo666 changed 3 cards
tchazx checks
x Diabolo666 checks
---
Summary:
Main pot: $0.22 won by x Diabolo666 ($0.21)
Rake taken: $0.01
Seat 8: DamonV2 ($0.05), net: -$0.02
Seat 10: tchazx ($0.90), net: -$0.10, [8h, 9h, 6s, Ah, Jh] (HIGH_CARD ACE)
Seat 1: x Diabolo666 ($11.34), net: +$0.11, [2c, Ac, Td, As, Qc] (PAIR ACE)
Seat 3: velabianca ($0.51)
***** End of hand R5-81962116-232 *****
***** History for hand R5-81962116-233 *****
Start hand: Mon Sep 13 00:21:42 GMT+0100 2010
Table: Suez [81962116] (LIMIT FIVE_CARD_DRAW $0.05/$0.10, Real money)
User: tchazx
Button: seat 8
Players in round: 5
Seat 10: tchazx ($0.90)
Seat 1: x Diabolo666 ($11.34)
Seat 3: velabianca ($0.51)
Seat 4: grommek ($9.40)
Seat 8: DamonV2 ($0.05)
tchazx posts small blind ($0.02)
x Diabolo666 posts big blind ($0.05)
grommek posts big blind ($0.05)
grommek posts dead blind ($0.02)
---
Dealing pocket cards
Dealing to tchazx: [Jd, 5s, 8h, 4h, 7d]
velabianca calls $0.05
grommek checks
DamonV2 calls $0.05 [all in]
tchazx calls $0.03
x Diabolo666 checks
---
tchazx changed 1 cards
New hand for tchazx: [Ah, 5s, 8h, 4h, 7d]
x Diabolo666 changed 4 cards
velabianca changed 2 cards
grommek changed 3 cards
DamonV2 changed 2 cards
tchazx checks
x Diabolo666 checks
velabianca bets $0.10
grommek folds
tchazx folds
x Diabolo666 folds
---
---
Summary:
Main pot: $0.27 won by velabianca ($0.26)
Rake taken: $0.01
Seat 10: tchazx ($0.85), net: -$0.05
Seat 1: x Diabolo666 ($11.29), net: -$0.05
Seat 3: velabianca ($0.72), net: +$0.21, [As, 9s, 6s, 6c, 9h] (TWO_PAIR NINE, SIX)
Seat 4: grommek ($9.33), net: -$0.07
Seat 8: DamonV2 ($0), net: -$0.05, [Jh, 2c, Kh, Td, 6h] (HIGH_CARD KING)
***** End of hand R5-81962116-233 *****
***** History for hand R5-81962116-234 *****
Start hand: Mon Sep 13 00:22:36 GMT+0100 2010
Table: Suez [81962116] (LIMIT FIVE_CARD_DRAW $0.05/$0.10, Real money)
User: tchazx
Button: seat 10
Players in round: 4
Seat 1: x Diabolo666 ($11.29)
Seat 3: velabianca ($0.72)
Seat 4: grommek ($9.33)
Seat 10: tchazx ($0.85)
x Diabolo666 posts small blind ($0.02)
velabianca posts big blind ($0.05)
---
Dealing pocket cards
Dealing to tchazx: [Kh, 9d, As, 4s, 7c]
grommek calls $0.05
tchazx folds
x Diabolo666 folds
velabianca checks
velabianca changed 3 cards
grommek changed 3 cards
velabianca checks
grommek bets $0.10
velabianca folds
---
Summary:
Main pot: $0.12 won by grommek ($0.12)
Rake taken: $0
Seat 1: x Diabolo666 ($11.27), net: -$0.02
Seat 3: velabianca ($0.67), net: -$0.05
Seat 4: grommek ($9.40), net: +$0.07
Seat 10: tchazx ($0.85)
***** End of hand R5-81962116-234 *****
***** History for hand R5-81962116-235 *****
Start hand: Mon Sep 13 00:23:04 GMT+0100 2010
Table: Suez [81962116] (LIMIT FIVE_CARD_DRAW $0.05/$0.10, Real money)
User: tchazx
Button: seat 1
Players in round: 4
Seat 3: velabianca ($0.67)
Seat 4: grommek ($9.40)
Seat 10: tchazx ($0.85)
Seat 1: x Diabolo666 ($11.27)
velabianca posts small blind ($0.02)
grommek posts big blind ($0.05)
---
Dealing pocket cards
Dealing to tchazx: [8d, Td, 2s, 3d, Qd]
tchazx calls $0.05
x Diabolo666 raises $0.10 to $0.10
velabianca calls $0.08
grommek calls $0.05
tchazx calls $0.05
---
velabianca changed 2 cards
grommek changed 2 cards
tchazx changed 1 cards
New hand for tchazx: [8d, Td, 8h, 3d, Qd]
x Diabolo666 changed 3 cards
velabianca checks
grommek checks
tchazx checks
x Diabolo666 checks
---
Summary:
Main pot: $0.40 won by velabianca ($0.38)
Rake taken: $0.02
Seat 3: velabianca ($0.95), net: +$0.28
Seat 4: grommek ($9.30), net: -$0.10
Seat 10: tchazx ($0.75), net: -$0.10
Seat 1: x Diabolo666 ($11.17), net: -$0.10, [6d, Qc, 4c, Th, Qs] (PAIR QUEEN)
***** End of hand R5-81962116-235 *****

View File

@ -0,0 +1,470 @@
{ u'player1': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 0,
'raiseFirstInChance': False,
'raisedFirstIn': False,
'rake': 0,
'sawShowdown': False,
'seatNo': 5,
'sitout': False,
'startCards': 0,
'startCash': 1315,
'street0Aggr': False,
'street0Bets': 0,
'street0Calls': 2,
'street0Raises': 0,
'street0VPI': True,
'street0_3BChance': True,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': False,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': False,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': False,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': -105,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 0,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'player2': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 1,
'raiseFirstInChance': False,
'raisedFirstIn': False,
'rake': 0,
'sawShowdown': False,
'seatNo': 3,
'sitout': False,
'startCards': 0,
'startCash': 3395,
'street0Aggr': False,
'street0Bets': 0,
'street0Calls': 0,
'street0Raises': 0,
'street0VPI': False,
'street0_3BChance': True,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': False,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': False,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': False,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': 0,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 0,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'player3': { 'card1': 25,
'card2': 51,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 2,
'raiseFirstInChance': True,
'raisedFirstIn': True,
'rake': 215,
'sawShowdown': True,
'seatNo': 1,
'sitout': False,
'startCards': 155,
'startCash': 2610,
'street0Aggr': True,
'street0Bets': 1,
'street0Calls': 1,
'street0Raises': 0,
'street0VPI': True,
'street0_3BChance': False,
'street0_3BDone': False,
'street0_4BChance': True,
'street0_4BDone': True,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': False,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': False,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': False,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': 120,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 325,
'wonAtSD': 1.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'player4': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 'S',
'raiseFirstInChance': False,
'raisedFirstIn': False,
'rake': 0,
'sawShowdown': False,
'seatNo': 7,
'sitout': False,
'startCards': 0,
'startCash': 3445,
'street0Aggr': False,
'street0Bets': 0,
'street0Calls': 0,
'street0Raises': 0,
'street0VPI': False,
'street0_3BChance': True,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': False,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': False,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': False,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': -25,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 0,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'player5': { 'card1': 24,
'card2': 11,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 'B',
'raiseFirstInChance': False,
'raisedFirstIn': False,
'rake': 0,
'sawShowdown': True,
'seatNo': 9,
'sitout': False,
'startCards': 141,
'startCash': 0,
'street0Aggr': True,
'street0Bets': 0,
'street0Calls': 0,
'street0Raises': 0,
'street0VPI': True,
'street0_3BChance': True,
'street0_3BDone': True,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': False,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': False,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': False,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': -205,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 0,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0}}

View File

@ -0,0 +1,444 @@
***** History for hand R5-81867677-656 *****
Start hand: Mon Sep 13 00:26:26 GMT+0100 2010
Table: Tilburg [81867677] (LIMIT OMAHA_HI $0.05/$0.10, Real money)
User: tchazx
Button: seat 8
Players in round: 3
Seat 3: nickgerm ($3.74)
Seat 4: tchazx ($5)
Seat 8: XYXY26XYXY ($1.79)
nickgerm posts small blind ($0.02)
tchazx posts big blind ($0.05)
---
Dealing pocket cards
Dealing to tchazx: [Ks, 4s, 6s, Th]
XYXY26XYXY calls $0.05
nickgerm calls $0.03
tchazx checks
--- Dealing flop [5h, 7d, 2s]
nickgerm checks
tchazx checks
XYXY26XYXY checks
--- Dealing turn [Qs]
nickgerm checks
tchazx checks
XYXY26XYXY checks
--- Dealing river [4d]
nickgerm bets $0.10
tchazx folds
XYXY26XYXY folds
---
Summary:
Main pot: $0.15 won by nickgerm ($0.15)
Rake taken: $0
Seat 3: nickgerm ($3.84), net: +$0.10
Seat 4: tchazx ($4.95), net: -$0.05
Seat 8: XYXY26XYXY ($1.74), net: -$0.05
***** End of hand R5-81867677-656 *****
***** History for hand R5-81867677-657 *****
Start hand: Mon Sep 13 00:27:13 GMT+0100 2010
Table: Tilburg [81867677] (LIMIT OMAHA_HI $0.05/$0.10, Real money)
User: tchazx
Button: seat 3
Players in round: 3
Seat 4: tchazx ($4.95)
Seat 8: XYXY26XYXY ($1.74)
Seat 3: nickgerm ($3.84)
tchazx posts small blind ($0.02)
XYXY26XYXY posts big blind ($0.05)
---
Dealing pocket cards
Dealing to tchazx: [Jd, Td, 8h, Tc]
nickgerm calls $0.05
tchazx calls $0.03
XYXY26XYXY checks
--- Dealing flop [4h, 7c, 2c]
tchazx checks
XYXY26XYXY checks
nickgerm checks
--- Dealing turn [Kc]
tchazx checks
XYXY26XYXY checks
nickgerm bets $0.10
tchazx folds
XYXY26XYXY calls $0.10
--- Dealing river [3d]
XYXY26XYXY checks
nickgerm bets $0.10
XYXY26XYXY calls $0.10
---
Summary:
Main pot: $0.55 won by nickgerm ($0.27), XYXY26XYXY ($0.26)
Rake taken: $0.02
Seat 4: tchazx ($4.90), net: -$0.05
Seat 8: XYXY26XYXY ($1.75), net: +$0.01, [7h, Qs, 9c, Kd] (TWO_PAIR KING, SEVEN)
Seat 3: nickgerm ($3.86), net: +$0.02, [7d, 6s, Ks, Jc] (TWO_PAIR KING, SEVEN)
***** End of hand R5-81867677-657 *****
***** History for hand R5-81867677-658 *****
Start hand: Mon Sep 13 00:28:06 GMT+0100 2010
Table: Tilburg [81867677] (LIMIT OMAHA_HI $0.05/$0.10, Real money)
User: tchazx
Button: seat 4
Players in round: 5
Seat 8: XYXY26XYXY ($1.75)
Seat 10: Mandala14 ($3)
Seat 1: ANOKATO ($2.33)
Seat 3: nickgerm ($3.86)
Seat 4: tchazx ($4.90)
XYXY26XYXY posts small blind ($0.02)
Mandala14 posts big blind ($0.05)
ANOKATO posts big blind ($0.05)
---
Dealing pocket cards
Dealing to tchazx: [Ad, Js, Jc, 9h]
ANOKATO checks
nickgerm raises $0.10 to $0.10
tchazx calls $0.10
XYXY26XYXY calls $0.08
Mandala14 calls $0.05
ANOKATO calls $0.05
--- Dealing flop [6h, 2s, 5c]
XYXY26XYXY checks
Mandala14 checks
ANOKATO bets $0.05
nickgerm raises $0.10 to $0.10
tchazx calls $0.10
XYXY26XYXY folds
Mandala14 calls $0.10
ANOKATO raises $0.10 to $0.15
nickgerm calls $0.05
tchazx calls $0.05
Mandala14 calls $0.05
--- Dealing turn [Kh]
Mandala14 checks
ANOKATO bets $0.10
nickgerm calls $0.10
tchazx calls $0.10
Mandala14 calls $0.10
--- Dealing river [Ks]
Mandala14 bets $0.10
ANOKATO calls $0.10
nickgerm folds
tchazx calls $0.10
---
Summary:
Main pot: $1.80 won by Mandala14 ($1.71)
Rake taken: $0.09
Seat 8: XYXY26XYXY ($1.65), net: -$0.10
Seat 10: Mandala14 ($4.26), net: +$1.26, [As, Ah, 5s, Qs] (TWO_PAIR ACE, KING)
Seat 1: ANOKATO ($1.88), net: -$0.45
Seat 3: nickgerm ($3.51), net: -$0.35
Seat 4: tchazx ($4.45), net: -$0.45
***** End of hand R5-81867677-658 *****
***** History for hand R5-81867677-659 *****
Start hand: Mon Sep 13 00:29:21 GMT+0100 2010
Table: Tilburg [81867677] (LIMIT OMAHA_HI $0.05/$0.10, Real money)
User: tchazx
Button: seat 8
Players in round: 5
Seat 10: Mandala14 ($4.26)
Seat 1: ANOKATO ($1.88)
Seat 3: nickgerm ($3.51)
Seat 4: tchazx ($4.45)
Seat 8: XYXY26XYXY ($1.65)
Mandala14 posts small blind ($0.02)
ANOKATO posts big blind ($0.05)
---
Dealing pocket cards
Dealing to tchazx: [5h, Tc, 9c, 3h]
nickgerm raises $0.10 to $0.10
tchazx calls $0.10
XYXY26XYXY calls $0.10
Mandala14 calls $0.08
ANOKATO calls $0.05
--- Dealing flop [8s, 4d, 6d]
Mandala14 checks
ANOKATO checks
nickgerm bets $0.05
tchazx calls $0.05
XYXY26XYXY calls $0.05
Mandala14 calls $0.05
ANOKATO calls $0.05
--- Dealing turn [9s]
Mandala14 checks
ANOKATO bets $0.10
nickgerm raises $0.20 to $0.20
tchazx folds
XYXY26XYXY calls $0.20
Mandala14 calls $0.20
ANOKATO raises $0.20 to $0.30
nickgerm calls $0.10
XYXY26XYXY calls $0.10
Mandala14 calls $0.10
--- Dealing river [4c]
Mandala14 checks
ANOKATO bets $0.10
nickgerm folds
XYXY26XYXY folds
Mandala14 folds
---
Summary:
Main pot: $1.95 won by ANOKATO ($1.86)
Rake taken: $0.09
Seat 10: Mandala14 ($3.81), net: -$0.45
Seat 1: ANOKATO ($3.29), net: +$1.41
Seat 3: nickgerm ($3.06), net: -$0.45
Seat 4: tchazx ($4.30), net: -$0.15
Seat 8: XYXY26XYXY ($1.20), net: -$0.45
***** End of hand R5-81867677-659 *****
***** History for hand R5-81867677-660 *****
Start hand: Mon Sep 13 00:30:43 GMT+0100 2010
Table: Tilburg [81867677] (LIMIT OMAHA_HI $0.05/$0.10, Real money)
User: tchazx
Button: seat 10
Players in round: 5
Seat 1: ANOKATO ($3.29)
Seat 3: nickgerm ($3.06)
Seat 4: tchazx ($4.30)
Seat 8: XYXY26XYXY ($1.20)
Seat 10: Mandala14 ($3.81)
ANOKATO posts small blind ($0.02)
nickgerm posts big blind ($0.05)
---
Dealing pocket cards
Dealing to tchazx: [Qh, 4d, Ts, 9d]
tchazx calls $0.05
XYXY26XYXY calls $0.05
Mandala14 calls $0.05
ANOKATO calls $0.03
nickgerm raises $0.05 to $0.10
tchazx calls $0.05
XYXY26XYXY calls $0.05
Mandala14 calls $0.05
ANOKATO calls $0.05
--- Dealing flop [6d, 3c, Qc]
ANOKATO checks
nickgerm bets $0.05
tchazx calls $0.05
XYXY26XYXY calls $0.05
Mandala14 calls $0.05
ANOKATO calls $0.05
--- Dealing turn [7h]
ANOKATO checks
nickgerm checks
tchazx checks
XYXY26XYXY checks
Mandala14 checks
--- Dealing river [Jh]
ANOKATO bets $0.10
nickgerm folds
tchazx calls $0.10
XYXY26XYXY folds
Mandala14 folds
---
Summary:
Main pot: $0.95 won by ANOKATO ($0.91)
Rake taken: $0.04
Seat 1: ANOKATO ($3.95), net: +$0.66, [7c, Qd, Ks, 5d] (TWO_PAIR QUEEN, SEVEN)
Seat 3: nickgerm ($2.91), net: -$0.15
Seat 4: tchazx ($4.05), net: -$0.25
Seat 8: XYXY26XYXY ($1.05), net: -$0.15
Seat 10: Mandala14 ($3.66), net: -$0.15
***** End of hand R5-81867677-660 *****
***** History for hand R5-81867677-661 *****
Start hand: Mon Sep 13 00:31:54 GMT+0100 2010
Table: Tilburg [81867677] (LIMIT OMAHA_HI $0.05/$0.10, Real money)
User: tchazx
Button: seat 1
Players in round: 5
Seat 3: nickgerm ($2.91)
Seat 4: tchazx ($4.05)
Seat 8: XYXY26XYXY ($1.05)
Seat 10: Mandala14 ($3.66)
Seat 1: ANOKATO ($3.95)
nickgerm posts small blind ($0.02)
tchazx posts big blind ($0.05)
---
Dealing pocket cards
Dealing to tchazx: [5d, 9h, 6h, 4h]
XYXY26XYXY calls $0.05
Mandala14 calls $0.05
ANOKATO calls $0.05
nickgerm calls $0.03
tchazx checks
--- Dealing flop [2d, 4d, Jh]
nickgerm bets $0.05
tchazx folds
XYXY26XYXY calls $0.05
Mandala14 folds
ANOKATO calls $0.05
--- Dealing turn [As]
nickgerm bets $0.10
XYXY26XYXY calls $0.10
ANOKATO raises $0.20 to $0.20
nickgerm calls $0.10
XYXY26XYXY calls $0.10
--- Dealing river [Jc]
nickgerm bets $0.10
XYXY26XYXY calls $0.10
ANOKATO raises $0.20 to $0.20
nickgerm raises $0.20 to $0.30
XYXY26XYXY folds
ANOKATO calls $0.10
---
Summary:
Main pot: $1.70 won by nickgerm ($1.62)
Rake taken: $0.08
Seat 3: nickgerm ($3.93), net: +$1.02, [9c, 4s, Jd, 6c] (FULL_HOUSE JACK, FOUR)
Seat 4: tchazx ($4), net: -$0.05
Seat 8: XYXY26XYXY ($0.65), net: -$0.40
Seat 10: Mandala14 ($3.61), net: -$0.05
Seat 1: ANOKATO ($3.35), net: -$0.60
***** End of hand R5-81867677-661 *****
***** History for hand R5-81867677-662 *****
Start hand: Mon Sep 13 00:33:20 GMT+0100 2010
Table: Tilburg [81867677] (LIMIT OMAHA_HI $0.05/$0.10, Real money)
User: tchazx
Button: seat 3
Players in round: 5
Seat 4: tchazx ($4)
Seat 8: XYXY26XYXY ($0.65)
Seat 10: Mandala14 ($3.61)
Seat 1: ANOKATO ($3.35)
Seat 3: nickgerm ($3.93)
tchazx posts small blind ($0.02)
XYXY26XYXY posts big blind ($0.05)
---
Dealing pocket cards
Dealing to tchazx: [5s, 6c, Kc, 3s]
Mandala14 calls $0.05
ANOKATO calls $0.05
nickgerm raises $0.10 to $0.10
tchazx folds
XYXY26XYXY calls $0.05
Mandala14 calls $0.05
ANOKATO calls $0.05
--- Dealing flop [3h, 2d, 2s]
XYXY26XYXY checks
Mandala14 checks
ANOKATO checks
nickgerm bets $0.05
XYXY26XYXY calls $0.05
Mandala14 folds
ANOKATO raises $0.10 to $0.10
nickgerm calls $0.05
XYXY26XYXY folds
--- Dealing turn [4d]
ANOKATO checks
nickgerm bets $0.10
ANOKATO raises $0.20 to $0.20
nickgerm calls $0.10
--- Dealing river [Ts]
ANOKATO checks
nickgerm checks
---
Summary:
Main pot: $1.07 won by ANOKATO ($1.02)
Rake taken: $0.05
Seat 4: tchazx ($3.98), net: -$0.02
Seat 8: XYXY26XYXY ($0.50), net: -$0.15
Seat 10: Mandala14 ($3.51), net: -$0.10
Seat 1: ANOKATO ($3.97), net: +$0.62, [Js, 5c, 9c, 2h] (THREE_OF_A_KIND TWO)
Seat 3: nickgerm ($3.53), net: -$0.40
***** End of hand R5-81867677-662 *****
***** History for hand R5-81867677-663 *****
Start hand: Mon Sep 13 00:34:34 GMT+0100 2010
Table: Tilburg [81867677] (LIMIT OMAHA_HI $0.05/$0.10, Real money)
User: tchazx
Button: seat 4
Players in round: 5
Seat 8: XYXY26XYXY ($0.50)
Seat 10: Mandala14 ($3.51)
Seat 1: ANOKATO ($3.97)
Seat 3: nickgerm ($3.53)
Seat 4: tchazx ($3.98)
XYXY26XYXY posts small blind ($0.02)
Mandala14 posts big blind ($0.05)
---
Dealing pocket cards
Dealing to tchazx: [Ac, 9h, 6h, Jc]
ANOKATO calls $0.05
nickgerm calls $0.05
tchazx calls $0.05
XYXY26XYXY calls $0.03
Mandala14 checks
--- Dealing flop [7s, 4c, 8s]
XYXY26XYXY checks
Mandala14 checks
ANOKATO bets $0.05
nickgerm calls $0.05
tchazx calls $0.05
XYXY26XYXY calls $0.05
Mandala14 calls $0.05
--- Dealing turn [2d]
XYXY26XYXY checks
Mandala14 checks
ANOKATO bets $0.10
nickgerm raises $0.20 to $0.20
tchazx calls $0.20
XYXY26XYXY calls $0.20
Mandala14 calls $0.20
ANOKATO calls $0.10
--- Dealing river [4h]
XYXY26XYXY bets $0.10
Mandala14 folds
ANOKATO calls $0.10
nickgerm raises $0.20 to $0.20
tchazx folds
XYXY26XYXY calls $0.10 [all in]
ANOKATO folds
---
Summary:
Main pot: $2 won by XYXY26XYXY ($1.90)
Rake taken: $0.10
Seat 8: XYXY26XYXY ($1.90), net: +$1.40, [8d, 5c, 4d, 3c] (FULL_HOUSE FOUR, EIGHT)
Seat 10: Mandala14 ($3.21), net: -$0.30
Seat 1: ANOKATO ($3.57), net: -$0.40
Seat 3: nickgerm ($3.03), net: -$0.50, [6s, Th, 3d, 5d] (STRAIGHT EIGHT)
Seat 4: tchazx ($3.68), net: -$0.30
***** End of hand R5-81867677-663 *****
***** History for hand R5-81867677-664 *****
Start hand: Mon Sep 13 00:36:21 GMT+0100 2010
Table: Tilburg [81867677] (LIMIT OMAHA_HI $0.05/$0.10, Real money)
User: tchazx
Button: seat 8
Players in round: 5
Seat 10: Mandala14 ($3.21)
Seat 1: ANOKATO ($3.57)
Seat 3: nickgerm ($3.03)
Seat 4: tchazx ($3.68)
Seat 8: XYXY26XYXY ($1.90)
Mandala14 posts small blind ($0.02)
ANOKATO posts big blind ($0.05)
---
Dealing pocket cards
Dealing to tchazx: [7d, Kh, 4s, Jh]
nickgerm calls $0.05
tchazx calls $0.05
XYXY26XYXY folds
Mandala14 calls $0.03
ANOKATO checks
--- Dealing flop [4h, Js, Ac]
Mandala14 checks
ANOKATO folds
nickgerm bets $0.05
tchazx calls $0.05
Mandala14 calls $0.05
--- Dealing turn [8c]
Mandala14 checks
nickgerm checks
tchazx checks
--- Dealing river [3d]
Mandala14 checks
nickgerm checks
tchazx checks
---
Summary:
Main pot: $0.35 won by tchazx ($0.34)
Rake taken: $0.01
Seat 10: Mandala14 ($3.11), net: -$0.10, [7h, 4d, Qh, 6d] (PAIR FOUR)
Seat 1: ANOKATO ($3.52), net: -$0.05
Seat 3: nickgerm ($2.93), net: -$0.10, [7s, Qd, 6s, Ah] (PAIR ACE)
Seat 4: tchazx ($3.92), net: +$0.24, [7d, Kh, 4s, Jh] (TWO_PAIR JACK, FOUR)
Seat 8: XYXY26XYXY ($1.90)
***** End of hand R5-81867677-664 *****

View File

@ -1,41 +1,41 @@
***** History for hand R5-70000684-006 ***** ***** History for hand R5-70000684-006 *****
Start hand: Wed Aug 11 03:21:00 GMT+0100 2010 Start hand: Wed Aug 11 03:21:00 GMT+0100 2010
Table: Kassel [73910684] (NO_LIMIT TEXAS_HOLDEM 0.05/0.10, Real money) Table: Kassel [73910684] (NO_LIMIT TEXAS_HOLDEM 0.05/0.10, Real money)
User: Player3 User: Player3
Button: seat 8 Button: seat 8
Players in round: 5 Players in round: 5
Seat 9: Player1 (4.35) Seat 9: Player1 (4.35)
Seat 3: Player0 (10.90) Seat 3: Player0 (10.90)
Seat 5: Player2 (12.88) Seat 5: Player2 (12.88)
Seat 6: Player3 (14.18) Seat 6: Player3 (14.18)
Seat 8: Player4 (9) Seat 8: Player4 (9)
Player1 posts small blind (0.05) Player1 posts small blind (0.05)
Player0 posts big blind (0.10) Player0 posts big blind (0.10)
--- ---
Dealing pocket cards Dealing pocket cards
Dealing to Player3: [6s, 7h] Dealing to Player3: [6s, 7h]
Player2 folds Player2 folds
Player3 folds Player3 folds
Player4 raises 0.30 to 0.30 Player4 raises 0.30 to 0.30
Player1 calls 0.25 Player1 calls 0.25
Player0 folds Player0 folds
--- Dealing flop [8c, Ts, 4d] --- Dealing flop [8c, Ts, 4d]
Player1 checks Player1 checks
Player4 checks Player4 checks
--- Dealing turn [Ac] --- Dealing turn [Ac]
Player1 bets 0.10 Player1 bets 0.10
Player4 calls 0.10 Player4 calls 0.10
--- Dealing river [5d] --- Dealing river [5d]
Player1 bets 0.10 Player1 bets 0.10
Player4 folds Player4 folds
--- ---
Summary: Summary:
Main pot: 0.90 won by Player1 (0.86) Main pot: 0.90 won by Player1 (0.86)
Rake taken: $0.04 Rake taken: $0.04
Seat 9: Player1 (4.81), net: +0.46 Seat 9: Player1 (4.81), net: +0.46
Seat 3: Player0 (10.80), net: -0.10 Seat 3: Player0 (10.80), net: -0.10
Seat 5: Player2 (12.88) Seat 5: Player2 (12.88)
Seat 6: Player3 (14.18) Seat 6: Player3 (14.18)
Seat 8: Player4 (8.60), net: -0.40 Seat 8: Player4 (8.60), net: -0.40
***** End of hand R5-73910684-276 ***** ***** End of hand R5-73910684-276 *****

View File

@ -0,0 +1,27 @@
***** History for hand R5-79836934-72 *****
Start hand: Sat Sep 4 05:34:19 GMT+0100 2010
Table: Bnei Brak [79836934] (NO_LIMIT TEXAS_HOLDEM $0.05/$0.10, Real money)
User: tchazx
Button: seat 10
Players in round: 2
Seat 1: feradf ($6.86)
Seat 10: tchazx ($15.44)
tchazx posts big blind ($0.10)
tchazx posts dead blind ($0.05)
feradf posts big blind ($0.10)
---
Dealing pocket cards
Dealing to tchazx: [Qh, 4h]
tchazx raises $0.20 to $0.30
feradf calls $0.20
--- Dealing flop [6c, Qs, 7h]
feradf checks
tchazx bets $0.45
feradf folds
---
Summary:
Main pot: $0.65 won by tchazx ($0.62)
Rake taken: $0.03
Seat 1: feradf ($6.56), net: -$0.30
Seat 10: tchazx ($15.71), net: +$0.27
***** End of hand R5-79836934-72 *****

View File

@ -0,0 +1,270 @@
***** History for hand R5-82086688-607 *****
Start hand: Mon Sep 13 22:31:30 GMT+0100 2010
Table: Milwaukee [82086688] (LIMIT SEVEN_CARD_STUD $0.10/$0.20, ante: $0.02, Real money)
User: tchazx
Players in round: 5
Seat 1: the bAAr ($6.53)
Seat 2: tchazx ($2)
Seat 6: kueto ($6.30)
Seat 8: E6y Ko3y ($2.70)
Seat 10: telozver123 ($6.49)
the bAAr posts ante $0.02
kueto posts ante $0.02
E6y Ko3y posts ante $0.02
telozver123 posts ante $0.02
tchazx posts ante $0.02
---
Dealing pocket cards
Dealing to the bAAr: [-, -, Kh]
Dealing to tchazx: [Jh, 9d, Ac]
Dealing to kueto: [-, -, 4h]
Dealing to E6y Ko3y: [-, -, Ad]
Dealing to telozver123: [-, -, 6h]
kueto small bring in $0.05
E6y Ko3y calls $0.05
telozver123 calls $0.05
the bAAr calls $0.05
tchazx calls $0.05
---
Dealing 4th street
Dealing to the bAAr: [3h]
Dealing to tchazx: [7h]
Dealing to kueto: [3d]
Dealing to E6y Ko3y: [Qs]
Dealing to telozver123: [Ts]
E6y Ko3y bets $0.10
telozver123 calls $0.10
the bAAr calls $0.10
tchazx calls $0.10
kueto folds
---
Dealing 5th street
Dealing to the bAAr: [9s]
Dealing to tchazx: [Js]
Dealing to E6y Ko3y: [6c]
Dealing to telozver123: [Kd]
E6y Ko3y checks
telozver123 checks
the bAAr bets $0.20
tchazx calls $0.20
E6y Ko3y calls $0.20
telozver123 folds
---
Dealing 6th street
Dealing to the bAAr: [8s]
Dealing to tchazx: [5c]
Dealing to E6y Ko3y: [5d]
E6y Ko3y checks
the bAAr bets $0.20
tchazx calls $0.20
E6y Ko3y calls $0.20
---
Dealing river
Dealing to tchazx: [9h]
E6y Ko3y checks
the bAAr checks
tchazx bets $0.20
E6y Ko3y folds
the bAAr calls $0.20
---
Summary:
Main pot: $2.35 won by tchazx ($2.24)
Rake taken: $0.11
Seat 1: the bAAr ($5.76), net: -$0.77
Seat 2: tchazx ($3.47), net: +$1.47, [Jh, 9d, Ac, 7h, Js, 5c, 9h] (TWO_PAIR JACK, NINE)
Seat 6: kueto ($6.23), net: -$0.07
Seat 8: E6y Ko3y ($2.13), net: -$0.57
Seat 10: telozver123 ($6.32), net: -$0.17
***** End of hand R5-82086688-607 *****
***** History for hand R5-82086688-608 *****
Start hand: Mon Sep 13 22:32:47 GMT+0100 2010
Table: Milwaukee [82086688] (LIMIT SEVEN_CARD_STUD $0.10/$0.20, ante: $0.02, Real money)
User: tchazx
Players in round: 5
Seat 1: the bAAr ($5.76)
Seat 2: tchazx ($3.47)
Seat 6: kueto ($6.23)
Seat 8: E6y Ko3y ($2.13)
Seat 10: telozver123 ($6.32)
the bAAr posts ante $0.02
tchazx posts ante $0.02
kueto posts ante $0.02
E6y Ko3y posts ante $0.02
telozver123 posts ante $0.02
---
Dealing pocket cards
Dealing to the bAAr: [-, -, 4s]
Dealing to tchazx: [8h, Ks, Qd]
Dealing to kueto: [-, -, 5h]
Dealing to E6y Ko3y: [-, -, 2h]
Dealing to telozver123: [-, -, 3c]
E6y Ko3y small bring in $0.05
telozver123 folds
the bAAr calls $0.05
tchazx calls $0.05
kueto folds
---
Dealing 4th street
Dealing to the bAAr: [Ad]
Dealing to tchazx: [8d]
Dealing to E6y Ko3y: [Qh]
the bAAr bets $0.10
tchazx calls $0.10
E6y Ko3y folds
---
Dealing 5th street
Dealing to the bAAr: [4c]
Dealing to tchazx: [Ah]
the bAAr bets $0.20
tchazx calls $0.20
---
Dealing 6th street
Dealing to the bAAr: [3d]
Dealing to tchazx: [Jh]
the bAAr checks
tchazx checks
---
Dealing river
Dealing to tchazx: [Kh]
the bAAr bets $0.20
tchazx calls $0.20
---
Summary:
Main pot: $1.25 won by tchazx ($1.19)
Rake taken: $0.06
Seat 1: the bAAr ($5.19), net: -$0.57, [6s, 9s, 4s, Ad, 4c, 3d, 3h] (TWO_PAIR FOUR, THREE)
Seat 2: tchazx ($4.09), net: +$0.62, [8h, Ks, Qd, 8d, Ah, Jh, Kh] (TWO_PAIR KING, EIGHT)
Seat 6: kueto ($6.21), net: -$0.02
Seat 8: E6y Ko3y ($2.06), net: -$0.07
Seat 10: telozver123 ($6.30), net: -$0.02
***** End of hand R5-82086688-608 *****
***** History for hand R5-82086688-609 *****
Start hand: Mon Sep 13 22:33:42 GMT+0100 2010
Table: Milwaukee [82086688] (LIMIT SEVEN_CARD_STUD $0.10/$0.20, ante: $0.02, Real money)
User: tchazx
Players in round: 5
Seat 1: the bAAr ($5.19)
Seat 2: tchazx ($4.09)
Seat 6: kueto ($6.21)
Seat 8: E6y Ko3y ($2.06)
Seat 10: telozver123 ($6.30)
the bAAr posts ante $0.02
tchazx posts ante $0.02
kueto posts ante $0.02
E6y Ko3y posts ante $0.02
telozver123 posts ante $0.02
---
Dealing pocket cards
Dealing to the bAAr: [-, -, 5c]
Dealing to tchazx: [Ad, As, Kh]
Dealing to kueto: [-, -, Qs]
Dealing to E6y Ko3y: [-, -, 8s]
Dealing to telozver123: [-, -, Tc]
the bAAr small bring in $0.05
tchazx bets $0.10
kueto calls $0.10
E6y Ko3y folds
telozver123 folds
the bAAr folds
---
Dealing 4th street
Dealing to tchazx: [Ks]
Dealing to kueto: [Qd]
tchazx bets $0.10
kueto calls $0.10
---
Dealing 5th street
Dealing to tchazx: [8c]
Dealing to kueto: [7s]
tchazx bets $0.20
kueto calls $0.20
---
Dealing 6th street
Dealing to tchazx: [7d]
Dealing to kueto: [5s]
tchazx bets $0.20
kueto calls $0.20
---
Dealing river
Dealing to tchazx: [7h]
tchazx bets $0.20
kueto calls $0.20
---
Summary:
Main pot: $1.75 won by kueto ($1.67)
Rake taken: $0.08
Seat 1: the bAAr ($5.12), net: -$0.07
Seat 2: tchazx ($3.27), net: -$0.82, [Ad, As, Kh, Ks, 8c, 7d, 7h] (TWO_PAIR ACE, KING)
Seat 6: kueto ($7.06), net: +$0.85, [Qc, 6c, Qs, Qd, 7s, 5s, 3c] (THREE_OF_A_KIND QUEEN)
Seat 8: E6y Ko3y ($2.04), net: -$0.02
Seat 10: telozver123 ($6.28), net: -$0.02
***** End of hand R5-82086688-609 *****
***** History for hand R5-82086688-610 *****
Start hand: Mon Sep 13 22:34:25 GMT+0100 2010
Table: Milwaukee [82086688] (LIMIT SEVEN_CARD_STUD $0.10/$0.20, ante: $0.02, Real money)
User: tchazx
Players in round: 5
Seat 1: the bAAr ($5.12)
Seat 2: tchazx ($3.27)
Seat 6: kueto ($7.06)
Seat 8: E6y Ko3y ($2.04)
Seat 10: telozver123 ($6.28)
the bAAr posts ante $0.02
tchazx posts ante $0.02
kueto posts ante $0.02
E6y Ko3y posts ante $0.02
telozver123 posts ante $0.02
---
Dealing pocket cards
Dealing to the bAAr: [-, -, Ts]
Dealing to tchazx: [9s, 6s, 7s]
Dealing to kueto: [-, -, Qs]
Dealing to E6y Ko3y: [-, -, 3s]
Dealing to telozver123: [-, -, 9d]
E6y Ko3y small bring in $0.05
telozver123 folds
the bAAr calls $0.05
tchazx calls $0.05
kueto calls $0.05
---
Dealing 4th street
Dealing to the bAAr: [Qd]
Dealing to tchazx: [Ah]
Dealing to kueto: [7h]
Dealing to E6y Ko3y: [Th]
tchazx checks
kueto checks
E6y Ko3y checks
the bAAr bets $0.10
tchazx calls $0.10
kueto folds
E6y Ko3y folds
---
Dealing 5th street
Dealing to the bAAr: [Jh]
Dealing to tchazx: [5c]
tchazx checks
the bAAr bets $0.20
tchazx calls $0.20
---
Dealing 6th street
Dealing to the bAAr: [7d]
Dealing to tchazx: [7c]
tchazx checks
the bAAr bets $0.20
tchazx calls $0.20
---
Dealing river
Dealing to tchazx: [5h]
tchazx checks
the bAAr checks
---
Summary:
Main pot: $1.30 won by the bAAr ($1.24)
Rake taken: $0.06
Seat 1: the bAAr ($5.79), net: +$0.67, [Tc, 9h, Ts, Qd, Jh, 7d, 9c] (TWO_PAIR TEN, NINE)
Seat 2: tchazx ($2.70), net: -$0.57, [9s, 6s, 7s, Ah, 5c, 7c, 5h] (TWO_PAIR SEVEN, FIVE)
Seat 6: kueto ($6.99), net: -$0.07
Seat 8: E6y Ko3y ($1.97), net: -$0.07
Seat 10: telozver123 ($6.26), net: -$0.02
***** End of hand R5-82086688-610 *****

View File

@ -0,0 +1,76 @@
***** History for hand R5-78227816-62 *****
Start hand: Sat Aug 28 20:33:38 GMT+0300 2010
Table: Taegu [78227816] (LIMIT SEVEN_CARD_STUD_HI_LO $0.25/$0.50, ante: $0.05, Real money)
User: XMAN1
Players in round: 8
Seat 1: XMAN1 ($25)
Seat 3: boneos56 ($27.78)
Seat 5: grumset2007 ($3.48)
Seat 6: mylonas77 ($40.73)
Seat 7: YMAN1 ($14.70)
Seat 8: Lee Clayton ($14.79)
Seat 9: guggi_cool ($8.34)
Seat 10: HangEv ($29.08)
boneos56 posts ante $0.05
grumset2007 posts ante $0.05
YMAN1 posts ante $0.05
Lee Clayton posts ante $0.05
guggi_cool posts ante $0.05
HangEv posts ante $0.05
mylonas77 posts ante $0.05
XMAN1 posts ante $0.05
---
Dealing pocket cards
Dealing to XMAN1: [8d, 8s, 4d]
Dealing to boneos56: [-, -, Kd]
Dealing to grumset2007: [-, -, Ks]
Dealing to mylonas77: [-, -, 5c]
Dealing to YMAN1: [-, -, As]
Dealing to Lee Clayton: [-, -, Js]
Dealing to guggi_cool: [-, -, 9s]
Dealing to HangEv: [-, -, 6s]
XMAN1 small bring in $0.12
boneos56 folds
grumset2007 folds
mylonas77 calls $0.12
YMAN1 folds
Lee Clayton folds
guggi_cool folds
HangEv folds
---
Dealing 4th street
Dealing to XMAN1: [3h]
Dealing to mylonas77: [2h]
mylonas77 bets $0.25
XMAN1 calls $0.25
---
Dealing 5th street
Dealing to XMAN1: [8c]
Dealing to mylonas77: [Kh]
mylonas77 bets $0.50
XMAN1 raises $1 to $1.37
mylonas77 calls $0.50
---
Dealing 6th street
Dealing to XMAN1: [4c]
Dealing to mylonas77: [Qh]
XMAN1 bets $0.50
mylonas77 calls $0.50
---
Dealing river
Dealing to XMAN1: [5h]
XMAN1 bets $0.50
mylonas77 calls $0.50
---
Summary:
Main pot: $5.14 won by XMAN1 ($4.89)
Rake taken: $0.25
Seat 1: XMAN1 ($27.47), net: +$2.47, [8d, 8s, 4d, 3h, 8c, 4c, 5h] (FULL_HOUSE EIGHT, FOUR)
Seat 3: boneos56 ($27.73), net: -$0.05
Seat 5: grumset2007 ($3.43), net: -$0.05
Seat 6: mylonas77 ($38.31), net: -$2.42
Seat 7: YMAN1 ($14.65), net: -$0.05
Seat 8: Lee Clayton ($14.74), net: -$0.05
Seat 9: guggi_cool ($8.29), net: -$0.05
Seat 10: HangEv ($29.03), net: -$0.05
***** End of hand R5-78227816-62 *****

View File

@ -1,61 +1,61 @@
Table #15200183 - Hapuna Beach 2 Table #15200183 - Hapuna Beach 2
Starting Hand #746382000 Starting Hand #746382000
Start time of hand: 30 Mar 2009 21:00:00 Start time of hand: 30 Mar 2009 21:00:00
Last Hand #746380000 Last Hand #746380000
Game Type: HOLD'EM Game Type: HOLD'EM
Limit Type: NO LIMIT Limit Type: NO LIMIT
Table Type: RING Table Type: RING
Money Type: REAL MONEY Money Type: REAL MONEY
Blinds are now $0.02/$0.04 Blinds are now $0.02/$0.04
Button is at seat 5 Button is at seat 5
Seat 1: Player1 - $0.23 Seat 1: Player1 - $0.23
Seat 2: Player2 - $5.28 Seat 2: Player2 - $5.28
Seat 3: Player3 - $1.80 Seat 3: Player3 - $1.80
Seat 4: allout96 - $3.99 Seat 4: allout96 - $3.99
Seat 5: Player4 - $1.47 Seat 5: Player4 - $1.47
Seat 6: Player5 - $4 Seat 6: Player5 - $4
Moving Button to seat 1 Moving Button to seat 1
Player2 posts small blind ($0.02) Player2 posts small blind ($0.02)
Player3 posts big blind ($0.04) Player3 posts big blind ($0.04)
Player5 posts $0.04 Player5 posts $0.04
Shuffling Deck Shuffling Deck
Dealing Cards Dealing Cards
Dealing [Ad 8h] to Player5 Dealing [Ad 8h] to Player5
allout96 folds allout96 folds
Player4 calls $0.04 Player4 calls $0.04
Player5 checks Player5 checks
Player1 folds Player1 folds
Player2 calls $0.04 Player2 calls $0.04
Player3 checks Player3 checks
Dealing Flop [9s Ac 5s] Dealing Flop [9s Ac 5s]
Player2 bets $0.08 Player2 bets $0.08
Player3 calls $0.08 Player3 calls $0.08
Player4 calls $0.08 Player4 calls $0.08
Player5 raises to $0.16 Player5 raises to $0.16
Player2 calls $0.16 Player2 calls $0.16
Player3 calls $0.16 Player3 calls $0.16
Player4 calls $0.16 Player4 calls $0.16
Dealing Turn [4s] Dealing Turn [4s]
Player2 checks Player2 checks
Player3 bets $0.04 Player3 bets $0.04
Player4 calls $0.04 Player4 calls $0.04
Player5 raises to $0.72 Player5 raises to $0.72
Player2 folds Player2 folds
Player3 raises to $1.40 Player3 raises to $1.40
Player4 calls $1.27 (all-in) Player4 calls $1.27 (all-in)
Player5 folds Player5 folds
Returning $0.13 to Player3 uncalled Returning $0.13 to Player3 uncalled
Player3 shows [2h 3d] Player3 shows [2h 3d]
Player4 shows [4d 9c] Player4 shows [4d 9c]
Dealing River [2c] Dealing River [2c]
Taking Rake of $0.40 from pot 1 Taking Rake of $0.40 from pot 1
Player3 has Straight, 5 high Player3 has Straight, 5 high
Player3 wins $3.66 with: Straight, 5 high Player3 wins $3.66 with: Straight, 5 high
Seat 1: Player1 - $0.23 Seat 1: Player1 - $0.23
Seat 2: Player2 - $5.08 Seat 2: Player2 - $5.08
Seat 3: Player3 - $3.99 Seat 3: Player3 - $3.99
Seat 4: allout96 - $3.99 Seat 4: allout96 - $3.99
Seat 5: Player4 - $0 Seat 5: Player4 - $0
Seat 6: Player5 - $3.08 Seat 6: Player5 - $3.08
End Of Hand #746382682 End Of Hand #746382682

View File

@ -186,8 +186,8 @@
'wonWhenSeenStreet2': 0.0, 'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0, 'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0}, 'wonWhenSeenStreet4': 0.0},
u'Player3': { 'card1': 0, u'Player3': { 'card1': 1,
'card2': 0, 'card2': 15,
'card3': 0, 'card3': 0,
'card4': 0, 'card4': 0,
'card5': 0, 'card5': 0,
@ -220,11 +220,11 @@
'position': 0, 'position': 0,
'raiseFirstInChance': False, 'raiseFirstInChance': False,
'raisedFirstIn': False, 'raisedFirstIn': False,
'rake': 0, 'rake': 40,
'sawShowdown': True, 'sawShowdown': True,
'seatNo': 3, 'seatNo': 3,
'sitout': False, 'sitout': False,
'startCards': 0, 'startCards': 2,
'startCash': 180, 'startCash': 180,
'street0Aggr': False, 'street0Aggr': False,
'street0Bets': 0, 'street0Bets': 0,
@ -271,7 +271,7 @@
'street4CheckCallRaiseDone': False, 'street4CheckCallRaiseDone': False,
'street4Raises': 0, 'street4Raises': 0,
'street4Seen': False, 'street4Seen': False,
'totalProfit': -159, 'totalProfit': 219,
'tourneyTypeId': None, 'tourneyTypeId': None,
'tourneysPlayersIds': None, 'tourneysPlayersIds': None,
'winnings': 0, 'winnings': 0,
@ -280,8 +280,8 @@
'wonWhenSeenStreet2': 0.0, 'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0, 'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0}, 'wonWhenSeenStreet4': 0.0},
u'Player4': { 'card1': 0, u'Player4': { 'card1': 16,
'card2': 0, 'card2': 34,
'card3': 0, 'card3': 0,
'card4': 0, 'card4': 0,
'card5': 0, 'card5': 0,

View File

@ -0,0 +1,565 @@
{ u'Lisypoker': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 2,
'raiseFirstInChance': True,
'raisedFirstIn': False,
'rake': 0,
'sawShowdown': False,
'seatNo': 9,
'sitout': False,
'startCards': 0,
'startCash': 357,
'street0Aggr': False,
'street0Bets': 0,
'street0Calls': 0,
'street0Raises': 0,
'street0VPI': False,
'street0_3BChance': False,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': False,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': False,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': False,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': 0,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 0,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Tortozendo': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': True,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': True,
'otherRaisedStreet2': False,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 0,
'raiseFirstInChance': True,
'raisedFirstIn': True,
'rake': 0,
'sawShowdown': False,
'seatNo': 6,
'sitout': False,
'startCards': 0,
'startCash': 214,
'street0Aggr': True,
'street0Bets': 0,
'street0Calls': 0,
'street0Raises': 0,
'street0VPI': True,
'street0_3BChance': False,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': True,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': False,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': False,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': -8,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 0,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'heulot': { 'card1': 49,
'card2': 9,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 'B',
'raiseFirstInChance': False,
'raisedFirstIn': False,
'rake': 0,
'sawShowdown': True,
'seatNo': 8,
'sitout': False,
'startCards': 114,
'startCash': 206,
'street0Aggr': False,
'street0Bets': 0,
'street0Calls': 1,
'street0Raises': 0,
'street0VPI': True,
'street0_3BChance': True,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': True,
'street1Bets': 1,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': True,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': True,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': True,
'street3Aggr': True,
'street3Bets': 1,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': True,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': -30,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 0,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'potikuus': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 1,
'raiseFirstInChance': True,
'raisedFirstIn': False,
'rake': 0,
'sawShowdown': False,
'seatNo': 1,
'sitout': False,
'startCards': 0,
'startCash': 44,
'street0Aggr': False,
'street0Bets': 0,
'street0Calls': 0,
'street0Raises': 0,
'street0VPI': False,
'street0_3BChance': False,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': False,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': False,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': False,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': 0,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 0,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'romkarnb': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': False,
'otherRaisedStreet2': False,
'otherRaisedStreet3': False,
'otherRaisedStreet4': False,
'position': 2,
'raiseFirstInChance': False,
'raisedFirstIn': False,
'rake': 0,
'sawShowdown': False,
'seatNo': 4,
'sitout': False,
'startCards': 0,
'startCash': 80,
'street0Aggr': False,
'street0Bets': 0,
'street0Calls': 0,
'street0Raises': 0,
'street0VPI': False,
'street0_3BChance': False,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 0,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': False,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': False,
'street2CheckCallRaiseDone': False,
'street2Raises': 0,
'street2Seen': False,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 0,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': False,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': 0,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 0,
'wonAtSD': 0.0,
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'suicini03': { 'card1': 11,
'card2': 23,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': True,
'foldToOtherRaisedStreet0': False,
'foldToOtherRaisedStreet1': False,
'foldToOtherRaisedStreet2': False,
'foldToOtherRaisedStreet3': False,
'foldToOtherRaisedStreet4': False,
'foldToStreet1CBChance': False,
'foldToStreet1CBDone': False,
'foldToStreet2CBChance': False,
'foldToStreet2CBDone': False,
'foldToStreet3CBChance': False,
'foldToStreet3CBDone': False,
'foldToStreet4CBChance': False,
'foldToStreet4CBDone': False,
'foldedBbToSteal': False,
'foldedSbToSteal': False,
'other3BStreet0': False,
'other4BStreet0': False,
'otherRaisedStreet0': False,
'otherRaisedStreet1': True,
'otherRaisedStreet2': False,
'otherRaisedStreet3': True,
'otherRaisedStreet4': False,
'position': 'S',
'raiseFirstInChance': False,
'raisedFirstIn': False,
'rake': 3,
'sawShowdown': True,
'seatNo': 7,
'sitout': False,
'startCards': 128,
'startCash': 144,
'street0Aggr': False,
'street0Bets': 0,
'street0Calls': 1,
'street0Raises': 0,
'street0VPI': True,
'street0_3BChance': True,
'street0_3BDone': False,
'street0_4BChance': False,
'street0_4BDone': False,
'street1Aggr': False,
'street1Bets': 0,
'street1CBChance': False,
'street1CBDone': False,
'street1Calls': 1,
'street1CheckCallRaiseChance': False,
'street1CheckCallRaiseDone': False,
'street1Raises': 0,
'street1Seen': True,
'street2Aggr': False,
'street2Bets': 0,
'street2CBChance': False,
'street2CBDone': False,
'street2Calls': 0,
'street2CheckCallRaiseChance': True,
'street2CheckCallRaiseDone': True,
'street2Raises': 0,
'street2Seen': True,
'street3Aggr': False,
'street3Bets': 0,
'street3CBChance': False,
'street3CBDone': False,
'street3Calls': 1,
'street3CheckCallRaiseChance': False,
'street3CheckCallRaiseDone': False,
'street3Raises': 0,
'street3Seen': True,
'street4Aggr': False,
'street4Bets': 0,
'street4CBChance': False,
'street4CBDone': False,
'street4Calls': 0,
'street4CheckCallRaiseChance': False,
'street4CheckCallRaiseDone': False,
'street4Raises': 0,
'street4Seen': False,
'totalProfit': 35,
'tourneyTypeId': None,
'tourneysPlayersIds': None,
'winnings': 65,
'wonAtSD': 1.0,
'wonWhenSeenStreet1': 1.0,
'wonWhenSeenStreet2': 1.0,
'wonWhenSeenStreet3': 1.0,
'wonWhenSeenStreet4': 0.0}}

View File

@ -0,0 +1,45 @@
Game #9507514114 starts.
#Game No : 9507514114
***** Hand History for Game 9507514114 *****
$2 USD NL Texas Hold'em - Saturday, August 07, 17:05:05 CEST 2010
Table Table 178053 (Real Money)
Seat 3 is the button
Total number of players : 9/9
Seat 9: Player1 ( $1.60 USD )
Seat 4: Player2 ( $1.98 USD )
Seat 7: Player3 ( $2.90 USD )
Seat 3: Player4 ( $1.97 USD )
Seat 8: Player5 ( $2.43 USD )
Seat 6: Player6 ( $2 USD )
Seat 5: Player7 ( $2 USD )
Seat 2: Player8 ( $0 USD )
Seat 1: Player9 ( $1.83 USD )
Player8 has joined the table.
Player2 posts small blind [$0.01 USD].
Player7 posts big blind [$0.02 USD].
Player8 posts big blind [$0.02 USD].
** Dealing down cards **
Dealt to Player3 [ 7c 6c ]
Player6 calls [$0.02 USD]
Player3 calls [$0.02 USD]
Player5 calls [$0.02 USD]
Player1 folds
Player9 folds
Player8 checks
Player4 folds
Player2 calls [$0.01 USD]
Player7 checks
** Dealing Flop ** [ 5d, 2s, 8h ]
Player2 checks
Player7 bets [$0.09 USD]
Player6 folds
Player3 calls [$0.09 USD]
Player5 folds
Player8 folds
Player2 folds
** Dealing Turn ** [ Kd ]
Player7 bets [$0.21 USD]
Player3 folds
Player7 does not show cards.
Player7 wins $0.50 USD

View File

@ -19,9 +19,9 @@ Player2 posts big blind [$0.04 USD].
Player7 posts big blind [$0.04 USD]. Player7 posts big blind [$0.04 USD].
** Dealing down cards ** ** Dealing down cards **
Dealt to Player1 [ Ad 4c ] Dealt to Player1 [ Ad 4c ]
marmitt84 has joined the table. Player8 has joined the table.
Player2 checks Player2 checks
samvel1976 has joined the table. Player9 has joined the table.
Player7 checks Player7 checks
Player5 folds Player5 folds
Player3 calls [$0.02 USD] Player3 calls [$0.02 USD]

View File

@ -0,0 +1,54 @@
Game #9581478205 starts.
#Game No : 9581478205
***** Hand History for Game 9581478205 *****
$0.50/$1 USD 7 Card Stud Hi-Lo - Monday, August 30, 20:20:17 EEST 2010
Table Table 136403 (Real Money)
Seat 0 is the button
Total number of players : 7/8
Seat 3: XMAN1 ( $24.95 USD )
Seat 5: ISqzUSqueal ( $31.02 USD )
Seat 7: PPPPPositive ( $4.20 USD )
Seat 8: Unladylike ( $19 USD )
Seat 6: YMAN1 ( $10.18 USD )
Seat 2: strandalleen ( $17.55 USD )
Seat 1: tubby09 ( $24.20 USD )
tubby09 posts ante [$0.05 USD]
strandalleen posts ante [$0.05 USD]
XMAN1 posts ante [$0.05 USD]
ISqzUSqueal posts ante [$0.05 USD]
YMAN1 posts ante [$0.05 USD]
PPPPPositive posts ante [$0.05 USD]
Unladylike posts ante [$0.05 USD]
** Dealing **
Dealt to XMAN1 [ Td 5s 3c ]
YMAN1 opens
YMAN1 bring-ins [$0.25 USD]
PPPPPositive completes [$0.50 USD]
Unladylike folds
tubby09 folds
strandalleen calls [$0.50 USD]
XMAN1 folds
ISqzUSqueal folds
YMAN1 calls [$0.25 USD]
** Dealing Fourth street **
PPPPPositive opens
PPPPPositive bets [$0.50 USD]
strandalleen calls [$0.50 USD]
YMAN1 folds
** Dealing Fifth street **
PPPPPositive opens
PPPPPositive bets [$1 USD]
strandalleen calls [$1 USD]
** Dealing Sixth street **
PPPPPositive opens
PPPPPositive bets [$1 USD]
strandalleen calls [$1 USD]
** Dealing River **
PPPPPositive opens
PPPPPositive bets [$1 USD]
strandalleen calls [$1 USD]
PPPPPositive shows [ Ad, Qd, Ah, 2d, 7d, Th, 6d ]a flush, Ace high.
strandalleen doesn't show [ 5h, 9d, 9c, Qc, 2h, Kc, Js ]a pair of Nines.
PPPPPositive wins $8.45 USD from the main pot with a flush, Ace high.
There was no qualifying low hand

View File

@ -0,0 +1,36 @@
PokerStars Game #49934100000: 5 Card Draw No Limit ($0.25/$0.50 USD) - 2010/09/20 20:50:00 PT [2010/09/20 23:50:00 ET]
Table 'Table VI' 6-max Seat #3 is the button
Seat 1: Player1 ($27.95 in chips)
Seat 2: Player2 ($7.50 in chips)
Seat 3: Player3 ($12.15 in chips)
Seat 4: Player4 ($9.25 in chips)
Seat 5: Player5 ($20 in chips)
Player4: posts small blind $0.25
Player5: posts big blind $0.50
vega104: sits out
*** DEALING HANDS ***
Dealt to Player5 [4d 7d 4c 5c Tc]
Player1: folds
Player2: folds
Player3: folds
Player4: calls $0.25
Player5: checks
Player4: discards 1 card
Player5: discards 1 card [4c]
Dealt to Player5 [4d 7d 5c Tc] [Ad]
Player4: checks
Player5: checks
*** SHOW DOWN ***
Player4: shows [6d Js As Jd 6c] (two pair, Jacks and Sixes)
Player5: mucks hand
Player4 collected $0.95 from pot
*** SUMMARY ***
Total pot $1 | Rake $0.05
Seat 1: Player1 folded before the Draw (didn't bet)
Seat 2: Player2 folded before the Draw (didn't bet)
Seat 3: Player3 (button) folded before the Draw (didn't bet)
Seat 4: Player4 (small blind) showed [6d Js As Jd 6c] and won ($0.95) with two pair, Jacks and Sixes
Seat 5: Player5 (big blind) mucked [4d 7d Ad 5c Tc]

View File

@ -0,0 +1,31 @@
PokerStars Game #49900000007: 5 Card Draw Pot Limit ($0.50/$1.00 USD) - 2010/09/20 20:00:00 PT [2010/09/20 20:00:00 ET]
Table 'Table II' 6-max Seat #3 is the button
Seat 1: Player1 ($106.80 in chips)
Seat 3: Player2 ($34.95 in chips)
Seat 4: Player3 ($40 in chips)
Player3: posts small blind $0.50
Player1: posts big blind $1
*** DEALING HANDS ***
Dealt to Player3 [6s Jh 7d 2h 3s]
Player2: raises $2 to $3
Player3: calls $2.50
Player1: calls $2
Player3: discards 1 card [Jh]
Dealt to Player3 [6s 7d 2h 3s] [Qs]
Player1: discards 1 card
Player2: discards 3 cards
Player3: bets $5
Player1: folds
Player2: calls $5
*** SHOW DOWN ***
Player3: shows [6s Qs 7d 2h 3s] (high card Queen)
Player2: shows [4d Ad Ks Kd 3h] (a pair of Kings)
Player2 collected $18.10 from pot
*** SUMMARY ***
Total pot $19 | Rake $0.90
Seat 1: Player1 (big blind) folded after the Draw
Seat 3: Player2 (button) showed [4d Ad Ks Kd 3h] and won ($18.10) with a pair of Kings
Seat 4: Player3 (small blind) showed [6s Qs 7d 2h 3s] and lost with high card Queen

Some files were not shown because too many files have changed in this diff Show More