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

This commit is contained in:
grindi 2009-12-01 11:11:34 +03:00
commit 45eccb0697
43 changed files with 33093 additions and 4919 deletions

View File

@ -10,7 +10,8 @@ Architecture: all
Section: games
Priority: extra
Depends: ${python:Depends}, python-gtk2, python-matplotlib,
python-support, mysql-server | postgresql | python-pysqlite2,
python-support, python-xlib,
mysql-server | postgresql | python-pysqlite2,
python-psycopg2 | python-mysqldb
Suggests: wine
Description: free poker database with HUD

View File

@ -51,7 +51,7 @@ if __name__ == "__main__":
parser.add_option("-x", "--failOnError", action="store_true",
help="If this option is passed it quits when it encounters any error")
(options, sys.argv) = parser.parse_args()
(options, argv) = parser.parse_args()
settings={'callFpdbHud':False, 'db-backend':2}
settings['db-host']=options.server

View File

@ -37,21 +37,106 @@ from xml.dom.minidom import Node
import logging, logging.config
import ConfigParser
try: # local path
logging.config.fileConfig(os.path.join(sys.path[0],"logging.conf"))
except ConfigParser.NoSectionError: # debian package path
logging.config.fileConfig('/usr/share/python-fpdb/logging.conf')
##############################################################################
# Functions for finding config files and setting up logging
# Also used in other modules that use logging.
log = logging.getLogger("config")
def get_default_config_path():
"""Returns the path where the fpdb config file _should_ be stored."""
if os.name == 'posix':
config_path = os.path.join(os.path.expanduser("~"), '.fpdb')
elif os.name == 'nt':
config_path = os.path.join(os.environ["APPDATA"], 'fpdb')
else: config_path = False
return config_path
def get_exec_path():
"""Returns the path to the fpdb.(py|exe) file we are executing"""
if hasattr(sys, "frozen"): # compiled by py2exe
return os.path.dirname(sys.executable)
else:
pathname = os.path.dirname(sys.argv[0])
return os.path.abspath(pathname)
def get_config(file_name, fallback = True):
"""Looks in cwd and in self.default_config_path for a config file."""
config_path = os.path.join(get_exec_path(), file_name)
# print "config_path=", config_path
if os.path.exists(config_path): # there is a file in the cwd
return config_path # so we use it
else: # no file in the cwd, look where it should be in the first place
config_path = os.path.join(get_default_config_path(), file_name)
# print "config path 2=", config_path
if os.path.exists(config_path):
return config_path
# No file found
if not fallback:
return False
# OK, fall back to the .example file, should be in the start dir
if os.path.exists(file_name + ".example"):
try:
shutil.copyfile(file_name + ".example", file_name)
print "No %s found, using %s.example.\n" % (file_name, file_name)
print "A %s file has been created. You will probably have to edit it." % file_name
sys.stderr.write("No %s found, using %s.example.\n" % (file_name, file_name) )
except:
print "No %s found, cannot fall back. Exiting.\n" % file_name
sys.stderr.write("No %s found, cannot fall back. Exiting.\n" % file_name)
sys.exit()
return file_name
def get_logger(file_name, config = "config", fallback = False):
conf = get_config(file_name, fallback = fallback)
if conf:
try:
logging.config.fileConfig(conf)
log = logging.getLogger(config)
log.debug("%s logger initialised" % config)
return log
except:
pass
log = logging.basicConfig()
log = logging.getLogger()
log.debug("config logger initialised")
return log
def fix_tf(x, default = True):
# The xml parser doesn't translate "True" to True. Therefore, we never get
# True or False from the parser only "True" or "False". So translate the
# string to the python boolean representation.
if x == "1" or x == 1 or string.lower(x) == "true" or string.lower(x) == "t":
# find a logging.conf file and set up logging
log = get_logger("logging.conf")
########################################################################
# application wide consts
APPLICATION_NAME_SHORT = 'fpdb'
APPLICATION_VERSION = 'xx.xx.xx'
DIR_SELF = os.path.dirname(get_exec_path())
#TODO: imo no good idea to place 'database' in parent dir
DIR_DATABASES = os.path.join(os.path.dirname(DIR_SELF), 'database')
DATABASE_TYPE_POSTGRESQL = 'postgresql'
DATABASE_TYPE_SQLITE = 'sqlite'
DATABASE_TYPE_MYSQL = 'mysql'
DATABASE_TYPES = (
DATABASE_TYPE_POSTGRESQL,
DATABASE_TYPE_SQLITE,
DATABASE_TYPE_MYSQL,
)
NEWIMPORT = False
########################################################################
def string_to_bool(string, default=True):
"""converts a string representation of a boolean value to boolean True or False
@param string: (str) the string to convert
@param default: value to return if the string can not be converted to a boolean value
"""
string = string.lower()
if string in ('1', 'true', 't'):
return True
if x == "0" or x == 0 or string.lower(x) == "false" or string.lower(x) == "f":
elif string in ('0', 'false', 'f'):
return False
return default
@ -106,7 +191,7 @@ class Site:
self.font = node.getAttribute("font")
self.font_size = node.getAttribute("font_size")
self.use_frames = node.getAttribute("use_frames")
self.enabled = fix_tf(node.getAttribute("enabled"), default = True)
self.enabled = string_to_bool(node.getAttribute("enabled"), default=True)
self.xpad = node.getAttribute("xpad")
self.ypad = node.getAttribute("ypad")
self.layout = {}
@ -201,14 +286,13 @@ class Game:
class Database:
def __init__(self, node):
self.db_name = node.getAttribute("db_name")
self.db_server = node.getAttribute("db_server")
self.db_server = node.getAttribute("db_server").lower()
self.db_ip = node.getAttribute("db_ip")
self.db_user = node.getAttribute("db_user")
self.db_type = node.getAttribute("db_type")
self.db_pass = node.getAttribute("db_pass")
self.db_selected = fix_tf(node.getAttribute("default"),"False")
log.debug("Database db_name:'%(name)s' db_server:'%(server)s' db_ip:'%(ip)s' db_user:'%(user)s' db_type:'%(type)s' db_pass (not logged) selected:'%(sel)s'" \
% { 'name':self.db_name, 'server':self.db_server, 'ip':self.db_ip, 'user':self.db_user, 'type':self.db_type, 'sel':self.db_selected} )
self.db_selected = string_to_bool(node.getAttribute("default"), default=False)
log.debug("Database db_name:'%(name)s' db_server:'%(server)s' db_ip:'%(ip)s' db_user:'%(user)s' db_pass (not logged) selected:'%(sel)s'" \
% { 'name':self.db_name, 'server':self.db_server, 'ip':self.db_ip, 'user':self.db_user, 'sel':self.db_selected} )
def __str__(self):
temp = 'Database = ' + self.db_name + '\n'
@ -270,8 +354,8 @@ class Import:
self.interval = node.getAttribute("interval")
self.callFpdbHud = node.getAttribute("callFpdbHud")
self.hhArchiveBase = node.getAttribute("hhArchiveBase")
self.saveActions = fix_tf(node.getAttribute("saveActions"), True)
self.fastStoreHudCache = fix_tf(node.getAttribute("fastStoreHudCache"), False)
self.saveActions = string_to_bool(node.getAttribute("saveActions"), default=True)
self.fastStoreHudCache = string_to_bool(node.getAttribute("fastStoreHudCache"), default=False)
def __str__(self):
return " interval = %s\n callFpdbHud = %s\n hhArchiveBase = %s\n saveActions = %s\n fastStoreHudCache = %s\n" \
@ -282,16 +366,16 @@ class HudUI:
self.node = node
self.label = node.getAttribute('label')
#
self.aggregate_ring = fix_tf(node.getAttribute('aggregate_ring_game_stats'))
self.aggregate_tour = fix_tf(node.getAttribute('aggregate_tourney_stats'))
self.hud_style = node.getAttribute('stat_aggregation_range')
self.hud_days = node.getAttribute('aggregation_days')
self.hud_style = node.getAttribute('stat_range')
self.hud_days = node.getAttribute('stat_days')
self.aggregate_ring = string_to_bool(node.getAttribute('aggregate_ring_game_stats'))
self.aggregate_tour = string_to_bool(node.getAttribute('aggregate_tourney_stats'))
self.agg_bb_mult = node.getAttribute('aggregation_level_multiplier')
#
self.h_aggregate_ring = fix_tf(node.getAttribute('aggregate_hero_ring_game_stats'))
self.h_aggregate_tour = fix_tf(node.getAttribute('aggregate_hero_tourney_stats'))
self.h_hud_style = node.getAttribute('hero_stat_aggregation_range')
self.h_hud_days = node.getAttribute('hero_aggregation_days')
self.h_hud_style = node.getAttribute('hero_stat_range')
self.h_hud_days = node.getAttribute('hero_stat_days')
self.h_aggregate_ring = string_to_bool(node.getAttribute('aggregate_hero_ring_game_stats'))
self.h_aggregate_tour = string_to_bool(node.getAttribute('aggregate_hero_tourney_stats'))
self.h_agg_bb_mult = node.getAttribute('hero_aggregation_level_multiplier')
@ -301,9 +385,9 @@ class HudUI:
class Tv:
def __init__(self, node):
self.combinedStealFold = node.getAttribute("combinedStealFold")
self.combined2B3B = node.getAttribute("combined2B3B")
self.combinedPostflop = node.getAttribute("combinedPostflop")
self.combinedStealFold = string_to_bool(node.getAttribute("combinedStealFold"), default=True)
self.combined2B3B = string_to_bool(node.getAttribute("combined2B3B"), default=True)
self.combinedPostflop = string_to_bool(node.getAttribute("combinedPostflop"), default=True)
def __str__(self):
return (" combinedStealFold = %s\n combined2B3B = %s\n combinedPostflop = %s\n" %
@ -315,7 +399,7 @@ class Config:
# "file" is a path to an xml file with the fpdb/HUD configuration
# we check the existence of "file" and try to recover if it doesn't exist
self.default_config_path = self.get_default_config_path()
# self.default_config_path = self.get_default_config_path()
if file is not None: # config file path passed in
file = os.path.expanduser(file)
if not os.path.exists(file):
@ -323,28 +407,12 @@ class Config:
sys.stderr.write("Configuration file %s not found. Using defaults." % (file))
file = None
if file is None: # configuration file path not passed or invalid
file = self.find_config() #Look for a config file in the normal places
if file is None: # no config file in the normal places
file = self.find_example_config() #Look for an example file to edit
if file is None: # that didn't work either, just die
print "No HUD_config_xml found after looking in current directory and "+self.default_config_path+"\nExiting"
sys.stderr.write("No HUD_config_xml found after looking in current directory and "+self.default_config_path+"\nExiting")
print "press enter to continue"
sys.stdin.readline()
sys.exit()
if file is None: file = get_config("HUD_config.xml")
# Parse even if there was no real config file found and we are using the example
# If using the example, we'll edit it later
# sc 2009/10/04 Example already copied to main filename, is this ok?
log.info("Reading configuration file %s" % file)
if os.sep in file:
print "\nReading configuration file %s\n" % file
else:
print "\nReading configuration file %s" % file
print "in %s\n" % os.getcwd()
try:
doc = xml.dom.minidom.parse(file)
except:
@ -358,10 +426,13 @@ class Config:
self.file = file
self.supported_sites = {}
self.supported_games = {}
self.supported_databases = {}
self.supported_databases = {} # databaseName --> Database instance
self.aux_windows = {}
self.hhcs = {}
self.popup_windows = {}
self.db_selected = None # database the user would like to use
self.tv = None
# s_sites = doc.getElementsByTagName("supported_sites")
for site_node in doc.getElementsByTagName("site"):
@ -373,29 +444,26 @@ class Config:
game = Game(node = game_node)
self.supported_games[game.game_name] = game
# parse databases defined by user in the <supported_databases> section
# the user may select the actual database to use via commandline or by setting the selected="bool"
# attribute of the tag. if no database is explicitely selected, we use the first one we come across
# s_dbs = doc.getElementsByTagName("supported_databases")
# select database from those defined in config by:
# 1) command line option
# or 2) selected="True" in config element
# or 3) just choose the first we come across
#TODO: do we want to take all <database> tags or all <database> tags contained in <supported_databases>
# ..this may break stuff for some users. so leave it unchanged for now untill there is a decission
for db_node in doc.getElementsByTagName("database"):
try:
db = Database(node=db_node)
except:
raise FpdbError("Unable to create database object")
else:
if db.db_name in self.supported_databases:
raise FpdbError("Database names must be unique")
# If there is only one Database node, or none are marked
# default, use first
if not self.supported_databases:
raise ValueError("Database names must be unique")
if self.db_selected is None or db.db_selected:
self.db_selected = db.db_name
self.supported_databases[db.db_name] = db
if db.db_selected:
self.db_selected = db.db_name
#TODO: if the user may passes '' (empty string) as database name via command line, his choice is ignored
# ..when we parse the xml we allow for ''. there has to be a decission if to allow '' or not
if dbname and dbname in self.supported_databases:
self.db_selected = dbname
#NOTE: fpdb can not handle the case when no database is defined in xml, so we throw an exception for now
if self.db_selected is None:
raise ValueError('There must be at least one database defined')
# s_dbs = doc.getElementsByTagName("mucked_windows")
for aw_node in doc.getElementsByTagName("aw"):
@ -421,8 +489,7 @@ class Config:
self.ui = hui
for tv_node in doc.getElementsByTagName("tv"):
tv = Tv(node = tv_node)
self.tv = tv
self.tv = Tv(node = tv_node)
db = self.get_db_parameters()
if db['db-password'] == 'YOUR MYSQL PASSWORD':
@ -441,28 +508,6 @@ class Config:
def set_hhArchiveBase(self, path):
self.imp.node.setAttribute("hhArchiveBase", path)
def find_config(self):
"""Looks in cwd and in self.default_config_path for a config file."""
if os.path.exists('HUD_config.xml'): # there is a HUD_config in the cwd
file = 'HUD_config.xml' # so we use it
else: # no HUD_config in the cwd, look where it should be in the first place
config_path = os.path.join(self.default_config_path, 'HUD_config.xml')
if os.path.exists(config_path):
file = config_path
else:
file = None
return file
def get_default_config_path(self):
"""Returns the path where the fpdb config file _should_ be stored."""
if os.name == 'posix':
config_path = os.path.join(os.path.expanduser("~"), '.fpdb')
elif os.name == 'nt':
config_path = os.path.join(os.environ["APPDATA"], 'fpdb')
else: config_path = None
return config_path
def find_default_conf(self):
if os.name == 'posix':
config_path = os.path.join(os.path.expanduser("~"), '.fpdb', 'default.conf')
@ -476,29 +521,8 @@ class Config:
file = None
return file
def read_default_conf(self, file):
parms = {}
with open(file, "r") as fh:
for line in fh:
line = string.strip(line)
(key, value) = line.split('=')
parms[key] = value
return parms
def find_example_config(self):
if os.path.exists('HUD_config.xml.example'): # there is a HUD_config in the cwd
file = 'HUD_config.xml' # so we use it
try:
shutil.copyfile(file+'.example', file)
except:
file = ''
print "No HUD_config.xml found, using HUD_config.xml.example.\n", \
"A HUD_config.xml has been created. You will probably have to edit it."
sys.stderr.write("No HUD_config.xml found, using HUD_config.xml.example.\n" + \
"A HUD_config.xml has been created. You will probably have to edit it.")
else:
file = None
return file
def get_doc(self):
return self.doc
def get_site_node(self, site):
for site_node in self.doc.getElementsByTagName("site"):
@ -534,13 +558,11 @@ class Config:
return location_node
def save(self, file = None):
if file is not None:
if file is None:
file = self.file
shutil.move(file, file+".backup")
with open(file, 'w') as f:
self.doc.writexml(f)
else:
shutil.move(self.file, self.file+".backup")
with open(self.file, 'w') as f:
self.doc.writexml(f)
def edit_layout(self, site_name, max, width = None, height = None,
fav_seat = None, locations = None):
@ -571,6 +593,13 @@ class Config:
else:
self.aux_windows[aux_name].layout[max].location[i] = ( locations[i][0], locations[i][1] )
#NOTE: we got a nice Database class, so why map it again here?
# user input validation should be done when initializing the Database class. this allows to give appropriate feddback when something goes wrong
# try ..except is evil here. it swallows all kinds of errors. dont do this
# naming database types 2, 3, 4 on the fly is no good idea. i see this all over the code. better use some globally defined consts (see DATABASE_TYPE_*)
# i would like to drop this method entirely and replace it by get_selected_database() or better get_active_database(), returning one of our Database instances
# thus we can drop self.db_selected (holding database name) entirely and replace it with self._active_database = Database, avoiding to define the same
# thing multiple times
def get_db_parameters(self):
db = {}
name = self.db_selected
@ -590,20 +619,18 @@ class Config:
try: db['db-server'] = self.supported_databases[name].db_server
except: pass
try: db['db-type'] = self.supported_databases[name].db_type
except: pass
if string.lower(self.supported_databases[name].db_server) == 'mysql':
if self.supported_databases[name].db_server== DATABASE_TYPE_MYSQL:
db['db-backend'] = 2
elif string.lower(self.supported_databases[name].db_server) == 'postgresql':
elif self.supported_databases[name].db_server== DATABASE_TYPE_POSTGRESQL:
db['db-backend'] = 3
elif string.lower(self.supported_databases[name].db_server) == 'sqlite':
elif self.supported_databases[name].db_server== DATABASE_TYPE_SQLITE:
db['db-backend'] = 4
else: db['db-backend'] = None # this is big trouble
else:
raise ValueError('Unsupported database backend: %s' % self.supported_databases[name].db_server)
return db
def set_db_parameters(self, db_name = 'fpdb', db_ip = None, db_user = None,
db_pass = None, db_server = None, db_type = None):
db_pass = None, db_server = None):
db_node = self.get_db_node(db_name)
if db_node != None:
if db_ip is not None: db_node.setAttribute("db_ip", db_ip)
@ -627,16 +654,13 @@ class Config:
return None
def get_tv_parameters(self):
tv = {}
try: tv['combinedStealFold'] = self.tv.combinedStealFold
except: tv['combinedStealFold'] = True
try: tv['combined2B3B'] = self.tv.combined2B3B
except: tv['combined2B3B'] = True
try: tv['combinedPostflop'] = self.tv.combinedPostflop
except: tv['combinedPostflop'] = True
return tv
if self.tv is not None:
return {
'combinedStealFold': self.tv.combinedStealFold,
'combined2B3B': self.tv.combined2B3B,
'combinedPostflop': self.tv.combinedPostflop
}
return {}
# Allow to change the menu appearance
def get_hud_ui_parameters(self):
@ -650,38 +674,50 @@ class Config:
except:
hui['label'] = default_text
try: hui['hud_style'] = self.ui.hud_style
except: hui['hud_style'] = 'A' # default is show stats for All-time, also S(session) and T(ime)
try: hui['hud_days'] = int(self.ui.hud_days)
except: hui['hud_days'] = 90
try: hui['aggregate_ring'] = self.ui.aggregate_ring
except: hui['aggregate_ring'] = False
try: hui['aggregate_tour'] = self.ui.aggregate_tour
except: hui['aggregate_tour'] = True
try: hui['hud_style'] = self.ui.hud_style
except: hui['hud_style'] = 'A'
try: hui['hud_days'] = int(self.ui.hud_days)
except: hui['hud_days'] = 90
try: hui['agg_bb_mult'] = self.ui.agg_bb_mult
except: hui['agg_bb_mult'] = 1
try: hui['seats_style'] = self.ui.seats_style
except: hui['seats_style'] = 'A' # A / C / E, use A(ll) / C(ustom) / E(xact) seat numbers
try: hui['seats_cust_nums'] = self.ui.seats_cust_nums
except: hui['seats_cust_nums'] = ['n/a', 'n/a', (2,2), (3,4), (3,5), (4,6), (5,7), (6,8), (7,9), (8,10), (8,10)]
# Hero specific
try: hui['h_aggregate_ring'] = self.ui.h_aggregate_ring
except: hui['h_aggregate_ring'] = False
try: hui['h_aggregate_tour'] = self.ui.h_aggregate_tour
except: hui['h_aggregate_tour'] = True
try: hui['h_hud_style'] = self.ui.h_hud_style
except: hui['h_hud_style'] = 'S'
try: hui['h_hud_days'] = int(self.ui.h_hud_days)
except: hui['h_hud_days'] = 30
try: hui['h_aggregate_ring'] = self.ui.h_aggregate_ring
except: hui['h_aggregate_ring'] = False
try: hui['h_aggregate_tour'] = self.ui.h_aggregate_tour
except: hui['h_aggregate_tour'] = True
try: hui['h_agg_bb_mult'] = self.ui.h_agg_bb_mult
except: hui['h_agg_bb_mult'] = 1
try: hui['h_seats_style'] = self.ui.h_seats_style
except: hui['h_seats_style'] = 'A' # A / C / E, use A(ll) / C(ustom) / E(xact) seat numbers
try: hui['h_seats_cust_nums'] = self.ui.h_seats_cust_nums
except: hui['h_seats_cust_nums'] = ['n/a', 'n/a', (2,2), (3,4), (3,5), (4,6), (5,7), (6,8), (7,9), (8,10), (8,10)]
return hui
@ -735,29 +771,27 @@ class Config:
return colors
def get_default_font(self, site='PokerStars'):
(font, font_size) = ("Sans", "8")
if site not in self.supported_sites:
return ("Sans", "8")
if self.supported_sites[site].font == "":
font = "Sans"
else:
font = self.supported_sites[site].font
if self.supported_sites[site].font_size == "":
font_size = "8"
else:
font_size = self.supported_sites[site].font_size
return (font, font_size)
site = self.supported_sites.get(site, None)
if site is not None:
if site.font:
font = site.font
if site.font_size:
font_size = site.font_size
return font, font_size
def get_locations(self, site = "PokerStars", max = "8"):
try:
locations = self.supported_sites[site].layout[max].location
except:
locations = ( ( 0, 0), (684, 61), (689, 239), (692, 346),
def get_locations(self, site_name="PokerStars", max=8):
site = self.supported_sites.get(site_name, None)
if site is not None:
location = site.layout.get(max, None)
if location is not None:
return location.location
return (
( 0, 0), (684, 61), (689, 239), (692, 346),
(586, 393), (421, 440), (267, 440), ( 0, 361),
( 0, 280), (121, 280), ( 46, 30) )
return locations
( 0, 280), (121, 280), ( 46, 30)
)
def get_aux_locations(self, aux = "mucked", max = "9"):
@ -771,12 +805,10 @@ class Config:
def get_supported_sites(self, all=False):
"""Returns the list of supported sites."""
the_sites = []
for site in self.supported_sites.keys():
params = self.get_site_parameters(site)
if all or params['enabled']:
the_sites.append(site)
return the_sites
if all:
return self.supported_sites.keys()
else:
return [site_name for (site_name, site) in self.supported_sites.items() if site.enabled]
def get_site_parameters(self, site):
"""Returns a dict of the site parameters for the specified site"""
@ -824,10 +856,7 @@ class Config:
def get_aux_windows(self):
"""Gets the list of mucked window formats in the configuration."""
mw = []
for w in self.aux_windows.keys():
mw.append(w)
return mw
return self.aux_windows.keys()
def get_aux_parameters(self, name):
"""Gets a dict of mucked window parameters from the named mw."""
@ -933,4 +962,14 @@ if __name__== "__main__":
for game in c.get_supported_games():
print c.get_game_parameters(game)
for hud_param, value in c.get_hud_ui_parameters().iteritems():
print "hud param %s = %s" % (hud_param, value)
print "start up path = ", c.execution_path("")
try:
from xml.dom.ext import PrettyPrint
for site_node in c.doc.getElementsByTagName("site"):
PrettyPrint(site_node, stream=sys.stdout, encoding="utf-8")
except:
print "xml.dom.ext needs PyXML to be installed!"

View File

@ -21,6 +21,11 @@ Create and manage the database objects.
########################################################################
# ToDo: - rebuild indexes / vacuum option
# - check speed of get_stats_from_hand() - add log info
# - check size of db, seems big? (mysql)
# - investigate size of mysql db (200K for just 7K hands? 2GB for 140K hands?)
# postmaster -D /var/lib/pgsql/data
# Standard Library modules
@ -45,16 +50,7 @@ import Card
import Tourney
from Exceptions import *
import logging, logging.config
import ConfigParser
try: # local path
logging.config.fileConfig(os.path.join(sys.path[0],"logging.conf"))
except ConfigParser.NoSectionError: # debian package path
logging.config.fileConfig('/usr/share/python-fpdb/logging.conf')
log = logging.getLogger('db')
log = Configuration.get_logger("logging.conf")
class Database:
@ -78,14 +74,9 @@ class Database:
indexes = [
[ ] # no db with index 0
, [ ] # no db with index 1
, [ # indexes for mysql (list index 2)
, [ # indexes for mysql (list index 2) (foreign keys not here, in next data structure)
# {'tab':'Players', 'col':'name', 'drop':0} unique indexes not dropped
# {'tab':'Hands', 'col':'siteHandNo', 'drop':0} unique indexes not dropped
{'tab':'Hands', 'col':'gametypeId', 'drop':0} # mct 22/3/09
, {'tab':'HandsPlayers', 'col':'handId', 'drop':0} # not needed, handled by fk
, {'tab':'HandsPlayers', 'col':'playerId', 'drop':0} # not needed, handled by fk
, {'tab':'HandsPlayers', 'col':'tourneyTypeId', 'drop':0}
, {'tab':'HandsPlayers', 'col':'tourneysPlayersId', 'drop':0}
#, {'tab':'Tourneys', 'col':'siteTourneyNo', 'drop':0} unique indexes not dropped
]
, [ # indexes for postgres (list index 3)
@ -126,6 +117,8 @@ class Database:
{'fktab':'Hands', 'fkcol':'gametypeId', 'rtab':'Gametypes', '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':'tourneyTypeId', 'rtab':'TourneyTypes', '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':'HudCache', 'fkcol':'gametypeId', 'rtab':'Gametypes', 'rcol':'id', 'drop':1}
, {'fktab':'HudCache', 'fkcol':'playerId', 'rtab':'Players', 'rcol':'id', 'drop':0}
@ -205,7 +198,7 @@ class Database:
# where possible avoid creating new SQL instance by using the global one passed in
if sql is None:
self.sql = SQL.Sql(type = self.type, db_server = self.db_server)
self.sql = SQL.Sql(db_server = self.db_server)
else:
self.sql = sql
@ -249,7 +242,6 @@ class Database:
db_params = c.get_db_parameters()
self.import_options = c.get_import_parameters()
self.type = db_params['db-type']
self.backend = db_params['db-backend']
self.db_server = db_params['db-server']
self.database = db_params['db-databaseName']
@ -441,21 +433,53 @@ class Database:
err = traceback.extract_tb(sys.exc_info()[2])[-1]
print "*** Database Error: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
# is get_stats_from_hand slow?
def get_stats_from_hand( self, hand, type # type is "ring" or "tour"
, hud_params = {'aggregate_tour':False, 'aggregate_ring':False, 'hud_style':'A', 'hud_days':30, 'agg_bb_mult':100
,'h_aggregate_tour':False, 'h_aggregate_ring':False, 'h_hud_style':'S', 'h_hud_days':30, 'h_agg_bb_mult':100}
, hud_params = {'hud_style':'A', 'agg_bb_mult':1000
,'seats_style':'A', 'seats_cust_nums':['n/a', 'n/a', (2,2), (3,4), (3,5), (4,6), (5,7), (6,8), (7,9), (8,10), (8,10)]
,'h_hud_style':'S', 'h_agg_bb_mult':1000
,'h_seats_style':'A', 'h_seats_cust_nums':['n/a', 'n/a', (2,2), (3,4), (3,5), (4,6), (5,7), (6,8), (7,9), (8,10), (8,10)]
}
, hero_id = -1
, num_seats = 6
):
aggregate = hud_params['aggregate_tour'] if type == "tour" else hud_params['aggregate_ring']
hud_style = hud_params['hud_style']
agg_bb_mult = hud_params['agg_bb_mult'] if aggregate else 1
h_aggregate = hud_params['h_aggregate_tour'] if type == "tour" else hud_params['h_aggregate_ring']
agg_bb_mult = hud_params['agg_bb_mult']
seats_style = hud_params['seats_style']
seats_cust_nums = hud_params['seats_cust_nums']
h_hud_style = hud_params['h_hud_style']
h_agg_bb_mult = hud_params['h_agg_bb_mult'] if h_aggregate else 1
h_agg_bb_mult = hud_params['h_agg_bb_mult']
h_seats_style = hud_params['h_seats_style']
h_seats_cust_nums = hud_params['h_seats_cust_nums']
stat_dict = {}
if seats_style == 'A':
seats_min, seats_max = 0, 10
elif seats_style == 'C':
seats_min, seats_max = seats_cust_nums[num_seats][0], seats_cust_nums[num_seats][1]
elif seats_style == 'E':
seats_min, seats_max = num_seats, num_seats
else:
seats_min, seats_max = 0, 10
print "bad seats_style value:", seats_style
if h_seats_style == 'A':
h_seats_min, h_seats_max = 0, 10
elif h_seats_style == 'C':
h_seats_min, h_seats_max = h_seats_cust_nums[num_seats][0], h_seats_cust_nums[num_seats][1]
elif h_seats_style == 'E':
h_seats_min, h_seats_max = num_seats, num_seats
else:
h_seats_min, h_seats_max = 0, 10
print "bad h_seats_style value:", h_seats_style
print "opp seats style", seats_style, "hero seats style", h_seats_style
print "opp seats:", seats_min, seats_max, " hero seats:", h_seats_min, h_seats_max
if hud_style == 'S' or h_hud_style == 'S':
self.get_stats_from_hand_session(hand, stat_dict, hero_id, hud_style, h_hud_style)
self.get_stats_from_hand_session(hand, stat_dict, hero_id
,hud_style, seats_min, seats_max
,h_hud_style, h_seats_min, h_seats_max)
if hud_style == 'S' and h_hud_style == 'S':
return stat_dict
@ -466,6 +490,10 @@ class Database:
stylekey = '0000000' # all stylekey values should be higher than this
elif hud_style == 'S':
stylekey = 'zzzzzzz' # all stylekey values should be lower than this
else:
stylekey = '0000000'
log.info('hud_style: %s' % hud_style)
#elif hud_style == 'H':
# stylekey = date_nhands_ago needs array by player here ...
@ -475,16 +503,17 @@ class Database:
h_stylekey = '0000000' # all stylekey values should be higher than this
elif h_hud_style == 'S':
h_stylekey = 'zzzzzzz' # all stylekey values should be lower than this
else:
h_stylekey = '000000'
log.info('h_hud_style: %s' % h_hud_style)
#elif h_hud_style == 'H':
# h_stylekey = date_nhands_ago needs array by player here ...
#if aggregate: always use aggregate query now: use agg_bb_mult of 1 for no aggregation:
query = 'get_stats_from_hand_aggregated'
subs = (hand, hero_id, stylekey, agg_bb_mult, agg_bb_mult, hero_id, h_stylekey, h_agg_bb_mult, h_agg_bb_mult)
#print "agg query subs:", subs
#else:
# query = 'get_stats_from_hand'
# subs = (hand, stylekey)
subs = (hand
,hero_id, stylekey, agg_bb_mult, agg_bb_mult, seats_min, seats_max # hero params
,hero_id, h_stylekey, h_agg_bb_mult, h_agg_bb_mult, h_seats_min, h_seats_max) # villain params
#print "get stats: hud style =", hud_style, "query =", query, "subs =", subs
c = self.connection.cursor()
@ -504,12 +533,15 @@ class Database:
return stat_dict
# uses query on handsplayers instead of hudcache to get stats on just this session
def get_stats_from_hand_session(self, hand, stat_dict, hero_id, hud_style, h_hud_style):
def get_stats_from_hand_session(self, hand, stat_dict, hero_id
,hud_style, seats_min, seats_max
,h_hud_style, h_seats_min, h_seats_max):
"""Get stats for just this session (currently defined as any play in the last 24 hours - to
be improved at some point ...)
h_hud_style and hud_style params indicate whether to get stats for hero and/or others
- only fetch heros stats if h_hud_style == 'S',
and only fetch others stats if hud_style == 'S'
seats_min/max params give seats limits, only include stats if between these values
"""
query = self.sql.query['get_stats_from_hand_session']
@ -518,7 +550,8 @@ class Database:
else:
query = query.replace("<signed>", '')
subs = (self.hand_1day_ago, hand)
subs = (self.hand_1day_ago, hand, hero_id, seats_min, seats_max
, hero_id, h_seats_min, h_seats_max)
c = self.get_cursor()
# now get the stats
@ -533,6 +566,7 @@ class Database:
# Loop through stats adding them to appropriate stat_dict:
while row:
playerid = row[0]
seats = row[1]
if (playerid == hero_id and h_hud_style == 'S') or (playerid != hero_id and hud_style == 'S'):
for name, val in zip(colnames, row):
if not playerid in stat_dict:
@ -544,7 +578,7 @@ class Database:
stat_dict[playerid][name.lower()] += val
n += 1
if n >= 10000: break # todo: don't think this is needed so set nice and high
# for now - comment out or remove?
# prevents infinite loop so leave for now - comment out or remove?
row = c.fetchone()
else:
log.error("ERROR: query %s result does not have player_id as first column" % (query,))
@ -1136,7 +1170,7 @@ class Database:
self.get_cursor().execute( "alter table %s drop index %s"
, (idx['tab'], idx['col']) )
except:
pass
print " drop idx failed: " + str(sys.exc_info())
elif self.backend == self.PGSQL:
print "dropping pg index ", idx['tab'], idx['col']
# mod to use tab_col for index name?
@ -1144,7 +1178,7 @@ class Database:
self.get_cursor().execute( "drop index %s_%s_idx"
% (idx['tab'],idx['col']) )
except:
pass
print " drop idx failed: " + str(sys.exc_info())
else:
print "Only MySQL and Postgres supported so far"
return -1
@ -1152,6 +1186,112 @@ class Database:
self.connection.set_isolation_level(1) # go back to normal isolation level
#end def dropAllIndexes
def createAllForeignKeys(self):
"""Create foreign keys"""
try:
if self.backend == self.PGSQL:
self.connection.set_isolation_level(0) # allow table/index operations to work
c = self.get_cursor()
except:
print " set_isolation_level failed: " + str(sys.exc_info())
for fk in self.foreignKeys[self.backend]:
if self.backend == self.MYSQL_INNODB:
c.execute("SELECT constraint_name " +
"FROM information_schema.KEY_COLUMN_USAGE " +
#"WHERE REFERENCED_TABLE_SCHEMA = 'fpdb'
"WHERE 1=1 " +
"AND table_name = %s AND column_name = %s " +
"AND referenced_table_name = %s " +
"AND referenced_column_name = %s ",
(fk['fktab'], fk['fkcol'], fk['rtab'], fk['rcol']) )
cons = c.fetchone()
#print "afterbulk: cons=", cons
if cons:
pass
else:
print "creating fk ", fk['fktab'], fk['fkcol'], "->", fk['rtab'], fk['rcol']
try:
c.execute("alter table " + fk['fktab'] + " add foreign key ("
+ fk['fkcol'] + ") references " + fk['rtab'] + "("
+ fk['rcol'] + ")")
except:
print " create fk failed: " + str(sys.exc_info())
elif self.backend == self.PGSQL:
print "creating fk ", fk['fktab'], fk['fkcol'], "->", fk['rtab'], fk['rcol']
try:
c.execute("alter table " + fk['fktab'] + " add constraint "
+ fk['fktab'] + '_' + fk['fkcol'] + '_fkey'
+ " foreign key (" + fk['fkcol']
+ ") references " + fk['rtab'] + "(" + fk['rcol'] + ")")
except:
print " create fk failed: " + str(sys.exc_info())
else:
print "Only MySQL and Postgres supported so far"
try:
if self.backend == self.PGSQL:
self.connection.set_isolation_level(1) # go back to normal isolation level
except:
print " set_isolation_level failed: " + str(sys.exc_info())
#end def createAllForeignKeys
def dropAllForeignKeys(self):
"""Drop all standalone indexes (i.e. not including primary keys or foreign keys)
using list of indexes in indexes data structure"""
# maybe upgrade to use data dictionary?? (but take care to exclude PK and FK)
if self.backend == self.PGSQL:
self.connection.set_isolation_level(0) # allow table/index operations to work
c = self.get_cursor()
for fk in self.foreignKeys[self.backend]:
if self.backend == self.MYSQL_INNODB:
c.execute("SELECT constraint_name " +
"FROM information_schema.KEY_COLUMN_USAGE " +
#"WHERE REFERENCED_TABLE_SCHEMA = 'fpdb'
"WHERE 1=1 " +
"AND table_name = %s AND column_name = %s " +
"AND referenced_table_name = %s " +
"AND referenced_column_name = %s ",
(fk['fktab'], fk['fkcol'], fk['rtab'], fk['rcol']) )
cons = c.fetchone()
#print "preparebulk find fk: cons=", cons
if cons:
print "dropping mysql fk", cons[0], fk['fktab'], fk['fkcol']
try:
c.execute("alter table " + fk['fktab'] + " drop foreign key " + cons[0])
except:
print " drop failed: " + str(sys.exc_info())
elif self.backend == self.PGSQL:
# DON'T FORGET TO RECREATE THEM!!
print "dropping pg fk", fk['fktab'], fk['fkcol']
try:
# try to lock table to see if index drop will work:
# hmmm, tested by commenting out rollback in grapher. lock seems to work but
# then drop still hangs :-( does work in some tests though??
# will leave code here for now pending further tests/enhancement ...
c.execute( "lock table %s in exclusive mode nowait" % (fk['fktab'],) )
#print "after lock, status:", c.statusmessage
#print "alter table %s drop constraint %s_%s_fkey" % (fk['fktab'], fk['fktab'], fk['fkcol'])
try:
c.execute("alter table %s drop constraint %s_%s_fkey" % (fk['fktab'], fk['fktab'], fk['fkcol']))
print "dropped pg fk pg fk %s_%s_fkey, continuing ..." % (fk['fktab'], fk['fkcol'])
except:
if "does not exist" not in str(sys.exc_value):
print "warning: drop pg fk %s_%s_fkey failed: %s, continuing ..." \
% (fk['fktab'], fk['fkcol'], str(sys.exc_value).rstrip('\n') )
except:
print "warning: constraint %s_%s_fkey not dropped: %s, continuing ..." \
% (fk['fktab'],fk['fkcol'], str(sys.exc_value).rstrip('\n'))
else:
print "Only MySQL and Postgres supported so far"
if self.backend == self.PGSQL:
self.connection.set_isolation_level(1) # go back to normal isolation level
#end def dropAllForeignKeys
def fillDefaultData(self):
c = self.get_cursor()
c.execute("INSERT INTO Settings (version) VALUES (118);")
@ -1178,6 +1318,12 @@ class Database:
#end def fillDefaultData
def rebuild_indexes(self, start=None):
self.dropAllIndexes()
self.createAllIndexes()
self.dropAllForeignKeys()
self.createAllForeignKeys()
def rebuild_hudcache(self, start=None):
"""clears hudcache and rebuilds from the individual handsplayers records"""
@ -1260,7 +1406,7 @@ class Database:
except:
print "Error during analyze:", str(sys.exc_value)
elif self.backend == self.PGSQL:
self.connection.set_isolation_level(0) # allow vacuum to work
self.connection.set_isolation_level(0) # allow analyze to work
try:
self.get_cursor().execute(self.sql.query['analyze'])
except:
@ -1271,6 +1417,25 @@ class Database:
print "Analyze took %.1f seconds" % (atime,)
#end def analyzeDB
def vacuumDB(self):
"""Do whatever the DB can offer to update index/table statistics"""
stime = time()
if self.backend == self.MYSQL_INNODB:
try:
self.get_cursor().execute(self.sql.query['vacuum'])
except:
print "Error during vacuum:", str(sys.exc_value)
elif self.backend == self.PGSQL:
self.connection.set_isolation_level(0) # allow vacuum to work
try:
self.get_cursor().execute(self.sql.query['vacuum'])
except:
print "Error during vacuum:", str(sys.exc_value)
self.connection.set_isolation_level(1) # go back to normal isolation level
self.commit()
atime = time() - stime
print "Vacuum took %.1f seconds" % (atime,)
#end def analyzeDB
# Start of Hand Writing routines. Idea is to provide a mixture of routines to store Hand data
# however the calling prog requires. Main aims:
@ -1352,7 +1517,9 @@ class Database:
q = q.replace('%s', self.sql.query['placeholder'])
self.cursor.execute(q, (
c = self.get_cursor()
c.execute(q, (
p['tableName'],
p['gameTypeId'],
p['siteHandNo'],
@ -1383,7 +1550,7 @@ class Database:
p['street4Pot'],
p['showdownPot']
))
return self.get_last_insert_id(self.cursor)
return self.get_last_insert_id(c)
# def storeHand
def storeHandsPlayers(self, hid, pids, pdata):
@ -1394,11 +1561,47 @@ class Database:
pids[p],
pdata[p]['startCash'],
pdata[p]['seatNo'],
pdata[p]['card1'],
pdata[p]['card2'],
pdata[p]['card3'],
pdata[p]['card4'],
pdata[p]['card5'],
pdata[p]['card6'],
pdata[p]['card7'],
pdata[p]['winnings'],
pdata[p]['rake'],
pdata[p]['totalProfit'],
pdata[p]['street0VPI'],
pdata[p]['street1Seen'],
pdata[p]['street2Seen'],
pdata[p]['street3Seen'],
pdata[p]['street4Seen'],
pdata[p]['sawShowdown'],
pdata[p]['wonAtSD'],
pdata[p]['street0Aggr'],
pdata[p]['street1Aggr'],
pdata[p]['street2Aggr'],
pdata[p]['street3Aggr'],
pdata[p]['street4Aggr']
pdata[p]['street4Aggr'],
pdata[p]['street1CBChance'],
pdata[p]['street2CBChance'],
pdata[p]['street3CBChance'],
pdata[p]['street4CBChance'],
pdata[p]['street1CBDone'],
pdata[p]['street2CBDone'],
pdata[p]['street3CBDone'],
pdata[p]['street4CBDone'],
pdata[p]['wonWhenSeenStreet1'],
pdata[p]['street0Calls'],
pdata[p]['street1Calls'],
pdata[p]['street2Calls'],
pdata[p]['street3Calls'],
pdata[p]['street4Calls'],
pdata[p]['street0Bets'],
pdata[p]['street1Bets'],
pdata[p]['street2Bets'],
pdata[p]['street3Bets'],
pdata[p]['street4Bets'],
) )
q = """INSERT INTO HandsPlayers (
@ -1406,35 +1609,65 @@ class Database:
playerId,
startCash,
seatNo,
card1,
card2,
card3,
card4,
card5,
card6,
card7,
winnings,
rake,
totalProfit,
street0VPI,
street1Seen,
street2Seen,
street3Seen,
street4Seen,
sawShowdown,
wonAtSD,
street0Aggr,
street1Aggr,
street2Aggr,
street3Aggr,
street4Aggr
street4Aggr,
street1CBChance,
street2CBChance,
street3CBChance,
street4CBChance,
street1CBDone,
street2CBDone,
street3CBDone,
street4CBDone,
wonWhenSeenStreet1,
street0Calls,
street1Calls,
street2Calls,
street3Calls,
street4Calls,
street0Bets,
street1Bets,
street2Bets,
street3Bets,
street4Bets
)
VALUES (
%s, %s, %s, %s, %s,
%s, %s, %s, %s
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s
)"""
# position,
# tourneyTypeId,
# card1,
# card2,
# card3,
# card4,
# startCards,
# winnings,
# rake,
# totalProfit,
# street0VPI,
# street0_3BChance,
# street0_3BDone,
# street1Seen,
# street2Seen,
# street3Seen,
# street4Seen,
# sawShowdown,
# otherRaisedStreet1,
# otherRaisedStreet2,
# otherRaisedStreet3,
@ -1443,22 +1676,12 @@ class Database:
# foldToOtherRaisedStreet2,
# foldToOtherRaisedStreet3,
# foldToOtherRaisedStreet4,
# wonWhenSeenStreet1,
# wonAtSD,
# stealAttemptChance,
# stealAttempted,
# foldBbToStealChance,
# foldedBbToSteal,
# foldSbToStealChance,
# foldedSbToSteal,
# street1CBChance,
# street1CBDone,
# street2CBChance,
# street2CBDone,
# street3CBChance,
# street3CBDone,
# street4CBChance,
# street4CBDone,
# foldToStreet1CBChance,
# foldToStreet1CBDone,
# foldToStreet2CBChance,
@ -1475,21 +1698,13 @@ class Database:
# street3CheckCallRaiseDone,
# street4CheckCallRaiseChance,
# street4CheckCallRaiseDone,
# street0Calls,
# street1Calls,
# street2Calls,
# street3Calls,
# street4Calls,
# street0Bets,
# street1Bets,
# street2Bets,
# street3Bets,
# street4Bets
q = q.replace('%s', self.sql.query['placeholder'])
#print "DEBUG: inserts: %s" %inserts
self.cursor.executemany(q, inserts)
#print "DEBUG: q: %s" % q
c = self.get_cursor()
c.executemany(q, inserts)
def storeHudCacheNew(self, gid, pid, hc):
q = """INSERT INTO HudCache (
@ -1631,6 +1846,15 @@ class Database:
# street4CheckCallRaiseChance,
# street4CheckCallRaiseDone)
def isDuplicate(self, gametypeID, siteHandNo):
dup = False
c = self.get_cursor()
c.execute(self.sql.query['isAlreadyInDB'], (gametypeID, siteHandNo))
result = c.fetchall()
if len(result) > 0:
dup = True
return dup
def getGameTypeId(self, siteid, game):
c = self.get_cursor()
#FIXME: Fixed for NL at the moment
@ -1670,6 +1894,13 @@ class Database:
q = "SELECT name, id FROM Players WHERE siteid=%s and name=%s"
q = q.replace('%s', self.sql.query['placeholder'])
#NOTE/FIXME?: MySQL has ON DUPLICATE KEY UPDATE
#Usage:
# INSERT INTO `tags` (`tag`, `count`)
# VALUES ($tag, 1)
# ON DUPLICATE KEY UPDATE `count`=`count`+1;
#print "DEBUG: name: %s site: %s" %(name, site_id)
c.execute (q, (site_id, name))
@ -2684,14 +2915,14 @@ class HandToWrite:
if __name__=="__main__":
c = Configuration.Config()
db_connection = Database(c, 'fpdb', 'holdem') # mysql fpdb holdem
db_connection = Database(c) # mysql fpdb holdem
# db_connection = Database(c, 'fpdb-p', 'test') # mysql fpdb holdem
# db_connection = Database(c, 'PTrackSv2', 'razz') # mysql razz
# db_connection = Database(c, 'ptracks', 'razz') # postgres
print "database connection object = ", db_connection.connection
print "database type = ", db_connection.type
db_connection.recreate_tables()
# db_connection.recreate_tables()
db_connection.dropAllIndexes()
db_connection.createAllIndexes()
h = db_connection.get_last_hand()
print "last hand = ", h
@ -2704,18 +2935,12 @@ if __name__=="__main__":
for p in stat_dict.keys():
print p, " ", stat_dict[p]
#print "nutOmatics stats:"
#stat_dict = db_connection.get_stats_from_hand(h, "ring")
#for p in stat_dict.keys():
# print p, " ", stat_dict[p]
print "cards =", db_connection.get_cards(u'1')
db_connection.close_connection
print "press enter to continue"
sys.stdin.readline()
#Code borrowed from http://push.cx/2008/caching-dictionaries-in-python-vs-ruby
class LambdaDict(dict):
def __init__(self, l):

View File

@ -1,28 +1,85 @@
"""Database manager
@todo: (gtk) how to validate user input in gtk.Dialog? as soon as the user clicks ok the dialog is dead. we use a while loop as workaround. not nice
@todo: (fpdb) we need the application name 'fpdb' from somewhere to put it in dialog titles
@todo: (fpdb) config object should be initialized globally and accessible from all modules via Configuration.py
@todo: (all dialogs) save/restore size and pos
@todo: (WidgetDatabaseManager) give database status meaningful colors
@todo: (WidgetDatabaseManager) implement database purging
@todo: (WidgetDatabaseManager) implement database export
@todo: (WidgetDatabaseManager) what to do on database doubleclick?
@todo: (WidgetDatabaseManager) context menu for database tree
@todo: (WidgetDatabaseManager) initializing/validating databases may take a while. how to give feedback?
"""
import os
import pygtk
pygtk.require('2.0')
import gtk
import gobject
#*******************************************************************************************************
class DatabaseManager(object):
class DatabaseManager(gobject.GObject):
DatabaseTypes = {}
@classmethod
def from_fpdb(klass, data, defaultDatabaseType=None):
#TODO: parse whatever data is
#TODO: sort out unsupported databases passed by user and log
databases = (
DatabaseTypeSqLite(name='myDb'),
DatabaseTypeSqLite(name='myDb2'),
)
#NOTE: if no databases are present in config fpdb fails with
# Traceback (most recent call last):
# File "/home/me2/Scr/Repos/fpdb-mme/pyfpdb/DatabaseManager.py", line 783, in <module>
# databaseManager = DatabaseManager.from_fpdb('', defaultDatabaseType=DatabaseTypeSqLite)
# File "/home/me2/Scr/Repos/fpdb-mme/pyfpdb/DatabaseManager.py", line 36, in from_fpdb
# config = Configuration.Config(file=options.config, dbname=options.dbname)
# File "/home/me2/Scr/Repos/fpdb-mme/pyfpdb/Configuration.py", line 436, in __init__
# db = self.get_db_parameters()
# File "/home/me2/Scr/Repos/fpdb-mme/pyfpdb/Configuration.py", line 583, in get_db_parameters
# name = self.db_selected
# AttributeError: Config instance has no attribute 'db_selected'
import sys
import Options
import Configuration
#NOTE: fpdb should perform this globally
(options, argv) = Options.fpdb_options()
config = Configuration.Config(file=options.config, dbname=options.dbname)
#TODO: handle no database present
defaultDatabaseName = config.get_db_parameters().get('db-databaseName', None)
#TODO: fpdb stores databases in no particular order. this has to be fixed somehow
databases = []
for name, fpdbDatabase in config.supported_databases.items():
databaseKlass = klass.DatabaseTypes.get(fpdbDatabase.db_server, None)
#NOTE: Config does not seem to validate user input, so anything may end up here
if databaseKlass is None:
raise ValueError('Unknown databasetype: %s' % fpdbDatabase.db_server)
database = databaseKlass()
if database.Type == 'sqlite':
database.name = fpdbDatabase.db_name
database.file = fpdbDatabase.db_server
else:
database.name = fpdbDatabase.db_name
database.host = fpdbDatabase.db_server
#NOTE: fpdbDatabase.db_ip is no is a string
database.port = int(fpdbDatabase.db_ip)
database.user = fpdbDatabase.db_user
database.password = fpdbDatabase.db_pass
databases.append(database)
return klass(databases=databases, defaultDatabaseType=defaultDatabaseType)
def to_fpdb(self):
pass
def __init__(self, databases=None, defaultDatabaseType=None):
gobject.GObject.__init__(self)
self._defaultDatabaseType = defaultDatabaseType
self._databases = [] if databases is None else list(databases)
self._activeDatabase = None
def __iter__(self):
return iter(self._databases)
def set_default_database_type(self, databaseType):
@ -31,7 +88,7 @@ class DatabaseManager(object):
return self._defaultDatabaseType
def database_from_id(self, idDatabase):
for database in self._databases:
if idDatabase == id(database):
if idDatabase == self.database_id(database):
return database
def database_id(self, database):
return id(database)
@ -41,8 +98,26 @@ class DatabaseManager(object):
self._databases.append(database)
def remove_database(self, database):
self._databases.remove(database)
def init_database(self, database):
pass
def activate_database(self, database):
if self._activeDatabase is not None:
self._activeDatabase.status = self._activeDatabase.StatusInactive
#TODO: finalize database
self.emit('database-deactivated', self.database_id(self._activeDatabase) )
database.status = database.StatusActive
#TODO: activate database
self._activeDatabase = database
self.emit('database-activated', self.database_id(database) )
def active_database(self):
return self._activeDatabase
# register DatabaseManager signals
gobject.type_register(DatabaseManager)
gobject.signal_new('database-activated', DatabaseManager, gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (int, ))
gobject.signal_new('database-deactivated', DatabaseManager, gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (int, ))
gobject.signal_new('database-error', DatabaseManager, gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (int, ))
class DatabaseTypeMeta(type):
def __new__(klass, name, bases, kws):
@ -56,10 +131,25 @@ class DatabaseTypeMeta(type):
class DatabaseTypeBase(object):
__metaclass__ = DatabaseTypeMeta
Type = None
Params = ()
StatusActive = 'active'
StatusInactive = 'inactive'
StatusError = 'error' #TODO: not implemented
#TODO: not happy with returning error string. just being too lazy to impl dozens of error codes for later translation
def init_new_database(self):
"""initializes a new empty database
@return: (str) error if something goes wrong, None otherwise
"""
raise NotImplementedError()
def validate_database(self):
"""checks if the database is valid
@return: (str) error if something goes wrong, None otherwise
"""
raise NotImplementedError()
class DatabaseTypePostgres(DatabaseTypeBase):
Type = 'postgres'
Type = 'postgresql'
@classmethod
def display_name(klass):
return 'Postgres'
@ -70,6 +160,15 @@ class DatabaseTypePostgres(DatabaseTypeBase):
self.user = user
self.password = password
self.database = database
self.status = self.StatusInactive
#TODO: implement
def init_new_database(self):
pass
#TODO: implement
def validate_database(self):
pass
class DatabaseTypeMysql(DatabaseTypeBase):
Type = 'mysql'
@ -83,6 +182,16 @@ class DatabaseTypeMysql(DatabaseTypeBase):
self.user = user
self.password = password
self.database = database
self.status = self.StatusInactive
#TODO: implement
def init_new_database(self):
pass
#TODO: implement
def validate_database(self):
pass
class DatabaseTypeSqLite(DatabaseTypeBase):
Type = 'sqlite'
@ -92,7 +201,26 @@ class DatabaseTypeSqLite(DatabaseTypeBase):
def __init__(self, name='', host='', file='', database='fpdb'):
self.name = name
self.file = file
self.database = database
self.status = self.StatusInactive
def init_new_database(self):
# make shure all attrs are specified
if not self.file:
return 'no database file specified'
# create file if necessary (this will truncate file if it exists)
try:
open(self.file, 'w').close()
except IOError:
return 'can not write file'
#TODO: init tables (...)
def validate_database(self):
pass
#TODO: check if tables (...) exist
#TODO: how do we want to handle unsupported database types?
# ..uncomment to remove unsupported database types
@ -104,6 +232,20 @@ class DatabaseTypeSqLite(DatabaseTypeBase):
#except ImportError: del DatabaseManager.DatabaseTypes['sqlite']
#***************************************************************************************************************************
#TODO: there is no title (on linux), wtf?
def DialogError(parent=None, msg=''):
dlg = gtk.MessageDialog(
parent=parent,
flags=gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
type=gtk.MESSAGE_ERROR,
buttons=gtk.BUTTONS_OK,
message_format=msg,
)
dlg.run()
dlg.destroy()
return None
#TODO: derrive from gtk.VBox?
class WidgetDatabaseProperties(gtk.VBox):
@ -158,7 +300,7 @@ class WidgetDatabaseProperties(gtk.VBox):
dlg.destroy()
#TODO: bit ugly this thingy. try to find a better way to map database attrs to gtk widgets
class FieldWidget(object):
def __init__(self, text='', attrDatabase='', widget=None, attrGet=None, attrSet=None, defaultValue=None, canEdit=False, tooltip=''):
"""
@ -212,16 +354,6 @@ class WidgetDatabaseProperties(gtk.VBox):
canEdit=True,
tooltip='Any name you like to name the database '
),
self.FieldWidget(
text='Db:',
attrDatabase='database',
widget=gtk.Entry(),
defaultValue='',
attrGet='get_text',
attrSet='set_text',
canEdit=False,
tooltip='Name of the database to create'
),
self.FieldWidget(
text='File:',
attrDatabase='file',
@ -272,6 +404,16 @@ class WidgetDatabaseProperties(gtk.VBox):
canEdit=False,
tooltip='Password used to login to the host'
),
self.FieldWidget(
text='Db:',
attrDatabase='database',
widget=gtk.Entry(),
defaultValue='',
attrGet='get_text',
attrSet='set_text',
canEdit=False,
tooltip='Name of the database'
),
)
# setup database type combo
@ -372,11 +514,22 @@ class DialogDatabaseProperties(gtk.Dialog):
#TODO: derrive from gtk.VBox?
# ..is there a way to derrive from gtk.Widget or similar? this would make parentWidget kw obsolete
class WidgetDatabaseManager(gtk.VBox):
"""
"""
def __init__(self, databaseManager, parentWidget=None):
gtk.VBox.__init__(self)
self.databaseManager = databaseManager
self.parentWidget = parentWidget
self.databaseManager = databaseManager
self.databaseManager.connect('database-activated', self.on_database_manager_database_activated)
self.databaseManager.connect('database-deactivated', self.on_database_manager_database_deactivated)
self.databaseStatusNames = {
DatabaseTypeBase.StatusActive: 'Active',
DatabaseTypeBase.StatusInactive: 'Inactive',
DatabaseTypeBase.StatusError: 'Error',
}
#TODO: dono how to make word wrap work as expected
self.labelInfo = gtk.Label('database management')
@ -389,6 +542,10 @@ class WidgetDatabaseManager(gtk.VBox):
#TODO: bit messy the distinction New/Add/Edit. we'd have to pass three flags to DialogDatabaseProperties
# to handle this. maybe drop Edit (is just a Remove + Add), to keep things simple
self.buttonDatabaseActivate = gtk.Button("Activate")
self.buttonDatabaseActivate.set_tooltip_text('activates the database')
self.buttonDatabaseActivate.connect('clicked', self.on_button_database_activate_clicked)
self.buttonDatabaseActivate.set_sensitive(False)
self.buttonDatabaseNew = gtk.Button("New..")
self.buttonDatabaseNew.set_tooltip_text('creates a new database')
self.buttonDatabaseNew.connect('clicked', self.on_button_database_new_clicked)
@ -402,31 +559,30 @@ class WidgetDatabaseManager(gtk.VBox):
self.buttonDatabaseRemove = gtk.Button("Remove")
self.buttonDatabaseRemove.set_tooltip_text('removes the database from the list')
self.buttonDatabaseRemove.set_sensitive(False)
self.buttonDatabaseRemove.connect('clicked', self.on_button_database_remove_clicked)
#TODO: i dont think we should do any real database management here. maybe drop it
self.buttonDatabaseDelete = gtk.Button("Delete")
self.buttonDatabaseDelete.set_tooltip_text('removes the database from the list and deletes it')
self.buttonDatabaseDelete.set_sensitive(False)
#self.buttonDatabaseDelete = gtk.Button("Delete")
#self.buttonDatabaseDelete.set_tooltip_text('removes the database from the list and deletes it')
#self.buttonDatabaseDelete.set_sensitive(False)
# init database tree
self.treeDatabases = gtk.TreeView()
self.treeDatabaseColumns = ( #NOTE: column names starting with '_' will be hidden
'Name',
'Status',
'Type',
'_id',
treeDatabaseColumns = ( # name, displayName, dataType
('name', 'Name', str),
('status', 'Status', str),
('type', 'Type', str),
('_id', '', int),
)
store = gtk.ListStore(str, str, str, int)
self.treeDatabaseColumns = {} # name --> index
store = gtk.ListStore( *[i[2] for i in treeDatabaseColumns] )
self.treeDatabases.set_model(store)
columns = ('Name', 'Status', 'Type', '_id')
for i, column in enumerate(columns):
col = gtk.TreeViewColumn(column, gtk.CellRendererText(), text=i)
for i, (name, displayName, dataType) in enumerate(treeDatabaseColumns):
col = gtk.TreeViewColumn(displayName, gtk.CellRendererText(), text=i)
self.treeDatabases.append_column(col)
if column.startswith('_'):
if name.startswith('_'):
col.set_visible(False)
self.treeDatabaseColumns = dict([(name, i) for (i, name) in enumerate(self.treeDatabaseColumns)])
self.treeDatabaseColumns[name] = i
self.treeDatabases.get_selection().connect('changed', self.on_tree_databases_selection_changed)
# layout widgets
@ -438,11 +594,12 @@ class WidgetDatabaseManager(gtk.VBox):
hbox.set_homogeneous(False)
vbox = gtk.VBox()
hbox.pack_start(vbox, False, False, 2)
vbox.pack_start(self.buttonDatabaseActivate, False, False, 2)
vbox.pack_start(self.buttonDatabaseNew, False, False, 2)
vbox.pack_start(self.buttonDatabaseAdd, False, False, 2)
vbox.pack_start(self.buttonDatabaseEdit, False, False, 2)
vbox.pack_start(self.buttonDatabaseRemove, False, False, 2)
vbox.pack_start(self.buttonDatabaseDelete, False, False, 2)
#vbox.pack_start(self.buttonDatabaseDelete, False, False, 2)
box = gtk.VBox()
vbox.pack_start(box, True, True, 0)
@ -452,48 +609,128 @@ class WidgetDatabaseManager(gtk.VBox):
self.show_all()
# init widget
model = self.treeDatabases.get_model()
for database in self.databaseManager:
self.treeDatabases.get_model().append( (database.name, 'foo', database.Type, self.databaseManager.database_id(database)) )
it = model.append()
model.set_value(it, self.treeDatabaseColumns['name'], database.name)
model.set_value(it, self.treeDatabaseColumns['status'], self.databaseStatusNames[database.status] )
model.set_value(it, self.treeDatabaseColumns['type'], database.display_name() )
model.set_value(it, self.treeDatabaseColumns['_id'], self.databaseManager.database_id(database))
def on_database_manager_database_activated(self, databaseManager, idDatabase):
database = self.databaseManager.database_from_id(idDatabase)
model = self.treeDatabases.get_model()
for row in iter(model):
if row[self.treeDatabaseColumns['_id']] == idDatabase:
row[self.treeDatabaseColumns['status']] = self.databaseStatusNames[database.StatusActive]
break
else:
raise ValueError('database not found')
def on_database_manager_database_deactivated(self, databaseManager, idDatabase):
database = self.databaseManager.database_from_id(idDatabase)
model = self.treeDatabases.get_model()
for row in iter(model):
if row[self.treeDatabaseColumns['_id']] == idDatabase:
row[self.treeDatabaseColumns['status']] = self.databaseStatusNames[database.StatusInactive]
break
else:
raise ValueError('database not found')
def on_button_database_activate_clicked(self, button):
selection = self.treeDatabases.get_selection()
if selection is None:
return
model, it = selection.get_selected()
idDatabase = model.get_value(it, self.treeDatabaseColumns['_id'])
database = self.databaseManager.database_from_id(idDatabase)
self.databaseManager.activate_database(database)
#TODO: for some reason i have to click OK/Cancel twice to close the dialog
def on_button_database_new_clicked(self, button):
databaseType = self.databaseManager.get_default_database_type()
if databaseType is None:
raise ValueError('no defult database type set')
databaseKlass = self.databaseManager.get_default_database_type()
if databaseKlass is None:
raise ValueError('no default database type set')
database = databaseKlass()
while True:
dlg = DialogDatabaseProperties(
self.databaseManager,
databaseType(),
database,
parent=self.parentWidget,
mode=WidgetDatabaseProperties.ModeNew,
title='[New database] - database properties'
title='New database'
)
if dlg.run() == gtk.RESPONSE_REJECT:
pass
if dlg.run() == gtk.RESPONSE_ACCEPT:
response = dlg.run()
if response == gtk.RESPONSE_ACCEPT:
database = dlg.get_widget_database_properties().get_database()
#TODO: sanity checks + init databse if necessary
self.databaseManager.add_database(database)
self.treeDatabases.get_model().append( (database.name, 'foo', database.Type, self.databaseManager.database_id(database)) )
#TODO: initing may or may not take a while. how to handle?
error = database.init_new_database()
if error:
DialogError(parent=dlg, msg=error)
dlg.destroy()
continue
else:
database = None
dlg.destroy()
break
if database is None:
return
self.databaseManager.add_database(database)
model = self.treeDatabases.get_model()
it = model.append()
model.set_value(it, self.treeDatabaseColumns['name'], database.name)
model.set_value(it, self.treeDatabaseColumns['status'], self.databaseStatusNames[database.status] )
model.set_value(it, self.treeDatabaseColumns['type'], database.display_name() )
model.set_value(it, self.treeDatabaseColumns['_id'], self.databaseManager.database_id(database))
def on_button_database_add_clicked(self, button):
databaseType = self.databaseManager.get_default_database_type()
if databaseType is None:
databaseKlass = self.databaseManager.get_default_database_type()
if databaseKlass is None:
raise ValueError('no defult database type set')
database = databaseKlass()
while True:
dlg = DialogDatabaseProperties(
self.databaseManager,
databaseType(),
database,
parent=self.parentWidget,
mode=WidgetDatabaseProperties.ModeAdd,
title='[Add database] - database properties'
title='Add database'
)
if dlg.run() == gtk.RESPONSE_REJECT:
pass
if dlg.run() == gtk.RESPONSE_ACCEPT:
response = dlg.run()
if response == gtk.RESPONSE_ACCEPT:
database = dlg.get_widget_database_properties().get_database()
#TODO: sanity checks
#TODO: validating may or may not take a while. how to handle?
error = database.validate_database()
if error:
DialogError(parent=self.parentWidget, msg=error)
dlg.destroy()
continue
else:
database = None
dlg.destroy()
break
if database is None:
return
self.databaseManager.add_database(database)
self.treeDatabases.get_model().append( (database.name, 'foo', database.Type, self.databaseManager.database_id(database)) )
model = self.treeDatabases.get_model()
it = model.append()
model.set_value(it, self.treeDatabaseColumns['name'], database.name)
model.set_value(it, self.treeDatabaseColumns['status'], self.databaseStatusNames[database.status] )
model.set_value(it, self.treeDatabaseColumns['type'], database.display_name() )
model.set_value(it, self.treeDatabaseColumns['_id'], self.databaseManager.database_id(database))
dlg.destroy()
def on_button_database_edit_clicked(self, button):
@ -501,39 +738,52 @@ class WidgetDatabaseManager(gtk.VBox):
if selection is None:
return
model, iter = selection.get_selected()
idDatabase = model.get_value(iter, self.treeDatabaseColumns['_id'])
model, it = selection.get_selected()
idDatabase = model.get_value(it, self.treeDatabaseColumns['_id'])
database = self.databaseManager.database_from_id(idDatabase)
dlg = DialogDatabaseProperties(
self.databaseManager,
database=database,
database,
parent=self.parentWidget,
mode=WidgetDatabaseProperties.ModeEdit,
title='[Edit database] - database properties'
title='Edit database'
)
if dlg.run() == gtk.RESPONSE_REJECT:
response = dlg.run()
if response == gtk.RESPONSE_REJECT:
pass
if dlg.run() == gtk.RESPONSE_ACCEPT:
elif response == gtk.RESPONSE_ACCEPT:
database = dlg.get_database()
selection = self.treeDatabases.get_selection()
if selection is not None:
model, iter = selection.get_selected()
model.set_value(iter, 0, database.name)
model, it = selection.get_selected()
model.set_value(it, self.treeDatabaseColumns['name'], database.name)
dlg.destroy()
def on_button_database_remove_clicked(self, button):
selection = self.treeDatabases.get_selection()
if selection is None:
return
model, it = selection.get_selected()
#TODO: finalize database
model.remove(it)
def on_tree_databases_selection_changed(self, treeSelection):
hasSelection = bool(treeSelection.count_selected_rows())
# enable/disable selection dependend widgets
self.buttonDatabaseActivate.set_sensitive(hasSelection)
self.buttonDatabaseEdit.set_sensitive(hasSelection)
self.buttonDatabaseRemove.set_sensitive(hasSelection)
self.buttonDatabaseDelete.set_sensitive(hasSelection)
#self.buttonDatabaseDelete.set_sensitive(hasSelection)
class DialogDatabaseManager(gtk.Dialog):
def __init__(self, databaseManager, parent=None):
gtk.Dialog.__init__(self,
title="My dialog",
title="Databases",
parent=parent,
flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
buttons=(
@ -558,5 +808,3 @@ if __name__ == '__main__':
d.connect("destroy", gtk.main_quit)
d.run()
#gtk.main()

View File

@ -18,6 +18,13 @@
#fpdb modules
import Card
DEBUG = False
if DEBUG:
import pprint
pp = pprint.PrettyPrinter(indent=4)
class DerivedStats():
def __init__(self, hand):
self.hand = hand
@ -30,13 +37,31 @@ class DerivedStats():
for player in hand.players:
self.handsplayers[player[1]] = {}
#Init vars that may not be used, but still need to be inserted.
# All stud street4 need this when importing holdem
self.handsplayers[player[1]]['winnings'] = 0
self.handsplayers[player[1]]['rake'] = 0
self.handsplayers[player[1]]['totalProfit'] = 0
self.handsplayers[player[1]]['street4Seen'] = False
self.handsplayers[player[1]]['street4Aggr'] = False
self.handsplayers[player[1]]['wonWhenSeenStreet1'] = False
self.handsplayers[player[1]]['sawShowdown'] = False
self.handsplayers[player[1]]['wonAtSD'] = False
for i in range(5):
self.handsplayers[player[1]]['street%dCalls' % i] = 0
self.handsplayers[player[1]]['street%dBets' % i] = 0
for i in range(1,5):
self.handsplayers[player[1]]['street%dCBChance' %i] = False
self.handsplayers[player[1]]['street%dCBDone' %i] = False
self.assembleHands(self.hand)
self.assembleHandsPlayers(self.hand)
print "hands =", self.hands
print "handsplayers =", self.handsplayers
if DEBUG:
print "Hands:"
pp.pprint(self.hands)
print "HandsPlayers:"
pp.pprint(self.handsplayers)
def getHands(self):
return self.hands
@ -68,12 +93,13 @@ class DerivedStats():
self.hands['boardcard5'] = cards[4]
#print "DEBUG: self.getStreetTotals = (%s, %s, %s, %s, %s)" % hand.getStreetTotals()
#FIXME: Pot size still in decimal, needs to be converted to cents
(self.hands['street1Pot'],
self.hands['street2Pot'],
self.hands['street3Pot'],
self.hands['street4Pot'],
self.hands['showdownPot']) = hand.getStreetTotals()
totals = hand.getStreetTotals()
totals = [int(100*i) for i in totals]
self.hands['street1Pot'] = totals[0]
self.hands['street2Pot'] = totals[1]
self.hands['street3Pot'] = totals[2]
self.hands['street4Pot'] = totals[3]
self.hands['showdownPot'] = totals[4]
self.vpip(hand) # Gives playersVpi (num of players vpip)
#print "DEBUG: vpip: %s" %(self.hands['playersVpi'])
@ -81,707 +107,49 @@ class DerivedStats():
#print "DEBUG: playersAtStreet 1:'%s' 2:'%s' 3:'%s' 4:'%s'" %(self.hands['playersAtStreet1'],self.hands['playersAtStreet2'],self.hands['playersAtStreet3'],self.hands['playersAtStreet4'])
self.streetXRaises(hand) # Empty function currently
# comment TEXT,
# commentTs DATETIME
def assembleHandsPlayers(self, hand):
#street0VPI/vpip already called in Hand
# sawShowdown is calculated in playersAtStreetX, as that calculation gives us a convenient list of names
#hand.players = [[seat, name, chips],[seat, name, chips]]
for player in hand.players:
self.handsplayers[player[1]]['seatNo'] = player[0]
self.handsplayers[player[1]]['startCash'] = player[2]
for i, street in enumerate(hand.actionStreets[2:]):
self.seen(self.hand, i+1)
for i, street in enumerate(hand.actionStreets[1:]):
self.aggr(self.hand, i)
self.calls(self.hand, i)
self.bets(self.hand, i)
# Winnings is a non-negative value of money collected from the pot, which already includes the
# rake taken out. hand.collectees is Decimal, database requires cents
for player in hand.collectees:
self.handsplayers[player]['winnings'] = int(100 * hand.collectees[player])
#FIXME: This is pretty dodgy, rake = hand.rake/#collectees
# You can really only pay rake when you collect money, but
# different sites calculate rake differently.
# Should be fine for split-pots, but won't be accurate for multi-way pots
self.handsplayers[player]['rake'] = int(100* hand.rake)/len(hand.collectees)
if self.handsplayers[player]['street1Seen'] == True:
self.handsplayers[player]['wonWhenSeenStreet1'] = True
if self.handsplayers[player]['sawShowdown'] == True:
self.handsplayers[player]['wonAtSD'] = True
for player in hand.pot.committed:
self.handsplayers[player]['totalProfit'] = int(self.handsplayers[player]['winnings'] - (100*hand.pot.committed[player]))
self.calcCBets(hand)
for player in hand.players:
hcs = hand.join_holecards(player[1], asList=True)
hcs = hcs + [u'0x', u'0x', u'0x', u'0x', u'0x']
for i, card in enumerate(hcs[:7], 1):
self.handsplayers[player[1]]['card%s' % i] = Card.encodeCard(card)
def assembleHudCache(self, hand):
# # def generateHudCacheData(player_ids, base, category, action_types, allIns, actionTypeByNo
# # ,winnings, totalWinnings, positions, actionTypes, actionAmounts, antes):
# #"""calculates data for the HUD during import. IMPORTANT: if you change this method make
# # sure to also change the following storage method and table_viewer.prepare_data if necessary
# #"""
# #print "generateHudCacheData, len(player_ids)=", len(player_ids)
# #setup subarrays of the result dictionary.
# street0VPI=[]
# street0Aggr=[]
# street0_3BChance=[]
# street0_3BDone=[]
# street1Seen=[]
# street2Seen=[]
# street3Seen=[]
# street4Seen=[]
# sawShowdown=[]
# street1Aggr=[]
# street2Aggr=[]
# street3Aggr=[]
# street4Aggr=[]
# otherRaisedStreet1=[]
# otherRaisedStreet2=[]
# otherRaisedStreet3=[]
# otherRaisedStreet4=[]
# foldToOtherRaisedStreet1=[]
# foldToOtherRaisedStreet2=[]
# foldToOtherRaisedStreet3=[]
# foldToOtherRaisedStreet4=[]
# wonWhenSeenStreet1=[]
#
# wonAtSD=[]
# stealAttemptChance=[]
# stealAttempted=[]
# hudDataPositions=[]
#
# street0Calls=[]
# street1Calls=[]
# street2Calls=[]
# street3Calls=[]
# street4Calls=[]
# street0Bets=[]
# street1Bets=[]
# street2Bets=[]
# street3Bets=[]
# street4Bets=[]
# #street0Raises=[]
# #street1Raises=[]
# #street2Raises=[]
# #street3Raises=[]
# #street4Raises=[]
#
# # Summary figures for hand table:
# result={}
# result['playersVpi']=0
# result['playersAtStreet1']=0
# result['playersAtStreet2']=0
# result['playersAtStreet3']=0
# result['playersAtStreet4']=0
# result['playersAtShowdown']=0
# result['street0Raises']=0
# result['street1Raises']=0
# result['street2Raises']=0
# result['street3Raises']=0
# result['street4Raises']=0
# result['street1Pot']=0
# result['street2Pot']=0
# result['street3Pot']=0
# result['street4Pot']=0
# result['showdownPot']=0
#
# firstPfRaiseByNo=-1
# firstPfRaiserId=-1
# firstPfRaiserNo=-1
# firstPfCallByNo=-1
# firstPfCallerId=-1
#
# for i, action in enumerate(actionTypeByNo[0]):
# if action[1] == "bet":
# firstPfRaiseByNo = i
# firstPfRaiserId = action[0]
# for j, pid in enumerate(player_ids):
# if pid == firstPfRaiserId:
# firstPfRaiserNo = j
# break
# break
# for i, action in enumerate(actionTypeByNo[0]):
# if action[1] == "call":
# firstPfCallByNo = i
# firstPfCallerId = action[0]
# break
# firstPlayId = firstPfCallerId
# if firstPfRaiseByNo <> -1:
# if firstPfRaiseByNo < firstPfCallByNo or firstPfCallByNo == -1:
# firstPlayId = firstPfRaiserId
#
#
# cutoffId=-1
# buttonId=-1
# sbId=-1
# bbId=-1
# if base=="hold":
# for player, pos in enumerate(positions):
# if pos == 1:
# cutoffId = player_ids[player]
# if pos == 0:
# buttonId = player_ids[player]
# if pos == 'S':
# sbId = player_ids[player]
# if pos == 'B':
# bbId = player_ids[player]
#
# someoneStole=False
#
# #run a loop for each player preparing the actual values that will be commited to SQL
# for player in xrange(len(player_ids)):
# #set default values
# myStreet0VPI=False
# myStreet0Aggr=False
# myStreet0_3BChance=False
# myStreet0_3BDone=False
# myStreet1Seen=False
# myStreet2Seen=False
# myStreet3Seen=False
# myStreet4Seen=False
# mySawShowdown=False
# myStreet1Aggr=False
# myStreet2Aggr=False
# myStreet3Aggr=False
# myStreet4Aggr=False
# myOtherRaisedStreet1=False
# myOtherRaisedStreet2=False
# myOtherRaisedStreet3=False
# myOtherRaisedStreet4=False
# myFoldToOtherRaisedStreet1=False
# myFoldToOtherRaisedStreet2=False
# myFoldToOtherRaisedStreet3=False
# myFoldToOtherRaisedStreet4=False
# myWonWhenSeenStreet1=0.0
# myWonAtSD=0.0
# myStealAttemptChance=False
# myStealAttempted=False
# myStreet0Calls=0
# myStreet1Calls=0
# myStreet2Calls=0
# myStreet3Calls=0
# myStreet4Calls=0
# myStreet0Bets=0
# myStreet1Bets=0
# myStreet2Bets=0
# myStreet3Bets=0
# myStreet4Bets=0
# #myStreet0Raises=0
# #myStreet1Raises=0
# #myStreet2Raises=0
# #myStreet3Raises=0
# #myStreet4Raises=0
#
# #calculate VPIP and PFR
# street=0
# heroPfRaiseCount=0
# for currentAction in action_types[street][player]: # finally individual actions
# if currentAction == "bet":
# myStreet0Aggr = True
# if currentAction == "bet" or currentAction == "call":
# myStreet0VPI = True
#
# if myStreet0VPI:
# result['playersVpi'] += 1
# myStreet0Calls = action_types[street][player].count('call')
# myStreet0Bets = action_types[street][player].count('bet')
# # street0Raises = action_types[street][player].count('raise') bet count includes raises for now
# result['street0Raises'] += myStreet0Bets
#
# #PF3BChance and PF3B
# pfFold=-1
# pfRaise=-1
# if firstPfRaiseByNo != -1:
# for i, actionType in enumerate(actionTypeByNo[0]):
# if actionType[0] == player_ids[player]:
# if actionType[1] == "bet" and pfRaise == -1 and i > firstPfRaiseByNo:
# pfRaise = i
# if actionType[1] == "fold" and pfFold == -1:
# pfFold = i
# if pfFold == -1 or pfFold > firstPfRaiseByNo:
# myStreet0_3BChance = True
# if pfRaise > firstPfRaiseByNo:
# myStreet0_3BDone = True
#
# #steal calculations
# if base=="hold":
# if len(player_ids)>=3: # no point otherwise # was 5, use 3 to match pokertracker definition
# if positions[player]==1:
# if firstPfRaiserId==player_ids[player] \
# and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo):
# myStealAttempted=True
# myStealAttemptChance=True
# if firstPlayId==cutoffId or firstPlayId==buttonId or firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1:
# myStealAttemptChance=True
# if positions[player]==0:
# if firstPfRaiserId==player_ids[player] \
# and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo):
# myStealAttempted=True
# myStealAttemptChance=True
# if firstPlayId==buttonId or firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1:
# myStealAttemptChance=True
# if positions[player]=='S':
# if firstPfRaiserId==player_ids[player] \
# and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo):
# myStealAttempted=True
# myStealAttemptChance=True
# if firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1:
# myStealAttemptChance=True
# if positions[player]=='B':
# pass
#
# if myStealAttempted:
# someoneStole=True
#
#
# #calculate saw* values
# isAllIn = False
# if any(i for i in allIns[0][player]):
# isAllIn = True
# if (len(action_types[1][player])>0 or isAllIn):
# myStreet1Seen = True
#
# if any(i for i in allIns[1][player]):
# isAllIn = True
# if (len(action_types[2][player])>0 or isAllIn):
# myStreet2Seen = True
#
# if any(i for i in allIns[2][player]):
# isAllIn = True
# if (len(action_types[3][player])>0 or isAllIn):
# myStreet3Seen = True
#
# #print "base:", base
# if base=="hold":
# mySawShowdown = True
# if any(actiontype == "fold" for actiontype in action_types[3][player]):
# mySawShowdown = False
# else:
# #print "in else"
# if any(i for i in allIns[3][player]):
# isAllIn = True
# if (len(action_types[4][player])>0 or isAllIn):
# #print "in if"
# myStreet4Seen = True
#
# mySawShowdown = True
# if any(actiontype == "fold" for actiontype in action_types[4][player]):
# mySawShowdown = False
#
# if myStreet1Seen:
# result['playersAtStreet1'] += 1
# if myStreet2Seen:
# result['playersAtStreet2'] += 1
# if myStreet3Seen:
# result['playersAtStreet3'] += 1
# if myStreet4Seen:
# result['playersAtStreet4'] += 1
# if mySawShowdown:
# result['playersAtShowdown'] += 1
#
# #flop stuff
# street=1
# if myStreet1Seen:
# if any(actiontype == "bet" for actiontype in action_types[street][player]):
# myStreet1Aggr = True
#
# myStreet1Calls = action_types[street][player].count('call')
# myStreet1Bets = action_types[street][player].count('bet')
# # street1Raises = action_types[street][player].count('raise') bet count includes raises for now
# result['street1Raises'] += myStreet1Bets
#
# for otherPlayer in xrange(len(player_ids)):
# if player==otherPlayer:
# pass
# else:
# for countOther in xrange(len(action_types[street][otherPlayer])):
# if action_types[street][otherPlayer][countOther]=="bet":
# myOtherRaisedStreet1=True
# for countOtherFold in xrange(len(action_types[street][player])):
# if action_types[street][player][countOtherFold]=="fold":
# myFoldToOtherRaisedStreet1=True
#
# #turn stuff - copy of flop with different vars
# street=2
# if myStreet2Seen:
# if any(actiontype == "bet" for actiontype in action_types[street][player]):
# myStreet2Aggr = True
#
# myStreet2Calls = action_types[street][player].count('call')
# myStreet2Bets = action_types[street][player].count('bet')
# # street2Raises = action_types[street][player].count('raise') bet count includes raises for now
# result['street2Raises'] += myStreet2Bets
#
# for otherPlayer in xrange(len(player_ids)):
# if player==otherPlayer:
# pass
# else:
# for countOther in xrange(len(action_types[street][otherPlayer])):
# if action_types[street][otherPlayer][countOther]=="bet":
# myOtherRaisedStreet2=True
# for countOtherFold in xrange(len(action_types[street][player])):
# if action_types[street][player][countOtherFold]=="fold":
# myFoldToOtherRaisedStreet2=True
#
# #river stuff - copy of flop with different vars
# street=3
# if myStreet3Seen:
# if any(actiontype == "bet" for actiontype in action_types[street][player]):
# myStreet3Aggr = True
#
# myStreet3Calls = action_types[street][player].count('call')
# myStreet3Bets = action_types[street][player].count('bet')
# # street3Raises = action_types[street][player].count('raise') bet count includes raises for now
# result['street3Raises'] += myStreet3Bets
#
# for otherPlayer in xrange(len(player_ids)):
# if player==otherPlayer:
# pass
# else:
# for countOther in xrange(len(action_types[street][otherPlayer])):
# if action_types[street][otherPlayer][countOther]=="bet":
# myOtherRaisedStreet3=True
# for countOtherFold in xrange(len(action_types[street][player])):
# if action_types[street][player][countOtherFold]=="fold":
# myFoldToOtherRaisedStreet3=True
#
# #stud river stuff - copy of flop with different vars
# street=4
# if myStreet4Seen:
# if any(actiontype == "bet" for actiontype in action_types[street][player]):
# myStreet4Aggr=True
#
# myStreet4Calls = action_types[street][player].count('call')
# myStreet4Bets = action_types[street][player].count('bet')
# # street4Raises = action_types[street][player].count('raise') bet count includes raises for now
# result['street4Raises'] += myStreet4Bets
#
# for otherPlayer in xrange(len(player_ids)):
# if player==otherPlayer:
# pass
# else:
# for countOther in xrange(len(action_types[street][otherPlayer])):
# if action_types[street][otherPlayer][countOther]=="bet":
# myOtherRaisedStreet4=True
# for countOtherFold in xrange(len(action_types[street][player])):
# if action_types[street][player][countOtherFold]=="fold":
# myFoldToOtherRaisedStreet4=True
#
# if winnings[player] != 0:
# if myStreet1Seen:
# myWonWhenSeenStreet1 = winnings[player] / float(totalWinnings)
# if mySawShowdown:
# myWonAtSD=myWonWhenSeenStreet1
#
# #add each value to the appropriate array
# street0VPI.append(myStreet0VPI)
# street0Aggr.append(myStreet0Aggr)
# street0_3BChance.append(myStreet0_3BChance)
# street0_3BDone.append(myStreet0_3BDone)
# street1Seen.append(myStreet1Seen)
# street2Seen.append(myStreet2Seen)
# street3Seen.append(myStreet3Seen)
# street4Seen.append(myStreet4Seen)
# sawShowdown.append(mySawShowdown)
# street1Aggr.append(myStreet1Aggr)
# street2Aggr.append(myStreet2Aggr)
# street3Aggr.append(myStreet3Aggr)
# street4Aggr.append(myStreet4Aggr)
# otherRaisedStreet1.append(myOtherRaisedStreet1)
# otherRaisedStreet2.append(myOtherRaisedStreet2)
# otherRaisedStreet3.append(myOtherRaisedStreet3)
# otherRaisedStreet4.append(myOtherRaisedStreet4)
# foldToOtherRaisedStreet1.append(myFoldToOtherRaisedStreet1)
# foldToOtherRaisedStreet2.append(myFoldToOtherRaisedStreet2)
# foldToOtherRaisedStreet3.append(myFoldToOtherRaisedStreet3)
# foldToOtherRaisedStreet4.append(myFoldToOtherRaisedStreet4)
# wonWhenSeenStreet1.append(myWonWhenSeenStreet1)
# wonAtSD.append(myWonAtSD)
# stealAttemptChance.append(myStealAttemptChance)
# stealAttempted.append(myStealAttempted)
# if base=="hold":
# pos=positions[player]
# if pos=='B':
# hudDataPositions.append('B')
# elif pos=='S':
# hudDataPositions.append('S')
# elif pos==0:
# hudDataPositions.append('D')
# elif pos==1:
# hudDataPositions.append('C')
# elif pos>=2 and pos<=4:
# hudDataPositions.append('M')
# elif pos>=5 and pos<=8:
# hudDataPositions.append('E')
# ### RHH Added this elif to handle being a dead hand before the BB (pos==9)
# elif pos==9:
# hudDataPositions.append('X')
# else:
# raise FpdbError("invalid position")
# elif base=="stud":
# #todo: stud positions and steals
# pass
#
# street0Calls.append(myStreet0Calls)
# street1Calls.append(myStreet1Calls)
# street2Calls.append(myStreet2Calls)
# street3Calls.append(myStreet3Calls)
# street4Calls.append(myStreet4Calls)
# street0Bets.append(myStreet0Bets)
# street1Bets.append(myStreet1Bets)
# street2Bets.append(myStreet2Bets)
# street3Bets.append(myStreet3Bets)
# street4Bets.append(myStreet4Bets)
# #street0Raises.append(myStreet0Raises)
# #street1Raises.append(myStreet1Raises)
# #street2Raises.append(myStreet2Raises)
# #street3Raises.append(myStreet3Raises)
# #street4Raises.append(myStreet4Raises)
#
# #add each array to the to-be-returned dictionary
# result['street0VPI']=street0VPI
# result['street0Aggr']=street0Aggr
# result['street0_3BChance']=street0_3BChance
# result['street0_3BDone']=street0_3BDone
# result['street1Seen']=street1Seen
# result['street2Seen']=street2Seen
# result['street3Seen']=street3Seen
# result['street4Seen']=street4Seen
# result['sawShowdown']=sawShowdown
#
# result['street1Aggr']=street1Aggr
# result['otherRaisedStreet1']=otherRaisedStreet1
# result['foldToOtherRaisedStreet1']=foldToOtherRaisedStreet1
# result['street2Aggr']=street2Aggr
# result['otherRaisedStreet2']=otherRaisedStreet2
# result['foldToOtherRaisedStreet2']=foldToOtherRaisedStreet2
# result['street3Aggr']=street3Aggr
# result['otherRaisedStreet3']=otherRaisedStreet3
# result['foldToOtherRaisedStreet3']=foldToOtherRaisedStreet3
# result['street4Aggr']=street4Aggr
# result['otherRaisedStreet4']=otherRaisedStreet4
# result['foldToOtherRaisedStreet4']=foldToOtherRaisedStreet4
# result['wonWhenSeenStreet1']=wonWhenSeenStreet1
# result['wonAtSD']=wonAtSD
# result['stealAttemptChance']=stealAttemptChance
# result['stealAttempted']=stealAttempted
# result['street0Calls']=street0Calls
# result['street1Calls']=street1Calls
# result['street2Calls']=street2Calls
# result['street3Calls']=street3Calls
# result['street4Calls']=street4Calls
# result['street0Bets']=street0Bets
# result['street1Bets']=street1Bets
# result['street2Bets']=street2Bets
# result['street3Bets']=street3Bets
# result['street4Bets']=street4Bets
# #result['street0Raises']=street0Raises
# #result['street1Raises']=street1Raises
# #result['street2Raises']=street2Raises
# #result['street3Raises']=street3Raises
# #result['street4Raises']=street4Raises
#
# #now the various steal values
# foldBbToStealChance=[]
# foldedBbToSteal=[]
# foldSbToStealChance=[]
# foldedSbToSteal=[]
# for player in xrange(len(player_ids)):
# myFoldBbToStealChance=False
# myFoldedBbToSteal=False
# myFoldSbToStealChance=False
# myFoldedSbToSteal=False
#
# if base=="hold":
# if someoneStole and (positions[player]=='B' or positions[player]=='S') and firstPfRaiserId!=player_ids[player]:
# street=0
# for count in xrange(len(action_types[street][player])):#individual actions
# if positions[player]=='B':
# myFoldBbToStealChance=True
# if action_types[street][player][count]=="fold":
# myFoldedBbToSteal=True
# if positions[player]=='S':
# myFoldSbToStealChance=True
# if action_types[street][player][count]=="fold":
# myFoldedSbToSteal=True
#
#
# foldBbToStealChance.append(myFoldBbToStealChance)
# foldedBbToSteal.append(myFoldedBbToSteal)
# foldSbToStealChance.append(myFoldSbToStealChance)
# foldedSbToSteal.append(myFoldedSbToSteal)
# result['foldBbToStealChance']=foldBbToStealChance
# result['foldedBbToSteal']=foldedBbToSteal
# result['foldSbToStealChance']=foldSbToStealChance
# result['foldedSbToSteal']=foldedSbToSteal
#
# #now CB
# street1CBChance=[]
# street1CBDone=[]
# didStreet1CB=[]
# for player in xrange(len(player_ids)):
# myStreet1CBChance=False
# myStreet1CBDone=False
#
# if street0VPI[player]:
# myStreet1CBChance=True
# if street1Aggr[player]:
# myStreet1CBDone=True
# didStreet1CB.append(player_ids[player])
#
# street1CBChance.append(myStreet1CBChance)
# street1CBDone.append(myStreet1CBDone)
# result['street1CBChance']=street1CBChance
# result['street1CBDone']=street1CBDone
#
# #now 2B
# street2CBChance=[]
# street2CBDone=[]
# didStreet2CB=[]
# for player in xrange(len(player_ids)):
# myStreet2CBChance=False
# myStreet2CBDone=False
#
# if street1CBDone[player]:
# myStreet2CBChance=True
# if street2Aggr[player]:
# myStreet2CBDone=True
# didStreet2CB.append(player_ids[player])
#
# street2CBChance.append(myStreet2CBChance)
# street2CBDone.append(myStreet2CBDone)
# result['street2CBChance']=street2CBChance
# result['street2CBDone']=street2CBDone
#
# #now 3B
# street3CBChance=[]
# street3CBDone=[]
# didStreet3CB=[]
# for player in xrange(len(player_ids)):
# myStreet3CBChance=False
# myStreet3CBDone=False
#
# if street2CBDone[player]:
# myStreet3CBChance=True
# if street3Aggr[player]:
# myStreet3CBDone=True
# didStreet3CB.append(player_ids[player])
#
# street3CBChance.append(myStreet3CBChance)
# street3CBDone.append(myStreet3CBDone)
# result['street3CBChance']=street3CBChance
# result['street3CBDone']=street3CBDone
#
# #and 4B
# street4CBChance=[]
# street4CBDone=[]
# didStreet4CB=[]
# for player in xrange(len(player_ids)):
# myStreet4CBChance=False
# myStreet4CBDone=False
#
# if street3CBDone[player]:
# myStreet4CBChance=True
# if street4Aggr[player]:
# myStreet4CBDone=True
# didStreet4CB.append(player_ids[player])
#
# street4CBChance.append(myStreet4CBChance)
# street4CBDone.append(myStreet4CBDone)
# result['street4CBChance']=street4CBChance
# result['street4CBDone']=street4CBDone
#
#
# result['position']=hudDataPositions
#
# foldToStreet1CBChance=[]
# foldToStreet1CBDone=[]
# foldToStreet2CBChance=[]
# foldToStreet2CBDone=[]
# foldToStreet3CBChance=[]
# foldToStreet3CBDone=[]
# foldToStreet4CBChance=[]
# foldToStreet4CBDone=[]
#
# for player in xrange(len(player_ids)):
# myFoldToStreet1CBChance=False
# myFoldToStreet1CBDone=False
# foldToStreet1CBChance.append(myFoldToStreet1CBChance)
# foldToStreet1CBDone.append(myFoldToStreet1CBDone)
#
# myFoldToStreet2CBChance=False
# myFoldToStreet2CBDone=False
# foldToStreet2CBChance.append(myFoldToStreet2CBChance)
# foldToStreet2CBDone.append(myFoldToStreet2CBDone)
#
# myFoldToStreet3CBChance=False
# myFoldToStreet3CBDone=False
# foldToStreet3CBChance.append(myFoldToStreet3CBChance)
# foldToStreet3CBDone.append(myFoldToStreet3CBDone)
#
# myFoldToStreet4CBChance=False
# myFoldToStreet4CBDone=False
# foldToStreet4CBChance.append(myFoldToStreet4CBChance)
# foldToStreet4CBDone.append(myFoldToStreet4CBDone)
#
# if len(didStreet1CB)>=1:
# generateFoldToCB(1, player_ids, didStreet1CB, street1CBDone, foldToStreet1CBChance, foldToStreet1CBDone, actionTypeByNo)
#
# if len(didStreet2CB)>=1:
# generateFoldToCB(2, player_ids, didStreet2CB, street2CBDone, foldToStreet2CBChance, foldToStreet2CBDone, actionTypeByNo)
#
# if len(didStreet3CB)>=1:
# generateFoldToCB(3, player_ids, didStreet3CB, street3CBDone, foldToStreet3CBChance, foldToStreet3CBDone, actionTypeByNo)
#
# if len(didStreet4CB)>=1:
# generateFoldToCB(4, player_ids, didStreet4CB, street4CBDone, foldToStreet4CBChance, foldToStreet4CBDone, actionTypeByNo)
#
# result['foldToStreet1CBChance']=foldToStreet1CBChance
# result['foldToStreet1CBDone']=foldToStreet1CBDone
# result['foldToStreet2CBChance']=foldToStreet2CBChance
# result['foldToStreet2CBDone']=foldToStreet2CBDone
# result['foldToStreet3CBChance']=foldToStreet3CBChance
# result['foldToStreet3CBDone']=foldToStreet3CBDone
# result['foldToStreet4CBChance']=foldToStreet4CBChance
# result['foldToStreet4CBDone']=foldToStreet4CBDone
#
#
# totalProfit=[]
#
# street1CheckCallRaiseChance=[]
# street1CheckCallRaiseDone=[]
# street2CheckCallRaiseChance=[]
# street2CheckCallRaiseDone=[]
# street3CheckCallRaiseChance=[]
# street3CheckCallRaiseDone=[]
# street4CheckCallRaiseChance=[]
# street4CheckCallRaiseDone=[]
# #print "b4 totprof calc, len(playerIds)=", len(player_ids)
# for pl in xrange(len(player_ids)):
# #print "pl=", pl
# myTotalProfit=winnings[pl] # still need to deduct other costs
# if antes:
# myTotalProfit=winnings[pl] - antes[pl]
# for i in xrange(len(actionTypes)): #iterate through streets
# #for j in xrange(len(actionTypes[i])): #iterate through names (using pl loop above)
# for k in xrange(len(actionTypes[i][pl])): #iterate through individual actions of that player on that street
# myTotalProfit -= actionAmounts[i][pl][k]
#
# myStreet1CheckCallRaiseChance=False
# myStreet1CheckCallRaiseDone=False
# myStreet2CheckCallRaiseChance=False
# myStreet2CheckCallRaiseDone=False
# myStreet3CheckCallRaiseChance=False
# myStreet3CheckCallRaiseDone=False
# myStreet4CheckCallRaiseChance=False
# myStreet4CheckCallRaiseDone=False
#
# #print "myTotalProfit=", myTotalProfit
# totalProfit.append(myTotalProfit)
# #print "totalProfit[]=", totalProfit
#
# street1CheckCallRaiseChance.append(myStreet1CheckCallRaiseChance)
# street1CheckCallRaiseDone.append(myStreet1CheckCallRaiseDone)
# street2CheckCallRaiseChance.append(myStreet2CheckCallRaiseChance)
# street2CheckCallRaiseDone.append(myStreet2CheckCallRaiseDone)
# street3CheckCallRaiseChance.append(myStreet3CheckCallRaiseChance)
# street3CheckCallRaiseDone.append(myStreet3CheckCallRaiseDone)
# street4CheckCallRaiseChance.append(myStreet4CheckCallRaiseChance)
# street4CheckCallRaiseDone.append(myStreet4CheckCallRaiseDone)
#
# result['totalProfit']=totalProfit
# #print "res[totalProfit]=", result['totalProfit']
#
# result['street1CheckCallRaiseChance']=street1CheckCallRaiseChance
# result['street1CheckCallRaiseDone']=street1CheckCallRaiseDone
# result['street2CheckCallRaiseChance']=street2CheckCallRaiseChance
# result['street2CheckCallRaiseDone']=street2CheckCallRaiseDone
# result['street3CheckCallRaiseChance']=street3CheckCallRaiseChance
# result['street3CheckCallRaiseDone']=street3CheckCallRaiseDone
# result['street4CheckCallRaiseChance']=street4CheckCallRaiseChance
# result['street4CheckCallRaiseDone']=street4CheckCallRaiseDone
# return result
# #end def generateHudCacheData
pass
def vpip(self, hand):
@ -794,9 +162,9 @@ class DerivedStats():
for player in hand.players:
if player[1] in vpipers:
self.handsplayers[player[1]]['vpip'] = True
self.handsplayers[player[1]]['street0VPI'] = True
else:
self.handsplayers[player[1]]['vpip'] = False
self.handsplayers[player[1]]['street0VPI'] = False
def playersAtStreetX(self, hand):
""" playersAtStreet1 SMALLINT NOT NULL, /* num of players seeing flop/street4/draw1 */"""
@ -812,14 +180,23 @@ class DerivedStats():
self.hands['playersAtStreet4'] = 0
self.hands['playersAtShowdown'] = 0
alliners = set()
for (i, street) in enumerate(hand.actionStreets[2:]):
actors = {}
for act in hand.actions[street]:
actors[act[0]] = 1
self.hands['playersAtStreet%s' % str(i+1)] = len(actors.keys())
actors = set()
for action in hand.actions[street]:
if len(action) > 2 and action[-1]: # allin
alliners.add(action[0])
actors.add(action[0])
if len(actors)==0 and len(alliners)<2:
alliners = set()
self.hands['playersAtStreet%d' % (i+1)] = len(set.union(alliners, actors))
#Need playersAtShowdown
actions = hand.actions[hand.actionStreets[-1]]
pas = set.union(self.pfba(actions) - self.pfba(actions, l=('folds',)), alliners)
self.hands['playersAtShowdown'] = len(pas)
for player in pas:
self.handsplayers[player]['sawShowdown'] = True
def streetXRaises(self, hand):
# self.actions[street] is a list of all actions in a tuple, contining the action as the second element
@ -827,11 +204,36 @@ class DerivedStats():
# No idea what this value is actually supposed to be
# In theory its "num small bets paid to see flop/street4, including blind" which makes sense for limit. Not so useful for nl
# Leaving empty for the moment,
self.hands['street0Raises'] = 0 # /* num small bets paid to see flop/street4, including blind */
self.hands['street1Raises'] = 0 # /* num small bets paid to see turn/street5 */
self.hands['street2Raises'] = 0 # /* num big bets paid to see river/street6 */
self.hands['street3Raises'] = 0 # /* num big bets paid to see sd/street7 */
self.hands['street4Raises'] = 0 # /* num big bets paid to see showdown */
for i in range(5): self.hands['street%dRaises' % i] = 0
for (i, street) in enumerate(hand.actionStreets[1:]):
self.hands['street%dRaises' % i] = len(filter( lambda action: action[1] in ('raises','bets'), hand.actions[street]))
def calcCBets(self, hand):
# Continuation Bet chance, action:
# Had the last bet (initiative) on previous street, got called, close street action
# Then no bets before the player with initiatives first action on current street
# ie. if player on street-1 had initiative
# and no donkbets occurred
for i, street in enumerate(hand.actionStreets[2:], start=1):
name = self.lastBetOrRaiser(hand.actionStreets[i])
if name:
chance = self.noBetsBefore(hand.actionStreets[i+1], name)
self.handsplayers[name]['street%dCBChance' %i] = True
if chance == True:
self.handsplayers[name]['street%dCBDone' %i] = self.betStreet(hand.actionStreets[i+1], name)
def seen(self, hand, i):
pas = set()
for act in hand.actions[hand.actionStreets[i+1]]:
pas.add(act[0])
for player in hand.players:
if player[1] in pas:
self.handsplayers[player[1]]['street%sSeen' % i] = True
else:
self.handsplayers[player[1]]['street%sSeen' % i] = False
def aggr(self, hand, i):
aggrers = set()
@ -845,5 +247,64 @@ class DerivedStats():
else:
self.handsplayers[player[1]]['street%sAggr' % i] = False
def calls(self, hand, i):
callers = []
for act in hand.actions[hand.actionStreets[i+1]]:
if act[1] in ('calls'):
self.handsplayers[act[0]]['street%sCalls' % i] = 1 + self.handsplayers[act[0]]['street%sCalls' % i]
# CG - I'm sure this stat is wrong
# Best guess is that raise = 2 bets
def bets(self, hand, i):
betters = []
for act in hand.actions[hand.actionStreets[i+1]]:
if act[1] in ('bets'):
self.handsplayers[act[0]]['street%sBets' % i] = 1 + self.handsplayers[act[0]]['street%sBets' % i]
def countPlayers(self, hand):
pass
def pfba(self, actions, f=None, l=None):
"""Helper method. Returns set of PlayersFilteredByActions
f - forbidden actions
l - limited to actions
"""
players = set()
for action in actions:
if l is not None and action[1] not in l: continue
if f is not None and action[1] in f: continue
players.add(action[0])
return players
def noBetsBefore(self, street, player):
"""Returns true if there were no bets before the specified players turn, false otherwise"""
betOrRaise = False
for act in self.hand.actions[street]:
#Must test for player first in case UTG
if act[0] == player:
betOrRaise = True
break
if act[1] in ('bets', 'raises'):
break
return betOrRaise
def betStreet(self, street, player):
"""Returns true if player bet/raised the street as their first action"""
betOrRaise = False
for act in self.hand.actions[street]:
if act[0] == player and act[1] in ('bets', 'raises'):
betOrRaise = True
else:
break
return betOrRaise
def lastBetOrRaiser(self, street):
"""Returns player name that placed the last bet or raise for that street.
None if there were no bets or raises on that street"""
lastbet = None
for act in self.hand.actions[street]:
if act[1] in ('bets', 'raises'):
lastbet = act[0]
return lastbet

View File

@ -17,8 +17,22 @@ class FpdbParseError(FpdbError):
class FpdbDatabaseError(FpdbError):
pass
class FpdbMySQLFailedError(FpdbDatabaseError):
class FpdbMySQLError(FpdbDatabaseError):
pass
class FpdbMySQLAccessDenied(FpdbDatabaseError):
def __init__(self, value='', errmsg=''):
self.value = value
self.errmsg = errmsg
def __str__(self):
return repr(self.value +" " + self.errmsg)
class FpdbMySQLNoDatabase(FpdbDatabaseError):
def __init__(self, value='', errmsg=''):
self.value = value
self.errmsg = errmsg
def __str__(self):
return repr(self.value +" " + self.errmsg)
class DuplicateError(FpdbError):
pass

View File

@ -312,8 +312,10 @@ class Filters(threading.Thread):
self.cbAllLimits.set_active(False)
if not self.limits[limit]:
if limit.isdigit():
if self.cbFL is not None:
self.cbFL.set_active(False)
else:
if self.cbNL is not None:
self.cbNL.set_active(False)
elif limit == "all":
if self.limits[limit]:
@ -327,7 +329,9 @@ class Filters(threading.Thread):
if self.limits[limit]:
for cb in self.cbLimits.values():
cb.set_active(False)
if self.cbNL is not None:
self.cbNL.set_active(False)
if self.cbFL is not None:
self.cbFL.set_active(False)
elif limit == "fl":
if not self.limits[limit]:
@ -731,7 +735,7 @@ def main(argv=None):
gtk.main_quit()
parser = OptionParser()
(options, sys.argv) = parser.parse_args(args = argv)
(options, argv) = parser.parse_args(args = argv)
config = Configuration.Config()
db = None
@ -750,5 +754,3 @@ def main(argv=None):
if __name__ == '__main__':
sys.exit(main())

View File

@ -71,22 +71,24 @@ class GuiAutoImport (threading.Thread):
self.intervalLabel = gtk.Label("Time between imports in seconds:")
self.intervalLabel.set_alignment(xalign=1.0, yalign=0.5)
vbox1.pack_start(self.intervalLabel, True, True, 0)
vbox1.pack_start(self.intervalLabel, False, True, 0)
hbox = gtk.HBox(False, 0)
vbox2.pack_start(hbox, True, True, 0)
vbox2.pack_start(hbox, False, True, 0)
self.intervalEntry = gtk.Entry()
self.intervalEntry.set_text(str(self.config.get_import_parameters().get("interval")))
hbox.pack_start(self.intervalEntry, False, False, 0)
lbl1 = gtk.Label()
hbox.pack_start(lbl1, expand=True, fill=True)
hbox.pack_start(lbl1, expand=False, fill=True)
lbl = gtk.Label('')
vbox1.pack_start(lbl, expand=True, fill=True)
vbox1.pack_start(lbl, expand=False, fill=True)
lbl = gtk.Label('')
vbox2.pack_start(lbl, expand=True, fill=True)
vbox2.pack_start(lbl, expand=False, fill=True)
self.addSites(vbox1, vbox2)
self.textbuffer = gtk.TextBuffer()
self.textview = gtk.TextView(self.textbuffer)
hbox = gtk.HBox(False, 0)
self.mainVBox.pack_start(hbox, expand=True, padding=3)
@ -102,13 +104,27 @@ class GuiAutoImport (threading.Thread):
self.startButton.connect("clicked", self.startClicked, "start clicked")
hbox.pack_start(self.startButton, expand=False, fill=False)
lbl2 = gtk.Label()
hbox.pack_start(lbl2, expand=True, fill=False)
hbox = gtk.HBox(False, 0)
hbox.show()
self.mainVBox.pack_start(hbox, expand=True, padding=3)
scrolledwindow = gtk.ScrolledWindow()
scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.mainVBox.pack_end(scrolledwindow, expand=True)
scrolledwindow.add(self.textview)
self.mainVBox.show_all()
self.addText("AutoImport Ready.")
def addText(self, text):
end_iter = self.textbuffer.get_end_iter()
self.textbuffer.insert(end_iter, text)
self.textview.scroll_to_mark(self.textbuffer.get_insert(), 0)
#end of GuiAutoImport.__init__
@ -139,8 +155,9 @@ class GuiAutoImport (threading.Thread):
if self.doAutoImportBool:
self.startButton.set_label(u' I M P O R T I N G ')
self.importer.runUpdated()
sys.stdout.write(".")
sys.stdout.flush()
self.addText(".")
#sys.stdout.write(".")
#sys.stdout.flush()
gobject.timeout_add(1000, self.reset_startbutton)
return True
return False
@ -172,7 +189,7 @@ class GuiAutoImport (threading.Thread):
# - Ideally we want to release the lock if the auto-import is killed by some
# kind of exception - is this possible?
if self.settings['global_lock'].acquire(False): # returns false immediately if lock not acquired
print "\nGlobal lock taken ..."
self.addText("\nGlobal lock taken ... Auto Import Started.\n")
self.doAutoImportBool = True
widget.set_label(u' _Stop Autoimport ')
if self.pipe_to_hud is None:
@ -190,12 +207,11 @@ class GuiAutoImport (threading.Thread):
universal_newlines=True)
except:
err = traceback.extract_tb(sys.exc_info()[2])[-1]
print "*** GuiAutoImport Error opening pipe: " + err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1])
self.addText( "\n*** GuiAutoImport Error opening pipe: " + err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1]))
else:
for site in self.input_settings:
self.importer.addImportDirectory(self.input_settings[site][0], True, site, self.input_settings[site][1])
print " * Add", site, " import directory", str(self.input_settings[site][0])
print "+Import directory - Site: " + site + " dir: " + str(self.input_settings[site][0])
self.addText("\n * Add "+ site+ " import directory "+ str(self.input_settings[site][0]))
self.do_import()
interval = int(self.intervalEntry.get_text())
if self.importtimer != 0:
@ -203,14 +219,14 @@ class GuiAutoImport (threading.Thread):
self.importtimer = gobject.timeout_add(interval * 1000, self.do_import)
else:
print "auto-import aborted - global lock not available"
self.addText("\nauto-import aborted - global lock not available")
else: # toggled off
gobject.source_remove(self.importtimer)
self.settings['global_lock'].release()
self.doAutoImportBool = False # do_import will return this and stop the gobject callback timer
print "Stopping autoimport - global lock released."
self.addText("\nStopping autoimport - global lock released.")
if self.pipe_to_hud.poll() is not None:
print " * Stop Autoimport: HUD already terminated"
self.addText("\n * Stop Autoimport: HUD already terminated")
else:
#print >>self.pipe_to_hud.stdin, "\n"
self.pipe_to_hud.communicate('\n') # waits for process to terminate
@ -281,7 +297,7 @@ if __name__== "__main__":
parser.add_option("-q", "--quiet", action="store_false", dest="gui", default=True, help="don't start gui")
parser.add_option("-m", "--minPrint", "--status", dest="minPrint", default="0", type="int",
help="How often to print a one-line status report (0 (default) means never)")
(options, sys.argv) = parser.parse_args()
(options, argv) = parser.parse_args()
config = Configuration.Config()
# db = fpdb_db.fpdb_db()
@ -305,4 +321,3 @@ if __name__== "__main__":
gtk.main()
else:
pass

View File

@ -53,7 +53,7 @@ class GuiBulkImport():
# Does the lock acquisition need to be more sophisticated for multiple dirs?
# (see comment above about what to do if pipe already open)
if self.settings['global_lock'].acquire(False): # returns false immediately if lock not acquired
try:
#try:
print "\nGlobal lock taken ..."
self.progressbar.set_text("Importing...")
self.progressbar.pulse()
@ -116,9 +116,10 @@ class GuiBulkImport():
self.progressbar.set_text("Import Complete")
self.progressbar.set_fraction(0)
except:
err = traceback.extract_tb(sys.exc_info()[2])[-1]
print "*** BulkImport Error: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
#except:
#err = traceback.extract_tb(sys.exc_info()[2])[-1]
#print "*** BulkImport Error: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
#self.settings['global_lock'].release()
self.settings['global_lock'].release()
else:
print "bulk-import aborted - global lock not available"
@ -325,7 +326,7 @@ def main(argv=None):
help="How often to print a one-line status report (0 (default) means never)")
parser.add_option("-u", "--usage", action="store_true", dest="usage", default=False,
help="Print some useful one liners")
(options, sys.argv) = parser.parse_args(args = argv)
(options, argv) = parser.parse_args(args = argv)
if options.usage == True:
#Print usage examples and exit
@ -376,4 +377,3 @@ def main(argv=None):
if __name__ == '__main__':
sys.exit(main())

View File

@ -152,14 +152,17 @@ class GuiGraphViewer (threading.Thread):
if not sitenos:
#Should probably pop up here.
print "No sites selected - defaulting to PokerStars"
self.db.rollback()
return
if not playerids:
print "No player ids found"
self.db.rollback()
return
if not limits:
print "No limits found"
self.db.rollback()
return
#Set graph properties
@ -216,6 +219,7 @@ class GuiGraphViewer (threading.Thread):
#nametest = nametest.replace("L", "")
lims = [int(x) for x in limits if x.isdigit()]
potlims = [int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'pl']
nolims = [int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'nl']
limittest = "and ( (gt.limitType = 'fl' and gt.bigBlind in "
# and ( (limit and bb in()) or (nolimit and bb in ()) )
@ -226,6 +230,14 @@ class GuiGraphViewer (threading.Thread):
limittest = limittest + blindtest + ' ) '
else:
limittest = limittest + '(-1) ) '
limittest = limittest + " or (gt.limitType = 'pl' and gt.bigBlind in "
if potlims:
blindtest = str(tuple(potlims))
blindtest = blindtest.replace("L", "")
blindtest = blindtest.replace(",)",")")
limittest = limittest + blindtest + ' ) '
else:
limittest = limittest + '(-1) ) '
limittest = limittest + " or (gt.limitType = 'nl' and gt.bigBlind in "
if nolims:
blindtest = str(tuple(nolims))
@ -234,6 +246,7 @@ class GuiGraphViewer (threading.Thread):
limittest = limittest + blindtest + ' ) )'
else:
limittest = limittest + '(-1) ) )'
if type == 'ring':
limittest = limittest + " and gt.type = 'ring' "
elif type == 'tour':

View File

@ -480,6 +480,7 @@ class GuiPlayerStats (threading.Thread):
query = query.replace('<orderbyseats>', '')
lims = [int(x) for x in limits if x.isdigit()]
potlims = [int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'pl']
nolims = [int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'nl']
bbtest = "and ( (gt.limitType = 'fl' and gt.bigBlind in "
# and ( (limit and bb in()) or (nolimit and bb in ()) )
@ -490,6 +491,14 @@ class GuiPlayerStats (threading.Thread):
bbtest = bbtest + blindtest + ' ) '
else:
bbtest = bbtest + '(-1) ) '
bbtest = bbtest + " or (gt.limitType = 'pl' and gt.bigBlind in "
if potlims:
blindtest = str(tuple(potlims))
blindtest = blindtest.replace("L", "")
blindtest = blindtest.replace(",)",")")
bbtest = bbtest + blindtest + ' ) '
else:
bbtest = bbtest + '(-1) ) '
bbtest = bbtest + " or (gt.limitType = 'nl' and gt.bigBlind in "
if nolims:
blindtest = str(tuple(nolims))
@ -544,7 +553,7 @@ class GuiPlayerStats (threading.Thread):
# set flag in self.columns to show posn column
[x for x in self.columns if x[0] == 'plposition'][0][1] = True
else:
query = query.replace("<position>", "'1'")
query = query.replace("<position>", "gt.base")
# unset flag in self.columns to hide posn column
[x for x in self.columns if x[0] == 'plposition'][0][1] = False

169
pyfpdb/GuiPrefs.py Executable file
View File

@ -0,0 +1,169 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#Copyright 2008 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 in the docs folder of the package.
import xml.dom.minidom
from xml.dom.minidom import Node
import pygtk
pygtk.require('2.0')
import gtk
import gobject
import Configuration
class GuiPrefs:
def __init__(self, config, mainwin, dia):
self.config = config
self.main_window = mainwin
self.dialog = dia
self.tree_box = gtk.ScrolledWindow()
self.tree_box.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.dialog.add(self.tree_box)
self.dialog.show()
self.doc = None
self.configStore = None
self.configView = None
self.fillFrames()
def fillFrames(self):
self.doc = self.config.get_doc()
self.configStore = gtk.TreeStore(gobject.TYPE_PYOBJECT, gobject.TYPE_STRING, gobject.TYPE_STRING)
self.configView = gtk.TreeView(self.configStore)
self.configView.set_enable_tree_lines(True)
configColumn = gtk.TreeViewColumn("Setting")
self.configView.append_column(configColumn)
cRender = gtk.CellRendererText()
configColumn.pack_start(cRender, True)
configColumn.add_attribute(cRender, 'text', 1)
configColumn = gtk.TreeViewColumn("Value")
self.configView.append_column(configColumn)
cRender = gtk.CellRendererText()
configColumn.pack_start(cRender, True)
configColumn.add_attribute(cRender, 'text', 2)
if self.doc.documentElement.tagName == 'FreePokerToolsConfig':
self.configStore.clear()
self.root = self.configStore.append( None, [self.doc.documentElement, "fpdb", None] )
for elem in self.doc.documentElement.childNodes:
iter = self.addTreeRows(self.root, elem)
if self.root != None:
self.configView.expand_row(self.configStore.get_path(self.root), False)
self.configView.connect("row-activated", self.rowChosen)
self.configView.show()
self.tree_box.add(self.configView)
self.tree_box.show()
self.dialog.show()
def addTreeRows(self, parent, node):
if (node.nodeType == node.ELEMENT_NODE):
(setting, value) = (node.nodeName, None)
elif (node.nodeType == node.TEXT_NODE):
# text nodes hold the whitespace (or whatever) between the xml elements, not used here
(setting, value) = ("TEXT: ["+node.nodeValue+"|"+node.nodeValue+"]", node.data)
else:
(setting, value) = ("?? "+node.nodeValue, "type="+str(node.nodeType))
#iter = self.configStore.append( parent, [node.nodeValue, None] )
iter = None
if node.nodeType != node.TEXT_NODE and node.nodeType != node.COMMENT_NODE:
iter = self.configStore.append( parent, [node, setting, value] )
if node.hasAttributes():
for i in xrange(node.attributes.length):
self.configStore.append( iter, [node, node.attributes.item(i).localName, node.attributes.item(i).value] )
if node.hasChildNodes():
for elem in node.childNodes:
self.addTreeRows(iter, elem)
return iter
def rowChosen(self, tview, path, something2, data=None):
# tview should= self.configStore
tmodel = tview.get_model()
iter = tmodel.get_iter(path)
if tmodel.iter_has_child(iter):
# toggle children display
if tview.row_expanded(path):
tview.collapse_row(tmodel.get_path(iter))
else:
tview.expand_row(tmodel.get_path(iter), False)
else:
# display value and allow edit
name = tmodel.get_value( iter, 1 )
val = tmodel.get_value( iter, 2 )
dia_edit = gtk.Dialog(name,
self.main_window,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
#dia_edit.set_default_size(350, 100)
entry = gtk.Entry()
if val:
entry.set_text(val)
entry.set_width_chars(40)
dia_edit.vbox.pack_start(entry, False, False, 0)
entry.show()
entry.connect("activate", self.__set_entry, dia_edit)
response = dia_edit.run()
if response == gtk.RESPONSE_ACCEPT:
# update configStore
new_val = entry.get_text()
tmodel.set_value(iter, 2, new_val)
tmodel.get_value(iter, 0).setAttribute(name, new_val)
dia_edit.destroy()
def __set_entry(self, w, dia=None):
if dia is not None:
dia.response(gtk.RESPONSE_ACCEPT)
if __name__=="__main__":
config = Configuration.Config()
win = gtk.Window(gtk.WINDOW_TOPLEVEL)
win.set_title("Test Preferences Dialog")
win.set_border_width(1)
win.set_default_size(600, 500)
win.set_resizable(True)
dia = gtk.Dialog("Preferences",
win,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT))
dia.set_default_size(500, 500)
prefs = GuiPrefs(config, win, dia.vbox)
response = dia.run()
if response == gtk.RESPONSE_ACCEPT:
# save updated config
config.save()
dia.destroy()

581
pyfpdb/HUD_config.test.xml Normal file
View File

@ -0,0 +1,581 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<FreePokerToolsConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FreePokerToolsConfig.xsd">
<import callFpdbHud = "True" interval = "10" fastStoreHudCache="False" hhArchiveBase="~/.fpdb/HandHistories/" saveActions="True"></import>
<!-- These values determine what stats are displayed in the HUD
The following values define how opponents' stats are done, the first 2 determine
the time period stats are displayed for, the next 3 determine what blind levels
are included (i.e. aggregated):
stat_range :
- A/S/T
- if set to A, includes stats from all time
- if set to S, includes stats from current session
- if set to T, includes stats from last N days; set value in stat_days
- defaults to A
stat_days :
- a numeric value
- only used if stat_range is set to 'T', this value tells how many days are
included in the stat calculation
- defaults to 90
- value not used by default as it depends on stat_range setting
aggregate_ring_game_stats :
- True/False
- if set to True, opponents stats include other blind levels during ring games
- defaults to False
aggregate_tourney_stats :
- True/False
- if set to True, opponents stats include other blind levels during tourneys
- defaults to True
aggregation_level_multiplier :
- float value
- defines how many blind levels are included in stats displayed in HUD
- if value is M, stats for blind levels are combined if the higher level
is less than or equal to M times the lower blind level
- defaults to 3, meaning blind levels from 1/3 of the current level to 3
times the current level are included in the stats displayed in the HUD
- e.g. if current big blind is 50, stats for blind levels from big blind
of 16.7 (50 divided by 3) to big blind of 150 (50 times 3) are included
The following values define how hero's stats are done, the first 2 determine
the time period stats are displayed for, the next 3 determine what blind levels
are included (i.e. aggregated):
hero_stat_range :
- A/S/T
- if set to A, includes stats from all time
- if set to S, includes stats from current session
- if set to T, includes stats from last N days; set value in hero_stat_days
- defaults to S
hero_stat_days :
- a numeric value
- if hero_stat_range is set to 'T', this value tells how many days are
included in the stat calculation
- defaults to 30
- value not used by default as it depends on hero_stat_range setting
aggregate_hero_ring_game_stats :
- True/False
- if set to True, hero's stats are calculated over multiple blind levels
- defaults to False
aggregate_hero_tourney_stats :
- True/False
- if set to True, hero's stats are calculated over multiple blind levels
- defaults to False
hero_aggregation_level_multiplier :
- float value
- defines how many blind levels are included in stats displayed in HUD
- if value is M, stats for blind levels are combined if the higher level
is less than or equal to M times the lower blind level
- defaults to 1, meaning only stats from current blind level are included
- e.g. if set to 3 and current big blind is 50, stats for blind levels from
16.7 (50 divided by 3) to big blind of 150 (50 times 3) are included
-->
<hud_ui
stat_range="A"
stat_days="90"
aggregate_ring_game_stats="False"
aggregate_tourney_stats="True"
aggregation_level_multiplier="3"
hero_stat_range="S"
hero_stat_days="30"
aggregate_hero_ring_game_stats="False"
aggregate_hero_tourney_stats="False"
hero_aggregation_level_multiplier="1"
label="FPDB Menu - Right-click
Left-Drag to Move"
/>
<supported_sites>
<site enabled="True"
site_name="PokerStars"
table_finder="PokerStars.exe"
screen_name="YOUR SCREEN NAME HERE"
site_path="C:/Program Files/PokerStars/"
HH_path="C:/Program Files/PokerStars/HandHistory/YOUR SCREEN NAME HERE/"
decoder="pokerstars_decode_table"
converter="PokerStarsToFpdb"
bgcolor="#000000"
fgcolor="#FFFFFF"
hudopacity="1.0"
font="Sans"
font_size="8"
supported_games="holdem,razz,omahahi,omahahilo,studhi,studhilo">
<layout max="8" width="792" height="546" fav_seat="0">
<location seat="1" x="684" y="61"> </location>
<location seat="2" x="689" y="239"> </location>
<location seat="3" x="692" y="346"> </location>
<location seat="4" x="525" y="402"> </location>
<location seat="5" x="259" y="402"> </location>
<location seat="6" x="0" y="348"> </location>
<location seat="7" x="0" y="240"> </location>
<location seat="8" x="0" y="35"> </location>
</layout>
<layout max="6" width="792" height="546" fav_seat="0">
<location seat="1" x="681" y="119"> </location>
<location seat="2" x="681" y="301"> </location>
<location seat="3" x="487" y="369"> </location>
<location seat="4" x="226" y="369"> </location>
<location seat="5" x="0" y="301"> </location>
<location seat="6" x="0" y="119"> </location>
</layout>
<layout max="10" width="792" height="546" fav_seat="0">
<location seat="1" x="684" y="61"> </location>
<location seat="2" x="689" y="239"> </location>
<location seat="3" x="692" y="346"> </location>
<location seat="4" x="586" y="393"> </location>
<location seat="5" x="421" y="440"> </location>
<location seat="6" x="267" y="440"> </location>
<location seat="7" x="0" y="361"> </location>
<location seat="8" x="0" y="280"> </location>
<location seat="9" x="121" y="280"> </location>
<location seat="10" x="46" y="30"> </location>
</layout>
<layout max="9" width="792" height="546" fav_seat="0">
<location seat="1" x="560" y="0"> </location>
<location seat="2" x="679" y="123"> </location>
<location seat="3" x="688" y="309"> </location>
<location seat="4" x="483" y="370"> </location>
<location seat="5" x="444" y="413"> </location>
<location seat="6" x="224" y="372"> </location>
<location seat="7" x="0" y="307"> </location>
<location seat="8" x="0" y="121"> </location>
<location seat="9" x="140" y="0"> </location>
</layout>
<layout fav_seat="0" height="546" max="2" width="792">
<location seat="1" x="651" y="288"> </location>
<location seat="2" x="10" y="288"> </location>
</layout>
</site>
<site enabled="True"
site_name="Full Tilt Poker"
table_finder="FullTiltPoker"
screen_name="YOUR SCREEN NAME HERE"
site_path="C:/Program Files/Full Tilt Poker/"
HH_path="C:/Program Files/Full Tilt Poker/HandHistory/YOUR SCREEN NAME HERE/"
decoder="fulltilt_decode_table"
converter="FulltiltToFpdb"
bgcolor="#000000"
fgcolor="#FFFFFF"
hudopacity="1.0"
font="Sans"
font_size="8"
supported_games="holdem,razz,omahahi,omahahilo,studhi,studhilo">
<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>
<site enabled="False"
site_name="Everleaf"
table_finder="Everleaf.exe"
screen_name="YOUR SCREEN NAME HERE"
site_path=""
HH_path=""
decoder="everleaf_decode_table"
converter="EverleafToFpdb"
supported_games="holdem">
<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>
<site enabled="False"
site_name="Win2day"
table_finder="Win2day.exe"
screen_name="YOUR SCREEN NAME HERE"
site_path=""
HH_path=""
decoder="everleaf_decode_table"
converter="Win2dayToFpdb"
supported_games="holdem">
<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>
<site enabled="False"
site_name="Absolute"
table_finder="AbsolutePoker.exe"
screen_name="YOUR SCREEN NAME HERE"
site_path=""
HH_path=""
decoder="everleaf_decode_table"
converter="AbsoluteToFpdb"
supported_games="holdem">
<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>
<site enabled="False"
site_name="PartyPoker"
table_finder="PartyGaming.exe"
screen_name="YOUR SCREEN NAME HERE"
site_path="C:/Program Files/PartyGaming/PartyPoker"
HH_path="C:/Program Files/PartyGaming/PartyPoker/HandHistory/YOUR SCREEN NAME HERE/"
decoder="everleaf_decode_table"
converter="PartyPokerToFpdb"
supported_games="holdem">
<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>
<site enabled="False"
site_name="Betfair"
table_finder="Betfair Poker.exe"
screen_name="YOUR SCREEN NAME HERE"
site_path="C:/Program Files/Betfair/Betfair Poker/"
HH_path="C:/Program Files/Betfair/Betfair Poker/HandHistory/YOUR SCREEN NAME HERE/"
decoder="everleaf_decode_table"
converter="BetfairToFpdb"
supported_games="holdem">
<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_games>
<game cols="3" db="fpdb" game_name="holdem" rows="2" aux="mucked">
<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="razz" rows="2" aux="stud_mucked">
<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="omahahi" rows="2" aux="mucked">
<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="omahahilo" rows="2" aux="mucked">
<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="studhi" rows="2" aux="stud_mucked">
<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="studhilo" rows="2" aux="stud_mucked">
<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>
<popup_windows>
<pu pu_name="default">
<pu_stat pu_stat_name="n"> </pu_stat>
<pu_stat pu_stat_name="vpip"> </pu_stat>
<pu_stat pu_stat_name="pfr"> </pu_stat>
<pu_stat pu_stat_name="three_B_0"> </pu_stat>
<pu_stat pu_stat_name="steal"> </pu_stat>
<pu_stat pu_stat_name="f_BB_steal"> </pu_stat>
<pu_stat pu_stat_name="f_SB_steal"> </pu_stat>
<pu_stat pu_stat_name="wmsd"> </pu_stat>
<pu_stat pu_stat_name="wtsd"> </pu_stat>
<pu_stat pu_stat_name="WMsF"> </pu_stat>
<pu_stat pu_stat_name="a_freq1"> </pu_stat>
<pu_stat pu_stat_name="a_freq2"> </pu_stat>
<pu_stat pu_stat_name="a_freq3"> </pu_stat>
<pu_stat pu_stat_name="a_freq4"> </pu_stat>
<pu_stat pu_stat_name="cb1"> </pu_stat>
<pu_stat pu_stat_name="cb2"> </pu_stat>
<pu_stat pu_stat_name="cb3"> </pu_stat>
<pu_stat pu_stat_name="cb4"> </pu_stat>
<pu_stat pu_stat_name="ffreq1"> </pu_stat>
<pu_stat pu_stat_name="ffreq2"> </pu_stat>
<pu_stat pu_stat_name="ffreq3"> </pu_stat>
<pu_stat pu_stat_name="ffreq4"> </pu_stat>
</pu>
</popup_windows>
<aux_windows>
<aw card_ht="42" card_wd="30" class="Stud_mucked" cols="11" deck="Cards01.png" module="Mucked" name="stud_mucked" rows="8"> </aw>
<aw class="Hello" module="Hello" name="Hello"> </aw>
<aw class="Hello_Menu" module="Hello" name="Hello_menu"> </aw>
<aw class="Hello_plus" module="Hello" name="Hello_plus"> </aw>
<aw card_ht="42" card_wd="30" class="Flop_Mucked" deck="Cards01.png" module="Mucked" name="mucked" opacity="0.7" timeout="5">
<layout height="546" max="6" width="792">
<location seat="1" x="555" y="169"> </location>
<location seat="2" x="572" y="276"> </location>
<location seat="3" x="363" y="348"> </location>
<location seat="4" x="150" y="273"> </location>
<location seat="5" x="150" y="169"> </location>
<location seat="6" x="363" y="113"> </location>
<location common="1" x="323" y="232"> </location>
</layout>
<layout height="546" max="9" width="792">
<location seat="1" x="486" y="113"> </location>
<location seat="2" x="555" y="169"> </location>
<location seat="3" x="572" y="276"> </location>
<location seat="4" x="522" y="345"> </location>
<location seat="5" x="363" y="348"> </location>
<location seat="6" x="217" y="341"> </location>
<location seat="7" x="150" y="273"> </location>
<location seat="8" x="150" y="169"> </location>
<location seat="9" x="230" y="115"> </location>
<location common="1" x="323" y="232"> </location>
</layout>
<layout height="546" max="10" width="792">
<location seat="1" x="486" y="113"> </location>
<location seat="2" x="499" y="138"> </location>
<location seat="3" x="522" y="212"> </location>
<location seat="4" x="501" y="281"> </location>
<location seat="5" x="402" y="323"> </location>
<location seat="6" x="243" y="311"> </location>
<location seat="7" x="203" y="262"> </location>
<location seat="8" x="170" y="185"> </location>
<location seat="9" x="183" y="128"> </location>
<location seat="10" x="213" y="86"> </location>
<location common="1" x="317" y="237"> </location>
</layout>
</aw>
</aux_windows>
<hhcs>
<hhc site="PokerStars" converter="PokerStarsToFpdb"/>
<hhc site="Full Tilt Poker" converter="FulltiltToFpdb"/>
<hhc site="Everleaf" converter="EverleafToFpdb"/>
<hhc site="Win2day" converter="Win2dayToFpdb"/>
<hhc site="Absolute" converter="AbsoluteToFpdb"/>
<hhc site="PartyPoker" converter="PartyPokerToFpdb"/>
<hhc site="Betfair" converter="BetfairToFpdb"/>
<hhc site="Partouche" converter="PartoucheToFpdb"/>
</hhcs>
<supported_databases>
<database db_ip="localhost" db_name=":memory:" db_pass="fpdb" db_server="sqlite" db_user="fpdb"/>
</supported_databases>
</FreePokerToolsConfig>

View File

@ -4,91 +4,95 @@
<import callFpdbHud = "True" interval = "10" fastStoreHudCache="False" hhArchiveBase="~/.fpdb/HandHistories/" saveActions="True"></import>
<!-- These values need some explaining
<!-- These values determine what stats are displayed in the HUD
The following values define how opponents' stats are done, the first 2 determine
the time period stats are displayed for, the next 3 determine what blind levels
are included (i.e. aggregated):
stat_range :
- A/S/T
- if set to A, includes stats from all time
- if set to S, includes stats from current session
- if set to T, includes stats from last N days; set value in stat_days
- defaults to A
stat_days :
- a numeric value
- only used if stat_range is set to 'T', this value tells how many days are
included in the stat calculation
- defaults to 90
- value not used by default as it depends on stat_range setting
aggregate_ring_game_stats :
- True/False
- if set to True, includes data from other blind levels
- if set to True, opponents stats include other blind levels during ring games
- defaults to False
aggregate_tourney_stats :
- True/False
- if set to True, includes data from other blind levels
- if set to True, opponents stats include other blind levels during tourneys
- defaults to True
stat_aggregation_range :
- A/S/T
- if set to A, includes stats from all time
- if set to S, includes stats from current sessions
- if set to T, includes stats from last N days; set value in hud_days
- defaults to A
aggregation_days :
- a numeric value
- if hud_style is set to 'T', this value tells how many days are
included in the stat calculation
- defaults to 90
- value not used by default, as depends on hud_style setting
aggregation_level_multiplier :
- float value
- defines how many blind levels are used for aggregation
- the logic is weird, at best
- if value is 100, almost all levels are included
- if value is 2.1, levels from half to double the current blind
level are included
- if value it 1, no aggregation is performed
- defaults to 1
- defines how many blind levels are included in stats displayed in HUD
- if value is M, stats for blind levels are combined if the higher level
is less than or equal to M times the lower blind level
- defaults to 3, meaning blind levels from 1/3 of the current level to 3
times the current level are included in the stats displayed in the HUD
- e.g. if current big blind is 50, stats for blind levels from big blind
of 16.7 (50 divided by 3) to big blind of 150 (50 times 3) are included
The following values define how hero's stats are done
The following values define how hero's stats are done, the first 2 determine
the time period stats are displayed for, the next 3 determine what blind levels
are included (i.e. aggregated):
hero_stat_range :
- A/S/T
- if set to A, includes stats from all time
- if set to S, includes stats from current session
- if set to T, includes stats from last N days; set value in hero_stat_days
- defaults to S
hero_stat_days :
- a numeric value
- if hero_stat_range is set to 'T', this value tells how many days are
included in the stat calculation
- defaults to 30
- value not used by default as it depends on hero_stat_range setting
aggregate_hero_ring_game_stats :
- True/False
- if set to True, hero's data is calculated over multiple blind levels
- if set to True, hero's stats are calculated over multiple blind levels
- defaults to False
aggregate_hero_tourney_stats :
- True/False
- if set to True, hero's data is calculated over multiple blind levels
- if set to True, hero's stats are calculated over multiple blind levels
- defaults to False
hero_stat_aggregation_range :
- A/S/T
- if set to A, includes stats from all time
- if set to S, includes stats from current sessions
- if set to T, includes stats from last N days; set value in hud_days
- defaults to S
hero_aggregation_days :
- a numeric value
- if hero_stat_aggregation_range is set to 'T', this value tells
how many days are included in the stat calculation
- defaults to 30
- value not used by default, as depends on hud_style setting
hero_aggregation_level_multiplier :
- float value
- defines how many blind levels are used for aggregation
- the logic is weird, at best
- if value is 100, almost all levels are included
- if value is 2.1, levels from half to double the current blind
level are included
- if value it 1, no aggregation is performed
- defaults to 1
- defines how many blind levels are included in stats displayed in HUD
- if value is M, stats for blind levels are combined if the higher level
is less than or equal to M times the lower blind level
- defaults to 1, meaning only stats from current blind level are included
- e.g. if set to 3 and current big blind is 50, stats for blind levels from
16.7 (50 divided by 3) to big blind of 150 (50 times 3) are included
-->
<hud_ui
stat_range="A"
stat_days="90"
aggregate_ring_game_stats="False"
aggregate_tourney_stats="False"
stat_aggregation_range="A"
aggregation_days="90"
aggregation_level_multiplier="1"
aggregate_tourney_stats="True"
aggregation_level_multiplier="3"
hero_stat_range="S"
hero_stat_days="30"
aggregate_hero_ring_game_stats="False"
aggregate_hero_tourney_stats="True"
hero_stat_aggregation_range="S"
hero_aggregation_days="30"
aggregate_hero_tourney_stats="False"
hero_aggregation_level_multiplier="1"
label="FPDB Menu - Right-click
@ -570,8 +574,8 @@ Left-Drag to Move"
</hhcs>
<supported_databases>
<database db_name="fpdb" db_server="mysql" db_ip="localhost" db_user="fpdb" db_pass="YOUR MYSQL PASSWORD" db_type="fpdb"></database>
<!-- <database db_ip="localhost" db_name="fpdb" db_pass="fpdb" db_server="sqlite" db_type="fpdb" db_user="fpdb"/> -->
<database db_name="fpdb" db_server="mysql" db_ip="localhost" db_user="fpdb" db_pass="YOUR MYSQL PASSWORD"></database>
<!-- <database db_ip="localhost" db_name="fpdb" db_pass="fpdb" db_server="sqlite" db_user="fpdb"/> -->
</supported_databases>
</FreePokerToolsConfig>

View File

@ -33,7 +33,7 @@ import os
import Options
import traceback
(options, sys.argv) = Options.fpdb_options()
(options, argv) = Options.fpdb_options()
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_."
@ -63,34 +63,6 @@ elif os.name == 'nt':
import Hud
# HUD params:
# - Set aggregate_ring and/or aggregate_tour to True is you want to include stats from other blind levels in the HUD display
# - If aggregation is used, the value of agg_bb_mult determines what levels are included. If
# agg_bb_mult is M and current blind level is L, blinds between L/M and L*M are included. e.g.
# if agg_bb_mult is 100, almost all levels are included in all HUD displays
# if agg_bb_mult is 2, levels from half to double the current blind level are included in the HUD
# if agg_bb_mult is 1 only the current level is included
# - Set hud_style to A to see stats for all-time
# Set hud_style to S to only see stats for current session (currently this shows stats for the last 24 hours)
# Set hud_style to T to only see stats for the last N days (uses value in hud_days)
# - Set hud_days to N to see stats for the last N days in the HUD (only applies if hud_style is T)
def_hud_params = { # Settings for all players apart from program owner ('hero')
'aggregate_ring' : False
, 'aggregate_tour' : True
, 'hud_style' : 'A'
, 'hud_days' : 90
, 'agg_bb_mult' : 10000 # 1 means no aggregation
# , 'hud_session_gap' : 30 not currently used
# Second set of variables for hero - these settings only apply to the program owner
, 'h_aggregate_ring' : False
, 'h_aggregate_tour' : True
, 'h_hud_style' : 'S' # A(ll) / S(ession) / T(ime in days)
, 'h_hud_days' : 60
, 'h_agg_bb_mult' : 10000 # 1 means no aggregation
# , 'h_hud_session_gap' : 30 not currently used
}
class HUD_main(object):
"""A main() object to own both the read_stdin thread and the gui."""
# This class mainly provides state for controlling the multiple HUDs.
@ -133,10 +105,7 @@ class HUD_main(object):
def idle_func():
gtk.gdk.threads_enter()
try: # TODO: seriously need to decrease the scope of this block.. what are we expecting to error?
# TODO: The purpose of this try/finally block is to make darn sure that threads_leave()
# TODO: gets called. If there is an exception and threads_leave() doesn't get called we
# TODO: lock up. REB
try:
table.gdkhandle = gtk.gdk.window_foreign_new(table.number)
newlabel = gtk.Label("%s - %s" % (table.site, table_name))
self.vb.add(newlabel)
@ -150,15 +119,20 @@ class HUD_main(object):
m.update_gui(new_hand_id)
self.hud_dict[table_name].update(new_hand_id, self.config)
self.hud_dict[table_name].reposition_windows()
return False
except:
print "*** Exception in HUD_main::idle_func() *** "
traceback.print_stack()
finally:
gtk.gdk.threads_leave()
return False
self.hud_dict[table_name] = Hud.Hud(self, table, max, poker_game, self.config, self.db_connection)
self.hud_dict[table_name].table_name = table_name
self.hud_dict[table_name].stat_dict = stat_dict
self.hud_dict[table_name].cards = cards
# set agg_bb_mult so that aggregate_tour and aggregate_ring can be ignored,
# agg_bb_mult == 1 means no aggregation after these if statements:
if type == "tour" and self.hud_params['aggregate_tour'] == False:
self.hud_dict[table_name].hud_params['agg_bb_mult'] = 1
elif type == "ring" and self.hud_params['aggregate_ring'] == False:
@ -167,8 +141,13 @@ class HUD_main(object):
self.hud_dict[table_name].hud_params['h_agg_bb_mult'] = 1
elif type == "ring" and self.hud_params['h_aggregate_ring'] == False:
self.hud_dict[table_name].hud_params['h_agg_bb_mult'] = 1
self.hud_params['aggregate_ring'] == True
self.hud_params['h_aggregate_ring'] == True
# sqlcoder: I forget why these are set to true (aren't they ignored from now on?)
# but I think it's needed:
self.hud_params['aggregate_ring'] = True
self.hud_params['h_aggregate_ring'] = True
# so maybe the tour ones should be set as well? does this fix the bug I see mentioned?
self.hud_params['aggregate_tour'] = True
self.hud_params['h_aggregate_tour'] = True
[aw.update_data(new_hand_id, self.db_connection) for aw in self.hud_dict[table_name].aux_windows]
gobject.idle_add(idle_func)
@ -180,10 +159,14 @@ class HUD_main(object):
# function idle_func() to be run by the gui thread, at its leisure.
def idle_func():
gtk.gdk.threads_enter()
# try:
self.hud_dict[table_name].update(new_hand_id, config)
# The HUD could get destroyed in the above call ^^, which leaves us with a KeyError here vv
# if we ever get an error we need to expect ^^ then we need to handle it vv - Eric
try:
[aw.update_gui(new_hand_id) for aw in self.hud_dict[table_name].aux_windows]
# finally:
except KeyError:
pass
finally:
gtk.gdk.threads_leave()
return False
@ -217,9 +200,9 @@ class HUD_main(object):
# get basic info about the new hand from the db
# if there is a db error, complain, skip hand, and proceed
try:
(table_name, max, poker_game, type, site_id, site_name, tour_number, tab_number) = \
(table_name, max, poker_game, type, site_id, site_name, num_seats, tour_number, tab_number) = \
self.db_connection.get_table_info(new_hand_id)
except Exception, err:
except Exception, err: # TODO: we need to make this a much less generic Exception lulz
print "db error: skipping %s" % new_hand_id
sys.stderr.write("Database error: could not find hand %s.\n" % new_hand_id)
continue
@ -232,10 +215,17 @@ class HUD_main(object):
# Update an existing HUD
if temp_key in self.hud_dict:
# get stats using hud's specific params and get cards
try:
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'])
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])
self.hud_dict[temp_key].stat_dict = stat_dict
except KeyError: # HUD instance has been killed off, key is stale
sys.stderr.write('hud_dict[%s] was not found\n' % temp_key)
sys.stderr.write('will not send hand\n')
# Unlocks table, copied from end of function
self.db_connection.connection.rollback()
return
cards = self.db_connection.get_cards(new_hand_id)
comm_cards = self.db_connection.get_common_cards(new_hand_id)
if comm_cards != {}: # stud!
@ -248,7 +238,8 @@ class HUD_main(object):
else:
# 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'] )
stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_params, self.hero_ids[site_id])
stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_params
,self.hero_ids[site_id], num_seats)
cards = self.db_connection.get_cards(new_hand_id)
comm_cards = self.db_connection.get_common_cards(new_hand_id)
if comm_cards != {}: # stud!
@ -266,7 +257,12 @@ class HUD_main(object):
else:
tablewindow.max = max
tablewindow.site = site_name
# Test that the table window still exists
if hasattr(tablewindow, 'number'):
self.create_HUD(new_hand_id, tablewindow, temp_key, max, poker_game, type, stat_dict, cards)
else:
sys.stderr.write('Table "%s" no longer exists\n' % table_name)
self.db_connection.connection.rollback()
if __name__== "__main__":

View File

@ -37,7 +37,8 @@ if __name__== "__main__":
HUD_main.config = Configuration.Config()
gobject.threads_init() # this is required
thread.start_new_thread(HUD_main.read_stdin, ()) # starts the thread
hud = HUD_main.HUD_main()
thread.start_new_thread(hud.read_stdin, ()) # starts the thread
HUD_main.main_window = gtk.Window()
HUD_main.main_window.connect("destroy", destroy)

View File

@ -210,23 +210,23 @@ db: a connected fpdb_db object"""
#####
# End prep functions
#####
# HandsActions - all actions for all players for all streets - self.actions
# HudCache data can be generated from HandsActions (HandsPlayers?)
# Hands - Summary information of hand indexed by handId - gameinfo
hh = self.stats.getHands()
if not db.isDuplicate(gtid, hh['siteHandNo']):
# Hands - Summary information of hand indexed by handId - gameinfo
hh['gameTypeId'] = gtid
# seats TINYINT NOT NULL,
hh['seats'] = len(sqlids)
#print hh
handid = db.storeHand(hh)
# HandsPlayers - ? ... Do we fix winnings?
db.storeHandsPlayers(handid, sqlids, self.stats.getHandsPlayers())
# HandsActions - all actions for all players for all streets - self.actions
# HudCache data can be generated from HandsActions (HandsPlayers?)
# Tourneys ?
# TourneysPlayers
else:
log.info("Hand.insert(): hid #: %s is a duplicate" % hh['siteHandNo'])
#Raise Duplicate exception?
pass
def select(self, handId):
@ -510,7 +510,7 @@ Map the tuple self.gametype onto the pokerstars string describing it
def printHand(self):
self.writeHand(sys.stdout)
def actionString(self, act):
def actionString(self, act, street=None):
if act[1] == 'folds':
return ("%s: folds " %(act[0]))
elif act[1] == 'checks':
@ -535,7 +535,7 @@ Map the tuple self.gametype onto the pokerstars string describing it
elif act[1] == 'bringin':
return ("%s: brings in for %s%s%s" %(act[0], self.sym, act[2], ' and is all-in' if act[3] else ''))
elif act[1] == 'discards':
return ("%s: discards %s %s%s" %(act[0], act[2], 'card' if act[2] == 1 else 'cards' , " [" + " ".join(self.discards[act[0]]['DRAWONE']) + "]" if self.hero == act[0] else ''))
return ("%s: discards %s %s%s" %(act[0], act[2], 'card' if act[2] == 1 else 'cards' , " [" + " ".join(self.discards[street][act[0]]) + "]" if self.hero == act[0] else ''))
elif act[1] == 'stands pat':
return ("%s: stands pat" %(act[0]))
@ -668,6 +668,27 @@ class HoldemOmahaHand(Hand):
tmp5 = 0
return (tmp1,tmp2,tmp3,tmp4,tmp5)
def join_holecards(self, player, asList=False):
"""With asList = True it returns the set cards for a player including down cards if they aren't know"""
# FIXME: This should actually return
hcs = [u'0x', u'0x', u'0x', u'0x']
for street in self.holeStreets:
if player in self.holecards[street].keys():
hcs[0] = self.holecards[street][player][1][0]
hcs[1] = self.holecards[street][player][1][1]
try:
hcs[2] = self.holecards[street][player][1][2]
hcs[3] = self.holecards[street][player][1][3]
except IndexError:
pass
if asList == False:
return " ".join(hcs)
else:
return hcs
def writeHTMLHand(self):
from nevow import tags as T
from nevow import flat
@ -872,7 +893,7 @@ class DrawHand(Hand):
self.streetList = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE']
self.allStreets = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE']
self.holeStreets = ['DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE']
self.actionStreets = ['PREDEAL', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE']
self.actionStreets = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE']
self.communityStreets = []
Hand.__init__(self, sitename, gametype, handText)
self.sb = gametype['sb']
@ -953,6 +974,13 @@ class DrawHand(Hand):
act = (player, 'discards', num)
self.actions[street].append(act)
def holecardsAsSet(self, street, player):
"""Return holdcards: (oc, nc) as set()"""
(nc,oc) = self.holecards[street][player]
nc = set(nc)
oc = set(oc)
return (nc, oc)
def getStreetTotals(self):
# street1Pot INT, /* pot size at flop/street4 */
# street2Pot INT, /* pot size at turn/street5 */
@ -961,6 +989,16 @@ class DrawHand(Hand):
# showdownPot INT, /* pot size at sd/street7 */
return (0,0,0,0,0)
def join_holecards(self, player, asList=False):
"""With asList = True it returns the set cards for a player including down cards if they aren't know"""
# FIXME: This should actually return
holecards = [u'0x', u'0x', u'0x', u'0x', u'0x']
if asList == False:
return " ".join(holecards)
else:
return holecards
def writeHand(self, fh=sys.__stdout__):
# PokerStars format.
@ -979,18 +1017,19 @@ class DrawHand(Hand):
if 'DEAL' in self.actions:
print >>fh, _("*** DEALING HANDS ***")
for player in [x[1] for x in self.players if x[1] in players_who_act_ondeal]:
if 'DEAL' in self.holecards[player]:
(nc,oc) = self.holecards[player]['DEAL']
if 'DEAL' in self.holecards:
if self.holecards['DEAL'].has_key(player):
(nc,oc) = self.holecards['DEAL'][player]
print >>fh, _("Dealt to %s: [%s]") % (player, " ".join(nc))
for act in self.actions['DEAL']:
print >>fh, self.actionString(act)
print >>fh, self.actionString(act, 'DEAL')
if 'DRAWONE' in self.actions:
print >>fh, _("*** FIRST DRAW ***")
for act in self.actions['DRAWONE']:
print >>fh, self.actionString(act)
print >>fh, self.actionString(act, 'DRAWONE')
if act[0] == self.hero and act[1] == 'discards':
(nc,oc) = self.holecards['DRAWONE'][act[0]]
(nc,oc) = self.holecardsAsSet('DRAWONE', act[0])
dc = self.discards['DRAWONE'][act[0]]
kc = oc - dc
print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc)))
@ -998,9 +1037,9 @@ class DrawHand(Hand):
if 'DRAWTWO' in self.actions:
print >>fh, _("*** SECOND DRAW ***")
for act in self.actions['DRAWTWO']:
print >>fh, self.actionString(act)
print >>fh, self.actionString(act, 'DRAWTWO')
if act[0] == self.hero and act[1] == 'discards':
(nc,oc) = self.holecards['DRAWTWO'][act[0]]
(nc,oc) = self.holecardsAsSet('DRAWONE', act[0])
dc = self.discards['DRAWTWO'][act[0]]
kc = oc - dc
print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc)))
@ -1008,9 +1047,9 @@ class DrawHand(Hand):
if 'DRAWTHREE' in self.actions:
print >>fh, _("*** THIRD DRAW ***")
for act in self.actions['DRAWTHREE']:
print >>fh, self.actionString(act)
print >>fh, self.actionString(act, 'DRAWTHREE')
if act[0] == self.hero and act[1] == 'discards':
(nc,oc) = self.holecards['DRAWTHREE'][act[0]]
(nc,oc) = self.holecardsAsSet('DRAWONE', act[0])
dc = self.discards['DRAWTHREE'][act[0]]
kc = oc - dc
print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc)))
@ -1286,7 +1325,9 @@ Add a complete on [street] by [player] to [amountTo]
if street == 'SEVENTH' and player != self.hero: return # only write 7th st line for hero, LDO
return hc + " ".join(self.holecards[street][player][1]) + "] [" + " ".join(self.holecards[street][player][0]) + "]"
def join_holecards(self, player):
def join_holecards(self, player, asList=False):
"""Function returns a string for the stud writeHand method by default
With asList = True it returns the set cards for a player including down cards if they aren't know"""
holecards = []
for street in self.holeStreets:
if self.holecards[street].has_key(player):
@ -1299,7 +1340,20 @@ Add a complete on [street] by [player] to [amountTo]
holecards = holecards + self.holecards[street][player][1]
else:
holecards = holecards + self.holecards[street][player][0]
if asList == False:
return " ".join(holecards)
else:
if player == self.hero or len(holecards) == 7:
return holecards
elif len(holecards) <= 4:
#Non hero folded before showdown, add first two downcards
holecards = [u'0x', u'0x'] + holecards
else:
log.warning("join_holecards: # of holecards should be either < 4, 4 or 7 - 5 and 6 should be impossible for anyone who is not a hero")
log.warning("join_holcards: holecards(%s): %s" %(player, holecards))
return holecards
class Pot(object):

View File

@ -32,19 +32,12 @@ from xml.dom.minidom import Node
import time
import datetime
from Exceptions import FpdbParseError
import Configuration
import gettext
gettext.install('fpdb')
import logging, logging.config
import ConfigParser
try:
logging.config.fileConfig(os.path.join(sys.path[0],"logging.conf"))
except ConfigParser.NoSectionError: # debian package path
logging.config.fileConfig('/usr/share/python-fpdb/logging.conf')
log = logging.getLogger("parser")
log = Configuration.get_logger("logging.conf")
import pygtk
import gtk
@ -101,7 +94,7 @@ follow : whether to tail -f the input"""
else:
log.info("Created directory '%s'" % out_dir)
try:
self.out_fh = codecs.open(self.out_path, 'w', 'cp1252')
self.out_fh = codecs.open(self.out_path, 'w', 'utf8')
except:
log.error("out_path %s couldn't be opened" % (self.out_path))
else:
@ -268,8 +261,8 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py.
gametype = self.determineGameType(handText)
log.debug("gametype %s" % gametype)
hand = None
if gametype is None:
l = None
if gametype is None:
gametype = "unmatched"
# TODO: not ideal, just trying to not error.
# TODO: Need to count failed hands.
@ -291,9 +284,7 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py.
log.info("Unsupported game type: %s" % gametype)
if hand:
# uncomment these to calculate some stats
# print hand
# hand.stats.getStats(hand)
if Configuration.NEWIMPORT == False:
hand.writeHand(self.out_fh)
return hand
else:

View File

@ -175,6 +175,24 @@ class Hud:
item.connect("activate", self.set_aggregation, ('P',10000))
setattr(self, 'h_aggBBmultItem10000', item)
#
item = gtk.MenuItem('For #Seats:')
self.aggMenu.append(item)
#
item = gtk.CheckMenuItem(' Any Number')
self.aggMenu.append(item)
item.connect("activate", self.set_seats_style, ('P','A'))
setattr(self, 'h_seatsStyleOptionA', item)
#
item = gtk.CheckMenuItem(' Custom')
self.aggMenu.append(item)
item.connect("activate", self.set_seats_style, ('P','C'))
setattr(self, 'h_seatsStyleOptionC', item)
#
item = gtk.CheckMenuItem(' Exact')
self.aggMenu.append(item)
item.connect("activate", self.set_seats_style, ('P','E'))
setattr(self, 'h_seatsStyleOptionE', item)
#
item = gtk.MenuItem('Since:')
self.aggMenu.append(item)
#
@ -226,6 +244,24 @@ class Hud:
item.connect("activate", self.set_aggregation, ('O',10000))
setattr(self, 'aggBBmultItem10000', item)
#
item = gtk.MenuItem('For #Seats:')
self.aggMenu.append(item)
#
item = gtk.CheckMenuItem(' Any Number')
self.aggMenu.append(item)
item.connect("activate", self.set_seats_style, ('O','A'))
setattr(self, 'seatsStyleOptionA', item)
#
item = gtk.CheckMenuItem(' Custom')
self.aggMenu.append(item)
item.connect("activate", self.set_seats_style, ('O','C'))
setattr(self, 'seatsStyleOptionC', item)
#
item = gtk.CheckMenuItem(' Exact')
self.aggMenu.append(item)
item.connect("activate", self.set_seats_style, ('O','E'))
setattr(self, 'seatsStyleOptionE', item)
#
item = gtk.MenuItem('Since:')
self.aggMenu.append(item)
#
@ -267,6 +303,20 @@ class Hud:
elif self.hud_params['agg_bb_mult'] > 9000:
getattr(self, 'aggBBmultItem10000').set_active(True)
#
if self.hud_params['h_seats_style'] == 'A':
getattr(self, 'h_seatsStyleOptionA').set_active(True)
elif self.hud_params['h_seats_style'] == 'C':
getattr(self, 'h_seatsStyleOptionC').set_active(True)
elif self.hud_params['h_seats_style'] == 'E':
getattr(self, 'h_seatsStyleOptionE').set_active(True)
#
if self.hud_params['seats_style'] == 'A':
getattr(self, 'seatsStyleOptionA').set_active(True)
elif self.hud_params['seats_style'] == 'C':
getattr(self, 'seatsStyleOptionC').set_active(True)
elif self.hud_params['seats_style'] == 'E':
getattr(self, 'seatsStyleOptionE').set_active(True)
#
if self.hud_params['h_hud_style'] == 'A':
getattr(self, 'h_hudStyleOptionA').set_active(True)
elif self.hud_params['h_hud_style'] == 'S':
@ -344,6 +394,29 @@ class Hud:
if mult != str(num):
getattr(self, 'aggBBmultItem'+mult).set_active(False)
def set_seats_style(self, widget, val):
(player_opp, style) = val
if player_opp == 'P':
param = 'h_seats_style'
prefix = 'h_'
else:
param = 'seats_style'
prefix = ''
if style == 'A' and getattr(self, prefix+'seatsStyleOptionA').get_active():
self.hud_params[param] = 'A'
getattr(self, prefix+'seatsStyleOptionC').set_active(False)
getattr(self, prefix+'seatsStyleOptionE').set_active(False)
elif style == 'C' and getattr(self, prefix+'seatsStyleOptionC').get_active():
self.hud_params[param] = 'C'
getattr(self, prefix+'seatsStyleOptionA').set_active(False)
getattr(self, prefix+'seatsStyleOptionE').set_active(False)
elif style == 'E' and getattr(self, prefix+'seatsStyleOptionE').get_active():
self.hud_params[param] = 'E'
getattr(self, prefix+'seatsStyleOptionA').set_active(False)
getattr(self, prefix+'seatsStyleOptionC').set_active(False)
print "setting self.hud_params[%s] = %s" % (param, style)
def set_hud_style(self, widget, val):
(player_opp, style) = val
if player_opp == 'P':
@ -409,7 +482,7 @@ class Hud:
try:
# throws "invalid window handle" in WinXP (sometimes?)
s.window.destroy()
except:
except: # TODO: what exception?
pass
self.stat_windows = {}
# also kill any aux windows
@ -530,7 +603,8 @@ class Hud:
def update(self, hand, config):
self.hand = hand # this is the last hand, so it is available later
if os.name == 'nt':
self.update_table_position()
if self.update_table_position() == False: # we got killed by finding our table was gone
return
for s in self.stat_dict:
try:

View File

@ -35,11 +35,14 @@ def fpdb_options():
parser.add_option("-r", "--rerunPython",
action="store_true",
help="Indicates program was restarted with a different path (only allowed once).")
(options, sys.argv) = parser.parse_args()
return (options, sys.argv)
parser.add_option("-i", "--infile",
dest="config", default=None,
help="Input file")
(options, argv) = parser.parse_args()
return (options, argv)
if __name__== "__main__":
(options, sys.argv) = fpdb_options()
(options, argv) = fpdb_options()
print "errorsToConsole =", options.errorsToConsole
print "database name =", options.dbname
print "config file =", options.config

View File

@ -31,18 +31,18 @@ class PokerStars(HandHistoryConverter):
sitename = "PokerStars"
filetype = "text"
codepage = "cp1252"
codepage = ("utf8", "cp1252")
siteId = 2 # Needs to match id entry in Sites database
mixes = { 'HORSE': 'horse', '8-Game': '8game', 'HOSE': 'hose'} # Legal mixed games
sym = {'USD': "\$", 'CAD': "\$", 'T$': "", "EUR": "\x80", "GBP": "\xa3"} # ADD Euro, Sterling, etc HERE
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' : "\$|\x80|\xa3" # legal currency symbols ADD Euro, Sterling, etc HERE
'LS' : "\$|\xe2\x82\xac|" # legal currency symbols - Euro(cp1252, utf-8)
}
# Static regexes
re_GameInfo = re.compile("""
re_GameInfo = re.compile(u"""
PokerStars\sGame\s\#(?P<HID>[0-9]+):\s+
(Tournament\s\# # open paren of tournament info
(?P<TOURNO>\d+),\s
@ -50,7 +50,7 @@ class PokerStars(HandHistoryConverter):
\s?(?P<TOUR_ISO>%(LEGAL_ISO)s)?
)\s)? # close paren of tournament info
(?P<MIXED>HORSE|8\-Game|HOSE)?\s?\(?
(?P<GAME>Hold\'em|Razz|7\sCard\sStud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball)\s
(?P<GAME>Hold\'em|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|Pot\sLimit)\)?,?\s
(-\sLevel\s(?P<LEVEL>[IVXLC]+)\s)?
\(? # open paren of the stakes
@ -62,7 +62,7 @@ class PokerStars(HandHistoryConverter):
(?P<DATETIME>.*$)""" % substitutions,
re.MULTILINE|re.VERBOSE)
re_PlayerInfo = re.compile("""
re_PlayerInfo = re.compile(u"""
^Seat\s(?P<SEAT>[0-9]+):\s
(?P<PNAME>.*)\s
\((%(LS)s)?(?P<CASH>[.0-9]+)\sin\schips\)""" % substitutions,
@ -92,7 +92,7 @@ class PokerStars(HandHistoryConverter):
self.compiledPlayers = players
player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")"
subst = {'PLYR': player_re, 'CUR': self.sym[hand.gametype['currency']]}
logging.debug("player_re: " + player_re)
log.debug("player_re: " + player_re)
self.re_PostSB = re.compile(r"^%(PLYR)s: posts small blind %(CUR)s(?P<SB>[.0-9]+)" % subst, re.MULTILINE)
self.re_PostBB = re.compile(r"^%(PLYR)s: 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)
@ -101,7 +101,7 @@ class PokerStars(HandHistoryConverter):
self.re_HeroCards = re.compile(r"^Dealt to %(PLYR)s(?: \[(?P<OLDCARDS>.+?)\])?( \[(?P<NEWCARDS>.+?)\])" % subst, re.MULTILINE)
self.re_Action = re.compile(r"""
^%(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>
(\scards?(\s\[(?P<DISCARDED>.+?)\])?)?"""
% subst, re.MULTILINE|re.VERBOSE)
self.re_ShowdownAction = re.compile(r"^%s: shows \[(?P<CARDS>.*)\]" % player_re, re.MULTILINE)
@ -133,6 +133,7 @@ class PokerStars(HandHistoryConverter):
info = {}
m = self.re_GameInfo.search(handText)
if not m:
print "DEBUG: determineGameType(): did not match"
return None
mg = m.groupdict()
@ -147,6 +148,7 @@ class PokerStars(HandHistoryConverter):
'7 Card Stud Hi/Lo' : ('stud','studhilo'),
'Badugi' : ('draw','badugi'),
'Triple Draw 2-7 Lowball' : ('draw','27_3draw'),
'5 Card Draw' : ('draw','fivedraw')
}
currencies = { u'':'EUR', '$':'USD', '':'T$' }
# I don't think this is doing what we think. mg will always have all
@ -186,7 +188,7 @@ class PokerStars(HandHistoryConverter):
# 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)
log.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]
@ -226,10 +228,10 @@ class PokerStars(HandHistoryConverter):
if m:
hand.buttonpos = int(m.group('BUTTON'))
else:
logging.info('readButton: not found')
log.info('readButton: not found')
def readPlayerStacks(self, hand):
logging.debug("readPlayerStacks")
log.debug("readPlayerStacks")
m = self.re_PlayerInfo.finditer(hand.handText)
players = []
for a in m:
@ -265,7 +267,7 @@ class PokerStars(HandHistoryConverter):
hand.setCommunityCards(street, m.group('CARDS').split(' '))
def readAntes(self, hand):
logging.debug("reading antes")
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')))
@ -373,12 +375,9 @@ if __name__ == "__main__":
parser.add_option("-i", "--input", dest="ipath", help="parse input hand history", default="regression-test-files/stars/horse/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")
#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()

View File

@ -33,12 +33,11 @@ import re
class Sql:
def __init__(self, game = 'holdem', type = 'fpdb', db_server = 'mysql'):
def __init__(self, game = 'holdem', db_server = 'mysql'):
self.query = {}
###############################################################################3
# Support for the Free Poker DataBase = fpdb http://fpdb.sourceforge.net/
#
if type == 'fpdb':
################################
# List tables
@ -213,7 +212,7 @@ class Sql:
if db_server == 'mysql':
self.query['createHandsTable'] = """CREATE TABLE Hands (
id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
tableName VARCHAR(20) NOT NULL,
tableName VARCHAR(22) NOT NULL,
siteHandNo BIGINT NOT NULL,
gametypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id),
handStart DATETIME NOT NULL,
@ -248,7 +247,7 @@ class Sql:
elif db_server == 'postgresql':
self.query['createHandsTable'] = """CREATE TABLE Hands (
id BIGSERIAL, PRIMARY KEY (id),
tableName VARCHAR(20) NOT NULL,
tableName VARCHAR(22) NOT NULL,
siteHandNo BIGINT NOT NULL,
gametypeId INT NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id),
handStart timestamp without time zone NOT NULL,
@ -282,7 +281,7 @@ class Sql:
elif db_server == 'sqlite':
self.query['createHandsTable'] = """CREATE TABLE Hands (
id INTEGER PRIMARY KEY,
tableName TEXT(20) NOT NULL,
tableName TEXT(22) NOT NULL,
siteHandNo INT NOT NULL,
gametypeId INT NOT NULL,
handStart REAL NOT NULL,
@ -462,7 +461,7 @@ class Sql:
totalProfit INT,
comment text,
commentTs DATETIME,
tourneysPlayersId BIGINT UNSIGNED,
tourneysPlayersId BIGINT UNSIGNED, FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id),
tourneyTypeId SMALLINT UNSIGNED NOT NULL DEFAULT 1, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
wonWhenSeenStreet1 FLOAT,
@ -552,9 +551,7 @@ class Sql:
street3Raises TINYINT,
street4Raises TINYINT,
actionString VARCHAR(15),
FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id))
actionString VARCHAR(15))
ENGINE=INNODB"""
elif db_server == 'postgresql':
self.query['createHandsPlayersTable'] = """CREATE TABLE HandsPlayers (
@ -1403,6 +1400,7 @@ class Sql:
AND gt1.bigblind <= gt2.bigblind * %s /* bigblind similar size */
AND gt1.bigblind >= gt2.bigblind / %s
AND gt2.id = h.gametypeId)
AND hc.activeSeats between %s and %s
)
OR
( hp.playerId = %s
@ -1416,6 +1414,7 @@ class Sql:
AND gt1.bigblind <= gt2.bigblind * %s /* bigblind similar size */
AND gt1.bigblind >= gt2.bigblind / %s
AND gt2.id = h.gametypeId)
AND hc.activeSeats between %s and %s
)
)
GROUP BY hc.PlayerId, p.name
@ -1433,11 +1432,11 @@ class Sql:
if db_server == 'mysql':
self.query['get_stats_from_hand_session'] = """
SELECT hp.playerId AS player_id,
SELECT hp.playerId AS player_id, /* playerId and seats must */
h.seats AS seats, /* be first and second field */
hp.handId AS hand_id,
hp.seatNo AS seat,
p.name AS screen_name,
h.seats AS seats,
1 AS n,
cast(hp2.street0VPI as <signed>integer) AS vpip,
cast(hp2.street0Aggr as <signed>integer) AS pfr,
@ -1495,21 +1494,30 @@ class Sql:
cast(hp2.street4CheckCallRaiseChance as <signed>integer) AS ccr_opp_4,
cast(hp2.street4CheckCallRaiseDone as <signed>integer) AS ccr_4
FROM
Hands h /* players in this hand */
Hands h
INNER JOIN Hands h2 ON (h2.id > %s AND h2.tableName = h.tableName)
INNER JOIN HandsPlayers hp ON (h.id = hp.handId)
INNER JOIN HandsPlayers hp ON (h.id = hp.handId) /* players in this hand */
INNER JOIN HandsPlayers hp2 ON (hp2.playerId+0 = hp.playerId+0 AND (hp2.handId = h2.id+0)) /* other hands by these players */
INNER JOIN Players p ON (p.id = hp2.PlayerId+0)
WHERE hp.handId = %s
/* check activeseats once this data returned (don't want to do that here as it might
assume a session ended just because the number of seats dipped for a few hands)
*/
AND ( /* 2 separate parts for hero and opponents */
( hp2.playerId != %s
AND h2.seats between %s and %s
)
OR
( hp2.playerId = %s
AND h2.seats between %s and %s
)
)
ORDER BY h.handStart desc, hp2.PlayerId
/* order rows by handstart descending so that we can stop reading rows when
there's a gap over X minutes between hands (ie. when we get back to start of
the session */
"""
else: # assume postgresql
elif db_server == 'postgresql':
self.query['get_stats_from_hand_session'] = """
SELECT hp.playerId AS player_id,
hp.handId AS hand_id,
@ -1583,6 +1591,103 @@ class Sql:
/* check activeseats once this data returned (don't want to do that here as it might
assume a session ended just because the number of seats dipped for a few hands)
*/
AND ( /* 2 separate parts for hero and opponents */
( hp2.playerId != %s
AND h2.seats between %s and %s
)
OR
( hp2.playerId = %s
AND h2.seats between %s and %s
)
)
ORDER BY h.handStart desc, hp2.PlayerId
/* order rows by handstart descending so that we can stop reading rows when
there's a gap over X minutes between hands (ie. when we get back to start of
the session */
"""
elif db_server == 'sqlite':
self.query['get_stats_from_hand_session'] = """
SELECT hp.playerId AS player_id,
hp.handId AS hand_id,
hp.seatNo AS seat,
p.name AS screen_name,
h.seats AS seats,
1 AS n,
cast(hp2.street0VPI as <signed>integer) AS vpip,
cast(hp2.street0Aggr as <signed>integer) AS pfr,
cast(hp2.street0_3BChance as <signed>integer) AS TB_opp_0,
cast(hp2.street0_3BDone as <signed>integer) AS TB_0,
cast(hp2.street1Seen as <signed>integer) AS saw_f,
cast(hp2.street1Seen as <signed>integer) AS saw_1,
cast(hp2.street2Seen as <signed>integer) AS saw_2,
cast(hp2.street3Seen as <signed>integer) AS saw_3,
cast(hp2.street4Seen as <signed>integer) AS saw_4,
cast(hp2.sawShowdown as <signed>integer) AS sd,
cast(hp2.street1Aggr as <signed>integer) AS aggr_1,
cast(hp2.street2Aggr as <signed>integer) AS aggr_2,
cast(hp2.street3Aggr as <signed>integer) AS aggr_3,
cast(hp2.street4Aggr as <signed>integer) AS aggr_4,
cast(hp2.otherRaisedStreet1 as <signed>integer) AS was_raised_1,
cast(hp2.otherRaisedStreet2 as <signed>integer) AS was_raised_2,
cast(hp2.otherRaisedStreet3 as <signed>integer) AS was_raised_3,
cast(hp2.otherRaisedStreet4 as <signed>integer) AS was_raised_4,
cast(hp2.foldToOtherRaisedStreet1 as <signed>integer) AS f_freq_1,
cast(hp2.foldToOtherRaisedStreet2 as <signed>integer) AS f_freq_2,
cast(hp2.foldToOtherRaisedStreet3 as <signed>integer) AS f_freq_3,
cast(hp2.foldToOtherRaisedStreet4 as <signed>integer) AS f_freq_4,
cast(hp2.wonWhenSeenStreet1 as <signed>integer) AS w_w_s_1,
cast(hp2.wonAtSD as <signed>integer) AS wmsd,
cast(hp2.stealAttemptChance as <signed>integer) AS steal_opp,
cast(hp2.stealAttempted as <signed>integer) AS steal,
cast(hp2.foldSbToStealChance as <signed>integer) AS SBstolen,
cast(hp2.foldedSbToSteal as <signed>integer) AS SBnotDef,
cast(hp2.foldBbToStealChance as <signed>integer) AS BBstolen,
cast(hp2.foldedBbToSteal as <signed>integer) AS BBnotDef,
cast(hp2.street1CBChance as <signed>integer) AS CB_opp_1,
cast(hp2.street1CBDone as <signed>integer) AS CB_1,
cast(hp2.street2CBChance as <signed>integer) AS CB_opp_2,
cast(hp2.street2CBDone as <signed>integer) AS CB_2,
cast(hp2.street3CBChance as <signed>integer) AS CB_opp_3,
cast(hp2.street3CBDone as <signed>integer) AS CB_3,
cast(hp2.street4CBChance as <signed>integer) AS CB_opp_4,
cast(hp2.street4CBDone as <signed>integer) AS CB_4,
cast(hp2.foldToStreet1CBChance as <signed>integer) AS f_cb_opp_1,
cast(hp2.foldToStreet1CBDone as <signed>integer) AS f_cb_1,
cast(hp2.foldToStreet2CBChance as <signed>integer) AS f_cb_opp_2,
cast(hp2.foldToStreet2CBDone as <signed>integer) AS f_cb_2,
cast(hp2.foldToStreet3CBChance as <signed>integer) AS f_cb_opp_3,
cast(hp2.foldToStreet3CBDone as <signed>integer) AS f_cb_3,
cast(hp2.foldToStreet4CBChance as <signed>integer) AS f_cb_opp_4,
cast(hp2.foldToStreet4CBDone as <signed>integer) AS f_cb_4,
cast(hp2.totalProfit as <signed>integer) AS net,
cast(hp2.street1CheckCallRaiseChance as <signed>integer) AS ccr_opp_1,
cast(hp2.street1CheckCallRaiseDone as <signed>integer) AS ccr_1,
cast(hp2.street2CheckCallRaiseChance as <signed>integer) AS ccr_opp_2,
cast(hp2.street2CheckCallRaiseDone as <signed>integer) AS ccr_2,
cast(hp2.street3CheckCallRaiseChance as <signed>integer) AS ccr_opp_3,
cast(hp2.street3CheckCallRaiseDone as <signed>integer) AS ccr_3,
cast(hp2.street4CheckCallRaiseChance as <signed>integer) AS ccr_opp_4,
cast(hp2.street4CheckCallRaiseDone as <signed>integer) AS ccr_4
FROM Hands h /* this hand */
INNER JOIN Hands h2 ON ( h2.id > %s /* other hands */
AND h2.tableName = h.tableName)
INNER JOIN HandsPlayers hp ON (h.id = hp.handId) /* players in this hand */
INNER JOIN HandsPlayers hp2 ON ( hp2.playerId+0 = hp.playerId+0
AND hp2.handId = h2.id) /* other hands by these players */
INNER JOIN Players p ON (p.id = hp2.PlayerId+0)
WHERE h.id = %s
/* check activeseats once this data returned (don't want to do that here as it might
assume a session ended just because the number of seats dipped for a few hands)
*/
AND ( /* 2 separate parts for hero and opponents */
( hp2.playerId != %s
AND h2.seats between %s and %s
)
OR
( hp2.playerId = %s
AND h2.seats between %s and %s
)
)
ORDER BY h.handStart desc, hp2.PlayerId
/* order rows by handstart descending so that we can stop reading rows when
there's a gap over X minutes between hands (ie. when we get back to start of
@ -1606,10 +1711,13 @@ class Sql:
self.query['get_table_name'] = """
SELECT h.tableName, h.maxSeats, gt.category, gt.type, s.id, s.name
FROM Hands h, Gametypes gt, Sites s
, count(1) as numseats
FROM Hands h, Gametypes gt, Sites s, HandsPlayers hp
WHERE h.id = %s
AND gt.id = h.gametypeId
AND s.id = gt.siteID
AND hp.handId = h.id
GROUP BY h.tableName, h.maxSeats, gt.category, gt.type, s.id, s.name
"""
self.query['get_actual_seat'] = """
@ -1646,15 +1754,6 @@ class Sql:
where Id = %s
"""
self.query['get_action_from_hand'] = """
SELECT street, Players.name, HandsActions.action, HandsActions.amount, actionno
FROM Players, HandsActions, HandsPlayers
WHERE HandsPlayers.handid = %s
AND HandsPlayers.playerid = Players.id
AND HandsActions.handsPlayerId = HandsPlayers.id
ORDER BY street, actionno
"""
if db_server == 'mysql':
self.query['get_hand_1day_ago'] = """
select coalesce(max(id),0)
@ -1950,7 +2049,7 @@ class Sql:
and h.seats <seats_test>
<flagtest>
<gtbigBlind_test>
and to_char(h.handStart, 'YYYY-MM-DD') <datestest>
and date(h.handStart) <datestest>
group by hgameTypeId
,hp.playerId
,gt.base
@ -1970,7 +2069,7 @@ class Sql:
end
<orderbyhgameTypeId>
,upper(gt.limitType) desc
,maxbigblind desc
,max(gt.bigBlind) desc
,s.name
"""
@ -2476,6 +2575,25 @@ class Sql:
GROUP BY h.handStart, hp.handId, hp.totalProfit
ORDER BY h.handStart"""
####################################
# Session stats query
####################################
if db_server == 'mysql':
self.query['sessionStats'] = """
SELECT UNIX_TIMESTAMP(h.handStart) as time, hp.handId, hp.startCash, hp.winnings, hp.totalProfit
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.handStart > '<startdate_test>'
AND h.handStart < '<enddate_test>'
<limit_test>
AND hp.tourneysPlayersId IS NULL
GROUP BY h.handStart, hp.handId, hp.totalProfit
ORDER BY h.handStart"""
####################################
# Session stats query
####################################
@ -2669,6 +2787,8 @@ class Sql:
,hp.tourneyTypeId
,date_format(h.handStart, 'd%y%m%d')
"""
#>>>>>>> 28ca49d592c8e706ad6ee58dd26655bcc33fc5fb:pyfpdb/SQL.py
#"""
elif db_server == 'postgresql':
self.query['rebuildHudCache'] = """
INSERT INTO HudCache
@ -2978,8 +3098,10 @@ class Sql:
analyze table Autorates, GameTypes, Hands, HandsPlayers, HudCache, Players
, Settings, Sites, Tourneys, TourneysPlayers, TourneyTypes
"""
else: # assume postgres
self.query['analyze'] = "vacuum analyze"
elif db_server == 'postgresql':
self.query['analyze'] = "analyze"
elif db_server == 'sqlite':
self.query['analyze'] = "analyze"
if db_server == 'mysql':
self.query['lockForInsert'] = """
@ -2987,8 +3109,20 @@ class Sql:
, HudCache write, GameTypes write, Sites write, Tourneys write
, TourneysPlayers write, TourneyTypes write, Autorates write
"""
else: # assume postgres
elif db_server == 'postgresql':
self.query['lockForInsert'] = ""
elif db_server == 'sqlite':
self.query['lockForInsert'] = ""
if db_server == 'mysql':
self.query['vacuum'] = """optimize table Hands, HandsPlayers, HandsActions, Players
, HudCache, GameTypes, Sites, Tourneys
, TourneysPlayers, TourneyTypes, Autorates
"""
elif db_server == 'postgresql':
self.query['vacuum'] = """ vacuum """
elif db_server == 'sqlite':
self.query['vacuum'] = """ vacuum """
self.query['getGametypeFL'] = """SELECT id
FROM Gametypes

View File

@ -82,18 +82,19 @@ if __name__=="__main__":
(tour_no, tab_no) = table_name.split(",", 1)
tour_no = tour_no.rstrip()
tab_no = tab_no.rstrip()
table = Tables.Table(tournament = tour_no, table_number = tab_no)
table = Tables.Table(None, tournament = tour_no, table_number = tab_no)
else: # not a tournament
print "cash game"
table_name = table_name.rstrip()
table = Tables.Table(table_name = table_name)
table = Tables.Table(None, table_name = table_name)
table.gdk_handle = gtk.gdk.window_foreign_new(table.number)
print "table =", table
print "game =", table.get_game()
# print "game =", table.get_game()
fake = fake_hud(table)
print "fake =", fake
gobject.timeout_add(100, check_on_table, table, fake)
# gobject.timeout_add(100, check_on_table, table, fake)
print "calling main"
gtk.main()

View File

@ -31,7 +31,7 @@ import os
import Options
import traceback
(options, sys.argv) = Options.fpdb_options()
(options, argv) = Options.fpdb_options()
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_."
@ -248,7 +248,7 @@ class ttracker_main(object):
# get basic info about the new hand from the db
# if there is a db error, complain, skip hand, and proceed
try:
(table_name, max, poker_game, type, site_id) = self.db_connection.get_table_name(new_hand_id)
(table_name, max, poker_game, type, site_id, numseats) = self.db_connection.get_table_name(new_hand_id)
stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, aggregate_stats[type]
,hud_style, agg_bb_mult)

View File

@ -57,9 +57,13 @@ class Table(Table_Window):
self.window = hwnd
break
try:
if self.window == None:
print "Window %s not found. Skipping." % search_string
return None
except AttributeError:
print "self.window doesn't exist? why?"
return None
(x, y, width, height) = win32gui.GetWindowRect(hwnd)
print "x = %s y = %s width = %s height = %s" % (x, y, width, height)
@ -149,4 +153,3 @@ class Table(Table_Window):
def win_enum_handler(hwnd, titles):
titles[hwnd] = win32gui.GetWindowText(hwnd)

View File

@ -25,6 +25,7 @@ of Table_Window objects representing the windows found.
# Standard Library modules
import re
import os
# pyGTK modules
import pygtk
@ -40,39 +41,70 @@ from TableWindow import Table_Window
# We might as well do this once and make them globals
disp = Xlib.display.Display()
root = disp.screen().root
name_atom = disp.get_atom("WM_NAME", 1)
class Table(Table_Window):
def find_table_parameters(self, search_string):
self.window = None
done_looping = False
for outside in root.query_tree().children:
for inside in outside.query_tree().children:
if done_looping: break
if inside.get_wm_name() and re.search(search_string, inside.get_wm_name()):
if self.check_bad_words(inside.get_wm_name()): continue
self.window = inside
self.parent = outside
done_looping = True
break
# 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
if self.window == None or self.parent == None:
window_number = None
for listing in os.popen('xwininfo -root -tree').readlines():
if re.search(search_string, listing):
print listing
mo = re.match('\s+([\dxabcdef]+) (.+):\s\(\"([a-zA-Z.]+)\".+ (\d+)x(\d+)\+\d+\+\d+ \+(\d+)\+(\d+)', listing)
self.number = int( mo.group(1), 0)
self.width = int( mo.group(4) )
self.height = int( mo.group(5) )
self.x = int( mo.group(6) )
self.y = int( mo.group(7) )
self.title = re.sub('\"', '', mo.group(2))
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:
print "Window %s not found. Skipping." % search_string
return None
my_geo = self.window.get_geometry()
pa_geo = self.parent.get_geometry()
# my_geo = self.window.get_geometry()
# pa_geo = self.parent.get_geometry()
#
# self.x = pa_geo.x + my_geo.x
# self.y = pa_geo.y + my_geo.y
# self.width = my_geo.width
# self.height = my_geo.height
# self.exe = self.window.get_wm_class()[0]
# self.title = self.window.get_wm_name()
# self.site = ""
# self.hud = None
self.x = pa_geo.x + my_geo.x
self.y = pa_geo.y + my_geo.y
self.width = my_geo.width
self.height = my_geo.height
self.exe = self.window.get_wm_class()[0]
self.title = self.window.get_wm_name()
self.site = ""
self.hud = None
window_string = str(self.window)
# window_string = str(self.window)
mo = re.match('Xlib\.display\.Window\(([\dxabcdef]+)', window_string)
if not mo:
print "Not matched"

View File

@ -53,7 +53,7 @@ import threading
import Options
import string
cl_options = string.join(sys.argv[1:])
(options, sys.argv) = Options.fpdb_options()
(options, argv) = Options.fpdb_options()
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_."
@ -69,6 +69,7 @@ import gtk
import interlocks
import GuiPrefs
import GuiBulkImport
import GuiPlayerStats
import GuiPositionalStats
@ -80,7 +81,7 @@ import SQL
import Database
import FpdbSQLQueries
import Configuration
from Exceptions import *
import Exceptions
VERSION = "0.12"
@ -94,37 +95,97 @@ class fpdb:
self.add_tab(new_tab, new_tab_name)
self.display_tab(new_tab_name)
def add_tab(self, new_tab, new_tab_name):
def add_tab(self, new_page, new_tab_name):
"""adds a tab, namely creates the button and displays it and appends all the relevant arrays"""
for i in self.tab_names: #todo: check this is valid
if i == new_tab_name:
for name in self.nb_tabs: #todo: check this is valid
if name == new_tab_name:
return # if tab already exists, just go to it
self.tabs.append(new_tab)
used_before = False
for i, name in enumerate(self.tab_names): #todo: check this is valid
if name == new_tab_name:
used_before = True
event_box = self.tabs[i]
page = self.pages[i]
break
if not used_before:
event_box = self.create_custom_tab(new_tab_name, self.nb)
page = new_page
self.pages.append(new_page)
self.tabs.append(event_box)
self.tab_names.append(new_tab_name)
new_tab_sel_button = gtk.ToggleButton(new_tab_name)
new_tab_sel_button.connect("clicked", self.tab_clicked, new_tab_name)
self.tab_box.add(new_tab_sel_button)
new_tab_sel_button.show()
self.tab_buttons.append(new_tab_sel_button)
#self.nb.append_page(new_page, gtk.Label(new_tab_name))
self.nb.append_page(page, event_box)
self.nb_tabs.append(new_tab_name)
page.show()
def display_tab(self, new_tab_name):
"""displays the indicated tab"""
tab_no = -1
for i, name in enumerate(self.tab_names):
if name == new_tab_name:
for i, name in enumerate(self.nb_tabs):
if new_tab_name == name:
tab_no = i
break
if tab_no == -1:
raise FpdbError("invalid tab_no")
if tab_no < 0 or tab_no >= self.nb.get_n_pages():
raise FpdbError("invalid tab_no " + str(tab_no))
else:
self.main_vbox.remove(self.current_tab)
self.current_tab=self.tabs[tab_no]
self.main_vbox.add(self.current_tab)
self.tab_buttons[tab_no].set_active(True)
self.current_tab.show()
self.nb.set_current_page(tab_no)
def create_custom_tab(self, text, nb):
#create a custom tab for notebook containing a
#label and a button with STOCK_ICON
eventBox = gtk.EventBox()
tabBox = gtk.HBox(False, 2)
tabLabel = gtk.Label(text)
tabBox.pack_start(tabLabel, False)
eventBox.add(tabBox)
if nb.get_n_pages() > 0:
tabButton = gtk.Button()
tabButton.connect('clicked', self.remove_tab, (nb, text))
#Add a picture on a button
self.add_icon_to_button(tabButton)
tabBox.pack_start(tabButton, False)
# needed, otherwise even calling show_all on the notebook won't
# make the hbox contents appear.
tabBox.show_all()
return eventBox
def add_icon_to_button(self, button):
iconBox = gtk.HBox(False, 0)
image = gtk.Image()
image.set_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_SMALL_TOOLBAR)
gtk.Button.set_relief(button, gtk.RELIEF_NONE)
settings = gtk.Widget.get_settings(button);
(w,h) = gtk.icon_size_lookup_for_settings(settings, gtk.ICON_SIZE_SMALL_TOOLBAR);
gtk.Widget.set_size_request (button, w + 4, h + 4);
image.show()
iconBox.pack_start(image, True, False, 0)
button.add(iconBox)
iconBox.show()
return
# Remove a page from the notebook
def remove_tab(self, button, data):
(nb, text) = data
page = -1
#print "\n remove_tab: start", text
for i, tab in enumerate(self.nb_tabs):
if text == tab:
page = i
#print " page =", page
if page >= 0 and page < self.nb.get_n_pages():
#print " removing page", page
del self.nb_tabs[page]
nb.remove_page(page)
# Need to refresh the widget --
# This forces the widget to redraw itself.
#nb.queue_draw_area(0,0,-1,-1) needed or not??
def delete_event(self, widget, event, data=None):
return False
@ -146,6 +207,20 @@ class fpdb:
dia.run()
dia.destroy()
def dia_preferences(self, widget, data=None):
dia = gtk.Dialog("Preferences",
self.window,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT))
dia.set_default_size(500, 500)
prefs = GuiPrefs.GuiPrefs(self.config, self.window, dia.vbox)
response = dia.run()
if response == gtk.RESPONSE_ACCEPT:
# save updated config
self.config.save()
dia.destroy()
def dia_create_del_database(self, widget, data=None):
self.warning_box("Unimplemented: Create/Delete Database")
self.obtain_global_lock()
@ -282,6 +357,27 @@ class fpdb:
self.release_global_lock()
def dia_rebuild_indexes(self, widget, data=None):
if self.obtain_global_lock():
self.dia_confirm = gtk.MessageDialog(parent=None
,flags=0
,type=gtk.MESSAGE_WARNING
,buttons=(gtk.BUTTONS_YES_NO)
,message_format="Confirm rebuilding database indexes")
diastring = "Please confirm that you want to rebuild the database indexes."
self.dia_confirm.format_secondary_text(diastring)
response = self.dia_confirm.run()
self.dia_confirm.destroy()
if response == gtk.RESPONSE_YES:
self.db.rebuild_indexes()
self.db.vacuumDB()
self.db.analyzeDB()
elif response == gtk.RESPONSE_NO:
print 'User cancelled rebuilding db indexes'
self.release_global_lock()
def __calendar_dialog(self, widget, entry):
self.dia_confirm.set_modal(False)
d = gtk.Window(gtk.WINDOW_TOPLEVEL)
@ -350,6 +446,7 @@ class fpdb:
<menuitem action="LoadProf"/>
<menuitem action="EditProf"/>
<menuitem action="SaveProf"/>
<menuitem action="Preferences"/>
<separator/>
<menuitem action="Quit"/>
</menu>
@ -375,6 +472,7 @@ class fpdb:
<menuitem action="createuser"/>
<menuitem action="createtabs"/>
<menuitem action="rebuildhudcache"/>
<menuitem action="rebuildindexes"/>
<menuitem action="stats"/>
</menu>
<menu action="help">
@ -396,6 +494,7 @@ class fpdb:
('LoadProf', None, '_Load Profile (broken)', '<control>L', 'Load your profile', self.dia_load_profile),
('EditProf', None, '_Edit Profile (todo)', '<control>E', 'Edit your profile', self.dia_edit_profile),
('SaveProf', None, '_Save Profile (todo)', '<control>S', 'Save your profile', self.dia_save_profile),
('Preferences', None, '_Preferences', None, 'Edit your preferences', self.dia_preferences),
('import', None, '_Import'),
('sethharchive', None, '_Set HandHistory Archive Directory', None, 'Set HandHistory Archive Directory', self.select_hhArchiveBase),
('bulkimp', None, '_Bulk Import', '<control>B', 'Bulk Import', self.tab_bulk_import),
@ -415,6 +514,7 @@ class fpdb:
('createuser', None, 'Create or Delete _User (todo)', None, 'Create or Delete User', self.dia_create_del_user),
('createtabs', None, 'Create or Recreate _Tables', None, 'Create or Recreate Tables ', self.dia_recreate_tables),
('rebuildhudcache', None, 'Rebuild HUD Cache', None, 'Rebuild HUD Cache', self.dia_recreate_hudcache),
('rebuildindexes', None, 'Rebuild DB Indexes', None, 'Rebuild DB Indexes', self.dia_rebuild_indexes),
('stats', None, '_Statistics (todo)', None, 'View Database Statistics', self.dia_database_stats),
('help', None, '_Help'),
('Abbrev', None, '_Abbrevations (todo)', None, 'List of Abbrevations', self.tab_abbreviations),
@ -450,24 +550,32 @@ class fpdb:
if self.db is not None and self.db.fdb is not None:
self.db.disconnect()
self.sql = SQL.Sql(type = self.settings['db-type'], db_server = self.settings['db-server'])
self.sql = SQL.Sql(db_server = self.settings['db-server'])
try:
self.db = Database.Database(self.config, sql = self.sql)
except FpdbMySQLFailedError:
self.warning_box("Unable to connect to MySQL! Is the MySQL server running?!", "FPDB ERROR")
except Exceptions.FpdbMySQLAccessDenied:
self.warning_box("MySQL Server reports: Access denied. Are your permissions set correctly?")
exit()
except FpdbError:
#print "Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user'])
self.warning_box("Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user']), "FPDB ERROR")
err = traceback.extract_tb(sys.exc_info()[2])[-1]
print "*** Error: " + err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1])
sys.stderr.write("Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user']))
except:
#print "Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user'])
self.warning_box("Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user']), "FPDB ERROR")
err = traceback.extract_tb(sys.exc_info()[2])[-1]
print "*** Error: " + err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1])
sys.stderr.write("Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user']))
except Exceptions.FpdbMySQLNoDatabase:
msg = "MySQL client reports: 2002 error. Unable to connect - Please check that the MySQL service has been started"
self.warning_box(msg)
exit
# except FpdbMySQLFailedError:
# self.warning_box("Unable to connect to MySQL! Is the MySQL server running?!", "FPDB ERROR")
# exit()
# except FpdbError:
# #print "Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user'])
# self.warning_box("Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user']), "FPDB ERROR")
# err = traceback.extract_tb(sys.exc_info()[2])[-1]
# print "*** Error: " + err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1])
# sys.stderr.write("Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user']))
# except:
# #print "Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user'])
# self.warning_box("Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user']), "FPDB ERROR")
# err = traceback.extract_tb(sys.exc_info()[2])[-1]
# print "*** Error: " + err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1])
# sys.stderr.write("Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user']))
if self.db.wrongDbVersion:
diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK))
@ -607,18 +715,14 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
menubar.show()
#done menubar
self.nb = gtk.Notebook()
self.nb.set_show_tabs(True)
self.nb.show()
self.main_vbox.pack_start(self.nb, True, True, 0)
self.pages=[]
self.tabs=[]
self.tab_names=[]
self.tab_buttons=[]
self.tab_box = gtk.HBox(True,1)
self.main_vbox.pack_start(self.tab_box, False, True, 0)
self.tab_box.show()
#done tab bar
self.current_tab = gtk.VBox(False,1)
self.current_tab.set_border_width(1)
self.main_vbox.add(self.current_tab)
self.current_tab.show()
self.nb_tabs=[]
self.tab_main_help(None, None)

View File

@ -20,6 +20,7 @@ import os
import re
import sys
import logging
import math
from time import time, strftime
from Exceptions import *
@ -30,15 +31,37 @@ except ImportError:
logging.info("Not using sqlalchemy connection pool.")
use_pool = False
try:
from numpy import var
use_numpy = True
except ImportError:
logging.info("Not using numpy to define variance in sqlite.")
use_numpy = False
import fpdb_simple
import FpdbSQLQueries
import Configuration
# Variance created as sqlite has a bunch of undefined aggregate functions.
class VARIANCE:
def __init__(self):
self.store = []
def step(self, value):
self.store.append(value)
def finalize(self):
return float(var(self.store))
class sqlitemath:
def mod(self, a, b):
return a%b
class fpdb_db:
MYSQL_INNODB = 2
PGSQL = 3
SQLITE = 4
sqlite_db_dir = ".." + os.sep + "database"
def __init__(self):
"""Simple constructor, doesnt really do anything"""
@ -77,11 +100,16 @@ class fpdb_db:
import MySQLdb
if use_pool:
MySQLdb = pool.manage(MySQLdb, pool_size=5)
# try:
try:
self.db = MySQLdb.connect(host=host, user=user, passwd=password, db=database, use_unicode=True)
#TODO: Add port option
# except:
# raise FpdbMySQLFailedError("MySQL connection failed")
except MySQLdb.Error, ex:
if ex.args[0] == 1045:
raise FpdbMySQLAccessDenied(ex.args[0], ex.args[1])
elif ex.args[0] == 2002:
raise FpdbMySQLNoDatabase(ex.args[0], ex.args[1])
else:
print "*** WARNING UNKNOWN MYSQL ERROR", ex
elif backend == fpdb_db.PGSQL:
import psycopg2
import psycopg2.extensions
@ -123,13 +151,20 @@ class fpdb_db:
else:
logging.warning("SQLite won't work well without 'sqlalchemy' installed.")
if not os.path.isdir(self.sqlite_db_dir):
print "Creating directory: '%s'" % (self.sqlite_db_dir)
os.mkdir(self.sqlite_db_dir)
self.db = sqlite3.connect( self.sqlite_db_dir + os.sep + database
, detect_types=sqlite3.PARSE_DECLTYPES )
if not os.path.isdir(Configuration.DIR_DATABASES) and not database == ":memory:":
print "Creating directory: '%s'" % (Configuration.DIR_DATABASES)
os.mkdir(Configuration.DIR_DATABASES)
database = os.path.join(Configuration.DIR_DATABASE, database)
self.db = sqlite3.connect(database, detect_types=sqlite3.PARSE_DECLTYPES )
sqlite3.register_converter("bool", lambda x: bool(int(x)))
sqlite3.register_adapter(bool, lambda x: "1" if x else "0")
self.db.create_function("floor", 1, math.floor)
tmp = sqlitemath()
self.db.create_function("mod", 2, tmp.mod)
if use_numpy:
self.db.create_aggregate("variance", 1, VARIANCE)
else:
logging.warning("Some database functions will not work without NumPy support")
else:
raise FpdbError("unrecognised database backend:"+backend)
self.cursor = self.db.cursor()

View File

@ -42,15 +42,7 @@ import fpdb_parse_logic
import Configuration
import Exceptions
import logging, logging.config
import ConfigParser
try:
logging.config.fileConfig(os.path.join(sys.path[0],"logging.conf"))
except ConfigParser.NoSectionError: # debian package path
logging.config.fileConfig('/usr/share/python-fpdb/logging.conf')
log = logging.getLogger('importer')
log = Configuration.get_logger("logging.conf", "importer")
# database interface modules
try:
@ -107,7 +99,7 @@ class Importer:
for i in xrange(self.settings['threads']):
self.writerdbs.append( Database.Database(self.config, sql = self.sql) )
self.NEWIMPORT = False
self.NEWIMPORT = Configuration.NEWIMPORT
#Set functions
def setCallHud(self, value):
@ -365,6 +357,11 @@ class Importer:
if file in self.updatedsize: # we should be able to assume that if we're in size, we're in time as well
if stat_info.st_size > self.updatedsize[file] or stat_info.st_mtime > self.updatedtime[file]:
# print "file",counter," updated", os.path.basename(file), stat_info.st_size, self.updatedsize[file], stat_info.st_mtime, self.updatedtime[file]
try:
if not os.path.isdir(file):
self.caller.addText("\n"+file)
except KeyError: # TODO: What error happens here?
pass
self.import_file_dict(self.database, file, self.filelist[file][0], self.filelist[file][1], None)
self.updatedsize[file] = stat_info.st_size
self.updatedtime[file] = time()
@ -556,7 +553,7 @@ class Importer:
if self.callHud:
#print "call to HUD here. handsId:",handsId
#pipe the Hands.id out to the HUD
print "fpdb_import: sending hand to hud", handsId, "pipe =", self.caller.pipe_to_hud
# print "fpdb_import: sending hand to hud", handsId, "pipe =", self.caller.pipe_to_hud
self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep)
except Exceptions.DuplicateError:
duplicates += 1

View File

@ -927,7 +927,7 @@ def recogniseTourneyTypeId(db, siteId, tourneySiteId, buyin, fee, knockout, rebu
except:
cursor.execute( """SELECT id FROM TourneyTypes
WHERE siteId=%s AND buyin=%s AND fee=%s
AND knockout=%s AND rebuyOrAddon=%s"""
AND knockout=%s AND rebuyOrAddon=%s""".replace('%s', db.sql.query['placeholder'])
, (siteId, buyin, fee, knockout, rebuyOrAddon) )
result = cursor.fetchone()
#print "tried selecting tourneytypes.id, result:", result
@ -939,14 +939,14 @@ def recogniseTourneyTypeId(db, siteId, tourneySiteId, buyin, fee, knockout, rebu
#print "insert new tourneytype record ..."
try:
cursor.execute( """INSERT INTO TourneyTypes (siteId, buyin, fee, knockout, rebuyOrAddon)
VALUES (%s, %s, %s, %s, %s)"""
VALUES (%s, %s, %s, %s, %s)""".replace('%s', db.sql.query['placeholder'])
, (siteId, buyin, fee, knockout, rebuyOrAddon) )
ret = db.get_last_insert_id(cursor)
except:
#print "maybe tourneytype was created since select, try selecting again ..."
cursor.execute( """SELECT id FROM TourneyTypes
WHERE siteId=%s AND buyin=%s AND fee=%s
AND knockout=%s AND rebuyOrAddon=%s"""
AND knockout=%s AND rebuyOrAddon=%s""".replace('%s', db.sql.query['placeholder'])
, (siteId, buyin, fee, knockout, rebuyOrAddon) )
result = cursor.fetchone()
try:

View File

@ -60,13 +60,9 @@ class InterProcessLockBase:
self._has_lock = False
def locked(self):
if self._has_lock:
return True
try:
self.acquire()
if self.acquire():
self.release()
return False
except SingleInstanceError:
return True
LOCK_FILE_DIRECTORY = '/tmp'
@ -162,38 +158,33 @@ def test_construct():
>>> lock1 = InterProcessLock(name=test_name)
>>> lock1.acquire()
True
>>> lock2 = InterProcessLock(name=test_name)
>>> lock3 = InterProcessLock(name=test_name)
# Since lock1 is locked, other attempts to acquire it fail.
>>> lock2.acquire()
Traceback (most recent call last):
...
SingleInstanceError: Could not acquire exclusive lock on /tmp/test.lck
False
>>> lock3.acquire()
Traceback (most recent call last):
...
SingleInstanceError: Could not acquire exclusive lock on /tmp/test.lck
False
# Release the lock and let lock2 have it.
>>> lock1.release()
>>> lock2.acquire()
True
>>> lock3.acquire()
Traceback (most recent call last):
...
SingleInstanceError: Could not acquire exclusive lock on /tmp/test.lck
False
# Release it and give it back to lock1
>>> lock2.release()
>>> lock1.acquire()
True
>>> lock2.acquire()
Traceback (most recent call last):
...
SingleInstanceError: Could not acquire exclusive lock on /tmp/test.lck
False
# Test lock status
>>> lock2.locked()
@ -224,7 +215,7 @@ def test_construct():
... import win32con
... import pywintypes
... handle = win32api.OpenProcess(win32con.PROCESS_TERMINATE , pywintypes.FALSE, pid)
... return (0 != win32api.TerminateProcess(handle, 0))
... #return (0 != win32api.TerminateProcess(handle, 0))
# Test to acquire the lock in another process.
>>> def execute(cmd):
@ -237,15 +228,14 @@ def test_construct():
>>> pid = execute('import interlocks;a=interlocks.InterProcessLock(name=\\''+test_name+ '\\');a.acquire();')
>>> lock1.acquire()
Traceback (most recent call last):
...
SingleInstanceError: Could not acquire exclusive lock on /tmp/test.lck
False
>>> os_independent_kill(pid)
>>> time.sleep(1)
>>> lock1.acquire()
True
>>> lock1.release()
# Testing wait
@ -253,13 +243,12 @@ def test_construct():
>>> pid = execute('import interlocks;a=interlocks.InterProcessLock(name=\\''+test_name+ '\\');a.acquire();')
>>> lock1.acquire()
Traceback (most recent call last):
...
SingleInstanceError: Could not acquire exclusive lock on /tmp/test.lck
False
>>> os_independent_kill(pid)
>>> lock1.acquire(True)
True
>>> lock1.release()
"""

View File

@ -27,6 +27,22 @@ Py2exe script for fpdb.
# get rid of all the uneeded libraries (e.g., pyQT)
# think about an installer
#HOW TO USE this script:
#
# cd to the folder where this script is stored, usually .../pyfpdb.
# If there are build and dist subfolders present , delete them to get
# rid of earlier builds.
# Run the script with "py2exe_setup.py py2exe"
# You will frequently get messages about missing .dll files. E. g.,
# MSVCP90.dll. These are somewhere in your windows install, so you
# can just copy them to your working folder.
# If it works, you'll have 2 new folders, build and dist. Build is
# working space and should be deleted. Dist contains the files to be
# distributed. Last, you must copy the etc/, lib/ and share/ folders
# from your gtk/bin/ folder to the dist folder. (the whole folders, not
# just the contents) You can (should) then prune the etc/, lib/ and
# share/ folders to remove components we don't need.
from distutils.core import setup
import py2exe
@ -36,7 +52,8 @@ setup(
version = '0.12',
console = [ {'script': 'fpdb.py', },
{'script': 'HUD_main.py', }
{'script': 'HUD_main.py', },
{'script': 'Configuration.py', }
],
options = {'py2exe': {
@ -47,8 +64,10 @@ setup(
}
},
data_files = ['HUD_config.xml',
'Cards01.png'
data_files = ['HUD_config.xml.example',
'Cards01.png',
'logging.conf',
(r'matplotlibdata', glob.glob(r'c:\python26\Lib\site-packages\matplotlib\mpl-data\*'))
]
)

View File

@ -0,0 +1,971 @@
PokerStars Game #35839001292: Triple Draw 2-7 Lowball Limit ($0.10/$0.20 USD) - 2009/11/25 14:12:58 ET
Table 'Theodora VI' 6-max Seat #5 is the button
Seat 1: s0rrow ($4 in chips)
Seat 2: rumble1111 ($4.58 in chips)
Seat 3: Eisenherz73 ($7.54 in chips)
Seat 4: cypis28 ($1.40 in chips)
Seat 5: bakter9 ($0.78 in chips)
Seat 6: TheLabman ($6.31 in chips)
TheLabman: posts small blind $0.05
s0rrow: posts big blind $0.10
*** DEALING HANDS ***
Dealt to s0rrow [8s Ts 8h 2s 3s]
rumble1111: calls $0.10
Eisenherz73: folds
cypis28: raises $0.10 to $0.20
bakter9: raises $0.10 to $0.30
TheLabman: folds
s0rrow: folds
rumble1111: calls $0.20
cypis28: raises $0.10 to $0.40
Betting is capped
bakter9: calls $0.10
rumble1111: calls $0.10
*** FIRST DRAW ***
rumble1111: discards 2 cards
cypis28: discards 2 cards
bakter9: discards 1 card
rumble1111: checks
cypis28: bets $0.10
bakter9: raises $0.10 to $0.20
rumble1111: folds
cypis28: calls $0.10
*** SECOND DRAW ***
cypis28: discards 1 card
bakter9: stands pat
cypis28: bets $0.20
bakter9: calls $0.18 and is all-in
Uncalled bet ($0.02) returned to cypis28
*** THIRD DRAW ***
cypis28: stands pat
bakter9: stands pat
*** SHOW DOWN ***
cypis28: shows [7c 6d 9c 4s 2c] (Lo: 9,7,6,4,2)
bakter9: shows [7s 5s 8d 4h 3c] (Lo: 8,7,5,4,3)
bakter9 collected $2.01 from pot
*** SUMMARY ***
Total pot $2.11 | Rake $0.10
Seat 1: s0rrow (big blind) folded before the Draw
Seat 2: rumble1111 folded after the 1st Draw
Seat 3: Eisenherz73 folded before the Draw (didn't bet)
Seat 4: cypis28 showed [7c 6d 9c 4s 2c] and lost with Lo: 9,7,6,4,2
Seat 5: bakter9 (button) showed [7s 5s 8d 4h 3c] and won ($2.01) with Lo: 8,7,5,4,3
Seat 6: TheLabman (small blind) folded before the Draw
PokerStars Game #35839050562: Triple Draw 2-7 Lowball Limit ($0.10/$0.20 USD) - 2009/11/25 14:14:02 ET
Table 'Theodora VI' 6-max Seat #6 is the button
Seat 1: s0rrow ($3.90 in chips)
Seat 2: rumble1111 ($4.18 in chips)
Seat 3: Eisenherz73 ($7.54 in chips)
Seat 4: cypis28 ($0.62 in chips)
Seat 5: bakter9 ($2.01 in chips)
Seat 6: TheLabman ($6.26 in chips)
s0rrow: posts small blind $0.05
rumble1111: posts big blind $0.10
*** DEALING HANDS ***
Dealt to s0rrow [Kh Th 3d Tc 7c]
Eisenherz73: folds
cypis28: folds
bakter9: calls $0.10
TheLabman: folds
s0rrow: calls $0.05
rumble1111: checks
*** FIRST DRAW ***
s0rrow: discards 2 cards [Kh Th]
Dealt to s0rrow [3d Tc 7c] [5c Qs]
rumble1111: discards 2 cards
bakter9: discards 2 cards
s0rrow: checks
rumble1111: bets $0.10
bakter9: folds
s0rrow: calls $0.10
*** SECOND DRAW ***
s0rrow: discards 2 cards [Qs Tc]
Dealt to s0rrow [3d 7c 5c] [4c 2s]
rumble1111: stands pat
s0rrow: bets $0.20
rumble1111: calls $0.20
*** THIRD DRAW ***
s0rrow: stands pat on [3d 7c 5c 4c 2s]
rumble1111: discards 1 card
s0rrow: bets $0.20
rumble1111: calls $0.20
*** SHOW DOWN ***
s0rrow: shows [5c 4c 3d 2s 7c] (Lo: 7,5,4,3,2)
rumble1111: mucks hand
s0rrow collected $1.24 from pot
*** SUMMARY ***
Total pot $1.30 | Rake $0.06
Seat 1: s0rrow (small blind) showed [5c 4c 3d 2s 7c] and won ($1.24) with Lo: 7,5,4,3,2
Seat 2: rumble1111 (big blind) mucked [8s 7d 3c 6d 2h]
Seat 3: Eisenherz73 folded before the Draw (didn't bet)
Seat 4: cypis28 folded before the Draw (didn't bet)
Seat 5: bakter9 folded after the 1st Draw
Seat 6: TheLabman (button) folded before the Draw (didn't bet)
PokerStars Game #35839109592: Triple Draw 2-7 Lowball Limit ($0.10/$0.20 USD) - 2009/11/25 14:15:18 ET
Table 'Theodora VI' 6-max Seat #1 is the button
Seat 1: s0rrow ($4.54 in chips)
Seat 2: rumble1111 ($3.58 in chips)
Seat 3: Eisenherz73 ($7.54 in chips)
Seat 4: cypis28 ($0.62 in chips)
Seat 5: bakter9 ($1.91 in chips)
Seat 6: TheLabman ($6.26 in chips)
rumble1111: posts small blind $0.05
Eisenherz73: posts big blind $0.10
*** DEALING HANDS ***
Dealt to s0rrow [Tc 9s Qc 8h 3d]
cypis28: folds
bakter9: folds
TheLabman: folds
s0rrow: folds
rumble1111: folds
Uncalled bet ($0.05) returned to Eisenherz73
Eisenherz73 collected $0.10 from pot
Eisenherz73: doesn't show hand
*** SUMMARY ***
Total pot $0.10 | Rake $0
Seat 1: s0rrow (button) folded before the Draw (didn't bet)
Seat 2: rumble1111 (small blind) folded before the Draw
Seat 3: Eisenherz73 (big blind) collected ($0.10)
Seat 4: cypis28 folded before the Draw (didn't bet)
Seat 5: bakter9 folded before the Draw (didn't bet)
Seat 6: TheLabman folded before the Draw (didn't bet)
PokerStars Game #35839118248: Triple Draw 2-7 Lowball Limit ($0.10/$0.20 USD) - 2009/11/25 14:15:29 ET
Table 'Theodora VI' 6-max Seat #2 is the button
Seat 1: s0rrow ($4.54 in chips)
Seat 2: rumble1111 ($3.53 in chips)
Seat 3: Eisenherz73 ($7.59 in chips)
Seat 4: cypis28 ($0.62 in chips)
Seat 5: bakter9 ($1.91 in chips)
Seat 6: TheLabman ($6.26 in chips)
Eisenherz73: posts small blind $0.05
cypis28: posts big blind $0.10
*** DEALING HANDS ***
Dealt to s0rrow [Js 3d Qc 9s 5h]
bakter9: raises $0.10 to $0.20
TheLabman: folds
s0rrow: folds
rumble1111: folds
Eisenherz73: folds
cypis28: raises $0.10 to $0.30
bakter9: raises $0.10 to $0.40
Betting is capped
cypis28: calls $0.10
*** FIRST DRAW ***
cypis28: discards 2 cards
bakter9: discards 1 card
cypis28: bets $0.10
bakter9: raises $0.10 to $0.20
cypis28: raises $0.02 to $0.22 and is all-in
bakter9: calls $0.02
*** SECOND DRAW ***
cypis28: discards 1 card
bakter9: stands pat
*** THIRD DRAW ***
cypis28: stands pat
bakter9: stands pat
*** SHOW DOWN ***
cypis28: shows [7h 3s 2h 8h 6h] (Lo: 8,7,6,3,2)
bakter9: shows [4d 7c 2c 5s 6d] (Lo: 7,6,5,4,2)
bakter9 collected $1.23 from pot
*** SUMMARY ***
Total pot $1.29 | Rake $0.06
Seat 1: s0rrow folded before the Draw (didn't bet)
Seat 2: rumble1111 (button) folded before the Draw (didn't bet)
Seat 3: Eisenherz73 (small blind) folded before the Draw
Seat 4: cypis28 (big blind) showed [7h 3s 2h 8h 6h] and lost with Lo: 8,7,6,3,2
Seat 5: bakter9 showed [4d 7c 2c 5s 6d] and won ($1.23) with Lo: 7,6,5,4,2
Seat 6: TheLabman folded before the Draw (didn't bet)
PokerStars Game #35839149377: Triple Draw 2-7 Lowball Limit ($0.10/$0.20 USD) - 2009/11/25 14:16:10 ET
Table 'Theodora VI' 6-max Seat #3 is the button
Seat 1: s0rrow ($4.54 in chips)
Seat 2: rumble1111 ($3.53 in chips)
Seat 3: Eisenherz73 ($7.54 in chips)
Seat 5: bakter9 ($2.52 in chips)
Seat 6: TheLabman ($6.26 in chips)
bakter9: posts small blind $0.05
TheLabman: posts big blind $0.10
*** DEALING HANDS ***
Dealt to s0rrow [2c 3c Ts Jc Kc]
cypis28 leaves the table
s0rrow: folds
rumble1111: folds
Eisenherz73: folds
bakter9: calls $0.05
TheLabman: checks
*** FIRST DRAW ***
bakter9: discards 2 cards
tom1206 joins the table at seat #4
TheLabman: discards 4 cards
bakter9: checks
TheLabman: checks
*** SECOND DRAW ***
bakter9: discards 1 card
TheLabman: discards 3 cards
bakter9: checks
TheLabman: checks
*** THIRD DRAW ***
bakter9: discards 1 card
TheLabman: discards 1 card
bakter9: bets $0.20
TheLabman: calls $0.20
*** SHOW DOWN ***
bakter9: shows [5d 4h 8h 7d 6h] (Lo: a straight, Four to Eight)
TheLabman: shows [3h 6d 7h 5h 8d] (Lo: 8,7,6,5,3)
TheLabman collected $0.58 from pot
*** SUMMARY ***
Total pot $0.60 | Rake $0.02
Seat 1: s0rrow folded before the Draw (didn't bet)
Seat 2: rumble1111 folded before the Draw (didn't bet)
Seat 3: Eisenherz73 (button) folded before the Draw (didn't bet)
Seat 5: bakter9 (small blind) showed [5d 4h 8h 7d 6h] and lost with Lo: a straight, Four to Eight
Seat 6: TheLabman (big blind) showed [3h 6d 7h 5h 8d] and won ($0.58) with Lo: 8,7,6,5,3
PokerStars Game #35839176665: Triple Draw 2-7 Lowball Limit ($0.10/$0.20 USD) - 2009/11/25 14:16:46 ET
Table 'Theodora VI' 6-max Seat #5 is the button
Seat 1: s0rrow ($4.54 in chips)
Seat 2: rumble1111 ($3.53 in chips)
Seat 3: Eisenherz73 ($7.54 in chips)
Seat 4: tom1206 ($4 in chips)
Seat 5: bakter9 ($2.22 in chips)
Seat 6: TheLabman ($6.54 in chips)
TheLabman: posts small blind $0.05
s0rrow: posts big blind $0.10
tom1206: posts big blind $0.10
*** DEALING HANDS ***
Dealt to s0rrow [5d Js 7d Jd 4d]
rumble1111: calls $0.10
Eisenherz73: calls $0.10
tom1206: checks
bakter9: folds
TheLabman: calls $0.05
s0rrow: checks
*** FIRST DRAW ***
TheLabman: discards 3 cards
s0rrow: discards 2 cards [Js Jd]
Dealt to s0rrow [5d 7d 4d] [6d 2s]
rumble1111: discards 2 cards
Eisenherz73: discards 2 cards
tom1206: discards 2 cards
TheLabman: checks
s0rrow: checks
rumble1111: checks
Eisenherz73: checks
tom1206: checks
*** SECOND DRAW ***
TheLabman: discards 3 cards
s0rrow: stands pat on [5d 7d 4d 6d 2s]
rumble1111: discards 2 cards
Eisenherz73: discards 1 card
tom1206: discards 2 cards
TheLabman: checks
s0rrow: checks
rumble1111: checks
Eisenherz73: checks
tom1206: checks
*** THIRD DRAW ***
TheLabman: discards 2 cards
s0rrow: stands pat on [5d 7d 4d 6d 2s]
rumble1111: discards 1 card
The deck is reshuffled
Eisenherz73: discards 1 card
tom1206: discards 2 cards
TheLabman: checks
s0rrow: bets $0.20
rumble1111: folds
Eisenherz73: folds
Eisenherz73 is sitting out
Eisenherz73 leaves the table
tom1206: folds
TheLabman: folds
Uncalled bet ($0.20) returned to s0rrow
X USN-USMC joins the table at seat #3
s0rrow collected $0.48 from pot
*** SUMMARY ***
Total pot $0.50 | Rake $0.02
Seat 1: s0rrow (big blind) collected ($0.48)
Seat 2: rumble1111 folded after the 3rd Draw
Seat 3: Eisenherz73 folded after the 3rd Draw
Seat 4: tom1206 folded after the 3rd Draw
Seat 5: bakter9 (button) folded before the Draw (didn't bet)
Seat 6: TheLabman (small blind) folded after the 3rd Draw
PokerStars Game #35839272371: Triple Draw 2-7 Lowball Limit ($0.10/$0.20 USD) - 2009/11/25 14:18:50 ET
Table 'Theodora VI' 6-max Seat #6 is the button
Seat 1: s0rrow ($4.92 in chips)
Seat 2: rumble1111 ($3.43 in chips)
Seat 3: X USN-USMC ($4 in chips)
Seat 4: tom1206 ($3.90 in chips)
Seat 5: bakter9 ($2.22 in chips)
Seat 6: TheLabman ($6.44 in chips)
s0rrow: posts small blind $0.05
rumble1111: posts big blind $0.10
X USN-USMC: posts big blind $0.10
*** DEALING HANDS ***
Dealt to s0rrow [Th Js Kd 2h Qc]
X USN-USMC: checks
tom1206 has timed out
tom1206: folds
tom1206 is sitting out
bakter9: folds
TheLabman: calls $0.10
s0rrow: folds
tom1206 has returned
rumble1111: checks
*** FIRST DRAW ***
rumble1111: discards 3 cards
X USN-USMC: discards 1 card
TheLabman: discards 2 cards
rumble1111: checks
X USN-USMC: bets $0.10
TheLabman: calls $0.10
rumble1111: calls $0.10
*** SECOND DRAW ***
rumble1111 said, "other fckers"
rumble1111: discards 1 card
X USN-USMC: discards 1 card
TheLabman: discards 1 card
rumble1111: checks
X USN-USMC: bets $0.20
TheLabman: calls $0.20
rumble1111: calls $0.20
*** THIRD DRAW ***
rumble1111: discards 1 card
X USN-USMC: discards 1 card
TheLabman: discards 1 card
rumble1111: checks
X USN-USMC: bets $0.20
TheLabman: folds
rumble1111: folds
Uncalled bet ($0.20) returned to X USN-USMC
X USN-USMC collected $1.19 from pot
X USN-USMC: doesn't show hand
*** SUMMARY ***
Total pot $1.25 | Rake $0.06
Seat 1: s0rrow (small blind) folded before the Draw
Seat 2: rumble1111 (big blind) folded after the 3rd Draw
Seat 3: X USN-USMC collected ($1.19)
Seat 4: tom1206 folded before the Draw (didn't bet)
Seat 5: bakter9 folded before the Draw (didn't bet)
Seat 6: TheLabman (button) folded after the 3rd Draw
PokerStars Game #35839360555: Triple Draw 2-7 Lowball Limit ($0.10/$0.20 USD) - 2009/11/25 14:20:53 ET
Table 'Theodora VI' 6-max Seat #1 is the button
Seat 1: s0rrow ($4.87 in chips)
Seat 2: rumble1111 ($3.03 in chips)
Seat 3: X USN-USMC ($4.79 in chips)
Seat 4: tom1206 ($3.90 in chips)
Seat 5: bakter9 ($2.22 in chips)
Seat 6: TheLabman ($6.04 in chips)
rumble1111: posts small blind $0.05
X USN-USMC: posts big blind $0.10
*** DEALING HANDS ***
Dealt to s0rrow [9s Kh 2d Ks 4c]
tom1206: raises $0.10 to $0.20
bakter9: folds
TheLabman: folds
s0rrow: folds
rumble1111: calls $0.15
X USN-USMC: calls $0.10
*** FIRST DRAW ***
rumble1111: discards 3 cards
X USN-USMC: discards 2 cards
tom1206: discards 2 cards
rumble1111: checks
X USN-USMC: bets $0.10
tom1206: calls $0.10
rumble1111: calls $0.10
*** SECOND DRAW ***
rumble1111: discards 3 cards
X USN-USMC: stands pat
tom1206: discards 1 card
rumble1111: checks
X USN-USMC: bets $0.20
tom1206: raises $0.20 to $0.40
rumble1111: calls $0.40
X USN-USMC: calls $0.20
*** THIRD DRAW ***
rumble1111: discards 2 cards
X USN-USMC: stands pat
tom1206: stands pat
rumble1111: bets $0.20
X USN-USMC: folds
tom1206: calls $0.20
*** SHOW DOWN ***
rumble1111: shows [7d 4s 2s 3s 6c] (Lo: 7,6,4,3,2)
tom1206: mucks hand
rumble1111 collected $2.38 from pot
*** SUMMARY ***
Total pot $2.50 | Rake $0.12
Seat 1: s0rrow (button) folded before the Draw (didn't bet)
Seat 2: rumble1111 (small blind) showed [7d 4s 2s 3s 6c] and won ($2.38) with Lo: 7,6,4,3,2
Seat 3: X USN-USMC (big blind) folded after the 3rd Draw
Seat 4: tom1206 mucked [4h 6d 8d 5c 3d]
Seat 5: bakter9 folded before the Draw (didn't bet)
Seat 6: TheLabman folded before the Draw (didn't bet)
PokerStars Game #35839412131: Triple Draw 2-7 Lowball Limit ($0.10/$0.20 USD) - 2009/11/25 14:21:58 ET
Table 'Theodora VI' 6-max Seat #2 is the button
Seat 1: s0rrow ($4.87 in chips)
Seat 2: rumble1111 ($4.51 in chips)
Seat 3: X USN-USMC ($4.09 in chips)
Seat 4: tom1206 ($3 in chips)
Seat 5: bakter9 ($2.22 in chips)
Seat 6: TheLabman ($6.04 in chips)
X USN-USMC: posts small blind $0.05
tom1206: posts big blind $0.10
*** DEALING HANDS ***
Dealt to s0rrow [8c 3s Tc Ac Qd]
bakter9: calls $0.10
TheLabman: calls $0.10
s0rrow: folds
rumble1111: calls $0.10
X USN-USMC: calls $0.05
tom1206: checks
*** FIRST DRAW ***
X USN-USMC: discards 4 cards
tom1206: discards 3 cards
bakter9: discards 2 cards
TheLabman: discards 3 cards
rumble1111: discards 3 cards
X USN-USMC: checks
tom1206: checks
bakter9: checks
TheLabman: checks
rumble1111: checks
*** SECOND DRAW ***
X USN-USMC: discards 2 cards
tom1206: discards 2 cards
bakter9: discards 1 card
TheLabman: discards 2 cards
The deck is reshuffled
rumble1111: discards 1 card
X USN-USMC: bets $0.20
tom1206: calls $0.20
bakter9: calls $0.20
TheLabman: folds
rumble1111: calls $0.20
*** THIRD DRAW ***
X USN-USMC: discards 1 card
tom1206: discards 1 card
bakter9: discards 1 card
rumble1111: stands pat
X USN-USMC: checks
tom1206: bets $0.20
bakter9: calls $0.20
rumble1111: folds
X USN-USMC: folds
*** SHOW DOWN ***
tom1206: shows [4s 3h 7d 8s 2c] (Lo: 8,7,4,3,2)
bakter9: shows [8d 5c 7c 2d 6h] (Lo: 8,7,6,5,2)
tom1206 collected $1.62 from pot
*** SUMMARY ***
Total pot $1.70 | Rake $0.08
Seat 1: s0rrow folded before the Draw (didn't bet)
Seat 2: rumble1111 (button) folded after the 3rd Draw
Seat 3: X USN-USMC (small blind) folded after the 3rd Draw
Seat 4: tom1206 (big blind) showed [4s 3h 7d 8s 2c] and won ($1.62) with Lo: 8,7,4,3,2
Seat 5: bakter9 showed [8d 5c 7c 2d 6h] and lost with Lo: 8,7,6,5,2
Seat 6: TheLabman folded after the 2nd Draw
PokerStars Game #35839484932: Triple Draw 2-7 Lowball Limit ($0.10/$0.20 USD) - 2009/11/25 14:23:30 ET
Table 'Theodora VI' 6-max Seat #3 is the button
Seat 1: s0rrow ($4.87 in chips)
Seat 2: rumble1111 ($4.21 in chips)
Seat 3: X USN-USMC ($3.79 in chips)
Seat 4: tom1206 ($4.12 in chips)
Seat 5: bakter9 ($1.72 in chips)
Seat 6: TheLabman ($5.94 in chips)
tom1206: posts small blind $0.05
bakter9: posts big blind $0.10
*** DEALING HANDS ***
Dealt to s0rrow [3d 7h 7c Jh 5s]
TheLabman: folds
s0rrow: calls $0.10
rumble1111: folds
rumble1111 leaves the table
X USN-USMC: folds
tom1206: calls $0.05
bakter9: raises $0.10 to $0.20
s0rrow: calls $0.10
tom1206: calls $0.10
*** FIRST DRAW ***
tom1206: discards 3 cards
bakter9: discards 2 cards
s0rrow: discards 2 cards [7c Jh]
Dealt to s0rrow [3d 7h 5s] [9h Ad]
tom1206: checks
bakter9: bets $0.10
s0rrow: calls $0.10
tom1206: calls $0.10
*** SECOND DRAW ***
tom1206: discards 2 cards
bakter9: discards 1 card
s0rrow: discards 1 card [9h]
Dealt to s0rrow [3d 7h 5s Ad] [4c]
tom1206: bets $0.20
bakter9: raises $0.20 to $0.40
bakter9 said, "zzzzzzzzzzzzzzzzzzz"
s0rrow: calls $0.40
tom1206: calls $0.20
*** THIRD DRAW ***
tom1206: discards 1 card
bakter9: stands pat
s0rrow: stands pat on [3d 7h 5s Ad 4c]
tom1206: checks
bakter9: bets $0.20
s0rrow: calls $0.20
tom1206: raises $0.20 to $0.40
bakter9: calls $0.20
s0rrow: calls $0.20
*** SHOW DOWN ***
tom1206: shows [4h 3c Qc 2c 6c] (Lo: Q,6,4,3,2)
bakter9: shows [3h 5d 2s 8c 6s] (Lo: 8,6,5,3,2)
s0rrow: mucks hand
bakter9 collected $3.14 from pot
*** SUMMARY ***
Total pot $3.30 | Rake $0.16
Seat 1: s0rrow mucked [3d 7h 4c Ad 5s]
Seat 2: rumble1111 folded before the Draw (didn't bet)
Seat 3: X USN-USMC (button) folded before the Draw (didn't bet)
Seat 4: tom1206 (small blind) showed [4h 3c Qc 2c 6c] and lost with Lo: Q,6,4,3,2
Seat 5: bakter9 (big blind) showed [3h 5d 2s 8c 6s] and won ($3.14) with Lo: 8,6,5,3,2
Seat 6: TheLabman folded before the Draw (didn't bet)
PokerStars Game #35839619404: Triple Draw 2-7 Lowball Limit ($0.10/$0.20 USD) - 2009/11/25 14:26:21 ET
Table 'Theodora VI' 6-max Seat #4 is the button
Seat 1: s0rrow ($3.77 in chips)
Seat 3: X USN-USMC ($3.79 in chips)
Seat 4: tom1206 ($3.02 in chips)
Seat 5: bakter9 ($3.76 in chips)
Seat 6: TheLabman ($5.94 in chips)
bakter9: posts small blind $0.05
TheLabman: posts big blind $0.10
*** DEALING HANDS ***
Dealt to s0rrow [Ah 7s Ad 5d As]
bakter9 said, "ty"
s0rrow: raises $0.10 to $0.20
X USN-USMC: folds
tom1206: folds
bakter9: folds
TheLabman: calls $0.10
*** FIRST DRAW ***
TheLabman: discards 2 cards
s0rrow: discards 2 cards [7s Ad]
Dealt to s0rrow [Ah 5d As] [5h 8s]
TheLabman: checks
Mamega joins the table at seat #2
s0rrow: bets $0.10
TheLabman: calls $0.10
*** SECOND DRAW ***
TheLabman: discards 1 card
s0rrow: stands pat on [Ah 5d As 5h 8s]
TheLabman: checks
s0rrow: bets $0.20
TheLabman: calls $0.20
*** THIRD DRAW ***
TheLabman: discards 1 card
s0rrow: stands pat on [Ah 5d As 5h 8s]
TheLabman: checks
s0rrow: bets $0.20
TheLabman: folds
Uncalled bet ($0.20) returned to s0rrow
s0rrow collected $1 from pot
*** SUMMARY ***
Total pot $1.05 | Rake $0.05
Seat 1: s0rrow collected ($1)
Seat 3: X USN-USMC folded before the Draw (didn't bet)
Seat 4: tom1206 (button) folded before the Draw (didn't bet)
Seat 5: bakter9 (small blind) folded before the Draw
Seat 6: TheLabman (big blind) folded after the 3rd Draw
PokerStars Game #35839669792: Triple Draw 2-7 Lowball Limit ($0.10/$0.20 USD) - 2009/11/25 14:27:24 ET
Table 'Theodora VI' 6-max Seat #5 is the button
Seat 1: s0rrow ($4.27 in chips)
Seat 3: X USN-USMC ($3.79 in chips)
Seat 4: tom1206 ($3.02 in chips)
Seat 5: bakter9 ($3.71 in chips)
Seat 6: TheLabman ($5.44 in chips)
TheLabman: posts small blind $0.05
s0rrow: posts big blind $0.10
Mamega: sits out
*** DEALING HANDS ***
Dealt to s0rrow [3h 6d 9s 5s Kc]
X USN-USMC: calls $0.10
tom1206: calls $0.10
bakter9: folds
TheLabman: calls $0.05
s0rrow: checks
*** FIRST DRAW ***
TheLabman: discards 1 card
s0rrow: discards 1 card [Kc]
Dealt to s0rrow [3h 6d 9s 5s] [Jh]
X USN-USMC: discards 2 cards
tom1206: discards 2 cards
TheLabman: checks
s0rrow: checks
X USN-USMC: bets $0.10
tom1206: raises $0.10 to $0.20
TheLabman: calls $0.20
s0rrow: folds
X USN-USMC: calls $0.10
*** SECOND DRAW ***
TheLabman: discards 1 card
X USN-USMC: discards 1 card
tom1206: stands pat
TheLabman: checks
X USN-USMC: bets $0.20
tom1206: raises $0.20 to $0.40
TheLabman: calls $0.40
X USN-USMC: raises $0.20 to $0.60
tom1206: calls $0.20
TheLabman: calls $0.20
*** THIRD DRAW ***
TheLabman: stands pat
X USN-USMC: stands pat
tom1206: stands pat
TheLabman: checks
X USN-USMC: bets $0.20
tom1206: calls $0.20
TheLabman: calls $0.20
bakter9 leaves the table
*** SHOW DOWN ***
X USN-USMC: shows [3s 4s 7s 2d 6c] (Lo: 7,6,4,3,2)
tom1206: mucks hand
TheLabman: mucks hand
X USN-USMC collected $3.24 from pot
LumBita joins the table at seat #5
*** SUMMARY ***
Total pot $3.40 | Rake $0.16
Seat 1: s0rrow (big blind) folded after the 1st Draw
Seat 3: X USN-USMC showed [3s 4s 7s 2d 6c] and won ($3.24) with Lo: 7,6,4,3,2
Seat 4: tom1206 mucked [8d 7c 4h 5h 3d]
Seat 5: bakter9 (button) folded before the Draw (didn't bet)
Seat 6: TheLabman (small blind) mucked [4d 6h 7h 2s 5c]
PokerStars Game #35839735773: Triple Draw 2-7 Lowball Limit ($0.10/$0.20 USD) - 2009/11/25 14:28:48 ET
Table 'Theodora VI' 6-max Seat #6 is the button
Seat 1: s0rrow ($4.17 in chips)
Seat 2: Mamega ($4 in chips)
Seat 3: X USN-USMC ($5.93 in chips)
Seat 4: tom1206 ($1.92 in chips)
Seat 5: LumBita ($1 in chips)
Seat 6: TheLabman ($4.34 in chips)
s0rrow: posts small blind $0.05
Mamega: posts big blind $0.10
LumBita: posts big blind $0.10
*** DEALING HANDS ***
Dealt to s0rrow [5c Kc Js Ts Jc]
X USN-USMC: calls $0.10
tom1206: calls $0.10
LumBita: checks
TheLabman: folds
s0rrow: folds
Mamega: checks
*** FIRST DRAW ***
Mamega: stands pat
X USN-USMC: discards 2 cards
tom1206: discards 3 cards
LumBita: discards 1 card
Mamega: checks
X USN-USMC: bets $0.10
tom1206: calls $0.10
LumBita: calls $0.10
Mamega: folds
*** SECOND DRAW ***
X USN-USMC: discards 1 card
tom1206: discards 1 card
LumBita: stands pat
X USN-USMC: checks
tom1206: checks
LumBita: bets $0.20
X USN-USMC: calls $0.20
tom1206: calls $0.20
*** THIRD DRAW ***
X USN-USMC: discards 1 card
tom1206: discards 1 card
LumBita: stands pat
X USN-USMC: checks
tom1206: checks
LumBita: checks
*** SHOW DOWN ***
X USN-USMC: shows [2h 4h 7d 5s 6c] (Lo: 7,6,5,4,2)
tom1206: mucks hand
LumBita: mucks hand
X USN-USMC collected $1.29 from pot
*** SUMMARY ***
Total pot $1.35 | Rake $0.06
Seat 1: s0rrow (small blind) folded before the Draw
Seat 2: Mamega (big blind) folded after the 1st Draw
Seat 3: X USN-USMC showed [2h 4h 7d 5s 6c] and won ($1.29) with Lo: 7,6,5,4,2
Seat 4: tom1206 mucked [7h 8c 3s 4d 5h]
Seat 5: LumBita mucked [4s 8s 3h 6h 2d]
Seat 6: TheLabman (button) folded before the Draw (didn't bet)
PokerStars Game #35839797257: Triple Draw 2-7 Lowball Limit ($0.10/$0.20 USD) - 2009/11/25 14:30:09 ET
Table 'Theodora VI' 6-max Seat #1 is the button
Seat 1: s0rrow ($4.12 in chips)
Seat 2: Mamega ($3.90 in chips)
Seat 3: X USN-USMC ($6.82 in chips)
Seat 4: tom1206 ($1.52 in chips)
Seat 5: LumBita ($0.60 in chips)
Seat 6: TheLabman ($4.34 in chips)
Mamega: posts small blind $0.05
X USN-USMC: posts big blind $0.10
*** DEALING HANDS ***
Dealt to s0rrow [2c Ah 3h 8h 5s]
tom1206: calls $0.10
LumBita: calls $0.10
TheLabman: folds
s0rrow: raises $0.10 to $0.20
Mamega: folds
X USN-USMC: folds
tom1206: calls $0.10
LumBita: calls $0.10
*** FIRST DRAW ***
tom1206: discards 2 cards
LumBita: discards 2 cards
s0rrow: discards 1 card [8h]
Dealt to s0rrow [2c Ah 3h 5s] [8d]
tom1206: checks
LumBita: checks
s0rrow: bets $0.10
tom1206: calls $0.10
LumBita: calls $0.10
*** SECOND DRAW ***
tom1206: discards 2 cards
LumBita: stands pat
s0rrow: discards 1 card [8d]
Dealt to s0rrow [2c Ah 3h 5s] [2s]
tom1206: checks
LumBita: bets $0.20
s0rrow: calls $0.20
tom1206: calls $0.20
*** THIRD DRAW ***
tom1206: discards 1 card
LumBita: stands pat
s0rrow: discards 1 card [2s]
Dealt to s0rrow [2c Ah 3h 5s] [Qd]
tom1206: checks
LumBita: bets $0.10 and is all-in
s0rrow: folds
tom1206: folds
Uncalled bet ($0.10) returned to LumBita
LumBita collected $1.57 from pot
LumBita: doesn't show hand
*** SUMMARY ***
Total pot $1.65 | Rake $0.08
Seat 1: s0rrow (button) folded after the 3rd Draw
Seat 2: Mamega (small blind) folded before the Draw
Seat 3: X USN-USMC (big blind) folded before the Draw
Seat 4: tom1206 folded after the 3rd Draw
Seat 5: LumBita collected ($1.57)
Seat 6: TheLabman folded before the Draw (didn't bet)
PokerStars Game #35839866916: Triple Draw 2-7 Lowball Limit ($0.10/$0.20 USD) - 2009/11/25 14:31:36 ET
Table 'Theodora VI' 6-max Seat #2 is the button
Seat 1: s0rrow ($3.62 in chips)
Seat 2: Mamega ($3.85 in chips)
Seat 3: X USN-USMC ($6.72 in chips)
Seat 4: tom1206 ($1.02 in chips)
Seat 5: LumBita ($1.67 in chips)
Seat 6: TheLabman ($4.34 in chips)
X USN-USMC: posts small blind $0.05
tom1206: posts big blind $0.10
*** DEALING HANDS ***
Dealt to s0rrow [Jd 5c 2s 5h Qs]
LumBita: calls $0.10
TheLabman: folds
s0rrow: folds
Mamega: folds
X USN-USMC: calls $0.05
tom1206: checks
*** FIRST DRAW ***
X USN-USMC: discards 3 cards
tom1206: discards 4 cards
LumBita: discards 2 cards
X USN-USMC: checks
tom1206: checks
LumBita: checks
*** SECOND DRAW ***
X USN-USMC: discards 2 cards
tom1206: discards 3 cards
LumBita: discards 2 cards
X USN-USMC: checks
tom1206: checks
LumBita: checks
*** THIRD DRAW ***
X USN-USMC: discards 2 cards
tom1206: discards 2 cards
LumBita: discards 1 card
X USN-USMC: bets $0.20
tom1206: calls $0.20
LumBita: folds
*** SHOW DOWN ***
X USN-USMC: shows [4h 3h 2d 7h 6d] (Lo: 7,6,4,3,2)
tom1206: mucks hand
X USN-USMC collected $0.67 from pot
*** SUMMARY ***
Total pot $0.70 | Rake $0.03
Seat 1: s0rrow folded before the Draw (didn't bet)
Seat 2: Mamega (button) folded before the Draw (didn't bet)
Seat 3: X USN-USMC (small blind) showed [4h 3h 2d 7h 6d] and won ($0.67) with Lo: 7,6,4,3,2
Seat 4: tom1206 (big blind) mucked [7c 5d 9s Th 8d]
Seat 5: LumBita folded after the 3rd Draw
Seat 6: TheLabman folded before the Draw (didn't bet)
PokerStars Game #35839926911: Triple Draw 2-7 Lowball Limit ($0.10/$0.20 USD) - 2009/11/25 14:32:52 ET
Table 'Theodora VI' 6-max Seat #3 is the button
Seat 1: s0rrow ($3.62 in chips)
Seat 2: Mamega ($3.85 in chips)
Seat 3: X USN-USMC ($7.09 in chips)
Seat 4: tom1206 ($0.72 in chips)
Seat 5: LumBita ($1.57 in chips)
Seat 6: TheLabman ($4.34 in chips)
tom1206: posts small blind $0.05
LumBita: posts big blind $0.10
*** DEALING HANDS ***
Dealt to s0rrow [Qd 2d 5s Ah 8d]
TheLabman: folds
s0rrow: calls $0.10
Mamega: folds
X USN-USMC: folds
tom1206: folds
LumBita: checks
*** FIRST DRAW ***
LumBita: discards 3 cards
s0rrow: discards 2 cards [Qd 8d]
Dealt to s0rrow [2d 5s Ah] [Jc 8h]
LumBita: checks
s0rrow: checks
*** SECOND DRAW ***
LumBita: discards 2 cards
s0rrow: discards 1 card [Jc]
Dealt to s0rrow [2d 5s Ah 8h] [9s]
LumBita: bets $0.20
s0rrow: calls $0.20
*** THIRD DRAW ***
LumBita: stands pat
s0rrow: stands pat on [2d 5s Ah 8h 9s]
LumBita: checks
s0rrow: checks
*** SHOW DOWN ***
LumBita: shows [7h 2s 5c 8c 6c] (Lo: 8,7,6,5,2)
s0rrow: mucks hand
LumBita collected $0.62 from pot
*** SUMMARY ***
Total pot $0.65 | Rake $0.03
Seat 1: s0rrow mucked [9s 2d 5s Ah 8h]
Seat 2: Mamega folded before the Draw (didn't bet)
Seat 3: X USN-USMC (button) folded before the Draw (didn't bet)
Seat 4: tom1206 (small blind) folded before the Draw
Seat 5: LumBita (big blind) showed [7h 2s 5c 8c 6c] and won ($0.62) with Lo: 8,7,6,5,2
Seat 6: TheLabman folded before the Draw (didn't bet)
PokerStars Game #35839959625: Triple Draw 2-7 Lowball Limit ($0.10/$0.20 USD) - 2009/11/25 14:33:33 ET
Table 'Theodora VI' 6-max Seat #4 is the button
Seat 1: s0rrow ($3.32 in chips)
Seat 2: Mamega ($3.85 in chips)
Seat 3: X USN-USMC ($7.09 in chips)
Seat 4: tom1206 ($0.67 in chips)
Seat 5: LumBita ($1.89 in chips)
Seat 6: TheLabman ($4.34 in chips)
LumBita: posts small blind $0.05
TheLabman: posts big blind $0.10
*** DEALING HANDS ***
Dealt to s0rrow [Jd As 8h 3s 7c]
s0rrow: calls $0.10
Mamega: folds
X USN-USMC: folds
tom1206: calls $0.10
LumBita: calls $0.05
TheLabman: checks
*** FIRST DRAW ***
LumBita: discards 2 cards
TheLabman: discards 1 card
s0rrow: discards 1 card [Jd]
Dealt to s0rrow [As 8h 3s 7c] [4h]
tom1206: discards 2 cards
LumBita: checks
TheLabman: bets $0.10
s0rrow: calls $0.10
tom1206: raises $0.10 to $0.20
LumBita: calls $0.20
TheLabman: calls $0.10
s0rrow: calls $0.10
*** SECOND DRAW ***
LumBita: discards 1 card
TheLabman: discards 1 card
s0rrow: discards 1 card [8h]
Dealt to s0rrow [As 3s 7c 4h] [8d]
tom1206: stands pat
LumBita: checks
TheLabman: checks
s0rrow: checks
tom1206: bets $0.20
LumBita: calls $0.20
TheLabman: calls $0.20
s0rrow: calls $0.20
*** THIRD DRAW ***
LumBita: discards 1 card
TheLabman: discards 1 card
s0rrow: stands pat on [As 3s 7c 4h 8d]
tom1206: stands pat
LumBita: checks
TheLabman: checks
s0rrow: checks
tom1206: bets $0.17 and is all-in
LumBita: calls $0.17
TheLabman: folds
s0rrow: calls $0.17
*** SHOW DOWN ***
tom1206: shows [5c 6c 4d 2h 8c] (Lo: 8,6,5,4,2)
LumBita: mucks hand
s0rrow: mucks hand
tom1206 collected $2.39 from pot
*** SUMMARY ***
Total pot $2.51 | Rake $0.12
Seat 1: s0rrow mucked [4h As 8d 3s 7c]
Seat 2: Mamega folded before the Draw (didn't bet)
Seat 3: X USN-USMC folded before the Draw (didn't bet)
Seat 4: tom1206 (button) showed [5c 6c 4d 2h 8c] and won ($2.39) with Lo: 8,6,5,4,2
Seat 5: LumBita (small blind) mucked [4c 3d 9c 7h 6h]
Seat 6: TheLabman (big blind) folded after the 3rd Draw

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,835 @@
PokerStars Game #35874004239: 7 Card Stud Limit ($0.04/$0.08 USD) - 2009/11/26 10:08:43 ET
Table 'Atalante II' 8-max
Seat 1: s0rrow ($1.60 in chips)
Seat 3: Nikolay Zem ($1.84 in chips)
Seat 4: totof51 ($1.34 in chips)
Seat 5: trs2758 ($1.76 in chips)
Seat 8: MasterTrini1 ($2.49 in chips)
s0rrow: posts the ante $0.01
Nikolay Zem: posts the ante $0.01
totof51: posts the ante $0.01
trs2758: posts the ante $0.01
MasterTrini1: posts the ante $0.01
*** 3rd STREET ***
Dealt to s0rrow [3d Th As]
Dealt to Nikolay Zem [9s]
Dealt to totof51 [Td]
Dealt to trs2758 [7d]
Dealt to MasterTrini1 [2c]
MasterTrini1: brings in for $0.02
s0rrow: calls $0.02
Nikolay Zem: calls $0.02
totof51: calls $0.02
trs2758: calls $0.02
*** 4th STREET ***
Dealt to s0rrow [3d Th As] [Qc]
Dealt to Nikolay Zem [9s] [6h]
Dealt to totof51 [Td] [4s]
Dealt to trs2758 [7d] [8d]
Dealt to MasterTrini1 [2c] [8c]
s0rrow: checks
Nikolay Zem: checks
totof51: checks
trs2758: checks
MasterTrini1: bets $0.04
s0rrow: folds
Nikolay Zem: calls $0.04
totof51: folds
trs2758: calls $0.04
*** 5th STREET ***
Dealt to Nikolay Zem [9s 6h] [7s]
Dealt to trs2758 [7d 8d] [8h]
Dealt to MasterTrini1 [2c 8c] [7h]
RoadDevil joins the table at seat #6
trs2758: bets $0.08
MasterTrini1: calls $0.08
Nikolay Zem: calls $0.08
*** 6th STREET ***
Dealt to Nikolay Zem [9s 6h 7s] [Qh]
Dealt to trs2758 [7d 8d 8h] [Ts]
Dealt to MasterTrini1 [2c 8c 7h] [5d]
trs2758: bets $0.08
MasterTrini1: calls $0.08
Nikolay Zem: folds
*** RIVER ***
trs2758: bets $0.08
MasterTrini1: folds
Uncalled bet ($0.08) returned to trs2758
trs2758 collected $0.64 from pot
*** SUMMARY ***
Total pot $0.67 | Rake $0.03
Seat 1: s0rrow folded on the 4th Street
Seat 3: Nikolay Zem folded on the 6th Street
Seat 4: totof51 folded on the 4th Street
Seat 5: trs2758 collected ($0.64)
Seat 8: MasterTrini1 folded on the River
PokerStars Game #35874039554: 7 Card Stud Limit ($0.04/$0.08 USD) - 2009/11/26 10:09:44 ET
Table 'Atalante II' 8-max
Seat 1: s0rrow ($1.57 in chips)
Seat 3: Nikolay Zem ($1.69 in chips)
Seat 4: totof51 ($1.31 in chips)
Seat 5: trs2758 ($2.17 in chips)
Seat 6: RoadDevil ($1.60 in chips)
Seat 8: MasterTrini1 ($2.26 in chips)
s0rrow: posts the ante $0.01
Nikolay Zem: posts the ante $0.01
totof51: posts the ante $0.01
trs2758: posts the ante $0.01
RoadDevil: posts the ante $0.01
MasterTrini1: posts the ante $0.01
*** 3rd STREET ***
Dealt to s0rrow [3s Qd 9h]
Dealt to Nikolay Zem [7d]
Dealt to totof51 [7c]
Dealt to trs2758 [5h]
Dealt to RoadDevil [5d]
Dealt to MasterTrini1 [Ts]
RoadDevil: brings in for $0.02
MasterTrini1: calls $0.02
s0rrow: folds
Nikolay Zem: calls $0.02
totof51: calls $0.02
trs2758: calls $0.02
*** 4th STREET ***
Dealt to Nikolay Zem [7d] [Td]
Dealt to totof51 [7c] [Th]
Dealt to trs2758 [5h] [8s]
Dealt to RoadDevil [5d] [Js]
Dealt to MasterTrini1 [Ts] [5c]
RoadDevil: checks
MasterTrini1: checks
Nikolay Zem: checks
totof51: bets $0.04
trs2758: calls $0.04
RoadDevil: folds
MasterTrini1: calls $0.04
Nikolay Zem: calls $0.04
*** 5th STREET ***
Dealt to Nikolay Zem [7d Td] [3d]
Dealt to totof51 [7c Th] [9s]
Dealt to trs2758 [5h 8s] [4s]
Dealt to MasterTrini1 [Ts 5c] [6h]
totof51: bets $0.08
trs2758: folds
MasterTrini1: calls $0.08
Nikolay Zem: calls $0.08
*** 6th STREET ***
Dealt to Nikolay Zem [7d Td 3d] [Tc]
Dealt to totof51 [7c Th 9s] [Ah]
Dealt to MasterTrini1 [Ts 5c 6h] [Jh]
Nikolay Zem: checks
totof51: bets $0.08
MasterTrini1: calls $0.08
Nikolay Zem: calls $0.08
*** RIVER ***
Nikolay Zem: checks
totof51: checks
MasterTrini1: checks
*** SHOW DOWN ***
Nikolay Zem: shows [Ac 4d 7d Td 3d Tc 2h] (a pair of Tens)
totof51: mucks hand
totof51 is sitting out
MasterTrini1: shows [4c 6d Ts 5c 6h Jh 9c] (a pair of Sixes)
totof51 leaves the table
Nikolay Zem collected $0.77 from pot
*** SUMMARY ***
Total pot $0.80 | Rake $0.03
Seat 1: s0rrow folded on the 3rd Street (didn't bet)
Seat 3: Nikolay Zem showed [Ac 4d 7d Td 3d Tc 2h] and won ($0.77) with a pair of Tens
Seat 4: totof51 mucked [3c 7s 7c Th 9s Ah Qc]
Seat 5: trs2758 folded on the 5th Street
Seat 6: RoadDevil folded on the 4th Street
Seat 8: MasterTrini1 showed [4c 6d Ts 5c 6h Jh 9c] and lost with a pair of Sixes
PokerStars Game #35874081088: 7 Card Stud Limit ($0.04/$0.08 USD) - 2009/11/26 10:10:56 ET
Table 'Atalante II' 8-max
Seat 1: s0rrow ($1.56 in chips)
Seat 3: Nikolay Zem ($2.23 in chips)
Seat 5: trs2758 ($2.10 in chips)
Seat 6: RoadDevil ($1.57 in chips)
Seat 8: MasterTrini1 ($2.03 in chips)
s0rrow: posts the ante $0.01
Nikolay Zem: posts the ante $0.01
trs2758: posts the ante $0.01
RoadDevil: posts the ante $0.01
MasterTrini1: posts the ante $0.01
*** 3rd STREET ***
Dealt to s0rrow [5h 5c 2s]
Dealt to Nikolay Zem [Ad]
Dealt to trs2758 [6h]
Dealt to RoadDevil [4h]
Dealt to MasterTrini1 [8h]
s0rrow: bets $0.04
Nikolay Zem: calls $0.04
trs2758: folds
RoadDevil: calls $0.04
MasterTrini1: raises $0.04 to $0.08
s0rrow: calls $0.04
Nikolay Zem: calls $0.04
RoadDevil: calls $0.04
*** 4th STREET ***
Dealt to s0rrow [5h 5c 2s] [As]
Dealt to Nikolay Zem [Ad] [4s]
Dealt to RoadDevil [4h] [Tc]
Dealt to MasterTrini1 [8h] [6d]
Nikolay Zem: checks
RoadDevil: checks
MasterTrini1: bets $0.04
s0rrow: calls $0.04
Nikolay Zem: folds
RoadDevil: folds
*** 5th STREET ***
Dealt to s0rrow [5h 5c 2s As] [5d]
Dealt to MasterTrini1 [8h 6d] [Ac]
MasterTrini1: bets $0.08
s0rrow: raises $0.08 to $0.16
MasterTrini1: calls $0.08
*** 6th STREET ***
Dealt to s0rrow [5h 5c 2s As 5d] [Ah]
Dealt to MasterTrini1 [8h 6d Ac] [Js]
s0rrow: bets $0.08
MasterTrini1: calls $0.08
*** RIVER ***
Dealt to s0rrow [5h 5c 2s As 5d Ah] [4d]
s0rrow: bets $0.08
MasterTrini1: calls $0.08
*** SHOW DOWN ***
s0rrow: shows [5h 5c 2s As 5d Ah 4d] (a full house, Fives full of Aces)
MasterTrini1: mucks hand
s0rrow collected $1.04 from pot
*** SUMMARY ***
Total pot $1.09 | Rake $0.05
Seat 1: s0rrow showed [5h 5c 2s As 5d Ah 4d] and won ($1.04) with a full house, Fives full of Aces
Seat 3: Nikolay Zem folded on the 4th Street
Seat 5: trs2758 folded on the 3rd Street (didn't bet)
Seat 6: RoadDevil folded on the 4th Street
Seat 8: MasterTrini1 mucked [Qs Qd 8h 6d Ac Js Jc]
PokerStars Game #35874124553: 7 Card Stud Limit ($0.04/$0.08 USD) - 2009/11/26 10:12:11 ET
Table 'Atalante II' 8-max
Seat 1: s0rrow ($2.15 in chips)
Seat 3: Nikolay Zem ($2.14 in chips)
Seat 5: trs2758 ($2.09 in chips)
Seat 6: RoadDevil ($1.48 in chips)
Seat 8: MasterTrini1 ($1.58 in chips)
s0rrow: posts the ante $0.01
Nikolay Zem: posts the ante $0.01
trs2758: posts the ante $0.01
RoadDevil: posts the ante $0.01
MasterTrini1: posts the ante $0.01
*** 3rd STREET ***
Dealt to s0rrow [Js Kc 3d]
Dealt to Nikolay Zem [6c]
Dealt to trs2758 [4d]
Dealt to RoadDevil [6d]
Dealt to MasterTrini1 [9h]
s0rrow: brings in for $0.02
Nikolay Zem: folds
trs2758: folds
RoadDevil: calls $0.02
MasterTrini1: calls $0.02
*** 4th STREET ***
Dealt to s0rrow [Js Kc 3d] [2h]
Dealt to RoadDevil [6d] [Ah]
Dealt to MasterTrini1 [9h] [8c]
RoadDevil: checks
MasterTrini1: bets $0.04
rv2020 joins the table at seat #4
s0rrow: folds
RoadDevil: calls $0.04
*** 5th STREET ***
Dealt to RoadDevil [6d Ah] [Td]
Dealt to MasterTrini1 [9h 8c] [5s]
RoadDevil: checks
MasterTrini1: bets $0.08
RoadDevil: calls $0.08
*** 6th STREET ***
Dealt to RoadDevil [6d Ah Td] [4c]
Dealt to MasterTrini1 [9h 8c 5s] [5h]
MasterTrini1: bets $0.08
RoadDevil: calls $0.08
*** RIVER ***
MasterTrini1: bets $0.08
RoadDevil: calls $0.08
*** SHOW DOWN ***
MasterTrini1: shows [6s 7d 9h 8c 5s 5h 9d] (a straight, Five to Nine)
RoadDevil: mucks hand
MasterTrini1 collected $0.64 from pot
*** SUMMARY ***
Total pot $0.67 | Rake $0.03
Seat 1: s0rrow folded on the 4th Street
Seat 3: Nikolay Zem folded on the 3rd Street (didn't bet)
Seat 5: trs2758 folded on the 3rd Street (didn't bet)
Seat 6: RoadDevil mucked [4s 8d 6d Ah Td 4c 8h]
Seat 8: MasterTrini1 showed [6s 7d 9h 8c 5s 5h 9d] and won ($0.64) with a straight, Five to Nine
PokerStars Game #35874153086: 7 Card Stud Limit ($0.04/$0.08 USD) - 2009/11/26 10:13:01 ET
Table 'Atalante II' 8-max
Seat 1: s0rrow ($2.12 in chips)
Seat 3: Nikolay Zem ($2.13 in chips)
Seat 4: rv2020 ($1 in chips)
Seat 5: trs2758 ($2.08 in chips)
Seat 6: RoadDevil ($1.17 in chips)
Seat 8: MasterTrini1 ($1.91 in chips)
s0rrow: posts the ante $0.01
Nikolay Zem: posts the ante $0.01
rv2020: posts the ante $0.01
trs2758: posts the ante $0.01
RoadDevil: posts the ante $0.01
MasterTrini1: posts the ante $0.01
*** 3rd STREET ***
Dealt to s0rrow [As 8s 6h]
Dealt to Nikolay Zem [4c]
Dealt to rv2020 [2s]
Dealt to trs2758 [7s]
Dealt to RoadDevil [7c]
Dealt to MasterTrini1 [Qd]
rv2020: brings in for $0.02
trs2758: calls $0.02
RoadDevil: calls $0.02
MasterTrini1: calls $0.02
s0rrow: calls $0.02
Nikolay Zem: folds
*** 4th STREET ***
Dealt to s0rrow [As 8s 6h] [3s]
Dealt to rv2020 [2s] [6d]
Dealt to trs2758 [7s] [Ah]
Dealt to RoadDevil [7c] [4h]
Dealt to MasterTrini1 [Qd] [Ad]
MasterTrini1: checks
s0rrow: checks
rv2020: checks
trs2758: checks
RoadDevil: checks
*** 5th STREET ***
Dealt to s0rrow [As 8s 6h 3s] [Jh]
Dealt to rv2020 [2s 6d] [Qh]
Dealt to trs2758 [7s Ah] [4d]
Dealt to RoadDevil [7c 4h] [7h]
Dealt to MasterTrini1 [Qd Ad] [5h]
RoadDevil: checks
MasterTrini1: checks
s0rrow: checks
rv2020: checks
trs2758: checks
*** 6th STREET ***
Dealt to s0rrow [As 8s 6h 3s Jh] [Tc]
Dealt to rv2020 [2s 6d Qh] [9h]
Dealt to trs2758 [7s Ah 4d] [3d]
Dealt to RoadDevil [7c 4h 7h] [5c]
Dealt to MasterTrini1 [Qd Ad 5h] [Td]
RoadDevil: checks
MasterTrini1: checks
s0rrow: checks
rv2020: checks
trs2758: checks
*** RIVER ***
Dealt to s0rrow [As 8s 6h 3s Jh Tc] [Qs]
RoadDevil: checks
MasterTrini1: checks
s0rrow: checks
rv2020: checks
trs2758: checks
*** SHOW DOWN ***
s0rrow: shows [As 8s 6h 3s Jh Tc Qs] (high card Ace)
rv2020: shows [8c Ac 2s 6d Qh 9h 2d] (a pair of Deuces)
trs2758: mucks hand
RoadDevil: shows [Jd Qc 7c 4h 7h 5c Kc] (a pair of Sevens)
MasterTrini1: shows [Jc 2h Qd Ad 5h Td Ks] (a straight, Ten to Ace)
MasterTrini1 collected $0.16 from pot
*** SUMMARY ***
Total pot $0.16 | Rake $0
Seat 1: s0rrow showed [As 8s 6h 3s Jh Tc Qs] and lost with high card Ace
Seat 3: Nikolay Zem folded on the 3rd Street (didn't bet)
Seat 4: rv2020 showed [8c Ac 2s 6d Qh 9h 2d] and lost with a pair of Deuces
Seat 5: trs2758 mucked [2c 9s 7s Ah 4d 3d 8d]
Seat 6: RoadDevil showed [Jd Qc 7c 4h 7h 5c Kc] and lost with a pair of Sevens
Seat 8: MasterTrini1 showed [Jc 2h Qd Ad 5h Td Ks] and won ($0.16) with a straight, Ten to Ace
PokerStars Game #35874195699: 7 Card Stud Limit ($0.04/$0.08 USD) - 2009/11/26 10:14:15 ET
Table 'Atalante II' 8-max
Seat 1: s0rrow ($2.09 in chips)
Seat 3: Nikolay Zem ($2.12 in chips)
Seat 4: rv2020 ($0.97 in chips)
Seat 5: trs2758 ($2.05 in chips)
Seat 6: RoadDevil ($1.14 in chips)
Seat 8: MasterTrini1 ($2.04 in chips)
s0rrow: posts the ante $0.01
Nikolay Zem: posts the ante $0.01
rv2020: posts the ante $0.01
trs2758: posts the ante $0.01
RoadDevil: posts the ante $0.01
MasterTrini1: posts the ante $0.01
*** 3rd STREET ***
Dealt to s0rrow [6c 4c Th]
Dealt to Nikolay Zem [9d]
Dealt to rv2020 [4s]
Dealt to trs2758 [3h]
Dealt to RoadDevil [Ac]
Dealt to MasterTrini1 [5d]
trs2758: brings in for $0.02
RoadDevil: folds
MasterTrini1: calls $0.02
s0rrow: folds
Nikolay Zem: calls $0.02
rv2020: folds
*** 4th STREET ***
Dealt to Nikolay Zem [9d] [3s]
Dealt to trs2758 [3h] [Jd]
Dealt to MasterTrini1 [5d] [2d]
trs2758: checks
MasterTrini1: checks
Nikolay Zem: checks
*** 5th STREET ***
Dealt to Nikolay Zem [9d 3s] [9c]
Dealt to trs2758 [3h Jd] [2h]
Dealt to MasterTrini1 [5d 2d] [7d]
Nikolay Zem: bets $0.08
trs2758: folds
MasterTrini1: raises $0.08 to $0.16
Nikolay Zem: calls $0.08
*** 6th STREET ***
Dealt to Nikolay Zem [9d 3s 9c] [Td]
Dealt to MasterTrini1 [5d 2d 7d] [5h]
Nikolay Zem: checks
MasterTrini1: checks
*** RIVER ***
Nikolay Zem: bets $0.08
MasterTrini1: folds
Uncalled bet ($0.08) returned to Nikolay Zem
Nikolay Zem collected $0.42 from pot
Nikolay Zem: doesn't show hand
*** SUMMARY ***
Total pot $0.44 | Rake $0.02
Seat 1: s0rrow folded on the 3rd Street (didn't bet)
Seat 3: Nikolay Zem collected ($0.42)
Seat 4: rv2020 folded on the 3rd Street (didn't bet)
Seat 5: trs2758 folded on the 5th Street
Seat 6: RoadDevil folded on the 3rd Street (didn't bet)
Seat 8: MasterTrini1 folded on the River
PokerStars Game #35874220204: 7 Card Stud Limit ($0.04/$0.08 USD) - 2009/11/26 10:14:58 ET
Table 'Atalante II' 8-max
Seat 1: s0rrow ($2.08 in chips)
Seat 3: Nikolay Zem ($2.35 in chips)
Seat 4: rv2020 ($0.96 in chips)
Seat 5: trs2758 ($2.02 in chips)
Seat 6: RoadDevil ($1.13 in chips)
Seat 8: MasterTrini1 ($1.85 in chips)
s0rrow: posts the ante $0.01
Nikolay Zem: posts the ante $0.01
rv2020: posts the ante $0.01
trs2758: posts the ante $0.01
RoadDevil: posts the ante $0.01
MasterTrini1: posts the ante $0.01
*** 3rd STREET ***
Dealt to s0rrow [Jd 9d 2h]
Dealt to Nikolay Zem [Ad]
Dealt to rv2020 [2c]
Dealt to trs2758 [8c]
Dealt to RoadDevil [3s]
Dealt to MasterTrini1 [3h]
rv2020: brings in for $0.02
trs2758: calls $0.02
RoadDevil: folds
MasterTrini1: calls $0.02
s0rrow: folds
Nikolay Zem: calls $0.02
*** 4th STREET ***
Dealt to Nikolay Zem [Ad] [9h]
Dealt to rv2020 [2c] [4d]
Dealt to trs2758 [8c] [Qd]
Dealt to MasterTrini1 [3h] [Qs]
Nikolay Zem: checks
rv2020: bets $0.04
trs2758: calls $0.04
MasterTrini1: calls $0.04
Nikolay Zem: folds
*** 5th STREET ***
Dealt to rv2020 [2c 4d] [Jh]
Dealt to trs2758 [8c Qd] [Js]
Dealt to MasterTrini1 [3h Qs] [4h]
trs2758: checks
MasterTrini1: bets $0.08
rv2020: raises $0.08 to $0.16
trs2758: calls $0.16
MasterTrini1: calls $0.08
*** 6th STREET ***
Dealt to rv2020 [2c 4d Jh] [7c]
Dealt to trs2758 [8c Qd Js] [5c]
Dealt to MasterTrini1 [3h Qs 4h] [7h]
trs2758: checks
MasterTrini1: checks
rv2020: bets $0.08
trs2758: folds
MasterTrini1: calls $0.08
*** RIVER ***
MasterTrini1: checks
rv2020: checks
*** SHOW DOWN ***
rv2020: shows [As Ac 2c 4d Jh 7c 3c] (a pair of Aces)
MasterTrini1: mucks hand
rv2020 collected $0.86 from pot
*** SUMMARY ***
Total pot $0.90 | Rake $0.04
Seat 1: s0rrow folded on the 3rd Street (didn't bet)
Seat 3: Nikolay Zem folded on the 4th Street
Seat 4: rv2020 showed [As Ac 2c 4d Jh 7c 3c] and won ($0.86) with a pair of Aces
Seat 5: trs2758 folded on the 6th Street
Seat 6: RoadDevil folded on the 3rd Street (didn't bet)
Seat 8: MasterTrini1 mucked [6s 8s 3h Qs 4h 7h 6d]
PokerStars Game #35874259784: 7 Card Stud Limit ($0.04/$0.08 USD) - 2009/11/26 10:16:07 ET
Table 'Atalante II' 8-max
Seat 1: s0rrow ($2.07 in chips)
Seat 3: Nikolay Zem ($2.32 in chips)
Seat 4: rv2020 ($1.51 in chips)
Seat 5: trs2758 ($1.79 in chips)
Seat 6: RoadDevil ($1.12 in chips)
Seat 8: MasterTrini1 ($1.54 in chips)
s0rrow: posts the ante $0.01
Nikolay Zem: posts the ante $0.01
rv2020: posts the ante $0.01
trs2758: posts the ante $0.01
RoadDevil: posts the ante $0.01
MasterTrini1: posts the ante $0.01
*** 3rd STREET ***
Dealt to s0rrow [7d 6h 9s]
Dealt to Nikolay Zem [Js]
Dealt to rv2020 [3d]
Dealt to trs2758 [7s]
Dealt to RoadDevil [Qh]
Dealt to MasterTrini1 [5d]
rv2020: brings in for $0.02
trs2758: folds
RoadDevil: calls $0.02
MasterTrini1: calls $0.02
s0rrow: calls $0.02
Nikolay Zem: calls $0.02
*** 4th STREET ***
Dealt to s0rrow [7d 6h 9s] [Kc]
Dealt to Nikolay Zem [Js] [6s]
Dealt to rv2020 [3d] [Jd]
Dealt to RoadDevil [Qh] [Th]
Dealt to MasterTrini1 [5d] [8c]
Katica65 was removed from the table for failing to post
s0rrow: checks
Nikolay Zem: checks
danjr655 joins the table at seat #2
rv2020: checks
RoadDevil: checks
MasterTrini1: checks
*** 5th STREET ***
Dealt to s0rrow [7d 6h 9s Kc] [Ah]
Dealt to Nikolay Zem [Js 6s] [Ad]
Dealt to rv2020 [3d Jd] [Tc]
Dealt to RoadDevil [Qh Th] [Qc]
Dealt to MasterTrini1 [5d 8c] [3h]
RoadDevil: bets $0.08
MasterTrini1: folds
s0rrow: raises $0.08 to $0.16
Nikolay Zem: calls $0.16
rv2020: folds
RoadDevil: calls $0.08
*** 6th STREET ***
Dealt to s0rrow [7d 6h 9s Kc Ah] [4d]
Dealt to Nikolay Zem [Js 6s Ad] [4s]
Dealt to RoadDevil [Qh Th Qc] [7h]
RoadDevil: checks
s0rrow: checks
Nikolay Zem: bets $0.08
RoadDevil: calls $0.08
s0rrow: folds
*** RIVER ***
RoadDevil: checks
Nikolay Zem: bets $0.08
RoadDevil: calls $0.08
*** SHOW DOWN ***
Nikolay Zem: shows [Qs 3s Js 6s Ad 4s 2s] (a flush, Queen high)
RoadDevil: mucks hand
Nikolay Zem collected $0.92 from pot
*** SUMMARY ***
Total pot $0.96 | Rake $0.04
Seat 1: s0rrow folded on the 6th Street
Seat 3: Nikolay Zem showed [Qs 3s Js 6s Ad 4s 2s] and won ($0.92) with a flush, Queen high
Seat 4: rv2020 folded on the 5th Street
Seat 5: trs2758 folded on the 3rd Street (didn't bet)
Seat 6: RoadDevil mucked [2h Ts Qh Th Qc 7h Kd]
Seat 8: MasterTrini1 folded on the 5th Street
PokerStars Game #35874289931: 7 Card Stud Limit ($0.04/$0.08 USD) - 2009/11/26 10:16:59 ET
Table 'Atalante II' 8-max
Seat 1: s0rrow ($1.88 in chips)
Seat 2: danjr655 ($0.45 in chips)
Seat 3: Nikolay Zem ($2.89 in chips)
Seat 4: rv2020 ($1.48 in chips)
Seat 5: trs2758 ($1.78 in chips)
Seat 6: RoadDevil ($0.77 in chips)
Seat 8: MasterTrini1 ($1.51 in chips)
s0rrow: posts the ante $0.01
danjr655: posts the ante $0.01
Nikolay Zem: posts the ante $0.01
rv2020: posts the ante $0.01
trs2758: posts the ante $0.01
RoadDevil: posts the ante $0.01
MasterTrini1: posts the ante $0.01
*** 3rd STREET ***
Dealt to s0rrow [2d Qs 8c]
Dealt to danjr655 [5d]
Dealt to Nikolay Zem [Jc]
Dealt to rv2020 [8d]
Dealt to trs2758 [Kd]
Dealt to RoadDevil [4s]
Dealt to MasterTrini1 [6h]
RoadDevil: brings in for $0.02
Trackr21 joins the table at seat #7
MasterTrini1: calls $0.02
s0rrow: folds
danjr655: folds
Nikolay Zem: calls $0.02
rv2020: calls $0.02
trs2758: calls $0.02
*** 4th STREET ***
Dealt to Nikolay Zem [Jc] [2h]
Dealt to rv2020 [8d] [Jd]
Dealt to trs2758 [Kd] [Ks]
Dealt to RoadDevil [4s] [6c]
Dealt to MasterTrini1 [6h] [4c]
Pair on board - a double bet is allowed
trs2758: bets $0.04
RoadDevil: calls $0.04
MasterTrini1: calls $0.04
Nikolay Zem: folds
rv2020: folds
*** 5th STREET ***
Dealt to trs2758 [Kd Ks] [7c]
Dealt to RoadDevil [4s 6c] [9d]
Dealt to MasterTrini1 [6h 4c] [3h]
trs2758: bets $0.08
RoadDevil: folds
MasterTrini1: raises $0.08 to $0.16
trs2758: raises $0.08 to $0.24
MasterTrini1: raises $0.08 to $0.32
Betting is capped
trs2758: calls $0.08
*** 6th STREET ***
Dealt to trs2758 [Kd Ks 7c] [9h]
Dealt to MasterTrini1 [6h 4c 3h] [3c]
trs2758: checks
MasterTrini1: bets $0.08
trs2758: calls $0.08
*** RIVER ***
trs2758: checks
MasterTrini1: checks
*** SHOW DOWN ***
trs2758: shows [Ac 2c Kd Ks 7c 9h 9c] (two pair, Kings and Nines)
MasterTrini1: shows [5h 8h 6h 4c 3h 3c As] (a pair of Threes)
trs2758 collected $1.04 from pot
*** SUMMARY ***
Total pot $1.09 | Rake $0.05
Seat 1: s0rrow folded on the 3rd Street (didn't bet)
Seat 2: danjr655 folded on the 3rd Street (didn't bet)
Seat 3: Nikolay Zem folded on the 4th Street
Seat 4: rv2020 folded on the 4th Street
Seat 5: trs2758 showed [Ac 2c Kd Ks 7c 9h 9c] and won ($1.04) with two pair, Kings and Nines
Seat 6: RoadDevil folded on the 5th Street
Seat 8: MasterTrini1 showed [5h 8h 6h 4c 3h 3c As] and lost with a pair of Threes
PokerStars Game #35874334277: 7 Card Stud Limit ($0.04/$0.08 USD) - 2009/11/26 10:18:16 ET
Table 'Atalante II' 8-max
Seat 1: s0rrow ($1.87 in chips)
Seat 2: danjr655 ($0.44 in chips)
Seat 3: Nikolay Zem ($2.86 in chips)
Seat 4: rv2020 ($1.45 in chips)
Seat 5: trs2758 ($2.35 in chips)
Seat 6: RoadDevil ($0.70 in chips)
Seat 7: Trackr21 ($1.60 in chips)
Seat 8: MasterTrini1 ($1.04 in chips)
s0rrow: posts the ante $0.01
danjr655: posts the ante $0.01
Nikolay Zem: posts the ante $0.01
rv2020: posts the ante $0.01
trs2758: posts the ante $0.01
RoadDevil: posts the ante $0.01
Trackr21: posts the ante $0.01
MasterTrini1: posts the ante $0.01
*** 3rd STREET ***
Dealt to s0rrow [7d Qs 8s]
Dealt to danjr655 [8d]
Dealt to Nikolay Zem [6d]
Dealt to rv2020 [4d]
Dealt to trs2758 [Ad]
Dealt to RoadDevil [Td]
Dealt to Trackr21 [Jh]
Dealt to MasterTrini1 [5s]
rv2020: brings in for $0.02
trs2758: calls $0.02
RoadDevil: folds
Trackr21: folds
MasterTrini1: calls $0.02
s0rrow: calls $0.02
danjr655: folds
Nikolay Zem: calls $0.02
*** 4th STREET ***
Dealt to s0rrow [7d Qs 8s] [2s]
Dealt to Nikolay Zem [6d] [2h]
Dealt to rv2020 [4d] [Kd]
Dealt to trs2758 [Ad] [Kh]
Dealt to MasterTrini1 [5s] [5c]
Pair on board - a double bet is allowed
MasterTrini1: bets $0.08
s0rrow: calls $0.08
Nikolay Zem: folds
rv2020: calls $0.08
trs2758: calls $0.08
*** 5th STREET ***
Dealt to s0rrow [7d Qs 8s 2s] [As]
Dealt to rv2020 [4d Kd] [Qd]
Dealt to trs2758 [Ad Kh] [3h]
Dealt to MasterTrini1 [5s 5c] [Js]
MasterTrini1: checks
s0rrow: bets $0.08
rv2020: folds
trs2758: folds
MasterTrini1: calls $0.08
*** 6th STREET ***
Dealt to s0rrow [7d Qs 8s 2s As] [5d]
Dealt to MasterTrini1 [5s 5c Js] [2c]
MasterTrini1: checks
s0rrow: bets $0.08
MasterTrini1: calls $0.08
*** RIVER ***
Dealt to s0rrow [7d Qs 8s 2s As 5d] [7h]
MasterTrini1: checks
s0rrow: bets $0.08
MasterTrini1: calls $0.08
*** SHOW DOWN ***
s0rrow: shows [7d Qs 8s 2s As 5d 7h] (a pair of Sevens)
MasterTrini1: mucks hand
s0rrow collected $0.94 from pot
*** SUMMARY ***
Total pot $0.98 | Rake $0.04
Seat 1: s0rrow showed [7d Qs 8s 2s As 5d 7h] and won ($0.94) with a pair of Sevens
Seat 2: danjr655 folded on the 3rd Street (didn't bet)
Seat 3: Nikolay Zem folded on the 4th Street
Seat 4: rv2020 folded on the 5th Street
Seat 5: trs2758 folded on the 5th Street
Seat 6: RoadDevil folded on the 3rd Street (didn't bet)
Seat 7: Trackr21 folded on the 3rd Street (didn't bet)
Seat 8: MasterTrini1 mucked [Ac 9d 5s 5c Js 2c Kc]
PokerStars Game #35874382643: 7 Card Stud Limit ($0.04/$0.08 USD) - 2009/11/26 10:19:39 ET
Table 'Atalante II' 8-max
Seat 1: s0rrow ($2.46 in chips)
Seat 2: danjr655 ($0.43 in chips)
Seat 3: Nikolay Zem ($2.83 in chips)
Seat 4: rv2020 ($1.34 in chips)
Seat 5: trs2758 ($2.24 in chips)
Seat 6: RoadDevil ($0.69 in chips)
Seat 7: Trackr21 ($1.59 in chips)
Seat 8: MasterTrini1 ($0.69 in chips)
s0rrow: posts the ante $0.01
danjr655: posts the ante $0.01
Nikolay Zem: posts the ante $0.01
rv2020: posts the ante $0.01
trs2758: posts the ante $0.01
RoadDevil: posts the ante $0.01
Trackr21: posts the ante $0.01
MasterTrini1: posts the ante $0.01
*** 3rd STREET ***
Dealt to s0rrow [8d 3d 8c]
Dealt to danjr655 [Kd]
Dealt to Nikolay Zem [9c]
Dealt to rv2020 [4h]
Dealt to trs2758 [6c]
Dealt to RoadDevil [6d]
Dealt to Trackr21 [5d]
Dealt to MasterTrini1 [8h]
rv2020: brings in for $0.02
trs2758: folds
RoadDevil: calls $0.02
Trackr21: calls $0.02
MasterTrini1: calls $0.02
s0rrow: calls $0.02
danjr655: calls $0.02
Nikolay Zem: calls $0.02
*** 4th STREET ***
Dealt to s0rrow [8d 3d 8c] [Qc]
Dealt to danjr655 [Kd] [Kc]
Dealt to Nikolay Zem [9c] [Jd]
Dealt to rv2020 [4h] [8s]
Dealt to RoadDevil [6d] [4s]
Dealt to Trackr21 [5d] [4d]
Dealt to MasterTrini1 [8h] [As]
Pair on board - a double bet is allowed
danjr655: bets $0.04
Nikolay Zem: calls $0.04
rv2020: folds
RoadDevil: folds
Trackr21: calls $0.04
MasterTrini1: calls $0.04
s0rrow: folds
*** 5th STREET ***
Dealt to danjr655 [Kd Kc] [2h]
Dealt to Nikolay Zem [9c Jd] [Qs]
Dealt to Trackr21 [5d 4d] [3h]
Dealt to MasterTrini1 [8h As] [Th]
danjr655: bets $0.08
Nikolay Zem: calls $0.08
Trackr21: calls $0.08
s0rrow is sitting out
MasterTrini1: calls $0.08
*** 6th STREET ***
Dealt to danjr655 [Kd Kc 2h] [7s]
Dealt to Nikolay Zem [9c Jd Qs] [9d]
Dealt to Trackr21 [5d 4d 3h] [5s]
Dealt to MasterTrini1 [8h As Th] [9h]
danjr655: checks
Nikolay Zem: checks
Trackr21: checks
MasterTrini1: checks
*** RIVER ***
danjr655: checks
Nikolay Zem: checks
Trackr21: bets $0.08
MasterTrini1: folds
danjr655: folds
Nikolay Zem: calls $0.08
*** SHOW DOWN ***
Trackr21: shows [6h Ah 5d 4d 3h 5s 5c] (three of a kind, Fives)
Nikolay Zem: mucks hand
Trackr21 collected $0.82 from pot
*** SUMMARY ***
Total pot $0.86 | Rake $0.04
Seat 1: s0rrow folded on the 4th Street
Seat 2: danjr655 folded on the River
Seat 3: Nikolay Zem mucked [7c 7d 9c Jd Qs 9d Ad]
Seat 4: rv2020 folded on the 4th Street
Seat 5: trs2758 folded on the 3rd Street (didn't bet)
Seat 6: RoadDevil folded on the 4th Street
Seat 7: Trackr21 showed [6h Ah 5d 4d 3h 5s 5c] and won ($0.82) with three of a kind, Fives
Seat 8: MasterTrini1 folded on the River

View File

@ -0,0 +1,611 @@
PokerStars Game #35874487284: 7 Card Stud Hi/Lo Limit ($0.04/$0.08 USD) - 2009/11/26 10:22:32 ET
Table 'Dawn II' 8-max
Seat 3: gashpor ($1.46 in chips)
Seat 4: denny501 ($0.93 in chips)
Seat 5: s0rrow ($1.60 in chips)
Seat 8: rdiezchang ($1.16 in chips)
gashpor: posts the ante $0.01
denny501: posts the ante $0.01
s0rrow: posts the ante $0.01
rdiezchang: posts the ante $0.01
*** 3rd STREET ***
Dealt to gashpor [Kc]
Dealt to denny501 [7c]
Dealt to s0rrow [5d Ks 2h]
Dealt to rdiezchang [3d]
s0rrow: brings in for $0.02
rdiezchang: calls $0.02
gashpor: calls $0.02
denny501: calls $0.02
*** 4th STREET ***
Dealt to gashpor [Kc] [4d]
Dealt to denny501 [7c] [Qh]
Dealt to s0rrow [5d Ks 2h] [9h]
Dealt to rdiezchang [3d] [7s]
Soroka69 joins the table at seat #7
gashpor: checks
poconoman is connected
denny501: checks
s0rrow: checks
rdiezchang: checks
*** 5th STREET ***
Dealt to gashpor [Kc 4d] [Qd]
Dealt to denny501 [7c Qh] [9s]
Dealt to s0rrow [5d Ks 2h 9h] [Js]
Dealt to rdiezchang [3d 7s] [Jh]
gashpor: checks
denny501: checks
s0rrow: checks
rdiezchang: checks
*** 6th STREET ***
Dealt to gashpor [Kc 4d Qd] [5s]
Dealt to denny501 [7c Qh 9s] [6s]
Dealt to s0rrow [5d Ks 2h 9h Js] [4c]
Dealt to rdiezchang [3d 7s Jh] [5c]
123smoothie joins the table at seat #2
gashpor: checks
denny501: checks
s0rrow: checks
rdiezchang: bets $0.08
gashpor: folds
denny501: folds
s0rrow: folds
Uncalled bet ($0.08) returned to rdiezchang
rdiezchang collected $0.12 from pot
rdiezchang: doesn't show hand
*** SUMMARY ***
Total pot $0.12 | Rake $0
Seat 3: gashpor folded on the 6th Street
Seat 4: denny501 folded on the 6th Street
Seat 5: s0rrow folded on the 6th Street
Seat 8: rdiezchang collected ($0.12)
PokerStars Game #35874523510: 7 Card Stud Hi/Lo Limit ($0.04/$0.08 USD) - 2009/11/26 10:23:32 ET
Table 'Dawn II' 8-max
Seat 2: 123smoothie ($1.60 in chips)
Seat 3: gashpor ($1.43 in chips)
Seat 4: denny501 ($0.90 in chips)
Seat 5: s0rrow ($1.57 in chips)
Seat 7: Soroka69 ($1 in chips)
Seat 8: rdiezchang ($1.25 in chips)
123smoothie: posts the ante $0.01
gashpor: posts the ante $0.01
denny501: posts the ante $0.01
s0rrow: posts the ante $0.01
Soroka69: posts the ante $0.01
rdiezchang: posts the ante $0.01
*** 3rd STREET ***
Dealt to 123smoothie [9h]
Dealt to gashpor [4s]
Dealt to denny501 [Qs]
Dealt to s0rrow [Qd Js Kc]
Dealt to Soroka69 [6s]
Dealt to rdiezchang [8d]
poconoman was removed from the table for failing to post
gashpor: brings in for $0.02
TomSludge joins the table at seat #6
denny501: calls $0.02
s0rrow: folds
Soroka69: calls $0.02
rdiezchang: calls $0.02
u.pressure joins the table at seat #1
123smoothie: calls $0.02
*** 4th STREET ***
Dealt to 123smoothie [9h] [Ah]
Dealt to gashpor [4s] [6h]
Dealt to denny501 [Qs] [4d]
Dealt to Soroka69 [6s] [3c]
Dealt to rdiezchang [8d] [Ac]
123smoothie: checks
gashpor: checks
denny501: checks
Soroka69: checks
rdiezchang: checks
*** 5th STREET ***
Dealt to 123smoothie [9h Ah] [5d]
Dealt to gashpor [4s 6h] [8h]
Dealt to denny501 [Qs 4d] [Tc]
Dealt to Soroka69 [6s 3c] [6c]
Dealt to rdiezchang [8d Ac] [8c]
rdiezchang: bets $0.08
123smoothie: calls $0.08
gashpor: calls $0.08
denny501: folds
Soroka69: folds
*** 6th STREET ***
Dealt to 123smoothie [9h Ah 5d] [4c]
Dealt to gashpor [4s 6h 8h] [Qh]
Dealt to rdiezchang [8d Ac 8c] [Jd]
rdiezchang: bets $0.08
123smoothie: calls $0.08
gashpor: calls $0.08
*** RIVER ***
rdiezchang: bets $0.08
123smoothie: calls $0.08
gashpor: folds
*** SHOW DOWN ***
rdiezchang: shows [Ad 5s 8d Ac 8c Jd Th] (HI: two pair, Aces and Eights)
123smoothie: mucks hand
rdiezchang collected $0.77 from pot
No low hand qualified
*** SUMMARY ***
Total pot $0.80 | Rake $0.03
Seat 2: 123smoothie mucked [9c Jc 9h Ah 5d 4c Qc]
Seat 3: gashpor folded on the River
Seat 4: denny501 folded on the 5th Street
Seat 5: s0rrow folded on the 3rd Street (didn't bet)
Seat 7: Soroka69 folded on the 5th Street
Seat 8: rdiezchang showed [Ad 5s 8d Ac 8c Jd Th] and won ($0.77) with HI: two pair, Aces and Eights
PokerStars Game #35874576282: 7 Card Stud Hi/Lo Limit ($0.04/$0.08 USD) - 2009/11/26 10:24:59 ET
Table 'Dawn II' 8-max
Seat 1: u.pressure ($11 in chips)
Seat 2: 123smoothie ($1.33 in chips)
Seat 3: gashpor ($1.24 in chips)
Seat 4: denny501 ($0.87 in chips)
Seat 5: s0rrow ($1.56 in chips)
Seat 6: TomSludge ($1.60 in chips)
Seat 7: Soroka69 ($0.97 in chips)
Seat 8: rdiezchang ($1.75 in chips)
u.pressure: posts the ante $0.01
123smoothie: posts the ante $0.01
gashpor: posts the ante $0.01
denny501: posts the ante $0.01
s0rrow: posts the ante $0.01
TomSludge: posts the ante $0.01
Soroka69: posts the ante $0.01
rdiezchang: posts the ante $0.01
*** 3rd STREET ***
Dealt to u.pressure [Qs]
Dealt to 123smoothie [4h]
Dealt to gashpor [4c]
Dealt to denny501 [8s]
Dealt to s0rrow [Ah Kd 8d]
Dealt to TomSludge [Ks]
Dealt to Soroka69 [3h]
Dealt to rdiezchang [5s]
Soroka69: brings in for $0.02
rdiezchang: calls $0.02
u.pressure: calls $0.02
123smoothie: calls $0.02
gashpor: calls $0.02
denny501: folds
s0rrow: calls $0.02
TomSludge: folds
*** 4th STREET ***
Dealt to u.pressure [Qs] [Td]
Dealt to 123smoothie [4h] [9d]
Dealt to gashpor [4c] [Jc]
Dealt to s0rrow [Ah Kd 8d] [Kc]
Dealt to Soroka69 [3h] [Ad]
Dealt to rdiezchang [5s] [7c]
Soroka69: checks
rdiezchang: checks
u.pressure: checks
123smoothie: checks
gashpor: checks
s0rrow: checks
*** 5th STREET ***
Dealt to u.pressure [Qs Td] [Jh]
Dealt to 123smoothie [4h 9d] [2c]
Dealt to gashpor [4c Jc] [5h]
Dealt to s0rrow [Ah Kd 8d Kc] [2d]
Dealt to Soroka69 [3h Ad] [Qd]
Dealt to rdiezchang [5s 7c] [4d]
Soroka69: checks
rdiezchang: checks
u.pressure: checks
123smoothie: checks
gashpor: bets $0.08
s0rrow: folds
Soroka69: calls $0.08
rdiezchang: calls $0.08
u.pressure: calls $0.08
123smoothie: folds
*** 6th STREET ***
Dealt to u.pressure [Qs Td Jh] [6d]
Dealt to gashpor [4c Jc 5h] [7s]
Dealt to Soroka69 [3h Ad Qd] [9s]
Dealt to rdiezchang [5s 7c 4d] [Th]
Soroka69: checks
rdiezchang: checks
u.pressure: checks
gashpor: checks
*** RIVER ***
Soroka69: checks
rdiezchang: checks
u.pressure: checks
gashpor: bets $0.08
Soroka69: folds
rdiezchang: calls $0.08
u.pressure: calls $0.08
*** SHOW DOWN ***
gashpor: shows [7h 2h 4c Jc 5h 7s 8c] (HI: a pair of Sevens; LO: 8,7,5,4,2)
rdiezchang: shows [As Qh 5s 7c 4d Th Ac] (HI: a pair of Aces)
u.pressure: shows [Qc Kh Qs Td Jh 6d 6s] (HI: two pair, Queens and Sixes)
u.pressure collected $0.37 from pot
gashpor collected $0.36 from pot
*** SUMMARY ***
Total pot $0.76 | Rake $0.03
Seat 1: u.pressure showed [Qc Kh Qs Td Jh 6d 6s] and won ($0.37) with HI: two pair, Queens and Sixes
Seat 2: 123smoothie folded on the 5th Street
Seat 3: gashpor showed [7h 2h 4c Jc 5h 7s 8c] and won ($0.36) with HI: a pair of Sevens; LO: 8,7,5,4,2
Seat 4: denny501 folded on the 3rd Street (didn't bet)
Seat 5: s0rrow folded on the 5th Street
Seat 6: TomSludge folded on the 3rd Street (didn't bet)
Seat 7: Soroka69 folded on the River
Seat 8: rdiezchang showed [As Qh 5s 7c 4d Th Ac] and lost with HI: a pair of Aces
PokerStars Game #35874635170: 7 Card Stud Hi/Lo Limit ($0.04/$0.08 USD) - 2009/11/26 10:26:37 ET
Table 'Dawn II' 8-max
Seat 1: u.pressure ($11.18 in chips)
Seat 2: 123smoothie ($1.30 in chips)
Seat 3: gashpor ($1.41 in chips)
Seat 4: denny501 ($0.86 in chips)
Seat 5: s0rrow ($1.53 in chips)
Seat 6: TomSludge ($1.59 in chips)
Seat 7: Soroka69 ($0.86 in chips)
Seat 8: rdiezchang ($1.56 in chips)
u.pressure: posts the ante $0.01
123smoothie: posts the ante $0.01
gashpor: posts the ante $0.01
denny501: posts the ante $0.01
s0rrow: posts the ante $0.01
TomSludge: posts the ante $0.01
Soroka69: posts the ante $0.01
rdiezchang: posts the ante $0.01
*** 3rd STREET ***
Dealt to u.pressure [8c]
Dealt to 123smoothie [2c]
Dealt to gashpor [Qd]
Dealt to denny501 [9d]
Dealt to s0rrow [Ts 5c Js]
Dealt to TomSludge [3h]
Dealt to Soroka69 [7s]
Dealt to rdiezchang [6c]
123smoothie: brings in for $0.02
gashpor: folds
denny501: calls $0.02
s0rrow: folds
TomSludge: folds
Soroka69: calls $0.02
rdiezchang: calls $0.02
u.pressure: folds
*** 4th STREET ***
Dealt to 123smoothie [2c] [8d]
Dealt to denny501 [9d] [3d]
Dealt to Soroka69 [7s] [Th]
Dealt to rdiezchang [6c] [Ac]
rdiezchang: bets $0.04
123smoothie: calls $0.04
denny501: calls $0.04
Soroka69: folds
*** 5th STREET ***
Dealt to 123smoothie [2c 8d] [3c]
Dealt to denny501 [9d 3d] [As]
Dealt to rdiezchang [6c Ac] [6s]
rdiezchang: bets $0.08
123smoothie: calls $0.08
denny501: calls $0.08
*** 6th STREET ***
Dealt to 123smoothie [2c 8d 3c] [3s]
Dealt to denny501 [9d 3d As] [Kc]
Dealt to rdiezchang [6c Ac 6s] [Qc]
rdiezchang: bets $0.08
123smoothie: calls $0.08
denny501: folds
*** RIVER ***
rdiezchang: bets $0.08
123smoothie: calls $0.08
*** SHOW DOWN ***
rdiezchang: shows [8s 7c 6c Ac 6s Qc Qs] (HI: two pair, Queens and Sixes)
123smoothie: mucks hand
rdiezchang collected $0.80 from pot
No low hand qualified
*** SUMMARY ***
Total pot $0.84 | Rake $0.04
Seat 1: u.pressure folded on the 3rd Street (didn't bet)
Seat 2: 123smoothie mucked [2d 7d 2c 8d 3c 3s Tc]
Seat 3: gashpor folded on the 3rd Street (didn't bet)
Seat 4: denny501 folded on the 6th Street
Seat 5: s0rrow folded on the 3rd Street (didn't bet)
Seat 6: TomSludge folded on the 3rd Street (didn't bet)
Seat 7: Soroka69 folded on the 4th Street
Seat 8: rdiezchang showed [8s 7c 6c Ac 6s Qc Qs] and won ($0.80) with HI: two pair, Queens and Sixes
PokerStars Game #35874676388: 7 Card Stud Hi/Lo Limit ($0.04/$0.08 USD) - 2009/11/26 10:27:46 ET
Table 'Dawn II' 8-max
Seat 1: u.pressure ($11.17 in chips)
Seat 2: 123smoothie ($0.99 in chips)
Seat 3: gashpor ($1.40 in chips)
Seat 4: denny501 ($0.71 in chips)
Seat 5: s0rrow ($1.52 in chips)
Seat 6: TomSludge ($1.58 in chips)
Seat 7: Soroka69 ($0.83 in chips)
Seat 8: rdiezchang ($2.05 in chips)
u.pressure: posts the ante $0.01
123smoothie: posts the ante $0.01
gashpor: posts the ante $0.01
denny501: posts the ante $0.01
s0rrow: posts the ante $0.01
TomSludge: posts the ante $0.01
Soroka69: posts the ante $0.01
rdiezchang: posts the ante $0.01
*** 3rd STREET ***
Dealt to u.pressure [Td]
Dealt to 123smoothie [4c]
Dealt to gashpor [5d]
Dealt to denny501 [2c]
Dealt to s0rrow [7c 3s 5h]
Dealt to TomSludge [8s]
Dealt to Soroka69 [7d]
Dealt to rdiezchang [Ad]
denny501: brings in for $0.02
s0rrow: calls $0.02
TomSludge: folds
Soroka69: calls $0.02
rdiezchang: calls $0.02
u.pressure: folds
123smoothie: calls $0.02
gashpor: calls $0.02
*** 4th STREET ***
Dealt to 123smoothie [4c] [3c]
Dealt to gashpor [5d] [Qd]
Dealt to denny501 [2c] [7s]
Dealt to s0rrow [7c 3s 5h] [Qc]
Dealt to Soroka69 [7d] [5s]
Dealt to rdiezchang [Ad] [Js]
rdiezchang: checks
123smoothie: checks
gashpor: checks
denny501: folds
denny501 leaves the table
s0rrow: checks
Soroka69: checks
*** 5th STREET ***
Dealt to 123smoothie [4c 3c] [9s]
Dealt to gashpor [5d Qd] [Jd]
Dealt to s0rrow [7c 3s 5h Qc] [Kc]
Dealt to Soroka69 [7d 5s] [5c]
Dealt to rdiezchang [Ad Js] [Ts]
LainaRahat joins the table at seat #4
Soroka69: checks
rdiezchang: checks
123smoothie: checks
gashpor: bets $0.08
s0rrow: calls $0.08
Soroka69: calls $0.08
rdiezchang: folds
123smoothie: folds
*** 6th STREET ***
Dealt to gashpor [5d Qd Jd] [9d]
Dealt to s0rrow [7c 3s 5h Qc Kc] [6d]
Dealt to Soroka69 [7d 5s 5c] [2s]
Soroka69: checks
gashpor: bets $0.08
s0rrow: calls $0.08
Soroka69: calls $0.08
*** RIVER ***
Dealt to s0rrow [7c 3s 5h Qc Kc 6d] [4d]
Soroka69: checks
gashpor: bets $0.08
s0rrow: calls $0.08
Soroka69: folds
*** SHOW DOWN ***
gashpor: shows [4h 3d 5d Qd Jd 9d 6h] (HI: a flush, Queen high)
s0rrow: shows [7c 3s 5h Qc Kc 6d 4d] (HI: a straight, Three to Seven; LO: 7,6,5,4,3)
gashpor collected $0.40 from pot
s0rrow collected $0.40 from pot
*** SUMMARY ***
Total pot $0.84 | Rake $0.04
Seat 1: u.pressure folded on the 3rd Street (didn't bet)
Seat 2: 123smoothie folded on the 5th Street
Seat 3: gashpor showed [4h 3d 5d Qd Jd 9d 6h] and won ($0.40) with HI: a flush, Queen high
Seat 4: denny501 folded on the 4th Street
Seat 5: s0rrow showed [7c 3s 5h Qc Kc 6d 4d] and won ($0.40) with HI: a straight, Three to Seven; LO: 7,6,5,4,3
Seat 6: TomSludge folded on the 3rd Street (didn't bet)
Seat 7: Soroka69 folded on the River
Seat 8: rdiezchang folded on the 5th Street
PokerStars Game #35874733203: 7 Card Stud Hi/Lo Limit ($0.04/$0.08 USD) - 2009/11/26 10:29:22 ET
Table 'Dawn II' 8-max
Seat 1: u.pressure ($11.16 in chips)
Seat 2: 123smoothie ($0.96 in chips)
Seat 3: gashpor ($1.53 in chips)
Seat 4: LainaRahat ($2 in chips)
Seat 5: s0rrow ($1.65 in chips)
Seat 6: TomSludge ($1.57 in chips)
Seat 7: Soroka69 ($0.64 in chips)
Seat 8: rdiezchang ($2.02 in chips)
u.pressure: posts the ante $0.01
123smoothie: posts the ante $0.01
gashpor: posts the ante $0.01
LainaRahat: posts the ante $0.01
s0rrow: posts the ante $0.01
TomSludge: posts the ante $0.01
Soroka69: posts the ante $0.01
rdiezchang: posts the ante $0.01
*** 3rd STREET ***
Dealt to u.pressure [Js]
Dealt to 123smoothie [Kc]
Dealt to gashpor [Kd]
Dealt to LainaRahat [Ts]
Dealt to s0rrow [Qd Ad 2s]
Dealt to TomSludge [4h]
Dealt to Soroka69 [3c]
Dealt to rdiezchang [3h]
s0rrow: brings in for $0.02
TomSludge: folds
Soroka69: calls $0.02
rdiezchang: folds
u.pressure: folds
123smoothie: calls $0.02
gashpor: folds
LainaRahat: calls $0.02
*** 4th STREET ***
Dealt to 123smoothie [Kc] [7d]
Dealt to LainaRahat [Ts] [4c]
Dealt to s0rrow [Qd Ad 2s] [As]
Dealt to Soroka69 [3c] [Qc]
rdiezchang leaves the table
s0rrow: bets $0.04
Soroka69: raises $0.04 to $0.08
geo_441 joins the table at seat #8
123smoothie: folds
LainaRahat: calls $0.08
s0rrow: calls $0.04
*** 5th STREET ***
Dealt to LainaRahat [Ts 4c] [Ks]
Dealt to s0rrow [Qd Ad 2s As] [2h]
Dealt to Soroka69 [3c Qc] [6h]
s0rrow: checks
Soroka69: bets $0.08
LainaRahat: calls $0.08
s0rrow: calls $0.08
*** 6th STREET ***
Dealt to LainaRahat [Ts 4c Ks] [Tc]
Dealt to s0rrow [Qd Ad 2s As 2h] [8d]
Dealt to Soroka69 [3c Qc 6h] [7h]
LainaRahat: checks
s0rrow: checks
Soroka69: checks
*** RIVER ***
Dealt to s0rrow [Qd Ad 2s As 2h 8d] [6c]
LainaRahat: checks
s0rrow: checks
Soroka69: checks
*** SHOW DOWN ***
LainaRahat: shows [Ac 3s Ts 4c Ks Tc Kh] (HI: two pair, Kings and Tens)
s0rrow: shows [Qd Ad 2s As 2h 8d 6c] (HI: two pair, Aces and Deuces)
Soroka69: mucks hand
s0rrow collected $0.61 from pot
No low hand qualified
*** SUMMARY ***
Total pot $0.64 | Rake $0.03
Seat 1: u.pressure folded on the 3rd Street (didn't bet)
Seat 2: 123smoothie folded on the 4th Street
Seat 3: gashpor folded on the 3rd Street (didn't bet)
Seat 4: LainaRahat showed [Ac 3s Ts 4c Ks Tc Kh] and lost with HI: two pair, Kings and Tens
Seat 5: s0rrow showed [Qd Ad 2s As 2h 8d 6c] and won ($0.61) with HI: two pair, Aces and Deuces
Seat 6: TomSludge folded on the 3rd Street (didn't bet)
Seat 7: Soroka69 mucked [2d Qh 3c Qc 6h 7h Jd]
Seat 8: rdiezchang folded on the 3rd Street (didn't bet)
PokerStars Game #35874789183: 7 Card Stud Hi/Lo Limit ($0.04/$0.08 USD) - 2009/11/26 10:30:56 ET
Table 'Dawn II' 8-max
Seat 1: u.pressure ($11.15 in chips)
Seat 2: 123smoothie ($0.93 in chips)
Seat 3: gashpor ($1.52 in chips)
Seat 4: LainaRahat ($1.81 in chips)
Seat 5: s0rrow ($2.07 in chips)
Seat 6: TomSludge ($1.56 in chips)
Seat 7: Soroka69 ($0.45 in chips)
Seat 8: geo_441 ($1.60 in chips)
u.pressure: posts the ante $0.01
123smoothie: posts the ante $0.01
gashpor: posts the ante $0.01
LainaRahat: posts the ante $0.01
s0rrow: posts the ante $0.01
TomSludge: posts the ante $0.01
Soroka69: posts the ante $0.01
geo_441: posts the ante $0.01
*** 3rd STREET ***
Dealt to u.pressure [5c]
Dealt to 123smoothie [8c]
Dealt to gashpor [5s]
Dealt to LainaRahat [2c]
Dealt to s0rrow [8d Qs Kc]
Dealt to TomSludge [As]
Dealt to Soroka69 [Tc]
Dealt to geo_441 [4d]
LainaRahat: brings in for $0.02
s0rrow: folds
TomSludge: calls $0.02
Soroka69: calls $0.02
geo_441: calls $0.02
u.pressure: folds
123smoothie: calls $0.02
gashpor: calls $0.02
*** 4th STREET ***
Dealt to 123smoothie [8c] [9d]
Dealt to gashpor [5s] [5d]
Dealt to LainaRahat [2c] [2d]
Dealt to TomSludge [As] [8h]
Dealt to Soroka69 [Tc] [2h]
Dealt to geo_441 [4d] [3s]
gashpor: checks
LainaRahat: checks
TomSludge: bets $0.04
Soroka69: calls $0.04
geo_441: calls $0.04
123smoothie: calls $0.04
gashpor: calls $0.04
LainaRahat: folds
*** 5th STREET ***
Dealt to 123smoothie [8c 9d] [Jd]
Dealt to gashpor [5s 5d] [Td]
Dealt to TomSludge [As 8h] [Js]
Dealt to Soroka69 [Tc 2h] [Qc]
Dealt to geo_441 [4d 3s] [7c]
gashpor: checks
TomSludge: checks
Soroka69: bets $0.08
geo_441: calls $0.08
123smoothie: calls $0.08
gashpor: calls $0.08
TomSludge: calls $0.08
*** 6th STREET ***
Dealt to 123smoothie [8c 9d Jd] [3c]
Dealt to gashpor [5s 5d Td] [9h]
Dealt to TomSludge [As 8h Js] [6c]
Dealt to Soroka69 [Tc 2h Qc] [5h]
Dealt to geo_441 [4d 3s 7c] [Jh]
gashpor: checks
TomSludge: checks
Soroka69: bets $0.08
geo_441: calls $0.08
123smoothie: calls $0.08
gashpor: calls $0.08
TomSludge: calls $0.08
*** RIVER ***
gashpor: checks
TomSludge: checks
Soroka69: checks
geo_441: checks
123smoothie: bets $0.08
gashpor: calls $0.08
TomSludge: calls $0.08
Soroka69: calls $0.08
geo_441: folds
*** SHOW DOWN ***
123smoothie: shows [Qd Ks 8c 9d Jd 3c 9c] (HI: a pair of Nines)
gashpor: shows [4c Th 5s 5d Td 9h Ad] (HI: two pair, Tens and Fives)
TomSludge: shows [7s Ah As 8h Js 6c Jc] (HI: two pair, Aces and Jacks)
Soroka69: mucks hand
TomSludge collected $1.45 from pot
No low hand qualified
*** SUMMARY ***
Total pot $1.52 | Rake $0.07
Seat 1: u.pressure folded on the 3rd Street (didn't bet)
Seat 2: 123smoothie showed [Qd Ks 8c 9d Jd 3c 9c] and lost with HI: a pair of Nines
Seat 3: gashpor showed [4c Th 5s 5d Td 9h Ad] and lost with HI: two pair, Tens and Fives
Seat 4: LainaRahat folded on the 4th Street
Seat 5: s0rrow folded on the 3rd Street (didn't bet)
Seat 6: TomSludge showed [7s Ah As 8h Js 6c Jc] and won ($1.45) with HI: two pair, Aces and Jacks
Seat 7: Soroka69 mucked [Qh Ts Tc 2h Qc 5h 6s]
Seat 8: geo_441 folded on the River

View File

@ -0,0 +1,574 @@
PokerStars Game #35874566077: Razz Limit ($0.04/$0.08 USD) - 2009/11/26 10:24:42 ET
Table 'Gotha II' 8-max
Seat 1: kobreli ($1.33 in chips)
Seat 3: willy32948 ($2.17 in chips)
Seat 5: meg100 ($1.71 in chips)
Seat 7: s0rrow ($1.60 in chips)
Seat 8: SilkZone ($1.65 in chips)
kobreli: posts the ante $0.01
willy32948: posts the ante $0.01
meg100: posts the ante $0.01
s0rrow: posts the ante $0.01
SilkZone: posts the ante $0.01
*** 3rd STREET ***
Dealt to kobreli [Qc]
Dealt to willy32948 [6h]
Dealt to meg100 [3s]
Dealt to s0rrow [Td 2s 9s]
Dealt to SilkZone [3h]
kobreli: brings in for $0.02
willy32948: calls $0.02
meg100: calls $0.02
s0rrow: folds
SilkZone: calls $0.02
*** 4th STREET ***
Dealt to kobreli [Qc] [8s]
Dealt to willy32948 [6h] [7h]
Dealt to meg100 [3s] [Js]
Dealt to SilkZone [3h] [3d]
kurczakkr2 is disconnected
willy32948: bets $0.04
meg100: calls $0.04
SilkZone: calls $0.04
kobreli: folds
*** 5th STREET ***
Dealt to willy32948 [6h 7h] [7s]
Dealt to meg100 [3s Js] [Kh]
Dealt to SilkZone [3h 3d] [4h]
meg100: checks
SilkZone: bets $0.08
willy32948: calls $0.08
meg100: folds
*** 6th STREET ***
Dealt to willy32948 [6h 7h 7s] [Jh]
Dealt to SilkZone [3h 3d 4h] [9c]
SilkZone: bets $0.08
willy32948: folds
Uncalled bet ($0.08) returned to SilkZone
willy32948 leaves the table
SilkZone collected $0.39 from pot
*** SUMMARY ***
Total pot $0.41 | Rake $0.02
Seat 1: kobreli folded on the 4th Street
Seat 3: willy32948 folded on the 6th Street
Seat 5: meg100 folded on the 5th Street
Seat 7: s0rrow folded on the 3rd Street (didn't bet)
Seat 8: SilkZone collected ($0.39)
PokerStars Game #35874590575: Razz Limit ($0.04/$0.08 USD) - 2009/11/26 10:25:23 ET
Table 'Gotha II' 8-max
Seat 1: kobreli ($1.30 in chips)
Seat 5: meg100 ($1.64 in chips)
Seat 7: s0rrow ($1.59 in chips)
Seat 8: SilkZone ($1.89 in chips)
kobreli: posts the ante $0.01
meg100: posts the ante $0.01
s0rrow: posts the ante $0.01
SilkZone: posts the ante $0.01
*** 3rd STREET ***
Dealt to kobreli [3h]
Dealt to meg100 [6s]
Dealt to s0rrow [4c 2h 8h]
Dealt to SilkZone [Jc]
SilkZone: brings in for $0.02
kobreli: calls $0.02
meg100: calls $0.02
s0rrow: calls $0.02
*** 4th STREET ***
Dealt to kobreli [3h] [Ks]
Dealt to meg100 [6s] [2d]
Dealt to s0rrow [4c 2h 8h] [7c]
Dealt to SilkZone [Jc] [3c]
meg100: checks
s0rrow: bets $0.04
SilkZone: calls $0.04
kobreli: folds
meg100: calls $0.04
*** 5th STREET ***
Dealt to meg100 [6s 2d] [5d]
Dealt to s0rrow [4c 2h 8h 7c] [Ah]
Dealt to SilkZone [Jc 3c] [8c]
meg100: checks
s0rrow: bets $0.08
SilkZone: calls $0.08
meg100: calls $0.08
*** 6th STREET ***
Dealt to meg100 [6s 2d 5d] [Qs]
Dealt to s0rrow [4c 2h 8h 7c Ah] [2s]
Dealt to SilkZone [Jc 3c 8c] [Kh]
s0rrow: checks
SilkZone: checks
meg100: checks
*** RIVER ***
Dealt to s0rrow [4c 2h 8h 7c Ah 2s] [5h]
s0rrow: bets $0.08
HIWAII2 joins the table at seat #6
SilkZone: folds
meg100: folds
Uncalled bet ($0.08) returned to s0rrow
s0rrow collected $0.46 from pot
*** SUMMARY ***
Total pot $0.48 | Rake $0.02
Seat 1: kobreli folded on the 4th Street
Seat 5: meg100 folded on the River
Seat 7: s0rrow collected ($0.46)
Seat 8: SilkZone folded on the River
PokerStars Game #35874623967: Razz Limit ($0.04/$0.08 USD) - 2009/11/26 10:26:19 ET
Table 'Gotha II' 8-max
Seat 1: kobreli ($1.27 in chips)
Seat 5: meg100 ($1.49 in chips)
Seat 6: HIWAII2 ($1.13 in chips)
Seat 7: s0rrow ($1.90 in chips)
Seat 8: SilkZone ($1.74 in chips)
kobreli: posts the ante $0.01
meg100: posts the ante $0.01
HIWAII2: posts the ante $0.01
s0rrow: posts the ante $0.01
SilkZone: posts the ante $0.01
*** 3rd STREET ***
Dealt to kobreli [8c]
Dealt to meg100 [7h]
Dealt to HIWAII2 [Kh]
Dealt to s0rrow [9h 2s 7c]
Dealt to SilkZone [6s]
HIWAII2: brings in for $0.02
manga130 joins the table at seat #3
s0rrow: calls $0.02
SilkZone: calls $0.02
kobreli: calls $0.02
meg100: calls $0.02
*** 4th STREET ***
Dealt to kobreli [8c] [8s]
Dealt to meg100 [7h] [As]
Dealt to HIWAII2 [Kh] [6h]
Dealt to s0rrow [9h 2s 7c] [6c]
Dealt to SilkZone [6s] [9c]
meg100: checks
HIWAII2: checks
s0rrow: checks
SilkZone: checks
kobreli: checks
*** 5th STREET ***
Dealt to kobreli [8c 8s] [3c]
Dealt to meg100 [7h As] [5d]
Dealt to HIWAII2 [Kh 6h] [3d]
Dealt to s0rrow [9h 2s 7c 6c] [Qh]
Dealt to SilkZone [6s 9c] [Qs]
meg100: checks
HIWAII2: bets $0.08
s0rrow: calls $0.08
SilkZone: folds
kobreli: folds
meg100: calls $0.08
*** 6th STREET ***
Dealt to meg100 [7h As 5d] [5c]
Dealt to HIWAII2 [Kh 6h 3d] [6d]
Dealt to s0rrow [9h 2s 7c 6c Qh] [Ad]
s0rrow: checks
meg100: checks
HIWAII2: checks
*** RIVER ***
Dealt to s0rrow [9h 2s 7c 6c Qh Ad] [Ac]
s0rrow: bets $0.08
meg100: folds
HIWAII2: raises $0.08 to $0.16
s0rrow: calls $0.08
*** SHOW DOWN ***
HIWAII2: shows [2h 8d Kh 6h 3d 6d 4h] (Lo: 8,6,4,3,2)
s0rrow: mucks hand
HIWAII2 collected $0.68 from pot
*** SUMMARY ***
Total pot $0.71 | Rake $0.03
Seat 1: kobreli folded on the 5th Street
Seat 5: meg100 folded on the River
Seat 6: HIWAII2 showed [2h 8d Kh 6h 3d 6d 4h] and won ($0.68) with Lo: 8,6,4,3,2
Seat 7: s0rrow mucked [9h 2s 7c 6c Qh Ad Ac]
Seat 8: SilkZone folded on the 5th Street
PokerStars Game #35874664176: Razz Limit ($0.04/$0.08 USD) - 2009/11/26 10:27:26 ET
Table 'Gotha II' 8-max
Seat 1: kobreli ($1.24 in chips)
Seat 3: manga130 ($0.68 in chips)
Seat 5: meg100 ($1.38 in chips)
Seat 6: HIWAII2 ($1.54 in chips)
Seat 7: s0rrow ($1.63 in chips)
Seat 8: SilkZone ($1.71 in chips)
kobreli: posts the ante $0.01
manga130: posts the ante $0.01
meg100: posts the ante $0.01
HIWAII2: posts the ante $0.01
s0rrow: posts the ante $0.01
SilkZone: posts the ante $0.01
*** 3rd STREET ***
Dealt to kobreli [Kd]
Dealt to manga130 [Td]
Dealt to meg100 [Qh]
Dealt to HIWAII2 [5h]
Dealt to s0rrow [9s Qd 2s]
Dealt to SilkZone [As]
kobreli: brings in for $0.02
manga130: folds
meg100: folds
HIWAII2: calls $0.02
s0rrow: folds
SilkZone: calls $0.02
*** 4th STREET ***
Dealt to kobreli [Kd] [4s]
Dealt to HIWAII2 [5h] [4h]
Dealt to SilkZone [As] [Ah]
HIWAII2: bets $0.04
SilkZone: folds
kobreli: folds
Uncalled bet ($0.04) returned to HIWAII2
HIWAII2 collected $0.12 from pot
HIWAII2: shows [3d 3s 5h 4h] (Lo: 3,3,5,4)
*** SUMMARY ***
Total pot $0.12 | Rake $0
Seat 1: kobreli folded on the 4th Street
Seat 3: manga130 folded on the 3rd Street (didn't bet)
Seat 5: meg100 folded on the 3rd Street (didn't bet)
Seat 6: HIWAII2 collected ($0.12)
Seat 7: s0rrow folded on the 3rd Street (didn't bet)
Seat 8: SilkZone folded on the 4th Street
PokerStars Game #35874682808: Razz Limit ($0.04/$0.08 USD) - 2009/11/26 10:27:57 ET
Table 'Gotha II' 8-max
Seat 1: kobreli ($1.21 in chips)
Seat 3: manga130 ($0.67 in chips)
Seat 5: meg100 ($1.37 in chips)
Seat 6: HIWAII2 ($1.63 in chips)
Seat 7: s0rrow ($1.62 in chips)
Seat 8: SilkZone ($1.68 in chips)
kobreli: posts the ante $0.01
manga130: posts the ante $0.01
meg100: posts the ante $0.01
HIWAII2: posts the ante $0.01
s0rrow: posts the ante $0.01
SilkZone: posts the ante $0.01
*** 3rd STREET ***
Dealt to kobreli [Tc]
Dealt to manga130 [Qd]
Dealt to meg100 [9h]
Dealt to HIWAII2 [5s]
Dealt to s0rrow [7h 9c Th]
Dealt to SilkZone [Kh]
SilkZone: brings in for $0.02
kobreli: folds
manga130: calls $0.02
meg100: calls $0.02
HIWAII2: calls $0.02
s0rrow: folds
*** 4th STREET ***
Dealt to manga130 [Qd] [8s]
Dealt to meg100 [9h] [Kd]
Dealt to HIWAII2 [5s] [6s]
Dealt to SilkZone [Kh] [2d]
HIWAII2: bets $0.04
SilkZone: raises $0.04 to $0.08
manga130: calls $0.08
meg100: folds
HIWAII2: calls $0.04
*** 5th STREET ***
Dealt to manga130 [Qd 8s] [3h]
Dealt to HIWAII2 [5s 6s] [4s]
Dealt to SilkZone [Kh 2d] [Js]
HIWAII2: bets $0.08
SilkZone: calls $0.08
manga130: calls $0.08
*** 6th STREET ***
Dealt to manga130 [Qd 8s 3h] [Ks]
Dealt to HIWAII2 [5s 6s 4s] [Qs]
Dealt to SilkZone [Kh 2d Js] [6c]
HIWAII2: bets $0.08
SilkZone: calls $0.08
manga130: calls $0.08
*** RIVER ***
HIWAII2: bets $0.08
SilkZone: raises $0.08 to $0.16
manga130: folds
HIWAII2: folds
Uncalled bet ($0.08) returned to SilkZone
SilkZone collected $0.98 from pot
*** SUMMARY ***
Total pot $1.02 | Rake $0.04
Seat 1: kobreli folded on the 3rd Street (didn't bet)
Seat 3: manga130 folded on the River
Seat 5: meg100 folded on the 4th Street
Seat 6: HIWAII2 folded on the River
Seat 7: s0rrow folded on the 3rd Street (didn't bet)
Seat 8: SilkZone collected ($0.98)
PokerStars Game #35874721245: Razz Limit ($0.04/$0.08 USD) - 2009/11/26 10:29:02 ET
Table 'Gotha II' 8-max
Seat 1: kobreli ($1.20 in chips)
Seat 3: manga130 ($0.40 in chips)
Seat 5: meg100 ($1.34 in chips)
Seat 6: HIWAII2 ($1.28 in chips)
Seat 7: s0rrow ($1.61 in chips)
Seat 8: SilkZone ($2.31 in chips)
kobreli: posts the ante $0.01
manga130: posts the ante $0.01
meg100: posts the ante $0.01
HIWAII2: posts the ante $0.01
s0rrow: posts the ante $0.01
SilkZone: posts the ante $0.01
*** 3rd STREET ***
Dealt to kobreli [3d]
Dealt to manga130 [Qc]
Dealt to meg100 [Qd]
Dealt to HIWAII2 [Js]
Dealt to s0rrow [Th Ah Qh]
Dealt to SilkZone [9d]
s0rrow: brings in for $0.02
SilkZone: calls $0.02
kobreli: calls $0.02
manga130: calls $0.02
meg100: folds
HIWAII2: folds
*** 4th STREET ***
Dealt to kobreli [3d] [Ad]
Dealt to manga130 [Qc] [6d]
Dealt to s0rrow [Th Ah Qh] [8s]
Dealt to SilkZone [9d] [7c]
kobreli: bets $0.04
manga130: folds
s0rrow: folds
SilkZone: raises $0.04 to $0.08
kobreli: raises $0.04 to $0.12
SilkZone: calls $0.04
*** 5th STREET ***
Dealt to kobreli [3d Ad] [Ac]
Dealt to SilkZone [9d 7c] [Ts]
SilkZone: checks
kobreli: bets $0.08
SilkZone: calls $0.08
*** 6th STREET ***
Dealt to kobreli [3d Ad Ac] [Kh]
Dealt to SilkZone [9d 7c Ts] [5s]
SilkZone: bets $0.08
kobreli: calls $0.08
*** RIVER ***
SilkZone: checks
kobreli: checks
*** SHOW DOWN ***
kobreli: shows [6h 8h 3d Ad Ac Kh 8c] (Lo: K,8,6,3,A)
SilkZone: shows [2d 4s 9d 7c Ts 5s Tc] (Lo: 9,7,5,4,2)
SilkZone collected $0.67 from pot
*** SUMMARY ***
Total pot $0.70 | Rake $0.03
Seat 1: kobreli showed [6h 8h 3d Ad Ac Kh 8c] and lost with Lo: K,8,6,3,A
Seat 3: manga130 folded on the 4th Street
Seat 5: meg100 folded on the 3rd Street (didn't bet)
Seat 6: HIWAII2 folded on the 3rd Street (didn't bet)
Seat 7: s0rrow folded on the 4th Street
Seat 8: SilkZone showed [2d 4s 9d 7c Ts 5s Tc] and won ($0.67) with Lo: 9,7,5,4,2
PokerStars Game #35874756552: Razz Limit ($0.04/$0.08 USD) - 2009/11/26 10:30:02 ET
Table 'Gotha II' 8-max
Seat 1: kobreli ($0.89 in chips)
Seat 3: manga130 ($0.37 in chips)
Seat 5: meg100 ($1.33 in chips)
Seat 6: HIWAII2 ($1.27 in chips)
Seat 7: s0rrow ($1.58 in chips)
Seat 8: SilkZone ($2.67 in chips)
kobreli: posts the ante $0.01
manga130: posts the ante $0.01
meg100: posts the ante $0.01
HIWAII2: posts the ante $0.01
s0rrow: posts the ante $0.01
SilkZone: posts the ante $0.01
*** 3rd STREET ***
Dealt to kobreli [4s]
Dealt to manga130 [5h]
Dealt to meg100 [3h]
Dealt to HIWAII2 [Qh]
Dealt to s0rrow [Kd Ad 7d]
Dealt to SilkZone [9d]
kobreli said, "this.is.lucky"
HIWAII2: brings in for $0.02
s0rrow: folds
SilkZone: folds
kobreli: calls $0.02
manga130: folds
meg100: calls $0.02
*** 4th STREET ***
Dealt to kobreli [4s] [Tc]
Dealt to meg100 [3h] [2s]
Dealt to HIWAII2 [Qh] [7s]
meg100: bets $0.04
HIWAII2: folds
kobreli: calls $0.04
*** 5th STREET ***
Dealt to kobreli [4s Tc] [8d]
Dealt to meg100 [3h 2s] [Jh]
kobreli: bets $0.08
meg100: folds
Uncalled bet ($0.08) returned to kobreli
kobreli collected $0.19 from pot
kobreli: doesn't show hand
*** SUMMARY ***
Total pot $0.20 | Rake $0.01
Seat 1: kobreli collected ($0.19)
Seat 3: manga130 folded on the 3rd Street (didn't bet)
Seat 5: meg100 folded on the 5th Street
Seat 6: HIWAII2 folded on the 4th Street
Seat 7: s0rrow folded on the 3rd Street (didn't bet)
Seat 8: SilkZone folded on the 3rd Street (didn't bet)
PokerStars Game #35874780027: Razz Limit ($0.04/$0.08 USD) - 2009/11/26 10:30:41 ET
Table 'Gotha II' 8-max
Seat 1: kobreli ($1.01 in chips)
Seat 3: manga130 ($0.36 in chips)
Seat 5: meg100 ($1.26 in chips)
Seat 6: HIWAII2 ($1.24 in chips)
Seat 7: s0rrow ($1.57 in chips)
Seat 8: SilkZone ($2.66 in chips)
kobreli: posts the ante $0.01
manga130: posts the ante $0.01
meg100: posts the ante $0.01
HIWAII2: posts the ante $0.01
s0rrow: posts the ante $0.01
SilkZone: posts the ante $0.01
*** 3rd STREET ***
Dealt to kobreli [6s]
Dealt to manga130 [9d]
Dealt to meg100 [5c]
Dealt to HIWAII2 [Qs]
Dealt to s0rrow [6d 9c 3d]
Dealt to SilkZone [Qc]
HIWAII2: brings in for $0.02
s0rrow: raises $0.02 to $0.04
SilkZone: calls $0.04
kobreli: calls $0.04
manga130: folds
meg100: calls $0.04
HIWAII2: folds
*** 4th STREET ***
Dealt to kobreli [6s] [7h]
Dealt to meg100 [5c] [5h]
Dealt to s0rrow [6d 9c 3d] [8s]
Dealt to SilkZone [Qc] [2c]
kobreli: bets $0.04
meg100: folds
s0rrow: raises $0.04 to $0.08
SilkZone: raises $0.04 to $0.12
kobreli: calls $0.08
s0rrow: calls $0.04
*** 5th STREET ***
Dealt to kobreli [6s 7h] [2h]
Dealt to s0rrow [6d 9c 3d 8s] [Jh]
Dealt to SilkZone [Qc 2c] [7c]
kobreli: bets $0.08
s0rrow: folds
SilkZone: calls $0.08
*** 6th STREET ***
Dealt to kobreli [6s 7h 2h] [3h]
Dealt to SilkZone [Qc 2c 7c] [Kd]
kobreli: bets $0.08
SilkZone: calls $0.08
*** RIVER ***
kobreli: bets $0.08
SilkZone: raises $0.08 to $0.16
kobreli: raises $0.08 to $0.24
SilkZone: raises $0.08 to $0.32
Betting is capped
kobreli: calls $0.08
*** SHOW DOWN ***
SilkZone: shows [3s 5d Qc 2c 7c Kd As] (Lo: 7,5,3,2,A)
kobreli: shows [Ac Qd 6s 7h 2h 3h 4c] (Lo: 6,4,3,2,A)
kobreli collected $1.49 from pot
*** SUMMARY ***
Total pot $1.56 | Rake $0.07
Seat 1: kobreli showed [Ac Qd 6s 7h 2h 3h 4c] and won ($1.49) with Lo: 6,4,3,2,A
Seat 3: manga130 folded on the 3rd Street (didn't bet)
Seat 5: meg100 folded on the 4th Street
Seat 6: HIWAII2 folded on the 3rd Street
Seat 7: s0rrow folded on the 5th Street
Seat 8: SilkZone showed [3s 5d Qc 2c 7c Kd As] and lost with Lo: 7,5,3,2,A
PokerStars Game #35874817957: Razz Limit ($0.04/$0.08 USD) - 2009/11/26 10:31:45 ET
Table 'Gotha II' 8-max
Seat 1: kobreli ($1.85 in chips)
Seat 3: manga130 ($0.35 in chips)
Seat 5: meg100 ($1.21 in chips)
Seat 6: HIWAII2 ($1.21 in chips)
Seat 7: s0rrow ($1.40 in chips)
Seat 8: SilkZone ($2.01 in chips)
kobreli: posts the ante $0.01
manga130: posts the ante $0.01
meg100: posts the ante $0.01
HIWAII2: posts the ante $0.01
s0rrow: posts the ante $0.01
SilkZone: posts the ante $0.01
*** 3rd STREET ***
Dealt to kobreli [As]
Dealt to manga130 [Ac]
Dealt to meg100 [Ah]
Dealt to HIWAII2 [Jd]
Dealt to s0rrow [6d 4h 3h]
Dealt to SilkZone [2c]
HIWAII2: brings in for $0.02
s0rrow: calls $0.02
SilkZone: calls $0.02
kobreli: calls $0.02
manga130: calls $0.02
meg100: folds
*** 4th STREET ***
Dealt to kobreli [As] [6s]
Dealt to manga130 [Ac] [6h]
Dealt to HIWAII2 [Jd] [Qc]
Dealt to s0rrow [6d 4h 3h] [3c]
Dealt to SilkZone [2c] [Th]
kobreli: bets $0.04
manga130: calls $0.04
HIWAII2: folds
s0rrow: calls $0.04
SilkZone: folds
*** 5th STREET ***
Dealt to kobreli [As 6s] [5c]
Dealt to manga130 [Ac 6h] [5s]
Dealt to s0rrow [6d 4h 3h 3c] [9s]
kobreli: bets $0.08
manga130: calls $0.08
s0rrow: folds
*** 6th STREET ***
Dealt to kobreli [As 6s 5c] [5d]
Dealt to manga130 [Ac 6h 5s] [9h]
manga130: bets $0.08
kobreli: raises $0.08 to $0.16
manga130: calls $0.08
*** RIVER ***
manga130: bets $0.04 and is all-in
kobreli: calls $0.04
*** SHOW DOWN ***
manga130: shows [Ad 8h Ac 6h 5s 9h Kh] (Lo: 9,8,6,5,A)
kobreli: shows [3d 2s As 6s 5c 5d 2d] (Lo: 6,5,3,2,A)
kobreli collected $0.80 from pot
*** SUMMARY ***
Total pot $0.84 | Rake $0.04
Seat 1: kobreli showed [3d 2s As 6s 5c 5d 2d] and won ($0.80) with Lo: 6,5,3,2,A
Seat 3: manga130 showed [Ad 8h Ac 6h 5s 9h Kh] and lost with Lo: 9,8,6,5,A
Seat 5: meg100 folded on the 3rd Street (didn't bet)
Seat 6: HIWAII2 folded on the 4th Street
Seat 7: s0rrow folded on the 5th Street
Seat 8: SilkZone folded on the 4th Street

File diff suppressed because it is too large Load Diff

67
pyfpdb/test_Database.py Normal file
View File

@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
import sqlite3
import fpdb_db
import math
# Should probably use our wrapper classes - creating sqlite db in memory
sqlite3.register_converter("bool", lambda x: bool(int(x)))
sqlite3.register_adapter(bool, lambda x: "1" if x else "0")
con = sqlite3.connect(":memory:")
con.isolation_level = None
#Floor function
con.create_function("floor", 1, math.floor)
#Mod function
tmp = fpdb_db.sqlitemath()
con.create_function("mod", 2, tmp.mod)
# Aggregate function VARIANCE()
con.create_aggregate("variance", 1, fpdb_db.VARIANCE)
cur = con.cursor()
def testSQLiteVarianceFunction():
cur.execute("CREATE TABLE test(i)")
cur.execute("INSERT INTO test(i) values (1)")
cur.execute("INSERT INTO test(i) values (2)")
cur.execute("INSERT INTO test(i) values (3)")
cur.execute("SELECT variance(i) from test")
result = cur.fetchone()[0]
print "DEBUG: Testing variance function"
print "DEBUG: result: %s expecting: 0.666666 (result-expecting ~= 0.0): %s" % (result, (result - 0.66666))
cur.execute("DROP TABLE test")
assert (result - 0.66666) <= 0.0001
def testSQLiteFloorFunction():
vars = [0.1, 1.5, 2.6, 3.5, 4.9]
cur.execute("CREATE TABLE test(i float)")
for var in vars:
cur.execute("INSERT INTO test(i) values(%f)" % var)
cur.execute("SELECT floor(i) from test")
result = cur.fetchall()
print "DEBUG: result: %s" % result
answer = 0
for i in result:
print "DEBUG: int(var): %s" % int(i[0])
assert answer == int(i[0])
answer = answer + 1
cur.execute("DROP TABLE test")
def testSQLiteModFunction():
vars = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ,17, 18]
cur.execute("CREATE TABLE test(i int)")
for var in vars:
cur.execute("INSERT INTO test(i) values(%i)" % var)
cur.execute("SELECT mod(i,13) from test")
result = cur.fetchall()
idx = 0
for i in result:
print "DEBUG: int(var): %s" % i[0]
assert vars[idx]%13 == int(i[0])
idx = idx+1
cur.execute("DROP TABLE test")

View File

@ -3,6 +3,21 @@ import PokerStarsToFpdb
from Hand import *
import py
import Configuration
import Database
import SQL
import fpdb_import
config = Configuration.Config(file = "HUD_config.test.xml")
db = Database.Database(config)
sql = SQL.Sql(db_server = 'sqlite')
settings = {}
settings.update(config.get_db_parameters())
settings.update(config.get_tv_parameters())
settings.update(config.get_import_parameters())
settings.update(config.get_default_paths())
#regression-test-files/stars/badugi/ring-fl-badugi.txt
# s0rrow: input: $30.00 end: $22.65 total: ($7.35)
#regression-test-files/stars/plo/PLO-6max.txt
@ -45,37 +60,66 @@ def testGameInfo():
yield checkGameInfo, hhc, header, info
def testHandInfo():
text = u"""PokerStars Game #20461877044: Hold'em No Limit ($1/$2) - 2008/09/16 18:58:01 ET"""
hhc = PokerStarsToFpdb.PokerStars(autostart=False)
h = HoldemOmahaHand(None, "PokerStars", gametype, text, builtFrom = "Test")
hhc.readHandInfo(h)
assert h.handid == '20461877044'
assert h.sitename == 'PokerStars'
assert h.starttime == (2008, 9, 16, 18, 58, 1, 1, 260, -1)
def testFlopImport():
db.recreate_tables()
importer = fpdb_import.Importer(False, settings, config)
importer.setDropIndexes("don't drop")
importer.setFailOnError(True)
importer.setThreads(-1)
importer.addBulkImportImportFileOrDir(
"""regression-test-files/cash/Stars/Flop/NLHE-6max-EUR-0.05-0.10-200911.txt""", site="PokerStars")
importer.addBulkImportImportFileOrDir(
"""regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200911.txt""", site="PokerStars")
#importer.addBulkImportImportFileOrDir(
# """regression-test-files/tour/Stars/Flop/NLHE-USD-MTT-5r-200710.txt""", site="PokerStars")
importer.addBulkImportImportFileOrDir(
"""regression-test-files/cash/Stars/Flop/PLO8-6max-USD-0.01-0.02-200911.txt""", site="PokerStars")
importer.setCallHud(False)
(stored, dups, partial, errs, ttime) = importer.runImport()
importer.clearFileList()
text = u"""PokerStars Game #18707234955: Razz Limit ($0.50/$1.00) - 2008/07/09 - 21:41:43 (ET)
Table 'Lepus II' 8-max"""
hhc = PokerStarsToFpdb.PokerStars(autostart=False)
h = HoldemOmahaHand(None, "PokerStars", gametype, text, builtFrom = "Test")
hhc.readHandInfo(h)
assert h.handid == '18707234955'
assert h.sitename == 'PokerStars'
assert h.maxseats == 8
assert h.tablename == 'Lepus II'
assert h.starttime == (2008,7 , 9, 21, 41, 43, 2, 191, -1)
# Should actually do some testing here
assert 1 == 1
def testStudImport():
db.recreate_tables()
importer = fpdb_import.Importer(False, settings, config)
importer.setDropIndexes("don't drop")
importer.setFailOnError(True)
importer.setThreads(-1)
importer.addBulkImportImportFileOrDir(
"""regression-test-files/cash/Stars/Stud/7-Stud-USD-0.04-0.08-200911.txt""", site="PokerStars")
importer.addBulkImportImportFileOrDir(
"""regression-test-files/cash/Stars/Stud/7-StudHL-USD-0.04-0.08-200911.txt""", site="PokerStars")
importer.addBulkImportImportFileOrDir(
"""regression-test-files/cash/Stars/Stud/Razz-USD-0.04-0.08-200911.txt""", site="PokerStars")
importer.setCallHud(False)
(stored, dups, partial, errs, ttime) = importer.runImport()
importer.clearFileList()
text = u"""PokerStars Game #22073591924: Hold'em No Limit ($0.50/$1.00) - 2008/11/16 1:22:21 CET [2008/11/15 19:22:21 ET]
Table 'Caia II' 6-max Seat #2 is the button"""
hhc = PokerStarsToFpdb.PokerStars(autostart=False)
h = HoldemOmahaHand(None, "PokerStars", gametype, text, builtFrom = "Test")
hhc.readHandInfo(h)
assert h.handid == '22073591924'
assert h.sitename == 'PokerStars'
assert h.maxseats == 6
assert h.tablename == 'Caia II'
assert h.buttonpos == '2' # TODO: should this be an int?
assert h.starttime == (2008,11 , 15, 19, 22, 21, 5, 320, -1)
# Should actually do some testing here
assert 1 == 1
def testDrawImport():
try:
db.recreate_tables()
importer = fpdb_import.Importer(False, settings, config)
importer.setDropIndexes("don't drop")
importer.setFailOnError(True)
importer.setThreads(-1)
importer.addBulkImportImportFileOrDir(
"""regression-test-files/cash/Stars/Draw/3-Draw-Limit-USD-0.10-0.20-200911.txt""", site="PokerStars")
importer.addBulkImportImportFileOrDir(
"""regression-test-files/cash/Stars/Draw/5-Carddraw-USD-0.10-0.20-200911.txt""", site="PokerStars")
importer.setCallHud(False)
(stored, dups, partial, errs, ttime) = importer.runImport()
importer.clearFileList()
except FpdbError:
if Configuration.NEWIMPORT == False:
#Old import code doesn't support draw
pass
else:
assert 0 == 1
# Should actually do some testing here
assert 1 == 1