diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 82a71331..a7be2e10 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -182,57 +182,23 @@ class Database: else: self.sql = sql + self.pcache = None # PlayerId cache + self.cachemiss = 0 # Delete me later - using to count player cache misses + # config while trying out new hudcache mechanism self.use_date_in_hudcache = True - # To add to config: - self.hud_session_gap = 30 # Gap (minutes) between hands that indicates a change of session - # (hands every 2 mins for 1 hour = one session, if followed - # by a 40 minute gap and then more hands on same table that is - # a new session) - self.hud_style = 'T' # A=All-time - # S=Session - # T=timed (last n days) - # Future values may also include: - # H=Hands (last n hands) - self.hud_hands = 2000 # Max number of hands from each player to use for hud stats - self.hud_days = 30 # Max number of days from each player to use for hud stats + #self.hud_hero_style = 'T' # Duplicate set of vars just for hero - not used yet. + #self.hud_hero_hands = 2000 # Idea is that you might want all-time stats for others + #self.hud_hero_days = 30 # but last T days or last H hands for yourself - self.hud_hero_style = 'T' # Duplicate set of vars just for hero - self.hud_hero_hands = 2000 - self.hud_hero_days = 30 + # vars for hand ids or dates fetched according to above config: + self.hand_1day_ago = 0 # max hand id more than 24 hrs earlier than now + self.date_ndays_ago = 'd000000' # date N days ago ('d' + YYMMDD) + self.date_nhands_ago = {} # dates N hands ago per player - not used yet self.cursor = self.fdb.cursor - if self.fdb.wrongDbVersion == False: - # self.hand_1day_ago used to fetch stats for current session (i.e. if hud_style = 'S') - self.hand_1day_ago = 0 - self.cursor.execute(self.sql.query['get_hand_1day_ago']) - row = self.cursor.fetchone() - if row and row[0]: - self.hand_1day_ago = row[0] - #print "hand 1day ago =", self.hand_1day_ago - - # self.date_ndays_ago used if hud_style = 'T' - d = timedelta(days=self.hud_days) - now = datetime.utcnow() - d - self.date_ndays_ago = "d%02d%02d%02d" % (now.year-2000, now.month, now.day) - - # self.hand_nhands_ago is used for fetching stats for last n hands (hud_style = 'H') - # This option not used yet - self.hand_nhands_ago = 0 - # should use aggregated version of query if appropriate - self.cursor.execute(self.sql.query['get_hand_nhands_ago'], (self.hud_hands,self.hud_hands)) - row = self.cursor.fetchone() - if row and row[0]: - self.hand_nhands_ago = row[0] - print "hand n hands ago =", self.hand_nhands_ago - - #self.cursor.execute(self.sql.query['get_table_name'], (hand_id, )) - #row = self.cursor.fetchone() - else: - print "Bailing on DB query, not sure it exists yet" - self.saveActions = False if self.import_options['saveActions'] == False else True self.connection.rollback() # make sure any locks taken so far are released @@ -365,22 +331,67 @@ class Database: winners[row[0]] = row[1] return winners - def get_stats_from_hand(self, hand, aggregate = False): - if self.hud_style == 'S': + def init_hud_stat_vars(self, hud_days): + """Initialise variables used by Hud to fetch stats.""" + + try: + # self.hand_1day_ago used to fetch stats for current session (i.e. if hud_style = 'S') + self.hand_1day_ago = 1 + c = self.get_cursor() + c.execute(self.sql.query['get_hand_1day_ago']) + row = c.fetchone() + if row and row[0]: + self.hand_1day_ago = row[0] + #print "hand 1day ago =", self.hand_1day_ago + + # self.date_ndays_ago used if hud_style = 'T' + d = timedelta(days=hud_days) + now = datetime.utcnow() - d + self.date_ndays_ago = "d%02d%02d%02d" % (now.year-2000, now.month, now.day) + except: + err = traceback.extract_tb(sys.exc_info()[2])[-1] + print "***Error: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) + + def init_player_hud_stat_vars(self, playerid): + # not sure if this is workable, to be continued ... + try: + # self.date_nhands_ago is used for fetching stats for last n hands (hud_style = 'H') + # This option not used yet - needs to be called for each player :-( + self.date_nhands_ago[str(playerid)] = 'd000000' + + # should use aggregated version of query if appropriate + c.execute(self.sql.query['get_date_nhands_ago'], (self.hud_hands, playerid)) + row = c.fetchone() + if row and row[0]: + self.date_nhands_ago[str(playerid)] = row[0] + c.close() + print "date n hands ago = " + self.date_nhands_ago[str(playerid)] + "(playerid "+str(playerid)+")" + except: + err = traceback.extract_tb(sys.exc_info()[2])[-1] + print "***Error: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) + + def get_stats_from_hand(self, hand, aggregate = False, hud_style = 'A', agg_bb_mult = 100): + if hud_style == 'S': + return( self.get_stats_from_hand_session(hand) ) - else: # self.hud_style == A + + else: # hud_style == A + + if hud_style == 'T': + stylekey = self.date_ndays_ago + #elif hud_style == 'H': + # stylekey = date_nhands_ago needs array by player here ... + else: # assume A (all-time) + stylekey = '0000000' # all stylekey values should be higher than this + if aggregate: query = 'get_stats_from_hand_aggregated' + subs = (hand, stylekey, agg_bb_mult, agg_bb_mult) else: query = 'get_stats_from_hand' - - if self.hud_style == 'T': - stylekey = self.date_ndays_ago - else: # assume A (all-time) - stylekey = '0000000' # all stylekey values should be higher than this + subs = (hand, stylekey) - subs = (hand, hand, stylekey) - #print "get stats: hud style =", self.hud_style, "subs =", subs + #print "get stats: hud style =", hud_style, "query =", query, "subs =", subs c = self.connection.cursor() # now get the stats @@ -399,17 +410,14 @@ class Database: # uses query on handsplayers instead of hudcache to get stats on just this session def get_stats_from_hand_session(self, hand): - if self.hud_style == 'S': - query = self.sql.query['get_stats_from_hand_session'] - if self.db_server == 'mysql': - query = query.replace("", 'signed ') - else: - query = query.replace("", '') - else: # self.hud_style == A - return None + query = self.sql.query['get_stats_from_hand_session'] + if self.db_server == 'mysql': + query = query.replace("", 'signed ') + else: + query = query.replace("", '') subs = (self.hand_1day_ago, hand) - c = self.connection.cursor() + c = self.get_cursor() # now get the stats #print "sess_stats: subs =", subs, "subs[0] =", subs[0] @@ -725,8 +733,8 @@ class Database: if self.backend == self.MYSQL_INNODB: print "creating mysql index ", idx['tab'], idx['col'] try: - c.execute( "alter table %s add index %s(%s)" - , (idx['tab'],idx['col'],idx['col']) ) + s = "alter table %s add index %s(%s)" % (idx['tab'],idx['col'],idx['col']) + c.execute(s) except: print " create fk failed: " + str(sys.exc_info()) elif self.backend == self.PGSQL: @@ -734,9 +742,8 @@ class Database: # mod to use tab_col for index name? print "creating pg index ", idx['tab'], idx['col'] try: - print "create index %s_%s_idx on %s(%s)" % (idx['tab'], idx['col'], idx['tab'], idx['col']) - c.execute( "create index %s_%s_idx on %s(%s)" - % (idx['tab'], idx['col'], idx['tab'], idx['col']) ) + s = "create index %s_%s_idx on %s(%s)" % (idx['tab'], idx['col'], idx['tab'], idx['col']) + c.execute(s) except: print " create index failed: " + str(sys.exc_info()) else: @@ -851,20 +858,18 @@ class Database: if self.backend == self.MYSQL_INNODB: print "creating mysql index ", idx['tab'], idx['col'] try: - self.get_cursor().execute( "alter table %s add index %s(%s)" - , (idx['tab'],idx['col'],idx['col']) ) + s = "create index %s on %s(%s)" % (idx['col'],idx['tab'],idx['col']) + self.get_cursor().execute(s) except: - pass + print " create idx failed: " + str(sys.exc_info()) elif self.backend == self.PGSQL: # mod to use tab_col for index name? print "creating pg index ", idx['tab'], idx['col'] try: - print "create index %s_%s_idx on %s(%s)" % (idx['tab'], idx['col'], idx['tab'], idx['col']) - self.get_cursor().execute( "create index %s_%s_idx on %s(%s)" - % (idx['tab'], idx['col'], idx['tab'], idx['col']) ) + s = "create index %s_%s_idx on %s(%s)" % (idx['tab'], idx['col'], idx['tab'], idx['col']) + self.get_cursor().execute(s) except: - print " ERROR! :-(" - pass + print " create idx failed: " + str(sys.exc_info()) else: print "Only MySQL and Postgres supported so far" return -1 @@ -964,6 +969,30 @@ class Database: print "Error during fdb.lock_for_insert:", str(sys.exc_value) #end def lock_for_insert + def getSqlPlayerIDs(self, pnames, siteid): + result = {} + if(self.pcache == None): + self.pcache = LambdaDict(lambda key:self.insertPlayer(key, siteid)) + + for player in pnames: + result[player] = self.pcache[player] + + return result + + def insertPlayer(self, name, site_id): + self.cachemiss += 1 + result = None + c = self.get_cursor() + c.execute ("SELECT id FROM Players WHERE name=%s", (name,)) + tmp=c.fetchall() + if (len(tmp)==0): #new player + c.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)", (name, site_id)) + c.execute ("SELECT id FROM Players WHERE name=%s", (name,)) + tmp=c.fetchall() + #print "recognisePlayerIDs, names[i]:",names[i],"tmp:",tmp + print "DEBUG: cache misses: %s" %self.cachemiss + return tmp[0][0] + def store_the_hand(self, h): """Take a HandToWrite object and store it in the db""" @@ -1780,3 +1809,17 @@ if __name__=="__main__": print "press enter to continue" sys.stdin.readline() + + +#Code borrowed from http://push.cx/2008/caching-dictionaries-in-python-vs-ruby +class LambdaDict(dict): + def __init__(self, l): + super(LambdaDict, self).__init__() + self.l = l + + def __getitem__(self, key): + if key in self: + return self.get(key) + else: + self.__setitem__(key, self.l(key)) + return self.get(key) diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py index aefe17d1..e86bab67 100755 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -31,10 +31,11 @@ import Configuration import string class GuiAutoImport (threading.Thread): - def __init__(self, settings, config): + def __init__(self, settings, config, sql): """Constructor for GuiAutoImport""" self.settings=settings self.config=config + self.sql = sql imp = self.config.get_import_parameters() @@ -44,7 +45,7 @@ class GuiAutoImport (threading.Thread): self.input_settings = {} self.pipe_to_hud = None - self.importer = fpdb_import.Importer(self,self.settings, self.config) + self.importer = fpdb_import.Importer(self, self.settings, self.config, self.sql) self.importer.setCallHud(True) self.importer.setMinPrint(settings['minPrint']) self.importer.setQuiet(False) diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index 3cd592cc..658c0527 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -210,7 +210,7 @@ - + @@ -219,7 +219,7 @@ - + @@ -228,7 +228,7 @@ - + @@ -237,7 +237,7 @@ - + @@ -246,7 +246,7 @@ - + @@ -255,7 +255,7 @@ - + @@ -274,18 +274,18 @@ - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index 7378d6f7..b240b64c 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -31,6 +31,7 @@ Main for FreePokerTools HUD. import sys import os import Options +import traceback (options, sys.argv) = Options.fpdb_options() @@ -55,7 +56,23 @@ import Database import Tables import Hud -aggregate_stats = {"ring": False, "tour": False} # config file! +# To add to config: +aggregate_stats = {"ring": False, "tour": False} # uses agg_bb_mult +hud_style = 'A' # A=All-time + # S=Session + # T=timed (last n days - set hud_days to required value) + # Future values may also include: + # H=Hands (last n hands) +hud_days = 90 # Max number of days from each player to use for hud stats +agg_bb_mult = 100 # 1 = no aggregation. When aggregating stats across levels larger blinds + # must be < (agg_bb_mult * smaller blinds) to be aggregated + # ie. 100 will aggregate almost everything, 2 will probably agg just the + # next higher and lower levels into the current one, try 3/10/30/100 +hud_session_gap = 30 # Gap (minutes) between hands that indicates a change of session + # (hands every 2 mins for 1 hour = one session, if followed + # by a 40 minute gap and then more hands on same table that is + # a new session) +#hud_hands = 0 # Max number of hands from each player to use for hud stats (not used) class HUD_main(object): """A main() object to own both the read_stdin thread and the gui.""" @@ -144,6 +161,7 @@ class HUD_main(object): # need their own access to the database, but should open their own # if it is required. self.db_connection = Database.Database(self.config, self.db_name, 'temp') + self.db_connection.init_hud_stat_vars(hud_days) tourny_finder = re.compile('(\d+) (\d+)') while 1: # wait for a new hand number on stdin @@ -156,13 +174,16 @@ class HUD_main(object): # if there is a db error, complain, skip hand, and proceed try: (table_name, max, poker_game, type) = self.db_connection.get_table_name(new_hand_id) - stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, aggregate = aggregate_stats[type]) + stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, aggregate_stats[type] + ,hud_style, agg_bb_mult) + cards = self.db_connection.get_cards(new_hand_id) comm_cards = self.db_connection.get_common_cards(new_hand_id) if comm_cards != {}: # stud! cards['common'] = comm_cards['common'] except Exception, err: - print "db error: skipping ", new_hand_id, err + err = traceback.extract_tb(sys.exc_info()[2])[-1] + print "db error: skipping "+str(new_hand_id)+" "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) if new_hand_id: # new_hand_id is none if we had an error prior to the store sys.stderr.write("Database error %s in hand %d. Skipping.\n" % (err, int(new_hand_id))) continue diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 0dbb9674..4d571b76 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -40,10 +40,12 @@ class Hand(object): LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'} SYMBOL = {'USD': '$', 'EUR': u'$', 'T$': '', 'play': ''} MS = {'horse' : 'HORSE', '8game' : '8-Game', 'hose' : 'HOSE', 'ha': 'HA'} + SITEIDS = {'Fulltilt':1, 'PokerStars':2, 'Everleaf':3, 'Win2day':4, 'OnGame':5, 'UltimateBet':6, 'Betfair':7} def __init__(self, sitename, gametype, handText, builtFrom = "HHC"): self.sitename = sitename + self.siteId = self.SITEIDS[sitename] self.stats = DerivedStats.DerivedStats(self) self.gametype = gametype self.starttime = 0 diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 39315ee1..1f109475 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -167,9 +167,9 @@ class Sql: ################################ if db_server == 'mysql': self.query['list_tables'] = """SHOW TABLES""" - elif db_server == 'postgresql': # what is the correct value here? + elif db_server == 'postgresql': self.query['list_tables'] = """SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'""" - elif db_server == 'sqlite': # what is the correct value here? + elif db_server == 'sqlite': self.query['list_tables'] = """SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;""" @@ -188,10 +188,10 @@ class Sql: self.query['createSettingsTable'] = """CREATE TABLE Settings ( version SMALLINT NOT NULL) ENGINE=INNODB""" - elif db_server == 'postgresql': # what is the correct value here? + elif db_server == 'postgresql': self.query['createSettingsTable'] = """CREATE TABLE Settings (version SMALLINT)""" - elif db_server == 'sqlite': # what is the correct value here? + elif db_server == 'sqlite': self.query['createSettingsTable'] = """CREATE TABLE Settings (version INTEGER) """ @@ -206,12 +206,12 @@ class Sql: name varchar(32) NOT NULL, currency char(3) NOT NULL) ENGINE=INNODB""" - elif db_server == 'postgresql': # what is the correct value here? + elif db_server == 'postgresql': self.query['createSitesTable'] = """CREATE TABLE Sites ( id SERIAL, PRIMARY KEY (id), name varchar(32), currency char(3))""" - elif db_server == 'sqlite': # what is the correct value here? + elif db_server == 'sqlite': self.query['createSitesTable'] = """CREATE TABLE Sites ( id INTEGER PRIMARY KEY, name TEXT NOT NULL, @@ -236,7 +236,7 @@ class Sql: smallBet int NOT NULL, bigBet int NOT NULL) ENGINE=INNODB""" - elif db_server == 'postgresql': # what is the correct value here? + elif db_server == 'postgresql': self.query['createGametypesTable'] = """CREATE TABLE Gametypes ( id SERIAL, PRIMARY KEY (id), siteId INTEGER, FOREIGN KEY (siteId) REFERENCES Sites(id), @@ -249,7 +249,7 @@ class Sql: bigBlind int, smallBet int, bigBet int)""" - elif db_server == 'sqlite': # what is the correct value here? + elif db_server == 'sqlite': self.query['createGametypesTable'] = """CREATE TABLE GameTypes ( id INTEGER PRIMARY KEY, siteId INTEGER, @@ -277,14 +277,14 @@ class Sql: comment text, commentTs DATETIME) ENGINE=INNODB""" - elif db_server == 'postgresql': # what is the correct value here? + elif db_server == 'postgresql': self.query['createPlayersTable'] = """CREATE TABLE Players ( id SERIAL, PRIMARY KEY (id), name VARCHAR(32), siteId INTEGER, FOREIGN KEY (siteId) REFERENCES Sites(id), comment text, commentTs timestamp without time zone)""" - elif db_server == 'sqlite': # what is the correct value here? + elif db_server == 'sqlite': self.query['createPlayersTable'] = """CREATE TABLE Players ( id INTEGER PRIMARY KEY, name TEXT, @@ -308,7 +308,7 @@ class Sql: ratingTime DATETIME NOT NULL, handCount int NOT NULL) ENGINE=INNODB""" - elif db_server == 'postgresql': # what is the correct value here? + elif db_server == 'postgresql': self.query['createAutoratesTable'] = """CREATE TABLE Autorates ( id BIGSERIAL, PRIMARY KEY (id), playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id), @@ -317,7 +317,7 @@ class Sql: shortDesc char(8), ratingTime timestamp without time zone, handCount int)""" - elif db_server == 'sqlite': # what is the correct value here? + elif db_server == 'sqlite': self.query['createAutoratesTable'] = """ """ @@ -360,7 +360,7 @@ class Sql: comment TEXT, commentTs DATETIME) ENGINE=INNODB""" - elif db_server == 'postgresql': # what is the correct value here? + elif db_server == 'postgresql': self.query['createHandsTable'] = """CREATE TABLE Hands ( id BIGSERIAL, PRIMARY KEY (id), tableName VARCHAR(20) NOT NULL, @@ -394,7 +394,7 @@ class Sql: showdownPot INT, /* pot size at sd/street7 */ comment TEXT, commentTs timestamp without time zone)""" - elif db_server == 'sqlite': # what is the correct value here? + elif db_server == 'sqlite': self.query['createHandsTable'] = """CREATE TABLE Hands ( id INTEGER PRIMARY KEY, tableName TEXT(20), @@ -422,7 +422,7 @@ class Sql: knockout INT NOT NULL, rebuyOrAddon BOOLEAN NOT NULL) ENGINE=INNODB""" - elif db_server == 'postgresql': # what is the correct value here? + elif db_server == 'postgresql': self.query['createTourneyTypesTable'] = """CREATE TABLE TourneyTypes ( id SERIAL, PRIMARY KEY (id), siteId INT, FOREIGN KEY (siteId) REFERENCES Sites(id), @@ -430,7 +430,7 @@ class Sql: fee INT, knockout INT, rebuyOrAddon BOOLEAN)""" - elif db_server == 'sqlite': # what is the correct value here? + elif db_server == 'sqlite': self.query['createTourneyTypesTable'] = """ """ @@ -449,7 +449,7 @@ class Sql: comment TEXT, commentTs DATETIME) ENGINE=INNODB""" - elif db_server == 'postgresql': # what is the correct value here? + elif db_server == 'postgresql': self.query['createTourneysTable'] = """CREATE TABLE Tourneys ( id SERIAL, PRIMARY KEY (id), tourneyTypeId INT, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), @@ -459,7 +459,7 @@ class Sql: startTime timestamp without time zone, comment TEXT, commentTs timestamp without time zone)""" - elif db_server == 'sqlite': # what is the correct value here? + elif db_server == 'sqlite': self.query['createTourneysTable'] = """CREATE TABLE TourneyTypes ( id INTEGER PRIMARY KEY, siteId INTEGER, @@ -591,7 +591,7 @@ class Sql: FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id)) ENGINE=INNODB""" - elif db_server == 'postgresql': # what is the correct value here? + elif db_server == 'postgresql': self.query['createHandsPlayersTable'] = """CREATE TABLE HandsPlayers ( id BIGSERIAL, PRIMARY KEY (id), handId BIGINT NOT NULL, FOREIGN KEY (handId) REFERENCES Hands(id), @@ -708,7 +708,7 @@ class Sql: actionString VARCHAR(15), FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id))""" - elif db_server == 'sqlite': # what is the correct value here? + elif db_server == 'sqlite': self.query['createHandsPlayersTable'] = """ """ @@ -727,7 +727,7 @@ class Sql: comment TEXT, commentTs DATETIME) ENGINE=INNODB""" - elif db_server == 'postgresql': # what is the correct value here? + elif db_server == 'postgresql': self.query['createTourneysPlayersTable'] = """CREATE TABLE TourneysPlayers ( id BIGSERIAL, PRIMARY KEY (id), tourneyId INT, FOREIGN KEY (tourneyId) REFERENCES Tourneys(id), @@ -737,7 +737,7 @@ class Sql: winnings INT, comment TEXT, commentTs timestamp without time zone)""" - elif db_server == 'sqlite': # what is the correct value here? + elif db_server == 'sqlite': self.query['createTourneysPlayersTable'] = """ """ @@ -757,7 +757,7 @@ class Sql: comment TEXT, commentTs DATETIME) ENGINE=INNODB""" - elif db_server == 'postgresql': # what is the correct value here? + elif db_server == 'postgresql': self.query['createHandsActionsTable'] = """CREATE TABLE HandsActions ( id BIGSERIAL, PRIMARY KEY (id), handsPlayerId BIGINT, FOREIGN KEY (handsPlayerId) REFERENCES HandsPlayers(id), @@ -768,7 +768,7 @@ class Sql: amount INT, comment TEXT, commentTs timestamp without time zone)""" - elif db_server == 'sqlite': # what is the correct value here? + elif db_server == 'sqlite': self.query['createHandsActionsTable'] = """ """ @@ -877,7 +877,7 @@ class Sql: street4Raises INT) ENGINE=INNODB""" - elif db_server == 'postgresql': # what is the correct value here? + elif db_server == 'postgresql': self.query['createHudCacheTable'] = """CREATE TABLE HudCache ( id BIGSERIAL, PRIMARY KEY (id), gametypeId INT, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), @@ -976,28 +976,28 @@ class Sql: street3Raises INT, street4Raises INT) """ - elif db_server == 'sqlite': # what is the correct value here? + elif db_server == 'sqlite': self.query['createHudCacheTable'] = """ """ if db_server == 'mysql': self.query['addTourneyIndex'] = """ALTER TABLE Tourneys ADD INDEX siteTourneyNo(siteTourneyNo)""" - elif db_server == 'postgresql': # what is the correct value here? + elif db_server == 'postgresql': self.query['addTourneyIndex'] = """CREATE INDEX siteTourneyNo ON Tourneys (siteTourneyNo)""" - elif db_server == 'sqlite': # what is the correct value here? + elif db_server == 'sqlite': self.query['addHandsIndex'] = """ """ if db_server == 'mysql': self.query['addHandsIndex'] = """ALTER TABLE Hands ADD INDEX siteHandNo(siteHandNo)""" - elif db_server == 'postgresql': # what is the correct value here? + elif db_server == 'postgresql': self.query['addHandsIndex'] = """CREATE INDEX siteHandNo ON Hands (siteHandNo)""" - elif db_server == 'sqlite': # what is the correct value here? + elif db_server == 'sqlite': self.query['addHandsIndex'] = """ """ if db_server == 'mysql': self.query['addPlayersIndex'] = """ALTER TABLE Players ADD INDEX name(name)""" - elif db_server == 'postgresql': # what is the correct value here? + elif db_server == 'postgresql': self.query['addPlayersIndex'] = """CREATE INDEX name ON Players (name)""" - elif db_server == 'sqlite': # what is the correct value here? + elif db_server == 'sqlite': self.query['addPlayersIndex'] = """ """ @@ -1073,7 +1073,7 @@ class Sql: sum(hc.street4CheckCallRaiseChance) AS ccr_opp_4, sum(hc.street4CheckCallRaiseDone) AS ccr_4 FROM Hands h - INNER JOIN HandsPlayers hp ON (hp.handId = %s) + INNER JOIN HandsPlayers hp ON (hp.handId = h.id) INNER JOIN HudCache hc ON ( hc.PlayerId = hp.PlayerId+0 AND hc.gametypeId+0 = h.gametypeId+0) INNER JOIN Players p ON (p.id = hp.PlayerId+0) @@ -1155,27 +1155,31 @@ class Sql: sum(hc.street4CheckCallRaiseChance) AS ccr_opp_4, sum(hc.street4CheckCallRaiseDone) AS ccr_4 FROM Hands h - INNER JOIN HandsPlayers hp ON (hp.handId = %s) + INNER JOIN HandsPlayers hp ON (hp.handId = h.id) INNER JOIN HudCache hc ON (hc.playerId = hp.playerId) INNER JOIN Players p ON (p.id = hc.playerId) WHERE h.id = %s AND hc.styleKey > %s /* styleKey is currently 'd' (for date) followed by a yyyymmdd date key. Set it to 0000000 or similar to get all records */ - /* also check activeseats here? even if only 3 groups eg 2-3/4-6/7+ ?? + /* Note: s means the placeholder 'percent's but we can't include that + in comments. (db api thinks they are actual arguments) + Could also check activeseats here? even if only 3 groups eg 2-3/4-6/7+ ?? e.g. could use a multiplier: - AND h.seats > %s / 1.25 and hp.seats < %s * 1.25 - where %s is the number of active players at the current table (and + AND h.seats > s / 1.25 and hp.seats < s * 1.25 + where s is the number of active players at the current table (and 1.25 would be a config value so user could change it) */ AND hc.gametypeId+0 in (SELECT gt1.id from Gametypes gt1, Gametypes gt2 - WHERE gt1.siteid = gt2.siteid - AND gt1.type = gt2.type - AND gt1.category = gt2.category - AND gt1.limittype = gt2.limittype + WHERE gt1.siteid = gt2.siteid /* find gametypes where these match: */ + AND gt1.type = gt2.type /* ring/tourney */ + AND gt1.category = gt2.category /* holdem/stud*/ + AND gt1.limittype = gt2.limittype /* fl/nl */ + AND gt1.bigblind < gt2.bigblind * %s /* bigblind similar size */ + AND gt1.bigblind > gt2.bigblind / %s AND gt2.id = h.gametypeId) - GROUP BY hc.PlayerId, p.name, hc.styleKey + GROUP BY hc.PlayerId, p.name """ if db_server == 'mysql': @@ -1406,16 +1410,50 @@ class Sql: select coalesce(max(id),0) from Hands where handStart < date_sub(utc_timestamp(), interval '1' day)""" - else: # assume postgresql + elif db_server == 'postgresql': self.query['get_hand_1day_ago'] = """ select coalesce(max(id),0) from Hands where handStart < now() at time zone 'UTC' - interval '1 day'""" - #if db_server == 'mysql': - self.query['get_hand_nhands_ago'] = """ - select coalesce(greatest(max(id),%s)-%s,0) - from Hands""" + # not used yet ... + # gets a date, would need to use handsplayers (not hudcache) to get exact hand Id + if db_server == 'mysql': + self.query['get_date_nhands_ago'] = """ + select concat( 'd', date_format(max(h.handStart), '%Y%m%d') ) + from (select hp.playerId + ,coalesce(greatest(max(hp.handId)-%s,1),1) as maxminusx + from HandsPlayers hp + where hp.playerId = %s + group by hp.playerId) hp2 + inner join HandsPlayers hp3 on ( hp3.handId <= hp2.maxminusx + and hp3.playerId = hp2.playerId) + inner join Hands h on (h.id = hp3.handId) + """ + elif db_server == 'postgresql': + self.query['get_date_nhands_ago'] = """ + select 'd' || to_char(max(h3.handStart), 'YYMMDD') + from (select hp.playerId + ,coalesce(greatest(max(hp.handId)-%s,1),1) as maxminusx + from HandsPlayers hp + where hp.playerId = %s + group by hp.playerId) hp2 + inner join HandsPlayers hp3 on ( hp3.handId <= hp2.maxminusx + and hp3.playerId = hp2.playerId) + inner join Hands h on (h.id = hp3.handId) + """ + elif db_server == 'sqlite': # untested guess at query: + self.query['get_date_nhands_ago'] = """ + select 'd' || strftime(max(h3.handStart), 'YYMMDD') + from (select hp.playerId + ,coalesce(greatest(max(hp.handId)-%s,1),1) as maxminusx + from HandsPlayers hp + where hp.playerId = %s + group by hp.playerId) hp2 + inner join HandsPlayers hp3 on ( hp3.handId <= hp2.maxminusx + and hp3.playerId = hp2.playerId) + inner join Hands h on (h.id = hp3.handId) + """ # used in GuiPlayerStats: self.query['getPlayerId'] = """SELECT id from Players where name = %s""" @@ -1586,7 +1624,7 @@ class Sql: ,upper(gt.limitType) ,s.name """ - #elif db_server == 'sqlite': # what is the correct value here? + #elif db_server == 'sqlite': # self.query['playerDetailedStats'] = """ """ if db_server == 'mysql': @@ -1798,7 +1836,7 @@ class Sql: ) hprof2 on hprof2.gtId = stats.gtId order by stats.base, stats.limittype, stats.bigBlindDesc desc """ - #elif db_server == 'sqlite': # what is the correct value here? + #elif db_server == 'sqlite': # self.query['playerStats'] = """ """ if db_server == 'mysql': @@ -2073,7 +2111,7 @@ class Sql: order by stats.category, stats.limitType, stats.bigBlindDesc desc , cast(stats.PlPosition as smallint) """ - #elif db_server == 'sqlite': # what is the correct value here? + #elif db_server == 'sqlite': # self.query['playerStatsByPosition'] = """ """ self.query['getRingProfitAllHandsPlayerIdSite'] = """ diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 7f648b52..37907397 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -491,7 +491,7 @@ class fpdb: def tab_auto_import(self, widget, data=None): """opens the auto import tab""" - new_aimp_thread=GuiAutoImport.GuiAutoImport(self.settings, self.config) + new_aimp_thread=GuiAutoImport.GuiAutoImport(self.settings, self.config, self.sql) self.threads.append(new_aimp_thread) aimp_tab=new_aimp_thread.get_vbox() self.add_and_display_tab(aimp_tab, "Auto Import") diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index c1d835b8..094b6d18 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -392,17 +392,17 @@ class Importer: mod = __import__(filter) obj = getattr(mod, filter_name, None) if callable(obj): - conv = obj(in_path = file, out_path = out_path, index = 0) # Index into file 0 until changeover - if(conv.getStatus() and self.NEWIMPORT == False): + hhc = obj(in_path = file, out_path = out_path, index = 0) # Index into file 0 until changeover + if(hhc.getStatus() and self.NEWIMPORT == False): (stored, duplicates, partial, errors, ttime) = self.import_fpdb_file(db, out_path, site, q) - elif (conv.getStatus() and self.NEWIMPORT == True): + elif (hhc.getStatus() and self.NEWIMPORT == True): #This code doesn't do anything yet handlist = hhc.getProcessedHands() self.pos_in_file[file] = hhc.getLastCharacterRead() for hand in handlist: - hand.prepInsert() - hand.insert() + #hand.prepInsert() + hand.insert(self.database) else: # conversion didn't work # TODO: appropriate response?