From d888b7d463ee19c4d94a4a8c7ca4d0cbfa68f2e9 Mon Sep 17 00:00:00 2001 From: grindi Date: Sun, 8 Nov 2009 23:09:14 +0300 Subject: [PATCH 001/320] Party hhc: cleand, added getTableTitleRe --- pyfpdb/PartyPokerToFpdb.py | 103 +++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 55 deletions(-) diff --git a/pyfpdb/PartyPokerToFpdb.py b/pyfpdb/PartyPokerToFpdb.py index 4ed0c965..ba597881 100755 --- a/pyfpdb/PartyPokerToFpdb.py +++ b/pyfpdb/PartyPokerToFpdb.py @@ -26,29 +26,21 @@ from HandHistoryConverter import * # PartyPoker HH Format -class PartyPokerParseError(FpdbParseError): - "Usage: raise PartyPokerParseError([, hh=][, hid=])" +class FpdbParseError(FpdbParseError): + "Usage: raise FpdbParseError([, hh=][, hid=])" def __init__(self, msg='', hh=None, hid=None): - if hh is not None: - msg += "\n\nHand history attached below:\n" + self.wrapHh(hh) - return super(PartyPokerParseError, self).__init__(msg, hid=hid) + return super(FpdbParseError, self).__init__(msg, hid=hid) def wrapHh(self, hh): return ("%(DELIMETER)s\n%(HH)s\n%(DELIMETER)s") % \ {'DELIMETER': '#'*50, 'HH': hh} class PartyPoker(HandHistoryConverter): - -############################################################ -# Class Variables - sitename = "PartyPoker" codepage = "cp1252" - siteId = 9 # TODO: automate; it's a class variable so shouldn't hit DB too often - filetype = "text" # "text" or "xml". I propose we subclass HHC to HHC_Text and HHC_XML. - - + siteId = 9 + filetype = "text" sym = {'USD': "\$", } # Static regexes @@ -86,15 +78,15 @@ class PartyPoker(HandHistoryConverter): re_HandInfo = re.compile(""" ^Table\s+ - (?P[a-zA-Z0-9 ]+)\s+ - (?: \#|\(|)(?P\d+)\)?\s+ - (?:[^ ]+\s+\#(?P\d+).+)? # table number for mtt - \((?PReal|Play)\s+Money\)\s+ # FIXME: check if play money is correct - Seat\s+(?P
\d+)\)?\s+ (?:[^ ]+\s+\#(?P\d+).+)? # table number for mtt + (\(No\sDP\)\s)? \((?PReal|Play)\s+Money\)\s+ # FIXME: check if play money is correct Seat\s+(?P
[ a-zA-Z]+) - \$?(?P[.0-9]+)/\$?(?P[.0-9]+) - (?P.*) - (?P
[0-9]+):(?P[0-9]+) ET - (?P[0-9]+)/(?P[0-9]+)/(?P[0-9]+)Table (?P
[ a-zA-Z]+)\nSeat (?P
\d+)\)?\s+ - (?:[^ ]+\s+\#(?P\d+).+)? # table number for mtt + (?:[a-zA-Z0-9 ]+\s+\#(?P\d+).+)? (\(No\sDP\)\s)? \((?PReal|Play)\s+Money\)\s+ # FIXME: check if play money is correct Seat\s+(?P
\d+)\)?\s+ - (?:[^ ]+\s+\#(?P\d+).+)? # table number for mtt + (?:[a-zA-Z0-9 ]+\s+\#(?P\d+).+)? (\(No\sDP\)\s)? \((?PReal|Play)\s+Money\)\s+ # FIXME: check if play money is correct Seat\s+(?P
\d+)\)?\s+ - (?:[^ ]+\s+\#(?P\d+).+)? # table number for mtt + (?:[a-zA-Z0-9 ]+\s+\#(?P\d+).+)? (\(No\sDP\)\s)? \((?PReal|Play)\s+Money\)\s+ # FIXME: check if play money is correct Seat\s+(?P
.+$)", re.MULTILINE) re_Button = re.compile(ur"^Seat (?P
[0-9]+)\.txt") def compilePlayerRegexs(self, hand): @@ -55,18 +56,25 @@ class Everleaf(HandHistoryConverter): self.re_Antes = re.compile(ur"^%s: posts ante \[(?:\$| €|) (?P[.0-9]+)" % player_re, re.MULTILINE) self.re_BringIn = re.compile(ur"^%s posts bring-in (?:\$| €|)(?P[.0-9]+)\." % player_re, re.MULTILINE) self.re_HeroCards = re.compile(ur"^Dealt to %s \[ (?P.*) \]" % player_re, re.MULTILINE) - self.re_Action = re.compile(ur"^%s(?P: bets| checks| raises| calls| folds)(\s\[(?:\$| €|) (?P[.\d]+) (USD|EUR|)\])?" % player_re, re.MULTILINE) + self.re_Action = re.compile(ur"^%s(?P: bets| checks| raises| calls| folds)(\s\[(?:\$| €|) (?P[.,\d]+) (USD|EUR|Chips)\])?" % player_re, re.MULTILINE) #self.re_Action = re.compile(ur"^%s(?P: bets| checks| raises| calls| folds| complete to)(\s\[?(?:\$| €|) ?(?P\d+\.?\d*)\.?\s?(USD|EUR|)\]?)?" % player_re, re.MULTILINE) self.re_ShowdownAction = re.compile(ur"^%s shows \[ (?P.*) \]" % player_re, re.MULTILINE) self.re_CollectPot = re.compile(ur"^%s wins (?:\$| €|) (?P[.\d]+) (USD|EUR|chips)(.*?\[ (?P.*?) \])?" % player_re, re.MULTILINE) self.re_SitsOut = re.compile(ur"^%s sits out" % player_re, re.MULTILINE) + else: + print "*** EverleafToFpdb: compilePlayerRegexs failed" + print players + print self.compiledPlayers + def readSupportedGames(self): return [["ring", "hold", "nl"], ["ring", "hold", "pl"], ["ring", "hold", "fl"], ["ring", "studhi", "fl"], - ["ring", "omahahi", "pl"] + ["ring", "omahahi", "pl"], + ["ring", "omahahilo", "pl"], + ["tour", "hold", "nl"] ] def determineGameType(self, handText): @@ -138,6 +146,13 @@ or None if we fail to get the info """ hand.tablename = m.group('TABLE') hand.maxseats = 6 # assume 6-max unless we have proof it's a larger/smaller game, since everleaf doesn't give seat max info + t = self.re_TourneyInfoFromFilename.search(self.in_path) + if t: + tourno = t.group('TOURNO') + if tourno: # we're a tourney, yay + hand.tourNo = tourno + hand.tablename = t.group('TABLE') + # Believe Everleaf time is GMT/UTC, no transation necessary # Stars format (Nov 10 2008): 2008/11/07 12:38:49 CET [2008/11/07 7:38:49 ET] # or : 2008/11/07 12:38:49 ET @@ -287,7 +302,9 @@ or None if we fail to get the info """ @staticmethod def getTableTitleRe(type, table_name=None, tournament = None, table_number=None): - return "^%s -" % (table_name) + if tournament: + return "%s - Tournament ID: %s -" % (table_number, tournament) + return "%s -" % (table_name) From e3be7db2a0631d875188b6ee22855535b8694f18 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Mon, 1 Feb 2010 09:17:42 -0500 Subject: [PATCH 188/320] fix bug i introduced that caused everleaf cash hands to fail --- pyfpdb/EverleafToFpdb.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index c9206ea5..fe17f158 100755 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -149,7 +149,6 @@ or None if we fail to get the info """ t = self.re_TourneyInfoFromFilename.search(self.in_path) if t: tourno = t.group('TOURNO') - if tourno: # we're a tourney, yay hand.tourNo = tourno hand.tablename = t.group('TABLE') From 81ff8e632cc483b0cc53678dd0c818734c8d7e7e Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Mon, 1 Feb 2010 09:41:33 -0500 Subject: [PATCH 189/320] remove my misunderstanding of how compileplayerregexs worked --- pyfpdb/EverleafToFpdb.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index fe17f158..fdc35bf6 100755 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -62,11 +62,6 @@ class Everleaf(HandHistoryConverter): self.re_CollectPot = re.compile(ur"^%s wins (?:\$| €|) (?P[.\d]+) (USD|EUR|chips)(.*?\[ (?P.*?) \])?" % player_re, re.MULTILINE) self.re_SitsOut = re.compile(ur"^%s sits out" % player_re, re.MULTILINE) - else: - print "*** EverleafToFpdb: compilePlayerRegexs failed" - print players - print self.compiledPlayers - def readSupportedGames(self): return [["ring", "hold", "nl"], ["ring", "hold", "pl"], From eff216919dd7ad03bdfe9a7500438c1c46ac6a80 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Mon, 1 Feb 2010 09:57:28 -0500 Subject: [PATCH 190/320] Everleaf: Change "EUR"(old) to "EURO"(new), still doesn't seem to allow eur import (is that because my site config is set for usd ?) --- pyfpdb/EverleafToFpdb.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index fdc35bf6..5dd8d041 100755 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -38,7 +38,7 @@ class Everleaf(HandHistoryConverter): #re.compile(ur"^(Blinds )?(?P\$| €|)(?P[.0-9]+)/(?:\$| €)?(?P[.0-9]+) (?PNL|PL|) (?P(Hold\'em|Omaha|7 Card Stud))", re.MULTILINE) re_HandInfo = re.compile(ur".*#(?P[0-9]+)\n.*\n(Blinds )?(?:\$| €|)(?P[.0-9]+)/(?:\$| €|)(?P[.0-9]+) (?P.*) - (?P\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P
.+$)", re.MULTILINE) re_Button = re.compile(ur"^Seat (?P
[0-9]+)\.txt") @@ -56,10 +56,10 @@ class Everleaf(HandHistoryConverter): self.re_Antes = re.compile(ur"^%s: posts ante \[(?:\$| €|) (?P[.0-9]+)" % player_re, re.MULTILINE) self.re_BringIn = re.compile(ur"^%s posts bring-in (?:\$| €|)(?P[.0-9]+)\." % player_re, re.MULTILINE) self.re_HeroCards = re.compile(ur"^Dealt to %s \[ (?P.*) \]" % player_re, re.MULTILINE) - self.re_Action = re.compile(ur"^%s(?P: bets| checks| raises| calls| folds)(\s\[(?:\$| €|) (?P[.,\d]+) (USD|EUR|Chips)\])?" % player_re, re.MULTILINE) + self.re_Action = re.compile(ur"^%s(?P: bets| checks| raises| calls| folds)(\s\[(?:\$| €|) (?P[.,\d]+) (USD|EURO|Chips)\])?" % player_re, re.MULTILINE) #self.re_Action = re.compile(ur"^%s(?P: bets| checks| raises| calls| folds| complete to)(\s\[?(?:\$| €|) ?(?P\d+\.?\d*)\.?\s?(USD|EUR|)\]?)?" % player_re, re.MULTILINE) self.re_ShowdownAction = re.compile(ur"^%s shows \[ (?P.*) \]" % player_re, re.MULTILINE) - self.re_CollectPot = re.compile(ur"^%s wins (?:\$| €|) (?P[.\d]+) (USD|EUR|chips)(.*?\[ (?P.*?) \])?" % player_re, re.MULTILINE) + self.re_CollectPot = re.compile(ur"^%s wins (?:\$| €|) (?P[.\d]+) (USD|EURO|chips)(.*?\[ (?P.*?) \])?" % player_re, re.MULTILINE) self.re_SitsOut = re.compile(ur"^%s sits out" % player_re, re.MULTILINE) def readSupportedGames(self): From 86330e536ae5c27e193de2fff66ede4502558db2 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 1 Feb 2010 21:03:51 +0000 Subject: [PATCH 191/320] tidy up logging so that log isn't created in /fpdb/log/ unless it is being used --- pyfpdb/Configuration.py | 7 +++++-- pyfpdb/Database.py | 7 +++++-- pyfpdb/GuiLogView.py | 15 ++++++++------- pyfpdb/fpdb.py | 2 +- pyfpdb/fpdb_import.py | 5 ++++- 5 files changed, 23 insertions(+), 13 deletions(-) mode change 100644 => 100755 pyfpdb/Configuration.py mode change 100644 => 100755 pyfpdb/fpdb_import.py diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py old mode 100644 new mode 100755 index 9c7e44b6..ec4c621e --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -38,6 +38,10 @@ from xml.dom.minidom import Node import logging, logging.config import ConfigParser +# logging has been set up in fpdb.py or HUD_main.py, use their settings: +log = logging.getLogger("config") + + ############################################################################## # Functions for finding config files and setting up logging # Also used in other modules that use logging. @@ -138,8 +142,6 @@ def check_dir(path, create = True): else: return False -# find a logging.conf file and set up logging -log = get_logger("logging.conf", "config") ######################################################################## # application wide consts @@ -458,6 +460,7 @@ class Config: self.dir_config = os.path.dirname(self.file) self.dir_log = os.path.join(self.dir_config, 'log') self.dir_database = os.path.join(self.dir_config, 'database') + self.log_file = os.path.join(self.dir_log, 'logging.out') log = get_logger("logging.conf", "config", log_dir=self.dir_log) # Parse even if there was no real config file found and we are using the example diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index a987b389..e7c01231 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -41,6 +41,10 @@ import Queue import codecs import math +import logging +# logging has been set up in fpdb.py or HUD_main.py, use their settings: +log = logging.getLogger("db") + # pyGTK modules @@ -52,7 +56,6 @@ import Tourney import Charset from Exceptions import * import Configuration -log = Configuration.get_logger("logging.conf","db") # Other library modules @@ -225,7 +228,7 @@ class Database: def __init__(self, c, sql = None): log = Configuration.get_logger("logging.conf", "db", log_dir=c.dir_log) - log.info("Creating Database instance, sql = %s" % sql) + log.debug("Creating Database instance, sql = %s" % sql) self.config = c self.__connected = False self.settings = {} diff --git a/pyfpdb/GuiLogView.py b/pyfpdb/GuiLogView.py index 29385fa0..9dcb9588 100755 --- a/pyfpdb/GuiLogView.py +++ b/pyfpdb/GuiLogView.py @@ -26,13 +26,13 @@ import gtk import gobject import pango -import Configuration +import logging +# logging has been set up in fpdb.py or HUD_main.py, use their settings: +log = logging.getLogger("logview") -log = Configuration.get_logger("logging.conf", "logview") MAX_LINES = 100000 # max lines to display in window EST_CHARS_PER_LINE = 150 # used to guesstimate number of lines in log file -logfile = 'logging.out' # name of logfile class GuiLogView: @@ -41,6 +41,7 @@ class GuiLogView: self.main_window = mainwin self.closeq = closeq + self.logfile = self.config.log_file # name of logfile self.dia = gtk.Dialog(title="Log Messages" ,parent=None ,flags=gtk.DIALOG_DESTROY_WITH_PARENT @@ -117,10 +118,10 @@ class GuiLogView: self.listcols = [] # guesstimate number of lines in file - if os.path.exists(logfile): - stat_info = os.stat(logfile) + if os.path.exists(self.logfile): + stat_info = os.stat(self.logfile) lines = stat_info.st_size / EST_CHARS_PER_LINE - print "logview: size =", stat_info.st_size, "lines =", lines + #print "logview: size =", stat_info.st_size, "lines =", lines # set startline to line number to start display from startline = 0 @@ -129,7 +130,7 @@ class GuiLogView: startline = lines - MAX_LINES l = 0 - for line in open(logfile): + for line in open(self.logfile): # eg line: # 2009-12-02 15:23:21,716 - config DEBUG config logger initialised l = l + 1 diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 58e0128d..c11301a9 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -117,7 +117,6 @@ import Exceptions VERSION = "0.12" -log = Configuration.get_logger("logging.conf", "fpdb") class fpdb: def tab_clicked(self, widget, tab_name): @@ -696,6 +695,7 @@ class fpdb: """Loads profile from the provided path name.""" self.config = Configuration.Config(file=options.config, dbname=options.dbname) log = Configuration.get_logger("logging.conf", "fpdb", log_dir=self.config.dir_log) + print "Logfile is " + os.path.join(self.config.dir_log, 'logging.out') + "\n" if self.config.example_copy: self.info_box( "Config file" , "has been created at:\n%s.\n" % self.config.file diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py old mode 100644 new mode 100755 index a02d3d99..8ba0da34 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -30,6 +30,10 @@ import Queue from collections import deque # using Queue for now import threading +import logging +# logging has been set up in fpdb.py or HUD_main.py, use their settings: +log = logging.getLogger("importer") + import pygtk import gtk @@ -39,7 +43,6 @@ import Database import Configuration import Exceptions -log = Configuration.get_logger("logging.conf", "importer") # database interface modules try: From d4248706e46ba65d5b2a05e2ac1a16421bfd1e32 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 1 Feb 2010 22:31:00 +0000 Subject: [PATCH 192/320] remove surplus get_logger calls, tidy up log messages some more --- pyfpdb/Database.py | 12 ++++++------ pyfpdb/HUD_main.py | 15 +++++++-------- pyfpdb/Hand.py | 9 ++++++--- pyfpdb/HandHistoryConverter.py | 8 ++++++-- pyfpdb/fpdb.py | 3 +++ pyfpdb/fpdb_import.py | 2 +- 6 files changed, 29 insertions(+), 20 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index e7c01231..77ae30f6 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -227,7 +227,7 @@ class Database: def __init__(self, c, sql = None): - log = Configuration.get_logger("logging.conf", "db", log_dir=c.dir_log) + #log = Configuration.get_logger("logging.conf", "db", log_dir=c.dir_log) log.debug("Creating Database instance, sql = %s" % sql) self.config = c self.__connected = False @@ -239,6 +239,7 @@ class Database: self.db_server = db_params['db-server'] self.database = db_params['db-databaseName'] self.host = db_params['db-host'] + self.db_path = '' # where possible avoid creating new SQL instance by using the global one passed in if sql is None: @@ -388,9 +389,9 @@ class Database: log.info("Creating directory: '%s'" % (self.config.dir_database)) os.mkdir(self.config.dir_database) database = os.path.join(self.config.dir_database, database) - log.info("Connecting to SQLite: %(database)s" % {'database':database}) - print "Connecting to SQLite: %(database)s" % {'database':database} - self.connection = sqlite3.connect(database, detect_types=sqlite3.PARSE_DECLTYPES ) + self.db_path = database + log.info("Connecting to SQLite: %(database)s" % {'database':self.db_path}) + self.connection = sqlite3.connect(self.db_path, detect_types=sqlite3.PARSE_DECLTYPES ) sqlite3.register_converter("bool", lambda x: bool(int(x))) sqlite3.register_adapter(bool, lambda x: "1" if x else "0") self.connection.create_function("floor", 1, math.floor) @@ -791,11 +792,10 @@ class Database: def get_player_id(self, config, site, player_name): c = self.connection.cursor() - print "get_player_id: player_name =", player_name, type(player_name) + #print "get_player_id: player_name =", player_name, type(player_name) p_name = Charset.to_utf8(player_name) c.execute(self.sql.query['get_player_id'], (p_name, site)) row = c.fetchone() - print "player id =", row if row: return row[0] else: diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index c792d802..f7979552 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -51,9 +51,6 @@ import gobject # FreePokerTools modules import Configuration -log = Configuration.get_logger("logging.conf", config = 'hud') -log.debug("%s logger initialized." % "hud") - import Database from HandHistoryConverter import getTableTitleRe @@ -66,6 +63,10 @@ elif os.name == 'nt': import Hud +# logger is set up in __init__, create temp logger here +log = Configuration.get_logger("logging.conf", config = 'hud') + + class HUD_main(object): """A main() object to own both the read_stdin thread and the gui.""" # This class mainly provides state for controlling the multiple HUDs. @@ -74,9 +75,10 @@ class HUD_main(object): try: print "HUD_main: starting ..." self.db_name = db_name - self.config = Configuration.Config(file=options.config, dbname=options.dbname) + self.config = Configuration.Config(file=options.config, dbname=db_name) log = Configuration.get_logger("logging.conf", "hud", log_dir=self.config.dir_log) - log.debug("starting ...") + log.info("HUD_main starting") + log.info("Using db name = %s" % (db_name)) self.hud_dict = {} self.hud_params = self.config.get_hud_ui_parameters() @@ -295,9 +297,6 @@ class HUD_main(object): if __name__== "__main__": - log.info("HUD_main starting") - log.info("Using db name = %s" % (options.dbname)) - # start the HUD_main object hm = HUD_main(db_name = options.dbname) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 0f69121a..9bec209b 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -21,7 +21,6 @@ import re import sys import traceback -import logging import os import os.path from decimal import Decimal @@ -30,12 +29,16 @@ import time,datetime from copy import deepcopy import pprint +import logging +# logging has been set up in fpdb.py or HUD_main.py, use their settings: +log = logging.getLogger("parser") + + import Configuration from Exceptions import * import DerivedStats import Card -log = Configuration.get_logger("logging.conf", "parser") class Hand(object): @@ -50,7 +53,7 @@ class Hand(object): def __init__(self, config, sitename, gametype, handText, builtFrom = "HHC"): self.config = config - log = Configuration.get_logger("logging.conf", "db", log_dir=self.config.dir_log) + #log = Configuration.get_logger("logging.conf", "db", log_dir=self.config.dir_log) self.sitename = sitename self.siteId = self.SITEIDS[sitename] self.stats = DerivedStats.DerivedStats(self) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 45760ee6..fa1805e0 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -30,6 +30,11 @@ from xml.dom.minidom import Node import time import datetime +import logging +# logging has been set up in fpdb.py or HUD_main.py, use their settings: +log = logging.getLogger("parser") + + import Hand import Tourney from Exceptions import FpdbParseError @@ -38,7 +43,6 @@ import Configuration import gettext gettext.install('fpdb') -log = Configuration.get_logger("logging.conf", "parser") import pygtk import gtk @@ -65,7 +69,7 @@ out_path (default '-' = sys.stdout) follow : whether to tail -f the input""" self.config = config - log = Configuration.get_logger("logging.conf", "parser", log_dir=self.config.dir_log) + #log = Configuration.get_logger("logging.conf", "parser", log_dir=self.config.dir_log) log.info("HandHistory init - %s subclass, in_path '%s'; out_path '%s'" % (self.sitename, in_path, out_path) ) self.index = index diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index c11301a9..5bef3503 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -721,6 +721,9 @@ class fpdb: err_msg = None try: self.db = Database.Database(self.config, sql = self.sql) + if self.db.get_backend_name() == 'SQLite': + # tell sqlite users where the db file is + print "Connected to SQLite: %(database)s" % {'database':self.db.db_path} except Exceptions.FpdbMySQLAccessDenied: err_msg = "MySQL Server reports: Access denied. Are your permissions set correctly?" except Exceptions.FpdbMySQLNoDatabase: diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 8ba0da34..8b3f71cd 100755 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -68,7 +68,7 @@ class Importer: self.config = config self.sql = sql - log = Configuration.get_logger("logging.conf", "importer", log_dir=self.config.dir_log) + #log = Configuration.get_logger("logging.conf", "importer", log_dir=self.config.dir_log) self.filelist = {} self.dirlist = {} self.siteIds = {} From 96d0e0f1818992359344bf0c55bba22d4c500c49 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 1 Feb 2010 22:56:40 +0000 Subject: [PATCH 193/320] fix key error and add filter to logging.conf --- pyfpdb/Filters.py | 43 +++++++++++++++++++++++++++---------------- pyfpdb/logging.conf | 8 +++++++- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index 96245898..27e5a49d 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -26,16 +26,21 @@ 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 - #print "start of GraphViewer constructor" self.db = db self.cursor = db.cursor self.sql = db.sql @@ -268,10 +273,10 @@ class Filters(threading.Thread): self.callback['button2'] = callback def cardCallback(self, widget, data=None): - print "DEBUG: %s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()]) + log.debug( "%s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()]) ) def createPlayerLine(self, hbox, site, player): - print 'DEBUG :: add:"%s"' % player + log.debug('add:"%s"' % player) label = gtk.Label(site +" id:") hbox.pack_start(label, False, False, 3) @@ -300,14 +305,14 @@ class Filters(threading.Thread): # get_text() returns a str but we want internal variables to be unicode: _guiname = unicode(_name) self.heroes[site] = _guiname -# print "DEBUG: setting heroes[%s]: %s"%(site, self.heroes[site]) +# log.debug("setting heroes[%s]: %s"%(site, self.heroes[site])) def __set_num_hands(self, w, val): try: self.numHands = int(w.get_text()) except: self.numHands = 0 -# print "DEBUG: setting numHands:", self.numHands +# log.debug("setting numHands:", self.numHands) def createSiteLine(self, hbox, site): cb = gtk.CheckButton(site) @@ -332,17 +337,17 @@ class Filters(threading.Thread): def __set_site_select(self, w, site): #print w.get_active() self.sites[site] = w.get_active() - print "self.sites[%s] set to %s" %(site, self.sites[site]) + 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() - print "self.games[%s] set to %s" %(game, self.games[game]) + log.debug("self.games[%s] set to %s" %(game, self.games[game])) def __set_limit_select(self, w, limit): #print w.get_active() self.limits[limit] = w.get_active() - print "self.limit[%s] set to %s" %(limit, self.limits[limit]) + 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: @@ -428,9 +433,11 @@ class Filters(threading.Thread): if self.limits[limit]: if not found[self.type]: if self.type == 'ring': - self.rb['tour'].set_active(True) + if 'tour' in self.rb: + self.rb['tour'].set_active(True) elif self.type == 'tour': - self.rb['ring'].set_active(True) + 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 @@ -452,11 +459,13 @@ class Filters(threading.Thread): if self.limits[limit]: if not found[self.type]: if self.type == 'ring': - self.rb['tour'].set_active(True) + if 'tour' in self.rb: + self.rb['tour'].set_active(True) elif self.type == 'tour': - self.rb['ring'].set_active(True) + if 'ring' in self.rb: + self.rb['ring'].set_active(True) elif limit == "ring": - print "set", limit, "to", self.limits[limit] + log.debug("set", limit, "to", self.limits[limit]) if self.limits[limit]: self.type = "ring" for cb in self.cbLimits.values(): @@ -464,7 +473,7 @@ class Filters(threading.Thread): if self.types[cb.get_children()[0].get_text()] == 'tour': cb.set_active(False) elif limit == "tour": - print "set", limit, "to", self.limits[limit] + log.debug( "set", limit, "to", self.limits[limit] ) if self.limits[limit]: self.type = "tour" for cb in self.cbLimits.values(): @@ -475,12 +484,12 @@ class Filters(threading.Thread): def __set_seat_select(self, w, seat): #print "__set_seat_select: seat =", seat, "active =", w.get_active() self.seats[seat] = w.get_active() - print "self.seats[%s] set to %s" %(seat, self.seats[seat]) + 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() - print "self.groups[%s] set to %s" %(group, self.groups[group]) + log.debug( "self.groups[%s] set to %s" %(group, self.groups[group]) ) def fillPlayerFrame(self, vbox, display): top_hbox = gtk.HBox(False, 0) @@ -579,6 +588,7 @@ class Filters(threading.Thread): self.createGameLine(hbox, line[0]) else: print "INFO: No games returned from database" + log.info("No games returned from database") def fillLimitsFrame(self, vbox, display): top_hbox = gtk.HBox(False, 0) @@ -660,6 +670,7 @@ class Filters(threading.Thread): 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']) diff --git a/pyfpdb/logging.conf b/pyfpdb/logging.conf index a7c0323f..ecd74fcc 100644 --- a/pyfpdb/logging.conf +++ b/pyfpdb/logging.conf @@ -1,5 +1,5 @@ [loggers] -keys=root,fpdb,logview,parser,importer,config,db,hud +keys=root,fpdb,logview,parser,importer,config,db,hud,filter [handlers] keys=consoleHandler,rotatingFileHandler @@ -53,6 +53,12 @@ handlers=consoleHandler,rotatingFileHandler qualname=hud propagate=0 +[logger_filter] +level=INFO +handlers=consoleHandler,rotatingFileHandler +qualname=filter +propagate=0 + [handler_consoleHandler] class=StreamHandler level=ERROR From aea7db22e367bee92eda58ebc72e2ef3808333d0 Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Mon, 1 Feb 2010 18:37:36 -0500 Subject: [PATCH 194/320] Options for logging level and version. Not connected yet. --- pyfpdb/Options.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Options.py b/pyfpdb/Options.py index ab226124..6570dbe4 100644 --- a/pyfpdb/Options.py +++ b/pyfpdb/Options.py @@ -15,9 +15,9 @@ #In the "official" distribution you can find the license in #agpl-3.0.txt in the docs folder of the package. -import os import sys from optparse import OptionParser +# http://docs.python.org/library/optparse.html def fpdb_options(): @@ -41,6 +41,14 @@ def fpdb_options(): parser.add_option("-k", "--konverter", dest="hhc", default="PokerStarsToFpdb", help="Module name for Hand History Converter") + parser.add_option("-l", "--logging", + dest = "log_level", + choices = ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL', 'EMPTY'), + help = "Error logging level. (DEBUG, INFO, WARNING, ERROR, CRITICAL, EMPTY)", + default = 'EMPTY') + parser.add_option("-v", "--version", action = "store_true", + help = "Print version information and exit.") + (options, argv) = parser.parse_args() return (options, argv) From 76f9517655da8881aaabef57996f80254d1a60c2 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Tue, 2 Feb 2010 14:54:27 -0500 Subject: [PATCH 195/320] WinTables will no longer accept trying to attach to "FPDBHUD" titled windows --- pyfpdb/WinTables.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyfpdb/WinTables.py b/pyfpdb/WinTables.py index f834eac9..5bca9e41 100644 --- a/pyfpdb/WinTables.py +++ b/pyfpdb/WinTables.py @@ -50,10 +50,12 @@ class Table(Table_Window): titles = {} win32gui.EnumWindows(win_enum_handler, titles) for hwnd in titles: + # print "searching ", search_string, " in ", titles[hwnd] if re.search(search_string, titles[hwnd]): if 'History for table:' in titles[hwnd]: continue # Everleaf Network HH viewer window if 'HUD:' in titles[hwnd]: continue # FPDB HUD window if 'Chat:' in titles[hwnd]: continue # Some sites (FTP? PS? Others?) have seperable or seperately constructed chat windows + if 'FPDBHUD' in titles[hwnd]: continue # can't attach to ourselves! self.window = hwnd break From fece7c914713c43c0a6c73c8dedd1381b4aa9d0f Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 2 Feb 2010 21:53:03 +0000 Subject: [PATCH 196/320] move fpdb-error-log and HUD-error to APPDATA, renamed as fpdb-errors.txt and HUD-errors.txt to be consistent --- pyfpdb/HUD_main.py | 11 ++++++++--- pyfpdb/fpdb.py | 15 ++++++++------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index f7979552..bae58825 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -35,9 +35,6 @@ import traceback (options, argv) = Options.fpdb_options() -if not options.errorsToConsole: - print "Note: error output is being logged. Any major error will be reported there _only_." - import thread import time import string @@ -79,6 +76,14 @@ class HUD_main(object): log = Configuration.get_logger("logging.conf", "hud", log_dir=self.config.dir_log) log.info("HUD_main starting") log.info("Using db name = %s" % (db_name)) + + if not options.errorsToConsole: + fileName = os.path.join(self.config.dir_log, 'HUD-errors.txt') + print "Note: error output is being diverted to\n"+fileName \ + + "\nAny major error will be reported there _only_.\n" + errorFile = open(fileName, 'w', 0) + sys.stderr = errorFile + self.hud_dict = {} self.hud_params = self.config.get_hud_ui_parameters() diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 5bef3503..d5e0350d 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -53,7 +53,7 @@ if os.name == 'nt': raw_input("Press ENTER to continue.") exit() -print "Python " + sys.version[0:3] + '...\n' +print "Python " + sys.version[0:3] + '...' import traceback import threading @@ -62,12 +62,6 @@ import string cl_options = string.join(sys.argv[1:]) (options, argv) = Options.fpdb_options() -if not options.errorsToConsole: - print "Note: error output is being diverted to fpdb-error-log.txt and HUD-error.txt. Any major error will be reported there _only_." - errorFile = open('fpdb-error-log.txt', 'w', 0) - sys.stderr = errorFile - -#import logging import logging, logging.config try: @@ -910,6 +904,13 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") self.window.show() self.load_profile() + if not options.errorsToConsole: + fileName = os.path.join(self.config.dir_log, 'fpdb-errors.txt') + print "\nNote: error output is being diverted to fpdb-errors.txt and HUD-errors.txt in\n" \ + + self.config.dir_log + "Any major error will be reported there _only_.\n" + errorFile = open(fileName, 'w', 0) + sys.stderr = errorFile + self.statusIcon = gtk.StatusIcon() if os.path.exists(os.path.join(sys.path[0], '../gfx/fpdb-cards.png')): self.statusIcon.set_from_file(os.path.join(sys.path[0], '../gfx/fpdb-cards.png')) From e3679a99fb0f7221798c3415aa98f0f819f8d6ac Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 3 Feb 2010 00:48:45 +0000 Subject: [PATCH 197/320] fix steal calcs --- pyfpdb/DerivedStats.py | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 88bb6407..23f1f99c 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -56,7 +56,6 @@ class DerivedStats(): self.handsplayers[player[1]]['stealAttemptChance'] = False self.handsplayers[player[1]]['stealAttempted'] = False self.handsplayers[player[1]]['foldBbToStealChance'] = False - self.handsplayers[player[1]]['foldBbToStealChance'] = False self.handsplayers[player[1]]['foldSbToStealChance'] = False self.handsplayers[player[1]]['foldedSbToSteal'] = False self.handsplayers[player[1]]['foldedBbToSteal'] = False @@ -281,33 +280,37 @@ class DerivedStats(): def calcSteals(self, hand): """Fills stealAttempt(Chance|ed, fold(Bb|Sb)ToSteal(Chance|) - Steal attemp - open raise on positions 2 1 0 S - i.e. MP3, CO, BU, SB + Steal attempt - open raise on positions 1 0 S - i.e. MP3, CO, BU, SB Fold to steal - folding blind after steal attemp wo any other callers or raisers """ - steal_attemp = False - steal_positions = ('2', '1', '0', 'S') + steal_attempt = False + steal_positions = (1, 0, 'S') if hand.gametype['base'] == 'stud': - steal_positions = ('2', '1', '0') + steal_positions = (2, 1, 0) for action in hand.actions[hand.actionStreets[1]]: pname, act = action[0], action[1] - #print action[0], hp.position, steal_attemp, act - if self.handsplayers[pname]['position'] == 'B': + posn = self.handsplayers[pname]['position'] + #print "\naction:", action[0], posn, type(posn), steal_attempt, act + if posn == 'B': #NOTE: Stud games will never hit this section - self.handsplayers[pname]['foldBbToStealChance'] = steal_attemp - self.handsplayers[pname]['foldBbToSteal'] = self.handsplayers[pname]['foldBbToStealChance'] and act == 'folds' + self.handsplayers[pname]['foldBbToStealChance'] = steal_attempt + self.handsplayers[pname]['foldedBbToSteal'] = steal_attempt and act == 'folds' break - elif self.handsplayers[pname]['position'] == 'S': - self.handsplayers[pname]['foldSbToStealChance'] = steal_attemp - self.handsplayers[pname]['foldSbToSteal'] = self.handsplayers[pname]['foldSbToStealChance'] and act == 'folds' + elif posn == 'S': + self.handsplayers[pname]['foldSbToStealChance'] = steal_attempt + self.handsplayers[pname]['foldedSbToSteal'] = steal_attempt and act == 'folds' - if steal_attemp and act != 'folds': + if steal_attempt and act != 'folds': break - if self.handsplayers[pname]['position'] in steal_positions and not steal_attemp: + if posn in steal_positions and not steal_attempt: self.handsplayers[pname]['stealAttemptChance'] = True if act in ('bets', 'raises'): self.handsplayers[pname]['stealAttempted'] = True - steal_attemp = True + steal_attempt = True + + if posn not in steal_positions and act != 'folds': + break def calc34BetStreet0(self, hand): """Fills street0_(3|4)B(Chance|Done), other(3|4)BStreet0""" From 864454f31c0408e9d24ff2a61c26a4077622dc74 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 3 Feb 2010 01:03:36 +0000 Subject: [PATCH 198/320] change 2 commits to 1, may help sqlite stop locking up --- pyfpdb/fpdb_import.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 8b3f71cd..95ffd525 100755 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -451,14 +451,14 @@ class Importer: to_hud.append(hand.dbid_hands) else: # TODO: Treat empty as an error, or just ignore? log.error("Hand processed but empty") - self.database.commit() + # Call hudcache update if not in bulk import mode # FIXME: Need to test for bulk import that isn't rebuilding the cache if self.callHud: for hand in handlist: if hand is not None: hand.updateHudCache(self.database) - self.database.commit() + self.database.commit() #pipe the Hands.id out to the HUD for hid in to_hud: From 33455cb1acacd092ac2ae955e31d360c24f42409 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 3 Feb 2010 21:52:44 +0800 Subject: [PATCH 199/320] PokerStars: Fix tablename regex to allow a # Occasionally Stars throws up a cash table that looks like PokerStars Game #22920951206: Triple Draw 2-7 Lowball Limit ($0.10/$0.20) - 2008/12/14 17:44:00 ET Table 'T #252691988' 6-max Seat #2 is the button a # was previously excluded from the regex. --- pyfpdb/PokerStarsToFpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index c8bfea70..c2a92881 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -69,7 +69,7 @@ class PokerStars(HandHistoryConverter): re.MULTILINE|re.VERBOSE) re_HandInfo = re.compile(""" - ^Table\s\'(?P
[-\ a-zA-Z\d]+)\'\s + ^Table\s\'(?P
[-\ \#a-zA-Z\d]+)\'\s ((?P\d+)-max\s)? (?P\(Play\sMoney\)\s)? (Seat\s\#(?P
\d+)\)?\s+ (?:[a-zA-Z0-9 ]+\s+\#(?P\d+).+)? (\(No\sDP\)\s)? From 2452293c1ebb3c9fe9cad0be2bc067341d519a27 Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Wed, 3 Mar 2010 13:05:06 -0500 Subject: [PATCH 298/320] Fix problem with old (pre 2010) HHs. --- pyfpdb/PartyPokerToFpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/PartyPokerToFpdb.py b/pyfpdb/PartyPokerToFpdb.py index 759ed33d..46c8776b 100755 --- a/pyfpdb/PartyPokerToFpdb.py +++ b/pyfpdb/PartyPokerToFpdb.py @@ -320,7 +320,7 @@ class PartyPoker(HandHistoryConverter): if key == 'PLAY' and info['PLAY'] != 'Real': # if realy party doesn's save play money hh hand.gametype['currency'] = 'play' - if key == 'MAX': + if key == 'MAX' and info[key] is not None: hand.maxseats = int(info[key]) From a3cab472b1cb069c925f8587c549fd81cafef2b0 Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Wed, 3 Mar 2010 15:08:00 -0500 Subject: [PATCH 299/320] Clean up guessMaxSeats. --- pyfpdb/PartyPokerToFpdb.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/pyfpdb/PartyPokerToFpdb.py b/pyfpdb/PartyPokerToFpdb.py index 46c8776b..f83c8672 100755 --- a/pyfpdb/PartyPokerToFpdb.py +++ b/pyfpdb/PartyPokerToFpdb.py @@ -106,18 +106,12 @@ class PartyPoker(HandHistoryConverter): def guessMaxSeats(self, hand): """Return a guess at max_seats when not specified in HH.""" - try: - m = re_seats.search(hand.handText) - mo = m.groupdict() - mo = _mo['SEATS'] - return mo - except: - mo = self.maxOccSeat(hand) - if mo == 10: return mo - if mo == 2: return 2 - if mo <= 6: return 6 - # there are 9-max tables for cash and 10-max for tournaments - return 9 if hand.gametype['type']=='ring' else 10 + mo = self.maxOccSeat(hand) + if mo == 10: return mo + if mo == 2: return 2 + if mo <= 6: return 6 + # there are 9-max tables for cash and 10-max for tournaments + return 9 if hand.gametype['type']=='ring' else 10 def compilePlayerRegexs(self, hand): players = set([player[1] for player in hand.players]) From 0e707c19f81a56a420dddd1ec19971ddde1ca23f Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 4 Mar 2010 17:50:51 +0800 Subject: [PATCH 300/320] PlayerStats: Fix sorting in # Hands col Patch from Almer Visser. Using %d causes Gtk to order as a string rather than a number. Convert to %1.0f and issue disappears. --- pyfpdb/GuiPlayerStats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 39c6c727..b856a5e2 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -92,7 +92,7 @@ class GuiPlayerStats (threading.Thread): , ["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, "%d", "str"] + , ["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"] From 519494878eb6843b53523b065639d7b2f19ba6ab Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Thu, 4 Mar 2010 11:50:03 -0500 Subject: [PATCH 301/320] Don't try to find out blinds for stud games. --- pyfpdb/PokerStarsToFpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 946d5ea2..bf0e8427 100644 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -181,7 +181,7 @@ class PokerStars(HandHistoryConverter): else: info['type'] = 'tour' - if info['limitType'] == 'fl' and info['bb'] != None and info['type'] == 'ring': + if info['limitType'] == 'fl' and info['bb'] is not None and info['type'] == 'ring' and info['base'] != 'stud': info['sb'] = Lim_Blinds[mg['BB']][0] info['bb'] = Lim_Blinds[mg['BB']][1] From a698b2e16de7a477834449ae6be696c1aed0a535 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 4 Mar 2010 17:50:51 +0800 Subject: [PATCH 302/320] PlayerStats: Fix sorting in # Hands col Patch from Almer Visser. Using %d causes Gtk to order as a string rather than a number. Convert to %1.0f and issue disappears. --- pyfpdb/GuiPlayerStats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 39c6c727..b856a5e2 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -92,7 +92,7 @@ class GuiPlayerStats (threading.Thread): , ["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, "%d", "str"] + , ["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"] From 14d2861cdd634a22fcd71af5e9f07b4717b433f7 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 5 Mar 2010 11:55:00 +0800 Subject: [PATCH 303/320] Re-enable 'variance' for sqlite. --- pyfpdb/SQL.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 116f21f5..fc2bc317 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -2079,8 +2079,7 @@ class Sql: ,100.0*avg((hp.totalProfit+hp.rake)/(gt.bigBlind+0.0)) AS bb100xr ,avg((hp.totalProfit+hp.rake)/100.0) AS profhndxr ,avg(h.seats+0.0) AS avgseats - /*,variance(hp.totalProfit/100.0) AS variance*/ - ,0.0 AS variance + ,variance(hp.totalProfit/100.0) AS variance from HandsPlayers hp inner join Hands h on (h.id = hp.handId) inner join Gametypes gt on (gt.Id = h.gameTypeId) From 685dd68cd14696ffb58d24bd5975ea7121e444de Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 5 Mar 2010 12:06:00 +0800 Subject: [PATCH 304/320] Update version in makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3d8ec313..078a3bd0 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ # Variable definitions -VERSION = 0.12 +VERSION = 0.20 DATE = $(shell date +%Y%m%d) all: From 014ddedc013dcb449596c2475b5744f664013291 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 7 Mar 2010 10:30:56 +0000 Subject: [PATCH 305/320] create db automatically if using sqlite --- pyfpdb/Database.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index f51ce5f5..8939d4b3 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -382,6 +382,7 @@ class Database: print msg raise FpdbError(msg) elif backend == Database.SQLITE: + create = True import sqlite3 if use_pool: sqlite3 = pool.manage(sqlite3, pool_size=1) From 2e83e91ba53802c2a59a93c162d159df51778212 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 8 Mar 2010 22:31:07 +0000 Subject: [PATCH 306/320] add having clause to sqlite version of guistats query --- pyfpdb/SQL.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 51863698..b6eb8ee0 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -2099,6 +2099,7 @@ class Sql: ,plposition ,upper(gt.limitType) ,s.name + having 1 = 1 order by hp.playerId ,gt.base ,gt.category From 04acf25416e4f87e680eb38dce9efeba2fe8974d Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 8 Mar 2010 22:32:09 +0000 Subject: [PATCH 307/320] don't display headings for bottom table when it can't be calculated --- pyfpdb/GuiPlayerStats.py | 41 +++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 3c3f46e3..a4bbdef1 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -208,6 +208,7 @@ class GuiPlayerStats (threading.Thread): 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) @@ -224,25 +225,30 @@ class GuiPlayerStats (threading.Thread): self.addGrid(swin, 'playerDetailedStats', flags, playerids ,sitenos, limits, type, seats, groups, dates, games) - # Separator - vbox2 = gtk.VBox(False, 0) - heading = gtk.Label(self.filterText['handhead']) - heading.show() - vbox2.pack_start(heading, expand=False, padding=3) + if 'allplayers' in groups and groups['allplayers']: + # can't currently do this combination so skip detailed table + show_detail = False - # 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() + 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) - # Detailed table - flags[0] = True - flags[2] = 1 - self.addGrid(swin, 'playerDetailedStats', flags, playerids - ,sitenos, limits, type, seats, groups, dates, games) + # 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) @@ -421,6 +427,7 @@ class GuiPlayerStats (threading.Thread): else: treerow.append(' ') iter = self.liststore[grid].append(treerow) + #print treerow sqlrow += 1 row += 1 vbox.show_all() From 6117eb64c8f30883bb0ca6d192b539157a497429 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 8 Mar 2010 22:47:44 +0000 Subject: [PATCH 308/320] remember separator position when refresh is clicked --- pyfpdb/GuiPlayerStats.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index a4bbdef1..30bef936 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -142,7 +142,7 @@ class GuiPlayerStats (threading.Thread): self.stats_frame = gtk.Frame() self.stats_frame.show() - 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) @@ -155,12 +155,15 @@ class GuiPlayerStats (threading.Thread): # 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 def refreshStats(self, widget, data): + self.last_pos = self.stats_vbox.get_position() try: self.stats_vbox.destroy() except AttributeError: pass self.liststore = [] @@ -170,6 +173,8 @@ class GuiPlayerStats (threading.Thread): 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) def fillStatsFrame(self, vbox): sites = self.filters.getSites() From a10f7c144ea8aa302cc73437b5126f3dce7220ef Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 9 Mar 2010 22:36:03 +0000 Subject: [PATCH 309/320] allow log viewer to view all 4 log/error files --- pyfpdb/GuiLogView.py | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/pyfpdb/GuiLogView.py b/pyfpdb/GuiLogView.py index 9dcb9588..755e1762 100755 --- a/pyfpdb/GuiLogView.py +++ b/pyfpdb/GuiLogView.py @@ -33,6 +33,11 @@ log = logging.getLogger("logview") MAX_LINES = 100000 # max lines to display in window EST_CHARS_PER_LINE = 150 # used to guesstimate number of lines in log file +LOGFILES = [ [ 'Fpdb Errors', 'fpdb-errors.txt', False ] # label, filename, start value + , [ 'Fpdb Log', 'fpdb-log.txt', True ] + , [ 'HUD Errors', 'HUD-errors.txt', False ] + , [ 'HUD Log', 'HUD-log.txt', False ] + ] class GuiLogView: @@ -41,7 +46,7 @@ class GuiLogView: self.main_window = mainwin self.closeq = closeq - self.logfile = self.config.log_file # name of logfile + self.logfile = os.path.join(self.config.dir_log, LOGFILES[1][1]) self.dia = gtk.Dialog(title="Log Messages" ,parent=None ,flags=gtk.DIALOG_DESTROY_WITH_PARENT @@ -69,10 +74,19 @@ class GuiLogView: scrolledwindow.add(self.listview) self.vbox.pack_start(scrolledwindow, expand=True, fill=True, padding=0) + hb = gtk.HBox(False, 0) + grp = None + for logf in LOGFILES: + rb = gtk.RadioButton(group=grp, label=logf[0], use_underline=True) + if grp is None: grp = rb + rb.set_active(logf[2]) + rb.connect('clicked', self.__set_logfile, logf[0]) + hb.pack_start(rb, False, False, 3) refreshbutton = gtk.Button("Refresh") refreshbutton.connect("clicked", self.refresh, None) - self.vbox.pack_start(refreshbutton, False, False, 3) + hb.pack_start(refreshbutton, False, False, 3) refreshbutton.show() + self.vbox.pack_start(hb, False, False, 0) self.listview.show() scrolledwindow.show() @@ -90,6 +104,14 @@ class GuiLogView: self.dia.connect('response', self.dialog_response_cb) + def __set_logfile(self, w, file): + #print "w is", w, "file is", file, "active is", w.get_active() + if w.get_active(): + for logf in LOGFILES: + if logf[0] == file: + self.logfile = os.path.join(self.config.dir_log, logf[1]) + self.refresh(w, file) # params are not used + def dialog_response_cb(self, dialog, response_id): # this is called whether close button is pressed or window is closed self.closeq.put(self.__class__) @@ -131,11 +153,14 @@ class GuiLogView: l = 0 for line in open(self.logfile): - # eg line: + # example line in logfile format: # 2009-12-02 15:23:21,716 - config DEBUG config logger initialised l = l + 1 - if l > startline and len(line) > 49: - iter = self.liststore.append( (line[0:23], line[26:32], line[39:46], line[48:].strip(), True) ) + if l > startline: + if len(line) > 49 and line[23:26] == ' - ' and line[34:39] == ' ': + iter = self.liststore.append( (line[0:23], line[26:32], line[39:46], line[48:].strip(), True) ) + else: + iter = self.liststore.append( ('', '', '', line.strip(), True) ) def sortCols(self, col, n): try: From fb6af1fe75b694995001770eefdaf51412e06d50 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 30 Mar 2010 13:04:39 +0800 Subject: [PATCH 310/320] Fix for PT-Stud exported Stars HH's Exports files as 'RAZZ LIMIT' instead of 'Razz Limit' --- pyfpdb/PokerStarsToFpdb.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index bf0e8427..801f17d6 100644 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -50,8 +50,8 @@ class PokerStars(HandHistoryConverter): (?P([%(LS)s\+\d\.]+\s?(?P%(LEGAL_ISO)s)?)|Freeroll)\s+)? # close paren of tournament info (?PHORSE|8\-Game|HOSE)?\s?\(? - (?PHold\'em|Razz|7\sCard\sStud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball|5\sCard\sDraw)\s - (?PNo\sLimit|Limit|Pot\sLimit)\)?,?\s + (?PHold\'em|Razz|RAZZ|7\sCard\sStud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball|5\sCard\sDraw)\s + (?PNo\sLimit|Limit|LIMIT|Pot\sLimit)\)?,?\s (-\sLevel\s(?P[IVXLC]+)\s)? \(? # open paren of the stakes (?P%(LS)s|)? @@ -148,12 +148,13 @@ class PokerStars(HandHistoryConverter): '1000.00': ('250.00', '500.00')} - limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl' } + limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl', 'LIMIT':'fl' } games = { # base, category "Hold'em" : ('hold','holdem'), 'Omaha' : ('hold','omahahi'), 'Omaha Hi/Lo' : ('hold','omahahilo'), 'Razz' : ('stud','razz'), + 'RAZZ' : ('stud','razz'), '7 Card Stud' : ('stud','studhi'), '7 Card Stud Hi/Lo' : ('stud','studhilo'), 'Badugi' : ('draw','badugi'), From 81c731b42ed54de9a665adfbcedfd979a39d085a Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 15 Apr 2010 14:51:20 +0800 Subject: [PATCH 311/320] Fix for CBet stat Patch from bbtgaf@googlemail.com aka gimick DerivedStats.betStreet() was only functioning if the player was the first person to act on a street. If the player was checked to the function would exit as False before ever finding the player --- pyfpdb/DerivedStats.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 327b8de2..ae581ee1 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -505,9 +505,13 @@ class DerivedStats(): """Returns true if player bet/raised the street as their first action""" betOrRaise = False for act in self.hand.actions[street]: - if act[0] == player and act[1] in ('bets', 'raises'): - betOrRaise = True - else: + if act[0] == player: + if act[1] in ('bets', 'raises'): + betOrRaise = True + else: + # player found but did not bet or raise as their first action break + #else: + # haven't found player's first action yet return betOrRaise From b14bed4e9b5a8cd9e0cb408d4e83d9d2caac2a4c Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 15 Apr 2010 15:48:57 +0800 Subject: [PATCH 312/320] Fix last patch - add pass --- pyfpdb/DerivedStats.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index ae581ee1..4e55cdfc 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -510,6 +510,7 @@ class DerivedStats(): betOrRaise = True else: # player found but did not bet or raise as their first action + pass break #else: # haven't found player's first action yet From 6ba7621f2a4a8eb934f02908c8afeef6d6533a88 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 23 Apr 2010 00:28:30 +0800 Subject: [PATCH 313/320] Fix 'errors' stat in importer Instead of: GuiBulkImport done: Stored: 32 Duplicates: 0 Partial: 0 Errors: 32 in 0.530081987381 seconds - 0/sec We have: GuiBulkImport done: Stored: 0 Duplicates: 0 Partial: 0 Errors: 32 in 0.530081987381 seconds - 0/sec --- pyfpdb/fpdb_import.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 689858e0..56c59b77 100755 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -468,6 +468,7 @@ class Importer: errors = getattr(hhc, 'numErrors') stored = getattr(hhc, 'numHands') stored -= duplicates + stored -= errors else: # conversion didn't work # TODO: appropriate response? From 3dd5f92a3c115f9761e6c51ae78bcb32dcd6d00b Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 23 Apr 2010 00:33:24 +0800 Subject: [PATCH 314/320] Add logging for two areas, fix RAZZ v Razz issue Add ERROR conditions for determineGameType failing, and raise a FpdbParseError in each case --- pyfpdb/PokerStarsToFpdb.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 801f17d6..24cf3bb7 100644 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -135,8 +135,10 @@ class PokerStars(HandHistoryConverter): info = {} m = self.re_GameInfo.search(handText) if not m: - print "DEBUG: determineGameType(): did not match" - return None + tmp = handText[0:100] + log.error("determineGameType: Unable to recognise gametype from: '%s'" % tmp) + log.error("determineGameType: Raising FpdbParseError") + raise FpdbParseError mg = m.groupdict() # translations from captured groups to fpdb info strings @@ -154,7 +156,7 @@ class PokerStars(HandHistoryConverter): 'Omaha' : ('hold','omahahi'), 'Omaha Hi/Lo' : ('hold','omahahilo'), 'Razz' : ('stud','razz'), - 'RAZZ' : ('stud','razz'), + 'RAZZ' : ('stud','razz'), '7 Card Stud' : ('stud','studhi'), '7 Card Stud Hi/Lo' : ('stud','studhilo'), 'Badugi' : ('draw','badugi'), @@ -183,8 +185,13 @@ class PokerStars(HandHistoryConverter): info['type'] = 'tour' if info['limitType'] == 'fl' and info['bb'] is not None and info['type'] == 'ring' and info['base'] != 'stud': - info['sb'] = Lim_Blinds[mg['BB']][0] - info['bb'] = Lim_Blinds[mg['BB']][1] + try: + info['sb'] = Lim_Blinds[mg['BB']][0] + info['bb'] = Lim_Blinds[mg['BB']][1] + except KeyError: + log.error("determineGameType: Lim_Blinds has no lookup for '%s'" % mg['BB']) + log.error("determineGameType: Raising FpdbParseError") + raise FpdbParseError # NB: SB, BB must be interpreted as blinds or bets depending on limit type. return info From 5aadf643be07b1fc12887181a0128265508e91d9 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 23 Apr 2010 00:36:12 +0800 Subject: [PATCH 315/320] Add '2' to the Lim_Blinds lookup table Fixes Dogs import issue. --- pyfpdb/PokerStarsToFpdb.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 24cf3bb7..75cf3cbb 100644 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -144,6 +144,7 @@ class PokerStars(HandHistoryConverter): # translations from captured groups to fpdb info strings Lim_Blinds = { '0.04': ('0.01', '0.02'), '0.10': ('0.02', '0.05'), '0.20': ('0.05', '0.10'), '0.50': ('0.10', '0.25'), '1.00': ('0.25', '0.50'), '2.00': ('0.50', '1.00'), + '2': ('0.50', '1.00'), '4.00': ('1.00', '2.00'), '6.00': ('1.00', '3.00'), '10.00': ('2.00', '5.00'), '20.00': ('5.00', '10.00'), '30.00': ('10.00', '15.00'), '60.00': ('15.00', '30.00'), '100.00': ('25.00', '50.00'),'200.00': ('50.00', '100.00'),'400.00': ('100.00', '200.00'), From c0ebc4b7cf4a039418e9eb0f5e6425312d1e3886 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 22 Apr 2010 23:22:28 +0800 Subject: [PATCH 316/320] Update to Session viewer Fix a couple of crashers - Make sure last session in list is displayed correctly - Actually calculate hands/hour (Thanks Socratic) - Make graph display the correct number of sessions --- pyfpdb/GuiSessionViewer.py | 62 +++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/pyfpdb/GuiSessionViewer.py b/pyfpdb/GuiSessionViewer.py index b5ca0867..d11f83d8 100755 --- a/pyfpdb/GuiSessionViewer.py +++ b/pyfpdb/GuiSessionViewer.py @@ -184,7 +184,7 @@ class GuiSessionViewer (threading.Thread): sitenos.append(siteids[site]) _q = self.sql.query['getPlayerId'] _name = Charset.to_utf8(heroes[site]) - print 'DEBUG(_name) :: %s' % _name + #print 'DEBUG(_name) :: %s' % _name self.cursor.execute(_q, (_name,)) # arg = tuple result = self.db.cursor.fetchall() if len(result) == 1: @@ -262,13 +262,20 @@ class GuiSessionViewer (threading.Thread): times = map(lambda x:long(x[0]), hands) handids = map(lambda x:int(x[1]), hands) winnings = map(lambda x:float(x[4]), hands) - print "DEBUG: len(times) %s" %(len(times)) + #print "DEBUG: len(times) %s" %(len(times)) diffs = diff(times) # This array is the difference in starttime between consecutive hands index = nonzero(diff(times) > THRESHOLD) # This array represents the indexes into 'times' for start/end times of sessions # ie. times[index[0][0]] is the end of the first session #print "DEBUG: len(index[0]) %s" %(len(index[0])) - #print "DEBUG: index %s" %(index) - #print "DEBUG: index[0][0] %s" %(index[0][0]) + if len(index[0]) > 0: + #print "DEBUG: index[0][0] %s" %(index[0][0]) + #print "DEBUG: index %s" %(index) + pass + else: + index = [[0]] + #print "DEBUG: index %s" %(index) + #print "DEBUG: index[0][0] %s" %(index[0][0]) + pass total = 0 last_idx = 0 @@ -281,27 +288,57 @@ class GuiSessionViewer (threading.Thread): results = [] cum_sum = cumsum(winnings) cum_sum = cum_sum/100 + sid = 0 # Take all results and format them into a list for feeding into gui model. for i in range(len(index[0])): - sid = i # Session id hds = index[0][i] - last_idx # Number of hands in session if hds > 0: stime = strftime("%d/%m/%Y %H:%M", localtime(times[last_idx])) # Formatted start time etime = strftime("%d/%m/%Y %H:%M", localtime(times[index[0][i]])) # Formatted end time - hph = (times[index[0][i]] - times[last_idx])/60 # Hands per hour + minutesplayed = (times[index[0][i]] - times[last_idx])/60 + if minutesplayed == 0: + minutesplayed = 1 + hph = hds*60/minutesplayed # Hands per hour won = sum(winnings[last_idx:index[0][i]])/100.0 hwm = max(cum_sum[last_idx:index[0][i]]) lwm = min(cum_sum[last_idx:index[0][i]]) - #print "DEBUG: range: (%s, %s) - (min, max): (%s, %s)" %(last_idx, index[0][i], hwm, lwm) + open = (sum(winnings[:last_idx]))/100 + close = (sum(winnings[:index[0][i]]))/100 + #print "DEBUG: range: (%s, %s) - (min, max): (%s, %s) - (open,close): (%s, %s)" %(last_idx, index[0][i], lwm, hwm, open, close) results.append([sid, hds, stime, etime, hph, won]) - opens.append((sum(winnings[:last_idx]))/100) - closes.append((sum(winnings[:index[0][i]]))/100) + opens.append(open) + closes.append(close) highs.append(hwm) lows.append(lwm) - #print "Hands in session %4s: %4s Start: %s End: %s HPH: %s Profit: %s" %(sid, hds, stime, etime, hph, won) + #print "DEBUG: Hands in session %4s: %4s Start: %s End: %s HPH: %s Profit: %s" %(sid, hds, stime, etime, hph, won) total = total + (index[0][i] - last_idx) last_idx = index[0][i] + 1 + sid = sid+1 + else: + print "hds <= 0" + + #The last session is between times[last_idx:-1] + hds = len(times) - last_idx + stime = strftime("%d/%m/%Y %H:%M", localtime(times[last_idx])) # Formatted start time + etime = strftime("%d/%m/%Y %H:%M", localtime(times[index[0][-1]])) # Formatted end time + minutesplayed = (times[-1] - times[last_idx])/60 + if minutesplayed == 0: + minutesplayed = 1 + hph = hds*60/minutesplayed # Hands per hour + won = sum(winnings[last_idx:-1])/100.0 + hwm = max(cum_sum[last_idx:-1]) + lwm = min(cum_sum[last_idx:-1]) + open = (sum(winnings[:last_idx]))/100 + close = (sum(winnings[:-1]))/100 + #print "DEBUG: range: (%s, %s) - (min, max): (%s, %s) - (open,close): (%s, %s)" %(last_idx, index[0][i], lwm, hwm, open, close) + + results.append([sid, hds, stime, etime, hph, won]) + opens.append(open) + closes.append(close) + highs.append(hwm) + lows.append(lwm) + #print "Hands in session %4s: %4s Start: %s End: %s HPH: %s Profit: %s" %(sid, hds, stime, etime, hph, won) return (results, opens, closes, highs, lows) @@ -330,11 +367,6 @@ class GuiSessionViewer (threading.Thread): def generateGraph(self, opens, closes, highs, lows): self.clearGraphData() - #FIXME: Weird - first data entry is crashing this for me - opens = opens[1:] - closes = closes[1:] - highs = highs[1:] - lows = lows[1:] # print "DEBUG:" # print "highs = %s" % highs # print "lows = %s" % lows From d11623c7364b8b7ed06cfd0e1b790093668ebcc0 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 23 Apr 2010 11:39:52 +0800 Subject: [PATCH 317/320] Update Session viewer based on Socratic comments --- pyfpdb/GuiSessionViewer.py | 61 ++++++++++++++------------------------ 1 file changed, 22 insertions(+), 39 deletions(-) diff --git a/pyfpdb/GuiSessionViewer.py b/pyfpdb/GuiSessionViewer.py index d11f83d8..b4f14d95 100755 --- a/pyfpdb/GuiSessionViewer.py +++ b/pyfpdb/GuiSessionViewer.py @@ -33,7 +33,7 @@ try: from matplotlib.backends.backend_gtkagg import NavigationToolbar2GTKAgg as NavigationToolbar from matplotlib.finance import candlestick2 - from numpy import diff, nonzero, sum, cumsum, max, min + from numpy import diff, nonzero, sum, cumsum, max, min, append # from matplotlib.dates import DateFormatter, WeekdayLocator, HourLocator, \ # DayLocator, MONDAY, timezone @@ -241,6 +241,9 @@ class GuiSessionViewer (threading.Thread): #end def fillStatsFrame(self, vbox): def generateDatasets(self, playerids, sitenos, limits, seats): + THRESHOLD = 1800 # Minimum number of seconds between consecutive hands before being considered a new session + PADDING = 5 # Additional time in minutes to add to a session, session startup, shutdown etc (FiXME: user configurable) + # Get a list of all handids and their timestampts #FIXME: Query still need to filter on blind levels @@ -255,7 +258,6 @@ class GuiSessionViewer (threading.Thread): q = q.replace("", "%s") self.db.cursor.execute(q) - THRESHOLD = 1800 hands = self.db.cursor.fetchall() # Take that list and create an array of the time between hands @@ -263,9 +265,11 @@ class GuiSessionViewer (threading.Thread): handids = map(lambda x:int(x[1]), hands) winnings = map(lambda x:float(x[4]), hands) #print "DEBUG: len(times) %s" %(len(times)) - diffs = diff(times) # This array is the difference in starttime between consecutive hands - index = nonzero(diff(times) > THRESHOLD) # This array represents the indexes into 'times' for start/end times of sessions - # ie. times[index[0][0]] is the end of the first session + diffs = diff(times) # This array is the difference in starttime between consecutive hands + diffs2 = append(diffs,THRESHOLD + 1) # Append an additional session to the end of the diffs, so the next line + # includes an index into the last 'session' + index = nonzero(diffs2 > THRESHOLD) # This array represents the indexes into 'times' for start/end times of sessions + # times[index[0][0]] is the end of the first session, #print "DEBUG: len(index[0]) %s" %(len(index[0])) if len(index[0]) > 0: #print "DEBUG: index[0][0] %s" %(index[0][0]) @@ -278,7 +282,7 @@ class GuiSessionViewer (threading.Thread): pass total = 0 - last_idx = 0 + first_idx = 0 lowidx = 0 uppidx = 0 opens = [] @@ -288,23 +292,24 @@ class GuiSessionViewer (threading.Thread): results = [] cum_sum = cumsum(winnings) cum_sum = cum_sum/100 - sid = 0 + sid = 1 # Take all results and format them into a list for feeding into gui model. for i in range(len(index[0])): - hds = index[0][i] - last_idx # Number of hands in session + hds = index[0][i] - first_idx + 1 # Number of hands in session if hds > 0: - stime = strftime("%d/%m/%Y %H:%M", localtime(times[last_idx])) # Formatted start time + stime = strftime("%d/%m/%Y %H:%M", localtime(times[first_idx])) # Formatted start time etime = strftime("%d/%m/%Y %H:%M", localtime(times[index[0][i]])) # Formatted end time - minutesplayed = (times[index[0][i]] - times[last_idx])/60 + minutesplayed = (times[index[0][i]] - times[first_idx])/60 if minutesplayed == 0: minutesplayed = 1 + minutesplayed = minutesplayed + PADDING hph = hds*60/minutesplayed # Hands per hour - won = sum(winnings[last_idx:index[0][i]])/100.0 - hwm = max(cum_sum[last_idx:index[0][i]]) - lwm = min(cum_sum[last_idx:index[0][i]]) - open = (sum(winnings[:last_idx]))/100 + won = sum(winnings[first_idx:index[0][i]])/100.0 + hwm = max(cum_sum[first_idx:index[0][i]]) + lwm = min(cum_sum[first_idx:index[0][i]]) + open = (sum(winnings[:first_idx]))/100 close = (sum(winnings[:index[0][i]]))/100 - #print "DEBUG: range: (%s, %s) - (min, max): (%s, %s) - (open,close): (%s, %s)" %(last_idx, index[0][i], lwm, hwm, open, close) + #print "DEBUG: range: (%s, %s) - (min, max): (%s, %s) - (open,close): (%s, %s)" %(first_idx, index[0][i], lwm, hwm, open, close) results.append([sid, hds, stime, etime, hph, won]) opens.append(open) @@ -312,34 +317,12 @@ class GuiSessionViewer (threading.Thread): highs.append(hwm) lows.append(lwm) #print "DEBUG: Hands in session %4s: %4s Start: %s End: %s HPH: %s Profit: %s" %(sid, hds, stime, etime, hph, won) - total = total + (index[0][i] - last_idx) - last_idx = index[0][i] + 1 + total = total + (index[0][i] - first_idx) + first_idx = index[0][i] + 1 sid = sid+1 else: print "hds <= 0" - #The last session is between times[last_idx:-1] - hds = len(times) - last_idx - stime = strftime("%d/%m/%Y %H:%M", localtime(times[last_idx])) # Formatted start time - etime = strftime("%d/%m/%Y %H:%M", localtime(times[index[0][-1]])) # Formatted end time - minutesplayed = (times[-1] - times[last_idx])/60 - if minutesplayed == 0: - minutesplayed = 1 - hph = hds*60/minutesplayed # Hands per hour - won = sum(winnings[last_idx:-1])/100.0 - hwm = max(cum_sum[last_idx:-1]) - lwm = min(cum_sum[last_idx:-1]) - open = (sum(winnings[:last_idx]))/100 - close = (sum(winnings[:-1]))/100 - #print "DEBUG: range: (%s, %s) - (min, max): (%s, %s) - (open,close): (%s, %s)" %(last_idx, index[0][i], lwm, hwm, open, close) - - results.append([sid, hds, stime, etime, hph, won]) - opens.append(open) - closes.append(close) - highs.append(hwm) - lows.append(lwm) - #print "Hands in session %4s: %4s Start: %s End: %s HPH: %s Profit: %s" %(sid, hds, stime, etime, hph, won) - return (results, opens, closes, highs, lows) def clearGraphData(self): From c871d7fc2fbe15bb7347be6bf685fab96b54ba46 Mon Sep 17 00:00:00 2001 From: gimick Date: Thu, 15 Apr 2010 23:16:26 +0100 Subject: [PATCH 318/320] gimick - Do not set CBChance if there has been a donkbet --- pyfpdb/DerivedStats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 4e55cdfc..f5278b99 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -368,8 +368,8 @@ class DerivedStats(): name = self.lastBetOrRaiser(hand.actionStreets[i+1]) if name: chance = self.noBetsBefore(hand.actionStreets[i+2], name) - self.handsplayers[name]['street%dCBChance' % (i+1)] = True if chance == True: + self.handsplayers[name]['street%dCBChance' % (i+1)] = True self.handsplayers[name]['street%dCBDone' % (i+1)] = self.betStreet(hand.actionStreets[i+2], name) def calcCheckCallRaise(self, hand): From 6e603149267822b07259d84ffa6c52c0590c8e53 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 23 Apr 2010 11:49:57 +0800 Subject: [PATCH 319/320] First part of making FTP archive files work --- pyfpdb/HandHistoryConverter.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 2053eba9..5b65b955 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -62,7 +62,7 @@ class HandHistoryConverter(): codepage = "cp1252" - def __init__(self, config, in_path = '-', out_path = '-', follow=False, index=0, autostart=True, starsArchive=False): + def __init__(self, config, in_path = '-', out_path = '-', follow=False, index=0, autostart=True, starsArchive=False, ftpArchive=False): """\ in_path (default '-' = sys.stdin) out_path (default '-' = sys.stdout) @@ -75,6 +75,7 @@ follow : whether to tail -f the input""" self.index = index self.starsArchive = starsArchive + self.ftpArchive = ftpArchive self.in_path = in_path self.out_path = out_path @@ -247,6 +248,11 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py. m = re.compile('^Hand #\d+', re.MULTILINE) self.obs = m.sub('', self.obs) + if self.ftpArchive == True: + log.debug("Converting ftpArchive format to readable") + m = re.compile('^\*\*\*\*\*\*+\s#\s\d+\s\*\*\*\*\*+$', re.MULTILINE) + self.obs = m.sub('', self.obs) + if self.obs is None or self.obs == "": log.info("Read no hands.") return [] From 9ac46c8c92c1c135e9741bc8812d39f0dd51eb52 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 23 Apr 2010 17:09:08 +0800 Subject: [PATCH 320/320] Add to Stars limit lookup table. --- pyfpdb/PokerStarsToFpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 75cf3cbb..c964faa5 100644 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -144,7 +144,7 @@ class PokerStars(HandHistoryConverter): # translations from captured groups to fpdb info strings Lim_Blinds = { '0.04': ('0.01', '0.02'), '0.10': ('0.02', '0.05'), '0.20': ('0.05', '0.10'), '0.50': ('0.10', '0.25'), '1.00': ('0.25', '0.50'), '2.00': ('0.50', '1.00'), - '2': ('0.50', '1.00'), + '2': ('0.50', '1.00'), '4': ('1.00', '2.00'), '6': ('1.00', '3.00'), '4.00': ('1.00', '2.00'), '6.00': ('1.00', '3.00'), '10.00': ('2.00', '5.00'), '20.00': ('5.00', '10.00'), '30.00': ('10.00', '15.00'), '60.00': ('15.00', '30.00'), '100.00': ('25.00', '50.00'),'200.00': ('50.00', '100.00'),'400.00': ('100.00', '200.00'),