Merge branch 'master' of git://trac-git.assembla.com/fpdb-sql
Conflicts: pyfpdb/Database.py Resolve by reverting to sqlcoder's version; it uses the nice insert in fillDefaultData for each case now and having the DB backends separate might be good for the foreseeable future.
This commit is contained in:
commit
5260f5c384
|
@ -26,17 +26,17 @@ def twoStartCards(value1, suit1, value2, suit2):
|
|||
if value1 < 2 or value2 < 2:
|
||||
ret = 0
|
||||
if value1 == value2: # pairs
|
||||
ret = (13 * (value2-2) + (value2-1) )
|
||||
ret = (13 * (value2-2) + (value2-2) )
|
||||
elif suit1 == suit2:
|
||||
if value1 > value2:
|
||||
ret = 13 * (value1-2) + (value2-1)
|
||||
ret = 13 * (value1-2) + (value2-2)
|
||||
else:
|
||||
ret = 13 * (value2-2) + (value1-1)
|
||||
ret = 13 * (value2-2) + (value1-2)
|
||||
else:
|
||||
if value1 > value2:
|
||||
ret = 13 * (value2-2) + (value2-1)
|
||||
ret = 13 * (value2-2) + (value1-2)
|
||||
else:
|
||||
ret = 13 * (value1-2) + (value2-1)
|
||||
ret = 13 * (value1-2) + (value2-2)
|
||||
|
||||
# print "twoStartCards(", value1, suit1, value2, suit2, ")=", ret
|
||||
return ret
|
||||
|
@ -46,7 +46,6 @@ def twoStartCardString(card):
|
|||
into a string like AQo """
|
||||
ret = 'xx'
|
||||
if card > 0:
|
||||
card -= 1
|
||||
s = ('2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A')
|
||||
x = card / 13
|
||||
y = card - 13 * x
|
||||
|
|
|
@ -49,12 +49,15 @@ import logging, logging.config
|
|||
logging.config.fileConfig(os.path.join(sys.path[0],"logging.conf"))
|
||||
log = logging.getLogger('db')
|
||||
|
||||
|
||||
class Database:
|
||||
|
||||
MYSQL_INNODB = 2
|
||||
PGSQL = 3
|
||||
SQLITE = 4
|
||||
|
||||
hero_hudstart_def = '1999-12-31' # default for length of Hero's stats in HUD
|
||||
|
||||
# Data Structures for index and foreign key creation
|
||||
# drop_code is an int with possible values: 0 - don't drop for bulk import
|
||||
# 1 - drop during bulk import
|
||||
|
@ -70,19 +73,19 @@ class Database:
|
|||
[ ] # no db with index 0
|
||||
, [ ] # no db with index 1
|
||||
, [ # indexes for mysql (list index 2)
|
||||
{'tab':'Players', 'col':'name', 'drop':0}
|
||||
, {'tab':'Hands', 'col':'siteHandNo', 'drop':0}
|
||||
, {'tab':'Hands', 'col':'gametypeId', 'drop':0} # mct 22/3/09
|
||||
# {'tab':'Players', 'col':'name', 'drop':0} unique indexes not dropped
|
||||
# {'tab':'Hands', 'col':'siteHandNo', 'drop':0} unique indexes not dropped
|
||||
{'tab':'Hands', 'col':'gametypeId', 'drop':0} # mct 22/3/09
|
||||
, {'tab':'HandsPlayers', 'col':'handId', 'drop':0} # not needed, handled by fk
|
||||
, {'tab':'HandsPlayers', 'col':'playerId', 'drop':0} # not needed, handled by fk
|
||||
, {'tab':'HandsPlayers', 'col':'tourneyTypeId', 'drop':0}
|
||||
, {'tab':'HandsPlayers', 'col':'tourneysPlayersId', 'drop':0}
|
||||
, {'tab':'Tourneys', 'col':'siteTourneyNo', 'drop':0}
|
||||
#, {'tab':'Tourneys', 'col':'siteTourneyNo', 'drop':0} unique indexes not dropped
|
||||
]
|
||||
, [ # indexes for postgres (list index 3)
|
||||
{'tab':'Gametypes', 'col':'siteId', 'drop':0}
|
||||
, {'tab':'Hands', 'col':'gametypeId', 'drop':0} # mct 22/3/09
|
||||
, {'tab':'Hands', 'col':'siteHandNo', 'drop':0}
|
||||
#, {'tab':'Hands', 'col':'siteHandNo', 'drop':0} unique indexes not dropped
|
||||
, {'tab':'HandsActions', 'col':'handsPlayerId', 'drop':0}
|
||||
, {'tab':'HandsPlayers', 'col':'handId', 'drop':1}
|
||||
, {'tab':'HandsPlayers', 'col':'playerId', 'drop':1}
|
||||
|
@ -91,22 +94,22 @@ class Database:
|
|||
, {'tab':'HudCache', 'col':'playerId', 'drop':0}
|
||||
, {'tab':'HudCache', 'col':'tourneyTypeId', 'drop':0}
|
||||
, {'tab':'Players', 'col':'siteId', 'drop':1}
|
||||
, {'tab':'Players', 'col':'name', 'drop':0}
|
||||
#, {'tab':'Players', 'col':'name', 'drop':0} unique indexes not dropped
|
||||
, {'tab':'Tourneys', 'col':'tourneyTypeId', 'drop':1}
|
||||
, {'tab':'Tourneys', 'col':'siteTourneyNo', 'drop':0}
|
||||
#, {'tab':'Tourneys', 'col':'siteTourneyNo', 'drop':0} unique indexes not dropped
|
||||
, {'tab':'TourneysPlayers', 'col':'playerId', 'drop':0}
|
||||
, {'tab':'TourneysPlayers', 'col':'tourneyId', 'drop':0}
|
||||
#, {'tab':'TourneysPlayers', 'col':'tourneyId', 'drop':0} unique indexes not dropped
|
||||
, {'tab':'TourneyTypes', 'col':'siteId', 'drop':0}
|
||||
]
|
||||
, [ # indexes for sqlite (list index 4)
|
||||
{'tab':'Players', 'col':'name', 'drop':0}
|
||||
, {'tab':'Hands', 'col':'siteHandNo', 'drop':0}
|
||||
, {'tab':'Hands', 'col':'gametypeId', 'drop':0}
|
||||
# {'tab':'Players', 'col':'name', 'drop':0} unique indexes not dropped
|
||||
# {'tab':'Hands', 'col':'siteHandNo', 'drop':0} unique indexes not dropped
|
||||
{'tab':'Hands', 'col':'gametypeId', 'drop':0}
|
||||
, {'tab':'HandsPlayers', 'col':'handId', 'drop':0}
|
||||
, {'tab':'HandsPlayers', 'col':'playerId', 'drop':0}
|
||||
, {'tab':'HandsPlayers', 'col':'tourneyTypeId', 'drop':0}
|
||||
, {'tab':'HandsPlayers', 'col':'tourneysPlayersId', 'drop':0}
|
||||
, {'tab':'Tourneys', 'col':'siteTourneyNo', 'drop':0}
|
||||
#, {'tab':'Tourneys', 'col':'siteTourneyNo', 'drop':0} unique indexes not dropped
|
||||
]
|
||||
]
|
||||
|
||||
|
@ -183,6 +186,7 @@ class Database:
|
|||
|
||||
def __init__(self, c, sql = None):
|
||||
log.info("Creating Database instance, sql = %s" % sql)
|
||||
self.config = c
|
||||
self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql
|
||||
self.fdb.do_connect(c)
|
||||
self.connection = self.fdb.db
|
||||
|
@ -368,7 +372,10 @@ class Database:
|
|||
return winners
|
||||
|
||||
def init_hud_stat_vars(self, hud_days):
|
||||
"""Initialise variables used by Hud to fetch stats."""
|
||||
"""Initialise variables used by Hud to fetch stats:
|
||||
self.hand_1day_ago handId of latest hand played more than a day ago
|
||||
self.date_ndays_ago date n days ago
|
||||
"""
|
||||
|
||||
self.hand_1day_ago = 1
|
||||
try:
|
||||
|
@ -381,6 +388,7 @@ class Database:
|
|||
else:
|
||||
if row and row[0]:
|
||||
self.hand_1_day_ago = row[0]
|
||||
|
||||
d = timedelta(days=hud_days)
|
||||
now = datetime.utcnow() - d
|
||||
self.date_ndays_ago = "d%02d%02d%02d" % (now.year - 2000, now.month, now.day)
|
||||
|
@ -403,10 +411,19 @@ class Database:
|
|||
err = traceback.extract_tb(sys.exc_info()[2])[-1]
|
||||
print "***Error: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
|
||||
|
||||
def get_stats_from_hand(self, hand, aggregate = False, hud_style = 'A', agg_bb_mult = 100):
|
||||
def get_stats_from_hand( self, hand
|
||||
, hud_params = {'aggregate_tour':False, 'aggregate_ring':False, 'hud_style':'A', 'agg_bb_mult':100}
|
||||
, hero_ids = {}
|
||||
):
|
||||
aggregate = hud_params['aggregate_tour'] if type == "tour" else hud_params['aggregate_ring']
|
||||
hud_style = hud_params['hud_style']
|
||||
agg_bb_mult = hud_params['agg_bb_mult']
|
||||
stat_dict = {}
|
||||
|
||||
if hud_style == 'S':
|
||||
|
||||
return( self.get_stats_from_hand_session(hand) )
|
||||
self.get_stats_from_hand_session(hand, stat_dict)
|
||||
return stat_dict
|
||||
|
||||
else: # hud_style == A
|
||||
|
||||
|
@ -430,7 +447,6 @@ class Database:
|
|||
# now get the stats
|
||||
c.execute(self.sql.query[query], subs)
|
||||
colnames = [desc[0] for desc in c.description]
|
||||
stat_dict = {}
|
||||
for row in c.fetchall():
|
||||
t_dict = {}
|
||||
for name, val in zip(colnames, row):
|
||||
|
@ -441,7 +457,7 @@ class Database:
|
|||
return stat_dict
|
||||
|
||||
# uses query on handsplayers instead of hudcache to get stats on just this session
|
||||
def get_stats_from_hand_session(self, hand):
|
||||
def get_stats_from_hand_session(self, hand, stat_dict):
|
||||
|
||||
query = self.sql.query['get_stats_from_hand_session']
|
||||
if self.db_server == 'mysql':
|
||||
|
@ -456,15 +472,13 @@ class Database:
|
|||
#print "sess_stats: subs =", subs, "subs[0] =", subs[0]
|
||||
c.execute(query, subs)
|
||||
colnames = [desc[0] for desc in c.description]
|
||||
n,stat_dict = 0,{}
|
||||
n = 0
|
||||
|
||||
row = c.fetchone()
|
||||
while row:
|
||||
if colnames[0].lower() == 'player_id':
|
||||
playerid = row[0]
|
||||
else:
|
||||
log.error("ERROR: query %s result does not have player_id as first column" % (query,))
|
||||
break
|
||||
|
||||
while row:
|
||||
for name, val in zip(colnames, row):
|
||||
if not playerid in stat_dict:
|
||||
stat_dict[playerid] = {}
|
||||
|
@ -474,13 +488,16 @@ class Database:
|
|||
elif name.lower() not in ('hand_id', 'player_id', 'seat', 'screen_name', 'seats'):
|
||||
stat_dict[playerid][name.lower()] += val
|
||||
n += 1
|
||||
if n >= 4000: break # todo: don't think this is needed so set nice and high
|
||||
if n >= 10000: break # todo: don't think this is needed so set nice and high
|
||||
# for now - comment out or remove?
|
||||
row = c.fetchone()
|
||||
else:
|
||||
log.error("ERROR: query %s result does not have player_id as first column" % (query,))
|
||||
|
||||
#print " %d rows fetched, len(stat_dict) = %d" % (n, len(stat_dict))
|
||||
|
||||
#print "session stat_dict =", stat_dict
|
||||
return stat_dict
|
||||
#return stat_dict
|
||||
|
||||
def get_player_id(self, config, site, player_name):
|
||||
c = self.connection.cursor()
|
||||
|
@ -491,6 +508,69 @@ class Database:
|
|||
else:
|
||||
return None
|
||||
|
||||
#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
|
||||
# { playername: id } instead of depending on it's relation to the positions list
|
||||
# then this can be reduced in complexity a bit
|
||||
|
||||
#def recognisePlayerIDs(cursor, names, site_id):
|
||||
# result = []
|
||||
# for i in xrange(len(names)):
|
||||
# cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],))
|
||||
# tmp=cursor.fetchall()
|
||||
# if (len(tmp)==0): #new player
|
||||
# cursor.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)", (names[i], site_id))
|
||||
# #print "Number of players rows inserted: %d" % cursor.rowcount
|
||||
# cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],))
|
||||
# tmp=cursor.fetchall()
|
||||
# #print "recognisePlayerIDs, names[i]:",names[i],"tmp:",tmp
|
||||
# result.append(tmp[0][0])
|
||||
# return result
|
||||
|
||||
def recognisePlayerIDs(self, names, site_id):
|
||||
c = self.get_cursor()
|
||||
q = "SELECT name,id FROM Players WHERE siteid=%d and (name=%s)" %(site_id, " OR name=".join([self.sql.query['placeholder'] for n in names]))
|
||||
c.execute(q, names) # get all playerids by the names passed in
|
||||
ids = dict(c.fetchall()) # convert to dict
|
||||
if len(ids) != len(names):
|
||||
notfound = [n for n in names if n not in ids] # make list of names not in database
|
||||
if notfound: # insert them into database
|
||||
q_ins = "INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")"
|
||||
q_ins = q_ins.replace('%s', self.sql.query['placeholder'])
|
||||
c.executemany(q_ins, [(n,) for n in notfound])
|
||||
q2 = "SELECT name,id FROM Players WHERE siteid=%d and (name=%s)" % (site_id, " OR name=".join(["%s" for n in notfound]))
|
||||
q2 = q2.replace('%s', self.sql.query['placeholder'])
|
||||
c.execute(q2, notfound) # get their new ids
|
||||
tmp = c.fetchall()
|
||||
for n,id in tmp: # put them all into the same dict
|
||||
ids[n] = id
|
||||
# return them in the SAME ORDER that they came in in the names argument, rather than the order they came out of the DB
|
||||
return [ids[n] for n in names]
|
||||
#end def recognisePlayerIDs
|
||||
|
||||
# Here's a version that would work if it wasn't for the fact that it needs to have the output in the same order as input
|
||||
# this version could also be improved upon using list comprehensions, etc
|
||||
|
||||
#def recognisePlayerIDs(cursor, names, site_id):
|
||||
# result = []
|
||||
# notfound = []
|
||||
# cursor.execute("SELECT name,id FROM Players WHERE name='%s'" % "' OR name='".join(names))
|
||||
# tmp = dict(cursor.fetchall())
|
||||
# for n in names:
|
||||
# if n not in tmp:
|
||||
# notfound.append(n)
|
||||
# else:
|
||||
# result.append(tmp[n])
|
||||
# if notfound:
|
||||
# cursor.executemany("INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")", (notfound))
|
||||
# cursor.execute("SELECT id FROM Players WHERE name='%s'" % "' OR name='".join(notfound))
|
||||
# tmp = cursor.fetchall()
|
||||
# for n in tmp:
|
||||
# result.append(n[0])
|
||||
#
|
||||
# return result
|
||||
|
||||
|
||||
def get_site_id(self, site):
|
||||
c = self.get_cursor()
|
||||
c.execute(self.sql.query['getSiteId'], (site,))
|
||||
|
@ -855,6 +935,7 @@ class Database:
|
|||
log.debug(self.sql.query['createSettingsTable'])
|
||||
c = self.get_cursor()
|
||||
c.execute(self.sql.query['createSettingsTable'])
|
||||
|
||||
log.debug(self.sql.query['createSitesTable'])
|
||||
c.execute(self.sql.query['createSitesTable'])
|
||||
c.execute(self.sql.query['createGametypesTable'])
|
||||
|
@ -867,9 +948,14 @@ class Database:
|
|||
c.execute(self.sql.query['createHandsPlayersTable'])
|
||||
c.execute(self.sql.query['createHandsActionsTable'])
|
||||
c.execute(self.sql.query['createHudCacheTable'])
|
||||
#c.execute(self.sql.query['addTourneyIndex'])
|
||||
#c.execute(self.sql.query['addHandsIndex'])
|
||||
#c.execute(self.sql.query['addPlayersIndex'])
|
||||
|
||||
# create unique indexes:
|
||||
c.execute(self.sql.query['addTourneyIndex'])
|
||||
c.execute(self.sql.query['addHandsIndex'])
|
||||
c.execute(self.sql.query['addPlayersIndex'])
|
||||
c.execute(self.sql.query['addTPlayersIndex'])
|
||||
c.execute(self.sql.query['addTTypesIndex'])
|
||||
|
||||
self.fillDefaultData()
|
||||
self.commit()
|
||||
except:
|
||||
|
@ -1011,20 +1097,48 @@ class Database:
|
|||
c.execute("INSERT INTO Sites (name,currency) VALUES ('PartyPoker', 'USD')")
|
||||
if self.backend == self.SQLITE:
|
||||
c.execute("INSERT INTO TourneyTypes (id, siteId, buyin, fee) VALUES (NULL, 1, 0, 0);")
|
||||
else:
|
||||
elif self.backend == self.PGSQL:
|
||||
c.execute("""insert into TourneyTypes(siteId, buyin, fee, maxSeats, knockout
|
||||
,rebuyOrAddon, speed, headsUp, shootout, matrix)
|
||||
values (1, 0, 0, 0, False, False, null, False, False, False);""")
|
||||
elif self.backend == self.MYSQL_INNODB:
|
||||
c.execute("""insert into TourneyTypes(id, siteId, buyin, fee, maxSeats, knockout
|
||||
,rebuyOrAddon, speed, headsUp, shootout, matrix)
|
||||
values (1, 0, 0, 0, False, False, null, False, False, False);""")
|
||||
|
||||
#end def fillDefaultData
|
||||
|
||||
def rebuild_hudcache(self):
|
||||
def rebuild_hudcache(self, start=None):
|
||||
"""clears hudcache and rebuilds from the individual handsplayers records"""
|
||||
|
||||
try:
|
||||
stime = time()
|
||||
# derive list of program owner's player ids
|
||||
self.hero = {} # name of program owner indexed by site id
|
||||
self.hero_ids = {'dummy':-53, 'dummy2':-52} # playerid of owner indexed by site id
|
||||
# make sure at least two values in list
|
||||
# so that tuple generation creates doesn't use
|
||||
# () or (1,) style
|
||||
for site in self.config.get_supported_sites():
|
||||
result = self.get_site_id(site)
|
||||
if result:
|
||||
site_id = result[0][0]
|
||||
self.hero[site_id] = self.config.supported_sites[site].screen_name
|
||||
p_id = self.get_player_id(self.config, site, self.hero[site_id])
|
||||
if p_id:
|
||||
self.hero_ids[site_id] = int(p_id)
|
||||
|
||||
if start == None:
|
||||
start = self.hero_hudstart_def
|
||||
if self.hero_ids == {}:
|
||||
where = ""
|
||||
else:
|
||||
where = "where hp.playerId not in " + str(tuple(self.hero_ids.values())) \
|
||||
+ " or h.handStart > '" + start + "'"
|
||||
rebuild_sql = self.sql.query['rebuildHudCache'].replace('<where_clause>', where)
|
||||
|
||||
self.get_cursor().execute(self.sql.query['clearHudCache'])
|
||||
self.get_cursor().execute(self.sql.query['rebuildHudCache'])
|
||||
self.get_cursor().execute(rebuild_sql)
|
||||
self.commit()
|
||||
print "Rebuild hudcache took %.1f seconds" % (time() - stime,)
|
||||
except:
|
||||
|
@ -1033,6 +1147,39 @@ class Database:
|
|||
print err
|
||||
#end def rebuild_hudcache
|
||||
|
||||
def get_hero_hudcache_start(self):
|
||||
"""fetches earliest stylekey from hudcache for one of hero's player ids"""
|
||||
|
||||
try:
|
||||
# derive list of program owner's player ids
|
||||
self.hero = {} # name of program owner indexed by site id
|
||||
self.hero_ids = {'dummy':-53, 'dummy2':-52} # playerid of owner indexed by site id
|
||||
# make sure at least two values in list
|
||||
# so that tuple generation creates doesn't use
|
||||
# () or (1,) style
|
||||
for site in self.config.get_supported_sites():
|
||||
result = self.get_site_id(site)
|
||||
if result:
|
||||
site_id = result[0][0]
|
||||
self.hero[site_id] = self.config.supported_sites[site].screen_name
|
||||
p_id = self.get_player_id(self.config, site, self.hero[site_id])
|
||||
if p_id:
|
||||
self.hero_ids[site_id] = int(p_id)
|
||||
|
||||
q = self.sql.query['get_hero_hudcache_start'].replace("<playerid_list>", str(tuple(self.hero_ids.values())))
|
||||
c = self.get_cursor()
|
||||
c.execute(q)
|
||||
tmp = c.fetchone()
|
||||
if tmp == (None,):
|
||||
return self.hero_hudstart_def
|
||||
else:
|
||||
return "20"+tmp[0][1:3] + "-" + tmp[0][3:5] + "-" + tmp[0][5:7]
|
||||
except:
|
||||
err = traceback.extract_tb(sys.exc_info()[2])[-1]
|
||||
print "Error rebuilding hudcache:", str(sys.exc_value)
|
||||
print err
|
||||
#end def get_hero_hudcache_start
|
||||
|
||||
|
||||
def analyzeDB(self):
|
||||
"""Do whatever the DB can offer to update index/table statistics"""
|
||||
|
@ -1623,6 +1770,8 @@ class Database:
|
|||
#cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i]))
|
||||
#result.append(cursor.fetchall()[0][0])
|
||||
except:
|
||||
err = traceback.extract_tb(sys.exc_info()[2])[-1]
|
||||
print "***Error storing hand: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
|
||||
raise FpdbError( "store_hands_players_holdem_omaha_tourney error: " + str(sys.exc_value) )
|
||||
|
||||
return result
|
||||
|
@ -1855,27 +2004,40 @@ class Database:
|
|||
#end def storeHudCache
|
||||
|
||||
def store_tourneys(self, tourneyTypeId, siteTourneyNo, entries, prizepool, startTime):
|
||||
ret = -1
|
||||
try:
|
||||
# try and create tourney record, fetch id if it already exists
|
||||
# avoids race condition when doing the select first
|
||||
cursor = self.get_cursor()
|
||||
cursor.execute("SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s".replace('%s', self.sql.query['placeholder'])
|
||||
, (siteTourneyNo, tourneyTypeId))
|
||||
tmp=cursor.fetchone()
|
||||
#print "tried SELECTing tourneys.id, result:",tmp
|
||||
|
||||
try:
|
||||
len(tmp)
|
||||
except TypeError:#means we have to create new one
|
||||
cursor.execute("savepoint ins_tourney")
|
||||
cursor.execute("""INSERT INTO Tourneys
|
||||
(tourneyTypeId, siteTourneyNo, entries, prizepool, startTime)
|
||||
VALUES (%s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder'])
|
||||
,(tourneyTypeId, siteTourneyNo, entries, prizepool, startTime))
|
||||
cursor.execute("SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s", (siteTourneyNo, tourneyTypeId))
|
||||
tmp=cursor.fetchone()
|
||||
#print "created new tourneys.id:",tmp
|
||||
ret = self.get_last_insert_id(cursor)
|
||||
#print "created new tourneys.id:",ret
|
||||
except:
|
||||
raise FpdbError( "store_tourneys error: " + str(sys.exc_value) )
|
||||
#if str(sys.exc_value) contains 'sitetourneyno':
|
||||
# raise FpdbError( "store_tourneys error: " + str(sys.exc_value) )
|
||||
#else:
|
||||
#print "error insert tourney (%s) trying select ..." % (str(sys.exc_value),)
|
||||
cursor.execute("rollback to savepoint ins_tourney")
|
||||
try:
|
||||
cursor.execute( "SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s".replace('%s', self.sql.query['placeholder'])
|
||||
, (siteTourneyNo, tourneyTypeId) )
|
||||
rec = cursor.fetchone()
|
||||
#print "select tourney result: ", rec
|
||||
try:
|
||||
len(rec)
|
||||
ret = rec[0]
|
||||
except:
|
||||
print "Tourney id not found"
|
||||
except:
|
||||
print "Error selecting tourney id:", str(sys.exc_info()[1])
|
||||
|
||||
return tmp[0]
|
||||
cursor.execute("release savepoint ins_tourney")
|
||||
#print "store_tourneys returning", ret
|
||||
return ret
|
||||
#end def store_tourneys
|
||||
|
||||
def store_tourneys_players(self, tourney_id, player_ids, payin_amounts, ranks, winnings):
|
||||
|
@ -1888,26 +2050,32 @@ class Database:
|
|||
#print "ranks:",ranks
|
||||
#print "winnings:",winnings
|
||||
for i in xrange(len(player_ids)):
|
||||
cursor.execute("SELECT id FROM TourneysPlayers WHERE tourneyId=%s AND playerId+0=%s".replace('%s', self.sql.query['placeholder'])
|
||||
,(tourney_id, player_ids[i]))
|
||||
tmp=cursor.fetchone()
|
||||
#print "tried SELECTing tourneys_players.id:",tmp
|
||||
|
||||
try:
|
||||
len(tmp)
|
||||
except TypeError:
|
||||
cursor.execute("savepoint ins_tplayer")
|
||||
cursor.execute("""INSERT INTO TourneysPlayers
|
||||
(tourneyId, playerId, payinAmount, rank, winnings) VALUES (%s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']),
|
||||
(tourney_id, player_ids[i], payin_amounts[i], ranks[i], winnings[i]))
|
||||
|
||||
cursor.execute("SELECT id FROM TourneysPlayers WHERE tourneyId=%s AND playerId+0=%s".replace('%s', self.sql.query['placeholder']),
|
||||
(tourney_id, player_ids[i]))
|
||||
tmp=cursor.fetchone()
|
||||
tmp = self.get_last_insert_id(cursor)
|
||||
result.append(tmp)
|
||||
#print "created new tourneys_players.id:", tmp
|
||||
except:
|
||||
cursor.execute("rollback to savepoint ins_tplayer")
|
||||
cursor.execute("SELECT id FROM TourneysPlayers WHERE tourneyId=%s AND playerId+0=%s".replace('%s', self.sql.query['placeholder'])
|
||||
,(tourney_id, player_ids[i]))
|
||||
tmp = cursor.fetchone()
|
||||
#print "tried SELECTing tourneys_players.id:", tmp
|
||||
try:
|
||||
len(tmp)
|
||||
result.append(tmp[0])
|
||||
except:
|
||||
print "tplayer id not found for tourney,player %s,%s" % (tourney_id, player_ids[i])
|
||||
pass
|
||||
except:
|
||||
raise FpdbError( "store_tourneys_players error: " + str(sys.exc_value) )
|
||||
|
||||
cursor.execute("release savepoint ins_tplayer")
|
||||
#print "store_tourneys_players returning", result
|
||||
return result
|
||||
#end def store_tourneys_players
|
||||
|
||||
|
@ -2130,10 +2298,10 @@ class Database:
|
|||
def tStoreTourneyPlayers(self, tourney, dbTourneyId):
|
||||
logging.debug("Database.tStoreTourneyPlayers")
|
||||
# First, get playerids for the players and specifically the one for hero :
|
||||
playersIds = fpdb_simple.recognisePlayerIDs(self, tourney.players, tourney.siteId)
|
||||
playersIds = self.recognisePlayerIDs(tourney.players, tourney.siteId)
|
||||
# hero may be None for matrix tourneys summaries
|
||||
# hero = [ tourney.hero ]
|
||||
# heroId = fpdb_simple.recognisePlayerIDs(self, hero , tourney.siteId)
|
||||
# heroId = self.recognisePlayerIDs(hero , tourney.siteId)
|
||||
# logging.debug("hero Id = %s - playersId = %s" % (heroId , playersIds))
|
||||
|
||||
tourneyPlayersIds=[]
|
||||
|
|
|
@ -56,24 +56,50 @@ import Database
|
|||
import Tables
|
||||
import Hud
|
||||
|
||||
# To add to config:
|
||||
aggregate_stats = {"ring": False, "tour": False} # uses agg_bb_mult
|
||||
hud_style = 'A' # A=All-time
|
||||
# To add to config: *** these vars now replaced by def_hud_params list
|
||||
#aggregate_stats = {"ring": False, "tour": False} # uses agg_bb_mult
|
||||
#hud_style = 'A' # A=All-time
|
||||
# S=Session
|
||||
# T=timed (last n days - set hud_days to required value)
|
||||
# Future values may also include:
|
||||
# H=Hands (last n hands)
|
||||
hud_days = 90 # Max number of days from each player to use for hud stats
|
||||
agg_bb_mult = 100 # 1 = no aggregation. When aggregating stats across levels larger blinds
|
||||
#hud_days = 90 # Max number of days from each player to use for hud stats
|
||||
#agg_bb_mult = 100 # 1 = no aggregation. When aggregating stats across levels larger blinds
|
||||
# must be < (agg_bb_mult * smaller blinds) to be aggregated
|
||||
# ie. 100 will aggregate almost everything, 2 will probably agg just the
|
||||
# next higher and lower levels into the current one, try 3/10/30/100
|
||||
hud_session_gap = 30 # Gap (minutes) between hands that indicates a change of session
|
||||
#hud_session_gap = 30 # Gap (minutes) between hands that indicates a change of session
|
||||
# (hands every 2 mins for 1 hour = one session, if followed
|
||||
# by a 40 minute gap and then more hands on same table that is
|
||||
# a new session)
|
||||
#hud_hands = 0 # Max number of hands from each player to use for hud stats (not used)
|
||||
|
||||
# New list to hold all HUD params
|
||||
# - Set aggregate_ring and/or aggregate_tour to True is you want to include stats from other blind levels in the HUD display
|
||||
# - If aggregation is used, the value of agg_bb_mult determines how what levels are included, e.g.
|
||||
# if agg_bb_mult is 100, almost all levels are included in all HUD displays
|
||||
# if agg_bb_mult is 2.1, levels from half to double the current blind level are included in the HUD
|
||||
# - Set hud_style to A to see stats for all-time
|
||||
# Set hud_style to S to only see stats for current session (currently this shows stats for the last 24 hours)
|
||||
# Set hud_style to T to only see stats for the last N days (uses value in hud_days)
|
||||
# - Set hud_days to N to see stats for the last N days in the HUD (only applies if hud_style is T)
|
||||
def_hud_params = { # Settings for all players apart from program owner ('hero')
|
||||
'aggregate_ring' : False
|
||||
, 'aggregate_tour' : True
|
||||
, 'hud_style' : 'A'
|
||||
, 'hud_days' : 90
|
||||
, 'agg_bb_mult' : 1 # 1 means no aggregation
|
||||
# , 'hud_session_gap' : 30 not currently used
|
||||
# Second set of variables for hero - these settings only apply to the program owner
|
||||
, 'h_aggregate_ring' : False
|
||||
, 'h_aggregate_tour' : True
|
||||
, 'h_hud_style' : 'A'
|
||||
, 'h_hud_days' : 90
|
||||
, 'h_agg_bb_mult' : 1 # 1 means no aggregation
|
||||
# , 'h_hud_session_gap' : 30 not currently used
|
||||
}
|
||||
|
||||
|
||||
class HUD_main(object):
|
||||
"""A main() object to own both the read_stdin thread and the gui."""
|
||||
# This class mainly provides state for controlling the multiple HUDs.
|
||||
|
@ -82,6 +108,7 @@ class HUD_main(object):
|
|||
self.db_name = db_name
|
||||
self.config = Configuration.Config(file=options.config, dbname=options.dbname)
|
||||
self.hud_dict = {}
|
||||
self.hud_params = def_hud_params
|
||||
|
||||
# a thread to read stdin
|
||||
gobject.threads_init() # this is required
|
||||
|
@ -104,7 +131,11 @@ class HUD_main(object):
|
|||
# called by an event in the HUD, to kill this specific HUD
|
||||
if table in self.hud_dict:
|
||||
self.hud_dict[table].kill()
|
||||
try:
|
||||
# throws exception in windows sometimes (when closing using main_window menu?)
|
||||
self.hud_dict[table].main_window.destroy()
|
||||
except:
|
||||
pass
|
||||
self.vb.remove(self.hud_dict[table].tablehudlabel)
|
||||
del(self.hud_dict[table])
|
||||
self.main_window.resize(1,1)
|
||||
|
@ -160,10 +191,19 @@ class HUD_main(object):
|
|||
# be passed to HUDs for use in the gui thread. HUD objects should not
|
||||
# need their own access to the database, but should open their own
|
||||
# if it is required.
|
||||
try:
|
||||
self.db_connection = Database.Database(self.config)
|
||||
self.db_connection.init_hud_stat_vars(hud_days)
|
||||
tourny_finder = re.compile('(\d+) (\d+)')
|
||||
|
||||
# get hero's screen names and player ids
|
||||
self.hero, self.hero_ids = {}, {}
|
||||
for site in self.config.get_supported_sites():
|
||||
result = self.db_connection.get_site_id(site)
|
||||
if result:
|
||||
site_id = result[0][0]
|
||||
self.hero[site_id] = self.config.supported_sites[site].screen_name
|
||||
self.hero_ids[site_id] = self.db_connection.get_player_id(self.config, site, self.hero[site_id])
|
||||
|
||||
while 1: # wait for a new hand number on stdin
|
||||
new_hand_id = sys.stdin.readline()
|
||||
new_hand_id = string.rstrip(new_hand_id)
|
||||
|
@ -173,9 +213,7 @@ class HUD_main(object):
|
|||
# get basic info about the new hand from the db
|
||||
# if there is a db error, complain, skip hand, and proceed
|
||||
try:
|
||||
(table_name, max, poker_game, type) = self.db_connection.get_table_name(new_hand_id)
|
||||
stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, aggregate_stats[type]
|
||||
,hud_style, agg_bb_mult)
|
||||
(table_name, max, poker_game, type, site_id) = self.db_connection.get_table_name(new_hand_id)
|
||||
|
||||
cards = self.db_connection.get_cards(new_hand_id)
|
||||
comm_cards = self.db_connection.get_common_cards(new_hand_id)
|
||||
|
@ -203,6 +241,16 @@ class HUD_main(object):
|
|||
|
||||
# Update an existing HUD
|
||||
if temp_key in self.hud_dict:
|
||||
try:
|
||||
# get stats using hud's specific params
|
||||
self.db_connection.init_hud_stat_vars( self.hud_dict[temp_key].hud_params['hud_days'] )
|
||||
stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, self.hud_dict[temp_key].hud_params, self.hero_ids)
|
||||
except:
|
||||
err = traceback.extract_tb(sys.exc_info()[2])[-1]
|
||||
print "db get_stats error: skipping "+str(new_hand_id)+" "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
|
||||
if new_hand_id: # new_hand_id is none if we had an error prior to the store
|
||||
sys.stderr.write("Database get_stats error %s in hand %d. Skipping.\n" % (err, int(new_hand_id)))
|
||||
continue
|
||||
self.hud_dict[temp_key].stat_dict = stat_dict
|
||||
self.hud_dict[temp_key].cards = cards
|
||||
[aw.update_data(new_hand_id, self.db_connection) for aw in self.hud_dict[temp_key].aux_windows]
|
||||
|
@ -210,6 +258,16 @@ class HUD_main(object):
|
|||
|
||||
# Or create a new HUD
|
||||
else:
|
||||
try:
|
||||
# get stats using default params
|
||||
self.db_connection.init_hud_stat_vars( self.hud_params['hud_days'] )
|
||||
stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, self.hud_params, self.hero_ids)
|
||||
except:
|
||||
err = traceback.extract_tb(sys.exc_info()[2])[-1]
|
||||
print "db get_stats error: skipping "+str(new_hand_id)+" "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
|
||||
if new_hand_id: # new_hand_id is none if we had an error prior to the store
|
||||
sys.stderr.write("Database get_stats error %s in hand %d. Skipping.\n" % (err, int(new_hand_id)))
|
||||
continue
|
||||
if type == "tour":
|
||||
tablewindow = Tables.discover_tournament_table(self.config, tour_number, tab_number)
|
||||
else:
|
||||
|
@ -222,6 +280,9 @@ class HUD_main(object):
|
|||
else:
|
||||
self.create_HUD(new_hand_id, tablewindow, temp_key, max, poker_game, stat_dict, cards)
|
||||
self.db_connection.connection.rollback()
|
||||
except:
|
||||
err = traceback.extract_tb(sys.exc_info()[2])[-1]
|
||||
print "***Error: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
|
||||
|
||||
if __name__== "__main__":
|
||||
|
||||
|
|
|
@ -673,7 +673,14 @@ class HoldemOmahaHand(Hand):
|
|||
if shown: self.shown.add(player)
|
||||
if mucked: self.mucked.add(player)
|
||||
else:
|
||||
if len(cards) in (2, 4): # avoid adding board by mistake (Everleaf problem)
|
||||
self.addHoleCards('PREFLOP', player, open=[], closed=cards, shown=shown, mucked=mucked, dealt=dealt)
|
||||
elif len(cards) == 5: # cards holds a winning hand, not hole cards
|
||||
# filter( lambda x: x not in b, a ) # calcs a - b where a and b are lists
|
||||
# so diff is set to the winning hand minus the board cards, if we're lucky that leaves the hole cards
|
||||
diff = filter( lambda x: x not in self.board['FLOP']+self.board['TURN']+self.board['RIVER'], cards )
|
||||
if len(diff) == 2 and self.gametype['category'] in ('holdem'):
|
||||
self.addHoleCards('PREFLOP', player, open=[], closed=diff, shown=shown, mucked=mucked, dealt=dealt)
|
||||
|
||||
def getStreetTotals(self):
|
||||
# street1Pot INT, /* pot size at flop/street4 */
|
||||
|
|
|
@ -73,6 +73,7 @@ class Hud:
|
|||
self.stacked = True
|
||||
self.site = table.site
|
||||
self.mw_created = False
|
||||
self.hud_params = parent.hud_params
|
||||
|
||||
self.stat_windows = {}
|
||||
self.popup_windows = {}
|
||||
|
@ -144,6 +145,47 @@ class Hud:
|
|||
menu.append(repositem)
|
||||
repositem.connect("activate", self.reposition_windows)
|
||||
|
||||
aggitem = gtk.MenuItem('Show Stats')
|
||||
menu.append(aggitem)
|
||||
aggMenu = gtk.Menu()
|
||||
aggitem.set_submenu(aggMenu)
|
||||
# set agg_bb_mult to 1 to stop aggregation
|
||||
item = gtk.MenuItem('For This Blind Level')
|
||||
item.ms = 1
|
||||
aggMenu.append(item)
|
||||
item.connect("activate", self.set_aggregation)
|
||||
setattr(self, 'showStatsMenuItem1', item)
|
||||
#
|
||||
item = gtk.MenuItem('For Multiple Blind Levels:')
|
||||
aggMenu.append(item)
|
||||
setattr(self, 'showStatsMenuItem2', item)
|
||||
#
|
||||
item = gtk.MenuItem(' 0.5 to 2.0 x Current Blinds')
|
||||
item.ms = 2.01
|
||||
aggMenu.append(item)
|
||||
item.connect("activate", self.set_aggregation)
|
||||
setattr(self, 'showStatsMenuItem3', item)
|
||||
#
|
||||
item = gtk.MenuItem(' 0.33 to 3.0 x Current Blinds')
|
||||
item.ms = 3.01
|
||||
aggMenu.append(item)
|
||||
item.connect("activate", self.set_aggregation)
|
||||
setattr(self, 'showStatsMenuItem4', item)
|
||||
#
|
||||
item = gtk.MenuItem(' 0.1 to 10 x Current Blinds')
|
||||
item.ms = 10.01
|
||||
aggMenu.append(item)
|
||||
item.connect("activate", self.set_aggregation)
|
||||
setattr(self, 'showStatsMenuItem5', item)
|
||||
#
|
||||
item = gtk.MenuItem(' All Levels')
|
||||
item.ms = 10000
|
||||
aggMenu.append(item)
|
||||
item.connect("activate", self.set_aggregation)
|
||||
setattr(self, 'showStatsMenuItem6', item)
|
||||
|
||||
eventbox.connect_object("button-press-event", self.on_button_press, menu)
|
||||
|
||||
debugitem = gtk.MenuItem('Debug StatWindows')
|
||||
menu.append(debugitem)
|
||||
debugitem.connect("activate", self.debug_stat_windows)
|
||||
|
@ -176,9 +218,18 @@ class Hud:
|
|||
self.create(*self.creation_attrs)
|
||||
self.update(self.hand, self.config)
|
||||
except Exception, e:
|
||||
print "Expcetion:",str(e)
|
||||
print "Exception:",str(e)
|
||||
pass
|
||||
|
||||
def set_aggregation(self, widget):
|
||||
# try setting these to true all the time, and set the multiplier to 1 to turn agg off:
|
||||
self.hud_params['aggregate_ring'] = True
|
||||
self.hud_params['aggregate_tour'] = True
|
||||
|
||||
if self.hud_params['agg_bb_mult'] != widget.ms:
|
||||
print 'set_aggregation', widget.ms
|
||||
self.hud_params['agg_bb_mult'] = widget.ms
|
||||
|
||||
def update_table_position(self):
|
||||
if os.name == 'nt':
|
||||
if not win32gui.IsWindow(self.table.number):
|
||||
|
@ -218,7 +269,11 @@ class Hud:
|
|||
# heap dead, burnt bodies, blood 'n guts, veins between my teeth
|
||||
for s in self.stat_windows.itervalues():
|
||||
s.kill_popups()
|
||||
try:
|
||||
# throws "invalid window handle" in WinXP (sometimes?)
|
||||
s.window.destroy()
|
||||
except:
|
||||
pass
|
||||
self.stat_windows = {}
|
||||
# also kill any aux windows
|
||||
for aux in self.aux_windows:
|
||||
|
|
|
@ -331,7 +331,8 @@ class Sql:
|
|||
speed varchar(10),
|
||||
headsUp BOOLEAN NOT NULL DEFAULT False,
|
||||
shootout BOOLEAN NOT NULL DEFAULT False,
|
||||
matrix BOOLEAN NOT NULL DEFAULT False
|
||||
matrix BOOLEAN NOT NULL DEFAULT False,
|
||||
sng BOOLEAN NOT NULL DEFAULT False
|
||||
)
|
||||
ENGINE=INNODB"""
|
||||
elif db_server == 'postgresql':
|
||||
|
@ -346,7 +347,8 @@ class Sql:
|
|||
speed varchar(10),
|
||||
headsUp BOOLEAN NOT NULL DEFAULT False,
|
||||
shootout BOOLEAN NOT NULL DEFAULT False,
|
||||
matrix BOOLEAN NOT NULL DEFAULT False
|
||||
matrix BOOLEAN NOT NULL DEFAULT False,
|
||||
sng BOOLEAN NOT NULL DEFAULT False
|
||||
)"""
|
||||
elif db_server == 'sqlite':
|
||||
self.query['createTourneyTypesTable'] = """CREATE TABLE TourneyTypes (
|
||||
|
@ -360,7 +362,8 @@ class Sql:
|
|||
speed TEXT,
|
||||
headsUp BOOLEAN NOT NULL DEFAULT 0,
|
||||
shootout BOOLEAN NOT NULL DEFAULT 0,
|
||||
matrix BOOLEAN NOT NULL DEFAULT 0
|
||||
matrix BOOLEAN NOT NULL DEFAULT 0,
|
||||
sng BOOLEAN NOT NULL DEFAULT 0
|
||||
)"""
|
||||
|
||||
################################
|
||||
|
@ -820,7 +823,21 @@ class Sql:
|
|||
comment TEXT,
|
||||
commentTs timestamp without time zone)"""
|
||||
elif db_server == 'sqlite':
|
||||
self.query['createTourneysPlayersTable'] = """ """
|
||||
self.query['createTourneysPlayersTable'] = """CREATE TABLE TourneysPlayers (
|
||||
id INT PRIMARY KEY,
|
||||
tourneyId INT,
|
||||
playerId INT,
|
||||
payinAmount INT,
|
||||
rank INT,
|
||||
winnings INT,
|
||||
nbRebuys INT DEFAULT 0,
|
||||
nbAddons INT DEFAULT 0,
|
||||
nbKO INT DEFAULT 0,
|
||||
comment TEXT,
|
||||
commentTs timestamp without time zone,
|
||||
FOREIGN KEY (tourneyId) REFERENCES Tourneys(id),
|
||||
FOREIGN KEY (playerId) REFERENCES Players(id)
|
||||
)"""
|
||||
|
||||
|
||||
################################
|
||||
|
@ -851,7 +868,18 @@ class Sql:
|
|||
comment TEXT,
|
||||
commentTs timestamp without time zone)"""
|
||||
elif db_server == 'sqlite':
|
||||
self.query['createHandsActionsTable'] = """ """
|
||||
self.query['createHandsActionsTable'] = """CREATE TABLE HandsActions (
|
||||
id INT PRIMARY KEY,
|
||||
handsPlayerId BIGINT,
|
||||
street SMALLINT,
|
||||
actionNo SMALLINT,
|
||||
action CHAR(5),
|
||||
allIn INT,
|
||||
amount INT,
|
||||
comment TEXT,
|
||||
commentTs timestamp without time zone,
|
||||
FOREIGN KEY (handsPlayerId) REFERENCES HandsPlayers(id)
|
||||
)"""
|
||||
|
||||
|
||||
################################
|
||||
|
@ -1160,26 +1188,42 @@ class Sql:
|
|||
|
||||
|
||||
if db_server == 'mysql':
|
||||
self.query['addTourneyIndex'] = """ALTER TABLE Tourneys ADD INDEX siteTourneyNo(siteTourneyNo)"""
|
||||
self.query['addTourneyIndex'] = """ALTER TABLE Tourneys ADD UNIQUE INDEX siteTourneyNo(siteTourneyNo, tourneyTypeId)"""
|
||||
elif db_server == 'postgresql':
|
||||
self.query['addTourneyIndex'] = """CREATE INDEX siteTourneyNo ON Tourneys (siteTourneyNo)"""
|
||||
self.query['addTourneyIndex'] = """CREATE UNIQUE INDEX siteTourneyNo ON Tourneys (siteTourneyNo, tourneyTypeId)"""
|
||||
elif db_server == 'sqlite':
|
||||
self.query['addHandsIndex'] = """ """
|
||||
self.query['addTourneyIndex'] = """CREATE UNIQUE INDEX siteTourneyNo ON Tourneys (siteTourneyNo, tourneyTypeId)"""
|
||||
|
||||
if db_server == 'mysql':
|
||||
self.query['addHandsIndex'] = """ALTER TABLE Hands ADD INDEX siteHandNo(siteHandNo)"""
|
||||
self.query['addHandsIndex'] = """ALTER TABLE Hands ADD UNIQUE INDEX siteHandNo(siteHandNo, gameTypeId)"""
|
||||
elif db_server == 'postgresql':
|
||||
self.query['addHandsIndex'] = """CREATE INDEX siteHandNo ON Hands (siteHandNo)"""
|
||||
self.query['addHandsIndex'] = """CREATE UNIQUE INDEX siteHandNo ON Hands (siteHandNo, gameTypeId)"""
|
||||
elif db_server == 'sqlite':
|
||||
self.query['addHandsIndex'] = """ """
|
||||
self.query['addHandsIndex'] = """CREATE UNIQUE INDEX siteHandNo ON Hands (siteHandNo, gameTypeId)"""
|
||||
|
||||
if db_server == 'mysql':
|
||||
self.query['addPlayersIndex'] = """ALTER TABLE Players ADD INDEX name(name)"""
|
||||
self.query['addPlayersIndex'] = """ALTER TABLE Players ADD UNIQUE INDEX name(name, siteId)"""
|
||||
elif db_server == 'postgresql':
|
||||
self.query['addPlayersIndex'] = """CREATE INDEX name ON Players (name)"""
|
||||
self.query['addPlayersIndex'] = """CREATE UNIQUE INDEX name ON Players (name, siteId)"""
|
||||
elif db_server == 'sqlite':
|
||||
self.query['addPlayersIndex'] = """ """
|
||||
self.query['addPlayersIndex'] = """CREATE UNIQUE INDEX name ON Players (name, siteId)"""
|
||||
|
||||
if db_server == 'mysql':
|
||||
self.query['addTPlayersIndex'] = """ALTER TABLE TourneysPlayers ADD UNIQUE INDEX tourneyId(tourneyId, playerId)"""
|
||||
elif db_server == 'postgresql':
|
||||
self.query['addTPlayersIndex'] = """CREATE UNIQUE INDEX tourneyId ON TourneysPlayers (tourneyId, playerId)"""
|
||||
elif db_server == 'sqlite':
|
||||
self.query['addTPlayersIndex'] = """CREATE UNIQUE INDEX tourneyId ON TourneysPlayers (tourneyId, playerId)"""
|
||||
|
||||
if db_server == 'mysql':
|
||||
self.query['addTTypesIndex'] = """ALTER TABLE TourneyTypes ADD UNIQUE INDEX tourneytypes_all(buyin, fee
|
||||
, maxSeats, knockout, rebuyOrAddon, speed, headsUp, shootout, matrix, sng)"""
|
||||
elif db_server == 'postgresql':
|
||||
self.query['addTTypesIndex'] = """CREATE UNIQUE INDEX tourneyTypes_all ON TourneyTypes (buyin, fee
|
||||
, maxSeats, knockout, rebuyOrAddon, speed, headsUp, shootout, matrix, sng)"""
|
||||
elif db_server == 'sqlite':
|
||||
self.query['addTTypesIndex'] = """CREATE UNIQUE INDEX tourneyTypes_all ON TourneyTypes (buyin, fee
|
||||
, maxSeats, knockout, rebuyOrAddon, speed, headsUp, shootout, matrix, sng)"""
|
||||
|
||||
self.query['get_last_hand'] = "select max(id) from Hands"
|
||||
|
||||
|
@ -1188,7 +1232,7 @@ class Sql:
|
|||
from Players, Sites
|
||||
where Players.name = %s
|
||||
and Sites.name = %s
|
||||
and Players.SiteId = Sites.id
|
||||
and Players.siteId = Sites.id
|
||||
"""
|
||||
|
||||
self.query['getSiteId'] = """SELECT id from Sites where name = %s"""
|
||||
|
@ -1537,10 +1581,11 @@ class Sql:
|
|||
"""
|
||||
|
||||
self.query['get_table_name'] = """
|
||||
select tableName, maxSeats, category, type
|
||||
from Hands,Gametypes
|
||||
where Hands.id = %s
|
||||
and Gametypes.id = Hands.gametypeId
|
||||
select h.tableName, h.maxSeats, gt.category, gt.type, gt.siteId
|
||||
from Hands h
|
||||
,Gametypes gt
|
||||
where h.id = %s
|
||||
and gt.id = h.gametypeId
|
||||
"""
|
||||
|
||||
self.query['get_actual_seat'] = """
|
||||
|
@ -2466,6 +2511,7 @@ class Sql:
|
|||
,sum(street4CheckCallRaiseDone)
|
||||
FROM HandsPlayers hp
|
||||
INNER JOIN Hands h ON (h.id = hp.handId)
|
||||
<where_clause>
|
||||
GROUP BY h.gametypeId
|
||||
,hp.playerId
|
||||
,h.seats
|
||||
|
@ -2614,6 +2660,7 @@ class Sql:
|
|||
,sum(CAST(street4CheckCallRaiseDone as integer))
|
||||
FROM HandsPlayers hp
|
||||
INNER JOIN Hands h ON (h.id = hp.handId)
|
||||
<where_clause>
|
||||
GROUP BY h.gametypeId
|
||||
,hp.playerId
|
||||
,h.seats
|
||||
|
@ -2762,6 +2809,7 @@ class Sql:
|
|||
,sum(CAST(street4CheckCallRaiseDone as integer))
|
||||
FROM HandsPlayers hp
|
||||
INNER JOIN Hands h ON (h.id = hp.handId)
|
||||
<where_clause>
|
||||
GROUP BY h.gametypeId
|
||||
,hp.playerId
|
||||
,h.seats
|
||||
|
@ -2770,9 +2818,14 @@ class Sql:
|
|||
,'d' || substr(strftime('%Y%m%d', h.handStart),3,7)
|
||||
"""
|
||||
|
||||
self.query['get_hero_hudcache_start'] = """select min(hc.styleKey)
|
||||
from HudCache hc
|
||||
where hc.playerId in <playerid_list>
|
||||
and hc.styleKey like 'd%'"""
|
||||
|
||||
if db_server == 'mysql':
|
||||
self.query['analyze'] = """
|
||||
analyze table Autorates, GameTypes, Hands, HandsPlayers, Hudcache, Players
|
||||
analyze table Autorates, GameTypes, Hands, HandsPlayers, HudCache, Players
|
||||
, Settings, Sites, Tourneys, TourneysPlayers, TourneyTypes
|
||||
"""
|
||||
else: # assume postgres
|
||||
|
|
|
@ -248,7 +248,7 @@ class ttracker_main(object):
|
|||
# get basic info about the new hand from the db
|
||||
# if there is a db error, complain, skip hand, and proceed
|
||||
try:
|
||||
(table_name, max, poker_game, type) = self.db_connection.get_table_name(new_hand_id)
|
||||
(table_name, max, poker_game, type, site_id) = self.db_connection.get_table_name(new_hand_id)
|
||||
stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, aggregate_stats[type]
|
||||
,hud_style, agg_bb_mult)
|
||||
|
||||
|
|
|
@ -257,18 +257,66 @@ class fpdb:
|
|||
|
||||
def dia_recreate_hudcache(self, widget, data=None):
|
||||
if self.obtain_global_lock():
|
||||
dia_confirm = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm recreating HUD cache")
|
||||
self.dia_confirm = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm recreating HUD cache")
|
||||
diastring = "Please confirm that you want to re-create the HUD cache."
|
||||
dia_confirm.format_secondary_text(diastring)
|
||||
self.dia_confirm.format_secondary_text(diastring)
|
||||
|
||||
response = dia_confirm.run()
|
||||
dia_confirm.destroy()
|
||||
hb = gtk.HBox(True, 1)
|
||||
self.start_date = gtk.Entry(max=12)
|
||||
self.start_date.set_text( self.db.get_hero_hudcache_start() )
|
||||
lbl = gtk.Label(" Hero's cache starts: ")
|
||||
btn = gtk.Button()
|
||||
btn.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON))
|
||||
btn.connect('clicked', self.__calendar_dialog, self.start_date)
|
||||
|
||||
hb.pack_start(lbl, expand=True, padding=3)
|
||||
hb.pack_start(self.start_date, expand=True, padding=2)
|
||||
hb.pack_start(btn, expand=False, padding=3)
|
||||
self.dia_confirm.vbox.add(hb)
|
||||
hb.show_all()
|
||||
|
||||
response = self.dia_confirm.run()
|
||||
self.dia_confirm.destroy()
|
||||
if response == gtk.RESPONSE_YES:
|
||||
self.db.rebuild_hudcache()
|
||||
elif response == gtk.REPSONSE_NO:
|
||||
self.db.rebuild_hudcache( self.start_date.get_text() )
|
||||
elif response == gtk.RESPONSE_NO:
|
||||
print 'User cancelled rebuilding hud cache'
|
||||
|
||||
self.release_global_lock()
|
||||
|
||||
def __calendar_dialog(self, widget, entry):
|
||||
self.dia_confirm.set_modal(False)
|
||||
d = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
||||
d.set_title('Pick a date')
|
||||
|
||||
vb = gtk.VBox()
|
||||
cal = gtk.Calendar()
|
||||
vb.pack_start(cal, expand=False, padding=0)
|
||||
|
||||
btn = gtk.Button('Done')
|
||||
btn.connect('clicked', self.__get_date, cal, entry, d)
|
||||
|
||||
vb.pack_start(btn, expand=False, padding=4)
|
||||
|
||||
d.add(vb)
|
||||
d.set_position(gtk.WIN_POS_MOUSE)
|
||||
d.show_all()
|
||||
|
||||
def __get_dates(self):
|
||||
t1 = self.start_date.get_text()
|
||||
if t1 == '':
|
||||
t1 = '1970-01-01'
|
||||
return (t1)
|
||||
|
||||
def __get_date(self, widget, calendar, entry, win):
|
||||
# year and day are correct, month is 0..11
|
||||
(year, month, day) = calendar.get_date()
|
||||
month += 1
|
||||
ds = '%04d-%02d-%02d' % (year, month, day)
|
||||
entry.set_text(ds)
|
||||
win.destroy()
|
||||
self.dia_confirm.set_modal(True)
|
||||
|
||||
def dia_regression_test(self, widget, data=None):
|
||||
self.warning_box("Unimplemented: Regression Test")
|
||||
self.obtain_global_lock()
|
||||
|
|
|
@ -38,6 +38,8 @@ class fpdb_db:
|
|||
MYSQL_INNODB = 2
|
||||
PGSQL = 3
|
||||
SQLITE = 4
|
||||
sqlite_db_dir = ".." + os.sep + "database"
|
||||
|
||||
def __init__(self):
|
||||
"""Simple constructor, doesnt really do anything"""
|
||||
self.db = None
|
||||
|
@ -119,7 +121,12 @@ class fpdb_db:
|
|||
sqlite3 = pool.manage(sqlite3, pool_size=1)
|
||||
else:
|
||||
logging.warning("SQLite won't work well without 'sqlalchemy' installed.")
|
||||
self.db = sqlite3.connect(database,detect_types=sqlite3.PARSE_DECLTYPES)
|
||||
|
||||
if not os.path.isdir(self.sqlite_db_dir):
|
||||
print "Creating directory: '%s'" % (self.sqlite_db_dir)
|
||||
os.mkdir(self.sqlite_db_dir)
|
||||
self.db = sqlite3.connect( self.sqlite_db_dir + os.sep + database
|
||||
, detect_types=sqlite3.PARSE_DECLTYPES )
|
||||
sqlite3.register_converter("bool", lambda x: bool(int(x)))
|
||||
sqlite3.register_adapter(bool, lambda x: "1" if x else "0")
|
||||
else:
|
||||
|
|
|
@ -547,7 +547,7 @@ class Importer:
|
|||
if self.callHud:
|
||||
#print "call to HUD here. handsId:",handsId
|
||||
#pipe the Hands.id out to the HUD
|
||||
#print "sending hand to hud", handsId, "pipe =", self.caller.pipe_to_hud
|
||||
print "sending hand to hud", handsId, "pipe =", self.caller.pipe_to_hud
|
||||
self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep)
|
||||
except Exceptions.DuplicateError:
|
||||
duplicates += 1
|
||||
|
|
|
@ -118,7 +118,7 @@ def mainParser(settings, siteID, category, hand, config, db = None, writeq = Non
|
|||
seatLines.append(line)
|
||||
|
||||
names = fpdb_simple.parseNames(seatLines)
|
||||
playerIDs = fpdb_simple.recognisePlayerIDs(db, names, siteID) # inserts players as needed
|
||||
playerIDs = db.recognisePlayerIDs(names, siteID) # inserts players as needed
|
||||
tmp = fpdb_simple.parseCashesAndSeatNos(seatLines)
|
||||
startCashes = tmp['startCashes']
|
||||
seatNos = tmp['seatNos']
|
||||
|
|
|
@ -913,6 +913,7 @@ def recogniseGametypeID(backend, db, cursor, topline, smallBlindLine, site_id, c
|
|||
#end def recogniseGametypeID
|
||||
|
||||
def recogniseTourneyTypeId(db, siteId, tourneySiteId, buyin, fee, knockout, rebuyOrAddon):
|
||||
ret = -1
|
||||
cursor = db.get_cursor()
|
||||
# First we try to find the tourney itself (by its tourneySiteId) in case it has already been inserted before (by a summary file for instance)
|
||||
# The reason is that some tourneys may not be identified correctly in the HH toplines (especially Buy-In and Fee which are used to search/create the TourneyTypeId)
|
||||
|
@ -922,83 +923,44 @@ def recogniseTourneyTypeId(db, siteId, tourneySiteId, buyin, fee, knockout, rebu
|
|||
|
||||
try:
|
||||
len(result)
|
||||
ret = result[0]
|
||||
except:
|
||||
cursor.execute ("SELECT id FROM TourneyTypes WHERE siteId=%s AND buyin=%s AND fee=%s AND knockout=%s AND rebuyOrAddon=%s", (siteId, buyin, fee, knockout, rebuyOrAddon))
|
||||
cursor.execute( """SELECT id FROM TourneyTypes
|
||||
WHERE siteId=%s AND buyin=%s AND fee=%s
|
||||
AND knockout=%s AND rebuyOrAddon=%s"""
|
||||
, (siteId, buyin, fee, knockout, rebuyOrAddon) )
|
||||
result = cursor.fetchone()
|
||||
#print "tried SELECTing gametypes.id, result:",result
|
||||
#print "tried selecting tourneytypes.id, result:", result
|
||||
|
||||
try:
|
||||
len(result)
|
||||
ret = result[0]
|
||||
except TypeError:#this means we need to create a new entry
|
||||
cursor.execute("""INSERT INTO TourneyTypes (siteId, buyin, fee, knockout, rebuyOrAddon) VALUES (%s, %s, %s, %s, %s)""", (siteId, buyin, fee, knockout, rebuyOrAddon))
|
||||
cursor.execute("SELECT id FROM TourneyTypes WHERE siteId=%s AND buyin=%s AND fee=%s AND knockout=%s AND rebuyOrAddon=%s", (siteId, buyin, fee, knockout, rebuyOrAddon))
|
||||
#print "insert new tourneytype record ..."
|
||||
try:
|
||||
cursor.execute( """INSERT INTO TourneyTypes (siteId, buyin, fee, knockout, rebuyOrAddon)
|
||||
VALUES (%s, %s, %s, %s, %s)"""
|
||||
, (siteId, buyin, fee, knockout, rebuyOrAddon) )
|
||||
ret = db.get_last_insert_id(cursor)
|
||||
except:
|
||||
#print "maybe tourneytype was created since select, try selecting again ..."
|
||||
cursor.execute( """SELECT id FROM TourneyTypes
|
||||
WHERE siteId=%s AND buyin=%s AND fee=%s
|
||||
AND knockout=%s AND rebuyOrAddon=%s"""
|
||||
, (siteId, buyin, fee, knockout, rebuyOrAddon) )
|
||||
result = cursor.fetchone()
|
||||
try:
|
||||
len(result)
|
||||
ret = result[0]
|
||||
except:
|
||||
print "Failed to find or insert TourneyTypes record"
|
||||
ret = -1 # failed to find or insert record
|
||||
#print "tried selecting tourneytypes.id again, result:", result
|
||||
|
||||
return result[0]
|
||||
#print "recogniseTourneyTypeId: returning", ret
|
||||
return ret
|
||||
#end def recogniseTourneyTypeId
|
||||
|
||||
#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
|
||||
# { playername: id } instead of depending on it's relation to the positions list
|
||||
# then this can be reduced in complexity a bit
|
||||
|
||||
#def recognisePlayerIDs(cursor, names, site_id):
|
||||
# result = []
|
||||
# for i in xrange(len(names)):
|
||||
# cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],))
|
||||
# tmp=cursor.fetchall()
|
||||
# if (len(tmp)==0): #new player
|
||||
# cursor.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)", (names[i], site_id))
|
||||
# #print "Number of players rows inserted: %d" % cursor.rowcount
|
||||
# cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],))
|
||||
# tmp=cursor.fetchall()
|
||||
# #print "recognisePlayerIDs, names[i]:",names[i],"tmp:",tmp
|
||||
# result.append(tmp[0][0])
|
||||
# return result
|
||||
|
||||
def recognisePlayerIDs(db, names, site_id):
|
||||
c = db.get_cursor()
|
||||
q = "SELECT name,id FROM Players WHERE siteid=%d and (name=%s)" %(site_id, " OR name=".join([db.sql.query['placeholder'] for n in names]))
|
||||
c.execute(q, names) # get all playerids by the names passed in
|
||||
ids = dict(c.fetchall()) # convert to dict
|
||||
if len(ids) != len(names):
|
||||
notfound = [n for n in names if n not in ids] # make list of names not in database
|
||||
if notfound: # insert them into database
|
||||
q_ins = "INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")"
|
||||
q_ins = q_ins.replace('%s', db.sql.query['placeholder'])
|
||||
c.executemany(q_ins, [(n,) for n in notfound])
|
||||
q2 = "SELECT name,id FROM Players WHERE siteid=%d and (name=%s)" % (site_id, " OR name=".join(["%s" for n in notfound]))
|
||||
q2 = q2.replace('%s', db.sql.query['placeholder'])
|
||||
c.execute(q2, notfound) # get their new ids
|
||||
tmp = c.fetchall()
|
||||
for n,id in tmp: # put them all into the same dict
|
||||
ids[n] = id
|
||||
# return them in the SAME ORDER that they came in in the names argument, rather than the order they came out of the DB
|
||||
return [ids[n] for n in names]
|
||||
#end def recognisePlayerIDs
|
||||
|
||||
|
||||
# Here's a version that would work if it wasn't for the fact that it needs to have the output in the same order as input
|
||||
# this version could also be improved upon using list comprehensions, etc
|
||||
|
||||
#def recognisePlayerIDs(cursor, names, site_id):
|
||||
# result = []
|
||||
# notfound = []
|
||||
# cursor.execute("SELECT name,id FROM Players WHERE name='%s'" % "' OR name='".join(names))
|
||||
# tmp = dict(cursor.fetchall())
|
||||
# for n in names:
|
||||
# if n not in tmp:
|
||||
# notfound.append(n)
|
||||
# else:
|
||||
# result.append(tmp[n])
|
||||
# if notfound:
|
||||
# cursor.executemany("INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")", (notfound))
|
||||
# cursor.execute("SELECT id FROM Players WHERE name='%s'" % "' OR name='".join(notfound))
|
||||
# tmp = cursor.fetchall()
|
||||
# for n in tmp:
|
||||
# result.append(n[0])
|
||||
#
|
||||
# return result
|
||||
|
||||
#recognises the name in the given line and returns its array position in the given array
|
||||
def recognisePlayerNo(line, names, atype):
|
||||
|
|
Loading…
Reference in New Issue
Block a user