From 2da6e44a75c803ac45c73a8e23c35e90edddc01c Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Mon, 23 Nov 2009 19:29:56 -0500 Subject: [PATCH 001/251] Changes for improved logging. --- pyfpdb/Configuration.py | 63 +++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 3f183204..3e3c00a3 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -58,29 +58,29 @@ def get_exec_path(): return os.path.dirname(sys.path[0]) def get_config(file_name, fallback = True): - """Looks in cwd and in self.default_config_path for a config file.""" - config_path = os.path.join(get_exec_path(), file_name) - if os.path.exists(config_path): # there is a file in the cwd - return config_path # so we use it - else: # no file in the cwd, look where it should be in the first place - config_path = os.path.join(get_default_config_path(), file_name) - if os.path.exists(config_path): + """Looks in exec dir and in self.default_config_path for a config file.""" + config_path = os.path.join(DIR_SELF, file_name) # look in exec dir + if os.path.exists(config_path) and os.path.isfile(config_path): + return config_path # there is a file in the exec dir so we use it + else: + config_path = os.path.join(DIR_CONFIG, file_name) # look in config dir + if os.path.exists(config_path) and os.path.isfile(config_path): return config_path # No file found if not fallback: return False -# OK, fall back to the .example file, should be in the start dir - if os.path.exists(file_name + ".example"): +# OK, fall back to the .example file, should be in the exec dir + if os.path.exists(os.path.join(DIR_SELF, file_name + ".example")): try: - shutil.copyfile(file_name + ".example", file_name) + shutil.copyfile(os.path.join(DIR_SELF, file_name + ".example"), os.path.join(DIR_CONFIG, file_name)) print "No %s found, using %s.example.\n" % (file_name, file_name) - print "A %s file has been created. You will probably have to edit it." % file_name - sys.stderr.write("No %s found, using %s.example.\n" % (file_name, file_name) ) + print "A %s file has been created. You will probably have to edit it." % os.path.join(DIR_CONFIG, file_name) + log.error("No %s found, using %s.example.\n" % (file_name, file_name) ) except: print "No %s found, cannot fall back. Exiting.\n" % file_name - sys.stderr.write("No %s found, cannot fall back. Exiting.\n" % file_name) + log.critical("No %s found, cannot fall back. Exiting.\n" % file_name) sys.exit() return file_name @@ -90,18 +90,26 @@ def get_logger(file_name, config = "config", fallback = False): try: logging.config.fileConfig(conf) log = logging.getLogger(config) - log.debug("%s logger initialised" % config) return log except: pass log = logging.basicConfig() log = logging.getLogger() - log.debug("config logger initialised") + log.error("basicConfig logger initialised") return log -# find a logging.conf file and set up logging -log = get_logger("logging.conf") +def check_dir(path, create = True): + """Check if a dir exists, optionally creates if not.""" + if os.path.exists(path): + if os.path.isdir(path): + return path + else: + return False + if create: + print "creating directory %s" % path + else: + return False ######################################################################## # application wide consts @@ -109,19 +117,31 @@ log = get_logger("logging.conf") APPLICATION_NAME_SHORT = 'fpdb' APPLICATION_VERSION = 'xx.xx.xx' -DIR_SELF = os.path.dirname(get_exec_path()) -#TODO: imo no good idea to place 'database' in parent dir -DIR_DATABASES = os.path.join(os.path.dirname(DIR_SELF), 'database') +DIR_SELF = get_exec_path() +DIR_CONFIG = check_dir(get_default_config_path()) +DIR_DATABASE = check_dir(os.path.join(DIR_CONFIG, 'database')) +DIR_LOG = check_dir(os.path.join(DIR_CONFIG, 'log')) DATABASE_TYPE_POSTGRESQL = 'postgresql' DATABASE_TYPE_SQLITE = 'sqlite' DATABASE_TYPE_MYSQL = 'mysql' +#TODO: should this be a tuple or a dict DATABASE_TYPES = ( DATABASE_TYPE_POSTGRESQL, DATABASE_TYPE_SQLITE, DATABASE_TYPE_MYSQL, ) +# find a logging.conf file and set up logging +log = get_logger("logging.conf", config = "config") +log.debug("config logger initialised") + +# and then log our consts +log.info("DIR SELF = %s" % DIR_SELF) +log.info("DIR CONFIG = %s" % DIR_CONFIG) +log.info("DIR DATABASE = %s" % DIR_DATABASE) +log.info("DIR LOG = %s" % DIR_LOG) + ######################################################################## def string_to_bool(string, default=True): """converts a string representation of a boolean value to boolean True or False @@ -398,8 +418,7 @@ class Config: if file is not None: # config file path passed in 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)) + log.error("Specified configuration file %s not found. Using defaults." % (file)) file = None if file is None: file = get_config("HUD_config.xml") From bdc3248597261ba97cc015371f2a974e4c49f407 Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Mon, 23 Nov 2009 19:32:19 -0500 Subject: [PATCH 002/251] Changes for new logging scheme. --- pyfpdb/Database.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 0314d78d..d2fb5651 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -45,7 +45,8 @@ import Card import Tourney from Exceptions import * -log = Configuration.get_logger("logging.conf") +log = Configuration.get_logger("logging.conf", config = "db") +log.debug("db logger initialized.") class Database: @@ -186,14 +187,13 @@ class Database: self.config = c self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql self.do_connect(c) - + print "connection =", self.connection if self.backend == self.PGSQL: from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT, ISOLATION_LEVEL_READ_COMMITTED, ISOLATION_LEVEL_SERIALIZABLE #ISOLATION_LEVEL_AUTOCOMMIT = 0 #ISOLATION_LEVEL_READ_COMMITTED = 1 #ISOLATION_LEVEL_SERIALIZABLE = 2 - # where possible avoid creating new SQL instance by using the global one passed in if sql is None: self.sql = SQL.Sql(db_server = self.db_server) From ad91c0a5268fe6dfdd8492d7c5f9cbf1ba70db80 Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Mon, 23 Nov 2009 19:34:40 -0500 Subject: [PATCH 003/251] Changes for logging. --- pyfpdb/HUD_main.py | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index 48a412ee..4b8b2eaa 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -36,9 +36,7 @@ import traceback (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_." - errorFile = open('HUD-error.txt', 'w', 0) - sys.stderr = errorFile + print "Note: error output is being logged. Any major error will be reported there _only_." import thread import time @@ -52,6 +50,13 @@ import gobject # FreePokerTools modules import Configuration + +print "start logging" +log = Configuration.get_logger("logging.conf", config = 'hud') +log.debug("%s logger initialized." % "dud") +print "logging started" + + import Database from HandHistoryConverter import getTableTitleRe # get the correct module for the current os @@ -97,6 +102,7 @@ class HUD_main(object): def __init__(self, db_name = 'fpdb'): self.db_name = db_name + self.log = log self.config = Configuration.Config(file=options.config, dbname=options.dbname) self.hud_dict = {} self.hud_params = self.config.get_hud_ui_parameters() @@ -116,6 +122,7 @@ class HUD_main(object): self.main_window.show_all() def destroy(self, *args): # call back for terminating the main eventloop + self.log.info("Terminating normally.") gtk.main_quit() def kill_hud(self, event, table): @@ -180,11 +187,11 @@ class HUD_main(object): # function idle_func() to be run by the gui thread, at its leisure. def idle_func(): gtk.gdk.threads_enter() -# try: - self.hud_dict[table_name].update(new_hand_id, config) - [aw.update_gui(new_hand_id) for aw in self.hud_dict[table_name].aux_windows] -# finally: - gtk.gdk.threads_leave() + try: + self.hud_dict[table_name].update(new_hand_id, config) + [aw.update_gui(new_hand_id) for aw in self.hud_dict[table_name].aux_windows] + finally: + gtk.gdk.threads_leave() return False gobject.idle_add(idle_func) @@ -197,7 +204,6 @@ class HUD_main(object): # need their own access to the database, but should open their own # if it is required. self.db_connection = Database.Database(self.config) - # get hero's screen names and player ids self.hero, self.hero_ids = {}, {} for site in self.config.get_supported_sites(): @@ -206,10 +212,11 @@ class HUD_main(object): site_id = result[0][0] self.hero[site_id] = self.config.supported_sites[site].screen_name self.hero_ids[site_id] = self.db_connection.get_player_id(self.config, site, self.hero[site_id]) - + while 1: # wait for a new hand number on stdin new_hand_id = sys.stdin.readline() new_hand_id = string.rstrip(new_hand_id) + self.log.debug("Received hand no %s" % new_hand_id) if new_hand_id == "": # blank line means quit self.destroy() break # this thread is not always killed immediately with gtk.main_quit() @@ -220,8 +227,7 @@ class HUD_main(object): (table_name, max, poker_game, type, site_id, site_name, tour_number, tab_number) = \ self.db_connection.get_table_info(new_hand_id) except Exception, err: - print "db error: skipping %s" % new_hand_id - sys.stderr.write("Database error: could not find hand %s.\n" % new_hand_id) + self.log.error("db error: skipping %s" % new_hand_id) continue if type == "tour": # hand is from a tournament @@ -262,7 +268,8 @@ class HUD_main(object): # If no client window is found on the screen, complain and continue if type == "tour": table_name = "%s %s" % (tour_number, tab_number) - sys.stderr.write("HUD create: table name "+table_name+" not found, skipping.\n") +# sys.stderr.write("HUD create: table name "+table_name+" not found, skipping.\n") + self.log.error("HUD create: table name %s not found, skipping." % table_name) else: tablewindow.max = max tablewindow.site = site_name @@ -271,8 +278,8 @@ class HUD_main(object): if __name__== "__main__": - sys.stderr.write("HUD_main starting\n") - sys.stderr.write("Using db name = %s\n" % (options.dbname)) + log.info("HUD_main starting") + log.info("Using db name = %s" % (options.dbname)) # start the HUD_main object hm = HUD_main(db_name = options.dbname) From 3e76033cd5ba2e18c4e155a201062b3a774ddd51 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Sun, 29 Nov 2009 11:21:11 +0200 Subject: [PATCH 004/251] Do not minimize window when workspace changes When we have the systray icon enabled, any window visibility event seems to have WINDOW_STATE_ICONIFIED bit on. By checking both _ICONIFIED and _WITHDRAWN the behaviour appears nicer. --- pyfpdb/fpdb.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 80d3fb93..77f13ca7 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -669,8 +669,8 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") sys.stderr.write("fpdb starting ...") def window_state_event_cb(self, window, event): - print "window_state_event", event - if event.changed_mask & gtk.gdk.WINDOW_STATE_ICONIFIED: + print "window_state_event: %s, mask=%s" % (event, event.changed_mask) + if event.changed_mask & gtk.gdk.WINDOW_STATE_ICONIFIED & gtk.gdk.WINDOW_STATE_WITHDRAWN: # -20 = GWL_EXSTYLE can't find it in the pywin32 libs #bits = win32api.GetWindowLong(self.window.window.handle, -20) #bits = bits ^ (win32con.WS_EX_TOOLWINDOW | win32con.WS_EX_APPWINDOW) From 761d53f2f44b3dd50a1eac7ac17f70feb4539da1 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Wed, 2 Dec 2009 18:38:58 +0200 Subject: [PATCH 005/251] Revert "Use wider try-except block" This reverts commit 2f742e371be64964fe9499824901c71f0509601c. --- pyfpdb/HUD_main.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index 4f7e8845..39096065 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -215,10 +215,10 @@ class HUD_main(object): # Update an existing HUD if temp_key in self.hud_dict: # get stats using hud's specific params and get cards - try: - self.db_connection.init_hud_stat_vars( self.hud_dict[temp_key].hud_params['hud_days'] + self.db_connection.init_hud_stat_vars( self.hud_dict[temp_key].hud_params['hud_days'] , self.hud_dict[temp_key].hud_params['h_hud_days']) - stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_dict[temp_key].hud_params, self.hero_ids[site_id]) + stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_dict[temp_key].hud_params, self.hero_ids[site_id]) + try: self.hud_dict[temp_key].stat_dict = stat_dict except KeyError: # HUD instance has been killed off, key is stale sys.stderr.write('hud_dict[%s] was not found\n' % temp_key) From 3e9353e3b9816aa36705c46c97b3f6a023e9cace Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Wed, 2 Dec 2009 18:39:06 +0200 Subject: [PATCH 006/251] Revert "Revert "Use wider try-except block"" This reverts commit 761d53f2f44b3dd50a1eac7ac17f70feb4539da1. --- pyfpdb/HUD_main.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index 39096065..4f7e8845 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -215,10 +215,10 @@ class HUD_main(object): # Update an existing HUD if temp_key in self.hud_dict: # get stats using hud's specific params and get cards - self.db_connection.init_hud_stat_vars( self.hud_dict[temp_key].hud_params['hud_days'] - , self.hud_dict[temp_key].hud_params['h_hud_days']) - stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_dict[temp_key].hud_params, self.hero_ids[site_id]) try: + self.db_connection.init_hud_stat_vars( self.hud_dict[temp_key].hud_params['hud_days'] + , self.hud_dict[temp_key].hud_params['h_hud_days']) + stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_dict[temp_key].hud_params, self.hero_ids[site_id]) self.hud_dict[temp_key].stat_dict = stat_dict except KeyError: # HUD instance has been killed off, key is stale sys.stderr.write('hud_dict[%s] was not found\n' % temp_key) From 87a8d57669343ebcfd78bd722d3973793566281a Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Wed, 2 Dec 2009 18:39:58 +0200 Subject: [PATCH 007/251] Revert "Do not minimize window when workspace changes" This reverts commit 3e76033cd5ba2e18c4e155a201062b3a774ddd51. --- pyfpdb/fpdb.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 77f13ca7..80d3fb93 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -669,8 +669,8 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") sys.stderr.write("fpdb starting ...") def window_state_event_cb(self, window, event): - print "window_state_event: %s, mask=%s" % (event, event.changed_mask) - if event.changed_mask & gtk.gdk.WINDOW_STATE_ICONIFIED & gtk.gdk.WINDOW_STATE_WITHDRAWN: + print "window_state_event", event + if event.changed_mask & gtk.gdk.WINDOW_STATE_ICONIFIED: # -20 = GWL_EXSTYLE can't find it in the pywin32 libs #bits = win32api.GetWindowLong(self.window.window.handle, -20) #bits = bits ^ (win32con.WS_EX_TOOLWINDOW | win32con.WS_EX_APPWINDOW) From e62ae6c31ff2d35277f7c89ac90d9e1e8db8110b Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Sun, 6 Dec 2009 14:08:27 +0200 Subject: [PATCH 008/251] Enclose dict key lookup in try-except block Some recent changes moved the dictionary access outside try-except block again. Widen the block enough again. --- pyfpdb/HUD_main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index 7e2d5fa6..108b89c7 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -159,10 +159,10 @@ class HUD_main(object): # function idle_func() to be run by the gui thread, at its leisure. def idle_func(): gtk.gdk.threads_enter() - self.hud_dict[table_name].update(new_hand_id, config) + try: + self.hud_dict[table_name].update(new_hand_id, config) # The HUD could get destroyed in the above call ^^, which leaves us with a KeyError here vv # if we ever get an error we need to expect ^^ then we need to handle it vv - Eric - try: [aw.update_gui(new_hand_id) for aw in self.hud_dict[table_name].aux_windows] except KeyError: pass From 5e7bd33cd03ce567f68af774d6806d5bf146b37b Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Tue, 8 Dec 2009 17:48:52 -0500 Subject: [PATCH 009/251] no changes here --- .../Flop/PLO8-6max-USD-0.01-0.02-200911.txt | 1204 ++++++++--------- ...7-StudHL-USD-0.04-0.08-200911.Cardtest.txt | 192 +-- pyfpdb/test1.py | 58 +- pyfpdb/test2.py | 114 +- 4 files changed, 784 insertions(+), 784 deletions(-) diff --git a/pyfpdb/regression-test-files/cash/Stars/Flop/PLO8-6max-USD-0.01-0.02-200911.txt b/pyfpdb/regression-test-files/cash/Stars/Flop/PLO8-6max-USD-0.01-0.02-200911.txt index fb96f3f9..dbe2a5bf 100644 --- a/pyfpdb/regression-test-files/cash/Stars/Flop/PLO8-6max-USD-0.01-0.02-200911.txt +++ b/pyfpdb/regression-test-files/cash/Stars/Flop/PLO8-6max-USD-0.01-0.02-200911.txt @@ -1,602 +1,602 @@ -PokerStars Game #35874998500: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:36:51 ET -Table 'Gaby II' 6-max Seat #3 is the button -Seat 1: EricSteph261 ($11.27 in chips) -Seat 2: UnderMeSensi ($3.33 in chips) -Seat 3: supermeXXX ($1.19 in chips) -Seat 4: xgz520 ($1.81 in chips) -Seat 5: s0rrow ($3 in chips) -Seat 6: tiger48475 ($5 in chips) -xgz520: posts small blind $0.01 -s0rrow: posts big blind $0.02 -*** HOLE CARDS *** -Dealt to s0rrow [2h 2c 3s 9h] -tiger48475: folds -EricSteph261: folds -UnderMeSensi: raises $0.05 to $0.07 -supermeXXX: folds -xgz520: folds -s0rrow: calls $0.05 -*** FLOP *** [Jd 5c Kc] -s0rrow: checks -UnderMeSensi: checks -*** TURN *** [Jd 5c Kc] [4c] -s0rrow: checks -UnderMeSensi: bets $0.08 -s0rrow: calls $0.08 -*** RIVER *** [Jd 5c Kc 4c] [Th] -s0rrow: checks -UnderMeSensi: bets $0.31 -EricSteph261 is sitting out -s0rrow: folds -Uncalled bet ($0.31) returned to UnderMeSensi -UnderMeSensi collected $0.31 from pot -UnderMeSensi: doesn't show hand -*** SUMMARY *** -Total pot $0.31 | Rake $0 -Board [Jd 5c Kc 4c Th] -Seat 1: EricSteph261 folded before Flop (didn't bet) -Seat 2: UnderMeSensi collected ($0.31) -Seat 3: supermeXXX (button) folded before Flop (didn't bet) -Seat 4: xgz520 (small blind) folded before Flop -Seat 5: s0rrow (big blind) folded on the River -Seat 6: tiger48475 folded before Flop (didn't bet) - - - -PokerStars Game #35875026976: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:37:39 ET -Table 'Gaby II' 6-max Seat #4 is the button -Seat 2: UnderMeSensi ($3.49 in chips) -Seat 3: supermeXXX ($1.19 in chips) -Seat 4: xgz520 ($1.80 in chips) -Seat 5: s0rrow ($2.85 in chips) -Seat 6: tiger48475 ($5 in chips) -s0rrow: posts small blind $0.01 -tiger48475: posts big blind $0.02 -*** HOLE CARDS *** -Dealt to s0rrow [4d 3s 8d Jd] -UnderMeSensi: raises $0.05 to $0.07 -supermeXXX: folds -xgz520: folds -s0rrow: folds -tiger48475: folds -Uncalled bet ($0.05) returned to UnderMeSensi -xgz520 leaves the table -UnderMeSensi collected $0.05 from pot -UnderMeSensi: doesn't show hand -*** SUMMARY *** -Total pot $0.05 | Rake $0 -Seat 2: UnderMeSensi collected ($0.05) -Seat 3: supermeXXX folded before Flop (didn't bet) -Seat 4: xgz520 (button) folded before Flop (didn't bet) -Seat 5: s0rrow (small blind) folded before Flop -Seat 6: tiger48475 (big blind) folded before Flop - - - -PokerStars Game #35875034981: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:37:53 ET -Table 'Gaby II' 6-max Seat #5 is the button -Seat 2: UnderMeSensi ($3.52 in chips) -Seat 3: supermeXXX ($1.19 in chips) -Seat 5: s0rrow ($2.84 in chips) -Seat 6: tiger48475 ($5 in chips) -tiger48475: posts small blind $0.01 -UnderMeSensi: posts big blind $0.02 -*** HOLE CARDS *** -Dealt to s0rrow [Qh 6c Th 9c] -supermeXXX: raises $0.04 to $0.06 -s0rrow: calls $0.06 -tiger48475: folds -UnderMeSensi: calls $0.04 -*** FLOP *** [5h 4d 2d] -UnderMeSensi: checks -supermeXXX: bets $0.10 -s0rrow: folds -UnderMeSensi: calls $0.10 -*** TURN *** [5h 4d 2d] [Jd] -UnderMeSensi: checks -supermeXXX: checks -*** RIVER *** [5h 4d 2d Jd] [6h] -UnderMeSensi: checks -supermeXXX: checks -*** SHOW DOWN *** -UnderMeSensi: shows [7c 6s 7h As] (HI: a pair of Sevens; LO: 6,5,4,2,A) -supermeXXX: shows [Ah 2h Kh 2s] (HI: three of a kind, Deuces; LO: 6,5,4,2,A) -supermeXXX collected $0.20 from pot -UnderMeSensi collected $0.10 from pot -supermeXXX collected $0.09 from pot -*** SUMMARY *** -Total pot $0.39 | Rake $0 -Board [5h 4d 2d Jd 6h] -Seat 2: UnderMeSensi (big blind) showed [7c 6s 7h As] and won ($0.10) with HI: a pair of Sevens; LO: 6,5,4,2,A -Seat 3: supermeXXX showed [Ah 2h Kh 2s] and won ($0.29) with HI: three of a kind, Deuces; LO: 6,5,4,2,A -Seat 5: s0rrow (button) folded on the Flop -Seat 6: tiger48475 (small blind) folded before Flop - - - -PokerStars Game #35875059163: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:38:34 ET -Table 'Gaby II' 6-max Seat #6 is the button -Seat 2: UnderMeSensi ($3.46 in chips) -Seat 3: supermeXXX ($1.32 in chips) -Seat 5: s0rrow ($2.78 in chips) -Seat 6: tiger48475 ($5 in chips) -UnderMeSensi: posts small blind $0.01 -supermeXXX: posts big blind $0.02 -*** HOLE CARDS *** -Dealt to s0rrow [Ts Qs 9d 7c] -s0rrow: raises $0.04 to $0.06 -tiger48475: folds -UnderMeSensi: calls $0.05 -diyi69 joins the table at seat #4 -supermeXXX: folds -*** FLOP *** [3h Ah 5d] -UnderMeSensi: checks -s0rrow: checks -*** TURN *** [3h Ah 5d] [Kc] -UnderMeSensi: checks -s0rrow: bets $0.14 -UnderMeSensi: folds -Uncalled bet ($0.14) returned to s0rrow -s0rrow collected $0.14 from pot -*** SUMMARY *** -Total pot $0.14 | Rake $0 -Board [3h Ah 5d Kc] -Seat 2: UnderMeSensi (small blind) folded on the Turn -Seat 3: supermeXXX (big blind) folded before Flop -Seat 5: s0rrow collected ($0.14) -Seat 6: tiger48475 (button) folded before Flop (didn't bet) - - - -PokerStars Game #35875079294: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:39:09 ET -Table 'Gaby II' 6-max Seat #2 is the button -Seat 2: UnderMeSensi ($3.40 in chips) -Seat 3: supermeXXX ($1.30 in chips) -Seat 4: diyi69 ($1 in chips) -Seat 5: s0rrow ($2.86 in chips) -Seat 6: tiger48475 ($5 in chips) -supermeXXX: posts small blind $0.01 -diyi69: posts big blind $0.02 -*** HOLE CARDS *** -Dealt to s0rrow [8s 6d 7s 2s] -s0rrow: folds -tiger48475: folds -UnderMeSensi: folds -supermeXXX: calls $0.01 -diyi69 has timed out -diyi69: checks -*** FLOP *** [As Js 5h] -supermeXXX: bets $0.04 -diyi69 has timed out -diyi69: folds -Uncalled bet ($0.04) returned to supermeXXX -diyi69 is sitting out -supermeXXX collected $0.04 from pot -*** SUMMARY *** -Total pot $0.04 | Rake $0 -Board [As Js 5h] -Seat 2: UnderMeSensi (button) folded before Flop (didn't bet) -Seat 3: supermeXXX (small blind) collected ($0.04) -Seat 4: diyi69 (big blind) folded on the Flop -Seat 5: s0rrow folded before Flop (didn't bet) -Seat 6: tiger48475 folded before Flop (didn't bet) - - - -PokerStars Game #35875131707: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:40:40 ET -Table 'Gaby II' 6-max Seat #3 is the button -Seat 2: UnderMeSensi ($3.40 in chips) -Seat 3: supermeXXX ($1.32 in chips) -Seat 5: s0rrow ($2.86 in chips) -Seat 6: tiger48475 ($5 in chips) -s0rrow: posts small blind $0.01 -tiger48475: posts big blind $0.02 -*** HOLE CARDS *** -Dealt to s0rrow [7c As 4d 4h] -UnderMeSensi: calls $0.02 -supermeXXX: folds -s0rrow: calls $0.01 -tiger48475: checks -*** FLOP *** [Ks 9d Ts] -s0rrow: checks -tiger48475: bets $0.06 -UnderMeSensi: calls $0.06 -s0rrow: folds -*** TURN *** [Ks 9d Ts] [7h] -tiger48475: checks -EricSteph261 has returned -UnderMeSensi: checks -*** RIVER *** [Ks 9d Ts 7h] [4s] -tiger48475: checks -UnderMeSensi: bets $0.10 -tiger48475: folds -Uncalled bet ($0.10) returned to UnderMeSensi -UnderMeSensi collected $0.18 from pot -UnderMeSensi: doesn't show hand -*** SUMMARY *** -Total pot $0.18 | Rake $0 -Board [Ks 9d Ts 7h 4s] -Seat 2: UnderMeSensi collected ($0.18) -Seat 3: supermeXXX (button) folded before Flop (didn't bet) -Seat 5: s0rrow (small blind) folded on the Flop -Seat 6: tiger48475 (big blind) folded on the River - - - -PokerStars Game #35875159084: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:41:27 ET -Table 'Gaby II' 6-max Seat #5 is the button -Seat 1: EricSteph261 ($11.27 in chips) -Seat 2: UnderMeSensi ($3.50 in chips) -Seat 3: supermeXXX ($1.32 in chips) -Seat 5: s0rrow ($2.84 in chips) -Seat 6: tiger48475 ($5 in chips) -tiger48475: posts small blind $0.01 -EricSteph261: posts big blind $0.02 -*** HOLE CARDS *** -Dealt to s0rrow [Jc 3h 2s Qc] -UnderMeSensi: calls $0.02 -supermeXXX: calls $0.02 -s0rrow: raises $0.08 to $0.10 -tiger48475: folds -EricSteph261: folds -UnderMeSensi: calls $0.08 -supermeXXX: folds -*** FLOP *** [Ac 5s Js] -UnderMeSensi: checks -s0rrow: bets $0.20 -UnderMeSensi: calls $0.20 -*** TURN *** [Ac 5s Js] [8c] -UnderMeSensi: checks -s0rrow: bets $0.50 -UnderMeSensi: calls $0.50 -*** RIVER *** [Ac 5s Js 8c] [Jd] -UnderMeSensi: bets $1.60 -s0rrow: calls $1.60 -*** SHOW DOWN *** -UnderMeSensi: shows [7s 9s Jh 3c] (HI: three of a kind, Jacks; LO: 8,7,5,3,A) -s0rrow: shows [Jc 3h 2s Qc] (HI: three of a kind, Jacks - Ace+Queen kicker; LO: 8,5,3,2,A) -s0rrow collected $2.33 from pot -s0rrow collected $2.32 from pot -*** SUMMARY *** -Total pot $4.85 | Rake $0.20 -Board [Ac 5s Js 8c Jd] -Seat 1: EricSteph261 (big blind) folded before Flop -Seat 2: UnderMeSensi showed [7s 9s Jh 3c] and lost with HI: three of a kind, Jacks; LO: 8,7,5,3,A -Seat 3: supermeXXX folded before Flop -Seat 5: s0rrow (button) showed [Jc 3h 2s Qc] and won ($4.65) with HI: three of a kind, Jacks; LO: 8,5,3,2,A -Seat 6: tiger48475 (small blind) folded before Flop - - - -PokerStars Game #35875194885: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:42:28 ET -Table 'Gaby II' 6-max Seat #6 is the button -Seat 1: EricSteph261 ($11.25 in chips) -Seat 2: UnderMeSensi ($1.10 in chips) -Seat 3: supermeXXX ($1.30 in chips) -Seat 5: s0rrow ($5.09 in chips) -Seat 6: tiger48475 ($5 in chips) -EricSteph261: posts small blind $0.01 -UnderMeSensi: posts big blind $0.02 -*** HOLE CARDS *** -Dealt to s0rrow [7s 3c 3h 8d] -supermeXXX: folds -s0rrow: raises $0.02 to $0.04 -tiger48475: calls $0.04 -EricSteph261: calls $0.03 -UnderMeSensi: calls $0.02 -*** FLOP *** [8c 3s 4s] -EricSteph261: checks -UnderMeSensi: checks -s0rrow: bets $0.14 -tiger48475: folds -EricSteph261: folds -UnderMeSensi: folds -Uncalled bet ($0.14) returned to s0rrow -s0rrow collected $0.16 from pot -*** SUMMARY *** -Total pot $0.16 | Rake $0 -Board [8c 3s 4s] -Seat 1: EricSteph261 (small blind) folded on the Flop -Seat 2: UnderMeSensi (big blind) folded on the Flop -Seat 3: supermeXXX folded before Flop (didn't bet) -Seat 5: s0rrow collected ($0.16) -Seat 6: tiger48475 (button) folded on the Flop - - - -PokerStars Game #35875219121: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:43:08 ET -Table 'Gaby II' 6-max Seat #1 is the button -Seat 1: EricSteph261 ($11.21 in chips) -Seat 2: UnderMeSensi ($1.06 in chips) -Seat 3: supermeXXX ($1.30 in chips) -Seat 5: s0rrow ($5.21 in chips) -Seat 6: tiger48475 ($5 in chips) -UnderMeSensi: posts small blind $0.01 -supermeXXX: posts big blind $0.02 -*** HOLE CARDS *** -Dealt to s0rrow [Ks Qd Kd Kc] -s0rrow: raises $0.04 to $0.06 -tiger48475: folds -EricSteph261: calls $0.06 -UnderMeSensi: calls $0.05 -supermeXXX: calls $0.04 -*** FLOP *** [2d Jh 5h] -UnderMeSensi: checks -supermeXXX: checks -s0rrow: checks -EricSteph261: checks -*** TURN *** [2d Jh 5h] [Js] -UnderMeSensi: checks -supermeXXX: checks -s0rrow: checks -EricSteph261: checks -*** RIVER *** [2d Jh 5h Js] [7s] -UnderMeSensi: checks -supermeXXX: checks -s0rrow: checks -EricSteph261: checks -*** SHOW DOWN *** -UnderMeSensi: shows [5d 6c As 9d] (HI: two pair, Jacks and Fives; LO: 7,6,5,2,A) -supermeXXX: shows [6s Th 7c Ac] (HI: two pair, Jacks and Sevens; LO: 7,6,5,2,A) -s0rrow: shows [Ks Qd Kd Kc] (HI: two pair, Kings and Jacks) -EricSteph261: shows [4s 9c 3d 2c] (HI: two pair, Jacks and Deuces; LO: 7,5,4,3,2) -s0rrow collected $0.12 from pot -EricSteph261 collected $0.12 from pot -*** SUMMARY *** -Total pot $0.24 | Rake $0 -Board [2d Jh 5h Js 7s] -Seat 1: EricSteph261 (button) showed [4s 9c 3d 2c] and won ($0.12) with HI: two pair, Jacks and Deuces; LO: 7,5,4,3,2 -Seat 2: UnderMeSensi (small blind) showed [5d 6c As 9d] and lost with HI: two pair, Jacks and Fives; LO: 7,6,5,2,A -Seat 3: supermeXXX (big blind) showed [6s Th 7c Ac] and lost with HI: two pair, Jacks and Sevens; LO: 7,6,5,2,A -Seat 5: s0rrow showed [Ks Qd Kd Kc] and won ($0.12) with HI: two pair, Kings and Jacks -Seat 6: tiger48475 folded before Flop (didn't bet) - - - -PokerStars Game #35875246335: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:43:54 ET -Table 'Gaby II' 6-max Seat #2 is the button -Seat 1: EricSteph261 ($11.27 in chips) -Seat 2: UnderMeSensi ($1 in chips) -Seat 3: supermeXXX ($1.24 in chips) -Seat 5: s0rrow ($5.27 in chips) -Seat 6: tiger48475 ($5 in chips) -supermeXXX: posts small blind $0.01 -s0rrow: posts big blind $0.02 -*** HOLE CARDS *** -Dealt to s0rrow [Jd Kc 6h Jc] -tiger48475: folds -EricSteph261: calls $0.02 -UnderMeSensi is disconnected -UnderMeSensi has timed out while disconnected -UnderMeSensi: folds -UnderMeSensi is sitting out -supermeXXX: calls $0.01 -s0rrow: checks -*** FLOP *** [8d 7s Qh] -supermeXXX: bets $0.02 -s0rrow: folds -EricSteph261: calls $0.02 -*** TURN *** [8d 7s Qh] [As] -supermeXXX: bets $0.04 -EricSteph261: calls $0.04 -*** RIVER *** [8d 7s Qh As] [5d] -supermeXXX: checks -EricSteph261: checks -*** SHOW DOWN *** -supermeXXX: shows [Kh Qd 9s Th] (HI: a pair of Queens) -EricSteph261: shows [Jh 2d 5s 6c] (HI: a pair of Fives; LO: 7,6,5,2,A) -supermeXXX collected $0.09 from pot -EricSteph261 collected $0.09 from pot -*** SUMMARY *** -Total pot $0.18 | Rake $0 -Board [8d 7s Qh As 5d] -Seat 1: EricSteph261 showed [Jh 2d 5s 6c] and won ($0.09) with HI: a pair of Fives; LO: 7,6,5,2,A -Seat 2: UnderMeSensi (button) folded before Flop (didn't bet) -Seat 3: supermeXXX (small blind) showed [Kh Qd 9s Th] and won ($0.09) with HI: a pair of Queens -Seat 5: s0rrow (big blind) folded on the Flop -Seat 6: tiger48475 folded before Flop (didn't bet) - - - -PokerStars Game #35875293439: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:45:14 ET -Table 'Gaby II' 6-max Seat #3 is the button -Seat 1: EricSteph261 ($11.28 in chips) -Seat 3: supermeXXX ($1.25 in chips) -Seat 5: s0rrow ($5.25 in chips) -Seat 6: tiger48475 ($5 in chips) -s0rrow: posts small blind $0.01 -tiger48475: posts big blind $0.02 -*** HOLE CARDS *** -Dealt to s0rrow [9c 8h 8s 3c] -EricSteph261: calls $0.02 -supermeXXX: calls $0.02 -s0rrow: calls $0.01 -tiger48475: checks -*** FLOP *** [Ah 2d Qc] -s0rrow: checks -tiger48475: checks -EricSteph261: checks -supermeXXX: checks -*** TURN *** [Ah 2d Qc] [3d] -s0rrow: checks -tiger48475: checks -EricSteph261: checks -supermeXXX: checks -*** RIVER *** [Ah 2d Qc 3d] [6s] -s0rrow: checks -tiger48475: checks -EricSteph261: checks -supermeXXX: checks -*** SHOW DOWN *** -s0rrow: shows [9c 8h 8s 3c] (HI: a pair of Eights; LO: 8,6,3,2,A) -tiger48475: shows [3s 5s Ts Th] (HI: a pair of Tens; LO: 6,5,3,2,A) -EricSteph261: shows [As Ks Jh 7h] (HI: a pair of Aces; LO: 7,6,3,2,A) -supermeXXX: mucks hand -EricSteph261 collected $0.04 from pot -tiger48475 collected $0.04 from pot -*** SUMMARY *** -Total pot $0.08 | Rake $0 -Board [Ah 2d Qc 3d 6s] -Seat 1: EricSteph261 showed [As Ks Jh 7h] and won ($0.04) with HI: a pair of Aces; LO: 7,6,3,2,A -Seat 3: supermeXXX (button) mucked [9h 9s 4c Kc] -Seat 5: s0rrow (small blind) showed [9c 8h 8s 3c] and lost with HI: a pair of Eights; LO: 8,6,3,2,A -Seat 6: tiger48475 (big blind) showed [3s 5s Ts Th] and won ($0.04) with HI: a pair of Tens; LO: 6,5,3,2,A - - - -PokerStars Game #35875328026: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:46:13 ET -Table 'Gaby II' 6-max Seat #5 is the button -Seat 1: EricSteph261 ($11.30 in chips) -Seat 3: supermeXXX ($1.23 in chips) -Seat 5: s0rrow ($5.23 in chips) -Seat 6: tiger48475 ($5.02 in chips) -tiger48475: posts small blind $0.01 -EricSteph261: posts big blind $0.02 -*** HOLE CARDS *** -Dealt to s0rrow [Qd 6h 8s 6c] -supermeXXX: calls $0.02 -s0rrow: folds -tiger48475: calls $0.01 -EricSteph261: checks -*** FLOP *** [Kc Ac 5s] -tiger48475: checks -EricSteph261: checks -supermeXXX: checks -*** TURN *** [Kc Ac 5s] [3h] -tiger48475: checks -EricSteph261: checks -supermeXXX: checks -*** RIVER *** [Kc Ac 5s 3h] [Qh] -tiger48475: bets $0.06 -EricSteph261: folds -EricSteph261 is sitting out -supermeXXX: folds -Uncalled bet ($0.06) returned to tiger48475 -tiger48475 collected $0.06 from pot -*** SUMMARY *** -Total pot $0.06 | Rake $0 -Board [Kc Ac 5s 3h Qh] -Seat 1: EricSteph261 (big blind) folded on the River -Seat 3: supermeXXX folded on the River -Seat 5: s0rrow (button) folded before Flop (didn't bet) -Seat 6: tiger48475 (small blind) collected ($0.06) - - - -PokerStars Game #35875356253: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:47:00 ET -Table 'Gaby II' 6-max Seat #6 is the button -Seat 3: supermeXXX ($1.21 in chips) -Seat 5: s0rrow ($5.23 in chips) -Seat 6: tiger48475 ($5.06 in chips) -supermeXXX: posts small blind $0.01 -s0rrow: posts big blind $0.02 -*** HOLE CARDS *** -Dealt to s0rrow [8h Jd 5d 8d] -tiger48475: folds -supermeXXX: calls $0.01 -s0rrow: checks -*** FLOP *** [Ks 9s 6c] -supermeXXX: bets $0.02 -s0rrow: calls $0.02 -*** TURN *** [Ks 9s 6c] [Qc] -supermeXXX: bets $0.02 -s0rrow: calls $0.02 -*** RIVER *** [Ks 9s 6c Qc] [Ad] -supermeXXX: checks -s0rrow: checks -*** SHOW DOWN *** -supermeXXX: shows [Tc 7d 8c 3s] (HI: high card Ace) -s0rrow: shows [8h Jd 5d 8d] (HI: a pair of Eights) -s0rrow collected $0.12 from pot -No low hand qualified -*** SUMMARY *** -Total pot $0.12 | Rake $0 -Board [Ks 9s 6c Qc Ad] -Seat 3: supermeXXX (small blind) showed [Tc 7d 8c 3s] and lost with HI: high card Ace -Seat 5: s0rrow (big blind) showed [8h Jd 5d 8d] and won ($0.12) with HI: a pair of Eights -Seat 6: tiger48475 (button) folded before Flop (didn't bet) - - - -PokerStars Game #35875379792: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:47:39 ET -Table 'Gaby II' 6-max Seat #3 is the button -Seat 3: supermeXXX ($1.15 in chips) -Seat 5: s0rrow ($5.29 in chips) -Seat 6: tiger48475 ($5.06 in chips) -s0rrow: posts small blind $0.01 -tiger48475: posts big blind $0.02 -*** HOLE CARDS *** -Dealt to s0rrow [9c 5h 3s Th] -supermeXXX: calls $0.02 -s0rrow: calls $0.01 -tiger48475: checks -*** FLOP *** [Jc 3h Jd] -s0rrow: checks -tiger48475: checks -supermeXXX: checks -*** TURN *** [Jc 3h Jd] [6d] -s0rrow: checks -tiger48475: bets $0.06 -supermeXXX: folds -EricSteph261 has returned -s0rrow: calls $0.06 -*** RIVER *** [Jc 3h Jd 6d] [5c] -s0rrow: checks -tiger48475: bets $0.14 -s0rrow: folds -Uncalled bet ($0.14) returned to tiger48475 -tiger48475 collected $0.18 from pot -*** SUMMARY *** -Total pot $0.18 | Rake $0 -Board [Jc 3h Jd 6d 5c] -Seat 3: supermeXXX (button) folded on the Turn -Seat 5: s0rrow (small blind) folded on the River -Seat 6: tiger48475 (big blind) collected ($0.18) - - - -PokerStars Game #35875409365: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:48:29 ET -Table 'Gaby II' 6-max Seat #5 is the button -Seat 1: EricSteph261 ($11.28 in chips) -Seat 3: supermeXXX ($1.13 in chips) -Seat 5: s0rrow ($5.21 in chips) -Seat 6: tiger48475 ($5.16 in chips) -tiger48475: posts small blind $0.01 -EricSteph261: posts big blind $0.02 -*** HOLE CARDS *** -Dealt to s0rrow [6h 3c Th 2s] -supermeXXX: calls $0.02 -s0rrow: calls $0.02 -tiger48475: calls $0.01 -EricSteph261 has timed out -EricSteph261: checks -*** FLOP *** [9d 5s Jh] -tiger48475: bets $0.06 -EricSteph261 has timed out -EricSteph261: folds -EricSteph261 is sitting out -supermeXXX: calls $0.06 -s0rrow: calls $0.06 -*** TURN *** [9d 5s Jh] [Ks] -tiger48475: checks -supermeXXX: bets $0.10 -s0rrow: folds -tiger48475: calls $0.10 -*** RIVER *** [9d 5s Jh Ks] [9s] -tiger48475: checks -supermeXXX: checks -*** SHOW DOWN *** -tiger48475: shows [6s 9h 9c Ad] (HI: four of a kind, Nines) -supermeXXX: mucks hand -tiger48475 collected $0.46 from pot -No low hand qualified -*** SUMMARY *** -Total pot $0.46 | Rake $0 -Board [9d 5s Jh Ks 9s] -Seat 1: EricSteph261 (big blind) folded on the Flop -Seat 3: supermeXXX mucked [Qd Tc 5h Ts] -Seat 5: s0rrow (button) folded on the Turn -Seat 6: tiger48475 (small blind) showed [6s 9h 9c Ad] and won ($0.46) with HI: four of a kind, Nines - - - +PokerStars Game #35874998500: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:36:51 ET +Table 'Gaby II' 6-max Seat #3 is the button +Seat 1: EricSteph261 ($11.27 in chips) +Seat 2: UnderMeSensi ($3.33 in chips) +Seat 3: supermeXXX ($1.19 in chips) +Seat 4: xgz520 ($1.81 in chips) +Seat 5: s0rrow ($3 in chips) +Seat 6: tiger48475 ($5 in chips) +xgz520: posts small blind $0.01 +s0rrow: posts big blind $0.02 +*** HOLE CARDS *** +Dealt to s0rrow [2h 2c 3s 9h] +tiger48475: folds +EricSteph261: folds +UnderMeSensi: raises $0.05 to $0.07 +supermeXXX: folds +xgz520: folds +s0rrow: calls $0.05 +*** FLOP *** [Jd 5c Kc] +s0rrow: checks +UnderMeSensi: checks +*** TURN *** [Jd 5c Kc] [4c] +s0rrow: checks +UnderMeSensi: bets $0.08 +s0rrow: calls $0.08 +*** RIVER *** [Jd 5c Kc 4c] [Th] +s0rrow: checks +UnderMeSensi: bets $0.31 +EricSteph261 is sitting out +s0rrow: folds +Uncalled bet ($0.31) returned to UnderMeSensi +UnderMeSensi collected $0.31 from pot +UnderMeSensi: doesn't show hand +*** SUMMARY *** +Total pot $0.31 | Rake $0 +Board [Jd 5c Kc 4c Th] +Seat 1: EricSteph261 folded before Flop (didn't bet) +Seat 2: UnderMeSensi collected ($0.31) +Seat 3: supermeXXX (button) folded before Flop (didn't bet) +Seat 4: xgz520 (small blind) folded before Flop +Seat 5: s0rrow (big blind) folded on the River +Seat 6: tiger48475 folded before Flop (didn't bet) + + + +PokerStars Game #35875026976: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:37:39 ET +Table 'Gaby II' 6-max Seat #4 is the button +Seat 2: UnderMeSensi ($3.49 in chips) +Seat 3: supermeXXX ($1.19 in chips) +Seat 4: xgz520 ($1.80 in chips) +Seat 5: s0rrow ($2.85 in chips) +Seat 6: tiger48475 ($5 in chips) +s0rrow: posts small blind $0.01 +tiger48475: posts big blind $0.02 +*** HOLE CARDS *** +Dealt to s0rrow [4d 3s 8d Jd] +UnderMeSensi: raises $0.05 to $0.07 +supermeXXX: folds +xgz520: folds +s0rrow: folds +tiger48475: folds +Uncalled bet ($0.05) returned to UnderMeSensi +xgz520 leaves the table +UnderMeSensi collected $0.05 from pot +UnderMeSensi: doesn't show hand +*** SUMMARY *** +Total pot $0.05 | Rake $0 +Seat 2: UnderMeSensi collected ($0.05) +Seat 3: supermeXXX folded before Flop (didn't bet) +Seat 4: xgz520 (button) folded before Flop (didn't bet) +Seat 5: s0rrow (small blind) folded before Flop +Seat 6: tiger48475 (big blind) folded before Flop + + + +PokerStars Game #35875034981: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:37:53 ET +Table 'Gaby II' 6-max Seat #5 is the button +Seat 2: UnderMeSensi ($3.52 in chips) +Seat 3: supermeXXX ($1.19 in chips) +Seat 5: s0rrow ($2.84 in chips) +Seat 6: tiger48475 ($5 in chips) +tiger48475: posts small blind $0.01 +UnderMeSensi: posts big blind $0.02 +*** HOLE CARDS *** +Dealt to s0rrow [Qh 6c Th 9c] +supermeXXX: raises $0.04 to $0.06 +s0rrow: calls $0.06 +tiger48475: folds +UnderMeSensi: calls $0.04 +*** FLOP *** [5h 4d 2d] +UnderMeSensi: checks +supermeXXX: bets $0.10 +s0rrow: folds +UnderMeSensi: calls $0.10 +*** TURN *** [5h 4d 2d] [Jd] +UnderMeSensi: checks +supermeXXX: checks +*** RIVER *** [5h 4d 2d Jd] [6h] +UnderMeSensi: checks +supermeXXX: checks +*** SHOW DOWN *** +UnderMeSensi: shows [7c 6s 7h As] (HI: a pair of Sevens; LO: 6,5,4,2,A) +supermeXXX: shows [Ah 2h Kh 2s] (HI: three of a kind, Deuces; LO: 6,5,4,2,A) +supermeXXX collected $0.20 from pot +UnderMeSensi collected $0.10 from pot +supermeXXX collected $0.09 from pot +*** SUMMARY *** +Total pot $0.39 | Rake $0 +Board [5h 4d 2d Jd 6h] +Seat 2: UnderMeSensi (big blind) showed [7c 6s 7h As] and won ($0.10) with HI: a pair of Sevens; LO: 6,5,4,2,A +Seat 3: supermeXXX showed [Ah 2h Kh 2s] and won ($0.29) with HI: three of a kind, Deuces; LO: 6,5,4,2,A +Seat 5: s0rrow (button) folded on the Flop +Seat 6: tiger48475 (small blind) folded before Flop + + + +PokerStars Game #35875059163: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:38:34 ET +Table 'Gaby II' 6-max Seat #6 is the button +Seat 2: UnderMeSensi ($3.46 in chips) +Seat 3: supermeXXX ($1.32 in chips) +Seat 5: s0rrow ($2.78 in chips) +Seat 6: tiger48475 ($5 in chips) +UnderMeSensi: posts small blind $0.01 +supermeXXX: posts big blind $0.02 +*** HOLE CARDS *** +Dealt to s0rrow [Ts Qs 9d 7c] +s0rrow: raises $0.04 to $0.06 +tiger48475: folds +UnderMeSensi: calls $0.05 +diyi69 joins the table at seat #4 +supermeXXX: folds +*** FLOP *** [3h Ah 5d] +UnderMeSensi: checks +s0rrow: checks +*** TURN *** [3h Ah 5d] [Kc] +UnderMeSensi: checks +s0rrow: bets $0.14 +UnderMeSensi: folds +Uncalled bet ($0.14) returned to s0rrow +s0rrow collected $0.14 from pot +*** SUMMARY *** +Total pot $0.14 | Rake $0 +Board [3h Ah 5d Kc] +Seat 2: UnderMeSensi (small blind) folded on the Turn +Seat 3: supermeXXX (big blind) folded before Flop +Seat 5: s0rrow collected ($0.14) +Seat 6: tiger48475 (button) folded before Flop (didn't bet) + + + +PokerStars Game #35875079294: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:39:09 ET +Table 'Gaby II' 6-max Seat #2 is the button +Seat 2: UnderMeSensi ($3.40 in chips) +Seat 3: supermeXXX ($1.30 in chips) +Seat 4: diyi69 ($1 in chips) +Seat 5: s0rrow ($2.86 in chips) +Seat 6: tiger48475 ($5 in chips) +supermeXXX: posts small blind $0.01 +diyi69: posts big blind $0.02 +*** HOLE CARDS *** +Dealt to s0rrow [8s 6d 7s 2s] +s0rrow: folds +tiger48475: folds +UnderMeSensi: folds +supermeXXX: calls $0.01 +diyi69 has timed out +diyi69: checks +*** FLOP *** [As Js 5h] +supermeXXX: bets $0.04 +diyi69 has timed out +diyi69: folds +Uncalled bet ($0.04) returned to supermeXXX +diyi69 is sitting out +supermeXXX collected $0.04 from pot +*** SUMMARY *** +Total pot $0.04 | Rake $0 +Board [As Js 5h] +Seat 2: UnderMeSensi (button) folded before Flop (didn't bet) +Seat 3: supermeXXX (small blind) collected ($0.04) +Seat 4: diyi69 (big blind) folded on the Flop +Seat 5: s0rrow folded before Flop (didn't bet) +Seat 6: tiger48475 folded before Flop (didn't bet) + + + +PokerStars Game #35875131707: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:40:40 ET +Table 'Gaby II' 6-max Seat #3 is the button +Seat 2: UnderMeSensi ($3.40 in chips) +Seat 3: supermeXXX ($1.32 in chips) +Seat 5: s0rrow ($2.86 in chips) +Seat 6: tiger48475 ($5 in chips) +s0rrow: posts small blind $0.01 +tiger48475: posts big blind $0.02 +*** HOLE CARDS *** +Dealt to s0rrow [7c As 4d 4h] +UnderMeSensi: calls $0.02 +supermeXXX: folds +s0rrow: calls $0.01 +tiger48475: checks +*** FLOP *** [Ks 9d Ts] +s0rrow: checks +tiger48475: bets $0.06 +UnderMeSensi: calls $0.06 +s0rrow: folds +*** TURN *** [Ks 9d Ts] [7h] +tiger48475: checks +EricSteph261 has returned +UnderMeSensi: checks +*** RIVER *** [Ks 9d Ts 7h] [4s] +tiger48475: checks +UnderMeSensi: bets $0.10 +tiger48475: folds +Uncalled bet ($0.10) returned to UnderMeSensi +UnderMeSensi collected $0.18 from pot +UnderMeSensi: doesn't show hand +*** SUMMARY *** +Total pot $0.18 | Rake $0 +Board [Ks 9d Ts 7h 4s] +Seat 2: UnderMeSensi collected ($0.18) +Seat 3: supermeXXX (button) folded before Flop (didn't bet) +Seat 5: s0rrow (small blind) folded on the Flop +Seat 6: tiger48475 (big blind) folded on the River + + + +PokerStars Game #35875159084: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:41:27 ET +Table 'Gaby II' 6-max Seat #5 is the button +Seat 1: EricSteph261 ($11.27 in chips) +Seat 2: UnderMeSensi ($3.50 in chips) +Seat 3: supermeXXX ($1.32 in chips) +Seat 5: s0rrow ($2.84 in chips) +Seat 6: tiger48475 ($5 in chips) +tiger48475: posts small blind $0.01 +EricSteph261: posts big blind $0.02 +*** HOLE CARDS *** +Dealt to s0rrow [Jc 3h 2s Qc] +UnderMeSensi: calls $0.02 +supermeXXX: calls $0.02 +s0rrow: raises $0.08 to $0.10 +tiger48475: folds +EricSteph261: folds +UnderMeSensi: calls $0.08 +supermeXXX: folds +*** FLOP *** [Ac 5s Js] +UnderMeSensi: checks +s0rrow: bets $0.20 +UnderMeSensi: calls $0.20 +*** TURN *** [Ac 5s Js] [8c] +UnderMeSensi: checks +s0rrow: bets $0.50 +UnderMeSensi: calls $0.50 +*** RIVER *** [Ac 5s Js 8c] [Jd] +UnderMeSensi: bets $1.60 +s0rrow: calls $1.60 +*** SHOW DOWN *** +UnderMeSensi: shows [7s 9s Jh 3c] (HI: three of a kind, Jacks; LO: 8,7,5,3,A) +s0rrow: shows [Jc 3h 2s Qc] (HI: three of a kind, Jacks - Ace+Queen kicker; LO: 8,5,3,2,A) +s0rrow collected $2.33 from pot +s0rrow collected $2.32 from pot +*** SUMMARY *** +Total pot $4.85 | Rake $0.20 +Board [Ac 5s Js 8c Jd] +Seat 1: EricSteph261 (big blind) folded before Flop +Seat 2: UnderMeSensi showed [7s 9s Jh 3c] and lost with HI: three of a kind, Jacks; LO: 8,7,5,3,A +Seat 3: supermeXXX folded before Flop +Seat 5: s0rrow (button) showed [Jc 3h 2s Qc] and won ($4.65) with HI: three of a kind, Jacks; LO: 8,5,3,2,A +Seat 6: tiger48475 (small blind) folded before Flop + + + +PokerStars Game #35875194885: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:42:28 ET +Table 'Gaby II' 6-max Seat #6 is the button +Seat 1: EricSteph261 ($11.25 in chips) +Seat 2: UnderMeSensi ($1.10 in chips) +Seat 3: supermeXXX ($1.30 in chips) +Seat 5: s0rrow ($5.09 in chips) +Seat 6: tiger48475 ($5 in chips) +EricSteph261: posts small blind $0.01 +UnderMeSensi: posts big blind $0.02 +*** HOLE CARDS *** +Dealt to s0rrow [7s 3c 3h 8d] +supermeXXX: folds +s0rrow: raises $0.02 to $0.04 +tiger48475: calls $0.04 +EricSteph261: calls $0.03 +UnderMeSensi: calls $0.02 +*** FLOP *** [8c 3s 4s] +EricSteph261: checks +UnderMeSensi: checks +s0rrow: bets $0.14 +tiger48475: folds +EricSteph261: folds +UnderMeSensi: folds +Uncalled bet ($0.14) returned to s0rrow +s0rrow collected $0.16 from pot +*** SUMMARY *** +Total pot $0.16 | Rake $0 +Board [8c 3s 4s] +Seat 1: EricSteph261 (small blind) folded on the Flop +Seat 2: UnderMeSensi (big blind) folded on the Flop +Seat 3: supermeXXX folded before Flop (didn't bet) +Seat 5: s0rrow collected ($0.16) +Seat 6: tiger48475 (button) folded on the Flop + + + +PokerStars Game #35875219121: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:43:08 ET +Table 'Gaby II' 6-max Seat #1 is the button +Seat 1: EricSteph261 ($11.21 in chips) +Seat 2: UnderMeSensi ($1.06 in chips) +Seat 3: supermeXXX ($1.30 in chips) +Seat 5: s0rrow ($5.21 in chips) +Seat 6: tiger48475 ($5 in chips) +UnderMeSensi: posts small blind $0.01 +supermeXXX: posts big blind $0.02 +*** HOLE CARDS *** +Dealt to s0rrow [Ks Qd Kd Kc] +s0rrow: raises $0.04 to $0.06 +tiger48475: folds +EricSteph261: calls $0.06 +UnderMeSensi: calls $0.05 +supermeXXX: calls $0.04 +*** FLOP *** [2d Jh 5h] +UnderMeSensi: checks +supermeXXX: checks +s0rrow: checks +EricSteph261: checks +*** TURN *** [2d Jh 5h] [Js] +UnderMeSensi: checks +supermeXXX: checks +s0rrow: checks +EricSteph261: checks +*** RIVER *** [2d Jh 5h Js] [7s] +UnderMeSensi: checks +supermeXXX: checks +s0rrow: checks +EricSteph261: checks +*** SHOW DOWN *** +UnderMeSensi: shows [5d 6c As 9d] (HI: two pair, Jacks and Fives; LO: 7,6,5,2,A) +supermeXXX: shows [6s Th 7c Ac] (HI: two pair, Jacks and Sevens; LO: 7,6,5,2,A) +s0rrow: shows [Ks Qd Kd Kc] (HI: two pair, Kings and Jacks) +EricSteph261: shows [4s 9c 3d 2c] (HI: two pair, Jacks and Deuces; LO: 7,5,4,3,2) +s0rrow collected $0.12 from pot +EricSteph261 collected $0.12 from pot +*** SUMMARY *** +Total pot $0.24 | Rake $0 +Board [2d Jh 5h Js 7s] +Seat 1: EricSteph261 (button) showed [4s 9c 3d 2c] and won ($0.12) with HI: two pair, Jacks and Deuces; LO: 7,5,4,3,2 +Seat 2: UnderMeSensi (small blind) showed [5d 6c As 9d] and lost with HI: two pair, Jacks and Fives; LO: 7,6,5,2,A +Seat 3: supermeXXX (big blind) showed [6s Th 7c Ac] and lost with HI: two pair, Jacks and Sevens; LO: 7,6,5,2,A +Seat 5: s0rrow showed [Ks Qd Kd Kc] and won ($0.12) with HI: two pair, Kings and Jacks +Seat 6: tiger48475 folded before Flop (didn't bet) + + + +PokerStars Game #35875246335: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:43:54 ET +Table 'Gaby II' 6-max Seat #2 is the button +Seat 1: EricSteph261 ($11.27 in chips) +Seat 2: UnderMeSensi ($1 in chips) +Seat 3: supermeXXX ($1.24 in chips) +Seat 5: s0rrow ($5.27 in chips) +Seat 6: tiger48475 ($5 in chips) +supermeXXX: posts small blind $0.01 +s0rrow: posts big blind $0.02 +*** HOLE CARDS *** +Dealt to s0rrow [Jd Kc 6h Jc] +tiger48475: folds +EricSteph261: calls $0.02 +UnderMeSensi is disconnected +UnderMeSensi has timed out while disconnected +UnderMeSensi: folds +UnderMeSensi is sitting out +supermeXXX: calls $0.01 +s0rrow: checks +*** FLOP *** [8d 7s Qh] +supermeXXX: bets $0.02 +s0rrow: folds +EricSteph261: calls $0.02 +*** TURN *** [8d 7s Qh] [As] +supermeXXX: bets $0.04 +EricSteph261: calls $0.04 +*** RIVER *** [8d 7s Qh As] [5d] +supermeXXX: checks +EricSteph261: checks +*** SHOW DOWN *** +supermeXXX: shows [Kh Qd 9s Th] (HI: a pair of Queens) +EricSteph261: shows [Jh 2d 5s 6c] (HI: a pair of Fives; LO: 7,6,5,2,A) +supermeXXX collected $0.09 from pot +EricSteph261 collected $0.09 from pot +*** SUMMARY *** +Total pot $0.18 | Rake $0 +Board [8d 7s Qh As 5d] +Seat 1: EricSteph261 showed [Jh 2d 5s 6c] and won ($0.09) with HI: a pair of Fives; LO: 7,6,5,2,A +Seat 2: UnderMeSensi (button) folded before Flop (didn't bet) +Seat 3: supermeXXX (small blind) showed [Kh Qd 9s Th] and won ($0.09) with HI: a pair of Queens +Seat 5: s0rrow (big blind) folded on the Flop +Seat 6: tiger48475 folded before Flop (didn't bet) + + + +PokerStars Game #35875293439: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:45:14 ET +Table 'Gaby II' 6-max Seat #3 is the button +Seat 1: EricSteph261 ($11.28 in chips) +Seat 3: supermeXXX ($1.25 in chips) +Seat 5: s0rrow ($5.25 in chips) +Seat 6: tiger48475 ($5 in chips) +s0rrow: posts small blind $0.01 +tiger48475: posts big blind $0.02 +*** HOLE CARDS *** +Dealt to s0rrow [9c 8h 8s 3c] +EricSteph261: calls $0.02 +supermeXXX: calls $0.02 +s0rrow: calls $0.01 +tiger48475: checks +*** FLOP *** [Ah 2d Qc] +s0rrow: checks +tiger48475: checks +EricSteph261: checks +supermeXXX: checks +*** TURN *** [Ah 2d Qc] [3d] +s0rrow: checks +tiger48475: checks +EricSteph261: checks +supermeXXX: checks +*** RIVER *** [Ah 2d Qc 3d] [6s] +s0rrow: checks +tiger48475: checks +EricSteph261: checks +supermeXXX: checks +*** SHOW DOWN *** +s0rrow: shows [9c 8h 8s 3c] (HI: a pair of Eights; LO: 8,6,3,2,A) +tiger48475: shows [3s 5s Ts Th] (HI: a pair of Tens; LO: 6,5,3,2,A) +EricSteph261: shows [As Ks Jh 7h] (HI: a pair of Aces; LO: 7,6,3,2,A) +supermeXXX: mucks hand +EricSteph261 collected $0.04 from pot +tiger48475 collected $0.04 from pot +*** SUMMARY *** +Total pot $0.08 | Rake $0 +Board [Ah 2d Qc 3d 6s] +Seat 1: EricSteph261 showed [As Ks Jh 7h] and won ($0.04) with HI: a pair of Aces; LO: 7,6,3,2,A +Seat 3: supermeXXX (button) mucked [9h 9s 4c Kc] +Seat 5: s0rrow (small blind) showed [9c 8h 8s 3c] and lost with HI: a pair of Eights; LO: 8,6,3,2,A +Seat 6: tiger48475 (big blind) showed [3s 5s Ts Th] and won ($0.04) with HI: a pair of Tens; LO: 6,5,3,2,A + + + +PokerStars Game #35875328026: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:46:13 ET +Table 'Gaby II' 6-max Seat #5 is the button +Seat 1: EricSteph261 ($11.30 in chips) +Seat 3: supermeXXX ($1.23 in chips) +Seat 5: s0rrow ($5.23 in chips) +Seat 6: tiger48475 ($5.02 in chips) +tiger48475: posts small blind $0.01 +EricSteph261: posts big blind $0.02 +*** HOLE CARDS *** +Dealt to s0rrow [Qd 6h 8s 6c] +supermeXXX: calls $0.02 +s0rrow: folds +tiger48475: calls $0.01 +EricSteph261: checks +*** FLOP *** [Kc Ac 5s] +tiger48475: checks +EricSteph261: checks +supermeXXX: checks +*** TURN *** [Kc Ac 5s] [3h] +tiger48475: checks +EricSteph261: checks +supermeXXX: checks +*** RIVER *** [Kc Ac 5s 3h] [Qh] +tiger48475: bets $0.06 +EricSteph261: folds +EricSteph261 is sitting out +supermeXXX: folds +Uncalled bet ($0.06) returned to tiger48475 +tiger48475 collected $0.06 from pot +*** SUMMARY *** +Total pot $0.06 | Rake $0 +Board [Kc Ac 5s 3h Qh] +Seat 1: EricSteph261 (big blind) folded on the River +Seat 3: supermeXXX folded on the River +Seat 5: s0rrow (button) folded before Flop (didn't bet) +Seat 6: tiger48475 (small blind) collected ($0.06) + + + +PokerStars Game #35875356253: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:47:00 ET +Table 'Gaby II' 6-max Seat #6 is the button +Seat 3: supermeXXX ($1.21 in chips) +Seat 5: s0rrow ($5.23 in chips) +Seat 6: tiger48475 ($5.06 in chips) +supermeXXX: posts small blind $0.01 +s0rrow: posts big blind $0.02 +*** HOLE CARDS *** +Dealt to s0rrow [8h Jd 5d 8d] +tiger48475: folds +supermeXXX: calls $0.01 +s0rrow: checks +*** FLOP *** [Ks 9s 6c] +supermeXXX: bets $0.02 +s0rrow: calls $0.02 +*** TURN *** [Ks 9s 6c] [Qc] +supermeXXX: bets $0.02 +s0rrow: calls $0.02 +*** RIVER *** [Ks 9s 6c Qc] [Ad] +supermeXXX: checks +s0rrow: checks +*** SHOW DOWN *** +supermeXXX: shows [Tc 7d 8c 3s] (HI: high card Ace) +s0rrow: shows [8h Jd 5d 8d] (HI: a pair of Eights) +s0rrow collected $0.12 from pot +No low hand qualified +*** SUMMARY *** +Total pot $0.12 | Rake $0 +Board [Ks 9s 6c Qc Ad] +Seat 3: supermeXXX (small blind) showed [Tc 7d 8c 3s] and lost with HI: high card Ace +Seat 5: s0rrow (big blind) showed [8h Jd 5d 8d] and won ($0.12) with HI: a pair of Eights +Seat 6: tiger48475 (button) folded before Flop (didn't bet) + + + +PokerStars Game #35875379792: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:47:39 ET +Table 'Gaby II' 6-max Seat #3 is the button +Seat 3: supermeXXX ($1.15 in chips) +Seat 5: s0rrow ($5.29 in chips) +Seat 6: tiger48475 ($5.06 in chips) +s0rrow: posts small blind $0.01 +tiger48475: posts big blind $0.02 +*** HOLE CARDS *** +Dealt to s0rrow [9c 5h 3s Th] +supermeXXX: calls $0.02 +s0rrow: calls $0.01 +tiger48475: checks +*** FLOP *** [Jc 3h Jd] +s0rrow: checks +tiger48475: checks +supermeXXX: checks +*** TURN *** [Jc 3h Jd] [6d] +s0rrow: checks +tiger48475: bets $0.06 +supermeXXX: folds +EricSteph261 has returned +s0rrow: calls $0.06 +*** RIVER *** [Jc 3h Jd 6d] [5c] +s0rrow: checks +tiger48475: bets $0.14 +s0rrow: folds +Uncalled bet ($0.14) returned to tiger48475 +tiger48475 collected $0.18 from pot +*** SUMMARY *** +Total pot $0.18 | Rake $0 +Board [Jc 3h Jd 6d 5c] +Seat 3: supermeXXX (button) folded on the Turn +Seat 5: s0rrow (small blind) folded on the River +Seat 6: tiger48475 (big blind) collected ($0.18) + + + +PokerStars Game #35875409365: Omaha Hi/Lo Pot Limit ($0.01/$0.02 USD) - 2009/11/26 10:48:29 ET +Table 'Gaby II' 6-max Seat #5 is the button +Seat 1: EricSteph261 ($11.28 in chips) +Seat 3: supermeXXX ($1.13 in chips) +Seat 5: s0rrow ($5.21 in chips) +Seat 6: tiger48475 ($5.16 in chips) +tiger48475: posts small blind $0.01 +EricSteph261: posts big blind $0.02 +*** HOLE CARDS *** +Dealt to s0rrow [6h 3c Th 2s] +supermeXXX: calls $0.02 +s0rrow: calls $0.02 +tiger48475: calls $0.01 +EricSteph261 has timed out +EricSteph261: checks +*** FLOP *** [9d 5s Jh] +tiger48475: bets $0.06 +EricSteph261 has timed out +EricSteph261: folds +EricSteph261 is sitting out +supermeXXX: calls $0.06 +s0rrow: calls $0.06 +*** TURN *** [9d 5s Jh] [Ks] +tiger48475: checks +supermeXXX: bets $0.10 +s0rrow: folds +tiger48475: calls $0.10 +*** RIVER *** [9d 5s Jh Ks] [9s] +tiger48475: checks +supermeXXX: checks +*** SHOW DOWN *** +tiger48475: shows [6s 9h 9c Ad] (HI: four of a kind, Nines) +supermeXXX: mucks hand +tiger48475 collected $0.46 from pot +No low hand qualified +*** SUMMARY *** +Total pot $0.46 | Rake $0 +Board [9d 5s Jh Ks 9s] +Seat 1: EricSteph261 (big blind) folded on the Flop +Seat 3: supermeXXX mucked [Qd Tc 5h Ts] +Seat 5: s0rrow (button) folded on the Turn +Seat 6: tiger48475 (small blind) showed [6s 9h 9c Ad] and won ($0.46) with HI: four of a kind, Nines + + + diff --git a/pyfpdb/regression-test-files/cash/Stars/Stud/7-StudHL-USD-0.04-0.08-200911.Cardtest.txt b/pyfpdb/regression-test-files/cash/Stars/Stud/7-StudHL-USD-0.04-0.08-200911.Cardtest.txt index 0ffdcc3d..7b1e2f44 100644 --- a/pyfpdb/regression-test-files/cash/Stars/Stud/7-StudHL-USD-0.04-0.08-200911.Cardtest.txt +++ b/pyfpdb/regression-test-files/cash/Stars/Stud/7-StudHL-USD-0.04-0.08-200911.Cardtest.txt @@ -1,96 +1,96 @@ -PokerStars Game #35874676388: 7 Card Stud Hi/Lo Limit ($0.04/$0.08 USD) - 2009/11/26 10:27:46 ET -Table 'Dawn II' 8-max -Seat 1: u.pressure ($11.17 in chips) -Seat 2: 123smoothie ($0.99 in chips) -Seat 3: gashpor ($1.40 in chips) -Seat 4: denny501 ($0.71 in chips) -Seat 5: s0rrow ($1.52 in chips) -Seat 6: TomSludge ($1.58 in chips) -Seat 7: Soroka69 ($0.83 in chips) -Seat 8: rdiezchang ($2.05 in chips) -u.pressure: posts the ante $0.01 -123smoothie: posts the ante $0.01 -gashpor: posts the ante $0.01 -denny501: posts the ante $0.01 -s0rrow: posts the ante $0.01 -TomSludge: posts the ante $0.01 -Soroka69: posts the ante $0.01 -rdiezchang: posts the ante $0.01 -*** 3rd STREET *** -Dealt to u.pressure [Td] -Dealt to 123smoothie [4c] -Dealt to gashpor [5d] -Dealt to denny501 [2c] -Dealt to s0rrow [7c 3s 5h] -Dealt to TomSludge [8s] -Dealt to Soroka69 [7d] -Dealt to rdiezchang [Ad] -denny501: brings in for $0.02 -s0rrow: calls $0.02 -TomSludge: folds -Soroka69: calls $0.02 -rdiezchang: calls $0.02 -u.pressure: folds -123smoothie: calls $0.02 -gashpor: calls $0.02 -*** 4th STREET *** -Dealt to 123smoothie [4c] [3c] -Dealt to gashpor [5d] [Qd] -Dealt to denny501 [2c] [7s] -Dealt to s0rrow [7c 3s 5h] [Qc] -Dealt to Soroka69 [7d] [5s] -Dealt to rdiezchang [Ad] [Js] -rdiezchang: checks -123smoothie: checks -gashpor: checks -denny501: folds -denny501 leaves the table -s0rrow: checks -Soroka69: checks -*** 5th STREET *** -Dealt to 123smoothie [4c 3c] [9s] -Dealt to gashpor [5d Qd] [Jd] -Dealt to s0rrow [7c 3s 5h Qc] [Kc] -Dealt to Soroka69 [7d 5s] [5c] -Dealt to rdiezchang [Ad Js] [Ts] -LainaRahat joins the table at seat #4 -Soroka69: checks -rdiezchang: checks -123smoothie: checks -gashpor: bets $0.08 -s0rrow: calls $0.08 -Soroka69: calls $0.08 -rdiezchang: folds -123smoothie: folds -*** 6th STREET *** -Dealt to gashpor [5d Qd Jd] [9d] -Dealt to s0rrow [7c 3s 5h Qc Kc] [6d] -Dealt to Soroka69 [7d 5s 5c] [2s] -Soroka69: checks -gashpor: bets $0.08 -s0rrow: calls $0.08 -Soroka69: calls $0.08 -*** RIVER *** -Dealt to s0rrow [7c 3s 5h Qc Kc 6d] [4d] -Soroka69: checks -gashpor: bets $0.08 -s0rrow: calls $0.08 -Soroka69: folds -*** SHOW DOWN *** -gashpor: shows [4h 3d 5d Qd Jd 9d 6h] (HI: a flush, Queen high) -s0rrow: shows [7c 3s 5h Qc Kc 6d 4d] (HI: a straight, Three to Seven; LO: 7,6,5,4,3) -gashpor collected $0.40 from pot -s0rrow collected $0.40 from pot -*** SUMMARY *** -Total pot $0.84 | Rake $0.04 -Seat 1: u.pressure folded on the 3rd Street (didn't bet) -Seat 2: 123smoothie folded on the 5th Street -Seat 3: gashpor showed [4h 3d 5d Qd Jd 9d 6h] and won ($0.40) with HI: a flush, Queen high -Seat 4: denny501 folded on the 4th Street -Seat 5: s0rrow showed [7c 3s 5h Qc Kc 6d 4d] and won ($0.40) with HI: a straight, Three to Seven; LO: 7,6,5,4,3 -Seat 6: TomSludge folded on the 3rd Street (didn't bet) -Seat 7: Soroka69 folded on the River -Seat 8: rdiezchang folded on the 5th Street - - - +PokerStars Game #35874676388: 7 Card Stud Hi/Lo Limit ($0.04/$0.08 USD) - 2009/11/26 10:27:46 ET +Table 'Dawn II' 8-max +Seat 1: u.pressure ($11.17 in chips) +Seat 2: 123smoothie ($0.99 in chips) +Seat 3: gashpor ($1.40 in chips) +Seat 4: denny501 ($0.71 in chips) +Seat 5: s0rrow ($1.52 in chips) +Seat 6: TomSludge ($1.58 in chips) +Seat 7: Soroka69 ($0.83 in chips) +Seat 8: rdiezchang ($2.05 in chips) +u.pressure: posts the ante $0.01 +123smoothie: posts the ante $0.01 +gashpor: posts the ante $0.01 +denny501: posts the ante $0.01 +s0rrow: posts the ante $0.01 +TomSludge: posts the ante $0.01 +Soroka69: posts the ante $0.01 +rdiezchang: posts the ante $0.01 +*** 3rd STREET *** +Dealt to u.pressure [Td] +Dealt to 123smoothie [4c] +Dealt to gashpor [5d] +Dealt to denny501 [2c] +Dealt to s0rrow [7c 3s 5h] +Dealt to TomSludge [8s] +Dealt to Soroka69 [7d] +Dealt to rdiezchang [Ad] +denny501: brings in for $0.02 +s0rrow: calls $0.02 +TomSludge: folds +Soroka69: calls $0.02 +rdiezchang: calls $0.02 +u.pressure: folds +123smoothie: calls $0.02 +gashpor: calls $0.02 +*** 4th STREET *** +Dealt to 123smoothie [4c] [3c] +Dealt to gashpor [5d] [Qd] +Dealt to denny501 [2c] [7s] +Dealt to s0rrow [7c 3s 5h] [Qc] +Dealt to Soroka69 [7d] [5s] +Dealt to rdiezchang [Ad] [Js] +rdiezchang: checks +123smoothie: checks +gashpor: checks +denny501: folds +denny501 leaves the table +s0rrow: checks +Soroka69: checks +*** 5th STREET *** +Dealt to 123smoothie [4c 3c] [9s] +Dealt to gashpor [5d Qd] [Jd] +Dealt to s0rrow [7c 3s 5h Qc] [Kc] +Dealt to Soroka69 [7d 5s] [5c] +Dealt to rdiezchang [Ad Js] [Ts] +LainaRahat joins the table at seat #4 +Soroka69: checks +rdiezchang: checks +123smoothie: checks +gashpor: bets $0.08 +s0rrow: calls $0.08 +Soroka69: calls $0.08 +rdiezchang: folds +123smoothie: folds +*** 6th STREET *** +Dealt to gashpor [5d Qd Jd] [9d] +Dealt to s0rrow [7c 3s 5h Qc Kc] [6d] +Dealt to Soroka69 [7d 5s 5c] [2s] +Soroka69: checks +gashpor: bets $0.08 +s0rrow: calls $0.08 +Soroka69: calls $0.08 +*** RIVER *** +Dealt to s0rrow [7c 3s 5h Qc Kc 6d] [4d] +Soroka69: checks +gashpor: bets $0.08 +s0rrow: calls $0.08 +Soroka69: folds +*** SHOW DOWN *** +gashpor: shows [4h 3d 5d Qd Jd 9d 6h] (HI: a flush, Queen high) +s0rrow: shows [7c 3s 5h Qc Kc 6d 4d] (HI: a straight, Three to Seven; LO: 7,6,5,4,3) +gashpor collected $0.40 from pot +s0rrow collected $0.40 from pot +*** SUMMARY *** +Total pot $0.84 | Rake $0.04 +Seat 1: u.pressure folded on the 3rd Street (didn't bet) +Seat 2: 123smoothie folded on the 5th Street +Seat 3: gashpor showed [4h 3d 5d Qd Jd 9d 6h] and won ($0.40) with HI: a flush, Queen high +Seat 4: denny501 folded on the 4th Street +Seat 5: s0rrow showed [7c 3s 5h Qc Kc 6d 4d] and won ($0.40) with HI: a straight, Three to Seven; LO: 7,6,5,4,3 +Seat 6: TomSludge folded on the 3rd Street (didn't bet) +Seat 7: Soroka69 folded on the River +Seat 8: rdiezchang folded on the 5th Street + + + diff --git a/pyfpdb/test1.py b/pyfpdb/test1.py index 76bde20e..4f220935 100755 --- a/pyfpdb/test1.py +++ b/pyfpdb/test1.py @@ -1,29 +1,29 @@ -#!/usr/bin/env python -"""test1.py - -Test if python is working. -""" -# Copyright 2008, Ray E. Barker -# -# 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; either version 2 of the License, or -# (at your option) any later version. -# -# 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 General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -######################################################################## - -import sys - -print "\npython is working!" -print "\npress return to finish" - -sys.stdin.readline() +#!/usr/bin/env python +"""test1.py + +Test if python is working. +""" +# Copyright 2008, Ray E. Barker +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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 General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +######################################################################## + +import sys + +print "\npython is working!" +print "\npress return to finish" + +sys.stdin.readline() diff --git a/pyfpdb/test2.py b/pyfpdb/test2.py index c52d0a6c..74ce1e72 100755 --- a/pyfpdb/test2.py +++ b/pyfpdb/test2.py @@ -1,57 +1,57 @@ -#!/usr/bin/env python -"""test2.py - -Test if gtk is working. -""" -# Copyright 2008, Ray E. Barker -# -# 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; either version 2 of the License, or -# (at your option) any later version. -# -# 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 General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -######################################################################## - -import sys - -try: - import pygtk - pygtk.require('2.0') - import gtk - - - win = gtk.Window(gtk.WINDOW_TOPLEVEL) - win.set_title("Test GTK") - win.set_border_width(1) - win.set_default_size(600, 500) - win.set_resizable(True) - #win.show() - - dia = gtk.Dialog("Test GTK", - win, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - (gtk.STOCK_CLOSE, gtk.RESPONSE_OK)) - dia.set_default_size(500, 300) - - l = gtk.Label("GTK is working!") - dia.vbox.add(l) - l.show() - - response = dia.run() - if response == gtk.RESPONSE_ACCEPT: - pass - dia.destroy() - -except: - print "\nError:", sys.exc_info() - print "\npress return to finish" - sys.stdin.readline() +#!/usr/bin/env python +"""test2.py + +Test if gtk is working. +""" +# Copyright 2008, Ray E. Barker +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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 General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +######################################################################## + +import sys + +try: + import pygtk + pygtk.require('2.0') + import gtk + + + win = gtk.Window(gtk.WINDOW_TOPLEVEL) + win.set_title("Test GTK") + win.set_border_width(1) + win.set_default_size(600, 500) + win.set_resizable(True) + #win.show() + + dia = gtk.Dialog("Test GTK", + win, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, + (gtk.STOCK_CLOSE, gtk.RESPONSE_OK)) + dia.set_default_size(500, 300) + + l = gtk.Label("GTK is working!") + dia.vbox.add(l) + l.show() + + response = dia.run() + if response == gtk.RESPONSE_ACCEPT: + pass + dia.destroy() + +except: + print "\nError:", sys.exc_info() + print "\npress return to finish" + sys.stdin.readline() From cf6e818ae5ae784ee778cdc11b9c204337f70da1 Mon Sep 17 00:00:00 2001 From: Carl Gherardi Date: Mon, 14 Dec 2009 16:45:08 +0800 Subject: [PATCH 010/251] [NEWIMPORT] Enable NEWIMPORT by defaul --- pyfpdb/Configuration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 996ef60c..bf8689a6 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -125,7 +125,7 @@ DATABASE_TYPES = ( DATABASE_TYPE_MYSQL, ) -NEWIMPORT = False +NEWIMPORT = True ######################################################################## def string_to_bool(string, default=True): From 97842c1be3daa75e687360dd697a3940ad1641b5 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 16 Dec 2009 18:15:07 +0000 Subject: [PATCH 011/251] remove merge comment --- pyfpdb/SQL.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 5a0d1965..fa6d50cf 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -2789,8 +2789,6 @@ class Sql: ,hp.tourneyTypeId ,date_format(h.handStart, 'd%y%m%d') """ -#>>>>>>> 28ca49d592c8e706ad6ee58dd26655bcc33fc5fb:pyfpdb/SQL.py -#""" elif db_server == 'postgresql': self.query['rebuildHudCache'] = """ INSERT INTO HudCache From f03a9c287fba9398aba1eff20a17e5b398656d99 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 17 Dec 2009 15:53:12 +0800 Subject: [PATCH 012/251] Add some code to kinda detect hand cancellation hhc.readHandInfo(self) hhc.readPlayerStacks(self) hhc.compilePlayerRegexs(self) hhc.markStreets(self) Is the order, the first correctly failing regex is markStreets --- pyfpdb/Hand.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 6901340e..32140256 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -54,6 +54,7 @@ class Hand(object): self.starttime = 0 self.handText = handText self.handid = 0 + self.cancelled = False self.dbid_hands = 0 self.dbid_pids = None self.dbid_gt = 0 @@ -263,6 +264,8 @@ If a player has None chips he won't be added.""" log.debug("markStreets:\n"+ str(self.streets)) else: log.error("markstreets didn't match") + log.error(" - Assuming hand cancelled") + self.cancelled = True def checkPlayerExists(self,player): if player not in [p[1] for p in self.players]: @@ -613,6 +616,8 @@ class HoldemOmahaHand(Hand): hhc.readPlayerStacks(self) hhc.compilePlayerRegexs(self) hhc.markStreets(self) + if self.cancelled: + return hhc.readBlinds(self) hhc.readAntes(self) hhc.readButton(self) From 26fc0b592837765c515277fc1f0b373b9934667b Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 17 Dec 2009 18:42:50 +0800 Subject: [PATCH 013/251] Add ability to import Stars archive files. PokerStars support can provide a HH archive. The format is similar but not the same as a a standard hh format as it contains an additional line "Hand #X" between each hand. Patch adds an option -s to GuiBulkImport, which when specified will strip these lines out and continue parsing. --- pyfpdb/GuiBulkImport.py | 4 ++++ pyfpdb/Hand.py | 1 + pyfpdb/HandHistoryConverter.py | 8 +++++++- pyfpdb/fpdb_import.py | 19 +++++++++++++------ 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/pyfpdb/GuiBulkImport.py b/pyfpdb/GuiBulkImport.py index 7db420c7..16131ab2 100755 --- a/pyfpdb/GuiBulkImport.py +++ b/pyfpdb/GuiBulkImport.py @@ -326,6 +326,8 @@ def main(argv=None): help="How often to print a one-line status report (0 (default) means never)") parser.add_option("-u", "--usage", action="store_true", dest="usage", default=False, help="Print some useful one liners") + parser.add_option("-s", "--starsarchive", action="store_true", dest="starsArchive", default=False, + help="Do the required conversion for Stars Archive format (ie. as provided by support") (options, argv) = parser.parse_args(args = argv) if options.usage == True: @@ -369,6 +371,8 @@ def main(argv=None): importer.setThreads(-1) importer.addBulkImportImportFileOrDir(os.path.expanduser(options.filename), site=options.filtername) importer.setCallHud(False) + if options.starsArchive: + importer.setStarsArchive(True) (stored, dups, partial, errs, ttime) = importer.runImport() importer.clearFileList() print 'GuiBulkImport done: Stored: %d \tDuplicates: %d \tPartial: %d \tErrors: %d in %s seconds - %.0f/sec'\ diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 32140256..3467216a 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -266,6 +266,7 @@ If a player has None chips he won't be added.""" log.error("markstreets didn't match") log.error(" - Assuming hand cancelled") self.cancelled = True + raise FpdbParseError def checkPlayerExists(self,player): if player not in [p[1] for p in self.players]: diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 27bb9b1a..a18797df 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -57,7 +57,7 @@ class HandHistoryConverter(): codepage = "cp1252" - def __init__(self, in_path = '-', out_path = '-', follow=False, index=0, autostart=True): + def __init__(self, in_path = '-', out_path = '-', follow=False, index=0, autostart=True, starsArchive=False): """\ in_path (default '-' = sys.stdin) out_path (default '-' = sys.stdout) @@ -66,6 +66,7 @@ follow : whether to tail -f the input""" log.info("HandHistory init - %s subclass, in_path '%s'; out_path '%s'" % (self.sitename, in_path, out_path) ) self.index = 0 + self.starsArchive = starsArchive self.in_path = in_path self.out_path = out_path @@ -254,6 +255,11 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py. self.readFile() self.obs = self.obs.strip() self.obs = self.obs.replace('\r\n', '\n') + if self.starsArchive == True: + log.debug("Converting starsArchive format to readable") + m = re.compile('^Hand #\d+', re.MULTILINE) + self.obs = m.sub('', self.obs) + if self.obs is None or self.obs == "": log.info("Read no hands.") return [] diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 7b3dd4f1..8921d9d8 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -91,6 +91,7 @@ class Importer: self.settings.setdefault("writeQMaxWait", 10) # not used self.settings.setdefault("dropIndexes", "don't drop") self.settings.setdefault("dropHudCache", "don't drop") + self.settings.setdefault("starsArchive", False) self.writeq = None self.database = Database.Database(self.config, sql = self.sql) @@ -134,6 +135,9 @@ class Importer: def setDropHudCache(self, value): self.settings['dropHudCache'] = value + def setStarsArchive(self, value): + self.settings['starsArchive'] = value + # def setWatchTime(self): # self.updated = time() @@ -425,7 +429,7 @@ class Importer: mod = __import__(filter) obj = getattr(mod, filter_name, None) if callable(obj): - hhc = obj(in_path = file, out_path = out_path, index = 0) # Index into file 0 until changeover + hhc = obj(in_path = file, out_path = out_path, index = 0, starsArchive = self.settings['starsArchive']) # Index into file 0 until changeover if hhc.getStatus() and self.NEWIMPORT == False: (stored, duplicates, partial, errors, ttime) = self.import_fpdb_file(db, out_path, site, q) elif hhc.getStatus() and self.NEWIMPORT == True: @@ -435,11 +439,14 @@ class Importer: to_hud = [] for hand in handlist: - #try, except duplicates here? - hand.prepInsert(self.database) - hand.insert(self.database) - if self.callHud and hand.dbid_hands != 0: - to_hud.append(hand.dbid_hands) + if hand is not None: + #try, except duplicates here? + hand.prepInsert(self.database) + hand.insert(self.database) + if self.callHud and hand.dbid_hands != 0: + to_hud.append(hand.dbid_hands) + else: + log.error("Hand processed but empty") self.database.commit() #pipe the Hands.id out to the HUD From 1093b1e43c3a12af748e0768cd71513e70d6d060 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 18 Dec 2009 10:27:09 +0800 Subject: [PATCH 014/251] Remove dead code --- pyfpdb/fpdb_import.py | 160 +----------------------------------------- 1 file changed, 1 insertion(+), 159 deletions(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 8921d9d8..21aa5d5c 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -430,9 +430,7 @@ class Importer: obj = getattr(mod, filter_name, None) if callable(obj): hhc = obj(in_path = file, out_path = out_path, index = 0, starsArchive = self.settings['starsArchive']) # Index into file 0 until changeover - if hhc.getStatus() and self.NEWIMPORT == False: - (stored, duplicates, partial, errors, ttime) = self.import_fpdb_file(db, out_path, site, q) - elif hhc.getStatus() and self.NEWIMPORT == True: + if hhc.getStatus() and self.NEWIMPORT == True: #This code doesn't do anything yet handlist = hhc.getProcessedHands() self.pos_in_file[file] = hhc.getLastCharacterRead() @@ -468,162 +466,6 @@ class Importer: return (stored, duplicates, partial, errors, ttime) - def import_fpdb_file(self, db, file, site, q): - starttime = time() - last_read_hand = 0 - loc = 0 - (stored, duplicates, partial, errors, ttime) = (0, 0, 0, 0, 0) - # print "file =", file - if file == "stdin": - inputFile = sys.stdin - else: - if os.path.exists(file): - inputFile = open(file, "rU") - else: - self.removeFromFileList[file] = True - return (0, 0, 0, 1, 0) - try: - loc = self.pos_in_file[file] - #size = os.path.getsize(file) - #print "loc =", loc, 'size =', size - except KeyError: - pass - # Read input file into class and close file - inputFile.seek(loc) - #tmplines = inputFile.readlines() - #if tmplines == None or tmplines == []: - # print "tmplines = ", tmplines - #else: - # print "tmplines[0] =", tmplines[0] - self.lines = fpdb_simple.removeTrailingEOL(inputFile.readlines()) - self.pos_in_file[file] = inputFile.tell() - inputFile.close() - - x = clock() - (stored, duplicates, partial, errors, ttime, handsId) = self.import_fpdb_lines(db, self.lines, starttime, file, site, q) - - db.commit() - y = clock() - ttime = y - x - #ttime = time() - starttime - if q is None: - log.info("Total stored: %(stored)d\tduplicates:%(duplicates)d\terrors:%(errors)d\ttime:%(ttime)s" % locals()) - - if not stored: - if duplicates: - for line_no in xrange(len(self.lines)): - if self.lines[line_no].find("Game #") != -1: - final_game_line = self.lines[line_no] - handsId=fpdb_simple.parseSiteHandNo(final_game_line) - else: - print "failed to read a single hand from file:", inputFile - handsId = 0 - #todo: this will cause return of an unstored hand number if the last hand was error - self.handsId = handsId - - return (stored, duplicates, partial, errors, ttime) - # end def import_fpdb_file - - - def import_fpdb_lines(self, db, lines, starttime, file, site, q = None): - """Import an fpdb hand history held in the list lines, could be one hand or many""" - - #db.lock_for_insert() # should be ok when using one thread, but doesn't help?? - while gtk.events_pending(): - gtk.main_iteration(False) - - try: # sometimes we seem to be getting an empty self.lines, in which case, we just want to return. - firstline = lines[0] - except: - # just skip the debug message and return silently: - #print "DEBUG: import_fpdb_file: failed on lines[0]: '%s' '%s' '%s' '%s' " %( file, site, lines, loc) - return (0,0,0,1,0,0) - - if "Tournament Summary" in firstline: - print "TODO: implement importing tournament summaries" - #self.faobs = readfile(inputFile) - #self.parseTourneyHistory() - return (0,0,0,1,0,0) - - category = fpdb_simple.recogniseCategory(firstline) - - startpos = 0 - stored = 0 #counter - duplicates = 0 #counter - partial = 0 #counter - errors = 0 #counter - ttime = 0 - handsId = 0 - - for i in xrange(len(lines)): - if len(lines[i]) < 2: #Wierd way to detect for '\r\n' or '\n' - endpos = i - hand = lines[startpos:endpos] - - if len(hand[0]) < 2: - hand=hand[1:] - - if len(hand) < 3: - pass - #TODO: This is ugly - we didn't actually find the start of the - # hand with the outer loop so we test again... - else: - isTourney = fpdb_simple.isTourney(hand[0]) - if not isTourney: - hand = fpdb_simple.filterAnteBlindFold(hand) - self.hand = hand - - try: - handsId = fpdb_parse_logic.mainParser( self.settings, self.siteIds[site] - , category, hand, self.config - , db, q ) - db.commit() - - stored += 1 - if self.callHud: - #print "call to HUD here. handsId:",handsId - #pipe the Hands.id out to the HUD - # print "fpdb_import: sending hand to hud", handsId, "pipe =", self.caller.pipe_to_hud - try: - self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep) - except IOError: # hud closed - self.callHud = False - pass # continue import without hud - except Exceptions.DuplicateError: - duplicates += 1 - db.rollback() - except (ValueError), fe: - errors += 1 - self.printEmailErrorMessage(errors, file, hand) - - if (self.settings['failOnError']): - db.commit() #dont remove this, in case hand processing was cancelled. - raise - else: - db.rollback() - except (fpdb_simple.FpdbError), fe: - errors += 1 - self.printEmailErrorMessage(errors, file, hand) - db.rollback() - - if self.settings['failOnError']: - db.commit() #dont remove this, in case hand processing was cancelled. - raise - - if self.settings['minPrint']: - if not ((stored+duplicates+errors) % self.settings['minPrint']): - print "stored:", stored, " duplicates:", duplicates, "errors:", errors - - if self.settings['handCount']: - if ((stored+duplicates+errors) >= self.settings['handCount']): - if not self.settings['quiet']: - print "quitting due to reaching the amount of hands to be imported" - print "Total stored:", stored, "duplicates:", duplicates, "errors:", errors, " time:", (time() - starttime) - sys.exit(0) - startpos = endpos - return (stored, duplicates, partial, errors, ttime, handsId) - # end def import_fpdb_lines - def printEmailErrorMessage(self, errors, filename, line): traceback.print_exc(file=sys.stderr) print "Error No.",errors,", please send the hand causing this to steffen@sycamoretest.info so I can fix it." From 975eb360ef96d3f669269117c9fe78f151662379 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 18 Dec 2009 10:27:43 +0800 Subject: [PATCH 015/251] [NEWIMPORT] Add stubbed variable to insert --- pyfpdb/Database.py | 3 ++- pyfpdb/SQL.py | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 9d1f3f85..72b41336 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1651,7 +1651,8 @@ class Database: pdata[p]['street2CheckCallRaiseDone'], pdata[p]['street3CheckCallRaiseChance'], pdata[p]['street3CheckCallRaiseDone'], - pdata[p]['street4CheckCallRaiseChance'] + pdata[p]['street4CheckCallRaiseChance'], + pdata[p]['street4CheckCallRaiseDone'] ) ) q = self.sql.query['store_hands_players'] diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index c0319dfe..56c1f388 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -3404,10 +3404,11 @@ class Sql: street2CheckCallRaiseDone, street3CheckCallRaiseChance, street3CheckCallRaiseDone, - street4CheckCallRaiseChance + 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, From 2b7d34c4842e40b9d8fdb950eefd23c99068e95d Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 18 Dec 2009 13:32:09 +0800 Subject: [PATCH 016/251] [NEWIMPORT] Fix syntax to be 2.5 compatible. Python 2.6 enumerate() function contains a useful 'start' paramater, apparently this did not exist in 2.5. Patch frim Mika Bostrom --- pyfpdb/DerivedStats.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 1a34db1e..5943a10f 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -168,8 +168,10 @@ class DerivedStats(): for player in hand.players: hcs = hand.join_holecards(player[1], asList=True) hcs = hcs + [u'0x', u'0x', u'0x', u'0x', u'0x'] - for i, card in enumerate(hcs[:7], 1): - self.handsplayers[player[1]]['card%s' % i] = Card.encodeCard(card) + #for i, card in enumerate(hcs[:7], 1): #Python 2.6 syntax + # self.handsplayers[player[1]]['card%s' % i] = Card.encodeCard(card) + for i, card in enumerate(hcs[:7]): + self.handsplayers[player[1]]['card%s' % (i+1)] = Card.encodeCard(card) # position, @@ -266,13 +268,17 @@ class DerivedStats(): # Then no bets before the player with initiatives first action on current street # ie. if player on street-1 had initiative # and no donkbets occurred - for i, street in enumerate(hand.actionStreets[2:], start=1): - name = self.lastBetOrRaiser(hand.actionStreets[i]) + + # XXX: enumerate(list, start=x) is python 2.6 syntax; 'start' + # came there + #for i, street in enumerate(hand.actionStreets[2:], start=1): + for i, street in enumerate(hand.actionStreets[2:]: + name = self.lastBetOrRaiser(hand.actionStreets[i+1]) if name: - chance = self.noBetsBefore(hand.actionStreets[i+1], name) - self.handsplayers[name]['street%dCBChance' %i] = True + chance = self.noBetsBefore(hand.actionStreets[i+2], name) + self.handsplayers[name]['street%dCBChance' % (i+1)] = True if chance == True: - self.handsplayers[name]['street%dCBDone' %i] = self.betStreet(hand.actionStreets[i+1], name) + self.handsplayers[name]['street%dCBDone' % (i+1)] = self.betStreet(hand.actionStreets[i+2], name) def seen(self, hand, i): pas = set() From 02453ce3c09096b50405265b433e29702b0859ec Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 22 Dec 2009 13:47:33 +0800 Subject: [PATCH 017/251] Move locale variable to Configuration --- 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 21aa5d5c..577562b8 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -409,7 +409,7 @@ class Importer: conv = None (stored, duplicates, partial, errors, ttime) = (0, 0, 0, 0, 0) - file = file.decode(fpdb_simple.LOCALE_ENCODING) + file = file.decode(Configuration.LOCALE_ENCODING) # Load filter, process file, pass returned filename to import_fpdb_file if self.settings['threads'] > 0 and self.writeq is not None: From 262eb5200d85cdc13691a09dab0885a8df11922d Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 22 Dec 2009 13:49:22 +0800 Subject: [PATCH 018/251] Add LOCALE static to Configuration --- pyfpdb/Configuration.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index bf8689a6..174d0673 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -31,6 +31,7 @@ import inspect import string import traceback import shutil +import locale import xml.dom.minidom from xml.dom.minidom import Node @@ -126,6 +127,7 @@ DATABASE_TYPES = ( ) NEWIMPORT = True +LOCALE_ENCODING = locale.getdefaultlocale()[1] ######################################################################## def string_to_bool(string, default=True): From 1b82f20411f02dfcaf3cc57aceebca514ecb5c45 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 22 Dec 2009 14:44:35 +0800 Subject: [PATCH 019/251] [NEWIMPORT] Remove legacy code. --- pyfpdb/CliFpdb.py | 66 -- pyfpdb/Database.py | 350 -------- pyfpdb/GuiBulkImport.py | 1 - pyfpdb/GuiTableViewer.py | 1 - pyfpdb/fpdb_db.py | 1 - pyfpdb/fpdb_import.py | 2 - pyfpdb/fpdb_parse_logic.py | 235 ----- pyfpdb/fpdb_simple.py | 1728 ------------------------------------ 8 files changed, 2384 deletions(-) delete mode 100755 pyfpdb/CliFpdb.py delete mode 100644 pyfpdb/fpdb_parse_logic.py delete mode 100644 pyfpdb/fpdb_simple.py diff --git a/pyfpdb/CliFpdb.py b/pyfpdb/CliFpdb.py deleted file mode 100755 index abdddb45..00000000 --- a/pyfpdb/CliFpdb.py +++ /dev/null @@ -1,66 +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. - -import os -import sys -import fpdb_simple -from optparse import OptionParser - -try: - import MySQLdb -except: - diaSQLLibMissing = gtk.Dialog(title="Fatal Error - SQL interface library missing", parent=None, flags=0, buttons=(gtk.STOCK_QUIT,gtk.RESPONSE_OK)) - - print "Please note that the CLI importer only works with MySQL, if you use PostgreSQL this error is expected." - -import fpdb_import -import fpdb_db - -if __name__ == "__main__": - #process CLI parameters - parser = OptionParser() - parser.add_option("-c", "--handCount", default="0", type="int", - help="Number of hands to import (default 0 means unlimited)") - parser.add_option("-d", "--database", default="fpdb", help="The MySQL database to use (default fpdb)") - parser.add_option("-e", "--errorFile", default="failed.txt", - help="File to store failed hands into. (default: failed.txt) Not implemented.") - parser.add_option("-f", "--inputFile", "--file", "--inputfile", default="stdin", - help="The file you want to import (remember to use quotes if necessary)") - parser.add_option("-m", "--minPrint", "--status", default="50", type="int", - help="How often to print a one-line status report (0 means never, default is 50)") - parser.add_option("-p", "--password", help="The password for the MySQL user") - parser.add_option("-q", "--quiet", action="store_true", - help="If this is passed it doesn't print a total at the end nor the opening line. Note that this purposely does NOT change --minPrint") - parser.add_option("-s", "--server", default="localhost", - help="Hostname/IP of the MySQL server (default localhost)") - parser.add_option("-u", "--user", default="fpdb", help="The MySQL username (default fpdb)") - parser.add_option("-x", "--failOnError", action="store_true", - help="If this option is passed it quits when it encounters any error") - - (options, argv) = parser.parse_args() - - settings={'callFpdbHud':False, 'db-backend':2} - settings['db-host']=options.server - settings['db-user']=options.user - settings['db-password']=options.password - settings['db-databaseName']=options.database - settings['handCount']=options.handCount - settings['failOnError']=options.failOnError - - importer = fpdb_import.Importer(options, settings) - importer.addImportFile(options.inputFile) - importer.runImport() diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 72b41336..412036ab 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -43,7 +43,6 @@ import Queue # FreePokerTools modules import fpdb_db -import fpdb_simple import Configuration import SQL import Card @@ -724,120 +723,6 @@ class Database: return ret - #stores a stud/razz hand into the database - def ring_stud(self, config, settings, 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): - - fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) - - hands_id = self.storeHands(self.backend, site_hand_no, gametype_id - ,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 = self.store_hands_players_stud(self.backend, hands_id, player_ids - ,start_cashes, antes, card_values - ,card_suits, winnings, rakes, seatNos) - - if 'dropHudCache' not in settings or settings['dropHudCache'] != 'drop': - self.storeHudCache(self.backend, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - - return hands_id - #end def ring_stud - - def ring_holdem_omaha(self, config, settings, 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""" - - t0 = time() - #print "in ring_holdem_omaha" - 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 = self.storeHands(self.backend, 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 = self.store_hands_players_holdem_omaha( - self.backend, category, hands_id, player_ids, start_cashes - , positions, card_values, card_suits, winnings, rakes, seatNos, hudImportData) - t4 = time() - if 'dropHudCache' not in settings or settings['dropHudCache'] != 'drop': - self.storeHudCache(self.backend, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - t5 = time() - #print "fills=(%4.3f) saves=(%4.3f,%4.3f,%4.3f)" % (t2-t0, t3-t2, t4-t3, t5-t4) - return hands_id - #end def ring_holdem_omaha - - def tourney_holdem_omaha(self, config, settings, 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""" - - fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) - fpdb_simple.fill_board_cards(board_values, board_suits) - - tourney_id = self.store_tourneys(tourneyTypeId, siteTourneyNo, entries, prizepool, tourney_start) - tourneys_players_ids = self.store_tourneys_players(tourney_id, player_ids, payin_amounts, ranks, winnings) - - hands_id = self.storeHands(self.backend, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats - ,hudImportData, board_values, board_suits) - - hands_players_ids = self.store_hands_players_holdem_omaha_tourney( - self.backend, category, hands_id, player_ids, start_cashes, positions - , card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids - , hudImportData, tourneyTypeId) - - #print "tourney holdem, backend=%d" % backend - if 'dropHudCache' not in settings or settings['dropHudCache'] != 'drop': - self.storeHudCache(self.backend, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - - return hands_id - #end def tourney_holdem_omaha - - def tourney_stud(self, config, settings, 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 - - fpdb_simple.fillCardArrays(len(names), base, category, cardValues, cardSuits) - - tourney_id = self.store_tourneys(tourneyTypeId, siteTourneyNo, entries, prizepool, tourneyStartTime) - - tourneys_players_ids = self.store_tourneys_players(tourney_id, playerIds, payin_amounts, ranks, winnings) - - hands_id = self.storeHands( self.backend, siteHandNo, gametypeId - , handStartTime, names, tableName, maxSeats - , hudImportData, (None, None, None, None, None), (None, None, None, None, None) ) - # changed board_values and board_suits to arrays of None, just like the - # cash game version of this function does - i don't believe this to be - # the correct thing to do (tell me if i'm wrong) but it should keep the - # importer from crashing - - hands_players_ids = self.store_hands_players_stud_tourney(self.backend, hands_id - , playerIds, startCashes, antes, cardValues, cardSuits - , winnings, rakes, seatNos, tourneys_players_ids, tourneyTypeId) - - if 'dropHudCache' not in settings or settings['dropHudCache'] != 'drop': - self.storeHudCache(self.backend, base, category, gametypeId, handStartTime, playerIds, hudImportData) - - return hands_id - #end def tourney_stud - def prepareBulkImport(self): """Drop some indexes/foreign keys to prepare for bulk import. Currently keeping the standalone indexes as needed to import quickly""" @@ -1465,64 +1350,6 @@ class Database: print "Error during fdb.lock_for_insert:", str(sys.exc_value) #end def lock_for_insert - def store_the_hand(self, h): - """Take a HandToWrite object and store it in the db""" - - # Following code writes hands to database and commits (or rolls back if there is an error) - try: - result = None - if h.isTourney: - ranks = map(lambda x: 0, h.names) # create an array of 0's equal to the length of names - payin_amounts = fpdb_simple.calcPayin(len(h.names), h.buyin, h.fee) - - if h.base == "hold": - result = self.tourney_holdem_omaha( - h.config, h.settings, h.base, h.category, h.siteTourneyNo, h.buyin - , h.fee, h.knockout, h.entries, h.prizepool, h.tourneyStartTime - , payin_amounts, ranks, h.tourneyTypeId, h.siteID, h.siteHandNo - , h.gametypeID, h.handStartTime, h.names, h.playerIDs, h.startCashes - , h.positions, h.cardValues, h.cardSuits, h.boardValues, h.boardSuits - , h.winnings, h.rakes, h.actionTypes, h.allIns, h.actionAmounts - , h.actionNos, h.hudImportData, h.maxSeats, h.tableName, h.seatNos) - elif h.base == "stud": - result = self.tourney_stud( - h.config, h.settings, h.base, h.category, h.siteTourneyNo - , h.buyin, h.fee, h.knockout, h.entries, h.prizepool, h.tourneyStartTime - , payin_amounts, ranks, h.tourneyTypeId, h.siteID, h.siteHandNo - , h.gametypeID, h.handStartTime, h.names, h.playerIDs, h.startCashes - , h.antes, h.cardValues, h.cardSuits, h.winnings, h.rakes, h.actionTypes - , h.allIns, h.actionAmounts, h.actionNos, h.hudImportData, h.maxSeats - , h.tableName, h.seatNos) - else: - raise FpdbError("unrecognised category") - else: - if h.base == "hold": - result = self.ring_holdem_omaha( - h.config, h.settings, h.base, h.category, h.siteHandNo - , h.gametypeID, h.handStartTime, h.names, h.playerIDs - , h.startCashes, h.positions, h.cardValues, h.cardSuits - , h.boardValues, h.boardSuits, h.winnings, h.rakes - , h.actionTypes, h.allIns, h.actionAmounts, h.actionNos - , h.hudImportData, h.maxSeats, h.tableName, h.seatNos) - elif h.base == "stud": - result = self.ring_stud( - h.config, h.settings, h.base, h.category, h.siteHandNo, h.gametypeID - , h.handStartTime, h.names, h.playerIDs, h.startCashes, h.antes - , h.cardValues, h.cardSuits, h.winnings, h.rakes, h.actionTypes, h.allIns - , h.actionAmounts, h.actionNos, h.hudImportData, h.maxSeats, h.tableName - , h.seatNos) - else: - raise FpdbError("unrecognised category") - except: - print "Error storing hand: " + str(sys.exc_value) - self.rollback() - # re-raise the exception so that the calling routine can decide what to do: - # (e.g. a write thread might try again) - raise - - return result - #end def store_the_hand - ########################### # NEWIMPORT CODE ########################### @@ -2583,183 +2410,6 @@ class Database: #end def tRecogniseTourneyType - def tRecognizeTourney(self, tourney, dbTourneyTypeId): - logging.debug("Database.tRecognizeTourney") - tourneyID = 1 - # Check if tourney exists in db (based on tourney.siteId and tourney.tourNo) - # If so retrieve all data to check for consistency - cursor = self.get_cursor() - cursor.execute (self.sql.query['getTourney'].replace('%s', self.sql.query['placeholder']), - (tourney.tourNo, tourney.siteId) - ) - result=cursor.fetchone() - - expectedValuesDecimal = { 2 : "entries", 3 : "prizepool", 6 : "buyInChips", 9 : "rebuyChips", - 10 : "addOnChips", 11 : "rebuyAmount", 12 : "addOnAmount", 13 : "totalRebuys", - 14 : "totalAddOns", 15 : "koBounty" } - expectedValues = { 7 : "tourneyName", 16 : "tourneyComment" } - - tourneyDataMatch = True - tCommentTs = None - starttime = None - endtime = None - - try: - len(result) - tourneyID = result[0] - logging.debug("Tourney found in db with TourneyID = %d" % tourneyID) - if result[1] <> dbTourneyTypeId: - tourneyDataMatch = False - logging.debug("Tourney has wrong type ID (expected : %s - found : %s)" % (dbTourneyTypeId, result[1])) - if (tourney.starttime is None and result[4] is not None) or ( tourney.starttime is not None and fpdb_simple.parseHandStartTime("- %s" % tourney.starttime) <> result[4]) : - tourneyDataMatch = False - logging.debug("Tourney data mismatch : wrong starttime : Tourney=%s / db=%s" % (tourney.starttime, result[4])) - if (tourney.endtime is None and result[5] is not None) or ( tourney.endtime is not None and fpdb_simple.parseHandStartTime("- %s" % tourney.endtime) <> result[5]) : - tourneyDataMatch = False - logging.debug("Tourney data mismatch : wrong endtime : Tourney=%s / db=%s" % (tourney.endtime, result[5])) - - for ev in expectedValues : - if ( getattr( tourney, expectedValues.get(ev) ) <> result[ev] ): - logging.debug("Tourney data mismatch : wrong %s : Tourney=%s / db=%s" % (expectedValues.get(ev), getattr( tourney, expectedValues.get(ev)), result[ev]) ) - tourneyDataMatch = False - #break - for evD in expectedValuesDecimal : - if ( Decimal(getattr( tourney, expectedValuesDecimal.get(evD)) ) <> result[evD] ): - logging.debug("Tourney data mismatch : wrong %s : Tourney=%s / db=%s" % (expectedValuesDecimal.get(evD), getattr( tourney, expectedValuesDecimal.get(evD)), result[evD]) ) - tourneyDataMatch = False - #break - - # TO DO : Deal with matrix summary mutliple parsings - - except: - # Tourney not found : create - logging.debug("Tourney is not found : create") - if tourney.tourneyComment is not None : - tCommentTs = datetime.today() - if tourney.starttime is not None : - starttime = fpdb_simple.parseHandStartTime("- %s" % tourney.starttime) - if tourney.endtime is not None : - endtime = fpdb_simple.parseHandStartTime("- %s" % tourney.endtime) - # TODO : deal with matrix Id processed - cursor.execute (self.sql.query['insertTourney'].replace('%s', self.sql.query['placeholder']), - (dbTourneyTypeId, tourney.tourNo, tourney.entries, tourney.prizepool, starttime, - endtime, tourney.buyInChips, tourney.tourneyName, 0, tourney.rebuyChips, tourney.addOnChips, - tourney.rebuyAmount, tourney.addOnAmount, tourney.totalRebuys, tourney.totalAddOns, tourney.koBounty, - tourney.tourneyComment, tCommentTs) - ) - tourneyID = self.get_last_insert_id(cursor) - - - # Deal with inconsistent tourney in db - if tourneyDataMatch == False : - # Update Tourney - if result[16] <> tourney.tourneyComment : - tCommentTs = datetime.today() - if tourney.starttime is not None : - starttime = fpdb_simple.parseHandStartTime("- %s" % tourney.starttime) - if tourney.endtime is not None : - endtime = fpdb_simple.parseHandStartTime("- %s" % tourney.endtime) - - cursor.execute (self.sql.query['updateTourney'].replace('%s', self.sql.query['placeholder']), - (dbTourneyTypeId, tourney.entries, tourney.prizepool, starttime, - endtime, tourney.buyInChips, tourney.tourneyName, 0, tourney.rebuyChips, tourney.addOnChips, - tourney.rebuyAmount, tourney.addOnAmount, tourney.totalRebuys, tourney.totalAddOns, tourney.koBounty, - tourney.tourneyComment, tCommentTs, tourneyID) - ) - - return tourneyID - #end def tRecognizeTourney - - def tStoreTourneyPlayers(self, tourney, dbTourneyId): - logging.debug("Database.tStoreTourneyPlayers") - # First, get playerids for the players and specifically the one for hero : - playersIds = self.recognisePlayerIDs(tourney.players, tourney.siteId) - # hero may be None for matrix tourneys summaries -# hero = [ tourney.hero ] -# heroId = self.recognisePlayerIDs(hero , tourney.siteId) -# logging.debug("hero Id = %s - playersId = %s" % (heroId , playersIds)) - - tourneyPlayersIds=[] - try: - cursor = self.get_cursor() - - for i in xrange(len(playersIds)): - cursor.execute(self.sql.query['getTourneysPlayers'].replace('%s', self.sql.query['placeholder']) - ,(dbTourneyId, playersIds[i])) - result=cursor.fetchone() - #print "tried SELECTing tourneys_players.id:",tmp - - try: - len(result) - # checking data - logging.debug("TourneysPlayers found : checking data") - expectedValuesDecimal = { 1 : "payinAmounts", 2 : "finishPositions", 3 : "winnings", 4 : "countRebuys", - 5 : "countAddOns", 6 : "countKO" } - - tourneyPlayersIds.append(result[0]); - - tourneysPlayersDataMatch = True - for evD in expectedValuesDecimal : - if ( Decimal(getattr( tourney, expectedValuesDecimal.get(evD))[tourney.players[i]] ) <> result[evD] ): - logging.debug("TourneysPlayers data mismatch for TourneysPlayer id=%d, name=%s : wrong %s : Tourney=%s / db=%s" % (result[0], tourney.players[i], expectedValuesDecimal.get(evD), getattr( tourney, expectedValuesDecimal.get(evD))[tourney.players[i]], result[evD]) ) - tourneysPlayersDataMatch = False - #break - - if tourneysPlayersDataMatch == False: - logging.debug("TourneysPlayers data update needed") - cursor.execute (self.sql.query['updateTourneysPlayers'].replace('%s', self.sql.query['placeholder']), - (tourney.payinAmounts[tourney.players[i]], tourney.finishPositions[tourney.players[i]], - tourney.winnings[tourney.players[i]] , tourney.countRebuys[tourney.players[i]], - tourney.countAddOns[tourney.players[i]] , tourney.countKO[tourney.players[i]], - result[7], result[8], result[0]) - ) - - except TypeError: - logging.debug("TourneysPlayers not found : need insert") - cursor.execute (self.sql.query['insertTourneysPlayers'].replace('%s', self.sql.query['placeholder']), - (dbTourneyId, playersIds[i], - tourney.payinAmounts[tourney.players[i]], tourney.finishPositions[tourney.players[i]], - tourney.winnings[tourney.players[i]] , tourney.countRebuys[tourney.players[i]], - tourney.countAddOns[tourney.players[i]] , tourney.countKO[tourney.players[i]], - None, None) - ) - tourneyPlayersIds.append(self.get_last_insert_id(cursor)) - - except: - raise fpdb_simple.FpdbError( "tStoreTourneyPlayers error: " + str(sys.exc_value) ) - - return tourneyPlayersIds - #end def tStoreTourneyPlayers - - def tUpdateTourneysHandsPlayers(self, tourney, dbTourneysPlayersIds, dbTourneyTypeId): - logging.debug("Database.tCheckTourneysHandsPlayers") - try: - # Massive update seems to take quite some time ... -# query = self.sql.query['updateHandsPlayersForTTypeId2'] % (dbTourneyTypeId, self.sql.query['handsPlayersTTypeId_joiner'].join([self.sql.query['placeholder'] for id in dbTourneysPlayersIds]) ) -# cursor = self.get_cursor() -# cursor.execute (query, dbTourneysPlayersIds) - - query = self.sql.query['selectHandsPlayersWithWrongTTypeId'] % (dbTourneyTypeId, self.sql.query['handsPlayersTTypeId_joiner'].join([self.sql.query['placeholder'] for id in dbTourneysPlayersIds]) ) - #print "query : %s" % query - cursor = self.get_cursor() - cursor.execute (query, dbTourneysPlayersIds) - result=cursor.fetchall() - - if (len(result) > 0): - logging.debug("%d lines need update : %s" % (len(result), result) ) - listIds = [] - for i in result: - listIds.append(i[0]) - - query2 = self.sql.query['updateHandsPlayersForTTypeId'] % (dbTourneyTypeId, self.sql.query['handsPlayersTTypeId_joiner_id'].join([self.sql.query['placeholder'] for id in listIds]) ) - cursor.execute (query2, listIds) - else: - logging.debug("No need to update, HandsPlayers are correct") - - except: - raise fpdb_simple.FpdbError( "tStoreTourneyPlayers error: " + str(sys.exc_value) ) - #end def tUpdateTourneysHandsPlayers - # Class used to hold all the data needed to write a hand to the db # mainParser() in fpdb_parse_logic.py creates one of these and then passes it to diff --git a/pyfpdb/GuiBulkImport.py b/pyfpdb/GuiBulkImport.py index 16131ab2..a64a9425 100755 --- a/pyfpdb/GuiBulkImport.py +++ b/pyfpdb/GuiBulkImport.py @@ -30,7 +30,6 @@ import gtk import gobject # fpdb/FreePokerTools modules -import fpdb_simple import fpdb_import import Configuration import Exceptions diff --git a/pyfpdb/GuiTableViewer.py b/pyfpdb/GuiTableViewer.py index c730f962..57fc772d 100644 --- a/pyfpdb/GuiTableViewer.py +++ b/pyfpdb/GuiTableViewer.py @@ -20,7 +20,6 @@ import pygtk pygtk.require('2.0') import gtk import os -import fpdb_simple import fpdb_import import fpdb_db diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 2d7f2e0c..9f6993b9 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -38,7 +38,6 @@ except ImportError: logging.info("Not using numpy to define variance in sqlite.") use_numpy = False -import fpdb_simple import FpdbSQLQueries import Configuration diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 577562b8..a7a21831 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -35,10 +35,8 @@ import gtk # fpdb/FreePokerTools modules -import fpdb_simple import fpdb_db import Database -import fpdb_parse_logic import Configuration import Exceptions diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py deleted file mode 100644 index 6fac3669..00000000 --- a/pyfpdb/fpdb_parse_logic.py +++ /dev/null @@ -1,235 +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. - -#parses an in-memory fpdb hand history and calls db routine to store it - -import sys -from time import time, strftime -from Exceptions import * - -import fpdb_simple -import Database - -def mainParser(settings, siteID, category, hand, config, db = None, writeq = None): - """ mainParser for Holdem Hands """ - t0 = time() - backend = settings['db-backend'] - # Ideally db connection is passed in, if not use sql list if passed in, - # otherwise start from scratch - if db is None: - db = Database.Database(c = config, sql = None) - category = fpdb_simple.recogniseCategory(hand[0]) - - base = "hold" if (category == "holdem" or category == "omahahi" or - category == "omahahilo") else "stud" - - #part 0: create the empty arrays - # lineTypes valid values: header, name, cards, action, win, rake, ignore - # lineStreets valid values: predeal, preflop, flop, turn, river - lineTypes = [] - lineStreets = [] - cardValues = [] - cardSuits = [] - boardValues = [] - boardSuits = [] - antes = [] - allIns = [] - actionAmounts = [] - actionNos = [] - actionTypes = [] - actionTypeByNo = [] - seatLines = [] - winnings = [] - rakes = [] - - #part 1: read hand no and check for duplicate - siteHandNo = fpdb_simple.parseSiteHandNo(hand[0]) - handStartTime = fpdb_simple.parseHandStartTime(hand[0]) - isTourney = fpdb_simple.isTourney(hand[0]) - - smallBlindLine = None - for i, line in enumerate(hand): - if 'posts small blind' in line or 'posts the small blind' in line: - if line[-2:] == "$0": continue - smallBlindLine = i - break - else: - smallBlindLine = 0 - # If we did not find a small blind line, what happens? - # if we leave it at None, it errors two lines down. - - gametypeID = fpdb_simple.recogniseGametypeID(backend, db, db.get_cursor(), - hand[0], hand[smallBlindLine], - siteID, category, isTourney) - if isTourney: - siteTourneyNo = fpdb_simple.parseTourneyNo(hand[0]) - buyin = fpdb_simple.parseBuyin(hand[0]) - fee = fpdb_simple.parseFee(hand[0]) - entries = -1 #todo: parse this - prizepool = -1 #todo: parse this - knockout = False - tourneyStartTime= handStartTime #todo: read tourney start time - rebuyOrAddon = fpdb_simple.isRebuyOrAddon(hand[0]) - - # The tourney site id has to be searched because it may already be in - # db with a TourneyTypeId which is different from the one automatically - # calculated (Summary import first) - tourneyTypeId = fpdb_simple.recogniseTourneyTypeId(db, siteID, - siteTourneyNo, - buyin, fee, - knockout, - rebuyOrAddon) - else: - siteTourneyNo = -1 - buyin = -1 - fee = -1 - entries = -1 - prizepool = -1 - knockout = 0 - tourneyStartTime= None - rebuyOrAddon = -1 - - tourneyTypeId = 1 - fpdb_simple.isAlreadyInDB(db, gametypeID, siteHandNo) - - hand = fpdb_simple.filterCrap(hand, isTourney) - - #part 2: classify lines by type (e.g. cards, action, win, sectionchange) and street - fpdb_simple.classifyLines(hand, category, lineTypes, lineStreets) - - #part 3: read basic player info - #3a read player names, startcashes - for i, line in enumerate(hand): - if lineTypes[i] == "name": - seatLines.append(line) - - names = fpdb_simple.parseNames(seatLines) - playerIDs = db.recognisePlayerIDs(names, siteID) # inserts players as needed - tmp = fpdb_simple.parseCashesAndSeatNos(seatLines) - startCashes = tmp['startCashes'] - seatNos = tmp['seatNos'] - - fpdb_simple.createArrays(category, len(names), cardValues, cardSuits, antes, - winnings, rakes, actionTypes, allIns, - actionAmounts, actionNos, actionTypeByNo) - - #3b read positions - if base == "hold": - positions = fpdb_simple.parsePositions(hand, names) - - #part 4: take appropriate action for each line based on linetype - for i, line in enumerate(hand): - if lineTypes[i] == "cards": - fpdb_simple.parseCardLine(category, lineStreets[i], line, names, - cardValues, cardSuits, boardValues, - boardSuits) - #if category=="studhilo": - # print "hand[i]:", hand[i] - # print "cardValues:", cardValues - # print "cardSuits:", cardSuits - elif lineTypes[i] == "action": - fpdb_simple.parseActionLine(base, isTourney, line, lineStreets[i], - playerIDs, names, actionTypes, allIns, - actionAmounts, actionNos, actionTypeByNo) - elif lineTypes[i] == "win": - fpdb_simple.parseWinLine(line, names, winnings, isTourney) - elif lineTypes[i] == "rake": - totalRake = 0 if isTourney else fpdb_simple.parseRake(line) - fpdb_simple.splitRake(winnings, rakes, totalRake) - elif (lineTypes[i] == "header" or lineTypes[i] == "rake" or - lineTypes[i] == "name" or lineTypes[i] == "ignore"): - pass - elif lineTypes[i] == "ante": - fpdb_simple.parseAnteLine(line, isTourney, names, antes) - elif lineTypes[i] == "table": - tableResult=fpdb_simple.parseTableLine(base, line) - else: - raise FpdbError("unrecognised lineType:" + lineTypes[i]) - - maxSeats = tableResult['maxSeats'] - tableName = tableResult['tableName'] - #print "before part5, antes:", antes - - #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": - fpdb_simple.convertCardValuesBoard(boardValues) - fpdb_simple.convertBlindBet(actionTypes, actionAmounts) - fpdb_simple.checkPositions(positions) - - c = db.get_cursor() - c.execute("SELECT limitType FROM Gametypes WHERE id=%s" % (db.sql.query['placeholder'],), (gametypeID, )) - limit_type = c.fetchone()[0] - fpdb_simple.convert3B4B(category, limit_type, actionTypes, actionAmounts) - - 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, actionTypes, - actionAmounts, None) - else: - hudImportData = fpdb_simple.generateHudCacheData(playerIDs, base, - category, actionTypes, - allIns, actionTypeByNo, - winnings, - totalWinnings, None, - actionTypes, - actionAmounts, antes) - - try: - db.commit() # need to commit new players as different db connection used - # for other writes. maybe this will change maybe not ... - except: # TODO: this really needs to be narrowed down - print "parse: error during commit: " + str(sys.exc_value) - -# HERE's an ugly kludge to keep from failing when positions is undef -# We'll fix this by getting rid of the legacy importer. REB - try: - if positions: - pass - except NameError: - positions = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - # save data structures in a HandToWrite instance and then insert into database: - htw = Database.HandToWrite() - htw.set_all( config, settings, base, category, siteTourneyNo, buyin - , fee, knockout, entries, prizepool, tourneyStartTime - , isTourney, tourneyTypeId, siteID, siteHandNo - , gametypeID, handStartTime, names, playerIDs, startCashes - , positions, antes, cardValues, cardSuits, boardValues, boardSuits - , winnings, rakes, actionTypes, allIns, actionAmounts - , actionNos, hudImportData, maxSeats, tableName, seatNos) - - # save hand in db via direct call or via q if in a thread - if writeq is None: - result = db.store_the_hand(htw) - else: - writeq.put(htw) - result = -999 # meaning unknown - - t9 = time() - #print "parse and save=(%4.3f)" % (t9-t0) - return result -#end def mainParser - diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py deleted file mode 100644 index 5f0c6507..00000000 --- a/pyfpdb/fpdb_simple.py +++ /dev/null @@ -1,1728 +0,0 @@ -#!/usr/bin/python -# -*- coding: iso-8859-15 -*- - -#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 simple functions for fpdb - -#Aiming to eventually remove this module, functions will move to, eg: -#fpdb_db db create/re-create/management/etc -#Hands or related files for saving hands to db, etc - -import datetime -import time -import re -import sys -from Exceptions import * -import locale - -import Card - -PS = 1 -FTP = 2 - -# TODO: these constants are also used in fpdb_save_to_db and others, is there a way to do like C #define, and #include ? -# answer - yes. These are defined in fpdb_db so are accessible through that class. -MYSQL_INNODB = 2 -PGSQL = 3 -SQLITE = 4 - -LOCALE_ENCODING = locale.getdefaultlocale()[1] - -#returns an array of the total money paid. intending to add rebuys/addons here -def calcPayin(count, buyin, fee): - return [buyin + fee for i in xrange(count)] -#end def calcPayin - -def checkPositions(positions): - """ verify positions are valid """ - if any(not (p == "B" or p == "S" or (p >= 0 and p <= 9)) for p in positions): - raise FpdbError("invalid position '"+p+"' found in checkPositions") - ### RHH modified to allow for "position 9" here (pos==9 is when you're a dead hand before the BB - ### eric - position 8 could be valid - if only one blind is posted, but there's still 10 people, ie a sitout is present, and the small is dead... - -def classifyLines(hand, category, lineTypes, lineStreets): - """ makes a list of classifications for each line for further processing - manipulates passed arrays """ - currentStreet = "predeal" - done = False #set this to true once we reach the last relevant line (the summary, except rake, is all repeats) - for i, line in enumerate(hand): - if done: - if "[" not in line or "mucked [" not in line: - lineTypes.append("ignore") - else: - lineTypes.append("cards") - elif line.startswith("Dealt to"): - lineTypes.append("cards") - elif i == 0: - lineTypes.append("header") - elif line.startswith("Table '"): - lineTypes.append("table") - elif line.startswith("Seat ") and ( ("in chips" in line) or "($" in line): - lineTypes.append("name") - elif isActionLine(line): - lineTypes.append("action") - if " posts " in line or " posts the " in line: - currentStreet="preflop" - elif " antes " in line or " posts the ante " in line: - lineTypes.append("ante") - elif line.startswith("*** FLOP *** ["): - lineTypes.append("cards") - currentStreet="flop" - elif line.startswith("*** TURN *** ["): - lineTypes.append("cards") - currentStreet="turn" - elif line.startswith("*** RIVER *** ["): - lineTypes.append("cards") - currentStreet="river" - elif line.startswith("*** 3"): - lineTypes.append("ignore") - currentStreet=0 - elif line.startswith("*** 4"): - lineTypes.append("ignore") - currentStreet=1 - elif line.startswith("*** 5"): - lineTypes.append("ignore") - currentStreet=2 - elif line.startswith("*** 6"): - lineTypes.append("ignore") - currentStreet=3 - elif line.startswith("*** 7") or line == "*** RIVER ***": - lineTypes.append("ignore") - currentStreet=4 - elif isWinLine(line): - lineTypes.append("win") - elif line.startswith("Total pot ") and "Rake" in line: - lineTypes.append("rake") - done=True - elif "*** SHOW DOWN ***" in line or "*** SUMMARY ***" in line: - lineTypes.append("ignore") - #print "in classifyLine, showdown or summary" - elif " shows [" in line: - lineTypes.append("cards") - else: - raise FpdbError("unrecognised linetype in:"+hand[i]) - lineStreets.append(currentStreet) - -def convert3B4B(category, limit_type, actionTypes, actionAmounts): - """calculates the actual bet amounts in the given amount array and changes it accordingly.""" - for i in xrange(len(actionTypes)): - for j in xrange(len(actionTypes[i])): - bets = [] - for k in xrange(len(actionTypes[i][j])): - if (actionTypes[i][j][k] == "bet"): - bets.append((i,j,k)) - if (len(bets)>=2): - #print "len(bets) 2 or higher, need to correct it. bets:",bets,"len:",len(bets) - for betNo in reversed(xrange (1,len(bets))): - amount2 = actionAmounts[bets[betNo][0]][bets[betNo][1]][bets[betNo][2]] - amount1 = actionAmounts[bets[betNo-1][0]][bets[betNo-1][1]][bets[betNo-1][2]] - actionAmounts[bets[betNo][0]][bets[betNo][1]][bets[betNo][2]] = amount2 - amount1 - -def convertBlindBet(actionTypes, actionAmounts): - """ Corrects the bet amount if the player had to pay blinds """ - i = 0#setting street to pre-flop - for j in xrange(len(actionTypes[i])):#playerloop - blinds = [] - bets = [] - for k in xrange(len(actionTypes[i][j])): - if actionTypes[i][j][k] == "blind": - blinds.append((i,j,k)) - - if blinds and actionTypes[i][j][k] == "bet": - bets.append((i,j,k)) - if len(bets) == 1: - blind_amount=actionAmounts[blinds[0][0]][blinds[0][1]][blinds[0][2]] - bet_amount=actionAmounts[bets[0][0]][bets[0][1]][bets[0][2]] - actionAmounts[bets[0][0]][bets[0][1]][bets[0][2]] = bet_amount - blind_amount - -#converts the strings in the given array to ints (changes the passed array, no returning). see table design for conversion details -#todo: make this use convertCardValuesBoard -def convertCardValues(arr): - map(convertCardValuesBoard, arr) - -# a 0-card is one in a stud game that we did not see or was not shown -card_map = { 0: 0, "2": 2, "3" : 3, "4" : 4, "5" : 5, "6" : 6, "7" : 7, "8" : 8, - "9" : 9, "T" : 10, "J" : 11, "Q" : 12, "K" : 13, "A" : 14} - -def convertCardValuesBoard(arr): - """ converts the strings in the given array to ints - (changes the passed array, no returning). see table design for - conversion details """ - for i in xrange(len(arr)): - arr[i] = card_map[arr[i]] - -def createArrays(category, seats, card_values, card_suits, antes, winnings, - rakes, action_types, allIns, action_amounts, actionNos, - actionTypeByNo): - """ this creates the 2D/3D arrays. manipulates the passed arrays instead of returning. """ - for i in xrange(seats):#create second dimension arrays - card_values.append( [] ) - card_suits.append( [] ) - antes.append(0) - winnings.append(0) - rakes.append(0) - - streetCount = 4 if (category == "holdem" or category == "omahahi" or - category == "omahahilo") else 5 - - for i in xrange(streetCount): #build the first dimension array, for streets - action_types.append([]) - allIns.append([]) - action_amounts.append([]) - actionNos.append([]) - actionTypeByNo.append([]) - for j in xrange(seats): # second dimension arrays: players - action_types[i].append([]) - allIns[i].append([]) - action_amounts[i].append([]) - actionNos[i].append([]) -# if (category=="holdem" or category=="omahahi" or category=="omahahilo"): -# pass - if category == "razz" or category == "studhi" or category == "studhilo": #need to fill card arrays. - for i in xrange(seats): - for j in xrange(7): - card_values[i].append(0) - card_suits[i].append("x") -# else: -# raise FpdbError("invalid category") -#end def createArrays - -def fill_board_cards(board_values, board_suits): - """ fill up the two board card arrays """ - while len(board_values) < 5: - board_values.append(0) - board_suits.append("x") - -def fillCardArrays(player_count, base, category, card_values, card_suits): - """fills up the two card arrays""" - if category == "holdem": - cardCount = 2 - elif category == "omahahi" or category == "omahahilo": - cardCount = 4 - elif base == "stud": - cardCount = 7 - else: - raise FpdbError("invalid category:", category) - - for i in xrange(player_count): - while len(card_values[i]) < cardCount: - card_values[i].append(0) - card_suits[i].append("x") -#end def fillCardArrays - -#filters out a player that folded before paying ante or blinds. This should be called -#before calling the actual hand parser. manipulates hand, no return. -def filterAnteBlindFold(hand): - #todo: this'll only get rid of one ante folder, not multiple ones - #todo: in tourneys this should not be removed but - #print "start of filterAnteBlindFold" - pre3rd = [] - for i, line in enumerate(hand): - if line.startswith("*** 3") or line.startswith("*** HOLE"): - pre3rd = hand[0:i] - - foldeeName = None - for line in pre3rd: - if line.endswith("folds") or line.endswith("is sitting out") or line.endswith(" stands up"): #found ante fold or timeout - pos = line.find(" folds") - foldeeName = line[0:pos] - if pos == -1 and " in chips)" not in line: - pos = line.find(" is sitting out") - foldeeName = line[0:pos] - if pos == -1: - pos = line.find(" stands up") - foldeeName = line[0:pos] - if pos == -1: - pos1 = line.find(": ") + 2 - pos2 = line.find(" (") - foldeeName = line[pos1:pos2] - - if foldeeName is not None: - #print "filterAnteBlindFold, foldeeName:",foldeeName - for i, line in enumerate(hand): - if foldeeName in line: - hand[i] = None - - return [line for line in hand if line] - -def stripEOLspaces(str): - return str.rstrip() - -def filterCrap(hand, isTourney): - """ removes useless lines as well as trailing spaces """ - - #remove trailing spaces at end of line - hand = [line.rstrip() for line in hand] - - #general variable position word filter/string filter - for i in xrange(len(hand)): - if hand[i].startswith("Board ["): - hand[i] = False - elif hand[i].find(" out of hand ")!=-1: - hand[i]=hand[i][:-56] - elif "($0 in chips)" in hand[i]: - hand[i] = False - elif hand[i]=="*** HOLE CARDS ***": - hand[i] = False - elif hand[i].endswith("has been disconnected"): - hand[i] = False - elif hand[i].endswith("has requested TIME"): - hand[i] = False - elif hand[i].endswith("has returned"): - hand[i] = False - elif hand[i].endswith("will be allowed to play after the button"): - hand[i] = False - elif hand[i].endswith("has timed out"): - hand[i] = False - elif hand[i].endswith("has timed out while disconnected"): - hand[i] = False - elif hand[i].endswith("has timed out while being disconnected"): - hand[i] = False - elif hand[i].endswith("is connected"): - hand[i] = False - elif hand[i].endswith("is disconnected"): - hand[i] = False - elif hand[i].find(" is low with [")!=-1: - hand[i] = False - elif hand[i].endswith(" mucks"): - hand[i] = False - elif hand[i].endswith(": mucks hand"): - hand[i] = False - elif hand[i] == "No low hand qualified": - hand[i] = False - elif hand[i] == "Pair on board - a double bet is allowed": - hand[i] = False - elif " shows " in hand[i] and "[" not in hand[i]: - hand[i] = False - elif hand[i].startswith("The button is in seat #"): - hand[i] = False - #above is alphabetic, reorder below if bored - elif hand[i].startswith("Time has expired"): - hand[i] = False - elif hand[i].endswith("has reconnected"): - hand[i] = False - elif hand[i].endswith("seconds left to act"): - hand[i] = False - elif hand[i].endswith("seconds to reconnect"): - hand[i] = False - elif hand[i].endswith("was removed from the table for failing to post"): - hand[i] = False - elif "joins the table at seat " in hand[i]: - hand[i] = False - elif (hand[i].endswith("leaves the table")): - hand[i] = False - elif "is high with " in hand[i]: - hand[i] = False - elif hand[i].endswith("doesn't show hand"): - hand[i] = False - elif hand[i].endswith("is being treated as all-in"): - hand[i] = False - elif " adds $" in hand[i]: - hand[i] = False - elif hand[i] == "Betting is capped": - hand[i] = False - elif (hand[i].find(" said, \"")!=-1): - hand[i] = False - - if isTourney and not hand[i] == False: - if (hand[i].endswith(" is sitting out") and (not hand[i].startswith("Seat "))): - hand[i] = False - elif hand[i]: - if (hand[i].endswith(": sits out")): - hand[i] = False - elif (hand[i].endswith(" is sitting out")): - hand[i] = False - # python docs say this is identical to filter(None, list) - # which removes all false items from the passed list (hand) - hand = [line for line in hand if line] - - return hand - -def float2int(string): - """ takes a poker float (including , for thousand seperator) and - converts it to an int """ - # Note that this automagically assumes US style currency formatters - pos = string.find(",") - if pos != -1: #remove , the thousand seperator - string = "%s%s" % (string[0:pos], string[pos+1:]) - - pos = string.find(".") - if pos != -1: #remove decimal point - string = "%s%s" % (string[0:pos], string[pos+1:]) - - result = int(string) - if pos == -1: #no decimal point - was in full dollars - need to multiply with 100 - result *= 100 - return result - -ActionLines = ( "calls $", ": calls ", "brings in for", "completes it to", - "posts small blind", "posts the small blind", "posts big blind", - "posts the big blind", "posts small & big blinds", "posts $", - "posts a dead", "bets $", ": bets ", " raises") - -def isActionLine(line): - if line.endswith("folds"): - return True - elif line.endswith("checks"): - return True - elif line.startswith("Uncalled bet"): - return True - - # searches for each member of ActionLines being in line, returns true - # on first match .. neat func - return any(x for x in ActionLines if x in line) - -def isAlreadyInDB(db, gametypeID, siteHandNo): - c = db.get_cursor() - c.execute(db.sql.query['isAlreadyInDB'], (gametypeID, siteHandNo)) - result = c.fetchall() - if len(result) >= 1: - raise DuplicateError ("dupl") - -def isRebuyOrAddon(topline): - """isRebuyOrAddon not implemented yet""" - return False - -#returns whether the passed topline indicates a tournament or not -def isTourney(topline): - return "Tournament" in topline - -WinLines = ( "wins the pot", "ties for the ", "wins side pot", "wins the low main pot", "wins the high main pot", - "wins the low", - "wins the high pot", "wins the high side pot", "wins the main pot", "wins the side pot", "collected" ) - -def isWinLine(line): - """ returns boolean whether the passed line is a win line """ - return any(x for x in WinLines if x in line) - -#returns the amount of cash/chips put into the put in the given action line -def parseActionAmount(line, atype, isTourney): - #if (line.endswith(" and is all-in")): - # line=line[:-14] - #elif (line.endswith(", and is all in")): - # line=line[:-15] - - #ideally we should recognise this as an all-in if category is capXl - if line.endswith(", and is capped"): - line=line[:-15] - if line.endswith(" and is capped"): - line=line[:-14] - - if atype == "fold" or atype == "check": - amount = 0 - elif atype == "unbet": - pos1 = line.find("$") + 1 - if pos1 == 0: - pos1 = line.find("(") + 1 - pos2 = line.find(")") - amount = float2int(line[pos1:pos2]) - elif atype == "bet" and ": raises $" in line and "to $" in line: - pos = line.find("to $")+4 - amount = float2int(line[pos:]) - else: - if not isTourney: - pos = line.rfind("$")+1 - #print "parseActionAmount, line:", line, "line[pos:]:", line[pos:] - amount = float2int(line[pos:]) - else: - #print "line:"+line+"EOL" - pos = line.rfind(" ")+1 - #print "pos:",pos - #print "pos of 20:", line.find("20") - amount = int(line[pos:]) - - if atype == "unbet": - amount *= -1 - return amount -#end def parseActionAmount - -#doesnt return anything, simply changes the passed arrays action_types and -# action_amounts. For stud this expects numeric streets (3-7), for -# holdem/omaha it expects predeal, preflop, flop, turn or river -def parseActionLine(base, isTourney, line, street, playerIDs, names, action_types, allIns, action_amounts, actionNos, actionTypeByNo): - if street == "predeal" or street == "preflop": - street = 0 - elif street == "flop": - street = 1 - elif street == "turn": - street = 2 - elif street == "river": - street = 3 - - nextActionNo = 0 - for player in xrange(len(actionNos[street])): - for count in xrange(len(actionNos[street][player])): - if actionNos[street][player][count]>=nextActionNo: - nextActionNo=actionNos[street][player][count]+1 - - (line, allIn) = goesAllInOnThisLine(line) - atype = parseActionType(line) - playerno = recognisePlayerNo(line, names, atype) - amount = parseActionAmount(line, atype, isTourney) - - action_types[street][playerno].append(atype) - allIns[street][playerno].append(allIn) - action_amounts[street][playerno].append(amount) - actionNos[street][playerno].append(nextActionNo) - tmp=(playerIDs[playerno], atype) - actionTypeByNo[street].append(tmp) - -def goesAllInOnThisLine(line): - """returns whether the player went all-in on this line and removes the all-in text from the line.""" - isAllIn = False - if (line.endswith(" and is all-in")): - line = line[:-14] - isAllIn = True - elif (line.endswith(", and is all in")): - line = line[:-15] - isAllIn = True - return (line, isAllIn) - -#returns the action type code (see table design) of the given action line -ActionTypes = { 'brings in for' :"blind", - ' posts $' :"blind", - ' posts a dead ' :"blind", - ' posts the small blind of $' :"blind", - ': posts big blind ' :"blind", - ': posts small blind ' :"blind", - ' posts the big blind of $' :"blind", - ': posts small & big blinds $' :"blind", - ': posts small blind $' :"blind", - 'calls' :"call", - 'completes it to' :"bet", - ' bets' :"bet", - ' raises' :"bet" - } -def parseActionType(line): - if (line.startswith("Uncalled bet")): - return "unbet" - elif (line.endswith(" folds")): - return "fold" - elif (line.endswith(" checks")): - return "check" - else: - for x in ActionTypes: - if x in line: - return ActionTypes[x] - raise FpdbError ("failed to recognise actiontype in parseActionLine in: "+line) - -#parses the ante out of the given line and checks which player paid it, updates antes accordingly. -def parseAnteLine(line, isTourney, names, antes): - for i, name in enumerate(names): - if line.startswith(name.encode(LOCALE_ENCODING)): - pos = line.rfind("$") + 1 - if not isTourney: - antes[i] += float2int(line[pos:]) - else: - if "all-in" not in line: - pos = line.rfind(" ") + 1 - antes[i] += int(line[pos:]) - else: - pos1 = line.rfind("ante") + 5 - pos2 = line.find(" ", pos1) - antes[i] += int(line[pos1:pos2]) - -#returns the buyin of a tourney in cents -def parseBuyin(topline): - pos1 = topline.find("$")+1 - if pos1 != 0: - pos2 = topline.find("+") - else: - pos1 = topline.find("€")+3 - pos2 = topline.find("+") - return float2int(topline[pos1:pos2]) - -#parses a card line and changes the passed arrays accordingly -#todo: reorganise this messy method -def parseCardLine(category, street, line, names, cardValues, cardSuits, boardValues, boardSuits): - if line.startswith("Dealt to") or " shows [" in line or "mucked [" in line: - playerNo = recognisePlayerNo(line, names, "card") #anything but unbet will be ok for that string - - pos = line.rfind("[")+1 - if category == "holdem": - for i in (pos, pos+3): - cardValues[playerNo].append(line[i:i+1]) - cardSuits[playerNo].append(line[i+1:i+2]) - if len(cardValues[playerNo]) != 2: - if (cardValues[playerNo][0] == cardValues[playerNo][2] and - cardSuits[playerNo][1] == cardSuits[playerNo][3]): - cardValues[playerNo]=cardValues[playerNo][0:2] - cardSuits[playerNo]=cardSuits[playerNo][0:2] - else: - print "line:",line,"cardValues[playerNo]:",cardValues[playerNo] - raise FpdbError("read too many/too few holecards in parseCardLine") - elif category == "omahahi" or category == "omahahilo": - for i in (pos, pos+3, pos+6, pos+9): - cardValues[playerNo].append(line[i:i+1]) - cardSuits[playerNo].append(line[i+1:i+2]) - if (len(cardValues[playerNo])!=4): - if (cardValues[playerNo][0] == cardValues[playerNo][4] and - cardSuits[playerNo][3] == cardSuits[playerNo][7]): #two tests will do - cardValues[playerNo] = cardValues[playerNo][0:4] - cardSuits[playerNo] = cardSuits[playerNo][0:4] - else: - print "line:",line,"cardValues[playerNo]:",cardValues[playerNo] - raise FpdbError("read too many/too few holecards in parseCardLine") - elif category == "razz" or category == "studhi" or category == "studhilo": - if "shows" not in line and "mucked" not in line: - #print "parseCardLine(in stud if), street:", street - if line[pos+2]=="]": #-> not (hero and 3rd street) - cardValues[playerNo][street+2]=line[pos:pos+1] - cardSuits[playerNo][street+2]=line[pos+1:pos+2] - else: - #print "hero card1:", line[pos:pos+2], "hero card2:", line[pos+3:pos+5], "hero card3:", line[pos+6:pos+8], - cardValues[playerNo][street]=line[pos:pos+1] - cardSuits[playerNo][street]=line[pos+1:pos+2] - cardValues[playerNo][street+1]=line[pos+3:pos+4] - cardSuits[playerNo][street+1]=line[pos+4:pos+5] - cardValues[playerNo][street+2]=line[pos+6:pos+7] - cardSuits[playerNo][street+2]=line[pos+7:pos+8] - else: - #print "parseCardLine(in stud else), street:", street - cardValues[playerNo][0]=line[pos:pos+1] - cardSuits[playerNo][0]=line[pos+1:pos+2] - pos+=3 - cardValues[playerNo][1]=line[pos:pos+1] - cardSuits[playerNo][1]=line[pos+1:pos+2] - if street==4: - pos=pos=line.rfind("]")-2 - cardValues[playerNo][6]=line[pos:pos+1] - cardSuits[playerNo][6]=line[pos+1:pos+2] - #print "cardValues:", cardValues - #print "cardSuits:", cardSuits - else: - print "line:",line,"street:",street - raise FpdbError("invalid category") - #print "end of parseCardLine/playercards, cardValues:",cardValues - elif (line.startswith("*** FLOP ***")): - pos=line.find("[")+1 - for i in (pos, pos+3, pos+6): - boardValues.append(line[i:i+1]) - boardSuits.append(line[i+1:i+2]) - #print boardValues - elif (line.startswith("*** TURN ***") or line.startswith("*** RIVER ***")): - pos=line.find("[")+1 - pos=line.find("[", pos+1)+1 - boardValues.append(line[pos:pos+1]) - boardSuits.append(line[pos+1:pos+2]) - #print boardValues - else: - raise FpdbError ("unrecognised line:"+line) - -def parseCashesAndSeatNos(lines): - """parses the startCashes and seatNos of each player out of the given lines and returns them as a dictionary of two arrays""" - cashes = [] - seatNos = [] - for i in xrange (len(lines)): - pos2=lines[i].find(":") - seatNos.append(int(lines[i][5:pos2])) - - pos1=lines[i].rfind("($")+2 - if pos1==1: #for tourneys - it's 1 instead of -1 due to adding 2 above - pos1=lines[i].rfind("(")+1 - pos2=lines[i].find(" in chips") - cashes.append(float2int(lines[i][pos1:pos2])) - return {'startCashes':cashes, 'seatNos':seatNos} - -#returns the buyin of a tourney in cents -def parseFee(topline): - pos1 = topline.find("$")+1 - if pos1 != 0: - pos1 = topline.find("$", pos1)+1 - pos2 = topline.find(" ", pos1) - else: - pos1 = topline.find("€")+3 - pos1 = topline.find("€", pos1)+3 - pos2 = topline.find(" ", pos1) - return float2int(topline[pos1:pos2]) - -#returns a datetime object with the starttime indicated in the given topline -def parseHandStartTime(topline): - #convert x:13:35 to 0x:13:35 - counter=0 - while counter < 10: - pos = topline.find(" %d:" % counter) - if pos != -1: - topline = "%s0%s" % (topline[0:pos+1], topline[pos+1:]) - break - counter += 1 - - isUTC=False - if topline.find("UTC")!=-1: - pos1 = topline.find("-")+2 - pos2 = topline.find("UTC") - tmp=topline[pos1:pos2] - isUTC=True - else: - tmp=topline - #print "parsehandStartTime, tmp:", tmp - pos = tmp.find("-")+2 - tmp = tmp[pos:] - #Need to match either - # 2008/09/07 06:23:14 ET or - # 2008/08/17 - 01:14:43 (ET) or - # 2008/11/12 9:33:31 CET [2008/11/12 3:33:31 ET] - rexx = '(?P[0-9]{4})\/(?P[0-9]{2})\/(?P[0-9]{2})[\- ]+(?P
[0-9]+):(?P[0-9]+):(?P[0-9]+)' - m = re.search(rexx,tmp) - result = datetime.datetime(int(m.group('YEAR')), int(m.group('MON')), int(m.group('DAY')), int(m.group('HR')), int(m.group('MIN')), int(m.group('SEC'))) - - if not isUTC: #these use US ET - result += datetime.timedelta(hours=5) - - return result - -#parses the names out of the given lines and returns them as an array -def findName(line): - pos1 = line.find(":") + 2 - pos2 = line.rfind("(") - 1 - return unicode(line[pos1:pos2], LOCALE_ENCODING) - -def parseNames(lines): - return [findName(line) for line in lines] - -def parsePositions(hand, names): - positions = [-1 for i in names] - sb, bb = -1, -1 - - for line in hand: - if sb == -1 and "small blind" in line and "dead small blind" not in line: - sb = line - if bb == -1 and "big blind" in line and "dead big blind" not in line: - bb = line - -#identify blinds -#print "parsePositions before recognising sb/bb. names:",names - sbExists = True - if sb != -1: - sb = recognisePlayerNo(sb, names, "bet") - else: - sbExists = False - if bb != -1: - bb = recognisePlayerNo(bb, names, "bet") - -# print "sb = ", sb, "bb = ", bb - if bb == sb: # if big and small are same, then don't duplicate the small - sbExists = False - sb = -1 - - #write blinds into array - if sbExists: - positions[sb]="S" - positions[bb]="B" - - #fill up rest of array - arraypos = sb - 1 if sbExists else bb - 1 - - distFromBtn=0 - while arraypos >= 0 and arraypos != bb: - #print "parsePositions first while, arraypos:",arraypos,"positions:",positions - positions[arraypos] = distFromBtn - arraypos -= 1 - distFromBtn += 1 - - # eric - this takes into account dead seats between blinds - if sbExists: - i = bb - 1 - while positions[i] < 0 and i != sb: - positions[i] = 9 - i -= 1 - ### RHH - Changed to set the null seats before BB to "9" - i = sb - 1 if sbExists else bb - 1 - - while positions[i] < 0: - positions[i]=9 - i-=1 - - arraypos=len(names)-1 - if (bb!=0 or (bb==0 and sbExists==False) or (bb == 1 and sb != arraypos) ): - while (arraypos > bb and arraypos > sb): - positions[arraypos] = distFromBtn - arraypos -= 1 - distFromBtn += 1 - - if any(p == -1 for p in positions): - print "parsePositions names:",names - print "result:",positions - raise FpdbError ("failed to read positions") -# print str(positions), "\n" - return positions - -#simply parses the rake amount and returns it as an int -def parseRake(line): - pos = line.find("Rake")+6 - rake = float2int(line[pos:]) - return rake - -def parseSiteHandNo(topline): - """returns the hand no assigned by the poker site""" - pos1 = topline.find("#")+1 - pos2 = topline.find(":") - return topline[pos1:pos2] - -def parseTableLine(base, line): - """returns a dictionary with maxSeats and tableName""" - pos1=line.find('\'')+1 - pos2=line.find('\'', pos1) - #print "table:",line[pos1:pos2] - pos3=pos2+2 - pos4=line.find("-max") - #print "seats:",line[pos3:pos4] - return {'maxSeats':int(line[pos3:pos4]), 'tableName':line[pos1:pos2]} -#end def parseTableLine - -#returns the hand no assigned by the poker site -def parseTourneyNo(topline): - pos1 = topline.find("Tournament #")+12 - pos2 = topline.find(",", pos1) - #print "parseTourneyNo pos1:",pos1," pos2:",pos2, " result:",topline[pos1:pos2] - return topline[pos1:pos2] - -#parses a win/collect line. manipulates the passed array winnings, no explicit return -def parseWinLine(line, names, winnings, isTourney): - #print "parseWinLine: line:",line - for i,n in enumerate(names): - n = n.encode(LOCALE_ENCODING) - if line.startswith(n): - if isTourney: - pos1 = line.rfind("collected ") + 10 - pos2 = line.find(" ", pos1) - winnings[i] += int(line[pos1:pos2]) - else: - pos1 = line.rfind("$") + 1 - pos2 = line.find(" ", pos1) - winnings[i] += float2int(line[pos1:pos2]) - -#returns the category (as per database) string for the given line -def recogniseCategory(line): - if "Razz" in line: - return "razz" - elif "Hold'em" in line: - return "holdem" - elif "Omaha" in line: - if "Hi/Lo" not in line and "H/L" not in line: - return "omahahi" - else: - return "omahahilo" - elif "Stud" in line: - if "Hi/Lo" not in line and "H/L" not in line: - return "studhi" - else: - return "studhilo" - else: - raise FpdbError("failed to recognise category, line:"+line) - -#returns the int for the gametype_id for the given line -def recogniseGametypeID(backend, db, cursor, topline, smallBlindLine, site_id, category, isTourney):#todo: this method is messy - #if (topline.find("HORSE")!=-1): - # raise FpdbError("recogniseGametypeID: HORSE is not yet supported.") - - #note: the below variable names small_bet and big_bet are misleading, in NL/PL they mean small/big blind - if isTourney: - type = "tour" - pos1 = topline.find("(")+1 - if(topline[pos1] == "H" or topline[pos1] == "O" or - topline[pos1] == "R" or topline[pos1]=="S" or - topline[pos1+2] == "C"): - pos1 = topline.find("(", pos1)+1 - pos2 = topline.find("/", pos1) - small_bet = int(topline[pos1:pos2]) - else: - type = "ring" - pos1 = topline.find("$")+1 - pos2 = topline.find("/$") - small_bet = float2int(topline[pos1:pos2]) - - pos1 = pos2+2 - if isTourney: - pos1 -= 1 - pos2 = topline.find(")") - - if pos2 <= pos1: - pos2 = topline.find(")", pos1) - - if isTourney: - big_bet = int(topline[pos1:pos2]) - else: - big_bet = float2int(topline[pos1:pos2]) - - if 'No Limit' in topline: - limit_type = "nl" if 'Cap No' not in topline else "cn" - elif 'Pot Limit' in topline: - limit_type = "pl" if 'Cap Pot' not in topline else "cp" - else: - limit_type = "fl" - - #print "recogniseGametypeID small_bet/blind:",small_bet,"big bet/blind:", big_bet,"limit type:",limit_type - if limit_type == "fl": - cursor.execute(db.sql.query['getGametypeFL'], (site_id, type, category, - limit_type, small_bet, - big_bet)) - else: - cursor.execute(db.sql.query['getGametypeNL'], (site_id, type, category, - limit_type, small_bet, - big_bet)) - result = cursor.fetchone() - #print "recgt1 result=",result - #ret=result[0] - #print "recgt1 ret=",ret - #print "tried SELECTing gametypes.id, result:",result - - try: - len(result) - except TypeError: - if category=="holdem" or category=="omahahi" or category=="omahahilo": - base="hold" - else: - base="stud" - - if category=="holdem" or category=="omahahi" or category=="studhi": - hiLo='h' - elif category=="razz": - hiLo='l' - else: - hiLo='s' - - if (limit_type=="fl"): - big_blind=small_bet - if base=="hold": - if smallBlindLine==topline: - raise FpdbError("invalid small blind line") - elif isTourney: - pos=smallBlindLine.rfind(" ")+1 - small_blind=int(smallBlindLine[pos:]) - else: - pos=smallBlindLine.rfind("$")+1 - small_blind=float2int(smallBlindLine[pos:]) - else: - small_blind=0 - result = db.insertGameTypes( (site_id, type, base, category, limit_type, hiLo - ,small_blind, big_blind, small_bet, big_bet) ) - #cursor.execute ("SELECT id FROM Gametypes WHERE siteId=%s AND type=%s AND category=%s - #AND limitType=%s AND smallBet=%s AND bigBet=%s", (site_id, type, category, limit_type, small_bet, big_bet)) - else: - result = db.insertGameTypes( (site_id, type, base, category, limit_type, hiLo - ,small_bet, big_bet, 0, 0) )#remember, for these bet means blind - #cursor.execute ("SELECT id FROM Gametypes WHERE siteId=%s AND type=%s AND category=%s - #AND limitType=%s AND smallBlind=%s AND bigBlind=%s", (site_id, type, category, limit_type, small_bet, big_bet)) - - return result[0] -#end def recogniseGametypeID - -def recogniseTourneyTypeId(db, siteId, tourneySiteId, buyin, fee, knockout, rebuyOrAddon): - ret = -1 - cursor = db.get_cursor() - # First we try to find the tourney itself (by its tourneySiteId) in case it has already been inserted before (by a summary file for instance) - # The reason is that some tourneys may not be identified correctly in the HH toplines (especially Buy-In and Fee which are used to search/create the TourneyTypeId) - #TODO: When the summary file will be dumped to BD, if the tourney is already in, Buy-In/Fee may need an update (e.g. creation of a new type and link to the Tourney) - cursor.execute (db.sql.query['getTourneyTypeIdByTourneyNo'].replace('%s', db.sql.query['placeholder']), (tourneySiteId, siteId)) - result = cursor.fetchone() - - try: - len(result) - ret = result[0] - except: - cursor.execute( """SELECT id FROM TourneyTypes - WHERE siteId=%s AND buyin=%s AND fee=%s - AND knockout=%s AND rebuyOrAddon=%s""".replace('%s', db.sql.query['placeholder']) - , (siteId, buyin, fee, knockout, rebuyOrAddon) ) - result = cursor.fetchone() - #print "tried selecting tourneytypes.id, result:", result - - try: - len(result) - ret = result[0] - except TypeError:#this means we need to create a new entry - #print "insert new tourneytype record ..." - try: - cursor.execute( """INSERT INTO TourneyTypes (siteId, buyin, fee, knockout, rebuyOrAddon) - VALUES (%s, %s, %s, %s, %s)""".replace('%s', db.sql.query['placeholder']) - , (siteId, buyin, fee, knockout, rebuyOrAddon) ) - ret = db.get_last_insert_id(cursor) - except: - #print "maybe tourneytype was created since select, try selecting again ..." - cursor.execute( """SELECT id FROM TourneyTypes - WHERE siteId=%s AND buyin=%s AND fee=%s - AND knockout=%s AND rebuyOrAddon=%s""".replace('%s', db.sql.query['placeholder']) - , (siteId, buyin, fee, knockout, rebuyOrAddon) ) - result = cursor.fetchone() - try: - len(result) - ret = result[0] - except: - print "Failed to find or insert TourneyTypes record" - ret = -1 # failed to find or insert record - #print "tried selecting tourneytypes.id again, result:", result - - #print "recogniseTourneyTypeId: returning", ret - return ret -#end def recogniseTourneyTypeId - - -#recognises the name in the given line and returns its array position in the given array -def recognisePlayerNo(line, names, atype): - #print "recogniseplayerno, names:",names - for i in xrange(len(names)): - encodedName = names[i].encode(LOCALE_ENCODING) - if (atype=="unbet"): - if (line.endswith(encodedName)): - return (i) - elif (line.startswith("Dealt to ")): - #print "recognisePlayerNo, card precut, line:",line - tmp=line[9:] - #print "recognisePlayerNo, card postcut, tmp:",tmp - if (tmp.startswith(encodedName)): - return (i) - elif (line.startswith("Seat ")): - if (line.startswith("Seat 10")): - tmp=line[9:] - else: - tmp=line[8:] - - if (tmp.startswith(encodedName)): - return (i) - else: - if (line.startswith(encodedName)): - return (i) - #if we're here we mustve failed - raise FpdbError ("failed to recognise player in: "+line+" atype:"+atype) -#end def recognisePlayerNo - - -#removes trailing \n from the given array -def removeTrailingEOL(arr): - for i in xrange(len(arr)): - if (arr[i].endswith("\n")): - #print "arr[i] before removetrailingEOL:", arr[i] - arr[i]=arr[i][:-1] - #print "arr[i] after removetrailingEOL:", arr[i] - return arr -#end def removeTrailingEOL - -#splits the rake according to the proportion of pot won. manipulates the second passed array. -def splitRake(winnings, rakes, totalRake): - winnercnt=0 - totalWin=0 - for i in xrange(len(winnings)): - if winnings[i]!=0: - winnercnt+=1 - totalWin+=winnings[i] - firstWinner=i - if winnercnt==1: - rakes[firstWinner]=totalRake - else: - totalWin=float(totalWin) - for i in xrange(len(winnings)): - if winnings[i]!=0: - winPortion=winnings[i]/totalWin - rakes[i]=totalRake*winPortion -#end def splitRake - -def generateHudCacheData(player_ids, base, category, action_types, allIns, actionTypeByNo - ,winnings, totalWinnings, positions, actionTypes, actionAmounts, antes): - """calculates data for the HUD during import. IMPORTANT: if you change this method make -sure to also change the following storage method and table_viewer.prepare_data if necessary -""" - #print "generateHudCacheData, len(player_ids)=", len(player_ids) - #setup subarrays of the result dictionary. - 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=[] - hudDataPositions=[] - - street0Calls=[] - street1Calls=[] - street2Calls=[] - street3Calls=[] - street4Calls=[] - street0Bets=[] - street1Bets=[] - street2Bets=[] - street3Bets=[] - street4Bets=[] - #street0Raises=[] - #street1Raises=[] - #street2Raises=[] - #street3Raises=[] - #street4Raises=[] - - # Summary figures for hand table: - result={} - result['playersVpi']=0 - result['playersAtStreet1']=0 - result['playersAtStreet2']=0 - result['playersAtStreet3']=0 - result['playersAtStreet4']=0 - result['playersAtShowdown']=0 - result['street0Raises']=0 - result['street1Raises']=0 - result['street2Raises']=0 - result['street3Raises']=0 - result['street4Raises']=0 - result['street1Pot']=0 - result['street2Pot']=0 - result['street3Pot']=0 - result['street4Pot']=0 - result['showdownPot']=0 - - firstPfRaiseByNo=-1 - firstPfRaiserId=-1 - firstPfRaiserNo=-1 - firstPfCallByNo=-1 - firstPfCallerId=-1 - - for i, action in enumerate(actionTypeByNo[0]): - if action[1] == "bet": - firstPfRaiseByNo = i - firstPfRaiserId = action[0] - for j, pid in enumerate(player_ids): - if pid == firstPfRaiserId: - firstPfRaiserNo = j - break - break - for i, action in enumerate(actionTypeByNo[0]): - if action[1] == "call": - firstPfCallByNo = i - firstPfCallerId = action[0] - break - firstPlayId = firstPfCallerId - if firstPfRaiseByNo <> -1: - if firstPfRaiseByNo < firstPfCallByNo or firstPfCallByNo == -1: - firstPlayId = firstPfRaiserId - - - cutoffId=-1 - buttonId=-1 - sbId=-1 - bbId=-1 - if base=="hold": - for player, pos in enumerate(positions): - if pos == 1: - cutoffId = player_ids[player] - if pos == 0: - buttonId = player_ids[player] - if pos == 'S': - sbId = player_ids[player] - if pos == 'B': - bbId = player_ids[player] - - someoneStole=False - - #run a loop for each player preparing the actual values that will be commited to SQL - for player in xrange(len(player_ids)): - #set default values - myStreet0VPI=False - myStreet0Aggr=False - myStreet0_3BChance=False - myStreet0_3BDone=False - myStreet1Seen=False - myStreet2Seen=False - myStreet3Seen=False - myStreet4Seen=False - mySawShowdown=False - myStreet1Aggr=False - myStreet2Aggr=False - myStreet3Aggr=False - myStreet4Aggr=False - myOtherRaisedStreet1=False - myOtherRaisedStreet2=False - myOtherRaisedStreet3=False - myOtherRaisedStreet4=False - myFoldToOtherRaisedStreet1=False - myFoldToOtherRaisedStreet2=False - myFoldToOtherRaisedStreet3=False - myFoldToOtherRaisedStreet4=False - myWonWhenSeenStreet1=0.0 - myWonAtSD=0.0 - myStealAttemptChance=False - myStealAttempted=False - myStreet0Calls=0 - myStreet1Calls=0 - myStreet2Calls=0 - myStreet3Calls=0 - myStreet4Calls=0 - myStreet0Bets=0 - myStreet1Bets=0 - myStreet2Bets=0 - myStreet3Bets=0 - myStreet4Bets=0 - #myStreet0Raises=0 - #myStreet1Raises=0 - #myStreet2Raises=0 - #myStreet3Raises=0 - #myStreet4Raises=0 - - #calculate VPIP and PFR - street=0 - heroPfRaiseCount=0 - for currentAction in action_types[street][player]: # finally individual actions - if currentAction == "bet": - myStreet0Aggr = True - if currentAction == "bet" or currentAction == "call": - myStreet0VPI = True - - if myStreet0VPI: - result['playersVpi'] += 1 - myStreet0Calls = action_types[street][player].count('call') - myStreet0Bets = action_types[street][player].count('bet') - # street0Raises = action_types[street][player].count('raise') bet count includes raises for now - result['street0Raises'] += myStreet0Bets - - #PF3BChance and PF3B - pfFold=-1 - pfRaise=-1 - if firstPfRaiseByNo != -1: - for i, actionType in enumerate(actionTypeByNo[0]): - if actionType[0] == player_ids[player]: - if actionType[1] == "bet" and pfRaise == -1 and i > firstPfRaiseByNo: - pfRaise = i - if actionType[1] == "fold" and pfFold == -1: - pfFold = i - if pfFold == -1 or pfFold > firstPfRaiseByNo: - myStreet0_3BChance = True - if pfRaise > firstPfRaiseByNo: - myStreet0_3BDone = True - - #steal calculations - if base=="hold": - if len(player_ids)>=3: # no point otherwise # was 5, use 3 to match pokertracker definition - if positions[player]==1: - if firstPfRaiserId==player_ids[player] \ - and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo): - myStealAttempted=True - myStealAttemptChance=True - if firstPlayId==cutoffId or firstPlayId==buttonId or firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1: - myStealAttemptChance=True - if positions[player]==0: - if firstPfRaiserId==player_ids[player] \ - and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo): - myStealAttempted=True - myStealAttemptChance=True - if firstPlayId==buttonId or firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1: - myStealAttemptChance=True - if positions[player]=='S': - if firstPfRaiserId==player_ids[player] \ - and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo): - myStealAttempted=True - myStealAttemptChance=True - if firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1: - myStealAttemptChance=True - if positions[player]=='B': - pass - - if myStealAttempted: - someoneStole=True - - - #calculate saw* values - isAllIn = any(i for i in allIns[0][player]) - if isAllIn or len(action_types[1][player]) > 0: - myStreet1Seen = True - - if not isAllIn: - isAllIn = any(i for i in allIns[1][player]) - if isAllIn or len(action_types[2][player]) > 0: - if all(actiontype != "fold" for actiontype in action_types[1][player]): - myStreet2Seen = True - - if not isAllIn: - isAllAin = any(i for i in allIns[2][player]) - if isAllIn or len(action_types[3][player]) > 0: - if all(actiontype != "fold" for actiontype in action_types[2][player]): - myStreet3Seen = True - - #print "base:", base - if base == "hold": - mySawShowdown = not any(actiontype == "fold" for actiontype in action_types[3][player]) - else: - #print "in else" - if not isAllIn: - isAllIn = any(i for i in allIns[3][player]) - if isAllIn or len(action_types[4][player]) > 0: - #print "in if" - myStreet4Seen = True - - mySawShowdown = not any(actiontype == "fold" for actiontype in action_types[4][player]) - - if myStreet1Seen: - result['playersAtStreet1'] += 1 - if myStreet2Seen: - result['playersAtStreet2'] += 1 - if myStreet3Seen: - result['playersAtStreet3'] += 1 - if myStreet4Seen: - result['playersAtStreet4'] += 1 - if mySawShowdown: - result['playersAtShowdown'] += 1 - - #flop stuff - street = 1 - if myStreet1Seen: - myStreet1Aggr = any(actiontype == "bet" for actiontype in action_types[street][player]) - myStreet1Calls = action_types[street][player].count('call') - myStreet1Bets = action_types[street][player].count('bet') - # street1Raises = action_types[street][player].count('raise') bet count includes raises for now - result['street1Raises'] += myStreet1Bets - - for otherPlayer in xrange(len(player_ids)): - if player == otherPlayer: - pass - else: - for countOther in xrange(len(action_types[street][otherPlayer])): - if action_types[street][otherPlayer][countOther] == "bet": - myOtherRaisedStreet1 = True - for countOtherFold in xrange(len(action_types[street][player])): - if action_types[street][player][countOtherFold] == "fold": - myFoldToOtherRaisedStreet1 = True - - #turn stuff - copy of flop with different vars - street = 2 - if myStreet2Seen: - myStreet2Aggr = any(actiontype == "bet" for actiontype in action_types[street][player]) - myStreet2Calls = action_types[street][player].count('call') - myStreet2Bets = action_types[street][player].count('bet') - # street2Raises = action_types[street][player].count('raise') bet count includes raises for now - result['street2Raises'] += myStreet2Bets - - for otherPlayer in xrange(len(player_ids)): - if player == otherPlayer: - pass - else: - for countOther in xrange(len(action_types[street][otherPlayer])): - if action_types[street][otherPlayer][countOther] == "bet": - myOtherRaisedStreet2 = True - for countOtherFold in xrange(len(action_types[street][player])): - if action_types[street][player][countOtherFold] == "fold": - myFoldToOtherRaisedStreet2 = True - - #river stuff - copy of flop with different vars - street = 3 - if myStreet3Seen: - myStreet3Aggr = any(actiontype == "bet" for actiontype in action_types[street][player]) - myStreet3Calls = action_types[street][player].count('call') - myStreet3Bets = action_types[street][player].count('bet') - # street3Raises = action_types[street][player].count('raise') bet count includes raises for now - result['street3Raises'] += myStreet3Bets - - for otherPlayer in xrange(len(player_ids)): - if player == otherPlayer: - pass - else: - for countOther in xrange(len(action_types[street][otherPlayer])): - if action_types[street][otherPlayer][countOther] == "bet": - myOtherRaisedStreet3 = True - for countOtherFold in xrange(len(action_types[street][player])): - if action_types[street][player][countOtherFold] == "fold": - myFoldToOtherRaisedStreet3 = True - - #stud river stuff - copy of flop with different vars - street = 4 - if myStreet4Seen: - myStreet4Aggr = any(actiontype == "bet" for actiontype in action_types[street][player]) - myStreet4Calls = action_types[street][player].count('call') - myStreet4Bets = action_types[street][player].count('bet') - # street4Raises = action_types[street][player].count('raise') bet count includes raises for now - result['street4Raises'] += myStreet4Bets - - for otherPlayer in xrange(len(player_ids)): - if player == otherPlayer: - pass - else: - for countOther in xrange(len(action_types[street][otherPlayer])): - if action_types[street][otherPlayer][countOther] == "bet": - myOtherRaisedStreet4 = True - for countOtherFold in xrange(len(action_types[street][player])): - if action_types[street][player][countOtherFold] == "fold": - myFoldToOtherRaisedStreet4 = True - - if winnings[player] != 0: - if myStreet1Seen: - myWonWhenSeenStreet1 = winnings[player] / float(totalWinnings) - if mySawShowdown: - myWonAtSD = myWonWhenSeenStreet1 - - #add each value to the appropriate array - street0VPI.append(myStreet0VPI) - street0Aggr.append(myStreet0Aggr) - street0_3BChance.append(myStreet0_3BChance) - street0_3BDone.append(myStreet0_3BDone) - street1Seen.append(myStreet1Seen) - street2Seen.append(myStreet2Seen) - street3Seen.append(myStreet3Seen) - street4Seen.append(myStreet4Seen) - sawShowdown.append(mySawShowdown) - street1Aggr.append(myStreet1Aggr) - street2Aggr.append(myStreet2Aggr) - street3Aggr.append(myStreet3Aggr) - street4Aggr.append(myStreet4Aggr) - otherRaisedStreet1.append(myOtherRaisedStreet1) - otherRaisedStreet2.append(myOtherRaisedStreet2) - otherRaisedStreet3.append(myOtherRaisedStreet3) - otherRaisedStreet4.append(myOtherRaisedStreet4) - foldToOtherRaisedStreet1.append(myFoldToOtherRaisedStreet1) - foldToOtherRaisedStreet2.append(myFoldToOtherRaisedStreet2) - foldToOtherRaisedStreet3.append(myFoldToOtherRaisedStreet3) - foldToOtherRaisedStreet4.append(myFoldToOtherRaisedStreet4) - wonWhenSeenStreet1.append(myWonWhenSeenStreet1) - wonAtSD.append(myWonAtSD) - stealAttemptChance.append(myStealAttemptChance) - stealAttempted.append(myStealAttempted) - if base=="hold": - pos=positions[player] - if pos=='B': - hudDataPositions.append('B') - elif pos=='S': - hudDataPositions.append('S') - elif pos==0: - hudDataPositions.append('D') - elif pos==1: - hudDataPositions.append('C') - elif pos>=2 and pos<=4: - hudDataPositions.append('M') - elif pos>=5 and pos<=8: - hudDataPositions.append('E') - ### RHH Added this elif to handle being a dead hand before the BB (pos==9) - elif pos==9: - hudDataPositions.append('X') - else: - raise FpdbError("invalid position") - elif base=="stud": - #todo: stud positions and steals - pass - - street0Calls.append(myStreet0Calls) - street1Calls.append(myStreet1Calls) - street2Calls.append(myStreet2Calls) - street3Calls.append(myStreet3Calls) - street4Calls.append(myStreet4Calls) - street0Bets.append(myStreet0Bets) - street1Bets.append(myStreet1Bets) - street2Bets.append(myStreet2Bets) - street3Bets.append(myStreet3Bets) - street4Bets.append(myStreet4Bets) - #street0Raises.append(myStreet0Raises) - #street1Raises.append(myStreet1Raises) - #street2Raises.append(myStreet2Raises) - #street3Raises.append(myStreet3Raises) - #street4Raises.append(myStreet4Raises) - - #add each array to the to-be-returned dictionary - result['street0VPI']=street0VPI - result['street0Aggr']=street0Aggr - result['street0_3BChance']=street0_3BChance - result['street0_3BDone']=street0_3BDone - result['street1Seen']=street1Seen - result['street2Seen']=street2Seen - result['street3Seen']=street3Seen - result['street4Seen']=street4Seen - result['sawShowdown']=sawShowdown - - result['street1Aggr']=street1Aggr - result['otherRaisedStreet1']=otherRaisedStreet1 - result['foldToOtherRaisedStreet1']=foldToOtherRaisedStreet1 - result['street2Aggr']=street2Aggr - result['otherRaisedStreet2']=otherRaisedStreet2 - result['foldToOtherRaisedStreet2']=foldToOtherRaisedStreet2 - result['street3Aggr']=street3Aggr - result['otherRaisedStreet3']=otherRaisedStreet3 - result['foldToOtherRaisedStreet3']=foldToOtherRaisedStreet3 - result['street4Aggr']=street4Aggr - result['otherRaisedStreet4']=otherRaisedStreet4 - result['foldToOtherRaisedStreet4']=foldToOtherRaisedStreet4 - result['wonWhenSeenStreet1']=wonWhenSeenStreet1 - result['wonAtSD']=wonAtSD - result['stealAttemptChance']=stealAttemptChance - result['stealAttempted']=stealAttempted - result['street0Calls']=street0Calls - result['street1Calls']=street1Calls - result['street2Calls']=street2Calls - result['street3Calls']=street3Calls - result['street4Calls']=street4Calls - result['street0Bets']=street0Bets - result['street1Bets']=street1Bets - result['street2Bets']=street2Bets - result['street3Bets']=street3Bets - result['street4Bets']=street4Bets - #result['street0Raises']=street0Raises - #result['street1Raises']=street1Raises - #result['street2Raises']=street2Raises - #result['street3Raises']=street3Raises - #result['street4Raises']=street4Raises - - #now the various steal values - foldBbToStealChance=[] - foldedBbToSteal=[] - foldSbToStealChance=[] - foldedSbToSteal=[] - for player in xrange(len(player_ids)): - myFoldBbToStealChance=False - myFoldedBbToSteal=False - myFoldSbToStealChance=False - myFoldedSbToSteal=False - - if base=="hold": - if someoneStole and (positions[player]=='B' or positions[player]=='S') and firstPfRaiserId!=player_ids[player]: - street=0 - for count in xrange(len(action_types[street][player])):#individual actions - if positions[player]=='B': - myFoldBbToStealChance=True - if action_types[street][player][count]=="fold": - myFoldedBbToSteal=True - if positions[player]=='S': - myFoldSbToStealChance=True - if action_types[street][player][count]=="fold": - myFoldedSbToSteal=True - - - foldBbToStealChance.append(myFoldBbToStealChance) - foldedBbToSteal.append(myFoldedBbToSteal) - foldSbToStealChance.append(myFoldSbToStealChance) - foldedSbToSteal.append(myFoldedSbToSteal) - result['foldBbToStealChance']=foldBbToStealChance - result['foldedBbToSteal']=foldedBbToSteal - result['foldSbToStealChance']=foldSbToStealChance - result['foldedSbToSteal']=foldedSbToSteal - - #now CB - street1CBChance=[] - street1CBDone=[] - didStreet1CB=[] - for player in xrange(len(player_ids)): - myStreet1CBChance=False - myStreet1CBDone=False - - if street0VPI[player]: - myStreet1CBChance=True - if street1Aggr[player]: - myStreet1CBDone=True - didStreet1CB.append(player_ids[player]) - - street1CBChance.append(myStreet1CBChance) - street1CBDone.append(myStreet1CBDone) - result['street1CBChance']=street1CBChance - result['street1CBDone']=street1CBDone - - #now 2B - street2CBChance=[] - street2CBDone=[] - didStreet2CB=[] - for player in xrange(len(player_ids)): - myStreet2CBChance=False - myStreet2CBDone=False - - if street1CBDone[player]: - myStreet2CBChance=True - if street2Aggr[player]: - myStreet2CBDone=True - didStreet2CB.append(player_ids[player]) - - street2CBChance.append(myStreet2CBChance) - street2CBDone.append(myStreet2CBDone) - result['street2CBChance']=street2CBChance - result['street2CBDone']=street2CBDone - - #now 3B - street3CBChance=[] - street3CBDone=[] - didStreet3CB=[] - for player in xrange(len(player_ids)): - myStreet3CBChance=False - myStreet3CBDone=False - - if street2CBDone[player]: - myStreet3CBChance=True - if street3Aggr[player]: - myStreet3CBDone=True - didStreet3CB.append(player_ids[player]) - - street3CBChance.append(myStreet3CBChance) - street3CBDone.append(myStreet3CBDone) - result['street3CBChance']=street3CBChance - result['street3CBDone']=street3CBDone - - #and 4B - street4CBChance=[] - street4CBDone=[] - didStreet4CB=[] - for player in xrange(len(player_ids)): - myStreet4CBChance=False - myStreet4CBDone=False - - if street3CBDone[player]: - myStreet4CBChance=True - if street4Aggr[player]: - myStreet4CBDone=True - didStreet4CB.append(player_ids[player]) - - street4CBChance.append(myStreet4CBChance) - street4CBDone.append(myStreet4CBDone) - result['street4CBChance']=street4CBChance - result['street4CBDone']=street4CBDone - - - result['position']=hudDataPositions - - foldToStreet1CBChance=[] - foldToStreet1CBDone=[] - foldToStreet2CBChance=[] - foldToStreet2CBDone=[] - foldToStreet3CBChance=[] - foldToStreet3CBDone=[] - foldToStreet4CBChance=[] - foldToStreet4CBDone=[] - - for player in xrange(len(player_ids)): - myFoldToStreet1CBChance=False - myFoldToStreet1CBDone=False - foldToStreet1CBChance.append(myFoldToStreet1CBChance) - foldToStreet1CBDone.append(myFoldToStreet1CBDone) - - myFoldToStreet2CBChance=False - myFoldToStreet2CBDone=False - foldToStreet2CBChance.append(myFoldToStreet2CBChance) - foldToStreet2CBDone.append(myFoldToStreet2CBDone) - - myFoldToStreet3CBChance=False - myFoldToStreet3CBDone=False - foldToStreet3CBChance.append(myFoldToStreet3CBChance) - foldToStreet3CBDone.append(myFoldToStreet3CBDone) - - myFoldToStreet4CBChance=False - myFoldToStreet4CBDone=False - foldToStreet4CBChance.append(myFoldToStreet4CBChance) - foldToStreet4CBDone.append(myFoldToStreet4CBDone) - - if len(didStreet1CB)>=1: - generateFoldToCB(1, player_ids, didStreet1CB, street1CBDone, foldToStreet1CBChance, foldToStreet1CBDone, actionTypeByNo) - - if len(didStreet2CB)>=1: - generateFoldToCB(2, player_ids, didStreet2CB, street2CBDone, foldToStreet2CBChance, foldToStreet2CBDone, actionTypeByNo) - - if len(didStreet3CB)>=1: - generateFoldToCB(3, player_ids, didStreet3CB, street3CBDone, foldToStreet3CBChance, foldToStreet3CBDone, actionTypeByNo) - - if len(didStreet4CB)>=1: - generateFoldToCB(4, player_ids, didStreet4CB, street4CBDone, foldToStreet4CBChance, foldToStreet4CBDone, actionTypeByNo) - - result['foldToStreet1CBChance']=foldToStreet1CBChance - result['foldToStreet1CBDone']=foldToStreet1CBDone - result['foldToStreet2CBChance']=foldToStreet2CBChance - result['foldToStreet2CBDone']=foldToStreet2CBDone - result['foldToStreet3CBChance']=foldToStreet3CBChance - result['foldToStreet3CBDone']=foldToStreet3CBDone - result['foldToStreet4CBChance']=foldToStreet4CBChance - result['foldToStreet4CBDone']=foldToStreet4CBDone - - - totalProfit=[] - - street1CheckCallRaiseChance=[] - street1CheckCallRaiseDone=[] - street2CheckCallRaiseChance=[] - street2CheckCallRaiseDone=[] - street3CheckCallRaiseChance=[] - street3CheckCallRaiseDone=[] - street4CheckCallRaiseChance=[] - street4CheckCallRaiseDone=[] - #print "b4 totprof calc, len(playerIds)=", len(player_ids) - for pl in xrange(len(player_ids)): - #print "pl=", pl - myTotalProfit=winnings[pl] # still need to deduct other costs - if antes: - myTotalProfit=winnings[pl] - antes[pl] - for i in xrange(len(actionTypes)): #iterate through streets - #for j in xrange(len(actionTypes[i])): #iterate through names (using pl loop above) - for k in xrange(len(actionTypes[i][pl])): #iterate through individual actions of that player on that street - myTotalProfit -= actionAmounts[i][pl][k] - - myStreet1CheckCallRaiseChance=False - myStreet1CheckCallRaiseDone=False - myStreet2CheckCallRaiseChance=False - myStreet2CheckCallRaiseDone=False - myStreet3CheckCallRaiseChance=False - myStreet3CheckCallRaiseDone=False - myStreet4CheckCallRaiseChance=False - myStreet4CheckCallRaiseDone=False - - #print "myTotalProfit=", myTotalProfit - totalProfit.append(myTotalProfit) - #print "totalProfit[]=", totalProfit - - street1CheckCallRaiseChance.append(myStreet1CheckCallRaiseChance) - street1CheckCallRaiseDone.append(myStreet1CheckCallRaiseDone) - street2CheckCallRaiseChance.append(myStreet2CheckCallRaiseChance) - street2CheckCallRaiseDone.append(myStreet2CheckCallRaiseDone) - street3CheckCallRaiseChance.append(myStreet3CheckCallRaiseChance) - street3CheckCallRaiseDone.append(myStreet3CheckCallRaiseDone) - street4CheckCallRaiseChance.append(myStreet4CheckCallRaiseChance) - street4CheckCallRaiseDone.append(myStreet4CheckCallRaiseDone) - - result['totalProfit']=totalProfit - #print "res[totalProfit]=", result['totalProfit'] - - result['street1CheckCallRaiseChance']=street1CheckCallRaiseChance - result['street1CheckCallRaiseDone']=street1CheckCallRaiseDone - result['street2CheckCallRaiseChance']=street2CheckCallRaiseChance - result['street2CheckCallRaiseDone']=street2CheckCallRaiseDone - result['street3CheckCallRaiseChance']=street3CheckCallRaiseChance - result['street3CheckCallRaiseDone']=street3CheckCallRaiseDone - result['street4CheckCallRaiseChance']=street4CheckCallRaiseChance - result['street4CheckCallRaiseDone']=street4CheckCallRaiseDone - return result -#end def generateHudCacheData - -def generateFoldToCB(street, playerIDs, didStreetCB, streetCBDone, foldToStreetCBChance, foldToStreetCBDone, actionTypeByNo): - """fills the passed foldToStreetCB* arrays appropriately depending on the given street""" - #print "beginning of generateFoldToCB, street:", street, "len(actionTypeByNo):", len(actionTypeByNo) - #print "len(actionTypeByNo[street]):",len(actionTypeByNo[street]) - firstCBReaction=0 - for action in xrange(len(actionTypeByNo[street])): - if actionTypeByNo[street][action][1]=="bet": - for player in didStreetCB: - if player==actionTypeByNo[street][action][0] and firstCBReaction==0: - firstCBReaction=action+1 - break - - for action in actionTypeByNo[street][firstCBReaction:]: - for player in xrange(len(playerIDs)): - if playerIDs[player]==action[0]: - foldToStreetCBChance[player]=True - if action[1]=="fold": - foldToStreetCBDone[player]=True -#end def generateFoldToCB From 0898ddf8a15700f01cdf43f3ac8d73207daeefcd Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 22 Dec 2009 17:20:07 +0800 Subject: [PATCH 020/251] [NEWIMPORT] HandsPlayers.startCards Dodgy function just to get things kinda working again. --- pyfpdb/Card.py | 21 ++++++++++++++++++++- pyfpdb/DerivedStats.py | 4 ++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/pyfpdb/Card.py b/pyfpdb/Card.py index 287a0f6a..8639fd35 100755 --- a/pyfpdb/Card.py +++ b/pyfpdb/Card.py @@ -16,6 +16,25 @@ #agpl-3.0.txt in the docs folder of the package. +# From fpdb_simple +card_map = { "0": 0, "2": 2, "3" : 3, "4" : 4, "5" : 5, "6" : 6, "7" : 7, "8" : 8, + "9" : 9, "T" : 10, "J" : 11, "Q" : 12, "K" : 13, "A" : 14} + +# FIXME: the following is a workaround until switching to newimport. +# This should be moved into DerivedStats +# I'd also like to change HandsPlayers.startCards to a different datatype +# so we can 'trivially' add different start card classifications + +def calcStartCards(hand, player): + if hand.gametype['category'] == 'holdem': + hcs = hand.join_holecards(player, asList=True) + #print "DEBUG: hcs: %s" % hcs + value1 = card_map[hcs[0][0]] + value2 = card_map[hcs[1][0]] + return twoStartCards(value1, hcs[0][1], value2, hcs[1][1]) + else: + # FIXME: Only do startCards value for holdem at the moment + return 0 def twoStartCards(value1, suit1, value2, suit2): @@ -127,4 +146,4 @@ if __name__ == '__main__': (i, valueSuitFromCard(i), i+13, valueSuitFromCard(i+13), i+26, valueSuitFromCard(i+26), i+39, valueSuitFromCard(i+39)) print - print encodeCard('7c') \ No newline at end of file + print encodeCard('7c') diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index dbd655a3..b65b0d05 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -47,6 +47,7 @@ class DerivedStats(): self.handsplayers[player[1]]['wonWhenSeenStreet1'] = 0.0 self.handsplayers[player[1]]['sawShowdown'] = False self.handsplayers[player[1]]['wonAtSD'] = 0.0 + self.handsplayers[player[1]]['startCards'] = 0 for i in range(5): self.handsplayers[player[1]]['street%dCalls' % i] = 0 self.handsplayers[player[1]]['street%dBets' % i] = 0 @@ -57,7 +58,6 @@ class DerivedStats(): #FIXME - Everything below this point is incomplete. self.handsplayers[player[1]]['position'] = 2 self.handsplayers[player[1]]['tourneyTypeId'] = 1 - self.handsplayers[player[1]]['startCards'] = 0 self.handsplayers[player[1]]['street0_3BChance'] = False self.handsplayers[player[1]]['street0_3BDone'] = False self.handsplayers[player[1]]['stealAttemptChance'] = False @@ -172,7 +172,7 @@ class DerivedStats(): # self.handsplayers[player[1]]['card%s' % i] = Card.encodeCard(card) for i, card in enumerate(hcs[:7]): self.handsplayers[player[1]]['card%s' % (i+1)] = Card.encodeCard(card) - + self.handsplayers[player[1]]['startCards'] = Card.calcStartCards(hand, player[1]) # position, #Stud 3rd street card test From ae55a89d7f16ee918c39372127ccb25de1ec31b7 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 22 Dec 2009 20:22:05 +0800 Subject: [PATCH 021/251] Remove reference to fpdb_simple --- pyfpdb/Tables.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyfpdb/Tables.py b/pyfpdb/Tables.py index ea5dfc4c..75bc574c 100755 --- a/pyfpdb/Tables.py +++ b/pyfpdb/Tables.py @@ -39,7 +39,6 @@ if os.name == 'nt': # FreePokerTools modules import Configuration -from fpdb_simple import LOCALE_ENCODING # Each TableWindow object must have the following attributes correctly populated: # tw.name = the table name from the title bar, which must to match the table name @@ -238,7 +237,7 @@ def discover_nt_by_name(c, tablename): try: # maybe it's better to make global titles[hwnd] decoding? # this can blow up in XP on some windows, eg firefox displaying http://docs.python.org/tutorial/classes.html - if not tablename.lower() in titles[hwnd].decode(LOCALE_ENCODING).lower(): + if not tablename.lower() in titles[hwnd].decode(Configuration.LOCALE_ENCODING).lower(): continue except: continue From 4d8d678d644a1cf7b439c5d4dc2ae8986a6f4656 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 22 Dec 2009 21:40:37 +0800 Subject: [PATCH 022/251] [NEWIMPORT] Make seek into autoimport function Now that the legacy import path is gone, enable the index for HHC --- pyfpdb/HandHistoryConverter.py | 2 +- pyfpdb/fpdb_import.py | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index a18797df..9d4807a2 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -65,7 +65,7 @@ follow : whether to tail -f the input""" log.info("HandHistory init - %s subclass, in_path '%s'; out_path '%s'" % (self.sitename, in_path, out_path) ) - self.index = 0 + self.index = index self.starsArchive = starsArchive self.in_path = in_path diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index a7a21831..2decf6b6 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -427,7 +427,12 @@ class Importer: mod = __import__(filter) obj = getattr(mod, filter_name, None) if callable(obj): - hhc = obj(in_path = file, out_path = out_path, index = 0, starsArchive = self.settings['starsArchive']) # Index into file 0 until changeover + idx = 0 + if file in self.pos_in_file: + idx = self.pos_in_file[file] + else: + self.pos_in_file[file] = 0 + hhc = obj(in_path = file, out_path = out_path, index = idx, starsArchive = self.settings['starsArchive']) # Index into file 0 until changeover if hhc.getStatus() and self.NEWIMPORT == True: #This code doesn't do anything yet handlist = hhc.getProcessedHands() From 284693e95e820e0e8e41428f82f6d93784ec23a7 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 22 Dec 2009 22:02:36 +0800 Subject: [PATCH 023/251] [NEWIMPORT] Rebuild hudcache after hand is committed --- pyfpdb/fpdb_import.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 2decf6b6..a2a466de 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -449,6 +449,7 @@ class Importer: else: log.error("Hand processed but empty") self.database.commit() + self.database.rebuild_hudcache() #pipe the Hands.id out to the HUD for hid in to_hud: From d8a87b92d4101ca406ab0866964737e2d3baba30 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 22 Dec 2009 22:15:27 +0800 Subject: [PATCH 024/251] [NEWIMPORT] Make hudcache rebuild only happen no call to hud --- pyfpdb/fpdb_import.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index a2a466de..24f16000 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -449,7 +449,8 @@ class Importer: else: log.error("Hand processed but empty") self.database.commit() - self.database.rebuild_hudcache() + if self.callHud: + self.database.rebuild_hudcache() #pipe the Hands.id out to the HUD for hid in to_hud: From 355225fc258e26b34e078e8baec5143267f9a0e5 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 22 Dec 2009 23:03:05 +0800 Subject: [PATCH 025/251] [NEWIMPORT] Remove test_fpdb_simple --- pyfpdb/test_fpdb_simple.py | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100755 pyfpdb/test_fpdb_simple.py diff --git a/pyfpdb/test_fpdb_simple.py b/pyfpdb/test_fpdb_simple.py deleted file mode 100755 index 3d9615cb..00000000 --- a/pyfpdb/test_fpdb_simple.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- -import fpdb_simple -import datetime -import py - -def checkDateParse(header, site, result): - assert fpdb_simple.parseHandStartTime(header, site) == result - -def testPokerStarsHHDate(): - tuples = ( - ("PokerStars Game #21969660557: Hold'em No Limit ($0.50/$1.00) - 2008/11/12 10:00:48 CET [2008/11/12 4:00:48 ET]", "ps", - datetime.datetime(2008,11,12,15,00,48)), - ("PokerStars Game #21969660557: Hold'em No Limit ($0.50/$1.00) - 2008/08/17 - 01:14:43 (ET)", "ps", - datetime.datetime(2008,8,17,6,14,43)), - ("PokerStars Game #21969660557: Hold'em No Limit ($0.50/$1.00) - 2008/09/07 06:23:14 ET", "ps", - datetime.datetime(2008,9,7,11,23,14)) - ) - -#def testTableDetection(): -# result = Tables.clean_title("French (deep)") -# assert result == "French" -# result = Tables.clean_title("French (deep) - $0.25/$0.50 - No Limit Hold'em - Logged In As xxxx") -# assert result == "French" -# -# for (header, site, result) in tuples: -# yield checkDateParse, header, site, result - From 6e9153c25c529a608020732bd329376f5692348f Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 23 Dec 2009 13:30:12 +0800 Subject: [PATCH 026/251] [NEWIMPORT] Copy Grigorij's code from Alchemy Copied some of Grigorij's code verbatim for calculating additional stats, still needs adapting. Also reorder some functions so the corresponding files are more mergeable in future. --- pyfpdb/DerivedStats.py | 112 +++++++++++++++++++++++++++++++++++------ 1 file changed, 96 insertions(+), 16 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index b65b0d05..c87e714a 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -262,13 +262,58 @@ class DerivedStats(): for (i, street) in enumerate(hand.actionStreets[1:]): self.hands['street%dRaises' % i] = len(filter( lambda action: action[1] in ('raises','bets'), hand.actions[street])) - def calcCBets(self, hand): - # Continuation Bet chance, action: - # Had the last bet (initiative) on previous street, got called, close street action - # Then no bets before the player with initiatives first action on current street - # ie. if player on street-1 had initiative - # and no donkbets occurred + def calcSteals(self, hand): + """Fills stealAttempt(Chance|ed, fold(Bb|Sb)ToSteal(Chance|) + Steal attemp - open raise on positions 2 1 0 S - i.e. MP3, CO, BU, SB + Fold to steal - folding blind after steal attemp wo any other callers or raisers + """ + if self.gametype_dict['base'] != 'hold': + # FIXME: add support for other games //grindi + return + steal_attemp = False + for action in hand.actions[hand.actionStreets[1]]: + hp, act = self.handplayers_by_name[action[0]], action[1] + #print action[0], hp.position, steal_attemp, act + if hp.position == 'B': + hp.foldBbToStealChance = steal_attemp + hp.foldBbToSteal = hp.foldBbToStealChance and act == 'folds' + break + elif hp.position == 'S': + hp.foldSbToStealChance = steal_attemp + hp.foldSbToSteal = hp.foldSbToStealChance and act == 'folds' + + if steal_attemp and act != 'folds': + break + + if hp.position in ('2', '1', '0', 'S') and not steal_attemp: + hp.stealAttemptChance = True + if act in ('bets', 'raises'): + hp.stealAttempted = True + steal_attemp = True + + def calc34BetStreet0(self, hand): + """Fills street0_(3|4)B(Chance|Done), other(3|4)BStreet0""" + bet_level = 1 # bet_level after 3-bet is equal to 3 + for action in hand.actions[hand.actionStreets[1]]: + # FIXME: fill other(3|4)BStreet0 - i have no idea what does it mean + hp, aggr = self.handplayers_by_name[action[0]], action[1] in ('raises', 'bets') + hp.street0_3BChance = bet_level == 2 + hp.street0_4BChance = bet_level == 3 + hp.street0_3BDone = aggr and (hp.street0_3BChance) + hp.street0_4BDone = aggr and (hp.street0_4BChance) + if aggr: + bet_level += 1 + + + def calcCBets(self, hand): + """Fill streetXCBChance, streetXCBDone, foldToStreetXCBDone, foldToStreetXCBChance + + Continuation Bet chance, action: + Had the last bet (initiative) on previous street, got called, close street action + Then no bets before the player with initiatives first action on current street + ie. if player on street-1 had initiative and no donkbets occurred + """ # XXX: enumerate(list, start=x) is python 2.6 syntax; 'start' # came there #for i, street in enumerate(hand.actionStreets[2:], start=1): @@ -280,6 +325,29 @@ class DerivedStats(): if chance == True: self.handsplayers[name]['street%dCBDone' % (i+1)] = self.betStreet(hand.actionStreets[i+2], name) + def calcCheckCallRaise(self, hand): + """Fill streetXCheckCallRaiseChance, streetXCheckCallRaiseDone + + streetXCheckCallRaiseChance = got raise/bet after check + streetXCheckCallRaiseDone = checked. got raise/bet. didn't fold + + CG: CheckCall would be a much better name for this. + """ + for i, street in enumerate(hand.actionStreets[2:], start=1): + actions = hand.actions[hand.actionStreets[i]] + checkers = set() + initial_raiser = None + for action in actions: + pname, act = action[0], action[1] + if act in ('bets', 'raises') and initial_raiser is None: + initial_raiser = pname + elif act == 'check' and initial_raiser is None: + checkers.add(pname) + elif initial_raiser is not None and pname in checkers: + hp = self.handplayers_by_name[pname] + setattr(hp, 'street%dCheckCallRaiseChance' % i, True) + setattr(hp, 'street%dCheckCallRaiseDone' % i, act!='folds') + def seen(self, hand, i): pas = set() for act in hand.actions[hand.actionStreets[i+1]]: @@ -333,6 +401,27 @@ class DerivedStats(): players.add(action[0]) return players + + def firstsBetOrRaiser(self, actions): + """Returns player name that placed the first bet or raise. + + None if there were no bets or raises on that street + """ + for act in actions: + if act[1] in ('bets', 'raises'): + return act[0] + return None + + def lastBetOrRaiser(self, street): + """Returns player name that placed the last bet or raise for that street. + None if there were no bets or raises on that street""" + lastbet = None + for act in self.hand.actions[street]: + if act[1] in ('bets', 'raises'): + lastbet = act[0] + return lastbet + + def noBetsBefore(self, street, player): """Returns true if there were no bets before the specified players turn, false otherwise""" betOrRaise = False @@ -345,6 +434,7 @@ class DerivedStats(): break return betOrRaise + def betStreet(self, street, player): """Returns true if player bet/raised the street as their first action""" betOrRaise = False @@ -353,14 +443,4 @@ class DerivedStats(): betOrRaise = True else: break - return betOrRaise - - def lastBetOrRaiser(self, street): - """Returns player name that placed the last bet or raise for that street. - None if there were no bets or raises on that street""" - lastbet = None - for act in self.hand.actions[street]: - if act[1] in ('bets', 'raises'): - lastbet = act[0] - return lastbet From a2d0657b3a2d3c2069a1f135d13a969f18852868 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 23 Dec 2009 13:56:18 +0800 Subject: [PATCH 027/251] [NEWIMPORT] Remove unused functions Move old HudCache update over in preparation for fixing --- pyfpdb/Database.py | 679 ++++++++------------------------------------- 1 file changed, 119 insertions(+), 560 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 412036ab..9614084f 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1490,532 +1490,11 @@ class Database: c = self.get_cursor() c.executemany(q, inserts) - def storeHudCacheNew(self, gid, pid, hc): - q = """INSERT INTO HudCache ( - gametypeId, - playerId - ) - VALUES ( - %s, %s - )""" - -# 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) - - q = q.replace('%s', self.sql.query['placeholder']) - - self.cursor.execute(q, ( - gid, - pid - )) - -# 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) - - def isDuplicate(self, gametypeID, siteHandNo): - dup = False - c = self.get_cursor() - c.execute(self.sql.query['isAlreadyInDB'], (gametypeID, siteHandNo)) - result = c.fetchall() - if len(result) > 0: - dup = True - return dup - - def getGameTypeId(self, siteid, game): - c = self.get_cursor() - #FIXME: Fixed for NL at the moment - c.execute(self.sql.query['getGametypeNL'], (siteid, game['type'], game['category'], game['limitType'], - int(Decimal(game['sb'])*100), int(Decimal(game['bb'])*100))) - tmp = c.fetchone() - if (tmp == None): - hilo = "h" - if game['category'] in ['studhilo', 'omahahilo']: - hilo = "s" - elif game['category'] in ['razz','27_3draw','badugi']: - hilo = "l" - tmp = self.insertGameTypes( (siteid, game['type'], game['base'], game['category'], game['limitType'], hilo, - int(Decimal(game['sb'])*100), int(Decimal(game['bb'])*100), 0, 0) ) - return tmp[0] - - def getSqlPlayerIDs(self, pnames, siteid): - result = {} - if(self.pcache == None): - self.pcache = LambdaDict(lambda key:self.insertPlayer(key, siteid)) - - for player in pnames: - result[player] = self.pcache[player] - # NOTE: Using the LambdaDict does the same thing as: - #if player in self.pcache: - # #print "DEBUG: cachehit" - # pass - #else: - # self.pcache[player] = self.insertPlayer(player, siteid) - #result[player] = self.pcache[player] - - return result - - def insertPlayer(self, name, site_id): - result = None - c = self.get_cursor() - q = "SELECT name, id FROM Players WHERE siteid=%s and name=%s" - q = q.replace('%s', self.sql.query['placeholder']) - - #NOTE/FIXME?: MySQL has ON DUPLICATE KEY UPDATE - #Usage: - # INSERT INTO `tags` (`tag`, `count`) - # VALUES ($tag, 1) - # ON DUPLICATE KEY UPDATE `count`=`count`+1; - - - #print "DEBUG: name: %s site: %s" %(name, site_id) - - c.execute (q, (site_id, name)) - - tmp = c.fetchone() - if (tmp == None): #new player - c.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)".replace('%s',self.sql.query['placeholder']) - ,(name, site_id)) - #Get last id might be faster here. - #c.execute ("SELECT id FROM Players WHERE name=%s", (name,)) - result = self.get_last_insert_id(c) - else: - result = tmp[1] - return result - - def insertGameTypes(self, row): - c = self.get_cursor() - c.execute( self.sql.query['insertGameTypes'], row ) - return [self.get_last_insert_id(c)] - - - -################################# -# Finish of NEWIMPORT CODE -################################# - - - - def storeHands(self, backend, site_hand_no, gametype_id - ,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: - try: - c = self.get_cursor() - c.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 - ) - 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) - """.replace('%s', self.sql.query['placeholder']) - , (site_hand_no, gametype_id, hand_start_time, len(names), tableName, 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'] - ,hudCache['street3Raises'], hudCache['street4Raises'], hudCache['street1Pot'] - ,hudCache['street2Pot'], hudCache['street3Pot'], hudCache['street4Pot'] - ,hudCache['showdownPot'] - )) - ret = self.get_last_insert_id(c) - except: - ret = -1 - raise FpdbError( "storeHands error: " + str(sys.exc_value) ) - - return ret - #end def storeHands - - def store_hands_players_holdem_omaha(self, backend, category, hands_id, player_ids, start_cashes - ,positions, card_values, card_suits, winnings, rakes, seatNos, hudCache): - result=[] - - # postgres (and others?) needs the booleans converted to ints before saving: - # (or we could just save them as boolean ... but then we can't sum them so easily in sql ???) - # NO - storing booleans for now so don't need this - #hudCacheInt = {} - #for k,v in hudCache.iteritems(): - # if k in ('wonWhenSeenStreet1', 'wonAtSD', 'totalProfit'): - # hudCacheInt[k] = v - # else: - # hudCacheInt[k] = map(lambda x: 1 if x else 0, v) - - try: - inserts = [] - for i in xrange(len(player_ids)): - card1 = Card.cardFromValueSuit(card_values[i][0], card_suits[i][0]) - card2 = Card.cardFromValueSuit(card_values[i][1], card_suits[i][1]) - - if (category=="holdem"): - startCards = Card.twoStartCards(card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1]) - card3 = None - card4 = None - elif (category=="omahahi" or category=="omahahilo"): - startCards = Card.fourStartCards(card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1] - ,card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3]) - card3 = Card.cardFromValueSuit(card_values[i][2], card_suits[i][2]) - card4 = Card.cardFromValueSuit(card_values[i][3], card_suits[i][3]) - else: - raise FpdbError("invalid category") - - inserts.append( ( - hands_id, player_ids[i], start_cashes[i], positions[i], 1, # tourneytypeid - needed for hudcache - card1, card2, card3, card4, startCards, - winnings[i], rakes[i], seatNos[i], hudCache['totalProfit'][i], - hudCache['street0VPI'][i], hudCache['street0Aggr'][i], - hudCache['street0_3BChance'][i], hudCache['street0_3BDone'][i], - hudCache['street1Seen'][i], hudCache['street2Seen'][i], hudCache['street3Seen'][i], - hudCache['street4Seen'][i], hudCache['sawShowdown'][i], - hudCache['street1Aggr'][i], hudCache['street2Aggr'][i], hudCache['street3Aggr'][i], hudCache['street4Aggr'][i], - hudCache['otherRaisedStreet1'][i], hudCache['otherRaisedStreet2'][i], - hudCache['otherRaisedStreet3'][i], hudCache['otherRaisedStreet4'][i], - hudCache['foldToOtherRaisedStreet1'][i], hudCache['foldToOtherRaisedStreet2'][i], - hudCache['foldToOtherRaisedStreet3'][i], hudCache['foldToOtherRaisedStreet4'][i], - hudCache['wonWhenSeenStreet1'][i], hudCache['wonAtSD'][i], - hudCache['stealAttemptChance'][i], hudCache['stealAttempted'][i], hudCache['foldBbToStealChance'][i], - hudCache['foldedBbToSteal'][i], hudCache['foldSbToStealChance'][i], hudCache['foldedSbToSteal'][i], - hudCache['street1CBChance'][i], hudCache['street1CBDone'][i], hudCache['street2CBChance'][i], hudCache['street2CBDone'][i], - hudCache['street3CBChance'][i], hudCache['street3CBDone'][i], hudCache['street4CBChance'][i], hudCache['street4CBDone'][i], - hudCache['foldToStreet1CBChance'][i], hudCache['foldToStreet1CBDone'][i], - hudCache['foldToStreet2CBChance'][i], hudCache['foldToStreet2CBDone'][i], - hudCache['foldToStreet3CBChance'][i], hudCache['foldToStreet3CBDone'][i], - hudCache['foldToStreet4CBChance'][i], hudCache['foldToStreet4CBDone'][i], - hudCache['street1CheckCallRaiseChance'][i], hudCache['street1CheckCallRaiseDone'][i], - hudCache['street2CheckCallRaiseChance'][i], hudCache['street2CheckCallRaiseDone'][i], - hudCache['street3CheckCallRaiseChance'][i], hudCache['street3CheckCallRaiseDone'][i], - hudCache['street4CheckCallRaiseChance'][i], hudCache['street4CheckCallRaiseDone'][i], - hudCache['street0Calls'][i], hudCache['street1Calls'][i], hudCache['street2Calls'][i], hudCache['street3Calls'][i], hudCache['street4Calls'][i], - hudCache['street0Bets'][i], hudCache['street1Bets'][i], hudCache['street2Bets'][i], hudCache['street3Bets'][i], hudCache['street4Bets'][i] - ) ) - c = self.get_cursor() - c.executemany (""" - INSERT INTO HandsPlayers - (handId, playerId, startCash, position, tourneyTypeId, - card1, card2, card3, card4, startCards, winnings, rake, seatNo, totalProfit, - 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, - street1CheckCallRaiseChance, street1CheckCallRaiseDone, street2CheckCallRaiseChance, street2CheckCallRaiseDone, - street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone, - street0Calls, street1Calls, street2Calls, street3Calls, street4Calls, - street0Bets, street1Bets, street2Bets, street3Bets, street4Bets - ) - 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, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']) - ,inserts ) - result.append( self.get_last_insert_id(c) ) # wrong? not used currently - except: - raise FpdbError( "store_hands_players_holdem_omaha error: " + str(sys.exc_value) ) - - return result - #end def store_hands_players_holdem_omaha - - def store_hands_players_stud(self, backend, hands_id, player_ids, start_cashes, antes, - card_values, card_suits, winnings, rakes, seatNos): - #stores hands_players rows for stud/razz games. returns an array of the resulting IDs - - try: - result=[] - #print "before inserts in store_hands_players_stud, antes:", antes - for i in xrange(len(player_ids)): - card1 = Card.cardFromValueSuit(card_values[i][0], card_suits[i][0]) - card2 = Card.cardFromValueSuit(card_values[i][1], card_suits[i][1]) - card3 = Card.cardFromValueSuit(card_values[i][2], card_suits[i][2]) - card4 = Card.cardFromValueSuit(card_values[i][3], card_suits[i][3]) - card5 = Card.cardFromValueSuit(card_values[i][4], card_suits[i][4]) - card6 = Card.cardFromValueSuit(card_values[i][5], card_suits[i][5]) - card7 = Card.cardFromValueSuit(card_values[i][6], card_suits[i][6]) - - c = self.get_cursor() - c.execute ("""INSERT INTO HandsPlayers - (handId, playerId, startCash, ante, tourneyTypeId, - card1, card2, - card3, card4, - card5, card6, - card7, winnings, rake, seatNo) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']), - (hands_id, player_ids[i], start_cashes[i], antes[i], 1, - card1, card2, - card3, card4, - card5, card6, - card7, winnings[i], rakes[i], seatNos[i])) - #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i])) - #result.append(cursor.fetchall()[0][0]) - result.append( self.get_last_insert_id(c) ) - except: - raise FpdbError( "store_hands_players_stud error: " + str(sys.exc_value) ) - - return result - #end def store_hands_players_stud - - def store_hands_players_holdem_omaha_tourney(self, backend, category, hands_id, player_ids - ,start_cashes, positions, card_values, card_suits - ,winnings, rakes, seatNos, tourneys_players_ids - ,hudCache, tourneyTypeId): - #stores hands_players for tourney holdem/omaha hands - - try: - result=[] - inserts = [] - for i in xrange(len(player_ids)): - card1 = Card.cardFromValueSuit(card_values[i][0], card_suits[i][0]) - card2 = Card.cardFromValueSuit(card_values[i][1], card_suits[i][1]) - - if len(card_values[0])==2: - startCards = Card.twoStartCards(card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1]) - card3 = None - card4 = None - elif len(card_values[0])==4: - startCards = Card.fourStartCards(card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1] - ,card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3]) - card3 = Card.cardFromValueSuit(card_values[i][2], card_suits[i][2]) - card4 = Card.cardFromValueSuit(card_values[i][3], card_suits[i][3]) - else: - raise FpdbError ("invalid card_values length:"+str(len(card_values[0]))) - - inserts.append( (hands_id, player_ids[i], start_cashes[i], positions[i], tourneyTypeId, - card1, card2, card3, card4, startCards, - winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i], hudCache['totalProfit'][i], - hudCache['street0VPI'][i], hudCache['street0Aggr'][i], - hudCache['street0_3BChance'][i], hudCache['street0_3BDone'][i], - hudCache['street1Seen'][i], hudCache['street2Seen'][i], hudCache['street3Seen'][i], - hudCache['street4Seen'][i], hudCache['sawShowdown'][i], - hudCache['street1Aggr'][i], hudCache['street2Aggr'][i], hudCache['street3Aggr'][i], hudCache['street4Aggr'][i], - hudCache['otherRaisedStreet1'][i], hudCache['otherRaisedStreet2'][i], - hudCache['otherRaisedStreet3'][i], hudCache['otherRaisedStreet4'][i], - hudCache['foldToOtherRaisedStreet1'][i], hudCache['foldToOtherRaisedStreet2'][i], - hudCache['foldToOtherRaisedStreet3'][i], hudCache['foldToOtherRaisedStreet4'][i], - hudCache['wonWhenSeenStreet1'][i], hudCache['wonAtSD'][i], - hudCache['stealAttemptChance'][i], hudCache['stealAttempted'][i], hudCache['foldBbToStealChance'][i], - hudCache['foldedBbToSteal'][i], hudCache['foldSbToStealChance'][i], hudCache['foldedSbToSteal'][i], - hudCache['street1CBChance'][i], hudCache['street1CBDone'][i], hudCache['street2CBChance'][i], hudCache['street2CBDone'][i], - hudCache['street3CBChance'][i], hudCache['street3CBDone'][i], hudCache['street4CBChance'][i], hudCache['street4CBDone'][i], - hudCache['foldToStreet1CBChance'][i], hudCache['foldToStreet1CBDone'][i], - hudCache['foldToStreet2CBChance'][i], hudCache['foldToStreet2CBDone'][i], - hudCache['foldToStreet3CBChance'][i], hudCache['foldToStreet3CBDone'][i], - hudCache['foldToStreet4CBChance'][i], hudCache['foldToStreet4CBDone'][i], - hudCache['street1CheckCallRaiseChance'][i], hudCache['street1CheckCallRaiseDone'][i], - hudCache['street2CheckCallRaiseChance'][i], hudCache['street2CheckCallRaiseDone'][i], - hudCache['street3CheckCallRaiseChance'][i], hudCache['street3CheckCallRaiseDone'][i], - hudCache['street4CheckCallRaiseChance'][i], hudCache['street4CheckCallRaiseDone'][i], - hudCache['street0Calls'][i], hudCache['street1Calls'][i], hudCache['street2Calls'][i], - hudCache['street3Calls'][i], hudCache['street4Calls'][i], - hudCache['street0Bets'][i], hudCache['street1Bets'][i], hudCache['street2Bets'][i], - hudCache['street3Bets'][i], hudCache['street4Bets'][i] - ) ) - - c = self.get_cursor() - c.executemany (""" - INSERT INTO HandsPlayers - (handId, playerId, startCash, position, tourneyTypeId, - card1, card2, card3, card4, startCards, winnings, rake, tourneysPlayersId, seatNo, totalProfit, - 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, - street1CheckCallRaiseChance, street1CheckCallRaiseDone, street2CheckCallRaiseChance, street2CheckCallRaiseDone, - street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone, - street0Calls, street1Calls, street2Calls, street3Calls, street4Calls, - street0Bets, street1Bets, street2Bets, street3Bets, street4Bets - ) - 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, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']) - ,inserts ) - - result.append( self.get_last_insert_id(c) ) - #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i])) - #result.append(cursor.fetchall()[0][0]) - except: - err = traceback.extract_tb(sys.exc_info()[2])[-1] - print "***Error storing hand: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) - raise FpdbError( "store_hands_players_holdem_omaha_tourney error: " + str(sys.exc_value) ) - - return result - #end def store_hands_players_holdem_omaha_tourney - - def store_hands_players_stud_tourney(self, backend, hands_id, player_ids, start_cashes, - antes, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids, tourneyTypeId): - #stores hands_players for tourney stud/razz hands - return # TODO: stubbed out until someone updates it for current database structuring - try: - result=[] - for i in xrange(len(player_ids)): - c = self.get_cursor() - c.execute ("""INSERT INTO HandsPlayers - (handId, playerId, startCash, ante, - card1Value, card1Suit, card2Value, card2Suit, - card3Value, card3Suit, card4Value, card4Suit, - card5Value, card5Suit, card6Value, card6Suit, - card7Value, card7Suit, winnings, rake, tourneysPlayersId, seatNo, tourneyTypeId) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']), - (hands_id, player_ids[i], start_cashes[i], antes[i], - card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], - card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3], - card_values[i][4], card_suits[i][4], card_values[i][5], card_suits[i][5], - card_values[i][6], card_suits[i][6], winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i], tourneyTypeId)) - #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i])) - #result.append(cursor.fetchall()[0][0]) - result.append( self.get_last_insert_id(c) ) - except: - raise FpdbError( "store_hands_players_stud_tourney error: " + str(sys.exc_value) ) - - return result - #end def store_hands_players_stud_tourney - - def storeHudCache(self, backend, base, category, gametypeId, hand_start_time, playerIds, hudImportData): + def storeHudCache(self, gid, pid, hc): """Update cached statistics. If update fails because no record exists, do an insert. Can't use array updates here (not easily anyway) because we need to insert any rows that don't get updated.""" - # if (category=="holdem" or category=="omahahi" or category=="omahahilo"): - try: if self.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) @@ -2200,48 +1679,128 @@ class Database: # else: # print "todo: implement storeHudCache for stud base" - except: - raise FpdbError( "storeHudCache error: " + str(sys.exc_value) ) - - #end def storeHudCache + def isDuplicate(self, gametypeID, siteHandNo): + dup = False + c = self.get_cursor() + c.execute(self.sql.query['isAlreadyInDB'], (gametypeID, siteHandNo)) + result = c.fetchall() + if len(result) > 0: + dup = True + return dup + + def getGameTypeId(self, siteid, game): + c = self.get_cursor() + #FIXME: Fixed for NL at the moment + c.execute(self.sql.query['getGametypeNL'], (siteid, game['type'], game['category'], game['limitType'], + int(Decimal(game['sb'])*100), int(Decimal(game['bb'])*100))) + tmp = c.fetchone() + if (tmp == None): + hilo = "h" + if game['category'] in ['studhilo', 'omahahilo']: + hilo = "s" + elif game['category'] in ['razz','27_3draw','badugi']: + hilo = "l" + tmp = self.insertGameTypes( (siteid, game['type'], game['base'], game['category'], game['limitType'], hilo, + int(Decimal(game['sb'])*100), int(Decimal(game['bb'])*100), 0, 0) ) + return tmp[0] + + def getSqlPlayerIDs(self, pnames, siteid): + result = {} + if(self.pcache == None): + self.pcache = LambdaDict(lambda key:self.insertPlayer(key, siteid)) - def store_tourneys(self, tourneyTypeId, siteTourneyNo, entries, prizepool, startTime): - ret = -1 - try: - # try and create tourney record, fetch id if it already exists - # avoids race condition when doing the select first - cursor = self.get_cursor() - cursor.execute("savepoint ins_tourney") - cursor.execute("""INSERT INTO Tourneys - (tourneyTypeId, siteTourneyNo, entries, prizepool, startTime) - VALUES (%s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']) - ,(tourneyTypeId, siteTourneyNo, entries, prizepool, startTime)) - ret = self.get_last_insert_id(cursor) - #print "created new tourneys.id:",ret - except: - #if str(sys.exc_value) contains 'sitetourneyno': - # raise FpdbError( "store_tourneys error: " + str(sys.exc_value) ) + for player in pnames: + result[player] = self.pcache[player] + # NOTE: Using the LambdaDict does the same thing as: + #if player in self.pcache: + # #print "DEBUG: cachehit" + # pass #else: - #print "error insert tourney (%s) trying select ..." % (str(sys.exc_value),) - cursor.execute("rollback to savepoint ins_tourney") - try: - cursor.execute( "SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s".replace('%s', self.sql.query['placeholder']) - , (siteTourneyNo, tourneyTypeId) ) - rec = cursor.fetchone() - #print "select tourney result: ", rec - try: - len(rec) - ret = rec[0] - except: - print "Tourney id not found" - except: - print "Error selecting tourney id:", str(sys.exc_info()[1]) + # self.pcache[player] = self.insertPlayer(player, siteid) + #result[player] = self.pcache[player] + + return result + + def insertPlayer(self, name, site_id): + result = None + c = self.get_cursor() + q = "SELECT name, id FROM Players WHERE siteid=%s and name=%s" + q = q.replace('%s', self.sql.query['placeholder']) + + #NOTE/FIXME?: MySQL has ON DUPLICATE KEY UPDATE + #Usage: + # INSERT INTO `tags` (`tag`, `count`) + # VALUES ($tag, 1) + # ON DUPLICATE KEY UPDATE `count`=`count`+1; + + + #print "DEBUG: name: %s site: %s" %(name, site_id) + + c.execute (q, (site_id, name)) + + tmp = c.fetchone() + if (tmp == None): #new player + c.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)".replace('%s',self.sql.query['placeholder']) + ,(name, site_id)) + #Get last id might be faster here. + #c.execute ("SELECT id FROM Players WHERE name=%s", (name,)) + result = self.get_last_insert_id(c) + else: + result = tmp[1] + return result + + def insertGameTypes(self, row): + c = self.get_cursor() + c.execute( self.sql.query['insertGameTypes'], row ) + return [self.get_last_insert_id(c)] + + + +################################# +# Finish of NEWIMPORT CODE +################################# + + + + def storeHands(self, backend, site_hand_no, gametype_id + ,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: + try: + c = self.get_cursor() + c.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 + ) + 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) + """.replace('%s', self.sql.query['placeholder']) + , (site_hand_no, gametype_id, hand_start_time, len(names), tableName, 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'] + ,hudCache['street3Raises'], hudCache['street4Raises'], hudCache['street1Pot'] + ,hudCache['street2Pot'], hudCache['street3Pot'], hudCache['street4Pot'] + ,hudCache['showdownPot'] + )) + ret = self.get_last_insert_id(c) + except: + ret = -1 + raise FpdbError( "storeHands error: " + str(sys.exc_value) ) - cursor.execute("release savepoint ins_tourney") - #print "store_tourneys returning", ret return ret - #end def store_tourneys - + #end def storeHands + def store_tourneys_players(self, tourney_id, player_ids, payin_amounts, ranks, winnings): try: result=[] From a0475aa4db5b9688625ef0d1009ec46b0988f8b3 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 23 Dec 2009 23:14:34 +0800 Subject: [PATCH 028/251] [NEWIMPORT] Add function to update hudcache for Hand --- pyfpdb/Database.py | 288 +++++++++++++++-------------------------- pyfpdb/DerivedStats.py | 2 + pyfpdb/Hand.py | 3 + pyfpdb/SQL.py | 141 ++++++++++++++++++++ pyfpdb/fpdb_import.py | 7 +- 5 files changed, 252 insertions(+), 189 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 9614084f..0b9cd32d 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -586,6 +586,7 @@ class Database: elif not name.lower() in stat_dict[playerid]: stat_dict[playerid][name.lower()] = val elif name.lower() not in ('hand_id', 'player_id', 'seat', 'screen_name', 'seats'): + #print "DEBUG: stat_dict[%s][%s]: %s" %(playerid, name.lower(), val) stat_dict[playerid][name.lower()] += val n += 1 if n >= 10000: break # todo: don't think this is needed so set nice and high @@ -1490,194 +1491,109 @@ class Database: c = self.get_cursor() c.executemany(q, inserts) - def storeHudCache(self, gid, pid, hc): - """Update cached statistics. If update fails because no record exists, do an insert. - Can't use array updates here (not easily anyway) because we need to insert any rows - that don't get updated.""" + def storeHudCache(self, gid, pids, starttime, pdata): + """Update cached statistics. If update fails because no record exists, do an insert.""" - if self.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' + if self.use_date_in_hudcache: + styleKey = datetime.strftime(starttime, 'd%y%m%d') + #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' + + update_hudcache = self.sql.query['update_hudcache'] + update_hudcache = update_hudcache.replace('%s', self.sql.query['placeholder']) + insert_hudcache = self.sql.query['insert_hudcache'] + insert_hudcache = insert_hudcache.replace('%s', self.sql.query['placeholder']) - #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: - cursor = self.get_cursor() - 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 - """.replace('%s', self.sql.query['placeholder']) - ,(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.rowcount - # num is a cursor in sqlite - if ( (backend == self.PGSQL and cursor.statusmessage != "UPDATE 1") - or (backend == self.MYSQL_INNODB and num == 0) - or (backend == self.SQLITE and num.rowcount == 0) - ): - #print "playerid before insert:",row[2]," num = ", 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)""".replace('%s', self.sql.query['placeholder']) - , (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.rowcount - # message seems to be "INSERT 0 1" - else: - #print "updated(2) hud data line" - pass - # else: - # print "todo: implement storeHudCache for stud base" + #print "DEBUG: %s %s %s" %(hid, pids, pdata) + inserts = [] + for p in pdata: + line = [0]*61 + + line[0] = 1 # HDs + if pdata[p]['street0VPI']: line[1] = 1 + if pdata[p]['street0Aggr']: line[2] = 1 + if pdata[p]['street0_3BChance']: line[3] = 1 + if pdata[p]['street0_3BDone']: line[4] = 1 + if pdata[p]['street1Seen']: line[5] = 1 + if pdata[p]['street2Seen']: line[6] = 1 + if pdata[p]['street3Seen']: line[7] = 1 + if pdata[p]['street4Seen']: line[8] = 1 + if pdata[p]['sawShowdown']: line[9] = 1 + if pdata[p]['street1Aggr']: line[10] = 1 + if pdata[p]['street2Aggr']: line[11] = 1 + if pdata[p]['street3Aggr']: line[12] = 1 + if pdata[p]['street4Aggr']: line[13] = 1 + if pdata[p]['otherRaisedStreet1']: line[14] = 1 + if pdata[p]['otherRaisedStreet2']: line[15] = 1 + if pdata[p]['otherRaisedStreet3']: line[16] = 1 + if pdata[p]['otherRaisedStreet4']: line[17] = 1 + if pdata[p]['foldToOtherRaisedStreet1']: line[18] = 1 + if pdata[p]['foldToOtherRaisedStreet2']: line[19] = 1 + if pdata[p]['foldToOtherRaisedStreet3']: line[20] = 1 + if pdata[p]['foldToOtherRaisedStreet4']: line[21] = 1 + line[22] = pdata[p]['wonWhenSeenStreet1'] + line[23] = pdata[p]['wonAtSD'] + if pdata[p]['stealAttemptChance']: line[24] = 1 + if pdata[p]['stealAttempted']: line[25] = 1 + if pdata[p]['foldBbToStealChance']: line[26] = 1 + if pdata[p]['foldedBbToSteal']: line[27] = 1 + if pdata[p]['foldSbToStealChance']: line[28] = 1 + if pdata[p]['foldedSbToSteal']: line[29] = 1 + if pdata[p]['street1CBChance']: line[30] = 1 + if pdata[p]['street1CBDone']: line[31] = 1 + if pdata[p]['street2CBChance']: line[32] = 1 + if pdata[p]['street2CBDone']: line[33] = 1 + if pdata[p]['street3CBChance']: line[34] = 1 + if pdata[p]['street3CBDone']: line[35] = 1 + if pdata[p]['street4CBChance']: line[36] = 1 + if pdata[p]['street4CBDone']: line[37] = 1 + if pdata[p]['foldToStreet1CBChance']: line[38] = 1 + if pdata[p]['foldToStreet1CBDone']: line[39] = 1 + if pdata[p]['foldToStreet2CBChance']: line[40] = 1 + if pdata[p]['foldToStreet2CBDone']: line[41] = 1 + if pdata[p]['foldToStreet3CBChance']: line[42] = 1 + if pdata[p]['foldToStreet3CBDone']: line[43] = 1 + if pdata[p]['foldToStreet4CBChance']: line[44] = 1 + if pdata[p]['foldToStreet4CBDone']: line[45] = 1 + line[46] = pdata[p]['totalProfit'] + if pdata[p]['street1CheckCallRaiseChance']: line[47] = 1 + if pdata[p]['street1CheckCallRaiseDone']: line[48] = 1 + if pdata[p]['street2CheckCallRaiseChance']: line[49] = 1 + if pdata[p]['street2CheckCallRaiseDone']: line[50] = 1 + if pdata[p]['street3CheckCallRaiseChance']: line[51] = 1 + if pdata[p]['street3CheckCallRaiseDone']: line[52] = 1 + if pdata[p]['street4CheckCallRaiseChance']: line[53] = 1 + if pdata[p]['street4CheckCallRaiseDone']: line[54] = 1 + line[55] = gid # gametypeId + line[56] = pids[p] # playerId + line[57] = len(pids) # activeSeats + line[58] = pdata[p]['position'] + line[59] = pdata[p]['tourneyTypeId'] + line[60] = styleKey # styleKey + inserts.append(line) + + + cursor = self.get_cursor() + + for row in inserts: + # Try to do the update first: + num = cursor.execute(update_hudcache, row) + # Test statusmessage to see if update worked, do insert if not + # num is a cursor in sqlite + if ((self.backend == self.PGSQL and cursor.statusmessage != "UPDATE 1") + or (self.backend == self.MYSQL_INNODB and num == 0) + or (self.backend == self.SQLITE and num.rowcount == 0)): + #move the last 6 items in WHERE clause of row from the end of the array + # to the beginning for the INSERT statement + print "DEBUG: using INSERT: %s" % num + row = row[-6:] + row[:-6] + num = cursor.execute(insert_hudcache, row) + print "DEBUG: Successfully(?: %s) updated HudCacho using INSERT" % num + else: + print "DEBUG: Successfully updated HudCacho using UPDATE" + pass def isDuplicate(self, gametypeID, siteHandNo): dup = False diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index c87e714a..1e81dd8d 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -201,6 +201,7 @@ class DerivedStats(): # 2 Hijack def assembleHudCache(self, hand): + # No real work to be done - HandsPlayers data already contains the correct info pass def vpip(self, hand): @@ -443,4 +444,5 @@ class DerivedStats(): betOrRaise = True else: break + return betOrRaise diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 3467216a..a660b56d 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -232,6 +232,9 @@ db: a connected fpdb_db object""" #Raise Duplicate exception? pass + def updateHudCache(self, db): + db.storeHudCache(self.dbid_gt, self.dbid_pids, self.starttime, self.stats.getHandsPlayers()) + def select(self, handId): """ Function to create Hand object from database """ diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 56c1f388..2b19b04a 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -3088,6 +3088,147 @@ class Sql: ,'d' || substr(strftime('%Y%m%d', h.handStart),3,7) """ + self.query['insert_hudcache'] = """ + 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)""" + + self.query['update_hudcache'] = """ + 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""" + self.query['get_hero_hudcache_start'] = """select min(hc.styleKey) from HudCache hc where hc.playerId in diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 24f16000..41d04283 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -432,9 +432,8 @@ class Importer: idx = self.pos_in_file[file] else: self.pos_in_file[file] = 0 - hhc = obj(in_path = file, out_path = out_path, index = idx, starsArchive = self.settings['starsArchive']) # Index into file 0 until changeover + hhc = obj(in_path = file, out_path = out_path, index = idx, starsArchive = self.settings['starsArchive']) if hhc.getStatus() and self.NEWIMPORT == True: - #This code doesn't do anything yet handlist = hhc.getProcessedHands() self.pos_in_file[file] = hhc.getLastCharacterRead() to_hud = [] @@ -449,8 +448,10 @@ class Importer: else: log.error("Hand processed but empty") self.database.commit() + # Call hudcache update if not in bulk import mode + # FIXME: Need to test for bulk import that isn't rebuilding the cache if self.callHud: - self.database.rebuild_hudcache() + hand.updateHudCache(self.database) #pipe the Hands.id out to the HUD for hid in to_hud: From 0adf0a7b18ae44b6a1b5f67b398a1788ea60303d Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 24 Dec 2009 01:12:39 +0800 Subject: [PATCH 029/251] [NEWIMPORT] updateHudCache update. Fix a couple of bugs: position != 2 its = 'M' actually commit changes to hud --- pyfpdb/Database.py | 14 ++++++++------ pyfpdb/fpdb_import.py | 1 + 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 0b9cd32d..fcb0c066 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1569,7 +1569,8 @@ class Database: line[55] = gid # gametypeId line[56] = pids[p] # playerId line[57] = len(pids) # activeSeats - line[58] = pdata[p]['position'] + pos = {-2:'B', -1:'S', 0:'D', 1:'C', 2:'M', 3:'M', 4:'M', 5:'E', 6:'E', 7:'E', 8:'E', 9:'E' } + line[58] = pos[pdata[p]['position']] line[59] = pdata[p]['tourneyTypeId'] line[60] = styleKey # styleKey inserts.append(line) @@ -1580,19 +1581,20 @@ class Database: for row in inserts: # Try to do the update first: num = cursor.execute(update_hudcache, row) - # Test statusmessage to see if update worked, do insert if not - # num is a cursor in sqlite + #print "DEBUG: values: %s" % row[-6:] + # Test statusmessage to see if update worked, do insert if not + # num is a cursor in sqlite if ((self.backend == self.PGSQL and cursor.statusmessage != "UPDATE 1") or (self.backend == self.MYSQL_INNODB and num == 0) or (self.backend == self.SQLITE and num.rowcount == 0)): #move the last 6 items in WHERE clause of row from the end of the array # to the beginning for the INSERT statement - print "DEBUG: using INSERT: %s" % num + #print "DEBUG: using INSERT: %s" % num row = row[-6:] + row[:-6] num = cursor.execute(insert_hudcache, row) - print "DEBUG: Successfully(?: %s) updated HudCacho using INSERT" % num + #print "DEBUG: Successfully(?: %s) updated HudCacho using INSERT" % num else: - print "DEBUG: Successfully updated HudCacho using UPDATE" + #print "DEBUG: Successfully updated HudCacho using UPDATE" pass def isDuplicate(self, gametypeID, siteHandNo): diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 41d04283..7c240cbe 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -452,6 +452,7 @@ class Importer: # FIXME: Need to test for bulk import that isn't rebuilding the cache if self.callHud: hand.updateHudCache(self.database) + self.database.commit() #pipe the Hands.id out to the HUD for hid in to_hud: From 3b1e67e78bcb0051fef3ade940466dfd403d8214 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Thu, 24 Dec 2009 09:52:47 +0200 Subject: [PATCH 030/251] Store names as UTF-8 The names should be always in UTF-8 encoding. At least for PostgreSQL the encdoding of the database comes from the time of running 'initdb' (which is different from 'createdb') and if the encoding was selected or set to something else at that time, the following error will occur: File ".../pyfpdb/Database.py", line 1630, in self.pcache = LambdaDict(lambda key:self.insertPlayer(key, siteid)) File ".../pyfpdb/Database.py", line 1661, in insertPlayer c.execute (q, (site_id, _name)) File "/usr/lib/python2.5/encodings/iso8859_15.py", line 12, in encode return codecs.charmap_encode(input,errors,encoding_table) UnicodeEncodeError: 'charmap' codec can't encode character u'\u2122' in position 10: character maps to This happens because 'name' is a regular string as opposed to a valid unicode object. By forcing the string to unicode and encoding it in UTF-8 the error goes away. In my case the database encoding was ISO-8859-15 (latin9) but any other "wrong" encoding would trigger the same problem. This is a relatively common problem in python. --- pyfpdb/Database.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index fcb0c066..fb70dbab 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -38,6 +38,7 @@ from decimal import Decimal import string import re import Queue +import codecs # pyGTK modules @@ -50,6 +51,7 @@ import Tourney from Exceptions import * log = Configuration.get_logger("logging.conf") +encoder = codecs.lookup('utf-8') class Database: @@ -1641,6 +1643,7 @@ class Database: def insertPlayer(self, name, site_id): result = None + (_name, _len) = encoder.encode(unicode(name)) c = self.get_cursor() q = "SELECT name, id FROM Players WHERE siteid=%s and name=%s" q = q.replace('%s', self.sql.query['placeholder']) @@ -1654,12 +1657,12 @@ class Database: #print "DEBUG: name: %s site: %s" %(name, site_id) - c.execute (q, (site_id, name)) + c.execute (q, (site_id, _name)) tmp = c.fetchone() if (tmp == None): #new player c.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)".replace('%s',self.sql.query['placeholder']) - ,(name, site_id)) + ,(_name, site_id)) #Get last id might be faster here. #c.execute ("SELECT id FROM Players WHERE name=%s", (name,)) result = self.get_last_insert_id(c) From 46e91e1a0f687aa25e33924807b554e097a1983b Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 25 Dec 2009 18:55:13 +0800 Subject: [PATCH 031/251] [NEWIMPORT] Remove a couple of unused functions --- pyfpdb/Database.py | 102 --------------------------------------------- 1 file changed, 102 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index fcb0c066..0e67e6b6 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -619,69 +619,6 @@ class Database: rows = c.fetchall() return rows - #returns the SQL ids of the names given in an array - # TODO: if someone gets industrious, they should make the parts that use the output of this function deal with a dict - # { playername: id } instead of depending on it's relation to the positions list - # then this can be reduced in complexity a bit - - #def recognisePlayerIDs(cursor, names, site_id): - # result = [] - # for i in xrange(len(names)): - # cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],)) - # tmp=cursor.fetchall() - # if (len(tmp)==0): #new player - # cursor.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)", (names[i], site_id)) - # #print "Number of players rows inserted: %d" % cursor.rowcount - # cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],)) - # tmp=cursor.fetchall() - # #print "recognisePlayerIDs, names[i]:",names[i],"tmp:",tmp - # result.append(tmp[0][0]) - # return result - - def recognisePlayerIDs(self, names, site_id): - c = self.get_cursor() - q = "SELECT name,id FROM Players WHERE siteid=%d and (name=%s)" %(site_id, " OR name=".join([self.sql.query['placeholder'] for n in names])) - c.execute(q, names) # get all playerids by the names passed in - ids = dict(c.fetchall()) # convert to dict - if len(ids) != len(names): - notfound = [n for n in names if n not in ids] # make list of names not in database - if notfound: # insert them into database - q_ins = "INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")" - q_ins = q_ins.replace('%s', self.sql.query['placeholder']) - c.executemany(q_ins, [(n,) for n in notfound]) - q2 = "SELECT name,id FROM Players WHERE siteid=%d and (name=%s)" % (site_id, " OR name=".join(["%s" for n in notfound])) - q2 = q2.replace('%s', self.sql.query['placeholder']) - c.execute(q2, notfound) # get their new ids - tmp = c.fetchall() - for n,id in tmp: # put them all into the same dict - ids[n] = id - # return them in the SAME ORDER that they came in in the names argument, rather than the order they came out of the DB - return [ids[n] for n in names] - #end def recognisePlayerIDs - - # Here's a version that would work if it wasn't for the fact that it needs to have the output in the same order as input - # this version could also be improved upon using list comprehensions, etc - - #def recognisePlayerIDs(cursor, names, site_id): - # result = [] - # notfound = [] - # cursor.execute("SELECT name,id FROM Players WHERE name='%s'" % "' OR name='".join(names)) - # tmp = dict(cursor.fetchall()) - # for n in names: - # if n not in tmp: - # notfound.append(n) - # else: - # result.append(tmp[n]) - # if notfound: - # cursor.executemany("INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")", (notfound)) - # cursor.execute("SELECT id FROM Players WHERE name='%s'" % "' OR name='".join(notfound)) - # tmp = cursor.fetchall() - # for n in tmp: - # result.append(n[0]) - # - # return result - - def get_site_id(self, site): c = self.get_cursor() c.execute(self.sql.query['getSiteId'], (site,)) @@ -1680,45 +1617,6 @@ class Database: - def storeHands(self, backend, site_hand_no, gametype_id - ,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: - try: - c = self.get_cursor() - c.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 - ) - 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) - """.replace('%s', self.sql.query['placeholder']) - , (site_hand_no, gametype_id, hand_start_time, len(names), tableName, 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'] - ,hudCache['street3Raises'], hudCache['street4Raises'], hudCache['street1Pot'] - ,hudCache['street2Pot'], hudCache['street3Pot'], hudCache['street4Pot'] - ,hudCache['showdownPot'] - )) - ret = self.get_last_insert_id(c) - except: - ret = -1 - raise FpdbError( "storeHands error: " + str(sys.exc_value) ) - - return ret - #end def storeHands - def store_tourneys_players(self, tourney_id, player_ids, payin_amounts, ranks, winnings): try: result=[] From 1bcb6736eb25e9e29f5f38ebbb1a4a2515f42409 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 26 Dec 2009 10:07:33 +0800 Subject: [PATCH 032/251] New test file - All-in pre flop --- ...HE-6max-USD-0.05-0.10-200912.Allin-pre.txt | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt diff --git a/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt b/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt new file mode 100644 index 00000000..b876c42a --- /dev/null +++ b/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt @@ -0,0 +1,41 @@ +PokerStars Game #37165169101: Hold'em No Limit ($0.10/$0.25 USD) - 2009/12/25 9:50:09 ET +Table 'Lucretia IV' 6-max Seat #2 is the button +Seat 1: Blåveis ($55.10 in chips) +Seat 2: Kinewma ($31.40 in chips) +Seat 3: AAALISAAAA ($20.20 in chips) +Seat 4: Arbaz ($25 in chips) +Seat 5: s0rrow ($29.85 in chips) +Seat 6: bys7 ($41.35 in chips) +AAALISAAAA: posts small blind $0.10 +Arbaz: posts big blind $0.25 +*** HOLE CARDS *** +Dealt to s0rrow [Ac As] +s0rrow: raises $0.50 to $0.75 +bys7: calls $0.75 +Blåveis: folds +Kinewma: folds +AAALISAAAA: raises $1.50 to $2.25 +Arbaz: folds +s0rrow: raises $3.50 to $5.75 +bys7: folds +AAALISAAAA: raises $14.45 to $20.20 and is all-in +s0rrow: calls $14.45 +*** FLOP *** [3d 7h Kh] +*** TURN *** [3d 7h Kh] [Ts] +*** RIVER *** [3d 7h Kh Ts] [5c] +*** SHOW DOWN *** +AAALISAAAA: shows [Kd 5d] (two pair, Kings and Fives) +s0rrow: shows [Ac As] (a pair of Aces) +AAALISAAAA collected $39.35 from pot +*** SUMMARY *** +Total pot $41.40 | Rake $2.05 +Board [3d 7h Kh Ts 5c] +Seat 1: Blåveis folded before Flop (didn't bet) +Seat 2: Kinewma (button) folded before Flop (didn't bet) +Seat 3: AAALISAAAA (small blind) showed [Kd 5d] and won ($39.35) with two pair, Kings and Fives +Seat 4: Arbaz (big blind) folded before Flop +Seat 5: s0rrow showed [Ac As] and lost with a pair of Aces +Seat 6: bys7 folded before Flop + + + From 624ab07f853bdf634f2086f66dadb61a3a8ebe4b Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 26 Dec 2009 12:23:20 +0800 Subject: [PATCH 033/251] New test for all-in preflop. Test still fails - need to sort out an issue with database placement --- pyfpdb/test_PokerStars.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/pyfpdb/test_PokerStars.py b/pyfpdb/test_PokerStars.py index e3e45c35..18a9f556 100644 --- a/pyfpdb/test_PokerStars.py +++ b/pyfpdb/test_PokerStars.py @@ -82,6 +82,8 @@ def testFlopImport(): # River: hero (continuation bets?) all-in and is not called importer.addBulkImportImportFileOrDir( """regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Stats-comparision.txt""", site="PokerStars") + importer.addBulkImportImportFileOrDir( + """regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt""", site="PokerStars") importer.setCallHud(False) (stored, dups, partial, errs, ttime) = importer.runImport() print "DEBUG: stored: %s dups: %s partial: %s errs: %s ttime: %s" %(stored, dups, partial, errs, ttime) @@ -114,6 +116,32 @@ and s.id = p.siteid""" # Assert if any sawShowdown = True assert result[row][col['sawShowdown']] == 0 + q = """SELECT + s.name, + p.name, + hp.sawShowdown +FROM + Hands as h, + Sites as s, + Gametypes as g, + HandsPlayers as hp, + Players as p +WHERE + h.siteHandNo = 37165169101 +and g.id = h.gametypeid +and hp.handid = h.id +and p.id = hp.playerid +and s.id = p.siteid""" + c = db.get_cursor() + c.execute(q) + result = c.fetchall() + for row, data in enumerate(result): + print "DEBUG: result[%s]: %s" %(row, result[row]) + # Assert if any sawShowdown = True + assert result[row][col['sawShowdown']] == 1 + + assert 0 == 1 + def testStudImport(): db.recreate_tables() importer = fpdb_import.Importer(False, settings, config) From 1245a0cab3091575f13da4e8a0c5d1aa2fb507ec Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 26 Dec 2009 10:07:33 +0800 Subject: [PATCH 034/251] New test file - All-in pre flop --- ...HE-6max-USD-0.05-0.10-200912.Allin-pre.txt | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt diff --git a/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt b/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt new file mode 100644 index 00000000..b876c42a --- /dev/null +++ b/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt @@ -0,0 +1,41 @@ +PokerStars Game #37165169101: Hold'em No Limit ($0.10/$0.25 USD) - 2009/12/25 9:50:09 ET +Table 'Lucretia IV' 6-max Seat #2 is the button +Seat 1: Blåveis ($55.10 in chips) +Seat 2: Kinewma ($31.40 in chips) +Seat 3: AAALISAAAA ($20.20 in chips) +Seat 4: Arbaz ($25 in chips) +Seat 5: s0rrow ($29.85 in chips) +Seat 6: bys7 ($41.35 in chips) +AAALISAAAA: posts small blind $0.10 +Arbaz: posts big blind $0.25 +*** HOLE CARDS *** +Dealt to s0rrow [Ac As] +s0rrow: raises $0.50 to $0.75 +bys7: calls $0.75 +Blåveis: folds +Kinewma: folds +AAALISAAAA: raises $1.50 to $2.25 +Arbaz: folds +s0rrow: raises $3.50 to $5.75 +bys7: folds +AAALISAAAA: raises $14.45 to $20.20 and is all-in +s0rrow: calls $14.45 +*** FLOP *** [3d 7h Kh] +*** TURN *** [3d 7h Kh] [Ts] +*** RIVER *** [3d 7h Kh Ts] [5c] +*** SHOW DOWN *** +AAALISAAAA: shows [Kd 5d] (two pair, Kings and Fives) +s0rrow: shows [Ac As] (a pair of Aces) +AAALISAAAA collected $39.35 from pot +*** SUMMARY *** +Total pot $41.40 | Rake $2.05 +Board [3d 7h Kh Ts 5c] +Seat 1: Blåveis folded before Flop (didn't bet) +Seat 2: Kinewma (button) folded before Flop (didn't bet) +Seat 3: AAALISAAAA (small blind) showed [Kd 5d] and won ($39.35) with two pair, Kings and Fives +Seat 4: Arbaz (big blind) folded before Flop +Seat 5: s0rrow showed [Ac As] and lost with a pair of Aces +Seat 6: bys7 folded before Flop + + + From 9f2f015fd0e65a6d64973d284b28d50d7a746c71 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 26 Dec 2009 12:23:20 +0800 Subject: [PATCH 035/251] New test for all-in preflop. Test still fails - need to sort out an issue with database placement --- pyfpdb/test_PokerStars.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/pyfpdb/test_PokerStars.py b/pyfpdb/test_PokerStars.py index e3e45c35..18a9f556 100644 --- a/pyfpdb/test_PokerStars.py +++ b/pyfpdb/test_PokerStars.py @@ -82,6 +82,8 @@ def testFlopImport(): # River: hero (continuation bets?) all-in and is not called importer.addBulkImportImportFileOrDir( """regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Stats-comparision.txt""", site="PokerStars") + importer.addBulkImportImportFileOrDir( + """regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt""", site="PokerStars") importer.setCallHud(False) (stored, dups, partial, errs, ttime) = importer.runImport() print "DEBUG: stored: %s dups: %s partial: %s errs: %s ttime: %s" %(stored, dups, partial, errs, ttime) @@ -114,6 +116,32 @@ and s.id = p.siteid""" # Assert if any sawShowdown = True assert result[row][col['sawShowdown']] == 0 + q = """SELECT + s.name, + p.name, + hp.sawShowdown +FROM + Hands as h, + Sites as s, + Gametypes as g, + HandsPlayers as hp, + Players as p +WHERE + h.siteHandNo = 37165169101 +and g.id = h.gametypeid +and hp.handid = h.id +and p.id = hp.playerid +and s.id = p.siteid""" + c = db.get_cursor() + c.execute(q) + result = c.fetchall() + for row, data in enumerate(result): + print "DEBUG: result[%s]: %s" %(row, result[row]) + # Assert if any sawShowdown = True + assert result[row][col['sawShowdown']] == 1 + + assert 0 == 1 + def testStudImport(): db.recreate_tables() importer = fpdb_import.Importer(False, settings, config) From 0e318e6d9f4e0a7b9d7911842e60091d084e172a Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 26 Dec 2009 17:18:05 +0800 Subject: [PATCH 036/251] [NEWIMPORT] Commit currnetly failing test - sawShowdown It would appear that all-in pre-flop doesn't flag sawShowdown. Also modified the query to select street0Aggr, as that appears to be wrong at the moment --- pyfpdb/DerivedStats.py | 2 +- pyfpdb/test_PokerStars.py | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 1e81dd8d..7c50178b 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -363,7 +363,7 @@ class DerivedStats(): def aggr(self, hand, i): aggrers = set() for act in hand.actions[hand.actionStreets[i]]: - if act[1] in ('completes', 'raises'): + if act[1] in ('completes', 'bets', 'raises'): aggrers.add(act[0]) for player in hand.players: diff --git a/pyfpdb/test_PokerStars.py b/pyfpdb/test_PokerStars.py index 18a9f556..72c9049c 100644 --- a/pyfpdb/test_PokerStars.py +++ b/pyfpdb/test_PokerStars.py @@ -89,13 +89,14 @@ def testFlopImport(): print "DEBUG: stored: %s dups: %s partial: %s errs: %s ttime: %s" %(stored, dups, partial, errs, ttime) importer.clearFileList() - col = { 'sawShowdown': 2 + col = { 'sawShowdown': 2, 'street0Aggr':3 } q = """SELECT s.name, p.name, - hp.sawShowdown + hp.sawShowdown, + hp.street0Aggr FROM Hands as h, Sites as s, @@ -119,7 +120,8 @@ and s.id = p.siteid""" q = """SELECT s.name, p.name, - hp.sawShowdown + hp.sawShowdown, + hp.street0Aggr FROM Hands as h, Sites as s, @@ -135,10 +137,10 @@ and s.id = p.siteid""" c = db.get_cursor() c.execute(q) result = c.fetchall() + pstats = { u'Kinewma':0, u'Arbaz':0, u's0rrow':1, u'bys7':0, u'AAALISAAAA':1, u'Bl\xe5veis':0 } for row, data in enumerate(result): - print "DEBUG: result[%s]: %s" %(row, result[row]) - # Assert if any sawShowdown = True - assert result[row][col['sawShowdown']] == 1 + print "DEBUG: result[%s]: %s == %s" %(row, result[row], pstats[data[1]]) + assert result[row][col['sawShowdown']] == pstats[data[1]] assert 0 == 1 From f66b8307d311b97fdfb667c0cebd66e4d5413fcf Mon Sep 17 00:00:00 2001 From: Gerko de Roo Date: Wed, 23 Dec 2009 21:12:56 +0100 Subject: [PATCH 037/251] search string for table detect changed --- pyfpdb/HandHistoryConverter.py | 2 +- pyfpdb/Tables.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index a18797df..1ea0d203 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -512,7 +512,7 @@ or None if we fail to get the info """ def getTableTitleRe(type, table_name=None, tournament = None, table_number=None): "Returns string to search in windows titles" if type=="tour": - return "%s.+Table\s%s" % (tournament, table_number) + return "%s.+Table.+%s" % (tournament, table_number) else: return table_name diff --git a/pyfpdb/Tables.py b/pyfpdb/Tables.py index ea5dfc4c..28bd313a 100755 --- a/pyfpdb/Tables.py +++ b/pyfpdb/Tables.py @@ -161,7 +161,7 @@ def discover_posix_by_name(c, tablename): def discover_posix_tournament(c, t_number, s_number): """Finds the X window for a client, given tournament and table nos.""" - search_string = "%s.+Table\s%s" % (t_number, s_number) + search_string = "%s.+Table.+%s" % (t_number, s_number) for listing in os.popen('xwininfo -root -tree').readlines(): if re.search(search_string, listing): return decode_xwininfo(c, listing) From 3553bdaf715575ee4b8e20de97d4062002bac798 Mon Sep 17 00:00:00 2001 From: Gerko de Roo Date: Wed, 23 Dec 2009 21:12:56 +0100 Subject: [PATCH 038/251] search string for table detect changed --- pyfpdb/HandHistoryConverter.py | 2 +- pyfpdb/Tables.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 9d4807a2..47cfd302 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -512,7 +512,7 @@ or None if we fail to get the info """ def getTableTitleRe(type, table_name=None, tournament = None, table_number=None): "Returns string to search in windows titles" if type=="tour": - return "%s.+Table\s%s" % (tournament, table_number) + return "%s.+Table.+%s" % (tournament, table_number) else: return table_name diff --git a/pyfpdb/Tables.py b/pyfpdb/Tables.py index 75bc574c..ce99b274 100755 --- a/pyfpdb/Tables.py +++ b/pyfpdb/Tables.py @@ -160,7 +160,7 @@ def discover_posix_by_name(c, tablename): def discover_posix_tournament(c, t_number, s_number): """Finds the X window for a client, given tournament and table nos.""" - search_string = "%s.+Table\s%s" % (t_number, s_number) + search_string = "%s.+Table.+%s" % (t_number, s_number) for listing in os.popen('xwininfo -root -tree').readlines(): if re.search(search_string, listing): return decode_xwininfo(c, listing) From 2cd57e826df07caebf37cacbfbf4019a78091682 Mon Sep 17 00:00:00 2001 From: Gerko de Roo Date: Wed, 23 Dec 2009 21:15:55 +0100 Subject: [PATCH 039/251] Added color highlight for stats window. high and low threshold and color can be set in the xml file --- pyfpdb/Configuration.py | 4 ++ pyfpdb/HUD_config.xml.example | 97 ++++++++++++++++++----------------- pyfpdb/Hud.py | 10 ++++ 3 files changed, 63 insertions(+), 48 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 996ef60c..117fd0c7 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -267,6 +267,10 @@ class Game: stat.hudprefix = stat_node.getAttribute("hudprefix") stat.hudsuffix = stat_node.getAttribute("hudsuffix") stat.hudcolor = stat_node.getAttribute("hudcolor") + stat.stat_loth = stat_node.getAttribute("stat_loth") + stat.stat_hith = stat_node.getAttribute("stat_hith") + stat.stat_locolor = stat_node.getAttribute("stat_locolor") + stat.stat_hicolor = stat_node.getAttribute("stat_hicolor") self.stats[stat.stat_name] = stat diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index b1ebd761..a772773e 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -449,59 +449,60 @@ Left-Drag to Move" - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + + diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index b61c17aa..1eb51aea 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -632,6 +632,16 @@ class Hud: self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.hudcolor)) + if this_stat.stat_loth != "": + if number[0] < (float(this_stat.stat_loth)/100): + self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) + window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_locolor)) + + if this_stat.stat_hith != "": + if number[0] > (float(this_stat.stat_hith)/100): + self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) + window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_hicolor)) + window.label[r][c].set_text(statstring) if statstring != "xxx": # is there a way to tell if this particular stat window is visible already, or no? window.window.show_all() From eb226c002678d2e63bd6f3d568386605c55e5af0 Mon Sep 17 00:00:00 2001 From: Gerko de Roo Date: Wed, 23 Dec 2009 21:15:55 +0100 Subject: [PATCH 040/251] Added color highlight for stats window. high and low threshold and color can be set in the xml file --- pyfpdb/Configuration.py | 4 ++ pyfpdb/HUD_config.xml.example | 97 ++++++++++++++++++----------------- pyfpdb/Hud.py | 10 ++++ 3 files changed, 63 insertions(+), 48 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 174d0673..39bf5921 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -269,6 +269,10 @@ class Game: stat.hudprefix = stat_node.getAttribute("hudprefix") stat.hudsuffix = stat_node.getAttribute("hudsuffix") stat.hudcolor = stat_node.getAttribute("hudcolor") + stat.stat_loth = stat_node.getAttribute("stat_loth") + stat.stat_hith = stat_node.getAttribute("stat_hith") + stat.stat_locolor = stat_node.getAttribute("stat_locolor") + stat.stat_hicolor = stat_node.getAttribute("stat_hicolor") self.stats[stat.stat_name] = stat diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index b1ebd761..a772773e 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -449,59 +449,60 @@ Left-Drag to Move" - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + + diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index b61c17aa..1eb51aea 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -632,6 +632,16 @@ class Hud: self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.hudcolor)) + if this_stat.stat_loth != "": + if number[0] < (float(this_stat.stat_loth)/100): + self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) + window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_locolor)) + + if this_stat.stat_hith != "": + if number[0] > (float(this_stat.stat_hith)/100): + self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) + window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_hicolor)) + window.label[r][c].set_text(statstring) if statstring != "xxx": # is there a way to tell if this particular stat window is visible already, or no? window.window.show_all() From 805d35c3fd35fbbf6c0e3ba398db27a7e57692c5 Mon Sep 17 00:00:00 2001 From: Worros Date: Mon, 28 Dec 2009 10:21:31 +0800 Subject: [PATCH 041/251] Fix tab spacing from Gerkos recent patch --- pyfpdb/Hud.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 1eb51aea..e2994de8 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -633,14 +633,14 @@ class Hud: window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.hudcolor)) if this_stat.stat_loth != "": - if number[0] < (float(this_stat.stat_loth)/100): - self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) - window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_locolor)) + if number[0] < (float(this_stat.stat_loth)/100): + self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) + window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_locolor)) if this_stat.stat_hith != "": - if number[0] > (float(this_stat.stat_hith)/100): - self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) - window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_hicolor)) + if number[0] > (float(this_stat.stat_hith)/100): + self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) + window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_hicolor)) window.label[r][c].set_text(statstring) if statstring != "xxx": # is there a way to tell if this particular stat window is visible already, or no? From 3f3d8ac54a59d0617d18e212621aa5045676f171 Mon Sep 17 00:00:00 2001 From: Worros Date: Mon, 28 Dec 2009 10:21:31 +0800 Subject: [PATCH 042/251] Fix tab spacing from Gerkos recent patch --- pyfpdb/Hud.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 1eb51aea..e2994de8 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -633,14 +633,14 @@ class Hud: window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.hudcolor)) if this_stat.stat_loth != "": - if number[0] < (float(this_stat.stat_loth)/100): - self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) - window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_locolor)) + if number[0] < (float(this_stat.stat_loth)/100): + self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) + window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_locolor)) if this_stat.stat_hith != "": - if number[0] > (float(this_stat.stat_hith)/100): - self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) - window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_hicolor)) + if number[0] > (float(this_stat.stat_hith)/100): + self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) + window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_hicolor)) window.label[r][c].set_text(statstring) if statstring != "xxx": # is there a way to tell if this particular stat window is visible already, or no? From 6efccd9067fe1dc48f3110748d068012038eddec Mon Sep 17 00:00:00 2001 From: Gerko de Roo Date: Wed, 23 Dec 2009 21:44:55 +0100 Subject: [PATCH 043/251] Hmm forgot the color reset to default. There must be a better methode --- pyfpdb/Hud.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index e2994de8..2b6d0237 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -631,7 +631,10 @@ class Hud: if this_stat.hudcolor != "": self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.hudcolor)) - + else: + self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) + window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#FFFFFF")) + if this_stat.stat_loth != "": if number[0] < (float(this_stat.stat_loth)/100): self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) From 1cf464283f15228f6c0d42abd8651bcaf3a4056e Mon Sep 17 00:00:00 2001 From: Gerko de Roo Date: Wed, 23 Dec 2009 21:44:55 +0100 Subject: [PATCH 044/251] Hmm forgot the color reset to default. There must be a better methode --- pyfpdb/Hud.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index e2994de8..2b6d0237 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -631,7 +631,10 @@ class Hud: if this_stat.hudcolor != "": self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.hudcolor)) - + else: + self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) + window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#FFFFFF")) + if this_stat.stat_loth != "": if number[0] < (float(this_stat.stat_loth)/100): self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) From c7aca0a32e9fe6398dfcc3d73ea9ce17cf3257e6 Mon Sep 17 00:00:00 2001 From: Worros Date: Mon, 28 Dec 2009 22:03:26 +0800 Subject: [PATCH 045/251] Update HUD_config.xml - Change default Holdem stat window layout to 3x3, add some more colouring - Fix tab breakage from Gerko. --- pyfpdb/HUD_config.xml.example | 91 ++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 45 deletions(-) diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index a772773e..3acfd812 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -448,61 +448,62 @@ Left-Drag to Move" + + + + + + + + + + + - + - - - - - - + + + + + + - + - - - - - - + + + + + + - + - - - - - - + + + + + + - + - - - - - - + + + + + + - + - - - - - - - - - - - - - - - - + + + + + + From 4800f2515fe37d277c27e497abaf4f5d34a66ccd Mon Sep 17 00:00:00 2001 From: Worros Date: Mon, 28 Dec 2009 22:03:26 +0800 Subject: [PATCH 046/251] Update HUD_config.xml - Change default Holdem stat window layout to 3x3, add some more colouring - Fix tab breakage from Gerko. --- pyfpdb/HUD_config.xml.example | 91 ++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 45 deletions(-) diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index a772773e..3acfd812 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -448,61 +448,62 @@ Left-Drag to Move" + + + + + + + + + + + - + - - - - - - + + + + + + - + - - - - - - + + + + + + - + - - - - - - + + + + + + - + - - - - - - + + + + + + - + - - - - - - - - - - - - - - - - + + + + + + From 478b82587dfcf307b6d7e9e907dc89fa8c68e291 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Thu, 24 Dec 2009 09:52:47 +0200 Subject: [PATCH 047/251] Store names as UTF-8 The names should be always in UTF-8 encoding. At least for PostgreSQL the encdoding of the database comes from the time of running 'initdb' (which is different from 'createdb') and if the encoding was selected or set to something else at that time, the following error will occur: File ".../pyfpdb/Database.py", line 1630, in self.pcache = LambdaDict(lambda key:self.insertPlayer(key, siteid)) File ".../pyfpdb/Database.py", line 1661, in insertPlayer c.execute (q, (site_id, _name)) File "/usr/lib/python2.5/encodings/iso8859_15.py", line 12, in encode return codecs.charmap_encode(input,errors,encoding_table) UnicodeEncodeError: 'charmap' codec can't encode character u'\u2122' in position 10: character maps to This happens because 'name' is a regular string as opposed to a valid unicode object. By forcing the string to unicode and encoding it in UTF-8 the error goes away. In my case the database encoding was ISO-8859-15 (latin9) but any other "wrong" encoding would trigger the same problem. This is a relatively common problem in python. --- pyfpdb/Database.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 0e67e6b6..63e9a0a5 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -38,6 +38,7 @@ from decimal import Decimal import string import re import Queue +import codecs # pyGTK modules @@ -50,6 +51,7 @@ import Tourney from Exceptions import * log = Configuration.get_logger("logging.conf") +encoder = codecs.lookup('utf-8') class Database: @@ -1578,6 +1580,7 @@ class Database: def insertPlayer(self, name, site_id): result = None + (_name, _len) = encoder.encode(unicode(name)) c = self.get_cursor() q = "SELECT name, id FROM Players WHERE siteid=%s and name=%s" q = q.replace('%s', self.sql.query['placeholder']) @@ -1591,12 +1594,12 @@ class Database: #print "DEBUG: name: %s site: %s" %(name, site_id) - c.execute (q, (site_id, name)) + c.execute (q, (site_id, _name)) tmp = c.fetchone() if (tmp == None): #new player c.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)".replace('%s',self.sql.query['placeholder']) - ,(name, site_id)) + ,(_name, site_id)) #Get last id might be faster here. #c.execute ("SELECT id FROM Players WHERE name=%s", (name,)) result = self.get_last_insert_id(c) From cd88de7c7e57c334cc87f09126711a2c1dd15c8f Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 30 Dec 2009 15:44:48 +0800 Subject: [PATCH 048/251] [NEWIMPORT] Copy in Alchemy files from Grigorij's alchemy branch --- pyfpdb/AlchemyFacilities.py | 116 +++++++++ pyfpdb/AlchemyMappings.py | 464 ++++++++++++++++++++++++++++++++++++ pyfpdb/AlchemyTables.py | 438 ++++++++++++++++++++++++++++++++++ 3 files changed, 1018 insertions(+) create mode 100644 pyfpdb/AlchemyFacilities.py create mode 100644 pyfpdb/AlchemyMappings.py create mode 100644 pyfpdb/AlchemyTables.py diff --git a/pyfpdb/AlchemyFacilities.py b/pyfpdb/AlchemyFacilities.py new file mode 100644 index 00000000..c8284efb --- /dev/null +++ b/pyfpdb/AlchemyFacilities.py @@ -0,0 +1,116 @@ +# -*- coding: utf-8 -*- +from decimal import Decimal + +from sqlalchemy import types +from sqlalchemy.orm.exc import NoResultFound +from sqlalchemy.exc import IntegrityError + +import Card + +class CardColumn(types.TypeDecorator): + """Stores cards as smallints + + Automatically converts values like '9h' to smallint + + >>> CardColumn().process_bind_param( 'Td', '' ) + 22 + >>> CardColumn().process_bind_param( u'Td', '' ) + 22 + >>> CardColumn().process_bind_param( 22, '' ) + 22 + >>> CardColumn().process_result_value( 22, '' ) + 'Td' + """ + + impl = types.SmallInteger + + def process_bind_param(self, value, dialect): + if value is None or isinstance(value, int): + return value + elif isinstance(value, basestring) and len(value) == 2: + return Card.encodeCard(str(value)) + else: + raise Exception, "Incorrect card value: " + repr(value) + + def process_result_value(self, value, dialect): + return Card.valueSuitFromCard( value ) + + +class MoneyColumn(types.TypeDecorator): + """Stores money: bets, pots, etc + + Understands: + Decimal as real amount + int as amount mupliplied by 100 + string as decimal + Returns Decimal + >>> MoneyColumn().process_bind_param( 230, '' ) + 230 + >>> MoneyColumn().process_bind_param( Decimal('2.30'), '' ) + 230 + >>> MoneyColumn().process_bind_param( '2.30', '' ) + 230 + >>> MoneyColumn().process_result_value( 230, '' ) + Decimal('2.3') + """ + + impl = types.Integer + + def process_bind_param(self, value, dialect): + if value is None or isinstance(value, int): + return value + elif isinstance(value, basestring) or isinstance(value, Decimal): + return int(Decimal(value)*100) + else: + raise Exception, "Incorrect amount:" + repr(value) + + def process_result_value(self, value, dialect): + if value is None: + return None + return Decimal(value)/100 + + +class BigIntColumn(types.TypeDecorator, types.Integer): + """Representing db-independent big integer """ + # Integer inheritance required for auto_increment flag + + impl = types.Integer + + def load_dialect_impl(self, dialect): + from sqlalchemy import databases + if dialect.name == 'mysql': + return databases.mysql.MSBigInteger() + elif dialect.name == 'postgres': + return databases.mysql.PGBigInteger() + return types.Integer() + + +class MappedBase(object): + """Provide dummy contrcutor""" + + def __init__(self, **kwargs): + for k, v in kwargs.iteritems(): + setattr(self, k, v) + + def get_columns_names(self): + return [i.name for i in self._sa_class_manager.mapper.c] + +def get_or_create(klass, session, **kwargs): + """ + Looks up an object with the given kwargs, creating one if necessary. + Returns a tuple of (object, created), where created is a boolean + specifying whether an object was created. + """ + assert kwargs, \ + 'get_or_create() must be passed at least one keyword argument' + try: + return session.query(klass).filter_by(**kwargs).one(), False + except NoResultFound: + try: + obj = klass(**kwargs) + session.add(obj) + session.flush() + return obj, True + except IntegrityError: + return session.query(klass).filter_by(**kwargs).one(), False + diff --git a/pyfpdb/AlchemyMappings.py b/pyfpdb/AlchemyMappings.py new file mode 100644 index 00000000..c2e088a9 --- /dev/null +++ b/pyfpdb/AlchemyMappings.py @@ -0,0 +1,464 @@ +# -*- coding: utf-8 -*- +"""@package AlchemyMappings +This package contains all classes to be mapped and mappers themselves +""" + +import logging +import re +from decimal import Decimal +from sqlalchemy.orm import mapper, relation, reconstructor +from sqlalchemy.sql import select +from collections import defaultdict + + +from AlchemyTables import * +from AlchemyFacilities import get_or_create, MappedBase +from DerivedStats import DerivedStats +from Exceptions import IncompleteHandError, FpdbError + + +class Player(MappedBase): + """Class reflecting Players db table""" + + @staticmethod + def get_or_create(session, siteId, name): + return get_or_create(Player, session, siteId=siteId, name=name)[0] + + def __str__(self): + return '' % (self.name, self.site and self.site.name) + + +class Gametype(MappedBase): + """Class reflecting Gametypes db table""" + + @staticmethod + def get_or_create(session, siteId, gametype): + map = zip( + ['type', 'base', 'category', 'limitType', 'smallBlind', 'bigBlind', 'smallBet', 'bigBet'], + ['type', 'base', 'category', 'limitType', 'sb', 'bb', 'dummy', 'dummy', ]) + gametype = dict([(new, gametype.get(old)) for new, old in map ]) + + hilo = "h" + if gametype['category'] in ('studhilo', 'omahahilo'): + hilo = "s" + elif gametype['category'] in ('razz','27_3draw','badugi'): + hilo = "l" + gametype['hiLo'] = hilo + + for f in ['smallBlind', 'bigBlind', 'smallBet', 'bigBet']: + if gametype[f] is None: + gametype[f] = 0 + gametype[f] = int(Decimal(gametype[f])*100) + + gametype['siteId'] = siteId + return get_or_create(Gametype, session, **gametype)[0] + + +class HandActions(object): + """Class reflecting HandsActions db table""" + def initFromImportedHand(self, hand, actions): + self.hand = hand + self.actions = {} + for street, street_actions in actions.iteritems(): + self.actions[street] = [] + for v in street_actions: + hp = hand.handplayers_by_name[v[0]] + self.actions[street].append({'street': street, 'pid': hp.id, 'seat': hp.seatNo, 'action':v}) + + @property + def flat_actions(self): + actions = [] + for street in self.hand.allStreets: + actions += self.actions[street] + return actions + + + +class HandInternal(DerivedStats): + """Class reflecting Hands db table""" + + def parseImportedHandStep1(self, hand): + """Extracts values to insert into from hand returned by HHC. No db is needed he""" + hand.players = hand.getAlivePlayers() + + # also save some data for step2. Those fields aren't in Hands table + self.siteId = hand.siteId + self.gametype_dict = hand.gametype + + self.attachHandPlayers(hand) + self.attachActions(hand) + + self.assembleHands(hand) + self.assembleHandsPlayers(hand) + + def parseImportedHandStep2(self, session): + """Fetching ids for gametypes and players""" + gametype = Gametype.get_or_create(session, self.siteId, self.gametype_dict) + self.gametypeId = gametype.id + for hp in self.handPlayers: + hp.playerId = Player.get_or_create(session, self.siteId, hp.name).id + + def getPlayerByName(self, name): + if not hasattr(self, 'handplayers_by_name'): + self.handplayers_by_name = {} + for hp in self.handPlayers: + pname = getattr(hp, 'name', None) or hp.player.name + self.handplayers_by_name[pname] = hp + return self.handplayers_by_name[name] + + def attachHandPlayers(self, hand): + """Fill HandInternal.handPlayers list. Create self.handplayers_by_name""" + hand.noSb = getattr(hand, 'noSb', None) + if hand.noSb is None and self.gametype_dict['base']=='hold': + saw_sb = False + for action in hand.actions[hand.actionStreets[0]]: # blindsantes + if action[1] == 'posts' and action[2] == 'small blind' and action[0] is not None: + saw_sb = True + hand.noSb = saw_sb + + self.handplayers_by_name = {} + for seat, name, chips in hand.players: + p = HandPlayer(hand = self, imported_hand=hand, seatNo=seat, + name=name, startCash=chips) + self.handplayers_by_name[name] = p + + def attachActions(self, hand): + """Create HandActions object""" + a = HandActions() + a.initFromImportedHand(self, hand.actions) + + def parseImportedTournament(self, hand, session): + """Fetching tourney, its type and players + + Must be called after Step2 + """ + if self.gametype_dict['type'] != 'tour': return + + # check for consistense + for i in ('buyin', 'tourNo'): + if not hasattr(hand, i): + raise IncompleteHandError( + "Field '%s' required for tournaments" % i, self.id, hand ) + + # repair old-style buyin value + m = re.match('\$(\d+)\+\$(\d+)', hand.buyin) + if m is not None: + hand.buyin, self.fee = m.groups() + + # fetch tourney type + tour_type_hand2db = { + 'buyin': 'buyin', + 'fee': 'fee', + 'speed': 'speed', + 'maxSeats': 'maxseats', + 'knockout': 'isKO', + 'rebuyOrAddon': 'isRebuy', + 'headsUp': 'isHU', + 'shootout': 'isShootout', + 'matrix': 'isMatrix', + 'sng': 'isSNG', + } + tour_type_index = dict([ + ( i_db, getattr(hand, i_hand, None) ) + for i_db, i_hand in tour_type_hand2db.iteritems() + ]) + tour_type_index['siteId'] = self.siteId + tour_type = TourneyType.get_or_create(session, **tour_type_index) + + # fetch and update tourney + tour = Tourney.get_or_create(session, hand.tourNo, tour_type.id) + cols = tour.get_columns_names() + for col in cols: + hand_val = getattr(hand, col, None) + if col in ('id', 'tourneyTypeId', 'comment', 'commentTs') or hand_val is None: + continue + db_val = getattr(tour, col, None) + if db_val is None: + setattr(tour, col, hand_val) + elif col == 'koBounty': + setattr(tour, col, max(db_val, hand_val)) + elif col == 'tourStartTime' and hand.handStart: + setattr(tour, col, min(db_val, hand.handStart)) + + if tour.entries is None and tour_type.sng: + tour.entries = tour_type.maxSeats + + # fetch and update tourney players + for hp in self.handPlayers: + tp = TourneyPlayer.get_or_create(session, tour.id, hp.playerId) + # FIXME: other TourneysPlayers should be added here + + session.flush() + + def isDuplicate(self, session): + """Checks if current hand already exists in db + + siteHandNo ans gameTypeId have to be setted + """ + return session.query(HandInternal).filter_by( + siteHandNo=self.siteHandNo, gametypeId=self.gametypeId).count()!=0 + + def __str__(self): + s = list() + for i in self._sa_class_manager.mapper.c: + s.append('%25s %s' % (i, getattr(self, i.name))) + + s+=['', ''] + for i,p in enumerate(self.handPlayers): + s.append('%d. %s' % (i, p.name or '???')) + s.append(str(p)) + return '\n'.join(s) + + @property + def boardcards(self): + cards = [] + for i in range(5): + cards.append(getattr(self, 'boardcard%d' % (i+1), None)) + return filter(bool, cards) + + @property + def HandClass(self): + """Return HoldemOmahaHand or something like this""" + import Hand + if self.gametype.base == 'hold': + return Hand.HoldemOmahaHand + elif self.gametype.base == 'draw': + return Hand.DrawHand + elif self.gametype.base == 'stud': + return Hand.StudHand + raise Exception("Unknow gametype.base: '%s'" % self.gametype.base) + + @property + def allStreets(self): + return self.HandClass.allStreets + + @property + def actionStreets(self): + return self.HandClass.actionStreets + + + +class HandPlayer(MappedBase): + """Class reflecting HandsPlayers db table""" + def __init__(self, **kwargs): + if 'imported_hand' in kwargs and 'seatNo' in kwargs: + imported_hand = kwargs.pop('imported_hand') + self.position = self.getPosition(imported_hand, kwargs['seatNo']) + super(HandPlayer, self).__init__(**kwargs) + + @reconstructor + def init_on_load(self): + self.name = self.player.name + + @staticmethod + def getPosition(hand, seat): + """Returns position value like 'B', 'S', '0', '1', ... + + >>> class A(object): pass + ... + >>> A.noSb = False + >>> A.maxseats = 6 + >>> A.buttonpos = 2 + >>> A.gametype = {'base': 'hold'} + >>> A.players = [(i, None, None) for i in (2, 4, 5, 6)] + >>> HandPlayer.getPosition(A, 6) # cut off + '1' + >>> HandPlayer.getPosition(A, 2) # button + '0' + >>> HandPlayer.getPosition(A, 4) # SB + 'S' + >>> HandPlayer.getPosition(A, 5) # BB + 'B' + >>> A.noSb = True + >>> HandPlayer.getPosition(A, 5) # MP3 + '2' + >>> HandPlayer.getPosition(A, 6) # cut off + '1' + >>> HandPlayer.getPosition(A, 2) # button + '0' + >>> HandPlayer.getPosition(A, 4) # BB + 'B' + """ + from itertools import chain + if hand.gametype['base'] == 'stud': + # FIXME: i've never played stud so plz check & del comment \\grindi + bringin = None + for action in chain(*[self.actions[street] for street in hand.allStreets]): + if action[1]=='bringin': + bringin = action[0] + break + if bringin is None: + raise Exception, "Cannot find bringin" + # name -> seat + bringin = int(filter(lambda p: p[1]==bringin, bringin)[0]) + seat = (int(seat) - int(bringin))%int(hand.maxseats) + return str(seat) + else: + seats_occupied = sorted([seat_ for seat_, name, chips in hand.players], key=int) + if hand.buttonpos not in seats_occupied: + # i.e. something like + # Seat 3: PlayerX ($0), is sitting out + # The button is in seat #3 + hand.buttonpos = max(seats_occupied, + key = lambda s: int(s) + if int(s) <= int(hand.buttonpos) + else int(s) - int(hand.maxseats) + ) + seats_occupied = sorted(seats_occupied, + key = lambda seat_: ( + - seats_occupied.index(seat_) + + seats_occupied.index(hand.buttonpos) + + 2) % len(seats_occupied) + ) + # now (if SB presents) seats_occupied contains seats in order: BB, SB, BU, CO, MP3, ... + if hand.noSb: + # fix order in the case nosb + seats_occupied = seats_occupied[1:] + seats_occupied[0:1] + seats_occupied.insert(1, -1) + seat = seats_occupied.index(seat) + if seat == 0: + return 'B' + elif seat == 1: + return 'S' + else: + return str(seat-2) + + @property + def cards(self): + cards = [] + for i in range(7): + cards.append(getattr(self, 'card%d' % (i+1), None)) + return filter(bool, cards) + + def __str__(self): + s = list() + for i in self._sa_class_manager.mapper.c: + s.append('%45s %s' % (i, getattr(self, i.name))) + return '\n'.join(s) + + +class Site(object): + """Class reflecting Players db table""" + INITIAL_DATA = [ + (1 , 'Full Tilt Poker','USD'), + (2 , 'PokerStars', 'USD'), + (3 , 'Everleaf', 'USD'), + (4 , 'Win2day', 'USD'), + (5 , 'OnGame', 'USD'), + (6 , 'UltimateBet', 'USD'), + (7 , 'Betfair', 'USD'), + (8 , 'Absolute', 'USD'), + (9 , 'PartyPoker', 'USD'), + (10, 'Partouche', 'EUR'), + ] + INITIAL_DATA_KEYS = ('id', 'name', 'currency') + + INITIAL_DATA_DICTS = [ dict(zip(INITIAL_DATA_KEYS, datum)) for datum in INITIAL_DATA ] + + @classmethod + def insert_initial(cls, connection): + connection.execute(sites_table.insert(), cls.INITIAL_DATA_DICTS) + + +class Tourney(MappedBase): + """Class reflecting Tourneys db table""" + + @classmethod + def get_or_create(cls, session, siteTourneyNo, tourneyTypeId): + """Fetch tourney by index or creates one if none. """ + return get_or_create(cls, session, siteTourneyNo=siteTourneyNo, + tourneyTypeId=tourneyTypeId)[0] + + + +class TourneyType(MappedBase): + """Class reflecting TourneysType db table""" + + @classmethod + def get_or_create(cls, session, **kwargs): + """Fetch tourney type by index or creates one if none + + Required kwargs: + buyin fee speed maxSeats knockout + rebuyOrAddon headsUp shootout matrix sng + """ + return get_or_create(cls, session, **kwargs)[0] + + +class TourneyPlayer(MappedBase): + """Class reflecting TourneysPlayers db table""" + + @classmethod + def get_or_create(cls, session, tourneyId, playerId): + """Fetch tourney player by index or creates one if none """ + return get_or_create(cls, session, tourneyId=tourneyId, playerId=playerId) + + +class Version(object): + """Provides read/write access for version var""" + CURRENT_VERSION = 120 # db version for current release + # 119 - first alchemy version + # 120 - add m_factor + + conn = None + ver = None + def __init__(self, connection=None): + if self.__class__.conn is None: + self.__class__.conn = connection + + @classmethod + def is_wrong(cls): + return cls.get() != cls.CURRENT_VERSION + + @classmethod + def get(cls): + if cls.ver is None: + try: + cls.ver = cls.conn.execute(select(['version'], settings_table)).fetchone()[0] + except: + return None + return cls.ver + + @classmethod + def set(cls, value): + if cls.conn.execute(settings_table.select()).rowcount==0: + cls.conn.execute(settings_table.insert(), version=value) + else: + cls.conn.execute(settings_table.update().values(version=value)) + cls.ver = value + + @classmethod + def set_initial(cls): + cls.set(cls.CURRENT_VERSION) + + +mapper (Gametype, gametypes_table, properties={ + 'hands': relation(HandInternal, backref='gametype'), +}) +mapper (Player, players_table, properties={ + 'playerHands': relation(HandPlayer, backref='player'), + 'playerTourney': relation(TourneyPlayer, backref='player'), +}) +mapper (Site, sites_table, properties={ + 'gametypes': relation(Gametype, backref = 'site'), + 'players': relation(Player, backref = 'site'), + 'tourneyTypes': relation(TourneyType, backref = 'site'), +}) +mapper (HandActions, hands_actions_table, properties={}) +mapper (HandInternal, hands_table, properties={ + 'handPlayers': relation(HandPlayer, backref='hand'), + 'actions_all': relation(HandActions, backref='hand', uselist=False), +}) +mapper (HandPlayer, hands_players_table, properties={}) + +mapper (Tourney, tourneys_table) +mapper (TourneyType, tourney_types_table, properties={ + 'tourneys': relation(Tourney, backref='type'), +}) +mapper (TourneyPlayer, tourneys_players_table) + +class LambdaKeyDict(defaultdict): + """Operates like defaultdict but passes key argument to the factory function""" + def __missing__(key): + return self.default_factory(key) + diff --git a/pyfpdb/AlchemyTables.py b/pyfpdb/AlchemyTables.py new file mode 100644 index 00000000..3165a480 --- /dev/null +++ b/pyfpdb/AlchemyTables.py @@ -0,0 +1,438 @@ +# -*- coding: utf-8 -*- +"""@package AlchemyTables +Contains all sqlalchemy tables +""" + +from sqlalchemy import Table, Float, Column, Integer, String, MetaData, \ + ForeignKey, Boolean, SmallInteger, DateTime, Text, Index, CHAR, \ + PickleType, Unicode + +from AlchemyFacilities import CardColumn, MoneyColumn, BigIntColumn + + +metadata = MetaData() + + +autorates_table = Table('Autorates', metadata, + Column('id', Integer, primary_key=True, nullable=False), + Column('playerId', Integer, ForeignKey("Players.id"), nullable=False), + Column('gametypeId', SmallInteger, ForeignKey("Gametypes.id"), nullable=False), + Column('description', String(50), nullable=False), + Column('shortDesc', CHAR(8), nullable=False), + Column('ratingTime', DateTime, nullable=False), + Column('handCount', Integer, nullable=False), + mysql_charset='utf8', + mysql_engine='InnoDB', +) + + +gametypes_table = Table('Gametypes', metadata, + Column('id', SmallInteger, primary_key=True), + Column('siteId', SmallInteger, ForeignKey("Sites.id"), nullable=False), # SMALLINT + Column('type', String(4), nullable=False), # char(4) NOT NULL + Column('base', String(4), nullable=False), # char(4) NOT NULL + Column('category', String(9), nullable=False), # varchar(9) NOT NULL + Column('limitType', CHAR(2), nullable=False), # char(2) NOT NULL + Column('hiLo', CHAR(1), nullable=False), # char(1) NOT NULL + Column('smallBlind', Integer(3)), # int + Column('bigBlind', Integer(3)), # int + Column('smallBet', Integer(3), nullable=False), # int NOT NULL + Column('bigBet', Integer(3), nullable=False), # int NOT NULL + mysql_charset='utf8', + mysql_engine='InnoDB', +) + + +hands_table = Table('Hands', metadata, + Column('id', BigIntColumn, primary_key=True), + Column('tableName', String(30), nullable=False), + Column('siteHandNo', BigIntColumn, nullable=False), + Column('gametypeId', SmallInteger, ForeignKey('Gametypes.id'), nullable=False), + Column('handStart', DateTime, nullable=False), + Column('importTime', DateTime, nullable=False), + Column('seats', SmallInteger, nullable=False), + Column('maxSeats', SmallInteger, nullable=False), + + Column('boardcard1', CardColumn), + Column('boardcard2', CardColumn), + Column('boardcard3', CardColumn), + Column('boardcard4', CardColumn), + Column('boardcard5', CardColumn), + Column('texture', SmallInteger), + Column('playersVpi', SmallInteger, nullable=False), + Column('playersAtStreet1', SmallInteger, nullable=False, default=0), + Column('playersAtStreet2', SmallInteger, nullable=False, default=0), + Column('playersAtStreet3', SmallInteger, nullable=False, default=0), + Column('playersAtStreet4', SmallInteger, nullable=False, default=0), + Column('playersAtShowdown',SmallInteger, nullable=False), + Column('street0Raises', SmallInteger, nullable=False), + Column('street1Raises', SmallInteger, nullable=False), + Column('street2Raises', SmallInteger, nullable=False), + Column('street3Raises', SmallInteger, nullable=False), + Column('street4Raises', SmallInteger, nullable=False), + Column('street1Pot', MoneyColumn), + Column('street2Pot', MoneyColumn), + Column('street3Pot', MoneyColumn), + Column('street4Pot', MoneyColumn), + Column('showdownPot', MoneyColumn), + Column('comment', Text), + Column('commentTs', DateTime), + mysql_charset='utf8', + mysql_engine='InnoDB', +) +Index('siteHandNo', hands_table.c.siteHandNo, hands_table.c.gametypeId, unique=True) + + +hands_actions_table = Table('HandsActions', metadata, + Column('id', BigIntColumn, primary_key=True, nullable=False), + Column('handId', BigIntColumn, ForeignKey("Hands.id"), nullable=False), + Column('actions', PickleType, nullable=False), + mysql_charset='utf8', + mysql_engine='InnoDB', +) + + +hands_players_table = Table('HandsPlayers', metadata, + Column('id', BigIntColumn, primary_key=True), + Column('handId', BigIntColumn, ForeignKey("Hands.id"), nullable=False), + Column('playerId', Integer, ForeignKey("Players.id"), nullable=False), + Column('startCash', MoneyColumn), + Column('position', CHAR(1)), #CHAR(1) + Column('seatNo', SmallInteger, nullable=False), #SMALLINT NOT NULL + + Column('card1', CardColumn), #smallint NOT NULL, + Column('card2', CardColumn), #smallint NOT NULL + Column('card3', CardColumn), #smallint + Column('card4', CardColumn), #smallint + Column('card5', CardColumn), #smallint + Column('card6', CardColumn), #smallint + Column('card7', CardColumn), #smallint + Column('startCards', SmallInteger), #smallint + + Column('m_factor', Integer), # null for ring games + Column('ante', MoneyColumn), #INT + Column('winnings', MoneyColumn, nullable=False, default=0), #int NOT NULL + Column('rake', MoneyColumn, nullable=False, default=0), #int NOT NULL + Column('totalProfit', MoneyColumn), #INT + Column('comment', Text), #text + Column('commentTs', DateTime), #DATETIME + Column('tourneysPlayersId', BigIntColumn, ForeignKey("TourneysPlayers.id"),), #BIGINT UNSIGNED + Column('tourneyTypeId', Integer, ForeignKey("TourneyTypes.id"),), #SMALLINT UNSIGNED + + Column('wonWhenSeenStreet1',Float), #FLOAT + Column('wonWhenSeenStreet2',Float), #FLOAT + Column('wonWhenSeenStreet3',Float), #FLOAT + Column('wonWhenSeenStreet4',Float), #FLOAT + Column('wonAtSD', Float), #FLOAT + + Column('street0VPI', Boolean), #BOOLEAN + Column('street0Aggr', Boolean), #BOOLEAN + Column('street0_3BChance', Boolean), #BOOLEAN + Column('street0_3BDone', Boolean), #BOOLEAN + Column('street0_4BChance', Boolean), #BOOLEAN + Column('street0_4BDone', Boolean), #BOOLEAN + Column('other3BStreet0', Boolean), #BOOLEAN + Column('other4BStreet0', Boolean), #BOOLEAN + + Column('street1Seen', Boolean), #BOOLEAN + Column('street2Seen', Boolean), #BOOLEAN + Column('street3Seen', Boolean), #BOOLEAN + Column('street4Seen', Boolean), #BOOLEAN + Column('sawShowdown', Boolean), #BOOLEAN + + Column('street1Aggr', Boolean), #BOOLEAN + Column('street2Aggr', Boolean), #BOOLEAN + Column('street3Aggr', Boolean), #BOOLEAN + Column('street4Aggr', Boolean), #BOOLEAN + + Column('otherRaisedStreet0',Boolean), #BOOLEAN + Column('otherRaisedStreet1',Boolean), #BOOLEAN + Column('otherRaisedStreet2',Boolean), #BOOLEAN + Column('otherRaisedStreet3',Boolean), #BOOLEAN + Column('otherRaisedStreet4',Boolean), #BOOLEAN + Column('foldToOtherRaisedStreet0', Boolean), #BOOLEAN + Column('foldToOtherRaisedStreet1', Boolean), #BOOLEAN + Column('foldToOtherRaisedStreet2', Boolean), #BOOLEAN + Column('foldToOtherRaisedStreet3', Boolean), #BOOLEAN + Column('foldToOtherRaisedStreet4', Boolean), #BOOLEAN + + Column('stealAttemptChance', Boolean), #BOOLEAN + Column('stealAttempted', Boolean), #BOOLEAN + Column('foldBbToStealChance', Boolean), #BOOLEAN + Column('foldedBbToSteal', Boolean), #BOOLEAN + Column('foldSbToStealChance', Boolean), #BOOLEAN + Column('foldedSbToSteal', Boolean), #BOOLEAN + + Column('street1CBChance', Boolean), #BOOLEAN + Column('street1CBDone', Boolean), #BOOLEAN + Column('street2CBChance', Boolean), #BOOLEAN + Column('street2CBDone', Boolean), #BOOLEAN + Column('street3CBChance', Boolean), #BOOLEAN + Column('street3CBDone', Boolean), #BOOLEAN + Column('street4CBChance', Boolean), #BOOLEAN + Column('street4CBDone', Boolean), #BOOLEAN + + Column('foldToStreet1CBChance', Boolean), #BOOLEAN + Column('foldToStreet1CBDone', Boolean), #BOOLEAN + Column('foldToStreet2CBChance', Boolean), #BOOLEAN + Column('foldToStreet2CBDone', Boolean), #BOOLEAN + Column('foldToStreet3CBChance', Boolean), #BOOLEAN + Column('foldToStreet3CBDone', Boolean), #BOOLEAN + Column('foldToStreet4CBChance', Boolean), #BOOLEAN + Column('foldToStreet4CBDone', Boolean), #BOOLEAN + + Column('street1CheckCallRaiseChance',Boolean), #BOOLEAN + Column('street1CheckCallRaiseDone', Boolean), #BOOLEAN + Column('street2CheckCallRaiseChance',Boolean), #BOOLEAN + Column('street2CheckCallRaiseDone', Boolean), #BOOLEAN + Column('street3CheckCallRaiseChance',Boolean), #BOOLEAN + Column('street3CheckCallRaiseDone', Boolean), #BOOLEAN + Column('street4CheckCallRaiseChance',Boolean), #BOOLEAN + Column('street4CheckCallRaiseDone', Boolean), #BOOLEAN + + Column('street0Calls', SmallInteger), #TINYINT + Column('street1Calls', SmallInteger), #TINYINT + Column('street2Calls', SmallInteger), #TINYINT + Column('street3Calls', SmallInteger), #TINYINT + Column('street4Calls', SmallInteger), #TINYINT + Column('street0Bets', SmallInteger), #TINYINT + Column('street1Bets', SmallInteger), #TINYINT + Column('street2Bets', SmallInteger), #TINYINT + Column('street3Bets', SmallInteger), #TINYINT + Column('street4Bets', SmallInteger), #TINYINT + Column('street0Raises', SmallInteger), #TINYINT + Column('street1Raises', SmallInteger), #TINYINT + Column('street2Raises', SmallInteger), #TINYINT + Column('street3Raises', SmallInteger), #TINYINT + Column('street4Raises', SmallInteger), #TINYINT + + Column('actionString', String(15)), #VARCHAR(15) + mysql_charset='utf8', + mysql_engine='InnoDB', +) + + +hud_cache_table = Table('HudCache', metadata, + Column('id', BigIntColumn, primary_key=True), + Column('gametypeId', SmallInteger, ForeignKey("Gametypes.id"), nullable=False), # SMALLINT + Column('playerId', Integer, ForeignKey("Players.id"), nullable=False), # SMALLINT + Column('activeSeats', SmallInteger, nullable=False), # SMALLINT NOT NULL + Column('position', CHAR(1)), # CHAR(1) + Column('tourneyTypeId', Integer, ForeignKey("TourneyTypes.id") ), # SMALLINT + Column('styleKey', CHAR(7), nullable=False), # CHAR(7) NOT NULL + Column('m_factor', Integer), + Column('HDs', Integer, nullable=False), # INT NOT NULL + + Column('wonWhenSeenStreet1', Float), # FLOAT + Column('wonWhenSeenStreet2', Float), # FLOAT + Column('wonWhenSeenStreet3', Float), # FLOAT + Column('wonWhenSeenStreet4', Float), # FLOAT + Column('wonAtSD', Float), # FLOAT + + Column('street0VPI', Integer), # INT + Column('street0Aggr', Integer), # INT + Column('street0_3BChance', Integer), # INT + Column('street0_3BDone', Integer), # INT + Column('street0_4BChance', Integer), # INT + Column('street0_4BDone', Integer), # INT + Column('other3BStreet0', Integer), # INT + Column('other4BStreet0', Integer), # INT + + Column('street1Seen', Integer), # INT + Column('street2Seen', Integer), # INT + Column('street3Seen', Integer), # INT + Column('street4Seen', Integer), # INT + Column('sawShowdown', Integer), # INT + + Column('street1Aggr', Integer), # INT + Column('street2Aggr', Integer), # INT + Column('street3Aggr', Integer), # INT + Column('street4Aggr', Integer), # INT + + Column('otherRaisedStreet0', Integer), # INT + Column('otherRaisedStreet1', Integer), # INT + Column('otherRaisedStreet2', Integer), # INT + Column('otherRaisedStreet3', Integer), # INT + Column('otherRaisedStreet4', Integer), # INT + Column('foldToOtherRaisedStreet0', Integer), # INT + Column('foldToOtherRaisedStreet1', Integer), # INT + Column('foldToOtherRaisedStreet2', Integer), # INT + Column('foldToOtherRaisedStreet3', Integer), # INT + Column('foldToOtherRaisedStreet4', Integer), # INT + + Column('stealAttemptChance', Integer), # INT + Column('stealAttempted', Integer), # INT + Column('foldBbToStealChance', Integer), # INT + Column('foldedBbToSteal', Integer), # INT + Column('foldSbToStealChance', Integer), # INT + Column('foldedSbToSteal', Integer), # INT + + Column('street1CBChance', Integer), # INT + Column('street1CBDone', Integer), # INT + Column('street2CBChance', Integer), # INT + Column('street2CBDone', Integer), # INT + Column('street3CBChance', Integer), # INT + Column('street3CBDone', Integer), # INT + Column('street4CBChance', Integer), # INT + Column('street4CBDone', Integer), # INT + + Column('foldToStreet1CBChance', Integer), # INT + Column('foldToStreet1CBDone', Integer), # INT + Column('foldToStreet2CBChance', Integer), # INT + Column('foldToStreet2CBDone', Integer), # INT + Column('foldToStreet3CBChance', Integer), # INT + Column('foldToStreet3CBDone', Integer), # INT + Column('foldToStreet4CBChance', Integer), # INT + Column('foldToStreet4CBDone', Integer), # INT + + Column('totalProfit', Integer), # INT + + Column('street1CheckCallRaiseChance', Integer), # INT + Column('street1CheckCallRaiseDone', Integer), # INT + Column('street2CheckCallRaiseChance', Integer), # INT + Column('street2CheckCallRaiseDone', Integer), # INT + Column('street3CheckCallRaiseChance', Integer), # INT + Column('street3CheckCallRaiseDone', Integer), # INT + Column('street4CheckCallRaiseChance', Integer), # INT + Column('street4CheckCallRaiseDone', Integer), # INT + + Column('street0Calls', Integer), # INT + Column('street1Calls', Integer), # INT + Column('street2Calls', Integer), # INT + Column('street3Calls', Integer), # INT + Column('street4Calls', Integer), # INT + Column('street0Bets', Integer), # INT + Column('street1Bets', Integer), # INT + Column('street2Bets', Integer), # INT + Column('street3Bets', Integer), # INT + Column('street4Bets', Integer), # INT + Column('street0Raises', Integer), # INT + Column('street1Raises', Integer), # INT + Column('street2Raises', Integer), # INT + Column('street3Raises', Integer), # INT + Column('street4Raises', Integer), # INT + mysql_charset='utf8', + mysql_engine='InnoDB', +) + + +players_table = Table('Players', metadata, + Column('id', Integer, primary_key=True), + Column('name', Unicode(32), nullable=False), # VARCHAR(32) CHARACTER SET utf8 NOT NULL + Column('siteId', SmallInteger, ForeignKey("Sites.id"), nullable=False), # SMALLINT + Column('comment', Text), # text + Column('commentTs', DateTime), # DATETIME + mysql_charset='utf8', + mysql_engine='InnoDB', +) +Index('name', players_table.c.name, players_table.c.siteId, unique=True) + + +settings_table = Table('Settings', metadata, + Column('version', SmallInteger, nullable=False), + mysql_charset='utf8', + mysql_engine='InnoDB', +) + + +sites_table = Table('Sites', metadata, + Column('id', SmallInteger, primary_key=True), + Column('name', String(32), nullable=False), # varchar(32) NOT NULL + Column('currency', String(3), nullable=False), # char(3) NOT NULL + mysql_charset='utf8', + mysql_engine='InnoDB', +) + + +tourneys_table = Table('Tourneys', metadata, + Column('id', Integer, primary_key=True), + Column('tourneyTypeId', Integer, ForeignKey("TourneyTypes.id"), nullable=False, default=1), + Column('siteTourneyNo', BigIntColumn, nullable=False), # BIGINT NOT NULL + Column('entries', Integer), # INT NOT NULL + Column('prizepool', Integer), # INT NOT NULL + Column('tourStartTime', DateTime), # DATETIME NOT NULL + Column('tourEndTime', DateTime), # DATETIME + Column('buyinChips', Integer), # INT + Column('tourneyName', String(40)), # varchar(40) + # Mask use : 1=Positionnal Winnings|2=Match1|4=Match2|...|pow(2,n)=Matchn + Column('matrixIdProcessed',SmallInteger, default=0), # TINYINT UNSIGNED DEFAULT 0 + Column('rebuyChips', Integer, default=0), # INT DEFAULT 0 + Column('addonChips', Integer, default=0), # INT DEFAULT 0 + Column('rebuyAmount', MoneyColumn, default=0), # INT DEFAULT 0 + Column('addonAmount', MoneyColumn, default=0), # INT DEFAULT 0 + Column('totalRebuys', Integer, default=0), # INT DEFAULT 0 + Column('totalAddons', Integer, default=0), # INT DEFAULT 0 + Column('koBounty', Integer, default=0), # INT DEFAULT 0 + Column('comment', Text), # TEXT + Column('commentTs', DateTime), # DATETIME + mysql_charset='utf8', + mysql_engine='InnoDB', +) +Index('siteTourneyNo', tourneys_table.c.siteTourneyNo, tourneys_table.c.tourneyTypeId, unique=True) + + +tourney_types_table = Table('TourneyTypes', metadata, + Column('id', Integer, primary_key=True), + Column('siteId', SmallInteger, ForeignKey("Sites.id"), nullable=False), + Column('buyin', Integer, nullable=False), # INT NOT NULL + Column('fee', Integer, nullable=False, default=0), # INT NOT NULL + Column('maxSeats', Boolean, nullable=False, default=-1), # INT NOT NULL DEFAULT -1 + Column('knockout', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False + Column('rebuyOrAddon', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False + Column('speed', String(10)), # varchar(10) + Column('headsUp', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False + Column('shootout', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False + Column('matrix', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False + Column('sng', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False + mysql_charset='utf8', + mysql_engine='InnoDB', +) +Index('tourneyTypes_all', + tourney_types_table.c.siteId, tourney_types_table.c.buyin, tourney_types_table.c.fee, + tourney_types_table.c.maxSeats, tourney_types_table.c.knockout, tourney_types_table.c.rebuyOrAddon, + tourney_types_table.c.speed, tourney_types_table.c.headsUp, tourney_types_table.c.shootout, + tourney_types_table.c.matrix, tourney_types_table.c.sng) + + +tourneys_players_table = Table('TourneysPlayers', metadata, + Column('id', BigIntColumn, primary_key=True), + Column('tourneyId', Integer, ForeignKey("Tourneys.id"), nullable=False), + Column('playerId', Integer, ForeignKey("Players.id"), nullable=False), + Column('payinAmount', Integer), # INT NOT NULL + Column('rank', Integer), # INT NOT NULL + Column('winnings', Integer), # INT NOT NULL + Column('nbRebuys', Integer, default=0), # INT DEFAULT 0 + Column('nbAddons', Integer, default=0), # INT DEFAULT 0 + Column('nbKO', Integer, default=0), # INT DEFAULT 0 + Column('comment', Text), # TEXT + Column('commentTs', DateTime), # DATETIME + mysql_charset='utf8', + mysql_engine='InnoDB', +) +Index('tourneyId', tourneys_players_table.c.tourneyId, tourneys_players_table.c.playerId, unique=True) + + +def sss(): + "Debug function. Returns (config, sql, db)" + + import Configuration, SQL, Database, os + class Dummy(object): + pass + self = Dummy() + self.config = Configuration.Config() + self.settings = {} + if (os.sep=="/"): + self.settings['os']="linuxmac" + else: + self.settings['os']="windows" + + self.settings.update(self.config.get_db_parameters()) + self.settings.update(self.config.get_tv_parameters()) + self.settings.update(self.config.get_import_parameters()) + self.settings.update(self.config.get_default_paths()) + + self.sql = SQL.Sql( db_server = self.settings['db-server']) + self.db = Database.Database(self.config, sql = self.sql) + + return self.config, self.sql, self.db + From 8cb73b822cfc258cf89256dfd0bda8ad9f9cfdc9 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Fri, 1 Jan 2010 22:57:25 +0000 Subject: [PATCH 049/251] set stats color to fgcolor --- pyfpdb/Hud.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 2b6d0237..1a27b682 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -606,6 +606,7 @@ class Hud: if self.update_table_position() == False: # we got killed by finding our table was gone return + self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) for s in self.stat_dict: try: statd = self.stat_dict[s] @@ -629,20 +630,16 @@ class Hud: window = self.stat_windows[statd['seat']] if this_stat.hudcolor != "": - self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.hudcolor)) else: - self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) - window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#FFFFFF")) + window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) if this_stat.stat_loth != "": if number[0] < (float(this_stat.stat_loth)/100): - self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_locolor)) if this_stat.stat_hith != "": if number[0] > (float(this_stat.stat_hith)/100): - self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_hicolor)) window.label[r][c].set_text(statstring) From 1287ab95e736cfa58aea0b5d51ecc91765a5edf5 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Fri, 1 Jan 2010 20:53:27 -0500 Subject: [PATCH 050/251] stupid windows git newline mangling --- ...HE-6max-USD-0.05-0.10-200912.Allin-pre.txt | 82 +++++++++---------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt b/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt index b876c42a..6c3ba7d3 100644 --- a/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt +++ b/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt @@ -1,41 +1,41 @@ -PokerStars Game #37165169101: Hold'em No Limit ($0.10/$0.25 USD) - 2009/12/25 9:50:09 ET -Table 'Lucretia IV' 6-max Seat #2 is the button -Seat 1: Blåveis ($55.10 in chips) -Seat 2: Kinewma ($31.40 in chips) -Seat 3: AAALISAAAA ($20.20 in chips) -Seat 4: Arbaz ($25 in chips) -Seat 5: s0rrow ($29.85 in chips) -Seat 6: bys7 ($41.35 in chips) -AAALISAAAA: posts small blind $0.10 -Arbaz: posts big blind $0.25 -*** HOLE CARDS *** -Dealt to s0rrow [Ac As] -s0rrow: raises $0.50 to $0.75 -bys7: calls $0.75 -Blåveis: folds -Kinewma: folds -AAALISAAAA: raises $1.50 to $2.25 -Arbaz: folds -s0rrow: raises $3.50 to $5.75 -bys7: folds -AAALISAAAA: raises $14.45 to $20.20 and is all-in -s0rrow: calls $14.45 -*** FLOP *** [3d 7h Kh] -*** TURN *** [3d 7h Kh] [Ts] -*** RIVER *** [3d 7h Kh Ts] [5c] -*** SHOW DOWN *** -AAALISAAAA: shows [Kd 5d] (two pair, Kings and Fives) -s0rrow: shows [Ac As] (a pair of Aces) -AAALISAAAA collected $39.35 from pot -*** SUMMARY *** -Total pot $41.40 | Rake $2.05 -Board [3d 7h Kh Ts 5c] -Seat 1: Blåveis folded before Flop (didn't bet) -Seat 2: Kinewma (button) folded before Flop (didn't bet) -Seat 3: AAALISAAAA (small blind) showed [Kd 5d] and won ($39.35) with two pair, Kings and Fives -Seat 4: Arbaz (big blind) folded before Flop -Seat 5: s0rrow showed [Ac As] and lost with a pair of Aces -Seat 6: bys7 folded before Flop - - - +PokerStars Game #37165169101: Hold'em No Limit ($0.10/$0.25 USD) - 2009/12/25 9:50:09 ET +Table 'Lucretia IV' 6-max Seat #2 is the button +Seat 1: Blåveis ($55.10 in chips) +Seat 2: Kinewma ($31.40 in chips) +Seat 3: AAALISAAAA ($20.20 in chips) +Seat 4: Arbaz ($25 in chips) +Seat 5: s0rrow ($29.85 in chips) +Seat 6: bys7 ($41.35 in chips) +AAALISAAAA: posts small blind $0.10 +Arbaz: posts big blind $0.25 +*** HOLE CARDS *** +Dealt to s0rrow [Ac As] +s0rrow: raises $0.50 to $0.75 +bys7: calls $0.75 +Blåveis: folds +Kinewma: folds +AAALISAAAA: raises $1.50 to $2.25 +Arbaz: folds +s0rrow: raises $3.50 to $5.75 +bys7: folds +AAALISAAAA: raises $14.45 to $20.20 and is all-in +s0rrow: calls $14.45 +*** FLOP *** [3d 7h Kh] +*** TURN *** [3d 7h Kh] [Ts] +*** RIVER *** [3d 7h Kh Ts] [5c] +*** SHOW DOWN *** +AAALISAAAA: shows [Kd 5d] (two pair, Kings and Fives) +s0rrow: shows [Ac As] (a pair of Aces) +AAALISAAAA collected $39.35 from pot +*** SUMMARY *** +Total pot $41.40 | Rake $2.05 +Board [3d 7h Kh Ts 5c] +Seat 1: Blåveis folded before Flop (didn't bet) +Seat 2: Kinewma (button) folded before Flop (didn't bet) +Seat 3: AAALISAAAA (small blind) showed [Kd 5d] and won ($39.35) with two pair, Kings and Fives +Seat 4: Arbaz (big blind) folded before Flop +Seat 5: s0rrow showed [Ac As] and lost with a pair of Aces +Seat 6: bys7 folded before Flop + + + From 62935664c80099f93d25b5dd4ca0628f9cc56f71 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Fri, 1 Jan 2010 22:57:25 +0000 Subject: [PATCH 051/251] set stats color to fgcolor --- pyfpdb/Hud.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 2b6d0237..1a27b682 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -606,6 +606,7 @@ class Hud: if self.update_table_position() == False: # we got killed by finding our table was gone return + self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) for s in self.stat_dict: try: statd = self.stat_dict[s] @@ -629,20 +630,16 @@ class Hud: window = self.stat_windows[statd['seat']] if this_stat.hudcolor != "": - self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.hudcolor)) else: - self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) - window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#FFFFFF")) + window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) if this_stat.stat_loth != "": if number[0] < (float(this_stat.stat_loth)/100): - self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_locolor)) if this_stat.stat_hith != "": if number[0] > (float(this_stat.stat_hith)/100): - self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_hicolor)) window.label[r][c].set_text(statstring) From 659443127711355cd47dc5a133bb456ddaae8a03 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 12 Jan 2010 22:10:59 +0000 Subject: [PATCH 052/251] fix twostartcards to handle 22 and unknowns properly --- pyfpdb/Card.py | 35 ++++++++++++++++++++++++----------- pyfpdb/GuiPlayerStats.py | 4 ++-- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/pyfpdb/Card.py b/pyfpdb/Card.py index 8639fd35..22eab979 100755 --- a/pyfpdb/Card.py +++ b/pyfpdb/Card.py @@ -39,23 +39,36 @@ def calcStartCards(hand, player): def twoStartCards(value1, suit1, value2, suit2): """ Function to convert 2 value,suit pairs into a Holdem style starting hand e.g. AQo - Hand is stored as an int 13 * x + y where (x+2) represents rank of 1st card and + Incoming values should be ints 2-14 (2,3,...K,A), suits are 'd'/'h'/'c'/'s' + Hand is stored as an int 13 * x + y + 1 where (x+2) represents rank of 1st card and (y+2) represents rank of second card (2=2 .. 14=Ace) - If x > y then pair is suited, if x < y then unsuited""" - if value1 < 2 or value2 < 2: + If x > y then pair is suited, if x < y then unsuited + Examples: + 0 Unknown / Illegal cards + 1 22 + 2 32o + 3 42o + ... + 14 32s + 15 33 + 16 42o + ... + 170 AA + """ + if value1 is None or value1 < 2 or value1 > 14 or value2 is None or value2 < 2 or value2 > 14: ret = 0 - if value1 == value2: # pairs - ret = (13 * (value2-2) + (value2-2) ) + elif value1 == value2: # pairs + ret = (13 * (value2-2) + (value2-2) ) + 1 elif suit1 == suit2: if value1 > value2: - ret = 13 * (value1-2) + (value2-2) + ret = 13 * (value1-2) + (value2-2) + 1 else: - ret = 13 * (value2-2) + (value1-2) + ret = 13 * (value2-2) + (value1-2) + 1 else: if value1 > value2: - ret = 13 * (value2-2) + (value1-2) + ret = 13 * (value2-2) + (value1-2) + 1 else: - ret = 13 * (value1-2) + (value2-2) + ret = 13 * (value1-2) + (value2-2) + 1 # print "twoStartCards(", value1, suit1, value2, suit2, ")=", ret return ret @@ -66,8 +79,8 @@ def twoStartCardString(card): ret = 'xx' if card > 0: s = ('2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A') - x = card / 13 - y = card - 13 * x + x = (card-1) / 13 + y = (card-1) - 13 * x if x == y: ret = s[x] + s[y] elif x > y: ret = s[x] + s[y] + 's' else: ret = s[y] + s[x] + 'o' diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index d65b9ab6..889988c5 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -516,8 +516,8 @@ class GuiPlayerStats (threading.Thread): if holecards: # re-use level variables for hole card query query = query.replace("", "hp.startcards") query = query.replace("" - , ",case when floor(hp.startcards/13) >= mod(hp.startcards,13) then hp.startcards + 0.1 " - + " else 13*mod(hp.startcards,13) + floor(hp.startcards/13) " + , ",case when floor((hp.startcards-1)/13) >= mod((hp.startcards-1),13) then hp.startcards + 0.1 " + + " else 13*mod((hp.startcards-1),13) + floor((hp.startcards-1)/13) + 1 " + " end desc ") else: query = query.replace("", "") From 012b5bc72c5ec08043237f619e10814d07c04f3c Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 12 Jan 2010 22:10:59 +0000 Subject: [PATCH 053/251] fix twostartcards to handle 22 and unknowns properly --- pyfpdb/Card.py | 35 ++++++++++++++++++++++++----------- pyfpdb/GuiPlayerStats.py | 4 ++-- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/pyfpdb/Card.py b/pyfpdb/Card.py index 287a0f6a..3eef58c5 100755 --- a/pyfpdb/Card.py +++ b/pyfpdb/Card.py @@ -20,23 +20,36 @@ def twoStartCards(value1, suit1, value2, suit2): """ Function to convert 2 value,suit pairs into a Holdem style starting hand e.g. AQo - Hand is stored as an int 13 * x + y where (x+2) represents rank of 1st card and + Incoming values should be ints 2-14 (2,3,...K,A), suits are 'd'/'h'/'c'/'s' + Hand is stored as an int 13 * x + y + 1 where (x+2) represents rank of 1st card and (y+2) represents rank of second card (2=2 .. 14=Ace) - If x > y then pair is suited, if x < y then unsuited""" - if value1 < 2 or value2 < 2: + If x > y then pair is suited, if x < y then unsuited + Examples: + 0 Unknown / Illegal cards + 1 22 + 2 32o + 3 42o + ... + 14 32s + 15 33 + 16 42o + ... + 170 AA + """ + if value1 is None or value1 < 2 or value1 > 14 or value2 is None or value2 < 2 or value2 > 14: ret = 0 - if value1 == value2: # pairs - ret = (13 * (value2-2) + (value2-2) ) + elif value1 == value2: # pairs + ret = (13 * (value2-2) + (value2-2) ) + 1 elif suit1 == suit2: if value1 > value2: - ret = 13 * (value1-2) + (value2-2) + ret = 13 * (value1-2) + (value2-2) + 1 else: - ret = 13 * (value2-2) + (value1-2) + ret = 13 * (value2-2) + (value1-2) + 1 else: if value1 > value2: - ret = 13 * (value2-2) + (value1-2) + ret = 13 * (value2-2) + (value1-2) + 1 else: - ret = 13 * (value1-2) + (value2-2) + ret = 13 * (value1-2) + (value2-2) + 1 # print "twoStartCards(", value1, suit1, value2, suit2, ")=", ret return ret @@ -47,8 +60,8 @@ def twoStartCardString(card): ret = 'xx' if card > 0: s = ('2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A') - x = card / 13 - y = card - 13 * x + x = (card-1) / 13 + y = (card-1) - 13 * x if x == y: ret = s[x] + s[y] elif x > y: ret = s[x] + s[y] + 's' else: ret = s[y] + s[x] + 'o' diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index d65b9ab6..889988c5 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -516,8 +516,8 @@ class GuiPlayerStats (threading.Thread): if holecards: # re-use level variables for hole card query query = query.replace("", "hp.startcards") query = query.replace("" - , ",case when floor(hp.startcards/13) >= mod(hp.startcards,13) then hp.startcards + 0.1 " - + " else 13*mod(hp.startcards,13) + floor(hp.startcards/13) " + , ",case when floor((hp.startcards-1)/13) >= mod((hp.startcards-1),13) then hp.startcards + 0.1 " + + " else 13*mod((hp.startcards-1),13) + floor((hp.startcards-1)/13) + 1 " + " end desc ") else: query = query.replace("", "") From bad744fd80ac6092a7d02deda0721157db9e61bf Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 15 Jan 2010 13:50:46 +0800 Subject: [PATCH 054/251] [NEWIMPORT] setPositions(), fix aggr function PFR now actually works --- pyfpdb/DerivedStats.py | 73 +++++++++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 22 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 7c50178b..920d60cf 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -48,6 +48,7 @@ class DerivedStats(): self.handsplayers[player[1]]['sawShowdown'] = False self.handsplayers[player[1]]['wonAtSD'] = 0.0 self.handsplayers[player[1]]['startCards'] = 0 + self.handsplayers[player[1]]['position'] = 2 for i in range(5): self.handsplayers[player[1]]['street%dCalls' % i] = 0 self.handsplayers[player[1]]['street%dBets' % i] = 0 @@ -56,7 +57,6 @@ class DerivedStats(): self.handsplayers[player[1]]['street%dCBDone' %i] = False #FIXME - Everything below this point is incomplete. - self.handsplayers[player[1]]['position'] = 2 self.handsplayers[player[1]]['tourneyTypeId'] = 1 self.handsplayers[player[1]]['street0_3BChance'] = False self.handsplayers[player[1]]['street0_3BDone'] = False @@ -174,31 +174,41 @@ class DerivedStats(): self.handsplayers[player[1]]['card%s' % (i+1)] = Card.encodeCard(card) self.handsplayers[player[1]]['startCards'] = Card.calcStartCards(hand, player[1]) - # position, - #Stud 3rd street card test - # denny501: brings in for $0.02 - # s0rrow: calls $0.02 - # TomSludge: folds - # Soroka69: calls $0.02 - # rdiezchang: calls $0.02 (Seat 8) - # u.pressure: folds (Seat 1) - # 123smoothie: calls $0.02 - # gashpor: calls $0.02 - + self.setPositions(hand) # Additional stats # 3betSB, 3betBB # Squeeze, Ratchet? - def getPosition(hand, seat): - """Returns position value like 'B', 'S', 0, 1, ...""" - # Flop/Draw games with blinds - # Need a better system??? - # -2 BB - B (all) - # -1 SB - S (all) - # 0 Button - # 1 Cutoff - # 2 Hijack + def setPositions(self, hand): + """Sets the position for each player in HandsPlayers + any blinds are negative values, and the last person to act on the + first betting round is 0 + NOTE: HU, both values are negative for non-stud games + NOTE2: I've never seen a HU stud match""" + # The position calculation must be done differently for Stud and other games as + # Stud the 'blind' acts first - in all other games they act last. + # + #This function is going to get it wrong when there in situations where there + # is no small blind. I can live with that. + positions = [7, 6, 5, 4, 3, 2, 1, 0, 'S', 'B'] + actions = hand.actions[hand.holeStreets[0]] + players = self.pfbao(actions) + seats = len(players) + map = [] + if hand.gametype['base'] == 'stud': + # Could posibly change this to be either -2 or -1 depending if they complete or bring-in + # First player to act is -1, last player is 0 for 6 players it should look like: + # ['S', 4, 3, 2, 1, 0] + map = positions[-seats-1:-1] # Copy required positions from postions array anding in -1 + map = map[-1:] + map[0:-1] # and move the -1 to the start of that array + else: + # For 6 players is should look like: + # [3, 2, 1, 0, 'S', 'B'] + map = positions[-seats:] # Copy required positions from array ending in -2 + + for i, player in enumerate(players): + self.handsplayers[player]['position'] = map[i] def assembleHudCache(self, hand): # No real work to be done - HandsPlayers data already contains the correct info @@ -362,11 +372,13 @@ class DerivedStats(): def aggr(self, hand, i): aggrers = set() - for act in hand.actions[hand.actionStreets[i]]: + # Growl - actionStreets contains 'BLINDSANTES', which isn't actually an action street + for act in hand.actions[hand.actionStreets[i+1]]: if act[1] in ('completes', 'bets', 'raises'): aggrers.add(act[0]) for player in hand.players: + #print "DEBUG: actionStreet[%s]: %s" %(hand.actionStreets[i+1], i) if player[1] in aggrers: self.handsplayers[player[1]]['street%sAggr' % i] = True else: @@ -402,6 +414,23 @@ class DerivedStats(): players.add(action[0]) return players + def pfbao(self, actions, f=None, l=None, unique=True): + """Helper method. Returns set of PlayersFilteredByActionsOrdered + + f - forbidden actions + l - limited to actions + """ + # Note, this is an adaptation of function 5 from: + # http://www.peterbe.com/plog/uniqifiers-benchmark + seen = {} + players = [] + for action in actions: + if l is not None and action[1] not in l: continue + if f is not None and action[1] in f: continue + if action[0] in seen and unique: continue + seen[action[0]] = 1 + players.append(action[0]) + return players def firstsBetOrRaiser(self, actions): """Returns player name that placed the first bet or raise. From 700a68bcc803647251dde8ce53c44b151458bd16 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 15 Jan 2010 18:29:16 +0800 Subject: [PATCH 055/251] [NEWIMPORT] calcCheckCallRaise() Modify function from Grigorij to calculate check/call --- pyfpdb/DerivedStats.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 920d60cf..fe857ae4 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -55,6 +55,8 @@ class DerivedStats(): for i in range(1,5): self.handsplayers[player[1]]['street%dCBChance' %i] = False self.handsplayers[player[1]]['street%dCBDone' %i] = False + self.handsplayers[player[1]]['street%dCheckCallRaiseChance' %i] = False + self.handsplayers[player[1]]['street%dCheckCallRaiseDone' %i] = False #FIXME - Everything below this point is incomplete. self.handsplayers[player[1]]['tourneyTypeId'] = 1 @@ -72,8 +74,6 @@ class DerivedStats(): self.handsplayers[player[1]]['foldToOtherRaisedStreet%d' %i] = False self.handsplayers[player[1]]['foldToStreet%dCBChance' %i] = False self.handsplayers[player[1]]['foldToStreet%dCBDone' %i] = False - self.handsplayers[player[1]]['street%dCheckCallRaiseChance' %i] = False - self.handsplayers[player[1]]['street%dCheckCallRaiseDone' %i] = False self.assembleHands(self.hand) self.assembleHandsPlayers(self.hand) @@ -175,6 +175,7 @@ class DerivedStats(): self.handsplayers[player[1]]['startCards'] = Card.calcStartCards(hand, player[1]) self.setPositions(hand) + self.calcCheckCallRaise(hand) # Additional stats # 3betSB, 3betBB # Squeeze, Ratchet? @@ -352,12 +353,11 @@ class DerivedStats(): pname, act = action[0], action[1] if act in ('bets', 'raises') and initial_raiser is None: initial_raiser = pname - elif act == 'check' and initial_raiser is None: + elif act == 'checks' and initial_raiser is None: checkers.add(pname) elif initial_raiser is not None and pname in checkers: - hp = self.handplayers_by_name[pname] - setattr(hp, 'street%dCheckCallRaiseChance' % i, True) - setattr(hp, 'street%dCheckCallRaiseDone' % i, act!='folds') + self.handsplayers[pname]['street%dCheckCallRaiseChance' % i] = True + self.handsplayers[pname]['street%dCheckCallRaiseDone' % i] = act!='folds' def seen(self, hand, i): pas = set() From ecf1c6b878ebcc02f49c751c6c9228014812f316 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 15 Jan 2010 19:42:24 +0800 Subject: [PATCH 056/251] [NEWIMPORT] Almost all remaining stats All conversions from Grigorij street0_3BChance street0_3BDone street0_4BChance street0_4BDone stealAttemptChance stealAttempted foldBbToStealChance foldBbToStealChance foldSbToStealChance foldedSbToSteal foldedBbToSteal 3Bet, 4Bet in Stud does appear to work. Unable to test steal in Stud games, all example hands in micros do not have a chance (I believe) --- pyfpdb/DerivedStats.py | 59 +++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index fe857ae4..8b9af93b 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -49,6 +49,17 @@ class DerivedStats(): self.handsplayers[player[1]]['wonAtSD'] = 0.0 self.handsplayers[player[1]]['startCards'] = 0 self.handsplayers[player[1]]['position'] = 2 + self.handsplayers[player[1]]['street0_3BChance'] = False + self.handsplayers[player[1]]['street0_3BDone'] = False + self.handsplayers[player[1]]['street0_4BChance'] = False + self.handsplayers[player[1]]['street0_4BDone'] = False + self.handsplayers[player[1]]['stealAttemptChance'] = False + self.handsplayers[player[1]]['stealAttempted'] = False + self.handsplayers[player[1]]['foldBbToStealChance'] = False + self.handsplayers[player[1]]['foldBbToStealChance'] = False + self.handsplayers[player[1]]['foldSbToStealChance'] = False + self.handsplayers[player[1]]['foldedSbToSteal'] = False + self.handsplayers[player[1]]['foldedBbToSteal'] = False for i in range(5): self.handsplayers[player[1]]['street%dCalls' % i] = 0 self.handsplayers[player[1]]['street%dBets' % i] = 0 @@ -60,15 +71,6 @@ class DerivedStats(): #FIXME - Everything below this point is incomplete. self.handsplayers[player[1]]['tourneyTypeId'] = 1 - self.handsplayers[player[1]]['street0_3BChance'] = False - self.handsplayers[player[1]]['street0_3BDone'] = False - self.handsplayers[player[1]]['stealAttemptChance'] = False - self.handsplayers[player[1]]['stealAttempted'] = False - self.handsplayers[player[1]]['foldBbToStealChance'] = False - self.handsplayers[player[1]]['foldBbToStealChance'] = False - self.handsplayers[player[1]]['foldSbToStealChance'] = False - self.handsplayers[player[1]]['foldedSbToSteal'] = False - self.handsplayers[player[1]]['foldedBbToSteal'] = False for i in range(1,5): self.handsplayers[player[1]]['otherRaisedStreet%d' %i] = False self.handsplayers[player[1]]['foldToOtherRaisedStreet%d' %i] = False @@ -176,6 +178,8 @@ class DerivedStats(): self.setPositions(hand) self.calcCheckCallRaise(hand) + self.calc34BetStreet0(hand) + self.calcSteals(hand) # Additional stats # 3betSB, 3betBB # Squeeze, Ratchet? @@ -280,28 +284,29 @@ class DerivedStats(): Steal attemp - open raise on positions 2 1 0 S - i.e. MP3, CO, BU, SB Fold to steal - folding blind after steal attemp wo any other callers or raisers """ - if self.gametype_dict['base'] != 'hold': - # FIXME: add support for other games //grindi - return steal_attemp = False + steal_positions = ('2', '1', '0', 'S') + if hand.gametype['base'] == 'stud': + steal_positions = ('2', '1', '0') for action in hand.actions[hand.actionStreets[1]]: - hp, act = self.handplayers_by_name[action[0]], action[1] + pname, act = action[0], action[1] #print action[0], hp.position, steal_attemp, act - if hp.position == 'B': - hp.foldBbToStealChance = steal_attemp - hp.foldBbToSteal = hp.foldBbToStealChance and act == 'folds' + if self.handsplayers[pname]['position'] == 'B': + #NOTE: Stud games will never hit this section + self.handsplayers[pname]['foldBbToStealChance'] = steal_attemp + self.handsplayers[pname]['foldBbToSteal'] = self.handsplayers[pname]['foldBbToStealChance'] and act == 'folds' break - elif hp.position == 'S': - hp.foldSbToStealChance = steal_attemp - hp.foldSbToSteal = hp.foldSbToStealChance and act == 'folds' + elif self.handsplayers[pname]['position'] == 'S': + self.handsplayers[pname]['foldSbToStealChance'] = steal_attemp + self.handsplayers[pname]['foldSbToSteal'] = self.handsplayers[pname]['foldSbToStealChance'] and act == 'folds' if steal_attemp and act != 'folds': break - if hp.position in ('2', '1', '0', 'S') and not steal_attemp: - hp.stealAttemptChance = True + if self.handsplayers[pname]['position'] in steal_positions and not steal_attemp: + self.handsplayers[pname]['stealAttemptChance'] = True if act in ('bets', 'raises'): - hp.stealAttempted = True + self.handsplayers[pname]['stealAttempted'] = True steal_attemp = True def calc34BetStreet0(self, hand): @@ -309,11 +314,11 @@ class DerivedStats(): bet_level = 1 # bet_level after 3-bet is equal to 3 for action in hand.actions[hand.actionStreets[1]]: # FIXME: fill other(3|4)BStreet0 - i have no idea what does it mean - hp, aggr = self.handplayers_by_name[action[0]], action[1] in ('raises', 'bets') - hp.street0_3BChance = bet_level == 2 - hp.street0_4BChance = bet_level == 3 - hp.street0_3BDone = aggr and (hp.street0_3BChance) - hp.street0_4BDone = aggr and (hp.street0_4BChance) + pname, aggr = action[0], action[1] in ('raises', 'bets') + self.handsplayers[pname]['street0_3BChance'] = bet_level == 2 + self.handsplayers[pname]['street0_4BChance'] = bet_level == 3 + self.handsplayers[pname]['street0_3BDone'] = aggr and (self.handsplayers[pname]['street0_3BChance']) + self.handsplayers[pname]['street0_4BDone'] = aggr and (self.handsplayers[pname]['street0_4BChance']) if aggr: bet_level += 1 From 95aa993903fe075cd89dc43a45c900f0ad19332e Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 15 Jan 2010 13:50:46 +0800 Subject: [PATCH 057/251] [NEWIMPORT] setPositions(), fix aggr function PFR now actually works --- pyfpdb/DerivedStats.py | 105 ++++++++++++++++++++++++++++------------- 1 file changed, 73 insertions(+), 32 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index b65b0d05..bd36f0fb 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -48,6 +48,7 @@ class DerivedStats(): self.handsplayers[player[1]]['sawShowdown'] = False self.handsplayers[player[1]]['wonAtSD'] = 0.0 self.handsplayers[player[1]]['startCards'] = 0 + self.handsplayers[player[1]]['position'] = 2 for i in range(5): self.handsplayers[player[1]]['street%dCalls' % i] = 0 self.handsplayers[player[1]]['street%dBets' % i] = 0 @@ -56,7 +57,6 @@ class DerivedStats(): self.handsplayers[player[1]]['street%dCBDone' %i] = False #FIXME - Everything below this point is incomplete. - self.handsplayers[player[1]]['position'] = 2 self.handsplayers[player[1]]['tourneyTypeId'] = 1 self.handsplayers[player[1]]['street0_3BChance'] = False self.handsplayers[player[1]]['street0_3BDone'] = False @@ -174,31 +174,41 @@ class DerivedStats(): self.handsplayers[player[1]]['card%s' % (i+1)] = Card.encodeCard(card) self.handsplayers[player[1]]['startCards'] = Card.calcStartCards(hand, player[1]) - # position, - #Stud 3rd street card test - # denny501: brings in for $0.02 - # s0rrow: calls $0.02 - # TomSludge: folds - # Soroka69: calls $0.02 - # rdiezchang: calls $0.02 (Seat 8) - # u.pressure: folds (Seat 1) - # 123smoothie: calls $0.02 - # gashpor: calls $0.02 - + self.setPositions(hand) # Additional stats # 3betSB, 3betBB # Squeeze, Ratchet? - def getPosition(hand, seat): - """Returns position value like 'B', 'S', 0, 1, ...""" - # Flop/Draw games with blinds - # Need a better system??? - # -2 BB - B (all) - # -1 SB - S (all) - # 0 Button - # 1 Cutoff - # 2 Hijack + def setPositions(self, hand): + """Sets the position for each player in HandsPlayers + any blinds are negative values, and the last person to act on the + first betting round is 0 + NOTE: HU, both values are negative for non-stud games + NOTE2: I've never seen a HU stud match""" + # The position calculation must be done differently for Stud and other games as + # Stud the 'blind' acts first - in all other games they act last. + # + #This function is going to get it wrong when there in situations where there + # is no small blind. I can live with that. + positions = [7, 6, 5, 4, 3, 2, 1, 0, 'S', 'B'] + actions = hand.actions[hand.holeStreets[0]] + players = self.pfbao(actions) + seats = len(players) + map = [] + if hand.gametype['base'] == 'stud': + # Could posibly change this to be either -2 or -1 depending if they complete or bring-in + # First player to act is -1, last player is 0 for 6 players it should look like: + # ['S', 4, 3, 2, 1, 0] + map = positions[-seats-1:-1] # Copy required positions from postions array anding in -1 + map = map[-1:] + map[0:-1] # and move the -1 to the start of that array + else: + # For 6 players is should look like: + # [3, 2, 1, 0, 'S', 'B'] + map = positions[-seats:] # Copy required positions from array ending in -2 + + for i, player in enumerate(players): + self.handsplayers[player]['position'] = map[i] def assembleHudCache(self, hand): pass @@ -293,11 +303,13 @@ class DerivedStats(): def aggr(self, hand, i): aggrers = set() - for act in hand.actions[hand.actionStreets[i]]: - if act[1] in ('completes', 'raises'): + # Growl - actionStreets contains 'BLINDSANTES', which isn't actually an action street + for act in hand.actions[hand.actionStreets[i+1]]: + if act[1] in ('completes', 'bets', 'raises'): aggrers.add(act[0]) for player in hand.players: + #print "DEBUG: actionStreet[%s]: %s" %(hand.actionStreets[i+1], i) if player[1] in aggrers: self.handsplayers[player[1]]['street%sAggr' % i] = True else: @@ -333,6 +345,44 @@ class DerivedStats(): players.add(action[0]) return players + def pfbao(self, actions, f=None, l=None, unique=True): + """Helper method. Returns set of PlayersFilteredByActionsOrdered + + f - forbidden actions + l - limited to actions + """ + # Note, this is an adaptation of function 5 from: + # http://www.peterbe.com/plog/uniqifiers-benchmark + seen = {} + players = [] + for action in actions: + if l is not None and action[1] not in l: continue + if f is not None and action[1] in f: continue + if action[0] in seen and unique: continue + seen[action[0]] = 1 + players.append(action[0]) + return players + + def firstsBetOrRaiser(self, actions): + """Returns player name that placed the first bet or raise. + + None if there were no bets or raises on that street + """ + for act in actions: + if act[1] in ('bets', 'raises'): + return act[0] + return None + + def lastBetOrRaiser(self, street): + """Returns player name that placed the last bet or raise for that street. + None if there were no bets or raises on that street""" + lastbet = None + for act in self.hand.actions[street]: + if act[1] in ('bets', 'raises'): + lastbet = act[0] + return lastbet + + def noBetsBefore(self, street, player): """Returns true if there were no bets before the specified players turn, false otherwise""" betOrRaise = False @@ -355,12 +405,3 @@ class DerivedStats(): break return betOrRaise - - def lastBetOrRaiser(self, street): - """Returns player name that placed the last bet or raise for that street. - None if there were no bets or raises on that street""" - lastbet = None - for act in self.hand.actions[street]: - if act[1] in ('bets', 'raises'): - lastbet = act[0] - return lastbet From 150b1891d63ad0d557add7f6beb891942c197453 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 15 Jan 2010 13:50:46 +0800 Subject: [PATCH 058/251] [NEWIMPORT] setPositions(), fix aggr function PFR now actually works --- pyfpdb/DerivedStats.py | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index bd36f0fb..e064f6be 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -55,6 +55,8 @@ class DerivedStats(): for i in range(1,5): self.handsplayers[player[1]]['street%dCBChance' %i] = False self.handsplayers[player[1]]['street%dCBDone' %i] = False + self.handsplayers[player[1]]['street%dCheckCallRaiseChance' %i] = False + self.handsplayers[player[1]]['street%dCheckCallRaiseDone' %i] = False #FIXME - Everything below this point is incomplete. self.handsplayers[player[1]]['tourneyTypeId'] = 1 @@ -72,8 +74,6 @@ class DerivedStats(): self.handsplayers[player[1]]['foldToOtherRaisedStreet%d' %i] = False self.handsplayers[player[1]]['foldToStreet%dCBChance' %i] = False self.handsplayers[player[1]]['foldToStreet%dCBDone' %i] = False - self.handsplayers[player[1]]['street%dCheckCallRaiseChance' %i] = False - self.handsplayers[player[1]]['street%dCheckCallRaiseDone' %i] = False self.assembleHands(self.hand) self.assembleHandsPlayers(self.hand) @@ -175,6 +175,7 @@ class DerivedStats(): self.handsplayers[player[1]]['startCards'] = Card.calcStartCards(hand, player[1]) self.setPositions(hand) + self.calcCheckCallRaise(hand) # Additional stats # 3betSB, 3betBB # Squeeze, Ratchet? @@ -290,6 +291,28 @@ class DerivedStats(): if chance == True: self.handsplayers[name]['street%dCBDone' % (i+1)] = self.betStreet(hand.actionStreets[i+2], name) + def calcCheckCallRaise(self, hand): + """Fill streetXCheckCallRaiseChance, streetXCheckCallRaiseDone + + streetXCheckCallRaiseChance = got raise/bet after check + streetXCheckCallRaiseDone = checked. got raise/bet. didn't fold + + CG: CheckCall would be a much better name for this. + """ + for i, street in enumerate(hand.actionStreets[2:], start=1): + actions = hand.actions[hand.actionStreets[i]] + checkers = set() + initial_raiser = None + for action in actions: + pname, act = action[0], action[1] + if act in ('bets', 'raises') and initial_raiser is None: + initial_raiser = pname + elif act == 'checks' and initial_raiser is None: + checkers.add(pname) + elif initial_raiser is not None and pname in checkers: + self.handsplayers[pname]['street%dCheckCallRaiseChance' % i] = True + self.handsplayers[pname]['street%dCheckCallRaiseDone' % i] = act!='folds' + def seen(self, hand, i): pas = set() for act in hand.actions[hand.actionStreets[i+1]]: From 5c0d695055fcfbdbaf64a82e7cde2e62bbe5d065 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 15 Jan 2010 19:42:24 +0800 Subject: [PATCH 059/251] [NEWIMPORT] Almost all remaining stats All conversions from Grigorij street0_3BChance street0_3BDone street0_4BChance street0_4BDone stealAttemptChance stealAttempted foldBbToStealChance foldBbToStealChance foldSbToStealChance foldedSbToSteal foldedBbToSteal 3Bet, 4Bet in Stud does appear to work. Unable to test steal in Stud games, all example hands in micros do not have a chance (I believe) --- pyfpdb/DerivedStats.py | 80 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 65 insertions(+), 15 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index e064f6be..f96b6af7 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -49,6 +49,17 @@ class DerivedStats(): self.handsplayers[player[1]]['wonAtSD'] = 0.0 self.handsplayers[player[1]]['startCards'] = 0 self.handsplayers[player[1]]['position'] = 2 + self.handsplayers[player[1]]['street0_3BChance'] = False + self.handsplayers[player[1]]['street0_3BDone'] = False + self.handsplayers[player[1]]['street0_4BChance'] = False + self.handsplayers[player[1]]['street0_4BDone'] = False + self.handsplayers[player[1]]['stealAttemptChance'] = False + self.handsplayers[player[1]]['stealAttempted'] = False + self.handsplayers[player[1]]['foldBbToStealChance'] = False + self.handsplayers[player[1]]['foldBbToStealChance'] = False + self.handsplayers[player[1]]['foldSbToStealChance'] = False + self.handsplayers[player[1]]['foldedSbToSteal'] = False + self.handsplayers[player[1]]['foldedBbToSteal'] = False for i in range(5): self.handsplayers[player[1]]['street%dCalls' % i] = 0 self.handsplayers[player[1]]['street%dBets' % i] = 0 @@ -60,15 +71,6 @@ class DerivedStats(): #FIXME - Everything below this point is incomplete. self.handsplayers[player[1]]['tourneyTypeId'] = 1 - self.handsplayers[player[1]]['street0_3BChance'] = False - self.handsplayers[player[1]]['street0_3BDone'] = False - self.handsplayers[player[1]]['stealAttemptChance'] = False - self.handsplayers[player[1]]['stealAttempted'] = False - self.handsplayers[player[1]]['foldBbToStealChance'] = False - self.handsplayers[player[1]]['foldBbToStealChance'] = False - self.handsplayers[player[1]]['foldSbToStealChance'] = False - self.handsplayers[player[1]]['foldedSbToSteal'] = False - self.handsplayers[player[1]]['foldedBbToSteal'] = False for i in range(1,5): self.handsplayers[player[1]]['otherRaisedStreet%d' %i] = False self.handsplayers[player[1]]['foldToOtherRaisedStreet%d' %i] = False @@ -176,6 +178,8 @@ class DerivedStats(): self.setPositions(hand) self.calcCheckCallRaise(hand) + self.calc34BetStreet0(hand) + self.calcSteals(hand) # Additional stats # 3betSB, 3betBB # Squeeze, Ratchet? @@ -273,13 +277,59 @@ class DerivedStats(): for (i, street) in enumerate(hand.actionStreets[1:]): self.hands['street%dRaises' % i] = len(filter( lambda action: action[1] in ('raises','bets'), hand.actions[street])) - def calcCBets(self, hand): - # Continuation Bet chance, action: - # Had the last bet (initiative) on previous street, got called, close street action - # Then no bets before the player with initiatives first action on current street - # ie. if player on street-1 had initiative - # and no donkbets occurred + def calcSteals(self, hand): + """Fills stealAttempt(Chance|ed, fold(Bb|Sb)ToSteal(Chance|) + Steal attemp - open raise on positions 2 1 0 S - i.e. MP3, CO, BU, SB + Fold to steal - folding blind after steal attemp wo any other callers or raisers + """ + steal_attemp = False + steal_positions = ('2', '1', '0', 'S') + if hand.gametype['base'] == 'stud': + steal_positions = ('2', '1', '0') + for action in hand.actions[hand.actionStreets[1]]: + pname, act = action[0], action[1] + #print action[0], hp.position, steal_attemp, act + if self.handsplayers[pname]['position'] == 'B': + #NOTE: Stud games will never hit this section + self.handsplayers[pname]['foldBbToStealChance'] = steal_attemp + self.handsplayers[pname]['foldBbToSteal'] = self.handsplayers[pname]['foldBbToStealChance'] and act == 'folds' + break + elif self.handsplayers[pname]['position'] == 'S': + self.handsplayers[pname]['foldSbToStealChance'] = steal_attemp + self.handsplayers[pname]['foldSbToSteal'] = self.handsplayers[pname]['foldSbToStealChance'] and act == 'folds' + + if steal_attemp and act != 'folds': + break + + if self.handsplayers[pname]['position'] in steal_positions and not steal_attemp: + self.handsplayers[pname]['stealAttemptChance'] = True + if act in ('bets', 'raises'): + self.handsplayers[pname]['stealAttempted'] = True + steal_attemp = True + + def calc34BetStreet0(self, hand): + """Fills street0_(3|4)B(Chance|Done), other(3|4)BStreet0""" + bet_level = 1 # bet_level after 3-bet is equal to 3 + for action in hand.actions[hand.actionStreets[1]]: + # FIXME: fill other(3|4)BStreet0 - i have no idea what does it mean + pname, aggr = action[0], action[1] in ('raises', 'bets') + self.handsplayers[pname]['street0_3BChance'] = bet_level == 2 + self.handsplayers[pname]['street0_4BChance'] = bet_level == 3 + self.handsplayers[pname]['street0_3BDone'] = aggr and (self.handsplayers[pname]['street0_3BChance']) + self.handsplayers[pname]['street0_4BDone'] = aggr and (self.handsplayers[pname]['street0_4BChance']) + if aggr: + bet_level += 1 + + + def calcCBets(self, hand): + """Fill streetXCBChance, streetXCBDone, foldToStreetXCBDone, foldToStreetXCBChance + + Continuation Bet chance, action: + Had the last bet (initiative) on previous street, got called, close street action + Then no bets before the player with initiatives first action on current street + ie. if player on street-1 had initiative and no donkbets occurred + """ # XXX: enumerate(list, start=x) is python 2.6 syntax; 'start' # came there #for i, street in enumerate(hand.actionStreets[2:], start=1): From 776405982b526f36fbd502ec43da5261ed4624aa Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 15 Jan 2010 21:24:37 +0800 Subject: [PATCH 060/251] Quick fix for hud --- pyfpdb/Database.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 63e9a0a5..c7b3e3b8 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1508,7 +1508,7 @@ class Database: line[55] = gid # gametypeId line[56] = pids[p] # playerId line[57] = len(pids) # activeSeats - pos = {-2:'B', -1:'S', 0:'D', 1:'C', 2:'M', 3:'M', 4:'M', 5:'E', 6:'E', 7:'E', 8:'E', 9:'E' } + pos = {'B':'B', 'S':'S', 0:'D', 1:'C', 2:'M', 3:'M', 4:'M', 5:'E', 6:'E', 7:'E', 8:'E', 9:'E' } line[58] = pos[pdata[p]['position']] line[59] = pdata[p]['tourneyTypeId'] line[60] = styleKey # styleKey From 3f0dfd2b2614ca5de2e807f71f2b3eff9703198a Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 16 Jan 2010 13:55:01 +0800 Subject: [PATCH 061/251] Fix enumerate() --- pyfpdb/DerivedStats.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 8b9af93b..88bb6407 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -350,8 +350,9 @@ class DerivedStats(): CG: CheckCall would be a much better name for this. """ - for i, street in enumerate(hand.actionStreets[2:], start=1): - actions = hand.actions[hand.actionStreets[i]] + #for i, street in enumerate(hand.actionStreets[2:], start=1): + for i, street in enumerate(hand.actionStreets[2:]): + actions = hand.actions[hand.actionStreets[i+1]] checkers = set() initial_raiser = None for action in actions: @@ -361,8 +362,8 @@ class DerivedStats(): elif act == 'checks' and initial_raiser is None: checkers.add(pname) elif initial_raiser is not None and pname in checkers: - self.handsplayers[pname]['street%dCheckCallRaiseChance' % i] = True - self.handsplayers[pname]['street%dCheckCallRaiseDone' % i] = act!='folds' + self.handsplayers[pname]['street%dCheckCallRaiseChance' % (i+1)] = True + self.handsplayers[pname]['street%dCheckCallRaiseDone' % (i+1)] = act!='folds' def seen(self, hand, i): pas = set() From cb172e15ae088a531f88d7a1701ae29c33ac2599 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Tue, 19 Jan 2010 19:25:36 +0200 Subject: [PATCH 062/251] Fix name display in HUD popup The names are stored in UTF-8, so simply converting the name from UTF-8 to Configuration.LOCALE_ENCODING before putting the string in tooltip is enough. Neat. --- pyfpdb/Stats.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Stats.py b/pyfpdb/Stats.py index 86caaea5..18913eed 100755 --- a/pyfpdb/Stats.py +++ b/pyfpdb/Stats.py @@ -62,9 +62,13 @@ import Database re_Places = re.compile("_[0-9]$") re_Percent = re.compile("%$") +# String manipulation +import codecs +encoder = codecs.lookup(Configuration.LOCALE_ENCODING) def do_tip(widget, tip): - widget.set_tooltip_text(tip) + (_tip, _len) = encoder.encode(tip) + widget.set_tooltip_text(_tip) def do_stat(stat_dict, player = 24, stat = 'vpip'): match = re_Places.search(stat) From 7ec58ad5c2789c69bcc97d113b7fb51378a0499c Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Tue, 19 Jan 2010 19:25:36 +0200 Subject: [PATCH 063/251] Fix name display in HUD popup The names are stored in UTF-8, so simply converting the name from UTF-8 to Configuration.LOCALE_ENCODING before putting the string in tooltip is enough. Neat. --- pyfpdb/Stats.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Stats.py b/pyfpdb/Stats.py index 86caaea5..18913eed 100755 --- a/pyfpdb/Stats.py +++ b/pyfpdb/Stats.py @@ -62,9 +62,13 @@ import Database re_Places = re.compile("_[0-9]$") re_Percent = re.compile("%$") +# String manipulation +import codecs +encoder = codecs.lookup(Configuration.LOCALE_ENCODING) def do_tip(widget, tip): - widget.set_tooltip_text(tip) + (_tip, _len) = encoder.encode(tip) + widget.set_tooltip_text(_tip) def do_stat(stat_dict, player = 24, stat = 'vpip'): match = re_Places.search(stat) From 41877097c999079b4c58221df13d301cfcee04a5 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 12 Jan 2010 22:10:59 +0000 Subject: [PATCH 064/251] fix twostartcards to handle 22 and unknowns properly --- pyfpdb/Card.py | 35 ++++++++++++++++++++++++----------- pyfpdb/GuiPlayerStats.py | 4 ++-- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/pyfpdb/Card.py b/pyfpdb/Card.py index 8639fd35..22eab979 100755 --- a/pyfpdb/Card.py +++ b/pyfpdb/Card.py @@ -39,23 +39,36 @@ def calcStartCards(hand, player): def twoStartCards(value1, suit1, value2, suit2): """ Function to convert 2 value,suit pairs into a Holdem style starting hand e.g. AQo - Hand is stored as an int 13 * x + y where (x+2) represents rank of 1st card and + Incoming values should be ints 2-14 (2,3,...K,A), suits are 'd'/'h'/'c'/'s' + Hand is stored as an int 13 * x + y + 1 where (x+2) represents rank of 1st card and (y+2) represents rank of second card (2=2 .. 14=Ace) - If x > y then pair is suited, if x < y then unsuited""" - if value1 < 2 or value2 < 2: + If x > y then pair is suited, if x < y then unsuited + Examples: + 0 Unknown / Illegal cards + 1 22 + 2 32o + 3 42o + ... + 14 32s + 15 33 + 16 42o + ... + 170 AA + """ + if value1 is None or value1 < 2 or value1 > 14 or value2 is None or value2 < 2 or value2 > 14: ret = 0 - if value1 == value2: # pairs - ret = (13 * (value2-2) + (value2-2) ) + elif value1 == value2: # pairs + ret = (13 * (value2-2) + (value2-2) ) + 1 elif suit1 == suit2: if value1 > value2: - ret = 13 * (value1-2) + (value2-2) + ret = 13 * (value1-2) + (value2-2) + 1 else: - ret = 13 * (value2-2) + (value1-2) + ret = 13 * (value2-2) + (value1-2) + 1 else: if value1 > value2: - ret = 13 * (value2-2) + (value1-2) + ret = 13 * (value2-2) + (value1-2) + 1 else: - ret = 13 * (value1-2) + (value2-2) + ret = 13 * (value1-2) + (value2-2) + 1 # print "twoStartCards(", value1, suit1, value2, suit2, ")=", ret return ret @@ -66,8 +79,8 @@ def twoStartCardString(card): ret = 'xx' if card > 0: s = ('2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A') - x = card / 13 - y = card - 13 * x + x = (card-1) / 13 + y = (card-1) - 13 * x if x == y: ret = s[x] + s[y] elif x > y: ret = s[x] + s[y] + 's' else: ret = s[y] + s[x] + 'o' diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index d65b9ab6..889988c5 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -516,8 +516,8 @@ class GuiPlayerStats (threading.Thread): if holecards: # re-use level variables for hole card query query = query.replace("", "hp.startcards") query = query.replace("" - , ",case when floor(hp.startcards/13) >= mod(hp.startcards,13) then hp.startcards + 0.1 " - + " else 13*mod(hp.startcards,13) + floor(hp.startcards/13) " + , ",case when floor((hp.startcards-1)/13) >= mod((hp.startcards-1),13) then hp.startcards + 0.1 " + + " else 13*mod((hp.startcards-1),13) + floor((hp.startcards-1)/13) + 1 " + " end desc ") else: query = query.replace("", "") From cd7177897562379fe799ac7238fb0e690bf4ccc4 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Tue, 19 Jan 2010 19:25:36 +0200 Subject: [PATCH 065/251] Fix name display in HUD popup The names are stored in UTF-8, so simply converting the name from UTF-8 to Configuration.LOCALE_ENCODING before putting the string in tooltip is enough. Neat. --- pyfpdb/Stats.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Stats.py b/pyfpdb/Stats.py index 86caaea5..18913eed 100755 --- a/pyfpdb/Stats.py +++ b/pyfpdb/Stats.py @@ -62,9 +62,13 @@ import Database re_Places = re.compile("_[0-9]$") re_Percent = re.compile("%$") +# String manipulation +import codecs +encoder = codecs.lookup(Configuration.LOCALE_ENCODING) def do_tip(widget, tip): - widget.set_tooltip_text(tip) + (_tip, _len) = encoder.encode(tip) + widget.set_tooltip_text(_tip) def do_stat(stat_dict, player = 24, stat = 'vpip'): match = re_Places.search(stat) From ef4f5289bb8ea8b8ce7fa301d2146d091b31b7e7 Mon Sep 17 00:00:00 2001 From: Gerko de Roo Date: Sun, 17 Jan 2010 19:54:40 +0100 Subject: [PATCH 066/251] Solved some merge issues --> Cards.py Issues Pokerstars when playing heads-up on ring games, being both on button and small blind now supported !!if not solved the winnings of the (button, small blind) is stored as rake!! Post both small and big blind when re-entering ring games solved --- pyfpdb/Card.py | 2 +- pyfpdb/PokerStarsToFpdb.py | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/pyfpdb/Card.py b/pyfpdb/Card.py index 22eab979..f33f08ed 100755 --- a/pyfpdb/Card.py +++ b/pyfpdb/Card.py @@ -61,7 +61,7 @@ def twoStartCards(value1, suit1, value2, suit2): ret = (13 * (value2-2) + (value2-2) ) + 1 elif suit1 == suit2: if value1 > value2: - ret = 13 * (value1-2) + (value2-2) + 1 + ret = 13 * (value1-2) + (value2-2) + 1 else: ret = 13 * (value2-2) + (value1-2) + 1 else: diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 5e2f9c21..09bd0390 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -81,6 +81,7 @@ class PokerStars(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
\d+)\)?\s+ - (?:[^ ]+\s+\#(?P\d+).+)? # table number for mtt + (?:[a-zA-Z0-9 ]+\s+\#(?P\d+).+)? (\(No\sDP\)\s)? \((?PReal|Play)\s+Money\)\s+ # FIXME: check if play money is correct Seat\s+(?P
\d+)\)?\s+ - (?:[^ ]+\s+\#(?P\d+).+)? # table number for mtt + (?:[a-zA-Z0-9 ]+\s+\#(?P\d+).+)? (\(No\sDP\)\s)? \((?PReal|Play)\s+Money\)\s+ # FIXME: check if play money is correct Seat\s+(?P
\d+)\)?\s+ - (?:[^ ]+\s+\#(?P\d+).+)? # table number for mtt + (?:[a-zA-Z0-9 ]+\s+\#(?P\d+).+)? (\(No\sDP\)\s)? \((?PReal|Play)\s+Money\)\s+ # FIXME: check if play money is correct Seat\s+(?P
.+$)", re.MULTILINE) re_Button = re.compile(ur"^Seat (?P
[0-9]+)\.txt") def compilePlayerRegexs(self, hand): @@ -55,18 +56,25 @@ class Everleaf(HandHistoryConverter): self.re_Antes = re.compile(ur"^%s: posts ante \[(?:\$| €|) (?P[.0-9]+)" % player_re, re.MULTILINE) self.re_BringIn = re.compile(ur"^%s posts bring-in (?:\$| €|)(?P[.0-9]+)\." % player_re, re.MULTILINE) self.re_HeroCards = re.compile(ur"^Dealt to %s \[ (?P.*) \]" % player_re, re.MULTILINE) - self.re_Action = re.compile(ur"^%s(?P: bets| checks| raises| calls| folds)(\s\[(?:\$| €|) (?P[.\d]+) (USD|EUR|)\])?" % player_re, re.MULTILINE) + self.re_Action = re.compile(ur"^%s(?P: bets| checks| raises| calls| folds)(\s\[(?:\$| €|) (?P[.,\d]+) (USD|EUR|Chips)\])?" % player_re, re.MULTILINE) #self.re_Action = re.compile(ur"^%s(?P: bets| checks| raises| calls| folds| complete to)(\s\[?(?:\$| €|) ?(?P\d+\.?\d*)\.?\s?(USD|EUR|)\]?)?" % player_re, re.MULTILINE) self.re_ShowdownAction = re.compile(ur"^%s shows \[ (?P.*) \]" % player_re, re.MULTILINE) self.re_CollectPot = re.compile(ur"^%s wins (?:\$| €|) (?P[.\d]+) (USD|EUR|chips)(.*?\[ (?P.*?) \])?" % player_re, re.MULTILINE) self.re_SitsOut = re.compile(ur"^%s sits out" % player_re, re.MULTILINE) + else: + print "*** EverleafToFpdb: compilePlayerRegexs failed" + print players + print self.compiledPlayers + def readSupportedGames(self): return [["ring", "hold", "nl"], ["ring", "hold", "pl"], ["ring", "hold", "fl"], ["ring", "studhi", "fl"], - ["ring", "omahahi", "pl"] + ["ring", "omahahi", "pl"], + ["ring", "omahahilo", "pl"], + ["tour", "hold", "nl"] ] def determineGameType(self, handText): @@ -138,6 +146,13 @@ or None if we fail to get the info """ hand.tablename = m.group('TABLE') hand.maxseats = 6 # assume 6-max unless we have proof it's a larger/smaller game, since everleaf doesn't give seat max info + t = self.re_TourneyInfoFromFilename.search(self.in_path) + if t: + tourno = t.group('TOURNO') + if tourno: # we're a tourney, yay + hand.tourNo = tourno + hand.tablename = t.group('TABLE') + # Believe Everleaf time is GMT/UTC, no transation necessary # Stars format (Nov 10 2008): 2008/11/07 12:38:49 CET [2008/11/07 7:38:49 ET] # or : 2008/11/07 12:38:49 ET @@ -287,7 +302,9 @@ or None if we fail to get the info """ @staticmethod def getTableTitleRe(type, table_name=None, tournament = None, table_number=None): - return "^%s -" % (table_name) + if tournament: + return "%s - Tournament ID: %s -" % (table_number, tournament) + return "%s -" % (table_name) From e3be7db2a0631d875188b6ee22855535b8694f18 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Mon, 1 Feb 2010 09:17:42 -0500 Subject: [PATCH 183/251] fix bug i introduced that caused everleaf cash hands to fail --- pyfpdb/EverleafToFpdb.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index c9206ea5..fe17f158 100755 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -149,7 +149,6 @@ or None if we fail to get the info """ t = self.re_TourneyInfoFromFilename.search(self.in_path) if t: tourno = t.group('TOURNO') - if tourno: # we're a tourney, yay hand.tourNo = tourno hand.tablename = t.group('TABLE') From 81ff8e632cc483b0cc53678dd0c818734c8d7e7e Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Mon, 1 Feb 2010 09:41:33 -0500 Subject: [PATCH 184/251] remove my misunderstanding of how compileplayerregexs worked --- pyfpdb/EverleafToFpdb.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index fe17f158..fdc35bf6 100755 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -62,11 +62,6 @@ class Everleaf(HandHistoryConverter): self.re_CollectPot = re.compile(ur"^%s wins (?:\$| €|) (?P[.\d]+) (USD|EUR|chips)(.*?\[ (?P.*?) \])?" % player_re, re.MULTILINE) self.re_SitsOut = re.compile(ur"^%s sits out" % player_re, re.MULTILINE) - else: - print "*** EverleafToFpdb: compilePlayerRegexs failed" - print players - print self.compiledPlayers - def readSupportedGames(self): return [["ring", "hold", "nl"], ["ring", "hold", "pl"], From eff216919dd7ad03bdfe9a7500438c1c46ac6a80 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Mon, 1 Feb 2010 09:57:28 -0500 Subject: [PATCH 185/251] Everleaf: Change "EUR"(old) to "EURO"(new), still doesn't seem to allow eur import (is that because my site config is set for usd ?) --- pyfpdb/EverleafToFpdb.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index fdc35bf6..5dd8d041 100755 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -38,7 +38,7 @@ class Everleaf(HandHistoryConverter): #re.compile(ur"^(Blinds )?(?P\$| €|)(?P[.0-9]+)/(?:\$| €)?(?P[.0-9]+) (?PNL|PL|) (?P(Hold\'em|Omaha|7 Card Stud))", re.MULTILINE) re_HandInfo = re.compile(ur".*#(?P[0-9]+)\n.*\n(Blinds )?(?:\$| €|)(?P[.0-9]+)/(?:\$| €|)(?P[.0-9]+) (?P.*) - (?P\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P
.+$)", re.MULTILINE) re_Button = re.compile(ur"^Seat (?P
[0-9]+)\.txt") @@ -56,10 +56,10 @@ class Everleaf(HandHistoryConverter): self.re_Antes = re.compile(ur"^%s: posts ante \[(?:\$| €|) (?P[.0-9]+)" % player_re, re.MULTILINE) self.re_BringIn = re.compile(ur"^%s posts bring-in (?:\$| €|)(?P[.0-9]+)\." % player_re, re.MULTILINE) self.re_HeroCards = re.compile(ur"^Dealt to %s \[ (?P.*) \]" % player_re, re.MULTILINE) - self.re_Action = re.compile(ur"^%s(?P: bets| checks| raises| calls| folds)(\s\[(?:\$| €|) (?P[.,\d]+) (USD|EUR|Chips)\])?" % player_re, re.MULTILINE) + self.re_Action = re.compile(ur"^%s(?P: bets| checks| raises| calls| folds)(\s\[(?:\$| €|) (?P[.,\d]+) (USD|EURO|Chips)\])?" % player_re, re.MULTILINE) #self.re_Action = re.compile(ur"^%s(?P: bets| checks| raises| calls| folds| complete to)(\s\[?(?:\$| €|) ?(?P\d+\.?\d*)\.?\s?(USD|EUR|)\]?)?" % player_re, re.MULTILINE) self.re_ShowdownAction = re.compile(ur"^%s shows \[ (?P.*) \]" % player_re, re.MULTILINE) - self.re_CollectPot = re.compile(ur"^%s wins (?:\$| €|) (?P[.\d]+) (USD|EUR|chips)(.*?\[ (?P.*?) \])?" % player_re, re.MULTILINE) + self.re_CollectPot = re.compile(ur"^%s wins (?:\$| €|) (?P[.\d]+) (USD|EURO|chips)(.*?\[ (?P.*?) \])?" % player_re, re.MULTILINE) self.re_SitsOut = re.compile(ur"^%s sits out" % player_re, re.MULTILINE) def readSupportedGames(self): From 86330e536ae5c27e193de2fff66ede4502558db2 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 1 Feb 2010 21:03:51 +0000 Subject: [PATCH 186/251] tidy up logging so that log isn't created in /fpdb/log/ unless it is being used --- pyfpdb/Configuration.py | 7 +++++-- pyfpdb/Database.py | 7 +++++-- pyfpdb/GuiLogView.py | 15 ++++++++------- pyfpdb/fpdb.py | 2 +- pyfpdb/fpdb_import.py | 5 ++++- 5 files changed, 23 insertions(+), 13 deletions(-) mode change 100644 => 100755 pyfpdb/Configuration.py mode change 100644 => 100755 pyfpdb/fpdb_import.py diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py old mode 100644 new mode 100755 index 9c7e44b6..ec4c621e --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -38,6 +38,10 @@ from xml.dom.minidom import Node import logging, logging.config import ConfigParser +# logging has been set up in fpdb.py or HUD_main.py, use their settings: +log = logging.getLogger("config") + + ############################################################################## # Functions for finding config files and setting up logging # Also used in other modules that use logging. @@ -138,8 +142,6 @@ def check_dir(path, create = True): else: return False -# find a logging.conf file and set up logging -log = get_logger("logging.conf", "config") ######################################################################## # application wide consts @@ -458,6 +460,7 @@ class Config: self.dir_config = os.path.dirname(self.file) self.dir_log = os.path.join(self.dir_config, 'log') self.dir_database = os.path.join(self.dir_config, 'database') + self.log_file = os.path.join(self.dir_log, 'logging.out') log = get_logger("logging.conf", "config", log_dir=self.dir_log) # Parse even if there was no real config file found and we are using the example diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index a987b389..e7c01231 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -41,6 +41,10 @@ import Queue import codecs import math +import logging +# logging has been set up in fpdb.py or HUD_main.py, use their settings: +log = logging.getLogger("db") + # pyGTK modules @@ -52,7 +56,6 @@ import Tourney import Charset from Exceptions import * import Configuration -log = Configuration.get_logger("logging.conf","db") # Other library modules @@ -225,7 +228,7 @@ class Database: def __init__(self, c, sql = None): log = Configuration.get_logger("logging.conf", "db", log_dir=c.dir_log) - log.info("Creating Database instance, sql = %s" % sql) + log.debug("Creating Database instance, sql = %s" % sql) self.config = c self.__connected = False self.settings = {} diff --git a/pyfpdb/GuiLogView.py b/pyfpdb/GuiLogView.py index 29385fa0..9dcb9588 100755 --- a/pyfpdb/GuiLogView.py +++ b/pyfpdb/GuiLogView.py @@ -26,13 +26,13 @@ import gtk import gobject import pango -import Configuration +import logging +# logging has been set up in fpdb.py or HUD_main.py, use their settings: +log = logging.getLogger("logview") -log = Configuration.get_logger("logging.conf", "logview") MAX_LINES = 100000 # max lines to display in window EST_CHARS_PER_LINE = 150 # used to guesstimate number of lines in log file -logfile = 'logging.out' # name of logfile class GuiLogView: @@ -41,6 +41,7 @@ class GuiLogView: self.main_window = mainwin self.closeq = closeq + self.logfile = self.config.log_file # name of logfile self.dia = gtk.Dialog(title="Log Messages" ,parent=None ,flags=gtk.DIALOG_DESTROY_WITH_PARENT @@ -117,10 +118,10 @@ class GuiLogView: self.listcols = [] # guesstimate number of lines in file - if os.path.exists(logfile): - stat_info = os.stat(logfile) + if os.path.exists(self.logfile): + stat_info = os.stat(self.logfile) lines = stat_info.st_size / EST_CHARS_PER_LINE - print "logview: size =", stat_info.st_size, "lines =", lines + #print "logview: size =", stat_info.st_size, "lines =", lines # set startline to line number to start display from startline = 0 @@ -129,7 +130,7 @@ class GuiLogView: startline = lines - MAX_LINES l = 0 - for line in open(logfile): + for line in open(self.logfile): # eg line: # 2009-12-02 15:23:21,716 - config DEBUG config logger initialised l = l + 1 diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 58e0128d..c11301a9 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -117,7 +117,6 @@ import Exceptions VERSION = "0.12" -log = Configuration.get_logger("logging.conf", "fpdb") class fpdb: def tab_clicked(self, widget, tab_name): @@ -696,6 +695,7 @@ class fpdb: """Loads profile from the provided path name.""" self.config = Configuration.Config(file=options.config, dbname=options.dbname) log = Configuration.get_logger("logging.conf", "fpdb", log_dir=self.config.dir_log) + print "Logfile is " + os.path.join(self.config.dir_log, 'logging.out') + "\n" if self.config.example_copy: self.info_box( "Config file" , "has been created at:\n%s.\n" % self.config.file diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py old mode 100644 new mode 100755 index a02d3d99..8ba0da34 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -30,6 +30,10 @@ import Queue from collections import deque # using Queue for now import threading +import logging +# logging has been set up in fpdb.py or HUD_main.py, use their settings: +log = logging.getLogger("importer") + import pygtk import gtk @@ -39,7 +43,6 @@ import Database import Configuration import Exceptions -log = Configuration.get_logger("logging.conf", "importer") # database interface modules try: From d4248706e46ba65d5b2a05e2ac1a16421bfd1e32 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 1 Feb 2010 22:31:00 +0000 Subject: [PATCH 187/251] remove surplus get_logger calls, tidy up log messages some more --- pyfpdb/Database.py | 12 ++++++------ pyfpdb/HUD_main.py | 15 +++++++-------- pyfpdb/Hand.py | 9 ++++++--- pyfpdb/HandHistoryConverter.py | 8 ++++++-- pyfpdb/fpdb.py | 3 +++ pyfpdb/fpdb_import.py | 2 +- 6 files changed, 29 insertions(+), 20 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index e7c01231..77ae30f6 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -227,7 +227,7 @@ class Database: def __init__(self, c, sql = None): - log = Configuration.get_logger("logging.conf", "db", log_dir=c.dir_log) + #log = Configuration.get_logger("logging.conf", "db", log_dir=c.dir_log) log.debug("Creating Database instance, sql = %s" % sql) self.config = c self.__connected = False @@ -239,6 +239,7 @@ class Database: self.db_server = db_params['db-server'] self.database = db_params['db-databaseName'] self.host = db_params['db-host'] + self.db_path = '' # where possible avoid creating new SQL instance by using the global one passed in if sql is None: @@ -388,9 +389,9 @@ class Database: log.info("Creating directory: '%s'" % (self.config.dir_database)) os.mkdir(self.config.dir_database) database = os.path.join(self.config.dir_database, database) - log.info("Connecting to SQLite: %(database)s" % {'database':database}) - print "Connecting to SQLite: %(database)s" % {'database':database} - self.connection = sqlite3.connect(database, detect_types=sqlite3.PARSE_DECLTYPES ) + self.db_path = database + log.info("Connecting to SQLite: %(database)s" % {'database':self.db_path}) + self.connection = sqlite3.connect(self.db_path, detect_types=sqlite3.PARSE_DECLTYPES ) sqlite3.register_converter("bool", lambda x: bool(int(x))) sqlite3.register_adapter(bool, lambda x: "1" if x else "0") self.connection.create_function("floor", 1, math.floor) @@ -791,11 +792,10 @@ class Database: def get_player_id(self, config, site, player_name): c = self.connection.cursor() - print "get_player_id: player_name =", player_name, type(player_name) + #print "get_player_id: player_name =", player_name, type(player_name) p_name = Charset.to_utf8(player_name) c.execute(self.sql.query['get_player_id'], (p_name, site)) row = c.fetchone() - print "player id =", row if row: return row[0] else: diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index c792d802..f7979552 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -51,9 +51,6 @@ import gobject # FreePokerTools modules import Configuration -log = Configuration.get_logger("logging.conf", config = 'hud') -log.debug("%s logger initialized." % "hud") - import Database from HandHistoryConverter import getTableTitleRe @@ -66,6 +63,10 @@ elif os.name == 'nt': import Hud +# logger is set up in __init__, create temp logger here +log = Configuration.get_logger("logging.conf", config = 'hud') + + class HUD_main(object): """A main() object to own both the read_stdin thread and the gui.""" # This class mainly provides state for controlling the multiple HUDs. @@ -74,9 +75,10 @@ class HUD_main(object): try: print "HUD_main: starting ..." self.db_name = db_name - self.config = Configuration.Config(file=options.config, dbname=options.dbname) + self.config = Configuration.Config(file=options.config, dbname=db_name) log = Configuration.get_logger("logging.conf", "hud", log_dir=self.config.dir_log) - log.debug("starting ...") + log.info("HUD_main starting") + log.info("Using db name = %s" % (db_name)) self.hud_dict = {} self.hud_params = self.config.get_hud_ui_parameters() @@ -295,9 +297,6 @@ class HUD_main(object): if __name__== "__main__": - log.info("HUD_main starting") - log.info("Using db name = %s" % (options.dbname)) - # start the HUD_main object hm = HUD_main(db_name = options.dbname) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 0f69121a..9bec209b 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -21,7 +21,6 @@ import re import sys import traceback -import logging import os import os.path from decimal import Decimal @@ -30,12 +29,16 @@ import time,datetime from copy import deepcopy import pprint +import logging +# logging has been set up in fpdb.py or HUD_main.py, use their settings: +log = logging.getLogger("parser") + + import Configuration from Exceptions import * import DerivedStats import Card -log = Configuration.get_logger("logging.conf", "parser") class Hand(object): @@ -50,7 +53,7 @@ class Hand(object): def __init__(self, config, sitename, gametype, handText, builtFrom = "HHC"): self.config = config - log = Configuration.get_logger("logging.conf", "db", log_dir=self.config.dir_log) + #log = Configuration.get_logger("logging.conf", "db", log_dir=self.config.dir_log) self.sitename = sitename self.siteId = self.SITEIDS[sitename] self.stats = DerivedStats.DerivedStats(self) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 45760ee6..fa1805e0 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -30,6 +30,11 @@ from xml.dom.minidom import Node import time import datetime +import logging +# logging has been set up in fpdb.py or HUD_main.py, use their settings: +log = logging.getLogger("parser") + + import Hand import Tourney from Exceptions import FpdbParseError @@ -38,7 +43,6 @@ import Configuration import gettext gettext.install('fpdb') -log = Configuration.get_logger("logging.conf", "parser") import pygtk import gtk @@ -65,7 +69,7 @@ out_path (default '-' = sys.stdout) follow : whether to tail -f the input""" self.config = config - log = Configuration.get_logger("logging.conf", "parser", log_dir=self.config.dir_log) + #log = Configuration.get_logger("logging.conf", "parser", log_dir=self.config.dir_log) log.info("HandHistory init - %s subclass, in_path '%s'; out_path '%s'" % (self.sitename, in_path, out_path) ) self.index = index diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index c11301a9..5bef3503 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -721,6 +721,9 @@ class fpdb: err_msg = None try: self.db = Database.Database(self.config, sql = self.sql) + if self.db.get_backend_name() == 'SQLite': + # tell sqlite users where the db file is + print "Connected to SQLite: %(database)s" % {'database':self.db.db_path} except Exceptions.FpdbMySQLAccessDenied: err_msg = "MySQL Server reports: Access denied. Are your permissions set correctly?" except Exceptions.FpdbMySQLNoDatabase: diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 8ba0da34..8b3f71cd 100755 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -68,7 +68,7 @@ class Importer: self.config = config self.sql = sql - log = Configuration.get_logger("logging.conf", "importer", log_dir=self.config.dir_log) + #log = Configuration.get_logger("logging.conf", "importer", log_dir=self.config.dir_log) self.filelist = {} self.dirlist = {} self.siteIds = {} From 96d0e0f1818992359344bf0c55bba22d4c500c49 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 1 Feb 2010 22:56:40 +0000 Subject: [PATCH 188/251] fix key error and add filter to logging.conf --- pyfpdb/Filters.py | 43 +++++++++++++++++++++++++++---------------- pyfpdb/logging.conf | 8 +++++++- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index 96245898..27e5a49d 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -26,16 +26,21 @@ from time import * import gobject #import pokereval +import logging +# logging has been set up in fpdb.py or HUD_main.py, use their settings: +log = logging.getLogger("filter") + + import Configuration import Database import SQL import Charset + class Filters(threading.Thread): def __init__(self, db, config, qdict, display = {}, debug=True): # config and qdict are now redundant self.debug = debug - #print "start of GraphViewer constructor" self.db = db self.cursor = db.cursor self.sql = db.sql @@ -268,10 +273,10 @@ class Filters(threading.Thread): self.callback['button2'] = callback def cardCallback(self, widget, data=None): - print "DEBUG: %s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()]) + log.debug( "%s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()]) ) def createPlayerLine(self, hbox, site, player): - print 'DEBUG :: add:"%s"' % player + log.debug('add:"%s"' % player) label = gtk.Label(site +" id:") hbox.pack_start(label, False, False, 3) @@ -300,14 +305,14 @@ class Filters(threading.Thread): # get_text() returns a str but we want internal variables to be unicode: _guiname = unicode(_name) self.heroes[site] = _guiname -# print "DEBUG: setting heroes[%s]: %s"%(site, self.heroes[site]) +# log.debug("setting heroes[%s]: %s"%(site, self.heroes[site])) def __set_num_hands(self, w, val): try: self.numHands = int(w.get_text()) except: self.numHands = 0 -# print "DEBUG: setting numHands:", self.numHands +# log.debug("setting numHands:", self.numHands) def createSiteLine(self, hbox, site): cb = gtk.CheckButton(site) @@ -332,17 +337,17 @@ class Filters(threading.Thread): def __set_site_select(self, w, site): #print w.get_active() self.sites[site] = w.get_active() - print "self.sites[%s] set to %s" %(site, self.sites[site]) + log.debug("self.sites[%s] set to %s" %(site, self.sites[site])) def __set_game_select(self, w, game): #print w.get_active() self.games[game] = w.get_active() - print "self.games[%s] set to %s" %(game, self.games[game]) + log.debug("self.games[%s] set to %s" %(game, self.games[game])) def __set_limit_select(self, w, limit): #print w.get_active() self.limits[limit] = w.get_active() - print "self.limit[%s] set to %s" %(limit, self.limits[limit]) + log.debug("self.limit[%s] set to %s" %(limit, self.limits[limit])) if limit.isdigit() or (len(limit) > 2 and (limit[-2:] == 'nl' or limit[-2:] == 'fl' or limit[-2:] == 'pl')): if self.limits[limit]: if self.cbNoLimits is not None: @@ -428,9 +433,11 @@ class Filters(threading.Thread): if self.limits[limit]: if not found[self.type]: if self.type == 'ring': - self.rb['tour'].set_active(True) + if 'tour' in self.rb: + self.rb['tour'].set_active(True) elif self.type == 'tour': - self.rb['ring'].set_active(True) + if 'ring' in self.rb: + self.rb['ring'].set_active(True) elif limit == "pl": if not self.limits[limit]: # only toggle all nl limits off if they are all currently on @@ -452,11 +459,13 @@ class Filters(threading.Thread): if self.limits[limit]: if not found[self.type]: if self.type == 'ring': - self.rb['tour'].set_active(True) + if 'tour' in self.rb: + self.rb['tour'].set_active(True) elif self.type == 'tour': - self.rb['ring'].set_active(True) + if 'ring' in self.rb: + self.rb['ring'].set_active(True) elif limit == "ring": - print "set", limit, "to", self.limits[limit] + log.debug("set", limit, "to", self.limits[limit]) if self.limits[limit]: self.type = "ring" for cb in self.cbLimits.values(): @@ -464,7 +473,7 @@ class Filters(threading.Thread): if self.types[cb.get_children()[0].get_text()] == 'tour': cb.set_active(False) elif limit == "tour": - print "set", limit, "to", self.limits[limit] + log.debug( "set", limit, "to", self.limits[limit] ) if self.limits[limit]: self.type = "tour" for cb in self.cbLimits.values(): @@ -475,12 +484,12 @@ class Filters(threading.Thread): def __set_seat_select(self, w, seat): #print "__set_seat_select: seat =", seat, "active =", w.get_active() self.seats[seat] = w.get_active() - print "self.seats[%s] set to %s" %(seat, self.seats[seat]) + log.debug( "self.seats[%s] set to %s" %(seat, self.seats[seat]) ) def __set_group_select(self, w, group): #print "__set_seat_select: seat =", seat, "active =", w.get_active() self.groups[group] = w.get_active() - print "self.groups[%s] set to %s" %(group, self.groups[group]) + log.debug( "self.groups[%s] set to %s" %(group, self.groups[group]) ) def fillPlayerFrame(self, vbox, display): top_hbox = gtk.HBox(False, 0) @@ -579,6 +588,7 @@ class Filters(threading.Thread): self.createGameLine(hbox, line[0]) else: print "INFO: No games returned from database" + log.info("No games returned from database") def fillLimitsFrame(self, vbox, display): top_hbox = gtk.HBox(False, 0) @@ -660,6 +670,7 @@ class Filters(threading.Thread): dest = vbox2 # for ring/tour buttons else: print "INFO: No games returned from database" + log.info("No games returned from database") if "Type" in display and display["Type"] == True and found['ring'] and found['tour']: rb1 = gtk.RadioButton(None, self.filterText['ring']) diff --git a/pyfpdb/logging.conf b/pyfpdb/logging.conf index a7c0323f..ecd74fcc 100644 --- a/pyfpdb/logging.conf +++ b/pyfpdb/logging.conf @@ -1,5 +1,5 @@ [loggers] -keys=root,fpdb,logview,parser,importer,config,db,hud +keys=root,fpdb,logview,parser,importer,config,db,hud,filter [handlers] keys=consoleHandler,rotatingFileHandler @@ -53,6 +53,12 @@ handlers=consoleHandler,rotatingFileHandler qualname=hud propagate=0 +[logger_filter] +level=INFO +handlers=consoleHandler,rotatingFileHandler +qualname=filter +propagate=0 + [handler_consoleHandler] class=StreamHandler level=ERROR From aea7db22e367bee92eda58ebc72e2ef3808333d0 Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Mon, 1 Feb 2010 18:37:36 -0500 Subject: [PATCH 189/251] Options for logging level and version. Not connected yet. --- pyfpdb/Options.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Options.py b/pyfpdb/Options.py index ab226124..6570dbe4 100644 --- a/pyfpdb/Options.py +++ b/pyfpdb/Options.py @@ -15,9 +15,9 @@ #In the "official" distribution you can find the license in #agpl-3.0.txt in the docs folder of the package. -import os import sys from optparse import OptionParser +# http://docs.python.org/library/optparse.html def fpdb_options(): @@ -41,6 +41,14 @@ def fpdb_options(): parser.add_option("-k", "--konverter", dest="hhc", default="PokerStarsToFpdb", help="Module name for Hand History Converter") + parser.add_option("-l", "--logging", + dest = "log_level", + choices = ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL', 'EMPTY'), + help = "Error logging level. (DEBUG, INFO, WARNING, ERROR, CRITICAL, EMPTY)", + default = 'EMPTY') + parser.add_option("-v", "--version", action = "store_true", + help = "Print version information and exit.") + (options, argv) = parser.parse_args() return (options, argv) From 76f9517655da8881aaabef57996f80254d1a60c2 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Tue, 2 Feb 2010 14:54:27 -0500 Subject: [PATCH 190/251] WinTables will no longer accept trying to attach to "FPDBHUD" titled windows --- pyfpdb/WinTables.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyfpdb/WinTables.py b/pyfpdb/WinTables.py index f834eac9..5bca9e41 100644 --- a/pyfpdb/WinTables.py +++ b/pyfpdb/WinTables.py @@ -50,10 +50,12 @@ class Table(Table_Window): titles = {} win32gui.EnumWindows(win_enum_handler, titles) for hwnd in titles: + # print "searching ", search_string, " in ", titles[hwnd] if re.search(search_string, titles[hwnd]): if 'History for table:' in titles[hwnd]: continue # Everleaf Network HH viewer window if 'HUD:' in titles[hwnd]: continue # FPDB HUD window if 'Chat:' in titles[hwnd]: continue # Some sites (FTP? PS? Others?) have seperable or seperately constructed chat windows + if 'FPDBHUD' in titles[hwnd]: continue # can't attach to ourselves! self.window = hwnd break From fece7c914713c43c0a6c73c8dedd1381b4aa9d0f Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 2 Feb 2010 21:53:03 +0000 Subject: [PATCH 191/251] move fpdb-error-log and HUD-error to APPDATA, renamed as fpdb-errors.txt and HUD-errors.txt to be consistent --- pyfpdb/HUD_main.py | 11 ++++++++--- pyfpdb/fpdb.py | 15 ++++++++------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index f7979552..bae58825 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -35,9 +35,6 @@ import traceback (options, argv) = Options.fpdb_options() -if not options.errorsToConsole: - print "Note: error output is being logged. Any major error will be reported there _only_." - import thread import time import string @@ -79,6 +76,14 @@ class HUD_main(object): log = Configuration.get_logger("logging.conf", "hud", log_dir=self.config.dir_log) log.info("HUD_main starting") log.info("Using db name = %s" % (db_name)) + + if not options.errorsToConsole: + fileName = os.path.join(self.config.dir_log, 'HUD-errors.txt') + print "Note: error output is being diverted to\n"+fileName \ + + "\nAny major error will be reported there _only_.\n" + errorFile = open(fileName, 'w', 0) + sys.stderr = errorFile + self.hud_dict = {} self.hud_params = self.config.get_hud_ui_parameters() diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 5bef3503..d5e0350d 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -53,7 +53,7 @@ if os.name == 'nt': raw_input("Press ENTER to continue.") exit() -print "Python " + sys.version[0:3] + '...\n' +print "Python " + sys.version[0:3] + '...' import traceback import threading @@ -62,12 +62,6 @@ import string cl_options = string.join(sys.argv[1:]) (options, argv) = Options.fpdb_options() -if not options.errorsToConsole: - print "Note: error output is being diverted to fpdb-error-log.txt and HUD-error.txt. Any major error will be reported there _only_." - errorFile = open('fpdb-error-log.txt', 'w', 0) - sys.stderr = errorFile - -#import logging import logging, logging.config try: @@ -910,6 +904,13 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") self.window.show() self.load_profile() + if not options.errorsToConsole: + fileName = os.path.join(self.config.dir_log, 'fpdb-errors.txt') + print "\nNote: error output is being diverted to fpdb-errors.txt and HUD-errors.txt in\n" \ + + self.config.dir_log + "Any major error will be reported there _only_.\n" + errorFile = open(fileName, 'w', 0) + sys.stderr = errorFile + self.statusIcon = gtk.StatusIcon() if os.path.exists(os.path.join(sys.path[0], '../gfx/fpdb-cards.png')): self.statusIcon.set_from_file(os.path.join(sys.path[0], '../gfx/fpdb-cards.png')) From e3679a99fb0f7221798c3415aa98f0f819f8d6ac Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 3 Feb 2010 00:48:45 +0000 Subject: [PATCH 192/251] fix steal calcs --- pyfpdb/DerivedStats.py | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 88bb6407..23f1f99c 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -56,7 +56,6 @@ class DerivedStats(): self.handsplayers[player[1]]['stealAttemptChance'] = False self.handsplayers[player[1]]['stealAttempted'] = False self.handsplayers[player[1]]['foldBbToStealChance'] = False - self.handsplayers[player[1]]['foldBbToStealChance'] = False self.handsplayers[player[1]]['foldSbToStealChance'] = False self.handsplayers[player[1]]['foldedSbToSteal'] = False self.handsplayers[player[1]]['foldedBbToSteal'] = False @@ -281,33 +280,37 @@ class DerivedStats(): def calcSteals(self, hand): """Fills stealAttempt(Chance|ed, fold(Bb|Sb)ToSteal(Chance|) - Steal attemp - open raise on positions 2 1 0 S - i.e. MP3, CO, BU, SB + Steal attempt - open raise on positions 1 0 S - i.e. MP3, CO, BU, SB Fold to steal - folding blind after steal attemp wo any other callers or raisers """ - steal_attemp = False - steal_positions = ('2', '1', '0', 'S') + steal_attempt = False + steal_positions = (1, 0, 'S') if hand.gametype['base'] == 'stud': - steal_positions = ('2', '1', '0') + steal_positions = (2, 1, 0) for action in hand.actions[hand.actionStreets[1]]: pname, act = action[0], action[1] - #print action[0], hp.position, steal_attemp, act - if self.handsplayers[pname]['position'] == 'B': + posn = self.handsplayers[pname]['position'] + #print "\naction:", action[0], posn, type(posn), steal_attempt, act + if posn == 'B': #NOTE: Stud games will never hit this section - self.handsplayers[pname]['foldBbToStealChance'] = steal_attemp - self.handsplayers[pname]['foldBbToSteal'] = self.handsplayers[pname]['foldBbToStealChance'] and act == 'folds' + self.handsplayers[pname]['foldBbToStealChance'] = steal_attempt + self.handsplayers[pname]['foldedBbToSteal'] = steal_attempt and act == 'folds' break - elif self.handsplayers[pname]['position'] == 'S': - self.handsplayers[pname]['foldSbToStealChance'] = steal_attemp - self.handsplayers[pname]['foldSbToSteal'] = self.handsplayers[pname]['foldSbToStealChance'] and act == 'folds' + elif posn == 'S': + self.handsplayers[pname]['foldSbToStealChance'] = steal_attempt + self.handsplayers[pname]['foldedSbToSteal'] = steal_attempt and act == 'folds' - if steal_attemp and act != 'folds': + if steal_attempt and act != 'folds': break - if self.handsplayers[pname]['position'] in steal_positions and not steal_attemp: + if posn in steal_positions and not steal_attempt: self.handsplayers[pname]['stealAttemptChance'] = True if act in ('bets', 'raises'): self.handsplayers[pname]['stealAttempted'] = True - steal_attemp = True + steal_attempt = True + + if posn not in steal_positions and act != 'folds': + break def calc34BetStreet0(self, hand): """Fills street0_(3|4)B(Chance|Done), other(3|4)BStreet0""" From 864454f31c0408e9d24ff2a61c26a4077622dc74 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 3 Feb 2010 01:03:36 +0000 Subject: [PATCH 193/251] change 2 commits to 1, may help sqlite stop locking up --- pyfpdb/fpdb_import.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 8b3f71cd..95ffd525 100755 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -451,14 +451,14 @@ class Importer: to_hud.append(hand.dbid_hands) else: # TODO: Treat empty as an error, or just ignore? log.error("Hand processed but empty") - self.database.commit() + # Call hudcache update if not in bulk import mode # FIXME: Need to test for bulk import that isn't rebuilding the cache if self.callHud: for hand in handlist: if hand is not None: hand.updateHudCache(self.database) - self.database.commit() + self.database.commit() #pipe the Hands.id out to the HUD for hid in to_hud: From 33455cb1acacd092ac2ae955e31d360c24f42409 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 3 Feb 2010 21:52:44 +0800 Subject: [PATCH 194/251] PokerStars: Fix tablename regex to allow a # Occasionally Stars throws up a cash table that looks like PokerStars Game #22920951206: Triple Draw 2-7 Lowball Limit ($0.10/$0.20) - 2008/12/14 17:44:00 ET Table 'T #252691988' 6-max Seat #2 is the button a # was previously excluded from the regex. --- pyfpdb/PokerStarsToFpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index c8bfea70..c2a92881 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -69,7 +69,7 @@ class PokerStars(HandHistoryConverter): re.MULTILINE|re.VERBOSE) re_HandInfo = re.compile(""" - ^Table\s\'(?P
[-\ a-zA-Z\d]+)\'\s + ^Table\s\'(?P
[-\ \#a-zA-Z\d]+)\'\s ((?P\d+)-max\s)? (?P\(Play\sMoney\)\s)? (Seat\s\#(?P