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

This commit is contained in:
grindi 2009-10-21 10:09:05 +04:00
commit ae6259e7ae
18 changed files with 2420 additions and 888 deletions

View File

@ -6,7 +6,7 @@ Build-Depends: debhelper, python-support
Standards-Version: 3.8.0 Standards-Version: 3.8.0
Package: python-fpdb Package: python-fpdb
Architecture: any Architecture: all
Section: games Section: games
Priority: extra Priority: extra
Depends: ${python:Depends}, python-gtk2, python-matplotlib, Depends: ${python:Depends}, python-gtk2, python-matplotlib,

View File

@ -105,7 +105,7 @@ class Betfair(HandHistoryConverter):
logging.debug("HID %s, Table %s" % (m.group('HID'), m.group('TABLE'))) logging.debug("HID %s, Table %s" % (m.group('HID'), m.group('TABLE')))
hand.handid = m.group('HID') hand.handid = m.group('HID')
hand.tablename = m.group('TABLE') hand.tablename = m.group('TABLE')
hand.starttime = time.strptime(m.group('DATETIME'), "%A, %B %d, %H:%M:%S GMT %Y") hand.starttime = datetime.datetime.strptime(m.group('DATETIME'), "%A, %B %d, %H:%M:%S GMT %Y")
#hand.buttonpos = int(m.group('BUTTON')) #hand.buttonpos = int(m.group('BUTTON'))
def readPlayerStacks(self, hand): def readPlayerStacks(self, hand):
@ -144,6 +144,7 @@ class Betfair(HandHistoryConverter):
def readAntes(self, hand): def readAntes(self, hand):
logging.debug("reading antes") logging.debug("reading antes")
m = self.re_Antes.finditer(hand.handText)
for player in m: for player in m:
logging.debug("hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE'))) logging.debug("hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE')))
hand.addAnte(player.group('PNAME'), player.group('ANTE')) hand.addAnte(player.group('PNAME'), player.group('ANTE'))
@ -160,17 +161,15 @@ class Betfair(HandHistoryConverter):
hand.buttonpos = int(self.re_Button.search(hand.handText).group('BUTTON')) hand.buttonpos = int(self.re_Button.search(hand.handText).group('BUTTON'))
def readHeroCards(self, hand): def readHeroCards(self, hand):
m = self.re_HeroCards.search(hand.handText) # streets PREFLOP, PREDRAW, and THIRD are special cases beacause
if(m == None): # we need to grab hero's cards
#Not involved in hand for street in ('PREFLOP', 'DEAL'):
hand.involved = False if street in hand.streets.keys():
else: m = self.re_HeroCards.finditer(hand.streets[street])
hand.hero = m.group('PNAME') for found in m:
# "2c, qh" -> set(["2c","qc"]) hand.hero = found.group('PNAME')
# Also works with Omaha hands. newcards = [c.strip() for c in found.group('CARDS').split(',')]
cards = m.group('CARDS') hand.addHoleCards(street, hand.hero, closed=newcards, shown=False, mucked=False, dealt=True)
cards = [c.strip() for c in cards.split(',')]
hand.addHoleCards(cards, m.group('PNAME'))
def readStudPlayerCards(self, hand, street): def readStudPlayerCards(self, hand, street):
# balh blah blah # balh blah blah

View File

@ -278,6 +278,28 @@ class Import:
return " interval = %s\n callFpdbHud = %s\n hhArchiveBase = %s\n saveActions = %s\n fastStoreHudCache = %s\n" \ return " interval = %s\n callFpdbHud = %s\n hhArchiveBase = %s\n saveActions = %s\n fastStoreHudCache = %s\n" \
% (self.interval, self.callFpdbHud, self.hhArchiveBase, self.saveActions, self.fastStoreHudCache) % (self.interval, self.callFpdbHud, self.hhArchiveBase, self.saveActions, self.fastStoreHudCache)
class HudUI:
def __init__(self, node):
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.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_agg_bb_mult = node.getAttribute('hero_aggregation_level_multiplier')
def __str__(self):
return " label = %s\n" % self.label
class Tv: class Tv:
def __init__(self, node): def __init__(self, node):
self.combinedStealFold = node.getAttribute("combinedStealFold") self.combinedStealFold = node.getAttribute("combinedStealFold")
@ -311,13 +333,21 @@ class Config:
pass pass
if file == None: # that didn't work either, just die if file == None: # that didn't work either, just die
print "No HUD_config_xml found. Exiting" 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. Exiting") 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() sys.exit()
# Parse even if there was no real config file found and we are using the example # 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 # 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) 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: try:
doc = xml.dom.minidom.parse(file) doc = xml.dom.minidom.parse(file)
except: except:
@ -389,6 +419,10 @@ class Config:
imp = Import(node = imp_node) imp = Import(node = imp_node)
self.imp = imp self.imp = imp
for hui_node in doc.getElementsByTagName('hud_ui'):
hui = HudUI(node = hui_node)
self.ui = hui
for tv_node in doc.getElementsByTagName("tv"): for tv_node in doc.getElementsByTagName("tv"):
tv = Tv(node = tv_node) tv = Tv(node = tv_node)
self.tv = tv self.tv = tv
@ -405,6 +439,8 @@ class Config:
db_pass = df_parms['db-password']) db_pass = df_parms['db-password'])
self.save(file=os.path.join(self.default_config_path, "HUD_config.xml")) self.save(file=os.path.join(self.default_config_path, "HUD_config.xml"))
print ""
def set_hhArchiveBase(self, path): def set_hhArchiveBase(self, path):
self.imp.node.setAttribute("hhArchiveBase", path) self.imp.node.setAttribute("hhArchiveBase", path)
@ -454,11 +490,15 @@ class Config:
def find_example_config(self): def find_example_config(self):
if os.path.exists('HUD_config.xml.example'): # there is a HUD_config in the cwd if os.path.exists('HUD_config.xml.example'): # there is a HUD_config in the cwd
file = 'HUD_config.xml.example' # so we use it 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", \ print "No HUD_config.xml found, using HUD_config.xml.example.\n", \
"A HUD_config.xml will be written. You will probably have to edit it." "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" + \ sys.stderr.write("No HUD_config.xml found, using HUD_config.xml.example.\n" + \
"A HUD_config.xml will be written. You will probably have to edit it.") "A HUD_config.xml has been created. You will probably have to edit it.")
else: else:
file = None file = None
return file return file
@ -599,6 +639,53 @@ class Config:
except: tv['combinedPostflop'] = True except: tv['combinedPostflop'] = True
return tv return tv
# Allow to change the menu appearance
def get_hud_ui_parameters(self):
hui = {}
default_text = 'FPDB Menu - Right click\nLeft-Drag to Move'
try:
hui['label'] = self.ui.label
if self.ui.label == '': # Empty menu label is a big no-no
hui['label'] = default_text
except:
hui['label'] = default_text
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
# 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_agg_bb_mult'] = self.ui.h_agg_bb_mult
except: hui['h_agg_bb_mult'] = 1
return hui
def get_import_parameters(self): def get_import_parameters(self):
imp = {} imp = {}
try: imp['callFpdbHud'] = self.imp.callFpdbHud try: imp['callFpdbHud'] = self.imp.callFpdbHud

View File

@ -188,14 +188,7 @@ class Database:
log.info("Creating Database instance, sql = %s" % sql) log.info("Creating Database instance, sql = %s" % sql)
self.config = c self.config = c
self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql
self.fdb.do_connect(c) self.do_connect(c)
self.connection = self.fdb.db
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']
if self.backend == self.PGSQL: if self.backend == self.PGSQL:
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT, ISOLATION_LEVEL_READ_COMMITTED, ISOLATION_LEVEL_SERIALIZABLE from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT, ISOLATION_LEVEL_READ_COMMITTED, ISOLATION_LEVEL_SERIALIZABLE
@ -206,14 +199,14 @@ class Database:
# where possible avoid creating new SQL instance by using the global one passed in # where possible avoid creating new SQL instance by using the global one passed in
if sql is None: if sql is None:
self.sql = SQL.Sql(type = self.type, db_server = db_params['db-server']) self.sql = SQL.Sql(type = self.type, db_server = self.db_server)
else: else:
self.sql = sql self.sql = sql
if self.backend == self.SQLITE and db_params['db-databaseName'] == ':memory:' and self.fdb.wrongDbVersion: if self.backend == self.SQLITE and self.database == ':memory:' and self.wrongDbVersion:
log.info("sqlite/:memory: - creating") log.info("sqlite/:memory: - creating")
self.recreate_tables() self.recreate_tables()
self.fdb.wrongDbVersion = False self.wrongDbVersion = False
self.pcache = None # PlayerId cache self.pcache = None # PlayerId cache
self.cachemiss = 0 # Delete me later - using to count player cache misses self.cachemiss = 0 # Delete me later - using to count player cache misses
@ -245,6 +238,16 @@ class Database:
def do_connect(self, c): def do_connect(self, c):
self.fdb.do_connect(c) self.fdb.do_connect(c)
self.connection = self.fdb.db
self.wrongDbVersion = self.fdb.wrongDbVersion
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']
self.host = db_params['db-host']
def commit(self): def commit(self):
self.fdb.db.commit() self.fdb.db.commit()
@ -389,7 +392,7 @@ class Database:
print "*** Error: " + err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1]) print "*** Error: " + err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1])
else: else:
if row and row[0]: if row and row[0]:
self.hand_1_day_ago = row[0] self.hand_1day_ago = int(row[0])
d = timedelta(days=hud_days) d = timedelta(days=hud_days)
now = datetime.utcnow() - d now = datetime.utcnow() - d
@ -431,6 +434,7 @@ class Database:
if hud_style == 'S' or h_hud_style == 'S': 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, h_hud_style)
if hud_style == 'S' and h_hud_style == 'S': if hud_style == 'S' and h_hud_style == 'S':
return stat_dict return stat_dict
@ -452,10 +456,10 @@ class Database:
#elif h_hud_style == 'H': #elif h_hud_style == 'H':
# h_stylekey = date_nhands_ago needs array by player here ... # h_stylekey = date_nhands_ago needs array by player here ...
#if aggregate: always use aggreagte query now: use agg_bb_mult of 1 for no aggregation: #if aggregate: always use aggregate query now: use agg_bb_mult of 1 for no aggregation:
query = 'get_stats_from_hand_aggregated' 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) 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 #print "agg query subs:", subs
#else: #else:
# query = 'get_stats_from_hand' # query = 'get_stats_from_hand'
# subs = (hand, stylekey) # subs = (hand, stylekey)
@ -467,6 +471,8 @@ class Database:
c.execute(self.sql.query[query], subs) c.execute(self.sql.query[query], subs)
colnames = [desc[0] for desc in c.description] colnames = [desc[0] for desc in c.description]
for row in c.fetchall(): for row in c.fetchall():
playerid = row[0]
if (playerid == hero_id and h_hud_style != 'S') or (playerid != hero_id and hud_style != 'S'):
t_dict = {} t_dict = {}
for name, val in zip(colnames, row): for name, val in zip(colnames, row):
t_dict[name.lower()] = val t_dict[name.lower()] = val
@ -501,10 +507,10 @@ class Database:
row = c.fetchone() row = c.fetchone()
if colnames[0].lower() == 'player_id': if colnames[0].lower() == 'player_id':
playerid = row[0]
# Loop through stats adding them to appropriate stat_dict: # Loop through stats adding them to appropriate stat_dict:
while row: while row:
playerid = row[0]
if (playerid == hero_id and h_hud_style == 'S') or (playerid != hero_id and hud_style == 'S'): if (playerid == hero_id and h_hud_style == 'S') or (playerid != hero_id and hud_style == 'S'):
for name, val in zip(colnames, row): for name, val in zip(colnames, row):
if not playerid in stat_dict: if not playerid in stat_dict:
@ -535,6 +541,16 @@ class Database:
else: else:
return None return None
def get_player_names(self, config, site_id=None, like_player_name="%"):
"""Fetch player names from players. Use site_id and like_player_name if provided"""
if site_id == None:
site_id = -1
c = self.get_cursor()
c.execute(self.sql.query['get_player_names'], (like_player_name, site_id, site_id))
rows = c.fetchall()
return rows
#returns the SQL ids of the names given in an array #returns the SQL ids of the names given in an array
# TODO: if someone gets industrious, they should make the parts that use the output of this function deal with a dict # TODO: if someone gets industrious, they should make the parts that use the output of this function deal with a dict
# { playername: id } instead of depending on it's relation to the positions list # { playername: id } instead of depending on it's relation to the positions list
@ -1131,7 +1147,7 @@ class Database:
elif self.backend == self.MYSQL_INNODB: elif self.backend == self.MYSQL_INNODB:
c.execute("""insert into TourneyTypes(id, siteId, buyin, fee, maxSeats, knockout c.execute("""insert into TourneyTypes(id, siteId, buyin, fee, maxSeats, knockout
,rebuyOrAddon, speed, headsUp, shootout, matrix) ,rebuyOrAddon, speed, headsUp, shootout, matrix)
values (1, 1, 0, 0, 0, False, False, null, False, False, False);""") values (DEFAULT, 1, 0, 0, 0, False, False, null, False, False, False);""")
#end def fillDefaultData #end def fillDefaultData
@ -1362,174 +1378,288 @@ class Database:
def storeHand(self, p): def storeHand(self, p):
#stores into table hands: #stores into table hands:
q = """INSERT INTO Hands ( q = self.sql.query['store_hand']
tablename,
gametypeid,
sitehandno,
handstart,
importtime,
seats,
maxseats,
boardcard1,
boardcard2,
boardcard3,
boardcard4,
boardcard5,
street1Pot,
street2Pot,
street3Pot,
street4Pot,
showdownPot
)
VALUES
(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
%s, %s, %s, %s, %s, %s, %s)"""
#--- texture,
#-- playersVpi,
#-- playersAtStreet1,
#-- playersAtStreet2,
#-- playersAtStreet3,
#-- playersAtStreet4,
#-- playersAtShowdown,
#-- street0Raises,
#-- street1Raises,
#-- street2Raises,
#-- street3Raises,
#-- street4Raises,
#-- seats,
q = q.replace('%s', self.sql.query['placeholder']) q = q.replace('%s', self.sql.query['placeholder'])
print "DEBUG: p: %s" %p
print "DEBUG: gtid: %s" % p['gameTypeId']
self.cursor.execute(q, ( self.cursor.execute(q, (
p['tableName'], p['tableName'],
p['gameTypeId'], p['gameTypeId'],
p['siteHandNo'], p['siteHandNo'],
p['handStart'], p['handStart'],
datetime.today(), #importtime datetime.today(), #importtime
# len(p['names']), #seats
p['maxSeats'],
p['seats'], p['seats'],
p['maxSeats'],
p['texture'],
p['playersVpi'],
p['boardcard1'], p['boardcard1'],
p['boardcard2'], p['boardcard2'],
p['boardcard3'], p['boardcard3'],
p['boardcard4'], p['boardcard4'],
p['boardcard5'], p['boardcard5'],
# hudCache['playersVpi'], p['playersAtStreet1'],
# hudCache['playersAtStreet1'], p['playersAtStreet2'],
# hudCache['playersAtStreet2'], p['playersAtStreet3'],
# hudCache['playersAtStreet3'], p['playersAtStreet4'],
# hudCache['playersAtStreet4'], p['playersAtShowdown'],
# hudCache['playersAtShowdown'], p['street0Raises'],
# hudCache['street0Raises'], p['street1Raises'],
# hudCache['street1Raises'], p['street2Raises'],
# hudCache['street2Raises'], p['street3Raises'],
# hudCache['street3Raises'], p['street4Raises'],
# hudCache['street4Raises'],
p['street1Pot'], p['street1Pot'],
p['street2Pot'], p['street2Pot'],
p['street3Pot'], p['street3Pot'],
p['street4Pot'], p['street4Pot'],
p['showdownPot'] p['showdownPot']
)) ))
#return getLastInsertId(backend, conn, cursor) return self.get_last_insert_id(self.cursor)
# def storeHand # def storeHand
def storeHandsPlayers(self, p): def storeHandsPlayers(self, hid, pids, pdata):
#def store_hands_players_holdem_omaha(self, backend, category, hands_id, player_ids, start_cashes #print "DEBUG: %s %s %s" %(hid, pids, pdata)
# ,positions, card_values, card_suits, winnings, rakes, seatNos, hudCache): inserts = []
# result=[] for p in pdata:
# inserts.append( (hid,
# # postgres (and others?) needs the booleans converted to ints before saving: pids[p],
# # (or we could just save them as boolean ... but then we can't sum them so easily in sql ???) pdata[p]['startCash'],
# # NO - storing booleans for now so don't need this pdata[p]['seatNo'],
# #hudCacheInt = {} pdata[p]['street0Aggr'],
# #for k,v in hudCache.iteritems(): pdata[p]['street1Aggr'],
# # if k in ('wonWhenSeenStreet1', 'wonAtSD', 'totalProfit'): pdata[p]['street2Aggr'],
# # hudCacheInt[k] = v pdata[p]['street3Aggr'],
# # else: pdata[p]['street4Aggr']
# # hudCacheInt[k] = map(lambda x: 1 if x else 0, v) ) )
#
# try:
# inserts = []
# for i in xrange(len(player_ids)):
# card1 = Card.cardFromValueSuit(card_values[i][0], card_suits[i][0])
# card2 = Card.cardFromValueSuit(card_values[i][1], card_suits[i][1])
#
# if (category=="holdem"):
# startCards = Card.twoStartCards(card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1])
# card3 = None
# card4 = None
# elif (category=="omahahi" or category=="omahahilo"):
# startCards = Card.fourStartCards(card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1]
# ,card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3])
# card3 = Card.cardFromValueSuit(card_values[i][2], card_suits[i][2])
# card4 = Card.cardFromValueSuit(card_values[i][3], card_suits[i][3])
# else:
# raise FpdbError("invalid category")
#
# inserts.append( (
# hands_id, player_ids[i], start_cashes[i], positions[i], 1, # tourneytypeid - needed for hudcache
# card1, card2, card3, card4, startCards,
# winnings[i], rakes[i], seatNos[i], hudCache['totalProfit'][i],
# hudCache['street0VPI'][i], hudCache['street0Aggr'][i],
# hudCache['street0_3BChance'][i], hudCache['street0_3BDone'][i],
# hudCache['street1Seen'][i], hudCache['street2Seen'][i], hudCache['street3Seen'][i],
# hudCache['street4Seen'][i], hudCache['sawShowdown'][i],
# hudCache['street1Aggr'][i], hudCache['street2Aggr'][i], hudCache['street3Aggr'][i], hudCache['street4Aggr'][i],
# hudCache['otherRaisedStreet1'][i], hudCache['otherRaisedStreet2'][i],
# hudCache['otherRaisedStreet3'][i], hudCache['otherRaisedStreet4'][i],
# hudCache['foldToOtherRaisedStreet1'][i], hudCache['foldToOtherRaisedStreet2'][i],
# hudCache['foldToOtherRaisedStreet3'][i], hudCache['foldToOtherRaisedStreet4'][i],
# hudCache['wonWhenSeenStreet1'][i], hudCache['wonAtSD'][i],
# hudCache['stealAttemptChance'][i], hudCache['stealAttempted'][i], hudCache['foldBbToStealChance'][i],
# hudCache['foldedBbToSteal'][i], hudCache['foldSbToStealChance'][i], hudCache['foldedSbToSteal'][i],
# hudCache['street1CBChance'][i], hudCache['street1CBDone'][i], hudCache['street2CBChance'][i], hudCache['street2CBDone'][i],
# hudCache['street3CBChance'][i], hudCache['street3CBDone'][i], hudCache['street4CBChance'][i], hudCache['street4CBDone'][i],
# hudCache['foldToStreet1CBChance'][i], hudCache['foldToStreet1CBDone'][i],
# hudCache['foldToStreet2CBChance'][i], hudCache['foldToStreet2CBDone'][i],
# hudCache['foldToStreet3CBChance'][i], hudCache['foldToStreet3CBDone'][i],
# hudCache['foldToStreet4CBChance'][i], hudCache['foldToStreet4CBDone'][i],
# hudCache['street1CheckCallRaiseChance'][i], hudCache['street1CheckCallRaiseDone'][i],
# hudCache['street2CheckCallRaiseChance'][i], hudCache['street2CheckCallRaiseDone'][i],
# hudCache['street3CheckCallRaiseChance'][i], hudCache['street3CheckCallRaiseDone'][i],
# hudCache['street4CheckCallRaiseChance'][i], hudCache['street4CheckCallRaiseDone'][i],
# hudCache['street0Calls'][i], hudCache['street1Calls'][i], hudCache['street2Calls'][i], hudCache['street3Calls'][i], hudCache['street4Calls'][i],
# hudCache['street0Bets'][i], hudCache['street1Bets'][i], hudCache['street2Bets'][i], hudCache['street3Bets'][i], hudCache['street4Bets'][i]
# ) )
# c = self.get_cursor()
# c.executemany ("""
# INSERT INTO HandsPlayers
# (handId, playerId, startCash, position, tourneyTypeId,
# card1, card2, card3, card4, startCards, winnings, rake, seatNo, totalProfit,
# 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, foldBbToStealChance, foldedBbToSteal, foldSbToStealChance, foldedSbToSteal,
# street1CBChance, street1CBDone, street2CBChance, street2CBDone,
# street3CBChance, street3CBDone, street4CBChance, street4CBDone,
# foldToStreet1CBChance, foldToStreet1CBDone, foldToStreet2CBChance, foldToStreet2CBDone,
# foldToStreet3CBChance, foldToStreet3CBDone, foldToStreet4CBChance, foldToStreet4CBDone,
# street1CheckCallRaiseChance, street1CheckCallRaiseDone, street2CheckCallRaiseChance, street2CheckCallRaiseDone,
# street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone,
# 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, %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)""".replace('%s', self.sql.query['placeholder'])
# ,inserts )
# result.append( self.get_last_insert_id(c) ) # wrong? not used currently
# except:
# raise FpdbError( "store_hands_players_holdem_omaha error: " + str(sys.exc_value) )
#
# return result
pass q = """INSERT INTO HandsPlayers (
handId,
playerId,
startCash,
seatNo,
street0Aggr,
street1Aggr,
street2Aggr,
street3Aggr,
street4Aggr
)
VALUES (
%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,
# otherRaisedStreet4,
# foldToOtherRaisedStreet1,
# foldToOtherRaisedStreet2,
# foldToOtherRaisedStreet3,
# foldToOtherRaisedStreet4,
# wonWhenSeenStreet1,
# wonAtSD,
# stealAttemptChance,
# stealAttempted,
# foldBbToStealChance,
# foldedBbToSteal,
# foldSbToStealChance,
# foldedSbToSteal,
# street1CBChance,
# street1CBDone,
# street2CBChance,
# street2CBDone,
# street3CBChance,
# street3CBDone,
# street4CBChance,
# street4CBDone,
# foldToStreet1CBChance,
# foldToStreet1CBDone,
# foldToStreet2CBChance,
# foldToStreet2CBDone,
# foldToStreet3CBChance,
# foldToStreet3CBDone,
# foldToStreet4CBChance,
# foldToStreet4CBDone,
# street1CheckCallRaiseChance,
# street1CheckCallRaiseDone,
# street2CheckCallRaiseChance,
# street2CheckCallRaiseDone,
# street3CheckCallRaiseChance,
# 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)
def storeHudCacheNew(self, gid, pid, hc):
q = """INSERT INTO HudCache (
gametypeId,
playerId
)
VALUES (
%s, %s
)"""
# gametypeId,
# playerId,
# activeSeats,
# position,
# tourneyTypeId,
# styleKey,
# HDs,
# 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,
# foldBbToStealChance,
# foldedBbToSteal,
# foldSbToStealChance,
# foldedSbToSteal,
# street1CBChance,
# street1CBDone,
# street2CBChance,
# street2CBDone,
# street3CBChance,
# street3CBDone,
# street4CBChance,
# street4CBDone,
# foldToStreet1CBChance,
# foldToStreet1CBDone,
# foldToStreet2CBChance,
# foldToStreet2CBDone,
# foldToStreet3CBChance,
# foldToStreet3CBDone,
# foldToStreet4CBChance,
# foldToStreet4CBDone,
# totalProfit,
# street1CheckCallRaiseChance,
# street1CheckCallRaiseDone,
# street2CheckCallRaiseChance,
# street2CheckCallRaiseDone,
# street3CheckCallRaiseChance,
# street3CheckCallRaiseDone,
# street4CheckCallRaiseChance,
# street4CheckCallRaiseDone)
q = q.replace('%s', self.sql.query['placeholder'])
self.cursor.execute(q, (
gid,
pid
))
# gametypeId,
# playerId,
# activeSeats,
# position,
# tourneyTypeId,
# styleKey,
# HDs,
# 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,
# foldBbToStealChance,
# foldedBbToSteal,
# foldSbToStealChance,
# foldedSbToSteal,
# street1CBChance,
# street1CBDone,
# street2CBChance,
# street2CBDone,
# street3CBChance,
# street3CBDone,
# street4CBChance,
# street4CBDone,
# foldToStreet1CBChance,
# foldToStreet1CBDone,
# foldToStreet2CBChance,
# foldToStreet2CBDone,
# foldToStreet3CBChance,
# foldToStreet3CBDone,
# foldToStreet4CBChance,
# foldToStreet4CBDone,
# totalProfit,
# street1CheckCallRaiseChance,
# street1CheckCallRaiseDone,
# street2CheckCallRaiseChance,
# street2CheckCallRaiseDone,
# street3CheckCallRaiseChance,
# street3CheckCallRaiseDone,
# street4CheckCallRaiseChance,
# street4CheckCallRaiseDone)
################################# #################################

View File

@ -22,76 +22,6 @@ class DerivedStats():
def __init__(self, hand): def __init__(self, hand):
self.hand = hand self.hand = hand
self.activeSeats = 0
self.position = 0
self.tourneyTypeId = 0
self.HDs = 0
self.street0VPI = 0
self.street0Aggr = 0
self.street0_3BChance = 0
self.street0_3BDone = 0
self.street0_4BChance = 0
self.street0_4BDone = 0
self.street1Seen = 0
self.street2Seen = 0
self.street3Seen = 0
self.street4Seen = 0
self.sawShowdown = 0
self.street1Aggr = 0
self.street2Aggr = 0
self.street3Aggr = 0
self.street4Aggr = 0
self.otherRaisedStreet1 = 0
self.otherRaisedStreet2 = 0
self.otherRaisedStreet3 = 0
self.otherRaisedStreet4 = 0
self.foldToOtherRaisedStreet1 = 0
self.foldToOtherRaisedStreet2 = 0
self.foldToOtherRaisedStreet3 = 0
self.foldToOtherRaisedStreet4 = 0
self.wonWhenSeenStreet1 = 0
self.wonAtSD = 0
self.stealAttemptChance = 0
self.stealAttempted = 0
self.foldBbToStealChance = 0
self.foldedBbToSteal = 0
self.foldSbToStealChance = 0
self.foldedSbToSteal = 0
self.street1CBChance = 0
self.street1CBDone = 0
self.street2CBChance = 0
self.street2CBDone = 0
self.street3CBChance = 0
self.street3CBDone = 0
self.street4CBChance = 0
self.street4CBDone = 0
self.foldToStreet1CBChance = 0
self.foldToStreet1CBDone = 0
self.foldToStreet2CBChance = 0
self.foldToStreet2CBDone = 0
self.foldToStreet3CBChance = 0
self.foldToStreet3CBDone = 0
self.foldToStreet4CBChance = 0
self.foldToStreet4CBDone = 0
self.totalProfit = 0
self.street1CheckCallRaiseChance = 0
self.street1CheckCallRaiseDone = 0
self.street2CheckCallRaiseChance = 0
self.street2CheckCallRaiseDone = 0
self.street3CheckCallRaiseChance = 0
self.street3CheckCallRaiseDone = 0
self.street4CheckCallRaiseChance = 0
self.street4CheckCallRaiseDone = 0
self.hands = {} self.hands = {}
self.handsplayers = {} self.handsplayers = {}
@ -99,6 +29,8 @@ class DerivedStats():
for player in hand.players: for player in hand.players:
self.handsplayers[player[1]] = {} self.handsplayers[player[1]] = {}
#Init vars that may not be used, but still need to be inserted.
self.handsplayers[player[1]]['street4Aggr'] = False
self.assembleHands(self.hand) self.assembleHands(self.hand)
self.assembleHandsPlayers(self.hand) self.assembleHandsPlayers(self.hand)
@ -106,6 +38,12 @@ class DerivedStats():
print "hands =", self.hands print "hands =", self.hands
print "handsplayers =", self.handsplayers print "handsplayers =", self.handsplayers
def getHands(self):
return self.hands
def getHandsPlayers(self):
return self.handsplayers
def assembleHands(self, hand): def assembleHands(self, hand):
self.hands['tableName'] = hand.tablename self.hands['tableName'] = hand.tablename
self.hands['siteHandNo'] = hand.handid self.hands['siteHandNo'] = hand.handid
@ -114,35 +52,796 @@ class DerivedStats():
self.hands['importTime'] = None self.hands['importTime'] = None
self.hands['seats'] = self.countPlayers(hand) self.hands['seats'] = self.countPlayers(hand)
self.hands['maxSeats'] = hand.maxseats self.hands['maxSeats'] = hand.maxseats
self.hands['boardcard1'] = None self.hands['texture'] = None # No calculation done for this yet.
self.hands['boardcard2'] = None
self.hands['boardcard3'] = None
self.hands['boardcard4'] = None
self.hands['boardcard5'] = None
boardCard = 1 # This (i think...) is correct for both stud and flop games, as hand.board['street'] disappears, and
for street in hand.communityStreets: # those values remain default in stud.
for card in hand.board[street]: boardcards = hand.board['FLOP'] + hand.board['TURN'] + hand.board['RIVER'] + [u'0x', u'0x', u'0x', u'0x', u'0x']
self.hands['boardcard%s' % str(boardCard)] = Card.encodeCard(card) cards = [Card.encodeCard(c) for c in boardcards[0:5]]
boardCard += 1 self.hands['boardcard1'] = cards[0]
self.hands['boardcard2'] = cards[1]
self.hands['boardcard3'] = cards[2]
self.hands['boardcard4'] = cards[3]
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()
self.vpip(hand) # Gives playersVpi (num of players vpip)
#print "DEBUG: vpip: %s" %(self.hands['playersVpi'])
self.playersAtStreetX(hand) # Gives playersAtStreet1..4 and Showdown
#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): def assembleHandsPlayers(self, hand):
self.vpip(self.hand) #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[1:]): for i, street in enumerate(hand.actionStreets[1:]):
self.aggr(self.hand, i) self.aggr(self.hand, i)
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): def vpip(self, hand):
vpipers = set() vpipers = set()
for act in hand.actions[hand.actionStreets[1]]: for act in hand.actions[hand.actionStreets[1]]:
if act[1] in ('calls','bets', 'raises'): if act[1] in ('calls','bets', 'raises'):
vpipers.add(act[0]) vpipers.add(act[0])
self.hands['playersVpi'] = len(vpipers)
for player in hand.players: for player in hand.players:
if player[1] in vpipers: if player[1] in vpipers:
self.handsplayers[player[1]]['vpip'] = True self.handsplayers[player[1]]['vpip'] = True
else: else:
self.handsplayers[player[1]]['vpip'] = False self.handsplayers[player[1]]['vpip'] = False
self.hands['playersVpi'] = len(vpipers)
def playersAtStreetX(self, hand):
""" playersAtStreet1 SMALLINT NOT NULL, /* num of players seeing flop/street4/draw1 */"""
# self.actions[street] is a list of all actions in a tuple, contining the player name first
# [ (player, action, ....), (player2, action, ...) ]
# The number of unique players in the list per street gives the value for playersAtStreetXXX
# FIXME?? - This isn't couting people that are all in - at least showdown needs to reflect this
self.hands['playersAtStreet1'] = 0
self.hands['playersAtStreet2'] = 0
self.hands['playersAtStreet3'] = 0
self.hands['playersAtStreet4'] = 0
self.hands['playersAtShowdown'] = 0
for street in hand.actionStreets:
actors = {}
for act in hand.actions[street]:
actors[act[0]] = 1
#print "len(actors.keys(%s)): %s" % ( street, len(actors.keys()))
if hand.gametype['base'] in ("hold"):
if street in "FLOP": self.hands['playersAtStreet1'] = len(actors.keys())
elif street in "TURN": self.hands['playersAtStreet2'] = len(actors.keys())
elif street in "RIVER": self.hands['playersAtStreet3'] = len(actors.keys())
elif hand.gametype['base'] in ("stud"):
if street in "FOURTH": self.hands['playersAtStreet1'] = len(actors.keys())
elif street in "FIFTH": self.hands['playersAtStreet2'] = len(actors.keys())
elif street in "SIXTH": self.hands['playersAtStreet3'] = len(actors.keys())
elif street in "SEVENTH": self.hands['playersAtStreet4'] = len(actors.keys())
elif hand.gametype['base'] in ("draw"):
if street in "DRAWONE": self.hands['playersAtStreet1'] = len(actors.keys())
elif street in "DRAWTWO": self.hands['playersAtStreet2'] = len(actors.keys())
elif street in "DRAWTHREE": self.hands['playersAtStreet3'] = len(actors.keys())
#Need playersAtShowdown
def streetXRaises(self, hand):
# self.actions[street] is a list of all actions in a tuple, contining the action as the second element
# [ (player, action, ....), (player2, action, ...) ]
# 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 */
def aggr(self, hand, i): def aggr(self, hand, i):
aggrers = set() aggrers = set()

View File

@ -17,5 +17,8 @@ class FpdbParseError(FpdbError):
class FpdbDatabaseError(FpdbError): class FpdbDatabaseError(FpdbError):
pass pass
class FpdbMySQLFailedError(FpdbDatabaseError):
pass
class DuplicateError(FpdbError): class DuplicateError(FpdbError):
pass pass

View File

@ -23,6 +23,7 @@ import os
import sys import sys
from optparse import OptionParser from optparse import OptionParser
from time import * from time import *
import gobject
#import pokereval #import pokereval
import Configuration import Configuration
@ -31,12 +32,13 @@ import FpdbSQLQueries
class Filters(threading.Thread): class Filters(threading.Thread):
def __init__(self, db, config, qdict, display = {}, debug=True): def __init__(self, db, config, qdict, display = {}, debug=True):
# config and qdict are now redundant
self.debug = debug self.debug = debug
#print "start of GraphViewer constructor" #print "start of GraphViewer constructor"
self.db = db self.db = db
self.cursor = db.cursor self.cursor = db.cursor
self.sql=qdict self.sql = db.sql
self.conf = config self.conf = db.config
self.display = display self.display = display
self.sites = {} self.sites = {}
@ -53,6 +55,8 @@ class Filters(threading.Thread):
,'seatsbetween':'Between:', 'seatsand':'And:', 'seatsshow':'Show Number of _Players' ,'seatsbetween':'Between:', 'seatsand':'And:', 'seatsshow':'Show Number of _Players'
,'limitstitle':'Limits:', 'seatstitle':'Number of Players:' ,'limitstitle':'Limits:', 'seatstitle':'Number of Players:'
,'groupstitle':'Grouping:', 'posnshow':'Show Position Stats:' ,'groupstitle':'Grouping:', 'posnshow':'Show Position Stats:'
,'groupsall':'All Players'
,'limitsFL':'FL', 'limitsNL':'NL', 'ring':'Ring', 'tour':'Tourney'
} }
# For use in date ranges. # For use in date ranges.
@ -61,6 +65,10 @@ class Filters(threading.Thread):
self.start_date.set_property('editable', False) self.start_date.set_property('editable', False)
self.end_date.set_property('editable', False) self.end_date.set_property('editable', False)
# For use in groups etc
self.sbGroups = {}
self.numHands = 0
# Outer Packing box # Outer Packing box
self.mainVBox = gtk.VBox(False, 0) self.mainVBox = gtk.VBox(False, 0)
@ -68,7 +76,7 @@ class Filters(threading.Thread):
playerFrame.set_label_align(0.0, 0.0) playerFrame.set_label_align(0.0, 0.0)
vbox = gtk.VBox(False, 0) vbox = gtk.VBox(False, 0)
self.fillPlayerFrame(vbox) self.fillPlayerFrame(vbox, self.display)
playerFrame.add(vbox) playerFrame.add(vbox)
self.boxes['player'] = vbox self.boxes['player'] = vbox
@ -97,6 +105,11 @@ class Filters(threading.Thread):
self.cbLimits = {} self.cbLimits = {}
self.cbNoLimits = None self.cbNoLimits = None
self.cbAllLimits = None self.cbAllLimits = None
self.cbFL = None
self.cbNL = None
self.rb = {} # radio buttons for ring/tour
self.type = None # ring/tour
self.types = {} # list of all ring/tour values
self.fillLimitsFrame(vbox, self.display) self.fillLimitsFrame(vbox, self.display)
limitsFrame.add(vbox) limitsFrame.add(vbox)
@ -114,7 +127,6 @@ class Filters(threading.Thread):
groupsFrame = gtk.Frame() groupsFrame = gtk.Frame()
groupsFrame.show() groupsFrame.show()
vbox = gtk.VBox(False, 0) vbox = gtk.VBox(False, 0)
self.sbGroups = {}
self.fillGroupsFrame(vbox, self.display) self.fillGroupsFrame(vbox, self.display)
groupsFrame.add(vbox) groupsFrame.add(vbox)
@ -173,6 +185,9 @@ class Filters(threading.Thread):
return self.mainVBox return self.mainVBox
#end def get_vbox #end def get_vbox
def getNumHands(self):
return self.numHands
def getSites(self): def getSites(self):
return self.sites return self.sites
@ -189,6 +204,9 @@ class Filters(threading.Thread):
ltuple.append(l) ltuple.append(l)
return ltuple return ltuple
def getType(self):
return(self.type)
def getSeats(self): def getSeats(self):
if 'from' in self.sbSeats: if 'from' in self.sbSeats:
self.seats['from'] = self.sbSeats['from'].get_value_as_int() self.seats['from'] = self.sbSeats['from'].get_value_as_int()
@ -228,7 +246,16 @@ class Filters(threading.Thread):
pname.set_width_chars(20) pname.set_width_chars(20)
hbox.pack_start(pname, False, True, 0) hbox.pack_start(pname, False, True, 0)
pname.connect("changed", self.__set_hero_name, site) pname.connect("changed", self.__set_hero_name, site)
#TODO: Look at GtkCompletion - to fill out usernames
# Added EntryCompletion but maybe comboBoxEntry is more flexible? (e.g. multiple choices)
completion = gtk.EntryCompletion()
pname.set_completion(completion)
liststore = gtk.ListStore(gobject.TYPE_STRING)
completion.set_model(liststore)
completion.set_text_column(0)
names = self.db.get_player_names(self.conf) # (config=self.conf, site_id=None, like_player_name="%")
for n in names:
liststore.append(n)
self.__set_hero_name(pname, site) self.__set_hero_name(pname, site)
@ -236,6 +263,13 @@ class Filters(threading.Thread):
self.heroes[site] = w.get_text() self.heroes[site] = w.get_text()
# print "DEBUG: setting heroes[%s]: %s"%(site, self.heroes[site]) # print "DEBUG: setting heroes[%s]: %s"%(site, self.heroes[site])
def __set_num_hands(self, w, val):
try:
self.numHands = int(w.get_text())
except:
self.numHands = 0
# print "DEBUG: setting numHands:", self.numHands
def createSiteLine(self, hbox, site): def createSiteLine(self, hbox, site):
cb = gtk.CheckButton(site) cb = gtk.CheckButton(site)
cb.connect('clicked', self.__set_site_select, site) cb.connect('clicked', self.__set_site_select, site)
@ -269,21 +303,99 @@ class Filters(threading.Thread):
#print w.get_active() #print w.get_active()
self.limits[limit] = w.get_active() self.limits[limit] = w.get_active()
print "self.limit[%s] set to %s" %(limit, self.limits[limit]) print "self.limit[%s] set to %s" %(limit, self.limits[limit])
if str(limit).isdigit(): if limit.isdigit() or (len(limit) > 2 and limit[-2:] == 'nl'):
if self.limits[limit]: if self.limits[limit]:
if self.cbNoLimits != None: if self.cbNoLimits != None:
self.cbNoLimits.set_active(False) self.cbNoLimits.set_active(False)
else: else:
if self.cbAllLimits != None: if self.cbAllLimits != None:
self.cbAllLimits.set_active(False) self.cbAllLimits.set_active(False)
if not self.limits[limit]:
if limit.isdigit():
self.cbFL.set_active(False)
else:
self.cbNL.set_active(False)
elif limit == "all": elif limit == "all":
if self.limits[limit]: if self.limits[limit]:
for cb in self.cbLimits.values(): #for cb in self.cbLimits.values():
cb.set_active(True) # cb.set_active(True)
if self.cbFL != None:
self.cbFL.set_active(True)
if self.cbNL != None:
self.cbNL.set_active(True)
elif limit == "none": elif limit == "none":
if self.limits[limit]: if self.limits[limit]:
for cb in self.cbLimits.values(): for cb in self.cbLimits.values():
cb.set_active(False) cb.set_active(False)
self.cbNL.set_active(False)
self.cbFL.set_active(False)
elif limit == "fl":
if not self.limits[limit]:
# only toggle all fl limits off if they are all currently on
# this stops turning one off from cascading into 'fl' box off
# and then all fl limits being turned off
all_fl_on = True
for cb in self.cbLimits.values():
t = cb.get_children()[0].get_text()
if t.isdigit():
if not cb.get_active():
all_fl_on = False
found = {'ring':False, 'tour':False}
for cb in self.cbLimits.values():
#print "cb label: ", cb.children()[0].get_text()
t = cb.get_children()[0].get_text()
if t.isdigit():
if self.limits[limit] or all_fl_on:
cb.set_active(self.limits[limit])
found[self.types[t]] = True
if self.limits[limit]:
if not found[self.type]:
if self.type == 'ring':
if 'tour' in self.rb:
self.rb['tour'].set_active(True)
elif self.type == 'tour':
if 'ring' in self.rb:
self.rb['ring'].set_active(True)
elif limit == "nl":
if not self.limits[limit]:
# only toggle all nl limits off if they are all currently on
# this stops turning one off from cascading into 'nl' box off
# and then all nl limits being turned off
all_nl_on = True
for cb in self.cbLimits.values():
t = cb.get_children()[0].get_text()
if "nl" in t and len(t) > 2:
if not cb.get_active():
all_nl_on = False
found = {'ring':False, 'tour':False}
for cb in self.cbLimits.values():
t = cb.get_children()[0].get_text()
if "nl" in t and len(t) > 2:
if self.limits[limit] or all_nl_on:
cb.set_active(self.limits[limit])
found[self.types[t]] = True
if self.limits[limit]:
if not found[self.type]:
if self.type == 'ring':
self.rb['tour'].set_active(True)
elif self.type == 'tour':
self.rb['ring'].set_active(True)
elif limit == "ring":
print "set", limit, "to", self.limits[limit]
if self.limits[limit]:
self.type = "ring"
for cb in self.cbLimits.values():
#print "cb label: ", cb.children()[0].get_text()
if self.types[cb.get_children()[0].get_text()] == 'tour':
cb.set_active(False)
elif limit == "tour":
print "set", limit, "to", self.limits[limit]
if self.limits[limit]:
self.type = "tour"
for cb in self.cbLimits.values():
#print "cb label: ", cb.children()[0].get_text()
if self.types[cb.get_children()[0].get_text()] == 'ring':
cb.set_active(False)
def __set_seat_select(self, w, seat): def __set_seat_select(self, w, seat):
#print "__set_seat_select: seat =", seat, "active =", w.get_active() #print "__set_seat_select: seat =", seat, "active =", w.get_active()
@ -295,13 +407,32 @@ class Filters(threading.Thread):
self.groups[group] = w.get_active() self.groups[group] = w.get_active()
print "self.groups[%s] set to %s" %(group, self.groups[group]) print "self.groups[%s] set to %s" %(group, self.groups[group])
def fillPlayerFrame(self, vbox): def fillPlayerFrame(self, vbox, display):
for site in self.conf.get_supported_sites(): for site in self.conf.get_supported_sites():
pathHBox = gtk.HBox(False, 0) hBox = gtk.HBox(False, 0)
vbox.pack_start(pathHBox, False, True, 0) vbox.pack_start(hBox, False, True, 0)
player = self.conf.supported_sites[site].screen_name player = self.conf.supported_sites[site].screen_name
self.createPlayerLine(pathHBox, site, player) self.createPlayerLine(hBox, site, player)
if "GroupsAll" in display and display["GroupsAll"] == True:
hbox = gtk.HBox(False, 0)
vbox.pack_start(hbox, False, False, 0)
cb = gtk.CheckButton(self.filterText['groupsall'])
cb.connect('clicked', self.__set_group_select, 'allplayers')
hbox.pack_start(cb, False, False, 0)
self.sbGroups['allplayers'] = cb
self.groups['allplayers'] = False
lbl = gtk.Label('Min # Hands:')
lbl.set_alignment(xalign=1.0, yalign=0.5)
hbox.pack_start(lbl, expand=True, padding=3)
phands = gtk.Entry()
phands.set_text('0')
phands.set_width_chars(8)
hbox.pack_start(phands, False, False, 0)
phands.connect("changed", self.__set_num_hands, site)
def fillSitesFrame(self, vbox): def fillSitesFrame(self, vbox):
for site in self.conf.get_supported_sites(): for site in self.conf.get_supported_sites():
@ -328,22 +459,23 @@ class Filters(threading.Thread):
print "INFO: No games returned from database" print "INFO: No games returned from database"
def fillLimitsFrame(self, vbox, display): def fillLimitsFrame(self, vbox, display):
hbox = gtk.HBox(False, 0) top_hbox = gtk.HBox(False, 0)
vbox.pack_start(hbox, False, False, 0) vbox.pack_start(top_hbox, False, False, 0)
lbl_title = gtk.Label(self.filterText['limitstitle']) lbl_title = gtk.Label(self.filterText['limitstitle'])
lbl_title.set_alignment(xalign=0.0, yalign=0.5) lbl_title.set_alignment(xalign=0.0, yalign=0.5)
hbox.pack_start(lbl_title, expand=True, padding=3) top_hbox.pack_start(lbl_title, expand=True, padding=3)
showb = gtk.Button(label="hide", stock=None, use_underline=True) showb = gtk.Button(label="hide", stock=None, use_underline=True)
showb.set_alignment(xalign=1.0, yalign=0.5) showb.set_alignment(xalign=1.0, yalign=0.5)
showb.connect('clicked', self.__toggle_box, 'limits') showb.connect('clicked', self.__toggle_box, 'limits')
hbox.pack_start(showb, expand=False, padding=1)
vbox1 = gtk.VBox(False, 0) vbox1 = gtk.VBox(False, 0)
vbox.pack_start(vbox1, False, False, 0) vbox.pack_start(vbox1, False, False, 0)
self.boxes['limits'] = vbox1 self.boxes['limits'] = vbox1
self.cursor.execute(self.sql.query['getLimits']) self.cursor.execute(self.sql.query['getLimits2'])
# selects limitType, bigBlind
result = self.db.cursor.fetchall() result = self.db.cursor.fetchall()
fl, nl = False, False
if len(result) >= 1: if len(result) >= 1:
hbox = gtk.HBox(True, 0) hbox = gtk.HBox(True, 0)
vbox1.pack_start(hbox, False, False, 0) vbox1.pack_start(hbox, False, False, 0)
@ -351,26 +483,72 @@ class Filters(threading.Thread):
hbox.pack_start(vbox2, False, False, 0) hbox.pack_start(vbox2, False, False, 0)
vbox3 = gtk.VBox(False, 0) vbox3 = gtk.VBox(False, 0)
hbox.pack_start(vbox3, False, False, 0) hbox.pack_start(vbox3, False, False, 0)
found = {'nl':False, 'fl':False, 'ring':False, 'tour':False}
for i, line in enumerate(result): for i, line in enumerate(result):
if "UseType" in self.display:
if line[0] != self.display["UseType"]:
continue
hbox = gtk.HBox(False, 0) hbox = gtk.HBox(False, 0)
if i <= len(result)/2: if i <= len(result)/2:
vbox2.pack_start(hbox, False, False, 0) vbox2.pack_start(hbox, False, False, 0)
else: else:
vbox3.pack_start(hbox, False, False, 0) vbox3.pack_start(hbox, False, False, 0)
self.cbLimits[line[0]] = self.createLimitLine(hbox, line[0], line[0]) if line[1] == 'fl':
name = str(line[2])
found['fl'] = True
else:
name = str(line[2])+line[1]
found['nl'] = True
self.cbLimits[name] = self.createLimitLine(hbox, name, name)
self.types[name] = line[0]
found[line[0]] = True # type is ring/tour
self.type = line[0] # if only one type, set it now
if "LimitSep" in display and display["LimitSep"] == True and len(result) >= 2: if "LimitSep" in display and display["LimitSep"] == True and len(result) >= 2:
hbox = gtk.HBox(True, 0)
vbox1.pack_start(hbox, False, False, 0)
vbox2 = gtk.VBox(False, 0)
hbox.pack_start(vbox2, False, False, 0)
vbox3 = gtk.VBox(False, 0)
hbox.pack_start(vbox3, False, False, 0)
hbox = gtk.HBox(False, 0) hbox = gtk.HBox(False, 0)
vbox1.pack_start(hbox, False, True, 0) vbox2.pack_start(hbox, False, False, 0)
self.cbAllLimits = self.createLimitLine(hbox, 'all', self.filterText['limitsall']) self.cbAllLimits = self.createLimitLine(hbox, 'all', self.filterText['limitsall'])
hbox = gtk.HBox(False, 0) hbox = gtk.HBox(False, 0)
vbox1.pack_start(hbox, False, True, 0) vbox2.pack_start(hbox, False, False, 0)
self.cbNoLimits = self.createLimitLine(hbox, 'none', self.filterText['limitsnone']) self.cbNoLimits = self.createLimitLine(hbox, 'none', self.filterText['limitsnone'])
dest = vbox3 # for ring/tour buttons
if "LimitType" in display and display["LimitType"] == True and found['nl'] and found['fl']:
#if found['fl']:
hbox = gtk.HBox(False, 0) hbox = gtk.HBox(False, 0)
vbox1.pack_start(hbox, False, True, 0) vbox3.pack_start(hbox, False, False, 0)
cb = self.createLimitLine(hbox, 'show', self.filterText['limitsshow']) self.cbFL = self.createLimitLine(hbox, 'fl', self.filterText['limitsFL'])
#if found['nl']:
hbox = gtk.HBox(False, 0)
vbox3.pack_start(hbox, False, False, 0)
self.cbNL = self.createLimitLine(hbox, 'nl', self.filterText['limitsNL'])
dest = vbox2 # for ring/tour buttons
else: else:
print "INFO: No games returned from database" print "INFO: No games returned from database"
if "Type" in display and display["Type"] == True and found['ring'] and found['tour']:
rb1 = gtk.RadioButton(None, self.filterText['ring'])
rb1.connect('clicked', self.__set_limit_select, 'ring')
rb2 = gtk.RadioButton(rb1, self.filterText['tour'])
rb2.connect('clicked', self.__set_limit_select, 'tour')
top_hbox.pack_start(rb1, False, False, 0) # (child, expand, fill, padding)
top_hbox.pack_start(rb2, True, True, 0) # child uses expand space if fill is true
self.rb['ring'] = rb1
self.rb['tour'] = rb2
#print "about to set ring to true"
rb1.set_active(True)
# set_active doesn't seem to call this for some reason so call manually:
self.__set_limit_select(rb1, 'ring')
self.type = 'ring'
top_hbox.pack_start(showb, expand=False, padding=1)
def fillSeatsFrame(self, vbox, display): def fillSeatsFrame(self, vbox, display):
hbox = gtk.HBox(False, 0) hbox = gtk.HBox(False, 0)
vbox.pack_start(hbox, False, False, 0) vbox.pack_start(hbox, False, False, 0)
@ -401,15 +579,6 @@ class Filters(threading.Thread):
hbox.pack_start(lbl_to, expand=False, padding=3) hbox.pack_start(lbl_to, expand=False, padding=3)
hbox.pack_start(sb2, False, False, 0) hbox.pack_start(sb2, False, False, 0)
if "SeatSep" in display and display["SeatSep"] == True:
hbox = gtk.HBox(False, 0)
vbox1.pack_start(hbox, False, True, 0)
cb = gtk.CheckButton(self.filterText['seatsshow'])
cb.connect('clicked', self.__set_seat_select, 'show')
hbox.pack_start(cb, False, False, 0)
self.sbSeats['show'] = cb
self.seats['show'] = False
self.sbSeats['from'] = sb1 self.sbSeats['from'] = sb1
self.sbSeats['to'] = sb2 self.sbSeats['to'] = sb2
@ -429,14 +598,26 @@ class Filters(threading.Thread):
self.boxes['groups'] = vbox1 self.boxes['groups'] = vbox1
hbox = gtk.HBox(False, 0) hbox = gtk.HBox(False, 0)
vbox1.pack_start(hbox, False, True, 0) vbox1.pack_start(hbox, False, False, 0)
cb = self.createLimitLine(hbox, 'show', self.filterText['limitsshow'])
hbox = gtk.HBox(False, 0)
vbox1.pack_start(hbox, False, True, 0)
cb = gtk.CheckButton(self.filterText['posnshow']) cb = gtk.CheckButton(self.filterText['posnshow'])
cb.connect('clicked', self.__set_group_select, 'posn') cb.connect('clicked', self.__set_group_select, 'posn')
hbox.pack_start(cb, False, False, 0) hbox.pack_start(cb, False, False, 0)
self.sbGroups['posn'] = cb self.sbGroups['posn'] = cb
self.groups['posn'] = False self.groups['posn'] = False
if "SeatSep" in display and display["SeatSep"] == True:
hbox = gtk.HBox(False, 0)
vbox1.pack_start(hbox, False, True, 0)
cb = gtk.CheckButton(self.filterText['seatsshow'])
cb.connect('clicked', self.__set_seat_select, 'show')
hbox.pack_start(cb, False, False, 0)
self.sbSeats['show'] = cb
self.seats['show'] = False
def fillCardsFrame(self, vbox): def fillCardsFrame(self, vbox):
hbox1 = gtk.HBox(True,0) hbox1 = gtk.HBox(True,0)
hbox1.show() hbox1.show()

View File

@ -40,21 +40,6 @@ class GuiBulkImport():
# CONFIGURATION - update these as preferred: # CONFIGURATION - update these as preferred:
allowThreads = True # set to True to try out the threads field allowThreads = True # set to True to try out the threads field
# not used
def import_dir(self):
"""imports a directory, non-recursive. todo: move this to fpdb_import so CLI can use it"""
self.path = self.inputFile
self.importer.addImportDirectory(self.path)
self.importer.setCallHud(False)
starttime = time()
if not self.importer.settings['threads'] > 1:
(stored, dups, partial, errs, ttime) = self.importer.runImport()
print 'GuiBulkImport.import_dir done: Stored: %d Duplicates: %d Partial: %d Errors: %d in %s seconds - %d/sec'\
% (stored, dups, partial, errs, ttime, stored / ttime)
else:
self.importer.RunImportThreaded()
def dopulse(self): def dopulse(self):
self.progressbar.pulse() self.progressbar.pulse()
return True return True
@ -77,7 +62,7 @@ class GuiBulkImport():
self.timer = gobject.timeout_add(100, self.dopulse) self.timer = gobject.timeout_add(100, self.dopulse)
# get the dir to import from the chooser # get the dir to import from the chooser
self.inputFile = self.chooser.get_filename() selected = self.chooser.get_filenames()
# get the import settings from the gui and save in the importer # get the import settings from the gui and save in the importer
self.importer.setHandCount(int(self.spin_hands.get_text())) self.importer.setHandCount(int(self.spin_hands.get_text()))
@ -103,7 +88,8 @@ class GuiBulkImport():
self.importer.setDropHudCache("auto") self.importer.setDropHudCache("auto")
sitename = self.cbfilter.get_model()[self.cbfilter.get_active()][0] sitename = self.cbfilter.get_model()[self.cbfilter.get_active()][0]
self.importer.addBulkImportImportFileOrDir(self.inputFile, site = sitename) for selection in selected:
self.importer.addBulkImportImportFileOrDir(selection, site = sitename)
self.importer.setCallHud(False) self.importer.setCallHud(False)
starttime = time() starttime = time()
# try: # try:
@ -151,6 +137,7 @@ class GuiBulkImport():
self.chooser = gtk.FileChooserWidget() self.chooser = gtk.FileChooserWidget()
self.chooser.set_filename(self.settings['bulkImport-defaultPath']) self.chooser.set_filename(self.settings['bulkImport-defaultPath'])
self.chooser.set_select_multiple(True)
self.vbox.add(self.chooser) self.vbox.add(self.chooser)
self.chooser.show() self.chooser.show()
@ -317,8 +304,20 @@ def main(argv=None):
help="If this option is passed it quits when it encounters any error") help="If this option is passed it quits when it encounters any error")
parser.add_option("-m", "--minPrint", "--status", dest="minPrint", default="0", type="int", 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)") 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, sys.argv) = parser.parse_args(args = argv)
if options.usage == True:
#Print usage examples and exit
print "USAGE:"
print 'PokerStars converter: ./GuiBulkImport -c PokerStars -f filename'
print 'Full Tilt converter: ./GuiBulkImport -c "Full Tilt Poker" -f filename'
print "Everleaf converter: ./GuiBulkImport -c Everleaf -f filename"
print "Absolute converter: ./GuiBulkImport -c Absolute -f filename"
print "PartyPoker converter: ./GuiBulkImport -c PartyPoker -f filename"
sys.exit(0)
config = Configuration.Config() config = Configuration.Config()
settings = {} settings = {}
@ -350,8 +349,10 @@ def main(argv=None):
importer.setThreads(-1) importer.setThreads(-1)
importer.addBulkImportImportFileOrDir(os.path.expanduser(options.filename), site=options.filtername) importer.addBulkImportImportFileOrDir(os.path.expanduser(options.filename), site=options.filtername)
importer.setCallHud(False) importer.setCallHud(False)
importer.runImport() (stored, dups, partial, errs, ttime) = importer.runImport()
importer.clearFileList() importer.clearFileList()
print 'GuiBulkImport done: Stored: %d \tDuplicates: %d \tPartial: %d \tErrors: %d in %s seconds - %.0f/sec'\
% (stored, dups, partial, errs, ttime, (stored+0.0) / ttime)
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -57,16 +57,22 @@ class GuiGraphViewer (threading.Thread):
"Sites" : True, "Sites" : True,
"Games" : True, "Games" : True,
"Limits" : True, "Limits" : True,
"LimitSep" : True,
"LimitType" : True,
"Type" : False,
"UseType" : 'ring',
"Seats" : False, "Seats" : False,
"SeatSep" : False,
"Dates" : True, "Dates" : True,
"Groups" : False,
"Button1" : True, "Button1" : True,
"Button2" : True "Button2" : True
} }
self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display) self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display)
self.filters.registerButton1Name("Refresh Graph") self.filters.registerButton1Name("Refresh _Graph")
self.filters.registerButton1Callback(self.generateGraph) self.filters.registerButton1Callback(self.generateGraph)
self.filters.registerButton2Name("Export to File") self.filters.registerButton2Name("_Export to File")
self.filters.registerButton2Callback(self.exportGraph) self.filters.registerButton2Callback(self.exportGraph)
self.mainHBox = gtk.HBox(False, 0) self.mainHBox = gtk.HBox(False, 0)
@ -146,10 +152,8 @@ class GuiGraphViewer (threading.Thread):
raise raise
def generateGraph(self, widget, data): def generateGraph(self, widget, data):
print "generateGraph: start"
try: try:
self.clearGraphData() self.clearGraphData()
print "after cleardata"
sitenos = [] sitenos = []
playerids = [] playerids = []
@ -158,15 +162,18 @@ class GuiGraphViewer (threading.Thread):
heroes = self.filters.getHeroes() heroes = self.filters.getHeroes()
siteids = self.filters.getSiteIds() siteids = self.filters.getSiteIds()
limits = self.filters.getLimits() limits = self.filters.getLimits()
print "got filter data" for i in ('show', 'none'):
if i in limits:
limits.remove(i)
# Which sites are selected? # Which sites are selected?
for site in sites: for site in sites:
if sites[site] == True: if sites[site] == True:
sitenos.append(siteids[site]) sitenos.append(siteids[site])
self.db.cursor.execute(self.sql.query['getPlayerId'], (heroes[site],)) c = self.db.get_cursor()
result = self.db.cursor.fetchall() c.execute(self.sql.query['getPlayerId'], (heroes[site],))
result = c.fetchall()
if len(result) == 1: if len(result) == 1:
playerids.append(result[0][0]) playerids.append( int(result[0][0]) )
if not sitenos: if not sitenos:
#Should probably pop up here. #Should probably pop up here.
@ -182,12 +189,10 @@ class GuiGraphViewer (threading.Thread):
return return
#Set graph properties #Set graph properties
print "add_subplot"
self.ax = self.fig.add_subplot(111) self.ax = self.fig.add_subplot(111)
#Get graph data from DB #Get graph data from DB
starttime = time() starttime = time()
print "get line: playerids =", playerids, "sitenos =", sitenos, "limits =", limits
line = self.getRingProfitGraph(playerids, sitenos, limits) line = self.getRingProfitGraph(playerids, sitenos, limits)
print "Graph generated in: %s" %(time() - starttime) print "Graph generated in: %s" %(time() - starttime)
@ -234,12 +239,31 @@ class GuiGraphViewer (threading.Thread):
# [5L] into (5) not (5,) and [5L, 2829L] into (5, 2829) # [5L] into (5) not (5,) and [5L, 2829L] into (5, 2829)
nametest = str(tuple(names)) nametest = str(tuple(names))
sitetest = str(tuple(sites)) sitetest = str(tuple(sites))
limittest = str(tuple(limits)) #nametest = nametest.replace("L", "")
nametest = nametest.replace("L", "")
nametest = nametest.replace(",)",")") lims = [int(x) for x in limits if x.isdigit()]
sitetest = sitetest.replace(",)",")") nolims = [int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'nl']
limittest = limittest.replace("L", "") limittest = "and ( (gt.limitType = 'fl' and gt.bigBlind in "
limittest = limittest.replace(",)",")") # and ( (limit and bb in()) or (nolimit and bb in ()) )
if lims:
blindtest = str(tuple(lims))
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))
blindtest = blindtest.replace("L", "")
blindtest = blindtest.replace(",)",")")
limittest = limittest + blindtest + ' ) )'
else:
limittest = limittest + '(-1) ) )'
if type == 'ring':
limittest = limittest + " and gt.type = 'ring' "
elif type == 'tour':
limittest = limittest + " and gt.type = 'tour' "
#Must be a nicer way to deal with tuples of size 1 ie. (2,) - which makes sql barf #Must be a nicer way to deal with tuples of size 1 ie. (2,) - which makes sql barf
tmp = tmp.replace("<player_test>", nametest) tmp = tmp.replace("<player_test>", nametest)
@ -247,6 +271,7 @@ class GuiGraphViewer (threading.Thread):
tmp = tmp.replace("<startdate_test>", start_date) tmp = tmp.replace("<startdate_test>", start_date)
tmp = tmp.replace("<enddate_test>", end_date) tmp = tmp.replace("<enddate_test>", end_date)
tmp = tmp.replace("<limit_test>", limittest) tmp = tmp.replace("<limit_test>", limittest)
tmp = tmp.replace(",)", ")")
#print "DEBUG: sql query:" #print "DEBUG: sql query:"
#print tmp #print tmp
@ -255,10 +280,10 @@ class GuiGraphViewer (threading.Thread):
winnings = self.db.cursor.fetchall() winnings = self.db.cursor.fetchall()
self.db.rollback() self.db.rollback()
if(winnings == ()): if winnings == ():
return None return None
y=map(lambda x:float(x[3]), winnings) y = map(lambda x:float(x[1]), winnings)
line = cumsum(y) line = cumsum(y)
return line/100 return line/100
#end of def getRingProfitGraph #end of def getRingProfitGraph

View File

@ -59,10 +59,13 @@ class GuiPlayerStats (threading.Thread):
"Games" : False, "Games" : False,
"Limits" : True, "Limits" : True,
"LimitSep" : True, "LimitSep" : True,
"LimitType" : True,
"Type" : True,
"Seats" : True, "Seats" : True,
"SeatSep" : True, "SeatSep" : True,
"Dates" : True, "Dates" : True,
"Groups" : True, "Groups" : True,
"GroupsAll" : True,
"Button1" : True, "Button1" : True,
"Button2" : True "Button2" : True
} }
@ -80,6 +83,7 @@ class GuiPlayerStats (threading.Thread):
self.columns = [ ["game", True, "Game", 0.0, "%s"] self.columns = [ ["game", True, "Game", 0.0, "%s"]
, ["hand", False, "Hand", 0.0, "%s"] # true not allowed for this line , ["hand", False, "Hand", 0.0, "%s"] # true not allowed for this line
, ["plposition", False, "Posn", 1.0, "%s"] # true not allowed for this line (set in code) , ["plposition", False, "Posn", 1.0, "%s"] # true not allowed for this line (set in code)
, ["pname", False, "Name", 0.0, "%s"] # true not allowed for this line (set in code)
, ["n", True, "Hds", 1.0, "%d"] , ["n", True, "Hds", 1.0, "%d"]
, ["avgseats", False, "Seats", 1.0, "%3.1f"] , ["avgseats", False, "Seats", 1.0, "%3.1f"]
, ["vpip", True, "VPIP", 1.0, "%3.1f"] , ["vpip", True, "VPIP", 1.0, "%3.1f"]
@ -123,8 +127,9 @@ class GuiPlayerStats (threading.Thread):
self.stats_vbox = None self.stats_vbox = None
self.detailFilters = [] # the data used to enhance the sql select self.detailFilters = [] # the data used to enhance the sql select
self.main_hbox = gtk.HBox(False, 0) #self.main_hbox = gtk.HBox(False, 0)
self.main_hbox.show() #self.main_hbox.show()
self.main_hbox = gtk.HPaned()
self.stats_frame = gtk.Frame() self.stats_frame = gtk.Frame()
self.stats_frame.show() self.stats_frame.show()
@ -134,8 +139,11 @@ class GuiPlayerStats (threading.Thread):
self.stats_frame.add(self.stats_vbox) self.stats_frame.add(self.stats_vbox)
# self.fillStatsFrame(self.stats_vbox) # self.fillStatsFrame(self.stats_vbox)
self.main_hbox.pack_start(self.filters.get_vbox()) #self.main_hbox.pack_start(self.filters.get_vbox())
self.main_hbox.pack_start(self.stats_frame, expand=True, fill=True) #self.main_hbox.pack_start(self.stats_frame, expand=True, fill=True)
self.main_hbox.pack1(self.filters.get_vbox())
self.main_hbox.pack2(self.stats_frame)
self.main_hbox.show()
# make sure Hand column is not displayed # make sure Hand column is not displayed
[x for x in self.columns if x[0] == 'hand'][0][1] = False [x for x in self.columns if x[0] == 'hand'][0][1] = False
@ -147,7 +155,8 @@ class GuiPlayerStats (threading.Thread):
def refreshStats(self, widget, data): def refreshStats(self, widget, data):
try: self.stats_vbox.destroy() try: self.stats_vbox.destroy()
except AttributeError: pass except AttributeError: pass
self.stats_vbox = gtk.VBox(False, 0) #self.stats_vbox = gtk.VBox(False, 0)
self.stats_vbox = gtk.VPaned()
self.stats_vbox.show() self.stats_vbox.show()
self.stats_frame.add(self.stats_vbox) self.stats_frame.add(self.stats_vbox)
self.fillStatsFrame(self.stats_vbox) self.fillStatsFrame(self.stats_vbox)
@ -157,6 +166,7 @@ class GuiPlayerStats (threading.Thread):
heroes = self.filters.getHeroes() heroes = self.filters.getHeroes()
siteids = self.filters.getSiteIds() siteids = self.filters.getSiteIds()
limits = self.filters.getLimits() limits = self.filters.getLimits()
type = self.filters.getType()
seats = self.filters.getSeats() seats = self.filters.getSeats()
groups = self.filters.getGroups() groups = self.filters.getGroups()
dates = self.filters.getDates() dates = self.filters.getDates()
@ -185,45 +195,47 @@ class GuiPlayerStats (threading.Thread):
print "No limits found" print "No limits found"
return return
self.createStatsTable(vbox, playerids, sitenos, limits, seats, groups, dates) self.createStatsTable(vbox, playerids, sitenos, limits, type, seats, groups, dates)
def createStatsTable(self, vbox, playerids, sitenos, limits, seats, groups, dates): def createStatsTable(self, vbox, playerids, sitenos, limits, type, seats, groups, dates):
starttime = time() starttime = time()
# Scrolled window for summary table
swin = gtk.ScrolledWindow(hadjustment=None, vadjustment=None)
swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
swin.show()
vbox.pack1(swin)
# Display summary table at top of page # Display summary table at top of page
# 3rd parameter passes extra flags, currently includes: # 3rd parameter passes extra flags, currently includes:
# holecards - whether to display card breakdown (True/False) # holecards - whether to display card breakdown (True/False)
flags = [False] # numhands - min number hands required when displaying all players
self.addTable(vbox, 'playerDetailedStats', flags, playerids, sitenos, limits, seats, groups, dates) flags = [False, self.filters.getNumHands()]
self.addTable(swin, 'playerDetailedStats', flags, playerids, sitenos, limits, type, seats, groups, dates)
# Separator # Separator
sep = gtk.HSeparator() vbox2 = gtk.VBox(False, 0)
vbox.pack_start(sep, expand=False, padding=3)
sep.show_now()
vbox.show_now()
heading = gtk.Label(self.filterText['handhead']) heading = gtk.Label(self.filterText['handhead'])
heading.show() heading.show()
vbox.pack_start(heading, expand=False, padding=3) vbox2.pack_start(heading, expand=False, padding=3)
# Scrolled window for detailed table (display by hand) # Scrolled window for detailed table (display by hand)
swin = gtk.ScrolledWindow(hadjustment=None, vadjustment=None) swin = gtk.ScrolledWindow(hadjustment=None, vadjustment=None)
swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
swin.show() swin.show()
vbox.pack_start(swin, expand=True, padding=3) vbox2.pack_start(swin, expand=True, padding=3)
vbox.pack2(vbox2)
vbox1 = gtk.VBox(False, 0) vbox2.show()
vbox1.show()
swin.add_with_viewport(vbox1)
# Detailed table # Detailed table
flags = [True] flags[0] = True
self.addTable(vbox1, 'playerDetailedStats', flags, playerids, sitenos, limits, seats, groups, dates) self.addTable(swin, 'playerDetailedStats', flags, playerids, sitenos, limits, type, seats, groups, dates)
self.db.rollback() self.db.rollback()
print "Stats page displayed in %4.2f seconds" % (time() - starttime) print "Stats page displayed in %4.2f seconds" % (time() - starttime)
#end def fillStatsFrame(self, vbox): #end def fillStatsFrame(self, vbox):
def addTable(self, vbox, query, flags, playerids, sitenos, limits, seats, groups, dates): def addTable(self, vbox, query, flags, playerids, sitenos, limits, type, seats, groups, dates):
row = 0 row = 0
sqlrow = 0 sqlrow = 0
colalias,colshow,colheading,colxalign,colformat = 0,1,2,3,4 colalias,colshow,colheading,colxalign,colformat = 0,1,2,3,4
@ -231,7 +243,7 @@ class GuiPlayerStats (threading.Thread):
else: holecards = flags[0] else: holecards = flags[0]
tmp = self.sql.query[query] tmp = self.sql.query[query]
tmp = self.refineQuery(tmp, flags, playerids, sitenos, limits, seats, groups, dates) tmp = self.refineQuery(tmp, flags, playerids, sitenos, limits, type, seats, groups, dates)
self.cursor.execute(tmp) self.cursor.execute(tmp)
result = self.cursor.fetchall() result = self.cursor.fetchall()
colnames = [desc[0].lower() for desc in self.cursor.description] colnames = [desc[0].lower() for desc in self.cursor.description]
@ -243,7 +255,8 @@ class GuiPlayerStats (threading.Thread):
liststore = gtk.ListStore(*([str] * len(cols_to_show))) liststore = gtk.ListStore(*([str] * len(cols_to_show)))
view = gtk.TreeView(model=liststore) view = gtk.TreeView(model=liststore)
view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH) view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH)
vbox.pack_start(view, expand=False, padding=3) #vbox.pack_start(view, expand=False, padding=3)
vbox.add(view)
textcell = gtk.CellRendererText() textcell = gtk.CellRendererText()
textcell50 = gtk.CellRendererText() textcell50 = gtk.CellRendererText()
textcell50.set_property('xalign', 0.5) textcell50.set_property('xalign', 0.5)
@ -317,19 +330,45 @@ class GuiPlayerStats (threading.Thread):
row += 1 row += 1
vbox.show_all() vbox.show_all()
#end def addTable(self, query, vars, playerids, sitenos, limits, seats): #end def addTable(self, query, vars, playerids, sitenos, limits, type, seats, groups, dates):
def refineQuery(self, query, flags, playerids, sitenos, limits, seats, groups, dates): def refineQuery(self, query, flags, playerids, sitenos, limits, type, seats, groups, dates):
if not flags: holecards = False having = ''
else: holecards = flags[0] if not flags:
holecards = False
numhands = 0
else:
holecards = flags[0]
numhands = flags[1]
if 'allplayers' in groups and groups['allplayers']:
nametest = "(hp.playerId)"
if holecards or groups['posn']:
pname = "'all players'"
# set flag in self.columns to not show player name column
[x for x in self.columns if x[0] == 'pname'][0][1] = False
# can't do this yet (re-write doing more maths in python instead of sql?)
if numhands:
nametest = "(-1)"
else:
pname = "p.name"
# set flag in self.columns to show player name column
[x for x in self.columns if x[0] == 'pname'][0][1] = True
if numhands:
having = ' and count(1) > %d ' % (numhands,)
else:
if playerids: if playerids:
nametest = str(tuple(playerids)) nametest = str(tuple(playerids))
nametest = nametest.replace("L", "") nametest = nametest.replace("L", "")
nametest = nametest.replace(",)",")") nametest = nametest.replace(",)",")")
query = query.replace("<player_test>", nametest)
else: else:
query = query.replace("<player_test>", "1 = 2") nametest = "1 = 2"
pname = "p.name"
# set flag in self.columns to not show player name column
[x for x in self.columns if x[0] == 'pname'][0][1] = False
query = query.replace("<player_test>", nametest)
query = query.replace("<playerName>", pname)
query = query.replace("<havingclause>", having)
if seats: if seats:
query = query.replace('<seats_test>', 'between ' + str(seats['from']) + ' and ' + str(seats['to'])) query = query.replace('<seats_test>', 'between ' + str(seats['from']) + ' and ' + str(seats['to']))
@ -344,17 +383,37 @@ class GuiPlayerStats (threading.Thread):
query = query.replace('<groupbyseats>', '') query = query.replace('<groupbyseats>', '')
query = query.replace('<orderbyseats>', '') query = query.replace('<orderbyseats>', '')
if [x for x in limits if str(x).isdigit()]: lims = [int(x) for x in limits if x.isdigit()]
blindtest = str(tuple([x for x in limits if str(x).isdigit()])) 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 ()) )
if lims:
blindtest = str(tuple(lims))
blindtest = blindtest.replace("L", "") blindtest = blindtest.replace("L", "")
blindtest = blindtest.replace(",)",")") blindtest = blindtest.replace(",)",")")
query = query.replace("<gtbigBlind_test>", " and gt.bigBlind in " + blindtest + " ") bbtest = bbtest + blindtest + ' ) '
else: else:
query = query.replace("<gtbigBlind_test>", "") bbtest = bbtest + '(-1) ) '
bbtest = bbtest + " or (gt.limitType = 'nl' and gt.bigBlind in "
if nolims:
blindtest = str(tuple(nolims))
blindtest = blindtest.replace("L", "")
blindtest = blindtest.replace(",)",")")
bbtest = bbtest + blindtest + ' ) )'
else:
bbtest = bbtest + '(-1) ) )'
if type == 'ring':
bbtest = bbtest + " and gt.type = 'ring' "
elif type == 'tour':
bbtest = bbtest + " and gt.type = 'tour' "
query = query.replace("<gtbigBlind_test>", bbtest)
if holecards: # pinch level variables for hole card query if holecards: # re-use level variables for hole card query
query = query.replace("<hgameTypeId>", "hp.startcards") query = query.replace("<hgameTypeId>", "hp.startcards")
query = query.replace("<orderbyhgameTypeId>", ",hgameTypeId desc") query = query.replace("<orderbyhgameTypeId>"
, ",case when floor(hp.startcards/13) >= mod(hp.startcards,13) then hp.startcards + 0.1 "
+ " else 13*mod(hp.startcards,13) + floor(hp.startcards/13) "
+ " end desc ")
else: else:
query = query.replace("<orderbyhgameTypeId>", "") query = query.replace("<orderbyhgameTypeId>", "")
groupLevels = "show" not in str(limits) groupLevels = "show" not in str(limits)

View File

@ -4,6 +4,98 @@
<import callFpdbHud = "True" interval = "10" fastStoreHudCache="False" hhArchiveBase="~/.fpdb/HandHistories/" saveActions="True"></import> <import callFpdbHud = "True" interval = "10" fastStoreHudCache="False" hhArchiveBase="~/.fpdb/HandHistories/" saveActions="True"></import>
<!-- These values need some explaining
aggregate_ring_game_stats :
- True/False
- if set to True, includes data from other blind levels
- defaults to False
aggregate_tourney_stats :
- True/False
- if set to True, includes data from other blind levels
- 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
The following values define how hero's stats are done
aggregate_hero_ring_game_stats :
- True/False
- if set to True, hero's data is 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
- 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
-->
<hud_ui
aggregate_ring_game_stats="False"
aggregate_tourney_stats="False"
stat_aggregation_range="A"
aggregation_days="90"
aggregation_level_multiplier="1"
aggregate_hero_ring_game_stats="False"
aggregate_hero_tourney_stats="True"
hero_stat_aggregation_range="S"
hero_aggregation_days="30"
hero_aggregation_level_multiplier="1"
label="FPDB Menu - Right-click
Left-Drag to Move"
/>
<supported_sites> <supported_sites>
<site enabled="True" <site enabled="True"
@ -293,6 +385,51 @@
<location seat="9" x="70" y="53"> </location> <location seat="9" x="70" y="53"> </location>
</layout> </layout>
</site> </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_sites>
<supported_games> <supported_games>
@ -429,6 +566,7 @@
<hhc site="Win2day" converter="Win2dayToFpdb"/> <hhc site="Win2day" converter="Win2dayToFpdb"/>
<hhc site="Absolute" converter="AbsoluteToFpdb"/> <hhc site="Absolute" converter="AbsoluteToFpdb"/>
<hhc site="PartyPoker" converter="PartyPokerToFpdb"/> <hhc site="PartyPoker" converter="PartyPokerToFpdb"/>
<hhc site="Betfair" converter="BetfairToFpdb"/>
</hhcs> </hhcs>
<supported_databases> <supported_databases>

View File

@ -59,9 +59,11 @@ import Hud
# HUD params: # 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 # - 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 how what levels are included, e.g. # - 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 100, almost all levels are included in all HUD displays
# if agg_bb_mult is 2.1, levels from half to double the current blind level are included in the HUD # 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 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 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_style to T to only see stats for the last N days (uses value in hud_days)
@ -71,14 +73,14 @@ def_hud_params = { # Settings for all players apart from program owner ('hero')
, 'aggregate_tour' : True , 'aggregate_tour' : True
, 'hud_style' : 'A' , 'hud_style' : 'A'
, 'hud_days' : 90 , 'hud_days' : 90
, 'agg_bb_mult' : 1 # 1 means no aggregation , 'agg_bb_mult' : 10000 # 1 means no aggregation
# , 'hud_session_gap' : 30 not currently used # , 'hud_session_gap' : 30 not currently used
# Second set of variables for hero - these settings only apply to the program owner # Second set of variables for hero - these settings only apply to the program owner
, 'h_aggregate_ring' : False , 'h_aggregate_ring' : False
, 'h_aggregate_tour' : True , 'h_aggregate_tour' : True
, 'h_hud_style' : 'S' # A(ll) / S(ession) / T(ime in days) , 'h_hud_style' : 'S' # A(ll) / S(ession) / T(ime in days)
, 'h_hud_days' : 30 , 'h_hud_days' : 60
, 'h_agg_bb_mult' : 1 # 1 means no aggregation , 'h_agg_bb_mult' : 10000 # 1 means no aggregation
# , 'h_hud_session_gap' : 30 not currently used # , 'h_hud_session_gap' : 30 not currently used
} }
@ -91,7 +93,7 @@ class HUD_main(object):
self.db_name = db_name self.db_name = db_name
self.config = Configuration.Config(file=options.config, dbname=options.dbname) self.config = Configuration.Config(file=options.config, dbname=options.dbname)
self.hud_dict = {} self.hud_dict = {}
self.hud_params = def_hud_params self.hud_params = self.config.get_hud_ui_parameters()
# a thread to read stdin # a thread to read stdin
gobject.threads_init() # this is required gobject.threads_init() # this is required

View File

@ -194,67 +194,36 @@ dealt whether they were seen in a 'dealt to' line
""" Function to insert Hand into database """ Function to insert Hand into database
Should not commit, and do minimal selects. Callers may want to cache commits Should not commit, and do minimal selects. Callers may want to cache commits
db: a connected fpdb_db object""" db: a connected fpdb_db object"""
# TODO:
#####
# Players, Gametypes, TourneyTypes are all shared functions that are needed for additional tables
# These functions are intended for prep insert eventually
#####
# Players - base playerid and siteid tuple # Players - base playerid and siteid tuple
sqlids = db.getSqlPlayerIDs([p[1] for p in self.players], self.siteId) sqlids = db.getSqlPlayerIDs([p[1] for p in self.players], self.siteId)
#Gametypes #Gametypes
gtid = db.getGameTypeId(self.siteId, self.gametype) gtid = db.getGameTypeId(self.siteId, self.gametype)
# HudCache data to come from DerivedStats class self.stats.getStats(self)
#####
# End prep functions
#####
# HandsActions - all actions for all players for all streets - self.actions # 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 # Hands - Summary information of hand indexed by handId - gameinfo
#This should be moved to prepInsert hh = self.stats.getHands()
hh = {}
hh['siteHandNo'] = self.handid
hh['handStart'] = self.starttime
hh['gameTypeId'] = gtid hh['gameTypeId'] = gtid
# seats TINYINT NOT NULL, # seats TINYINT NOT NULL,
hh['tableName'] = self.tablename
hh['maxSeats'] = self.maxseats
hh['seats'] = len(sqlids) hh['seats'] = len(sqlids)
# Flop turn and river may all be empty - add (likely) too many elements and trim with range
boardcards = self.board['FLOP'] + self.board['TURN'] + self.board['RIVER'] + [u'0x', u'0x', u'0x', u'0x', u'0x']
cards = [Card.encodeCard(c) for c in boardcards[0:5]]
hh['boardcard1'] = cards[0]
hh['boardcard2'] = cards[1]
hh['boardcard3'] = cards[2]
hh['boardcard4'] = cards[3]
hh['boardcard5'] = cards[4]
# texture smallint,
# playersVpi SMALLINT NOT NULL, /* num of players vpi */
# Needs to be recorded
# playersAtStreet1 SMALLINT NOT NULL, /* num of players seeing flop/street4 */
# Needs to be recorded
# playersAtStreet2 SMALLINT NOT NULL,
# Needs to be recorded
# playersAtStreet3 SMALLINT NOT NULL,
# Needs to be recorded
# playersAtStreet4 SMALLINT NOT NULL,
# Needs to be recorded
# playersAtShowdown SMALLINT NOT NULL,
# Needs to be recorded
# street0Raises TINYINT NOT NULL, /* num small bets paid to see flop/street4, including blind */
# Needs to be recorded
# street1Raises TINYINT NOT NULL, /* num small bets paid to see turn/street5 */
# Needs to be recorded
# street2Raises TINYINT NOT NULL, /* num big bets paid to see river/street6 */
# Needs to be recorded
# street3Raises TINYINT NOT NULL, /* num big bets paid to see sd/street7 */
# Needs to be recorded
# street4Raises TINYINT NOT NULL, /* num big bets paid to see showdown */
# Needs to be recorded
#print "DEBUG: self.getStreetTotals = (%s, %s, %s, %s, %s)" % self.getStreetTotals()
#FIXME: Pot size still in decimal, needs to be converted to cents
(hh['street1Pot'], hh['street2Pot'], hh['street3Pot'], hh['street4Pot'], hh['showdownPot']) = self.getStreetTotals()
# comment TEXT,
# commentTs DATETIME
#print hh #print hh
handid = db.storeHand(hh) handid = db.storeHand(hh)
# HandsPlayers - ? ... Do we fix winnings? # HandsPlayers - ? ... Do we fix winnings?
db.storeHandsPlayers(handid, sqlids, self.stats.getHandsPlayers())
# Tourneys ? # Tourneys ?
# TourneysPlayers # TourneysPlayers
@ -603,7 +572,11 @@ Map the tuple self.gametype onto the pokerstars string describing it
return gs + timestr return gs + timestr
def writeTableLine(self): def writeTableLine(self):
table_string = "Table \'%s\' %s-max" % (self.tablename, self.maxseats) table_string = "Table "
if self.gametype['type'] == 'tour':
table_string = table_string + "\'%s %s\' %s-max" % (self.tourNo, self.tablename, self.maxseats)
else:
table_string = table_string + "\'%s\' %s-max" % (self.tablename, self.maxseats)
if self.gametype['currency'] == 'play': if self.gametype['currency'] == 'play':
table_string = table_string + " (Play Money)" table_string = table_string + " (Play Money)"
if self.buttonpos != None and self.buttonpos != 0: if self.buttonpos != None and self.buttonpos != 0:

View File

@ -82,6 +82,7 @@ class Hud:
(font, font_size) = config.get_default_font(self.table.site) (font, font_size) = config.get_default_font(self.table.site)
self.colors = config.get_default_colors(self.table.site) self.colors = config.get_default_colors(self.table.site)
self.hud_ui = config.get_hud_ui_parameters()
self.backgroundcolor = gtk.gdk.color_parse(self.colors['hudbgcolor']) self.backgroundcolor = gtk.gdk.color_parse(self.colors['hudbgcolor'])
self.foregroundcolor = gtk.gdk.color_parse(self.colors['hudfgcolor']) self.foregroundcolor = gtk.gdk.color_parse(self.colors['hudfgcolor'])
@ -116,7 +117,7 @@ class Hud:
win.set_opacity(self.colors["hudopacity"]) win.set_opacity(self.colors["hudopacity"])
eventbox = gtk.EventBox() eventbox = gtk.EventBox()
label = gtk.Label("FPDB Menu - Right click\nLeft-Drag to Move") label = gtk.Label(self.hud_ui['label'])
win.add(eventbox) win.add(eventbox)
eventbox.add(label) eventbox.add(label)
@ -146,14 +147,65 @@ class Hud:
menu.append(repositem) menu.append(repositem)
repositem.connect("activate", self.reposition_windows) repositem.connect("activate", self.reposition_windows)
aggitem = gtk.MenuItem('Show Stats') aggitem = gtk.MenuItem('Show Player Stats')
menu.append(aggitem) menu.append(aggitem)
self.aggMenu = gtk.Menu() self.aggMenu = gtk.Menu()
aggitem.set_submenu(self.aggMenu) aggitem.set_submenu(self.aggMenu)
# set agg_bb_mult to 1 to stop aggregation # set agg_bb_mult to 1 to stop aggregation
item = gtk.CheckMenuItem('For This Blind Level Only') item = gtk.CheckMenuItem('For This Blind Level Only')
self.aggMenu.append(item) self.aggMenu.append(item)
item.connect("activate", self.set_aggregation, 1) item.connect("activate", self.set_aggregation, ('P',1))
setattr(self, 'h_aggBBmultItem1', item)
#
item = gtk.MenuItem('For Multiple Blind Levels:')
self.aggMenu.append(item)
#
item = gtk.CheckMenuItem(' 0.5 to 2.0 x Current Blinds')
self.aggMenu.append(item)
item.connect("activate", self.set_aggregation, ('P',2))
setattr(self, 'h_aggBBmultItem2', item)
#
item = gtk.CheckMenuItem(' 0.33 to 3.0 x Current Blinds')
self.aggMenu.append(item)
item.connect("activate", self.set_aggregation, ('P',3))
setattr(self, 'h_aggBBmultItem3', item)
#
item = gtk.CheckMenuItem(' 0.1 to 10 x Current Blinds')
self.aggMenu.append(item)
item.connect("activate", self.set_aggregation, ('P',10))
setattr(self, 'h_aggBBmultItem10', item)
#
item = gtk.CheckMenuItem(' All Levels')
self.aggMenu.append(item)
item.connect("activate", self.set_aggregation, ('P',10000))
setattr(self, 'h_aggBBmultItem10000', item)
#
item = gtk.MenuItem('Since:')
self.aggMenu.append(item)
#
item = gtk.CheckMenuItem(' All Time')
self.aggMenu.append(item)
item.connect("activate", self.set_hud_style, ('P','A'))
setattr(self, 'h_hudStyleOptionA', item)
#
item = gtk.CheckMenuItem(' Session')
self.aggMenu.append(item)
item.connect("activate", self.set_hud_style, ('P','S'))
setattr(self, 'h_hudStyleOptionS', item)
#
item = gtk.CheckMenuItem(' %s Days' % (self.hud_params['h_hud_days']))
self.aggMenu.append(item)
item.connect("activate", self.set_hud_style, ('P','T'))
setattr(self, 'h_hudStyleOptionT', item)
aggitem = gtk.MenuItem('Show Opponent Stats')
menu.append(aggitem)
self.aggMenu = gtk.Menu()
aggitem.set_submenu(self.aggMenu)
# set agg_bb_mult to 1 to stop aggregation
item = gtk.CheckMenuItem('For This Blind Level Only')
self.aggMenu.append(item)
item.connect("activate", self.set_aggregation, ('O',1))
setattr(self, 'aggBBmultItem1', item) setattr(self, 'aggBBmultItem1', item)
# #
item = gtk.MenuItem('For Multiple Blind Levels:') item = gtk.MenuItem('For Multiple Blind Levels:')
@ -161,44 +213,54 @@ class Hud:
# #
item = gtk.CheckMenuItem(' 0.5 to 2.0 x Current Blinds') item = gtk.CheckMenuItem(' 0.5 to 2.0 x Current Blinds')
self.aggMenu.append(item) self.aggMenu.append(item)
item.connect("activate", self.set_aggregation, 2) item.connect("activate", self.set_aggregation, ('O',2))
setattr(self, 'aggBBmultItem2', item) setattr(self, 'aggBBmultItem2', item)
# #
item = gtk.CheckMenuItem(' 0.33 to 3.0 x Current Blinds') item = gtk.CheckMenuItem(' 0.33 to 3.0 x Current Blinds')
self.aggMenu.append(item) self.aggMenu.append(item)
item.connect("activate", self.set_aggregation, 3) item.connect("activate", self.set_aggregation, ('O',3))
setattr(self, 'aggBBmultItem3', item) setattr(self, 'aggBBmultItem3', item)
# #
item = gtk.CheckMenuItem(' 0.1 to 10 x Current Blinds') item = gtk.CheckMenuItem(' 0.1 to 10 x Current Blinds')
self.aggMenu.append(item) self.aggMenu.append(item)
item.connect("activate", self.set_aggregation, 10) item.connect("activate", self.set_aggregation, ('O',10))
setattr(self, 'aggBBmultItem10', item) setattr(self, 'aggBBmultItem10', item)
# #
item = gtk.CheckMenuItem(' All Levels') item = gtk.CheckMenuItem(' All Levels')
self.aggMenu.append(item) self.aggMenu.append(item)
item.connect("activate", self.set_aggregation, 10000) item.connect("activate", self.set_aggregation, ('O',10000))
setattr(self, 'aggBBmultItem10000', item) setattr(self, 'aggBBmultItem10000', item)
# #
item = gtk.MenuItem('For Hero:') item = gtk.MenuItem('Since:')
self.aggMenu.append(item) self.aggMenu.append(item)
setattr(self, 'showStatsMenuItem7', item)
# #
item = gtk.CheckMenuItem(' All Time') item = gtk.CheckMenuItem(' All Time')
self.aggMenu.append(item) self.aggMenu.append(item)
item.connect("activate", self.set_hud_style, 'HA') item.connect("activate", self.set_hud_style, ('O','A'))
setattr(self, 'HAStyleOption', item) setattr(self, 'hudStyleOptionA', item)
# #
item = gtk.CheckMenuItem(' Session') item = gtk.CheckMenuItem(' Session')
self.aggMenu.append(item) self.aggMenu.append(item)
item.connect("activate", self.set_hud_style, 'HS') item.connect("activate", self.set_hud_style, ('O','S'))
setattr(self, 'HSStyleOption', item) setattr(self, 'hudStyleOptionS', item)
# #
item = gtk.CheckMenuItem(' %s Days' % (self.hud_params['h_hud_days'])) item = gtk.CheckMenuItem(' %s Days' % (self.hud_params['h_hud_days']))
self.aggMenu.append(item) self.aggMenu.append(item)
item.connect("activate", self.set_hud_style, 'HT') item.connect("activate", self.set_hud_style, ('O','T'))
setattr(self, 'HTStyleOption', item) setattr(self, 'hudStyleOptionT', item)
# set active on current options: # set active on current options:
if self.hud_params['h_agg_bb_mult'] == 1:
getattr(self, 'h_aggBBmultItem1').set_active(True)
elif self.hud_params['h_agg_bb_mult'] == 2:
getattr(self, 'h_aggBBmultItem2').set_active(True)
elif self.hud_params['h_agg_bb_mult'] == 3:
getattr(self, 'h_aggBBmultItem3').set_active(True)
elif self.hud_params['h_agg_bb_mult'] == 10:
getattr(self, 'h_aggBBmultItem10').set_active(True)
elif self.hud_params['h_agg_bb_mult'] > 9000:
getattr(self, 'h_aggBBmultItem10000').set_active(True)
#
if self.hud_params['agg_bb_mult'] == 1: if self.hud_params['agg_bb_mult'] == 1:
getattr(self, 'aggBBmultItem1').set_active(True) getattr(self, 'aggBBmultItem1').set_active(True)
elif self.hud_params['agg_bb_mult'] == 2: elif self.hud_params['agg_bb_mult'] == 2:
@ -208,13 +270,21 @@ class Hud:
elif self.hud_params['agg_bb_mult'] == 10: elif self.hud_params['agg_bb_mult'] == 10:
getattr(self, 'aggBBmultItem10').set_active(True) getattr(self, 'aggBBmultItem10').set_active(True)
elif self.hud_params['agg_bb_mult'] > 9000: elif self.hud_params['agg_bb_mult'] > 9000:
getattr(self, 'aggBBmultItemAll').set_active(True) getattr(self, 'aggBBmultItem10000').set_active(True)
#
if self.hud_params['h_hud_style'] == 'A': if self.hud_params['h_hud_style'] == 'A':
getattr(self, 'HAStyleOption').set_active(True) getattr(self, 'h_hudStyleOptionA').set_active(True)
elif self.hud_params['h_hud_style'] == 'S': elif self.hud_params['h_hud_style'] == 'S':
getattr(self, 'HSStyleOption').set_active(True) getattr(self, 'h_hudStyleOptionS').set_active(True)
elif self.hud_params['h_hud_style'] == 'T': elif self.hud_params['h_hud_style'] == 'T':
getattr(self, 'HTStyleOption').set_active(True) getattr(self, 'h_hudStyleOptionT').set_active(True)
#
if self.hud_params['hud_style'] == 'A':
getattr(self, 'hudStyleOptionA').set_active(True)
elif self.hud_params['hud_style'] == 'S':
getattr(self, 'hudStyleOptionS').set_active(True)
elif self.hud_params['hud_style'] == 'T':
getattr(self, 'hudStyleOptionT').set_active(True)
eventbox.connect_object("button-press-event", self.on_button_press, menu) eventbox.connect_object("button-press-event", self.on_button_press, menu)
@ -254,41 +324,53 @@ class Hud:
pass pass
def set_aggregation(self, widget, val): def set_aggregation(self, widget, val):
# try setting these to true all the time, and set the multiplier to 1 to turn agg off: (player_opp, num) = val
self.hud_params['aggregate_ring'] = True if player_opp == 'P':
self.hud_params['aggregate_tour'] = True # set these true all the time, set the multiplier to 1 to turn agg off:
self.hud_params['h_aggregate_ring'] = True self.hud_params['h_aggregate_ring'] = True
self.hud_params['h_aggregate_tour'] = True self.hud_params['h_aggregate_tour'] = True
if self.hud_params['agg_bb_mult'] != val \ if self.hud_params['h_agg_bb_mult'] != num \
and getattr(self, 'aggBBmultItem'+str(val)).get_active(): and getattr(self, 'h_aggBBmultItem'+str(num)).get_active():
print 'set_aggregation', val print 'set_player_aggregation', num
self.hud_params['agg_bb_mult'] = val self.hud_params['h_agg_bb_mult'] = num
self.hud_params['h_agg_bb_mult'] = val
for mult in ('1', '2', '3', '10', '10000'): for mult in ('1', '2', '3', '10', '10000'):
if mult != str(val): if mult != str(num):
getattr(self, 'h_aggBBmultItem'+mult).set_active(False)
else:
self.hud_params['aggregate_ring'] = True
self.hud_params['aggregate_tour'] = True
if self.hud_params['agg_bb_mult'] != num \
and getattr(self, 'aggBBmultItem'+str(num)).get_active():
print 'set_opponent_aggregation', num
self.hud_params['agg_bb_mult'] = num
for mult in ('1', '2', '3', '10', '10000'):
if mult != str(num):
getattr(self, 'aggBBmultItem'+mult).set_active(False) getattr(self, 'aggBBmultItem'+mult).set_active(False)
def set_hud_style(self, widget, val): def set_hud_style(self, widget, val):
# try setting these to true all the time, and set the multiplier to 1 to turn agg off: (player_opp, style) = val
if val[0] == 'H': if player_opp == 'P':
param = 'h_hud_style' param = 'h_hud_style'
prefix = 'h_'
else: else:
param = 'hud_style' param = 'hud_style'
prefix = ''
if val[1] == 'A' and getattr(self, 'HAStyleOption').get_active(): if style == 'A' and getattr(self, prefix+'hudStyleOptionA').get_active():
self.hud_params[param] = 'A' self.hud_params[param] = 'A'
getattr(self, 'HSStyleOption').set_active(False) getattr(self, prefix+'hudStyleOptionS').set_active(False)
getattr(self, 'HTStyleOption').set_active(False) getattr(self, prefix+'hudStyleOptionT').set_active(False)
elif val[1] == 'S' and getattr(self, 'HSStyleOption').get_active(): elif style == 'S' and getattr(self, prefix+'hudStyleOptionS').get_active():
self.hud_params[param] = 'S' self.hud_params[param] = 'S'
getattr(self, 'HAStyleOption').set_active(False) getattr(self, prefix+'hudStyleOptionA').set_active(False)
getattr(self, 'HTStyleOption').set_active(False) getattr(self, prefix+'hudStyleOptionT').set_active(False)
elif val[1] == 'T' and self.HTStyleOption.get_active(): elif style == 'T' and getattr(self, prefix+'hudStyleOptionT').get_active():
self.hud_params[param] = 'T' self.hud_params[param] = 'T'
getattr(self, 'HAStyleOption').set_active(False) getattr(self, prefix+'hudStyleOptionA').set_active(False)
getattr(self, 'HSStyleOption').set_active(False) getattr(self, prefix+'hudStyleOptionS').set_active(False)
print "setting self.hud_params[%s] = %s" % (param, val[1]) print "setting self.hud_params[%s] = %s" % (param, style)
def update_table_position(self): def update_table_position(self):
if os.name == 'nt': if os.name == 'nt':

View File

@ -1235,6 +1235,13 @@ class Sql:
and Players.siteId = Sites.id and Players.siteId = Sites.id
""" """
self.query['get_player_names'] = """
select p.name
from Players p
where lower(p.name) like lower(%s)
and (p.siteId = %s or %s = -1)
"""
self.query['getSiteId'] = """SELECT id from Sites where name = %s""" self.query['getSiteId'] = """SELECT id from Sites where name = %s"""
self.query['get_stats_from_hand'] = """ self.query['get_stats_from_hand'] = """
@ -1713,10 +1720,14 @@ class Sql:
self.query['getSiteId'] = """SELECT id from Sites where name = %s""" self.query['getSiteId'] = """SELECT id from Sites where name = %s"""
self.query['getGames'] = """SELECT DISTINCT category from Gametypes""" self.query['getGames'] = """SELECT DISTINCT category from Gametypes"""
self.query['getLimits'] = """SELECT DISTINCT bigBlind from Gametypes ORDER by bigBlind DESC""" self.query['getLimits'] = """SELECT DISTINCT bigBlind from Gametypes ORDER by bigBlind DESC"""
self.query['getLimits2'] = """SELECT DISTINCT type, limitType, bigBlind
from Gametypes
ORDER by type, limitType DESC, bigBlind DESC"""
if db_server == 'mysql': if db_server == 'mysql':
self.query['playerDetailedStats'] = """ self.query['playerDetailedStats'] = """
select <hgameTypeId> AS hgametypeid select <hgameTypeId> AS hgametypeid
,<playerName> AS pname
,gt.base ,gt.base
,gt.category ,gt.category
,upper(gt.limitType) AS limittype ,upper(gt.limitType) AS limittype
@ -1767,21 +1778,23 @@ class Sql:
inner join Hands h on (h.id = hp.handId) inner join Hands h on (h.id = hp.handId)
inner join Gametypes gt on (gt.Id = h.gameTypeId) inner join Gametypes gt on (gt.Id = h.gameTypeId)
inner join Sites s on (s.Id = gt.siteId) inner join Sites s on (s.Id = gt.siteId)
inner join Players p on (p.Id = hp.playerId)
where hp.playerId in <player_test> where hp.playerId in <player_test>
and hp.tourneysPlayersId IS NULL /*and hp.tourneysPlayersId IS NULL*/
and h.seats <seats_test> and h.seats <seats_test>
<flagtest> <flagtest>
<gtbigBlind_test> <gtbigBlind_test>
and date_format(h.handStart, '%Y-%m-%d') <datestest> and date_format(h.handStart, '%Y-%m-%d') <datestest>
group by hgameTypeId group by hgameTypeId
,hp.playerId ,pname
,gt.base ,gt.base
,gt.category ,gt.category
<groupbyseats> <groupbyseats>
,plposition ,plposition
,upper(gt.limitType) ,upper(gt.limitType)
,s.name ,s.name
order by hp.playerId having 1 = 1 <havingclause>
order by pname
,gt.base ,gt.base
,gt.category ,gt.category
<orderbyseats> <orderbyseats>
@ -1790,11 +1803,95 @@ class Sql:
else concat('Z', <position>) else concat('Z', <position>)
end end
<orderbyhgameTypeId> <orderbyhgameTypeId>
,upper(gt.limitType) desc
,maxbigblind desc ,maxbigblind desc
,upper(gt.limitType)
,s.name ,s.name
""" """
else: # assume postgresql elif db_server == 'postgresql':
self.query['playerDetailedStats'] = """
select <hgameTypeId> AS hgametypeid
,<playerName> AS pname
,gt.base
,gt.category
,upper(gt.limitType) AS limittype
,s.name
,min(gt.bigBlind) AS minbigblind
,max(gt.bigBlind) AS maxbigblind
/*,<hcgametypeId> AS gtid*/
,<position> AS plposition
,count(1) AS n
,100.0*sum(cast(hp.street0VPI as <signed>integer))/count(1) AS vpip
,100.0*sum(cast(hp.street0Aggr as <signed>integer))/count(1) AS pfr
,case when sum(cast(hp.street0_3Bchance as <signed>integer)) = 0 then -999
else 100.0*sum(cast(hp.street0_3Bdone as <signed>integer))/sum(cast(hp.street0_3Bchance as <signed>integer))
end AS pf3
,case when sum(cast(hp.stealattemptchance as <signed>integer)) = 0 then -999
else 100.0*sum(cast(hp.stealattempted as <signed>integer))/sum(cast(hp.stealattemptchance as <signed>integer))
end AS steals
,100.0*sum(cast(hp.street1Seen as <signed>integer))/count(1) AS saw_f
,100.0*sum(cast(hp.sawShowdown as <signed>integer))/count(1) AS sawsd
,case when sum(cast(hp.street1Seen as <signed>integer)) = 0 then -999
else 100.0*sum(cast(hp.sawShowdown as <signed>integer))/sum(cast(hp.street1Seen as <signed>integer))
end AS wtsdwsf
,case when sum(cast(hp.sawShowdown as <signed>integer)) = 0 then -999
else 100.0*sum(cast(hp.wonAtSD as <signed>integer))/sum(cast(hp.sawShowdown as <signed>integer))
end AS wmsd
,case when sum(cast(hp.street1Seen as <signed>integer)) = 0 then -999
else 100.0*sum(cast(hp.street1Aggr as <signed>integer))/sum(cast(hp.street1Seen as <signed>integer))
end AS flafq
,case when sum(cast(hp.street2Seen as <signed>integer)) = 0 then -999
else 100.0*sum(cast(hp.street2Aggr as <signed>integer))/sum(cast(hp.street2Seen as <signed>integer))
end AS tuafq
,case when sum(cast(hp.street3Seen as <signed>integer)) = 0 then -999
else 100.0*sum(cast(hp.street3Aggr as <signed>integer))/sum(cast(hp.street3Seen as <signed>integer))
end AS rvafq
,case when sum(cast(hp.street1Seen as <signed>integer))+sum(cast(hp.street2Seen as <signed>integer))+sum(cast(hp.street3Seen as <signed>integer)) = 0 then -999
else 100.0*(sum(cast(hp.street1Aggr as <signed>integer))+sum(cast(hp.street2Aggr as <signed>integer))+sum(cast(hp.street3Aggr as <signed>integer)))
/(sum(cast(hp.street1Seen as <signed>integer))+sum(cast(hp.street2Seen as <signed>integer))+sum(cast(hp.street3Seen as <signed>integer)))
end AS pofafq
,sum(hp.totalProfit)/100.0 AS net
,sum(hp.rake)/100.0 AS rake
,100.0*avg(hp.totalProfit/(gt.bigBlind+0.0)) AS bbper100
,avg(hp.totalProfit)/100.0 AS profitperhand
,100.0*avg((hp.totalProfit+hp.rake)/(gt.bigBlind+0.0)) AS bb100xr
,avg((hp.totalProfit+hp.rake)/100.0) AS profhndxr
,avg(h.seats+0.0) AS avgseats
,variance(hp.totalProfit/100.0) AS variance
from HandsPlayers hp
inner join Hands h on (h.id = hp.handId)
inner join Gametypes gt on (gt.Id = h.gameTypeId)
inner join Sites s on (s.Id = gt.siteId)
inner join Players p on (p.Id = hp.playerId)
where hp.playerId in <player_test>
/*and hp.tourneysPlayersId IS NULL*/
and h.seats <seats_test>
<flagtest>
<gtbigBlind_test>
and to_char(h.handStart, 'YYYY-MM-DD') <datestest>
group by hgameTypeId
,pname
,gt.base
,gt.category
<groupbyseats>
,plposition
,upper(gt.limitType)
,s.name
having 1 = 1 <havingclause>
order by pname
,gt.base
,gt.category
<orderbyseats>
,case <position> when 'B' then 'B'
when 'S' then 'S'
when '0' then 'Y'
else 'Z'||<position>
end
<orderbyhgameTypeId>
,upper(gt.limitType) desc
,maxbigblind desc
,s.name
"""
elif db_server == 'sqlite':
self.query['playerDetailedStats'] = """ self.query['playerDetailedStats'] = """
select <hgameTypeId> AS hgametypeid select <hgameTypeId> AS hgametypeid
,gt.base ,gt.base
@ -1848,7 +1945,7 @@ class Sql:
inner join Gametypes gt on (gt.Id = h.gameTypeId) inner join Gametypes gt on (gt.Id = h.gameTypeId)
inner join Sites s on (s.Id = gt.siteId) inner join Sites s on (s.Id = gt.siteId)
where hp.playerId in <player_test> where hp.playerId in <player_test>
and hp.tourneysPlayersId IS NULL /*and hp.tourneysPlayersId IS NULL*/
and h.seats <seats_test> and h.seats <seats_test>
<flagtest> <flagtest>
<gtbigBlind_test> <gtbigBlind_test>
@ -1871,12 +1968,10 @@ class Sql:
else 'Z'||<position> else 'Z'||<position>
end end
<orderbyhgameTypeId> <orderbyhgameTypeId>
,upper(gt.limitType) desc
,maxbigblind desc ,maxbigblind desc
,upper(gt.limitType)
,s.name ,s.name
""" """
#elif db_server == 'sqlite':
# self.query['playerDetailedStats'] = """ """
if db_server == 'mysql': if db_server == 'mysql':
self.query['playerStats'] = """ self.query['playerStats'] = """
@ -2366,16 +2461,16 @@ class Sql:
# self.query['playerStatsByPosition'] = """ """ # self.query['playerStatsByPosition'] = """ """
self.query['getRingProfitAllHandsPlayerIdSite'] = """ self.query['getRingProfitAllHandsPlayerIdSite'] = """
SELECT hp.handId, hp.totalProfit, hp.totalProfit, hp.totalProfit SELECT hp.handId, hp.totalProfit
FROM HandsPlayers hp FROM HandsPlayers hp
INNER JOIN Players pl ON (hp.playerId = pl.id) INNER JOIN Players pl ON (pl.id = hp.playerId)
INNER JOIN Hands h ON (h.id = hp.handId) INNER JOIN Hands h ON (h.id = hp.handId)
INNER JOIN Gametypes g ON (h.gametypeId = g.id) INNER JOIN Gametypes gt ON (gt.id = h.gametypeId)
where pl.id in <player_test> WHERE pl.id in <player_test>
AND pl.siteId in <site_test> AND pl.siteId in <site_test>
AND h.handStart > '<startdate_test>' AND h.handStart > '<startdate_test>'
AND h.handStart < '<enddate_test>' AND h.handStart < '<enddate_test>'
AND g.bigBlind in <limit_test> <limit_test>
AND hp.tourneysPlayersId IS NULL AND hp.tourneysPlayersId IS NULL
GROUP BY h.handStart, hp.handId, hp.totalProfit GROUP BY h.handStart, hp.handId, hp.totalProfit
ORDER BY h.handStart""" ORDER BY h.handStart"""
@ -3021,6 +3116,44 @@ class Sql:
self.query['handsPlayersTTypeId_joiner'] = " OR TourneysPlayersId+0=" self.query['handsPlayersTTypeId_joiner'] = " OR TourneysPlayersId+0="
self.query['handsPlayersTTypeId_joiner_id'] = " OR id=" self.query['handsPlayersTTypeId_joiner_id'] = " OR id="
self.query['store_hand'] = """INSERT INTO Hands (
tablename,
gametypeid,
sitehandno,
handstart,
importtime,
seats,
maxseats,
texture,
playersVpi,
boardcard1,
boardcard2,
boardcard3,
boardcard4,
boardcard5,
playersAtStreet1,
playersAtStreet2,
playersAtStreet3,
playersAtStreet4,
playersAtShowdown,
street0Raises,
street1Raises,
street2Raises,
street3Raises,
street4Raises,
street1Pot,
street2Pot,
street3Pot,
street4Pot,
showdownPot
)
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)"""
if db_server == 'mysql': if db_server == 'mysql':

View File

@ -257,6 +257,10 @@ def discover_nt_tournament(c, tour_number, tab_number):
titles ={} titles ={}
win32gui.EnumWindows(win_enum_handler, titles) win32gui.EnumWindows(win_enum_handler, titles)
for hwnd in titles: for hwnd in titles:
if 'Chat:' in titles[hwnd]: continue # Some sites (FTP? PS? Others?) have seperable or seperately constructed chat windows
if 'History for table:' in titles[hwnd]: continue # Everleaf Network HH viewer window
if 'HUD:' in titles[hwnd]: continue # FPDB HUD window
if re.search(search_string, titles[hwnd]): if re.search(search_string, titles[hwnd]):
return decode_windows(c, titles[hwnd], hwnd) return decode_windows(c, titles[hwnd], hwnd)
return None return None

View File

@ -44,6 +44,7 @@ else:
print "Python " + sys.version[0:3] + '...\n' print "Python " + sys.version[0:3] + '...\n'
import traceback
import threading import threading
import Options import Options
import string import string
@ -64,7 +65,6 @@ import gtk
import interlocks import interlocks
import fpdb_simple
import GuiBulkImport import GuiBulkImport
import GuiPlayerStats import GuiPlayerStats
import GuiPositionalStats import GuiPositionalStats
@ -234,13 +234,13 @@ class fpdb:
dia_confirm = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, dia_confirm = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING,
buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm deleting and recreating tables") buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm deleting and recreating tables")
diastring = "Please confirm that you want to (re-)create the tables. If there already are tables in the database " \ diastring = "Please confirm that you want to (re-)create the tables. If there already are tables in the database " \
+self.db.fdb.database+" on "+self.db.fdb.host+" they will be deleted." +self.db.database+" on "+self.db.host+" they will be deleted."
dia_confirm.format_secondary_text(diastring)#todo: make above string with bold for db, host and deleted dia_confirm.format_secondary_text(diastring)#todo: make above string with bold for db, host and deleted
response = dia_confirm.run() response = dia_confirm.run()
dia_confirm.destroy() dia_confirm.destroy()
if response == gtk.RESPONSE_YES: if response == gtk.RESPONSE_YES:
#if self.db.fdb.backend == self.fdb_lock.fdb.MYSQL_INNODB: #if self.db.backend == self.fdb_lock.fdb.MYSQL_INNODB:
# mysql requires locks on all tables or none - easier to release this lock # mysql requires locks on all tables or none - easier to release this lock
# than lock all the other tables # than lock all the other tables
# ToDo: lock all other tables so that lock doesn't have to be released # ToDo: lock all other tables so that lock doesn't have to be released
@ -453,9 +453,25 @@ class fpdb:
self.db.disconnect() self.db.disconnect()
self.sql = SQL.Sql(type = self.settings['db-type'], db_server = self.settings['db-server']) self.sql = SQL.Sql(type = self.settings['db-type'], db_server = self.settings['db-server'])
try:
self.db = Database.Database(self.config, sql = self.sql) 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")
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.fdb.wrongDbVersion: if self.db.wrongDbVersion:
diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK))
label = gtk.Label("An invalid DB version or missing tables have been detected.") label = gtk.Label("An invalid DB version or missing tables have been detected.")
@ -474,14 +490,14 @@ class fpdb:
diaDbVersionWarning.destroy() diaDbVersionWarning.destroy()
if self.status_bar == None: if self.status_bar == None:
self.status_bar = gtk.Label("Status: Connected to %s database named %s on host %s"%(self.db.get_backend_name(),self.db.fdb.database, self.db.fdb.host)) self.status_bar = gtk.Label("Status: Connected to %s database named %s on host %s"%(self.db.get_backend_name(),self.db.database, self.db.host))
self.main_vbox.pack_end(self.status_bar, False, True, 0) self.main_vbox.pack_end(self.status_bar, False, True, 0)
self.status_bar.show() self.status_bar.show()
else: else:
self.status_bar.set_text("Status: Connected to %s database named %s on host %s" % (self.db.get_backend_name(),self.db.fdb.database, self.db.fdb.host)) self.status_bar.set_text("Status: Connected to %s database named %s on host %s" % (self.db.get_backend_name(),self.db.database, self.db.host))
# Database connected to successfully, load queries to pass on to other classes # Database connected to successfully, load queries to pass on to other classes
self.db.connection.rollback() self.db.rollback()
self.validate_config() self.validate_config()

View File

@ -80,7 +80,7 @@ class fpdb_db:
try: try:
self.db = MySQLdb.connect(host = host, user = user, passwd = password, db = database, use_unicode=True) self.db = MySQLdb.connect(host = host, user = user, passwd = password, db = database, use_unicode=True)
except: except:
raise FpdbError("MySQL connection failed") raise FpdbMySQLFailedError("MySQL connection failed")
elif backend==fpdb_db.PGSQL: elif backend==fpdb_db.PGSQL:
import psycopg2 import psycopg2
import psycopg2.extensions import psycopg2.extensions
@ -111,7 +111,7 @@ class fpdb_db:
password = password, password = password,
database = database) database = database)
except: except:
msg = "PostgreSQL connection to database (%s) user (%s) failed." % (database, user) msg = "PostgreSQL connection to database (%s) user (%s) failed. Are you sure the DB is running?" % (database, user)
print msg print msg
raise FpdbError(msg) raise FpdbError(msg)
elif backend == fpdb_db.SQLITE: elif backend == fpdb_db.SQLITE: