From e526501384e90d2a8528ee76841d3236d7bb9b12 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Sun, 11 Jul 2010 05:49:58 +0200 Subject: [PATCH] rename GuiPlayerStats to GuiRingPlayerStats and Filters to RingFilters --- pyfpdb/Filters.py | 948 ----------------------------------- pyfpdb/GuiGraphViewer.py | 4 +- pyfpdb/GuiPlayerStats.py | 680 ------------------------- pyfpdb/GuiPositionalStats.py | 4 +- pyfpdb/GuiRingPlayerStats.py | 678 ++++++++++++++++++++++++- pyfpdb/GuiSessionViewer.py | 4 +- pyfpdb/RingFilters.py | 946 +++++++++++++++++++++++++++++++++- pyfpdb/SQL.py | 4 +- pyfpdb/fpdb.pyw | 4 +- 9 files changed, 1597 insertions(+), 1675 deletions(-) delete mode 100644 pyfpdb/Filters.py delete mode 100644 pyfpdb/GuiPlayerStats.py diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py deleted file mode 100644 index a2420f7f..00000000 --- a/pyfpdb/Filters.py +++ /dev/null @@ -1,948 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -#Copyright 2008-2010 Steffen Schaumburg -#This program is free software: you can redistribute it and/or modify -#it under the terms of the GNU Affero General Public License as published by -#the Free Software Foundation, version 3 of the License. -# -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU Affero General Public License -#along with this program. If not, see . -#In the "official" distribution you can find the license in agpl-3.0.txt. - -import threading -import pygtk -pygtk.require('2.0') -import gtk -import os -import sys -from optparse import OptionParser -from time import * -import gobject -#import pokereval - -import logging -# logging has been set up in fpdb.py or HUD_main.py, use their settings: -log = logging.getLogger("filter") - - -import Configuration -import Database -import SQL -import Charset - - -class Filters(threading.Thread): - def __init__(self, db, config, qdict, display = {}, debug=True): - # config and qdict are now redundant - self.debug = debug - self.db = db - self.cursor = db.cursor - self.sql = db.sql - self.conf = db.config - self.display = display - - # text used on screen stored here so that it can be configured - self.filterText = {'limitsall':'All', 'limitsnone':'None', 'limitsshow':'Show _Limits' - ,'seatsbetween':'Between:', 'seatsand':'And:', 'seatsshow':'Show Number of _Players' - ,'playerstitle':'Hero:', 'sitestitle':'Sites:', 'gamestitle':'Games:' - ,'limitstitle':'Limits:', 'seatstitle':'Number of Players:' - ,'groupstitle':'Grouping:', 'posnshow':'Show Position Stats:' - ,'datestitle':'Date:' - ,'groupsall':'All Players' - ,'limitsFL':'FL', 'limitsNL':'NL', 'limitsPL':'PL', 'ring':'Ring', 'tour':'Tourney' - } - - gen = self.conf.get_general_params() - self.day_start = 0 - if 'day_start' in gen: - self.day_start = float(gen['day_start']) - - # Outer Packing box - self.mainVBox = gtk.VBox(False, 0) - - self.label = {} - self.callback = {} - - self.make_filter() - - def make_filter(self): - self.sites = {} - self.games = {} - self.limits = {} - self.seats = {} - self.groups = {} - self.siteid = {} - self.heroes = {} - self.boxes = {} - - for site in self.conf.get_supported_sites(): - #Get db site id for filtering later - self.cursor.execute(self.sql.query['getSiteId'], (site,)) - result = self.db.cursor.fetchall() - if len(result) == 1: - self.siteid[site] = result[0][0] - else: - print "Either 0 or more than one site matched (%s) - EEK" % site - - # For use in date ranges. - self.start_date = gtk.Entry(max=12) - self.end_date = gtk.Entry(max=12) - self.start_date.set_property('editable', False) - self.end_date.set_property('editable', False) - - # For use in groups etc - self.sbGroups = {} - self.numHands = 0 - - playerFrame = gtk.Frame() - playerFrame.set_label_align(0.0, 0.0) - vbox = gtk.VBox(False, 0) - - self.fillPlayerFrame(vbox, self.display) - playerFrame.add(vbox) - - sitesFrame = gtk.Frame() - sitesFrame.set_label_align(0.0, 0.0) - vbox = gtk.VBox(False, 0) - - self.fillSitesFrame(vbox) - sitesFrame.add(vbox) - - # Game types - gamesFrame = gtk.Frame() - gamesFrame.set_label_align(0.0, 0.0) - gamesFrame.show() - vbox = gtk.VBox(False, 0) - - self.fillGamesFrame(vbox) - gamesFrame.add(vbox) - - # Limits - limitsFrame = gtk.Frame() - limitsFrame.show() - vbox = gtk.VBox(False, 0) - self.cbLimits = {} - self.cbNoLimits = None - self.cbAllLimits = None - self.cbFL = None - self.cbNL = None - self.cbPL = None - self.rb = {} # radio buttons for ring/tour - self.type = None # ring/tour - self.types = {} # list of all ring/tour values - - self.fillLimitsFrame(vbox, self.display) - limitsFrame.add(vbox) - - # Seats - seatsFrame = gtk.Frame() - seatsFrame.show() - vbox = gtk.VBox(False, 0) - self.sbSeats = {} - - self.fillSeatsFrame(vbox, self.display) - seatsFrame.add(vbox) - - # Groups - groupsFrame = gtk.Frame() - groupsFrame.show() - vbox = gtk.VBox(False, 0) - - self.fillGroupsFrame(vbox, self.display) - groupsFrame.add(vbox) - - # Date - dateFrame = gtk.Frame() - dateFrame.set_label_align(0.0, 0.0) - dateFrame.show() - vbox = gtk.VBox(False, 0) - - self.fillDateFrame(vbox) - dateFrame.add(vbox) - - # Buttons - self.Button1=gtk.Button("Unnamed 1") - self.Button1.set_sensitive(False) - - self.Button2=gtk.Button("Unnamed 2") - self.Button2.set_sensitive(False) - - self.mainVBox.add(playerFrame) - self.mainVBox.add(sitesFrame) - self.mainVBox.add(gamesFrame) - self.mainVBox.add(limitsFrame) - self.mainVBox.add(seatsFrame) - self.mainVBox.add(groupsFrame) - self.mainVBox.add(dateFrame) - self.mainVBox.add(self.Button1) - self.mainVBox.add(self.Button2) - - self.mainVBox.show_all() - - # Should do this cleaner - if "Heroes" not in self.display or self.display["Heroes"] == False: - playerFrame.hide() - if "Sites" not in self.display or self.display["Sites"] == False: - sitesFrame.hide() - if "Games" not in self.display or self.display["Games"] == False: - gamesFrame.hide() - if "Limits" not in self.display or self.display["Limits"] == False: - limitsFrame.hide() - if "Seats" not in self.display or self.display["Seats"] == False: - seatsFrame.hide() - if "Groups" not in self.display or self.display["Groups"] == False: - groupsFrame.hide() - if "Dates" not in self.display or self.display["Dates"] == False: - dateFrame.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: - self.Button2.hide() - - if 'button1' in self.label and self.label['button1']: - self.Button1.set_label( self.label['button1'] ) - if 'button2' in self.label and self.label['button2']: - self.Button2.set_label( self.label['button2'] ) - if 'button1' in self.callback and self.callback['button1']: - self.Button1.connect("clicked", self.callback['button1'], "clicked") - self.Button1.set_sensitive(True) - if 'button2' in self.callback and self.callback['button2']: - self.Button2.connect("clicked", self.callback['button2'], "clicked") - self.Button2.set_sensitive(True) - - # make sure any locks on db are released: - self.db.rollback() - - def get_vbox(self): - """returns the vbox of this thread""" - return self.mainVBox - #end def get_vbox - - def getNumHands(self): - return self.numHands - #end def getNumHands - - def getSites(self): - return self.sites - #end def getSites - - def getGames(self): - return self.games - - def getSiteIds(self): - return self.siteid - #end def getSiteIds - - def getHeroes(self): - return self.heroes - #end def getHeroes - - def getLimits(self): - ltuple = [] - for l in self.limits: - if self.limits[l] == True: - ltuple.append(l) - return ltuple - - def getType(self): - return(self.type) - - def getSeats(self): - if 'from' in self.sbSeats: - self.seats['from'] = self.sbSeats['from'].get_value_as_int() - if 'to' in self.sbSeats: - self.seats['to'] = self.sbSeats['to'].get_value_as_int() - return self.seats - #end def getSeats - - def getGroups(self): - return self.groups - - def getDates(self): - return self.__get_dates() - #end def getDates - - def registerButton1Name(self, title): - self.Button1.set_label(title) - self.label['button1'] = title - - def registerButton1Callback(self, callback): - self.Button1.connect("clicked", callback, "clicked") - self.Button1.set_sensitive(True) - self.callback['button1'] = callback - - def registerButton2Name(self, title): - self.Button2.set_label(title) - self.label['button2'] = title - #end def registerButton2Name - - def registerButton2Callback(self, callback): - self.Button2.connect("clicked", callback, "clicked") - self.Button2.set_sensitive(True) - self.callback['button2'] = callback - #end def registerButton2Callback - - def cardCallback(self, widget, data=None): - log.debug( "%s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()]) ) - - def createPlayerLine(self, hbox, site, player): - log.debug('add:"%s"' % player) - label = gtk.Label(site +" id:") - hbox.pack_start(label, False, False, 3) - - pname = gtk.Entry() - pname.set_text(player) - pname.set_width_chars(20) - hbox.pack_start(pname, False, True, 0) - pname.connect("changed", self.__set_hero_name, site) - - # Added EntryCompletion but maybe comboBoxEntry is more flexible? (e.g. multiple choices) - completion = gtk.EntryCompletion() - pname.set_completion(completion) - liststore = gtk.ListStore(gobject.TYPE_STRING) - completion.set_model(liststore) - completion.set_text_column(0) - names = self.db.get_player_names(self.conf, self.siteid[site]) # (config=self.conf, site_id=None, like_player_name="%") - for n in names: # list of single-element "tuples" - _n = Charset.to_gui(n[0]) - _nt = (_n, ) - liststore.append(_nt) - - self.__set_hero_name(pname, site) - - def __set_hero_name(self, w, site): - _name = w.get_text() - # get_text() returns a str but we want internal variables to be unicode: - _guiname = unicode(_name) - self.heroes[site] = _guiname - #log.debug("setting heroes[%s]: %s"%(site, self.heroes[site])) - #end def __set_hero_name - - def __set_num_hands(self, w, val): - try: - self.numHands = int(w.get_text()) - except: - self.numHands = 0 - #log.debug("setting numHands:", self.numHands) - #end def __set_num_hands - - def createSiteLine(self, hbox, site): - cb = gtk.CheckButton(site) - cb.connect('clicked', self.__set_site_select, site) - cb.set_active(True) - hbox.pack_start(cb, False, False, 0) - - def createGameLine(self, hbox, game): - cb = gtk.CheckButton(game) - cb.connect('clicked', self.__set_game_select, game) - hbox.pack_start(cb, False, False, 0) - cb.set_active(True) - - def createLimitLine(self, hbox, limit, ltext): - cb = gtk.CheckButton(str(ltext)) - cb.connect('clicked', self.__set_limit_select, limit) - hbox.pack_start(cb, False, False, 0) - if limit != "none": - cb.set_active(True) - return(cb) - - def __set_site_select(self, w, site): - #print w.get_active() - self.sites[site] = w.get_active() - log.debug("self.sites[%s] set to %s" %(site, self.sites[site])) - - def __set_game_select(self, w, game): - #print w.get_active() - self.games[game] = w.get_active() - log.debug("self.games[%s] set to %s" %(game, self.games[game])) - #end def __set_game_select - - def __set_limit_select(self, w, limit): - #print w.get_active() - self.limits[limit] = w.get_active() - log.debug("self.limit[%s] set to %s" %(limit, self.limits[limit])) - if limit.isdigit() or (len(limit) > 2 and (limit[-2:] == 'nl' or limit[-2:] == 'fl' or limit[-2:] == 'pl')): - if self.limits[limit]: - if self.cbNoLimits is not None: - self.cbNoLimits.set_active(False) - else: - if self.cbAllLimits is not None: - self.cbAllLimits.set_active(False) - if not self.limits[limit]: - if limit.isdigit(): - if self.cbFL is not None: - self.cbFL.set_active(False) - elif (len(limit) > 2 and (limit[-2:] == 'nl')): - if self.cbNL is not None: - self.cbNL.set_active(False) - else: - if self.cbPL is not None: - self.cbPL.set_active(False) - elif limit == "all": - if self.limits[limit]: - #for cb in self.cbLimits.values(): - # cb.set_active(True) - if self.cbFL is not None: - self.cbFL.set_active(True) - if self.cbNL is not None: - self.cbNL.set_active(True) - if self.cbPL is not None: - self.cbPL.set_active(True) - elif limit == "none": - if self.limits[limit]: - for cb in self.cbLimits.values(): - cb.set_active(False) - if self.cbNL is not None: - self.cbNL.set_active(False) - if self.cbFL is not None: - self.cbFL.set_active(False) - if self.cbPL is not None: - self.cbPL.set_active(False) - elif limit == "fl": - if not self.limits[limit]: - # only toggle all fl limits off if they are all currently on - # this stops turning one off from cascading into 'fl' box off - # and then all fl limits being turned off - all_fl_on = True - for cb in self.cbLimits.values(): - t = cb.get_children()[0].get_text() - if t.isdigit(): - if not cb.get_active(): - all_fl_on = False - found = {'ring':False, 'tour':False} - for cb in self.cbLimits.values(): - #print "cb label: ", cb.children()[0].get_text() - t = cb.get_children()[0].get_text() - if t.isdigit(): - if self.limits[limit] or all_fl_on: - cb.set_active(self.limits[limit]) - found[self.types[t]] = True - if self.limits[limit]: - if not found[self.type]: - if self.type == 'ring': - if 'tour' in self.rb: - self.rb['tour'].set_active(True) - elif self.type == 'tour': - if 'ring' in self.rb: - self.rb['ring'].set_active(True) - elif limit == "nl": - if not self.limits[limit]: - # only toggle all nl limits off if they are all currently on - # this stops turning one off from cascading into 'nl' box off - # and then all nl limits being turned off - all_nl_on = True - for cb in self.cbLimits.values(): - t = cb.get_children()[0].get_text() - if "nl" in t and len(t) > 2: - if not cb.get_active(): - all_nl_on = False - found = {'ring':False, 'tour':False} - for cb in self.cbLimits.values(): - t = cb.get_children()[0].get_text() - if "nl" in t and len(t) > 2: - if self.limits[limit] or all_nl_on: - cb.set_active(self.limits[limit]) - found[self.types[t]] = True - if self.limits[limit]: - if not found[self.type]: - if self.type == 'ring': - if 'tour' in self.rb: - self.rb['tour'].set_active(True) - elif self.type == 'tour': - if 'ring' in self.rb: - self.rb['ring'].set_active(True) - elif limit == "pl": - if not self.limits[limit]: - # only toggle all nl limits off if they are all currently on - # this stops turning one off from cascading into 'nl' box off - # and then all nl limits being turned off - all_nl_on = True - for cb in self.cbLimits.values(): - t = cb.get_children()[0].get_text() - if "pl" in t and len(t) > 2: - if not cb.get_active(): - all_nl_on = False - found = {'ring':False, 'tour':False} - for cb in self.cbLimits.values(): - t = cb.get_children()[0].get_text() - if "pl" in t and len(t) > 2: - if self.limits[limit] or all_nl_on: - cb.set_active(self.limits[limit]) - found[self.types[t]] = True - if self.limits[limit]: - if not found[self.type]: - if self.type == 'ring': - if 'tour' in self.rb: - self.rb['tour'].set_active(True) - elif self.type == 'tour': - if 'ring' in self.rb: - self.rb['ring'].set_active(True) - elif limit == "ring": - log.debug("set", limit, "to", self.limits[limit]) - if self.limits[limit]: - self.type = "ring" - for cb in self.cbLimits.values(): - #print "cb label: ", cb.children()[0].get_text() - if self.types[cb.get_children()[0].get_text()] == 'tour': - cb.set_active(False) - elif limit == "tour": - log.debug( "set", limit, "to", self.limits[limit] ) - if self.limits[limit]: - self.type = "tour" - for cb in self.cbLimits.values(): - #print "cb label: ", cb.children()[0].get_text() - if self.types[cb.get_children()[0].get_text()] == 'ring': - cb.set_active(False) - - def __set_seat_select(self, w, seat): - #print "__set_seat_select: seat =", seat, "active =", w.get_active() - self.seats[seat] = w.get_active() - log.debug( "self.seats[%s] set to %s" %(seat, self.seats[seat]) ) - - def __set_group_select(self, w, group): - #print "__set_seat_select: seat =", seat, "active =", w.get_active() - self.groups[group] = w.get_active() - log.debug( "self.groups[%s] set to %s" %(group, self.groups[group]) ) - - def fillPlayerFrame(self, vbox, display): - top_hbox = gtk.HBox(False, 0) - vbox.pack_start(top_hbox, False, False, 0) - lbl_title = gtk.Label(self.filterText['playerstitle']) - lbl_title.set_alignment(xalign=0.0, yalign=0.5) - top_hbox.pack_start(lbl_title, expand=True, padding=3) - showb = gtk.Button(label="refresh", stock=None, use_underline=True) - showb.set_alignment(xalign=1.0, yalign=0.5) - showb.connect('clicked', self.__refresh, 'players') - - vbox1 = gtk.VBox(False, 0) - vbox.pack_start(vbox1, False, False, 0) - self.boxes['players'] = vbox1 - - for site in self.conf.get_supported_sites(): - hBox = gtk.HBox(False, 0) - vbox1.pack_start(hBox, False, True, 0) - - player = self.conf.supported_sites[site].screen_name - _pname = Charset.to_gui(player) - self.createPlayerLine(hBox, site, _pname) - - if "GroupsAll" in display and display["GroupsAll"] == True: - hbox = gtk.HBox(False, 0) - vbox1.pack_start(hbox, False, False, 0) - cb = gtk.CheckButton(self.filterText['groupsall']) - cb.connect('clicked', self.__set_group_select, 'allplayers') - hbox.pack_start(cb, False, False, 0) - self.sbGroups['allplayers'] = cb - self.groups['allplayers'] = False - - lbl = gtk.Label('Min # Hands:') - lbl.set_alignment(xalign=1.0, yalign=0.5) - hbox.pack_start(lbl, expand=True, padding=3) - - phands = gtk.Entry() - phands.set_text('0') - phands.set_width_chars(8) - hbox.pack_start(phands, False, False, 0) - phands.connect("changed", self.__set_num_hands, site) - top_hbox.pack_start(showb, expand=False, padding=1) - - def fillSitesFrame(self, vbox): - top_hbox = gtk.HBox(False, 0) - top_hbox.show() - vbox.pack_start(top_hbox, False, False, 0) - - lbl_title = gtk.Label(self.filterText['sitestitle']) - lbl_title.set_alignment(xalign=0.0, yalign=0.5) - top_hbox.pack_start(lbl_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, 'sites') - showb.show() - top_hbox.pack_start(showb, expand=False, padding=1) - - vbox1 = gtk.VBox(False, 0) - self.boxes['sites'] = vbox1 - vbox.pack_start(vbox1, False, False, 0) - - for site in self.conf.get_supported_sites(): - hbox = gtk.HBox(False, 0) - vbox1.pack_start(hbox, False, True, 0) - self.createSiteLine(hbox, site) - #Get db site id for filtering later - #self.cursor.execute(self.sql.query['getSiteId'], (site,)) - #result = self.db.cursor.fetchall() - #if len(result) == 1: - # self.siteid[site] = result[0][0] - #else: - # print "Either 0 or more than one site matched - EEK" - - def fillGamesFrame(self, vbox): - top_hbox = gtk.HBox(False, 0) - vbox.pack_start(top_hbox, False, False, 0) - lbl_title = gtk.Label(self.filterText['gamestitle']) - lbl_title.set_alignment(xalign=0.0, yalign=0.5) - top_hbox.pack_start(lbl_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) - - vbox1 = gtk.VBox(False, 0) - vbox.pack_start(vbox1, False, False, 0) - self.boxes['games'] = vbox1 - - self.cursor.execute(self.sql.query['getGames']) - result = self.db.cursor.fetchall() - if len(result) >= 1: - for line in result: - hbox = gtk.HBox(False, 0) - vbox1.pack_start(hbox, False, True, 0) - self.createGameLine(hbox, line[0]) - else: - print "INFO: No games returned from database" - log.info("No games returned from database") - #end def fillGamesFrame - - def fillLimitsFrame(self, vbox, display): - top_hbox = gtk.HBox(False, 0) - vbox.pack_start(top_hbox, False, False, 0) - lbl_title = gtk.Label(self.filterText['limitstitle']) - lbl_title.set_alignment(xalign=0.0, yalign=0.5) - top_hbox.pack_start(lbl_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, 'limits') - - vbox1 = gtk.VBox(False, 0) - vbox.pack_start(vbox1, False, False, 0) - self.boxes['limits'] = vbox1 - - self.cursor.execute(self.sql.query['getLimits3']) - # selects limitType, bigBlind - result = self.db.cursor.fetchall() - found = {'nl':False, 'fl':False, 'pl':False, 'ring':False, 'tour':False} - - if len(result) >= 1: - hbox = gtk.HBox(True, 0) - vbox1.pack_start(hbox, False, False, 0) - vbox2 = gtk.VBox(False, 0) - hbox.pack_start(vbox2, False, False, 0) - vbox3 = gtk.VBox(False, 0) - hbox.pack_start(vbox3, False, False, 0) - for i, line in enumerate(result): - if "UseType" in self.display: - if line[0] != self.display["UseType"]: - continue - hbox = gtk.HBox(False, 0) - if i <= len(result)/2: - vbox2.pack_start(hbox, False, False, 0) - else: - vbox3.pack_start(hbox, False, False, 0) - if True: #line[0] == 'ring': - if line[1] == 'fl': - name = str(line[2]) - found['fl'] = True - elif line[1] == 'pl': - name = str(line[2])+line[1] - found['pl'] = True - else: - name = str(line[2])+line[1] - found['nl'] = True - self.cbLimits[name] = self.createLimitLine(hbox, name, name) - self.types[name] = line[0] - found[line[0]] = True # type is ring/tour - self.type = line[0] # if only one type, set it now - if "LimitSep" in display and display["LimitSep"] == True and len(result) >= 2: - hbox = gtk.HBox(True, 0) - vbox1.pack_start(hbox, False, False, 0) - vbox2 = gtk.VBox(False, 0) - hbox.pack_start(vbox2, False, False, 0) - vbox3 = gtk.VBox(False, 0) - hbox.pack_start(vbox3, False, False, 0) - - hbox = gtk.HBox(False, 0) - vbox2.pack_start(hbox, False, False, 0) - self.cbAllLimits = self.createLimitLine(hbox, 'all', self.filterText['limitsall']) - hbox = gtk.HBox(False, 0) - vbox2.pack_start(hbox, False, False, 0) - self.cbNoLimits = self.createLimitLine(hbox, 'none', self.filterText['limitsnone']) - - dest = vbox3 # for ring/tour buttons - if "LimitType" in display and display["LimitType"] == True and found['nl'] and found['fl']: - #if found['fl']: - hbox = gtk.HBox(False, 0) - vbox3.pack_start(hbox, False, False, 0) - self.cbFL = self.createLimitLine(hbox, 'fl', self.filterText['limitsFL']) - #if found['nl']: - hbox = gtk.HBox(False, 0) - vbox3.pack_start(hbox, False, False, 0) - self.cbNL = self.createLimitLine(hbox, 'nl', self.filterText['limitsNL']) - hbox = gtk.HBox(False, 0) - vbox3.pack_start(hbox, False, False, 0) - self.cbPL = self.createLimitLine(hbox, 'pl', self.filterText['limitsPL']) - dest = vbox2 # for ring/tour buttons - else: - print "INFO: No games returned from database" - log.info("No games returned from database") - - if "Type" in display and display["Type"] == True and found['ring'] and found['tour']: - rb1 = gtk.RadioButton(None, self.filterText['ring']) - rb1.connect('clicked', self.__set_limit_select, 'ring') - rb2 = gtk.RadioButton(rb1, self.filterText['tour']) - rb2.connect('clicked', self.__set_limit_select, 'tour') - top_hbox.pack_start(rb1, False, False, 0) # (child, expand, fill, padding) - top_hbox.pack_start(rb2, True, True, 0) # child uses expand space if fill is true - - self.rb['ring'] = rb1 - self.rb['tour'] = rb2 - #print "about to set ring to true" - rb1.set_active(True) - # 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 fillSeatsFrame(self, vbox, display): - hbox = gtk.HBox(False, 0) - vbox.pack_start(hbox, False, False, 0) - lbl_title = gtk.Label(self.filterText['seatstitle']) - lbl_title.set_alignment(xalign=0.0, yalign=0.5) - hbox.pack_start(lbl_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, 'seats') - hbox.pack_start(showb, expand=False, padding=1) - - vbox1 = gtk.VBox(False, 0) - vbox.pack_start(vbox1, False, False, 0) - self.boxes['seats'] = vbox1 - - hbox = gtk.HBox(False, 0) - vbox1.pack_start(hbox, False, True, 0) - - lbl_from = gtk.Label(self.filterText['seatsbetween']) - lbl_to = gtk.Label(self.filterText['seatsand']) - adj1 = gtk.Adjustment(value=2, lower=2, upper=10, step_incr=1, page_incr=1, page_size=0) - sb1 = gtk.SpinButton(adjustment=adj1, climb_rate=0.0, digits=0) - adj2 = gtk.Adjustment(value=10, lower=2, upper=10, step_incr=1, page_incr=1, page_size=0) - sb2 = gtk.SpinButton(adjustment=adj2, climb_rate=0.0, digits=0) - - hbox.pack_start(lbl_from, expand=False, padding=3) - hbox.pack_start(sb1, False, False, 0) - hbox.pack_start(lbl_to, expand=False, padding=3) - hbox.pack_start(sb2, False, False, 0) - - self.sbSeats['from'] = sb1 - self.sbSeats['to'] = sb2 - #end def fillSeatsFrame - - def fillGroupsFrame(self, vbox, display): - hbox = gtk.HBox(False, 0) - vbox.pack_start(hbox, False, False, 0) - lbl_title = gtk.Label(self.filterText['groupstitle']) - lbl_title.set_alignment(xalign=0.0, yalign=0.5) - hbox.pack_start(lbl_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, 'groups') - hbox.pack_start(showb, expand=False, padding=1) - - vbox1 = gtk.VBox(False, 0) - vbox.pack_start(vbox1, False, False, 0) - self.boxes['groups'] = vbox1 - - hbox = gtk.HBox(False, 0) - vbox1.pack_start(hbox, False, False, 0) - cb = self.createLimitLine(hbox, 'show', self.filterText['limitsshow']) - - hbox = gtk.HBox(False, 0) - vbox1.pack_start(hbox, False, True, 0) - cb = gtk.CheckButton(self.filterText['posnshow']) - cb.connect('clicked', self.__set_group_select, 'posn') - hbox.pack_start(cb, False, False, 0) - self.sbGroups['posn'] = cb - self.groups['posn'] = False - - if "SeatSep" in display and display["SeatSep"] == True: - hbox = gtk.HBox(False, 0) - vbox1.pack_start(hbox, False, True, 0) - cb = gtk.CheckButton(self.filterText['seatsshow']) - cb.connect('clicked', self.__set_seat_select, 'show') - hbox.pack_start(cb, False, False, 0) - self.sbSeats['show'] = cb - self.seats['show'] = False - - def fillCardsFrame(self, vbox): - hbox1 = gtk.HBox(True,0) - hbox1.show() - vbox.pack_start(hbox1, True, True, 0) - - cards = [ "A", "K","Q","J","T","9","8","7","6","5","4","3","2" ] - - for j in range(0, len(cards)): - hbox1 = gtk.HBox(True,0) - hbox1.show() - vbox.pack_start(hbox1, True, True, 0) - for i in range(0, len(cards)): - if i < (j + 1): - suit = "o" - else: - suit = "s" - button = gtk.ToggleButton("%s%s%s" %(cards[i], cards[j], suit)) - button.connect("toggled", self.cardCallback, "%s%s%s" %(cards[i], cards[j], suit)) - hbox1.pack_start(button, True, True, 0) - button.show() - - def fillDateFrame(self, vbox): - # Hat tip to Mika Bostrom - calendar code comes from PokerStats - top_hbox = gtk.HBox(False, 0) - vbox.pack_start(top_hbox, False, False, 0) - lbl_title = gtk.Label(self.filterText['datestitle']) - lbl_title.set_alignment(xalign=0.0, yalign=0.5) - top_hbox.pack_start(lbl_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, 'dates') - top_hbox.pack_start(showb, expand=False, padding=1) - - vbox1 = gtk.VBox(False, 0) - vbox.pack_start(vbox1, False, False, 0) - self.boxes['dates'] = vbox1 - - hbox = gtk.HBox() - vbox1.pack_start(hbox, False, True, 0) - - lbl_start = gtk.Label('From:') - - btn_start = gtk.Button() - btn_start.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)) - btn_start.connect('clicked', self.__calendar_dialog, self.start_date) - - hbox.pack_start(lbl_start, expand=False, padding=3) - hbox.pack_start(btn_start, expand=False, padding=3) - hbox.pack_start(self.start_date, expand=False, padding=2) - - #New row for end date - hbox = gtk.HBox() - vbox1.pack_start(hbox, False, True, 0) - - lbl_end = gtk.Label(' To:') - btn_end = gtk.Button() - btn_end.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)) - btn_end.connect('clicked', self.__calendar_dialog, self.end_date) - - btn_clear = gtk.Button(label=' Clear Dates ') - btn_clear.connect('clicked', self.__clear_dates) - - hbox.pack_start(lbl_end, expand=False, padding=3) - hbox.pack_start(btn_end, expand=False, padding=3) - hbox.pack_start(self.end_date, expand=False, padding=2) - - hbox.pack_start(btn_clear, expand=False, padding=15) - #end def fillDateFrame - - def __refresh(self, widget, entry): - for w in self.mainVBox.get_children(): - w.destroy() - self.make_filter() - - def __toggle_box(self, widget, entry): - if self.boxes[entry].props.visible: - self.boxes[entry].hide() - widget.set_label("show") - else: - self.boxes[entry].show() - widget.set_label("hide") - #end def __toggle_box - - def __calendar_dialog(self, widget, entry): - d = gtk.Window(gtk.WINDOW_TOPLEVEL) - d.set_title('Pick a date') - - vb = gtk.VBox() - cal = gtk.Calendar() - vb.pack_start(cal, expand=False, padding=0) - - btn = gtk.Button('Done') - btn.connect('clicked', self.__get_date, cal, entry, d) - - vb.pack_start(btn, expand=False, padding=4) - - d.add(vb) - d.set_position(gtk.WIN_POS_MOUSE) - d.show_all() - #end def __calendar_dialog - - def __clear_dates(self, w): - self.start_date.set_text('') - self.end_date.set_text('') - #end def __clear_dates - - def __get_dates(self): - # self.day_start gives user's start of day in hours - offset = int(self.day_start * 3600) # calc day_start in seconds - - t1 = self.start_date.get_text() - t2 = self.end_date.get_text() - - if t1 == '': - t1 = '1970-01-02' - if t2 == '': - t2 = '2020-12-12' - - s1 = strptime(t1, "%Y-%m-%d") # make time_struct - s2 = strptime(t2, "%Y-%m-%d") - e1 = mktime(s1) + offset # s1 is localtime, but returned time since epoch is UTC, then add the - e2 = mktime(s2) + offset # s2 is localtime, but returned time since epoch is UTC - e2 = e2 + 24 * 3600 - 1 # date test is inclusive, so add 23h 59m 59s to e2 - - adj_t1 = strftime("%Y-%m-%d %H:%M:%S", gmtime(e1)) # make adjusted string including time - adj_t2 = strftime("%Y-%m-%d %H:%M:%S", gmtime(e2)) - log.info("t1="+t1+" adj_t1="+adj_t1+'.') - - return (adj_t1, adj_t2) - #end def __get_dates - - def __get_date(self, widget, calendar, entry, win): - # year and day are correct, month is 0..11 - (year, month, day) = calendar.get_date() - month += 1 - ds = '%04d-%02d-%02d' % (year, month, day) - entry.set_text(ds) - win.destroy() - -def main(argv=None): - """main can also be called in the python interpreter, by supplying the command line as the argument.""" - if argv is None: - argv = sys.argv[1:] - - def destroy(*args): # call back for terminating the main eventloop - gtk.main_quit() - - parser = OptionParser() - (options, argv) = parser.parse_args(args = argv) - - config = Configuration.Config() - db = None - - db = Database.Database() - db.do_connect(config) - - qdict = SQL.SQL(db.get_backend_name()) - - i = Filters(db, config, qdict) - main_window = gtk.Window() - main_window.connect('destroy', destroy) - main_window.add(i.get_vbox()) - main_window.show() - gtk.main() - -if __name__ == '__main__': - sys.exit(main()) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index 96026864..68cbacc7 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -44,7 +44,7 @@ except ImportError, inst: import fpdb_import import Database -import Filters +import RingFilters import Charset class GuiGraphViewer (threading.Thread): @@ -75,7 +75,7 @@ class GuiGraphViewer (threading.Thread): "Button2" : True } - self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display) + self.filters = RingFilters.RingFilters(self.db, self.conf, self.sql, display = filters_display) self.filters.registerButton1Name("Refresh _Graph") self.filters.registerButton1Callback(self.generateGraph) self.filters.registerButton2Name("_Export to File") diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py deleted file mode 100644 index 80786d76..00000000 --- a/pyfpdb/GuiPlayerStats.py +++ /dev/null @@ -1,680 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -#Copyright 2008-2010 Steffen Schaumburg -#This program is free software: you can redistribute it and/or modify -#it under the terms of the GNU Affero General Public License as published by -#the Free Software Foundation, version 3 of the License. -# -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU Affero General Public License -#along with this program. If not, see . -#In the "official" distribution you can find the license in agpl-3.0.txt. - -import traceback -import threading -import pygtk -pygtk.require('2.0') -import gtk -import os -import sys -from time import time, strftime - -import Card -import fpdb_import -import Database -import Filters -import Charset - -colalias,colshow,colheading,colxalign,colformat,coltype = 0,1,2,3,4,5 -ranks = {'x':0, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9, 'T':10, 'J':11, 'Q':12, 'K':13, 'A':14} - -class GuiPlayerStats (threading.Thread): - - def __init__(self, config, querylist, mainwin, debug=True): - self.debug = debug - self.conf = config - self.main_window = mainwin - self.sql = querylist - - self.liststore = [] # gtk.ListStore[] stores the contents of the grids - self.listcols = [] # gtk.TreeViewColumn[][] stores the columns in the grids - - self.MYSQL_INNODB = 2 - self.PGSQL = 3 - self.SQLITE = 4 - - # create new db connection to avoid conflicts with other threads - self.db = Database.Database(self.conf, sql=self.sql) - self.cursor = self.db.cursor - - settings = {} - settings.update(self.conf.get_db_parameters()) - settings.update(self.conf.get_tv_parameters()) - settings.update(self.conf.get_import_parameters()) - settings.update(self.conf.get_default_paths()) - - # text used on screen stored here so that it can be configured - self.filterText = {'handhead':'Hand Breakdown for all levels listed above' - } - - filters_display = { "Heroes" : True, - "Sites" : True, - "Games" : True, - "Limits" : True, - "LimitSep" : True, - "LimitType" : True, - "Type" : True, - "Seats" : True, - "SeatSep" : True, - "Dates" : True, - "Groups" : True, - "GroupsAll" : True, - "Button1" : True, - "Button2" : True - } - - self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display) - self.filters.registerButton1Name("_Filters") - self.filters.registerButton1Callback(self.showDetailFilter) - self.filters.registerButton2Name("_Refresh Stats") - self.filters.registerButton2Callback(self.refreshStats) - - # ToDo: store in config - # ToDo: create popup to adjust column config - # columns to display, keys match column name returned by sql, values in tuple are: - # is column displayed, column heading, xalignment, formatting, celltype - self.columns = [ ["game", True, "Game", 0.0, "%s", "str"] - , ["hand", False, "Hand", 0.0, "%s", "str"] # true not allowed for this line - , ["plposition", False, "Posn", 1.0, "%s", "str"] # true not allowed for this line (set in code) - , ["pname", False, "Name", 0.0, "%s", "str"] # true not allowed for this line (set in code) - , ["n", True, "Hds", 1.0, "%1.0f", "str"] - , ["avgseats", False, "Seats", 1.0, "%3.1f", "str"] - , ["vpip", True, "VPIP", 1.0, "%3.1f", "str"] - , ["pfr", True, "PFR", 1.0, "%3.1f", "str"] - , ["pf3", True, "PF3", 1.0, "%3.1f", "str"] - , ["aggfac", True, "AggFac", 1.0, "%2.2f", "str"] - , ["aggfrq", True, "AggFreq", 1.0, "%3.1f", "str"] - , ["conbet", True, "ContBet", 1.0, "%3.1f", "str"] - , ["steals", True, "Steals", 1.0, "%3.1f", "str"] - , ["saw_f", True, "Saw_F", 1.0, "%3.1f", "str"] - , ["sawsd", True, "SawSD", 1.0, "%3.1f", "str"] - , ["wtsdwsf", True, "WtSDwsF", 1.0, "%3.1f", "str"] - , ["wmsd", True, "W$SD", 1.0, "%3.1f", "str"] - , ["flafq", True, "FlAFq", 1.0, "%3.1f", "str"] - , ["tuafq", True, "TuAFq", 1.0, "%3.1f", "str"] - , ["rvafq", True, "RvAFq", 1.0, "%3.1f", "str"] - , ["pofafq", False, "PoFAFq", 1.0, "%3.1f", "str"] - , ["net", True, "Net($)", 1.0, "%6.2f", "cash"] - , ["bbper100", True, "bb/100", 1.0, "%4.2f", "str"] - , ["rake", True, "Rake($)", 1.0, "%6.2f", "cash"] - , ["bb100xr", True, "bbxr/100", 1.0, "%4.2f", "str"] - , ["variance", True, "Variance", 1.0, "%5.2f", "str"] - ] - - # Detail filters: This holds the data used in the popup window, extra values are - # added at the end of these lists during processing - # sql test, screen description, min, max - self.handtests = [ # already in filter class : ['h.seats', 'Number of Players', 2, 10] - ['h.maxSeats', 'Size of Table', 2, 10] - ,['h.playersVpi', 'Players who VPI', 0, 10] - ,['h.playersAtStreet1', 'Players at Flop', 0, 10] - ,['h.playersAtStreet2', 'Players at Turn', 0, 10] - ,['h.playersAtStreet3', 'Players at River', 0, 10] - ,['h.playersAtStreet4', 'Players at Street7', 0, 10] - ,['h.playersAtShowdown', 'Players at Showdown', 0, 10] - ,['h.street0Raises', 'Bets to See Flop', 0, 5] - ,['h.street1Raises', 'Bets to See Turn', 0, 5] - ,['h.street2Raises', 'Bets to See River', 0, 5] - ,['h.street3Raises', 'Bets to See Street7', 0, 5] - ,['h.street4Raises', 'Bets to See Showdown', 0, 5] - ] - - self.stats_frame = None - self.stats_vbox = None - self.detailFilters = [] # the data used to enhance the sql select - - #self.main_hbox = gtk.HBox(False, 0) - #self.main_hbox.show() - self.main_hbox = gtk.HPaned() - - self.stats_frame = gtk.Frame() - self.stats_frame.show() - - self.stats_vbox = gtk.VPaned() - self.stats_vbox.show() - self.stats_frame.add(self.stats_vbox) - # self.fillStatsFrame(self.stats_vbox) - - #self.main_hbox.pack_start(self.filters.get_vbox()) - #self.main_hbox.pack_start(self.stats_frame, expand=True, fill=True) - self.main_hbox.pack1(self.filters.get_vbox()) - self.main_hbox.pack2(self.stats_frame) - self.main_hbox.show() - - # make sure Hand column is not displayed - [x for x in self.columns if x[0] == 'hand'][0][1] = False - self.last_pos = -1 - - - def get_vbox(self): - """returns the vbox of this thread""" - return self.main_hbox - #end def get_vbox - - def refreshStats(self, widget, data): - self.last_pos = self.stats_vbox.get_position() - try: self.stats_vbox.destroy() - except AttributeError: pass - self.liststore = [] - self.listcols = [] - #self.stats_vbox = gtk.VBox(False, 0) - self.stats_vbox = gtk.VPaned() - self.stats_vbox.show() - self.stats_frame.add(self.stats_vbox) - self.fillStatsFrame(self.stats_vbox) - if self.last_pos > 0: - self.stats_vbox.set_position(self.last_pos) - #end def refreshStats - - def fillStatsFrame(self, vbox): - sites = self.filters.getSites() - heroes = self.filters.getHeroes() - siteids = self.filters.getSiteIds() - limits = self.filters.getLimits() - type = self.filters.getType() - seats = self.filters.getSeats() - groups = self.filters.getGroups() - dates = self.filters.getDates() - games = self.filters.getGames() - sitenos = [] - playerids = [] - - # Which sites are selected? - for site in sites: - if sites[site] == True: - sitenos.append(siteids[site]) - _hname = Charset.to_utf8(heroes[site]) - result = self.db.get_player_id(self.conf, site, _hname) - if result is not None: - playerids.append(int(result)) - - if not sitenos: - #Should probably pop up here. - print "No sites selected - defaulting to PokerStars" - sitenos = [2] - if not playerids: - print "No player ids found" - return - if not limits: - print "No limits found" - return - - self.createStatsTable(vbox, playerids, sitenos, limits, type, seats, groups, dates, games) - #end def fillStatsFrame - - def createStatsTable(self, vbox, playerids, sitenos, limits, type, seats, groups, dates, games): - startTime = time() - show_detail = True - - # Scrolled window for summary table - swin = gtk.ScrolledWindow(hadjustment=None, vadjustment=None) - swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - swin.show() - vbox.pack1(swin) - - # Display summary table at top of page - # 3rd parameter passes extra flags, currently includes: - # holecards - whether to display card breakdown (True/False) - # numhands - min number hands required when displaying all players - # gridnum - index for grid data structures - flags = [False, self.filters.getNumHands(), 0] - self.addGrid(swin, 'playerDetailedStats', flags, playerids - ,sitenos, limits, type, seats, groups, dates, games) - - if 'allplayers' in groups and groups['allplayers']: - # can't currently do this combination so skip detailed table - show_detail = False - - if show_detail: - # Separator - vbox2 = gtk.VBox(False, 0) - heading = gtk.Label(self.filterText['handhead']) - heading.show() - vbox2.pack_start(heading, expand=False, padding=3) - - # Scrolled window for detailed table (display by hand) - swin = gtk.ScrolledWindow(hadjustment=None, vadjustment=None) - swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - swin.show() - vbox2.pack_start(swin, expand=True, padding=3) - vbox.pack2(vbox2) - vbox2.show() - - # Detailed table - flags[0] = True - flags[2] = 1 - self.addGrid(swin, 'playerDetailedStats', flags, playerids - ,sitenos, limits, type, seats, groups, dates, games) - - self.db.rollback() - print "Stats page displayed in %4.2f seconds" % (time() - startTime) - #end def createStatsTable - - def reset_style_render_func(self, treeviewcolumn, cell, model, iter): - cell.set_property('foreground', 'black') - #end def reset_style_render_func - - def ledger_style_render_func(self, tvcol, cell, model, iter): - str = cell.get_property('text') - if '-' in str: - str = str.replace("-", "") - str = "(%s)" %(str) - cell.set_property('text', str) - cell.set_property('foreground', 'red') - else: - cell.set_property('foreground', 'darkgreen') - - return - - def sortnums(self, model, iter1, iter2, nums): - try: - ret = 0 - (n, grid) = nums - a = self.liststore[grid].get_value(iter1, n) - b = self.liststore[grid].get_value(iter2, n) - if 'f' in self.cols_to_show[n][4]: - try: a = float(a) - except: a = 0.0 - try: b = float(b) - except: b = 0.0 - if n == 0 and grid == 1: #make sure it only works on the starting hands - a1,a2,a3 = ranks[a[0]], ranks[a[1]], (a+'o')[2] - b1,b2,b3 = ranks[b[0]], ranks[b[1]], (b+'o')[2] - if a1 > b1 or ( a1 == b1 and (a2 > b2 or (a2 == b2 and a3 > b3) ) ): - ret = 1 - else: - ret = -1 - else: - if a < b: - ret = -1 - elif a == b: - ret = 0 - else: - ret = 1 - #print "n =", n, "iter1[n] =", self.liststore[grid].get_value(iter1,n), "iter2[n] =", self.liststore[grid].get_value(iter2,n), "ret =", ret - except: - err = traceback.extract_tb(sys.exc_info()[2]) - print "***sortnums error: " + str(sys.exc_info()[1]) - print "\n".join( [e[0]+':'+str(e[1])+" "+e[2] for e in err] ) - - return(ret) - - def sortcols(self, col, nums): - try: - #This doesn't actually work yet - clicking heading in top section sorts bottom section :-( - (n, grid) = nums - if not col.get_sort_indicator() or col.get_sort_order() == gtk.SORT_ASCENDING: - col.set_sort_order(gtk.SORT_DESCENDING) - else: - col.set_sort_order(gtk.SORT_ASCENDING) - self.liststore[grid].set_sort_column_id(n, col.get_sort_order()) - self.liststore[grid].set_sort_func(n, self.sortnums, (n,grid)) - for i in xrange(len(self.listcols[grid])): - self.listcols[grid][i].set_sort_indicator(False) - self.listcols[grid][n].set_sort_indicator(True) - # use this listcols[col].set_sort_indicator(True) - # to turn indicator off for other cols - except: - err = traceback.extract_tb(sys.exc_info()[2]) - print "***sortcols error: " + str(sys.exc_info()[1]) - print "\n".join( [e[0]+':'+str(e[1])+" "+e[2] for e in err] ) - #end def sortcols - - def addGrid(self, vbox, query, flags, playerids, sitenos, limits, type, seats, groups, dates, games): - counter = 0 - row = 0 - sqlrow = 0 - if not flags: holecards,grid = False,0 - else: holecards,grid = flags[0],flags[2] - - tmp = self.sql.query[query] - tmp = self.refineQuery(tmp, flags, playerids, sitenos, limits, type, seats, groups, dates, games) - self.cursor.execute(tmp) - result = self.cursor.fetchall() - colnames = [desc[0].lower() for desc in self.cursor.description] - - # pre-fetch some constant values: - self.cols_to_show = [x for x in self.columns if x[colshow]] - hgametypeid_idx = colnames.index('hgametypeid') - - assert len(self.liststore) == grid, "len(self.liststore)="+str(len(self.liststore))+" grid-1="+str(grid) - self.liststore.append( gtk.ListStore(*([str] * len(self.cols_to_show))) ) - view = gtk.TreeView(model=self.liststore[grid]) - view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH) - #vbox.pack_start(view, expand=False, padding=3) - vbox.add(view) - textcell = gtk.CellRendererText() - textcell50 = gtk.CellRendererText() - textcell50.set_property('xalign', 0.5) - numcell = gtk.CellRendererText() - numcell.set_property('xalign', 1.0) - assert len(self.listcols) == grid - self.listcols.append( [] ) - - # Create header row eg column: ("game", True, "Game", 0.0, "%s") - for col, column in enumerate(self.cols_to_show): - if column[colalias] == 'game' and holecards: - s = [x for x in self.columns if x[colalias] == 'hand'][0][colheading] - else: - s = column[colheading] - self.listcols[grid].append(gtk.TreeViewColumn(s)) - view.append_column(self.listcols[grid][col]) - if column[colformat] == '%s': - if column[colxalign] == 0.0: - self.listcols[grid][col].pack_start(textcell, expand=True) - self.listcols[grid][col].add_attribute(textcell, 'text', col) - cellrend = textcell - else: - self.listcols[grid][col].pack_start(textcell50, expand=True) - self.listcols[grid][col].add_attribute(textcell50, 'text', col) - cellrend = textcell50 - self.listcols[grid][col].set_expand(True) - else: - self.listcols[grid][col].pack_start(numcell, expand=True) - self.listcols[grid][col].add_attribute(numcell, 'text', col) - self.listcols[grid][col].set_expand(True) - cellrend = numcell - #self.listcols[grid][col].set_alignment(column[colxalign]) # no effect? - self.listcols[grid][col].set_clickable(True) - self.listcols[grid][col].connect("clicked", self.sortcols, (col,grid)) - if col == 0: - self.listcols[grid][col].set_sort_order(gtk.SORT_DESCENDING) - self.listcols[grid][col].set_sort_indicator(True) - if column[coltype] == 'cash': - self.listcols[grid][col].set_cell_data_func(numcell, self.ledger_style_render_func) - else: - self.listcols[grid][col].set_cell_data_func(cellrend, self.reset_style_render_func) - - rows = len(result) # +1 for title row - - while sqlrow < rows: - treerow = [] - for col,column in enumerate(self.cols_to_show): - if column[colalias] in colnames: - value = result[sqlrow][colnames.index(column[colalias])] - if column[colalias] == 'plposition': - if value == 'B': - value = 'BB' - elif value == 'S': - value = 'SB' - elif value == '0': - value = 'Btn' - else: - if column[colalias] == 'game': - if holecards: - value = Card.twoStartCardString( result[sqlrow][hgametypeid_idx] ) - else: - minbb = result[sqlrow][colnames.index('minbigblind')] - maxbb = result[sqlrow][colnames.index('maxbigblind')] - value = result[sqlrow][colnames.index('limittype')] + ' ' \ - + result[sqlrow][colnames.index('category')].title() + ' ' \ - + result[sqlrow][colnames.index('name')] + ' $' - if 100 * int(minbb/100.0) != minbb: - value += '%.2f' % (minbb/100.0) - else: - value += '%.0f' % (minbb/100.0) - if minbb != maxbb: - if 100 * int(maxbb/100.0) != maxbb: - value += ' - $' + '%.2f' % (maxbb/100.0) - else: - value += ' - $' + '%.0f' % (maxbb/100.0) - else: - continue - if value and value != -999: - treerow.append(column[colformat] % value) - else: - treerow.append(' ') - iter = self.liststore[grid].append(treerow) - #print treerow - sqlrow += 1 - row += 1 - vbox.show_all() - #end def addGrid - - def refineQuery(self, query, flags, playerids, sitenos, limits, type, seats, groups, dates, games): - having = '' - if not flags: - holecards = False - numhands = 0 - else: - holecards = flags[0] - numhands = flags[1] - - if 'allplayers' in groups and groups['allplayers']: - nametest = "(hp.playerId)" - if holecards or groups['posn']: - pname = "'all players'" - # set flag in self.columns to not show player name column - [x for x in self.columns if x[0] == 'pname'][0][1] = False - # can't do this yet (re-write doing more maths in python instead of sql?) - if numhands: - nametest = "(-1)" - else: - pname = "p.name" - # set flag in self.columns to show player name column - [x for x in self.columns if x[0] == 'pname'][0][1] = True - if numhands: - having = ' and count(1) > %d ' % (numhands,) - else: - if playerids: - nametest = str(tuple(playerids)) - nametest = nametest.replace("L", "") - nametest = nametest.replace(",)",")") - else: - nametest = "1 = 2" - pname = "p.name" - # set flag in self.columns to not show player name column - [x for x in self.columns if x[0] == 'pname'][0][1] = False - query = query.replace("", nametest) - query = query.replace("", pname) - query = query.replace("", having) - - gametest = "" - q = [] - for m in self.filters.display.items(): - if m[0] == 'Games' and m[1]: - for n in games: - if games[n]: - q.append(n) - if len(q) > 0: - gametest = str(tuple(q)) - gametest = gametest.replace("L", "") - gametest = gametest.replace(",)",")") - gametest = gametest.replace("u'","'") - gametest = "and gt.category in %s" % gametest - else: - gametest = "and gt.category IS NULL" - query = query.replace("", gametest) - - sitetest = "" - q = [] - for m in self.filters.display.items(): - if m[0] == 'Sites' and m[1]: - for n in sitenos: - q.append(n) - if len(q) > 0: - sitetest = str(tuple(q)) - sitetest = sitetest.replace("L", "") - sitetest = sitetest.replace(",)",")") - sitetest = sitetest.replace("u'","'") - sitetest = "and gt.siteId in %s" % sitetest - else: - sitetest = "and gt.siteId IS NULL" - query = query.replace("", sitetest) - - if seats: - query = query.replace('', 'between ' + str(seats['from']) + ' and ' + str(seats['to'])) - if 'show' in seats and seats['show']: - query = query.replace('', ',h.seats') - query = query.replace('', ',h.seats') - else: - query = query.replace('', '') - query = query.replace('', '') - else: - query = query.replace('', 'between 0 and 100') - query = query.replace('', '') - query = query.replace('', '') - - lims = [int(x) for x in limits if x.isdigit()] - potlims = [int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'pl'] - nolims = [int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'nl'] - bbtest = "and ( (gt.limitType = 'fl' and gt.bigBlind in " - # and ( (limit and bb in()) or (nolimit and bb in ()) ) - if lims: - blindtest = str(tuple(lims)) - blindtest = blindtest.replace("L", "") - blindtest = blindtest.replace(",)",")") - bbtest = bbtest + blindtest + ' ) ' - else: - bbtest = bbtest + '(-1) ) ' - bbtest = bbtest + " or (gt.limitType = 'pl' and gt.bigBlind in " - if potlims: - blindtest = str(tuple(potlims)) - blindtest = blindtest.replace("L", "") - blindtest = blindtest.replace(",)",")") - bbtest = bbtest + blindtest + ' ) ' - else: - bbtest = bbtest + '(-1) ) ' - bbtest = bbtest + " or (gt.limitType = 'nl' and gt.bigBlind in " - if nolims: - blindtest = str(tuple(nolims)) - blindtest = blindtest.replace("L", "") - blindtest = blindtest.replace(",)",")") - bbtest = bbtest + blindtest + ' ) )' - else: - bbtest = bbtest + '(-1) ) )' - if type == 'ring': - bbtest = bbtest + " and gt.type = 'ring' " - elif type == 'tour': - bbtest = " and gt.type = 'tour' " - query = query.replace("", bbtest) - - if holecards: # re-use level variables for hole card query - query = query.replace("", "hp.startcards") - query = query.replace("" - , ",case when floor((hp.startcards-1)/13) >= mod((hp.startcards-1),13) then hp.startcards + 0.1 " - + " else 13*mod((hp.startcards-1),13) + floor((hp.startcards-1)/13) + 1 " - + " end desc ") - else: - query = query.replace("", "") - groupLevels = "show" not in str(limits) - if groupLevels: - query = query.replace("", "p.name") # need to use p.name for sqlite posn stats to work - else: - query = query.replace("", "h.gameTypeId") - - # process self.detailFilters (a list of tuples) - flagtest = '' - #self.detailFilters = [('h.seats', 5, 6)] # for debug - if self.detailFilters: - for f in self.detailFilters: - if len(f) == 3: - # X between Y and Z - flagtest += ' and %s between %s and %s ' % (f[0], str(f[1]), str(f[2])) - query = query.replace("", flagtest) - - # allow for differences in sql cast() function: - if self.db.backend == self.MYSQL_INNODB: - query = query.replace("", 'signed ') - else: - query = query.replace("", '') - - # Filter on dates - query = query.replace("", " between '" + dates[0] + "' and '" + dates[1] + "'") - - # Group by position? - if groups['posn']: - #query = query.replace("", "case hp.position when '0' then 'Btn' else hp.position end") - query = query.replace("", "hp.position") - # set flag in self.columns to show posn column - [x for x in self.columns if x[0] == 'plposition'][0][1] = True - else: - query = query.replace("", "gt.base") - # unset flag in self.columns to hide posn column - [x for x in self.columns if x[0] == 'plposition'][0][1] = False - - #print "query =\n", query - return(query) - #end def refineQuery - - def showDetailFilter(self, widget, data): - detailDialog = gtk.Dialog(title="Detailed Filters", parent=self.main_window - ,flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT - ,buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, - gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)) - - handbox = gtk.VBox(True, 0) - detailDialog.vbox.pack_start(handbox, False, False, 0) - handbox.show() - - label = gtk.Label("Hand Filters:") - handbox.add(label) - label.show() - - betweenFilters = [] - for htest in self.handtests: - hbox = gtk.HBox(False, 0) - handbox.pack_start(hbox, False, False, 0) - hbox.show() - - cb = gtk.CheckButton() - lbl_from = gtk.Label(htest[1]) - lbl_from.set_alignment(xalign=0.0, yalign=0.5) - lbl_tween = gtk.Label('between') - lbl_to = gtk.Label('and') - adj1 = gtk.Adjustment(value=htest[2], lower=0, upper=10, step_incr=1, page_incr=1, page_size=0) - sb1 = gtk.SpinButton(adjustment=adj1, climb_rate=0.0, digits=0) - adj2 = gtk.Adjustment(value=htest[3], lower=2, upper=10, step_incr=1, page_incr=1, page_size=0) - sb2 = gtk.SpinButton(adjustment=adj2, climb_rate=0.0, digits=0) - - for df in [x for x in self.detailFilters if x[0] == htest[0]]: - cb.set_active(True) - - hbox.pack_start(cb, expand=False, padding=3) - hbox.pack_start(lbl_from, expand=True, padding=3) - hbox.pack_start(lbl_tween, expand=False, padding=3) - hbox.pack_start(sb1, False, False, 0) - hbox.pack_start(lbl_to, expand=False, padding=3) - hbox.pack_start(sb2, False, False, 0) - - cb.show() - lbl_from.show() - lbl_tween.show() - sb1.show() - lbl_to.show() - sb2.show() - - htest[4:7] = [cb,sb1,sb2] - - response = detailDialog.run() - - if response == gtk.RESPONSE_ACCEPT: - self.detailFilters = [] - for ht in self.handtests: - if ht[4].get_active(): - self.detailFilters.append( (ht[0], ht[5].get_value_as_int(), ht[6].get_value_as_int()) ) - ht[2],ht[3] = ht[5].get_value_as_int(), ht[6].get_value_as_int() - print "detailFilters =", self.detailFilters - self.refreshStats(None, None) - - detailDialog.destroy() - - - - - diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index 724d0f84..1764c5ea 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -24,7 +24,7 @@ from time import time, strftime import fpdb_import import Database -import Filters +import RingFilters import FpdbSQLQueries class GuiPositionalStats (threading.Thread): @@ -58,7 +58,7 @@ class GuiPositionalStats (threading.Thread): "Button2" : False } - self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display) + self.filters = RingFilters.RingFilters(self.db, self.conf, self.sql, display = filters_display) self.filters.registerButton1Name("Refresh") self.filters.registerButton1Callback(self.refreshStats) diff --git a/pyfpdb/GuiRingPlayerStats.py b/pyfpdb/GuiRingPlayerStats.py index 11e8a1b1..68878606 100644 --- a/pyfpdb/GuiRingPlayerStats.py +++ b/pyfpdb/GuiRingPlayerStats.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -#Copyright 2010 Steffen Schaumburg +#Copyright 2008-2010 Steffen Schaumburg #This program is free software: you can redistribute it and/or modify #it under the terms of the GNU Affero General Public License as published by #the Free Software Foundation, version 3 of the License. @@ -15,22 +15,666 @@ #along with this program. If not, see . #In the "official" distribution you can find the license in agpl-3.0.txt. -#import traceback -#import threading -#import pygtk -#pygtk.require('2.0') -#import gtk -#import os -#import sys -#from time import time, strftime +import traceback +import threading +import pygtk +pygtk.require('2.0') +import gtk +import os +import sys +from time import time, strftime -#import Card -#import fpdb_import -#import Database +import Card +import fpdb_import +import Database import RingFilters -import GuiPlayerStats -#import Charset +import Charset + +colalias,colshow,colheading,colxalign,colformat,coltype = 0,1,2,3,4,5 +ranks = {'x':0, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9, 'T':10, 'J':11, 'Q':12, 'K':13, 'A':14} + +class GuiRingPlayerStats (threading.Thread): + + def __init__(self, config, querylist, mainwin, debug=True): + self.debug = debug + self.conf = config + self.main_window = mainwin + self.sql = querylist + + self.liststore = [] # gtk.ListStore[] stores the contents of the grids + self.listcols = [] # gtk.TreeViewColumn[][] stores the columns in the grids + + self.MYSQL_INNODB = 2 + self.PGSQL = 3 + self.SQLITE = 4 + + # create new db connection to avoid conflicts with other threads + self.db = Database.Database(self.conf, sql=self.sql) + self.cursor = self.db.cursor + + settings = {} + settings.update(self.conf.get_db_parameters()) + settings.update(self.conf.get_tv_parameters()) + settings.update(self.conf.get_import_parameters()) + settings.update(self.conf.get_default_paths()) + + # text used on screen stored here so that it can be configured + self.filterText = {'handhead':'Hand Breakdown for all levels listed above' + } + + filters_display = { "Heroes" : True, + "Sites" : True, + "Games" : True, + "Limits" : True, + "LimitSep" : True, + "LimitType" : True, + "Type" : True, + "Seats" : True, + "SeatSep" : True, + "Dates" : True, + "Groups" : True, + "GroupsAll" : True, + "Button1" : True, + "Button2" : True + } + + self.filters = RingFilters.RingFilters(self.db, self.conf, self.sql, display = filters_display) + self.filters.registerButton1Name("_Filters") + self.filters.registerButton1Callback(self.showDetailFilter) + self.filters.registerButton2Name("_Refresh Stats") + self.filters.registerButton2Callback(self.refreshStats) + + # ToDo: store in config + # ToDo: create popup to adjust column config + # columns to display, keys match column name returned by sql, values in tuple are: + # is column displayed, column heading, xalignment, formatting, celltype + self.columns = [ ["game", True, "Game", 0.0, "%s", "str"] + , ["hand", False, "Hand", 0.0, "%s", "str"] # true not allowed for this line + , ["plposition", False, "Posn", 1.0, "%s", "str"] # true not allowed for this line (set in code) + , ["pname", False, "Name", 0.0, "%s", "str"] # true not allowed for this line (set in code) + , ["n", True, "Hds", 1.0, "%1.0f", "str"] + , ["avgseats", False, "Seats", 1.0, "%3.1f", "str"] + , ["vpip", True, "VPIP", 1.0, "%3.1f", "str"] + , ["pfr", True, "PFR", 1.0, "%3.1f", "str"] + , ["pf3", True, "PF3", 1.0, "%3.1f", "str"] + , ["aggfac", True, "AggFac", 1.0, "%2.2f", "str"] + , ["aggfrq", True, "AggFreq", 1.0, "%3.1f", "str"] + , ["conbet", True, "ContBet", 1.0, "%3.1f", "str"] + , ["steals", True, "Steals", 1.0, "%3.1f", "str"] + , ["saw_f", True, "Saw_F", 1.0, "%3.1f", "str"] + , ["sawsd", True, "SawSD", 1.0, "%3.1f", "str"] + , ["wtsdwsf", True, "WtSDwsF", 1.0, "%3.1f", "str"] + , ["wmsd", True, "W$SD", 1.0, "%3.1f", "str"] + , ["flafq", True, "FlAFq", 1.0, "%3.1f", "str"] + , ["tuafq", True, "TuAFq", 1.0, "%3.1f", "str"] + , ["rvafq", True, "RvAFq", 1.0, "%3.1f", "str"] + , ["pofafq", False, "PoFAFq", 1.0, "%3.1f", "str"] + , ["net", True, "Net($)", 1.0, "%6.2f", "cash"] + , ["bbper100", True, "bb/100", 1.0, "%4.2f", "str"] + , ["rake", True, "Rake($)", 1.0, "%6.2f", "cash"] + , ["bb100xr", True, "bbxr/100", 1.0, "%4.2f", "str"] + , ["variance", True, "Variance", 1.0, "%5.2f", "str"] + ] + + # Detail filters: This holds the data used in the popup window, extra values are + # added at the end of these lists during processing + # sql test, screen description, min, max + self.handtests = [ # already in filter class : ['h.seats', 'Number of Players', 2, 10] + ['h.maxSeats', 'Size of Table', 2, 10] + ,['h.playersVpi', 'Players who VPI', 0, 10] + ,['h.playersAtStreet1', 'Players at Flop', 0, 10] + ,['h.playersAtStreet2', 'Players at Turn', 0, 10] + ,['h.playersAtStreet3', 'Players at River', 0, 10] + ,['h.playersAtStreet4', 'Players at Street7', 0, 10] + ,['h.playersAtShowdown', 'Players at Showdown', 0, 10] + ,['h.street0Raises', 'Bets to See Flop', 0, 5] + ,['h.street1Raises', 'Bets to See Turn', 0, 5] + ,['h.street2Raises', 'Bets to See River', 0, 5] + ,['h.street3Raises', 'Bets to See Street7', 0, 5] + ,['h.street4Raises', 'Bets to See Showdown', 0, 5] + ] + + self.stats_frame = None + self.stats_vbox = None + self.detailFilters = [] # the data used to enhance the sql select + + #self.main_hbox = gtk.HBox(False, 0) + #self.main_hbox.show() + self.main_hbox = gtk.HPaned() + + self.stats_frame = gtk.Frame() + self.stats_frame.show() + + self.stats_vbox = gtk.VPaned() + self.stats_vbox.show() + self.stats_frame.add(self.stats_vbox) + # self.fillStatsFrame(self.stats_vbox) + + #self.main_hbox.pack_start(self.filters.get_vbox()) + #self.main_hbox.pack_start(self.stats_frame, expand=True, fill=True) + self.main_hbox.pack1(self.filters.get_vbox()) + self.main_hbox.pack2(self.stats_frame) + self.main_hbox.show() + + # make sure Hand column is not displayed + [x for x in self.columns if x[0] == 'hand'][0][1] = False + self.last_pos = -1 + + + def get_vbox(self): + """returns the vbox of this thread""" + return self.main_hbox + #end def get_vbox + + def refreshStats(self, widget, data): + self.last_pos = self.stats_vbox.get_position() + try: self.stats_vbox.destroy() + except AttributeError: pass + self.liststore = [] + self.listcols = [] + #self.stats_vbox = gtk.VBox(False, 0) + self.stats_vbox = gtk.VPaned() + self.stats_vbox.show() + self.stats_frame.add(self.stats_vbox) + self.fillStatsFrame(self.stats_vbox) + if self.last_pos > 0: + self.stats_vbox.set_position(self.last_pos) + #end def refreshStats + + def fillStatsFrame(self, vbox): + sites = self.filters.getSites() + heroes = self.filters.getHeroes() + siteids = self.filters.getSiteIds() + limits = self.filters.getLimits() + type = self.filters.getType() + seats = self.filters.getSeats() + groups = self.filters.getGroups() + dates = self.filters.getDates() + games = self.filters.getGames() + sitenos = [] + playerids = [] + + # Which sites are selected? + for site in sites: + if sites[site] == True: + sitenos.append(siteids[site]) + _hname = Charset.to_utf8(heroes[site]) + result = self.db.get_player_id(self.conf, site, _hname) + if result is not None: + playerids.append(int(result)) + + if not sitenos: + #Should probably pop up here. + print "No sites selected - defaulting to PokerStars" + sitenos = [2] + if not playerids: + print "No player ids found" + return + if not limits: + print "No limits found" + return + + self.createStatsTable(vbox, playerids, sitenos, limits, type, seats, groups, dates, games) + #end def fillStatsFrame + + def createStatsTable(self, vbox, playerids, sitenos, limits, type, seats, groups, dates, games): + startTime = time() + show_detail = True + + # Scrolled window for summary table + swin = gtk.ScrolledWindow(hadjustment=None, vadjustment=None) + swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + swin.show() + vbox.pack1(swin) + + # Display summary table at top of page + # 3rd parameter passes extra flags, currently includes: + # holecards - whether to display card breakdown (True/False) + # numhands - min number hands required when displaying all players + # gridnum - index for grid data structures + flags = [False, self.filters.getNumHands(), 0] + self.addGrid(swin, 'playerDetailedStats', flags, playerids + ,sitenos, limits, type, seats, groups, dates, games) + + if 'allplayers' in groups and groups['allplayers']: + # can't currently do this combination so skip detailed table + show_detail = False + + if show_detail: + # Separator + vbox2 = gtk.VBox(False, 0) + heading = gtk.Label(self.filterText['handhead']) + heading.show() + vbox2.pack_start(heading, expand=False, padding=3) + + # Scrolled window for detailed table (display by hand) + swin = gtk.ScrolledWindow(hadjustment=None, vadjustment=None) + swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + swin.show() + vbox2.pack_start(swin, expand=True, padding=3) + vbox.pack2(vbox2) + vbox2.show() + + # Detailed table + flags[0] = True + flags[2] = 1 + self.addGrid(swin, 'playerDetailedStats', flags, playerids + ,sitenos, limits, type, seats, groups, dates, games) + + self.db.rollback() + print "Stats page displayed in %4.2f seconds" % (time() - startTime) + #end def createStatsTable + + def reset_style_render_func(self, treeviewcolumn, cell, model, iter): + cell.set_property('foreground', 'black') + #end def reset_style_render_func + + def ledger_style_render_func(self, tvcol, cell, model, iter): + str = cell.get_property('text') + if '-' in str: + str = str.replace("-", "") + str = "(%s)" %(str) + cell.set_property('text', str) + cell.set_property('foreground', 'red') + else: + cell.set_property('foreground', 'darkgreen') + + return + + def sortnums(self, model, iter1, iter2, nums): + try: + ret = 0 + (n, grid) = nums + a = self.liststore[grid].get_value(iter1, n) + b = self.liststore[grid].get_value(iter2, n) + if 'f' in self.cols_to_show[n][4]: + try: a = float(a) + except: a = 0.0 + try: b = float(b) + except: b = 0.0 + if n == 0 and grid == 1: #make sure it only works on the starting hands + a1,a2,a3 = ranks[a[0]], ranks[a[1]], (a+'o')[2] + b1,b2,b3 = ranks[b[0]], ranks[b[1]], (b+'o')[2] + if a1 > b1 or ( a1 == b1 and (a2 > b2 or (a2 == b2 and a3 > b3) ) ): + ret = 1 + else: + ret = -1 + else: + if a < b: + ret = -1 + elif a == b: + ret = 0 + else: + ret = 1 + #print "n =", n, "iter1[n] =", self.liststore[grid].get_value(iter1,n), "iter2[n] =", self.liststore[grid].get_value(iter2,n), "ret =", ret + except: + err = traceback.extract_tb(sys.exc_info()[2]) + print "***sortnums error: " + str(sys.exc_info()[1]) + print "\n".join( [e[0]+':'+str(e[1])+" "+e[2] for e in err] ) + + return(ret) + + def sortcols(self, col, nums): + try: + #This doesn't actually work yet - clicking heading in top section sorts bottom section :-( + (n, grid) = nums + if not col.get_sort_indicator() or col.get_sort_order() == gtk.SORT_ASCENDING: + col.set_sort_order(gtk.SORT_DESCENDING) + else: + col.set_sort_order(gtk.SORT_ASCENDING) + self.liststore[grid].set_sort_column_id(n, col.get_sort_order()) + self.liststore[grid].set_sort_func(n, self.sortnums, (n,grid)) + for i in xrange(len(self.listcols[grid])): + self.listcols[grid][i].set_sort_indicator(False) + self.listcols[grid][n].set_sort_indicator(True) + # use this listcols[col].set_sort_indicator(True) + # to turn indicator off for other cols + except: + err = traceback.extract_tb(sys.exc_info()[2]) + print "***sortcols error: " + str(sys.exc_info()[1]) + print "\n".join( [e[0]+':'+str(e[1])+" "+e[2] for e in err] ) + #end def sortcols + + def addGrid(self, vbox, query, flags, playerids, sitenos, limits, type, seats, groups, dates, games): + counter = 0 + row = 0 + sqlrow = 0 + if not flags: holecards,grid = False,0 + else: holecards,grid = flags[0],flags[2] + + tmp = self.sql.query[query] + tmp = self.refineQuery(tmp, flags, playerids, sitenos, limits, type, seats, groups, dates, games) + self.cursor.execute(tmp) + result = self.cursor.fetchall() + colnames = [desc[0].lower() for desc in self.cursor.description] + + # pre-fetch some constant values: + self.cols_to_show = [x for x in self.columns if x[colshow]] + hgametypeid_idx = colnames.index('hgametypeid') + + assert len(self.liststore) == grid, "len(self.liststore)="+str(len(self.liststore))+" grid-1="+str(grid) + self.liststore.append( gtk.ListStore(*([str] * len(self.cols_to_show))) ) + view = gtk.TreeView(model=self.liststore[grid]) + view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH) + #vbox.pack_start(view, expand=False, padding=3) + vbox.add(view) + textcell = gtk.CellRendererText() + textcell50 = gtk.CellRendererText() + textcell50.set_property('xalign', 0.5) + numcell = gtk.CellRendererText() + numcell.set_property('xalign', 1.0) + assert len(self.listcols) == grid + self.listcols.append( [] ) + + # Create header row eg column: ("game", True, "Game", 0.0, "%s") + for col, column in enumerate(self.cols_to_show): + if column[colalias] == 'game' and holecards: + s = [x for x in self.columns if x[colalias] == 'hand'][0][colheading] + else: + s = column[colheading] + self.listcols[grid].append(gtk.TreeViewColumn(s)) + view.append_column(self.listcols[grid][col]) + if column[colformat] == '%s': + if column[colxalign] == 0.0: + self.listcols[grid][col].pack_start(textcell, expand=True) + self.listcols[grid][col].add_attribute(textcell, 'text', col) + cellrend = textcell + else: + self.listcols[grid][col].pack_start(textcell50, expand=True) + self.listcols[grid][col].add_attribute(textcell50, 'text', col) + cellrend = textcell50 + self.listcols[grid][col].set_expand(True) + else: + self.listcols[grid][col].pack_start(numcell, expand=True) + self.listcols[grid][col].add_attribute(numcell, 'text', col) + self.listcols[grid][col].set_expand(True) + cellrend = numcell + #self.listcols[grid][col].set_alignment(column[colxalign]) # no effect? + self.listcols[grid][col].set_clickable(True) + self.listcols[grid][col].connect("clicked", self.sortcols, (col,grid)) + if col == 0: + self.listcols[grid][col].set_sort_order(gtk.SORT_DESCENDING) + self.listcols[grid][col].set_sort_indicator(True) + if column[coltype] == 'cash': + self.listcols[grid][col].set_cell_data_func(numcell, self.ledger_style_render_func) + else: + self.listcols[grid][col].set_cell_data_func(cellrend, self.reset_style_render_func) + + rows = len(result) # +1 for title row + + while sqlrow < rows: + treerow = [] + for col,column in enumerate(self.cols_to_show): + if column[colalias] in colnames: + value = result[sqlrow][colnames.index(column[colalias])] + if column[colalias] == 'plposition': + if value == 'B': + value = 'BB' + elif value == 'S': + value = 'SB' + elif value == '0': + value = 'Btn' + else: + if column[colalias] == 'game': + if holecards: + value = Card.twoStartCardString( result[sqlrow][hgametypeid_idx] ) + else: + minbb = result[sqlrow][colnames.index('minbigblind')] + maxbb = result[sqlrow][colnames.index('maxbigblind')] + value = result[sqlrow][colnames.index('limittype')] + ' ' \ + + result[sqlrow][colnames.index('category')].title() + ' ' \ + + result[sqlrow][colnames.index('name')] + ' $' + if 100 * int(minbb/100.0) != minbb: + value += '%.2f' % (minbb/100.0) + else: + value += '%.0f' % (minbb/100.0) + if minbb != maxbb: + if 100 * int(maxbb/100.0) != maxbb: + value += ' - $' + '%.2f' % (maxbb/100.0) + else: + value += ' - $' + '%.0f' % (maxbb/100.0) + else: + continue + if value and value != -999: + treerow.append(column[colformat] % value) + else: + treerow.append(' ') + iter = self.liststore[grid].append(treerow) + #print treerow + sqlrow += 1 + row += 1 + vbox.show_all() + #end def addGrid + + def refineQuery(self, query, flags, playerids, sitenos, limits, type, seats, groups, dates, games): + having = '' + if not flags: + holecards = False + numhands = 0 + else: + holecards = flags[0] + numhands = flags[1] + + if 'allplayers' in groups and groups['allplayers']: + nametest = "(hp.playerId)" + if holecards or groups['posn']: + pname = "'all players'" + # set flag in self.columns to not show player name column + [x for x in self.columns if x[0] == 'pname'][0][1] = False + # can't do this yet (re-write doing more maths in python instead of sql?) + if numhands: + nametest = "(-1)" + else: + pname = "p.name" + # set flag in self.columns to show player name column + [x for x in self.columns if x[0] == 'pname'][0][1] = True + if numhands: + having = ' and count(1) > %d ' % (numhands,) + else: + if playerids: + nametest = str(tuple(playerids)) + nametest = nametest.replace("L", "") + nametest = nametest.replace(",)",")") + else: + nametest = "1 = 2" + pname = "p.name" + # set flag in self.columns to not show player name column + [x for x in self.columns if x[0] == 'pname'][0][1] = False + query = query.replace("", nametest) + query = query.replace("", pname) + query = query.replace("", having) + + gametest = "" + q = [] + for m in self.filters.display.items(): + if m[0] == 'Games' and m[1]: + for n in games: + if games[n]: + q.append(n) + if len(q) > 0: + gametest = str(tuple(q)) + gametest = gametest.replace("L", "") + gametest = gametest.replace(",)",")") + gametest = gametest.replace("u'","'") + gametest = "and gt.category in %s" % gametest + else: + gametest = "and gt.category IS NULL" + query = query.replace("", gametest) + + sitetest = "" + q = [] + for m in self.filters.display.items(): + if m[0] == 'Sites' and m[1]: + for n in sitenos: + q.append(n) + if len(q) > 0: + sitetest = str(tuple(q)) + sitetest = sitetest.replace("L", "") + sitetest = sitetest.replace(",)",")") + sitetest = sitetest.replace("u'","'") + sitetest = "and gt.siteId in %s" % sitetest + else: + sitetest = "and gt.siteId IS NULL" + query = query.replace("", sitetest) + + if seats: + query = query.replace('', 'between ' + str(seats['from']) + ' and ' + str(seats['to'])) + if 'show' in seats and seats['show']: + query = query.replace('', ',h.seats') + query = query.replace('', ',h.seats') + else: + query = query.replace('', '') + query = query.replace('', '') + else: + query = query.replace('', 'between 0 and 100') + query = query.replace('', '') + query = query.replace('', '') + + lims = [int(x) for x in limits if x.isdigit()] + potlims = [int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'pl'] + nolims = [int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'nl'] + bbtest = "and ( (gt.limitType = 'fl' and gt.bigBlind in " + # and ( (limit and bb in()) or (nolimit and bb in ()) ) + if lims: + blindtest = str(tuple(lims)) + blindtest = blindtest.replace("L", "") + blindtest = blindtest.replace(",)",")") + bbtest = bbtest + blindtest + ' ) ' + else: + bbtest = bbtest + '(-1) ) ' + bbtest = bbtest + " or (gt.limitType = 'pl' and gt.bigBlind in " + if potlims: + blindtest = str(tuple(potlims)) + blindtest = blindtest.replace("L", "") + blindtest = blindtest.replace(",)",")") + bbtest = bbtest + blindtest + ' ) ' + else: + bbtest = bbtest + '(-1) ) ' + bbtest = bbtest + " or (gt.limitType = 'nl' and gt.bigBlind in " + if nolims: + blindtest = str(tuple(nolims)) + blindtest = blindtest.replace("L", "") + blindtest = blindtest.replace(",)",")") + bbtest = bbtest + blindtest + ' ) )' + else: + bbtest = bbtest + '(-1) ) )' + if type == 'ring': + bbtest = bbtest + " and gt.type = 'ring' " + elif type == 'tour': + bbtest = " and gt.type = 'tour' " + query = query.replace("", bbtest) + + if holecards: # re-use level variables for hole card query + query = query.replace("", "hp.startcards") + query = query.replace("" + , ",case when floor((hp.startcards-1)/13) >= mod((hp.startcards-1),13) then hp.startcards + 0.1 " + + " else 13*mod((hp.startcards-1),13) + floor((hp.startcards-1)/13) + 1 " + + " end desc ") + else: + query = query.replace("", "") + groupLevels = "show" not in str(limits) + if groupLevels: + query = query.replace("", "p.name") # need to use p.name for sqlite posn stats to work + else: + query = query.replace("", "h.gameTypeId") + + # process self.detailFilters (a list of tuples) + flagtest = '' + #self.detailFilters = [('h.seats', 5, 6)] # for debug + if self.detailFilters: + for f in self.detailFilters: + if len(f) == 3: + # X between Y and Z + flagtest += ' and %s between %s and %s ' % (f[0], str(f[1]), str(f[2])) + query = query.replace("", flagtest) + + # allow for differences in sql cast() function: + if self.db.backend == self.MYSQL_INNODB: + query = query.replace("", 'signed ') + else: + query = query.replace("", '') + + # Filter on dates + query = query.replace("", " between '" + dates[0] + "' and '" + dates[1] + "'") + + # Group by position? + if groups['posn']: + #query = query.replace("", "case hp.position when '0' then 'Btn' else hp.position end") + query = query.replace("", "hp.position") + # set flag in self.columns to show posn column + [x for x in self.columns if x[0] == 'plposition'][0][1] = True + else: + query = query.replace("", "gt.base") + # unset flag in self.columns to hide posn column + [x for x in self.columns if x[0] == 'plposition'][0][1] = False + + #print "query =\n", query + return(query) + #end def refineQuery + + def showDetailFilter(self, widget, data): + detailDialog = gtk.Dialog(title="Detailed Filters", parent=self.main_window + ,flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT + ,buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, + gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)) + + handbox = gtk.VBox(True, 0) + detailDialog.vbox.pack_start(handbox, False, False, 0) + handbox.show() + + label = gtk.Label("Hand Filters:") + handbox.add(label) + label.show() + + betweenFilters = [] + for htest in self.handtests: + hbox = gtk.HBox(False, 0) + handbox.pack_start(hbox, False, False, 0) + hbox.show() + + cb = gtk.CheckButton() + lbl_from = gtk.Label(htest[1]) + lbl_from.set_alignment(xalign=0.0, yalign=0.5) + lbl_tween = gtk.Label('between') + lbl_to = gtk.Label('and') + adj1 = gtk.Adjustment(value=htest[2], lower=0, upper=10, step_incr=1, page_incr=1, page_size=0) + sb1 = gtk.SpinButton(adjustment=adj1, climb_rate=0.0, digits=0) + adj2 = gtk.Adjustment(value=htest[3], lower=2, upper=10, step_incr=1, page_incr=1, page_size=0) + sb2 = gtk.SpinButton(adjustment=adj2, climb_rate=0.0, digits=0) + + for df in [x for x in self.detailFilters if x[0] == htest[0]]: + cb.set_active(True) + + hbox.pack_start(cb, expand=False, padding=3) + hbox.pack_start(lbl_from, expand=True, padding=3) + hbox.pack_start(lbl_tween, expand=False, padding=3) + hbox.pack_start(sb1, False, False, 0) + hbox.pack_start(lbl_to, expand=False, padding=3) + hbox.pack_start(sb2, False, False, 0) + + cb.show() + lbl_from.show() + lbl_tween.show() + sb1.show() + lbl_to.show() + sb2.show() + + htest[4:7] = [cb,sb1,sb2] + + response = detailDialog.run() + + if response == gtk.RESPONSE_ACCEPT: + self.detailFilters = [] + for ht in self.handtests: + if ht[4].get_active(): + self.detailFilters.append( (ht[0], ht[5].get_value_as_int(), ht[6].get_value_as_int()) ) + ht[2],ht[3] = ht[5].get_value_as_int(), ht[6].get_value_as_int() + print "detailFilters =", self.detailFilters + self.refreshStats(None, None) + + detailDialog.destroy() + + + + -class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats): - pass -#end class GuiRingPlayerStats \ No newline at end of file diff --git a/pyfpdb/GuiSessionViewer.py b/pyfpdb/GuiSessionViewer.py index 05249051..38cd7b74 100755 --- a/pyfpdb/GuiSessionViewer.py +++ b/pyfpdb/GuiSessionViewer.py @@ -45,7 +45,7 @@ except ImportError, inst: import Card import fpdb_import import Database -import Filters +import RingFilters import FpdbSQLQueries import Charset @@ -96,7 +96,7 @@ class GuiSessionViewer (threading.Thread): "Button2" : False } - self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display) + self.filters = RingFilters.RingFilters(self.db, self.conf, self.sql, display = filters_display) self.filters.registerButton1Name("_Refresh") self.filters.registerButton1Callback(self.refreshStats) diff --git a/pyfpdb/RingFilters.py b/pyfpdb/RingFilters.py index 4780b131..44fc790a 100644 --- a/pyfpdb/RingFilters.py +++ b/pyfpdb/RingFilters.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -#Copyright 2010 Steffen Schaumburg +#Copyright 2008-2010 Steffen Schaumburg #This program is free software: you can redistribute it and/or modify #it under the terms of the GNU Affero General Public License as published by #the Free Software Foundation, version 3 of the License. @@ -15,28 +15,934 @@ #along with this program. If not, see . #In the "official" distribution you can find the license in agpl-3.0.txt. -#import threading -#import pygtk -#pygtk.require('2.0') -#import gtk -#import os -#import sys -#from optparse import OptionParser -#from time import * -#import gobject +import threading +import pygtk +pygtk.require('2.0') +import gtk +import os +import sys +from optparse import OptionParser +from time import * +import gobject #import pokereval -#import logging +import logging # logging has been set up in fpdb.py or HUD_main.py, use their settings: -#log = logging.getLogger("filter") +log = logging.getLogger("filter") -#import Configuration -#import Database -#import SQL -#import Charset -import Filters +import Configuration +import Database +import SQL +import Charset -class RingFilters(Filters.Filters): - pass -#end class RingFilters \ No newline at end of file + +class RingFilters(threading.Thread): + def __init__(self, db, config, qdict, display = {}, debug=True): + # config and qdict are now redundant + self.debug = debug + self.db = db + self.cursor = db.cursor + self.sql = db.sql + self.conf = db.config + self.display = display + + # text used on screen stored here so that it can be configured + self.filterText = {'limitsall':'All', 'limitsnone':'None', 'limitsshow':'Show _Limits' + ,'seatsbetween':'Between:', 'seatsand':'And:', 'seatsshow':'Show Number of _Players' + ,'playerstitle':'Hero:', 'sitestitle':'Sites:', 'gamestitle':'Games:' + ,'limitstitle':'Limits:', 'seatstitle':'Number of Players:' + ,'groupstitle':'Grouping:', 'posnshow':'Show Position Stats:' + ,'datestitle':'Date:' + ,'groupsall':'All Players' + ,'limitsFL':'FL', 'limitsNL':'NL', 'limitsPL':'PL', 'ring':'Ring', 'tour':'Tourney' + } + + gen = self.conf.get_general_params() + self.day_start = 0 + if 'day_start' in gen: + self.day_start = float(gen['day_start']) + + # Outer Packing box + self.mainVBox = gtk.VBox(False, 0) + + self.label = {} + self.callback = {} + + self.make_filter() + + def make_filter(self): + self.sites = {} + self.games = {} + self.limits = {} + self.seats = {} + self.groups = {} + self.siteid = {} + self.heroes = {} + self.boxes = {} + + for site in self.conf.get_supported_sites(): + #Get db site id for filtering later + self.cursor.execute(self.sql.query['getSiteId'], (site,)) + result = self.db.cursor.fetchall() + if len(result) == 1: + self.siteid[site] = result[0][0] + else: + print "Either 0 or more than one site matched (%s) - EEK" % site + + # For use in date ranges. + self.start_date = gtk.Entry(max=12) + self.end_date = gtk.Entry(max=12) + self.start_date.set_property('editable', False) + self.end_date.set_property('editable', False) + + # For use in groups etc + self.sbGroups = {} + self.numHands = 0 + + playerFrame = gtk.Frame() + playerFrame.set_label_align(0.0, 0.0) + vbox = gtk.VBox(False, 0) + + self.fillPlayerFrame(vbox, self.display) + playerFrame.add(vbox) + + sitesFrame = gtk.Frame() + sitesFrame.set_label_align(0.0, 0.0) + vbox = gtk.VBox(False, 0) + + self.fillSitesFrame(vbox) + sitesFrame.add(vbox) + + # Game types + gamesFrame = gtk.Frame() + gamesFrame.set_label_align(0.0, 0.0) + gamesFrame.show() + vbox = gtk.VBox(False, 0) + + self.fillGamesFrame(vbox) + gamesFrame.add(vbox) + + # Limits + limitsFrame = gtk.Frame() + limitsFrame.show() + vbox = gtk.VBox(False, 0) + self.cbLimits = {} + self.cbNoLimits = None + self.cbAllLimits = None + self.cbFL = None + self.cbNL = None + self.cbPL = None + self.rb = {} # radio buttons for ring/tour + self.type = None # ring/tour + self.types = {} # list of all ring/tour values + + self.fillLimitsFrame(vbox, self.display) + limitsFrame.add(vbox) + + # Seats + seatsFrame = gtk.Frame() + seatsFrame.show() + vbox = gtk.VBox(False, 0) + self.sbSeats = {} + + self.fillSeatsFrame(vbox, self.display) + seatsFrame.add(vbox) + + # Groups + groupsFrame = gtk.Frame() + groupsFrame.show() + vbox = gtk.VBox(False, 0) + + self.fillGroupsFrame(vbox, self.display) + groupsFrame.add(vbox) + + # Date + dateFrame = gtk.Frame() + dateFrame.set_label_align(0.0, 0.0) + dateFrame.show() + vbox = gtk.VBox(False, 0) + + self.fillDateFrame(vbox) + dateFrame.add(vbox) + + # Buttons + self.Button1=gtk.Button("Unnamed 1") + self.Button1.set_sensitive(False) + + self.Button2=gtk.Button("Unnamed 2") + self.Button2.set_sensitive(False) + + self.mainVBox.add(playerFrame) + self.mainVBox.add(sitesFrame) + self.mainVBox.add(gamesFrame) + self.mainVBox.add(limitsFrame) + self.mainVBox.add(seatsFrame) + self.mainVBox.add(groupsFrame) + self.mainVBox.add(dateFrame) + self.mainVBox.add(self.Button1) + self.mainVBox.add(self.Button2) + + self.mainVBox.show_all() + + # Should do this cleaner + if "Heroes" not in self.display or self.display["Heroes"] == False: + playerFrame.hide() + if "Sites" not in self.display or self.display["Sites"] == False: + sitesFrame.hide() + if "Games" not in self.display or self.display["Games"] == False: + gamesFrame.hide() + if "Limits" not in self.display or self.display["Limits"] == False: + limitsFrame.hide() + if "Seats" not in self.display or self.display["Seats"] == False: + seatsFrame.hide() + if "Groups" not in self.display or self.display["Groups"] == False: + groupsFrame.hide() + if "Dates" not in self.display or self.display["Dates"] == False: + dateFrame.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: + self.Button2.hide() + + if 'button1' in self.label and self.label['button1']: + self.Button1.set_label( self.label['button1'] ) + if 'button2' in self.label and self.label['button2']: + self.Button2.set_label( self.label['button2'] ) + if 'button1' in self.callback and self.callback['button1']: + self.Button1.connect("clicked", self.callback['button1'], "clicked") + self.Button1.set_sensitive(True) + if 'button2' in self.callback and self.callback['button2']: + self.Button2.connect("clicked", self.callback['button2'], "clicked") + self.Button2.set_sensitive(True) + + # make sure any locks on db are released: + self.db.rollback() + + def get_vbox(self): + """returns the vbox of this thread""" + return self.mainVBox + #end def get_vbox + + def getNumHands(self): + return self.numHands + #end def getNumHands + + def getSites(self): + return self.sites + #end def getSites + + def getGames(self): + return self.games + + def getSiteIds(self): + return self.siteid + #end def getSiteIds + + def getHeroes(self): + return self.heroes + #end def getHeroes + + def getLimits(self): + ltuple = [] + for l in self.limits: + if self.limits[l] == True: + ltuple.append(l) + return ltuple + + def getType(self): + return(self.type) + + def getSeats(self): + if 'from' in self.sbSeats: + self.seats['from'] = self.sbSeats['from'].get_value_as_int() + if 'to' in self.sbSeats: + self.seats['to'] = self.sbSeats['to'].get_value_as_int() + return self.seats + #end def getSeats + + def getGroups(self): + return self.groups + + def getDates(self): + return self.__get_dates() + #end def getDates + + def registerButton1Name(self, title): + self.Button1.set_label(title) + self.label['button1'] = title + + def registerButton1Callback(self, callback): + self.Button1.connect("clicked", callback, "clicked") + self.Button1.set_sensitive(True) + self.callback['button1'] = callback + + def registerButton2Name(self, title): + self.Button2.set_label(title) + self.label['button2'] = title + #end def registerButton2Name + + def registerButton2Callback(self, callback): + self.Button2.connect("clicked", callback, "clicked") + self.Button2.set_sensitive(True) + self.callback['button2'] = callback + #end def registerButton2Callback + + def cardCallback(self, widget, data=None): + log.debug( "%s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()]) ) + + def createPlayerLine(self, hbox, site, player): + log.debug('add:"%s"' % player) + label = gtk.Label(site +" id:") + hbox.pack_start(label, False, False, 3) + + pname = gtk.Entry() + pname.set_text(player) + pname.set_width_chars(20) + hbox.pack_start(pname, False, True, 0) + pname.connect("changed", self.__set_hero_name, site) + + # Added EntryCompletion but maybe comboBoxEntry is more flexible? (e.g. multiple choices) + completion = gtk.EntryCompletion() + pname.set_completion(completion) + liststore = gtk.ListStore(gobject.TYPE_STRING) + completion.set_model(liststore) + completion.set_text_column(0) + names = self.db.get_player_names(self.conf, self.siteid[site]) # (config=self.conf, site_id=None, like_player_name="%") + for n in names: # list of single-element "tuples" + _n = Charset.to_gui(n[0]) + _nt = (_n, ) + liststore.append(_nt) + + self.__set_hero_name(pname, site) + + def __set_hero_name(self, w, site): + _name = w.get_text() + # get_text() returns a str but we want internal variables to be unicode: + _guiname = unicode(_name) + self.heroes[site] = _guiname + #log.debug("setting heroes[%s]: %s"%(site, self.heroes[site])) + #end def __set_hero_name + + def __set_num_hands(self, w, val): + try: + self.numHands = int(w.get_text()) + except: + self.numHands = 0 + #log.debug("setting numHands:", self.numHands) + #end def __set_num_hands + + def createSiteLine(self, hbox, site): + cb = gtk.CheckButton(site) + cb.connect('clicked', self.__set_site_select, site) + cb.set_active(True) + hbox.pack_start(cb, False, False, 0) + + def createGameLine(self, hbox, game): + cb = gtk.CheckButton(game) + cb.connect('clicked', self.__set_game_select, game) + hbox.pack_start(cb, False, False, 0) + cb.set_active(True) + + def createLimitLine(self, hbox, limit, ltext): + cb = gtk.CheckButton(str(ltext)) + cb.connect('clicked', self.__set_limit_select, limit) + hbox.pack_start(cb, False, False, 0) + if limit != "none": + cb.set_active(True) + return(cb) + + def __set_site_select(self, w, site): + #print w.get_active() + self.sites[site] = w.get_active() + log.debug("self.sites[%s] set to %s" %(site, self.sites[site])) + + def __set_game_select(self, w, game): + #print w.get_active() + self.games[game] = w.get_active() + log.debug("self.games[%s] set to %s" %(game, self.games[game])) + #end def __set_game_select + + def __set_limit_select(self, w, limit): + #print w.get_active() + self.limits[limit] = w.get_active() + log.debug("self.limit[%s] set to %s" %(limit, self.limits[limit])) + if limit.isdigit() or (len(limit) > 2 and (limit[-2:] == 'nl' or limit[-2:] == 'fl' or limit[-2:] == 'pl')): + if self.limits[limit]: + if self.cbNoLimits is not None: + self.cbNoLimits.set_active(False) + else: + if self.cbAllLimits is not None: + self.cbAllLimits.set_active(False) + if not self.limits[limit]: + if limit.isdigit(): + if self.cbFL is not None: + self.cbFL.set_active(False) + elif (len(limit) > 2 and (limit[-2:] == 'nl')): + if self.cbNL is not None: + self.cbNL.set_active(False) + else: + if self.cbPL is not None: + self.cbPL.set_active(False) + elif limit == "all": + if self.limits[limit]: + #for cb in self.cbLimits.values(): + # cb.set_active(True) + if self.cbFL is not None: + self.cbFL.set_active(True) + if self.cbNL is not None: + self.cbNL.set_active(True) + if self.cbPL is not None: + self.cbPL.set_active(True) + elif limit == "none": + if self.limits[limit]: + for cb in self.cbLimits.values(): + cb.set_active(False) + if self.cbNL is not None: + self.cbNL.set_active(False) + if self.cbFL is not None: + self.cbFL.set_active(False) + if self.cbPL is not None: + self.cbPL.set_active(False) + elif limit == "fl": + if not self.limits[limit]: + # only toggle all fl limits off if they are all currently on + # this stops turning one off from cascading into 'fl' box off + # and then all fl limits being turned off + all_fl_on = True + for cb in self.cbLimits.values(): + t = cb.get_children()[0].get_text() + if t.isdigit(): + if not cb.get_active(): + all_fl_on = False + found = {'ring':False, 'tour':False} + for cb in self.cbLimits.values(): + #print "cb label: ", cb.children()[0].get_text() + t = cb.get_children()[0].get_text() + if t.isdigit(): + if self.limits[limit] or all_fl_on: + cb.set_active(self.limits[limit]) + found[self.types[t]] = True + if self.limits[limit]: + if not found[self.type]: + if self.type == 'ring': + if 'tour' in self.rb: + self.rb['tour'].set_active(True) + elif self.type == 'tour': + if 'ring' in self.rb: + self.rb['ring'].set_active(True) + elif limit == "nl": + if not self.limits[limit]: + # only toggle all nl limits off if they are all currently on + # this stops turning one off from cascading into 'nl' box off + # and then all nl limits being turned off + all_nl_on = True + for cb in self.cbLimits.values(): + t = cb.get_children()[0].get_text() + if "nl" in t and len(t) > 2: + if not cb.get_active(): + all_nl_on = False + found = {'ring':False, 'tour':False} + for cb in self.cbLimits.values(): + t = cb.get_children()[0].get_text() + if "nl" in t and len(t) > 2: + if self.limits[limit] or all_nl_on: + cb.set_active(self.limits[limit]) + found[self.types[t]] = True + if self.limits[limit]: + if not found[self.type]: + if self.type == 'ring': + if 'tour' in self.rb: + self.rb['tour'].set_active(True) + elif self.type == 'tour': + if 'ring' in self.rb: + self.rb['ring'].set_active(True) + elif limit == "pl": + if not self.limits[limit]: + # only toggle all nl limits off if they are all currently on + # this stops turning one off from cascading into 'nl' box off + # and then all nl limits being turned off + all_nl_on = True + for cb in self.cbLimits.values(): + t = cb.get_children()[0].get_text() + if "pl" in t and len(t) > 2: + if not cb.get_active(): + all_nl_on = False + found = {'ring':False, 'tour':False} + for cb in self.cbLimits.values(): + t = cb.get_children()[0].get_text() + if "pl" in t and len(t) > 2: + if self.limits[limit] or all_nl_on: + cb.set_active(self.limits[limit]) + found[self.types[t]] = True + if self.limits[limit]: + if not found[self.type]: + if self.type == 'ring': + if 'tour' in self.rb: + self.rb['tour'].set_active(True) + elif self.type == 'tour': + if 'ring' in self.rb: + self.rb['ring'].set_active(True) + elif limit == "ring": + log.debug("set", limit, "to", self.limits[limit]) + if self.limits[limit]: + self.type = "ring" + for cb in self.cbLimits.values(): + #print "cb label: ", cb.children()[0].get_text() + if self.types[cb.get_children()[0].get_text()] == 'tour': + cb.set_active(False) + elif limit == "tour": + log.debug( "set", limit, "to", self.limits[limit] ) + if self.limits[limit]: + self.type = "tour" + for cb in self.cbLimits.values(): + #print "cb label: ", cb.children()[0].get_text() + if self.types[cb.get_children()[0].get_text()] == 'ring': + cb.set_active(False) + + def __set_seat_select(self, w, seat): + #print "__set_seat_select: seat =", seat, "active =", w.get_active() + self.seats[seat] = w.get_active() + log.debug( "self.seats[%s] set to %s" %(seat, self.seats[seat]) ) + + def __set_group_select(self, w, group): + #print "__set_seat_select: seat =", seat, "active =", w.get_active() + self.groups[group] = w.get_active() + log.debug( "self.groups[%s] set to %s" %(group, self.groups[group]) ) + + def fillPlayerFrame(self, vbox, display): + top_hbox = gtk.HBox(False, 0) + vbox.pack_start(top_hbox, False, False, 0) + lbl_title = gtk.Label(self.filterText['playerstitle']) + lbl_title.set_alignment(xalign=0.0, yalign=0.5) + top_hbox.pack_start(lbl_title, expand=True, padding=3) + showb = gtk.Button(label="refresh", stock=None, use_underline=True) + showb.set_alignment(xalign=1.0, yalign=0.5) + showb.connect('clicked', self.__refresh, 'players') + + vbox1 = gtk.VBox(False, 0) + vbox.pack_start(vbox1, False, False, 0) + self.boxes['players'] = vbox1 + + for site in self.conf.get_supported_sites(): + hBox = gtk.HBox(False, 0) + vbox1.pack_start(hBox, False, True, 0) + + player = self.conf.supported_sites[site].screen_name + _pname = Charset.to_gui(player) + self.createPlayerLine(hBox, site, _pname) + + if "GroupsAll" in display and display["GroupsAll"] == True: + hbox = gtk.HBox(False, 0) + vbox1.pack_start(hbox, False, False, 0) + cb = gtk.CheckButton(self.filterText['groupsall']) + cb.connect('clicked', self.__set_group_select, 'allplayers') + hbox.pack_start(cb, False, False, 0) + self.sbGroups['allplayers'] = cb + self.groups['allplayers'] = False + + lbl = gtk.Label('Min # Hands:') + lbl.set_alignment(xalign=1.0, yalign=0.5) + hbox.pack_start(lbl, expand=True, padding=3) + + phands = gtk.Entry() + phands.set_text('0') + phands.set_width_chars(8) + hbox.pack_start(phands, False, False, 0) + phands.connect("changed", self.__set_num_hands, site) + top_hbox.pack_start(showb, expand=False, padding=1) + + def fillSitesFrame(self, vbox): + top_hbox = gtk.HBox(False, 0) + top_hbox.show() + vbox.pack_start(top_hbox, False, False, 0) + + lbl_title = gtk.Label(self.filterText['sitestitle']) + lbl_title.set_alignment(xalign=0.0, yalign=0.5) + top_hbox.pack_start(lbl_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, 'sites') + showb.show() + top_hbox.pack_start(showb, expand=False, padding=1) + + vbox1 = gtk.VBox(False, 0) + self.boxes['sites'] = vbox1 + vbox.pack_start(vbox1, False, False, 0) + + for site in self.conf.get_supported_sites(): + hbox = gtk.HBox(False, 0) + vbox1.pack_start(hbox, False, True, 0) + self.createSiteLine(hbox, site) + #Get db site id for filtering later + #self.cursor.execute(self.sql.query['getSiteId'], (site,)) + #result = self.db.cursor.fetchall() + #if len(result) == 1: + # self.siteid[site] = result[0][0] + #else: + # print "Either 0 or more than one site matched - EEK" + + def fillGamesFrame(self, vbox): + top_hbox = gtk.HBox(False, 0) + vbox.pack_start(top_hbox, False, False, 0) + lbl_title = gtk.Label(self.filterText['gamestitle']) + lbl_title.set_alignment(xalign=0.0, yalign=0.5) + top_hbox.pack_start(lbl_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) + + vbox1 = gtk.VBox(False, 0) + vbox.pack_start(vbox1, False, False, 0) + self.boxes['games'] = vbox1 + + self.cursor.execute(self.sql.query['getGames']) + result = self.db.cursor.fetchall() + if len(result) >= 1: + for line in result: + hbox = gtk.HBox(False, 0) + vbox1.pack_start(hbox, False, True, 0) + self.createGameLine(hbox, line[0]) + else: + print "INFO: No games returned from database" + log.info("No games returned from database") + #end def fillGamesFrame + + def fillLimitsFrame(self, vbox, display): + top_hbox = gtk.HBox(False, 0) + vbox.pack_start(top_hbox, False, False, 0) + lbl_title = gtk.Label(self.filterText['limitstitle']) + lbl_title.set_alignment(xalign=0.0, yalign=0.5) + top_hbox.pack_start(lbl_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, 'limits') + + vbox1 = gtk.VBox(False, 0) + vbox.pack_start(vbox1, False, False, 0) + self.boxes['limits'] = vbox1 + + self.cursor.execute(self.sql.query['getLimits3']) + # selects limitType, bigBlind + result = self.db.cursor.fetchall() + found = {'nl':False, 'fl':False, 'pl':False, 'ring':False, 'tour':False} + + if len(result) >= 1: + hbox = gtk.HBox(True, 0) + vbox1.pack_start(hbox, False, False, 0) + vbox2 = gtk.VBox(False, 0) + hbox.pack_start(vbox2, False, False, 0) + vbox3 = gtk.VBox(False, 0) + hbox.pack_start(vbox3, False, False, 0) + for i, line in enumerate(result): + if "UseType" in self.display: + if line[0] != self.display["UseType"]: + continue + hbox = gtk.HBox(False, 0) + if i <= len(result)/2: + vbox2.pack_start(hbox, False, False, 0) + else: + vbox3.pack_start(hbox, False, False, 0) + if True: #line[0] == 'ring': + if line[1] == 'fl': + name = str(line[2]) + found['fl'] = True + elif line[1] == 'pl': + name = str(line[2])+line[1] + found['pl'] = True + else: + name = str(line[2])+line[1] + found['nl'] = True + self.cbLimits[name] = self.createLimitLine(hbox, name, name) + self.types[name] = line[0] + found[line[0]] = True # type is ring/tour + self.type = line[0] # if only one type, set it now + if "LimitSep" in display and display["LimitSep"] == True and len(result) >= 2: + hbox = gtk.HBox(True, 0) + vbox1.pack_start(hbox, False, False, 0) + vbox2 = gtk.VBox(False, 0) + hbox.pack_start(vbox2, False, False, 0) + vbox3 = gtk.VBox(False, 0) + hbox.pack_start(vbox3, False, False, 0) + + hbox = gtk.HBox(False, 0) + vbox2.pack_start(hbox, False, False, 0) + self.cbAllLimits = self.createLimitLine(hbox, 'all', self.filterText['limitsall']) + hbox = gtk.HBox(False, 0) + vbox2.pack_start(hbox, False, False, 0) + self.cbNoLimits = self.createLimitLine(hbox, 'none', self.filterText['limitsnone']) + + dest = vbox3 # for ring/tour buttons + if "LimitType" in display and display["LimitType"] == True and found['nl'] and found['fl']: + #if found['fl']: + hbox = gtk.HBox(False, 0) + vbox3.pack_start(hbox, False, False, 0) + self.cbFL = self.createLimitLine(hbox, 'fl', self.filterText['limitsFL']) + #if found['nl']: + hbox = gtk.HBox(False, 0) + vbox3.pack_start(hbox, False, False, 0) + self.cbNL = self.createLimitLine(hbox, 'nl', self.filterText['limitsNL']) + hbox = gtk.HBox(False, 0) + vbox3.pack_start(hbox, False, False, 0) + self.cbPL = self.createLimitLine(hbox, 'pl', self.filterText['limitsPL']) + dest = vbox2 # for ring/tour buttons + else: + print "INFO: No games returned from database" + log.info("No games returned from database") + + if "Type" in display and display["Type"] == True and found['ring'] and found['tour']: + rb1 = gtk.RadioButton(None, self.filterText['ring']) + rb1.connect('clicked', self.__set_limit_select, 'ring') + rb2 = gtk.RadioButton(rb1, self.filterText['tour']) + rb2.connect('clicked', self.__set_limit_select, 'tour') + top_hbox.pack_start(rb1, False, False, 0) # (child, expand, fill, padding) + top_hbox.pack_start(rb2, True, True, 0) # child uses expand space if fill is true + + self.rb['ring'] = rb1 + self.rb['tour'] = rb2 + #print "about to set ring to true" + rb1.set_active(True) + # 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 fillSeatsFrame(self, vbox, display): + hbox = gtk.HBox(False, 0) + vbox.pack_start(hbox, False, False, 0) + lbl_title = gtk.Label(self.filterText['seatstitle']) + lbl_title.set_alignment(xalign=0.0, yalign=0.5) + hbox.pack_start(lbl_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, 'seats') + hbox.pack_start(showb, expand=False, padding=1) + + vbox1 = gtk.VBox(False, 0) + vbox.pack_start(vbox1, False, False, 0) + self.boxes['seats'] = vbox1 + + hbox = gtk.HBox(False, 0) + vbox1.pack_start(hbox, False, True, 0) + + lbl_from = gtk.Label(self.filterText['seatsbetween']) + lbl_to = gtk.Label(self.filterText['seatsand']) + adj1 = gtk.Adjustment(value=2, lower=2, upper=10, step_incr=1, page_incr=1, page_size=0) + sb1 = gtk.SpinButton(adjustment=adj1, climb_rate=0.0, digits=0) + adj2 = gtk.Adjustment(value=10, lower=2, upper=10, step_incr=1, page_incr=1, page_size=0) + sb2 = gtk.SpinButton(adjustment=adj2, climb_rate=0.0, digits=0) + + hbox.pack_start(lbl_from, expand=False, padding=3) + hbox.pack_start(sb1, False, False, 0) + hbox.pack_start(lbl_to, expand=False, padding=3) + hbox.pack_start(sb2, False, False, 0) + + self.sbSeats['from'] = sb1 + self.sbSeats['to'] = sb2 + #end def fillSeatsFrame + + def fillGroupsFrame(self, vbox, display): + hbox = gtk.HBox(False, 0) + vbox.pack_start(hbox, False, False, 0) + lbl_title = gtk.Label(self.filterText['groupstitle']) + lbl_title.set_alignment(xalign=0.0, yalign=0.5) + hbox.pack_start(lbl_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, 'groups') + hbox.pack_start(showb, expand=False, padding=1) + + vbox1 = gtk.VBox(False, 0) + vbox.pack_start(vbox1, False, False, 0) + self.boxes['groups'] = vbox1 + + hbox = gtk.HBox(False, 0) + vbox1.pack_start(hbox, False, False, 0) + cb = self.createLimitLine(hbox, 'show', self.filterText['limitsshow']) + + hbox = gtk.HBox(False, 0) + vbox1.pack_start(hbox, False, True, 0) + cb = gtk.CheckButton(self.filterText['posnshow']) + cb.connect('clicked', self.__set_group_select, 'posn') + hbox.pack_start(cb, False, False, 0) + self.sbGroups['posn'] = cb + self.groups['posn'] = False + + if "SeatSep" in display and display["SeatSep"] == True: + hbox = gtk.HBox(False, 0) + vbox1.pack_start(hbox, False, True, 0) + cb = gtk.CheckButton(self.filterText['seatsshow']) + cb.connect('clicked', self.__set_seat_select, 'show') + hbox.pack_start(cb, False, False, 0) + self.sbSeats['show'] = cb + self.seats['show'] = False + + def fillCardsFrame(self, vbox): + hbox1 = gtk.HBox(True,0) + hbox1.show() + vbox.pack_start(hbox1, True, True, 0) + + cards = [ "A", "K","Q","J","T","9","8","7","6","5","4","3","2" ] + + for j in range(0, len(cards)): + hbox1 = gtk.HBox(True,0) + hbox1.show() + vbox.pack_start(hbox1, True, True, 0) + for i in range(0, len(cards)): + if i < (j + 1): + suit = "o" + else: + suit = "s" + button = gtk.ToggleButton("%s%s%s" %(cards[i], cards[j], suit)) + button.connect("toggled", self.cardCallback, "%s%s%s" %(cards[i], cards[j], suit)) + hbox1.pack_start(button, True, True, 0) + button.show() + + def fillDateFrame(self, vbox): + # Hat tip to Mika Bostrom - calendar code comes from PokerStats + top_hbox = gtk.HBox(False, 0) + vbox.pack_start(top_hbox, False, False, 0) + lbl_title = gtk.Label(self.filterText['datestitle']) + lbl_title.set_alignment(xalign=0.0, yalign=0.5) + top_hbox.pack_start(lbl_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, 'dates') + top_hbox.pack_start(showb, expand=False, padding=1) + + vbox1 = gtk.VBox(False, 0) + vbox.pack_start(vbox1, False, False, 0) + self.boxes['dates'] = vbox1 + + hbox = gtk.HBox() + vbox1.pack_start(hbox, False, True, 0) + + lbl_start = gtk.Label('From:') + + btn_start = gtk.Button() + btn_start.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)) + btn_start.connect('clicked', self.__calendar_dialog, self.start_date) + + hbox.pack_start(lbl_start, expand=False, padding=3) + hbox.pack_start(btn_start, expand=False, padding=3) + hbox.pack_start(self.start_date, expand=False, padding=2) + + #New row for end date + hbox = gtk.HBox() + vbox1.pack_start(hbox, False, True, 0) + + lbl_end = gtk.Label(' To:') + btn_end = gtk.Button() + btn_end.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)) + btn_end.connect('clicked', self.__calendar_dialog, self.end_date) + + btn_clear = gtk.Button(label=' Clear Dates ') + btn_clear.connect('clicked', self.__clear_dates) + + hbox.pack_start(lbl_end, expand=False, padding=3) + hbox.pack_start(btn_end, expand=False, padding=3) + hbox.pack_start(self.end_date, expand=False, padding=2) + + hbox.pack_start(btn_clear, expand=False, padding=15) + #end def fillDateFrame + + def __refresh(self, widget, entry): + for w in self.mainVBox.get_children(): + w.destroy() + self.make_filter() + + def __toggle_box(self, widget, entry): + if self.boxes[entry].props.visible: + self.boxes[entry].hide() + widget.set_label("show") + else: + self.boxes[entry].show() + widget.set_label("hide") + #end def __toggle_box + + def __calendar_dialog(self, widget, entry): + d = gtk.Window(gtk.WINDOW_TOPLEVEL) + d.set_title('Pick a date') + + vb = gtk.VBox() + cal = gtk.Calendar() + vb.pack_start(cal, expand=False, padding=0) + + btn = gtk.Button('Done') + btn.connect('clicked', self.__get_date, cal, entry, d) + + vb.pack_start(btn, expand=False, padding=4) + + d.add(vb) + d.set_position(gtk.WIN_POS_MOUSE) + d.show_all() + #end def __calendar_dialog + + def __clear_dates(self, w): + self.start_date.set_text('') + self.end_date.set_text('') + #end def __clear_dates + + def __get_dates(self): + # self.day_start gives user's start of day in hours + offset = int(self.day_start * 3600) # calc day_start in seconds + + t1 = self.start_date.get_text() + t2 = self.end_date.get_text() + + if t1 == '': + t1 = '1970-01-02' + if t2 == '': + t2 = '2020-12-12' + + s1 = strptime(t1, "%Y-%m-%d") # make time_struct + s2 = strptime(t2, "%Y-%m-%d") + e1 = mktime(s1) + offset # s1 is localtime, but returned time since epoch is UTC, then add the + e2 = mktime(s2) + offset # s2 is localtime, but returned time since epoch is UTC + e2 = e2 + 24 * 3600 - 1 # date test is inclusive, so add 23h 59m 59s to e2 + + adj_t1 = strftime("%Y-%m-%d %H:%M:%S", gmtime(e1)) # make adjusted string including time + adj_t2 = strftime("%Y-%m-%d %H:%M:%S", gmtime(e2)) + log.info("t1="+t1+" adj_t1="+adj_t1+'.') + + return (adj_t1, adj_t2) + #end def __get_dates + + def __get_date(self, widget, calendar, entry, win): + # year and day are correct, month is 0..11 + (year, month, day) = calendar.get_date() + month += 1 + ds = '%04d-%02d-%02d' % (year, month, day) + entry.set_text(ds) + win.destroy() + +def main(argv=None): + """main can also be called in the python interpreter, by supplying the command line as the argument.""" + if argv is None: + argv = sys.argv[1:] + + def destroy(*args): # call back for terminating the main eventloop + gtk.main_quit() + + parser = OptionParser() + (options, argv) = parser.parse_args(args = argv) + + config = Configuration.Config() + db = None + + db = Database.Database() + db.do_connect(config) + + qdict = SQL.SQL(db.get_backend_name()) + + i = Filters(db, config, qdict) + main_window = gtk.Window() + main_window.connect('destroy', destroy) + main_window.add(i.get_vbox()) + main_window.show() + gtk.main() + +if __name__ == '__main__': + sys.exit(main()) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 77a3883c..cc2e9cc1 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -1941,12 +1941,12 @@ class Sql: inner join Hands h on (h.id = hp3.handId) """ - # used in GuiPlayerStats: + # used in Gui*PlayerStats: self.query['getPlayerId'] = """SELECT id from Players where name = %s""" self.query['getPlayerIdBySite'] = """SELECT id from Players where name = %s AND siteId = %s""" - # used in Filters: + # used in *Filters: self.query['getSiteId'] = """SELECT id from Sites where name = %s""" self.query['getGames'] = """SELECT DISTINCT category from Gametypes""" self.query['getLimits'] = """SELECT DISTINCT bigBlind from Gametypes ORDER by bigBlind DESC""" diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index d5dc0656..d97a0f75 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -103,7 +103,7 @@ import GuiLogView import GuiDatabase import GuiBulkImport import ImapSummaries -import GuiPlayerStats +import GuiRingPlayerStats import GuiTourneyPlayerStats import GuiPositionalStats import GuiTableViewer @@ -860,7 +860,7 @@ class fpdb: self.add_and_display_tab(bulk_tab, "Bulk Import") def tab_ring_player_stats(self, widget, data=None): - new_ps_thread = GuiPlayerStats.GuiPlayerStats(self.config, self.sql, self.window) + new_ps_thread = GuiRingPlayerStats.GuiRingPlayerStats(self.config, self.sql, self.window) self.threads.append(new_ps_thread) ps_tab=new_ps_thread.get_vbox() self.add_and_display_tab(ps_tab, "Ring Player Stats")