From 126eb0c0bc651a06334d5d9c43713601026ce08c Mon Sep 17 00:00:00 2001 From: danny Date: Sun, 3 Oct 2010 04:27:56 -0400 Subject: [PATCH] Added graphing improvements. --- pyfpdb/Filters.py | 82 ++++++++++++++++++++++++++++++++++++++++ pyfpdb/GuiGraphViewer.py | 53 +++++++++++++++++++++----- pyfpdb/SQL.py | 34 +++++++++++++++++ 3 files changed, 159 insertions(+), 10 deletions(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index a4afb24a..4226bced 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -62,6 +62,7 @@ class Filters(threading.Thread): gen = self.conf.get_general_params() self.day_start = 0 + if 'day_start' in gen: self.day_start = float(gen['day_start']) @@ -83,6 +84,7 @@ class Filters(threading.Thread): self.siteid = {} self.heroes = {} self.boxes = {} + self.graphops = {} for site in self.conf.get_supported_sites(): #Get db site id for filtering later @@ -103,6 +105,12 @@ class Filters(threading.Thread): self.sbGroups = {} self.numHands = 0 + # for use in graphops + # dspin = display in '$' or 'B' + self.graphops['dspin'] = "$" + self.graphops['showdown'] = 'OFF' + self.graphops['nonshowdown'] = 'OFF' + playerFrame = gtk.Frame() playerFrame.set_label_align(0.0, 0.0) vbox = gtk.VBox(False, 0) @@ -143,6 +151,16 @@ class Filters(threading.Thread): self.fillLimitsFrame(vbox, self.display) limitsFrame.add(vbox) + # GraphOps + graphopsFrame = gtk.Frame() + #graphops.set_label_align(0,0, 0.0) + graphopsFrame.show() + vbox = gtk.VBox(False, 0) + + self.fillGraphOpsFrame(vbox) + graphopsFrame.add(vbox) + + # Seats seatsFrame = gtk.Frame() seatsFrame.show() @@ -183,6 +201,7 @@ class Filters(threading.Thread): self.mainVBox.add(seatsFrame) self.mainVBox.add(groupsFrame) self.mainVBox.add(dateFrame) + self.mainVBox.add(graphopsFrame) self.mainVBox.add(self.Button1) self.mainVBox.add(self.Button2) @@ -203,6 +222,8 @@ class Filters(threading.Thread): groupsFrame.hide() if "Dates" not in self.display or self.display["Dates"] == False: dateFrame.hide() + if "GraphOps" not in self.display or self.display["GraphOps"] == False: + graphopsFrame.hide() if "Button1" not in self.display or self.display["Button1"] == False: self.Button1.hide() if "Button2" not in self.display or self.display["Button2"] == False: @@ -255,6 +276,9 @@ class Filters(threading.Thread): return self.heroes #end def getHeroes + def getGraphOps(self): + return self.graphops + def getLimits(self): ltuple = [] for l in self.limits: @@ -539,6 +563,14 @@ class Filters(threading.Thread): self.groups[group] = w.get_active() log.debug( _("self.groups[%s] set to %s") %(group, self.groups[group]) ) + + def __set_displayin_select(self, w, ops): + self.graphops['dspin'] = ops + + def __set_graphopscheck_select(self, w, data): + #print "%s was toggled %s" % (data, ("OFF", "ON")[w.get_active()]) + self.graphops[data] = ("OFF", "ON")[w.get_active()] + def fillPlayerFrame(self, vbox, display): top_hbox = gtk.HBox(False, 0) vbox.pack_start(top_hbox, False, False, 0) @@ -770,8 +802,58 @@ class Filters(threading.Thread): # set_active doesn't seem to call this for some reason so call manually: self.__set_limit_select(rb1, 'ring') self.type = 'ring' + top_hbox.pack_start(showb, expand=False, padding=1) + + def fillGraphOpsFrame(self, vbox): + top_hbox = gtk.HBox(False, 0) + vbox.pack_start(top_hbox, False, False, 0) + title = gtk.Label("Graphing Options:") + title.set_alignment(xalign=0.0, yalign=0.5) + top_hbox.pack_start(title, expand=True, padding=3) + showb = gtk.Button(label="hide", stock=None, use_underline=True) + showb.set_alignment(xalign=1.0, yalign=0.5) + showb.connect('clicked', self.__toggle_box, 'games') top_hbox.pack_start(showb, expand=False, padding=1) + hbox1 = gtk.HBox(False, 0) + vbox.pack_start(hbox1, False, False, 0) + hbox1.show() + + label = gtk.Label("Show Graph In:") + label.set_alignment(xalign=0.0, yalign=0.5) + hbox1.pack_start(label, True, True, 0) + label.show() + + button = gtk.RadioButton(None, "$$") + hbox1.pack_start(button, True, True, 0) + button.connect("toggled", self.__set_displayin_select, "$") + button.set_active(True) + button.show() + + button = gtk.RadioButton(button, "BB") + hbox1.pack_start(button, True, True, 0) + button.connect("toggled", self.__set_displayin_select, "BB") + button.show() + + vbox1 = gtk.VBox(False, 0) + vbox.pack_start(vbox1, False, False, 0) + vbox1.show() + + button = gtk.CheckButton("Showdown Winnings", False) + vbox1.pack_start(button, True, True, 0) + # wouldn't it be awesome if there was a way to remember the state of things like + # this and be able to set it to what it was last time? + #button.set_active(True) + button.connect("toggled", self.__set_graphopscheck_select, "showdown") + button.show() + + button = gtk.CheckButton("Non-Showdown Winnings", False) + vbox1.pack_start(button, True, True, 0) + # ditto as 8 lines up :) + #button.set_active(True) + button.connect("toggled", self.__set_graphopscheck_select, "nonshowdown"); + button.show() + def fillSeatsFrame(self, vbox, display): hbox = gtk.HBox(False, 0) vbox.pack_start(hbox, False, False, 0) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index e43657c8..7f4dc7b9 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -73,6 +73,7 @@ class GuiGraphViewer (threading.Thread): "Seats" : False, "SeatSep" : False, "Dates" : True, + "GraphOps" : True, "Groups" : False, "Button1" : True, "Button2" : True @@ -144,6 +145,7 @@ class GuiGraphViewer (threading.Thread): siteids = self.filters.getSiteIds() limits = self.filters.getLimits() games = self.filters.getGames() + graphops = self.filters.getGraphOps() graphs = { "profit" : True, "sawShowdown" : True, @@ -183,13 +185,15 @@ class GuiGraphViewer (threading.Thread): #Get graph data from DB starttime = time() - (green, blue, red) = self.getRingProfitGraph(playerids, sitenos, limits, games) + (green, blue, red) = self.getRingProfitGraph(playerids, sitenos, limits, games, graphops['dspin']) print _("Graph generated in: %s") %(time() - starttime) + #Set axis labels and grid overlay properites self.ax.set_xlabel(_("Hands"), fontsize = 12) - self.ax.set_ylabel("$", fontsize = 12) + # SET LABEL FOR X AXIS + self.ax.set_ylabel(graphops['dspin'], fontsize = 12) self.ax.grid(color='g', linestyle=':', linewidth=0.2) if green == None or green == []: self.ax.set_title(_("No Data for Player(s) Found")) @@ -228,12 +232,28 @@ class GuiGraphViewer (threading.Thread): self.ax.set_title(_("Profit graph for ring games")) #Draw plot - if graphs['profit'] == True: - self.ax.plot(green, color='green', label=_('Hands: %d\nProfit: $%.2f') %(len(green), green[-1])) - if graphs['sawShowdown'] == True: - self.ax.plot(blue, color='blue', label=_('Showdown: $%.2f') %(blue[-1])) - if graphs['nonShowdown'] == True: - self.ax.plot(red, color='red', label=_('Non-showdown: $%.2f') %(red[-1])) + # this if is only to switch the dollar sign in the labels + # since one goes in the front and one goes in back i cant think of a better + # way to do it. + if graphops['dspin'] == '$': + if graphs['profit'] == True: + self.ax.plot(green, color='green', label=_('Hands: %d\nProfit: $%.2f') %(len(green),green[-1])) + if graphops['showdown'] == 'ON': + if graphs['sawShowdown'] == True: + self.ax.plot(blue, color='blue', label=_('Showdown: $%.2f') %(blue[-1])) + if graphops['nonshowdown'] == 'ON': + if graphs['nonShowdown'] == True: + self.ax.plot(red, color='red', label=_('Non-showdown: $%.2f') %(red[-1])) + elif graphops['dspin'] == 'BB': + if graphs['profit'] == True: + self.ax.plot(green, color='green', label=_('Hands: %d\nProfit: %.2fBB') %(len(green),green[-1])) + if graphops['showdown'] == 'ON': + if graphs['sawShowdown'] == True: + self.ax.plot(blue, color='blue', label=_('Showdown: %.2fBB') %(blue[-1])) + if graphops['nonshowdown'] == 'ON': + if graphs['nonShowdown'] == True: + self.ax.plot(red, color='red', label=_('Non-showdown: %.2fBB') %(red[-1])) + if sys.version[0:3] == '2.5': self.ax.legend(loc='upper left', shadow=True, prop=FontProperties(size='smaller')) else: @@ -249,9 +269,22 @@ class GuiGraphViewer (threading.Thread): #end of def showClicked - def getRingProfitGraph(self, names, sites, limits, games): - tmp = self.sql.query['getRingProfitAllHandsPlayerIdSite'] + + + + + + + def getRingProfitGraph(self, names, sites, limits, games, units): +# tmp = self.sql.query['getRingProfitAllHandsPlayerIdSite'] # print "DEBUG: getRingProfitGraph" + + if units == '$': + tmp = self.sql.query['getRingProfitAllHandsPlayerIdSiteInDollars'] + elif units == 'BB': + tmp = self.sql.query['getRingProfitAllHandsPlayerIdSiteInBB'] + + start_date, end_date = self.filters.getDates() #Buggered if I can find a way to do this 'nicely' take a list of integers and longs diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 7d2931a7..46931d46 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -3077,6 +3077,40 @@ class Sql: GROUP BY h.startTime, hp.handId, hp.sawShowdown, hp.totalProfit ORDER BY h.startTime""" + self.query['getRingProfitAllHandsPlayerIdSiteInBB'] = """ + SELECT hp.handId, ( hp.totalProfit / ( gt.bigBlind * 2 ) ) * 100 , hp.sawShowdown + FROM HandsPlayers hp + INNER JOIN Players pl ON (pl.id = hp.playerId) + INNER JOIN Hands h ON (h.id = hp.handId) + INNER JOIN Gametypes gt ON (gt.id = h.gametypeId) + WHERE pl.id in + AND pl.siteId in + AND h.startTime > '' + AND h.startTime < '' + + + AND hp.tourneysPlayersId IS NULL + GROUP BY h.startTime, hp.handId, hp.sawShowdown, hp.totalProfit + ORDER BY h.startTime""" + + self.query['getRingProfitAllHandsPlayerIdSiteInDollars'] = """ + SELECT hp.handId, hp.totalProfit, hp.sawShowdown + FROM HandsPlayers hp + INNER JOIN Players pl ON (pl.id = hp.playerId) + INNER JOIN Hands h ON (h.id = hp.handId) + INNER JOIN Gametypes gt ON (gt.id = h.gametypeId) + WHERE pl.id in + AND pl.siteId in + AND h.startTime > '' + AND h.startTime < '' + + + AND hp.tourneysPlayersId IS NULL + GROUP BY h.startTime, hp.handId, hp.sawShowdown, hp.totalProfit + ORDER BY h.startTime""" + + + #################################### # Tourney Results query ####################################