示例#1
0
class GuiRingPlayerStats(QSplitter):
    def __init__(self, config, querylist, mainwin, debug=True):
        QSplitter.__init__(self, None)
        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_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,
            "Currencies": 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, display=filters_display)
        self.filters.registerButton1Name(_("Filters"))
        self.filters.registerButton1Callback(self.showDetailFilter)
        self.filters.registerButton2Name(_("Refresh Stats"))
        self.filters.registerButton2Callback(self.refreshStats)

        scroll = QScrollArea()
        scroll.setWidget(self.filters)

        # 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(summary then position), column heading, xalignment, formatting, celltype
        self.columns = self.conf.get_gui_cash_stat_params()

        # 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]
            ['gt.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.cardstests = [
            [Card.DATABASE_FILTERS['pair'],
             _('Pocket pairs')],
            [Card.DATABASE_FILTERS['suited'],
             _('Suited')],
            [
                Card.DATABASE_FILTERS['suited_connectors'],
                _('Suited connectors')
            ],
            [Card.DATABASE_FILTERS['offsuit'],
             _('Offsuit')],
            [
                Card.DATABASE_FILTERS['offsuit_connectors'],
                _('Offsuit connectors')
            ],
        ]
        self.stats_frame = None
        self.stats_vbox = None
        self.detailFilters = []  # the data used to enhance the sql select
        self.cardsFilters = []

        self.stats_frame = QFrame()
        self.stats_frame.setLayout(QVBoxLayout())

        self.stats_vbox = QSplitter(Qt.Vertical)
        self.stats_frame.layout().addWidget(self.stats_vbox)

        self.addWidget(scroll)
        self.addWidget(self.stats_frame)
        self.setStretchFactor(0, 0)
        self.setStretchFactor(1, 1)

        # Make sure Hand column is not displayed.
        hand_column = (x for x in self.columns if x[0] == 'hand').next()
        hand_column[colshowsumm] = hand_column[colshowposn] = False

        # If rfi and steal both on for summaries, turn rfi off.
        rfi_column = (x for x in self.columns if x[0] == 'rfi').next()
        steals_column = (x for x in self.columns if x[0] == 'steals').next()
        if rfi_column[colshowsumm] and steals_column[colshowsumm]:
            rfi_column[colshowsumm] = False

        # If rfi and steal both on for position breakdowns, turn steals off.
        if rfi_column[colshowposn] and steals_column[colshowposn]:
            steals_column[colshowposn] = False

    def refreshStats(self, checkState):
        self.liststore = []
        self.listcols = []
        self.stats_frame.layout().removeWidget(self.stats_vbox)
        self.stats_vbox.setParent(None)
        self.stats_vbox = QSplitter(Qt.Vertical)
        self.stats_frame.layout().addWidget(self.stats_vbox)
        self.fillStatsFrame(self.stats_vbox)

        if self.liststore:
            topsize = self.stats_vbox.widget(0).sizeHint().height()
            self.stats_vbox.setSizes(
                [topsize, self.stats_vbox.height() - topsize])
            self.stats_vbox.setStretchFactor(0, 0)
            self.stats_vbox.setStretchFactor(1, 1)

    def fillStatsFrame(self, vbox):
        sites = self.filters.getSites()
        heroes = self.filters.getHeroes()
        siteids = self.filters.getSiteIds()
        limits = self.filters.getLimits()
        seats = self.filters.getSeats()
        groups = self.filters.getGroups()
        dates = self.filters.getDates()
        games = self.filters.getGames()
        currencies = self.filters.getCurrencies()
        sitenos = []
        playerids = []

        # Which sites are selected?
        for site in sites:
            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, seats, groups,
                              dates, games, currencies)

    def createStatsTable(self, vbox, playerids, sitenos, limits, seats, groups,
                         dates, games, currencies):
        startTime = time()
        show_detail = True

        #        # 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(vbox, 'playerDetailedStats', flags, playerids, sitenos,
                     limits, seats, groups, dates, games, currencies)

        if 'allplayers' in groups:
            # can't currently do this combination so skip detailed table
            show_detail = False

        if show_detail:
            # Separator
            frame = QWidget()
            vbox2 = QVBoxLayout()
            vbox2.setContentsMargins(0, 0, 0, 0)
            frame.setLayout(vbox2)
            vbox.addWidget(frame)
            heading = QLabel(self.filterText['handhead'])
            heading.setAlignment(Qt.AlignHCenter)
            vbox2.addWidget(heading)

            # Detailed table
            flags[0] = True
            flags[2] = 1
            self.addGrid(vbox2, 'playerDetailedStats', flags, playerids,
                         sitenos, limits, seats, groups, dates, games,
                         currencies)

        self.db.rollback()
        print(
            _("Stats page displayed in %4.2f seconds") % (time() - startTime))

    def addGrid(self, vbox, query, flags, playerids, sitenos, limits, seats,
                groups, dates, games, currencies):
        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, seats,
                               groups, dates, games, currencies)
        self.cursor.execute(tmp)
        result = self.cursor.fetchall()
        colnames = [desc[0].lower() for desc in self.cursor.description]

        # pre-fetch some constant values:
        colshow = colshowsumm
        if 'posn' in groups: colshow = colshowposn
        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)
        view = QTableView()
        self.liststore.append(
            QStandardItemModel(0, len(self.cols_to_show), view))
        self.liststore[grid].setSortRole(Qt.UserRole)
        view.setModel(self.liststore[grid])
        view.verticalHeader().hide()
        vbox.addWidget(view)
        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(s)
        self.liststore[grid].setHorizontalHeaderLabels(self.listcols[grid])

        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.decodeStartHandValue(
                                result[sqlrow][colnames.index('category')],
                                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')] + ' ' \
                                    + result[sqlrow][colnames.index('currency')] + ' '
                            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)
                            ante = result[sqlrow][colnames.index('ante')]
                            if ante > 0:
                                value += ' ante: %.2f' % (ante / 100.0)
                            if result[sqlrow][colnames.index('fast')] == 1:
                                value += ' ' + fast_names[result[sqlrow][
                                    colnames.index('name')]]
                    else:
                        continue
                item = QStandardItem('')
                sortValue = -1e9
                if value is not None and value != -999:
                    item = QStandardItem(column[colformat] % value)
                    if column[colalias] == 'game' and holecards:
                        if result[sqlrow][colnames.index(
                                'category')] == 'holdem':
                            sortValue = 1000 * ranks[value[0]] + 10 * ranks[
                                value[1]] + (1 if len(value) == 3
                                             and value[2] == 's' else 0)
                        else:
                            sortValue = -1
                    elif column[colalias] in ('game', 'pname'):
                        sortValue = value
                    elif column[colalias] == 'plposition':
                        sortValue = [
                            'BB', 'SB', 'Btn', '1', '2', '3', '4', '5', '6',
                            '7'
                        ].index(value)
                    else:
                        sortValue = float(value)
                item.setData(sortValue, Qt.UserRole)
                item.setEditable(False)
                if col != 0:
                    item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
                if column[colalias] != 'game':
                    item.setToolTip('<big>%s for %s</big><br/><i>%s</i>' %
                                    (column[colheading], treerow[0].text(),
                                     onlinehelp[column[colheading]]))
                treerow.append(item)
            self.liststore[grid].appendRow(treerow)
            sqlrow += 1

        view.resizeColumnsToContents()
        view.setSortingEnabled(
            True
        )  # do this after resizing columns, otherwise it leaves room for the sorting triangle in every heading
        view.resizeColumnToContents(
            0
        )  # we want room for the sorting triangle in column 0 where it starts.
        view.resizeRowsToContents()

    def refineQuery(self, query, flags, playerids, sitenos, limits, seats,
                    groups, dates, games, currencies):
        having = ''
        if not flags:
            holecards = False
            numhands = 0
        else:
            holecards = flags[0]
            numhands = flags[1]
        colshow = colshowsumm
        if 'posn' in groups: colshow = colshowposn

        pname_column = (x for x in self.columns if x[0] == 'pname').next()
        if 'allplayers' in groups:
            nametest = "(hp.playerId)"
            if holecards or 'posn' in groups:
                pname = "'all players'"
                # set flag in self.columns to not show player name column
                pname_column[colshow] = 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
                pname_column[colshow] = 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
            pname_column[colshow] = False
        query = query.replace("<player_test>", nametest)
        query = query.replace("<playerName>", pname)
        query = query.replace("<havingclause>", having)

        gametest = ""
        for m in self.filters.display.items():
            if m[0] == 'Games' and m[1]:
                if len(games) > 0:
                    gametest = str(tuple(games))
                    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("<game_test>", gametest)

        currencytest = str(tuple(currencies))
        currencytest = currencytest.replace(",)", ")")
        currencytest = currencytest.replace("u'", "'")
        currencytest = "AND gt.currency in %s" % currencytest
        query = query.replace("<currency_test>", currencytest)

        sitetest = ""
        for m in self.filters.display.items():
            if m[0] == 'Sites' and m[1]:
                if len(sitenos) > 0:
                    sitetest = str(tuple(sitenos))
                    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("<site_test>", sitetest)

        if seats:
            query = query.replace(
                '<seats_test>',
                'between ' + str(seats['from']) + ' and ' + str(seats['to']))
            if 'seats' in groups:
                query = query.replace('<groupbyseats>', ',h.seats')
                query = query.replace('<orderbyseats>', ',h.seats')
            else:
                query = query.replace('<groupbyseats>', '')
                query = query.replace('<orderbyseats>', '')
        else:
            query = query.replace('<seats_test>', 'between 0 and 100')
            query = query.replace('<groupbyseats>', '')
            query = query.replace('<orderbyseats>', '')

        bbtest = self.filters.get_limits_where_clause(limits)

        query = query.replace("<gtbigBlind_test>", bbtest)

        if holecards:  # re-use level variables for hole card query
            query = query.replace("<hgametypeId>", "hp.startcards")
            query = query.replace(
                "<orderbyhgametypeId>",
                ",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("<orderbyhgametypeId>", "")
            groupLevels = 'limits' not in groups
            if groupLevels:
                query = query.replace(
                    "<hgametypeId>", "p.name"
                )  # need to use p.name for sqlite posn stats to work
            else:
                query = query.replace("<hgametypeId>", "h.gametypeId")

        # process self.detailFilters (a list of tuples)
        flagtest = ''
        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>", flagtest)
        if self.cardsFilters:
            cardstests = []

            for cardFilter in self.cardsFilters:
                cardstests.append(cardFilter)
            cardstests = ''.join(('and (', ' or '.join(cardstests), ')'))
        else:
            cardstests = ''
        query = query.replace("<cardstest>", cardstests)
        # allow for differences in sql cast() function:
        if self.db.backend == self.MYSQL_INNODB:
            query = query.replace("<signed>", 'signed ')
        else:
            query = query.replace("<signed>", '')

        # Filter on dates
        query = query.replace(
            "<datestest>",
            " between '" + dates[0] + "' and '" + dates[1] + "'")

        # Group by position?
        plposition_column = (x for x in self.columns
                             if x[0] == 'plposition').next()
        if 'posn' in groups:
            query = query.replace("<position>", "hp.position")
            plposition_column[colshow] = True
        else:
            query = query.replace("<position>", "gt.base")
            plposition_column[colshow] = False

        return (query)

    def showDetailFilter(self, checkState):
        detailDialog = QDialog(self.main_window)
        detailDialog.setWindowTitle(_("Detailed Filters"))

        handbox = QVBoxLayout()
        detailDialog.setLayout(handbox)

        label = QLabel(_("Hand Filters:"))
        handbox.addWidget(label)
        label.setAlignment(Qt.AlignCenter)

        grid = QGridLayout()
        handbox.addLayout(grid)
        for row, htest in enumerate(self.handtests):
            cb = QCheckBox()
            lbl_from = QLabel(htest[1])
            lbl_tween = QLabel(_('between'))
            lbl_to = QLabel(_('and'))
            sb1 = QSpinBox()
            sb1.setRange(0, 10)
            sb1.setValue(htest[2])
            sb2 = QSpinBox()
            sb2.setRange(2, 10)
            sb2.setValue(htest[3])

            for df in self.detailFilters:
                if df[0] == htest[0]:
                    cb.setChecked(True)
                    break

            grid.addWidget(cb, row, 0)
            grid.addWidget(lbl_from, row, 1, Qt.AlignLeft)
            grid.addWidget(lbl_tween, row, 2)
            grid.addWidget(sb1, row, 3)
            grid.addWidget(lbl_to, row, 4)
            grid.addWidget(sb2, row, 5)

            htest[4:7] = [cb, sb1, sb2]

        label = QLabel(_('Restrict to hand types:'))
        handbox.addWidget(label)
        for ctest in self.cardstests:
            hbox = QHBoxLayout()
            handbox.addLayout(hbox)
            cb = QCheckBox()
            if ctest[0] in self.cardsFilters:
                cb.setChecked(True)
            label = QLabel(ctest[1])
            hbox.addWidget(cb)
            hbox.addWidget(label)
            ctest[2:3] = [cb]
        btnBox = QDialogButtonBox(QDialogButtonBox.Ok
                                  | QDialogButtonBox.Cancel)
        handbox.addWidget(btnBox)
        btnBox.accepted.connect(detailDialog.accept)
        btnBox.rejected.connect(detailDialog.reject)
        response = detailDialog.exec_()

        if response:
            self.detailFilters = []
            for ht in self.handtests:
                if ht[4].isChecked():
                    self.detailFilters.append(
                        (ht[0], ht[5].value(), ht[6].value()))
                ht[2], ht[3] = ht[5].value(), ht[6].value()
            self.cardsFilters = []
            for ct in self.cardstests:
                if ct[2].isChecked():
                    self.cardsFilters.append(ct[0])
            self.refreshStats(None)
示例#2
0
 def initWin(self):
     iptGrid = QGridLayout()
     title = Text("TSP", (255, 0, 0), 16, "center")
     pic = QPixmap("C:\\tsp.png")
     picLbl = QLabel()
     picLbl.setPixmap(pic)
     picLbl.setScaledContents(True)
     titleLayout = QVBoxLayout()
     titleLayout.addWidget(title)
     titleLayout.addWidget(picLbl)
     titleFrame = QFrame()
     titleFrame.setFrameShape(QFrame.StyledPanel)
     titleFrame.setAutoFillBackground(True)
     p5 = titleFrame.palette()
     p5.setColor(titleFrame.backgroundRole(), QColor(255, 255, 255))
     titleFrame.setPalette(p5)
     titleFrame.setLayout(titleLayout)
     iptTitle = Text("Program Input", (255, 0, 0), 12, "center")
     iptTxt1 = QLabel("Cities No:")
     iptTxt1.setFont(QFont("Decorative", 12))
     iptTxt2 = QLabel("start:")
     iptTxt2.setFont(QFont("Decorative", 12))
     self.iptEdt1 = QLineEdit()
     self.iptEdt1.textChanged[str].connect(self.get_input)
     self.iptEdt2 = QLineEdit()
     self.iptEdt2.textChanged[str].connect(self.get_input)
     self.iptBtn1 = QPushButton("Build")
     self.iptBtn1.clicked.connect(self.bulid_map)
     self.iptBtn2 = QPushButton("Rturn")
     self.iptBtn2.clicked.connect(self.get_initial)
     iptH = QHBoxLayout()
     iptH.addWidget(self.iptBtn1)
     iptH.addWidget(self.iptBtn2)
     iptGrid.addWidget(iptTitle, 1, 0, 1, 5)
     iptGrid.addWidget(iptTxt1, 2, 0)
     iptGrid.addWidget(self.iptEdt1, 2, 1)
     iptGrid.addWidget(iptTxt2, 3, 0)
     iptGrid.addWidget(self.iptEdt2, 3, 1)
     iptGrid.setVerticalSpacing(10)
     iptV = QVBoxLayout()
     iptV.addLayout(iptGrid)
     iptV.addLayout(iptH)
     iptFrame = QFrame()
     iptFrame.setAutoFillBackground(True)
     p6 = iptFrame.palette()
     p6.setColor(iptFrame.backgroundRole(), QColor(220, 225, 255))
     iptFrame.setPalette(p6)
     iptFrame.setFrameShape(QFrame.StyledPanel)
     iptFrame.setLayout(iptV)
     srgGrid = QGridLayout()
     #srgGrid.setVerticalSpacing(10)
     srgTitle = Text("Algorithms", (255, 0, 0), 12, "center")
     self.srgBtn1 = QPushButton("Genetic")
     self.srgBtn1.clicked.connect(self.run_algorithm)
     self.srgBtn2 = QPushButton("Simulated")
     self.srgBtn2.clicked.connect(self.run_algorithm)
     self.srgBtn3 = QPushButton("Tabu")
     self.srgBtn3.clicked.connect(self.run_algorithm)
     self.srgBtn4 = QPushButton("reset")
     self.srgBtn4.clicked.connect(self.reset)
     srgGrid.addWidget(srgTitle, 1, 0, 1, 6)
     srgGrid.addWidget(self.srgBtn1, 2, 1, 2, 4)
     srgGrid.addWidget(self.srgBtn2, 3, 1, 3, 4)
     srgGrid.addWidget(self.srgBtn3, 4, 1, 4, 4)
     srgGrid.addWidget(self.srgBtn4, 5, 1, 5, 4)
     srgFrame = QFrame()
     srgFrame.setFrameShape(QFrame.StyledPanel)
     srgFrame.setAutoFillBackground(True)
     p7 = srgFrame.palette()
     p7.setColor(srgFrame.backgroundRole(), QColor(255, 255, 255))
     srgFrame.setPalette(p7)
     srgFrame.setLayout(srgGrid)
     otpGrid = QGridLayout()
     otpTitle = Text("Program Output", (255, 0, 0), 12, "center")
     otpTxt1 = QLabel("The Cost")
     otpTxt1.setFont(QFont("Decorative", 12))
     self.lcd1 = QLCDNumber()
     otpGrid.addWidget(otpTitle, 1, 0, 1, 2)
     otpGrid.addWidget(otpTxt1, 2, 0)
     otpGrid.addWidget(self.lcd1, 2, 1)
     otpFrame = QFrame()
     otpFrame.setFrameShape(QFrame.StyledPanel)
     otpFrame.setAutoFillBackground(True)
     p8 = otpFrame.palette()
     p8.setColor(otpFrame.backgroundRole(), QColor(220, 225, 255))
     otpFrame.setPalette(p8)
     otpFrame.setLayout(otpGrid)
     splitter1 = QSplitter(Qt.Vertical)
     splitter1.addWidget(titleFrame)
     splitter1.addWidget(iptFrame)
     splitter1.setSizes([240, 135])
     splitter2 = QSplitter(Qt.Vertical)
     splitter2.addWidget(srgFrame)
     splitter2.addWidget(otpFrame)
     splitter2.setSizes([200, 92])
     splitter3 = QSplitter(Qt.Vertical)
     splitter3.addWidget(splitter1)
     splitter3.addWidget(splitter2)
     splitter3.setSizes([382, 291])
     splitter3.resize(260, 685)
     splitter3.move(1100, 5)
     splitter3.setParent(self)
     splitter3.setAutoFillBackground(True)
     p3 = splitter3.palette()
     p3.setColor(splitter3.backgroundRole(), QColor(255, 255, 255))
     splitter3.setPalette(p3)
     self.mapFrame = QFrame()
     self.mapFrame.setFrameShape(QFrame.StyledPanel)
     self.mapFrame.move(5, 5)
     self.mapFrame.resize(1090, 685)
     self.mapFrame.setParent(self)
     self.setAutoFillBackground(True)
     p2 = self.palette()
     p2.setColor(self.backgroundRole(), QColor(0, 0, 0))
     self.setPalette(p2)
     self.mapFrame.setParent(self)
     self.hint = Text("Click the bulid button to bulid a random map",
                      (255, 0, 0), 23, "center")
     self.hint.move(230, 100)
     self.hint.setParent(self)
     self.setWindowTitle("TSP")
     self.width = QDesktopWidget().availableGeometry().width()
     self.height = QDesktopWidget().availableGeometry().height() - 40
     self.resize(self.width, self.height)
     self.show()
     self.nodes = {}
     self.points = {}
     self.flag = True
class GuiTourneyPlayerStats(QSplitter):
    def __init__(self, config, db, sql, mainwin, debug=True):
        QSplitter.__init__(self, mainwin)
        self.conf = config
        self.db = db
        self.cursor = self.db.cursor
        self.sql = sql
        self.main_window = mainwin
        self.debug = debug

        self.liststore = [
        ]  # QStandardItemModel[] stores the contents of the grids
        self.listcols = []

        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.stats_frame = None
        self.stats_vbox = None
        self.detailFilters = []  # the data used to enhance the sql select

        self.filters = Filters.Filters(self.db, display=filters_display)
        #self.filters.registerButton1Name(_("_Filters"))
        #self.filters.registerButton1Callback(self.showDetailFilter)
        self.filters.registerButton2Name(_("_Refresh Stats"))
        self.filters.registerButton2Callback(self.refreshStats)

        scroll = QScrollArea()
        scroll.setWidget(self.filters)

        # 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 = [
            ["siteName", True, _("Site"), 0.0, "%s", "str"]
            #,["tourney",        False, _("Tourney"), 0.0, "%s", "str"]   # true not allowed for this line
            ,
            ["category", True, _("Cat."), 0.0, "%s", "str"],
            ["limitType", True,
             _("Limit"), 0.0, "%s", "str"],
            ["currency", True, _("Curr."), 0.0, "%s", "str"],
            ["buyIn", True, _("BuyIn"), 1.0, "%3.2f", "str"],
            ["fee", True, _("Fee"), 1.0, "%3.2f", "str"],
            ["playerName", False,
             _("Name"), 0.0, "%s",
             "str"]  # true not allowed for this line (set in code)
            ,
            ["tourneyCount", True,
             _("#"), 1.0, "%1.0f", "str"],
            ["itm", True, _("ITM%"), 1.0, "%3.2f", "str"],
            ["_1st", False, _("1st"), 1.0, "%1.0f", "str"],
            ["_2nd", True, _("2nd"), 1.0, "%1.0f", "str"],
            ["_3rd", True, _("3rd"), 1.0, "%1.0f", "str"],
            ["unknownRank", True,
             _("Rank?"), 1.0, "%1.0f", "str"],
            ["spent", True, _("Spent"), 1.0, "%3.2f", "str"],
            ["won", True, _("Won"), 1.0, "%3.2f", "str"],
            ["roi", True, _("ROI%"), 1.0, "%3.0f", "str"],
            ["profitPerTourney", True,
             _("$/Tour"), 1.0, "%3.2f", "str"]
        ]

        self.stats_frame = QFrame()
        self.stats_frame.setLayout(QVBoxLayout())

        self.stats_vbox = QSplitter(Qt.Vertical)
        self.stats_frame.layout().addWidget(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.addWidget(scroll)
        self.addWidget(self.stats_frame)
        self.setStretchFactor(0, 0)
        self.setStretchFactor(1, 1)

    def addGrid(self, vbox, query, numTourneys, tourneyTypes, playerids,
                sitenos, seats):
        sqlrow = 0
        grid = numTourneys  #TODO: should this be numTourneyTypes?

        query = self.sql.query[query]
        query = self.refineQuery(query, numTourneys, tourneyTypes, playerids,
                                 sitenos, seats)
        self.cursor.execute(query)
        result = self.cursor.fetchall()
        colnames = [desc[0] for desc in self.cursor.description]

        # pre-fetch some constant values:
        #self.cols_to_show = [x for x in self.columns if x[colshow]]
        #htourneytypeid_idx = colnames.index('tourneyTypeId')
        self.cols_to_show = self.columns  #TODO do i need above 2 lines?

        assert len(self.liststore) == grid, "len(self.liststore)=" + str(
            len(self.liststore)) + " grid-1=" + str(grid)
        view = QTableView()
        self.liststore.append(
            QStandardItemModel(0, len(self.cols_to_show), view))
        view.setModel(self.liststore[grid])
        view.verticalHeader().hide()
        vbox.addWidget(view)
        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(s)
        self.liststore[grid].setHorizontalHeaderLabels(self.listcols[grid])

        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])]
                else:
                    value = 111
                if column[colalias] == 'siteName':
                    if result[sqlrow][colnames.index('speed')] != 'Normal':
                        if (result[sqlrow][colnames.index('speed')] == 'Hyper'
                                and result[sqlrow][colnames.index('siteName')]
                                == 'Full Tilt Poker'):
                            value = value + ' ' + 'Super Turbo'
                        else:
                            value = value + ' ' + result[sqlrow][
                                colnames.index('speed')]
                item = QStandardItem('')
                if value != None and value != -999:
                    item = QStandardItem(column[colformat] % value)
                item.setEditable(False)
                item.setTextAlignment(Qt.AlignRight)
                treerow.append(item)
            self.liststore[grid].appendRow(treerow)
            sqlrow += 1

        view.resizeColumnsToContents()
        view.setSortingEnabled(True)

    def createStatsTable(self, vbox, tourneyTypes, playerids, sitenos, seats):
        startTime = time()

        numTourneys = self.filters.getNumTourneys()
        self.addGrid(vbox, 'tourneyPlayerDetailedStats', numTourneys,
                     tourneyTypes, playerids, sitenos, seats)

        print _("Stats page displayed in %4.2f seconds") % (time() - startTime)

    def fillStatsFrame(self, vbox):
        tourneyTypes = self.filters.getTourneyTypes()
        #tourneys = self.tourneys.getTourneys()
        sites = self.filters.getSites()
        heroes = self.filters.getHeroes()
        siteids = self.filters.getSiteIds()
        seats = self.filters.getSeats()
        dates = self.filters.getDates()
        sitenos = []
        playerids = []

        # Which sites are selected?
        for site in sites:
            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

        self.createStatsTable(vbox, tourneyTypes, playerids, sitenos, seats)

    def refineQuery(self, query, numTourneys, tourneyTypes, playerids, sitenos,
                    seats):
        having = ''

        #print "start of refinequery, playerids:",playerids
        if playerids:
            nametest = str(tuple(playerids))
            nametest = nametest.replace("L", "")
            nametest = nametest.replace(",)", ")")
        else:
            nametest = "1 = 2"
        #print "refinequery, nametest after initial creation:",nametest
        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 #TODO: fix and reactivate

        query = query.replace("<nametest>", nametest)
        query = query.replace("<playerName>", pname)
        query = query.replace("<havingclause>", having)

        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 tt.siteId in %s" % sitetest  #[1:-1]
                else:
                    sitetest = "and tt.siteId IS NULL"
        #print "refinequery, sitetest before its use for replacement:",sitetest
        query = query.replace("<sitetest>", sitetest)

        if seats:
            query = query.replace(
                '<seats_test>',
                'between ' + str(seats['from']) + ' and ' + str(seats['to']))
            if False:  #'show' in seats and seats['show']: should be 'show' in groups but we don't even display the groups filter
                query = query.replace('<groupbyseats>', ',h.seats')
                query = query.replace('<orderbyseats>', ',h.seats')
            else:
                query = query.replace('<groupbyseats>', '')
                query = query.replace('<orderbyseats>', '')
        else:
            query = query.replace('<seats_test>', 'between 0 and 100')
            query = query.replace('<groupbyseats>', '')
            query = query.replace('<orderbyseats>', '')

        #bbtest = self.filters.get_limits_where_clause(limits)

        #query = query.replace("<gtbigBlind_test>", bbtest)

        #query = query.replace("<orderbyhgametypeId>", "")

        # 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>", flagtest)

        # allow for differences in sql cast() function:
        if self.db.backend == self.db.MYSQL_INNODB:
            query = query.replace("<signed>", 'signed ')
        else:
            query = query.replace("<signed>", '')

        # Filter on dates
        start_date, end_date = self.filters.getDates()
        query = query.replace("<startdate_test>", start_date)
        query = query.replace("<enddate_test>", end_date)

        return (query)

    def refreshStats(self, widget):
        #        self.last_pos = self.stats_vbox.get_position()
        self.stats_frame.layout().removeWidget(self.stats_vbox)
        self.stats_vbox.setParent(None)
        self.liststore = []
        self.listcols = []
        #self.stats_vbox = gtk.VBox(False, 0)
        self.stats_vbox = QSplitter(Qt.Vertical)
        self.stats_frame.layout().addWidget(self.stats_vbox)
        self.fillStatsFrame(self.stats_vbox)


#        if self.last_pos > 0:
#            self.stats_vbox.set_position(self.last_pos)

    def reset_style_render_func(self, treeviewcolumn, cell, model, iter):
        cell.set_property('foreground', None)

    def sortCols(self, col, nums):
        #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)