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

This commit is contained in:
Eric Blade 2009-12-15 06:08:30 -05:00
commit 7ca08899c5
10 changed files with 252 additions and 152 deletions

View File

@ -187,6 +187,7 @@ class Database:
def __init__(self, c, sql = None):
log.info("Creating Database instance, sql = %s" % sql)
self.config = c
self.__connected = False
self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql
self.do_connect(c)
@ -237,7 +238,12 @@ class Database:
self.hud_style = style
def do_connect(self, c):
self.fdb.do_connect(c)
try:
self.fdb.do_connect(c)
except:
# error during connect
self.__connected = False
raise
self.connection = self.fdb.db
self.wrongDbVersion = self.fdb.wrongDbVersion
@ -247,6 +253,7 @@ class Database:
self.db_server = db_params['db-server']
self.database = db_params['db-databaseName']
self.host = db_params['db-host']
self.__connected = True
def commit(self):
self.fdb.db.commit()
@ -254,6 +261,9 @@ class Database:
def rollback(self):
self.fdb.db.rollback()
def connected(self):
return self.__connected
def get_cursor(self):
return self.connection.cursor()
@ -1608,103 +1618,43 @@ class Database:
pdata[p]['street2Bets'],
pdata[p]['street3Bets'],
pdata[p]['street4Bets'],
pdata[p]['position'],
pdata[p]['tourneyTypeId'],
pdata[p]['startCards'],
pdata[p]['street0_3BChance'],
pdata[p]['street0_3BDone'],
pdata[p]['otherRaisedStreet1'],
pdata[p]['otherRaisedStreet2'],
pdata[p]['otherRaisedStreet3'],
pdata[p]['otherRaisedStreet4'],
pdata[p]['foldToOtherRaisedStreet1'],
pdata[p]['foldToOtherRaisedStreet2'],
pdata[p]['foldToOtherRaisedStreet3'],
pdata[p]['foldToOtherRaisedStreet4'],
pdata[p]['stealAttemptChance'],
pdata[p]['stealAttempted'],
pdata[p]['foldBbToStealChance'],
pdata[p]['foldedBbToSteal'],
pdata[p]['foldSbToStealChance'],
pdata[p]['foldedSbToSteal'],
pdata[p]['foldToStreet1CBChance'],
pdata[p]['foldToStreet1CBDone'],
pdata[p]['foldToStreet2CBChance'],
pdata[p]['foldToStreet2CBDone'],
pdata[p]['foldToStreet3CBChance'],
pdata[p]['foldToStreet3CBDone'],
pdata[p]['foldToStreet4CBChance'],
pdata[p]['foldToStreet4CBDone'],
pdata[p]['street1CheckCallRaiseChance'],
pdata[p]['street1CheckCallRaiseDone'],
pdata[p]['street2CheckCallRaiseChance'],
pdata[p]['street2CheckCallRaiseDone'],
pdata[p]['street3CheckCallRaiseChance'],
pdata[p]['street3CheckCallRaiseDone'],
pdata[p]['street4CheckCallRaiseChance']
) )
q = """INSERT INTO HandsPlayers (
handId,
playerId,
startCash,
seatNo,
card1,
card2,
card3,
card4,
card5,
card6,
card7,
winnings,
rake,
totalProfit,
street0VPI,
street1Seen,
street2Seen,
street3Seen,
street4Seen,
sawShowdown,
wonAtSD,
street0Aggr,
street1Aggr,
street2Aggr,
street3Aggr,
street4Aggr,
street1CBChance,
street2CBChance,
street3CBChance,
street4CBChance,
street1CBDone,
street2CBDone,
street3CBDone,
street4CBDone,
wonWhenSeenStreet1,
street0Calls,
street1Calls,
street2Calls,
street3Calls,
street4Calls,
street0Bets,
street1Bets,
street2Bets,
street3Bets,
street4Bets
)
VALUES (
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s
)"""
# position,
# tourneyTypeId,
# startCards,
# street0_3BChance,
# street0_3BDone,
# otherRaisedStreet1,
# otherRaisedStreet2,
# otherRaisedStreet3,
# otherRaisedStreet4,
# foldToOtherRaisedStreet1,
# foldToOtherRaisedStreet2,
# foldToOtherRaisedStreet3,
# foldToOtherRaisedStreet4,
# stealAttemptChance,
# stealAttempted,
# foldBbToStealChance,
# foldedBbToSteal,
# foldSbToStealChance,
# foldedSbToSteal,
# foldToStreet1CBChance,
# foldToStreet1CBDone,
# foldToStreet2CBChance,
# foldToStreet2CBDone,
# foldToStreet3CBChance,
# foldToStreet3CBDone,
# foldToStreet4CBChance,
# foldToStreet4CBDone,
# street1CheckCallRaiseChance,
# street1CheckCallRaiseDone,
# street2CheckCallRaiseChance,
# street2CheckCallRaiseDone,
# street3CheckCallRaiseChance,
# street3CheckCallRaiseDone,
# street4CheckCallRaiseChance,
# street4CheckCallRaiseDone,
q = self.sql.query['store_hands_players']
q = q.replace('%s', self.sql.query['placeholder'])
#print "DEBUG: inserts: %s" %inserts

View File

@ -53,6 +53,27 @@ class DerivedStats():
self.handsplayers[player[1]]['street%dCBChance' %i] = False
self.handsplayers[player[1]]['street%dCBDone' %i] = False
#FIXME - Everything below this point is incomplete.
self.handsplayers[player[1]]['position'] = 2
self.handsplayers[player[1]]['tourneyTypeId'] = 1
self.handsplayers[player[1]]['startCards'] = 0
self.handsplayers[player[1]]['street0_3BChance'] = False
self.handsplayers[player[1]]['street0_3BDone'] = False
self.handsplayers[player[1]]['stealAttemptChance'] = False
self.handsplayers[player[1]]['stealAttempted'] = False
self.handsplayers[player[1]]['foldBbToStealChance'] = False
self.handsplayers[player[1]]['foldBbToStealChance'] = False
self.handsplayers[player[1]]['foldSbToStealChance'] = False
self.handsplayers[player[1]]['foldedSbToSteal'] = False
self.handsplayers[player[1]]['foldedBbToSteal'] = False
for i in range(1,5):
self.handsplayers[player[1]]['otherRaisedStreet%d' %i] = False
self.handsplayers[player[1]]['foldToOtherRaisedStreet%d' %i] = False
self.handsplayers[player[1]]['foldToStreet%dCBChance' %i] = False
self.handsplayers[player[1]]['foldToStreet%dCBDone' %i] = False
self.handsplayers[player[1]]['street%dCheckCallRaiseChance' %i] = False
self.handsplayers[player[1]]['street%dCheckCallRaiseDone' %i] = False
self.assembleHands(self.hand)
self.assembleHandsPlayers(self.hand)
@ -149,6 +170,7 @@ class DerivedStats():
for i, card in enumerate(hcs[:7], 1):
self.handsplayers[player[1]]['card%s' % i] = Card.encodeCard(card)
# position,
#Stud 3rd street card test
# denny501: brings in for $0.02
@ -159,16 +181,6 @@ class DerivedStats():
# u.pressure: folds (Seat 1)
# 123smoothie: calls $0.02
# gashpor: calls $0.02
# tourneyTypeId,
# startCards,
# street0_3BChance,street0_3BDone,
# otherRaisedStreet1-4
# foldToOtherRaisedStreet1-4
# stealAttemptChance,stealAttempted,
# foldBbToStealChance,foldedBbToSteal,
# foldSbToStealChance,foldedSbToSteal,
# foldToStreet1-4CBChance, foldToStreet1-4CBDone,
# street1-4CheckCallRaiseChance, street1-4CheckCallRaiseDone,
# Additional stats
# 3betSB, 3betBB

View File

@ -34,5 +34,19 @@ class FpdbMySQLNoDatabase(FpdbDatabaseError):
def __str__(self):
return repr(self.value +" " + self.errmsg)
class FpdbPostgresqlAccessDenied(FpdbDatabaseError):
def __init__(self, value='', errmsg=''):
self.value = value
self.errmsg = errmsg
def __str__(self):
return repr(self.value +" " + self.errmsg)
class FpdbPostgresqlNoDatabase(FpdbDatabaseError):
def __init__(self, value='', errmsg=''):
self.value = value
self.errmsg = errmsg
def __str__(self):
return repr(self.value +" " + self.errmsg)
class DuplicateError(FpdbError):
pass

View File

@ -91,10 +91,15 @@ class GuiPrefs:
#iter = self.configStore.append( parent, [node.nodeValue, None] )
iter = None
if node.nodeType != node.TEXT_NODE and node.nodeType != node.COMMENT_NODE:
name = ""
iter = self.configStore.append( parent, [node, setting, value] )
if node.hasAttributes():
for i in xrange(node.attributes.length):
self.configStore.append( iter, [node, node.attributes.item(i).localName, node.attributes.item(i).value] )
if node.attributes.item(i).localName in ('site_name', 'game_name', 'stat_name', 'name', 'db_server', 'site'):
name = " " + node.attributes.item(i).value
if name != "":
self.configStore.set_value(iter, 1, setting+name)
if node.hasChildNodes():
for elem in node.childNodes:
self.addTreeRows(iter, elem)
@ -156,7 +161,7 @@ if __name__=="__main__":
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT))
dia.set_default_size(500, 500)
dia.set_default_size(700, 500)
prefs = GuiPrefs(config, win, dia.vbox)
response = dia.run()
if response == gtk.RESPONSE_ACCEPT:

View File

@ -55,6 +55,8 @@ class Hand(object):
self.handText = handText
self.handid = 0
self.dbid_hands = 0
self.dbid_pids = None
self.dbid_gt = 0
self.tablename = ""
self.hero = ""
self.maxseats = None
@ -189,22 +191,21 @@ dealt whether they were seen in a 'dealt to' line
self.holecards[street][player] = [open, closed]
def prepInsert(self, db):
pass
#####
# 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
self.dbid_pids = db.getSqlPlayerIDs([p[1] for p in self.players], self.siteId)
#Gametypes
self.dbid_gt = db.getGameTypeId(self.siteId, self.gametype)
def insert(self, db):
""" Function to insert Hand into database
Should not commit, and do minimal selects. Callers may want to cache commits
db: a connected fpdb_db object"""
#####
# 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
sqlids = db.getSqlPlayerIDs([p[1] for p in self.players], self.siteId)
#Gametypes
gtid = db.getGameTypeId(self.siteId, self.gametype)
self.stats.getStats(self)
@ -213,14 +214,14 @@ db: a connected fpdb_db object"""
#####
hh = self.stats.getHands()
if not db.isDuplicate(gtid, hh['siteHandNo']):
if not db.isDuplicate(self.dbid_gt, hh['siteHandNo']):
# Hands - Summary information of hand indexed by handId - gameinfo
hh['gameTypeId'] = gtid
hh['gameTypeId'] = self.dbid_gt
# seats TINYINT NOT NULL,
hh['seats'] = len(sqlids)
hh['seats'] = len(self.dbid_pids)
self.dbid_hands = db.storeHand(hh)
db.storeHandsPlayers(self.dbid_hands, sqlids, self.stats.getHandsPlayers())
db.storeHandsPlayers(self.dbid_hands, self.dbid_pids, self.stats.getHandsPlayers())
# HandsActions - all actions for all players for all streets - self.actions
# HudCache data can be generated from HandsActions (HandsPlayers?)
# Tourneys ?

View File

@ -3327,8 +3327,105 @@ class Sql:
%s, %s, %s, %s, %s, %s, %s, %s, %s)"""
self.query['store_hands_players'] = """INSERT INTO HandsPlayers (
handId,
playerId,
startCash,
seatNo,
card1,
card2,
card3,
card4,
card5,
card6,
card7,
winnings,
rake,
totalProfit,
street0VPI,
street1Seen,
street2Seen,
street3Seen,
street4Seen,
sawShowdown,
wonAtSD,
street0Aggr,
street1Aggr,
street2Aggr,
street3Aggr,
street4Aggr,
street1CBChance,
street2CBChance,
street3CBChance,
street4CBChance,
street1CBDone,
street2CBDone,
street3CBDone,
street4CBDone,
wonWhenSeenStreet1,
street0Calls,
street1Calls,
street2Calls,
street3Calls,
street4Calls,
street0Bets,
street1Bets,
street2Bets,
street3Bets,
street4Bets,
position,
tourneyTypeId,
startCards,
street0_3BChance,
street0_3BDone,
otherRaisedStreet1,
otherRaisedStreet2,
otherRaisedStreet3,
otherRaisedStreet4,
foldToOtherRaisedStreet1,
foldToOtherRaisedStreet2,
foldToOtherRaisedStreet3,
foldToOtherRaisedStreet4,
stealAttemptChance,
stealAttempted,
foldBbToStealChance,
foldedBbToSteal,
foldSbToStealChance,
foldedSbToSteal,
foldToStreet1CBChance,
foldToStreet1CBDone,
foldToStreet2CBChance,
foldToStreet2CBDone,
foldToStreet3CBChance,
foldToStreet3CBDone,
foldToStreet4CBChance,
foldToStreet4CBDone,
street1CheckCallRaiseChance,
street1CheckCallRaiseDone,
street2CheckCallRaiseChance,
street2CheckCallRaiseDone,
street3CheckCallRaiseChance,
street3CheckCallRaiseDone,
street4CheckCallRaiseChance
)
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, %s, %s
)"""
if db_server == 'mysql':
self.query['placeholder'] = u'%s'

View File

@ -237,7 +237,8 @@ class fpdb:
dia.set_comments("GTK AboutDialog comments here")
dia.set_license("GPL v3")
dia.set_website("http://fpdb.sourceforge.net/")
dia.set_authors("Steffen, Eratosthenes, s0rrow, EricBlade, _mt, sqlcoder, Bostik, and others")
dia.set_authors(['Steffen', 'Eratosthenes', 's0rrow',
'EricBlade', '_mt', 'sqlcoder', 'Bostik', 'and others'])
dia.set_program_name("Free Poker Database (FPDB)")
db_version = ""
@ -279,12 +280,20 @@ class fpdb:
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT))
dia.set_default_size(500, 500)
dia.set_default_size(700, 500)
prefs = GuiPrefs.GuiPrefs(self.config, self.window, dia.vbox)
response = dia.run()
if response == gtk.RESPONSE_ACCEPT:
# save updated config
self.config.save()
if len(self.nb_tab_names) == 1:
# only main tab open, reload profile
self.load_profile()
else:
self.warning_box("Updated preferences have not been loaded because "
+ "windows are open. Re-start fpdb to load them.")
dia.destroy()
def dia_create_del_database(self, widget, data=None):
@ -646,7 +655,7 @@ class fpdb:
('LoadProf', None, '_Load Profile (broken)', '<control>L', 'Load your profile', self.dia_load_profile),
('EditProf', None, '_Edit Profile (todo)', '<control>E', 'Edit your profile', self.dia_edit_profile),
('SaveProf', None, '_Save Profile (todo)', '<control>S', 'Save your profile', self.dia_save_profile),
('Preferences', None, '_Preferences', None, 'Edit your preferences', self.dia_preferences),
('Preferences', None, 'Pre_ferences', '<control>F', 'Edit your preferences', self.dia_preferences),
('import', None, '_Import'),
('sethharchive', None, '_Set HandHistory Archive Directory', None, 'Set HandHistory Archive Directory', self.select_hhArchiveBase),
('bulkimp', None, '_Bulk Import', '<control>B', 'Bulk Import', self.tab_bulk_import),
@ -700,21 +709,26 @@ class fpdb:
self.settings.update(self.config.get_import_parameters())
self.settings.update(self.config.get_default_paths())
if self.db is not None and self.db.fdb is not None:
if self.db is not None and self.db.connected:
self.db.disconnect()
self.sql = SQL.Sql(db_server = self.settings['db-server'])
err_msg = None
try:
self.db = Database.Database(self.config, sql = self.sql)
except Exceptions.FpdbMySQLAccessDenied:
#self.db = None
self.warning_box("MySQL Server reports: Access denied. Are your permissions set correctly?")
exit()
err_msg = "MySQL Server reports: Access denied. Are your permissions set correctly?"
except Exceptions.FpdbMySQLNoDatabase:
#self.db = None
msg = "MySQL client reports: 2002 or 2003 error. Unable to connect - Please check that the MySQL service has been started"
self.warning_box(msg)
exit
err_msg = "MySQL client reports: 2002 or 2003 error. Unable to connect - " \
+ "Please check that the MySQL service has been started"
except Exceptions.FpdbPostgresqlAccessDenied:
err_msg = "Postgres Server reports: Access denied. Are your permissions set correctly?"
except Exceptions.FpdbPostgresqlNoDatabase:
err_msg = "Postgres client reports: Unable to connect - " \
+ "Please check that the Postgres service has been started"
if err_msg is not None:
self.db = None
self.warning_box(err_msg)
# except FpdbMySQLFailedError:
# self.warning_box("Unable to connect to MySQL! Is the MySQL server running?!", "FPDB ERROR")
@ -732,7 +746,7 @@ class fpdb:
# print "*** Error: " + err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1])
# sys.stderr.write("Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user']))
if self.db.wrongDbVersion:
if self.db is not None and self.db.wrongDbVersion:
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.")
@ -751,14 +765,15 @@ class fpdb:
diaDbVersionWarning.destroy()
if self.status_bar is None:
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.status_bar = gtk.Label("")
self.main_vbox.pack_end(self.status_bar, False, True, 0)
self.status_bar.show()
else:
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
self.db.rollback()
if self.db is not None and self.db.connected:
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))
# rollback to make sure any locks are cleared:
self.db.rollback()
self.validate_config()
@ -779,7 +794,8 @@ class fpdb:
# TODO: can we get some / all of the stuff done in this function to execute on any kind of abort?
print "Quitting normally"
# TODO: check if current settings differ from profile, if so offer to save or abort
self.db.disconnect()
if self.db is not None and self.db.connected:
self.db.disconnect()
self.statusIcon.set_visible(False)
gtk.main_quit()

View File

@ -129,18 +129,22 @@ class fpdb_db:
self.db = psycopg2.connect(database = database)
connected = True
except:
# direct connection failed so try user/pass/... version
pass
#msg = "PostgreSQL direct connection to database (%s) failed, trying with user ..." % (database,)
#print msg
#raise FpdbError(msg)
if not connected:
try:
self.db = psycopg2.connect(host = host,
user = user,
password = password,
database = database)
except:
msg = "PostgreSQL connection to database (%s) user (%s) failed. Are you sure the DB is running?" % (database, user)
except Exception, ex:
if 'Connection refused' in ex.args[0]:
# meaning eg. db not running
raise FpdbPostgresqlNoDatabase(errmsg = ex.args[0])
elif 'password authentication' in ex.args[0]:
raise FpdbPostgresqlAccessDenied(errmsg = ex.args[0])
else:
msg = ex.args[0]
print msg
raise FpdbError(msg)
elif backend == fpdb_db.SQLITE:
@ -167,6 +171,7 @@ class fpdb_db:
logging.warning("Some database functions will not work without NumPy support")
else:
raise FpdbError("unrecognised database backend:"+backend)
self.cursor = self.db.cursor()
# Set up query dictionary as early in the connection process as we can.
self.sql = FpdbSQLQueries.FpdbSQLQueries(self.get_backend_name())

View File

@ -435,13 +435,13 @@ class Importer:
for hand in handlist:
#try, except duplicates here?
#hand.prepInsert()
hand.prepInsert(self.database)
hand.insert(self.database)
if self.callHud and hand.dbid_hands != 0:
#print "DEBUG: call to HUD: handsId: %s" % hand.dbid_hands
#pipe the Hands.id out to the HUD
# print "fpdb_import: sending hand to hud", handsId, "pipe =", self.caller.pipe_to_hud
self.caller.pipe_to_hud.stdin.write("%s" % (hand.dbid_hands) + os.linesep)
print "fpdb_import: sending hand to hud", handsId, "pipe =", self.caller.pipe_to_hud
#self.caller.pipe_to_hud.stdin.write("%s" % (hand.dbid_hands) + os.linesep)
errors = getattr(hhc, 'numErrors')
stored = getattr(hhc, 'numHands')

View File

@ -1247,13 +1247,13 @@ sure to also change the following storage method and table_viewer.prepare_data i
if not isAllIn:
isAllIn = any(i for i in allIns[1][player])
elif len(action_types[2][player]) > 0:
if isAllIn or len(action_types[2][player]) > 0:
if all(actiontype != "fold" for actiontype in action_types[1][player]):
myStreet2Seen = True
if not isAllIn:
isAllAin = any(i for i in allIns[2][player])
elif len(action_types[3][player]) > 0:
if isAllIn or len(action_types[3][player]) > 0:
if all(actiontype != "fold" for actiontype in action_types[2][player]):
myStreet3Seen = True
@ -1264,7 +1264,7 @@ sure to also change the following storage method and table_viewer.prepare_data i
#print "in else"
if not isAllIn:
isAllIn = any(i for i in allIns[3][player])
elif len(action_types[4][player]) > 0:
if isAllIn or len(action_types[4][player]) > 0:
#print "in if"
myStreet4Seen = True