From 9d87e350821aa90234a44b4bf5d5583fa5faa793 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 9 Jun 2009 21:38:30 +0100 Subject: [PATCH 001/143] fix quit option and postgres/windows connecting after last merges --- pyfpdb/fpdb.py | 2 +- pyfpdb/fpdb_db.py | 27 +++++++++++++++++++++------ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 79dab478..c0f63a04 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -409,7 +409,7 @@ class fpdb: return self.fdb_lock.get_global_lock() #end def obtain_global_lock - def quit(self, widget, data): + def quit(self, widget, data=None): print "Quitting normally" #check if current settings differ from profile, if so offer to save or abort self.db.disconnect() diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index e0ccd813..7c1fc800 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -179,13 +179,28 @@ class fpdb_db: # For local domain-socket connections, only DB name is # needed, and everything else is in fact undefined and/or # flat out wrong + # sqlcoder: This database only connect failed in my windows setup?? + # Modifed it to try the 4 parameter style if the first connect fails - does this work everywhere? + connected = False if self.host == "localhost" or self.host == "127.0.0.1": - self.db = psycopg2.connect(database = database) - else: - self.db = psycopg2.connect(host = host, - user = user, - password = password, - database = database) + try: + self.db = psycopg2.connect(database = database) + connected = True + except: + pass + #msg = "PostgreSQL direct connection to database (%s) failed, trying with user ..." % (database,) + #print msg + #raise fpdb_simple.FpdbError(msg) + if not connected: + try: + self.db = psycopg2.connect(host = host, + user = user, + password = password, + database = database) + except: + msg = "PostgreSQL connection to database (%s) user (%s) failed." % (database, user) + print msg + raise fpdb_simple.FpdbError(msg) else: raise fpdb_simple.FpdbError("unrecognised database backend:"+backend) self.cursor=self.db.cursor() From 680e5c2f897589fd893cf6cf2484507184edf18d Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 9 Jun 2009 22:22:10 +0100 Subject: [PATCH 002/143] use new more flexible function to decide whether to drop indexes --- pyfpdb/fpdb_import.py | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 9b779574..99330bb9 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -165,9 +165,10 @@ class Importer: start = datetime.datetime.now() print "started at", start, "--", len(self.filelist), "files to import.", self.settings['dropIndexes'] if self.settings['dropIndexes'] == 'auto': - self.settings['dropIndexes'] = self.calculate_auto() + self.settings['dropIndexes'] = self.calculate_auto2(10.0, 500.0) if self.settings['dropIndexes'] == 'drop': self.fdb.prepareBulkImport() + #self.settings['updateHudCache'] = self.calculate_auto2(10.0, 500.0) totstored = 0 totdups = 0 totpartial = 0 @@ -202,6 +203,40 @@ class Importer: if self.settings['handsInDB'] > 50000: return "don't drop" return "drop" + def calculate_auto2(self, scale, increment): + """A second heuristic to determine a reasonable value of drop/don't drop + This one adds up size of files to import to guess number of hands in them + Example values of scale and increment params might be 10 and 500 meaning + roughly: drop if importing more than 10% (100/scale) of hands in db or if + less than 500 hands in db""" + size_per_hand = 1300.0 # wag based on a PS 6-up FLHE file. Actual value not hugely important + # as values of scale and increment compensate for it anyway. + # decimal used to force float arithmetic + + # get number of hands in db + if 'handsInDB' not in self.settings: + try: + tmpcursor = self.fdb.db.cursor() + tmpcursor.execute("Select count(1) from Hands;") + self.settings['handsInDB'] = tmpcursor.fetchone()[0] + except: + pass # if this fails we're probably doomed anyway + + # add up size of import files + total_size = 0.0 + for file in self.filelist: + if os.path.exists(file): + stat_info = os.stat(file) + total_size += stat_info.st_size + + # if hands_in_db is zero or very low, we want to drop indexes, otherwise compare + # import size with db size somehow: + #print "auto2: handsindb =", self.settings['handsInDB'], "total_size =", total_size, "size_per_hand =", \ + # size_per_hand, "inc =", increment + if self.settings['handsInDB'] < scale * (total_size/size_per_hand) + increment: + return "drop" + return "don't drop" + #Run import on updated files, then store latest update time. def runUpdated(self): #Check for new files in monitored directories From b935a5ad67e3f88f765499f33a832500690cc939 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 9 Jun 2009 22:55:18 +0100 Subject: [PATCH 003/143] pass all settings through so that a new one can be used to skip updating hudcache (not used yet) --- pyfpdb/fpdb_import.py | 2 +- pyfpdb/fpdb_save_to_db.py | 36 ++++++++++++++++++++++-------------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 99330bb9..3fa20b40 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -394,7 +394,7 @@ class Importer: self.hand=hand try: - handsId = fpdb_parse_logic.mainParser(self.settings['db-backend'], self.fdb.db + handsId = fpdb_parse_logic.mainParser(self.settings, self.fdb.db ,self.fdb.cursor, self.siteIds[site], category, hand, self.config) self.fdb.db.commit() diff --git a/pyfpdb/fpdb_save_to_db.py b/pyfpdb/fpdb_save_to_db.py index 3c99d084..d06f8c45 100644 --- a/pyfpdb/fpdb_save_to_db.py +++ b/pyfpdb/fpdb_save_to_db.py @@ -35,11 +35,12 @@ SQLITE = 4 # # no graphs #stores a stud/razz hand into the database -def ring_stud(config, backend, db, cursor, base, category, site_hand_no, gametype_id, hand_start_time +def ring_stud(config, settings, db, cursor, base, category, site_hand_no, gametype_id, hand_start_time ,names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes ,action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName ,seatNos): + backend = settings['db-backend'] import_options = config.get_import_parameters() saveActions = False if import_options['saveActions'] == False else True @@ -55,7 +56,8 @@ def ring_stud(config, backend, db, cursor, base, category, site_hand_no, gametyp ,start_cashes, antes, card_values ,card_suits, winnings, rakes, seatNos) - fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': + fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) if saveActions: fpdb_simple.storeActions(cursor, hands_players_ids, action_types @@ -63,12 +65,13 @@ def ring_stud(config, backend, db, cursor, base, category, site_hand_no, gametyp return hands_id #end def ring_stud -def ring_holdem_omaha(config, backend, db, cursor, base, category, site_hand_no, gametype_id +def ring_holdem_omaha(config, settings, db, cursor, base, category, site_hand_no, gametype_id ,hand_start_time, names, player_ids, start_cashes, positions, card_values ,card_suits, board_values, board_suits, winnings, rakes, action_types, allIns ,action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): """stores a holdem/omaha hand into the database""" + backend = settings['db-backend'] import_options = config.get_import_parameters() saveActions = False if import_options['saveActions'] == False else True fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False @@ -90,10 +93,11 @@ def ring_holdem_omaha(config, backend, db, cursor, base, category, site_hand_no, , positions, card_values, card_suits, winnings, rakes, seatNos, hudImportData) t4 = time() #print "ring holdem, backend=%d" % backend - if fastStoreHudCache: - fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - else: - fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': + if fastStoreHudCache: + fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + else: + fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) t5 = time() fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) t6 = time() @@ -104,7 +108,7 @@ def ring_holdem_omaha(config, backend, db, cursor, base, category, site_hand_no, return hands_id #end def ring_holdem_omaha -def tourney_holdem_omaha(config, backend, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout +def tourney_holdem_omaha(config, settings, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout ,entries, prizepool, tourney_start, payin_amounts, ranks, tourneyTypeId ,siteId #end of tourney specific params ,site_hand_no, gametype_id, hand_start_time, names, player_ids @@ -113,6 +117,7 @@ def tourney_holdem_omaha(config, backend, db, cursor, base, category, siteTourne ,actionNos, hudImportData, maxSeats, tableName, seatNos): """stores a tourney holdem/omaha hand into the database""" + backend = settings['db-backend'] import_options = config.get_import_parameters() saveActions = True if import_options['saveActions'] == True else False fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False @@ -131,10 +136,11 @@ def tourney_holdem_omaha(config, backend, db, cursor, base, category, siteTourne , card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids) #print "tourney holdem, backend=%d" % backend - if fastStoreHudCache: - fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - else: - fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': + if fastStoreHudCache: + fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + else: + fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) @@ -143,13 +149,14 @@ def tourney_holdem_omaha(config, backend, db, cursor, base, category, siteTourne return hands_id #end def tourney_holdem_omaha -def tourney_stud(config, backend, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries +def tourney_stud(config, settings, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries ,prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteId ,siteHandNo, gametypeId, handStartTime, names, playerIds, startCashes, antes ,cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts ,actionNos, hudImportData, maxSeats, tableName, seatNos): #stores a tourney stud/razz hand into the database + backend = settings['db-backend'] import_options = config.get_import_parameters() saveActions = True if import_options['saveActions'] == True else False fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False @@ -166,7 +173,8 @@ def tourney_stud(config, backend, db, cursor, base, category, siteTourneyNo, buy , playerIds, startCashes, antes, cardValues, cardSuits , winnings, rakes, seatNos, tourneys_players_ids) - fpdb_simple.storeHudCache(backend, cursor, base, category, gametypeId, hand_start_time, playerIds, hudImportData) + if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': + fpdb_simple.storeHudCache(backend, cursor, base, category, gametypeId, hand_start_time, playerIds, hudImportData) if saveActions: fpdb_simple.storeActions(cursor, hands_players_ids, actionTypes, allIns, actionAmounts, actionNos) From e212bbd751771e984a3271727e828951f580aece Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 10 Jun 2009 18:19:49 +0800 Subject: [PATCH 004/143] Remove unused file --- pyfpdb/FpdbRegex.py | 161 -------------------------------------------- 1 file changed, 161 deletions(-) delete mode 100644 pyfpdb/FpdbRegex.py diff --git a/pyfpdb/FpdbRegex.py b/pyfpdb/FpdbRegex.py deleted file mode 100644 index 8bfb9362..00000000 --- a/pyfpdb/FpdbRegex.py +++ /dev/null @@ -1,161 +0,0 @@ -# pokerstars_cash.py -# -*- coding: iso-8859-15 -# -# PokerStats, an online poker statistics tracking software for Linux -# Copyright (C) 2007-2008 Mika Boström -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, version 3 of the License. -# - -# Modified for use in fpdb by Carl Gherardi - -import re - -# These are PokerStars specific; -# More importantly, they are currently valid for cash game only. -##### -# XXX: There was a weird problem with saved hand histories in PokerStars -# client 2.491; if a user was present on the table (and thus anywhere in -# the hand history), with non-standard characters in their username, the -# client would prepend a literal Ctrl-P (ASCII 16, 0x10) character to -# the hand history title line. Hence, to allow these strangely saved -# hands to be parsed and imported, there is a conditional "one extra -# character" allowed at the start of the new hand regex. - - -class FpdbRegex: - def __init__(self): - self.__GAME_INFO_REGEX='' - self.__SPLIT_HAND_REGEX='\n\n\n' - self.__NEW_HAND_REGEX='^.?PokerStars Game #\d+:\s+Hold\'em' - self.__HAND_INFO_REGEX='^.*#(\d+):\s+(\S+)\s([\s\S]+)\s\(\$?([.0-9]+)/\$?([.0-9]+)\)\s-\s(\S+)\s-?\s?(\S+)\s\(?(\w+)\)?' - self.__TABLE_INFO_REGEX='^\S+\s+\'.*\'\s+(\d+)-max\s+Seat\s#(\d+)' - self.__PLAYER_INFO_REGEX='^Seat\s(\d+):\s(.*)\s\(\$?([.\d]+)\s' - self.__POST_SB_REGEX='^(.*):\sposts small blind' - self.__POST_BB_REGEX='^(.*):\sposts big blind' - self.__POST_BOTH_REGEX='^(.*):\sposts small & big blinds' - self.__HAND_STAGE_REGEX='^\*{3}\s(.*)\s\*{3}' - self.__HOLE_CARD_REGEX='^\*{3}\sHOLE CARDS' - self.__FLOP_CARD_REGEX='^\*{3}\sFLOP\s\*{3}\s\[(\S{2})\s(\S{2})\s(\S{2})\]' - self.__TURN_CARD_REGEX='^\*{3}\sTURN\s\*{3}\s\[\S{2}\s\S{2}\s\S{2}\]\s\[(\S{2})\]' - self.__RIVER_CARD_REGEX='^\*{3}\sRIVER\s\*{3}\s\[\S{2}\s\S{2}\s\S{2}\s\S{2}\]\s\[(\S{2})\]' - self.__SHOWDOWN_REGEX='^\*{3}\sSHOW DOWN' - self.__SUMMARY_REGEX='^\*{3}\sSUMMARY' - self.__UNCALLED_BET_REGEX='^Uncalled bet \(\$([.\d]+)\) returned to (.*)' - self.__POT_AND_RAKE_REGEX='^Total\spot\s\$([.\d]+).*\|\sRake\s\$([.\d]+)' - self.__COLLECT_POT_REGEX='^(.*)\scollected\s\$([.\d]+)\sfrom\s((main|side)\s)?pot' - self.__HERO_CARDS_REGEX='^Dealt\sto\s(.*)\s\[(\S{2})\s(\S{2})\]' - self.__SHOWN_CARDS_REGEX='^(.*):\sshows\s\[(\S{2})\s(\S{2})\]' - self.__ACTION_STEP_REGEX='^(.*):\s(bets|checks|raises|calls|folds)((\s\$([.\d]+))?(\sto\s\$([.\d]+))?)?' - - self.__SHOWDOWN_ACTION_REGEX='^(.*):\s(shows|mucks)' - self.__SUMMARY_CARDS_REGEX='^Seat\s\d+:\s(.*)\s(showed|mucked)\s\[(\S{2})\s(\S{2})\]' - self.__SUMMARY_CARDS_EXTRA_REGEX='^Seat\s\d+:\s(.*)\s(\(.*\)\s)(showed|mucked)\s\[(\S{2})\s(\S{2})\]' - - def compileRegexes(self): - ### Compile the regexes - self.game_info_re = re.compile(self.__GAME_INFO_REGEX) - self.split_hand_re = re.compile(self.__SPLIT_HAND_REGEX) - self.hand_start_re = re.compile(self.__NEW_HAND_REGEX) - self.hand_info_re = re.compile(self.__HAND_INFO_REGEX) - self.table_info_re = re.compile(self.__TABLE_INFO_REGEX) - self.player_info_re = re.compile(self.__PLAYER_INFO_REGEX) - self.small_blind_re = re.compile(self.__POST_SB_REGEX) - self.big_blind_re = re.compile(self.__POST_BB_REGEX) - self.both_blinds_re = re.compile(self.__POST_BOTH_REGEX) - self.hand_stage_re = re.compile(self.__HAND_STAGE_REGEX) - self.hole_cards_re = re.compile(self.__HOLE_CARD_REGEX) - self.flop_cards_re = re.compile(self.__FLOP_CARD_REGEX) - self.turn_card_re = re.compile(self.__TURN_CARD_REGEX) - self.river_card_re = re.compile(self.__RIVER_CARD_REGEX) - self.showdown_re = re.compile(self.__SHOWDOWN_REGEX) - self.summary_re = re.compile(self.__SUMMARY_REGEX) - self.uncalled_bet_re = re.compile(self.__UNCALLED_BET_REGEX) - self.collect_pot_re = re.compile(self.__COLLECT_POT_REGEX) - self.hero_cards_re = re.compile(self.__HERO_CARDS_REGEX) - self.cards_shown_re = re.compile(self.__SHOWN_CARDS_REGEX) - self.summary_cards_re = re.compile(self.__SUMMARY_CARDS_REGEX) - self.summary_cards_extra_re = re.compile(self.__SUMMARY_CARDS_EXTRA_REGEX) - self.action_re = re.compile(self.__ACTION_STEP_REGEX) - self.rake_re = re.compile(self.__POT_AND_RAKE_REGEX) - self.showdown_action_re = re.compile(self.__SHOWDOWN_ACTION_REGEX) - - # Set methods for plugins to override - - def setGameInfoRegex(self, string): - self.__GAME_INFO_REGEX = string - - def setSplitHandRegex(self, string): - self.__SPLIT_HAND_REGEX = string - - def setNewHandRegex(self, string): - self.__NEW_HAND_REGEX = string - - def setHandInfoRegex(self, string): - self.__HAND_INFO_REGEX = string - - def setTableInfoRegex(self, string): - self.__TABLE_INFO_REGEX = string - - def setPlayerInfoRegex(self, string): - self.__PLAYER_INFO_REGEX = string - - def setPostSbRegex(self, string): - self.__POST_SB_REGEX = string - - def setPostBbRegex(self, string): - self.__POST_BB_REGEX = string - - def setPostBothRegex(self, string): - self.__POST_BOTH_REGEX = string - - def setHandStageRegex(self, string): - self.__HAND_STAGE_REGEX = string - - def setHoleCardRegex(self, string): - self.__HOLE_CARD_REGEX = string - - def setFlopCardRegex(self, string): - self.__FLOP_CARD_REGEX = string - - def setTurnCardRegex(self, string): - self.__TURN_CARD_REGEX = string - - def setRiverCardRegex(self, string): - self.__RIVER_CARD_REGEX = string - - def setShowdownRegex(self, string): - self.__SHOWDOWN_REGEX = string - - def setSummaryRegex(self, string): - self.__SUMMARY_REGEX = string - - def setUncalledBetRegex(self, string): - self.__UNCALLED_BET_REGEX = string - - def setCollectPotRegex(self, string): - self.__COLLECT_POT_REGEX = string - - def setHeroCardsRegex(self, string): - self.__HERO_CARDS_REGEX = string - - def setShownCardsRegex(self, string): - self.__SHOWN_CARDS_REGEX = string - - def setSummaryCardsRegex(self, string): - self.__SUMMARY_CARDS_REGEX = string - - def setSummaryCardsExtraRegex(self, string): - self.__SUMMARY_CARDS_EXTRA_REGEX = string - - def setActionStepRegex(self, string): - self.__ACTION_STEP_REGEX = string - - def setPotAndRakeRegex(self, string): - self.__POT_AND_RAKE_REGEX = string - - def setShowdownActionRegex(self, string): - self.__SHOWDOWN_ACTION_REGEX = string - From ed9f02b11390fb63fb1be989ca615d108be4fba4 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 10 Jun 2009 20:48:33 +0800 Subject: [PATCH 005/143] Revert "pass all settings through so that a new one can be used to skip updating hudcache (not used yet)" This reverts commit b935a5ad67e3f88f765499f33a832500690cc939. --- pyfpdb/fpdb_import.py | 2 +- pyfpdb/fpdb_save_to_db.py | 36 ++++++++++++++---------------------- 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 3fa20b40..99330bb9 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -394,7 +394,7 @@ class Importer: self.hand=hand try: - handsId = fpdb_parse_logic.mainParser(self.settings, self.fdb.db + handsId = fpdb_parse_logic.mainParser(self.settings['db-backend'], self.fdb.db ,self.fdb.cursor, self.siteIds[site], category, hand, self.config) self.fdb.db.commit() diff --git a/pyfpdb/fpdb_save_to_db.py b/pyfpdb/fpdb_save_to_db.py index d06f8c45..3c99d084 100644 --- a/pyfpdb/fpdb_save_to_db.py +++ b/pyfpdb/fpdb_save_to_db.py @@ -35,12 +35,11 @@ SQLITE = 4 # # no graphs #stores a stud/razz hand into the database -def ring_stud(config, settings, db, cursor, base, category, site_hand_no, gametype_id, hand_start_time +def ring_stud(config, backend, db, cursor, base, category, site_hand_no, gametype_id, hand_start_time ,names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes ,action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName ,seatNos): - backend = settings['db-backend'] import_options = config.get_import_parameters() saveActions = False if import_options['saveActions'] == False else True @@ -56,8 +55,7 @@ def ring_stud(config, settings, db, cursor, base, category, site_hand_no, gamety ,start_cashes, antes, card_values ,card_suits, winnings, rakes, seatNos) - if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': - fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) if saveActions: fpdb_simple.storeActions(cursor, hands_players_ids, action_types @@ -65,13 +63,12 @@ def ring_stud(config, settings, db, cursor, base, category, site_hand_no, gamety return hands_id #end def ring_stud -def ring_holdem_omaha(config, settings, db, cursor, base, category, site_hand_no, gametype_id +def ring_holdem_omaha(config, backend, db, cursor, base, category, site_hand_no, gametype_id ,hand_start_time, names, player_ids, start_cashes, positions, card_values ,card_suits, board_values, board_suits, winnings, rakes, action_types, allIns ,action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): """stores a holdem/omaha hand into the database""" - backend = settings['db-backend'] import_options = config.get_import_parameters() saveActions = False if import_options['saveActions'] == False else True fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False @@ -93,11 +90,10 @@ def ring_holdem_omaha(config, settings, db, cursor, base, category, site_hand_no , positions, card_values, card_suits, winnings, rakes, seatNos, hudImportData) t4 = time() #print "ring holdem, backend=%d" % backend - if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': - if fastStoreHudCache: - fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - else: - fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + if fastStoreHudCache: + fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + else: + fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) t5 = time() fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) t6 = time() @@ -108,7 +104,7 @@ def ring_holdem_omaha(config, settings, db, cursor, base, category, site_hand_no return hands_id #end def ring_holdem_omaha -def tourney_holdem_omaha(config, settings, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout +def tourney_holdem_omaha(config, backend, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout ,entries, prizepool, tourney_start, payin_amounts, ranks, tourneyTypeId ,siteId #end of tourney specific params ,site_hand_no, gametype_id, hand_start_time, names, player_ids @@ -117,7 +113,6 @@ def tourney_holdem_omaha(config, settings, db, cursor, base, category, siteTourn ,actionNos, hudImportData, maxSeats, tableName, seatNos): """stores a tourney holdem/omaha hand into the database""" - backend = settings['db-backend'] import_options = config.get_import_parameters() saveActions = True if import_options['saveActions'] == True else False fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False @@ -136,11 +131,10 @@ def tourney_holdem_omaha(config, settings, db, cursor, base, category, siteTourn , card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids) #print "tourney holdem, backend=%d" % backend - if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': - if fastStoreHudCache: - fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - else: - fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + if fastStoreHudCache: + fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + else: + fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) @@ -149,14 +143,13 @@ def tourney_holdem_omaha(config, settings, db, cursor, base, category, siteTourn return hands_id #end def tourney_holdem_omaha -def tourney_stud(config, settings, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries +def tourney_stud(config, backend, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries ,prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteId ,siteHandNo, gametypeId, handStartTime, names, playerIds, startCashes, antes ,cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts ,actionNos, hudImportData, maxSeats, tableName, seatNos): #stores a tourney stud/razz hand into the database - backend = settings['db-backend'] import_options = config.get_import_parameters() saveActions = True if import_options['saveActions'] == True else False fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False @@ -173,8 +166,7 @@ def tourney_stud(config, settings, db, cursor, base, category, siteTourneyNo, bu , playerIds, startCashes, antes, cardValues, cardSuits , winnings, rakes, seatNos, tourneys_players_ids) - if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': - fpdb_simple.storeHudCache(backend, cursor, base, category, gametypeId, hand_start_time, playerIds, hudImportData) + fpdb_simple.storeHudCache(backend, cursor, base, category, gametypeId, hand_start_time, playerIds, hudImportData) if saveActions: fpdb_simple.storeActions(cursor, hands_players_ids, actionTypes, allIns, actionAmounts, actionNos) From b1ea38bea9361b678b1cc98487547a88c8845734 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 14 Jun 2009 23:14:53 -0400 Subject: [PATCH 006/143] Add -c config cl option. Fpdb passes cl options to HUD. --- pyfpdb/Configuration.py | 1 + pyfpdb/GuiAutoImport.py | 7 ++++++- pyfpdb/HUD_main.py | 31 +++++++++++++++------------- pyfpdb/Hud.py | 2 +- pyfpdb/Options.py | 45 +++++++++++++++++++++++++++++++++++++++++ pyfpdb/fpdb.py | 15 ++++++-------- 6 files changed, 76 insertions(+), 25 deletions(-) create mode 100644 pyfpdb/Options.py diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 1d93f3f1..0ea4b371 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -250,6 +250,7 @@ class Config: self.default_config_path = self.get_default_config_path() if file != None: # configuration file path has been passed + file = os.path.expanduser(file) if not os.path.exists(file): print "Configuration file %s not found. Using defaults." % (file) sys.stderr.write("Configuration file %s not found. Using defaults." % (file)) diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py index 2b4c8b76..7f6c80e8 100755 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -28,6 +28,7 @@ import time import fpdb_import from optparse import OptionParser import Configuration +import string class GuiAutoImport (threading.Thread): def __init__(self, settings, config): @@ -165,7 +166,11 @@ class GuiAutoImport (threading.Thread): command = os.path.join(sys.path[0], 'HUD_main.py') #command = self.config.execution_path('HUD_main.py') # Hi Ray. Sorry about this, kludging. bs = 1 - self.pipe_to_hud = subprocess.Popen((command, self.database), bufsize = bs, stdin = subprocess.PIPE, + print "GUI:options =", self.settings['cl_options'] + options = string.split(self.settings['cl_options']) + cl = [command, ] + options + print "cl =", cl + self.pipe_to_hud = subprocess.Popen(cl, bufsize = bs, stdin = subprocess.PIPE, universal_newlines=True) # self.pipe_to_hud = subprocess.Popen((command, self.database), bufsize = bs, stdin = subprocess.PIPE, # universal_newlines=True) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index 64cafaf8..2ffd057b 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -29,12 +29,20 @@ Main for FreePokerTools HUD. # Standard Library modules import sys - -# redirect the stderr -errorfile = open('HUD-error.txt', 'w', 0) -sys.stderr = errorfile - import os +import Options + +(options, sys.argv) = Options.fpdb_options() + +print "HUD: dbname =", options.dbname +print "HUD: config =", options.config +print "HUD: logging =", options.errorsToConsole + +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 thread import time import string @@ -59,7 +67,7 @@ class HUD_main(object): def __init__(self, db_name = 'fpdb'): self.db_name = db_name - self.config = Configuration.Config() + self.config = Configuration.Config(file=options.config, dbname=options.dbname) self.hud_dict = {} # a thread to read stdin @@ -198,17 +206,12 @@ class HUD_main(object): self.db_connection.connection.rollback() if __name__== "__main__": - sys.stderr.write("HUD_main starting\n") -# database name can be passed on command line - try: - db_name = sys.argv[1] - except: - db_name = 'fpdb' - sys.stderr.write("Using db name = %s\n" % (db_name)) + sys.stderr.write("HUD_main starting\n") + sys.stderr.write("Using db name = %s\n" % (options.dbname)) # start the HUD_main object - hm = HUD_main(db_name = db_name) + hm = HUD_main(db_name = options.dbname) # start the event loop gtk.main() diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 363175a1..56ad08f3 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -43,7 +43,7 @@ import Configuration import Stats import Mucked import Database -import HUD_main +#import HUD_main def importName(module_name, name): """Import a named object 'name' from module 'module_name'.""" diff --git a/pyfpdb/Options.py b/pyfpdb/Options.py new file mode 100644 index 00000000..38307d40 --- /dev/null +++ b/pyfpdb/Options.py @@ -0,0 +1,45 @@ +#!/usr/bin/python + +#Copyright 2008 Ray E. Barker +#This program is free software: you can redistribute it and/or modify +#it under the terms of the GNU Affero General Public License as published by +#the Free Software Foundation, version 3 of the License. +# +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. +# +#You should have received a copy of the GNU Affero General Public License +#along with this program. If not, see . +#In the "official" distribution you can find the license in +#agpl-3.0.txt in the docs folder of the package. + +import os +import sys +from optparse import OptionParser + +def fpdb_options(): + + """Process command line options for fpdb and HUD_main.""" + parser = OptionParser() + parser.add_option("-x", "--errorsToConsole", + action="store_true", + help="If passed error output will go to the console rather than .") + parser.add_option("-d", "--databaseName", + dest="dbname", default="fpdb", + help="Overrides the default database name") + parser.add_option("-c", "--configFile", + dest="config", default=None, + help="Specifies a configuration file.") + (options, sys.argv) = parser.parse_args() + return (options, sys.argv) + +if __name__== "__main__": + (options, sys.argv) = fpdb_options() + print "errorsToConsole =", options.errorsToConsole + print "database name =", options.dbname + print "config file =", options.config + + print "press enter to end" + sys.stdin.readline() \ No newline at end of file diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index c0f63a04..b03e8424 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -17,15 +17,11 @@ import os import sys -from optparse import OptionParser +import Options +import string - -parser = OptionParser() -parser.add_option("-x", "--errorsToConsole", action="store_true", - help="If passed error output will go to the console rather than .") -parser.add_option("-d", "--databaseName", dest="dbname", default="fpdb", - help="Overrides the default database name") -(options, sys.argv) = parser.parse_args() +cl_options = string.join(sys.argv[1:]) +(options, sys.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_." @@ -356,6 +352,7 @@ class fpdb: else: self.settings['os']="windows" + self.settings.update({'cl_options': cl_options}) self.settings.update(self.config.get_db_parameters()) self.settings.update(self.config.get_tv_parameters()) self.settings.update(self.config.get_import_parameters()) @@ -486,7 +483,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") def __init__(self): self.threads=[] self.db=None - self.config = Configuration.Config(dbname=options.dbname) + self.config = Configuration.Config(file=options.config, dbname=options.dbname) self.load_profile() self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) From 14fbae1b54a3d8beed6b472880cd04ce333b1a07 Mon Sep 17 00:00:00 2001 From: Matt Turnbull Date: Mon, 15 Jun 2009 22:21:27 +0100 Subject: [PATCH 007/143] get cards out --- pyfpdb/Hand.py | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index d660a5ea..ff59645f 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -1146,14 +1146,18 @@ limit 1""", {'handid':handid}) res = c.fetchone() gametype = {'category':res[1],'base':res[2],'type':res[3],'limitType':res[4],'hilo':res[5],'sb':res[6],'bb':res[7], 'currency':res[10]} h = HoldemOmahaHand(hhc = None, sitename=res[0], gametype = gametype, handText=None, builtFrom = "DB", handid=handid) - cards = map("".join, zip(map(str,res[11:21:2]), res[12:21:2])) + rank = {0:'X',1:'1',2:'2',3:'3',4:'4', + 5:'5',6:'6',7:'7',8:'8',9:'9', + 10:'T',11:'J',12:'Q',13:'K',14:'A'} + ranks = [rank[r] for r in res[11:21:2]] + cards = map("".join, zip(ranks, res[12:21:2])) - if cards[0] != "0x": + if cards[0] != "Xx": h.setCommunityCards('FLOP', cards[0:3]) - if cards[3] != "0x": - h.setCommunityCards('TURN', cards[3]) - if cards[4] != "0x": - h.setCommunityCards('RIVER', cards[4]) + if cards[3] != "Xx": + h.setCommunityCards('TURN', [cards[3]]) + if cards[4] != "Xx": + h.setCommunityCards('RIVER', [cards[4]]) #[Card.valueSuitFromCard(x) for x in cards] @@ -1182,9 +1186,10 @@ WHERE h.id = %(handid)s c.execute(""" SELECT hp.seatno, + hp.winnings / 100.0 as winnings, p.name, round(hp.startcash / 100.0,2) as chips, - (hp.card1,hp.card2) as hole + hp.card1,hp.card2 FROM handsplayers as hp, players as p @@ -1192,9 +1197,11 @@ WHERE hp.handid = %(handid)s and p.id = hp.playerid """, {'handid':handid}) - for (seat, name, chips, cards) in c.fetchall(): + for (seat, winnings, name, chips, card1,card2) in c.fetchall(): h.addPlayer(seat,name,chips) - h.addHoleCards([Card.valueSuitFromCard(x) for x in cards],name) + h.addHoleCards(map(Card.valueSuitFromCard, (card1,card2)),name) + if winnings > 0: + h.addCollectPot(name, winnings) # actions c.execute(""" @@ -1237,7 +1244,7 @@ ORDER BY else: print act, player, streetnum, allin, amount # TODO : other actions - #hhc.readCollectPot(self) + #hhc.readShowdownActions(self) #hc.readShownCards(self) h.totalPot() From 574a286e0c89adf06c23fb8245c0328ea0d7187f Mon Sep 17 00:00:00 2001 From: Matt Turnbull Date: Mon, 15 Jun 2009 22:30:58 +0100 Subject: [PATCH 008/143] round amounts to 2 dp --- pyfpdb/Hand.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 05be0520..46bd55e7 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -1115,10 +1115,10 @@ select g.type, g.limitType, g.hilo, - g.smallBlind / 100.0, - g.bigBlind / 100.0 , - g.smallBet / 100.0, - g.bigBet / 100.0, + round(g.smallBlind / 100.0,2), + round(g.bigBlind / 100.0,2), + round(g.smallBet / 100.0,2), + round(g.bigBet / 100.0,2), s.currency, bc.card1value, bc.card1suit, @@ -1185,7 +1185,7 @@ WHERE h.id = %(handid)s c.execute(""" SELECT hp.seatno, - hp.winnings / 100.0 as winnings, + round(hp.winnings / 100.0,2) as winnings, p.name, round(hp.startcash / 100.0,2) as chips, hp.card1,hp.card2 @@ -1210,7 +1210,7 @@ SELECT ha.street, ha.action, ha.allin, - ha.amount / 100.0 + round(ha.amount / 100.0,2) FROM handsplayers as hp, handsactions as ha, From 2a7a275e3a28117c2c62e446aadcc4213df5fc73 Mon Sep 17 00:00:00 2001 From: Matt Turnbull Date: Tue, 16 Jun 2009 00:29:44 +0100 Subject: [PATCH 009/143] some stan to write an HTML hand --- pyfpdb/Hand.py | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 46bd55e7..6c4cd0e8 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -514,6 +514,59 @@ Card ranks will be uppercased self.addHoleCards(holeandboard.difference(board),player,shown=True) + def writeHTMLHand(self, fh=sys.__stdout__): + from nevow import tags as T + from nevow import flat + players_who_act_preflop = (([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']])) + players_stacks = [x for x in self.players if x[1] in players_who_act_preflop] + + action_streets = [x for x in self.actionStreets if len(self.actions[x]) > 0] + def render_stack(context,data): + pat = context.tag.patternGenerator('list_item') + for player in data: + x = "Seat %s: %s ($%s in chips) " %(player[0], player[1], + player[2]) + context.tag[ pat().fillSlots('playerStack', x)] + return context.tag + + def render_street(context,data): + pat = context.tag.patternGenerator('list_item') + for street in data: + actions = [ + T.h3['%s' % street], + T.ol(class_='actions', data=self.actions[street], + render=render_action)[ + T.li(pattern='list_item')[ T.slot(name='action')] + ] + ] + context.tag[ pat().fillSlots('street', actions)] + return context.tag + + def render_action(context,data): + pat = context.tag.patternGenerator('list_item') + for act in data: + x = "%s %s" % (act[0],act[1]) + context.tag[ pat().fillSlots('action', x)] + return context.tag + + s = T.p[ + T.h1[ "%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, + self.getGameTypeAsString(), self.sb, self.bb, + datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET')) + ], + T.h2[ "Table '%s' %d-max Seat #%s is the button" %(self.tablename, + self.maxseats, self.buttonpos)], + T.ol(class_='stacks', data = players_stacks, render=render_stack)[ + T.li(pattern='list_item')[ T.slot(name='playerStack') ] + ], + T.ol(class_='streets', data = action_streets, + render=render_street)[ + T.li(pattern='list_item')[ T.slot(name='street')] + ] + ] + return flat.flatten(s) + + def writeHand(self, fh=sys.__stdout__): # PokerStars format. print >>fh, ("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET'))) From c4659ce5efa6d5940e7d8879deebd6387db231f8 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 16 Jun 2009 09:55:23 -0400 Subject: [PATCH 010/143] Untangle settings and backend changes. --- pyfpdb/fpdb_parse_logic.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py index 150707c1..2d93b69f 100644 --- a/pyfpdb/fpdb_parse_logic.py +++ b/pyfpdb/fpdb_parse_logic.py @@ -21,7 +21,8 @@ import fpdb_simple import fpdb_save_to_db #parses a holdem hand -def mainParser(backend, db, cursor, siteID, category, hand, config): +def mainParser(settings, db, cursor, siteID, category, hand, config): + backend = settings['db-backend'] category = fpdb_simple.recogniseCategory(hand[0]) base = "hold" if category == "holdem" or category == "omahahi" or category == "omahahilo" else "stud" @@ -141,7 +142,7 @@ def mainParser(backend, db, cursor, siteID, category, hand, config): if base == "hold": result = fpdb_save_to_db.tourney_holdem_omaha( - config, backend, db, cursor, base, category, siteTourneyNo, buyin + config, settings, db, cursor, base, category, siteTourneyNo, buyin , fee, knockout, entries, prizepool, tourneyStartTime , payin_amounts, ranks, tourneyTypeId, siteID, siteHandNo , gametypeID, handStartTime, names, playerIDs, startCashes @@ -150,7 +151,7 @@ def mainParser(backend, db, cursor, siteID, category, hand, config): , actionNos, hudImportData, maxSeats, tableName, seatNos) elif base == "stud": result = fpdb_save_to_db.tourney_stud( - config, backend, db, cursor, base, category, siteTourneyNo + config, settings, db, cursor, base, category, siteTourneyNo , buyin, fee, knockout, entries, prizepool, tourneyStartTime , payin_amounts, ranks, tourneyTypeId, siteID, siteHandNo , gametypeID, handStartTime, names, playerIDs, startCashes @@ -162,7 +163,7 @@ def mainParser(backend, db, cursor, siteID, category, hand, config): else: if base == "hold": result = fpdb_save_to_db.ring_holdem_omaha( - config, backend, db, cursor, base, category, siteHandNo + config, settings, db, cursor, base, category, siteHandNo , gametypeID, handStartTime, names, playerIDs , startCashes, positions, cardValues, cardSuits , boardValues, boardSuits, winnings, rakes @@ -170,7 +171,7 @@ def mainParser(backend, db, cursor, siteID, category, hand, config): , hudImportData, maxSeats, tableName, seatNos) elif base == "stud": result = fpdb_save_to_db.ring_stud( - config, backend, db, cursor, base, category, siteHandNo, gametypeID + config, settings, db, cursor, base, category, siteHandNo, gametypeID , handStartTime, names, playerIDs, startCashes, antes , cardValues, cardSuits, winnings, rakes, actionTypes, allIns , actionAmounts, actionNos, hudImportData, maxSeats, tableName From bb633fd43554da6fa7ee8eff1d5d96639baf488f Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 16 Jun 2009 20:04:06 -0400 Subject: [PATCH 011/143] Correctly pass cl options to HUD_main in Windows. --- pyfpdb/GuiAutoImport.py | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py index 7f6c80e8..fb278f17 100755 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -158,25 +158,15 @@ class GuiAutoImport (threading.Thread): widget.set_label(u' _Stop Autoimport ') if self.pipe_to_hud is None: if os.name == 'nt': - command = "python HUD_main.py" + " %s" % (self.database) + command = "python HUD_main.py" + " " + self.settings['cl_options'] bs = 0 # windows is not happy with line buffing here self.pipe_to_hud = subprocess.Popen(command, bufsize = bs, stdin = subprocess.PIPE, universal_newlines=True) else: command = os.path.join(sys.path[0], 'HUD_main.py') - #command = self.config.execution_path('HUD_main.py') # Hi Ray. Sorry about this, kludging. - bs = 1 - print "GUI:options =", self.settings['cl_options'] - options = string.split(self.settings['cl_options']) - cl = [command, ] + options - print "cl =", cl - self.pipe_to_hud = subprocess.Popen(cl, bufsize = bs, stdin = subprocess.PIPE, + cl = [command, ] + string.split(self.settings['cl_options']) + self.pipe_to_hud = subprocess.Popen(cl, bufsize = 1, stdin = subprocess.PIPE, universal_newlines=True) - # self.pipe_to_hud = subprocess.Popen((command, self.database), bufsize = bs, stdin = subprocess.PIPE, - # universal_newlines=True) - # command = command + " %s" % (self.database) - # print "command = ", command - # self.pipe_to_hud = os.popen(command, 'w') # Add directories to importer object. for site in self.input_settings: From 4a6c257b0fff8595650742cc917c4ea6e38983a8 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 16 Jun 2009 23:00:46 -0400 Subject: [PATCH 012/143] get_cards query now works directly with the 0-52 card encoding scheme. --- pyfpdb/Database.py | 16 ++++------------ pyfpdb/SQL.py | 1 - 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 9582354a..b6c97a29 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -156,21 +156,13 @@ class Database: def get_cards(self, hand): """Get and return the cards for each player in the hand.""" - cards = {} # dict of cards, the key is the seat number example: {1: 'AcQd9hTs5d'} + cards = {} # dict of cards, the key is the seat number, + # the value is a tuple of the players cards + # example: {1: (0, 0, 20, 21, 22, 0 , 0)} c = self.connection.cursor() c.execute(self.sql.query['get_cards'], [hand]) - colnames = [desc[0] for desc in c.description] - cardnames = ['card1', 'card2', 'card3', 'card4', 'card5', 'card6', 'card7'] for row in c.fetchall(): - cs = ['', '', '', '', '', '', ''] - seat = -1 - for col,name in enumerate(colnames): - if name in cardnames: - cs[cardnames.index(name)] = Card.valueSuitFromCard(row[col]) - elif name == 'seat_number': - seat = row[col] - if seat != -1: - cards[seat] = ''.join(cs) + cards[row[0]] = row[1:] return cards def get_common_cards(self, hand): diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index a36f812d..1a9deb60 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -528,7 +528,6 @@ class Sql: self.query['get_cards'] = """ select seatNo AS seat_number, - name AS screen_name, card1, /*card1Value, card1Suit, */ card2, /*card2Value, card2Suit, */ card3, /*card3Value, card3Suit, */ From 63efc13cc944fec7e47e927de553080fa18f4834 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 17 Jun 2009 14:24:16 -0400 Subject: [PATCH 013/143] Make Stud_Mucked work with the new card encoding scheme. --- pyfpdb/Mucked.py | 89 +++++++++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 38 deletions(-) diff --git a/pyfpdb/Mucked.py b/pyfpdb/Mucked.py index 93f6d102..12da2a97 100755 --- a/pyfpdb/Mucked.py +++ b/pyfpdb/Mucked.py @@ -35,6 +35,7 @@ import gobject # FreePokerTools modules import Configuration import Database +import Card class Aux_Window: def __init__(self, hud, params, config): @@ -67,16 +68,23 @@ class Aux_Window: # Some utility routines useful for Aux_Windows # def get_card_images(self): - card_images = {} - suits = ('S', 'H', 'D', 'C') - ranks = ('A', 'K', 'Q', 'J', 'T', '9', '8', '7', '6', '5', '4', '3', '2', 'B') + + card_images = 53 * [0] + suits = ('s', 'h', 'd', 'c') + ranks = (14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2) pb = gtk.gdk.pixbuf_new_from_file(self.config.execution_path(self.params['deck'])) - for j in range(0, 14): + for j in range(0, 13): for i in range(0, 4): temp_pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, pb.get_has_alpha(), pb.get_bits_per_sample(), 30, 42) pb.copy_area(30*j, 42*i, 30, 42, temp_pb, 0, 0) - card_images[(ranks[j], suits[i])] = temp_pb + card_images[Card.cardFromValueSuit(ranks[j], suits[i])] = temp_pb + temp_pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, pb.get_has_alpha(), pb.get_bits_per_sample(), 30, 42) +# also pick out a card back and store in [0] + j = 13 + i = 2 + pb.copy_area(30*j, 42*i, 30, 42, temp_pb, 0, 0) + card_images[0] = temp_pb return(card_images) # cards are 30 wide x 42 high @@ -108,9 +116,10 @@ class Stud_mucked(Aux_Window): def create(self): - self.container =gtk.Window() + self.container = gtk.Window() self.vbox = gtk.VBox() self.container.add(self.vbox) + self.container.set_title(self.hud.table.name) self.mucked_list.create(self.vbox) self.mucked_cards.create(self.vbox) @@ -207,7 +216,9 @@ class Stud_list: # find the hero's seat from the stat_dict for stat in self.parent.hud.stat_dict.itervalues(): if stat['screen_name'] == hero: - return self.parent.hud.cards[stat['seat']][0:6] + return Card.valueSuitFromCard(self.parent.hud.cards[stat['seat']][0]) +\ + Card.valueSuitFromCard(self.parent.hud.cards[stat['seat']][1]) +\ + Card.valueSuitFromCard(self.parent.hud.cards[stat['seat']][2]) return "xxxxxx" def update_gui(self, new_hand_id): @@ -240,7 +251,7 @@ class Stud_cards: for r in range(0, self.rows): for c in range(0, self.cols): - self.seen_cards[(c, r)] = gtk.image_new_from_pixbuf(self.card_images[('B', 'S')]) + self.seen_cards[(c, r)] = gtk.image_new_from_pixbuf(self.card_images[(0)]) self.eb[(c, r)]= gtk.EventBox() # set up the contents for the cells @@ -287,11 +298,11 @@ class Stud_cards: self.clear() for c, cards in self.parent.hud.cards.iteritems(): self.grid_contents[(1, c - 1)].set_text(self.get_screen_name(c)) - for i in ((0, cards[0:2]), (1, cards[2:4]), (2, cards[4:6]), (3, cards[6:8]), - (4, cards[8:10]), (5, cards[10:12]), (6, cards[12:14])): - if not i[1] == "xx": + for i in ((0, cards[0]), (1, cards[1]), (2, cards[2]), (3, cards[3]), + (4, cards[4]), (5, cards[5]), (6, cards[6])): + if not i[1] == 0: self.seen_cards[(i[0], c - 1)]. \ - set_from_pixbuf(self.card_images[self.parent.split_cards(i[1])]) + set_from_pixbuf(self.card_images[i[1]]) ## action in tool tips for 3rd street cards for c in (0, 1, 2): for r in range(0, self.rows): @@ -314,7 +325,7 @@ class Stud_cards: for r in range(0, self.rows): self.grid_contents[(1, r)].set_text(" ") for c in range(0, 7): - self.seen_cards[(c, r)].set_from_pixbuf(self.card_images[('B', 'S')]) + self.seen_cards[(c, r)].set_from_pixbuf(self.card_images[0]) self.eb[(c, r)].set_tooltip_text('') class Flop_Mucked(Aux_Window): @@ -459,29 +470,31 @@ class Flop_Mucked(Aux_Window): new_locs[i] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y) self.config.edit_aux_layout(self.params['name'], self.hud.max, locations = new_locs) -if __name__== "__main__": - - def destroy(*args): # call back for terminating the main eventloop - gtk.main_quit() # used only for testing +# This test program doesn't work - def process_new_hand(source, condition, db_connection): #callback from stdin watch -- testing only -# there is a new hand_id to be processed -# just read it and pass it to update - new_hand_id = sys.stdin.readline() - new_hand_id = new_hand_id.rstrip() # remove trailing whitespace - m.update_data(new_hand_id, db_connection) - m.update_gui(new_hand_id) - return(True) - - config = Configuration.Config() - db_connection = Database.Database(config, 'fpdb', '') - main_window = gtk.Window() - main_window.set_keep_above(True) - main_window.connect("destroy", destroy) - - aux_to_call = "stud_mucked" - aux_params = config.get_aux_parameters(aux_to_call) - m = eval("%s(main_window, None, config, aux_params)" % aux_params['class']) - - s_id = gobject.io_add_watch(sys.stdin, gobject.IO_IN, process_new_hand, db_connection) - gtk.main() +#if __name__== "__main__": +# +# def destroy(*args): # call back for terminating the main eventloop +# gtk.main_quit() # used only for testing +# +# def process_new_hand(source, condition, db_connection): #callback from stdin watch -- testing only +## there is a new hand_id to be processed +## just read it and pass it to update +# new_hand_id = sys.stdin.readline() +# new_hand_id = new_hand_id.rstrip() # remove trailing whitespace +# m.update_data(new_hand_id, db_connection) +# m.update_gui(new_hand_id) +# return(True) +# +# config = Configuration.Config() +# db_connection = Database.Database(config, 'fpdbTEST', '') +# main_window = gtk.Window() +# main_window.set_keep_above(True) +# main_window.connect("destroy", destroy) +# +# aux_to_call = "stud_mucked" +# aux_params = config.get_aux_parameters(aux_to_call) +# m = eval("%s(None, config, aux_params)" % aux_params['class']) +# +# s_id = gobject.io_add_watch(sys.stdin, gobject.IO_IN, process_new_hand, db_connection) +# gtk.main() From 42f2b73c1a089bfbdedbe427721bb44ee68a08d7 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 17 Jun 2009 14:26:16 -0400 Subject: [PATCH 014/143] Get rid of some intermediate print. --- pyfpdb/HUD_main.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index 2ffd057b..218707bd 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -34,10 +34,6 @@ import Options (options, sys.argv) = Options.fpdb_options() -print "HUD: dbname =", options.dbname -print "HUD: config =", options.config -print "HUD: logging =", options.errorsToConsole - 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) From dcaf6fed2759cfb19f4ea7e662e3a522b249f29e Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 17 Jun 2009 21:43:30 +0100 Subject: [PATCH 015/143] apologies - looks like I missed this out of my last release :-( --- pyfpdb/fpdb_parse_logic.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py index 150707c1..ee5d9c40 100644 --- a/pyfpdb/fpdb_parse_logic.py +++ b/pyfpdb/fpdb_parse_logic.py @@ -21,7 +21,8 @@ import fpdb_simple import fpdb_save_to_db #parses a holdem hand -def mainParser(backend, db, cursor, siteID, category, hand, config): +def mainParser(settings, db, cursor, siteID, category, hand, config): + backend = settings['db-backend'] category = fpdb_simple.recogniseCategory(hand[0]) base = "hold" if category == "holdem" or category == "omahahi" or category == "omahahilo" else "stud" @@ -34,6 +35,7 @@ def mainParser(backend, db, cursor, siteID, category, hand, config): #part 1: read hand no and check for duplicate siteHandNo = fpdb_simple.parseSiteHandNo(hand[0]) + #print "siteHandNo =", siteHandNo handStartTime = fpdb_simple.parseHandStartTime(hand[0]) isTourney = fpdb_simple.isTourney(hand[0]) @@ -126,6 +128,7 @@ def mainParser(backend, db, cursor, siteID, category, hand, config): totalWinnings = sum(winnings) # if hold'em, use positions and not antes, if stud do not use positions, use antes + # this is used for handsplayers inserts, so still needed even if hudcache update is being skipped if base == "hold": hudImportData = fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes , allIns, actionTypeByNo, winnings, totalWinnings, positions @@ -141,7 +144,7 @@ def mainParser(backend, db, cursor, siteID, category, hand, config): if base == "hold": result = fpdb_save_to_db.tourney_holdem_omaha( - config, backend, db, cursor, base, category, siteTourneyNo, buyin + config, settings, db, cursor, base, category, siteTourneyNo, buyin , fee, knockout, entries, prizepool, tourneyStartTime , payin_amounts, ranks, tourneyTypeId, siteID, siteHandNo , gametypeID, handStartTime, names, playerIDs, startCashes @@ -150,7 +153,7 @@ def mainParser(backend, db, cursor, siteID, category, hand, config): , actionNos, hudImportData, maxSeats, tableName, seatNos) elif base == "stud": result = fpdb_save_to_db.tourney_stud( - config, backend, db, cursor, base, category, siteTourneyNo + config, settings, db, cursor, base, category, siteTourneyNo , buyin, fee, knockout, entries, prizepool, tourneyStartTime , payin_amounts, ranks, tourneyTypeId, siteID, siteHandNo , gametypeID, handStartTime, names, playerIDs, startCashes @@ -162,7 +165,7 @@ def mainParser(backend, db, cursor, siteID, category, hand, config): else: if base == "hold": result = fpdb_save_to_db.ring_holdem_omaha( - config, backend, db, cursor, base, category, siteHandNo + config, settings, db, cursor, base, category, siteHandNo , gametypeID, handStartTime, names, playerIDs , startCashes, positions, cardValues, cardSuits , boardValues, boardSuits, winnings, rakes @@ -170,7 +173,7 @@ def mainParser(backend, db, cursor, siteID, category, hand, config): , hudImportData, maxSeats, tableName, seatNos) elif base == "stud": result = fpdb_save_to_db.ring_stud( - config, backend, db, cursor, base, category, siteHandNo, gametypeID + config, settings, db, cursor, base, category, siteHandNo, gametypeID , handStartTime, names, playerIDs, startCashes, antes , cardValues, cardSuits, winnings, rakes, actionTypes, allIns , actionAmounts, actionNos, hudImportData, maxSeats, tableName From 7664373648b4b865c9dfd61198f6ac75ba7f2a97 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 17 Jun 2009 23:03:43 +0100 Subject: [PATCH 016/143] use fpdb_db for db connection --- pyfpdb/Database.py | 66 +++++++++------------------------------------- 1 file changed, 13 insertions(+), 53 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 9582354a..e5fbda6d 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -32,62 +32,22 @@ import string # pyGTK modules # FreePokerTools modules +import fpdb_db import Configuration import SQL import Card class Database: def __init__(self, c, db_name, game): + self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql + self.fdb.do_connect(c) + self.connection = self.fdb.db + db_params = c.get_db_parameters() - if (string.lower(db_params['db-server']) == 'postgresql' or - string.lower(db_params['db-server']) == 'postgres'): - import psycopg2 # posgres via DB-API - import psycopg2.extensions - psycopg2.extensions.register_type(psycopg2.extensions.UNICODE) - - try: - if db_params['db-host'] == 'localhost' or db_params['db-host'] == '127.0.0.1': - self.connection = psycopg2.connect(database = db_params['db-databaseName']) - else: - self.connection = psycopg2.connect(host = db_params['db-host'], - user = db_params['db-user'], - password = db_params['db-password'], - database = db_params['db-databaseName']) - except: - print "Error opening database connection %s. See error log file." % (file) - traceback.print_exc(file=sys.stderr) - print "press enter to continue" - sys.stdin.readline() - sys.exit() - - elif string.lower(db_params['db-server']) == 'mysql': - import MySQLdb # mysql bindings - try: - self.connection = MySQLdb.connect(host = db_params['db-host'], - user = db_params['db-user'], - passwd = db_params['db-password'], - db = db_params['db-databaseName']) - cur_iso = self.connection.cursor() - cur_iso.execute('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED') - cur_iso.close() - - except: - print "Error opening database connection %s. See error log file." % (file) - traceback.print_exc(file=sys.stderr) - print "press enter to continue" - sys.stdin.readline() - sys.exit() - - else: - print "Database = %s not recognized." % (c.supported_databases[db_name].db_server) - sys.stderr.write("Database not recognized, exiting.\n") - print "press enter to continue" - sys.exit() - self.type = db_params['db-type'] - self.sql = SQL.Sql(game = game, type = self.type) + self.sql = SQL.Sql(game = game, type = self.type, db_server = db_params['db-backend']) self.connection.rollback() - + # To add to config: self.hud_style = 'T' # A=All-time # S=Session @@ -211,7 +171,7 @@ class Database: def get_action_from_hand(self, hand_no): action = [ [], [], [], [], [] ] c = self.connection.cursor() - c.execute(self.sql.query['get_action_from_hand'], (hand_no, )) + c.execute(self.sql.query['get_action_from_hand'], (hand_no,)) for row in c.fetchall(): street = row[0] act = row[1:] @@ -222,7 +182,7 @@ class Database: """Returns a hash of winners:amount won, given a hand number.""" winners = {} c = self.connection.cursor() - c.execute(self.sql.query['get_winners_from_hand'], (hand, )) + c.execute(self.sql.query['get_winners_from_hand'], (hand,)) for row in c.fetchall(): winners[row[0]] = row[1] return winners @@ -333,10 +293,10 @@ if __name__=="__main__": for p in stat_dict.keys(): print p, " ", stat_dict[p] -# print "nutOmatics stats:" -# stat_dict = db_connection.get_stats_from_hand(h, hero) -# for p in stat_dict.keys(): -# print p, " ", stat_dict[p] + #print "nutOmatics stats:" + #stat_dict = db_connection.get_stats_from_hand(h, hero) + #for p in stat_dict.keys(): + # print p, " ", stat_dict[p] print "cards =", db_connection.get_cards(u'1') db_connection.close_connection From 8bbd21fa6a2d7215a4282e758ae8a4cac6ba4637 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 17 Jun 2009 23:05:20 +0100 Subject: [PATCH 017/143] hide error when a window has non UTF-8 char in title --- pyfpdb/Tables.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Tables.py b/pyfpdb/Tables.py index 58da2690..5884e81e 100755 --- a/pyfpdb/Tables.py +++ b/pyfpdb/Tables.py @@ -231,7 +231,12 @@ def discover_nt_by_name(c, tablename): titles = {} win32gui.EnumWindows(win_enum_handler, titles) for hwnd in titles: - if not tablename in titles[hwnd]: continue + print "Tbales.py: tablename =", tablename, "title =", titles[hwnd] + try: + # this can blow up in XP on some windows, eg firefox displaying http://docs.python.org/tutorial/classes.html + if not tablename in titles[hwnd]: continue + except: + continue 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 From a6a98a750f0cce8a86f1247fd86c760551d73625 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 18 Jun 2009 14:11:53 -0400 Subject: [PATCH 018/143] Clean up changes to use 0-52 card encoding. --- pyfpdb/Mucked.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/pyfpdb/Mucked.py b/pyfpdb/Mucked.py index 12da2a97..8ae6bc60 100755 --- a/pyfpdb/Mucked.py +++ b/pyfpdb/Mucked.py @@ -76,18 +76,19 @@ class Aux_Window: for j in range(0, 13): for i in range(0, 4): - temp_pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, pb.get_has_alpha(), pb.get_bits_per_sample(), 30, 42) - pb.copy_area(30*j, 42*i, 30, 42, temp_pb, 0, 0) - card_images[Card.cardFromValueSuit(ranks[j], suits[i])] = temp_pb + card_images[Card.cardFromValueSuit(ranks[j], suits[i])] = self.cropper(pb, i, j) temp_pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, pb.get_has_alpha(), pb.get_bits_per_sample(), 30, 42) # also pick out a card back and store in [0] - j = 13 - i = 2 - pb.copy_area(30*j, 42*i, 30, 42, temp_pb, 0, 0) - card_images[0] = temp_pb + card_images[0] = self.cropper(pb, 2, 13) return(card_images) # cards are 30 wide x 42 high + def cropper(self, pb, i, j): + """Crop out a card image given an FTP deck and the i, j position.""" + temp_pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, pb.get_has_alpha(), pb.get_bits_per_sample(), 30, 42) + pb.copy_area(30*j, 42*i, 30, 42, temp_pb, 0, 0) + return temp_pb + def split_cards(self, card): if card == 'xx': return ('B', 'S') return (card[0], card[1].upper()) From 2b240efd0a15d6e13fa3c8dcca358cab01184da4 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 18 Jun 2009 20:29:02 +0100 Subject: [PATCH 019/143] unimportant fix to storehudcache2 --- pyfpdb/fpdb_simple.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index 31321aeb..b140a2a8 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -2381,7 +2381,7 @@ def storeHudCache2(backend, cursor, base, category, gametypeId, hand_start_time, # Try to do the update first: num = cursor.execute("""UPDATE HudCache SET HDs=HDs+%s, street0VPI=street0VPI+%s, street0Aggr=street0Aggr+%s, - street0_3B4BChance=street0_3B4BChance+%s, street0_3B4BDone=street0_3B4BDone+%s, + street0_3BChance=street0_3BChance+%s, street0_3BDone=street0_3BDone+%s, street1Seen=street1Seen+%s, street2Seen=street2Seen+%s, street3Seen=street3Seen+%s, street4Seen=street4Seen+%s, sawShowdown=sawShowdown+%s, street1Aggr=street1Aggr+%s, street2Aggr=street2Aggr+%s, street3Aggr=street3Aggr+%s, From 44aed2c95f3b7e68b73902cbf00c7f368cb3cc86 Mon Sep 17 00:00:00 2001 From: Matt Turnbull Date: Fri, 19 Jun 2009 07:04:57 +0100 Subject: [PATCH 020/143] populate hands.boardcards --- pyfpdb/Card.py | 17 ++++++++++++++++- pyfpdb/fpdb_save_to_db.py | 3 ++- pyfpdb/fpdb_simple.py | 9 +++++++-- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/pyfpdb/Card.py b/pyfpdb/Card.py index 75c742f9..ab6843c5 100755 --- a/pyfpdb/Card.py +++ b/pyfpdb/Card.py @@ -57,6 +57,21 @@ def fourStartCards(value1, suit1, value2, suit2, value3, suit3, value4, suit4): #AAKKs #AAKKr # Is probably what we are looking for + + # mct: + # my maths says there are 4 classes of suitedness + # SSSS SSSx SSxy SSHH + # encode them as follows: + # SSSS (K, J, 6, 3) + # - 13C4 = 715 possibilities + # SSSx (K, J, 6),(3) + # - 13C3 * 13 = 3718 possibilities + # SSxy (K, J),(6),(3) + # - 13C2 * 13*13 = 13182 possibilities + # SSHH (K, J),(6, 3) + # - 13C2 * 13C2 = 6084 possibilities + # Needless to say they won't fit on a 13x13 grid. + # The actual number of hands in each class is far greater return(0) def cardFromValueSuit(value, suit): @@ -70,7 +85,7 @@ def cardFromValueSuit(value, suit): def valueSuitFromCard(card): """ Function to convert a card stored in the database (int 0-52) into value and suit like 9s, 4c etc """ - if card < 0 or card > 52: + if card < 0 or card > 52 or not card: return('') else: return( ['', '2h', '3h', '4h', '5h', '6h', '7h', '8h', '9h', 'Th', 'Jh', 'Qh', 'Kh', 'Ah' diff --git a/pyfpdb/fpdb_save_to_db.py b/pyfpdb/fpdb_save_to_db.py index 3c99d084..2eba8bfa 100644 --- a/pyfpdb/fpdb_save_to_db.py +++ b/pyfpdb/fpdb_save_to_db.py @@ -83,7 +83,8 @@ def ring_holdem_omaha(config, backend, db, cursor, base, category, site_hand_no, t2 = time() hands_id = fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats, hudImportData) + ,hand_start_time, names, tableName, maxSeats, + hudImportData, board_values, board_suits) t3 = time() hands_players_ids = fpdb_simple.store_hands_players_holdem_omaha( backend, db, cursor, category, hands_id, player_ids, start_cashes diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index 31321aeb..adc1a106 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -1147,10 +1147,13 @@ card5Value, card5Suit) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", #end def store_board_cards def storeHands(backend, conn, cursor, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats, hudCache): + ,hand_start_time, names, tableName, maxSeats, hudCache, + board_values, board_suits): + cards = [Card.cardFromValueSuit(v,s) for v,s in zip(board_values,board_suits)] #stores into table hands: cursor.execute ("""INSERT INTO Hands (siteHandNo, gametypeId, handStart, seats, tableName, importTime, maxSeats + ,boardcard1,boardcard2,boardcard3,boardcard4,boardcard5 ,playersVpi, playersAtStreet1, playersAtStreet2 ,playersAtStreet3, playersAtStreet4, playersAtShowdown ,street0Raises, street1Raises, street2Raises @@ -1159,9 +1162,11 @@ def storeHands(backend, conn, cursor, site_hand_no, gametype_id ,showdownPot ) VALUES - (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) + (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) """ , (site_hand_no, gametype_id, hand_start_time, len(names), tableName, datetime.datetime.today(), maxSeats + ,cards[0], cards[1], cards[2], cards[3], cards[4] ,hudCache['playersVpi'], hudCache['playersAtStreet1'], hudCache['playersAtStreet2'] ,hudCache['playersAtStreet3'], hudCache['playersAtStreet4'], hudCache['playersAtShowdown'] ,hudCache['street0Raises'], hudCache['street1Raises'], hudCache['street2Raises'] From 620576ba210c24a9d94b8cec4593abd3a5907da8 Mon Sep 17 00:00:00 2001 From: Matt Turnbull Date: Fri, 19 Jun 2009 07:21:35 +0100 Subject: [PATCH 021/143] more html output --- pyfpdb/Hand.py | 237 ++++++++++++++++++++++--------------- pyfpdb/PokerStarsToFpdb.py | 2 +- 2 files changed, 143 insertions(+), 96 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 6c4cd0e8..bee52dd5 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -39,15 +39,14 @@ class Hand: self.starttime = 0 self.handText = handText self.handid = 0 - self.tablename = "Slartibartfast" - self.hero = "Hiro" + self.tablename = "" + self.hero = "" self.maxseats = 10 self.counted_seats = 0 self.buttonpos = 0 self.seating = [] self.players = [] self.posted = [] - self.involved = True # Collections indexed by street names self.bets = {} @@ -55,23 +54,26 @@ class Hand: self.streets = {} self.actions = {} # [['mct','bets','$10'],['mika','folds'],['carlg','raises','$20']] self.board = {} # dict from street names to community cards - for street in self.streetList: + self.holecards = {} + for street in self.allStreets: self.streets[street] = "" # portions of the handText, filled by markStreets() self.bets[street] = {} self.lastBet[street] = 0 self.actions[street] = [] self.board[street] = [] + self.holecards[street] = {} # dict from player names to holecards # Collections indexed by player names - self.holecards = {} # dict from player names to dicts by street ... of tuples ... of holecards +# self.holecards = {} # dict from player names to dicts by street ... of tuples ... of holecards self.discards = {} # dict from player names to dicts by street ... of tuples ... of discarded holecards self.stacks = {} self.collected = [] #list of ? self.collectees = {} # dict from player names to amounts collected (?) # Sets of players - self.shown = set() self.folded = set() + self.dealt = set() # 'dealt to' line to be printed + self.shown = set() # cards were shown # self.action = [] # Things to do with money @@ -90,7 +92,7 @@ db: a connected fpdb_db object""" sqlids = db.getSqlPlayerIDs([p[1] for p in self.players], self.siteId) # HudCache data to come from DerivedStats class # HandsActions - all actions for all players for all streets - self.actions - # BoardCards - Skip - no longer necessary? + # BoardCards - Skip - no longer necessary # Hands - Summary information of hand indexed by handId - gameinfo #hh['siteHandNo'] = self.handid # gametypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), @@ -163,12 +165,10 @@ If a player has None chips he won't be added.""" if chips is not None: self.players.append([seat, name, chips]) self.stacks[name] = Decimal(chips) - self.holecards[name] = [] - self.discards[name] = [] self.pot.addPlayer(name) - for street in self.streetList: + for street in self.allStreets: self.bets[street][name] = [] - self.holecards[name] = {} # dict from street names. + #self.holecards[name] = {} # dict from street names. self.discards[name] = {} # dict from street names. @@ -407,32 +407,32 @@ Map the tuple self.gametype onto the pokerstars string describing it def printHand(self): self.writeHand(sys.stdout) - def printActionLine(self, act, fh): + def actionString(self, act): if act[1] == 'folds': - print >>fh, ("%s: folds " %(act[0])) + return ("%s: folds " %(act[0])) elif act[1] == 'checks': - print >>fh, ("%s: checks " %(act[0])) + return ("%s: checks " %(act[0])) elif act[1] == 'calls': - print >>fh, ("%s: calls $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) + return ("%s: calls $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) elif act[1] == 'bets': - print >>fh, ("%s: bets $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) + return ("%s: bets $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) elif act[1] == 'raises': - print >>fh, ("%s: raises $%s to $%s%s" %(act[0], act[2], act[3], ' and is all-in' if act[5] else '')) + return ("%s: raises $%s to $%s%s" %(act[0], act[2], act[3], ' and is all-in' if act[5] else '')) elif act[1] == 'completea': - print >>fh, ("%s: completes to $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) + return ("%s: completes to $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) elif act[1] == 'posts': if(act[2] == "small blind"): - print >>fh, ("%s: posts small blind $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else '')) + return ("%s: posts small blind $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else '')) elif(act[2] == "big blind"): - print >>fh, ("%s: posts big blind $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else '')) + return ("%s: posts big blind $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else '')) elif(act[2] == "both"): - print >>fh, ("%s: posts small & big blinds $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else '')) + return ("%s: posts small & big blinds $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else '')) elif act[1] == 'bringin': - print >>fh, ("%s: brings in for $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) + return ("%s: brings in for $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) elif act[1] == 'discards': - print >>fh, ("%s: discards %s %s%s" %(act[0], act[2], 'card' if act[2] == 1 else 'cards' , " [" + " ".join(self.discards[act[0]]['DRAWONE']) + "]" if self.hero == act[0] else '')) + return ("%s: discards %s %s%s" %(act[0], act[2], 'card' if act[2] == 1 else 'cards' , " [" + " ".join(self.discards[act[0]]['DRAWONE']) + "]" if self.hero == act[0] else '')) elif act[1] == 'stands pat': - print >>fh, ("%s: stands pat" %(act[0])) + return ("%s: stands pat" %(act[0])) class HoldemOmahaHand(Hand): @@ -440,9 +440,10 @@ class HoldemOmahaHand(Hand): if gametype['base'] != 'hold': pass # or indeed don't pass and complain instead logging.debug("HoldemOmahaHand") - self.streetList = ['BLINDSANTES', 'DEAL', 'PREFLOP','FLOP','TURN','RIVER'] # a list of the observed street names in order + self.allStreets = ['BLINDSANTES', 'PREFLOP','FLOP','TURN','RIVER'] + self.holeStreets = ['PREFLOP'] self.communityStreets = ['FLOP', 'TURN', 'RIVER'] - self.actionStreets = ['PREFLOP','FLOP','TURN','RIVER'] + self.actionStreets = ['BLINDSANTES','PREFLOP','FLOP','TURN','RIVER'] Hand.__init__(self, sitename, gametype, handText, builtFrom = "HHC") self.sb = gametype['sb'] self.bb = gametype['bb'] @@ -480,24 +481,32 @@ class HoldemOmahaHand(Hand): pass - def addHoleCards(self, cards, player, shown=False): + def addHoleCards(self, cards, player, shown=False, dealt=False): """\ Assigns observed holecards to a player. cards list of card bigrams e.g. ['2h','Jc'] player (string) name of player +shown whether they were revealed at showdown +dealt whether they were seen in a 'dealt to' line """ logging.debug("addHoleCards %s %s" % (cards, player)) try: self.checkPlayerExists(player) - cardset = set(self.card(c) for c in cards) - if shown and len(cardset) > 0: - self.shown.add(player) - if 'PREFLOP' in self.holecards[player]: - self.holecards[player]['PREFLOP'].update(cardset) - else: - self.holecards[player]['PREFLOP'] = cardset except FpdbParseError, e: print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) + return + + cardset = set((self.card(c) for c in cards)) + if len(cardset) == 0: + return + if dealt: + self.dealt.add(player) + if shown: + self.shown.add(player) + if player in self.holecards['PREFLOP']: + self.holecards['PREFLOP'][player].update(cardset) + else: + self.holecards['PREFLOP'][player] = cardset def addShownCards(self, cards, player, holeandboard=None): """\ @@ -506,8 +515,7 @@ Card ranks will be uppercased """ logging.debug("addShownCards %s hole=%s all=%s" % (player, cards, holeandboard)) if cards is not None: - self.shown.add(player) - self.addHoleCards(cards,player) + self.addHoleCards(cards,player,shown=True) elif holeandboard is not None: holeandboard = set([self.card(c) for c in holeandboard]) board = set([c for s in self.board.values() for c in s]) @@ -519,7 +527,6 @@ Card ranks will be uppercased from nevow import flat players_who_act_preflop = (([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']])) players_stacks = [x for x in self.players if x[1] in players_who_act_preflop] - action_streets = [x for x in self.actionStreets if len(self.actions[x]) > 0] def render_stack(context,data): pat = context.tag.patternGenerator('list_item') @@ -532,39 +539,82 @@ Card ranks will be uppercased def render_street(context,data): pat = context.tag.patternGenerator('list_item') for street in data: - actions = [ - T.h3['%s' % street], - T.ol(class_='actions', data=self.actions[street], - render=render_action)[ - T.li(pattern='list_item')[ T.slot(name='action')] - ] - ] - context.tag[ pat().fillSlots('street', actions)] + lines = [] + if street in self.holeStreets and self.holecards[street]: + lines.append( + T.ol(class_='dealclosed', data=street, + render=render_deal) [ + T.li(pattern='list_item')[ T.slot(name='deal') ] + ] + ) + if street in self.communityStreets and self.board[street]: + lines.append( + T.ol(class_='community', data=street, + render=render_deal_community)[ + T.li(pattern='list_item')[ T.slot(name='deal') ] + ] + ) + if street in self.actionStreets and self.actions[street]: + lines.append( + T.ol(class_='actions', data=self.actions[street], render=render_action) [ + T.li(pattern='list_item')[ T.slot(name='action') ] + ] + ) + if lines: + context.tag[ pat().fillSlots('street', [ T.h3[ street ] ]+lines)] return context.tag + def render_deal(context,data): + # data is streetname +# we can have open+closed, or just open, or just closed. + + if self.holecards[data]: + for player in self.holecards[data]: + somestuff = 'dealt to %s %s' % (player, self.holecards[data][player]) + pat = context.tag.patternGenerator('list_item') + context.tag[ pat().fillSlots('deal', somestuff)] + return context.tag + + def render_deal_community(context,data): + # data is streetname + if self.board[data]: + somestuff = '[' + ' '.join(self.board[data]) + ']' + pat = context.tag.patternGenerator('list_item') + context.tag[ pat().fillSlots('deal', somestuff)] + return context.tag def render_action(context,data): pat = context.tag.patternGenerator('list_item') for act in data: - x = "%s %s" % (act[0],act[1]) + x = self.actionString(act) context.tag[ pat().fillSlots('action', x)] return context.tag s = T.p[ - T.h1[ "%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, - self.getGameTypeAsString(), self.sb, self.bb, - datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET')) + T.h1[ + T.span(class_='site')["%s Game #%s]" % ('PokerStars', self.handid)], + T.span(class_='type_limit')[ "%s ($%s/$%s)" %(self.getGameTypeAsString(), self.sb, self.bb) ], + T.span(class_='date')[ datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET') ] ], T.h2[ "Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)], T.ol(class_='stacks', data = players_stacks, render=render_stack)[ T.li(pattern='list_item')[ T.slot(name='playerStack') ] ], - T.ol(class_='streets', data = action_streets, + T.ol(class_='streets', data = self.allStreets, render=render_street)[ T.li(pattern='list_item')[ T.slot(name='street')] ] ] - return flat.flatten(s) + import tidy + + options = dict(input_xml=True, + output_xhtml=True, + add_xml_decl=False, + doctype='omit', + indent='auto', + tidy_mark=False) + + return str(tidy.parseString(flat.flatten(s), **options)) def writeHand(self, fh=sys.__stdout__): @@ -580,33 +630,36 @@ Card ranks will be uppercased if self.actions['BLINDSANTES']: for act in self.actions['BLINDSANTES']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) print >>fh, ("*** HOLE CARDS ***") - if self.involved: - print >>fh, ("Dealt to %s [%s]" %(self.hero , " ".join(self.holecards[self.hero]['PREFLOP']))) + for player in self.dealt: + print >>fh, ("Dealt to %s [%s]" %(player, " ".join(self.holecards['PREFLOP'][player]))) + if self.hero == "": + for player in self.shown.difference(self.dealt): + print >>fh, ("Dealt to %s [%s]" %(player, " ".join(self.holecards['PREFLOP'][player]))) if self.actions['PREFLOP']: for act in self.actions['PREFLOP']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if self.board['FLOP']: print >>fh, ("*** FLOP *** [%s]" %( " ".join(self.board['FLOP']))) if self.actions['FLOP']: for act in self.actions['FLOP']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if self.board['TURN']: print >>fh, ("*** TURN *** [%s] [%s]" %( " ".join(self.board['FLOP']), " ".join(self.board['TURN']))) if self.actions['TURN']: for act in self.actions['TURN']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if self.board['RIVER']: print >>fh, ("*** RIVER *** [%s] [%s]" %(" ".join(self.board['FLOP']+self.board['TURN']), " ".join(self.board['RIVER']) )) if self.actions['RIVER']: for act in self.actions['RIVER']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) #Some sites don't have a showdown section so we have to figure out if there should be one @@ -622,8 +675,8 @@ Card ranks will be uppercased numOfHoleCardsNeeded = 4 elif self.gametype['category'] in ('holdem'): numOfHoleCardsNeeded = 2 - if len(self.holecards[name]['PREFLOP']) == numOfHoleCardsNeeded: - print >>fh, ("%s shows [%s] (a hand...)" % (name, " ".join(self.holecards[name]['PREFLOP']))) + if len(self.holecards['PREFLOP'][name]) == numOfHoleCardsNeeded: + print >>fh, ("%s shows [%s] (a hand...)" % (name, " ".join(self.holecards['PREFLOP'][name]))) # Current PS format has the lines: # Uncalled bet ($111.25) returned to s0rrow @@ -792,12 +845,12 @@ Card ranks will be uppercased (nc,oc) = self.holecards[player]['DEAL'] print >>fh, _("Dealt to %s: [%s]") % (player, " ".join(nc)) for act in self.actions['DEAL']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if 'DRAWONE' in self.actions: print >>fh, _("*** FIRST DRAW ***") for act in self.actions['DRAWONE']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if act[0] == self.hero and act[1] == 'discards': (nc,oc) = self.holecards[act[0]]['DRAWONE'] dc = self.discards[act[0]]['DRAWONE'] @@ -807,7 +860,7 @@ Card ranks will be uppercased if 'DRAWTWO' in self.actions: print >>fh, _("*** SECOND DRAW ***") for act in self.actions['DRAWTWO']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if act[0] == self.hero and act[1] == 'discards': (nc,oc) = self.holecards[act[0]]['DRAWTWO'] dc = self.discards[act[0]]['DRAWTWO'] @@ -817,7 +870,7 @@ Card ranks will be uppercased if 'DRAWTHREE' in self.actions: print >>fh, _("*** THIRD DRAW ***") for act in self.actions['DRAWTHREE']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if act[0] == self.hero and act[1] == 'discards': (nc,oc) = self.holecards[act[0]]['DRAWTHREE'] dc = self.discards[act[0]]['DRAWTHREE'] @@ -956,7 +1009,7 @@ Add a complete on [street] by [player] to [amountTo] print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(closed) + "] " if closed else " ", "[" + " ".join(open) + "]" if open else "") for act in self.actions['THIRD']: #FIXME: Need some logic here for bringin vs completes - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if 'FOURTH' in self.actions: dealt = 0 @@ -973,7 +1026,7 @@ Add a complete on [street] by [player] to [amountTo] print >>fh, _("*** 4TH STREET ***") print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "") for act in self.actions['FOURTH']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if 'FIFTH' in self.actions: dealt = 0 @@ -991,7 +1044,7 @@ Add a complete on [street] by [player] to [amountTo] print >>fh, _("*** 5TH STREET ***") print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "") for act in self.actions['FIFTH']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if 'SIXTH' in self.actions: dealt = 0 @@ -1009,7 +1062,7 @@ Add a complete on [street] by [player] to [amountTo] print >>fh, _("*** 6TH STREET ***") print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "") for act in self.actions['SIXTH']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if 'SEVENTH' in self.actions: # OK. It's possible that they're all in at an earlier street, but only closed cards are dealt. @@ -1028,7 +1081,7 @@ Add a complete on [street] by [player] to [amountTo] if new: print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "") for act in self.actions['SEVENTH']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) #Some sites don't have a showdown section so we have to figure out if there should be one # The logic for a showdown is: at the end of river action there are at least two players in the hand @@ -1159,7 +1212,8 @@ class Pot(object): def assemble(cnxn, handid): c = cnxn.cursor() - # We need the following for the Hand.__init__ + # We need at least sitename, gametype, handid + # for the Hand.__init__ c.execute(""" select s.name, @@ -1173,22 +1227,19 @@ select round(g.smallBet / 100.0,2), round(g.bigBet / 100.0,2), s.currency, - bc.card1value, - bc.card1suit, - bc.card2value,bc.card2suit, - bc.card3value,bc.card3suit, - bc.card4value,bc.card4suit, - bc.card5value,bc.card5suit + h.boardcard1, + h.boardcard2, + h.boardcard3, + h.boardcard4, + h.boardcard5 from hands as h, - boardcards as bc, sites as s, gametypes as g, handsplayers as hp, players as p where h.id = %(handid)s -and bc.handid = h.id and g.id = h.gametypeid and hp.handid = h.id and p.id = hp.playerid @@ -1198,24 +1249,15 @@ limit 1""", {'handid':handid}) res = c.fetchone() gametype = {'category':res[1],'base':res[2],'type':res[3],'limitType':res[4],'hilo':res[5],'sb':res[6],'bb':res[7], 'currency':res[10]} h = HoldemOmahaHand(hhc = None, sitename=res[0], gametype = gametype, handText=None, builtFrom = "DB", handid=handid) - rank = {0:'X',1:'1',2:'2',3:'3',4:'4', - 5:'5',6:'6',7:'7',8:'8',9:'9', - 10:'T',11:'J',12:'Q',13:'K',14:'A'} - ranks = [rank[r] for r in res[11:21:2]] - cards = map("".join, zip(ranks, res[12:21:2])) - - if cards[0] != "Xx": + cards = map(Card.valueSuitFromCard, res[11:16] ) + if cards[0]: h.setCommunityCards('FLOP', cards[0:3]) - if cards[3] != "Xx": + if cards[3]: h.setCommunityCards('TURN', [cards[3]]) - if cards[4] != "Xx": + if cards[4]: h.setCommunityCards('RIVER', [cards[4]]) #[Card.valueSuitFromCard(x) for x in cards] - - #TODO : doesn't look like this is in the database; don't like the way Hand requires it - h.hero = 'mcturnbull' - # HandInfo : HID, TABLE # BUTTON - why is this treated specially in Hand? # answer: it is written out in hand histories @@ -1241,7 +1283,8 @@ SELECT round(hp.winnings / 100.0,2) as winnings, p.name, round(hp.startcash / 100.0,2) as chips, - hp.card1,hp.card2 + hp.card1,hp.card2, + hp.position FROM handsplayers as hp, players as p @@ -1249,12 +1292,16 @@ WHERE hp.handid = %(handid)s and p.id = hp.playerid """, {'handid':handid}) - for (seat, winnings, name, chips, card1,card2) in c.fetchall(): + for (seat, winnings, name, chips, card1,card2, position) in c.fetchall(): h.addPlayer(seat,name,chips) - h.addHoleCards(map(Card.valueSuitFromCard, (card1,card2)),name) + if card1 and card2: + h.addHoleCards(map(Card.valueSuitFromCard, (card1,card2)), name, dealt=True) if winnings > 0: h.addCollectPot(name, winnings) + if position == 'B': + h.buttonpos = seat + # actions c.execute(""" SELECT @@ -1278,7 +1325,7 @@ ORDER BY res = c.fetchall() for (actnum,player, streetnum, act, allin, amount) in res: act=act.strip() - street = h.streetList[streetnum+2] + street = h.allStreets[streetnum+1] if act==u'blind': h.addBlind(player, 'big blind', amount) # TODO: The type of blind is not recorded in the DB. diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 703dadcf..aaf18463 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -208,7 +208,7 @@ follow : whether to tail -f the input""" for a in self.re_PostBB.finditer(hand.handText): hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB')) for a in self.re_PostBoth.finditer(hand.handText): - hand.addBlind(a.group('PNAME'), 'small & big blinds', a.group('SBBB')) + hand.addBlind(a.group('PNAME'), 'both', a.group('SBBB')) def readHeroCards(self, hand): m = self.re_HeroCards.search(hand.handText) From afddc130a5cea12e5d86274597b5b22d79a55524 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 19 Jun 2009 09:39:17 -0400 Subject: [PATCH 022/143] Fix minor error in writing seen hole cards. --- pyfpdb/Hand.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 5342487b..c8481269 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -703,11 +703,12 @@ Card ranks will be uppercased if board: # sometimes hand ends preflop without a board print >>fh, ("Board [%s]" % (" ".join(board))) + print "holecards =", self.holecards for player in [x for x in self.players if x[1] in players_who_act_preflop]: seatnum = player[0] name = player[1] if name in self.collectees and name in self.shown: - print >>fh, ("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards[name]['PREFLOP']), self.collectees[name])) + print >>fh, ("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards['PREFLOP'][name]), self.collectees[name])) elif name in self.collectees: print >>fh, ("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name])) #~ elif name in self.shown: @@ -716,7 +717,7 @@ Card ranks will be uppercased print >>fh, ("Seat %d: %s folded" % (seatnum, name)) else: if name in self.shown: - print >>fh, ("Seat %d: %s showed [%s] and lost with..." % (seatnum, name, " ".join(self.holecards[name]['PREFLOP']))) + print >>fh, ("Seat %d: %s showed [%s] and lost with..." % (seatnum, name, " ".join(self.holecards['PREFLOP'][name]))) else: print >>fh, ("Seat %d: %s mucked" % (seatnum, name)) From 053bfb9cee0f5b9c263004bcadc6b5a115cb4d37 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 19 Jun 2009 09:43:49 -0400 Subject: [PATCH 023/143] Remove intermediate print from previous commit. --- pyfpdb/Hand.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index c8481269..6849a32c 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -703,7 +703,6 @@ Card ranks will be uppercased if board: # sometimes hand ends preflop without a board print >>fh, ("Board [%s]" % (" ".join(board))) - print "holecards =", self.holecards for player in [x for x in self.players if x[1] in players_who_act_preflop]: seatnum = player[0] name = player[1] From a47ff7fb9be821870197ef36c3b6e1bcf14c1890 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 20 Jun 2009 00:58:41 +0800 Subject: [PATCH 024/143] Fix case sensitivity in test for Hands table before dropping --- pyfpdb/fpdb_db.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 7c1fc800..86776b82 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -578,7 +578,7 @@ class fpdb_db: self.cursor.execute( "lock tables Hands write" ) except: # Table 'fpdb.hands' doesn't exist - if str(sys.exc_value).find(".hands' doesn't exist") >= 0: + if str(sys.exc_value).find(".Hands' doesn't exist") >= 0: return(2) print "Error! failed to obtain global lock. Close all programs accessing " \ + "database (including fpdb) and try again (%s)." \ From 966fba2165334dee1a2c9bee0d0491c9c1045bd7 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 20 Jun 2009 01:17:06 +0800 Subject: [PATCH 025/143] Fix parameter being passed to Sql __init__ db_server not db_backend --- pyfpdb/Database.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 10780c69..f8dd8f0d 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -45,7 +45,7 @@ class Database: db_params = c.get_db_parameters() self.type = db_params['db-type'] - self.sql = SQL.Sql(game = game, type = self.type, db_server = db_params['db-backend']) + self.sql = SQL.Sql(game = game, type = self.type, db_server = db_params['db-server']) self.connection.rollback() # To add to config: From fdf4b65136f8e0d1c7f9cde859bb3de759ca33cd Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 9 Jun 2009 22:55:18 +0100 Subject: [PATCH 026/143] pass all settings through so that a new one can be used to skip updating hudcache (not used yet) --- pyfpdb/fpdb_import.py | 2 +- pyfpdb/fpdb_save_to_db.py | 36 ++++++++++++++++++++++-------------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 99330bb9..3fa20b40 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -394,7 +394,7 @@ class Importer: self.hand=hand try: - handsId = fpdb_parse_logic.mainParser(self.settings['db-backend'], self.fdb.db + handsId = fpdb_parse_logic.mainParser(self.settings, self.fdb.db ,self.fdb.cursor, self.siteIds[site], category, hand, self.config) self.fdb.db.commit() diff --git a/pyfpdb/fpdb_save_to_db.py b/pyfpdb/fpdb_save_to_db.py index e612a166..b6e8686c 100644 --- a/pyfpdb/fpdb_save_to_db.py +++ b/pyfpdb/fpdb_save_to_db.py @@ -34,11 +34,12 @@ saveActions = True # set this to False to avoid storing action data # variance not available on stats page # : No graphs #stores a stud/razz hand into the database -def ring_stud(config, backend, db, cursor, base, category, site_hand_no, gametype_id, hand_start_time +def ring_stud(config, settings, db, cursor, base, category, site_hand_no, gametype_id, hand_start_time ,names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes ,action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName ,seatNos): + backend = settings['db-backend'] import_options = config.get_import_parameters() saveActions = False if import_options['saveActions'] == False else True @@ -54,7 +55,8 @@ def ring_stud(config, backend, db, cursor, base, category, site_hand_no, gametyp ,start_cashes, antes, card_values ,card_suits, winnings, rakes, seatNos) - fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': + fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) if saveActions: fpdb_simple.storeActions(cursor, hands_players_ids, action_types @@ -62,12 +64,13 @@ def ring_stud(config, backend, db, cursor, base, category, site_hand_no, gametyp return hands_id #end def ring_stud -def ring_holdem_omaha(config, backend, db, cursor, base, category, site_hand_no, gametype_id +def ring_holdem_omaha(config, settings, db, cursor, base, category, site_hand_no, gametype_id ,hand_start_time, names, player_ids, start_cashes, positions, card_values ,card_suits, board_values, board_suits, winnings, rakes, action_types, allIns ,action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): """stores a holdem/omaha hand into the database""" + backend = settings['db-backend'] import_options = config.get_import_parameters() saveActions = False if import_options['saveActions'] == False else True fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False @@ -90,10 +93,11 @@ def ring_holdem_omaha(config, backend, db, cursor, base, category, site_hand_no, , positions, card_values, card_suits, winnings, rakes, seatNos, hudImportData) t4 = time() #print "ring holdem, backend=%d" % backend - if fastStoreHudCache: - fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - else: - fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': + if fastStoreHudCache: + fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + else: + fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) t5 = time() fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) t6 = time() @@ -104,7 +108,7 @@ def ring_holdem_omaha(config, backend, db, cursor, base, category, site_hand_no, return hands_id #end def ring_holdem_omaha -def tourney_holdem_omaha(config, backend, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout +def tourney_holdem_omaha(config, settings, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout ,entries, prizepool, tourney_start, payin_amounts, ranks, tourneyTypeId ,siteId #end of tourney specific params ,site_hand_no, gametype_id, hand_start_time, names, player_ids @@ -113,6 +117,7 @@ def tourney_holdem_omaha(config, backend, db, cursor, base, category, siteTourne ,actionNos, hudImportData, maxSeats, tableName, seatNos): """stores a tourney holdem/omaha hand into the database""" + backend = settings['db-backend'] import_options = config.get_import_parameters() saveActions = True if import_options['saveActions'] == True else False fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False @@ -131,10 +136,11 @@ def tourney_holdem_omaha(config, backend, db, cursor, base, category, siteTourne , card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids) #print "tourney holdem, backend=%d" % backend - if fastStoreHudCache: - fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - else: - fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': + if fastStoreHudCache: + fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + else: + fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) @@ -143,13 +149,14 @@ def tourney_holdem_omaha(config, backend, db, cursor, base, category, siteTourne return hands_id #end def tourney_holdem_omaha -def tourney_stud(config, backend, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries +def tourney_stud(config, settings, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries ,prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteId ,siteHandNo, gametypeId, handStartTime, names, playerIds, startCashes, antes ,cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts ,actionNos, hudImportData, maxSeats, tableName, seatNos): #stores a tourney stud/razz hand into the database + backend = settings['db-backend'] import_options = config.get_import_parameters() saveActions = True if import_options['saveActions'] == True else False fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False @@ -166,7 +173,8 @@ def tourney_stud(config, backend, db, cursor, base, category, siteTourneyNo, buy , playerIds, startCashes, antes, cardValues, cardSuits , winnings, rakes, seatNos, tourneys_players_ids) - fpdb_simple.storeHudCache(backend, cursor, base, category, gametypeId, hand_start_time, playerIds, hudImportData) + if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': + fpdb_simple.storeHudCache(backend, cursor, base, category, gametypeId, hand_start_time, playerIds, hudImportData) if saveActions: fpdb_simple.storeActions(cursor, hands_players_ids, actionTypes, allIns, actionAmounts, actionNos) From e00887b865d4d58e31e0441a6d8900b50959769f Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 19 Jun 2009 15:47:26 -0400 Subject: [PATCH 027/143] Make Flop_Mucked work with the 0-52 card encoding. --- pyfpdb/Mucked.py | 52 +++++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/pyfpdb/Mucked.py b/pyfpdb/Mucked.py index 8ae6bc60..be9228d3 100755 --- a/pyfpdb/Mucked.py +++ b/pyfpdb/Mucked.py @@ -37,7 +37,7 @@ import Configuration import Database import Card -class Aux_Window: +class Aux_Window(object): def __init__(self, hud, params, config): self.hud = hud self.params = params @@ -94,9 +94,11 @@ class Aux_Window: return (card[0], card[1].upper()) def has_cards(self, cards): + """Returns the number of cards in the list.""" + n = 0 for c in cards: - if c in set('shdc'): return True - return False + if c != None and c > 0: n = n + 1 + return n class Stud_mucked(Aux_Window): def __init__(self, hud, config, params): @@ -329,21 +331,26 @@ class Stud_cards: self.seen_cards[(c, r)].set_from_pixbuf(self.card_images[0]) self.eb[(c, r)].set_tooltip_text('') -class Flop_Mucked(Aux_Window): - """Aux_Window class for displaying mucked cards for flop games.""" +class Aux_Seats(Aux_Window): + """A super class to display an aux_window at each seat.""" def __init__(self, hud, config, params): self.hud = hud # hud object that this aux window supports self.config = config # configuration object for this aux window to use self.params = params # dict aux params from config self.positions = {} # dict of window positions -# self.rel_positions = {} # dict of window positions, relative to the table origin - self.displayed_cards = False + self.displayed = False self.timer_on = False # bool = Ture if the timeout for removing the cards is on + +class Flop_Mucked(Aux_Seats): + """Aux_Window class for displaying mucked cards for flop games.""" + + def __init__(self, hud, config, params): + super(Flop_Mucked, self).__init__(hud, config, params) self.card_images = self.get_card_images() def create(self): - self.adj = self.hud.adj_seats(0, self.config) + self.adj = self.hud.adj_seats(0, self.config) # move adj_seats to aux and get rid of it in Hud.py loc = self.config.get_aux_locations(self.params['name'], int(self.hud.max)) self.m_windows = {} # windows to put the card images in @@ -364,7 +371,7 @@ class Flop_Mucked(Aux_Window): self.eb[i].connect("button_press_event", self.button_press_cb) self.m_windows[i].connect("configure_event", self.configure_event_cb, i) self.m_windows[i].add(self.eb[i]) - self.seen_cards[i] = gtk.image_new_from_pixbuf(self.card_images[('B', 'H')]) + self.seen_cards[i] = gtk.image_new_from_pixbuf(self.card_images[0]) self.eb[i].add(self.seen_cards[i]) self.positions[i] = (int(x) + self.hud.table.x, int(y) + self.hud.table.y) # self.rel_positions[i] = (int(x), int(y)) @@ -373,35 +380,40 @@ class Flop_Mucked(Aux_Window): self.m_windows[i].show_all() self.m_windows[i].hide() + def create_contents(self, i): + """Create the widgets for showing the contents of the Aux_seats window.""" + def update_gui(self, new_hand_id): """Prepare and show the mucked cards.""" - if self.displayed_cards: + if self.displayed: self.hide_mucked_cards() - self.displayed_cards = False + self.displayed = False for (i, cards) in self.hud.cards.iteritems(): - if self.has_cards(cards): + n_cards = self.has_cards(cards) + if n_cards > 0: # scratch is a working pixbuf, used to assemble the image scratch = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, - int(self.params['card_wd'])*len(cards)/2, + int(self.params['card_wd'])*n_cards, int(self.params['card_ht'])) x = 0 # x coord where the next card starts in scratch - for card in [cards[k:k+2] for k in xrange(0, len(cards), 2)]: + for card in cards: # concatenate each card image to scratch - self.card_images[self.split_cards(card)].copy_area(0, 0, + if card == None or card ==0: + break + self.card_images[card].copy_area(0, 0, int(self.params['card_wd']), int(self.params['card_ht']), scratch, x, 0) x = x + int(self.params['card_wd']) self.seen_cards[i].set_from_pixbuf(scratch) -# self.m_windows[i].show_all() self.m_windows[i].resize(1,1) self.m_windows[i].show() self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) # here is where I move back - self.displayed_cards = True + self.displayed = True for stats in self.hud.stat_dict.itervalues(): self.eb[stats['seat']].set_tooltip_text(stats['screen_name']) - if self.displayed_cards and float(self.params['timeout']) > 0: + if self.displayed and float(self.params['timeout']) > 0: self.timer_on = True gobject.timeout_add(int(1000*float(self.params['timeout'])), self.timed_out) @@ -425,7 +437,7 @@ class Flop_Mucked(Aux_Window): """Hide the mucked card windows.""" for (i, w) in self.m_windows.iteritems(): w.hide() - self.displayed_cards = False + self.displayed = False def button_press_cb(self, widget, event, *args): """Handle button clicks in the event boxes.""" @@ -458,7 +470,7 @@ class Flop_Mucked(Aux_Window): for (i, cards) in self.hud.cards.iteritems(): self.m_windows[i].show() self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) # here is where I move back - self.displayed_cards = True + self.displayed = True def save_layout(self, *args): """Save new layout back to the aux element in the config file.""" From a30708157462b66788432daf1fe66ef3b28d327d Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 19 Jun 2009 15:51:56 -0400 Subject: [PATCH 028/143] More for Flop_Mucked with 0-52 encoding. --- pyfpdb/Database.py | 8 ++------ pyfpdb/SQL.py | 21 ++++++++------------- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index b6c97a29..d3abfa06 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -170,12 +170,8 @@ class Database: cards = {} c = self.connection.cursor() c.execute(self.sql.query['get_common_cards'], [hand]) - colnames = [desc[0] for desc in c.description] - for row in c.fetchall(): - s_dict = {} - for name, val in zip(colnames, row): - s_dict[name] = val - cards['common'] = (self.convert_cards(s_dict)) +# row = c.fetchone() + cards['common'] = c.fetchone() return cards def convert_cards(self, d): diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 1a9deb60..77115c50 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -541,19 +541,14 @@ class Sql: """ self.query['get_common_cards'] = """ - select - card1Value AS card1value, - card1Suit AS card1suit, - card2Value AS card2value, - card2Suit AS card2suit, - card3Value AS card3value, - card3Suit AS card3suit, - card4Value AS card4value, - card4Suit AS card4suit, - card5Value AS card5value, - card5Suit AS card5suit - from BoardCards - where handId = %s + select + boardcard1, + boardcard2, + boardcard3, + boardcard4, + boardcard5 + from Hands + where Id = %s """ self.query['get_action_from_hand'] = """ From f1921bebdea33ab3c6624bce7356c750e3fa2d56 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 20 Jun 2009 04:15:52 +0800 Subject: [PATCH 029/143] Move functions from fpdb_save_to_db into Database.py Doesn't actually do much cleanup. Intend on moving all db functions into Database.py and fpdb_db.py and providing and API, the functionality of fpdb_simple et all to shift into the HHC --- pyfpdb/Database.py | 167 ++++++++++++++++++++++++++++++++++ pyfpdb/fpdb_import.py | 4 +- pyfpdb/fpdb_parse_logic.py | 38 ++++---- pyfpdb/fpdb_save_to_db.py | 182 ------------------------------------- 4 files changed, 189 insertions(+), 202 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index f8dd8f0d..7c13283c 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -33,6 +33,7 @@ import string # FreePokerTools modules import fpdb_db +import fpdb_simple import Configuration import SQL import Card @@ -77,6 +78,9 @@ class Database: #cur.execute(self.sql.query['get_table_name'], (hand_id, )) #row = cur.fetchone() + def commit(self): + self.fdb.db.commit() + def close_connection(self): self.connection.close() @@ -264,6 +268,169 @@ class Database: else: return None +#import fpdb_simple +# +#MYSQL_INNODB = 2 +#PGSQL = 3 +#SQLITE = 4 +# +#fastStoreHudCache = False # set this to True to test the new storeHudCache routine +# +#saveActions = True # set this to False to avoid storing action data +# # Pros: speeds up imports +# # Cons: no action data is saved, so you need to keep the hand histories +# # variance not available on stats page +# # : No graphs + + + #stores a stud/razz hand into the database + def ring_stud(self, config, settings, db, cursor, base, category, site_hand_no, gametype_id, hand_start_time + ,names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes + ,action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName + ,seatNos): + + backend = settings['db-backend'] + import_options = config.get_import_parameters() + + saveActions = False if import_options['saveActions'] == False else True + fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False + + fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) + + hands_id = fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id + ,hand_start_time, names, tableName, maxSeats, hudImportData) + + #print "before calling store_hands_players_stud, antes:", antes + hands_players_ids = fpdb_simple.store_hands_players_stud(backend, db, cursor, hands_id, player_ids + ,start_cashes, antes, card_values + ,card_suits, winnings, rakes, seatNos) + + if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': + fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + + if saveActions: + fpdb_simple.storeActions(cursor, hands_players_ids, action_types + ,allIns, action_amounts, actionNos) + return hands_id + #end def ring_stud + + def ring_holdem_omaha(self, config, settings, db, cursor, base, category, site_hand_no, gametype_id + ,hand_start_time, names, player_ids, start_cashes, positions, card_values + ,card_suits, board_values, board_suits, winnings, rakes, action_types, allIns + ,action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): + """stores a holdem/omaha hand into the database""" + + backend = settings['db-backend'] + import_options = config.get_import_parameters() + saveActions = False if import_options['saveActions'] == False else True + fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False + + # print "DEBUG: saveActions = '%s' fastStoreHudCache = '%s'"%(saveActions, fastStoreHudCache) + # print "DEBUG: import_options = ", import_options + + t0 = time() + fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) + t1 = time() + fpdb_simple.fill_board_cards(board_values, board_suits) + t2 = time() + + hands_id = fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id + ,hand_start_time, names, tableName, maxSeats, + hudImportData, board_values, board_suits) + t3 = time() + hands_players_ids = fpdb_simple.store_hands_players_holdem_omaha( + backend, db, cursor, category, hands_id, player_ids, start_cashes + , positions, card_values, card_suits, winnings, rakes, seatNos, hudImportData) + t4 = time() + #print "ring holdem, backend=%d" % backend + if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': + if fastStoreHudCache: + fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + else: + fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + t5 = time() + fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) + t6 = time() + if saveActions: + fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) + t7 = time() + #print "fills=(%4.3f) saves=(%4.3f,%4.3f,%4.3f,%4.3f)" % (t2-t0, t3-t2, t4-t3, t5-t4, t6-t5) + return hands_id + #end def ring_holdem_omaha + + def tourney_holdem_omaha(self, config, settings, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout + ,entries, prizepool, tourney_start, payin_amounts, ranks, tourneyTypeId + ,siteId #end of tourney specific params + ,site_hand_no, gametype_id, hand_start_time, names, player_ids + ,start_cashes, positions, card_values, card_suits, board_values + ,board_suits, winnings, rakes, action_types, allIns, action_amounts + ,actionNos, hudImportData, maxSeats, tableName, seatNos): + """stores a tourney holdem/omaha hand into the database""" + + backend = settings['db-backend'] + import_options = config.get_import_parameters() + saveActions = True if import_options['saveActions'] == True else False + fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False + + fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) + fpdb_simple.fill_board_cards(board_values, board_suits) + + tourney_id = fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourney_start) + tourneys_players_ids = fpdb_simple.store_tourneys_players(cursor, tourney_id, player_ids, payin_amounts, ranks, winnings) + + hands_id = fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id + ,hand_start_time, names, tableName, maxSeats) + + hands_players_ids = fpdb_simple.store_hands_players_holdem_omaha_tourney( + backend, db, cursor, category, hands_id, player_ids, start_cashes, positions + , card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids) + + #print "tourney holdem, backend=%d" % backend + if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': + if fastStoreHudCache: + fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + else: + fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + + fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) + + if saveActions: + fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) + return hands_id + #end def tourney_holdem_omaha + + def tourney_stud(self, config, settings, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries + ,prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteId + ,siteHandNo, gametypeId, handStartTime, names, playerIds, startCashes, antes + ,cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts + ,actionNos, hudImportData, maxSeats, tableName, seatNos): + #stores a tourney stud/razz hand into the database + + backend = settings['db-backend'] + import_options = config.get_import_parameters() + saveActions = True if import_options['saveActions'] == True else False + fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False + + fpdb_simple.fillCardArrays(len(names), base, category, cardValues, cardSuits) + + tourney_id = fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourneyStartTime) + + tourneys_players_ids = fpdb_simple.store_tourneys_players(cursor, tourney_id, playerIds, payin_amounts, ranks, winnings) + + hands_id = fpdb_simple.storeHands(backend, db, cursor, siteHandNo, gametypeId, handStartTime, names, tableName, maxSeats) + + hands_players_ids = fpdb_simple.store_hands_players_stud_tourney(backend, db, cursor, hands_id + , playerIds, startCashes, antes, cardValues, cardSuits + , winnings, rakes, seatNos, tourneys_players_ids) + + if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': + fpdb_simple.storeHudCache(backend, cursor, base, category, gametypeId, hand_start_time, playerIds, hudImportData) + + if saveActions: + fpdb_simple.storeActions(cursor, hands_players_ids, actionTypes, allIns, actionAmounts, actionNos) + return hands_id + #end def tourney_stud + if __name__=="__main__": c = Configuration.Config() diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 3fa20b40..99411573 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -394,8 +394,8 @@ class Importer: self.hand=hand try: - handsId = fpdb_parse_logic.mainParser(self.settings, self.fdb.db - ,self.fdb.cursor, self.siteIds[site], category, hand, self.config) + handsId = fpdb_parse_logic.mainParser(self.settings, self.fdb + , self.siteIds[site], category, hand, self.config) self.fdb.db.commit() stored += 1 diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py index ee5d9c40..eff8179f 100644 --- a/pyfpdb/fpdb_parse_logic.py +++ b/pyfpdb/fpdb_parse_logic.py @@ -18,11 +18,13 @@ #methods that are specific to holdem but not trivial import fpdb_simple -import fpdb_save_to_db +import Database #parses a holdem hand -def mainParser(settings, db, cursor, siteID, category, hand, config): +def mainParser(settings, fdb, siteID, category, hand, config): backend = settings['db-backend'] + #This is redundant - hopefully fdb will be a Database object in an interation soon + db = Database.Database(config, 'fpdb', '') category = fpdb_simple.recogniseCategory(hand[0]) base = "hold" if category == "holdem" or category == "omahahi" or category == "omahahilo" else "stud" @@ -47,7 +49,7 @@ def mainParser(settings, db, cursor, siteID, category, hand, config): break #print "small blind line:",smallBlindLine - gametypeID = fpdb_simple.recogniseGametypeID(backend, db, cursor, hand[0], hand[smallBlindLine], siteID, category, isTourney) + gametypeID = fpdb_simple.recogniseGametypeID(backend, fdb.db, fdb.cursor, hand[0], hand[smallBlindLine], siteID, category, isTourney) if isTourney: siteTourneyNo = fpdb_simple.parseTourneyNo(hand[0]) buyin = fpdb_simple.parseBuyin(hand[0]) @@ -58,9 +60,9 @@ def mainParser(settings, db, cursor, siteID, category, hand, config): tourneyStartTime= handStartTime #todo: read tourney start time rebuyOrAddon = fpdb_simple.isRebuyOrAddon(hand[0]) - tourneyTypeId = fpdb_simple.recogniseTourneyTypeId(cursor, siteID, buyin, fee, knockout, rebuyOrAddon) + tourneyTypeId = fpdb_simple.recogniseTourneyTypeId(fdb.cursor, siteID, buyin, fee, knockout, rebuyOrAddon) - fpdb_simple.isAlreadyInDB(cursor, gametypeID, siteHandNo) + fpdb_simple.isAlreadyInDB(fdb.cursor, gametypeID, siteHandNo) hand = fpdb_simple.filterCrap(hand, isTourney) @@ -74,7 +76,7 @@ def mainParser(settings, db, cursor, siteID, category, hand, config): seatLines.append(line) names = fpdb_simple.parseNames(seatLines) - playerIDs = fpdb_simple.recognisePlayerIDs(cursor, names, siteID) + playerIDs = fpdb_simple.recognisePlayerIDs(fdb.cursor, names, siteID) tmp = fpdb_simple.parseCashesAndSeatNos(seatLines) startCashes = tmp['startCashes'] seatNos = tmp['seatNos'] @@ -113,7 +115,7 @@ def mainParser(settings, db, cursor, siteID, category, hand, config): tableName = tableResult['tableName'] #print "before part5, antes:", antes - #part 5: final preparations, then call fpdb_save_to_db.* with + #part 5: final preparations, then call Database.* with # the arrays as they are - that file will fill them. fpdb_simple.convertCardValues(cardValues) if base == "hold": @@ -121,8 +123,8 @@ def mainParser(settings, db, cursor, siteID, category, hand, config): fpdb_simple.convertBlindBet(actionTypes, actionAmounts) fpdb_simple.checkPositions(positions) - cursor.execute("SELECT limitType FROM Gametypes WHERE id=%s",(gametypeID, )) - limit_type = cursor.fetchone()[0] + fdb.cursor.execute("SELECT limitType FROM Gametypes WHERE id=%s",(gametypeID, )) + limit_type = fdb.cursor.fetchone()[0] fpdb_simple.convert3B4B(category, limit_type, actionTypes, actionAmounts) totalWinnings = sum(winnings) @@ -143,8 +145,8 @@ def mainParser(settings, db, cursor, siteID, category, hand, config): payin_amounts = fpdb_simple.calcPayin(len(names), buyin, fee) if base == "hold": - result = fpdb_save_to_db.tourney_holdem_omaha( - config, settings, db, cursor, base, category, siteTourneyNo, buyin + result = db.tourney_holdem_omaha( + config, settings, fdb.db, fdb.cursor, base, category, siteTourneyNo, buyin , fee, knockout, entries, prizepool, tourneyStartTime , payin_amounts, ranks, tourneyTypeId, siteID, siteHandNo , gametypeID, handStartTime, names, playerIDs, startCashes @@ -152,8 +154,8 @@ def mainParser(settings, db, cursor, siteID, category, hand, config): , winnings, rakes, actionTypes, allIns, actionAmounts , actionNos, hudImportData, maxSeats, tableName, seatNos) elif base == "stud": - result = fpdb_save_to_db.tourney_stud( - config, settings, db, cursor, base, category, siteTourneyNo + result = db.tourney_stud( + config, settings, fdb.db, fdb.cursor, base, category, siteTourneyNo , buyin, fee, knockout, entries, prizepool, tourneyStartTime , payin_amounts, ranks, tourneyTypeId, siteID, siteHandNo , gametypeID, handStartTime, names, playerIDs, startCashes @@ -164,23 +166,23 @@ def mainParser(settings, db, cursor, siteID, category, hand, config): raise fpdb_simple.FpdbError("unrecognised category") else: if base == "hold": - result = fpdb_save_to_db.ring_holdem_omaha( - config, settings, db, cursor, base, category, siteHandNo + result = db.ring_holdem_omaha( + config, settings, fdb.db, fdb.cursor, base, category, siteHandNo , gametypeID, handStartTime, names, playerIDs , startCashes, positions, cardValues, cardSuits , boardValues, boardSuits, winnings, rakes , actionTypes, allIns, actionAmounts, actionNos , hudImportData, maxSeats, tableName, seatNos) elif base == "stud": - result = fpdb_save_to_db.ring_stud( - config, settings, db, cursor, base, category, siteHandNo, gametypeID + result = db.ring_stud( + config, settings, fdb.db, fdb.cursor, base, category, siteHandNo, gametypeID , handStartTime, names, playerIDs, startCashes, antes , cardValues, cardSuits, winnings, rakes, actionTypes, allIns , actionAmounts, actionNos, hudImportData, maxSeats, tableName , seatNos) else: raise fpdb_simple.FpdbError ("unrecognised category") - db.commit() + fdb.db.commit() return result #end def mainParser diff --git a/pyfpdb/fpdb_save_to_db.py b/pyfpdb/fpdb_save_to_db.py index b6e8686c..e69de29b 100644 --- a/pyfpdb/fpdb_save_to_db.py +++ b/pyfpdb/fpdb_save_to_db.py @@ -1,182 +0,0 @@ -#!/usr/bin/python - -#Copyright 2008 Steffen Jobbagy-Felso -#This program is free software: you can redistribute it and/or modify -#it under the terms of the GNU Affero General Public License as published by -#the Free Software Foundation, version 3 of the License. -# -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU Affero General Public License -#along with this program. If not, see . -#In the "official" distribution you can find the license in -#agpl-3.0.txt in the docs folder of the package. - -#This file contains methods to store hands into the db. decides to move this -#into a seperate file since its ugly, fairly long and just generally in the way. - -from time import time - -import fpdb_simple - -MYSQL_INNODB = 2 -PGSQL = 3 -SQLITE = 4 - -fastStoreHudCache = False # set this to True to test the new storeHudCache routine - -saveActions = True # set this to False to avoid storing action data - # Pros: speeds up imports - # Cons: no action data is saved, so you need to keep the hand histories - # variance not available on stats page - # : No graphs -#stores a stud/razz hand into the database -def ring_stud(config, settings, db, cursor, base, category, site_hand_no, gametype_id, hand_start_time - ,names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes - ,action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName - ,seatNos): - - backend = settings['db-backend'] - import_options = config.get_import_parameters() - - saveActions = False if import_options['saveActions'] == False else True - fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False - - fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) - - hands_id = fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats, hudImportData) - - #print "before calling store_hands_players_stud, antes:", antes - hands_players_ids = fpdb_simple.store_hands_players_stud(backend, db, cursor, hands_id, player_ids - ,start_cashes, antes, card_values - ,card_suits, winnings, rakes, seatNos) - - if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': - fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - - if saveActions: - fpdb_simple.storeActions(cursor, hands_players_ids, action_types - ,allIns, action_amounts, actionNos) - return hands_id -#end def ring_stud - -def ring_holdem_omaha(config, settings, db, cursor, base, category, site_hand_no, gametype_id - ,hand_start_time, names, player_ids, start_cashes, positions, card_values - ,card_suits, board_values, board_suits, winnings, rakes, action_types, allIns - ,action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): - """stores a holdem/omaha hand into the database""" - - backend = settings['db-backend'] - import_options = config.get_import_parameters() - saveActions = False if import_options['saveActions'] == False else True - fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False - -# print "DEBUG: saveActions = '%s' fastStoreHudCache = '%s'"%(saveActions, fastStoreHudCache) -# print "DEBUG: import_options = ", import_options - - t0 = time() - fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) - t1 = time() - fpdb_simple.fill_board_cards(board_values, board_suits) - t2 = time() - - hands_id = fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats, - hudImportData, board_values, board_suits) - t3 = time() - hands_players_ids = fpdb_simple.store_hands_players_holdem_omaha( - backend, db, cursor, category, hands_id, player_ids, start_cashes - , positions, card_values, card_suits, winnings, rakes, seatNos, hudImportData) - t4 = time() - #print "ring holdem, backend=%d" % backend - if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': - if fastStoreHudCache: - fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - else: - fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - t5 = time() - fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) - t6 = time() - if saveActions: - fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) - t7 = time() - #print "fills=(%4.3f) saves=(%4.3f,%4.3f,%4.3f,%4.3f)" % (t2-t0, t3-t2, t4-t3, t5-t4, t6-t5) - return hands_id -#end def ring_holdem_omaha - -def tourney_holdem_omaha(config, settings, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout - ,entries, prizepool, tourney_start, payin_amounts, ranks, tourneyTypeId - ,siteId #end of tourney specific params - ,site_hand_no, gametype_id, hand_start_time, names, player_ids - ,start_cashes, positions, card_values, card_suits, board_values - ,board_suits, winnings, rakes, action_types, allIns, action_amounts - ,actionNos, hudImportData, maxSeats, tableName, seatNos): - """stores a tourney holdem/omaha hand into the database""" - - backend = settings['db-backend'] - import_options = config.get_import_parameters() - saveActions = True if import_options['saveActions'] == True else False - fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False - - fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) - fpdb_simple.fill_board_cards(board_values, board_suits) - - tourney_id = fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourney_start) - tourneys_players_ids = fpdb_simple.store_tourneys_players(cursor, tourney_id, player_ids, payin_amounts, ranks, winnings) - - hands_id = fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats) - - hands_players_ids = fpdb_simple.store_hands_players_holdem_omaha_tourney( - backend, db, cursor, category, hands_id, player_ids, start_cashes, positions - , card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids) - - #print "tourney holdem, backend=%d" % backend - if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': - if fastStoreHudCache: - fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - else: - fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - - fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) - - if saveActions: - fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) - return hands_id -#end def tourney_holdem_omaha - -def tourney_stud(config, settings, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries - ,prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteId - ,siteHandNo, gametypeId, handStartTime, names, playerIds, startCashes, antes - ,cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts - ,actionNos, hudImportData, maxSeats, tableName, seatNos): -#stores a tourney stud/razz hand into the database - - backend = settings['db-backend'] - import_options = config.get_import_parameters() - saveActions = True if import_options['saveActions'] == True else False - fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False - - fpdb_simple.fillCardArrays(len(names), base, category, cardValues, cardSuits) - - tourney_id = fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourneyStartTime) - - tourneys_players_ids = fpdb_simple.store_tourneys_players(cursor, tourney_id, playerIds, payin_amounts, ranks, winnings) - - hands_id = fpdb_simple.storeHands(backend, db, cursor, siteHandNo, gametypeId, handStartTime, names, tableName, maxSeats) - - hands_players_ids = fpdb_simple.store_hands_players_stud_tourney(backend, db, cursor, hands_id - , playerIds, startCashes, antes, cardValues, cardSuits - , winnings, rakes, seatNos, tourneys_players_ids) - - if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': - fpdb_simple.storeHudCache(backend, cursor, base, category, gametypeId, hand_start_time, playerIds, hudImportData) - - if saveActions: - fpdb_simple.storeActions(cursor, hands_players_ids, actionTypes, allIns, actionAmounts, actionNos) - return hands_id -#end def tourney_stud From c9572129a655ce6ae5773588fc895141f7dd7569 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 19 Jun 2009 16:48:42 -0400 Subject: [PATCH 030/143] Fix passing settings in import chain. --- pyfpdb/fpdb_import.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 99330bb9..3fa20b40 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -394,7 +394,7 @@ class Importer: self.hand=hand try: - handsId = fpdb_parse_logic.mainParser(self.settings['db-backend'], self.fdb.db + handsId = fpdb_parse_logic.mainParser(self.settings, self.fdb.db ,self.fdb.cursor, self.siteIds[site], category, hand, self.config) self.fdb.db.commit() From 2b3e507a3c5cd2a5e7ed09d1b87e00f221f0a32f Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 20 Jun 2009 05:33:33 +0800 Subject: [PATCH 031/143] Factor out some common code --- pyfpdb/Database.py | 80 +++++++++++++++------------------------------- 1 file changed, 25 insertions(+), 55 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 7c13283c..b394622a 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -45,7 +45,9 @@ class Database: self.connection = self.fdb.db db_params = c.get_db_parameters() + self.import_options = c.get_import_parameters() self.type = db_params['db-type'] + self.backend = db_params['db-backend'] self.sql = SQL.Sql(game = game, type = self.type, db_server = db_params['db-server']) self.connection.rollback() @@ -77,6 +79,9 @@ class Database: self.hand_nhands_ago = 0 # todo #cur.execute(self.sql.query['get_table_name'], (hand_id, )) #row = cur.fetchone() + self.saveActions = False if self.import_options['saveActions'] == False else True + self.fastStoreHudCache = True if self.import_options['fastStoreHudCache'] == True else False + def commit(self): self.fdb.db.commit() @@ -268,20 +273,6 @@ class Database: else: return None -#import fpdb_simple -# -#MYSQL_INNODB = 2 -#PGSQL = 3 -#SQLITE = 4 -# -#fastStoreHudCache = False # set this to True to test the new storeHudCache routine -# -#saveActions = True # set this to False to avoid storing action data -# # Pros: speeds up imports -# # Cons: no action data is saved, so you need to keep the hand histories -# # variance not available on stats page -# # : No graphs - #stores a stud/razz hand into the database def ring_stud(self, config, settings, db, cursor, base, category, site_hand_no, gametype_id, hand_start_time @@ -289,26 +280,20 @@ class Database: ,action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName ,seatNos): - backend = settings['db-backend'] - import_options = config.get_import_parameters() - - saveActions = False if import_options['saveActions'] == False else True - fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False - fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) - hands_id = fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id + hands_id = fpdb_simple.storeHands(self.backend, db, cursor, site_hand_no, gametype_id ,hand_start_time, names, tableName, maxSeats, hudImportData) #print "before calling store_hands_players_stud, antes:", antes - hands_players_ids = fpdb_simple.store_hands_players_stud(backend, db, cursor, hands_id, player_ids + hands_players_ids = fpdb_simple.store_hands_players_stud(self.backend, db, cursor, hands_id, player_ids ,start_cashes, antes, card_values ,card_suits, winnings, rakes, seatNos) if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': - fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - if saveActions: + if self.saveActions: fpdb_simple.storeActions(cursor, hands_players_ids, action_types ,allIns, action_amounts, actionNos) return hands_id @@ -320,11 +305,6 @@ class Database: ,action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): """stores a holdem/omaha hand into the database""" - backend = settings['db-backend'] - import_options = config.get_import_parameters() - saveActions = False if import_options['saveActions'] == False else True - fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False - # print "DEBUG: saveActions = '%s' fastStoreHudCache = '%s'"%(saveActions, fastStoreHudCache) # print "DEBUG: import_options = ", import_options @@ -334,24 +314,24 @@ class Database: fpdb_simple.fill_board_cards(board_values, board_suits) t2 = time() - hands_id = fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id + hands_id = fpdb_simple.storeHands(self.backend, db, cursor, site_hand_no, gametype_id ,hand_start_time, names, tableName, maxSeats, hudImportData, board_values, board_suits) t3 = time() hands_players_ids = fpdb_simple.store_hands_players_holdem_omaha( - backend, db, cursor, category, hands_id, player_ids, start_cashes + self.backend, db, cursor, category, hands_id, player_ids, start_cashes , positions, card_values, card_suits, winnings, rakes, seatNos, hudImportData) t4 = time() #print "ring holdem, backend=%d" % backend if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': - if fastStoreHudCache: - fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + if self.fastStoreHudCache: + fpdb_simple.storeHudCache2(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) else: - fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) t5 = time() fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) t6 = time() - if saveActions: + if self.saveActions: fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) t7 = time() #print "fills=(%4.3f) saves=(%4.3f,%4.3f,%4.3f,%4.3f)" % (t2-t0, t3-t2, t4-t3, t5-t4, t6-t5) @@ -367,34 +347,29 @@ class Database: ,actionNos, hudImportData, maxSeats, tableName, seatNos): """stores a tourney holdem/omaha hand into the database""" - backend = settings['db-backend'] - import_options = config.get_import_parameters() - saveActions = True if import_options['saveActions'] == True else False - fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False - fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) fpdb_simple.fill_board_cards(board_values, board_suits) tourney_id = fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourney_start) tourneys_players_ids = fpdb_simple.store_tourneys_players(cursor, tourney_id, player_ids, payin_amounts, ranks, winnings) - hands_id = fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id + hands_id = fpdb_simple.storeHands(self.backend, db, cursor, site_hand_no, gametype_id ,hand_start_time, names, tableName, maxSeats) hands_players_ids = fpdb_simple.store_hands_players_holdem_omaha_tourney( - backend, db, cursor, category, hands_id, player_ids, start_cashes, positions + self.backend, db, cursor, category, hands_id, player_ids, start_cashes, positions , card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids) #print "tourney holdem, backend=%d" % backend if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': - if fastStoreHudCache: - fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + if self.fastStoreHudCache: + fpdb_simple.storeHudCache2(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) else: - fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) - if saveActions: + if self.saveActions: fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) return hands_id #end def tourney_holdem_omaha @@ -406,27 +381,22 @@ class Database: ,actionNos, hudImportData, maxSeats, tableName, seatNos): #stores a tourney stud/razz hand into the database - backend = settings['db-backend'] - import_options = config.get_import_parameters() - saveActions = True if import_options['saveActions'] == True else False - fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False - fpdb_simple.fillCardArrays(len(names), base, category, cardValues, cardSuits) tourney_id = fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourneyStartTime) tourneys_players_ids = fpdb_simple.store_tourneys_players(cursor, tourney_id, playerIds, payin_amounts, ranks, winnings) - hands_id = fpdb_simple.storeHands(backend, db, cursor, siteHandNo, gametypeId, handStartTime, names, tableName, maxSeats) + hands_id = fpdb_simple.storeHands(self.backend, db, cursor, siteHandNo, gametypeId, handStartTime, names, tableName, maxSeats) - hands_players_ids = fpdb_simple.store_hands_players_stud_tourney(backend, db, cursor, hands_id + hands_players_ids = fpdb_simple.store_hands_players_stud_tourney(self.backend, db, cursor, hands_id , playerIds, startCashes, antes, cardValues, cardSuits , winnings, rakes, seatNos, tourneys_players_ids) if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': - fpdb_simple.storeHudCache(backend, cursor, base, category, gametypeId, hand_start_time, playerIds, hudImportData) + fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametypeId, hand_start_time, playerIds, hudImportData) - if saveActions: + if self.saveActions: fpdb_simple.storeActions(cursor, hands_players_ids, actionTypes, allIns, actionAmounts, actionNos) return hands_id #end def tourney_stud From 2569eeddc813304fd5a1b4bfe79d5ecc4611c8d4 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 20 Jun 2009 05:37:30 +0800 Subject: [PATCH 032/143] Remve legacy storeHudCache function --- pyfpdb/Database.py | 12 +-- pyfpdb/fpdb_simple.py | 183 ------------------------------------------ 2 files changed, 2 insertions(+), 193 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index b394622a..2762143e 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -80,7 +80,6 @@ class Database: #cur.execute(self.sql.query['get_table_name'], (hand_id, )) #row = cur.fetchone() self.saveActions = False if self.import_options['saveActions'] == False else True - self.fastStoreHudCache = True if self.import_options['fastStoreHudCache'] == True else False def commit(self): @@ -305,7 +304,6 @@ class Database: ,action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): """stores a holdem/omaha hand into the database""" - # print "DEBUG: saveActions = '%s' fastStoreHudCache = '%s'"%(saveActions, fastStoreHudCache) # print "DEBUG: import_options = ", import_options t0 = time() @@ -324,10 +322,7 @@ class Database: t4 = time() #print "ring holdem, backend=%d" % backend if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': - if self.fastStoreHudCache: - fpdb_simple.storeHudCache2(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - else: - fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) t5 = time() fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) t6 = time() @@ -362,10 +357,7 @@ class Database: #print "tourney holdem, backend=%d" % backend if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': - if self.fastStoreHudCache: - fpdb_simple.storeHudCache2(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - else: - fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index 398a20e5..34f99e2f 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -2126,189 +2126,6 @@ def storeHudCache(backend, cursor, base, category, gametypeId, hand_start_time, # hard-code styleKey as 'A000000' (all-time cache, no key) for now styleKey = 'A000000' - #print "storeHudCache, len(playerIds)=", len(playerIds), " len(vpip)=" \ - #, len(hudImportData['street0VPI']), " len(totprof)=", len(hudImportData['totalProfit']) - for player in xrange(len(playerIds)): - - # Set up a clean row - row=[] - row.append(0)#blank for id - row.append(gametypeId) - row.append(playerIds[player]) - row.append(len(playerIds))#seats - for i in xrange(len(hudImportData)+2): - row.append(0) - - if base=="hold": - row[4]=hudImportData['position'][player] - else: - row[4]=0 - row[5]=1 #tourneysGametypeId - row[6]+=1 #HDs - if hudImportData['street0VPI'][player]: row[7]+=1 - if hudImportData['street0Aggr'][player]: row[8]+=1 - if hudImportData['street0_3BChance'][player]: row[9]+=1 - if hudImportData['street0_3BDone'][player]: row[10]+=1 - if hudImportData['street1Seen'][player]: row[11]+=1 - if hudImportData['street2Seen'][player]: row[12]+=1 - if hudImportData['street3Seen'][player]: row[13]+=1 - if hudImportData['street4Seen'][player]: row[14]+=1 - if hudImportData['sawShowdown'][player]: row[15]+=1 - if hudImportData['street1Aggr'][player]: row[16]+=1 - if hudImportData['street2Aggr'][player]: row[17]+=1 - if hudImportData['street3Aggr'][player]: row[18]+=1 - if hudImportData['street4Aggr'][player]: row[19]+=1 - if hudImportData['otherRaisedStreet1'][player]: row[20]+=1 - if hudImportData['otherRaisedStreet2'][player]: row[21]+=1 - if hudImportData['otherRaisedStreet3'][player]: row[22]+=1 - if hudImportData['otherRaisedStreet4'][player]: row[23]+=1 - if hudImportData['foldToOtherRaisedStreet1'][player]: row[24]+=1 - if hudImportData['foldToOtherRaisedStreet2'][player]: row[25]+=1 - if hudImportData['foldToOtherRaisedStreet3'][player]: row[26]+=1 - if hudImportData['foldToOtherRaisedStreet4'][player]: row[27]+=1 - if hudImportData['wonWhenSeenStreet1'][player]!=0.0: row[28]+=hudImportData['wonWhenSeenStreet1'][player] - if hudImportData['wonAtSD'][player]!=0.0: row[29]+=hudImportData['wonAtSD'][player] - if hudImportData['stealAttemptChance'][player]: row[30]+=1 - if hudImportData['stealAttempted'][player]: row[31]+=1 - if hudImportData['foldBbToStealChance'][player]: row[32]+=1 - if hudImportData['foldedBbToSteal'][player]: row[33]+=1 - if hudImportData['foldSbToStealChance'][player]: row[34]+=1 - if hudImportData['foldedSbToSteal'][player]: row[35]+=1 - - if hudImportData['street1CBChance'][player]: row[36]+=1 - if hudImportData['street1CBDone'][player]: row[37]+=1 - if hudImportData['street2CBChance'][player]: row[38]+=1 - if hudImportData['street2CBDone'][player]: row[39]+=1 - if hudImportData['street3CBChance'][player]: row[40]+=1 - if hudImportData['street3CBDone'][player]: row[41]+=1 - if hudImportData['street4CBChance'][player]: row[42]+=1 - if hudImportData['street4CBDone'][player]: row[43]+=1 - - if hudImportData['foldToStreet1CBChance'][player]: row[44]+=1 - if hudImportData['foldToStreet1CBDone'][player]: row[45]+=1 - if hudImportData['foldToStreet2CBChance'][player]: row[46]+=1 - if hudImportData['foldToStreet2CBDone'][player]: row[47]+=1 - if hudImportData['foldToStreet3CBChance'][player]: row[48]+=1 - if hudImportData['foldToStreet3CBDone'][player]: row[49]+=1 - if hudImportData['foldToStreet4CBChance'][player]: row[50]+=1 - if hudImportData['foldToStreet4CBDone'][player]: row[51]+=1 - - #print "player=", player - #print "len(totalProfit)=", len(hudImportData['totalProfit']) - if hudImportData['totalProfit'][player]: - row[52]+=hudImportData['totalProfit'][player] - - if hudImportData['street1CheckCallRaiseChance'][player]: row[53]+=1 - if hudImportData['street1CheckCallRaiseDone'][player]: row[54]+=1 - if hudImportData['street2CheckCallRaiseChance'][player]: row[55]+=1 - if hudImportData['street2CheckCallRaiseDone'][player]: row[56]+=1 - if hudImportData['street3CheckCallRaiseChance'][player]: row[57]+=1 - if hudImportData['street3CheckCallRaiseDone'][player]: row[58]+=1 - if hudImportData['street4CheckCallRaiseChance'][player]: row[59]+=1 - if hudImportData['street4CheckCallRaiseDone'][player]: row[60]+=1 - - # Try to do the update first: - num = cursor.execute("""UPDATE HudCache -SET HDs=HDs+%s, street0VPI=street0VPI+%s, street0Aggr=street0Aggr+%s, - street0_3BChance=street0_3BChance+%s, street0_3BDone=street0_3BDone+%s, - street1Seen=street1Seen+%s, street2Seen=street2Seen+%s, street3Seen=street3Seen+%s, - street4Seen=street4Seen+%s, sawShowdown=sawShowdown+%s, - street1Aggr=street1Aggr+%s, street2Aggr=street2Aggr+%s, street3Aggr=street3Aggr+%s, - street4Aggr=street4Aggr+%s, otherRaisedStreet1=otherRaisedStreet1+%s, - otherRaisedStreet2=otherRaisedStreet2+%s, otherRaisedStreet3=otherRaisedStreet3+%s, - otherRaisedStreet4=otherRaisedStreet4+%s, - foldToOtherRaisedStreet1=foldToOtherRaisedStreet1+%s, foldToOtherRaisedStreet2=foldToOtherRaisedStreet2+%s, - foldToOtherRaisedStreet3=foldToOtherRaisedStreet3+%s, foldToOtherRaisedStreet4=foldToOtherRaisedStreet4+%s, - wonWhenSeenStreet1=wonWhenSeenStreet1+%s, wonAtSD=wonAtSD+%s, stealAttemptChance=stealAttemptChance+%s, - stealAttempted=stealAttempted+%s, foldBbToStealChance=foldBbToStealChance+%s, - foldedBbToSteal=foldedBbToSteal+%s, - foldSbToStealChance=foldSbToStealChance+%s, foldedSbToSteal=foldedSbToSteal+%s, - street1CBChance=street1CBChance+%s, street1CBDone=street1CBDone+%s, street2CBChance=street2CBChance+%s, - street2CBDone=street2CBDone+%s, street3CBChance=street3CBChance+%s, - street3CBDone=street3CBDone+%s, street4CBChance=street4CBChance+%s, street4CBDone=street4CBDone+%s, - foldToStreet1CBChance=foldToStreet1CBChance+%s, foldToStreet1CBDone=foldToStreet1CBDone+%s, - foldToStreet2CBChance=foldToStreet2CBChance+%s, foldToStreet2CBDone=foldToStreet2CBDone+%s, - foldToStreet3CBChance=foldToStreet3CBChance+%s, - foldToStreet3CBDone=foldToStreet3CBDone+%s, foldToStreet4CBChance=foldToStreet4CBChance+%s, - foldToStreet4CBDone=foldToStreet4CBDone+%s, totalProfit=totalProfit+%s, - street1CheckCallRaiseChance=street1CheckCallRaiseChance+%s, - street1CheckCallRaiseDone=street1CheckCallRaiseDone+%s, street2CheckCallRaiseChance=street2CheckCallRaiseChance+%s, - street2CheckCallRaiseDone=street2CheckCallRaiseDone+%s, street3CheckCallRaiseChance=street3CheckCallRaiseChance+%s, - street3CheckCallRaiseDone=street3CheckCallRaiseDone+%s, street4CheckCallRaiseChance=street4CheckCallRaiseChance+%s, - street4CheckCallRaiseDone=street4CheckCallRaiseDone+%s -WHERE gametypeId+0=%s -AND playerId=%s -AND activeSeats=%s -AND position=%s -AND tourneyTypeId+0=%s -AND styleKey=%s - """, (row[6], row[7], row[8], row[9], row[10], - row[11], row[12], row[13], row[14], row[15], - row[16], row[17], row[18], row[19], row[20], - row[21], row[22], row[23], row[24], row[25], - row[26], row[27], row[28], row[29], row[30], - row[31], row[32], row[33], row[34], row[35], - row[36], row[37], row[38], row[39], row[40], - row[41], row[42], row[43], row[44], row[45], - row[46], row[47], row[48], row[49], row[50], - row[51], row[52], row[53], row[54], row[55], - row[56], row[57], row[58], row[59], row[60], - row[1], row[2], row[3], str(row[4]), row[5], styleKey)) - # Test statusmessage to see if update worked, do insert if not - #print "storehud2, upd num =", num - if ( (backend == PGSQL and cursor.statusmessage != "UPDATE 1") - or (backend == MYSQL_INNODB and num == 0) ): - #print "playerid before insert:",row[2]," num = ", num - cursor.execute("""INSERT INTO HudCache -(gametypeId, playerId, activeSeats, position, tourneyTypeId, styleKey, -HDs, street0VPI, street0Aggr, street0_3BChance, street0_3BDone, -street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown, -street1Aggr, street2Aggr, street3Aggr, street4Aggr, otherRaisedStreet1, -otherRaisedStreet2, otherRaisedStreet3, otherRaisedStreet4, foldToOtherRaisedStreet1, foldToOtherRaisedStreet2, -foldToOtherRaisedStreet3, foldToOtherRaisedStreet4, wonWhenSeenStreet1, wonAtSD, stealAttemptChance, -stealAttempted, foldBbToStealChance, foldedBbToSteal, foldSbToStealChance, foldedSbToSteal, -street1CBChance, street1CBDone, street2CBChance, street2CBDone, street3CBChance, -street3CBDone, street4CBChance, street4CBDone, foldToStreet1CBChance, foldToStreet1CBDone, -foldToStreet2CBChance, foldToStreet2CBDone, foldToStreet3CBChance, foldToStreet3CBDone, foldToStreet4CBChance, -foldToStreet4CBDone, totalProfit, street1CheckCallRaiseChance, street1CheckCallRaiseDone, street2CheckCallRaiseChance, -street2CheckCallRaiseDone, street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone) -VALUES (%s, %s, %s, %s, %s, %s, -%s, %s, %s, %s, %s, -%s, %s, %s, %s, %s, -%s, %s, %s, %s, %s, -%s, %s, %s, %s, %s, -%s, %s, %s, %s, %s, -%s, %s, %s, %s, %s, -%s, %s, %s, %s, %s, -%s, %s, %s, %s, %s, -%s, %s, %s, %s, %s, -%s, %s, %s, %s, %s, -%s, %s, %s, %s, %s)""" - , (row[1], row[2], row[3], row[4], row[5], styleKey, row[6], row[7], row[8], row[9], row[10] - ,row[11], row[12], row[13], row[14], row[15], row[16], row[17], row[18], row[19], row[20] - ,row[21], row[22], row[23], row[24], row[25], row[26], row[27], row[28], row[29], row[30] - ,row[31], row[32], row[33], row[34], row[35], row[36], row[37], row[38], row[39], row[40] - ,row[41], row[42], row[43], row[44], row[45], row[46], row[47], row[48], row[49], row[50] - ,row[51], row[52], row[53], row[54], row[55], row[56], row[57], row[58], row[59], row[60]) ) - #print "hopefully inserted hud data line: ", cursor.statusmessage - # message seems to be "INSERT 0 1" - else: - #print "updated(2) hud data line" - pass -# else: -# print "todo: implement storeHudCache for stud base" -#end def storeHudCache - -def storeHudCache2(backend, cursor, base, category, gametypeId, hand_start_time, playerIds, hudImportData): - """Modified version aiming for more speed ...""" -# if (category=="holdem" or category=="omahahi" or category=="omahahilo"): - if use_date_in_hudcache: - #print "key =", "d%02d%02d%02d " % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day) - styleKey = "d%02d%02d%02d" % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day) - else: - # hard-code styleKey as 'A000000' (all-time cache, no key) for now - styleKey = 'A000000' - #print "storeHudCache2, len(playerIds)=", len(playerIds), " len(vpip)=" \ #, len(hudImportData['street0VPI']), " len(totprof)=", len(hudImportData['totalProfit']) for player in xrange(len(playerIds)): From 864e37ddc863d76b8a50de1beb4a0edf870d3fd8 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 20 Jun 2009 05:38:33 +0800 Subject: [PATCH 033/143] Remove empty file --- pyfpdb/fpdb_save_to_db.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 pyfpdb/fpdb_save_to_db.py diff --git a/pyfpdb/fpdb_save_to_db.py b/pyfpdb/fpdb_save_to_db.py deleted file mode 100644 index e69de29b..00000000 From d00031edf7d161cc4ec2c319e644d1063156501c Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 20 Jun 2009 06:22:57 +0800 Subject: [PATCH 034/143] Add get_last_insert_id() to Database API --- pyfpdb/Database.py | 6 ++++-- pyfpdb/fpdb_db.py | 30 +++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 2762143e..932a8578 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -272,6 +272,9 @@ class Database: else: return None + def get_last_insert_id(self): + return self.fdb.getLastInsertId() + #stores a stud/razz hand into the database def ring_stud(self, config, settings, db, cursor, base, category, site_hand_no, gametype_id, hand_start_time @@ -304,8 +307,6 @@ class Database: ,action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): """stores a holdem/omaha hand into the database""" - # print "DEBUG: import_options = ", import_options - t0 = time() fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) t1 = time() @@ -315,6 +316,7 @@ class Database: hands_id = fpdb_simple.storeHands(self.backend, db, cursor, site_hand_no, gametype_id ,hand_start_time, names, tableName, maxSeats, hudImportData, board_values, board_suits) + #TEMPORARY CALL! - Just until all functions are migrated t3 = time() hands_players_ids = fpdb_simple.store_hands_players_holdem_omaha( self.backend, db, cursor, category, hands_id, player_ids, start_cashes diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 86776b82..201b98fd 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -596,7 +596,35 @@ class fpdb_db: + "database (including fpdb) and try again (%s)." \ % ( str(sys.exc_value).rstrip('\n'), ) return(1) - return(0) + return(0) + + def getLastInsertId(self): + if self.backend == self.MYSQL_INNODB: + ret = self.db.insert_id() + if ret < 1 or ret > 999999999: + print "getLastInsertId(): problem fetching insert_id? ret=", ret + ret = -1 + elif self.backend == self.PGSQL: + # some options: + # currval(hands_id_seq) - use name of implicit seq here + # lastval() - still needs sequences set up? + # insert ... returning is useful syntax (but postgres specific?) + # see rules (fancy trigger type things) + self.cursor.execute ("SELECT lastval()") + row = self.cursor.fetchone() + if not row: + print "getLastInsertId(%s): problem fetching lastval? row=" % seq, row + ret = -1 + else: + ret = row[0] + elif self.backend == self.SQLITE: + # don't know how to do this in sqlite + print "getLastInsertId(): not coded for sqlite yet" + ret = -1 + else: + print "getLastInsertId(): unknown backend ", self.backend + ret = -1 + return ret def storeHand(self, p): #stores into table hands: From 706ce46a9f06c71a7eaa52a21ed5f6941da5e1c0 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 20 Jun 2009 07:58:53 +0800 Subject: [PATCH 035/143] Boardcards for Hands table in new importer --- pyfpdb/Hand.py | 9 +++++++++ pyfpdb/fpdb_db.py | 2 ++ 2 files changed, 11 insertions(+) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 6849a32c..38c3609b 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -111,6 +111,14 @@ db: a connected fpdb_db object""" # boardcard3 smallint, # boardcard4 smallint, # boardcard5 smallint, + # Flop turn and river may all be empty - add (likely) too many elements and trim with range + # boardcards = board['FLOP'] + board['TURN'] + board['RIVER'] + [u'0x', u'0x', u'0x', u'0x', u'0x'] + # cards = [Card.cardFromValueSuit(v,s) for v,s in boardcards[0:4]] + # hh['boardcard1'] = cards[0] + # hh['boardcard2'] = cards[1] + # hh['boardcard3'] = cards[2] + # hh['boardcard4'] = cards[3] + # hh['boardcard5'] = cards[4] # texture smallint, # playersVpi SMALLINT NOT NULL, /* num of players vpi */ # Needs to be recorded @@ -194,6 +202,7 @@ If a player has None chips he won't be added.""" def setCommunityCards(self, street, cards): logging.debug("setCommunityCards %s %s" %(street, cards)) self.board[street] = [self.card(c) for c in cards] + print "DEBUG: self.board: %s" % self.board def card(self,c): """upper case the ranks but not suits, 'atjqk' => 'ATJQK'""" diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 201b98fd..29817af9 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -630,6 +630,7 @@ class fpdb_db: #stores into table hands: self.cursor.execute ("""INSERT INTO Hands (siteHandNo, gametypeId, handStart, seats, tableName, importTime, maxSeats + ,boardcard1, boardcard2, boardcard3, boardcard4, boardcard5 ,playersVpi, playersAtStreet1, playersAtStreet2 ,playersAtStreet3, playersAtStreet4, playersAtShowdown ,street0Raises, street1Raises, street2Raises @@ -640,6 +641,7 @@ class fpdb_db: VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""" ,(p['siteHandNo'], gametype_id, p['handStart'], len(names), p['tableName'], datetime.datetime.today(), p['maxSeats'] + ,p['boardcard1'], ['boardcard2'], p['boardcard3'], ['boardcard4'], ['boardcard5'] ,hudCache['playersVpi'], hudCache['playersAtStreet1'], hudCache['playersAtStreet2'] ,hudCache['playersAtStreet3'], hudCache['playersAtStreet4'], hudCache['playersAtShowdown'] ,hudCache['street0Raises'], hudCache['street1Raises'], hudCache['street2Raises'] From 22ff98d7c9461c9e54351609574bbbc1b1e36723 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 20 Jun 2009 14:02:03 +0800 Subject: [PATCH 036/143] Remove passthrough section from import_file_dict --- pyfpdb/fpdb_import.py | 50 +++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 99411573..455c1e27 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -288,36 +288,34 @@ class Importer: if os.path.isdir(file): self.addToDirList[file] = [site] + [filter] return - if filter == "passthrough" or filter == "": - (stored, duplicates, partial, errors, ttime) = self.import_fpdb_file(file, site) - else: - conv = None - # Load filter, process file, pass returned filename to import_fpdb_file + + conv = None + # Load filter, process file, pass returned filename to import_fpdb_file - print "\nConverting %s" % file - hhbase = self.config.get_import_parameters().get("hhArchiveBase") - hhbase = os.path.expanduser(hhbase) - hhdir = os.path.join(hhbase,site) - try: - out_path = os.path.join(hhdir, file.split(os.path.sep)[-2]+"-"+os.path.basename(file)) - except: - out_path = os.path.join(hhdir, "x"+strftime("%d-%m-%y")+os.path.basename(file)) + print "\nConverting %s" % file + hhbase = self.config.get_import_parameters().get("hhArchiveBase") + hhbase = os.path.expanduser(hhbase) + hhdir = os.path.join(hhbase,site) + try: + out_path = os.path.join(hhdir, file.split(os.path.sep)[-2]+"-"+os.path.basename(file)) + except: + out_path = os.path.join(hhdir, "x"+strftime("%d-%m-%y")+os.path.basename(file)) - filter_name = filter.replace("ToFpdb", "") + filter_name = filter.replace("ToFpdb", "") - mod = __import__(filter) - obj = getattr(mod, filter_name, None) - if callable(obj): - conv = obj(in_path = file, out_path = out_path) - if(conv.getStatus()): - (stored, duplicates, partial, errors, ttime) = self.import_fpdb_file(out_path, site) - else: - # conversion didn't work - # TODO: appropriate response? - return (0, 0, 0, 1, 0) + mod = __import__(filter) + obj = getattr(mod, filter_name, None) + if callable(obj): + conv = obj(in_path = file, out_path = out_path) + if(conv.getStatus()): + (stored, duplicates, partial, errors, ttime) = self.import_fpdb_file(out_path, site) else: - print "Unknown filter filter_name:'%s' in filter:'%s'" %(filter_name, filter) - return + # conversion didn't work + # TODO: appropriate response? + return (0, 0, 0, 1, 0) + else: + print "Unknown filter filter_name:'%s' in filter:'%s'" %(filter_name, filter) + return #This will barf if conv.getStatus != True return (stored, duplicates, partial, errors, ttime) From 462ff87596648dc2ea41327543b705263dc4f4da Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 20 Jun 2009 09:43:05 -0400 Subject: [PATCH 037/143] Add xpad and ypad to site and game elements. Cleanup some defaults. --- pyfpdb/Configuration.py | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 0ea4b371..13e7cd28 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -86,14 +86,34 @@ class Site: self.aux_window = node.getAttribute("aux_window") self.font = node.getAttribute("font") self.font_size = node.getAttribute("font_size") - self.use_frames = node.getAttribute("use_frames") + self.use_frames = node.getAttribute("use_frames") self.enabled = fix_tf(node.getAttribute("enabled"), default = True) + self.xpad = node.getAttribute("xpad") + self.ypad = node.getAttribute("ypad") self.layout = {} for layout_node in node.getElementsByTagName('layout'): lo = Layout(layout_node) self.layout[lo.max] = lo +# Site defaults + if self.xpad == "": self.xpad = 1 + else: self.xpad = int(self.xpad) + + if self.ypad == "": self.ypad = 0 + else: self.ypad = int(self.ypad) + + if self.font_size == "": self.font_size = 7 + else: self.font_size = int(self.font_size) + + if self.hudopacity == "": self.hudopacity = 1.0 + else: self.hudopacity = float(self.hudopacity) + + if self.use_frames == "": self.use_frames = False + if self.font == "": self.font = "Sans" + if self.hudbgcolor == "": self.hudbgcolor = "000000" + if self.hudfgcolor == "": self.hudfgcolor = "FFFFFF" + def __str__(self): temp = "Site = " + self.site_name + "\n" for key in dir(self): @@ -119,9 +139,16 @@ class Stat: class Game: def __init__(self, node): self.game_name = node.getAttribute("game_name") - self.db = node.getAttribute("db") self.rows = int( node.getAttribute("rows") ) self.cols = int( node.getAttribute("cols") ) + self.xpad = node.getAttribute("xpad") + self.ypad = node.getAttribute("ypad") + +# Defaults + if self.xpad == "": self.xpad = 1 + else: self.xpad = int(self.xpad) + if self.ypad == "": self.ypad = 0 + else: self.ypad = int(self.ypad) aux_text = node.getAttribute("aux") aux_list = aux_text.split(',') @@ -146,9 +173,10 @@ class Game: def __str__(self): temp = "Game = " + self.game_name + "\n" - temp = temp + " db = %s\n" % self.db temp = temp + " rows = %d\n" % self.rows temp = temp + " cols = %d\n" % self.cols + temp = temp + " xpad = %d\n" % self.xpad + temp = temp + " ypad = %d\n" % self.ypad temp = temp + " aux = %s\n" % self.aux for stat in self.stats.keys(): @@ -631,6 +659,8 @@ class Config: parms["font"] = self.supported_sites[site].font parms["font_size"] = self.supported_sites[site].font_size parms["enabled"] = self.supported_sites[site].enabled + parms["xpad"] = self.supported_sites[site].xpad + parms["ypad"] = self.supported_sites[site].ypad return parms def set_site_parameters(self, site_name, converter = None, decoder = None, @@ -681,9 +711,10 @@ class Config: param = {} if self.supported_games.has_key(name): param['game_name'] = self.supported_games[name].game_name - param['db'] = self.supported_games[name].db param['rows'] = self.supported_games[name].rows param['cols'] = self.supported_games[name].cols + param['xpad'] = self.supported_games[name].xpad + param['ypad'] = self.supported_games[name].ypad param['aux'] = self.supported_games[name].aux return param From 287394c97dfcb4e764684973ae0dde0ab88ee289 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 20 Jun 2009 10:01:52 -0400 Subject: [PATCH 038/143] Use xpad and ypad from game element. --- pyfpdb/Hud.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 56ad08f3..77381749 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -445,10 +445,10 @@ class Stat_Window: Stats.do_tip(e_box[r][c], 'stuff') if usegtkframes: - grid.attach(self.frame[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0) + grid.attach(self.frame[r][c], c, c+1, r, r+1, xpadding = game.xpad, ypadding = game.ypad) self.frame[r][c].add(e_box[r][c]) else: - grid.attach(e_box[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0) + grid.attach(e_box[r][c], c, c+1, r, r+1, xpadding = game.xpad, ypadding = game.ypad) label[r].append( gtk.Label('xxx') ) if usegtkframes: From ac30e912c76bc3f6a731d5657850d1ee1133a0a4 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 22 Jun 2009 21:39:14 +0100 Subject: [PATCH 039/143] smarten up positional stats tab (still needs configurable columns) --- pyfpdb/GuiPositionalStats.py | 184 ++++++++++++++++++++++------------- 1 file changed, 119 insertions(+), 65 deletions(-) diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index 0e20e632..dce7cb77 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -62,17 +62,46 @@ class GuiPositionalStats (threading.Thread): self.filters.registerButton1Name("Refresh") self.filters.registerButton1Callback(self.refreshStats) + # ToDo: store in config + # ToDo: create popup to adjust column config + # columns to display, keys match column name returned by sql, values in tuple are: + # is column displayed, column heading, xalignment, formatting + self.columns = [ ["game", True, "Game", 0.0, "%s"] + , ["hand", False, "Hand", 0.0, "%s"] # true not allowed for this line + , ["plposition", False, "Posn", 1.0, "%s"] # true not allowed for this line (set in code) + , ["n", True, "Hds", 1.0, "%d"] + , ["avgseats", True, "Seats", 1.0, "%3.1f"] + , ["vpip", True, "VPIP", 1.0, "%3.1f"] + , ["pfr", True, "PFR", 1.0, "%3.1f"] + , ["pf3", True, "PF3", 1.0, "%3.1f"] + , ["steals", True, "Steals", 1.0, "%3.1f"] + , ["saw_f", True, "Saw_F", 1.0, "%3.1f"] + , ["sawsd", True, "SawSD", 1.0, "%3.1f"] + , ["wtsdwsf", True, "WtSDwsF", 1.0, "%3.1f"] + , ["wmsd", True, "W$SD", 1.0, "%3.1f"] + , ["flafq", True, "FlAFq", 1.0, "%3.1f"] + , ["tuafq", True, "TuAFq", 1.0, "%3.1f"] + , ["rvafq", True, "RvAFq", 1.0, "%3.1f"] + , ["pofafq", False, "PoFAFq", 1.0, "%3.1f"] + , ["net", True, "Net($)", 1.0, "%6.2f"] + , ["bbper100", True, "bb/100", 1.0, "%4.2f"] + , ["rake", True, "Rake($)", 1.0, "%6.2f"] + , ["bb100xr", True, "bbxr/100", 1.0, "%4.2f"] + , ["variance", True, "Variance", 1.0, "%5.2f"] + ] + self.stat_table = None self.stats_frame = None + self.stats_vbox = None self.main_hbox = gtk.HBox(False, 0) self.main_hbox.show() - statsFrame = gtk.Frame("Stats:") - statsFrame.set_label_align(0.0, 0.0) - statsFrame.show() - self.stats_frame = gtk.VBox(False, 0) + self.stats_frame = gtk.Frame() + self.stats_frame.set_label_align(0.0, 0.0) self.stats_frame.show() + self.stats_vbox = gtk.VBox(False, 0) + self.stats_vbox.show() # This could be stored in config eventually, or maybe configured in this window somehow. # Each posncols element is the name of a column returned by the sql @@ -90,11 +119,11 @@ class GuiPositionalStats (threading.Thread): , "PoFAFq", "Net($)", "bb/100", "$/hand", "Variance", "Hds" ) - self.fillStatsFrame(self.stats_frame) - statsFrame.add(self.stats_frame) + self.fillStatsFrame(self.stats_vbox) + self.stats_frame.add(self.stats_vbox) self.main_hbox.pack_start(self.filters.get_vbox()) - self.main_hbox.pack_start(statsFrame) + self.main_hbox.pack_start(self.stats_frame) def get_vbox(self): @@ -107,9 +136,12 @@ class GuiPositionalStats (threading.Thread): print "DEBUG: activesite set to %s" %(self.activesite) def refreshStats(self, widget, data): - try: self.stats_table.destroy() + try: self.stats_vbox.destroy() except AttributeError: pass - self.fillStatsFrame(self.stats_frame) + self.stats_vbox = gtk.VBox(False, 0) + self.stats_vbox.show() + self.stats_frame.add(self.stats_vbox) + self.fillStatsFrame(self.stats_vbox) def fillStatsFrame(self, vbox): sites = self.filters.getSites() @@ -144,66 +176,103 @@ class GuiPositionalStats (threading.Thread): self.createStatsTable(vbox, playerids, sitenos, limits, seats, dates) def createStatsTable(self, vbox, playerids, sitenos, limits, seats, dates): - self.stats_table = gtk.Table(1, 1, False) # gtk table expands as required - self.stats_table.set_col_spacings(4) - self.stats_table.show() - vbox.add(self.stats_table) + colalias,colshow,colheading,colxalign,colformat = 0,1,2,3,4 row = 0 col = 0 - for t in self.posnheads: - l = gtk.Label(self.posnheads[col]) - l.show() - self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK) - col +=1 tmp = self.sql.query['playerStatsByPosition'] tmp = self.refineQuery(tmp, playerids, sitenos, limits, seats, dates) self.cursor.execute(tmp) result = self.cursor.fetchall() + colnames = [desc[0].lower() for desc in self.cursor.description] + + liststore = gtk.ListStore(*([str] * len(colnames))) + view = gtk.TreeView(model=liststore) + view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH) + vbox.pack_start(view, expand=False, padding=3) + # left-aligned cells: + textcell = gtk.CellRendererText() + # centred cells: + textcell50 = gtk.CellRendererText() + textcell50.set_property('xalign', 0.5) + # right-aligned cells: + numcell = gtk.CellRendererText() + numcell.set_property('xalign', 1.0) + listcols = [] + + for t in self.posnheads: + listcols.append(gtk.TreeViewColumn(self.posnheads[col])) + view.append_column(listcols[col]) + if col == 0: + listcols[col].pack_start(textcell, expand=True) + listcols[col].add_attribute(textcell, 'text', col) + listcols[col].set_expand(True) + elif col in (1, 2): + listcols[col].pack_start(textcell50, expand=True) + listcols[col].add_attribute(textcell50, 'text', col) + listcols[col].set_expand(True) + else: + listcols[col].pack_start(numcell, expand=True) + listcols[col].add_attribute(numcell, 'text', col) + listcols[col].set_expand(True) + col +=1 + + # Code below to be used when full column data structures implemented like in player stats: + + # Create header row eg column: ("game", True, "Game", 0.0, "%s") + #for col, column in enumerate(cols_to_show): + # if column[colalias] == 'game' and holecards: + # s = [x for x in self.columns if x[colalias] == 'hand'][0][colheading] + # else: + # s = column[colheading] + # listcols.append(gtk.TreeViewColumn(s)) + # view.append_column(listcols[col]) + # if column[colformat] == '%s': + # if column[colxalign] == 0.0: + # listcols[col].pack_start(textcell, expand=True) + # listcols[col].add_attribute(textcell, 'text', col) + # else: + # listcols[col].pack_start(textcell50, expand=True) + # listcols[col].add_attribute(textcell50, 'text', col) + # listcols[col].set_expand(True) + # else: + # listcols[col].pack_start(numcell, expand=True) + # listcols[col].add_attribute(numcell, 'text', col) + # listcols[col].set_expand(True) + # #listcols[col].set_alignment(column[colxalign]) # no effect? rows = len(result) - colnames = [desc[0].lower() for desc in self.cursor.description] last_game,last_seats,sqlrow = "","",0 while sqlrow < rows: - if(row%2 == 0): - bgcolor = "white" - else: - bgcolor = "lightgrey" rowprinted=0 + treerow = [] avgcol = colnames.index('avgseats') for col,colname in enumerate(self.posncols): if colname in colnames: sqlcol = colnames.index(colname) else: continue - eb = gtk.EventBox() - eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) - # print blank row between levels: if result[sqlrow][sqlcol]: if sqlrow == 0: - l = gtk.Label(result[sqlrow][sqlcol]) + value = result[sqlrow][sqlcol] rowprinted=1 elif result[sqlrow][0] != last_game: - l = gtk.Label(' ') + value = ' ' elif 'show' in seats and seats['show'] and result[sqlrow][avgcol] != last_seats: - l = gtk.Label(' ') + value = ' ' else: - l = gtk.Label(result[sqlrow][sqlcol]) + value = result[sqlrow][sqlcol] rowprinted=1 else: l = gtk.Label(' ') - if col == 0: - l.set_alignment(xalign=0.0, yalign=0.5) - elif col == 1: - l.set_alignment(xalign=0.5, yalign=0.5) + value = ' ' + if value and value != -999: + treerow.append(value) else: - l.set_alignment(xalign=1.0, yalign=0.5) - eb.add(l) - self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) - l.show() - eb.show() + treerow.append(' ') + iter = liststore.append(treerow) last_game = result[sqlrow][0] last_seats = result[sqlrow][avgcol] if rowprinted: @@ -220,48 +289,33 @@ class GuiPositionalStats (threading.Thread): # blank row between main stats and totals: col = 0 - if(row%2 == 0): - bgcolor = "white" - else: - bgcolor = "lightgrey" - eb = gtk.EventBox() - eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) - l = gtk.Label(' ') - eb.add(l) - self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) - l.show() - eb.show() + treerow = [' ' for x in self.posncols] + iter = liststore.append(treerow) row = row + 1 for sqlrow in range(rows): - if(row%2 == 0): - bgcolor = "white" - else: - bgcolor = "lightgrey" + treerow = [] for col,colname in enumerate(self.posncols): if colname in colnames: sqlcol = colnames.index(colname) elif colname != "plposition": continue - eb = gtk.EventBox() - eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) if colname == 'plposition': l = gtk.Label('Totals') + value = 'Totals' elif result[sqlrow][sqlcol]: l = gtk.Label(result[sqlrow][sqlcol]) + value = result[sqlrow][sqlcol] else: l = gtk.Label(' ') - if col == 0: - l.set_alignment(xalign=0.0, yalign=0.5) - elif col == 1: - l.set_alignment(xalign=0.5, yalign=0.5) + value = ' ' + if value and value != -999: + treerow.append(value) else: - l.set_alignment(xalign=1.0, yalign=0.5) - eb.add(l) - self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) - l.show() - eb.show() + treerow.append(' ') + iter = liststore.append(treerow) row = row + 1 + vbox.show_all() self.db.db.rollback() #end def fillStatsFrame(self, vbox): From 1fbb7d166c2ec32c2a02fbbeeb0f122df121ef22 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 22 Jun 2009 21:41:41 +0100 Subject: [PATCH 040/143] remove redundant code --- pyfpdb/GuiPlayerStats.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 268aeab3..79ab75a4 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -227,11 +227,6 @@ class GuiPlayerStats (threading.Thread): if not flags: holecards = False else: holecards = flags[0] - - self.stats_table = gtk.Table(1, 1, False) - self.stats_table.set_col_spacings(4) - self.stats_table.show() - tmp = self.sql.query[query] tmp = self.refineQuery(tmp, flags, playerids, sitenos, limits, seats, groups, dates) self.cursor.execute(tmp) @@ -279,10 +274,6 @@ class GuiPlayerStats (threading.Thread): while sqlrow < rows: treerow = [] - if(row%2 == 0): - bgcolor = "white" - else: - bgcolor = "lightgrey" for col,column in enumerate(cols_to_show): if column[colalias] in colnames: value = result[sqlrow][colnames.index(column[colalias])] From 699f79722b99b073ce7fc27a5bfd8d83fda0dcf5 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 22 Jun 2009 22:05:28 +0100 Subject: [PATCH 041/143] add time print for positional stats tab --- pyfpdb/GuiPositionalStats.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index dce7cb77..21a3bc9a 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -20,6 +20,7 @@ import pygtk pygtk.require('2.0') import gtk import os +from time import time, strftime import fpdb_import import fpdb_db @@ -177,6 +178,7 @@ class GuiPositionalStats (threading.Thread): def createStatsTable(self, vbox, playerids, sitenos, limits, seats, dates): + starttime = time() colalias,colshow,colheading,colxalign,colformat = 0,1,2,3,4 row = 0 col = 0 @@ -318,6 +320,7 @@ class GuiPositionalStats (threading.Thread): vbox.show_all() self.db.db.rollback() + print "Positional Stats page displayed in %4.2f seconds" % (time() - starttime) #end def fillStatsFrame(self, vbox): def refineQuery(self, query, playerids, sitenos, limits, seats, dates): From 45a9358cbd67a111ac42a056712fbc1995f9d000 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 22 Jun 2009 23:16:34 +0100 Subject: [PATCH 042/143] set defaults for unused params to allow new calls without needing to set them --- pyfpdb/Database.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 932a8578..5bc8afe9 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -39,7 +39,7 @@ import SQL import Card class Database: - def __init__(self, c, db_name, game): + def __init__(self, c, db_name = None, game = None): # db_name and game not used any more self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql self.fdb.do_connect(c) self.connection = self.fdb.db @@ -48,7 +48,7 @@ class Database: self.import_options = c.get_import_parameters() self.type = db_params['db-type'] self.backend = db_params['db-backend'] - self.sql = SQL.Sql(game = game, type = self.type, db_server = db_params['db-server']) + self.sql = SQL.Sql(type = self.type, db_server = db_params['db-server']) self.connection.rollback() # To add to config: From 456ddb3e91ceda9d9305d562a56769f38a9ddc23 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 22 Jun 2009 23:19:03 +0100 Subject: [PATCH 043/143] use do_connect() instead of connect() and remove settings parameter (config includes them) --- pyfpdb/Filters.py | 20 ++++---------------- pyfpdb/GuiGraphViewer.py | 2 +- pyfpdb/GuiPlayerStats.py | 2 +- pyfpdb/GuiPositionalStats.py | 2 +- 4 files changed, 7 insertions(+), 19 deletions(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index 4846b998..9ded56b4 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -30,12 +30,11 @@ import fpdb_db import FpdbSQLQueries class Filters(threading.Thread): - def __init__(self, db, settings, config, qdict, display = {},debug=True): + def __init__(self, db, config, qdict, display = {}, debug=True): self.debug=debug #print "start of GraphViewer constructor" self.db=db self.cursor=db.cursor - self.settings=settings self.sql=qdict self.conf = config self.display = display @@ -235,7 +234,7 @@ class Filters(threading.Thread): def __set_hero_name(self, w, site): self.heroes[site] = w.get_text() -# print "DEBUG: settings heroes[%s]: %s"%(site, self.heroes[site]) +# print "DEBUG: setting heroes[%s]: %s"%(site, self.heroes[site]) def createSiteLine(self, hbox, site): cb = gtk.CheckButton(site) @@ -556,23 +555,12 @@ def main(argv=None): config = Configuration.Config() db = None - settings = {} - - settings.update(config.get_db_parameters()) - settings.update(config.get_tv_parameters()) - settings.update(config.get_import_parameters()) - settings.update(config.get_default_paths()) - db = fpdb_db.fpdb_db() - db.connect(settings['db-backend'], - settings['db-host'], - settings['db-databaseName'], - settings['db-user'], - settings['db-password']) + db.do_connect(config) qdict = FpdbSQLQueries.FpdbSQLQueries(db.get_backend_name()) - i = Filters(db, settings, config, qdict) + i = Filters(db, config, qdict) main_window = gtk.Window() main_window.connect('destroy', destroy) main_window.add(i.get_vbox()) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index cec91e61..fc14a536 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -63,7 +63,7 @@ class GuiGraphViewer (threading.Thread): "Button2" : True } - self.filters = Filters.Filters(db, settings, config, querylist, display = filters_display) + self.filters = Filters.Filters(db, config, querylist, display = filters_display) self.filters.registerButton1Name("Refresh Graph") self.filters.registerButton1Callback(self.generateGraph) self.filters.registerButton2Name("Export to File") diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 79ab75a4..4ad21764 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -66,7 +66,7 @@ class GuiPlayerStats (threading.Thread): "Button2" : True } - self.filters = Filters.Filters(self.db, settings, config, querylist, display = filters_display) + self.filters = Filters.Filters(self.db, config, querylist, display = filters_display) self.filters.registerButton1Name("_Filters") self.filters.registerButton1Callback(self.showDetailFilter) self.filters.registerButton2Name("_Refresh") diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index 21a3bc9a..6fde0617 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -59,7 +59,7 @@ class GuiPositionalStats (threading.Thread): "Button2" : False } - self.filters = Filters.Filters(self.db, settings, config, querylist, display = filters_display) + self.filters = Filters.Filters(self.db, config, querylist, display = filters_display) self.filters.registerButton1Name("Refresh") self.filters.registerButton1Callback(self.refreshStats) From 14561043828eed31639787a7751a3e54b28e79d2 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 22 Jun 2009 23:30:54 +0100 Subject: [PATCH 044/143] make graph viewer use its own db connection --- pyfpdb/GuiGraphViewer.py | 16 ++++++++-------- pyfpdb/fpdb.py | 5 ++++- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index fc14a536..811b1e82 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -43,14 +43,14 @@ import Filters class GuiGraphViewer (threading.Thread): - def __init__(self, db, settings, querylist, config, debug=True): + def __init__(self, querylist, config, debug=True): """Constructor for GraphViewer""" self.debug=debug #print "start of GraphViewer constructor" - self.db=db - self.cursor=db.cursor - self.settings=settings - self.sql=querylist + self.db = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql + self.db.do_connect(config) + + self.sql = querylist self.conf = config filters_display = { "Heroes" : True, @@ -63,7 +63,7 @@ class GuiGraphViewer (threading.Thread): "Button2" : True } - self.filters = Filters.Filters(db, config, querylist, display = filters_display) + self.filters = Filters.Filters(self.db, config, querylist, display = filters_display) self.filters.registerButton1Name("Refresh Graph") self.filters.registerButton1Callback(self.generateGraph) self.filters.registerButton2Name("Export to File") @@ -146,7 +146,7 @@ class GuiGraphViewer (threading.Thread): for site in sites: if sites[site] == True: sitenos.append(siteids[site]) - self.cursor.execute(self.sql.query['getPlayerId'], (heroes[site],)) + self.db.cursor.execute(self.sql.query['getPlayerId'], (heroes[site],)) result = self.db.cursor.fetchall() if len(result) == 1: playerids.append(result[0][0]) @@ -226,7 +226,7 @@ class GuiGraphViewer (threading.Thread): #print "DEBUG: sql query:" #print tmp - self.cursor.execute(tmp) + self.db.cursor.execute(tmp) #returns (HandId,Winnings,Costs,Profit) winnings = self.db.cursor.fetchall() self.db.db.rollback() diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index b03e8424..172eedee 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -41,6 +41,7 @@ import GuiTableViewer import GuiAutoImport import GuiGraphViewer import GuiSessionViewer +import Database import FpdbSQLQueries import Configuration @@ -388,6 +389,8 @@ class fpdb: # Database connected to successfully, load queries to pass on to other classes self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) + self.dbi = Database.Database(self.config) # dbi for db interface and to avoid clashes with db/database/etc + # can rename later if required self.db.db.rollback() #end def load_profile @@ -474,7 +477,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") def tabGraphViewer(self, widget, data=None): """opens a graph viewer tab""" #print "start of tabGraphViewer" - new_gv_thread=GuiGraphViewer.GuiGraphViewer(self.db, self.settings, self.querydict, self.config) + new_gv_thread = GuiGraphViewer.GuiGraphViewer(self.querydict, self.config) self.threads.append(new_gv_thread) gv_tab=new_gv_thread.get_vbox() self.add_and_display_tab(gv_tab, "Graphs") From 0afd8e2e707dba139d879242564604f48bbcb26d Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 22 Jun 2009 23:43:11 +0100 Subject: [PATCH 045/143] use do_connect() instead of connect() --- pyfpdb/fpdb.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 172eedee..b36c62bb 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -364,11 +364,7 @@ class fpdb: self.db = fpdb_db.fpdb_db() #print "end of fpdb.load_profile, databaseName:",self.settings['db-databaseName'] - self.db.connect(self.settings['db-backend'], - self.settings['db-host'], - self.settings['db-databaseName'], - self.settings['db-user'], - self.settings['db-password']) + self.db.do_connect(self.config) if self.db.wrongDbVersion: diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) @@ -401,11 +397,7 @@ class fpdb: def obtain_global_lock(self): print "\nTaking global lock ..." self.fdb_lock = fpdb_db.fpdb_db() - self.fdb_lock.connect(self.settings['db-backend'], - self.settings['db-host'], - self.settings['db-databaseName'], - self.settings['db-user'], - self.settings['db-password']) + self.fdb_lock.do_connect(self.config) return self.fdb_lock.get_global_lock() #end def obtain_global_lock From 8cdac245179503f597cab5ef508e14e2eebb2bd3 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 23 Jun 2009 09:56:29 -0400 Subject: [PATCH 046/143] Subclass Aux_Seats from Aux_Windows. Flop_mucked now a Aux_Seats. --- pyfpdb/Mucked.py | 176 +++++++++++++++++++++-------------------------- 1 file changed, 77 insertions(+), 99 deletions(-) diff --git a/pyfpdb/Mucked.py b/pyfpdb/Mucked.py index be9228d3..eb1d7c86 100755 --- a/pyfpdb/Mucked.py +++ b/pyfpdb/Mucked.py @@ -43,21 +43,12 @@ class Aux_Window(object): self.params = params self.config = config - def update_data(self, *args): - pass - - def update_gui(self, *args): - pass - - def create(self, *args): - pass - - def relocate(self, *args): - pass - - def save_layout(self, *args): - pass - +# Override these methods as needed + def update_data(self, *args): pass + def update_gui(self, *args): pass + def create(self, *args): pass + def relocate(self, *args): pass + def save_layout(self, *args): pass def destroy(self): try: self.container.destroy() @@ -89,10 +80,6 @@ class Aux_Window(object): pb.copy_area(30*j, 42*i, 30, 42, temp_pb, 0, 0) return temp_pb - def split_cards(self, card): - if card == 'xx': return ('B', 'S') - return (card[0], card[1].upper()) - def has_cards(self, cards): """Returns the number of cards in the list.""" n = 0 @@ -331,6 +318,9 @@ class Stud_cards: self.seen_cards[(c, r)].set_from_pixbuf(self.card_images[0]) self.eb[(c, r)].set_tooltip_text('') +class Seat_Window(gtk.Window): + """Subclass gtk.Window for the seat windows.""" + class Aux_Seats(Aux_Window): """A super class to display an aux_window at each seat.""" @@ -339,55 +329,83 @@ class Aux_Seats(Aux_Window): self.config = config # configuration object for this aux window to use self.params = params # dict aux params from config self.positions = {} # dict of window positions - self.displayed = False + self.displayed = False # the seat windows are displayed + self.uses_timer = False # the Aux_seats object uses a timer to control hiding self.timer_on = False # bool = Ture if the timeout for removing the cards is on +# placeholders that should be overridden--so we don't throw errors + def create_contents(self): pass + + def create(self): + self.adj = self.hud.adj_seats(0, self.config) # move adj_seats to aux and get rid of it in Hud.py + loc = self.config.get_aux_locations(self.params['name'], int(self.hud.max)) + + self.m_windows = {} # windows to put the card images in + + for i in (range(1, self.hud.max + 1) + ['common']): + if i == 'common': + (x, y) = self.params['layout'][self.hud.max].common + else: + (x, y) = loc[self.adj[i]] + self.m_windows[i] = Seat_Window() + self.m_windows[i].set_decorated(False) + self.m_windows[i].set_property("skip-taskbar-hint", True) + self.m_windows[i].set_transient_for(self.hud.main_window) + self.m_windows[i].set_focus_on_map(False) + self.m_windows[i].connect("configure_event", self.configure_event_cb, i) + self.positions[i] = (int(x) + self.hud.table.x, int(y) + self.hud.table.y) + self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) + self.m_windows[i].set_opacity(float(self.params['opacity'])) + +# the create_contents method is supplied by the subclass + self.create_contents(self.m_windows[i], i) + + self.m_windows[i].show_all() + self.m_windows[i].hide() + +# Methods likely to be of use for any Seat_Window implementation + def destroy(self): + """Destroy all of the seat windows.""" + for i in self.m_windows.keys(): + self.m_windows[i].destroy() + del(self.m_windows[i]) + +# Methods likely to be useful for mucked card windows (or similar) only + def hide(self): + """Hide the seat windows.""" + for (i, w) in self.m_windows.iteritems(): + w.hide() + self.displayed = False + class Flop_Mucked(Aux_Seats): """Aux_Window class for displaying mucked cards for flop games.""" def __init__(self, hud, config, params): super(Flop_Mucked, self).__init__(hud, config, params) self.card_images = self.get_card_images() + self.uses_timer = True # this Aux_seats object uses a timer to control hiding - def create(self): - self.adj = self.hud.adj_seats(0, self.config) # move adj_seats to aux and get rid of it in Hud.py - loc = self.config.get_aux_locations(self.params['name'], int(self.hud.max)) - - self.m_windows = {} # windows to put the card images in - self.eb = {} # event boxes so we can interact with the mucked cards - self.seen_cards = {} # image objects to stash the cards in - - for i in (range(1, self.hud.max + 1) + ['common']): - if i == 'common': - (x, y) = self.params['layout'][self.hud.max].common - else: - (x, y) = loc[self.adj[i]] - self.m_windows[i] = gtk.Window() - self.m_windows[i].set_decorated(False) - self.m_windows[i].set_property("skip-taskbar-hint", True) - self.m_windows[i].set_transient_for(self.hud.main_window) - self.m_windows[i].set_focus_on_map(False) - self.eb[i] = gtk.EventBox() - self.eb[i].connect("button_press_event", self.button_press_cb) - self.m_windows[i].connect("configure_event", self.configure_event_cb, i) - self.m_windows[i].add(self.eb[i]) - self.seen_cards[i] = gtk.image_new_from_pixbuf(self.card_images[0]) - self.eb[i].add(self.seen_cards[i]) - self.positions[i] = (int(x) + self.hud.table.x, int(y) + self.hud.table.y) -# self.rel_positions[i] = (int(x), int(y)) - self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) - self.m_windows[i].set_opacity(float(self.params['opacity'])) - self.m_windows[i].show_all() - self.m_windows[i].hide() - - def create_contents(self, i): + def create_contents(self, container, i): """Create the widgets for showing the contents of the Aux_seats window.""" + container.eb = gtk.EventBox() + container.eb.connect("button_press_event", self.button_press_cb) + container.add(container.eb) + container.seen_cards = gtk.image_new_from_pixbuf(self.card_images[0]) + container.eb.add(container.seen_cards) def update_gui(self, new_hand_id): """Prepare and show the mucked cards.""" - if self.displayed: - self.hide_mucked_cards() - self.displayed = False + if self.displayed: self.hide() + +# See how many players showed a hand. Skip if only 1 shows (= hero) + n_sd = 0 + for (i, cards) in self.hud.cards.iteritems(): + n_cards = self.has_cards(cards) + if n_cards > 0: + n_sd = n_sd + 1 + if n_sd < 2: return + +# More than 1 player showed, so display the hole cards for (i, cards) in self.hud.cards.iteritems(): n_cards = self.has_cards(cards) if n_cards > 0: @@ -404,24 +422,19 @@ class Flop_Mucked(Aux_Seats): int(self.params['card_wd']), int(self.params['card_ht']), scratch, x, 0) x = x + int(self.params['card_wd']) - self.seen_cards[i].set_from_pixbuf(scratch) + self.m_windows[i].seen_cards.set_from_pixbuf(scratch) self.m_windows[i].resize(1,1) self.m_windows[i].show() self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) # here is where I move back self.displayed = True for stats in self.hud.stat_dict.itervalues(): - self.eb[stats['seat']].set_tooltip_text(stats['screen_name']) + self.m_windows[i].eb.set_tooltip_text(stats['screen_name']) if self.displayed and float(self.params['timeout']) > 0: self.timer_on = True gobject.timeout_add(int(1000*float(self.params['timeout'])), self.timed_out) - def destroy(self): - """Destroy all of the mucked windows.""" - for w in self.m_windows.values(): - w.destroy() - def timed_out(self): # this is the callback from the timeout @@ -430,15 +443,9 @@ class Flop_Mucked(Aux_Seats): if not self.timer_on: return False else: - self.hide_mucked_cards() + self.hide() return False - def hide_mucked_cards(self): - """Hide the mucked card windows.""" - for (i, w) in self.m_windows.iteritems(): - w.hide() - self.displayed = False - def button_press_cb(self, widget, event, *args): """Handle button clicks in the event boxes.""" @@ -456,7 +463,7 @@ class Flop_Mucked(Aux_Seats): self.timer_on = False else: self.timer_on = False - self.hide_mucked_cards() + self.hide() elif event.button == 1: # left button event window = widget.get_parent() @@ -482,32 +489,3 @@ class Flop_Mucked(Aux_Seats): else: new_locs[i] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y) self.config.edit_aux_layout(self.params['name'], self.hud.max, locations = new_locs) - -# This test program doesn't work - -#if __name__== "__main__": -# -# def destroy(*args): # call back for terminating the main eventloop -# gtk.main_quit() # used only for testing -# -# def process_new_hand(source, condition, db_connection): #callback from stdin watch -- testing only -## there is a new hand_id to be processed -## just read it and pass it to update -# new_hand_id = sys.stdin.readline() -# new_hand_id = new_hand_id.rstrip() # remove trailing whitespace -# m.update_data(new_hand_id, db_connection) -# m.update_gui(new_hand_id) -# return(True) -# -# config = Configuration.Config() -# db_connection = Database.Database(config, 'fpdbTEST', '') -# main_window = gtk.Window() -# main_window.set_keep_above(True) -# main_window.connect("destroy", destroy) -# -# aux_to_call = "stud_mucked" -# aux_params = config.get_aux_parameters(aux_to_call) -# m = eval("%s(None, config, aux_params)" % aux_params['class']) -# -# s_id = gobject.io_add_watch(sys.stdin, gobject.IO_IN, process_new_hand, db_connection) -# gtk.main() From 2f0c7e8167f8380349db0d4148104b91b2666327 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 23 Jun 2009 20:45:11 +0100 Subject: [PATCH 047/143] make load_profile reload HUD_config.xml and update status bar --- pyfpdb/fpdb.py | 53 ++++++++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index b36c62bb..6c982002 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -41,6 +41,7 @@ import GuiTableViewer import GuiAutoImport import GuiGraphViewer import GuiSessionViewer +import SQL import Database import FpdbSQLQueries import Configuration @@ -179,20 +180,21 @@ class fpdb: def dia_load_profile(self, widget, data=None): """Dialogue to select a file to load a profile from""" if self.obtain_global_lock() == 0: # returns 0 if successful - try: - chooser = gtk.FileChooserDialog(title="Please select a profile file to load", - action=gtk.FILE_CHOOSER_ACTION_OPEN, - buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) - chooser.set_filename(self.profile) + #try: + # chooser = gtk.FileChooserDialog(title="Please select a profile file to load", + # action=gtk.FILE_CHOOSER_ACTION_OPEN, + # buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) + # chooser.set_filename(self.profile) - response = chooser.run() - chooser.destroy() - if response == gtk.RESPONSE_OK: - self.load_profile(chooser.get_filename()) - elif response == gtk.RESPONSE_CANCEL: - print 'User cancelled loading profile' - except: - pass + # response = chooser.run() + # chooser.destroy() + # if response == gtk.RESPONSE_OK: + # self.load_profile(chooser.get_filename()) + # elif response == gtk.RESPONSE_CANCEL: + # print 'User cancelled loading profile' + #except: + # pass + self.load_profile() self.release_global_lock() #end def dia_load_profile @@ -347,6 +349,7 @@ class fpdb: def load_profile(self): """Loads profile from the provided path name.""" + self.config = Configuration.Config(file=options.config, dbname=options.dbname) self.settings = {} if (os.sep=="/"): self.settings['os']="linuxmac" @@ -383,10 +386,18 @@ class fpdb: response = diaDbVersionWarning.run() diaDbVersionWarning.destroy() + if self.status_bar == None: + self.status_bar = gtk.Label("Status: Connected to %s database named %s on host %s"%(self.db.get_backend_name(),self.db.database, self.db.host)) + self.main_vbox.pack_end(self.status_bar, False, True, 0) + self.status_bar.show() + else: + self.status_bar.set_text("Status: Connected to %s database named %s on host %s" % (self.db.get_backend_name(),self.db.database, self.db.host)) + # Database connected to successfully, load queries to pass on to other classes self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) - self.dbi = Database.Database(self.config) # dbi for db interface and to avoid clashes with db/database/etc - # can rename later if required + self.sql = SQL.Sql(type = self.settings['db-type'], db_server = self.settings['db-server']) + self.dbi = Database.Database(self.config, sql = self.sql) # dbi for db interface and to avoid clashes with db/database/etc + # can rename later if required self.db.db.rollback() #end def load_profile @@ -476,10 +487,9 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") #end def tabGraphViewer def __init__(self): - self.threads=[] - self.db=None - self.config = Configuration.Config(file=options.config, dbname=options.dbname) - self.load_profile() + self.threads = [] + self.db = None + self.status_bar = None self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.connect("delete_event", self.delete_event) @@ -514,11 +524,8 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") self.tab_main_help(None, None) - self.status_bar = gtk.Label("Status: Connected to %s database named %s on host %s"%(self.db.get_backend_name(),self.db.database, self.db.host)) - self.main_vbox.pack_end(self.status_bar, False, True, 0) - self.status_bar.show() - self.window.show() + self.load_profile() sys.stderr.write("fpdb starting ...") #end def __init__ From 84cc951045ee3e8981d7dc40d26d1346a250cf59 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 23 Jun 2009 22:05:22 +0100 Subject: [PATCH 048/143] comment out database creation wrongly included from my dev code --- pyfpdb/fpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 6c982002..a6d4cb3c 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -396,7 +396,7 @@ class fpdb: # Database connected to successfully, load queries to pass on to other classes self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) self.sql = SQL.Sql(type = self.settings['db-type'], db_server = self.settings['db-server']) - self.dbi = Database.Database(self.config, sql = self.sql) # dbi for db interface and to avoid clashes with db/database/etc + #self.dbi = Database.Database(self.config, sql = self.sql) # dbi for db interface and to avoid clashes with db/database/etc # can rename later if required self.db.db.rollback() #end def load_profile From 9b50987d0cf05d9e8cbe0c5cc97d288770e882e0 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 23 Jun 2009 23:44:37 +0100 Subject: [PATCH 049/143] add sql param to Database constructor - aim is to have just one SQL instance passed around and to use Database for db connections and methods --- pyfpdb/Database.py | 9 +++++++-- pyfpdb/fpdb.py | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index f652d9a7..392681eb 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -39,7 +39,8 @@ import SQL import Card class Database: - def __init__(self, c, db_name = None, game = None): # db_name and game not used any more + def __init__(self, c, db_name = None, game = None, sql = None): # db_name and game not used any more + print "creating Database instance, sql =", sql self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql self.fdb.do_connect(c) self.connection = self.fdb.db @@ -48,7 +49,11 @@ class Database: self.import_options = c.get_import_parameters() self.type = db_params['db-type'] self.backend = db_params['db-backend'] - self.sql = SQL.Sql(type = self.type, db_server = db_params['db-server']) + # where possible avoid creating new SQL instance by using the global one passed in + if sql == None: + self.sql = SQL.Sql(type = self.type, db_server = db_params['db-server']) + else: + self.sql = sql self.connection.rollback() # To add to config: diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index a6d4cb3c..6c982002 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -396,7 +396,7 @@ class fpdb: # Database connected to successfully, load queries to pass on to other classes self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) self.sql = SQL.Sql(type = self.settings['db-type'], db_server = self.settings['db-server']) - #self.dbi = Database.Database(self.config, sql = self.sql) # dbi for db interface and to avoid clashes with db/database/etc + self.dbi = Database.Database(self.config, sql = self.sql) # dbi for db interface and to avoid clashes with db/database/etc # can rename later if required self.db.db.rollback() #end def load_profile From 7f7ad2a13e0e342468909fae20c5545474b2e91a Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 25 Jun 2009 10:07:40 -0400 Subject: [PATCH 050/143] Further on Aux_Seats interface. Works. Not ready for prime time. --- pyfpdb/Mucked.py | 85 +++++++++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 37 deletions(-) diff --git a/pyfpdb/Mucked.py b/pyfpdb/Mucked.py index eb1d7c86..4c8b2eb4 100755 --- a/pyfpdb/Mucked.py +++ b/pyfpdb/Mucked.py @@ -335,6 +335,7 @@ class Aux_Seats(Aux_Window): # placeholders that should be overridden--so we don't throw errors def create_contents(self): pass + def update_contents(self): pass def create(self): self.adj = self.hud.adj_seats(0, self.config) # move adj_seats to aux and get rid of it in Hud.py @@ -363,6 +364,11 @@ class Aux_Seats(Aux_Window): self.m_windows[i].show_all() self.m_windows[i].hide() + def update_gui(self, new_hand_id): + """Update the gui, LDO.""" + for i in self.m_windows.keys(): + self.update_contents(self.m_windows[i], i) + # Methods likely to be of use for any Seat_Window implementation def destroy(self): """Destroy all of the seat windows.""" @@ -377,6 +383,17 @@ class Aux_Seats(Aux_Window): w.hide() self.displayed = False + def save_layout(self, *args): + """Save new layout back to the aux element in the config file.""" + new_locs = {} +# print "adj =", self.adj + for (i, pos) in self.positions.iteritems(): + if i != 'common': + new_locs[self.adj[int(i)]] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y) + else: + new_locs[i] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y) + self.config.edit_aux_layout(self.params['name'], self.hud.max, locations = new_locs) + class Flop_Mucked(Aux_Seats): """Aux_Window class for displaying mucked cards for flop games.""" @@ -393,6 +410,33 @@ class Flop_Mucked(Aux_Seats): container.seen_cards = gtk.image_new_from_pixbuf(self.card_images[0]) container.eb.add(container.seen_cards) + def update_contents(self, container, i): + if not self.hud.cards.has_key(i): return + cards = self.hud.cards[i] + n_cards = self.has_cards(cards) + if n_cards > 1: + +# scratch is a working pixbuf, used to assemble the image + scratch = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, + int(self.params['card_wd'])*n_cards, + int(self.params['card_ht'])) + x = 0 # x coord where the next card starts in scratch + for card in cards: +# concatenate each card image to scratch + if card == None or card ==0: + break + self.card_images[card].copy_area(0, 0, + int(self.params['card_wd']), int(self.params['card_ht']), + scratch, x, 0) + x = x + int(self.params['card_wd']) + container.seen_cards.set_from_pixbuf(scratch) + container.resize(1,1) + container.show() + container.move(self.positions[i][0], self.positions[i][1]) # here is where I move back + self.displayed = True + if i != "common": + self.m_windows[i].eb.set_tooltip_text(self.hud.stat_dict[i]['screen_name']) + def update_gui(self, new_hand_id): """Prepare and show the mucked cards.""" if self.displayed: self.hide() @@ -403,33 +447,11 @@ class Flop_Mucked(Aux_Seats): n_cards = self.has_cards(cards) if n_cards > 0: n_sd = n_sd + 1 - if n_sd < 2: return + if n_sd < 2: + print "skipping, n_sd =", n_sd + return -# More than 1 player showed, so display the hole cards - for (i, cards) in self.hud.cards.iteritems(): - n_cards = self.has_cards(cards) - if n_cards > 0: -# scratch is a working pixbuf, used to assemble the image - scratch = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, - int(self.params['card_wd'])*n_cards, - int(self.params['card_ht'])) - x = 0 # x coord where the next card starts in scratch - for card in cards: -# concatenate each card image to scratch - if card == None or card ==0: - break - self.card_images[card].copy_area(0, 0, - int(self.params['card_wd']), int(self.params['card_ht']), - scratch, x, 0) - x = x + int(self.params['card_wd']) - self.m_windows[i].seen_cards.set_from_pixbuf(scratch) - self.m_windows[i].resize(1,1) - self.m_windows[i].show() - self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) # here is where I move back - self.displayed = True - - for stats in self.hud.stat_dict.itervalues(): - self.m_windows[i].eb.set_tooltip_text(stats['screen_name']) + super(Flop_Mucked, self).update_gui(new_hand_id) if self.displayed and float(self.params['timeout']) > 0: self.timer_on = True @@ -478,14 +500,3 @@ class Flop_Mucked(Aux_Seats): self.m_windows[i].show() self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) # here is where I move back self.displayed = True - - def save_layout(self, *args): - """Save new layout back to the aux element in the config file.""" - new_locs = {} -# print "adj =", self.adj - for (i, pos) in self.positions.iteritems(): - if i != 'common': - new_locs[self.adj[int(i)]] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y) - else: - new_locs[i] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y) - self.config.edit_aux_layout(self.params['name'], self.hud.max, locations = new_locs) From 9b4e47df9abf8a6293f9d2fc12b902307950b221 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 25 Jun 2009 23:10:37 +0100 Subject: [PATCH 051/143] comment out debug message --- pyfpdb/Tables.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Tables.py b/pyfpdb/Tables.py index ead3beba..dcd145f4 100755 --- a/pyfpdb/Tables.py +++ b/pyfpdb/Tables.py @@ -231,7 +231,7 @@ def discover_nt_by_name(c, tablename): titles = {} win32gui.EnumWindows(win_enum_handler, titles) for hwnd in titles: - print "Tbales.py: tablename =", tablename, "title =", titles[hwnd] + #print "Tables.py: tablename =", tablename, "title =", titles[hwnd] try: # this can blow up in XP on some windows, eg firefox displaying http://docs.python.org/tutorial/classes.html if not tablename in titles[hwnd]: continue From a2db28ebf241ee077c7e89caa4daa084448dabc0 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 25 Jun 2009 23:14:32 +0100 Subject: [PATCH 052/143] create Database instance in import to pass into parser - will eventually replace fpdb_db --- pyfpdb/Database.py | 1 + pyfpdb/fpdb_import.py | 10 +++++++--- pyfpdb/fpdb_parse_logic.py | 9 ++++++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 392681eb..2cade5de 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -49,6 +49,7 @@ class Database: self.import_options = c.get_import_parameters() self.type = db_params['db-type'] self.backend = db_params['db-backend'] + self.db_server = db_params['db-server'] # where possible avoid creating new SQL instance by using the global one passed in if sql == None: self.sql = SQL.Sql(type = self.type, db_server = db_params['db-server']) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 455c1e27..2468fecf 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -31,6 +31,7 @@ import re import fpdb_simple import fpdb_db +import Database import fpdb_parse_logic import Configuration @@ -57,7 +58,8 @@ class Importer: self.settings = settings self.caller = caller self.config = config - self.fdb = None + self.database = None # database will be the main db interface eventually + self.fdb = None # fdb may disappear or just hold the simple db connection self.cursor = None self.filelist = {} self.dirlist = {} @@ -75,6 +77,7 @@ class Importer: self.settings.setdefault("minPrint", 30) self.settings.setdefault("handCount", 0) + self.database = Database.Database(self.config) # includes .connection and .sql variables self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql self.fdb.do_connect(self.config) self.fdb.db.rollback() @@ -392,8 +395,9 @@ class Importer: self.hand=hand try: - handsId = fpdb_parse_logic.mainParser(self.settings, self.fdb - , self.siteIds[site], category, hand, self.config) + handsId = fpdb_parse_logic.mainParser( self.settings, self.fdb + , self.siteIds[site], category, hand + , self.config, self.database ) self.fdb.db.commit() stored += 1 diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py index eff8179f..bb361f63 100644 --- a/pyfpdb/fpdb_parse_logic.py +++ b/pyfpdb/fpdb_parse_logic.py @@ -21,10 +21,13 @@ import fpdb_simple import Database #parses a holdem hand -def mainParser(settings, fdb, siteID, category, hand, config): +def mainParser(settings, fdb, siteID, category, hand, config, db = None): backend = settings['db-backend'] - #This is redundant - hopefully fdb will be a Database object in an interation soon - db = Database.Database(config, 'fpdb', '') + if db == None: + #This is redundant - hopefully fdb will be a Database object in an iteration soon + db = Database.Database(c = config, sql = None) + else: + db = db category = fpdb_simple.recogniseCategory(hand[0]) base = "hold" if category == "holdem" or category == "omahahi" or category == "omahahilo" else "stud" From cb323d2d6323a508c53fb430e39786c2aefdbc32 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 28 Jun 2009 17:20:41 +0100 Subject: [PATCH 053/143] remove unused queries --- pyfpdb/FpdbSQLQueries.py | 167 --------------------------------------- pyfpdb/fpdb_db.py | 1 - 2 files changed, 168 deletions(-) diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index 598c0868..db2d7231 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -248,43 +248,6 @@ class FpdbSQLQueries: self.query['createHandsTable'] = """ """ - ################################ - # Create Gametypes - ################################ - - if(self.dbname == 'MySQL InnoDB'): - self.query['createBoardCardsTable'] = """CREATE TABLE BoardCards ( - id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), - handId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handId) REFERENCES Hands(id), - card1Value smallint NOT NULL, - card1Suit char(1) NOT NULL, - card2Value smallint NOT NULL, - card2Suit char(1) NOT NULL, - card3Value smallint NOT NULL, - card3Suit char(1) NOT NULL, - card4Value smallint NOT NULL, - card4Suit char(1) NOT NULL, - card5Value smallint NOT NULL, - card5Suit char(1) NOT NULL) - ENGINE=INNODB""" - elif(self.dbname == 'PostgreSQL'): - self.query['createBoardCardsTable'] = """CREATE TABLE BoardCards ( - id BIGSERIAL, PRIMARY KEY (id), - handId BIGINT, FOREIGN KEY (handId) REFERENCES Hands(id), - card1Value smallint, - card1Suit char(1), - card2Value smallint, - card2Suit char(1), - card3Value smallint, - card3Suit char(1), - card4Value smallint, - card4Suit char(1), - card5Value smallint, - card5Suit char(1))""" - elif(self.dbname == 'SQLite'): - self.query['createBoardCardsTable'] = """ """ - - ################################ # Create TourneyTypes ################################ @@ -1550,136 +1513,6 @@ class FpdbSQLQueries: elif(self.dbname == 'SQLite'): self.query['playerStatsByPosition'] = """ """ - if(self.dbname == 'MySQL InnoDB'): - self.query['playerStatsByPositionAndHoleCards'] = """ - SELECT - concat(upper(stats.limitType), ' ' - ,concat(upper(substring(stats.category,1,1)),substring(stats.category,2) ), ' ' - ,stats.name, ' $' - ,cast(trim(leading ' ' from - case when stats.bigBlind < 100 then format(stats.bigBlind/100.0,2) - else format(stats.bigBlind/100.0,0) - end ) as char) - ) AS Game - ,case when stats.PlPosition = -2 then 'BB' - when stats.PlPosition = -1 then 'SB' - when stats.PlPosition = 0 then 'Btn' - when stats.PlPosition = 1 then 'CO' - when stats.PlPosition = 2 then 'MP' - when stats.PlPosition = 5 then 'EP' - else '??' - end AS PlPosition - /*,stats.n*/,hprof2.n - /*,stats.vpip*/,0 - /*,stats.pfr*/,0 - /*,stats.saw_f*/,0 - /*,stats.sawsd*/,0 - /*,stats.wtsdwsf*/,0 - /*,stats.wmsd*/,0 - /*,stats.FlAFq*/,0 - /*,stats.TuAFq*/,0 - /*,stats.RvAFq*/,0 - /*,stats.PoFAFq*/,0 - /* if you have handsactions data the next 3 fields should give same answer as - following 3 commented out fields */ - /*,stats.Net - ,stats.BBper100 - ,stats.Profitperhand*/ - ,format(hprof2.sum_profit/100.0,2) AS Net - /*,format((hprof2.sum_profit/(stats.bigBlind+0.0)) / (stats.n/100.0),2)*/,0 - AS BBlPer100 - ,hprof2.profitperhand AS Profitperhand - ,format(hprof2.variance,2) AS Variance - FROM - (select /* stats from hudcache */ - gt.base - ,gt.category - ,upper(gt.limitType) as limitType - ,s.name - ,gt.bigBlind - ,hc.gametypeId - ,case when hc.position = 'B' then -2 - when hc.position = 'S' then -1 - when hc.position = 'D' then 0 - when hc.position = 'C' then 1 - when hc.position = 'M' then 2 - when hc.position = 'E' then 5 - else 9 - end as PlPosition - ,sum(HDs) AS n - ,format(100.0*sum(street0VPI)/sum(HDs),1) AS vpip - ,format(100.0*sum(street0Aggr)/sum(HDs),1) AS pfr - ,format(100.0*sum(street1Seen)/sum(HDs),1) AS saw_f - ,format(100.0*sum(sawShowdown)/sum(HDs),1) AS sawsd - ,case when sum(street1Seen) = 0 then '-' - else format(100.0*sum(sawShowdown)/sum(street1Seen),1) - end AS wtsdwsf - ,case when sum(sawShowdown) = 0 then '-' - end AS wtsdwsf - ,case when sum(sawShowdown) = 0 then '-' - else format(100.0*sum(wonAtSD)/sum(sawShowdown),1) - end AS wmsd - ,case when sum(street1Seen) = 0 then '-' - else format(100.0*sum(street1Aggr)/sum(street1Seen),1) - end AS FlAFq - ,case when sum(street2Seen) = 0 then '-' - else format(100.0*sum(street2Aggr)/sum(street2Seen),1) - end AS TuAFq - ,case when sum(street3Seen) = 0 then '-' - else format(100.0*sum(street3Aggr)/sum(street3Seen),1) - end AS RvAFq - ,case when sum(street1Seen)+sum(street2Seen)+sum(street3Seen) = 0 then '-' - else format(100.0*(sum(street1Aggr)+sum(street2Aggr)+sum(street3Aggr)) - /(sum(street1Seen)+sum(street2Seen)+sum(street3Seen)),1) - end AS PoFAFq - ,format(sum(totalProfit)/100.0,2) AS Net - ,format((sum(totalProfit)/(gt.bigBlind+0.0)) / (sum(HDs)/100.0),2) - AS BBper100 - ,format( (sum(totalProfit)/100.0) / sum(HDs), 4) AS Profitperhand - from Gametypes gt - inner join Sites s on s.Id = gt.siteId - inner join HudCache hc on hc.gameTypeId = gt.Id - where hc.playerId in - # use here ? - group by gt.base - ,gt.category - ,upper(gt.limitType) - ,s.name - ,gt.bigBlind - ,hc.gametypeId - ,PlPosition - ) stats - inner join - ( select # profit from handsplayers/handsactions - hprof.gameTypeId, - case when hprof.position = 'B' then -2 - when hprof.position = 'S' then -1 - when hprof.position in ('3','4') then 2 - when hprof.position in ('6','7') then 5 - else hprof.position - end as PlPosition, - sum(hprof.profit) as sum_profit, - avg(hprof.profit/100.0) as profitperhand, - variance(hprof.profit/100.0) as variance, - count(*) as n - from - (select hp.handId, h.gameTypeId, hp.position, hp.winnings, SUM(ha.amount) as costs - , hp.winnings - SUM(ha.amount) as profit - from HandsPlayers hp - inner join Hands h ON h.id = hp.handId - left join HandsActions ha ON ha.handsPlayerId = hp.id - where hp.playerId in - # use here ? - and hp.tourneysPlayersId IS NULL - and ((hp.card1Value = and hp.card2Value = ) or (hp.card1Value = and hp.card2Value = )) - group by hp.handId, h.gameTypeId, hp.position, hp.winnings - ) hprof - group by hprof.gameTypeId, PlPosition - ) hprof2 - on ( hprof2.gameTypeId = stats.gameTypeId - and hprof2.PlPosition = stats.PlPosition) - order by stats.category, stats.limittype, stats.bigBlind, cast(stats.PlPosition as signed) - """ if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'): self.query['getGames'] = """SELECT DISTINCT category from Gametypes""" diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 29817af9..911618e1 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -243,7 +243,6 @@ class fpdb_db: self.cursor.execute(self.sql.query['createPlayersTable']) self.cursor.execute(self.sql.query['createAutoratesTable']) self.cursor.execute(self.sql.query['createHandsTable']) - self.cursor.execute(self.sql.query['createBoardCardsTable']) self.cursor.execute(self.sql.query['createTourneyTypesTable']) self.cursor.execute(self.sql.query['createTourneysTable']) self.cursor.execute(self.sql.query['createTourneysPlayersTable']) From dc7a3fb88ebd82f90a87c6e344474498749727d4 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 28 Jun 2009 18:56:18 +0100 Subject: [PATCH 054/143] finish removal of store_board_cards() --- pyfpdb/Database.py | 3 --- pyfpdb/fpdb_simple.py | 10 ---------- 2 files changed, 13 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 2cade5de..f59476b9 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -328,7 +328,6 @@ class Database: if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) t5 = time() - fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) t6 = time() if self.saveActions: fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) @@ -363,8 +362,6 @@ class Database: if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) - if self.saveActions: fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) return hands_id diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index 34f99e2f..3e862254 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -1136,16 +1136,6 @@ def storeActions(cursor, handsPlayersIds, actionTypes, allIns, actionAmounts, ac cursor.executemany("INSERT INTO HandsActions (handsPlayerId, street, actionNo, action, allIn, amount) VALUES (%s, %s, %s, %s, %s, %s)", inserts) #end def storeActions -def store_board_cards(cursor, hands_id, board_values, board_suits): -#stores into table board_cards - cursor.execute ("""INSERT INTO BoardCards (handId, card1Value, card1Suit, -card2Value, card2Suit, card3Value, card3Suit, card4Value, card4Suit, -card5Value, card5Suit) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", - (hands_id, board_values[0], board_suits[0], board_values[1], board_suits[1], - board_values[2], board_suits[2], board_values[3], board_suits[3], - board_values[4], board_suits[4])) -#end def store_board_cards - def storeHands(backend, conn, cursor, site_hand_no, gametype_id ,hand_start_time, names, tableName, maxSeats, hudCache, board_values, board_suits): From a3e6c2696faa9dde60316b3f091d723aa06dbd37 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 28 Jun 2009 19:19:32 +0100 Subject: [PATCH 055/143] use Database instead of fpdb_db --- pyfpdb/fpdb.py | 58 ++++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 6c982002..3f6b7fb6 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -32,7 +32,7 @@ import pygtk pygtk.require('2.0') import gtk -import fpdb_db + import fpdb_simple import GuiBulkImport import GuiPlayerStats @@ -206,22 +206,23 @@ class fpdb: try: dia_confirm = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm deleting and recreating tables") - diastring = "Please confirm that you want to (re-)create the tables. If there already are tables in the database "+self.db.database+" on "+self.db.host+" they will be deleted." + diastring = "Please confirm that you want to (re-)create the tables. If there already are tables in the database " \ + +self.db.fdb.database+" on "+self.db.fdb.host+" they will be deleted." dia_confirm.format_secondary_text(diastring)#todo: make above string with bold for db, host and deleted response = dia_confirm.run() dia_confirm.destroy() if response == gtk.RESPONSE_YES: - if self.db.backend == self.fdb_lock.MYSQL_INNODB: + if self.db.fdb.backend == self.fdb_lock.fdb.MYSQL_INNODB: # mysql requires locks on all tables or none - easier to release this lock # than lock all the other tables # ToDo: lock all other tables so that lock doesn't have to be released self.release_global_lock() lock_released = True - self.db.recreate_tables() + self.db.fdb.recreate_tables() else: # for other dbs use same connection as holds global lock - self.fdb_lock.recreate_tables() + self.fdb_lock.fdb.recreate_tables() elif response == gtk.RESPONSE_NO: print 'User cancelled recreating tables' except: @@ -362,13 +363,18 @@ class fpdb: self.settings.update(self.config.get_import_parameters()) self.settings.update(self.config.get_default_paths()) - if self.db!=None: - self.db.disconnect() + if self.db != None and self.db.fdb != None: + self.db.fdb.disconnect() - self.db = fpdb_db.fpdb_db() - #print "end of fpdb.load_profile, databaseName:",self.settings['db-databaseName'] - self.db.do_connect(self.config) - if self.db.wrongDbVersion: + self.sql = SQL.Sql(type = self.settings['db-type'], db_server = self.settings['db-server']) + self.db = Database.Database(self.config, sql = self.sql) + + + + + + + if self.db.fdb.wrongDbVersion: diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) label = gtk.Label("An invalid DB version or missing tables have been detected.") @@ -387,18 +393,19 @@ class fpdb: diaDbVersionWarning.destroy() if self.status_bar == None: - self.status_bar = gtk.Label("Status: Connected to %s database named %s on host %s"%(self.db.get_backend_name(),self.db.database, self.db.host)) + self.status_bar = gtk.Label("Status: Connected to %s database named %s on host %s"%(self.db.fdb.get_backend_name(),self.db.fdb.database, self.db.fdb.host)) self.main_vbox.pack_end(self.status_bar, False, True, 0) self.status_bar.show() else: - self.status_bar.set_text("Status: Connected to %s database named %s on host %s" % (self.db.get_backend_name(),self.db.database, self.db.host)) + self.status_bar.set_text("Status: Connected to %s database named %s on host %s" % (self.db.fdb.get_backend_name(),self.db.fdb.database, self.db.fdb.host)) # Database connected to successfully, load queries to pass on to other classes - self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) - self.sql = SQL.Sql(type = self.settings['db-type'], db_server = self.settings['db-server']) - self.dbi = Database.Database(self.config, sql = self.sql) # dbi for db interface and to avoid clashes with db/database/etc - # can rename later if required - self.db.db.rollback() + self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.fdb.get_backend_name()) + self.db.fdb.db.rollback() + + + + #end def load_profile def not_implemented(self, widget, data=None): @@ -407,21 +414,22 @@ class fpdb: def obtain_global_lock(self): print "\nTaking global lock ..." - self.fdb_lock = fpdb_db.fpdb_db() - self.fdb_lock.do_connect(self.config) - return self.fdb_lock.get_global_lock() + self.fdb_lock = Database.Database(self.config, sql = self.sql) + + self.fdb_lock.fdb.do_connect(self.config) + return self.fdb_lock.fdb.get_global_lock() #end def obtain_global_lock def quit(self, widget, data=None): print "Quitting normally" #check if current settings differ from profile, if so offer to save or abort - self.db.disconnect() + self.db.fdb.disconnect() gtk.main_quit() #end def quit_cliecked def release_global_lock(self): - self.fdb_lock.db.rollback() - self.fdb_lock.disconnect() + self.fdb_lock.fdb.db.rollback() + self.fdb_lock.fdb.disconnect() print "Global lock released." #end def release_global_lock @@ -471,7 +479,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") def tab_table_viewer(self, widget, data=None): """opens a table viewer tab""" #print "start of tab_table_viewer" - new_tv_thread=GuiTableViewer.GuiTableViewer(self.db, self.settings) + new_tv_thread=GuiTableViewer.GuiTableViewer(self.db.fdb, self.settings) self.threads.append(new_tv_thread) tv_tab=new_tv_thread.get_vbox() self.add_and_display_tab(tv_tab, "Table Viewer") From 5611f115cddeae2948a2e538860a7d15baf114b1 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 30 Jun 2009 18:32:30 +0800 Subject: [PATCH 056/143] Remove DEBUG line that wasn't supposed to make the last commit --- pyfpdb/Hand.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 38c3609b..61e06930 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -202,7 +202,6 @@ If a player has None chips he won't be added.""" def setCommunityCards(self, street, cards): logging.debug("setCommunityCards %s %s" %(street, cards)) self.board[street] = [self.card(c) for c in cards] - print "DEBUG: self.board: %s" % self.board def card(self,c): """upper case the ranks but not suits, 'atjqk' => 'ATJQK'""" From 3c438a92985881430a5705d2705237f021a11c83 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 30 Jun 2009 18:32:58 +0800 Subject: [PATCH 057/143] Make site selection behave like other options --- pyfpdb/GuiGraphViewer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index cec91e61..2dfb0173 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -154,7 +154,7 @@ class GuiGraphViewer (threading.Thread): if not sitenos: #Should probably pop up here. print "No sites selected - defaulting to PokerStars" - sitenos = [2] + return if not playerids: print "No player ids found" From a8b8ff2f4d5542aa3fab36a923cb8e69f275058b Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 30 Jun 2009 11:43:47 -0400 Subject: [PATCH 058/143] More on Aux_Seats class. This seems to work OK. --- pyfpdb/Mucked.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/pyfpdb/Mucked.py b/pyfpdb/Mucked.py index 4c8b2eb4..c0715632 100755 --- a/pyfpdb/Mucked.py +++ b/pyfpdb/Mucked.py @@ -87,6 +87,13 @@ class Aux_Window(object): if c != None and c > 0: n = n + 1 return n + def get_id_from_seat(self, seat): + """Determine player id from seat number, given stat_dict.""" + for id, dict in self.hud.stat_dict.iteritems(): + if seat == dict['seat']: + return id + return None + class Stud_mucked(Aux_Window): def __init__(self, hud, config, params): @@ -356,13 +363,15 @@ class Aux_Seats(Aux_Window): self.m_windows[i].connect("configure_event", self.configure_event_cb, i) self.positions[i] = (int(x) + self.hud.table.x, int(y) + self.hud.table.y) self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) - self.m_windows[i].set_opacity(float(self.params['opacity'])) + if self.params.has_key('opacity'): + self.m_windows[i].set_opacity(float(self.params['opacity'])) # the create_contents method is supplied by the subclass self.create_contents(self.m_windows[i], i) self.m_windows[i].show_all() - self.m_windows[i].hide() + if self.uses_timer: + self.m_windows[i].hide() def update_gui(self, new_hand_id): """Update the gui, LDO.""" @@ -394,6 +403,10 @@ class Aux_Seats(Aux_Window): new_locs[i] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y) self.config.edit_aux_layout(self.params['name'], self.hud.max, locations = new_locs) + def configure_event_cb(self, widget, event, i, *args): + self.positions[i] = widget.get_position() +# self.rel_positions[i] = (self.positions[i][0] - self.hud.table.x, self.positions[i][1] - self.hud.table.y) + class Flop_Mucked(Aux_Seats): """Aux_Window class for displaying mucked cards for flop games.""" @@ -491,10 +504,6 @@ class Flop_Mucked(Aux_Seats): window = widget.get_parent() window.begin_move_drag(event.button, int(event.x_root), int(event.y_root), event.time) - def configure_event_cb(self, widget, event, i, *args): - self.positions[i] = widget.get_position() -# self.rel_positions[i] = (self.positions[i][0] - self.hud.table.x, self.positions[i][1] - self.hud.table.y) - def expose_all(self): for (i, cards) in self.hud.cards.iteritems(): self.m_windows[i].show() From 71d673f64f32c8ae1ef576fa5b6861d808eceee4 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 30 Jun 2009 11:45:14 -0400 Subject: [PATCH 059/143] Added Hello_Seats to Hello.py. Demo of Aux_Seats class. --- pyfpdb/Hello.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/pyfpdb/Hello.py b/pyfpdb/Hello.py index 41262d6c..7f3f6442 100644 --- a/pyfpdb/Hello.py +++ b/pyfpdb/Hello.py @@ -34,10 +34,13 @@ import gobject # FreePokerTools modules from Mucked import Aux_Window +from Mucked import Seat_Window +from Mucked import Aux_Seats class Hello(Aux_Window): """A 'Hello World' Aux_Window demo.""" def create(self): + print "creating Hello" # This demo simply creates a label in a window. self.container = gtk.Window() self.container.add(gtk.Label("Hello World")) @@ -99,15 +102,18 @@ class Hello_plus(Aux_Window): # hands played that was updated in the "update_data()" function. self.label.set_text("Hello %s\nYou have played %d hands\n on %s." % (self.hero, self.hands_played, self.site)) -class Hello_Menu(Aux_Window): - """A 'Hello World' Aux_Window demo.""" - def create(self): -# This demo puts a menu item on the HUD mainwindow. - self.item = gtk.MenuItem('Print cards') - self.hud.menu.append(self.item) - self.item.connect("activate", self.print_cards) - self.item.show() +class Hello_Seats(Aux_Seats): + """A 'Hello World' Seat_Window demo.""" - def print_cards(self, *args): -# callback for the menu item - print "cards =", self.hud.cards + def create_contents(self, container, i): + container.label = gtk.Label("empty") + container.add(container.label) + container.show_all() + + def update_contents(self, container, i): + if i == "common": return + id = self.get_id_from_seat(i) + if id == None: + container.label.set_text("empty") + else: + container.label.set_text("player = %s" % self.hud.stat_dict[id]['screen_name']) From a3f233ca07e13bfa1c07ac8f7f44c7889792afae Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 30 Jun 2009 14:21:06 -0400 Subject: [PATCH 060/143] Comment out a DEBUG print. --- pyfpdb/Hand.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 38c3609b..b9272031 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -202,7 +202,7 @@ If a player has None chips he won't be added.""" def setCommunityCards(self, street, cards): logging.debug("setCommunityCards %s %s" %(street, cards)) self.board[street] = [self.card(c) for c in cards] - print "DEBUG: self.board: %s" % self.board +# print "DEBUG: self.board: %s" % self.board def card(self,c): """upper case the ranks but not suits, 'atjqk' => 'ATJQK'""" From 04b9dd91268563e2569417a5252ababaf8376cd4 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 30 Jun 2009 21:58:59 +0100 Subject: [PATCH 061/143] use Players table for global lock because Database.init() tries to access Hands --- pyfpdb/fpdb_db.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 911618e1..f89b5d6d 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -567,17 +567,18 @@ class fpdb_db: print "analyze took", atime, "seconds" #end def analyzeDB - # Currently uses an exclusive lock on the Hands table as a global lock + # Currently uses an exclusive lock on the Players table as a global lock + # ( Changed because Hands is used in Database.init() ) # Return values are Unix style, 0 for success, positive integers for errors # 1 = generic error - # 2 = hands table does not exist (error message is suppressed) + # 2 = players table does not exist (error message is suppressed) def get_global_lock(self): if self.backend == self.MYSQL_INNODB: try: - self.cursor.execute( "lock tables Hands write" ) + self.cursor.execute( "lock tables Players write" ) except: - # Table 'fpdb.hands' doesn't exist - if str(sys.exc_value).find(".Hands' doesn't exist") >= 0: + # Table 'fpdb.players' doesn't exist + if str(sys.exc_value).find(".Players' doesn't exist") >= 0: return(2) print "Error! failed to obtain global lock. Close all programs accessing " \ + "database (including fpdb) and try again (%s)." \ @@ -585,11 +586,11 @@ class fpdb_db: return(1) elif self.backend == self.PGSQL: try: - self.cursor.execute( "lock table Hands in exclusive mode nowait" ) + self.cursor.execute( "lock table Players in exclusive mode nowait" ) #print "... after lock table, status =", self.cursor.statusmessage except: - # relation "hands" does not exist - if str(sys.exc_value).find('relation "hands" does not exist') >= 0: + # relation "players" does not exist + if str(sys.exc_value).find('relation "players" does not exist') >= 0: return(2) print "Error! failed to obtain global lock. Close all programs accessing " \ + "database (including fpdb) and try again (%s)." \ From cb1a4d2d0ab6500e11666cf92b4677b8f51953dc Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 30 Jun 2009 22:00:55 +0100 Subject: [PATCH 062/143] add wrappers for fpdb_db methods (plan is to move the fpdb_db methods into Database) --- pyfpdb/Database.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index f59476b9..cf80b3d3 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -40,7 +40,7 @@ import Card class Database: def __init__(self, c, db_name = None, game = None, sql = None): # db_name and game not used any more - print "creating Database instance, sql =", sql + print "\ncreating Database instance, sql =", sql self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql self.fdb.do_connect(c) self.connection = self.fdb.db @@ -87,13 +87,28 @@ class Database: #row = cur.fetchone() self.saveActions = False if self.import_options['saveActions'] == False else True + def do_connect(self, c): + self.fdb.do_connect(c) def commit(self): self.fdb.db.commit() def close_connection(self): self.connection.close() + + def disconnect(self, due_to_error=False): + """Disconnects the DB (rolls back if param is true, otherwise commits""" + self.fdb.disconnect(due_to_error) + + def reconnect(self, due_to_error=False): + """Reconnects the DB""" + self.fdb.reconnect(due_to_error=False) + + def get_backend_name(self): + """Reconnects the DB""" + return self.fdb.get_backend_name() + def get_table_name(self, hand_id): c = self.connection.cursor() c.execute(self.sql.query['get_table_name'], (hand_id, )) From 56ef131bedb9dc06998250d11b2890a83b886a7c Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 30 Jun 2009 22:18:15 +0100 Subject: [PATCH 063/143] use 1 or 2 Database methods instead of the underlying fpdb_db methods (more to do) --- pyfpdb/fpdb.py | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 3f6b7fb6..cdb89894 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -364,16 +364,11 @@ class fpdb: self.settings.update(self.config.get_default_paths()) if self.db != None and self.db.fdb != None: - self.db.fdb.disconnect() + self.db.disconnect() self.sql = SQL.Sql(type = self.settings['db-type'], db_server = self.settings['db-server']) self.db = Database.Database(self.config, sql = self.sql) - - - - - if self.db.fdb.wrongDbVersion: diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) @@ -393,19 +388,15 @@ class fpdb: diaDbVersionWarning.destroy() if self.status_bar == None: - self.status_bar = gtk.Label("Status: Connected to %s database named %s on host %s"%(self.db.fdb.get_backend_name(),self.db.fdb.database, self.db.fdb.host)) + self.status_bar = gtk.Label("Status: Connected to %s database named %s on host %s"%(self.db.get_backend_name(),self.db.fdb.database, self.db.fdb.host)) self.main_vbox.pack_end(self.status_bar, False, True, 0) self.status_bar.show() else: - self.status_bar.set_text("Status: Connected to %s database named %s on host %s" % (self.db.fdb.get_backend_name(),self.db.fdb.database, self.db.fdb.host)) + self.status_bar.set_text("Status: Connected to %s database named %s on host %s" % (self.db.get_backend_name(),self.db.fdb.database, self.db.fdb.host)) # Database connected to successfully, load queries to pass on to other classes - self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.fdb.get_backend_name()) - self.db.fdb.db.rollback() - - - - + self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) + self.db.connection.rollback() #end def load_profile def not_implemented(self, widget, data=None): @@ -415,22 +406,21 @@ class fpdb: def obtain_global_lock(self): print "\nTaking global lock ..." self.fdb_lock = Database.Database(self.config, sql = self.sql) - - self.fdb_lock.fdb.do_connect(self.config) + self.fdb_lock.do_connect(self.config) return self.fdb_lock.fdb.get_global_lock() #end def obtain_global_lock def quit(self, widget, data=None): print "Quitting normally" #check if current settings differ from profile, if so offer to save or abort - self.db.fdb.disconnect() + self.db.disconnect() gtk.main_quit() #end def quit_cliecked def release_global_lock(self): self.fdb_lock.fdb.db.rollback() self.fdb_lock.fdb.disconnect() - print "Global lock released." + print "Global lock released.\n" #end def release_global_lock def tab_abbreviations(self, widget, data=None): From 2cfe7f2ccc5ab27b567962de5c52926e8a463db8 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 1 Jul 2009 08:29:37 -0400 Subject: [PATCH 064/143] Fix bug--get correct player id in Flop_Mucked tool tip. --- pyfpdb/Mucked.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Mucked.py b/pyfpdb/Mucked.py index c0715632..b3b134c5 100755 --- a/pyfpdb/Mucked.py +++ b/pyfpdb/Mucked.py @@ -448,7 +448,8 @@ class Flop_Mucked(Aux_Seats): container.move(self.positions[i][0], self.positions[i][1]) # here is where I move back self.displayed = True if i != "common": - self.m_windows[i].eb.set_tooltip_text(self.hud.stat_dict[i]['screen_name']) + id = self.get_id_from_seat(i) + self.m_windows[i].eb.set_tooltip_text(self.hud.stat_dict[id]['screen_name']) def update_gui(self, new_hand_id): """Prepare and show the mucked cards.""" @@ -458,7 +459,7 @@ class Flop_Mucked(Aux_Seats): n_sd = 0 for (i, cards) in self.hud.cards.iteritems(): n_cards = self.has_cards(cards) - if n_cards > 0: + if n_cards > 0 and i != 'common': n_sd = n_sd + 1 if n_sd < 2: print "skipping, n_sd =", n_sd From 4394c7beb38af9fbad8b82da97562eabab939b82 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 1 Jul 2009 13:53:30 -0400 Subject: [PATCH 065/143] Fix to convert stud hands. --- pyfpdb/Hand.py | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index b9272031..a0c1537c 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -916,6 +916,11 @@ class StudHand(Hand): def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC"): if gametype['base'] != 'stud': pass # or indeed don't pass and complain instead + + self.allStreets = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] + self.communityStreets = [] + self.actionStreets = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] + self.streetList = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] # a list of the observed street names in order self.holeStreets = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] Hand.__init__(self, sitename, gametype, handText) @@ -957,7 +962,7 @@ closed likewise, but known only to player logging.debug("addPlayerCards %s, o%s x%s" % (player, open, closed)) try: self.checkPlayerExists(player) - self.holecards[player][street] = (open, closed) + self.holecards[street][player] = (open, closed) # cards = set([self.card(c) for c in cards]) # self.holecards[player].update(cards) except FpdbParseError, e: @@ -1015,8 +1020,8 @@ Add a complete on [street] by [player] to [amountTo] dealt = 0 #~ print >>fh, _("*** 3RD STREET ***") for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: - if 'THIRD' in self.holecards[player]: - (open, closed) = self.holecards[player]['THIRD'] + if self.holecards['THIRD'].has_key(player): + (open, closed) = self.holecards['THIRD'][player] dealt+=1 if dealt==1: print >>fh, _("*** 3RD STREET ***") @@ -1029,12 +1034,12 @@ Add a complete on [street] by [player] to [amountTo] dealt = 0 #~ print >>fh, _("*** 4TH STREET ***") for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: - if 'FOURTH' in self.holecards[player]: + if player in self.holecards['FOURTH']: old = [] - (o,c) = self.holecards[player]['THIRD'] + (o,c) = self.holecards['THIRD'][player] if o:old.extend(o) if c:old.extend(c) - new = self.holecards[player]['FOURTH'][0] + new = self.holecards['FOURTH'][player][0] dealt+=1 if dealt==1: print >>fh, _("*** 4TH STREET ***") @@ -1046,13 +1051,13 @@ Add a complete on [street] by [player] to [amountTo] dealt = 0 #~ print >>fh, _("*** 5TH STREET ***") for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: - if 'FIFTH' in self.holecards[player]: + if self.holecards['FIFTH'].has_key(player): old = [] for street in ('THIRD','FOURTH'): - (o,c) = self.holecards[player][street] + (o,c) = self.holecards[street][player] if o:old.extend(o) if c:old.extend(c) - new = self.holecards[player]['FIFTH'][0] + new = self.holecards['FIFTH'][player][0] dealt+=1 if dealt==1: print >>fh, _("*** 5TH STREET ***") @@ -1064,13 +1069,13 @@ Add a complete on [street] by [player] to [amountTo] dealt = 0 #~ print >>fh, _("*** 6TH STREET ***") for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: - if 'SIXTH' in self.holecards[player]: + if self.holecards['SIXTH'].has_key(player): old = [] for street in ('THIRD','FOURTH','FIFTH'): - (o,c) = self.holecards[player][street] + (o,c) = self.holecards[street][player] if o:old.extend(o) if c:old.extend(c) - new = self.holecards[player]['SIXTH'][0] + new = self.holecards['SIXTH'][player][0] dealt += 1 if dealt == 1: print >>fh, _("*** 6TH STREET ***") @@ -1085,13 +1090,13 @@ Add a complete on [street] by [player] to [amountTo] # i.e. are all but one players folded; is there an allin showdown; and all that. print >>fh, _("*** 7TH STREET ***") for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: - if 'SEVENTH' in self.holecards[player]: + if self.holecards['SEVENTH'].has_key(player): old = [] for street in ('THIRD','FOURTH','FIFTH','SIXTH'): - (o,c) = self.holecards[player][street] + (o,c) = self.holecards[street][player] if o:old.extend(o) if c:old.extend(c) - new = self.holecards[player]['SEVENTH'][0] + new = self.holecards['SEVENTH'][player][0] if new: print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "") for act in self.actions['SEVENTH']: From 97520bfee9705d936c48c9e183999db60dbb0900 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 1 Jul 2009 13:55:12 -0400 Subject: [PATCH 066/143] Fix call to StoreHands for stud games. --- pyfpdb/Database.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 2cade5de..e9401d35 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -287,7 +287,8 @@ class Database: fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) hands_id = fpdb_simple.storeHands(self.backend, db, cursor, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats, hudImportData) + ,hand_start_time, names, tableName, maxSeats, hudImportData + ,(None, None, None, None, None), (None, None, None, None, None)) #print "before calling store_hands_players_stud, antes:", antes hands_players_ids = fpdb_simple.store_hands_players_stud(self.backend, db, cursor, hands_id, player_ids From 3c2c328f5ae6aea2dc3b90b13f027c8f96ee648b Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 3 Jul 2009 13:23:30 -0400 Subject: [PATCH 067/143] Fix for PokerStars NewVPP tables. --- pyfpdb/Tables.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Tables.py b/pyfpdb/Tables.py index dcd145f4..d4b879b2 100755 --- a/pyfpdb/Tables.py +++ b/pyfpdb/Tables.py @@ -369,7 +369,7 @@ def clean_title(name): for pattern in [' \(6 max\)', ' \(heads up\)', ' \(deep\)', ' \(deep hu\)', ' \(deep 6\)', ' \(2\)', ' \(edu\)', ' \(edu, 6 max\)', ' \(6\)', - ' \(speed\)', + ' \(speed\)', 'special', 'newVPP', ' no all-in', ' fast', ',', ' 50BB min', '50bb min', '\s+$']: name = re.sub(pattern, '', name) name = name.rstrip() From 9d7c370449f62dfef40b6c9f7978bec827fb1c3e Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 3 Jul 2009 18:59:50 -0400 Subject: [PATCH 068/143] Get mucked cards from Stars flop games. __str__ method for Hand. --- pyfpdb/Hand.py | 56 ++++++++++++++++++++++++++++++++++---- pyfpdb/PokerStarsToFpdb.py | 12 ++++++-- 2 files changed, 60 insertions(+), 8 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index a0c1537c..fa472b03 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -26,6 +26,7 @@ import operator import time,datetime from copy import deepcopy from Exceptions import * +import pprint import DerivedStats import Card @@ -74,6 +75,7 @@ class Hand: self.folded = set() self.dealt = set() # 'dealt to' line to be printed self.shown = set() # cards were shown + self.mucked = set() # cards were mucked at showdown # self.action = [] # Things to do with money @@ -83,8 +85,49 @@ class Hand: self.rake = None def __str__(self): + vars = ( ("BB", self.bb), + ("SB", self.sb), + ("BUTTONPOS", self.buttonpos), + ("HAND NO.", self.handid), + ("SITE", self.sitename), + ("TABLE NAME", self.tablename), + ("HERO", self.hero), + ("MAXSEATS", self.maxseats), + ("LASTBET", self.lastBet), + ("ACTION STREETS", self.actionStreets), + ("STREETS", self.streets), + ("ALL STREETS", self.allStreets), + ("COMMUNITY STREETS", self.communityStreets), + ("HOLE STREETS", self.holeStreets), + ("COUNTED SEATS", self.counted_seats), + ("DEALT", self.dealt), + ("SHOWN", self.shown), + ("MUCKED", self.mucked), + ("TOTAL POT", self.totalpot), + ("TOTAL COLLECTED", self.totalcollected), + ("RAKE", self.rake), + ("START TIME", self.starttime), + ) + + structs = ( ("PLAYERS", self.players), + ("STACKS", self.stacks), + ("POSTED", self.posted), + ("POT", self.pot), + ("SEATING", self.seating), + ("GAMETYPE", self.gametype), + ("ACTION", self.actions), + ("COLLECTEES", self.collectees), + ("BETS", self.bets), + ("BOARD", self.board), + ("DISCARDS", self.discards), + ("HOLECARDS", self.holecards), + ) str = '' - str = str + "Hand Object for %s at %s" % (self.handid, self.sitename) + for (name, var) in vars: + str = str + "\n%s = " % name + pprint.pformat(var) + + for (name, struct) in structs: + str = str + "\n%s =\n" % name + pprint.pformat(struct, 4) return str def insert(self, db): @@ -494,12 +537,13 @@ class HoldemOmahaHand(Hand): pass - def addHoleCards(self, cards, player, shown=False, dealt=False): + def addHoleCards(self, cards, player, shown, mucked, dealt=False): """\ Assigns observed holecards to a player. cards list of card bigrams e.g. ['2h','Jc'] player (string) name of player shown whether they were revealed at showdown +mucked whether they were mucked at showdown dealt whether they were seen in a 'dealt to' line """ logging.debug("addHoleCards %s %s" % (cards, player)) @@ -516,23 +560,25 @@ dealt whether they were seen in a 'dealt to' line self.dealt.add(player) if shown: self.shown.add(player) + if mucked: + self.mucked.add(player) if player in self.holecards['PREFLOP']: self.holecards['PREFLOP'][player].update(cardset) else: self.holecards['PREFLOP'][player] = cardset - def addShownCards(self, cards, player, holeandboard=None): + def addShownCards(self, cards, player, holeandboard=None, shown=True, mucked=False): """\ For when a player shows cards for any reason (for showdown or out of choice). Card ranks will be uppercased """ logging.debug("addShownCards %s hole=%s all=%s" % (player, cards, holeandboard)) if cards is not None: - self.addHoleCards(cards,player,shown=True) + self.addHoleCards(cards,player,shown, mucked) elif holeandboard is not None: holeandboard = set([self.card(c) for c in holeandboard]) board = set([c for s in self.board.values() for c in s]) - self.addHoleCards(holeandboard.difference(board),player,shown=True) + self.addHoleCards(holeandboard.difference(board),player,shown, mucked) def writeHTMLHand(self, fh=sys.__stdout__): diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 5350713c..154d2b9d 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -66,7 +66,7 @@ follow : whether to tail -f the input""" self.re_ShowdownAction = re.compile(r"^%s: shows \[(?P.*)\]" % player_re, re.MULTILINE) self.re_CollectPot = re.compile(r"Seat (?P[0-9]+): %s (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(\$(?P[.\d]+)\)(, mucked| with.*|)" % player_re, re.MULTILINE) self.re_sitsOut = re.compile("^%s sits out" % player_re, re.MULTILINE) - self.re_ShownCards = re.compile("^Seat (?P[0-9]+): %s \(.*\) showed \[(?P.*)\].*" % player_re, re.MULTILINE) + self.re_ShownCards = re.compile("^Seat (?P[0-9]+): %s \(.*\) (?Pshowed|mucked) \[(?P.*)\].*" % player_re, re.MULTILINE) def readSupportedGames(self): @@ -222,7 +222,7 @@ follow : whether to tail -f the input""" # Also works with Omaha hands. cards = m.group('NEWCARDS') cards = set(cards.split(' ')) - hand.addHoleCards(cards, m.group('PNAME')) + hand.addHoleCards(cards, m.group('PNAME'), shown=False, mucked=False) def readDrawCards(self, hand, street): logging.debug("readDrawCards") @@ -314,9 +314,15 @@ follow : whether to tail -f the input""" def readShownCards(self,hand): for m in self.re_ShownCards.finditer(hand.handText): if m.group('CARDS') is not None: + print "SHOWED", m.group('SHOWED') cards = m.group('CARDS') cards = set(cards.split(' ')) - hand.addShownCards(cards=cards, player=m.group('PNAME')) + + (shown, mucked) = (False, False) + if m.group('SHOWED') == "showed": shown = True + elif m.group('SHOWED') == "mucked": mucked = True + + hand.addShownCards(cards=cards, player=m.group('PNAME'), shown=shown, mucked=mucked) if __name__ == "__main__": parser = OptionParser() From 0636a290f7a24eeebee311f3687488cc65540de8 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 3 Jul 2009 19:28:32 -0400 Subject: [PATCH 069/143] Get mixed game info and put it in gameType structure. --- pyfpdb/PokerStarsToFpdb.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 154d2b9d..8719a8c0 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -26,7 +26,7 @@ from HandHistoryConverter import * class PokerStars(HandHistoryConverter): # Static regexes - re_GameInfo = re.compile("PokerStars Game #(?P[0-9]+):\s+(HORSE)? \(?(?PHold\'em|Razz|7 Card Stud|7 Card Stud Hi/Lo|Omaha|Omaha Hi/Lo|Badugi) (?PNo Limit|Limit|Pot Limit),? \(?(?P\$|)?(?P[.0-9]+)/\$?(?P[.0-9]+)\) - (?P.*$)", re.MULTILINE) + re_GameInfo = re.compile("PokerStars Game #(?P[0-9]+):\s+(?PHORSE|8\-Game|HOSE)? \(?(?PHold\'em|Razz|7 Card Stud|7 Card Stud Hi/Lo|Omaha|Omaha Hi/Lo|Badugi) (?PNo Limit|Limit|Pot Limit),? \(?(?P\$|)?(?P[.0-9]+)/\$?(?P[.0-9]+)\) - (?P.*$)", re.MULTILINE) re_SplitHands = re.compile('\n\n+') re_TailSplitHands = re.compile('(\n\n\n+)') re_HandInfo = re.compile("^Table \'(?P[- a-zA-Z]+)\'(?P.+?$)?", re.MULTILINE) @@ -89,6 +89,7 @@ follow : whether to tail -f the input""" # translations from captured groups to our info strings limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl' } + mixes = { 'HORSE': 'horse', '8-Game': '8game', 'HOSE': 'hose'} games = { # base, category "Hold'em" : ('hold','holdem'), 'Omaha' : ('hold','omahahi'), @@ -109,6 +110,8 @@ follow : whether to tail -f the input""" info['bb'] = mg['BB'] if 'CURRENCY' in mg: info['currency'] = currencies[mg['CURRENCY']] + if 'MIXED' in mg: + info['mixedType'] = mixes[mg['MIXED']] # NB: SB, BB must be interpreted as blinds or bets depending on limit type. return info From 23a4ca34c8a6ecd54b9fba5617856fc0e0c90a1c Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 3 Jul 2009 20:41:08 -0400 Subject: [PATCH 070/143] Fix bug preventing some shown cards from being read. --- pyfpdb/PokerStarsToFpdb.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 8719a8c0..75609001 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -66,8 +66,7 @@ follow : whether to tail -f the input""" self.re_ShowdownAction = re.compile(r"^%s: shows \[(?P.*)\]" % player_re, re.MULTILINE) self.re_CollectPot = re.compile(r"Seat (?P[0-9]+): %s (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(\$(?P[.\d]+)\)(, mucked| with.*|)" % player_re, re.MULTILINE) self.re_sitsOut = re.compile("^%s sits out" % player_re, re.MULTILINE) - self.re_ShownCards = re.compile("^Seat (?P[0-9]+): %s \(.*\) (?Pshowed|mucked) \[(?P.*)\].*" % player_re, re.MULTILINE) - + self.re_ShownCards = re.compile("^Seat (?P[0-9]+): %s (\(.*\) )?(?Pshowed|mucked) \[(?P.*)\].*" % player_re, re.MULTILINE) def readSupportedGames(self): return [["ring", "hold", "nl"], @@ -317,7 +316,6 @@ follow : whether to tail -f the input""" def readShownCards(self,hand): for m in self.re_ShownCards.finditer(hand.handText): if m.group('CARDS') is not None: - print "SHOWED", m.group('SHOWED') cards = m.group('CARDS') cards = set(cards.split(' ')) From f323447313ddcc3efe8bdafbe775e0914787647c Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 4 Jul 2009 14:35:20 -0400 Subject: [PATCH 071/143] Get shown and mucked cards for stud games. --- pyfpdb/Hand.py | 61 ++++++++++++++++++++++++++++---------- pyfpdb/PokerStarsToFpdb.py | 2 +- 2 files changed, 47 insertions(+), 16 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index fa472b03..237b609a 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -410,6 +410,20 @@ Add a raise on [street] by [player] to [amountTo] self.collectees[player] += Decimal(pot) + def addShownCards(self, cards, player, holeandboard=None, shown=True, mucked=False): + """\ +For when a player shows cards for any reason (for showdown or out of choice). +Card ranks will be uppercased +""" + logging.debug("addShownCards %s hole=%s all=%s" % (player, cards, holeandboard)) + if cards is not None: + self.addHoleCards(cards,player,shown, mucked) + elif holeandboard is not None: + holeandboard = set([self.card(c) for c in holeandboard]) + board = set([c for s in self.board.values() for c in s]) + self.addHoleCards(holeandboard.difference(board),player,shown, mucked) + + def totalPot(self): """If all bets and blinds have been added, totals up the total pot size""" @@ -567,20 +581,6 @@ dealt whether they were seen in a 'dealt to' line else: self.holecards['PREFLOP'][player] = cardset - def addShownCards(self, cards, player, holeandboard=None, shown=True, mucked=False): - """\ -For when a player shows cards for any reason (for showdown or out of choice). -Card ranks will be uppercased -""" - logging.debug("addShownCards %s hole=%s all=%s" % (player, cards, holeandboard)) - if cards is not None: - self.addHoleCards(cards,player,shown, mucked) - elif holeandboard is not None: - holeandboard = set([self.card(c) for c in holeandboard]) - board = set([c for s in self.board.values() for c in s]) - self.addHoleCards(holeandboard.difference(board),player,shown, mucked) - - def writeHTMLHand(self, fh=sys.__stdout__): from nevow import tags as T from nevow import flat @@ -991,7 +991,7 @@ class StudHand(Hand): hhc.readStudPlayerCards(self, street) hhc.readAction(self, street) hhc.readCollectPot(self) - #hhc.readShownCards(self) # not done yet + hhc.readShownCards(self) # not done yet self.totalPot() # finalise it (total the pot) hhc.getRake(self) elif builtFrom == "DB": @@ -1014,6 +1014,36 @@ closed likewise, but known only to player except FpdbParseError, e: print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) + def addHoleCards(self, cards, player, shown, mucked, dealt=False): + """\ +Assigns observed holecards to a player. +cards list of card bigrams e.g. ['2h','Jc'] +player (string) name of player +shown whether they were revealed at showdown +mucked whether they were mucked at showdown +dealt whether they were seen in a 'dealt to' line +""" +# +# For stud games we just need to do the routine setting of shown/mucked/etc +# and then update the cards 'THIRD' and 'SEVENTH' + logging.debug("addHoleCards %s %s" % (cards, player)) + try: + self.checkPlayerExists(player) + except FpdbParseError, e: + print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) + return + + if dealt: + self.dealt.add(player) + if shown: + self.shown.add(player) + if mucked: + self.mucked.add(player) + if len(cards) > 2: + self.holecards['THIRD'][player] = (cards[0:3], None) + if len(cards) > 6: + self.holecards['SEVENTH'][player] = (cards[6], None) + # TODO: def addComplete(self, player, amount): def addComplete(self, street, player, amountTo): # assert street=='THIRD' @@ -1045,6 +1075,7 @@ Add a complete on [street] by [player] to [amountTo] self.actions['THIRD'].append(act) self.lastBet['THIRD'] = Decimal(bringin) self.pot.addMoney(player, Decimal(bringin)) + def writeHand(self, fh=sys.__stdout__): # PokerStars format. diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 75609001..2181b7cc 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -317,7 +317,7 @@ follow : whether to tail -f the input""" for m in self.re_ShownCards.finditer(hand.handText): if m.group('CARDS') is not None: cards = m.group('CARDS') - cards = set(cards.split(' ')) + cards = cards.split(' ') # needs to be a list, not a set--stud needs the order (shown, mucked) = (False, False) if m.group('SHOWED') == "showed": shown = True From a35b1a8b3c48924fc1141a4f39a9bed26b1b1caf Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 4 Jul 2009 15:19:46 -0400 Subject: [PATCH 072/143] Make WriteHand for stud report mucked hand. --- pyfpdb/Hand.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 237b609a..bf2b1ab2 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -1042,7 +1042,7 @@ dealt whether they were seen in a 'dealt to' line if len(cards) > 2: self.holecards['THIRD'][player] = (cards[0:3], None) if len(cards) > 6: - self.holecards['SEVENTH'][player] = (cards[6], None) + self.holecards['SEVENTH'][player] = ([cards[6]], None) # TODO: def addComplete(self, player, amount): def addComplete(self, street, player, amountTo): @@ -1212,11 +1212,13 @@ Add a complete on [street] by [player] to [amountTo] seatnum = player[0] name = player[1] if name in self.collectees and name in self.shown: - print >>fh, _("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards[name]), self.collectees[name])) + print >>fh, _("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, self.join_holecards(name), self.collectees[name])) elif name in self.collectees: print >>fh, _("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name])) elif name in self.shown: - print >>fh, _("Seat %d: %s showed [%s]" % (seatnum, name, " ".join(self.holecards[name]))) + print >>fh, _("Seat %d: %s showed [%s]" % (seatnum, name, self.join_holecards(name))) + elif name in self.mucked: + print >>fh, _("Seat %d: %s mucked [%s]" % (seatnum, name, self.join_holecards(name))) elif name in self.folded: print >>fh, _("Seat %d: %s folded" % (seatnum, name)) else: @@ -1225,6 +1227,12 @@ Add a complete on [street] by [player] to [amountTo] print >>fh, "\n\n" + def join_holecards(self, player): + holecards = [] + for street in self.holeStreets: + if self.holecards[street].has_key(player): + holecards = holecards + self.holecards[street][player][0] + return " ".join(holecards) class Pot(object): From c4cc6bd1aa066a91fec77c089327a5c6c8ec5140 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 4 Jul 2009 15:28:20 -0400 Subject: [PATCH 073/143] Make WriteHand for holdem report mucked cards. --- pyfpdb/Hand.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index bf2b1ab2..2a5c671d 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -772,6 +772,8 @@ dealt whether they were seen in a 'dealt to' line else: if name in self.shown: print >>fh, ("Seat %d: %s showed [%s] and lost with..." % (seatnum, name, " ".join(self.holecards['PREFLOP'][name]))) + elif name in self.mucked: + print >>fh, ("Seat %d: %s mucked [%s] " % (seatnum, name, " ".join(self.holecards['PREFLOP'][name]))) else: print >>fh, ("Seat %d: %s mucked" % (seatnum, name)) From 8f2350f86198fd8da88c22a9401855f1f4c18844 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 5 Jul 2009 11:47:18 -0400 Subject: [PATCH 074/143] Set dealt flag when reading holdem hero cards. --- pyfpdb/PokerStarsToFpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 2181b7cc..6cb81081 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -224,7 +224,7 @@ follow : whether to tail -f the input""" # Also works with Omaha hands. cards = m.group('NEWCARDS') cards = set(cards.split(' ')) - hand.addHoleCards(cards, m.group('PNAME'), shown=False, mucked=False) + hand.addHoleCards(cards, m.group('PNAME'), shown=False, mucked=False, dealt=True) def readDrawCards(self, hand, street): logging.debug("readDrawCards") From 799aa41c1ed8c2571ffef3cf92caf7d1c90c3c02 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 5 Jul 2009 23:44:53 -0400 Subject: [PATCH 075/143] Correct handling of open/closed stud hole cards. --- pyfpdb/Hand.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 2a5c671d..db1d1197 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -1041,10 +1041,16 @@ dealt whether they were seen in a 'dealt to' line self.shown.add(player) if mucked: self.mucked.add(player) - if len(cards) > 2: - self.holecards['THIRD'][player] = (cards[0:3], None) - if len(cards) > 6: - self.holecards['SEVENTH'][player] = ([cards[6]], None) + if player == self.hero: + if len(cards) > 2: + self.holecards['THIRD'][player] = ([cards[0:3]], []) + if len(cards) > 6: + self.holecards['SEVENTH'][player] = ([cards[6]], []) + else: + if len(cards) > 2: + self.holecards['THIRD'][player] = ([cards[0]], cards[1:3]) + if len(cards) > 6: + self.holecards['SEVENTH'][player] = ([], [cards[6]]) # TODO: def addComplete(self, player, amount): def addComplete(self, street, player, amountTo): From 4ae8b123ce1561a0bba727a9aec39ac3ec15e396 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 6 Jul 2009 12:00:16 -0400 Subject: [PATCH 076/143] Fix game type for non-Mixed games. --- pyfpdb/PokerStarsToFpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 6cb81081..45306281 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -109,7 +109,7 @@ follow : whether to tail -f the input""" info['bb'] = mg['BB'] if 'CURRENCY' in mg: info['currency'] = currencies[mg['CURRENCY']] - if 'MIXED' in mg: + if 'MIXED' in mg and mg['MIXED'] != None: info['mixedType'] = mixes[mg['MIXED']] # NB: SB, BB must be interpreted as blinds or bets depending on limit type. From 21d227667966b844fcaff561133eebc3075f24d3 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 6 Jul 2009 12:01:39 -0400 Subject: [PATCH 077/143] Get rid of intermediate hand obj print. --- pyfpdb/HandHistoryConverter.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index f5c4c2a5..fc6567f0 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -238,6 +238,7 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py. logging.info("Unsupported game type: %s" % gametype) if hand: +# print hand hand.writeHand(self.out_fh) else: logging.info("Unsupported game type: %s" % gametype) From 56bd7b37baedba73f5c45ee611150c2be86ef116 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 7 Jul 2009 13:48:43 -0400 Subject: [PATCH 078/143] Parse Stars tournaments for flop and stud games. Tournaments are not correctly written in writehand(). Nor are stud games. --- pyfpdb/Hand.py | 5 +++++ pyfpdb/PokerStarsToFpdb.py | 39 +++++++++++++++++++++++++++++++++----- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index db1d1197..d51424e6 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -1088,6 +1088,11 @@ Add a complete on [street] by [player] to [amountTo] def writeHand(self, fh=sys.__stdout__): # PokerStars format. # print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d - %H:%M:%S (ET)', self.starttime))) + +# TODO: +# Hole cards are not currently correctly written. Currently the down cards for non-heros +# are shown in the "dealt to" lines. They should be hidden in those lines. I tried to fix +# but mind got boggled, will try again. print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET'))) print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 45306281..3c2c959c 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -26,7 +26,18 @@ from HandHistoryConverter import * class PokerStars(HandHistoryConverter): # Static regexes - re_GameInfo = re.compile("PokerStars Game #(?P[0-9]+):\s+(?PHORSE|8\-Game|HOSE)? \(?(?PHold\'em|Razz|7 Card Stud|7 Card Stud Hi/Lo|Omaha|Omaha Hi/Lo|Badugi) (?PNo Limit|Limit|Pot Limit),? \(?(?P\$|)?(?P[.0-9]+)/\$?(?P[.0-9]+)\) - (?P.*$)", re.MULTILINE) +# re_GameInfo = re.compile("PokerStars Game #(?P[0-9]+):\s+(?PHORSE|8\-Game|HOSE)? \(?(?PHold\'em|Razz|7 Card Stud|7 Card Stud Hi/Lo|Omaha|Omaha Hi/Lo|Badugi) (?PNo Limit|Limit|Pot Limit),? \(?(?P\$|)?(?P[.0-9]+)/\$?(?P[.0-9]+)\) - (?P.*$)", re.MULTILINE) + re_GameInfo = re.compile("""PokerStars\sGame\s\#(?P[0-9]+):\s+ + (Tournament\s\#(?P\d+),\s(?P[\$\+\d\.]+)\s)? + (?PHORSE|8\-Game|HOSE)?\s?\(? + (?PHold\'em|Razz|7\sCard Stud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi)\s + (?PNo\sLimit|Limit|Pot\sLimit),?\s + (-\sLevel\s(?P[IVXLC]+)\s)?\(? + (?P\$|)? + (?P[.0-9]+)/\$? + (?P[.0-9]+)\)\s-\s + (?P.*$)""", + re.MULTILINE|re.VERBOSE) re_SplitHands = re.compile('\n\n+') re_TailSplitHands = re.compile('(\n\n\n+)') re_HandInfo = re.compile("^Table \'(?P
[- a-zA-Z]+)\'(?P.+?$)?", re.MULTILINE) @@ -62,7 +73,8 @@ follow : whether to tail -f the input""" self.re_BringIn = re.compile(r"^%s: brings[- ]in( low|) for \$?(?P[.0-9]+)" % player_re, re.MULTILINE) self.re_PostBoth = re.compile(r"^%s: posts small \& big blinds \[\$? (?P[.0-9]+)" % player_re, re.MULTILINE) self.re_HeroCards = re.compile(r"^Dealt to %s(?: \[(?P.+?)\])?( \[(?P.+?)\])" % player_re, re.MULTILINE) - self.re_Action = re.compile(r"^%s:(?P bets| checks| raises| calls| folds| discards| stands pat)( \$(?P[.\d]+))?( to \$(?P[.\d]+))?( (?P\d) cards?( \[(?P.+?)\])?)?" % player_re, re.MULTILINE) +# self.re_Action = re.compile(r"^%s:(?P bets| checks| raises| calls| folds| discards| stands pat)( \$(?P[.\d]+))?( to \$(?P[.\d]+))?( (?P\d) cards?( \[(?P.+?)\])?)?" % player_re, re.MULTILINE) + self.re_Action = re.compile(r"^%s:(?P bets| checks| raises| calls| folds| discards| stands pat)( \$?(?P[.\d]+))?( to \$?(?P[.\d]+))?( (?P\d) cards?( \[(?P.+?)\])?)?" % player_re, re.MULTILINE) self.re_ShowdownAction = re.compile(r"^%s: shows \[(?P.*)\]" % player_re, re.MULTILINE) self.re_CollectPot = re.compile(r"Seat (?P[0-9]+): %s (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(\$(?P[.\d]+)\)(, mucked| with.*|)" % player_re, re.MULTILINE) self.re_sitsOut = re.compile("^%s sits out" % player_re, re.MULTILINE) @@ -72,20 +84,26 @@ follow : whether to tail -f the input""" return [["ring", "hold", "nl"], ["ring", "hold", "pl"], ["ring", "hold", "fl"], + ["ring", "stud", "fl"], #["ring", "draw", "fl"], - ["ring", "omaha", "pl"] + + ["tour", "hold", "nl"], + ["tour", "hold", "pl"], + ["tour", "hold", "fl"], + + ["tour", "stud", "fl"], ] def determineGameType(self, handText): - info = {'type':'ring'} + info = {} m = self.re_GameInfo.search(handText) if not m: return None mg = m.groupdict() - + print "mg =", mg # translations from captured groups to our info strings limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl' } mixes = { 'HORSE': 'horse', '8-Game': '8game', 'HOSE': 'hose'} @@ -99,6 +117,10 @@ follow : whether to tail -f the input""" 'Badugi' : ('draw','badugi') } currencies = { u'€':'EUR', '$':'USD', '':'T$' } +# I don't think this is doing what we think. mg will always have all +# the expected keys, but the ones that didn't match in the regex will +# have a value of None. It is OK if it throws an exception when it +# runs across an unknown game or limit or whatever. if 'LIMIT' in mg: info['limitType'] = limits[mg['LIMIT']] if 'GAME' in mg: @@ -111,6 +133,13 @@ follow : whether to tail -f the input""" info['currency'] = currencies[mg['CURRENCY']] if 'MIXED' in mg and mg['MIXED'] != None: info['mixedType'] = mixes[mg['MIXED']] + info['tourNo'] = mg['TOURNO'] + if info['tourNo'] == None: + info['type'] = 'ring' + else: + info['type'] = 'tour' + info['buyin'] = mg['BUYIN'] + info['level'] = mg['LEVEL'] # NB: SB, BB must be interpreted as blinds or bets depending on limit type. return info From 4e952de82529b3e6ff8595998fbcee7e8e2c2672 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 7 Jul 2009 14:15:36 -0400 Subject: [PATCH 079/143] Remove intermediate print. --- pyfpdb/PokerStarsToFpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 3c2c959c..580d5481 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -103,7 +103,7 @@ follow : whether to tail -f the input""" return None mg = m.groupdict() - print "mg =", mg +# print "mg =", mg # translations from captured groups to our info strings limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl' } mixes = { 'HORSE': 'horse', '8-Game': '8game', 'HOSE': 'hose'} From d8820ae1f7a5dbf5b963144b42d1dcfd60a20e8a Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 11 Jul 2009 13:44:32 -0400 Subject: [PATCH 080/143] Allow parsing of tournaments, draw and play money. Sorry about the massive commit. There are still numerous bugs parsing non-holdem hands and writehand() is broken for all but holdem cash games. --- pyfpdb/Hand.py | 76 ++++++++++++++++++++++++++--------- pyfpdb/PokerStarsToFpdb.py | 81 ++++++++++++++++++++++++-------------- 2 files changed, 108 insertions(+), 49 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index d51424e6..cc1dfd5a 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -45,6 +45,9 @@ class Hand: self.maxseats = 10 self.counted_seats = 0 self.buttonpos = 0 + self.tourNo = None + self.buyin = None + self.level = None self.seating = [] self.players = [] self.posted = [] @@ -56,17 +59,19 @@ class Hand: self.actions = {} # [['mct','bets','$10'],['mika','folds'],['carlg','raises','$20']] self.board = {} # dict from street names to community cards self.holecards = {} + self.discards = {} for street in self.allStreets: self.streets[street] = "" # portions of the handText, filled by markStreets() + self.actions[street] = [] + for street in self.actionStreets: self.bets[street] = {} self.lastBet[street] = 0 - self.actions[street] = [] self.board[street] = [] + for street in self.holeStreets: self.holecards[street] = {} # dict from player names to holecards - + self.discards[street] = {} # dict from player names to dicts by street ... of tuples ... of discarded holecards # Collections indexed by player names # self.holecards = {} # dict from player names to dicts by street ... of tuples ... of holecards - self.discards = {} # dict from player names to dicts by street ... of tuples ... of discarded holecards self.stacks = {} self.collected = [] #list of ? self.collectees = {} # dict from player names to amounts collected (?) @@ -93,6 +98,9 @@ class Hand: ("TABLE NAME", self.tablename), ("HERO", self.hero), ("MAXSEATS", self.maxseats), + ("TOURNAMENT NO", self.tourNo), + ("BUYIN", self.buyin), + ("LEVEL", self.level), ("LASTBET", self.lastBet), ("ACTION STREETS", self.actionStreets), ("STREETS", self.streets), @@ -221,10 +229,10 @@ If a player has None chips he won't be added.""" self.players.append([seat, name, chips]) self.stacks[name] = Decimal(chips) self.pot.addPlayer(name) - for street in self.allStreets: + for street in self.actionStreets: self.bets[street][name] = [] #self.holecards[name] = {} # dict from street names. - self.discards[name] = {} # dict from street names. + #self.discards[name] = {} # dict from street names. def addStreets(self, match): @@ -784,8 +792,10 @@ class DrawHand(Hand): if gametype['base'] != 'draw': pass # or indeed don't pass and complain instead self.streetList = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] + self.allStreets = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] self.holeStreets = ['DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] self.actionStreets = ['PREDEAL', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] + self.communityStreets = [] Hand.__init__(self, sitename, gametype, handText) self.sb = gametype['sb'] self.bb = gametype['bb'] @@ -849,18 +859,19 @@ player (string) name of player self.checkPlayerExists(player) # if shown and len(cardset) > 0: # self.shown.add(player) - self.holecards[player][street] = (newcards,oldcards) + self.holecards[street][player] = (newcards,oldcards) except FpdbParseError, e: print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) def discardDrawHoleCards(self, cards, player, street): logging.debug("discardDrawHoleCards '%s' '%s' '%s'" % (cards, player, street)) - self.discards[player][street] = set([cards]) + self.discards[street][player] = set([cards]) def addDiscard(self, street, player, num, cards): self.checkPlayerExists(player) + print "street, player, num, cards =", street, player, num, cards if cards: act = (player, 'discards', num, cards) self.discardDrawHoleCards(cards, player, street) @@ -869,12 +880,12 @@ player (string) name of player self.actions[street].append(act) - def addShownCards(self, cards, player, holeandboard=None): - """\ -For when a player shows cards for any reason (for showdown or out of choice). -Card ranks will be uppercased -""" - logging.debug("addShownCards %s hole=%s all=%s" % (player, cards, holeandboard)) +# def addShownCards(self, cards, player, holeandboard=None, shown=False, mucked=False): +# """\ +#For when a player shows cards for any reason (for showdown or out of choice). +#Card ranks will be uppercased +#""" +# logging.debug("addShownCards %s hole=%s all=%s" % (player, cards, holeandboard)) # if cards is not None: # self.shown.add(player) # self.addHoleCards(cards,player) @@ -884,6 +895,33 @@ Card ranks will be uppercased # self.addHoleCards(holeandboard.difference(board),player,shown=True) + def addHoleCards(self, cards, player, shown, mucked, dealt=False): + """\ +Assigns observed holecards to a player. +cards list of card bigrams e.g. ['2h','Jc'] +player (string) name of player +shown whether they were revealed at showdown +mucked whether they were mucked at showdown +dealt whether they were seen in a 'dealt to' line +""" +# I think this only gets called for shown cards. + logging.debug("addHoleCards %s %s" % (cards, player)) + try: + self.checkPlayerExists(player) + except FpdbParseError, e: + print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) + return + + if dealt: + self.dealt.add(player) + if shown: + self.shown.add(player) + if mucked: + self.mucked.add(player) + if player != self.hero: #skip hero, we know his cards + print "player, cards =", player, cards + self.holecards[self.holeStreets[-1]][player] = (cards, set([])) + def writeHand(self, fh=sys.__stdout__): # PokerStars format. print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d %H:%M:%S ET', self.starttime))) @@ -913,8 +951,8 @@ Card ranks will be uppercased for act in self.actions['DRAWONE']: print >>fh, self.actionString(act) if act[0] == self.hero and act[1] == 'discards': - (nc,oc) = self.holecards[act[0]]['DRAWONE'] - dc = self.discards[act[0]]['DRAWONE'] + (nc,oc) = self.holecards['DRAWONE'][act[0]] + dc = self.discards['DRAWONE'][act[0]] kc = oc - dc print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc))) @@ -923,8 +961,8 @@ Card ranks will be uppercased for act in self.actions['DRAWTWO']: print >>fh, self.actionString(act) if act[0] == self.hero and act[1] == 'discards': - (nc,oc) = self.holecards[act[0]]['DRAWTWO'] - dc = self.discards[act[0]]['DRAWTWO'] + (nc,oc) = self.holecards['DRAWTWO'][act[0]] + dc = self.discards['DRAWTWO'][act[0]] kc = oc - dc print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc))) @@ -933,8 +971,8 @@ Card ranks will be uppercased for act in self.actions['DRAWTHREE']: print >>fh, self.actionString(act) if act[0] == self.hero and act[1] == 'discards': - (nc,oc) = self.holecards[act[0]]['DRAWTHREE'] - dc = self.discards[act[0]]['DRAWTHREE'] + (nc,oc) = self.holecards['DRAWTHREE'][act[0]] + dc = self.discards['DRAWTHREE'][act[0]] kc = oc - dc print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc))) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 580d5481..80c16d07 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -30,7 +30,7 @@ class PokerStars(HandHistoryConverter): re_GameInfo = re.compile("""PokerStars\sGame\s\#(?P[0-9]+):\s+ (Tournament\s\#(?P\d+),\s(?P[\$\+\d\.]+)\s)? (?PHORSE|8\-Game|HOSE)?\s?\(? - (?PHold\'em|Razz|7\sCard Stud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi)\s + (?PHold\'em|Razz|7\sCard Stud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball)\s (?PNo\sLimit|Limit|Pot\sLimit),?\s (-\sLevel\s(?P[IVXLC]+)\s)?\(? (?P\$|)? @@ -40,7 +40,11 @@ class PokerStars(HandHistoryConverter): re.MULTILINE|re.VERBOSE) re_SplitHands = re.compile('\n\n+') re_TailSplitHands = re.compile('(\n\n\n+)') - re_HandInfo = re.compile("^Table \'(?P
[- a-zA-Z]+)\'(?P.+?$)?", re.MULTILINE) + re_HandInfo = re.compile("""^Table\s\'(?P
[-\ a-zA-Z\d]+)\'\s + ((?P\d+)-max\s)? + (?P\(Play\sMoney\)\s)? + (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
[- a-zA-Z]+)\'(?P.+?$)?", re.MULTILINE) + re_Button = re.compile('\n\n\n + re_PlayerInfo = re.compile('^', re.MULTILINE) + re_Card = re.compile('^', re.MULTILINE) + re_BoardLast = re.compile('^', re.MULTILINE) + + def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True): + HandHistoryConverter.__init__(self, in_path, out_path, sitename="Win2day", follow=follow) + logging.info("Initialising Win2day converter class") + self.filetype = "text" + self.codepage = "cp1252" + self.sideID = 4 + if autostart: + self.start() + + + def compilePlayerRegexs(self, hand): + players = set([player[1] for player in hand.players]) + if not players <= self.compiledPlayers: # x <= y means 'x is subset of y' + # we need to recompile the player regexs. + self.compiledPlayers = players + player_re = "(?P" + "|".join(map(re.escape, players)) + ")" + logging.debug("player_re: " + player_re) + # + + self.re_PostSB = re.compile(r'^' % player_re, re.MULTILINE) + self.re_PostBB = re.compile(r'^' % player_re, re.MULTILINE) + self.re_Antes = re.compile(r"^%s: posts the ante \$?(?P[.0-9]+)" % player_re, re.MULTILINE) + self.re_BringIn = re.compile(r"^%s: brings[- ]in( low|) for \$?(?P[.0-9]+)" % player_re, re.MULTILINE) + self.re_PostBoth = re.compile(r'^' % player_re, re.MULTILINE) + + #r'\n\n' + self.re_HeroCards = re.compile(r'\n(?P\n)' % player_re, re.MULTILINE) + + #'^' + self.re_Action = re.compile(r'^' % player_re, re.MULTILINE) + + self.re_ShowdownAction = re.compile(r'\n(?P\n)' % player_re, re.MULTILINE) + # + # + self.re_CollectPot = re.compile(r'' % player_re, re.MULTILINE) + self.re_sitsOut = re.compile("^%s sits out" % player_re, re.MULTILINE) + self.re_ShownCards = re.compile("^Seat (?P[0-9]+): %s \(.*\) showed \[(?P.*)\].*" % player_re, re.MULTILINE) + + + def readSupportedGames(self): + return [["ring", "hold", "nl"], + ["ring", "hold", "pl"], + ["ring", "hold", "fl"], + ["ring", "stud", "fl"], + ["ring", "draw", "fl"], + ["ring", "omaha", "pl"] + ] + + def determineGameType(self, handText): + info = {'type':'ring'} + + m = self.re_GameInfo.search(handText) + if not m: + print "determineGameType:", handText + return None + + mg = m.groupdict() + + # translations from captured groups to our info strings + #limits = { 'NL':'nl', 'PL':'pl', 'Limit':'fl' } + limits = { 'NL':'nl', 'PL':'pl'} + games = { # base, category + "GAME_THM" : ('hold','holdem'), + # 'Omaha' : ('hold','omahahi'), + #'Omaha Hi/Lo' : ('hold','omahahilo'), + # 'Razz' : ('stud','razz'), + #'7 Card Stud' : ('stud','studhi'), + # 'Badugi' : ('draw','badugi') + } + if 'LIMIT' in mg: + info['limitType'] = limits[mg['LIMIT']] + if 'GAME' in mg: + (info['base'], info['category']) = games[mg['GAME']] + if 'SB' in mg: + info['sb'] = mg['SB'] + if 'BB' in mg: + info['bb'] = mg['BB'] + if 'CURRENCY' in mg: + info['currency'] = mg['CURRENCY'] + # NB: SB, BB must be interpreted as blinds or bets depending on limit type. + + return info + + + def readHandInfo(self, hand): + info = {} + m = self.re_HandInfo.search(hand.handText,re.DOTALL) + if m: + info.update(m.groupdict()) + # TODO: Be less lazy and parse maxseats from the HandInfo regex + if m.group('TABLEATTRIBUTES'): + m2 = re.search("\s*(\d+)-max", m.group('TABLEATTRIBUTES')) + hand.maxseats = int(m2.group(1)) + m = self.re_GameInfo.search(hand.handText) + if m: info.update(m.groupdict()) + m = self.re_Button.search(hand.handText) + if m: info.update(m.groupdict()) + # TODO : I rather like the idea of just having this dict as hand.info + logging.debug("readHandInfo: %s" % info) + for key in info: + if key == 'DATETIME': + # Win2day uses UTC timestamp + # m2 = re.search("(?P[0-9]{4})\/(?P[0-9]{2})\/(?P[0-9]{2})[\- ]+(?P[0-9]+):(?P[0-9]+):(?P[0-9]+)", info[key]) + # datetime = "%s/%s/%s %s:%s:%s" % (m2.group('Y'), m2.group('M'),m2.group('D'),m2.group('H'),m2.group('MIN'),m2.group('S')) + # hand.starttime = time.strptime(time.gmtime(info[key])) + # hand.starttime = time.gmtime(int(info[key])) + hand.starttime = time.gmtime(int(info[key])) + if key == 'HID': + hand.handid = info[key] + if key == 'TABLE': + hand.tablename = info[key] + if key == 'BUTTON': + hand.buttonpos = info[key] + + def readButton(self, hand): + m = self.re_Button.search(hand.handText) + if m: + for player in hand.players: + if player[1] == m.group('BUTTON'): + hand.buttonpos = player[0] + break + else: + logging.info('readButton: not found') + + def readPlayerStacks(self, hand): + logging.debug("readPlayerStacks") + m = self.re_PlayerInfo.finditer(hand.handText) + players = [] + for a in m: + hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH')) + + def markStreets(self, hand): + # PREFLOP = ** Dealing down cards ** + # This re fails if, say, river is missing; then we don't get the ** that starts the river. + if hand.gametype['base'] in ("hold"): + #m = re.search(r"\*\*\* HOLE CARDS \*\*\*(?P.+(?=\*\*\* FLOP \*\*\*)|.+)" + # r"(\*\*\* FLOP \*\*\*(?P \[\S\S \S\S \S\S\].+(?=\*\*\* TURN \*\*\*)|.+))?" + # r"(\*\*\* TURN \*\*\* \[\S\S \S\S \S\S] (?P\[\S\S\].+(?=\*\*\* RIVER \*\*\*)|.+))?" + # r"(\*\*\* RIVER \*\*\* \[\S\S \S\S \S\S \S\S] (?P\[\S\S\].+))?", hand.handText,re.DOTALL) + + m = re.search('(?P.+(?=.+(?=.+(?=.+(?= 38): + retCard += 's' + elif(card > 25): + retCard += 'h' + elif(card > 12): + retCard += 'c' + else: + retCard += 'd' + + return(retCard) + + def readDrawCards(self, hand, street): + logging.debug("readDrawCards") + m = self.re_HeroCards.finditer(hand.streets[street]) + if m == None: + hand.involved = False + else: + for player in m: + hand.hero = player.group('PNAME') # Only really need to do this once + newcards = player.group('NEWCARDS') + oldcards = player.group('OLDCARDS') + if newcards == None: + newcards = set() + else: + newcards = set(newcards.split(' ')) + if oldcards == None: + oldcards = set() + else: + oldcards = set(oldcards.split(' ')) + hand.addDrawHoleCards(newcards, oldcards, player.group('PNAME'), street) + + + def readStudPlayerCards(self, hand, street): + # See comments of reference implementation in FullTiltToFpdb.py + logging.debug("readStudPlayerCards") + m = self.re_HeroCards.finditer(hand.streets[street]) + for player in m: + #~ logging.debug(player.groupdict()) + (pname, oldcards, newcards) = (player.group('PNAME'), player.group('OLDCARDS'), player.group('NEWCARDS')) + if oldcards: + oldcards = [c.strip() for c in oldcards.split(' ')] + if newcards: + newcards = [c.strip() for c in newcards.split(' ')] + if street=='ANTES': + return + elif street=='THIRD': + # we'll have observed hero holecards in CARDS and thirdstreet open cards in 'NEWCARDS' + # hero: [xx][o] + # others: [o] + hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = oldcards, open = newcards) + elif street in ('FOURTH', 'FIFTH', 'SIXTH'): + # 4th: + # hero: [xxo] [o] + # others: [o] [o] + # 5th: + # hero: [xxoo] [o] + # others: [oo] [o] + # 6th: + # hero: [xxooo] [o] + # others: [ooo] [o] + hand.addPlayerCards(player = player.group('PNAME'), street = street, open = newcards) + # we may additionally want to check the earlier streets tally with what we have but lets trust it for now. + elif street=='SEVENTH' and newcards: + # hero: [xxoooo] [x] + # others: not reported. + hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = newcards) + + def readAction(self, hand, street): + m = self.re_Action.finditer(hand.streets[street]) + for action in m: + if action.group('ATYPE') == 'ACTION_RAISE': + hand.addRaiseBy( street, action.group('PNAME'), action.group('BET') ) + elif action.group('ATYPE') == 'ACTION_CALL': + hand.addCall( street, action.group('PNAME'), action.group('BET') ) + elif action.group('ATYPE') == 'ACTION_ALLIN': + hand.addRaiseBy( street, action.group('PNAME'), action.group('BET') ) + elif action.group('ATYPE') == 'ACTION_BET': + hand.addBet( street, action.group('PNAME'), action.group('BET') ) + elif action.group('ATYPE') == 'ACTION_FOLD': + hand.addFold( street, action.group('PNAME')) + elif action.group('ATYPE') == 'ACTION_CHECK': + hand.addCheck( street, action.group('PNAME')) + elif action.group('ATYPE') == 'ACTION_DISCARD': + hand.addDiscard(street, action.group('PNAME'), action.group('NODISCARDED'), action.group('DISCARDED')) + elif action.group('ATYPE') == 'ACTION_STAND': + hand.addStandsPat( street, action.group('PNAME')) + else: + print "DEBUG: unimplemented readAction: '%s' '%s'" %(action.group('PNAME'),action.group('ATYPE'),) + + + def readShowdownActions(self, hand): + for shows in self.re_ShowdownAction.finditer(hand.handText): + showdownCards = set([]) + for card in self.re_Card.finditer(shows.group('CARDS')): + print "DEBUG:", card, card.group('CARD'), self.convertWin2dayCards(card.group('CARD')) + showdownCards.add(self.convertWin2dayCards(card.group('CARD'))) + + hand.addShownCards(showdownCards, shows.group('PNAME')) + + def readCollectPot(self,hand): + for m in self.re_CollectPot.finditer(hand.handText): + potcoll = Decimal(m.group('POT')) + if potcoll > 0: + hand.addCollectPot(player=m.group('PNAME'),pot=potcoll) + + def readShownCards(self,hand): + for m in self.re_ShownCards.finditer(hand.handText): + if m.group('CARDS') is not None: + cards = m.group('CARDS') + cards = set(cards.split(' ')) + hand.addShownCards(cards=cards, player=m.group('PNAME')) + +if __name__ == "__main__": + parser = OptionParser() + parser.add_option("-i", "--input", dest="ipath", help="parse input hand history", default="-") + parser.add_option("-o", "--output", dest="opath", help="output translation to", default="-") + parser.add_option("-f", "--follow", dest="follow", help="follow (tail -f) the input", action="store_true", default=False) + parser.add_option("-q", "--quiet", + action="store_const", const=logging.CRITICAL, dest="verbosity", default=logging.INFO) + parser.add_option("-v", "--verbose", + action="store_const", const=logging.INFO, dest="verbosity") + parser.add_option("--vv", + action="store_const", const=logging.DEBUG, dest="verbosity") + + (options, args) = parser.parse_args() + + LOG_FILENAME = './logging.out' + logging.basicConfig(filename=LOG_FILENAME,level=options.verbosity) + + e = Win2day(in_path = options.ipath, out_path = options.opath, follow = options.follow) From dc6a1c45f9fae72155dde1dc97dd404dc459a4a8 Mon Sep 17 00:00:00 2001 From: Matt Turnbull Date: Tue, 14 Jul 2009 00:04:10 +0100 Subject: [PATCH 087/143] sqlite - connecting and (re)creating some tables --- pyfpdb/Configuration.py | 2 + pyfpdb/FpdbSQLQueries.py | 66 +++++++++++++++--- pyfpdb/fpdb.py | 8 ++- pyfpdb/fpdb_db.py | 144 ++++++++++++++++++++++++++++----------- pyfpdb/fpdb_import.py | 1 + 5 files changed, 170 insertions(+), 51 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 0ea4b371..27e06b3d 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -493,6 +493,8 @@ class Config: db['db-backend'] = 2 elif string.lower(self.supported_databases[name].db_server) == 'postgresql': db['db-backend'] = 3 + elif string.lower(self.supported_databases[name].db_server) == 'sqlite': + db['db-backend'] = 4 else: db['db-backend'] = None # this is big trouble return db diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index 598c0868..b7e5679e 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -38,7 +38,9 @@ class FpdbSQLQueries: elif(self.dbname == 'PostgreSQL'): self.query['list_tables'] = """SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'""" elif(self.dbname == 'SQLite'): - self.query['list_tables'] = """ """ + self.query['list_tables'] = """SELECT name FROM sqlite_master + WHERE type='table' + ORDER BY name;""" ################################################################## # Drop Tables - MySQL, PostgreSQL and SQLite all share same syntax @@ -63,8 +65,8 @@ class FpdbSQLQueries: self.query['createSettingsTable'] = """CREATE TABLE Settings (version SMALLINT)""" elif(self.dbname == 'SQLite'): - #Probably doesn't work. - self.query['createSettingsTable'] = """ """ + self.query['createSettingsTable'] = """CREATE TABLE Settings + (version INTEGER) """ ################################ @@ -83,7 +85,10 @@ class FpdbSQLQueries: name varchar(32), currency char(3))""" elif(self.dbname == 'SQLite'): - self.query['createSitesTable'] = """ """ + self.query['createSitesTable'] = """CREATE TABLE Sites ( + id INTEGER PRIMARY KEY, + name TEXT NOT NULL, + currency TEXT NOT NULL)""" ################################ @@ -118,7 +123,19 @@ class FpdbSQLQueries: smallBet int, bigBet int)""" elif(self.dbname == 'SQLite'): - self.query['createGametypesTable'] = """ """ + self.query['createGametypesTable'] = """CREATE TABLE GameTypes ( + id INTEGER PRIMARY KEY, + siteId INTEGER, + type TEXT, + base TEXT, + category TEXT, + limitType TEXT, + hiLo TEXT, + smallBlind INTEGER, + bigBlind INTEGER, + smallBet INTEGER, + bigBet INTEGER, + FOREIGN KEY(siteId) REFERENCES Sites(id) ON DELETE CASCADE)""" ################################ @@ -141,7 +158,13 @@ class FpdbSQLQueries: comment text, commentTs timestamp without time zone)""" elif(self.dbname == 'SQLite'): - self.query['createPlayersTable'] = """ """ + self.query['createPlayersTable'] = """CREATE TABLE Players ( + id INTEGER PRIMARY KEY, + name TEXT, + siteId INTEGER, + comment TEXT, + commentTs BLOB, + FOREIGN KEY(siteId) REFERENCES Sites(id) ON DELETE CASCADE)""" ################################ @@ -245,11 +268,22 @@ class FpdbSQLQueries: comment TEXT, commentTs timestamp without time zone)""" elif(self.dbname == 'SQLite'): - self.query['createHandsTable'] = """ """ + self.query['createHandsTable'] = """CREATE TABLE Hands ( + id INTEGER PRIMARY KEY, + tableName TEXT(20), + siteHandNo INTEGER, + gametypeId INTEGER, + handStart BLOB, + importTime BLOB, + seats INTEGER, + maxSeats INTEGER, + comment TEXT, + commentTs BLOB, + FOREIGN KEY(gametypeId) REFERENCES Gametypes(id) ON DELETE CASCADE)""" ################################ - # Create Gametypes + # Create BoardCards ################################ if(self.dbname == 'MySQL InnoDB'): @@ -336,7 +370,14 @@ class FpdbSQLQueries: comment TEXT, commentTs timestamp without time zone)""" elif(self.dbname == 'SQLite'): - self.query['createTourneysTable'] = """ """ + self.query['createTourneysTable'] = """CREATE TABLE TourneyTypes ( + id INTEGER PRIMARY KEY, + siteId INTEGER, + buyin INTEGER, + fee INTEGER, + knockout INTEGER, + rebuyOrAddon BOOL, + FOREIGN KEY(siteId) REFERENCES Sites(id) ON DELETE CASCADE)""" ################################ # Create HandsPlayers @@ -869,6 +910,13 @@ class FpdbSQLQueries: elif(self.dbname == 'SQLite'): self.query['addPlayersIndex'] = """ """ + + if(self.dbname == 'MySQL InnoDB' or self.dbname == 'PostgreSQL'): + self.query['set tx level'] = """SET SESSION TRANSACTION + ISOLATION LEVEL READ COMMITTED""" + elif(self.dbname == 'SQLite'): + self.query['set tx level'] = """ """ + ################################ # Queries used in GuiGraphViewer ################################ diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index b03e8424..61f5f111 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -19,7 +19,6 @@ import os import sys import Options import string - cl_options = string.join(sys.argv[1:]) (options, sys.argv) = Options.fpdb_options() @@ -28,6 +27,8 @@ if not options.errorsToConsole: errorFile = open('fpdb-error-log.txt', 'w', 0) sys.stderr = errorFile +import logging + import pygtk pygtk.require('2.0') import gtk @@ -481,6 +482,11 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") #end def tabGraphViewer def __init__(self): + LOG_FILENAME = './logging.out' + LOG_FORMAT = "%(asctime)-15s %(levelname)-8s %(message)s" + logging.basicConfig(filename=LOG_FILENAME,level=10,format=LOG_FORMAT) + logging.info("Fpdb started") + self.threads=[] self.db=None self.config = Configuration.Config(file=options.config, dbname=options.dbname) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 29817af9..c52a2e56 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -18,20 +18,21 @@ import os import re import sys +import logging from time import time, strftime import fpdb_simple import FpdbSQLQueries class fpdb_db: + MYSQL_INNODB = 2 + PGSQL = 3 + SQLITE = 4 def __init__(self): """Simple constructor, doesnt really do anything""" self.db = None self.cursor = None self.sql = {} - self.MYSQL_INNODB = 2 - self.PGSQL = 3 - self.SQLITE = 4 # Data Structures for index and foreign key creation # drop_code is an int with possible values: 0 - don't drop for bulk import @@ -72,6 +73,8 @@ class fpdb_db: , {'tab':'TourneysPlayers', 'col':'tourneyId', 'drop':0} , {'tab':'TourneyTypes', 'col':'siteId', 'drop':0} ] + , [ # indexes for sqlite (list index 4) + ] ] self.foreignKeys = [ @@ -146,12 +149,12 @@ class fpdb_db: self.settings = {} self.settings['os'] = "linuxmac" if os.name != "nt" else "windows" - self.settings.update(config.get_db_parameters()) - self.connect(self.settings['db-backend'], - self.settings['db-host'], - self.settings['db-databaseName'], - self.settings['db-user'], - self.settings['db-password']) + db = config.get_db_parameters() + self.connect(backend=db['db-backend'], + host=db['db-host'], + database=db['db-databaseName'], + user=db['db-user'], + password=db['db-password']) #end def do_connect def connect(self, backend=None, host=None, database=None, @@ -164,13 +167,13 @@ class fpdb_db: self.user=user self.password=password self.database=database - if backend==self.MYSQL_INNODB: + if backend==fpdb_db.MYSQL_INNODB: import MySQLdb try: self.db = MySQLdb.connect(host = host, user = user, passwd = password, db = database, use_unicode=True) except: raise fpdb_simple.FpdbError("MySQL connection failed") - elif backend==self.PGSQL: + elif backend==fpdb_db.PGSQL: import psycopg2 import psycopg2.extensions psycopg2.extensions.register_type(psycopg2.extensions.UNICODE) @@ -201,12 +204,19 @@ class fpdb_db: msg = "PostgreSQL connection to database (%s) user (%s) failed." % (database, user) print msg raise fpdb_simple.FpdbError(msg) + elif backend==fpdb_db.SQLITE: + logging.info("Connecting to SQLite:(%s)") + import sqlite3 + self.db = sqlite3.connect(database,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") + else: raise fpdb_simple.FpdbError("unrecognised database backend:"+backend) self.cursor=self.db.cursor() - self.cursor.execute('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED') # Set up query dictionary as early in the connection process as we can. self.sql = FpdbSQLQueries.FpdbSQLQueries(self.get_backend_name()) + self.cursor.execute(self.sql.query['set tx level']) self.wrongDbVersion=False try: self.cursor.execute("SELECT * FROM Settings") @@ -237,7 +247,9 @@ class fpdb_db: def create_tables(self): #todo: should detect and fail gracefully if tables already exist. + logging.debug(self.sql.query['createSettingsTable']) self.cursor.execute(self.sql.query['createSettingsTable']) + logging.debug(self.sql.query['createSitesTable']) self.cursor.execute(self.sql.query['createSitesTable']) self.cursor.execute(self.sql.query['createGametypesTable']) self.cursor.execute(self.sql.query['createPlayersTable']) @@ -275,10 +287,12 @@ class fpdb_db: for table in tables: self.cursor.execute(self.sql.query['drop_table'] + table[0] + ' cascade') elif(self.get_backend_name() == 'SQLite'): - #todo: sqlite version here - print "Empty function here" + self.cursor.execute(self.sql.query['list_tables']) + for table in self.cursor.fetchall(): + logging.debug(self.sql.query['drop_table'] + table[0]) + self.cursor.execute(self.sql.query['drop_table'] + table[0]) - self.db.commit() + self.db.commit() #end def drop_tables def drop_referential_integrity(self): @@ -307,6 +321,8 @@ class fpdb_db: return "MySQL InnoDB" elif self.backend==3: return "PostgreSQL" + elif self.backend==4: + return "SQLite" else: raise fpdb_simple.FpdbError("invalid backend") #end def get_backend_name @@ -316,11 +332,14 @@ class fpdb_db: #end def get_db_info def fillDefaultData(self): - self.cursor.execute("INSERT INTO Settings VALUES (118);") - self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'Full Tilt Poker', 'USD');") - self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'PokerStars', 'USD');") - self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'Everleaf', 'USD');") - self.cursor.execute("INSERT INTO TourneyTypes VALUES (DEFAULT, 1, 0, 0, 0, False);") + logging.debug("INSERT INTO Settings (version) VALUES (118);") + self.cursor.execute("INSERT INTO Settings (version) VALUES (118);") + self.cursor.execute("INSERT INTO Sites (name,currency) VALUES ('Full Tilt Poker', 'USD')") + self.cursor.execute("INSERT INTO Sites (name,currency) VALUES ('PokerStars', 'USD')") + self.cursor.execute("INSERT INTO Sites (name,currency) VALUES ('Everleaf', 'USD')") + self.cursor.execute("""INSERT INTO TourneyTypes + (siteId,buyin,fee,knockout,rebuyOrAddon) VALUES + (1,0,0,0,?)""",(False,) ) #end def fillDefaultData def recreate_tables(self): @@ -617,7 +636,7 @@ class fpdb_db: ret = -1 else: ret = row[0] - elif self.backend == self.SQLITE: + elif self.backend == fpdb_db.SQLITE: # don't know how to do this in sqlite print "getLastInsertId(): not coded for sqlite yet" ret = -1 @@ -628,27 +647,70 @@ class fpdb_db: def storeHand(self, p): #stores into table hands: - self.cursor.execute ("""INSERT INTO Hands - (siteHandNo, gametypeId, handStart, seats, tableName, importTime, maxSeats - ,boardcard1, boardcard2, boardcard3, boardcard4, boardcard5 - ,playersVpi, playersAtStreet1, playersAtStreet2 - ,playersAtStreet3, playersAtStreet4, playersAtShowdown - ,street0Raises, street1Raises, street2Raises - ,street3Raises, street4Raises, street1Pot - ,street2Pot, street3Pot, street4Pot - ,showdownPot + self.cursor.execute ("""INSERT INTO Hands ( + tablename, + sitehandno, + gametypeid, + handstart, + importtime, + seats, + maxseats, + boardcard1, + boardcard2, + boardcard3, + boardcard4, + boardcard5, +-- texture, + playersVpi, + playersAtStreet1, + playersAtStreet2, + playersAtStreet3, + playersAtStreet4, + playersAtShowdown, + street0Raises, + street1Raises, + street2Raises, + street3Raises, + street4Raises, +-- street1Pot, +-- street2Pot, +-- street3Pot, +-- street4Pot, +-- showdownPot ) VALUES - (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""" - ,(p['siteHandNo'], gametype_id, p['handStart'], len(names), p['tableName'], datetime.datetime.today(), p['maxSeats'] - ,p['boardcard1'], ['boardcard2'], p['boardcard3'], ['boardcard4'], ['boardcard5'] - ,hudCache['playersVpi'], hudCache['playersAtStreet1'], hudCache['playersAtStreet2'] - ,hudCache['playersAtStreet3'], hudCache['playersAtStreet4'], hudCache['playersAtShowdown'] - ,hudCache['street0Raises'], hudCache['street1Raises'], hudCache['street2Raises'] - ,hudCache['street3Raises'], hudCache['street4Raises'], hudCache['street1Pot'] - ,hudCache['street2Pot'], hudCache['street3Pot'], hudCache['street4Pot'] - ,hudCache['showdownPot'] - ) - ) + (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, %s, %s)""", + ( + p['tablename'], + p['sitehandno'], + p['gametypeid'], + p['handStart'], + datetime.datetime.today(), + len(p['names']), + p['maxSeats'], + p['boardcard1'], + p['boardcard2'], + p['boardcard3'], + p['boardcard4'], + p['boardcard5'], + hudCache['playersVpi'], + hudCache['playersAtStreet1'], + hudCache['playersAtStreet2'], + hudCache['playersAtStreet3'], + hudCache['playersAtStreet4'], + hudCache['playersAtShowdown'], + hudCache['street0Raises'], + hudCache['street1Raises'], + hudCache['street2Raises'], + hudCache['street3Raises'], + hudCache['street4Raises'], + hudCache['street1Pot'], + hudCache['street2Pot'], + hudCache['street3Pot'], + hudCache['street4Pot'], + hudCache['showdownPot'] + ) + ) #return getLastInsertId(backend, conn, cursor) #end class fpdb_db diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 455c1e27..bcc5d02f 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -22,6 +22,7 @@ import os # todo: remove this once import_dir is in fpdb_import import sys from time import time, strftime +import logging import traceback import math import datetime From 599aee6393be37b2512ea27f7aa64f0e74ddbdfa Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 14 Jul 2009 10:55:39 -0400 Subject: [PATCH 088/143] Fix parsing of tournaments of mixed games. --- pyfpdb/PokerStarsToFpdb.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index b6fd09fb..5661e16e 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -33,8 +33,8 @@ class PokerStars(HandHistoryConverter): re_GameInfo = re.compile("""PokerStars\sGame\s\#(?P[0-9]+):\s+ (Tournament\s\#(?P\d+),\s(?P[\$\+\d\.]+)\s)? (?PHORSE|8\-Game|HOSE)?\s?\(? - (?PHold\'em|Razz|7\sCard Stud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball)\s - (?PNo\sLimit|Limit|Pot\sLimit),?\s + (?PHold\'em|Razz|7\sCard\sStud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball)\s + (?PNo\sLimit|Limit|Pot\sLimit)\)?,?\s (-\sLevel\s(?P[IVXLC]+)\s)?\(? (?P\$|)? (?P[.0-9]+)/\$? From b252e350d619089fcbe5cd54e9f242689f236704 Mon Sep 17 00:00:00 2001 From: Matt Turnbull Date: Tue, 14 Jul 2009 23:34:47 +0100 Subject: [PATCH 089/143] fix my breakage.. --- pyfpdb/HandHistoryConverter.py | 79 ++++++++-------------------------- 1 file changed, 19 insertions(+), 60 deletions(-) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index f5c4c2a5..cd3a1db0 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -28,91 +28,51 @@ import codecs from decimal import Decimal import operator from xml.dom.minidom import Node -# from pokereval import PokerEval import time import datetime -import gettext -#from pokerengine.pokercards import * -# provides letter2name{}, letter2names{}, visible_card(), not_visible_card(), is_visible(), card_value(), class PokerCards -# but it's probably not installed so here are the ones we may want: -letter2name = { - 'A': 'Ace', - 'K': 'King', - 'Q': 'Queen', - 'J': 'Jack', - 'T': 'Ten', - '9': 'Nine', - '8': 'Eight', - '7': 'Seven', - '6': 'Six', - '5': 'Five', - '4': 'Four', - '3': 'Trey', - '2': 'Deuce' - } - -letter2names = { - 'A': 'Aces', - 'K': 'Kings', - 'Q': 'Queens', - 'J': 'Jacks', - 'T': 'Tens', - '9': 'Nines', - '8': 'Eights', - '7': 'Sevens', - '6': 'Sixes', - '5': 'Fives', - '4': 'Fours', - '3': 'Treys', - '2': 'Deuces' - } - -import gettext -gettext.install('myapplication') +#import gettext +#gettext.install('fpdb') class HandHistoryConverter(): READ_CHUNK_SIZE = 10000 # bytes to read at a time from file (in tail mode) def __init__(self, in_path = '-', out_path = '-', sitename = None, follow=False): - logging.info("HandHistory init called") + logging.info("HandHistory init") # default filetype and codepage. Subclasses should set these properly. self.filetype = "text" self.codepage = "utf8" - + self.in_path = in_path self.out_path = out_path - if self.out_path == '-': - # write to stdout + + if in_path == '-': + self.in_fh = sys.stdin + + if out_path == '-': self.out_fh = sys.stdout else: - # TODO: out_path should be sanity checked before opening. Perhaps in fpdb_import? - # I'm not sure what we're looking for, although we don't want out_path==in_path!='-' - self.out_fh = open(self.out_path, 'w') # doomswitch is now on :| + # TODO: out_path should be sanity checked. + self.out_fh = open(self.out_path, 'w') + self.sitename = sitename self.follow = follow self.compiledPlayers = set() self.maxseats = 10 def __str__(self): - #TODO : I got rid of most of the hhdir stuff. - tmp = "HandHistoryConverter: '%s'\n" % (self.sitename) - #tmp = tmp + "\thhbase: '%s'\n" % (self.hhbase) - #tmp = tmp + "\thhdir: '%s'\n" % (self.hhdir) - tmp = tmp + "\tfiletype: '%s'\n" % (self.filetype) - tmp = tmp + "\tinfile: '%s'\n" % (self.in_path) - tmp = tmp + "\toutfile: '%s'\n" % (self.out_path) - #tmp = tmp + "\tgametype: '%s'\n" % (self.gametype[0]) - #tmp = tmp + "\tgamebase: '%s'\n" % (self.gametype[1]) - #tmp = tmp + "\tlimit: '%s'\n" % (self.gametype[2]) - #tmp = tmp + "\tsb/bb: '%s/%s'\n" % (self.gametype[3], self.gametype[4]) - return tmp + return """ +HandHistoryConverter: '%(sitename)s' + filetype: '%(filetype)s' + in_path: '%(in_path)s' + out_path: '%(out_path)s' + """ % { 'sitename':self.sitename, 'filetype':self.filetype, 'in_path':self.in_path, 'out_path':self.out_path } def start(self): """process a hand at a time from the input specified by in_path. If in follow mode, wait for more data to turn up. -Otherwise, finish at eof... +Otherwise, finish at eof. """ starttime = time.time() @@ -224,7 +184,6 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py. base = gametype['base'] limit = gametype['limitType'] l = [type] + [base] + [limit] - hand = None if l in self.readSupportedGames(): hand = None if gametype['base'] == 'hold': From 806d61ae2368315bc6f9d18e86a89e9066cb06cf Mon Sep 17 00:00:00 2001 From: Matt Turnbull Date: Wed, 15 Jul 2009 00:14:25 +0100 Subject: [PATCH 090/143] log line --- pyfpdb/fpdb_db.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index c52a2e56..a0f6ca92 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -205,7 +205,7 @@ class fpdb_db: print msg raise fpdb_simple.FpdbError(msg) elif backend==fpdb_db.SQLITE: - logging.info("Connecting to SQLite:(%s)") + logging.info("Connecting to SQLite:%(database)s" % {'database':database}) import sqlite3 self.db = sqlite3.connect(database,detect_types=sqlite3.PARSE_DECLTYPES) sqlite3.register_converter("bool", lambda x: bool(int(x))) From 70f271ef78bd8e4f722540718f426b6cbdb3bc12 Mon Sep 17 00:00:00 2001 From: Matt Turnbull Date: Wed, 15 Jul 2009 00:15:04 +0100 Subject: [PATCH 091/143] location of test PS horse hh --- pyfpdb/PokerStarsToFpdb.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 5350713c..4b66e899 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -1,4 +1,4 @@ - #!/usr/bin/env python +#!/usr/bin/env python # -*- coding: utf-8 -*- # # Copyright 2008, Carl Gherardi @@ -320,7 +320,7 @@ follow : whether to tail -f the input""" if __name__ == "__main__": parser = OptionParser() - parser.add_option("-i", "--input", dest="ipath", help="parse input hand history", default="regression-test-files/pokerstars/HH20090226 Natalie V - $0.10-$0.20 - HORSE.txt") + parser.add_option("-i", "--input", dest="ipath", help="parse input hand history", default="regression-test-files/stars/horse/HH20090226 Natalie V - $0.10-$0.20 - HORSE.txt") parser.add_option("-o", "--output", dest="opath", help="output translation to", default="-") parser.add_option("-f", "--follow", dest="follow", help="follow (tail -f) the input", action="store_true", default=False) parser.add_option("-q", "--quiet", From 021b9934eab2804009183ccce90ced20c9ba712f Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 14 Jul 2009 19:18:38 -0400 Subject: [PATCH 092/143] Fix writing of mixed tournament hands. Other minor changes. --- pyfpdb/Hand.py | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 1846b240..a14ecaeb 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -545,22 +545,25 @@ Map the tuple self.gametype onto the pokerstars string describing it return ("%s: stands pat" %(act[0])) def getStakesAsString(self): - retstring = "%s%s/%s%s" % (self.SYMBOL[self.gametype['currency']], self.sb, self.SYMBOL[self.gametype['currency']], self.bb) - return retstring + """Return a string of the stakes of the current hand.""" + return "%s%s/%s%s" % (self.sym, self.sb, self.sym, self.bb) def writeGameLine(self): -# print >>fh, ("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET'))) - game_string = "PokerStars Game #%s: " % self.handid - if self.tourNo != None: - game_string = game_string + "Tournament #%s, %s %s - Level %s (%s) - " % (self.tourNo, + """Return the first HH line for the current hand.""" + gs = "PokerStars Game #%s: " % self.handid + + if self.tourNo != None and self.mixed != None: # mixed tournament + gs = gs + "Tournament #%s, %s %s (%s) - Level %s (%s) - " % (self.tourNo, self.buyin, self.MS[self.mixed], self.getGameTypeAsString(), self.level, self.getStakesAsString()) + elif self.tourNo != None: # all other tournaments + gs = gs + "Tournament #%s, %s %s - Level %s (%s) - " % (self.tourNo, self.buyin, self.getGameTypeAsString(), self.level, self.getStakesAsString()) - elif self.mixed != None: - game_string = game_string + " %s (%s, %s) - " % (self.MS[self.mixed], + elif self.mixed != None: # all other mixed games + gs = gs + " %s (%s, %s) - " % (self.MS[self.mixed], self.getGameTypeAsString(), self.getStakesAsString()) - else: - game_string = game_string + " %s (%s) - " % (self.getGameTypeAsString(), self.getStakesAsString()) - game_string = game_string + datetime.datetime.strftime(self.starttime,'%Y/%m/%d %H:%M:%S ET') - return game_string + else: # non-mixed cash games + gs = gs + " %s (%s) - " % (self.getGameTypeAsString(), self.getStakesAsString()) + + return gs + datetime.datetime.strftime(self.starttime,'%Y/%m/%d %H:%M:%S ET') def writeTableLine(self): @@ -723,12 +726,10 @@ class HoldemOmahaHand(Hand): def writeHand(self, fh=sys.__stdout__): # PokerStars format. -# print >>fh, ("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET'))) + self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done print >>fh, self.writeGameLine() print >>fh, self.writeTableLine() -# print >>fh, ("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) - players_who_act_preflop = set(([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']])) logging.debug(self.actions['PREFLOP']) for player in [x for x in self.players if x[1] in players_who_act_preflop]: @@ -972,9 +973,8 @@ class DrawHand(Hand): def writeHand(self, fh=sys.__stdout__): # PokerStars format. -# print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d %H:%M:%S ET', self.starttime))) + self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done print >>fh, self.writeGameLine() -# print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) print >>fh, self.writeTableLine() players_who_act_ondeal = set(([x[0] for x in self.actions['DEAL']]+[x[0] for x in self.actions['BLINDSANTES']])) @@ -1188,16 +1188,14 @@ Add a complete on [street] by [player] to [amountTo] def writeHand(self, fh=sys.__stdout__): # PokerStars format. -# print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d - %H:%M:%S (ET)', self.starttime))) # TODO: # Hole cards are not currently correctly written. Currently the down cards for non-heros # are shown in the "dealt to" lines. They should be hidden in those lines. I tried to fix # but mind got boggled, will try again. -# print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET'))) + self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done print >>fh, self.writeGameLine() print >>fh, self.writeTableLine() -# print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) players_who_post_antes = set([x[0] for x in self.actions['ANTES']]) From 35a5cffb77b07399b4dec80cfbec9451e2b2bc51 Mon Sep 17 00:00:00 2001 From: Matt Turnbull Date: Wed, 15 Jul 2009 00:26:53 +0100 Subject: [PATCH 093/143] Working on PS HORSE file now.. --- pyfpdb/HandHistoryConverter.py | 4 ++-- pyfpdb/PokerStarsToFpdb.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 590ee065..47ddecf5 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -31,8 +31,8 @@ from xml.dom.minidom import Node import time import datetime -#import gettext -#gettext.install('fpdb') +import gettext +gettext.install('fpdb') class HandHistoryConverter(): diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 41b3c67f..b855586b 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -298,7 +298,7 @@ follow : whether to tail -f the input""" hand.addHoleCards(street, hand.hero, closed=newcards, shown=False, mucked=False, dealt=True) for street, text in hand.streets.iteritems(): - if street in ('PREFLOP', 'DEAL'): continue # already done these + if not text or street in ('PREFLOP', 'DEAL'): continue # already done these m = self.re_HeroCards.finditer(hand.streets[street]) for found in m: player = found.group('PNAME') From 521e17f8568b1bcd21b5a0a4cb08f879f5d94381 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 15 Jul 2009 12:22:46 +0800 Subject: [PATCH 094/143] Add some boilerplate stuff for Boss Media/Win2day plugin --- pyfpdb/HUD_config.xml.example | 46 +++++++++++++++++++++++++++++++++- pyfpdb/HandHistoryConverter.py | 2 +- pyfpdb/Win2dayToFpdb.py | 0 pyfpdb/fpdb_db.py | 1 + 4 files changed, 47 insertions(+), 2 deletions(-) mode change 100644 => 100755 pyfpdb/Win2dayToFpdb.py diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index ef30fb9b..3cd592cc 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -159,6 +159,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -292,6 +336,7 @@ + @@ -300,4 +345,3 @@ - diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index fc6567f0..7e08554b 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -114,7 +114,7 @@ class HandHistoryConverter(): If in follow mode, wait for more data to turn up. Otherwise, finish at eof... -""" +""" starttime = time.time() if not self.sanityCheck(): print "Cowardly refusing to continue after failed sanity check" diff --git a/pyfpdb/Win2dayToFpdb.py b/pyfpdb/Win2dayToFpdb.py old mode 100644 new mode 100755 diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index f89b5d6d..0af29aa1 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -319,6 +319,7 @@ class fpdb_db: self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'Full Tilt Poker', 'USD');") self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'PokerStars', 'USD');") self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'Everleaf', 'USD');") + self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'Win2day', 'USD');") self.cursor.execute("INSERT INTO TourneyTypes VALUES (DEFAULT, 1, 0, 0, 0, False);") #end def fillDefaultData From ec9ce544ca6cef56c7b1cc46003a3a4d09e7c85c Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 15 Jul 2009 23:32:17 +0800 Subject: [PATCH 095/143] Fix if database hasn't been created yet. Still broken on my setup, but at least fpdb now starts --- pyfpdb/Database.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 0f354054..d4e667df 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -71,20 +71,23 @@ class Database: # a new session) cur = self.connection.cursor() - self.hand_1day_ago = 0 - cur.execute(self.sql.query['get_hand_1day_ago']) - row = cur.fetchone() - if row and row[0]: - self.hand_1day_ago = row[0] - #print "hand 1day ago =", self.hand_1day_ago + if self.fdb.wrongDbVersion == False: + self.hand_1day_ago = 0 + cur.execute(self.sql.query['get_hand_1day_ago']) + row = cur.fetchone() + if row and row[0]: + self.hand_1day_ago = row[0] + #print "hand 1day ago =", self.hand_1day_ago - 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) + 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 = 0 # todo - #cur.execute(self.sql.query['get_table_name'], (hand_id, )) - #row = cur.fetchone() + self.hand_nhands_ago = 0 # todo + #cur.execute(self.sql.query['get_table_name'], (hand_id, )) + #row = cur.fetchone() + else: + print "Bailing on DB query, not sure it exists yet" self.saveActions = False if self.import_options['saveActions'] == False else True def do_connect(self, c): From 0e76c3a6767e24e3ad7089558e396f4678d9ec34 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Jul 2009 11:48:58 -0400 Subject: [PATCH 096/143] Fix findHeroCards() for empty streets. --- pyfpdb/PokerStarsToFpdb.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 5661e16e..dbed145b 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -299,6 +299,7 @@ follow : whether to tail -f the input""" for street, text in hand.streets.iteritems(): if street in ('PREFLOP', 'DEAL'): continue # already done these + if hand.streets[street] == None: continue # don't regex a None m = self.re_HeroCards.finditer(hand.streets[street]) for found in m: player = found.group('PNAME') @@ -398,7 +399,7 @@ follow : whether to tail -f the input""" def readShowdownActions(self, hand): -# TODO: pick up mucks also +# TODO: pick up mucks also?? for shows in self.re_ShowdownAction.finditer(hand.handText): cards = shows.group('CARDS').split(' ') hand.addShownCards(cards, shows.group('PNAME')) From bd2db9861210d673d012c03569e837a704beba59 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Jul 2009 11:50:27 -0400 Subject: [PATCH 097/143] Housecleaning. Refactoring writeHand() = not finished. --- pyfpdb/Hand.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index a14ecaeb..8cac4e7a 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -32,7 +32,7 @@ import pprint import DerivedStats import Card -class Hand: +class Hand(object): ###############################################################3 # Class Variables @@ -575,6 +575,13 @@ Map the tuple self.gametype onto the pokerstars string describing it return table_string + def writeHand(self, fh=sys.__stdout__): + # PokerStars format. + self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done + print >>fh, self.writeGameLine() + print >>fh, self.writeTableLine() + + class HoldemOmahaHand(Hand): def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC", handid=None): if gametype['base'] != 'hold': @@ -726,9 +733,7 @@ class HoldemOmahaHand(Hand): def writeHand(self, fh=sys.__stdout__): # PokerStars format. - self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done - print >>fh, self.writeGameLine() - print >>fh, self.writeTableLine() + super(HoldemOmahaHand, self).writeHand(fh) players_who_act_preflop = set(([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']])) logging.debug(self.actions['PREFLOP']) @@ -973,9 +978,7 @@ class DrawHand(Hand): def writeHand(self, fh=sys.__stdout__): # PokerStars format. - self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done - print >>fh, self.writeGameLine() - print >>fh, self.writeTableLine() + super(DrawHand, self).writeHand(fh) players_who_act_ondeal = set(([x[0] for x in self.actions['DEAL']]+[x[0] for x in self.actions['BLINDSANTES']])) @@ -1193,9 +1196,7 @@ Add a complete on [street] by [player] to [amountTo] # Hole cards are not currently correctly written. Currently the down cards for non-heros # are shown in the "dealt to" lines. They should be hidden in those lines. I tried to fix # but mind got boggled, will try again. - self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done - print >>fh, self.writeGameLine() - print >>fh, self.writeTableLine() + super(StudHand, self).writeHand(fh) players_who_post_antes = set([x[0] for x in self.actions['ANTES']]) From b92feee021229886e5baabaa9a3d8c7d3732d9c6 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 15 Jul 2009 23:58:34 +0800 Subject: [PATCH 098/143] Revert Matts change for sqlite until fixed. Previous syntax failed to insert the required line into TourneyTypes --- pyfpdb/fpdb_db.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 30101d0c..2b75ea12 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -336,9 +336,10 @@ class fpdb_db: self.cursor.execute("INSERT INTO Sites (name,currency) VALUES ('PokerStars', 'USD')") self.cursor.execute("INSERT INTO Sites (name,currency) VALUES ('Everleaf', 'USD')") self.cursor.execute("INSERT INTO Sites (name,currency) VALUES ('Win2day', 'USD')") - self.cursor.execute("""INSERT INTO TourneyTypes - (siteId,buyin,fee,knockout,rebuyOrAddon) VALUES - (1,0,0,0,?)""",(False,) ) + self.cursor.execute("INSERT INTO TourneyTypes VALUES (DEFAULT, 1, 0, 0, 0, False);") + #self.cursor.execute("""INSERT INTO TourneyTypes + # (siteId,buyin,fee,knockout,rebuyOrAddon) VALUES + # (1,0,0,0,?)""",(False,) ) #end def fillDefaultData def recreate_tables(self): From 427999b69cbb2c4b0afa3ed8807d10d66847c728 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Jul 2009 21:22:07 -0400 Subject: [PATCH 099/143] Correctly write stud holecards in writeHand(). --- pyfpdb/Hand.py | 58 +++++++++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 34 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 8c1e2173..fbb4b491 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -286,6 +286,7 @@ If a player has None chips he won't be added.""" def setCommunityCards(self, street, cards): logging.debug("setCommunityCards %s %s" %(street, cards)) self.board[street] = [self.card(c) for c in cards] +# print "DEBUG: self.board: %s" % self.board def card(self,c): """upper case the ranks but not suits, 'atjqk' => 'ATJQK'""" @@ -1060,7 +1061,7 @@ class StudHand(Hand): self.actionStreets = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] self.streetList = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] # a list of the observed street names in order - self.holeStreets = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] + self.holeStreets = ['THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] Hand.__init__(self, sitename, gametype, handText) self.sb = gametype['sb'] self.bb = gametype['bb'] @@ -1097,9 +1098,9 @@ class StudHand(Hand): else: # self.addHoleCards('PREFLOP', player, open=[], closed=cards, shown=shown, mucked=mucked, dealt=dealt) self.addHoleCards('THIRD', player, open=[cards[2]], closed=cards[0:2], shown=shown, mucked=mucked) - self.addHoleCards('FOURTH', player, open=[cards[3]], closed=[], shown=shown, mucked=mucked) - self.addHoleCards('FIFTH', player, open=[cards[4]], closed=[], shown=shown, mucked=mucked) - self.addHoleCards('SIXTH', player, open=[cards[5]], closed=[], shown=shown, mucked=mucked) + self.addHoleCards('FOURTH', player, open=[cards[3]], closed=[cards[2]], shown=shown, mucked=mucked) + self.addHoleCards('FIFTH', player, open=[cards[4]], closed=cards[2:4], shown=shown, mucked=mucked) + self.addHoleCards('SIXTH', player, open=[cards[5]], closed=cards[2:5], shown=shown, mucked=mucked) self.addHoleCards('SEVENTH', player, open=[], closed=[cards[6]], shown=shown, mucked=mucked) @@ -1216,7 +1217,8 @@ Add a complete on [street] by [player] to [amountTo] dealt+=1 if dealt==1: print >>fh, _("*** 3RD STREET ***") - print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(closed) + "] " if closed else " ", "[" + " ".join(open) + "]" if open else "") +# print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(closed) + "] " if closed else " ", "[" + " ".join(open) + "]" if open else "") + print >>fh, self.writeHoleCards('THIRD', player) for act in self.actions['THIRD']: #FIXME: Need some logic here for bringin vs completes print >>fh, self.actionString(act) @@ -1226,15 +1228,10 @@ Add a complete on [street] by [player] to [amountTo] #~ print >>fh, _("*** 4TH STREET ***") for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: if player in self.holecards['FOURTH']: - old = [] - (o,c) = self.holecards['THIRD'][player] - if o:old.extend(o) - if c:old.extend(c) - new = self.holecards['FOURTH'][player][0] dealt+=1 if dealt==1: print >>fh, _("*** 4TH STREET ***") - print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "") + print >>fh, self.writeHoleCards('FOURTH', player) for act in self.actions['FOURTH']: print >>fh, self.actionString(act) @@ -1243,16 +1240,10 @@ Add a complete on [street] by [player] to [amountTo] #~ print >>fh, _("*** 5TH STREET ***") for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: if self.holecards['FIFTH'].has_key(player): - old = [] - for street in ('THIRD','FOURTH'): - (o,c) = self.holecards[street][player] - if o:old.extend(o) - if c:old.extend(c) - new = self.holecards['FIFTH'][player][0] dealt+=1 if dealt==1: print >>fh, _("*** 5TH STREET ***") - print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "") + print >>fh, self.writeHoleCards('FIFTH', player) for act in self.actions['FIFTH']: print >>fh, self.actionString(act) @@ -1261,16 +1252,10 @@ Add a complete on [street] by [player] to [amountTo] #~ print >>fh, _("*** 6TH STREET ***") for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: if self.holecards['SIXTH'].has_key(player): - old = [] - for street in ('THIRD','FOURTH','FIFTH'): - (o,c) = self.holecards[street][player] - if o:old.extend(o) - if c:old.extend(c) - new = self.holecards['SIXTH'][player][0] dealt += 1 if dealt == 1: print >>fh, _("*** 6TH STREET ***") - print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "") + print >>fh, self.writeHoleCards('SIXTH', player) for act in self.actions['SIXTH']: print >>fh, self.actionString(act) @@ -1279,17 +1264,11 @@ Add a complete on [street] by [player] to [amountTo] # Then we have no 'dealt to' lines, no action lines, but still 7th street should appear. # The only way I can see to know whether to print this line is by knowing the state of the hand # i.e. are all but one players folded; is there an allin showdown; and all that. - print >>fh, _("*** 7TH STREET ***") + print >>fh, _("*** RIVER ***") for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: if self.holecards['SEVENTH'].has_key(player): - old = [] - for street in ('THIRD','FOURTH','FIFTH','SIXTH'): - (o,c) = self.holecards[street][player] - if o:old.extend(o) - if c:old.extend(c) - new = self.holecards['SEVENTH'][player][0] - if new: - print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "") + if self.writeHoleCards('SEVENTH', player): + print >>fh, self.writeHoleCards('SEVENTH', player) for act in self.actions['SEVENTH']: print >>fh, self.actionString(act) @@ -1341,6 +1320,17 @@ Add a complete on [street] by [player] to [amountTo] print >>fh, "\n\n" + def writeHoleCards(self, street, player): + hc = "Dealt to %s [" % player + if street == 'THIRD': + if player == self.hero: + return hc + " ".join(self.holecards[street][player][1]) + " " + " ".join(self.holecards[street][player][0]) + ']' + else: + return hc + " ".join(self.holecards[street][player][0]) + ']' + + if street == 'SEVENTH' and player != self.hero: return # only write 7th st line for hero, LDO + return hc + " ".join(self.holecards[street][player][1]) + "][" + " ".join(self.holecards[street][player][0]) + "]" + def join_holecards(self, player): holecards = [] for street in self.holeStreets: From 12db3c0d55b660c6f9045d3373f856f930411c5d Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Jul 2009 21:46:45 -0400 Subject: [PATCH 100/143] Add a space to make stud holecard printing perfect. --- pyfpdb/Hand.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index fbb4b491..c97e88f1 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -733,6 +733,7 @@ class HoldemOmahaHand(Hand): def writeHand(self, fh=sys.__stdout__): # PokerStars format. +# TODO: board cards (in summary) not printed in correct order super(HoldemOmahaHand, self).writeHand(fh) players_who_act_preflop = set(([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']])) @@ -1329,7 +1330,7 @@ Add a complete on [street] by [player] to [amountTo] return hc + " ".join(self.holecards[street][player][0]) + ']' if street == 'SEVENTH' and player != self.hero: return # only write 7th st line for hero, LDO - return hc + " ".join(self.holecards[street][player][1]) + "][" + " ".join(self.holecards[street][player][0]) + "]" + return hc + " ".join(self.holecards[street][player][1]) + "] [" + " ".join(self.holecards[street][player][0]) + "]" def join_holecards(self, player): holecards = [] From 3253d5a234a4f68e8b0de7ef63ad04f1bc1f84b6 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Jul 2009 22:11:23 -0400 Subject: [PATCH 101/143] Get stud shown cards right in writeHand(). --- pyfpdb/Hand.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index c97e88f1..95fd74a5 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -1336,7 +1336,15 @@ Add a complete on [street] by [player] to [amountTo] holecards = [] for street in self.holeStreets: if self.holecards[street].has_key(player): - holecards = holecards + self.holecards[street][player][0] + if street == 'THIRD': + holecards = holecards + self.holecards[street][player][1] + self.holecards[street][player][0] + elif street == 'SEVENTH': + if player == self.hero: + holecards = holecards + self.holecards[street][player][0] + else: + holecards = holecards + self.holecards[street][player][1] + else: + holecards = holecards + self.holecards[street][player][0] return " ".join(holecards) class Pot(object): From e0dc556a679e7b6991a68db05c04c9d31f0c2218 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Jul 2009 22:15:20 -0400 Subject: [PATCH 102/143] Clean up some methods previously commented out. --- pyfpdb/Hand.py | 92 -------------------------------------------------- 1 file changed, 92 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 95fd74a5..f5a07644 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -905,21 +905,6 @@ class DrawHand(Hand): self.addHoleCards('DRAWTHREE', player, open=[], closed=cards, shown=shown, mucked=mucked, dealt=dealt) -# def addDrawHoleCards(self, newcards, oldcards, player, street, shown=False): -# """\ -#Assigns observed holecards to a player. -#cards list of card bigrams e.g. ['2h','Jc'] -#player (string) name of player -#""" -# try: -# self.checkPlayerExists(player) -## if shown and len(cardset) > 0: -## self.shown.add(player) -# self.holecards[street][player] = (newcards,oldcards) -# except FpdbParseError, e: -# print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) - - def discardDrawHoleCards(self, cards, player, street): logging.debug("discardDrawHoleCards '%s' '%s' '%s'" % (cards, player, street)) self.discards[street][player] = set([cards]) @@ -935,48 +920,6 @@ class DrawHand(Hand): self.actions[street].append(act) -# def addShownCards(self, cards, player, holeandboard=None, shown=False, mucked=False): -# """\ -#For when a player shows cards for any reason (for showdown or out of choice). -#Card ranks will be uppercased -#""" -# logging.debug("addShownCards %s hole=%s all=%s" % (player, cards, holeandboard)) -# if cards is not None: -# self.shown.add(player) -# self.addHoleCards(cards,player) -# elif holeandboard is not None: -# holeandboard = set([self.card(c) for c in holeandboard]) -# board = set([c for s in self.board.values() for c in s]) -# self.addHoleCards(holeandboard.difference(board),player,shown=True) - - -# def addHoleCards(self, cards, player, shown, mucked, dealt=False): -# """\ -#Assigns observed holecards to a player. -#cards list of card bigrams e.g. ['2h','Jc'] -#player (string) name of player -#shown whether they were revealed at showdown -#mucked whether they were mucked at showdown -#dealt whether they were seen in a 'dealt to' line -#""" -## I think this only gets called for shown cards. -# logging.debug("addHoleCards %s %s" % (cards, player)) -# try: -# self.checkPlayerExists(player) -# except FpdbParseError, e: -# print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) -# return -# -# if dealt: -# self.dealt.add(player) -# if shown: -# self.shown.add(player) -# if mucked: -# self.mucked.add(player) -# if player != self.hero: #skip hero, we know his cards -# print "player, cards =", player, cards -# self.holecards[self.holeStreets[-1]][player] = (cards, set([])) - def writeHand(self, fh=sys.__stdout__): # PokerStars format. super(DrawHand, self).writeHand(fh) @@ -1122,41 +1065,6 @@ closed likewise, but known only to player except FpdbParseError, e: print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) -# def addHoleCards(self, cards, player, shown, mucked, dealt=False): -# """\ -#Assigns observed holecards to a player. -#cards list of card bigrams e.g. ['2h','Jc'] -#player (string) name of player -#shown whether they were revealed at showdown -#mucked whether they were mucked at showdown -#dealt whether they were seen in a 'dealt to' line -#""" -## -## For stud games we just need to do the routine setting of shown/mucked/etc -## and then update the cards 'THIRD' and 'SEVENTH' -# logging.debug("addHoleCards %s %s" % (cards, player)) -# try: -# self.checkPlayerExists(player) -# except FpdbParseError, e: -# print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) -# return -# -# if dealt: -# self.dealt.add(player) -# if shown: -# self.shown.add(player) -# if mucked: -# self.mucked.add(player) -# if player == self.hero: -# if len(cards) > 2: -# self.holecards['THIRD'][player] = ([cards[0:3]], []) -# if len(cards) > 6: -# self.holecards['SEVENTH'][player] = ([cards[6]], []) -# else: -# if len(cards) > 2: -# self.holecards['THIRD'][player] = ([cards[0]], cards[1:3]) -# if len(cards) > 6: -# self.holecards['SEVENTH'][player] = ([], [cards[6]]) # TODO: def addComplete(self, player, amount): def addComplete(self, street, player, amountTo): # assert street=='THIRD' From 889aea48b6805ab42121048a17c264a85842b3c4 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Jul 2009 22:30:41 -0400 Subject: [PATCH 103/143] Make the board in the summary of flop games print in the right order. --- pyfpdb/Hand.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index f5a07644..65745c2c 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -808,8 +808,8 @@ class HoldemOmahaHand(Hand): print >>fh, "%s | Rake $%.2f" % (self.pot, self.rake) board = [] - for s in self.board.values(): - board += s + for street in ["FLOP", "TURN", "RIVER"]: + board += self.board[street] if board: # sometimes hand ends preflop without a board print >>fh, ("Board [%s]" % (" ".join(board))) From b5b0b6a7b70a791124fb0f29d9b79bf487e440de Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Jul 2009 23:04:16 -0400 Subject: [PATCH 104/143] Get rid of hard wired $ in writeHand. Replace with appropriate symbol based on ring, tournament, play, etc. --- pyfpdb/Hand.py | 54 +++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 65745c2c..5f2174b8 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -523,22 +523,22 @@ Map the tuple self.gametype onto the pokerstars string describing it elif act[1] == 'checks': return ("%s: checks " %(act[0])) elif act[1] == 'calls': - return ("%s: calls $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) + return ("%s: calls %s%s%s" %(act[0], self.sym, act[2], ' and is all-in' if act[3] else '')) elif act[1] == 'bets': - return ("%s: bets $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) + return ("%s: bets %s%s%s" %(act[0], self.sym, act[2], ' and is all-in' if act[3] else '')) elif act[1] == 'raises': - return ("%s: raises $%s to $%s%s" %(act[0], act[2], act[3], ' and is all-in' if act[5] else '')) + return ("%s: raises %s%s to %s%s%s" %(act[0], self.sym, act[2], self.sym, act[3], ' and is all-in' if act[5] else '')) elif act[1] == 'completea': - return ("%s: completes to $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) + return ("%s: completes to %s%s%s" %(act[0], self.sym, act[2], ' and is all-in' if act[3] else '')) elif act[1] == 'posts': if(act[2] == "small blind"): - return ("%s: posts small blind $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else '')) + return ("%s: posts small blind %s%s%s" %(act[0], self.sym, act[3], ' and is all-in' if act[4] else '')) elif(act[2] == "big blind"): - return ("%s: posts big blind $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else '')) + return ("%s: posts big blind %s%s%s" %(act[0], self.sym, act[3], ' and is all-in' if act[4] else '')) elif(act[2] == "both"): - return ("%s: posts small & big blinds $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else '')) + return ("%s: posts small & big blinds %s%s%s" %(act[0], self.sym, act[3], ' and is all-in' if act[4] else '')) elif act[1] == 'bringin': - return ("%s: brings in for $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) + return ("%s: brings in for %s%s%s" %(act[0], self.sym, act[2], ' and is all-in' if act[3] else '')) elif act[1] == 'discards': return ("%s: discards %s %s%s" %(act[0], act[2], 'card' if act[2] == 1 else 'cards' , " [" + " ".join(self.discards[act[0]]['DRAWONE']) + "]" if self.hero == act[0] else '')) elif act[1] == 'stands pat': @@ -645,8 +645,8 @@ class HoldemOmahaHand(Hand): def render_stack(context,data): pat = context.tag.patternGenerator('list_item') for player in data: - x = "Seat %s: %s ($%s in chips) " %(player[0], player[1], - player[2]) + x = "Seat %s: %s (%s%s in chips) " %(player[0], player[1], + self.sym, player[2]) context.tag[ pat().fillSlots('playerStack', x)] return context.tag @@ -800,12 +800,12 @@ class HoldemOmahaHand(Hand): # Immediately before the summary. # The current importer uses those lines for importing winning rather than the summary for name in self.pot.returned: - print >>fh, ("Uncalled bet ($%s) returned to %s" %(self.pot.returned[name],name)) + print >>fh, ("Uncalled bet (%s%s) returned to %s" %(self.sym, self.pot.returned[name],name)) for entry in self.collected: - print >>fh, ("%s collected $%s from x pot" %(entry[0], entry[1])) + print >>fh, ("%s collected %s%s from x pot" %(entry[0], self.sym, entry[1])) print >>fh, ("*** SUMMARY ***") - print >>fh, "%s | Rake $%.2f" % (self.pot, self.rake) + print >>fh, "%s | Rake %s%.2f" % (self.pot, self.sym, self.rake) board = [] for street in ["FLOP", "TURN", "RIVER"]: @@ -817,9 +817,9 @@ class HoldemOmahaHand(Hand): seatnum = player[0] name = player[1] if name in self.collectees and name in self.shown: - print >>fh, ("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards['PREFLOP'][name][1]), self.collectees[name])) + print >>fh, ("Seat %d: %s showed [%s] and won (%s%s)" % (seatnum, name, " ".join(self.holecards['PREFLOP'][name][1]), self.sym, self.collectees[name])) elif name in self.collectees: - print >>fh, ("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name])) + print >>fh, ("Seat %d: %s collected (%s%s)" % (seatnum, name, self.sym, self.collectees[name])) #~ elif name in self.shown: #~ print >>fh, _("Seat %d: %s showed [%s]" % (seatnum, name, " ".join(self.holecards[name]['PREFLOP']))) elif name in self.folded: @@ -928,11 +928,11 @@ class DrawHand(Hand): for player in [x for x in self.players if x[1] in players_who_act_ondeal]: #Only print stacks of players who do something on deal - print >>fh, _("Seat %s: %s ($%s in chips) " %(player[0], player[1], player[2])) + print >>fh, _("Seat %s: %s (%s%s in chips) " %(player[0], player[1], self.sym, player[2])) if 'BLINDSANTES' in self.actions: for act in self.actions['BLINDSANTES']: - print >>fh, _("%s: %s %s $%s" %(act[0], act[1], act[2], act[3])) + print >>fh, _("%s: %s %s %s%s" %(act[0], act[1], act[2], self.sym, act[3])) if 'DEAL' in self.actions: print >>fh, _("*** DEALING HANDS ***") @@ -985,12 +985,12 @@ class DrawHand(Hand): # Immediately before the summary. # The current importer uses those lines for importing winning rather than the summary for name in self.pot.returned: - print >>fh, _("Uncalled bet ($%s) returned to %s" %(self.pot.returned[name],name)) + print >>fh, _("Uncalled bet (%s%s) returned to %s" %(self.sym, self.pot.returned[name],name)) for entry in self.collected: - print >>fh, _("%s collected $%s from x pot" %(entry[0], entry[1])) + print >>fh, _("%s collected %s%s from x pot" %(entry[0], self.sym, entry[1])) print >>fh, _("*** SUMMARY ***") - print >>fh, "%s | Rake $%.2f" % (self.pot, self.rake) + print >>fh, "%s | Rake %s%.2f" % (self.pot, self.sym, self.rake) print >>fh, "\n\n" @@ -1111,11 +1111,11 @@ Add a complete on [street] by [player] to [amountTo] for player in [x for x in self.players if x[1] in players_who_post_antes]: #Only print stacks of players who do something preflop - print >>fh, _("Seat %s: %s ($%s)" %(player[0], player[1], player[2])) + print >>fh, _("Seat %s: %s (%s%s)" %(player[0], player[1], self.sym, player[2])) if 'ANTES' in self.actions: for act in self.actions['ANTES']: - print >>fh, _("%s: posts the ante $%s" %(act[0], act[3])) + print >>fh, _("%s: posts the ante %s%s" %(act[0], self.sym, act[3])) if 'THIRD' in self.actions: dealt = 0 @@ -1196,12 +1196,12 @@ Add a complete on [street] by [player] to [amountTo] # Immediately before the summary. # The current importer uses those lines for importing winning rather than the summary for name in self.pot.returned: - print >>fh, _("Uncalled bet ($%s) returned to %s" %(self.pot.returned[name],name)) + print >>fh, _("Uncalled bet (%s%s) returned to %s" %(self.sym, self.pot.returned[name],name)) for entry in self.collected: - print >>fh, _("%s collected $%s from x pot" %(entry[0], entry[1])) + print >>fh, _("%s collected %s%s from x pot" %(entry[0], self.sym, entry[1])) print >>fh, _("*** SUMMARY ***") - print >>fh, "%s | Rake $%.2f" % (self.pot, self.rake) + print >>fh, "%s | Rake %s%.2f" % (self.pot, self.sym, self.rake) #print >>fh, _("Total pot $%s | Rake $%.2f" % (self.totalpot, self.rake)) # TODO: side pots board = [] @@ -1214,9 +1214,9 @@ Add a complete on [street] by [player] to [amountTo] seatnum = player[0] name = player[1] if name in self.collectees and name in self.shown: - print >>fh, _("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, self.join_holecards(name), self.collectees[name])) + print >>fh, _("Seat %d: %s showed [%s] and won (%s%s)" % (seatnum, name, self.join_holecards(name), self.sym, self.collectees[name])) elif name in self.collectees: - print >>fh, _("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name])) + print >>fh, _("Seat %d: %s collected (%s%s)" % (seatnum, name, self.sym, self.collectees[name])) elif name in self.shown: print >>fh, _("Seat %d: %s showed [%s]" % (seatnum, name, self.join_holecards(name))) elif name in self.mucked: From 52fcbd79667ef4556e8b898bf8ae8e702f4d4953 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Jul 2009 23:40:07 -0400 Subject: [PATCH 105/143] Remove completed TODOs(plenty left!). Remove obsolete comments. --- pyfpdb/Hand.py | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 5f2174b8..d4a1ca44 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -81,7 +81,6 @@ class Hand(object): self.holecards[street] = {} # dict from player names to holecards self.discards[street] = {} # dict from player names to dicts by street ... of tuples ... of discarded holecards # Collections indexed by player names -# self.holecards = {} # dict from player names to dicts by street ... of tuples ... of holecards self.stacks = {} self.collected = [] #list of ? self.collectees = {} # dict from player names to amounts collected (?) @@ -92,7 +91,6 @@ class Hand(object): self.shown = set() # cards were shown self.mucked = set() # cards were mucked at showdown -# self.action = [] # Things to do with money self.pot = Pot() self.totalpot = None @@ -733,7 +731,6 @@ class HoldemOmahaHand(Hand): def writeHand(self, fh=sys.__stdout__): # PokerStars format. -# TODO: board cards (in summary) not printed in correct order super(HoldemOmahaHand, self).writeHand(fh) players_who_act_preflop = set(([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']])) @@ -859,8 +856,6 @@ class DrawHand(Hand): # Read actions in street order for street in self.streetList: if self.streets[street]: - # hhc.readCommunityCards(self, street) -# hhc.readDrawCards(self, street) hhc.readAction(self, street) hhc.readCollectPot(self) hhc.readShownCards(self) @@ -1020,13 +1015,11 @@ class StudHand(Hand): hhc.readAntes(self) hhc.readBringIn(self) hhc.readHeroCards(self) - #hhc.readShowdownActions(self) # not done yet # Read actions in street order for street in self.streetList: if self.streets[street]: logging.debug(street) logging.debug(self.streets[street]) -# hhc.readStudPlayerCards(self, street) hhc.readAction(self, street) hhc.readCollectPot(self) hhc.readShownCards(self) # not done yet @@ -1040,7 +1033,6 @@ class StudHand(Hand): if shown: self.shown.add(player) if mucked: self.mucked.add(player) else: -# self.addHoleCards('PREFLOP', player, open=[], closed=cards, shown=shown, mucked=mucked, dealt=dealt) self.addHoleCards('THIRD', player, open=[cards[2]], closed=cards[0:2], shown=shown, mucked=mucked) self.addHoleCards('FOURTH', player, open=[cards[3]], closed=[cards[2]], shown=shown, mucked=mucked) self.addHoleCards('FIFTH', player, open=[cards[4]], closed=cards[2:4], shown=shown, mucked=mucked) @@ -1060,8 +1052,6 @@ closed likewise, but known only to player try: self.checkPlayerExists(player) self.holecards[street][player] = (open, closed) -# cards = set([self.card(c) for c in cards]) -# self.holecards[player].update(cards) except FpdbParseError, e: print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) @@ -1101,17 +1091,13 @@ Add a complete on [street] by [player] to [amountTo] def writeHand(self, fh=sys.__stdout__): # PokerStars format. -# TODO: -# Hole cards are not currently correctly written. Currently the down cards for non-heros -# are shown in the "dealt to" lines. They should be hidden in those lines. I tried to fix -# but mind got boggled, will try again. super(StudHand, self).writeHand(fh) players_who_post_antes = set([x[0] for x in self.actions['ANTES']]) for player in [x for x in self.players if x[1] in players_who_post_antes]: #Only print stacks of players who do something preflop - print >>fh, _("Seat %s: %s (%s%s)" %(player[0], player[1], self.sym, player[2])) + print >>fh, _("Seat %s: %s (%s%s in chips)" %(player[0], player[1], self.sym, player[2])) if 'ANTES' in self.actions: for act in self.actions['ANTES']: @@ -1202,7 +1188,7 @@ Add a complete on [street] by [player] to [amountTo] print >>fh, _("*** SUMMARY ***") print >>fh, "%s | Rake %s%.2f" % (self.pot, self.sym, self.rake) - #print >>fh, _("Total pot $%s | Rake $%.2f" % (self.totalpot, self.rake)) # TODO: side pots +# TODO: side pots board = [] for s in self.board.values(): From d8df3ea11ad75c5226c250d6ec094072cd14adf6 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 16 Jul 2009 11:46:52 +0800 Subject: [PATCH 106/143] Possible fix for 2.6 versions of Matplotlib Long standing issue with multiple plots being added to a single canvas. Calling canvas.draw() appears to be the "correct" way to do this in pythin 2.6 Need someone to test if this still works in python 2.5 --- pyfpdb/GuiGraphViewer.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index e3f08b75..c52ebe1d 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -126,11 +126,12 @@ class GuiGraphViewer (threading.Thread): #end def get_vbox def clearGraphData(self): - self.fig.clf() + self.fig.clear() if self.canvas is not None: self.canvas.destroy() - self.canvas = FigureCanvas(self.fig) # a gtk.DrawingArea + if self.canvas == None: + self.canvas = FigureCanvas(self.fig) # a gtk.DrawingArea def generateGraph(self, widget, data): self.clearGraphData() @@ -197,6 +198,7 @@ class GuiGraphViewer (threading.Thread): self.graphBox.add(self.canvas) self.canvas.show() + self.canvas.draw() #self.exportButton.set_sensitive(True) #end of def showClicked From 2fa37813491447fd18fa02b963d65927528c115c Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 16 Jul 2009 00:54:09 -0400 Subject: [PATCH 107/143] Make euros print as $ in writeHand. --- pyfpdb/Hand.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index d4a1ca44..6355eef4 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -38,7 +38,7 @@ class Hand(object): # Class Variables UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K', 'S':'s', 'C':'c', 'H':'h', 'D':'d'} LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'} - SYMBOL = {'USD': '$', 'EUR': u'E', 'T$': '', 'play': ''} + SYMBOL = {'USD': '$', 'EUR': u'$', 'T$': '', 'play': ''} MS = {'horse' : 'HORSE', '8game' : '8-Game', 'hose' : 'HOSE'} From 0d5af4c9741f5f22a1940f6aeeb935fdead95a76 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 16 Jul 2009 12:58:39 +0800 Subject: [PATCH 108/143] Make Win2day client use updated readHeroCards api --- pyfpdb/HandHistoryConverter.py | 2 +- pyfpdb/Win2dayToFpdb.py | 31 ++++++++++++++----------------- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 16a89267..94ca5fec 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -173,6 +173,7 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py. def processHand(self, handText): gametype = self.determineGameType(handText) logging.debug("gametype %s" % gametype) + hand = None if gametype is None: l = None gametype = "unmatched" @@ -185,7 +186,6 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py. limit = gametype['limitType'] l = [type] + [base] + [limit] if l in self.readSupportedGames(): - hand = None if gametype['base'] == 'hold': logging.debug("hand = Hand.HoldemOmahaHand(self, self.sitename, gametype, handtext)") hand = Hand.HoldemOmahaHand(self, self.sitename, gametype, handText) diff --git a/pyfpdb/Win2dayToFpdb.py b/pyfpdb/Win2dayToFpdb.py index 0417dcb1..ab66ab5e 100755 --- a/pyfpdb/Win2dayToFpdb.py +++ b/pyfpdb/Win2dayToFpdb.py @@ -19,6 +19,7 @@ ######################################################################## import sys +import datetime from HandHistoryConverter import * # Win2day HH Format @@ -140,11 +141,7 @@ class Win2day(HandHistoryConverter): for key in info: if key == 'DATETIME': # Win2day uses UTC timestamp - # m2 = re.search("(?P[0-9]{4})\/(?P[0-9]{2})\/(?P[0-9]{2})[\- ]+(?P[0-9]+):(?P[0-9]+):(?P[0-9]+)", info[key]) - # datetime = "%s/%s/%s %s:%s:%s" % (m2.group('Y'), m2.group('M'),m2.group('D'),m2.group('H'),m2.group('MIN'),m2.group('S')) - # hand.starttime = time.strptime(time.gmtime(info[key])) - # hand.starttime = time.gmtime(int(info[key])) - hand.starttime = time.gmtime(int(info[key])) + hand.starttime = datetime.datetime.fromtimestamp(int(info[key])) if key == 'HID': hand.handid = info[key] if key == 'TABLE': @@ -225,18 +222,18 @@ class Win2day(HandHistoryConverter): hand.addBlind(a.group('PNAME'), 'small & big blinds', a.group('SBBB')) def readHeroCards(self, hand): - m = self.re_HeroCards.search(hand.handText) - if(m == None): - #Not involved in hand - hand.involved = False - else: +# streets PREFLOP, PREDRAW, and THIRD are special cases beacause +# we need to grab hero's cards + m = self.re_HeroCards.finditer(hand.streets['PREFLOP']) + newcards = [] + for found in m: + hand.hero = found.group('PNAME') + for card in self.re_Card.finditer(found.group('CARDS')): + print self.convertWin2dayCards(card.group('CARD')) + newcards.append(self.convertWin2dayCards(card.group('CARD'))) - hand.hero = m.group('PNAME') - holeCards = set([]) - for card in self.re_Card.finditer(m.group('CARDS')): - holeCards.add(self.convertWin2dayCards(card.group('CARD'))) - - hand.addHoleCards(holeCards, m.group('PNAME')) + #hand.addHoleCards(holeCards, m.group('PNAME')) + hand.addHoleCards('PREFLOP', hand.hero, closed=newcards, shown=False, mucked=False, dealt=True) def convertWin2dayCards(self, card): card = int(card) @@ -346,7 +343,7 @@ class Win2day(HandHistoryConverter): for shows in self.re_ShowdownAction.finditer(hand.handText): showdownCards = set([]) for card in self.re_Card.finditer(shows.group('CARDS')): - print "DEBUG:", card, card.group('CARD'), self.convertWin2dayCards(card.group('CARD')) + #print "DEBUG:", card, card.group('CARD'), self.convertWin2dayCards(card.group('CARD')) showdownCards.add(self.convertWin2dayCards(card.group('CARD'))) hand.addShownCards(showdownCards, shows.group('PNAME')) From 152f16c7a0fa928db707b1aa9a2ad97fec87c809 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 16 Jul 2009 13:54:41 +0800 Subject: [PATCH 109/143] Make euros print as $ in writeHand. fpdb_simple avoidance at the moment. --- pyfpdb/Hand.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 7d27828e..48d2c38f 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -38,7 +38,7 @@ class Hand: # Class Variables UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K', 'S':'s', 'C':'c', 'H':'h', 'D':'d'} LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'} - SYMBOL = {'USD': '$', 'EUR': u'E', 'T$': '', 'play': ''} + SYMBOL = {'USD': '$', 'EUR': u'$', 'T$': '', 'play': ''} MS = {'horse' : 'HORSE', '8game' : '8-Game', 'hose' : 'HOSE'} From 26a199635382bc31f7a792d3b1922b96aa9972a1 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 16 Jul 2009 12:13:24 -0400 Subject: [PATCH 110/143] Change Pot object to support variable currency symbol. --- pyfpdb/Hand.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 6355eef4..67f565a7 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -96,6 +96,9 @@ class Hand(object): self.totalpot = None self.totalcollected = None self.rake = None + # currency symbol for this hand + self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done + self.pot.setSym(self.sym) def __str__(self): vars = ( ("BB", self.bb), @@ -575,7 +578,6 @@ Map the tuple self.gametype onto the pokerstars string describing it def writeHand(self, fh=sys.__stdout__): # PokerStars format. - self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done print >>fh, self.writeGameLine() print >>fh, self.writeTableLine() @@ -1249,6 +1251,10 @@ class Pot(object): self.committed = {} self.total = None self.returned = {} + self.sym = u'$' # this is the default currency symbol + + def setSym(self, sym): + self.sym = sym def addPlayer(self,player): self.committed[player] = Decimal(0) @@ -1300,16 +1306,16 @@ class Pot(object): raise FpdbParseError - +# TODO: This really neeads to be a loop to handle multiple side pots if len(self.pots) == 1: # (only use Total pot) - return "Total pot $%.2f" % (self.total,) + return "Total pot %s%.2f" % (self.sym, self.total,) elif len(self.pots) == 2: - return "Total pot $%.2f Main pot $%.2f. Side pot $%2.f." % (self.total, self.pots[0], self.pots[1]) + return "Total pot %s%.2f Main pot %s%.2f. Side pot %s%2.f." % (self.sym, self.total, self.sym, self.pots[0], self.sym, self.pots[1]) elif len(self.pots) == 3: - return "Total pot $%.2f Main pot $%.2f. Side pot-1 $%2.2f. Side pot-2 $%.2f." % (self.total, self.pots[0], self.pots[1], self.pots[2]) + return "Total pot %s%.2f Main pot $%.2f. Side pot-1 %s%2.2f. Side pot-2 %s%.2f." % (self.sym, self.total, self.sym, self.pots[0], self.sym, self.pots[1], self.sym, self.pots[2]) elif len(self.pots) == 0: # no small blind and walk in bb (hopefully) - return "Total pot $%.2f" % (self.total,) + return "Total pot %s%.2f" % (self.sym, self.total,) else: return ("too many pots.. no small blind and walk in bb?. self.pots: %s" %(self.pots)) # I don't know stars format for a walk in the bb when sb doesn't post. From 61b0b8f4fe35171873300c88238b401ba349d040 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 17 Jul 2009 17:16:06 +0800 Subject: [PATCH 111/143] Prep work for inserting directly from HHC --- pyfpdb/fpdb_import.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 3129c22c..8323a790 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -83,6 +83,8 @@ class Importer: self.fdb.do_connect(self.config) self.fdb.db.rollback() + self.NEWIMPORT = False + #Set functions def setCallHud(self, value): self.callHud = value @@ -311,8 +313,16 @@ class Importer: obj = getattr(mod, filter_name, None) if callable(obj): conv = obj(in_path = file, out_path = out_path) - if(conv.getStatus()): + if(conv.getStatus() and self.NEWIMPORT == False): (stored, duplicates, partial, errors, ttime) = self.import_fpdb_file(out_path, site) + elif (conv.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() else: # conversion didn't work # TODO: appropriate response? From 34932c14eeace93d3f0e48bd1ad360ba2a4a3687 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 17 Jul 2009 17:45:22 +0800 Subject: [PATCH 112/143] Add index parameter to Plugins Change constructor to HHC to accept an index arg, so that file reads can seek --- pyfpdb/BetfairToFpdb.py | 4 ++-- pyfpdb/EverleafToFpdb.py | 4 ++-- pyfpdb/FulltiltToFpdb.py | 4 ++-- pyfpdb/HandHistoryConverter.py | 8 +++++++- pyfpdb/PokerStarsToFpdb.py | 4 ++-- pyfpdb/UltimateBetToFpdb.py | 4 ++-- pyfpdb/Win2dayToFpdb.py | 4 ++-- pyfpdb/fpdb_import.py | 2 +- 8 files changed, 20 insertions(+), 14 deletions(-) diff --git a/pyfpdb/BetfairToFpdb.py b/pyfpdb/BetfairToFpdb.py index 672e858a..1ccec5d0 100755 --- a/pyfpdb/BetfairToFpdb.py +++ b/pyfpdb/BetfairToFpdb.py @@ -34,12 +34,12 @@ class Betfair(HandHistoryConverter): re_PlayerInfo = re.compile("Seat (?P[0-9]+): (?P.*)\s\(\s(\$(?P[.0-9]+)) \)") re_Board = re.compile(ur"\[ (?P.+) \]") - def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True): + def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, index=0): """\ in_path (default '-' = sys.stdin) out_path (default '-' = sys.stdout) follow : whether to tail -f the input""" - HandHistoryConverter.__init__(self, in_path, out_path, sitename="Betfair", follow=follow) # Call super class init. + HandHistoryConverter.__init__(self, in_path, out_path, sitename="Betfair", follow=follow, index) # Call super class init. logging.info("Initialising Betfair converter class") self.filetype = "text" self.codepage = "cp1252" diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index ee4942f1..10468378 100755 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -37,7 +37,7 @@ class Everleaf(HandHistoryConverter): re_Board = re.compile(ur"\[ (?P.+) \]") - def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, debugging=False): + def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, debugging=False, index=0): """\ in_path (default '-' = sys.stdin) out_path (default '-' = sys.stdout) @@ -45,7 +45,7 @@ follow : whether to tail -f the input autostart: whether to run the thread (or you can call start() yourself) debugging: if False, pass on partially supported game types. If true, have a go and error...""" print "DEBUG: XXXXXXXXXXXXXXX" - HandHistoryConverter.__init__(self, in_path, out_path, sitename="Everleaf", follow=follow) + HandHistoryConverter.__init__(self, in_path, out_path, sitename="Everleaf", follow=follow, index=index) logging.info("Initialising Everleaf converter class") self.filetype = "text" self.codepage = "cp1252" diff --git a/pyfpdb/FulltiltToFpdb.py b/pyfpdb/FulltiltToFpdb.py index f7b834a6..173489f7 100755 --- a/pyfpdb/FulltiltToFpdb.py +++ b/pyfpdb/FulltiltToFpdb.py @@ -36,12 +36,12 @@ class Fulltilt(HandHistoryConverter): re_Board = re.compile(r"\[(?P.+)\]") # NB: if we ever match "Full Tilt Poker" we should also match "FullTiltPoker", which PT Stud erroneously exports. - def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True): + def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, index=0): """\ in_path (default '-' = sys.stdin) out_path (default '-' = sys.stdout) follow : whether to tail -f the input""" - HandHistoryConverter.__init__(self, in_path, out_path, sitename="Fulltilt", follow=follow) + HandHistoryConverter.__init__(self, in_path, out_path, sitename="Fulltilt", follow=follow, index=index) logging.info("Initialising Fulltilt converter class") self.filetype = "text" self.codepage = "cp1252" diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 94ca5fec..712260f9 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -37,12 +37,13 @@ gettext.install('fpdb') class HandHistoryConverter(): READ_CHUNK_SIZE = 10000 # bytes to read at a time from file (in tail mode) - def __init__(self, in_path = '-', out_path = '-', sitename = None, follow=False): + def __init__(self, in_path = '-', out_path = '-', sitename = None, follow=False, index=0): logging.info("HandHistory init") # default filetype and codepage. Subclasses should set these properly. self.filetype = "text" self.codepage = "utf8" + self.index = 0 self.in_path = in_path self.out_path = out_path @@ -330,7 +331,9 @@ or None if we fail to get the info """ else: logging.debug("Opening %s with %s" % (self.in_path, self.codepage)) in_fh = codecs.open(self.in_path, 'r', self.codepage) + in_fh.seek(self.index) self.obs = in_fh.read() + self.index = in_fh.tell() in_fh.close() elif(self.filetype == "xml"): try: @@ -346,3 +349,6 @@ or None if we fail to get the info """ def getProcessedFile(self): return self.out_path + + def getLastCharacterRead(self): + return self.index diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index b855586b..4e1bbf29 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -55,12 +55,12 @@ class PokerStars(HandHistoryConverter): mixes = { 'HORSE': 'horse', '8-Game': '8game', 'HOSE': 'hose'} - def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True): + def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, index=0): """\ in_path (default '-' = sys.stdin) out_path (default '-' = sys.stdout) follow : whether to tail -f the input""" - HandHistoryConverter.__init__(self, in_path, out_path, sitename="PokerStars", follow=follow) + HandHistoryConverter.__init__(self, in_path, out_path, sitename="PokerStars", follow=follow, index=index) logging.info("Initialising PokerStars converter class") self.filetype = "text" self.codepage = "cp1252" diff --git a/pyfpdb/UltimateBetToFpdb.py b/pyfpdb/UltimateBetToFpdb.py index b57e789e..cce2df4c 100755 --- a/pyfpdb/UltimateBetToFpdb.py +++ b/pyfpdb/UltimateBetToFpdb.py @@ -33,12 +33,12 @@ class UltimateBet(HandHistoryConverter): re_Board = re.compile(r"\[(?P.+)\]") # self.re_setHandInfoRegex('.*#(?P[0-9]+): Table (?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
[- a-zA-Z]+) (\((?P.+)\) )?- \$?(?P[.0-9]+)/\$?(?P[.0-9]+) (Ante \$(?P[.0-9]+) )?- (?P[a-zA-Z\' ]+) - (?P.*)') + re_HandInfo = re.compile('''.*\#(?P[0-9]+):\s + Table\s(?P
[-\sa-zA-Z]+)\s + (\((?P.+)\)\s)?-\s + \$?(?P[.0-9]+)/\$?(?P[.0-9]+)\s(Ante\s\$(?P[.0-9]+)\s)?-\s + (?P[a-zA-Z\/\'\s]+)\s-\s + (?P.*) + ''', re.VERBOSE) re_Button = re.compile('^The button is in seat #(?P
[-\sa-zA-Z]+)\s + (?:(?P.+)\s\((?P\d+)\),\s)? + Table\s(?P
[-\s\da-zA-Z]+)\s (\((?P.+)\)\s)?-\s \$?(?P[.0-9]+)/\$?(?P[.0-9]+)\s(Ante\s\$(?P[.0-9]+)\s)?-\s (?P[a-zA-Z\/\'\s]+)\s-\s (?P.*) ''', re.VERBOSE) re_Button = re.compile('^The button is in seat #(?P
[-\s\da-zA-Z]+)\s + Table\s + (?PPlay\sChip\s|PC) + (?P
[-\s\da-zA-Z]+)\s (\((?P.+)\)\s)?-\s - \$?(?P[.0-9]+)/\$?(?P[.0-9]+)\s(Ante\s\$(?P[.0-9]+)\s)?-\s + \$?(?P[.0-9]+)/\$?(?P[.0-9]+)\s(Ante\s\$?(?P[.0-9]+)\s)?-\s (?P[a-zA-Z\/\'\s]+)\s-\s (?P.*) ''', re.VERBOSE) @@ -109,7 +111,6 @@ follow : whether to tail -f the input""" m = self.re_GameInfo.search(handText) if not m: return None - mg = m.groupdict() # translations from captured groups to our info strings @@ -119,8 +120,8 @@ follow : whether to tail -f the input""" 'Omaha Hi' : ('hold','omahahi'), 'Omaha H/L' : ('hold','omahahilo'), 'Razz' : ('stud','razz'), - '7 Card Stud' : ('stud','studhi'), - 'Stud H/L' : ('stud', 'studhilo') + 'Stud Hi' : ('stud','studhi'), + 'Stud H/L' : ('stud','studhilo') } currencies = { u' €':'EUR', '$':'USD', '':'T$' } info['limitType'] = limits[mg['LIMIT']] @@ -137,7 +138,7 @@ follow : whether to tail -f the input""" def readHandInfo(self, hand): m = self.re_HandInfo.search(hand.handText,re.DOTALL) - + print "m =", m.groupdict() if(m == None): logging.info("Didn't match re_HandInfo") logging.info(hand.handText) @@ -150,8 +151,8 @@ follow : whether to tail -f the input""" hand.maxseats = int(m2.group(2)) hand.tourNo = m.group('TOURNO') -# if key == 'PLAY' and info['PLAY'] != None: -# hand.gametype['currency'] = 'play' + if m.group('PLAY') != None: + hand.gametype['currency'] = 'play' # These work, but the info is already in the Hand class - should be used for tourneys though. # m.group('SB') @@ -214,6 +215,7 @@ follow : whether to tail -f the input""" m = self.re_Antes.finditer(hand.handText) for player in m: logging.debug("hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE'))) +# if player.group() != hand.addAnte(player.group('PNAME'), player.group('ANTE')) def readBringIn(self, hand): From 9d803957cb7638b1ad775ad6193f27c7f8e7af4f Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 22 Jul 2009 10:24:29 -0400 Subject: [PATCH 133/143] Detect mixed games in FTP HH. Fix typos. --- pyfpdb/FulltiltToFpdb.py | 11 ++++++++++- pyfpdb/Hand.py | 3 ++- pyfpdb/HandHistoryConverter.py | 7 ++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/pyfpdb/FulltiltToFpdb.py b/pyfpdb/FulltiltToFpdb.py index b860fe94..be3b6ba5 100755 --- a/pyfpdb/FulltiltToFpdb.py +++ b/pyfpdb/FulltiltToFpdb.py @@ -42,7 +42,7 @@ class Fulltilt(HandHistoryConverter): re_HandInfo = re.compile('''.*\#(?P[0-9]+):\s (?:(?P.+)\s\((?P\d+)\),\s)? Table\s - (?PPlay\sChip\s|PC) + (?PPlay\sChip\s|PC)? (?P
[-\s\da-zA-Z]+)\s (\((?P.+)\)\s)?-\s \$?(?P[.0-9]+)/\$?(?P[.0-9]+)\s(Ante\s\$?(?P[.0-9]+)\s)?-\s @@ -52,8 +52,11 @@ class Fulltilt(HandHistoryConverter): re_Button = re.compile('^The button is in seat #(?P