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

This commit is contained in:
Mika Bostrom 2010-07-22 23:29:24 +03:00
commit d50030e479
7 changed files with 217 additions and 65 deletions

View File

@ -357,6 +357,7 @@ class Game:
class Database: class Database:
def __init__(self, node): def __init__(self, node):
self.db_name = node.getAttribute("db_name") self.db_name = node.getAttribute("db_name")
self.db_desc = node.getAttribute("db_desc")
self.db_server = node.getAttribute("db_server").lower() self.db_server = node.getAttribute("db_server").lower()
self.db_ip = node.getAttribute("db_ip") self.db_ip = node.getAttribute("db_ip")
self.db_user = node.getAttribute("db_user") self.db_user = node.getAttribute("db_user")
@ -817,6 +818,9 @@ class Config:
try: db['db-databaseName'] = name try: db['db-databaseName'] = name
except: pass except: pass
try: db['db-desc'] = self.supported_databases[name].db_desc
except: pass
try: db['db-host'] = self.supported_databases[name].db_ip try: db['db-host'] = self.supported_databases[name].db_ip
except: pass except: pass
@ -834,20 +838,29 @@ class Config:
return db return db
def set_db_parameters(self, db_name = 'fpdb', db_ip = None, db_user = None, def set_db_parameters(self, db_name = 'fpdb', db_ip = None, db_user = None,
db_pass = None, db_server = None): db_pass = None, db_desc = None, db_server = None,
default = "False"):
db_node = self.get_db_node(db_name) db_node = self.get_db_node(db_name)
default = default.lower()
defaultb = string_to_bool(default, False)
if db_node != None: if db_node != None:
if db_desc is not None: db_node.setAttribute("db_desc", db_desc)
if db_ip is not None: db_node.setAttribute("db_ip", db_ip) if db_ip is not None: db_node.setAttribute("db_ip", db_ip)
if db_user is not None: db_node.setAttribute("db_user", db_user) if db_user is not None: db_node.setAttribute("db_user", db_user)
if db_pass is not None: db_node.setAttribute("db_pass", db_pass) if db_pass is not None: db_node.setAttribute("db_pass", db_pass)
if db_server is not None: db_node.setAttribute("db_server", db_server) if db_server is not None: db_node.setAttribute("db_server", db_server)
if db_type is not None: db_node.setAttribute("db_type", db_type) if defaultb: db_node.setAttribute("default", default)
elif db_node.hasAttribute("default"):
db_node.removeAttribute("default")
if self.supported_databases.has_key(db_name): if self.supported_databases.has_key(db_name):
if db_desc is not None: self.supported_databases[db_name].dp_desc = db_desc
if db_ip is not None: self.supported_databases[db_name].dp_ip = db_ip if db_ip is not None: self.supported_databases[db_name].dp_ip = db_ip
if db_user is not None: self.supported_databases[db_name].dp_user = db_user if db_user is not None: self.supported_databases[db_name].dp_user = db_user
if db_pass is not None: self.supported_databases[db_name].dp_pass = db_pass if db_pass is not None: self.supported_databases[db_name].dp_pass = db_pass
if db_server is not None: self.supported_databases[db_name].dp_server = db_server if db_server is not None: self.supported_databases[db_name].dp_server = db_server
if db_type is not None: self.supported_databases[db_name].dp_type = db_type self.supported_databases[db_name].db_selected = defaultb
if defaultb:
self.db_selected = db_name
return return
def get_backend(self, name): def get_backend(self, name):

View File

@ -74,7 +74,7 @@ except ImportError:
use_numpy = False use_numpy = False
DB_VERSION = 136 DB_VERSION = 137
# Variance created as sqlite has a bunch of undefined aggregate functions. # Variance created as sqlite has a bunch of undefined aggregate functions.
@ -147,7 +147,6 @@ class Database:
{'tab':'Hands', 'col':'gametypeId', 'drop':0} {'tab':'Hands', 'col':'gametypeId', 'drop':0}
, {'tab':'HandsPlayers', 'col':'handId', 'drop':0} , {'tab':'HandsPlayers', 'col':'handId', 'drop':0}
, {'tab':'HandsPlayers', 'col':'playerId', 'drop':0} , {'tab':'HandsPlayers', 'col':'playerId', 'drop':0}
, {'tab':'HandsPlayers', 'col':'tourneyTypeId', 'drop':0}
, {'tab':'HandsPlayers', 'col':'tourneysPlayersId', 'drop':0} , {'tab':'HandsPlayers', 'col':'tourneysPlayersId', 'drop':0}
, {'tab':'HudCache', 'col':'gametypeId', 'drop':1} , {'tab':'HudCache', 'col':'gametypeId', 'drop':1}
, {'tab':'HudCache', 'col':'playerId', 'drop':0} , {'tab':'HudCache', 'col':'playerId', 'drop':0}
@ -168,7 +167,6 @@ class Database:
{'fktab':'Hands', 'fkcol':'gametypeId', 'rtab':'Gametypes', 'rcol':'id', 'drop':1} {'fktab':'Hands', 'fkcol':'gametypeId', 'rtab':'Gametypes', 'rcol':'id', 'drop':1}
, {'fktab':'HandsPlayers', 'fkcol':'handId', 'rtab':'Hands', 'rcol':'id', 'drop':1} , {'fktab':'HandsPlayers', 'fkcol':'handId', 'rtab':'Hands', 'rcol':'id', 'drop':1}
, {'fktab':'HandsPlayers', 'fkcol':'playerId', 'rtab':'Players', 'rcol':'id', 'drop':1} , {'fktab':'HandsPlayers', 'fkcol':'playerId', 'rtab':'Players', 'rcol':'id', 'drop':1}
, {'fktab':'HandsPlayers', 'fkcol':'tourneyTypeId', 'rtab':'TourneyTypes', 'rcol':'id', 'drop':1}
, {'fktab':'HandsPlayers', 'fkcol':'tourneysPlayersId','rtab':'TourneysPlayers','rcol':'id', 'drop':1} , {'fktab':'HandsPlayers', 'fkcol':'tourneysPlayersId','rtab':'TourneysPlayers','rcol':'id', 'drop':1}
, {'fktab':'HandsActions', 'fkcol':'handsPlayerId', 'rtab':'HandsPlayers', 'rcol':'id', 'drop':1} , {'fktab':'HandsActions', 'fkcol':'handsPlayerId', 'rtab':'HandsPlayers', 'rcol':'id', 'drop':1}
, {'fktab':'HudCache', 'fkcol':'gametypeId', 'rtab':'Gametypes', 'rcol':'id', 'drop':1} , {'fktab':'HudCache', 'fkcol':'gametypeId', 'rtab':'Gametypes', 'rcol':'id', 'drop':1}
@ -1641,7 +1639,6 @@ class Database:
pdata[p]['street3Bets'], pdata[p]['street3Bets'],
pdata[p]['street4Bets'], pdata[p]['street4Bets'],
pdata[p]['position'], pdata[p]['position'],
pdata[p]['tourneyTypeId'],
pdata[p]['tourneysPlayersIds'], pdata[p]['tourneysPlayersIds'],
pdata[p]['startCards'], pdata[p]['startCards'],
pdata[p]['street0_3BChance'], pdata[p]['street0_3BChance'],
@ -1983,17 +1980,21 @@ class Database:
(hand.tourNo, hand.siteId) (hand.tourNo, hand.siteId)
) )
result=cursor.fetchone() result=cursor.fetchone()
#print "result of fetching TT by number and site:",result
if result: if result:
tourneyTypeId = result[0] tourneyTypeId = result[0]
else: else:
# Check for an existing TTypeId that matches tourney info, if not found create it # Check for an existing TTypeId that matches tourney info, if not found create it
#print "info that we use to get TT by detail:", hand.siteId, hand.buyinCurrency, hand.buyin, hand.fee, hand.gametype['category'], hand.gametype['limitType'], hand.isKO, hand.isRebuy, hand.isAddOn, hand.speed, hand.isShootout, hand.isMatrix
#print "the query:",self.sql.query['getTourneyTypeId'].replace('%s', self.sql.query['placeholder'])
cursor.execute (self.sql.query['getTourneyTypeId'].replace('%s', self.sql.query['placeholder']), cursor.execute (self.sql.query['getTourneyTypeId'].replace('%s', self.sql.query['placeholder']),
(hand.siteId, hand.buyinCurrency, hand.buyin, hand.fee, hand.gametype['category'], hand.gametype['limitType'], hand.isKO, (hand.siteId, hand.buyinCurrency, hand.buyin, hand.fee, hand.gametype['category'], hand.gametype['limitType'], hand.isKO,
hand.isRebuy, hand.isRebuy, hand.speed, hand.isShootout, hand.isMatrix, hand.added, hand.addedCurrency) hand.isRebuy, hand.isAddOn, hand.speed, hand.isShootout, hand.isMatrix)
) )
result=cursor.fetchone() result=cursor.fetchone()
#print "result of fetching TT by details:",result
try: try:
tourneyTypeId = result[0] tourneyTypeId = result[0]
except TypeError: #this means we need to create a new entry except TypeError: #this means we need to create a new entry

View File

@ -59,7 +59,6 @@ class DerivedStats():
self.handsplayers[player[1]]['foldSbToStealChance'] = False self.handsplayers[player[1]]['foldSbToStealChance'] = False
self.handsplayers[player[1]]['foldedSbToSteal'] = False self.handsplayers[player[1]]['foldedSbToSteal'] = False
self.handsplayers[player[1]]['foldedBbToSteal'] = False self.handsplayers[player[1]]['foldedBbToSteal'] = False
self.handsplayers[player[1]]['tourneyTypeId'] = None
for i in range(5): for i in range(5):
self.handsplayers[player[1]]['street%dCalls' % i] = 0 self.handsplayers[player[1]]['street%dCalls' % i] = 0
@ -143,7 +142,6 @@ class DerivedStats():
self.handsplayers[player[1]]['startCash'] = int(100 * Decimal(player[2])) self.handsplayers[player[1]]['startCash'] = int(100 * Decimal(player[2]))
self.handsplayers[player[1]]['sitout'] = False #TODO: implement actual sitout detection self.handsplayers[player[1]]['sitout'] = False #TODO: implement actual sitout detection
if hand.gametype["type"]=="tour": if hand.gametype["type"]=="tour":
self.handsplayers[player[1]]['tourneyTypeId']=hand.tourneyTypeId
self.handsplayers[player[1]]['tourneysPlayersIds'] = hand.tourneysPlayersIds[player[1]] self.handsplayers[player[1]]['tourneysPlayersIds'] = hand.tourneysPlayersIds[player[1]]
else: else:
self.handsplayers[player[1]]['tourneysPlayersIds'] = None self.handsplayers[player[1]]['tourneysPlayersIds'] = None

View File

@ -33,17 +33,32 @@ log = logging.getLogger("maintdbs")
import Exceptions import Exceptions
import Database import Database
import SQL
class GuiDatabase: class GuiDatabase:
# columns in liststore:
MODEL_DBMS = 0
MODEL_NAME = 1
MODEL_DESC = 2
MODEL_USER = 3
MODEL_PASS = 4
MODEL_HOST = 5
MODEL_DFLT = 6
MODEL_DFLTIC = 7
MODEL_STATUS = 8
MODEL_STATIC = 9
# columns in listview:
COL_DBMS = 0 COL_DBMS = 0
COL_NAME = 1 COL_NAME = 1
COL_DESC = 2 COL_DESC = 2
COL_USER = 3 COL_USER = 3
COL_PASS = 4 COL_PASS = 4
COL_HOST = 5 COL_HOST = 5
COL_ICON = 6 COL_DFLT = 6
COL_ICON = 7
def __init__(self, config, mainwin, dia): def __init__(self, config, mainwin, dia):
self.config = config self.config = config
@ -56,9 +71,9 @@ class GuiDatabase:
#gtk.Widget.set_size_request(self.vbox, 700, 400); #gtk.Widget.set_size_request(self.vbox, 700, 400);
# list of databases in self.config.supported_databases: # list of databases in self.config.supported_databases:
self.liststore = gtk.ListStore(str, str, str, str self.liststore = gtk.ListStore(str, str, str, str, str
,str, str, str, str) #object, gtk.gdk.Pixbuf) ,str, str, str, str, str)
# dbms, name, comment, user, pass, ip, status(, icon?) # dbms, name, comment, user, passwd, host, "", default_icon, status, icon
# this is how to add a filter: # this is how to add a filter:
# #
# # Creation of the filter, from the model # # Creation of the filter, from the model
@ -70,11 +85,12 @@ class GuiDatabase:
self.listview = gtk.TreeView(model=self.liststore) self.listview = gtk.TreeView(model=self.liststore)
self.listview.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_NONE) self.listview.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_NONE)
self.listcols = [] self.listcols = []
self.changes = False
scrolledwindow = gtk.ScrolledWindow() self.scrolledwindow = gtk.ScrolledWindow()
scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
scrolledwindow.add(self.listview) self.scrolledwindow.add(self.listview)
self.vbox.pack_start(scrolledwindow, expand=True, fill=True, padding=0) self.vbox.pack_start(self.scrolledwindow, expand=True, fill=True, padding=0)
refreshbutton = gtk.Button("Refresh") refreshbutton = gtk.Button("Refresh")
refreshbutton.connect("clicked", self.refresh, None) refreshbutton.connect("clicked", self.refresh, None)
@ -87,18 +103,28 @@ class GuiDatabase:
col = self.addTextColumn("Username", 3, True) col = self.addTextColumn("Username", 3, True)
col = self.addTextColumn("Password", 4, True) col = self.addTextColumn("Password", 4, True)
col = self.addTextColumn("Host", 5, True) col = self.addTextColumn("Host", 5, True)
col = self.addTextObjColumn("", 6) col = self.addTextObjColumn("Default", 6, 6)
col = self.addTextObjColumn("Status", 7, 8)
#self.listview.get_selection().set_mode(gtk.SELECTION_SINGLE)
#self.listview.get_selection().connect("changed", self.on_selection_changed)
self.listview.add_events(gtk.gdk.BUTTON_PRESS_MASK)
self.listview.connect('button_press_event', self.selectTest)
self.loadDbs() self.loadDbs()
self.dia.connect('response', self.dialog_response_cb) #self.dia.connect('response', self.dialog_response_cb)
except: except:
err = traceback.extract_tb(sys.exc_info()[2])[-1] err = traceback.extract_tb(sys.exc_info()[2])[-1]
print 'guidbmaint: '+ err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1]) print 'guidbmaint: '+ err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1])
def dialog_response_cb(self, dialog, response_id): def dialog_response_cb(self, dialog, response_id):
# this is called whether close button is pressed or window is closed # this is called whether close button is pressed or window is closed
log.info('dialog_response_cb: response_id='+str(response_id))
#if self.changes:
# self.config.save()
dialog.destroy() dialog.destroy()
return(response_id)
def get_dialog(self): def get_dialog(self):
@ -125,6 +151,7 @@ class GuiDatabase:
def edited_cb(self, cell, path, new_text, user_data): def edited_cb(self, cell, path, new_text, user_data):
liststore, col = user_data liststore, col = user_data
log.info('edited_cb: col = '+str(col))
valid = True valid = True
name = self.liststore[path][self.COL_NAME] name = self.liststore[path][self.COL_NAME]
@ -138,10 +165,11 @@ class GuiDatabase:
self.config.set_db_parameters( db_server = self.liststore[path][self.COL_DBMS] self.config.set_db_parameters( db_server = self.liststore[path][self.COL_DBMS]
, db_name = name , db_name = name
, db_desc = self.liststore[path][self.COL_DESC]
, db_ip = self.liststore[path][self.COL_HOST] , db_ip = self.liststore[path][self.COL_HOST]
, db_user = self.liststore[path][self.COL_USER] , db_user = self.liststore[path][self.COL_USER]
, db_pass = self.liststore[path][self.COL_PASS] ) , db_pass = self.liststore[path][self.COL_PASS] )
self.changes = True
return return
def check_new_name(self, path, new_text): def check_new_name(self, path, new_text):
@ -152,38 +180,73 @@ class GuiDatabase:
#TODO: popup an error message telling user names must be unique #TODO: popup an error message telling user names must be unique
return name_ok return name_ok
def addTextObjColumn(self, title, n): def addTextObjColumn(self, title, viewcol, storecol, editable=False):
col = gtk.TreeViewColumn(title) col = gtk.TreeViewColumn(title)
self.listview.append_column(col) self.listview.append_column(col)
cRenderT = gtk.CellRendererText() cRenderT = gtk.CellRendererText()
cRenderT.set_property("wrap-mode", pango.WRAP_WORD_CHAR) cRenderT.set_property("wrap-mode", pango.WRAP_WORD_CHAR)
col.pack_start(cRenderT, False) col.pack_start(cRenderT, False)
col.add_attribute(cRenderT, 'text', n) col.add_attribute(cRenderT, 'text', storecol)
cRenderP = gtk.CellRendererPixbuf() cRenderP = gtk.CellRendererPixbuf()
col.pack_start(cRenderP, False) col.pack_start(cRenderP, True)
col.add_attribute(cRenderP, 'stock-id', n+1) col.add_attribute(cRenderP, 'stock-id', storecol+1)
col.set_max_width(1000) col.set_max_width(1000)
col.set_spacing(0) # no effect col.set_spacing(0) # no effect
self.listcols.append(col) self.listcols.append(col)
#col.set_clickable(True)
#col.connect("clicked", self.sortCols, p) col.set_clickable(True)
col.connect("clicked", self.sortCols, viewcol)
return(col) return(col)
def selectTest(self, widget, event):
if event.button == 1: # and event.type == gtk.gdk._2BUTTON_PRESS:
pthinfo = self.listview.get_path_at_pos( int(event.x), int(event.y) )
if pthinfo is not None:
path, col, cellx, celly = pthinfo
row = path[0]
if col == self.listcols[self.COL_DFLT]:
if self.liststore[row][self.MODEL_STATUS] == 'ok' and self.liststore[row][self.MODEL_DFLTIC] is None:
self.setDefaultDB(row)
def setDefaultDB(self, row):
print "set new defaultdb:", row, self.liststore[row][self.MODEL_NAME]
for r in xrange(len(self.liststore)):
if r == row:
self.liststore[r][self.MODEL_DFLTIC] = gtk.STOCK_APPLY
default = "True"
else:
self.liststore[r][self.MODEL_DFLTIC] = None
default = "False"
self.config.set_db_parameters( db_server = self.liststore[r][self.COL_DBMS]
, db_name = self.liststore[r][self.COL_NAME]
, db_desc = self.liststore[r][self.COL_DESC]
, db_ip = self.liststore[r][self.COL_HOST]
, db_user = self.liststore[r][self.COL_USER]
, db_pass = self.liststore[r][self.COL_PASS]
, default = default
)
self.changes = True
return
def loadDbs(self): def loadDbs(self):
self.liststore.clear() self.liststore.clear()
self.listcols = [] #self.listcols = []
self.dbs = [] # list of tuples: (dbms, name, comment, user, passwd, host, status, icon) dia = self.info_box2(None, 'Testing database connections ... ', "", False, False)
while gtk.events_pending():
gtk.mainiteration()
try: try:
# want to fill: dbms, name, comment, user, passwd, host, status(, icon?) # want to fill: dbms, name, comment, user, passwd, host, default, status, icon
for name in self.config.supported_databases: #db_ip/db_user/db_pass/db_server for name in self.config.supported_databases: #db_ip/db_user/db_pass/db_server
dbms = self.config.supported_databases[name].db_server # mysql/postgresql/sqlite dbms = self.config.supported_databases[name].db_server # mysql/postgresql/sqlite
dbms_num = self.config.get_backend(dbms) # 2 / 3 / 4 dbms_num = self.config.get_backend(dbms) # 2 / 3 / 4
comment = "" comment = self.config.supported_databases[name].db_desc
if dbms == 'sqlite': if dbms == 'sqlite':
user = "" user = ""
passwd = "" passwd = ""
@ -191,22 +254,30 @@ class GuiDatabase:
user = self.config.supported_databases[name].db_user user = self.config.supported_databases[name].db_user
passwd = self.config.supported_databases[name].db_pass passwd = self.config.supported_databases[name].db_pass
host = self.config.supported_databases[name].db_ip host = self.config.supported_databases[name].db_ip
default = (name == self.config.db_selected)
default_icon = None
if default: default_icon = gtk.STOCK_APPLY
status = "" status = ""
icon = None icon = None
err_msg = "" err_msg = ""
db = Database.Database(self.config, sql = None, autoconnect = False) sql = SQL.Sql(db_server=dbms)
db = Database.Database(self.config, sql = sql, autoconnect = False)
# try to connect to db, set status and err_msg if it fails # try to connect to db, set status and err_msg if it fails
try: try:
# is creating empty db for sqlite ... mod db.py further? # is creating empty db for sqlite ... mod db.py further?
# add noDbTables flag to db.py? # add noDbTables flag to db.py?
log.debug("loaddbs: trying to connect to: %s/%s, %s, %s/%s" % (str(dbms_num),dbms,name,user,passwd))
db.connect(backend=dbms_num, host=host, database=name, user=user, password=passwd, create=False) db.connect(backend=dbms_num, host=host, database=name, user=user, password=passwd, create=False)
if db.connected: if db.connected:
log.debug(" connected ok")
status = 'ok' status = 'ok'
icon = gtk.STOCK_APPLY icon = gtk.STOCK_APPLY
if db.wrongDbVersion: if db.wrongDbVersion:
status = 'old' status = 'old'
icon = gtk.STOCK_INFO icon = gtk.STOCK_INFO
else:
log.debug(" not connected but no exception")
except Exceptions.FpdbMySQLAccessDenied: except Exceptions.FpdbMySQLAccessDenied:
err_msg = "MySQL Server reports: Access denied. Are your permissions set correctly?" err_msg = "MySQL Server reports: Access denied. Are your permissions set correctly?"
status = "failed" status = "failed"
@ -230,13 +301,17 @@ class GuiDatabase:
+ err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1]) ) + err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1]) )
status = "failed" status = "failed"
icon = gtk.STOCK_CANCEL icon = gtk.STOCK_CANCEL
if err_msg:
log.info( 'db connection to '+str(dbms_num)+','+host+','+name+','+user+','+passwd+' failed: '
+ err_msg )
b = gtk.Button(name) b = gtk.Button(name)
b.show() b.show()
iter = self.liststore.append( (dbms, name, comment, user, passwd, host, status, icon) ) iter = self.liststore.append( (dbms, name, comment, user, passwd, host, "", default_icon, status, icon) )
self.info_box2(dia[0], "finished.", "", False, True)
self.listview.show() self.listview.show()
scrolledwindow.show() self.scrolledwindow.show()
self.vbox.show() self.vbox.show()
self.dia.set_focus(self.listview) self.dia.set_focus(self.listview)
@ -249,13 +324,16 @@ class GuiDatabase:
def sortCols(self, col, n): def sortCols(self, col, n):
try: try:
log.info('sortcols n='+str(n))
if not col.get_sort_indicator() or col.get_sort_order() == gtk.SORT_ASCENDING: if not col.get_sort_indicator() or col.get_sort_order() == gtk.SORT_ASCENDING:
col.set_sort_order(gtk.SORT_DESCENDING) col.set_sort_order(gtk.SORT_DESCENDING)
else: else:
col.set_sort_order(gtk.SORT_ASCENDING) col.set_sort_order(gtk.SORT_ASCENDING)
self.liststore.set_sort_column_id(n, col.get_sort_order()) self.liststore.set_sort_column_id(n, col.get_sort_order())
#self.liststore.set_sort_func(n, self.sortnums, (n,grid)) #self.liststore.set_sort_func(n, self.sortnums, (n,grid))
log.info('sortcols len(listcols)='+str(len(self.listcols)))
for i in xrange(len(self.listcols)): for i in xrange(len(self.listcols)):
log.info('sortcols i='+str(i))
self.listcols[i].set_sort_indicator(False) self.listcols[i].set_sort_indicator(False)
self.listcols[n].set_sort_indicator(True) self.listcols[n].set_sort_indicator(True)
# use this listcols[col].set_sort_indicator(True) # use this listcols[col].set_sort_indicator(True)
@ -264,10 +342,69 @@ class GuiDatabase:
err = traceback.extract_tb(sys.exc_info()[2]) err = traceback.extract_tb(sys.exc_info()[2])
print "***sortCols error: " + str(sys.exc_info()[1]) print "***sortCols error: " + str(sys.exc_info()[1])
print "\n".join( [e[0]+':'+str(e[1])+" "+e[2] for e in err] ) print "\n".join( [e[0]+':'+str(e[1])+" "+e[2] for e in err] )
log.info('sortCols error: ' + str(sys.exc_info()) )
def refresh(self, widget, data): def refresh(self, widget, data):
self.loadDbs() self.loadDbs()
def info_box(self, dia, str1, str2, run, destroy):
if dia is None:
#if run:
btns = gtk.BUTTONS_NONE
btns = gtk.BUTTONS_OK
dia = gtk.MessageDialog( parent=self.main_window, flags=gtk.DIALOG_DESTROY_WITH_PARENT
, type=gtk.MESSAGE_INFO, buttons=(btns), message_format=str1 )
# try to remove buttons!
# (main message is in inverse video if no buttons, so try removing them after
# creating dialog)
# NO! message just goes back to inverse video :-( use info_box2 instead
for c in dia.vbox.get_children():
if isinstance(c, gtk.HButtonBox):
for d in c.get_children():
log.info('child: '+str(d)+' is a '+str(d.__class__))
if isinstance(d, gtk.Button):
log.info('removing button '+str(d))
c.remove(d)
if str2:
dia.format_secondary_text(str2)
else:
dia.set_markup(str1)
if str2:
dia.format_secondary_text(str2)
dia.show()
response = None
if run: response = dia.run()
if destroy: dia.destroy()
return (dia, response)
def info_box2(self, dia, str1, str2, run, destroy):
if dia is None:
# create dialog and add icon and label
btns = (gtk.BUTTONS_OK)
btns = None
# messagedialog puts text in inverse colors if no buttons are displayed??
#dia = gtk.MessageDialog( parent=self.main_window, flags=gtk.DIALOG_DESTROY_WITH_PARENT
# , type=gtk.MESSAGE_INFO, buttons=(btns), message_format=str1 )
dia = gtk.Dialog( parent=self.main_window, flags=gtk.DIALOG_DESTROY_WITH_PARENT
, title="" ) # , buttons=btns
vbox = dia.vbox
h = gtk.HBox(False, 2)
i = gtk.Image()
i.set_from_stock(gtk.STOCK_DIALOG_INFO, gtk.ICON_SIZE_DIALOG)
l = gtk.Label(str1)
h.pack_start(i, padding=5)
h.pack_start(l, padding=5)
vbox.pack_start(h)
else:
# add extra label
vbox = dia.vbox
vbox.pack_start( gtk.Label(str1) )
dia.show_all()
response = None
if run: response = dia.run()
if destroy: dia.destroy()
return (dia, response)
if __name__=="__main__": if __name__=="__main__":

View File

@ -560,7 +560,6 @@ class Sql:
comment text, comment text,
commentTs DATETIME, commentTs DATETIME,
tourneysPlayersId BIGINT UNSIGNED, FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id), tourneysPlayersId BIGINT UNSIGNED, FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id),
tourneyTypeId SMALLINT UNSIGNED, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
wonWhenSeenStreet1 FLOAT, wonWhenSeenStreet1 FLOAT,
wonWhenSeenStreet2 FLOAT, wonWhenSeenStreet2 FLOAT,
@ -677,7 +676,6 @@ class Sql:
comment text, comment text,
commentTs timestamp without time zone, commentTs timestamp without time zone,
tourneysPlayersId BIGINT, FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id), tourneysPlayersId BIGINT, FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id),
tourneyTypeId INT, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
wonWhenSeenStreet1 FLOAT, wonWhenSeenStreet1 FLOAT,
wonWhenSeenStreet2 FLOAT, wonWhenSeenStreet2 FLOAT,
@ -793,7 +791,6 @@ class Sql:
comment TEXT, comment TEXT,
commentTs REAL, commentTs REAL,
tourneysPlayersId INT, tourneysPlayersId INT,
tourneyTypeId INT,
wonWhenSeenStreet1 REAL, wonWhenSeenStreet1 REAL,
wonWhenSeenStreet2 REAL, wonWhenSeenStreet2 REAL,
@ -2989,7 +2986,7 @@ class Sql:
when hp.position = '9' then 'E' when hp.position = '9' then 'E'
else 'E' else 'E'
end AS hc_position end AS hc_position
,hp.tourneyTypeId ,t.tourneyTypeId
,date_format(h.startTime, 'd%y%m%d') ,date_format(h.startTime, 'd%y%m%d')
,count(1) ,count(1)
,sum(wonWhenSeenStreet1) ,sum(wonWhenSeenStreet1)
@ -3063,12 +3060,14 @@ class Sql:
,sum(hp.street4Raises) ,sum(hp.street4Raises)
FROM HandsPlayers hp FROM HandsPlayers hp
INNER JOIN Hands h ON (h.id = hp.handId) INNER JOIN Hands h ON (h.id = hp.handId)
INNER JOIN TourneysPlayers tp ON (tp.id = hp.tourneysPlayersId)
INNER JOIN Tourneys t ON (t.id = tp.tourneyId)
<where_clause> <where_clause>
GROUP BY h.gametypeId GROUP BY h.gametypeId
,hp.playerId ,hp.playerId
,h.seats ,h.seats
,hc_position ,hc_position
,hp.tourneyTypeId ,t.tourneyTypeId
,date_format(h.startTime, 'd%y%m%d') ,date_format(h.startTime, 'd%y%m%d')
""" """
elif db_server == 'postgresql': elif db_server == 'postgresql':
@ -3168,7 +3167,7 @@ class Sql:
when hp.position = '9' then 'E' when hp.position = '9' then 'E'
else 'E' else 'E'
end AS hc_position end AS hc_position
,hp.tourneyTypeId ,t.tourneyTypeId
,'d' || to_char(h.startTime, 'YYMMDD') ,'d' || to_char(h.startTime, 'YYMMDD')
,count(1) ,count(1)
,sum(wonWhenSeenStreet1) ,sum(wonWhenSeenStreet1)
@ -3242,12 +3241,14 @@ class Sql:
,sum(CAST(hp.street4Raises as integer)) ,sum(CAST(hp.street4Raises as integer))
FROM HandsPlayers hp FROM HandsPlayers hp
INNER JOIN Hands h ON (h.id = hp.handId) INNER JOIN Hands h ON (h.id = hp.handId)
INNER JOIN TourneysPlayers tp ON (tp.id = hp.tourneysPlayersId)
INNER JOIN Tourneys t ON (t.id = tp.tourneyId)
<where_clause> <where_clause>
GROUP BY h.gametypeId GROUP BY h.gametypeId
,hp.playerId ,hp.playerId
,h.seats ,h.seats
,hc_position ,hc_position
,hp.tourneyTypeId ,t.tourneyTypeId
,to_char(h.startTime, 'YYMMDD') ,to_char(h.startTime, 'YYMMDD')
""" """
else: # assume sqlite else: # assume sqlite
@ -3347,7 +3348,7 @@ class Sql:
when hp.position = '9' then 'E' when hp.position = '9' then 'E'
else 'E' else 'E'
end AS hc_position end AS hc_position
,hp.tourneyTypeId ,t.tourneyTypeId
,'d' || substr(strftime('%Y%m%d', h.startTime),3,7) ,'d' || substr(strftime('%Y%m%d', h.startTime),3,7)
,count(1) ,count(1)
,sum(wonWhenSeenStreet1) ,sum(wonWhenSeenStreet1)
@ -3421,12 +3422,14 @@ class Sql:
,sum(CAST(hp.street4Raises as integer)) ,sum(CAST(hp.street4Raises as integer))
FROM HandsPlayers hp FROM HandsPlayers hp
INNER JOIN Hands h ON (h.id = hp.handId) INNER JOIN Hands h ON (h.id = hp.handId)
INNER JOIN TourneysPlayers tp ON (tp.id = hp.tourneysPlayersId)
INNER JOIN Tourneys t ON (t.id = tp.tourneyId)
<where_clause> <where_clause>
GROUP BY h.gametypeId GROUP BY h.gametypeId
,hp.playerId ,hp.playerId
,h.seats ,h.seats
,hc_position ,hc_position
,hp.tourneyTypeId ,t.tourneyTypeId
,'d' || substr(strftime('%Y%m%d', h.startTime),3,7) ,'d' || substr(strftime('%Y%m%d', h.startTime),3,7)
""" """
@ -3698,8 +3701,6 @@ class Sql:
AND speed=%s AND speed=%s
AND shootout=%s AND shootout=%s
AND matrix=%s AND matrix=%s
AND added=%s
AND addedCurrency=%s
""" """
self.query['insertTourneyType'] = """INSERT INTO TourneyTypes self.query['insertTourneyType'] = """INSERT INTO TourneyTypes
@ -3860,7 +3861,6 @@ class Sql:
street3Bets, street3Bets,
street4Bets, street4Bets,
position, position,
tourneyTypeId,
tourneysPlayersId, tourneysPlayersId,
startCards, startCards,
street0_3BChance, street0_3BChance,
@ -3919,7 +3919,7 @@ class Sql:
%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
)""" )"""
################################ ################################

View File

@ -117,7 +117,7 @@ import Configuration
import Exceptions import Exceptions
import Stats import Stats
VERSION = "0.20.1 plus git" VERSION = "0.20.901"
class fpdb: class fpdb:
@ -306,8 +306,8 @@ class fpdb:
dia.destroy() dia.destroy()
def dia_maintain_dbs(self, widget, data=None): def dia_maintain_dbs(self, widget, data=None):
self.warning_box("Unimplemented: Maintain Databases") #self.warning_box("Unimplemented: Maintain Databases")
return #return
if len(self.tab_names) == 1: if len(self.tab_names) == 1:
if self.obtain_global_lock("dia_maintain_dbs"): # returns true if successful if self.obtain_global_lock("dia_maintain_dbs"): # returns true if successful
# only main tab has been opened, open dialog # only main tab has been opened, open dialog
@ -321,8 +321,14 @@ class fpdb:
prefs = GuiDatabase.GuiDatabase(self.config, self.window, dia) prefs = GuiDatabase.GuiDatabase(self.config, self.window, dia)
response = dia.run() response = dia.run()
if response == gtk.RESPONSE_ACCEPT: if response == gtk.RESPONSE_ACCEPT:
log.info('saving updated db data')
# save updated config # save updated config
self.config.save() self.config.save()
self.load_profile()
for name in self.config.supported_databases: #db_ip/db_user/db_pass/db_server
log.info('fpdb: name,desc='+name+','+self.config.supported_databases[name].db_desc)
else:
log.info('guidb response was '+str(response))
self.release_global_lock() self.release_global_lock()
@ -547,23 +553,14 @@ class fpdb:
# self.release_global_lock() # self.release_global_lock()
# lock_released = True # lock_released = True
self.db.recreate_tables() self.db.recreate_tables()
# find any guibulkimport windows and clear player cache: # find any guibulkimport/guiautoimport windows and clear player cache:
for t in self.threads: for t in self.threads:
if isinstance(t, GuiBulkImport.GuiBulkImport): if isinstance(t, GuiBulkImport.GuiBulkImport) or isinstance(t, GuiAutoImport.GuiAutoImport):
t.importer.database.resetPlayerIDs() t.importer.database.resetPlayerIDs()
self.release_global_lock() self.release_global_lock()
#else: #else:
# for other dbs use same connection as holds global lock # for other dbs use same connection as holds global lock
# self.fdb_lock.fdb.recreate_tables() # self.fdb_lock.fdb.recreate_tables()
# TODO: figure out why this seems to be necessary
dia_restart = gtk.MessageDialog(parent=self.window, flags=0, type=gtk.MESSAGE_WARNING,
buttons=(gtk.BUTTONS_OK), message_format="Restart fpdb")
diastring = "Fpdb now needs to close. Please restart it."
dia_restart.format_secondary_text(diastring)
dia_restart.run()
dia_restart.destroy()
self.quit(None, None)
elif response == gtk.RESPONSE_NO: elif response == gtk.RESPONSE_NO:
self.release_global_lock() self.release_global_lock()
print 'User cancelled recreating tables' print 'User cancelled recreating tables'
@ -839,12 +836,12 @@ class fpdb:
('hudConfigurator', None, '_HUD Configurator', '<control>H', 'HUD Configurator', self.diaHudConfigurator), ('hudConfigurator', None, '_HUD Configurator', '<control>H', 'HUD Configurator', self.diaHudConfigurator),
('graphs', None, '_Graphs', '<control>G', 'Graphs', self.tabGraphViewer), ('graphs', None, '_Graphs', '<control>G', 'Graphs', self.tabGraphViewer),
('ringplayerstats', None, 'Ring _Player Stats (tabulated view)', '<control>P', 'Ring Player Stats (tabulated view)', self.tab_ring_player_stats), ('ringplayerstats', None, 'Ring _Player Stats (tabulated view)', '<control>P', 'Ring Player Stats (tabulated view)', self.tab_ring_player_stats),
('tourneyplayerstats', None, '_Tourney Player Stats (tabulated view)', '<control>T', 'Tourney Player Stats (tabulated view)', self.tab_tourney_player_stats), ('tourneyplayerstats', None, '_Tourney Player Stats (tabulated view, mysql only)', '<control>T', 'Tourney Player Stats (tabulated view, mysql only)', self.tab_tourney_player_stats),
('posnstats', None, 'P_ositional Stats (tabulated view)', '<control>O', 'Positional Stats (tabulated view)', self.tab_positional_stats), ('posnstats', None, 'P_ositional Stats (tabulated view)', '<control>O', 'Positional Stats (tabulated view)', self.tab_positional_stats),
('sessionstats', None, 'Session Stats', None, 'Session Stats', self.tab_session_stats), ('sessionstats', None, 'Session Stats', None, 'Session Stats', self.tab_session_stats),
('tableviewer', None, 'Poker_table Viewer (mostly obselete)', None, 'Poker_table Viewer (mostly obselete)', self.tab_table_viewer), ('tableviewer', None, 'Poker_table Viewer (mostly obselete)', None, 'Poker_table Viewer (mostly obselete)', self.tab_table_viewer),
('database', None, '_Database'), ('database', None, '_Database'),
('maintaindbs', None, '_Maintain Databases (todo)', None, 'Maintain Databases', self.dia_maintain_dbs), ('maintaindbs', None, '_Maintain Databases', None, 'Maintain Databases', self.dia_maintain_dbs),
('createtabs', None, 'Create or Recreate _Tables', None, 'Create or Recreate Tables ', self.dia_recreate_tables), ('createtabs', None, 'Create or Recreate _Tables', None, 'Create or Recreate Tables ', self.dia_recreate_tables),
('rebuildhudcache', None, 'Rebuild HUD Cache', None, 'Rebuild HUD Cache', self.dia_recreate_hudcache), ('rebuildhudcache', None, 'Rebuild HUD Cache', None, 'Rebuild HUD Cache', self.dia_recreate_hudcache),
('rebuildindexes', None, 'Rebuild DB Indexes', None, 'Rebuild DB Indexes', self.dia_rebuild_indexes), ('rebuildindexes', None, 'Rebuild DB Indexes', None, 'Rebuild DB Indexes', self.dia_rebuild_indexes),

View File

@ -1,5 +1,5 @@
[loggers] [loggers]
keys=root,fpdb,logview,parser,importer,config,db,hud,filter keys=root,fpdb,logview,parser,importer,config,db,hud,filter,maintdbs
[handlers] [handlers]
keys=consoleHandler,rotatingFileHandler keys=consoleHandler,rotatingFileHandler
@ -17,6 +17,12 @@ handlers=consoleHandler,rotatingFileHandler
qualname=fpdb qualname=fpdb
propagate=0 propagate=0
[logger_maintdbs]
level=INFO
handlers=consoleHandler,rotatingFileHandler
qualname=maintdbs
propagate=0
[logger_logview] [logger_logview]
level=INFO level=INFO
handlers=consoleHandler,rotatingFileHandler handlers=consoleHandler,rotatingFileHandler