Merge branch 'master' of git://git.assembla.com/fpdb-sql
This commit is contained in:
commit
a1b3259db9
|
@ -880,37 +880,12 @@ class FpdbSQLQueries:
|
||||||
elif(self.dbname == 'SQLite'):
|
elif(self.dbname == 'SQLite'):
|
||||||
self.query['set tx level'] = """ """
|
self.query['set tx level'] = """ """
|
||||||
|
|
||||||
################################
|
|
||||||
# Queries used in GuiGraphViewer
|
|
||||||
################################
|
|
||||||
|
|
||||||
|
|
||||||
if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'):
|
|
||||||
self.query['getPlayerId'] = """SELECT id from Players where name = %s"""
|
|
||||||
elif(self.dbname == 'SQLite'):
|
|
||||||
self.query['getPlayerId'] = """SELECT id from Players where name = %s"""
|
|
||||||
|
|
||||||
if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'):
|
if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'):
|
||||||
self.query['getSiteId'] = """SELECT id from Sites where name = %s"""
|
self.query['getSiteId'] = """SELECT id from Sites where name = %s"""
|
||||||
elif(self.dbname == 'SQLite'):
|
elif(self.dbname == 'SQLite'):
|
||||||
self.query['getSiteId'] = """SELECT id from Sites where name = %s"""
|
self.query['getSiteId'] = """SELECT id from Sites where name = %s"""
|
||||||
|
|
||||||
if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'):
|
|
||||||
self.query['getRingProfitAllHandsPlayerIdSite'] = """
|
|
||||||
SELECT hp.handId, hp.totalProfit, hp.totalProfit, hp.totalProfit
|
|
||||||
FROM HandsPlayers hp
|
|
||||||
INNER JOIN Players pl ON hp.playerId = pl.id
|
|
||||||
INNER JOIN Hands h ON h.id = hp.handId
|
|
||||||
INNER JOIN Gametypes g ON h.gametypeId = g.id
|
|
||||||
where pl.id in <player_test>
|
|
||||||
AND pl.siteId in <site_test>
|
|
||||||
AND h.handStart > '<startdate_test>'
|
|
||||||
AND h.handStart < '<enddate_test>'
|
|
||||||
AND g.bigBlind in <limit_test>
|
|
||||||
AND hp.tourneysPlayersId IS NULL
|
|
||||||
GROUP BY h.handStart, hp.handId, hp.totalProfit
|
|
||||||
ORDER BY h.handStart"""
|
|
||||||
|
|
||||||
if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'):
|
if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'):
|
||||||
self.query['getGames'] = """SELECT DISTINCT category from Gametypes"""
|
self.query['getGames'] = """SELECT DISTINCT category from Gametypes"""
|
||||||
|
|
||||||
|
@ -918,311 +893,6 @@ class FpdbSQLQueries:
|
||||||
self.query['getLimits'] = """SELECT DISTINCT bigBlind from Gametypes ORDER by bigBlind DESC"""
|
self.query['getLimits'] = """SELECT DISTINCT bigBlind from Gametypes ORDER by bigBlind DESC"""
|
||||||
|
|
||||||
|
|
||||||
####################################
|
|
||||||
# Queries to rebuild/modify hudcache
|
|
||||||
####################################
|
|
||||||
|
|
||||||
if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'):
|
|
||||||
self.query['clearHudCache'] = """DELETE FROM HudCache"""
|
|
||||||
|
|
||||||
if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'):
|
|
||||||
self.query['rebuildHudCache'] = """
|
|
||||||
INSERT INTO HudCache
|
|
||||||
(gametypeId
|
|
||||||
,playerId
|
|
||||||
,activeSeats
|
|
||||||
,position
|
|
||||||
,tourneyTypeId
|
|
||||||
,styleKey
|
|
||||||
,HDs
|
|
||||||
,wonWhenSeenStreet1
|
|
||||||
,wonAtSD
|
|
||||||
,street0VPI
|
|
||||||
,street0Aggr
|
|
||||||
,street0_3BChance
|
|
||||||
,street0_3BDone
|
|
||||||
,street1Seen
|
|
||||||
,street2Seen
|
|
||||||
,street3Seen
|
|
||||||
,street4Seen
|
|
||||||
,sawShowdown
|
|
||||||
,street1Aggr
|
|
||||||
,street2Aggr
|
|
||||||
,street3Aggr
|
|
||||||
,street4Aggr
|
|
||||||
,otherRaisedStreet1
|
|
||||||
,otherRaisedStreet2
|
|
||||||
,otherRaisedStreet3
|
|
||||||
,otherRaisedStreet4
|
|
||||||
,foldToOtherRaisedStreet1
|
|
||||||
,foldToOtherRaisedStreet2
|
|
||||||
,foldToOtherRaisedStreet3
|
|
||||||
,foldToOtherRaisedStreet4
|
|
||||||
,stealAttemptChance
|
|
||||||
,stealAttempted
|
|
||||||
,foldBbToStealChance
|
|
||||||
,foldedBbToSteal
|
|
||||||
,foldSbToStealChance
|
|
||||||
,foldedSbToSteal
|
|
||||||
,street1CBChance
|
|
||||||
,street1CBDone
|
|
||||||
,street2CBChance
|
|
||||||
,street2CBDone
|
|
||||||
,street3CBChance
|
|
||||||
,street3CBDone
|
|
||||||
,street4CBChance
|
|
||||||
,street4CBDone
|
|
||||||
,foldToStreet1CBChance
|
|
||||||
,foldToStreet1CBDone
|
|
||||||
,foldToStreet2CBChance
|
|
||||||
,foldToStreet2CBDone
|
|
||||||
,foldToStreet3CBChance
|
|
||||||
,foldToStreet3CBDone
|
|
||||||
,foldToStreet4CBChance
|
|
||||||
,foldToStreet4CBDone
|
|
||||||
,totalProfit
|
|
||||||
,street1CheckCallRaiseChance
|
|
||||||
,street1CheckCallRaiseDone
|
|
||||||
,street2CheckCallRaiseChance
|
|
||||||
,street2CheckCallRaiseDone
|
|
||||||
,street3CheckCallRaiseChance
|
|
||||||
,street3CheckCallRaiseDone
|
|
||||||
,street4CheckCallRaiseChance
|
|
||||||
,street4CheckCallRaiseDone
|
|
||||||
)
|
|
||||||
SELECT h.gametypeId
|
|
||||||
,hp.playerId
|
|
||||||
,h.seats
|
|
||||||
,case when hp.position = 'B' then 'B'
|
|
||||||
when hp.position = 'S' then 'S'
|
|
||||||
when hp.position = '0' then 'D'
|
|
||||||
when hp.position = '1' then 'C'
|
|
||||||
when hp.position = '2' then 'M'
|
|
||||||
when hp.position = '3' then 'M'
|
|
||||||
when hp.position = '4' then 'M'
|
|
||||||
when hp.position = '5' then 'E'
|
|
||||||
when hp.position = '6' then 'E'
|
|
||||||
when hp.position = '7' then 'E'
|
|
||||||
when hp.position = '8' then 'E'
|
|
||||||
when hp.position = '9' then 'E'
|
|
||||||
else 'E'
|
|
||||||
end AS hc_position
|
|
||||||
,hp.tourneyTypeId
|
|
||||||
,date_format(h.handStart, 'd%y%m%d')
|
|
||||||
,count(1)
|
|
||||||
,sum(wonWhenSeenStreet1)
|
|
||||||
,sum(wonAtSD)
|
|
||||||
,sum(CAST(street0VPI as integer))
|
|
||||||
,sum(CAST(street0Aggr as integer))
|
|
||||||
,sum(CAST(street0_3BChance as integer))
|
|
||||||
,sum(CAST(street0_3BDone as integer))
|
|
||||||
,sum(CAST(street1Seen as integer))
|
|
||||||
,sum(CAST(street2Seen as integer))
|
|
||||||
,sum(CAST(street3Seen as integer))
|
|
||||||
,sum(CAST(street4Seen as integer))
|
|
||||||
,sum(CAST(sawShowdown as integer))
|
|
||||||
,sum(CAST(street1Aggr as integer))
|
|
||||||
,sum(CAST(street2Aggr as integer))
|
|
||||||
,sum(CAST(street3Aggr as integer))
|
|
||||||
,sum(CAST(street4Aggr as integer))
|
|
||||||
,sum(CAST(otherRaisedStreet1 as integer))
|
|
||||||
,sum(CAST(otherRaisedStreet2 as integer))
|
|
||||||
,sum(CAST(otherRaisedStreet3 as integer))
|
|
||||||
,sum(CAST(otherRaisedStreet4 as integer))
|
|
||||||
,sum(CAST(foldToOtherRaisedStreet1 as integer))
|
|
||||||
,sum(CAST(foldToOtherRaisedStreet2 as integer))
|
|
||||||
,sum(CAST(foldToOtherRaisedStreet3 as integer))
|
|
||||||
,sum(CAST(foldToOtherRaisedStreet4 as integer))
|
|
||||||
,sum(CAST(stealAttemptChance as integer))
|
|
||||||
,sum(CAST(stealAttempted as integer))
|
|
||||||
,sum(CAST(foldBbToStealChance as integer))
|
|
||||||
,sum(CAST(foldedBbToSteal as integer))
|
|
||||||
,sum(CAST(foldSbToStealChance as integer))
|
|
||||||
,sum(CAST(foldedSbToSteal as integer))
|
|
||||||
,sum(CAST(street1CBChance as integer))
|
|
||||||
,sum(CAST(street1CBDone as integer))
|
|
||||||
,sum(CAST(street2CBChance as integer))
|
|
||||||
,sum(CAST(street2CBDone as integer))
|
|
||||||
,sum(CAST(street3CBChance as integer))
|
|
||||||
,sum(CAST(street3CBDone as integer))
|
|
||||||
,sum(CAST(street4CBChance as integer))
|
|
||||||
,sum(CAST(street4CBDone as integer))
|
|
||||||
,sum(CAST(foldToStreet1CBChance as integer))
|
|
||||||
,sum(CAST(foldToStreet1CBDone as integer))
|
|
||||||
,sum(CAST(foldToStreet2CBChance as integer))
|
|
||||||
,sum(CAST(foldToStreet2CBDone as integer))
|
|
||||||
,sum(CAST(foldToStreet3CBChance as integer))
|
|
||||||
,sum(CAST(foldToStreet3CBDone as integer))
|
|
||||||
,sum(CAST(foldToStreet4CBChance as integer))
|
|
||||||
,sum(CAST(foldToStreet4CBDone as integer))
|
|
||||||
,sum(CAST(totalProfit as integer))
|
|
||||||
,sum(CAST(street1CheckCallRaiseChance as integer))
|
|
||||||
,sum(CAST(street1CheckCallRaiseDone as integer))
|
|
||||||
,sum(CAST(street2CheckCallRaiseChance as integer))
|
|
||||||
,sum(CAST(street2CheckCallRaiseDone as integer))
|
|
||||||
,sum(CAST(street3CheckCallRaiseChance as integer))
|
|
||||||
,sum(CAST(street3CheckCallRaiseDone as integer))
|
|
||||||
,sum(CAST(street4CheckCallRaiseChance as integer))
|
|
||||||
,sum(CAST(street4CheckCallRaiseDone as integer))
|
|
||||||
FROM HandsPlayers hp
|
|
||||||
INNER JOIN Hands h ON (h.id = hp.handId)
|
|
||||||
GROUP BY h.gametypeId
|
|
||||||
,hp.playerId
|
|
||||||
,h.seats
|
|
||||||
,hc_position
|
|
||||||
,hp.tourneyTypeId
|
|
||||||
,date_format(h.handStart, 'd%y%m%d')
|
|
||||||
"""
|
|
||||||
elif (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'):
|
|
||||||
self.query['rebuildHudCache'] = """
|
|
||||||
INSERT INTO HudCache
|
|
||||||
(gametypeId
|
|
||||||
,playerId
|
|
||||||
,activeSeats
|
|
||||||
,position
|
|
||||||
,tourneyTypeId
|
|
||||||
,styleKey
|
|
||||||
,HDs
|
|
||||||
,wonWhenSeenStreet1
|
|
||||||
,wonAtSD
|
|
||||||
,street0VPI
|
|
||||||
,street0Aggr
|
|
||||||
,street0_3BChance
|
|
||||||
,street0_3BDone
|
|
||||||
,street1Seen
|
|
||||||
,street2Seen
|
|
||||||
,street3Seen
|
|
||||||
,street4Seen
|
|
||||||
,sawShowdown
|
|
||||||
,street1Aggr
|
|
||||||
,street2Aggr
|
|
||||||
,street3Aggr
|
|
||||||
,street4Aggr
|
|
||||||
,otherRaisedStreet1
|
|
||||||
,otherRaisedStreet2
|
|
||||||
,otherRaisedStreet3
|
|
||||||
,otherRaisedStreet4
|
|
||||||
,foldToOtherRaisedStreet1
|
|
||||||
,foldToOtherRaisedStreet2
|
|
||||||
,foldToOtherRaisedStreet3
|
|
||||||
,foldToOtherRaisedStreet4
|
|
||||||
,stealAttemptChance
|
|
||||||
,stealAttempted
|
|
||||||
,foldBbToStealChance
|
|
||||||
,foldedBbToSteal
|
|
||||||
,foldSbToStealChance
|
|
||||||
,foldedSbToSteal
|
|
||||||
,street1CBChance
|
|
||||||
,street1CBDone
|
|
||||||
,street2CBChance
|
|
||||||
,street2CBDone
|
|
||||||
,street3CBChance
|
|
||||||
,street3CBDone
|
|
||||||
,street4CBChance
|
|
||||||
,street4CBDone
|
|
||||||
,foldToStreet1CBChance
|
|
||||||
,foldToStreet1CBDone
|
|
||||||
,foldToStreet2CBChance
|
|
||||||
,foldToStreet2CBDone
|
|
||||||
,foldToStreet3CBChance
|
|
||||||
,foldToStreet3CBDone
|
|
||||||
,foldToStreet4CBChance
|
|
||||||
,foldToStreet4CBDone
|
|
||||||
,totalProfit
|
|
||||||
,street1CheckCallRaiseChance
|
|
||||||
,street1CheckCallRaiseDone
|
|
||||||
,street2CheckCallRaiseChance
|
|
||||||
,street2CheckCallRaiseDone
|
|
||||||
,street3CheckCallRaiseChance
|
|
||||||
,street3CheckCallRaiseDone
|
|
||||||
,street4CheckCallRaiseChance
|
|
||||||
,street4CheckCallRaiseDone
|
|
||||||
)
|
|
||||||
SELECT h.gametypeId
|
|
||||||
,hp.playerId
|
|
||||||
,h.seats
|
|
||||||
,case when hp.position = 'B' then 'B'
|
|
||||||
when hp.position = 'S' then 'S'
|
|
||||||
when hp.position = '0' then 'D'
|
|
||||||
when hp.position = '1' then 'C'
|
|
||||||
when hp.position = '2' then 'M'
|
|
||||||
when hp.position = '3' then 'M'
|
|
||||||
when hp.position = '4' then 'M'
|
|
||||||
when hp.position = '5' then 'E'
|
|
||||||
when hp.position = '6' then 'E'
|
|
||||||
when hp.position = '7' then 'E'
|
|
||||||
when hp.position = '8' then 'E'
|
|
||||||
when hp.position = '9' then 'E'
|
|
||||||
else 'E'
|
|
||||||
end AS hc_position
|
|
||||||
,hp.tourneyTypeId
|
|
||||||
,'d' || to_char(h.handStart, 'YYMMDD')
|
|
||||||
,count(1)
|
|
||||||
,sum(wonWhenSeenStreet1)
|
|
||||||
,sum(wonAtSD)
|
|
||||||
,sum(CAST(street0VPI as integer))
|
|
||||||
,sum(CAST(street0Aggr as integer))
|
|
||||||
,sum(CAST(street0_3BChance as integer))
|
|
||||||
,sum(CAST(street0_3BDone as integer))
|
|
||||||
,sum(CAST(street1Seen as integer))
|
|
||||||
,sum(CAST(street2Seen as integer))
|
|
||||||
,sum(CAST(street3Seen as integer))
|
|
||||||
,sum(CAST(street4Seen as integer))
|
|
||||||
,sum(CAST(sawShowdown as integer))
|
|
||||||
,sum(CAST(street1Aggr as integer))
|
|
||||||
,sum(CAST(street2Aggr as integer))
|
|
||||||
,sum(CAST(street3Aggr as integer))
|
|
||||||
,sum(CAST(street4Aggr as integer))
|
|
||||||
,sum(CAST(otherRaisedStreet1 as integer))
|
|
||||||
,sum(CAST(otherRaisedStreet2 as integer))
|
|
||||||
,sum(CAST(otherRaisedStreet3 as integer))
|
|
||||||
,sum(CAST(otherRaisedStreet4 as integer))
|
|
||||||
,sum(CAST(foldToOtherRaisedStreet1 as integer))
|
|
||||||
,sum(CAST(foldToOtherRaisedStreet2 as integer))
|
|
||||||
,sum(CAST(foldToOtherRaisedStreet3 as integer))
|
|
||||||
,sum(CAST(foldToOtherRaisedStreet4 as integer))
|
|
||||||
,sum(CAST(stealAttemptChance as integer))
|
|
||||||
,sum(CAST(stealAttempted as integer))
|
|
||||||
,sum(CAST(foldBbToStealChance as integer))
|
|
||||||
,sum(CAST(foldedBbToSteal as integer))
|
|
||||||
,sum(CAST(foldSbToStealChance as integer))
|
|
||||||
,sum(CAST(foldedSbToSteal as integer))
|
|
||||||
,sum(CAST(street1CBChance as integer))
|
|
||||||
,sum(CAST(street1CBDone as integer))
|
|
||||||
,sum(CAST(street2CBChance as integer))
|
|
||||||
,sum(CAST(street2CBDone as integer))
|
|
||||||
,sum(CAST(street3CBChance as integer))
|
|
||||||
,sum(CAST(street3CBDone as integer))
|
|
||||||
,sum(CAST(street4CBChance as integer))
|
|
||||||
,sum(CAST(street4CBDone as integer))
|
|
||||||
,sum(CAST(foldToStreet1CBChance as integer))
|
|
||||||
,sum(CAST(foldToStreet1CBDone as integer))
|
|
||||||
,sum(CAST(foldToStreet2CBChance as integer))
|
|
||||||
,sum(CAST(foldToStreet2CBDone as integer))
|
|
||||||
,sum(CAST(foldToStreet3CBChance as integer))
|
|
||||||
,sum(CAST(foldToStreet3CBDone as integer))
|
|
||||||
,sum(CAST(foldToStreet4CBChance as integer))
|
|
||||||
,sum(CAST(foldToStreet4CBDone as integer))
|
|
||||||
,sum(CAST(totalProfit as integer))
|
|
||||||
,sum(CAST(street1CheckCallRaiseChance as integer))
|
|
||||||
,sum(CAST(street1CheckCallRaiseDone as integer))
|
|
||||||
,sum(CAST(street2CheckCallRaiseChance as integer))
|
|
||||||
,sum(CAST(street2CheckCallRaiseDone as integer))
|
|
||||||
,sum(CAST(street3CheckCallRaiseChance as integer))
|
|
||||||
,sum(CAST(street3CheckCallRaiseDone as integer))
|
|
||||||
,sum(CAST(street4CheckCallRaiseChance as integer))
|
|
||||||
,sum(CAST(street4CheckCallRaiseDone as integer))
|
|
||||||
FROM HandsPlayers hp
|
|
||||||
INNER JOIN Hands h ON (h.id = hp.handId)
|
|
||||||
GROUP BY h.gametypeId
|
|
||||||
,hp.playerId
|
|
||||||
,h.seats
|
|
||||||
,hc_position
|
|
||||||
,hp.tourneyTypeId
|
|
||||||
,to_char(h.handStart, 'YYMMDD')
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
if __name__== "__main__":
|
if __name__== "__main__":
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
|
|
||||||
|
|
|
@ -38,20 +38,19 @@ except:
|
||||||
and HUD are NOT affected by this problem."""
|
and HUD are NOT affected by this problem."""
|
||||||
|
|
||||||
import fpdb_import
|
import fpdb_import
|
||||||
import fpdb_db
|
import Database
|
||||||
import Filters
|
import Filters
|
||||||
|
|
||||||
class GuiGraphViewer (threading.Thread):
|
class GuiGraphViewer (threading.Thread):
|
||||||
|
|
||||||
def __init__(self, querylist, config, debug=True):
|
def __init__(self, querylist, config, debug=True):
|
||||||
"""Constructor for GraphViewer"""
|
"""Constructor for GraphViewer"""
|
||||||
self.debug=debug
|
|
||||||
#print "start of GraphViewer constructor"
|
|
||||||
self.db = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql
|
|
||||||
self.db.do_connect(config)
|
|
||||||
|
|
||||||
self.sql = querylist
|
self.sql = querylist
|
||||||
self.conf = config
|
self.conf = config
|
||||||
|
self.debug = debug
|
||||||
|
#print "start of GraphViewer constructor"
|
||||||
|
self.db = Database.Database(self.conf, sql=self.sql)
|
||||||
|
|
||||||
|
|
||||||
filters_display = { "Heroes" : True,
|
filters_display = { "Heroes" : True,
|
||||||
"Sites" : True,
|
"Sites" : True,
|
||||||
|
@ -63,7 +62,7 @@ class GuiGraphViewer (threading.Thread):
|
||||||
"Button2" : True
|
"Button2" : True
|
||||||
}
|
}
|
||||||
|
|
||||||
self.filters = Filters.Filters(self.db, config, querylist, display = filters_display)
|
self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display)
|
||||||
self.filters.registerButton1Name("Refresh Graph")
|
self.filters.registerButton1Name("Refresh Graph")
|
||||||
self.filters.registerButton1Callback(self.generateGraph)
|
self.filters.registerButton1Callback(self.generateGraph)
|
||||||
self.filters.registerButton2Name("Export to File")
|
self.filters.registerButton2Name("Export to File")
|
||||||
|
@ -90,7 +89,7 @@ class GuiGraphViewer (threading.Thread):
|
||||||
self.canvas = None
|
self.canvas = None
|
||||||
|
|
||||||
|
|
||||||
self.db.db.rollback()
|
self.db.rollback()
|
||||||
|
|
||||||
#################################
|
#################################
|
||||||
#
|
#
|
||||||
|
@ -130,7 +129,6 @@ class GuiGraphViewer (threading.Thread):
|
||||||
if self.canvas is not None:
|
if self.canvas is not None:
|
||||||
self.canvas.destroy()
|
self.canvas.destroy()
|
||||||
|
|
||||||
if self.canvas == None:
|
|
||||||
self.canvas = FigureCanvas(self.fig) # a gtk.DrawingArea
|
self.canvas = FigureCanvas(self.fig) # a gtk.DrawingArea
|
||||||
|
|
||||||
def generateGraph(self, widget, data):
|
def generateGraph(self, widget, data):
|
||||||
|
@ -207,7 +205,7 @@ class GuiGraphViewer (threading.Thread):
|
||||||
# print "DEBUG: getRingProfitGraph"
|
# print "DEBUG: getRingProfitGraph"
|
||||||
start_date, end_date = self.filters.getDates()
|
start_date, end_date = self.filters.getDates()
|
||||||
|
|
||||||
#Buggered if I can find a way to do this 'nicely' take a list of intergers and longs
|
#Buggered if I can find a way to do this 'nicely' take a list of integers and longs
|
||||||
# and turn it into a tuple readale by sql.
|
# and turn it into a tuple readale by sql.
|
||||||
# [5L] into (5) not (5,) and [5L, 2829L] into (5, 2829)
|
# [5L] into (5) not (5,) and [5L, 2829L] into (5, 2829)
|
||||||
nametest = str(tuple(names))
|
nametest = str(tuple(names))
|
||||||
|
@ -231,7 +229,7 @@ class GuiGraphViewer (threading.Thread):
|
||||||
self.db.cursor.execute(tmp)
|
self.db.cursor.execute(tmp)
|
||||||
#returns (HandId,Winnings,Costs,Profit)
|
#returns (HandId,Winnings,Costs,Profit)
|
||||||
winnings = self.db.cursor.fetchall()
|
winnings = self.db.cursor.fetchall()
|
||||||
self.db.db.rollback()
|
self.db.rollback()
|
||||||
|
|
||||||
if(winnings == ()):
|
if(winnings == ()):
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -25,7 +25,7 @@ from numpy import diff, nonzero
|
||||||
|
|
||||||
import Card
|
import Card
|
||||||
import fpdb_import
|
import fpdb_import
|
||||||
import fpdb_db
|
import Database
|
||||||
import Filters
|
import Filters
|
||||||
import FpdbSQLQueries
|
import FpdbSQLQueries
|
||||||
|
|
||||||
|
@ -33,21 +33,20 @@ class GuiSessionViewer (threading.Thread):
|
||||||
def __init__(self, config, querylist, debug=True):
|
def __init__(self, config, querylist, debug=True):
|
||||||
self.debug = debug
|
self.debug = debug
|
||||||
self.conf = config
|
self.conf = config
|
||||||
|
self.sql = querylist
|
||||||
self.MYSQL_INNODB = 2
|
self.MYSQL_INNODB = 2
|
||||||
self.PGSQL = 3
|
self.PGSQL = 3
|
||||||
self.SQLITE = 4
|
self.SQLITE = 4
|
||||||
|
|
||||||
# create new db connection to avoid conflicts with other threads
|
# create new db connection to avoid conflicts with other threads
|
||||||
self.db = fpdb_db.fpdb_db()
|
self.db = Database.Database(self.conf, sql=self.sql)
|
||||||
self.db.do_connect(self.conf)
|
|
||||||
self.cursor = self.db.cursor
|
self.cursor = self.db.cursor
|
||||||
self.sql = querylist
|
|
||||||
|
|
||||||
settings = {}
|
settings = {}
|
||||||
settings.update(config.get_db_parameters())
|
settings.update(self.conf.get_db_parameters())
|
||||||
settings.update(config.get_tv_parameters())
|
settings.update(self.conf.get_tv_parameters())
|
||||||
settings.update(config.get_import_parameters())
|
settings.update(self.conf.get_import_parameters())
|
||||||
settings.update(config.get_default_paths())
|
settings.update(self.conf.get_default_paths())
|
||||||
|
|
||||||
# text used on screen stored here so that it can be configured
|
# text used on screen stored here so that it can be configured
|
||||||
self.filterText = {'handhead':'Hand Breakdown for all levels listed above'
|
self.filterText = {'handhead':'Hand Breakdown for all levels listed above'
|
||||||
|
@ -66,7 +65,7 @@ class GuiSessionViewer (threading.Thread):
|
||||||
"Button2" : True
|
"Button2" : True
|
||||||
}
|
}
|
||||||
|
|
||||||
self.filters = Filters.Filters(self.db, settings, config, querylist, display = filters_display)
|
self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display)
|
||||||
self.filters.registerButton2Name("_Refresh")
|
self.filters.registerButton2Name("_Refresh")
|
||||||
self.filters.registerButton2Callback(self.refreshStats)
|
self.filters.registerButton2Callback(self.refreshStats)
|
||||||
|
|
||||||
|
@ -195,7 +194,7 @@ class GuiSessionViewer (threading.Thread):
|
||||||
flags = [True]
|
flags = [True]
|
||||||
self.addTable(vbox1, 'playerDetailedStats', flags, playerids, sitenos, limits, seats)
|
self.addTable(vbox1, 'playerDetailedStats', flags, playerids, sitenos, limits, seats)
|
||||||
|
|
||||||
self.db.db.commit()
|
self.db.rollback()
|
||||||
print "Stats page displayed in %4.2f seconds" % (time() - starttime)
|
print "Stats page displayed in %4.2f seconds" % (time() - starttime)
|
||||||
#end def fillStatsFrame(self, vbox):
|
#end def fillStatsFrame(self, vbox):
|
||||||
|
|
||||||
|
|
319
pyfpdb/SQL.py
319
pyfpdb/SQL.py
|
@ -1235,6 +1235,325 @@ class Sql:
|
||||||
#elif(self.dbname == 'SQLite'):
|
#elif(self.dbname == 'SQLite'):
|
||||||
# self.query['playerStatsByPosition'] = """ """
|
# self.query['playerStatsByPosition'] = """ """
|
||||||
|
|
||||||
|
self.query['getRingProfitAllHandsPlayerIdSite'] = """
|
||||||
|
SELECT hp.handId, hp.totalProfit, hp.totalProfit, hp.totalProfit
|
||||||
|
FROM HandsPlayers hp
|
||||||
|
INNER JOIN Players pl ON (hp.playerId = pl.id)
|
||||||
|
INNER JOIN Hands h ON (h.id = hp.handId)
|
||||||
|
INNER JOIN Gametypes g ON (h.gametypeId = g.id)
|
||||||
|
where pl.id in <player_test>
|
||||||
|
AND pl.siteId in <site_test>
|
||||||
|
AND h.handStart > '<startdate_test>'
|
||||||
|
AND h.handStart < '<enddate_test>'
|
||||||
|
AND g.bigBlind in <limit_test>
|
||||||
|
AND hp.tourneysPlayersId IS NULL
|
||||||
|
GROUP BY h.handStart, hp.handId, hp.totalProfit
|
||||||
|
ORDER BY h.handStart"""
|
||||||
|
|
||||||
|
|
||||||
|
####################################
|
||||||
|
# Queries to rebuild/modify hudcache
|
||||||
|
####################################
|
||||||
|
|
||||||
|
self.query['clearHudCache'] = """DELETE FROM HudCache"""
|
||||||
|
|
||||||
|
if db_server == 'mysql':
|
||||||
|
self.query['rebuildHudCache'] = """
|
||||||
|
INSERT INTO HudCache
|
||||||
|
(gametypeId
|
||||||
|
,playerId
|
||||||
|
,activeSeats
|
||||||
|
,position
|
||||||
|
,tourneyTypeId
|
||||||
|
,styleKey
|
||||||
|
,HDs
|
||||||
|
,wonWhenSeenStreet1
|
||||||
|
,wonAtSD
|
||||||
|
,street0VPI
|
||||||
|
,street0Aggr
|
||||||
|
,street0_3BChance
|
||||||
|
,street0_3BDone
|
||||||
|
,street1Seen
|
||||||
|
,street2Seen
|
||||||
|
,street3Seen
|
||||||
|
,street4Seen
|
||||||
|
,sawShowdown
|
||||||
|
,street1Aggr
|
||||||
|
,street2Aggr
|
||||||
|
,street3Aggr
|
||||||
|
,street4Aggr
|
||||||
|
,otherRaisedStreet1
|
||||||
|
,otherRaisedStreet2
|
||||||
|
,otherRaisedStreet3
|
||||||
|
,otherRaisedStreet4
|
||||||
|
,foldToOtherRaisedStreet1
|
||||||
|
,foldToOtherRaisedStreet2
|
||||||
|
,foldToOtherRaisedStreet3
|
||||||
|
,foldToOtherRaisedStreet4
|
||||||
|
,stealAttemptChance
|
||||||
|
,stealAttempted
|
||||||
|
,foldBbToStealChance
|
||||||
|
,foldedBbToSteal
|
||||||
|
,foldSbToStealChance
|
||||||
|
,foldedSbToSteal
|
||||||
|
,street1CBChance
|
||||||
|
,street1CBDone
|
||||||
|
,street2CBChance
|
||||||
|
,street2CBDone
|
||||||
|
,street3CBChance
|
||||||
|
,street3CBDone
|
||||||
|
,street4CBChance
|
||||||
|
,street4CBDone
|
||||||
|
,foldToStreet1CBChance
|
||||||
|
,foldToStreet1CBDone
|
||||||
|
,foldToStreet2CBChance
|
||||||
|
,foldToStreet2CBDone
|
||||||
|
,foldToStreet3CBChance
|
||||||
|
,foldToStreet3CBDone
|
||||||
|
,foldToStreet4CBChance
|
||||||
|
,foldToStreet4CBDone
|
||||||
|
,totalProfit
|
||||||
|
,street1CheckCallRaiseChance
|
||||||
|
,street1CheckCallRaiseDone
|
||||||
|
,street2CheckCallRaiseChance
|
||||||
|
,street2CheckCallRaiseDone
|
||||||
|
,street3CheckCallRaiseChance
|
||||||
|
,street3CheckCallRaiseDone
|
||||||
|
,street4CheckCallRaiseChance
|
||||||
|
,street4CheckCallRaiseDone
|
||||||
|
)
|
||||||
|
SELECT h.gametypeId
|
||||||
|
,hp.playerId
|
||||||
|
,h.seats
|
||||||
|
,case when hp.position = 'B' then 'B'
|
||||||
|
when hp.position = 'S' then 'S'
|
||||||
|
when hp.position = '0' then 'D'
|
||||||
|
when hp.position = '1' then 'C'
|
||||||
|
when hp.position = '2' then 'M'
|
||||||
|
when hp.position = '3' then 'M'
|
||||||
|
when hp.position = '4' then 'M'
|
||||||
|
when hp.position = '5' then 'E'
|
||||||
|
when hp.position = '6' then 'E'
|
||||||
|
when hp.position = '7' then 'E'
|
||||||
|
when hp.position = '8' then 'E'
|
||||||
|
when hp.position = '9' then 'E'
|
||||||
|
else 'E'
|
||||||
|
end AS hc_position
|
||||||
|
,hp.tourneyTypeId
|
||||||
|
,date_format(h.handStart, 'd%y%m%d')
|
||||||
|
,count(1)
|
||||||
|
,sum(wonWhenSeenStreet1)
|
||||||
|
,sum(wonAtSD)
|
||||||
|
,sum(CAST(street0VPI as integer))
|
||||||
|
,sum(CAST(street0Aggr as integer))
|
||||||
|
,sum(CAST(street0_3BChance as integer))
|
||||||
|
,sum(CAST(street0_3BDone as integer))
|
||||||
|
,sum(CAST(street1Seen as integer))
|
||||||
|
,sum(CAST(street2Seen as integer))
|
||||||
|
,sum(CAST(street3Seen as integer))
|
||||||
|
,sum(CAST(street4Seen as integer))
|
||||||
|
,sum(CAST(sawShowdown as integer))
|
||||||
|
,sum(CAST(street1Aggr as integer))
|
||||||
|
,sum(CAST(street2Aggr as integer))
|
||||||
|
,sum(CAST(street3Aggr as integer))
|
||||||
|
,sum(CAST(street4Aggr as integer))
|
||||||
|
,sum(CAST(otherRaisedStreet1 as integer))
|
||||||
|
,sum(CAST(otherRaisedStreet2 as integer))
|
||||||
|
,sum(CAST(otherRaisedStreet3 as integer))
|
||||||
|
,sum(CAST(otherRaisedStreet4 as integer))
|
||||||
|
,sum(CAST(foldToOtherRaisedStreet1 as integer))
|
||||||
|
,sum(CAST(foldToOtherRaisedStreet2 as integer))
|
||||||
|
,sum(CAST(foldToOtherRaisedStreet3 as integer))
|
||||||
|
,sum(CAST(foldToOtherRaisedStreet4 as integer))
|
||||||
|
,sum(CAST(stealAttemptChance as integer))
|
||||||
|
,sum(CAST(stealAttempted as integer))
|
||||||
|
,sum(CAST(foldBbToStealChance as integer))
|
||||||
|
,sum(CAST(foldedBbToSteal as integer))
|
||||||
|
,sum(CAST(foldSbToStealChance as integer))
|
||||||
|
,sum(CAST(foldedSbToSteal as integer))
|
||||||
|
,sum(CAST(street1CBChance as integer))
|
||||||
|
,sum(CAST(street1CBDone as integer))
|
||||||
|
,sum(CAST(street2CBChance as integer))
|
||||||
|
,sum(CAST(street2CBDone as integer))
|
||||||
|
,sum(CAST(street3CBChance as integer))
|
||||||
|
,sum(CAST(street3CBDone as integer))
|
||||||
|
,sum(CAST(street4CBChance as integer))
|
||||||
|
,sum(CAST(street4CBDone as integer))
|
||||||
|
,sum(CAST(foldToStreet1CBChance as integer))
|
||||||
|
,sum(CAST(foldToStreet1CBDone as integer))
|
||||||
|
,sum(CAST(foldToStreet2CBChance as integer))
|
||||||
|
,sum(CAST(foldToStreet2CBDone as integer))
|
||||||
|
,sum(CAST(foldToStreet3CBChance as integer))
|
||||||
|
,sum(CAST(foldToStreet3CBDone as integer))
|
||||||
|
,sum(CAST(foldToStreet4CBChance as integer))
|
||||||
|
,sum(CAST(foldToStreet4CBDone as integer))
|
||||||
|
,sum(CAST(totalProfit as integer))
|
||||||
|
,sum(CAST(street1CheckCallRaiseChance as integer))
|
||||||
|
,sum(CAST(street1CheckCallRaiseDone as integer))
|
||||||
|
,sum(CAST(street2CheckCallRaiseChance as integer))
|
||||||
|
,sum(CAST(street2CheckCallRaiseDone as integer))
|
||||||
|
,sum(CAST(street3CheckCallRaiseChance as integer))
|
||||||
|
,sum(CAST(street3CheckCallRaiseDone as integer))
|
||||||
|
,sum(CAST(street4CheckCallRaiseChance as integer))
|
||||||
|
,sum(CAST(street4CheckCallRaiseDone as integer))
|
||||||
|
FROM HandsPlayers hp
|
||||||
|
INNER JOIN Hands h ON (h.id = hp.handId)
|
||||||
|
GROUP BY h.gametypeId
|
||||||
|
,hp.playerId
|
||||||
|
,h.seats
|
||||||
|
,hc_position
|
||||||
|
,hp.tourneyTypeId
|
||||||
|
,date_format(h.handStart, 'd%y%m%d')
|
||||||
|
"""
|
||||||
|
else: # assume postgres
|
||||||
|
self.query['rebuildHudCache'] = """
|
||||||
|
INSERT INTO HudCache
|
||||||
|
(gametypeId
|
||||||
|
,playerId
|
||||||
|
,activeSeats
|
||||||
|
,position
|
||||||
|
,tourneyTypeId
|
||||||
|
,styleKey
|
||||||
|
,HDs
|
||||||
|
,wonWhenSeenStreet1
|
||||||
|
,wonAtSD
|
||||||
|
,street0VPI
|
||||||
|
,street0Aggr
|
||||||
|
,street0_3BChance
|
||||||
|
,street0_3BDone
|
||||||
|
,street1Seen
|
||||||
|
,street2Seen
|
||||||
|
,street3Seen
|
||||||
|
,street4Seen
|
||||||
|
,sawShowdown
|
||||||
|
,street1Aggr
|
||||||
|
,street2Aggr
|
||||||
|
,street3Aggr
|
||||||
|
,street4Aggr
|
||||||
|
,otherRaisedStreet1
|
||||||
|
,otherRaisedStreet2
|
||||||
|
,otherRaisedStreet3
|
||||||
|
,otherRaisedStreet4
|
||||||
|
,foldToOtherRaisedStreet1
|
||||||
|
,foldToOtherRaisedStreet2
|
||||||
|
,foldToOtherRaisedStreet3
|
||||||
|
,foldToOtherRaisedStreet4
|
||||||
|
,stealAttemptChance
|
||||||
|
,stealAttempted
|
||||||
|
,foldBbToStealChance
|
||||||
|
,foldedBbToSteal
|
||||||
|
,foldSbToStealChance
|
||||||
|
,foldedSbToSteal
|
||||||
|
,street1CBChance
|
||||||
|
,street1CBDone
|
||||||
|
,street2CBChance
|
||||||
|
,street2CBDone
|
||||||
|
,street3CBChance
|
||||||
|
,street3CBDone
|
||||||
|
,street4CBChance
|
||||||
|
,street4CBDone
|
||||||
|
,foldToStreet1CBChance
|
||||||
|
,foldToStreet1CBDone
|
||||||
|
,foldToStreet2CBChance
|
||||||
|
,foldToStreet2CBDone
|
||||||
|
,foldToStreet3CBChance
|
||||||
|
,foldToStreet3CBDone
|
||||||
|
,foldToStreet4CBChance
|
||||||
|
,foldToStreet4CBDone
|
||||||
|
,totalProfit
|
||||||
|
,street1CheckCallRaiseChance
|
||||||
|
,street1CheckCallRaiseDone
|
||||||
|
,street2CheckCallRaiseChance
|
||||||
|
,street2CheckCallRaiseDone
|
||||||
|
,street3CheckCallRaiseChance
|
||||||
|
,street3CheckCallRaiseDone
|
||||||
|
,street4CheckCallRaiseChance
|
||||||
|
,street4CheckCallRaiseDone
|
||||||
|
)
|
||||||
|
SELECT h.gametypeId
|
||||||
|
,hp.playerId
|
||||||
|
,h.seats
|
||||||
|
,case when hp.position = 'B' then 'B'
|
||||||
|
when hp.position = 'S' then 'S'
|
||||||
|
when hp.position = '0' then 'D'
|
||||||
|
when hp.position = '1' then 'C'
|
||||||
|
when hp.position = '2' then 'M'
|
||||||
|
when hp.position = '3' then 'M'
|
||||||
|
when hp.position = '4' then 'M'
|
||||||
|
when hp.position = '5' then 'E'
|
||||||
|
when hp.position = '6' then 'E'
|
||||||
|
when hp.position = '7' then 'E'
|
||||||
|
when hp.position = '8' then 'E'
|
||||||
|
when hp.position = '9' then 'E'
|
||||||
|
else 'E'
|
||||||
|
end AS hc_position
|
||||||
|
,hp.tourneyTypeId
|
||||||
|
,'d' || to_char(h.handStart, 'YYMMDD')
|
||||||
|
,count(1)
|
||||||
|
,sum(wonWhenSeenStreet1)
|
||||||
|
,sum(wonAtSD)
|
||||||
|
,sum(CAST(street0VPI as integer))
|
||||||
|
,sum(CAST(street0Aggr as integer))
|
||||||
|
,sum(CAST(street0_3BChance as integer))
|
||||||
|
,sum(CAST(street0_3BDone as integer))
|
||||||
|
,sum(CAST(street1Seen as integer))
|
||||||
|
,sum(CAST(street2Seen as integer))
|
||||||
|
,sum(CAST(street3Seen as integer))
|
||||||
|
,sum(CAST(street4Seen as integer))
|
||||||
|
,sum(CAST(sawShowdown as integer))
|
||||||
|
,sum(CAST(street1Aggr as integer))
|
||||||
|
,sum(CAST(street2Aggr as integer))
|
||||||
|
,sum(CAST(street3Aggr as integer))
|
||||||
|
,sum(CAST(street4Aggr as integer))
|
||||||
|
,sum(CAST(otherRaisedStreet1 as integer))
|
||||||
|
,sum(CAST(otherRaisedStreet2 as integer))
|
||||||
|
,sum(CAST(otherRaisedStreet3 as integer))
|
||||||
|
,sum(CAST(otherRaisedStreet4 as integer))
|
||||||
|
,sum(CAST(foldToOtherRaisedStreet1 as integer))
|
||||||
|
,sum(CAST(foldToOtherRaisedStreet2 as integer))
|
||||||
|
,sum(CAST(foldToOtherRaisedStreet3 as integer))
|
||||||
|
,sum(CAST(foldToOtherRaisedStreet4 as integer))
|
||||||
|
,sum(CAST(stealAttemptChance as integer))
|
||||||
|
,sum(CAST(stealAttempted as integer))
|
||||||
|
,sum(CAST(foldBbToStealChance as integer))
|
||||||
|
,sum(CAST(foldedBbToSteal as integer))
|
||||||
|
,sum(CAST(foldSbToStealChance as integer))
|
||||||
|
,sum(CAST(foldedSbToSteal as integer))
|
||||||
|
,sum(CAST(street1CBChance as integer))
|
||||||
|
,sum(CAST(street1CBDone as integer))
|
||||||
|
,sum(CAST(street2CBChance as integer))
|
||||||
|
,sum(CAST(street2CBDone as integer))
|
||||||
|
,sum(CAST(street3CBChance as integer))
|
||||||
|
,sum(CAST(street3CBDone as integer))
|
||||||
|
,sum(CAST(street4CBChance as integer))
|
||||||
|
,sum(CAST(street4CBDone as integer))
|
||||||
|
,sum(CAST(foldToStreet1CBChance as integer))
|
||||||
|
,sum(CAST(foldToStreet1CBDone as integer))
|
||||||
|
,sum(CAST(foldToStreet2CBChance as integer))
|
||||||
|
,sum(CAST(foldToStreet2CBDone as integer))
|
||||||
|
,sum(CAST(foldToStreet3CBChance as integer))
|
||||||
|
,sum(CAST(foldToStreet3CBDone as integer))
|
||||||
|
,sum(CAST(foldToStreet4CBChance as integer))
|
||||||
|
,sum(CAST(foldToStreet4CBDone as integer))
|
||||||
|
,sum(CAST(totalProfit as integer))
|
||||||
|
,sum(CAST(street1CheckCallRaiseChance as integer))
|
||||||
|
,sum(CAST(street1CheckCallRaiseDone as integer))
|
||||||
|
,sum(CAST(street2CheckCallRaiseChance as integer))
|
||||||
|
,sum(CAST(street2CheckCallRaiseDone as integer))
|
||||||
|
,sum(CAST(street3CheckCallRaiseChance as integer))
|
||||||
|
,sum(CAST(street3CheckCallRaiseDone as integer))
|
||||||
|
,sum(CAST(street4CheckCallRaiseChance as integer))
|
||||||
|
,sum(CAST(street4CheckCallRaiseDone as integer))
|
||||||
|
FROM HandsPlayers hp
|
||||||
|
INNER JOIN Hands h ON (h.id = hp.handId)
|
||||||
|
GROUP BY h.gametypeId
|
||||||
|
,hp.playerId
|
||||||
|
,h.seats
|
||||||
|
,hc_position
|
||||||
|
,hp.tourneyTypeId
|
||||||
|
,to_char(h.handStart, 'YYMMDD')
|
||||||
|
"""
|
||||||
|
|
||||||
if __name__== "__main__":
|
if __name__== "__main__":
|
||||||
# just print the default queries and exit
|
# just print the default queries and exit
|
||||||
s = Sql(game = 'razz', type = 'ptracks')
|
s = Sql(game = 'razz', type = 'ptracks')
|
||||||
|
|
|
@ -134,7 +134,7 @@ class fpdb:
|
||||||
#end def dia_database_stats
|
#end def dia_database_stats
|
||||||
|
|
||||||
def dia_database_sessions(self, widget, data=None):
|
def dia_database_sessions(self, widget, data=None):
|
||||||
new_sessions_thread=GuiSessionViewer.GuiSessionViewer(self.config, self.querydict)
|
new_sessions_thread=GuiSessionViewer.GuiSessionViewer(self.config, self.sql)
|
||||||
self.threads.append(new_sessions_thread)
|
self.threads.append(new_sessions_thread)
|
||||||
sessions_tab=new_sessions_thread.get_vbox()
|
sessions_tab=new_sessions_thread.get_vbox()
|
||||||
self.add_and_display_tab(sessions_tab, "Sessions")
|
self.add_and_display_tab(sessions_tab, "Sessions")
|
||||||
|
@ -497,7 +497,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
|
||||||
def tabGraphViewer(self, widget, data=None):
|
def tabGraphViewer(self, widget, data=None):
|
||||||
"""opens a graph viewer tab"""
|
"""opens a graph viewer tab"""
|
||||||
#print "start of tabGraphViewer"
|
#print "start of tabGraphViewer"
|
||||||
new_gv_thread = GuiGraphViewer.GuiGraphViewer(self.querydict, self.config)
|
new_gv_thread = GuiGraphViewer.GuiGraphViewer(self.sql, self.config)
|
||||||
self.threads.append(new_gv_thread)
|
self.threads.append(new_gv_thread)
|
||||||
gv_tab=new_gv_thread.get_vbox()
|
gv_tab=new_gv_thread.get_vbox()
|
||||||
self.add_and_display_tab(gv_tab, "Graphs")
|
self.add_and_display_tab(gv_tab, "Graphs")
|
||||||
|
|
Loading…
Reference in New Issue
Block a user