From 8bf01a13e70435ceefd24fe4e7ec26f8b7e68c51 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 2 Dec 2008 00:00:44 +0000 Subject: [PATCH 01/32] Start of fpdb-sql repository --- readme.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 readme.txt diff --git a/readme.txt b/readme.txt new file mode 100644 index 00000000..e69de29b From a824814c0a34689f7ed36321f7217b5a66e61e81 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 2 Dec 2008 00:15:50 +0000 Subject: [PATCH 02/32] sqlcoder initial updates --- pyfpdb/CliFpdb.py | 0 pyfpdb/Configuration.py | 1219 +++++++++++++++++++----------------- pyfpdb/FpdbSQLQueries.py | 29 +- pyfpdb/GuiAutoImport.py | 427 +++++++------ pyfpdb/GuiGraphViewer.py | 18 +- pyfpdb/HUD_main.py | 337 +++++----- pyfpdb/Hud.py | 1140 ++++++++++++++++----------------- pyfpdb/SQL.py | 19 +- pyfpdb/Stats.py | 110 +++- pyfpdb/fpdb.py | 898 +++++++++++++------------- pyfpdb/fpdb_db.py | 0 pyfpdb/fpdb_import.py | 608 +++++++++--------- pyfpdb/fpdb_parse_logic.py | 10 +- pyfpdb/fpdb_save_to_db.py | 24 +- pyfpdb/fpdb_simple.py | 73 ++- 15 files changed, 2578 insertions(+), 2334 deletions(-) mode change 100755 => 100644 pyfpdb/CliFpdb.py mode change 100755 => 100644 pyfpdb/Configuration.py mode change 100755 => 100644 pyfpdb/HUD_main.py mode change 100755 => 100644 pyfpdb/fpdb.py mode change 100755 => 100644 pyfpdb/fpdb_db.py mode change 100755 => 100644 pyfpdb/fpdb_import.py diff --git a/pyfpdb/CliFpdb.py b/pyfpdb/CliFpdb.py old mode 100755 new mode 100644 diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py old mode 100755 new mode 100644 index 5e599d4b..3b5c6d70 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -1,578 +1,641 @@ -#!/usr/bin/env python -"""Configuration.py - -Handles HUD configuration files. -""" -# 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 - -######################################################################## - -# Standard Library modules -import os -import sys -import string -import traceback -import shutil -import xml.dom.minidom -from xml.dom.minidom import Node - -class Layout: - def __init__(self, max): - self.max = int(max) - self.location = [] - for i in range(self.max + 1): self.location.append(None) - - def __str__(self): - temp = " Layout = %d max, width= %d, height = %d, fav_seat = %d\n" % (self.max, self.width, self.height, self.fav_seat) - temp = temp + " Locations = " - for i in range(1, len(self.location)): - temp = temp + "(%d,%d)" % self.location[i] - - return temp + "\n" - -class Site: - def __init__(self, node): - self.site_name = node.getAttribute("site_name") - self.table_finder = node.getAttribute("table_finder") - self.screen_name = node.getAttribute("screen_name") - self.site_path = node.getAttribute("site_path") - self.HH_path = node.getAttribute("HH_path") - self.decoder = node.getAttribute("decoder") - self.hudopacity = node.getAttribute("hudopacity") - self.hudbgcolor = node.getAttribute("bgcolor") - self.hudfgcolor = node.getAttribute("fgcolor") - self.converter = node.getAttribute("converter") - self.layout = {} - - for layout_node in node.getElementsByTagName('layout'): - max = int( layout_node.getAttribute('max') ) - lo = Layout(max) - lo.fav_seat = int( layout_node.getAttribute('fav_seat') ) - lo.width = int( layout_node.getAttribute('width') ) - lo.height = int( layout_node.getAttribute('height') ) - - for location_node in layout_node.getElementsByTagName('location'): - lo.location[int( location_node.getAttribute('seat') )] = (int( location_node.getAttribute('x') ), int( location_node.getAttribute('y'))) - - self.layout[lo.max] = lo - - def __str__(self): - temp = "Site = " + self.site_name + "\n" - for key in dir(self): - if key.startswith('__'): continue - if key == 'layout': continue - value = getattr(self, key) - if callable(value): continue - temp = temp + ' ' + key + " = " + str(value) + "\n" - - for layout in self.layout: - temp = temp + "%s" % self.layout[layout] - - return temp - -class Stat: - def __init__(self): - pass - - def __str__(self): - temp = " stat_name = %s, row = %d, col = %d, tip = %s, click = %s, popup = %s\n" % (self.stat_name, self.row, self.col, self.tip, self.click, self.popup) - return temp - -class Game: - def __init__(self, node): - self.game_name = node.getAttribute("game_name") - self.db = node.getAttribute("db") - self.rows = int( node.getAttribute("rows") ) - self.cols = int( node.getAttribute("cols") ) - - self.stats = {} - for stat_node in node.getElementsByTagName('stat'): - stat = Stat() - stat.stat_name = stat_node.getAttribute("stat_name") - stat.row = int( stat_node.getAttribute("row") ) - stat.col = int( stat_node.getAttribute("col") ) - stat.tip = stat_node.getAttribute("tip") - stat.click = stat_node.getAttribute("click") - stat.popup = stat_node.getAttribute("popup") - stat.hudprefix = stat_node.getAttribute("hudprefix") - stat.hudsuffix = stat_node.getAttribute("hudsuffix") - - self.stats[stat.stat_name] = stat - - def __str__(self): - temp = "Game = " + self.game_name + "\n" - temp = temp + " db = %s\n" % self.db - temp = temp + " rows = %d\n" % self.rows - temp = temp + " cols = %d\n" % self.cols - - for stat in self.stats.keys(): - temp = temp + "%s" % self.stats[stat] - - return temp - -class Database: - def __init__(self, node): - self.db_name = node.getAttribute("db_name") - self.db_server = node.getAttribute("db_server") - self.db_ip = node.getAttribute("db_ip") - self.db_user = node.getAttribute("db_user") - self.db_type = node.getAttribute("db_type") - self.db_pass = node.getAttribute("db_pass") - - def __str__(self): - temp = 'Database = ' + self.db_name + '\n' - for key in dir(self): - if key.startswith('__'): continue - value = getattr(self, key) - if callable(value): continue - temp = temp + ' ' + key + " = " + value + "\n" - return temp - -class Mucked: - def __init__(self, node): - self.name = node.getAttribute("mw_name") - self.cards = node.getAttribute("deck") - self.card_wd = node.getAttribute("card_wd") - self.card_ht = node.getAttribute("card_ht") - self.rows = node.getAttribute("rows") - self.cols = node.getAttribute("cols") - self.format = node.getAttribute("stud") - - def __str__(self): - temp = 'Mucked = ' + self.name + "\n" - for key in dir(self): - if key.startswith('__'): continue - value = getattr(self, key) - if callable(value): continue - temp = temp + ' ' + key + " = " + value + "\n" - return temp - -class Popup: - def __init__(self, node): - self.name = node.getAttribute("pu_name") - self.pu_stats = [] - for stat_node in node.getElementsByTagName('pu_stat'): - self.pu_stats.append(stat_node.getAttribute("pu_stat_name")) - - def __str__(self): - temp = "Popup = " + self.name + "\n" - for stat in self.pu_stats: - temp = temp + " " + stat - return temp + "\n" - -class Import: - def __init__(self, node): - self.interval = node.getAttribute("interval") - self.callFpdbHud = node.getAttribute("callFpdbHud") - - def __str__(self): - return " interval = %s\n callFpdbHud = %s\n" % (self.interval, self.callFpdbHud) - -class Tv: - def __init__(self, node): - self.combinedStealFold = node.getAttribute("combinedStealFold") - self.combined2B3B = node.getAttribute("combined2B3B") - self.combinedPostflop = node.getAttribute("combinedPostflop") - - def __str__(self): - return (" combinedStealFold = %s\n combined2B3B = %s\n combinedPostflop = %s\n" % - (self.combinedStealFold, self.combined2B3B, self.combinedPostflop) ) - -class Config: - def __init__(self, file = None): - -# "file" is a path to an xml file with the fpdb/HUD configuration -# we check the existence of "file" and try to recover if it doesn't exist - - self.default_config_path = self.get_default_config_path() - if not file == None: # configuration file path has been passed - 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)) - file = None - - if file == None: # configuration file path not passed or invalid - file = self.find_config() #Look for a config file in the normal places - - if file == None: # no config file in the normal places - file = self.find_example_config() #Look for an example file to edit - if not file == None: - pass - - if file == None: # that didn't work either, just die - print "No HUD_config_xml found. Exiting" - sys.stderr.write("No HUD_config_xml found. Exiting") - sys.exit() - -# Parse even if there was no real config file found and we are using the example -# If using the example, we'll edit it later - try: - print "Reading configuration file %s\n" % (file) - doc = xml.dom.minidom.parse(file) - except: - print "Error parsing %s. See error log file." % (file) - traceback.print_exc(file=sys.stderr) - print "press enter to continue" - sys.stdin.readline() - sys.exit() - - self.doc = doc - self.file = file - self.supported_sites = {} - self.supported_games = {} - self.supported_databases = {} - self.mucked_windows = {} - self.popup_windows = {} - -# s_sites = doc.getElementsByTagName("supported_sites") - for site_node in doc.getElementsByTagName("site"): - site = Site(node = site_node) - self.supported_sites[site.site_name] = site - -# s_games = doc.getElementsByTagName("supported_games") - for game_node in doc.getElementsByTagName("game"): - game = Game(node = game_node) - self.supported_games[game.game_name] = game - -# s_dbs = doc.getElementsByTagName("supported_databases") - for db_node in doc.getElementsByTagName("database"): - db = Database(node = db_node) - self.supported_databases[db.db_name] = db - -# s_dbs = doc.getElementsByTagName("mucked_windows") - for mw_node in doc.getElementsByTagName("mw"): - mw = Mucked(node = mw_node) - self.mucked_windows[mw.name] = mw - -# s_dbs = doc.getElementsByTagName("popup_windows") - for pu_node in doc.getElementsByTagName("pu"): - pu = Popup(node = pu_node) - self.popup_windows[pu.name] = pu - - for imp_node in doc.getElementsByTagName("import"): - imp = Import(node = imp_node) - self.imp = imp - - for tv_node in doc.getElementsByTagName("tv"): - tv = Tv(node = tv_node) - self.tv = tv - - db = self.get_db_parameters('fpdb') - if db['db-password'] == 'YOUR MYSQL PASSWORD': - df_file = self.find_default_conf() - if df_file == None: # this is bad - pass - else: - df_parms = self.read_default_conf(df_file) - self.set_db_parameters(db_name = 'fpdb', db_ip = df_parms['db-host'], - db_user = df_parms['db-user'], - db_pass = df_parms['db-password']) - self.save(file=os.path.join(self.default_config_path, "HUD_config.xml")) - - - def find_config(self): - """Looks in cwd and in self.default_config_path for a config file.""" - if os.path.exists('HUD_config.xml'): # there is a HUD_config in the cwd - file = 'HUD_config.xml' # so we use it - else: # no HUD_config in the cwd, look where it should be in the first place - config_path = os.path.join(self.default_config_path, 'HUD_config.xml') - if os.path.exists(config_path): - file = config_path - else: - file = None - return file - - def get_default_config_path(self): - """Returns the path where the fpdb config file _should_ be stored.""" - if os.name == 'posix': - config_path = os.path.join(os.path.expanduser("~"), '.fpdb') - elif os.name == 'nt': - config_path = os.path.join(os.environ["APPDATA"], 'fpdb') - else: config_path = None - return config_path - - - def find_default_conf(self): - if os.name == 'posix': - config_path = os.path.join(os.path.expanduser("~"), '.fpdb', 'default.conf') - elif os.name == 'nt': - config_path = os.path.join(os.environ["APPDATA"], 'fpdb', 'default.conf') - else: config_path = False - - if config_path and os.path.exists(config_path): - file = config_path - else: - file = None - return file - - def read_default_conf(self, file): - parms = {} - fh = open(file, "r") - for line in fh: - line = string.strip(line) - (key, value) = line.split('=') - parms[key] = value - fh.close - return parms - - def find_example_config(self): - if os.path.exists('HUD_config.xml.example'): # there is a HUD_config in the cwd - file = 'HUD_config.xml.example' # so we use it - print "No HUD_config.xml found, using HUD_config.xml.example.\n", \ - "A HUD_config.xml will be written. You will probably have to edit it." - sys.stderr.write("No HUD_config.xml found, using HUD_config.xml.example.\n" + \ - "A HUD_config.xml will be written. You will probably have to edit it.") - else: - file = None - return file - - def get_site_node(self, site): - for site_node in self.doc.getElementsByTagName("site"): - if site_node.getAttribute("site_name") == site: - return site_node - - def get_db_node(self, db_name): - for db_node in self.doc.getElementsByTagName("database"): - if db_node.getAttribute("db_name") == db_name: - return db_node - return None - - def get_layout_node(self, site_node, layout): - for layout_node in site_node.getElementsByTagName("layout"): - if layout_node.getAttribute("max") == None: - return None - if int( layout_node.getAttribute("max") ) == int( layout ): - return layout_node - - def get_location_node(self, layout_node, seat): - for location_node in layout_node.getElementsByTagName("location"): - if int( location_node.getAttribute("seat") ) == int( seat ): - return location_node - - def save(self, file = None): - if not file == None: - f = open(file, 'w') - self.doc.writexml(f) - f.close() - else: - shutil.move(self.file, self.file+".backup") - f = open(self.file, 'w') - self.doc.writexml(f) - f.close - - def edit_layout(self, site_name, max, width = None, height = None, - fav_seat = None, locations = None): - print "max = ", max - site_node = self.get_site_node(site_name) - layout_node = self.get_layout_node(site_node, max) - if layout_node == None: return - for i in range(1, max + 1): - location_node = self.get_location_node(layout_node, i) - location_node.setAttribute("x", str( locations[i-1][0] )) - location_node.setAttribute("y", str( locations[i-1][1] )) - self.supported_sites[site_name].layout[max].location[i] = ( locations[i-1][0], locations[i-1][1] ) - - def get_db_parameters(self, name = None): - if name == None: name = 'fpdb' - db = {} - try: - db['db-databaseName'] = name - db['db-host'] = self.supported_databases[name].db_ip - db['db-user'] = self.supported_databases[name].db_user - db['db-password'] = self.supported_databases[name].db_pass - db['db-server'] = self.supported_databases[name].db_server - if string.lower(self.supported_databases[name].db_server) == 'mysql': - db['db-backend'] = 2 - elif string.lower(self.supported_databases[name].db_server) == 'postgresql': - db['db-backend'] = 3 - else: db['db-backend'] = None # this is big trouble - except: - pass - return db - - def set_db_parameters(self, db_name = 'fpdb', db_ip = None, db_user = None, - db_pass = None, db_server = None, db_type = None): - db_node = self.get_db_node(db_name) - if not db_node == None: - if not db_ip == None: db_node.setAttribute("db_ip", db_ip) - if not db_user == None: db_node.setAttribute("db_user", db_user) - if not db_pass == None: db_node.setAttribute("db_pass", db_pass) - if not db_server == None: db_node.setAttribute("db_server", db_server) - if not db_type == None: db_node.setAttribute("db_type", db_type) - if self.supported_databases.has_key(db_name): - if not db_ip == None: self.supported_databases[db_name].dp_ip = db_ip - if not db_user == None: self.supported_databases[db_name].dp_user = db_user - if not db_pass == None: self.supported_databases[db_name].dp_pass = db_pass - if not db_server == None: self.supported_databases[db_name].dp_server = db_server - if not db_type == None: self.supported_databases[db_name].dp_type = db_type - return - - def get_tv_parameters(self): - tv = {} - try: - tv['combinedStealFold'] = self.tv.combinedStealFold - tv['combined2B3B'] = self.tv.combined2B3B - tv['combinedPostflop'] = self.tv.combinedPostflop - except: # Default tv parameters - tv['combinedStealFold'] = True - tv['combined2B3B'] = True - tv['combinedPostflop'] = True - return tv - - def get_import_parameters(self): - imp = {} - try: - imp['imp-callFpdbHud'] = self.imp.callFpdbHud - imp['hud-defaultInterval'] = int(self.imp.interval) - except: # Default import parameters - imp['imp-callFpdbHud'] = True - imp['hud-defaultInterval'] = 10 - return imp - - def get_default_paths(self, site = "PokerStars"): - paths = {} - try: - paths['hud-defaultPath'] = os.path.expanduser(self.supported_sites[site].HH_path) - paths['bulkImport-defaultPath'] = os.path.expanduser(self.supported_sites[site].HH_path) - except: - paths['hud-defaultPath'] = "default" - paths['bulkImport-defaultPath'] = "default" - return paths - - def get_default_colors(self, site = "PokerStars"): - colors = {} - if self.supported_sites[site].hudopacity == "": - colors['hudopacity'] = 0.90 - else: - colors['hudopacity'] = float(self.supported_sites[site].hudopacity) - if self.supported_sites[site].hudbgcolor == "": - colors['hudbgcolor'] = "#FFFFFF" - else: - colors['hudbgcolor'] = self.supported_sites[site].hudbgcolor - if self.supported_sites[site].hudfgcolor == "": - colors['hudfgcolor'] = "#000000" - else: - colors['hudfgcolor'] = self.supported_sites[site].hudfgcolor - return colors - - def get_locations(self, site = "PokerStars", max = "8"): - - try: - locations = self.supported_sites[site].layout[max].location - except: - locations = ( ( 0, 0), (684, 61), (689, 239), (692, 346), - (586, 393), (421, 440), (267, 440), ( 0, 361), - ( 0, 280), (121, 280), ( 46, 30) ) - return locations - - def get_site_parameters(self, site): - """Returns a dict of the site parameters for the specified site""" - if not self.supported_sites.has_key(site): - return None - parms = {} - parms["converter"] = self.supported_sites[site].converter - parms["decoder"] = self.supported_sites[site].decoder - parms["hudbgcolor"] = self.supported_sites[site].hudbgcolor - parms["hudfgcolor"] = self.supported_sites[site].hudfgcolor - parms["hudopacity"] = self.supported_sites[site].hudopacity - parms["screen_name"] = self.supported_sites[site].screen_name - parms["site_path"] = self.supported_sites[site].site_path - parms["table_finder"] = self.supported_sites[site].table_finder - parms["HH_path"] = self.supported_sites[site].HH_path - return parms - - def set_site_parameters(self, site_name, converter = None, decoder = None, - hudbgcolor = None, hudfgcolor = None, - hudopacity = None, screen_name = None, - site_path = None, table_finder = None, - HH_path = None): - """Sets the specified site parameters for the specified site.""" - site_node = self.get_site_node(site_name) - if not db_node == None: - if not converter == None: site_node.setAttribute("converter", converter) - if not decoder == None: site_node.setAttribute("decoder", decoder) - if not hudbgcolor == None: site_node.setAttribute("hudbgcolor", hudbgcolor) - if not hudfgcolor == None: site_node.setAttribute("hudfgcolor", hudfgcolor) - if not hudopacity == None: site_node.setAttribute("hudopacity", hudopacity) - if not screen_name == None: site_node.setAttribute("screen_name", screen_name) - if not site_path == None: site_node.setAttribute("site_path", site_path) - if not table_finder == None: site_node.setAttribute("table_finder", table_finder) - if not HH_path == None: site_node.setAttribute("HH_path", HH_path) - - if self.supported_databases.has_key(db_name): - if not converter == None: self.supported_sites[site].converter = converter - if not decoder == None: self.supported_sites[site].decoder = decoder - if not hudbgcolor == None: self.supported_sites[site].hudbgcolor = hudbgcolor - if not hudfgcolor == None: self.supported_sites[site].hudfgcolor = hudfgcolor - if not hudopacity == None: self.supported_sites[site].hudopacity = hudopacity - if not screen_name == None: self.supported_sites[site].screen_name = screen_name - if not site_path == None: self.supported_sites[site].site_path = site_path - if not table_finder == None: self.supported_sites[site].table_finder = table_finder - if not HH_path == None: self.supported_sites[site].HH_path = HH_path - return - -if __name__== "__main__": - c = Config() - - print "\n----------- SUPPORTED SITES -----------" - for s in c.supported_sites.keys(): - print c.supported_sites[s] - print "----------- END SUPPORTED SITES -----------" - - - print "\n----------- SUPPORTED GAMES -----------" - for game in c.supported_games.keys(): - print c.supported_games[game] - print "----------- END SUPPORTED GAMES -----------" - - - print "\n----------- SUPPORTED DATABASES -----------" - for db in c.supported_databases.keys(): - print c.supported_databases[db] - print "----------- END SUPPORTED DATABASES -----------" - - print "\n----------- MUCKED WINDOW FORMATS -----------" - for w in c.mucked_windows.keys(): - print c.mucked_windows[w] - print "----------- END MUCKED WINDOW FORMATS -----------" - - print "\n----------- POPUP WINDOW FORMATS -----------" - for w in c.popup_windows.keys(): - print c.popup_windows[w] - print "----------- END MUCKED WINDOW FORMATS -----------" - - print "\n----------- IMPORT -----------" -# print c.imp - print "----------- END IMPORT -----------" - - print "\n----------- TABLE VIEW -----------" -# print c.tv - print "----------- END TABLE VIEW -----------" - - c.edit_layout("PokerStars", 6, locations=( (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6) )) - c.save(file="testout.xml") - - print "db = ", c.get_db_parameters() -# print "tv = ", c.get_tv_parameters() -# print "imp = ", c.get_import_parameters() - print "paths = ", c.get_default_paths("PokerStars") - print "colors = ", c.get_default_colors("PokerStars") - print "locs = ", c.get_locations("PokerStars", 8) - for site in c.supported_sites.keys(): - print "site = ", site, - print c.get_site_parameters(site) \ No newline at end of file +#!/usr/bin/env python +"""Configuration.py + +Handles HUD configuration files. +""" +# 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 + +######################################################################## + +# Standard Library modules +import os +import sys +import string +import traceback +import shutil +import xml.dom.minidom +from xml.dom.minidom import Node + +class Layout: + def __init__(self, max): + self.max = int(max) + self.location = [] + for i in range(self.max + 1): self.location.append(None) + + def __str__(self): + temp = " Layout = %d max, width= %d, height = %d, fav_seat = %d\n" % (self.max, self.width, self.height, self.fav_seat) + temp = temp + " Locations = " + for i in range(1, len(self.location)): + temp = temp + "(%d,%d)" % self.location[i] + + return temp + "\n" + +class Site: + def __init__(self, node): + self.site_name = node.getAttribute("site_name") + self.table_finder = node.getAttribute("table_finder") + self.screen_name = node.getAttribute("screen_name") + self.site_path = node.getAttribute("site_path") + self.HH_path = node.getAttribute("HH_path") + self.decoder = node.getAttribute("decoder") + self.hudopacity = node.getAttribute("hudopacity") + self.hudbgcolor = node.getAttribute("bgcolor") + self.hudfgcolor = node.getAttribute("fgcolor") + self.converter = node.getAttribute("converter") + self.enabled = node.getAttribute("enabled") + self.aux_window = node.getAttribute("aux_window") + self.layout = {} + + for layout_node in node.getElementsByTagName('layout'): + max = int( layout_node.getAttribute('max') ) + lo = Layout(max) + lo.fav_seat = int( layout_node.getAttribute('fav_seat') ) + lo.width = int( layout_node.getAttribute('width') ) + lo.height = int( layout_node.getAttribute('height') ) + + for location_node in layout_node.getElementsByTagName('location'): + lo.location[int( location_node.getAttribute('seat') )] = (int( location_node.getAttribute('x') ), int( location_node.getAttribute('y'))) + + self.layout[lo.max] = lo + + def __str__(self): + temp = "Site = " + self.site_name + "\n" + for key in dir(self): + if key.startswith('__'): continue + if key == 'layout': continue + value = getattr(self, key) + if callable(value): continue + temp = temp + ' ' + key + " = " + str(value) + "\n" + + for layout in self.layout: + temp = temp + "%s" % self.layout[layout] + + return temp + +class Stat: + def __init__(self): + pass + + def __str__(self): + temp = " stat_name = %s, row = %d, col = %d, tip = %s, click = %s, popup = %s\n" % (self.stat_name, self.row, self.col, self.tip, self.click, self.popup) + return temp + +class Game: + def __init__(self, node): + self.game_name = node.getAttribute("game_name") + self.db = node.getAttribute("db") + self.rows = int( node.getAttribute("rows") ) + self.cols = int( node.getAttribute("cols") ) + self.aux = node.getAttribute("aux") + + self.stats = {} + for stat_node in node.getElementsByTagName('stat'): + stat = Stat() + stat.stat_name = stat_node.getAttribute("stat_name") + stat.row = int( stat_node.getAttribute("row") ) + stat.col = int( stat_node.getAttribute("col") ) + stat.tip = stat_node.getAttribute("tip") + stat.click = stat_node.getAttribute("click") + stat.popup = stat_node.getAttribute("popup") + stat.hudprefix = stat_node.getAttribute("hudprefix") + stat.hudsuffix = stat_node.getAttribute("hudsuffix") + + self.stats[stat.stat_name] = stat + + def __str__(self): + temp = "Game = " + self.game_name + "\n" + temp = temp + " db = %s\n" % self.db + temp = temp + " rows = %d\n" % self.rows + temp = temp + " cols = %d\n" % self.cols + temp = temp + " aux = %s\n" % self.aux + + for stat in self.stats.keys(): + temp = temp + "%s" % self.stats[stat] + + return temp + +class Database: + def __init__(self, node): + self.db_name = node.getAttribute("db_name") + self.db_server = node.getAttribute("db_server") + self.db_ip = node.getAttribute("db_ip") + self.db_user = node.getAttribute("db_user") + self.db_type = node.getAttribute("db_type") + self.db_pass = node.getAttribute("db_pass") + + def __str__(self): + temp = 'Database = ' + self.db_name + '\n' + for key in dir(self): + if key.startswith('__'): continue + value = getattr(self, key) + if callable(value): continue + temp = temp + ' ' + key + " = " + value + "\n" + return temp + +class Aux_window: + def __init__(self, node): + for (name, value) in node.attributes.items(): + setattr(self, name, value) +# self.name = node.getAttribute("mw_name") +# self.cards = node.getAttribute("deck") +# self.card_wd = node.getAttribute("card_wd") +# self.card_ht = node.getAttribute("card_ht") +# self.rows = node.getAttribute("rows") +# self.cols = node.getAttribute("cols") +# self.format = node.getAttribute("stud") + + def __str__(self): + temp = 'Aux = ' + self.name + "\n" + for key in dir(self): + if key.startswith('__'): continue + value = getattr(self, key) + if callable(value): continue + temp = temp + ' ' + key + " = " + value + "\n" + return temp + +class Popup: + def __init__(self, node): + self.name = node.getAttribute("pu_name") + self.pu_stats = [] + for stat_node in node.getElementsByTagName('pu_stat'): + self.pu_stats.append(stat_node.getAttribute("pu_stat_name")) + + def __str__(self): + temp = "Popup = " + self.name + "\n" + for stat in self.pu_stats: + temp = temp + " " + stat + return temp + "\n" + +class Import: + def __init__(self, node): + self.interval = node.getAttribute("interval") + self.callFpdbHud = node.getAttribute("callFpdbHud") + self.hhArchiveBase = node.getAttribute("hhArchiveBase") + + def __str__(self): + return " interval = %s\n callFpdbHud = %s\n hhArchiveBase = %s" % (self.interval, self.callFpdbHud, self.hhArchiveBase) + +class Tv: + def __init__(self, node): + self.combinedStealFold = node.getAttribute("combinedStealFold") + self.combined2B3B = node.getAttribute("combined2B3B") + self.combinedPostflop = node.getAttribute("combinedPostflop") + + def __str__(self): + return (" combinedStealFold = %s\n combined2B3B = %s\n combinedPostflop = %s\n" % + (self.combinedStealFold, self.combined2B3B, self.combinedPostflop) ) + +class Config: + def __init__(self, file = None): + +# "file" is a path to an xml file with the fpdb/HUD configuration +# we check the existence of "file" and try to recover if it doesn't exist + + self.default_config_path = self.get_default_config_path() + if not file == None: # configuration file path has been passed + 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)) + file = None + + if file == None: # configuration file path not passed or invalid + file = self.find_config() #Look for a config file in the normal places + + if file == None: # no config file in the normal places + file = self.find_example_config() #Look for an example file to edit + if not file == None: + pass + + if file == None: # that didn't work either, just die + print "No HUD_config_xml found. Exiting" + sys.stderr.write("No HUD_config_xml found. Exiting") + sys.exit() + +# Parse even if there was no real config file found and we are using the example +# If using the example, we'll edit it later + try: + print "Reading configuration file %s\n" % (file) + doc = xml.dom.minidom.parse(file) + except: + print "Error parsing %s. See error log file." % (file) + traceback.print_exc(file=sys.stderr) + print "press enter to continue" + sys.stdin.readline() + sys.exit() + + self.doc = doc + self.file = file + self.supported_sites = {} + self.supported_games = {} + self.supported_databases = {} + self.aux_windows = {} + self.popup_windows = {} + +# s_sites = doc.getElementsByTagName("supported_sites") + for site_node in doc.getElementsByTagName("site"): + site = Site(node = site_node) + self.supported_sites[site.site_name] = site + +# s_games = doc.getElementsByTagName("supported_games") + for game_node in doc.getElementsByTagName("game"): + game = Game(node = game_node) + self.supported_games[game.game_name] = game + +# s_dbs = doc.getElementsByTagName("supported_databases") + for db_node in doc.getElementsByTagName("database"): + db = Database(node = db_node) + self.supported_databases[db.db_name] = db + +# s_dbs = doc.getElementsByTagName("mucked_windows") + for aw_node in doc.getElementsByTagName("aw"): + aw = Aux_window(node = aw_node) + self.aux_windows[aw.name] = aw + +# s_dbs = doc.getElementsByTagName("popup_windows") + for pu_node in doc.getElementsByTagName("pu"): + pu = Popup(node = pu_node) + self.popup_windows[pu.name] = pu + + for imp_node in doc.getElementsByTagName("import"): + imp = Import(node = imp_node) + self.imp = imp + + for tv_node in doc.getElementsByTagName("tv"): + tv = Tv(node = tv_node) + self.tv = tv + + db = self.get_db_parameters('fpdb') + if db['db-password'] == 'YOUR MYSQL PASSWORD': + df_file = self.find_default_conf() + if df_file == None: # this is bad + pass + else: + df_parms = self.read_default_conf(df_file) + self.set_db_parameters(db_name = 'fpdb', db_ip = df_parms['db-host'], + db_user = df_parms['db-user'], + db_pass = df_parms['db-password']) + self.save(file=os.path.join(self.default_config_path, "HUD_config.xml")) + + + def find_config(self): + """Looks in cwd and in self.default_config_path for a config file.""" + if os.path.exists('HUD_config.xml'): # there is a HUD_config in the cwd + file = 'HUD_config.xml' # so we use it + else: # no HUD_config in the cwd, look where it should be in the first place + config_path = os.path.join(self.default_config_path, 'HUD_config.xml') + if os.path.exists(config_path): + file = config_path + else: + file = None + return file + + def get_default_config_path(self): + """Returns the path where the fpdb config file _should_ be stored.""" + if os.name == 'posix': + config_path = os.path.join(os.path.expanduser("~"), '.fpdb') + elif os.name == 'nt': + config_path = os.path.join(os.environ["APPDATA"], 'fpdb') + else: config_path = None + return config_path + + + def find_default_conf(self): + if os.name == 'posix': + config_path = os.path.join(os.path.expanduser("~"), '.fpdb', 'default.conf') + elif os.name == 'nt': + config_path = os.path.join(os.environ["APPDATA"], 'fpdb', 'default.conf') + else: config_path = False + + if config_path and os.path.exists(config_path): + file = config_path + else: + file = None + return file + + def read_default_conf(self, file): + parms = {} + fh = open(file, "r") + for line in fh: + line = string.strip(line) + (key, value) = line.split('=') + parms[key] = value + fh.close + return parms + + def find_example_config(self): + if os.path.exists('HUD_config.xml.example'): # there is a HUD_config in the cwd + file = 'HUD_config.xml.example' # so we use it + print "No HUD_config.xml found, using HUD_config.xml.example.\n", \ + "A HUD_config.xml will be written. You will probably have to edit it." + sys.stderr.write("No HUD_config.xml found, using HUD_config.xml.example.\n" + \ + "A HUD_config.xml will be written. You will probably have to edit it.") + else: + file = None + return file + + def get_site_node(self, site): + for site_node in self.doc.getElementsByTagName("site"): + if site_node.getAttribute("site_name") == site: + return site_node + + def get_db_node(self, db_name): + for db_node in self.doc.getElementsByTagName("database"): + if db_node.getAttribute("db_name") == db_name: + return db_node + return None + + def get_layout_node(self, site_node, layout): + for layout_node in site_node.getElementsByTagName("layout"): + if layout_node.getAttribute("max") == None: + return None + if int( layout_node.getAttribute("max") ) == int( layout ): + return layout_node + + def get_location_node(self, layout_node, seat): + for location_node in layout_node.getElementsByTagName("location"): + if int( location_node.getAttribute("seat") ) == int( seat ): + return location_node + + def save(self, file = None): + if not file == None: + f = open(file, 'w') + self.doc.writexml(f) + f.close() + else: + shutil.move(self.file, self.file+".backup") + f = open(self.file, 'w') + self.doc.writexml(f) + f.close + + def edit_layout(self, site_name, max, width = None, height = None, + fav_seat = None, locations = None): + site_node = self.get_site_node(site_name) + layout_node = self.get_layout_node(site_node, max) + if layout_node == None: return + for i in range(1, max + 1): + location_node = self.get_location_node(layout_node, i) + location_node.setAttribute("x", str( locations[i-1][0] )) + location_node.setAttribute("y", str( locations[i-1][1] )) + self.supported_sites[site_name].layout[max].location[i] = ( locations[i-1][0], locations[i-1][1] ) + + def get_db_parameters(self, name = None): + if name == None: name = 'fpdb' + db = {} + try: + db['db-databaseName'] = name + db['db-host'] = self.supported_databases[name].db_ip + db['db-user'] = self.supported_databases[name].db_user + db['db-password'] = self.supported_databases[name].db_pass + db['db-server'] = self.supported_databases[name].db_server + if string.lower(self.supported_databases[name].db_server) == 'mysql': + db['db-backend'] = 2 + elif string.lower(self.supported_databases[name].db_server) == 'postgresql': + db['db-backend'] = 3 + else: db['db-backend'] = None # this is big trouble + except: + pass + return db + + def set_db_parameters(self, db_name = 'fpdb', db_ip = None, db_user = None, + db_pass = None, db_server = None, db_type = None): + db_node = self.get_db_node(db_name) + if not db_node == None: + if not db_ip == None: db_node.setAttribute("db_ip", db_ip) + if not db_user == None: db_node.setAttribute("db_user", db_user) + if not db_pass == None: db_node.setAttribute("db_pass", db_pass) + if not db_server == None: db_node.setAttribute("db_server", db_server) + if not db_type == None: db_node.setAttribute("db_type", db_type) + if self.supported_databases.has_key(db_name): + if not db_ip == None: self.supported_databases[db_name].dp_ip = db_ip + if not db_user == None: self.supported_databases[db_name].dp_user = db_user + if not db_pass == None: self.supported_databases[db_name].dp_pass = db_pass + if not db_server == None: self.supported_databases[db_name].dp_server = db_server + if not db_type == None: self.supported_databases[db_name].dp_type = db_type + return + + def get_tv_parameters(self): + tv = {} + try: + tv['combinedStealFold'] = self.tv.combinedStealFold + tv['combined2B3B'] = self.tv.combined2B3B + tv['combinedPostflop'] = self.tv.combinedPostflop + except: # Default tv parameters + tv['combinedStealFold'] = True + tv['combined2B3B'] = True + tv['combinedPostflop'] = True + return tv + + def get_import_parameters(self): + imp = {} + try: + imp['callFpdbHud'] = self.callFpdbHud + imp['interval'] = self.interval + imp['hhArchiveBase'] = self.hhArchiveBase + except: # Default params + imp['callFpdbHud'] = True + imp['interval'] = 10 + imp['hhArchiveBase'] = "~/.fpdb/HandHistories/" + return imp + + def get_default_paths(self, site = "PokerStars"): + paths = {} + try: + paths['hud-defaultPath'] = os.path.expanduser(self.supported_sites[site].HH_path) + paths['bulkImport-defaultPath'] = os.path.expanduser(self.supported_sites[site].HH_path) + except: + paths['hud-defaultPath'] = "default" + paths['bulkImport-defaultPath'] = "default" + return paths + + def get_default_colors(self, site = "PokerStars"): + colors = {} + if self.supported_sites[site].hudopacity == "": + colors['hudopacity'] = 0.90 + else: + colors['hudopacity'] = float(self.supported_sites[site].hudopacity) + if self.supported_sites[site].hudbgcolor == "": + colors['hudbgcolor'] = "#FFFFFF" + else: + colors['hudbgcolor'] = self.supported_sites[site].hudbgcolor + if self.supported_sites[site].hudfgcolor == "": + colors['hudfgcolor'] = "#000000" + else: + colors['hudfgcolor'] = self.supported_sites[site].hudfgcolor + return colors + + def get_locations(self, site = "PokerStars", max = "8"): + + try: + locations = self.supported_sites[site].layout[max].location + except: + locations = ( ( 0, 0), (684, 61), (689, 239), (692, 346), + (586, 393), (421, 440), (267, 440), ( 0, 361), + ( 0, 280), (121, 280), ( 46, 30) ) + return locations + + def get_supported_sites(self): + """Returns the list of supported sites.""" + return self.supported_sites.keys() + + def get_site_parameters(self, site): + """Returns a dict of the site parameters for the specified site""" + if not self.supported_sites.has_key(site): + return None + parms = {} + parms["converter"] = self.supported_sites[site].converter + parms["decoder"] = self.supported_sites[site].decoder + parms["hudbgcolor"] = self.supported_sites[site].hudbgcolor + parms["hudfgcolor"] = self.supported_sites[site].hudfgcolor + parms["hudopacity"] = self.supported_sites[site].hudopacity + parms["screen_name"] = self.supported_sites[site].screen_name + parms["site_path"] = self.supported_sites[site].site_path + parms["table_finder"] = self.supported_sites[site].table_finder + parms["HH_path"] = self.supported_sites[site].HH_path + parms["site_name"] = self.supported_sites[site].site_name + parms["enabled"] = self.supported_sites[site].enabled + parms["aux_window"] = self.supported_sites[site].aux_window + return parms + + def set_site_parameters(self, site_name, converter = None, decoder = None, + hudbgcolor = None, hudfgcolor = None, + hudopacity = None, screen_name = None, + site_path = None, table_finder = None, + HH_path = None, enabled = None): + """Sets the specified site parameters for the specified site.""" + site_node = self.get_site_node(site_name) + if not db_node == None: + if not converter == None: site_node.setAttribute("converter", converter) + if not decoder == None: site_node.setAttribute("decoder", decoder) + if not hudbgcolor == None: site_node.setAttribute("hudbgcolor", hudbgcolor) + if not hudfgcolor == None: site_node.setAttribute("hudfgcolor", hudfgcolor) + if not hudopacity == None: site_node.setAttribute("hudopacity", hudopacity) + if not screen_name == None: site_node.setAttribute("screen_name", screen_name) + if not site_path == None: site_node.setAttribute("site_path", site_path) + if not table_finder == None: site_node.setAttribute("table_finder", table_finder) + if not HH_path == None: site_node.setAttribute("HH_path", HH_path) + if not enabled == None: site_node.setAttribute("enabled", enabled) + + if self.supported_databases.has_key(db_name): + if not converter == None: self.supported_sites[site].converter = converter + if not decoder == None: self.supported_sites[site].decoder = decoder + if not hudbgcolor == None: self.supported_sites[site].hudbgcolor = hudbgcolor + if not hudfgcolor == None: self.supported_sites[site].hudfgcolor = hudfgcolor + if not hudopacity == None: self.supported_sites[site].hudopacity = hudopacity + if not screen_name == None: self.supported_sites[site].screen_name = screen_name + if not site_path == None: self.supported_sites[site].site_path = site_path + if not table_finder == None: self.supported_sites[site].table_finder = table_finder + if not HH_path == None: self.supported_sites[site].HH_path = HH_path + if not enabled == None: self.supported_sites[site].enabled = enabled + return + + def get_aux_windows(self): + """Gets the list of mucked window formats in the configuration.""" + mw = [] + for w in self.aux_windows.keys(): + mw.append(w) + return mw + + def get_aux_parameters(self, name): + """Gets a dict of mucked window parameters from the named mw.""" + param = {} + if self.aux_windows.has_key(name): + for key in dir(self.aux_windows[name]): + if key.startswith('__'): continue + value = getattr(self.aux_windows[name], key) + if callable(value): continue + param[key] = value + + return param + return None + + def get_game_parameters(self, name): + """Get the configuration parameters for the named game.""" + param = {} + if self.supported_games.has_key(name): + param['game_name'] = self.supported_games[name].game_name + param['db'] = self.supported_games[name].db + param['rows'] = self.supported_games[name].rows + param['cols'] = self.supported_games[name].cols + param['aux'] = self.supported_games[name].aux + return param + + def get_supported_games(self): + """Get the list of supported games.""" + sg = [] + for game in c.supported_games.keys(): + sg.append(c.supported_games[game].game_name) + return sg + +if __name__== "__main__": + c = Config() + + print "\n----------- SUPPORTED SITES -----------" + for s in c.supported_sites.keys(): + print c.supported_sites[s] + print "----------- END SUPPORTED SITES -----------" + + + print "\n----------- SUPPORTED GAMES -----------" + for game in c.supported_games.keys(): + print c.supported_games[game] + print "----------- END SUPPORTED GAMES -----------" + + + print "\n----------- SUPPORTED DATABASES -----------" + for db in c.supported_databases.keys(): + print c.supported_databases[db] + print "----------- END SUPPORTED DATABASES -----------" + + print "\n----------- AUX WINDOW FORMATS -----------" + for w in c.aux_windows.keys(): + print c.aux_windows[w] + print "----------- END AUX WINDOW FORMATS -----------" + + print "\n----------- POPUP WINDOW FORMATS -----------" + for w in c.popup_windows.keys(): + print c.popup_windows[w] + print "----------- END POPUP WINDOW FORMATS -----------" + + print "\n----------- IMPORT -----------" + tmp = c.get_import_parameters() + for param in tmp: + print " " + str(param) + ": " + str(tmp[param]) + print "----------- END IMPORT -----------" + + print "\n----------- TABLE VIEW -----------" +# print c.tv + print "----------- END TABLE VIEW -----------" + + c.edit_layout("PokerStars", 6, locations=( (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6) )) + c.save(file="testout.xml") + + print "db = ", c.get_db_parameters() +# print "tv = ", c.get_tv_parameters() +# print "imp = ", c.get_import_parameters() + print "paths = ", c.get_default_paths("PokerStars") + print "colors = ", c.get_default_colors("PokerStars") + print "locs = ", c.get_locations("PokerStars", 8) + for mw in c.get_aux_windows(): + print c.get_aux_parameters(mw) + + for site in c.supported_sites.keys(): + print "site = ", site, + print c.get_site_parameters(site) + + for game in c.get_supported_games(): + print c.get_game_parameters(game) diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index e582c681..9b791f5d 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -601,7 +601,34 @@ class FpdbSQLQueries: WHERE Players.name = %s AND Players.siteId = %s AND (tourneysPlayersId IS NULL) ORDER BY handStart""" - # Returns the profit for a given ring game handId, Total pot - money invested by playerId + # Returns the profit for all hands, Total pot - money invested by playerId + if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'): + self.query['getRingProfitAllHandsPlayerIdSite'] = """ + SELECT hp.handId, hp.winnings, SUM(ha.amount) costs, hp.winnings - SUM(ha.amount) profit + FROM HandsPlayers hp + INNER JOIN Players pl ON hp.playerId = pl.id + INNER JOIN Hands h ON h.id = hp.handId + INNER JOIN HandsActions ha ON ha.handPlayerId = hp.id + WHERE pl.name = %s + AND pl.siteId = %s + AND hp.tourneysPlayersId IS NULL + group by hp.handId, hp.winnings, h.handStart + ORDER BY h.handStart""" + elif(self.dbname == 'SQLite'): + #May not work. + self.query['getRingProfitAllHandsPlayerIdSite'] = """ + SELECT hp.handId, hp.winnings, SUM(ha.amount) costs, hp.winnings - SUM(ha.amount) profit + FROM HandsPlayers hp + INNER JOIN Players pl ON hp.playerId = pl.id + INNER JOIN Hands h ON h.id = hp.handId + INNER JOIN HandsActions ha ON ha.handPlayerId = hp.id + WHERE pl.name = %s + AND pl.siteId = %s + AND hp.tourneysPlayersId IS NULL + group by hp.handId, hp.winnings, h.handStart + ORDER BY h.handStart""" + + # Returns the profit for a given ring game handId, Total pot - money invested by playerId - WRONG, returns players costs if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'): self.query['getRingProfitFromHandId'] = """SELECT SUM(amount) FROM HandsActions INNER JOIN HandsPlayers ON HandsActions.handPlayerId = HandsPlayers.id diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py index 916170f0..9f07910c 100644 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -1,216 +1,211 @@ -#!/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 threading -import subprocess - -import pygtk -pygtk.require('2.0') -import gtk -import gobject -import os -import time -import fpdb_import - -class GuiAutoImport (threading.Thread): - def starsBrowseClicked(self, widget, data): - """runs when user clicks browse on auto import tab""" - #print "start of GuiAutoImport.starsBrowseClicked" - current_path=self.starsDirPath.get_text() - - dia_chooser = gtk.FileChooserDialog(title="Please choose the path that you want to auto import", - action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, - buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) - #dia_chooser.set_current_folder(pathname) - dia_chooser.set_filename(current_path) - #dia_chooser.set_select_multiple(select_multiple) #not in tv, but want this in bulk import - - response = dia_chooser.run() - if response == gtk.RESPONSE_OK: - #print dia_chooser.get_filename(), 'selected' - self.starsDirPath.set_text(dia_chooser.get_filename()) - elif response == gtk.RESPONSE_CANCEL: - print 'Closed, no files selected' - dia_chooser.destroy() - #end def GuiAutoImport.starsBrowseClicked - - def tiltBrowseClicked(self, widget, data): - """runs when user clicks browse on auto import tab""" - #print "start of GuiAutoImport.tiltBrowseClicked" - current_path=self.tiltDirPath.get_text() - - dia_chooser = gtk.FileChooserDialog(title="Please choose the path that you want to auto import", - action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, - buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) - #dia_chooser.set_current_folder(pathname) - dia_chooser.set_filename(current_path) - #dia_chooser.set_select_multiple(select_multiple) #not in tv, but want this in bulk import - - response = dia_chooser.run() - if response == gtk.RESPONSE_OK: - #print dia_chooser.get_filename(), 'selected' - self.tiltDirPath.set_text(dia_chooser.get_filename()) - elif response == gtk.RESPONSE_CANCEL: - print 'Closed, no files selected' - dia_chooser.destroy() - #end def GuiAutoImport.tiltBrowseClicked - - def do_import(self): - """Callback for timer to do an import iteration.""" - self.importer.runUpdated() - print "GuiAutoImport.import_dir done" - return True - - def startClicked(self, widget, data): - """runs when user clicks start on auto import tab""" - -# Check to see if we have an open file handle to the HUD and open one if we do not. -# bufsize = 1 means unbuffered -# We need to close this file handle sometime. - -# TODO: Allow for importing from multiple dirs - REB 29AUG2008 -# As presently written this function does nothing if there is already a pipe open. -# That is not correct. It should open another dir for importing while piping the -# results to the same pipe. This means that self.path should be a a list of dirs -# to watch. - try: #uhhh, I don't this this is the best way to check for the existence of an attr - getattr(self, "pipe_to_hud") - except AttributeError: - if os.name == 'nt': - command = "python HUD_main.py" + " %s" % (self.database) - bs = 0 # windows is not happy with line buffing here - self.pipe_to_hud = subprocess.Popen(command, bufsize = bs, stdin = subprocess.PIPE, - universal_newlines=True) - else: - cwd = os.getcwd() - command = os.path.join(cwd, 'HUD_main.py') - bs = 1 - self.pipe_to_hud = subprocess.Popen((command, self.database), bufsize = bs, stdin = subprocess.PIPE, - universal_newlines=True) -# self.pipe_to_hud = subprocess.Popen((command, self.database), bufsize = bs, stdin = subprocess.PIPE, -# universal_newlines=True) -# command = command + " %s" % (self.database) -# print "command = ", command -# self.pipe_to_hud = os.popen(command, 'w') - self.starspath=self.starsDirPath.get_text() - self.tiltpath=self.tiltDirPath.get_text() - -# Add directory to importer object. - self.importer.addImportDirectory(self.starspath, True, "PokerStars", "passthrough") - self.importer.addImportDirectory(self.tiltpath, True, "FullTilt", "passthrough") - self.do_import() - - interval=int(self.intervalEntry.get_text()) - gobject.timeout_add(interval*1000, self.do_import) - #end def GuiAutoImport.startClicked - - def get_vbox(self): - """returns the vbox of this thread""" - return self.mainVBox - #end def get_vbox - - def __init__(self, settings, config, debug=True): - """Constructor for GuiAutoImport""" - self.settings=settings - self.config=config - self.importer = fpdb_import.Importer(self,self.settings) - self.importer.setCallHud(True) - self.importer.setMinPrint(30) - self.importer.setQuiet(False) - self.importer.setFailOnError(False) - self.importer.setHandCount(0) -# self.importer.setWatchTime() - - self.server=settings['db-host'] - self.user=settings['db-user'] - self.password=settings['db-password'] - self.database=settings['db-databaseName'] - - self.mainVBox=gtk.VBox(False,1) - self.mainVBox.show() - - self.settingsHBox = gtk.HBox(False, 0) - self.mainVBox.pack_start(self.settingsHBox, False, True, 0) - self.settingsHBox.show() - - self.intervalLabel = gtk.Label("Interval (ie. break) between imports in seconds:") - self.settingsHBox.pack_start(self.intervalLabel) - self.intervalLabel.show() - - self.intervalEntry=gtk.Entry() - self.intervalEntry.set_text(str(self.settings['hud-defaultInterval'])) - self.settingsHBox.pack_start(self.intervalEntry) - self.intervalEntry.show() - - self.pathHBox = gtk.HBox(False, 0) - self.mainVBox.pack_start(self.pathHBox, False, True, 0) - self.pathHBox.show() - - self.pathStarsLabel = gtk.Label("Path to PokerStars auto-import:") - self.pathHBox.pack_start(self.pathStarsLabel, False, False, 0) - self.pathStarsLabel.show() - - self.starsDirPath=gtk.Entry() - paths = self.config.get_default_paths("PokerStars") - self.starsDirPath.set_text(paths['hud-defaultPath']) - self.pathHBox.pack_start(self.starsDirPath, False, True, 0) - self.starsDirPath.show() - - self.browseButton=gtk.Button("Browse...") - self.browseButton.connect("clicked", self.starsBrowseClicked, "Browse clicked") - self.pathHBox.pack_start(self.browseButton, False, False, 0) - self.browseButton.show() - - self.pathTiltLabel = gtk.Label("Path to Full Tilt auto-import:") - self.pathHBox.pack_start(self.pathTiltLabel, False, False, 0) - self.pathTiltLabel.show() - - self.tiltDirPath=gtk.Entry() - paths = self.config.get_default_paths("Full Tilt") - self.tiltDirPath.set_text(paths['hud-defaultPath']) - self.pathHBox.pack_start(self.tiltDirPath, False, True, 0) - self.tiltDirPath.show() - - self.browseButton=gtk.Button("Browse...") - self.browseButton.connect("clicked", self.tiltBrowseClicked, "Browse clicked") - self.pathHBox.pack_start(self.browseButton, False, False, 0) - self.browseButton.show() - - self.startButton=gtk.Button("Start Autoimport") - self.startButton.connect("clicked", self.startClicked, "start clicked") - self.mainVBox.add(self.startButton) - self.startButton.show() - #end of GuiAutoImport.__init__ -if __name__== "__main__": - def destroy(*args): # call back for terminating the main eventloop - gtk.main_quit() - - settings = {} - settings['db-host'] = "192.168.1.100" - settings['db-user'] = "mythtv" - settings['db-password'] = "mythtv" - settings['db-databaseName'] = "fpdb" - settings['hud-defaultInterval'] = 10 - settings['hud-defaultPath'] = 'C:/Program Files/PokerStars/HandHistory/nutOmatic' - settings['imp-callFpdbHud'] = True - - i = GuiAutoImport(settings) - main_window = gtk.Window() - main_window.connect("destroy", destroy) - main_window.add(i.mainVBox) - main_window.show() - gtk.main() +#!/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 threading +import subprocess + +import pygtk +pygtk.require('2.0') +import gtk +import gobject +import os +import time +import fpdb_import + + +class GuiAutoImport (threading.Thread): + def __init__(self, settings, config): + """Constructor for GuiAutoImport""" + self.settings=settings + self.config=config + + imp = self.config.get_import_parameters() + + print "Import parameters" + print imp + + self.input_settings = {} + + self.importer = fpdb_import.Importer(self, self.settings, self.config) + self.importer.setCallHud(True) + self.importer.setMinPrint(30) + self.importer.setQuiet(False) + self.importer.setFailOnError(False) + self.importer.setHandCount(0) +# self.importer.setWatchTime() + + self.server=settings['db-host'] + self.user=settings['db-user'] + self.password=settings['db-password'] + self.database=settings['db-databaseName'] + + self.mainVBox=gtk.VBox(False,1) + self.mainVBox.show() + + self.settingsHBox = gtk.HBox(False, 0) + self.mainVBox.pack_start(self.settingsHBox, False, True, 0) + self.settingsHBox.show() + + self.intervalLabel = gtk.Label("Time between imports in seconds:") + self.settingsHBox.pack_start(self.intervalLabel) + self.intervalLabel.show() + + self.intervalEntry=gtk.Entry() + self.intervalEntry.set_text(str(self.config.get_import_parameters().get("interval"))) + self.settingsHBox.pack_start(self.intervalEntry) + self.intervalEntry.show() + + self.addSites(self.mainVBox) + + self.startButton=gtk.Button("Start Autoimport") + self.startButton.connect("clicked", self.startClicked, "start clicked") + self.mainVBox.add(self.startButton) + self.startButton.show() + + + #end of GuiAutoImport.__init__ + def browseClicked(self, widget, data): + """runs when user clicks one of the browse buttons in the auto import tab""" + current_path=data[1].get_text() + + dia_chooser = gtk.FileChooserDialog(title="Please choose the path that you want to auto import", + action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, + buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) + #dia_chooser.set_current_folder(pathname) + dia_chooser.set_filename(current_path) + #dia_chooser.set_select_multiple(select_multiple) #not in tv, but want this in bulk import + + response = dia_chooser.run() + if response == gtk.RESPONSE_OK: + #print dia_chooser.get_filename(), 'selected' + data[1].set_text(dia_chooser.get_filename()) + self.input_settings[data[0]][0] = dia_chooser.get_filename() + elif response == gtk.RESPONSE_CANCEL: + print 'Closed, no files selected' + dia_chooser.destroy() + #end def GuiAutoImport.browseClicked + + def do_import(self): + """Callback for timer to do an import iteration.""" + self.importer.runUpdated() + print "GuiAutoImport.import_dir done" + return True + + def startClicked(self, widget, data): + """runs when user clicks start on auto import tab""" + +# Check to see if we have an open file handle to the HUD and open one if we do not. +# bufsize = 1 means unbuffered +# We need to close this file handle sometime. + +# TODO: Allow for importing from multiple dirs - REB 29AUG2008 +# As presently written this function does nothing if there is already a pipe open. +# That is not correct. It should open another dir for importing while piping the +# results to the same pipe. This means that self.path should be a a list of dirs +# to watch. + try: #uhhh, I don't this this is the best way to check for the existence of an attr + getattr(self, "pipe_to_hud") + except AttributeError: + if os.name == 'nt': + command = "python HUD_main.py" + " %s" % (self.database) + bs = 0 # windows is not happy with line buffing here + self.pipe_to_hud = subprocess.Popen(command, bufsize = bs, stdin = subprocess.PIPE, + universal_newlines=True) + else: + cwd = os.getcwd() + command = os.path.join(cwd, 'HUD_main.py') + bs = 1 + self.pipe_to_hud = subprocess.Popen((command, self.database), bufsize = bs, stdin = subprocess.PIPE, + universal_newlines=True) +# self.pipe_to_hud = subprocess.Popen((command, self.database), bufsize = bs, stdin = subprocess.PIPE, +# universal_newlines=True) +# command = command + " %s" % (self.database) +# print "command = ", command +# self.pipe_to_hud = os.popen(command, 'w') + +# Add directories to importer object. + for site in self.input_settings: + self.importer.addImportDirectory(self.input_settings[site][0], True, site, self.input_settings[site][1]) + print "Adding import directories - Site: " + site + " dir: "+ str(self.input_settings[site][0]) + self.do_import() + + interval=int(self.intervalEntry.get_text()) + gobject.timeout_add(interval*1000, self.do_import) + #end def GuiAutoImport.startClicked + + def get_vbox(self): + """returns the vbox of this thread""" + return self.mainVBox + #end def get_vbox + + #Create the site line given required info and setup callbacks + #enabling and disabling sites from this interface not possible + #expects a box to layout the line horizontally + def createSiteLine(self, hbox, site, iconpath, hhpath, filter_name, active = True): + label = gtk.Label(site + " auto-import:") + hbox.pack_start(label, False, False, 0) + label.show() + + dirPath=gtk.Entry() + dirPath.set_text(hhpath) + hbox.pack_start(dirPath, False, True, 0) + dirPath.show() + + browseButton=gtk.Button("Browse...") + browseButton.connect("clicked", self.browseClicked, [site] + [dirPath]) + hbox.pack_start(browseButton, False, False, 0) + browseButton.show() + + label = gtk.Label(site + " filter:") + hbox.pack_start(label, False, False, 0) + label.show() + + filter=gtk.Entry() + filter.set_text(filter_name) + hbox.pack_start(filter, False, True, 0) + filter.show() + + def addSites(self, vbox): + for site in self.config.supported_sites.keys(): + pathHBox = gtk.HBox(False, 0) + vbox.pack_start(pathHBox, False, True, 0) + pathHBox.show() + + paths = self.config.get_default_paths(site) + params = self.config.get_site_parameters(site) + self.createSiteLine(pathHBox, site, False, paths['hud-defaultPath'], params['converter'], params['enabled']) + self.input_settings[site] = [paths['hud-defaultPath']] + [params['converter']] + +if __name__== "__main__": + def destroy(*args): # call back for terminating the main eventloop + gtk.main_quit() + + settings = {} + settings['db-host'] = "192.168.1.100" + settings['db-user'] = "mythtv" + settings['db-password'] = "mythtv" + settings['db-databaseName'] = "fpdb" + settings['hud-defaultInterval'] = 10 + settings['hud-defaultPath'] = 'C:/Program Files/PokerStars/HandHistory/nutOmatic' + settings['callFpdbHud'] = True + + i = GuiAutoImport(settings) + main_window = gtk.Window() + main_window.connect("destroy", destroy) + main_window.add(i.mainVBox) + main_window.show() + gtk.main() diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index 7385e9fe..e4f9270e 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -87,16 +87,20 @@ class GuiGraphViewer (threading.Thread): #end of def showClicked def getRingProfitGraph(self, name, site): - self.cursor.execute(self.sql.query['getRingWinningsAllGamesPlayerIdSite'], (name, site)) + #self.cursor.execute(self.sql.query['getRingWinningsAllGamesPlayerIdSite'], (name, site)) + self.cursor.execute(self.sql.query['getRingProfitAllHandsPlayerIdSite'], (name, site)) + # returns (HandId,Winnings,Costs,Profit) winnings = self.db.cursor.fetchall() - profit=range(len(winnings)) - for i in profit: - self.cursor.execute(self.sql.query['getRingProfitFromHandId'], (name, winnings[i][0], site)) - spent = self.db.cursor.fetchone() - profit[i]=(i, winnings[i][1]-spent[0]) + #profit=range(len(winnings)) + #for i in profit: + # self.cursor.execute(self.sql.query['getRingProfitFromHandId'], (name, winnings[i][0], site)) + # spent = self.db.cursor.fetchone() + # profit[i]=(i, winnings[i][1]-spent[0]) + + #y=map(lambda x:float(x[1]), profit) + y=map(lambda x:float(x[3]), winnings) - y=map(lambda x:float(x[1]), profit) line = cumsum(y) return line/100 #end of def getRingProfitGraph diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py old mode 100755 new mode 100644 index f54fa9af..c0244e8d --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -1,166 +1,171 @@ -#!/usr/bin/env python - -"""Hud_main.py - -Main for FreePokerTools HUD. -""" -# 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 - -######################################################################## - -# to do kill window on my seat -# to do adjust for preferred seat -# to do allow window resizing -# to do hud to echo, but ignore non numbers -# to do no hud window for hero -# to do things to add to config.xml -# to do font and size -# to do opacity - -# Standard Library modules -import sys -import os -import thread -import time -import string -import re - -errorfile = open('HUD-error.txt', 'w', 0) -sys.stderr = errorfile - -# pyGTK modules -import pygtk -import gtk -import gobject - -# FreePokerTools modules -import Configuration -import Database -import Tables -import Hud - -# global dict for keeping the huds -hud_dict = {} - -db_connection = 0; -config = 0; - -def destroy(*args): # call back for terminating the main eventloop - gtk.main_quit() - -def create_HUD(new_hand_id, table, db_name, table_name, max, poker_game, db_connection, config, stat_dict): - global hud_dict - def idle_func(): - global hud_dict - gtk.gdk.threads_enter() - try: - hud_dict[table_name] = Hud.Hud(table, max, poker_game, config, db_name) - hud_dict[table_name].create(new_hand_id, config) - hud_dict[table_name].update(new_hand_id, config, stat_dict) - hud_dict[table_name].reposition_windows() - return False - finally: - gtk.gdk.threads_leave() - gobject.idle_add(idle_func) - -def update_HUD(new_hand_id, table_name, config, stat_dict): - global hud_dict - def idle_func(): - gtk.gdk.threads_enter() - try: - hud_dict[table_name].update(new_hand_id, config, stat_dict) - return False - finally: - gtk.gdk.threads_leave() - gobject.idle_add(idle_func) - -def read_stdin(): # This is the thread function - global hud_dict - - db_connection = Database.Database(config, db_name, 'temp') -# tourny_finder = re.compile('(\d+) (\d+)') - - while True: # wait for a new hand number on stdin - new_hand_id = sys.stdin.readline() - new_hand_id = string.rstrip(new_hand_id) - if new_hand_id == "": # blank line means quit - destroy() - -# delete hud_dict entries for any HUD destroyed since last iteration - for h in hud_dict.keys(): - if hud_dict[h].deleted: - del(hud_dict[h]) - -# get basic info about the new hand from the db - (table_name, max, poker_game) = db_connection.get_table_name(new_hand_id) - -# find out if this hand is from a tournament - is_tournament = False -# (t_number, s_number) = (0, 0) -# mat_obj = tourny_finder(table_name) -# if len(mat_obj.groups) == 2: -# is_tournament = True -# (t_number, s_number) = mat_obj.group(1, 2) - - stat_dict = db_connection.get_stats_from_hand(new_hand_id) - -# if a hud for this CASH table exists, just update it - if hud_dict.has_key(table_name): - update_HUD(new_hand_id, table_name, config, stat_dict) -# if a hud for this TOURNAMENT table exists, just update it -# elif hud_dict.has_key(t_number): -# update_HUD(new_hand_id, t_number, config, stat_dict) -# otherwise create a new hud - else: - if is_tournament: - tablewindow = Tables.discover_tournament_table(config, t_number, s_number) - if tablewindow == None: - sys.stderr.write("table name "+table_name+" not found\n") - else: - create_HUD(new_hand_id, tablewindow, db_name, t_number, max, poker_game, db_connection, config, stat_dict) - else: - tablewindow = Tables.discover_table_by_name(config, table_name) - if tablewindow == None: - sys.stderr.write("table name "+table_name+" not found\n") - else: - create_HUD(new_hand_id, tablewindow, db_name, table_name, max, poker_game, db_connection, config, stat_dict) - -if __name__== "__main__": - sys.stderr.write("HUD_main starting\n") - - try: - db_name = sys.argv[1] - except: - db_name = 'fpdb' - sys.stderr.write("Using db name = %s\n" % (db_name)) - - config = Configuration.Config() - - gobject.threads_init() # this is required - thread.start_new_thread(read_stdin, ()) # starts the thread - - main_window = gtk.Window() - main_window.connect("destroy", destroy) - eb = gtk.EventBox() - label = gtk.Label('Closing this window will exit from the HUD.') - eb.add(label) - main_window.add(eb) - main_window.set_title("HUD Main Window") - main_window.show_all() - - gtk.main() - +#!/usr/bin/env python + +"""Hud_main.py + +Main for FreePokerTools HUD. +""" +# 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 + +######################################################################## + +# to do kill window on my seat +# to do adjust for preferred seat +# to do allow window resizing +# to do hud to echo, but ignore non numbers +# to do no hud window for hero +# to do things to add to config.xml +# to do font and size +# to do opacity + +# Standard Library modules +import sys +import os +import thread +import time +import string +import re + +errorfile = open('HUD-error.txt', 'w', 0) +sys.stderr = errorfile + +# pyGTK modules +import pygtk +import gtk +import gobject + +# FreePokerTools modules +import Configuration +import Database +import Tables +import Hud + +# global dict for keeping the huds +hud_dict = {} + +db_connection = 0; +config = 0; + +def destroy(*args): # call back for terminating the main eventloop + gtk.main_quit() + +def create_HUD(new_hand_id, table, db_name, table_name, max, poker_game, db_connection, config, stat_dict): + global hud_dict + def idle_func(): + global hud_dict + gtk.gdk.threads_enter() + try: + hud_dict[table_name] = Hud.Hud(table, max, poker_game, config, db_name) + hud_dict[table_name].create(new_hand_id, config) + hud_dict[table_name].update(new_hand_id, config, stat_dict) + hud_dict[table_name].reposition_windows() + return False + finally: + gtk.gdk.threads_leave() + gobject.idle_add(idle_func) + +def update_HUD(new_hand_id, table_name, config, stat_dict): + global hud_dict + def idle_func(): + gtk.gdk.threads_enter() + try: + hud_dict[table_name].update(new_hand_id, config, stat_dict) + for m in hud_dict[table_name].aux_windows: + m.update_gui(new_hand_id) + return False + finally: + gtk.gdk.threads_leave() + gobject.idle_add(idle_func) + +def read_stdin(): # This is the thread function + global hud_dict + + db_connection = Database.Database(config, db_name, 'temp') + tourny_finder = re.compile('(\d+) (\d+)') + + while True: # wait for a new hand number on stdin + new_hand_id = sys.stdin.readline() + new_hand_id = string.rstrip(new_hand_id) + if new_hand_id == "": # blank line means quit + destroy() + +# delete hud_dict entries for any HUD destroyed since last iteration + for h in hud_dict.keys(): + if hud_dict[h].deleted: + del(hud_dict[h]) + +# get basic info about the new hand from the db + (table_name, max, poker_game) = db_connection.get_table_name(new_hand_id) + +# find out if this hand is from a tournament + is_tournament = False + (tour_number, tab_number) = (0, 0) + mat_obj = tourny_finder.search(table_name) +# if len(mat_obj.groups) == 2: + if mat_obj: + is_tournament = True + (tour_number, tab_number) = mat_obj.group(1, 2) + + stat_dict = db_connection.get_stats_from_hand(new_hand_id) + +# if a hud for this CASH table exists, just update it + if hud_dict.has_key(table_name): +# update the data for the aux_windows + for aw in hud_dict[table_name].aux_windows: + aw.update_data(new_hand_id) + update_HUD(new_hand_id, table_name, config, stat_dict) +# if a hud for this TOURNAMENT table exists, just update it + elif hud_dict.has_key(tour_number): + update_HUD(new_hand_id, tour_number, config, stat_dict) +# otherwise create a new hud + else: + if is_tournament: + tablewindow = Tables.discover_tournament_table(config, tour_number, tab_number) + if tablewindow == None: + sys.stderr.write("tournament %s, table %s not found\n" % (tour_number, tab_number)) + else: + create_HUD(new_hand_id, tablewindow, db_name, tour_number, max, poker_game, db_connection, config, stat_dict) + else: + tablewindow = Tables.discover_table_by_name(config, table_name) + if tablewindow == None: + sys.stderr.write("table name "+table_name+" not found\n") + else: + create_HUD(new_hand_id, tablewindow, db_name, table_name, max, poker_game, db_connection, config, stat_dict) + +if __name__== "__main__": + sys.stderr.write("HUD_main starting\n") + + try: + db_name = sys.argv[1] + except: + db_name = 'fpdb' + sys.stderr.write("Using db name = %s\n" % (db_name)) + + config = Configuration.Config() + + gobject.threads_init() # this is required + thread.start_new_thread(read_stdin, ()) # starts the thread + + main_window = gtk.Window() + main_window.connect("destroy", destroy) + eb = gtk.EventBox() + label = gtk.Label('Closing this window will exit from the HUD.') + eb.add(label) + main_window.add(eb) + main_window.set_title("HUD Main Window") + main_window.show_all() + + gtk.main() diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 2490ad91..1ad38ee0 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -1,562 +1,578 @@ -#!/usr/bin/env python -"""Hud.py - -Create and manage the hud overlays. -""" -# 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 - -######################################################################## -# Standard Library modules -import os -import sys - -# pyGTK modules -import pygtk -import gtk -import pango -import gobject - -# win32 modules -- only imported on windows systems -if os.name == 'nt': - import win32gui - import win32con - import win32api - -# FreePokerTools modules -import Tables # needed for testing only -import Configuration -import Stats -import Mucked -import Database -import HUD_main - -class Hud: - - def __init__(self, table, max, poker_game, config, db_name): - self.table = table - self.config = config - self.poker_game = poker_game - self.max = max - self.db_name = db_name - self.deleted = False - self.stacked = True - self.colors = config.get_default_colors(self.table.site) - - self.stat_windows = {} - self.popup_windows = {} - self.font = pango.FontDescription("Sans 8") - -# Set up a main window for this this instance of the HUD - self.main_window = gtk.Window() -# self.window.set_decorated(0) - self.main_window.set_gravity(gtk.gdk.GRAVITY_STATIC) - self.main_window.set_title(table.name + " FPDBHUD") - self.main_window.connect("destroy", self.kill_hud) - self.main_window.set_decorated(False) - #self.main_window.set_transient_for(parent.get_toplevel()) - - self.ebox = gtk.EventBox() - self.label = gtk.Label("Right click to close HUD for %s\nor Save Stat Positions." % (table.name)) - - self.label.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudbgcolor'])) - self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) - - self.main_window.add(self.ebox) - self.ebox.add(self.label) - self.ebox.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudbgcolor'])) - self.ebox.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) - - self.main_window.move(self.table.x, self.table.y) - -# A popup window for the main window - self.menu = gtk.Menu() - self.item1 = gtk.MenuItem('Kill this HUD') - self.menu.append(self.item1) - self.item1.connect("activate", self.kill_hud) - self.item1.show() - self.item2 = gtk.MenuItem('Save Layout') - self.menu.append(self.item2) - self.item2.connect("activate", self.save_layout) - self.item2.show() - self.item3 = gtk.MenuItem('Reposition Stats') - self.menu.append(self.item3) - self.item3.connect("activate", self.reposition_windows) - self.item3.show() - self.ebox.connect_object("button-press-event", self.on_button_press, self.menu) - - self.main_window.show_all() -# set_keep_above(1) for windows - if os.name == 'nt': - self.topify_window(self.main_window) - else: - self.main_window.parentgdkhandle = gtk.gdk.window_foreign_new(self.table.number) # gets a gdk handle for poker client - self.main_window.gdkhandle = gtk.gdk.window_foreign_new(self.main_window.window.xid) # gets a gdk handle for the hud table window - self.main_window.gdkhandle.set_transient_for(self.main_window.parentgdkhandle) # - - self.main_window.set_destroy_with_parent(True) - - def on_button_press(self, widget, event): - if event.button == 3: - widget.popup(None, None, None, event.button, event.time) - return True - return False - - def kill_hud(self, args): - for k in self.stat_windows.keys(): - self.stat_windows[k].window.destroy() - self.main_window.destroy() - self.deleted = True - - def reposition_windows(self, args): - for w in self.stat_windows: - self.stat_windows[w].window.move(self.stat_windows[w].x, - self.stat_windows[w].y) - def save_layout(self, *args): - new_layout = [] -# todo: have the hud track the poker table's window position regularly, don't forget to update table.x and table.y. - for sw in self.stat_windows: - loc = self.stat_windows[sw].window.get_position() - new_loc = (loc[0] - self.table.x, loc[1] - self.table.y) - new_layout.append(new_loc) -# print new_layout - self.config.edit_layout(self.table.site, self.max, locations = new_layout) - self.config.save() - - def adj_seats(self, hand, config): - adj = range(0, self.max + 1) # default seat adjustments = no adjustment -# does the user have a fav_seat? - try: - if int(config.supported_sites[self.table.site].layout[self.max].fav_seat) > 0: - fav_seat = config.supported_sites[self.table.site].layout[self.max].fav_seat - db_connection = Database.Database(config, self.db_name, 'temp') - actual_seat = db_connection.get_actual_seat(hand, config.supported_sites[self.table.site].screen_name) - db_connection.close_connection() - for i in range(0, self.max + 1): - j = actual_seat + i - if j > self.max: j = j - self.max - adj[j] = fav_seat + i - if adj[j] > self.max: adj[j] = adj[j] - self.max - except: - pass - return adj - - def create(self, hand, config): -# update this hud, to the stats and players as of "hand" -# hand is the hand id of the most recent hand played at this table -# -# this method also manages the creating and destruction of stat -# windows via calls to the Stat_Window class - - adj = self.adj_seats(hand, config) - loc = self.config.get_locations(self.table.site, self.max) - -# create the stat windows - for i in range(1, self.max + 1): - (x, y) = loc[adj[i]] - if self.stat_windows.has_key(i): - self.stat_windows[i].relocate(x, y) - else: - self.stat_windows[i] = Stat_Window(game = config.supported_games[self.poker_game], - parent = self, - table = self.table, - x = x, - y = y, - seat = i, - player_id = 'fake', - font = self.font) - - self.stats = [] - for i in range(0, config.supported_games[self.poker_game].rows + 1): - row_list = [''] * config.supported_games[self.poker_game].cols - self.stats.append(row_list) - for stat in config.supported_games[self.poker_game].stats.keys(): - self.stats[config.supported_games[self.poker_game].stats[stat].row] \ - [config.supported_games[self.poker_game].stats[stat].col] = \ - config.supported_games[self.poker_game].stats[stat].stat_name -# self.mucked_window = gtk.Window() -# self.m = Mucked.Mucked(self.mucked_window, self.db_connection) -# self.mucked_window.show_all() - - def update(self, hand, config, stat_dict): - self.hand = hand # this is the last hand, so it is available later - for s in stat_dict.keys(): - try: - self.stat_windows[stat_dict[s]['seat']].player_id = stat_dict[s]['player_id'] - except: # omg, we have more seats than stat windows .. damn poker sites with incorrect max seating info .. let's force 10 here - self.max = 10 - self.create(hand, config) - self.stat_windows[stat_dict[s]['seat']].player_id = stat_dict[s]['player_id'] - - for r in range(0, config.supported_games[self.poker_game].rows): - for c in range(0, config.supported_games[self.poker_game].cols): - this_stat = config.supported_games[self.poker_game].stats[self.stats[r][c]] - number = Stats.do_stat(stat_dict, player = stat_dict[s]['player_id'], stat = self.stats[r][c]) - statstring = this_stat.hudprefix + str(number[1]) + this_stat.hudsuffix - self.stat_windows[stat_dict[s]['seat']].label[r][c].set_text(statstring) - tip = stat_dict[s]['screen_name'] + "\n" + number[5] + "\n" + \ - number[3] + ", " + number[4] - Stats.do_tip(self.stat_windows[stat_dict[s]['seat']].e_box[r][c], tip) -# self.m.update(hand) - - def topify_window(self, window): - """Set the specified gtk window to stayontop in MS Windows.""" - - def windowEnumerationHandler(hwnd, resultList): - '''Callback for win32gui.EnumWindows() to generate list of window handles.''' - resultList.append((hwnd, win32gui.GetWindowText(hwnd))) - - unique_name = 'unique name for finding this window' - real_name = window.get_title() - window.set_title(unique_name) - tl_windows = [] - win32gui.EnumWindows(windowEnumerationHandler, tl_windows) - - for w in tl_windows: - if w[1] == unique_name: - #win32gui.ShowWindow(w[0], win32con.SW_HIDE) - window.parentgdkhandle = gtk.gdk.window_foreign_new(long(self.table.number)) - self.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0]) - self.main_window.gdkhandle.set_transient_for(window.parentgdkhandle) - #win32gui.ShowWindow(w[0], win32con.SW_SHOW) - - style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE) - #style |= win32con.WS_EX_TOOLWINDOW - #style &= ~win32con.WS_EX_APPWINDOW - style |= win32con.WS_CLIPCHILDREN - win32gui.SetWindowLong(self.table.number, win32con.GWL_EXSTYLE, style) - - - #win32gui.SetWindowPos(w[0], win32con.HWND_TOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE|win32con.SWP_NOSIZE) - -# notify_id = (w[0], -# 0, -# win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP, -# win32con.WM_USER+20, -# 0, -# '') -# win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, notify_id) -# - window.set_title(real_name) - -class Stat_Window: - - def button_press_cb(self, widget, event, *args): -# This handles all callbacks from button presses on the event boxes in -# the stat windows. There is a bit of an ugly kludge to separate single- -# and double-clicks. - if event.button == 1: # left button event - if event.type == gtk.gdk.BUTTON_PRESS: # left button single click - if self.sb_click > 0: return - self.sb_click = gobject.timeout_add(250, self.single_click, widget) - elif event.type == gtk.gdk._2BUTTON_PRESS: # left button double click - if self.sb_click > 0: - gobject.source_remove(self.sb_click) - self.sb_click = 0 - self.double_click(widget, event, *args) - - if event.button == 2: # middle button event - pass -# print "middle button clicked" - - if event.button == 3: # right button event - pass -# print "right button clicked" - - def single_click(self, widget): -# Callback from the timeout in the single-click finding part of the -# button press call back. This needs to be modified to get all the -# arguments from the call. -# print "left button clicked" - self.sb_click = 0 - Popup_window(widget, self) - return False - - def double_click(self, widget, event, *args): - self.toggle_decorated(widget) - - def toggle_decorated(self, widget): - top = widget.get_toplevel() - (x, y) = top.get_position() - - if top.get_decorated(): - top.set_decorated(0) - top.move(x, y) - else: - top.set_decorated(1) - top.move(x, y) - - def relocate(self, x, y): - self.x = x + self.table.x - self.y = y + self.table.y - self.window.move(self.x, self.y) - - def __init__(self, parent, game, table, seat, x, y, player_id, font): - self.parent = parent # Hud object that this stat window belongs to - self.game = game # Configuration object for the curren - self.table = table # Table object where this is going - self.x = x + table.x # table.x and y are the location of the table - self.y = y + table.y # x and y are the location relative to table.x & y - self.player_id = player_id # looks like this isn't used ;) - self.sb_click = 0 # used to figure out button clicks - - self.window = gtk.Window() - self.window.set_decorated(0) - self.window.set_gravity(gtk.gdk.GRAVITY_STATIC) - - self.window.set_title("%s" % seat) - self.window.set_property("skip-taskbar-hint", True) - self.window.set_transient_for(parent.main_window) - - self.grid = gtk.Table(rows = self.game.rows, columns = self.game.cols, homogeneous = False) - self.window.add(self.grid) - - self.e_box = [] - self.frame = [] - self.label = [] - for r in range(self.game.rows): - self.e_box.append([]) - self.label.append([]) - for c in range(self.game.cols): - self.e_box[r].append( gtk.EventBox() ) - - self.e_box[r][c].modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(parent.colors['hudbgcolor'])) - self.e_box[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(parent.colors['hudfgcolor'])) - - Stats.do_tip(self.e_box[r][c], 'farts') - self.grid.attach(self.e_box[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0) - self.label[r].append( gtk.Label('xxx') ) - - self.label[r][c].modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(parent.colors['hudbgcolor'])) - self.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(parent.colors['hudfgcolor'])) - - self.e_box[r][c].add(self.label[r][c]) - self.e_box[r][c].connect("button_press_event", self.button_press_cb) -# font = pango.FontDescription("Sans 8") - self.label[r][c].modify_font(font) - - if not os.name == 'nt': # seems to be a bug in opacity on windows - self.window.set_opacity(parent.colors['hudopacity']) - self.window.realize - self.window.move(self.x, self.y) - self.window.show_all() -# set_keep_above(1) for windows - if os.name == 'nt': self.topify_window(self.window) - - def topify_window(self, window): - """Set the specified gtk window to stayontop in MS Windows.""" - - def windowEnumerationHandler(hwnd, resultList): - '''Callback for win32gui.EnumWindows() to generate list of window handles.''' - resultList.append((hwnd, win32gui.GetWindowText(hwnd))) - - unique_name = 'unique name for finding this window' - real_name = window.get_title() - window.set_title(unique_name) - tl_windows = [] - win32gui.EnumWindows(windowEnumerationHandler, tl_windows) - - for w in tl_windows: - if w[1] == unique_name: - - #win32gui.SetWindowPos(w[0], win32con.HWND_TOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE|win32con.SWP_NOSIZE) - -# style = win32gui.GetWindowLong(w[0], win32con.GWL_EXSTYLE) -# style |= win32con.WS_EX_TOOLWINDOW -# style &= ~win32con.WS_EX_APPWINDOW -# win32gui.SetWindowLong(w[0], win32con.GWL_EXSTYLE, style) - win32gui.ShowWindow(w[0], win32con.SW_SHOW) - window.set_title(real_name) - -def destroy(*args): # call back for terminating the main eventloop - gtk.main_quit() - -class Popup_window: - def __init__(self, parent, stat_window): - self.sb_click = 0 - -# create the popup window - self.window = gtk.Window() - self.window.set_decorated(0) - self.window.set_gravity(gtk.gdk.GRAVITY_STATIC) -# self.window.set_keep_above(1) - self.window.set_title("popup") - self.window.set_property("skip-taskbar-hint", True) - self.window.set_transient_for(parent.get_toplevel()) - - self.window.set_position(gtk.WIN_POS_CENTER_ON_PARENT) - - self.ebox = gtk.EventBox() - self.ebox.connect("button_press_event", self.button_press_cb) - self.lab = gtk.Label("stuff\nstuff\nstuff") - -# need an event box so we can respond to clicks - self.window.add(self.ebox) - self.ebox.add(self.lab) - - self.ebox.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(stat_window.parent.colors['hudbgcolor'])) - self.ebox.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(stat_window.parent.colors['hudfgcolor'])) - self.window.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(stat_window.parent.colors['hudbgcolor'])) - self.window.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(stat_window.parent.colors['hudfgcolor'])) - self.lab.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(stat_window.parent.colors['hudbgcolor'])) - self.lab.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(stat_window.parent.colors['hudfgcolor'])) - - self.window.realize - -# figure out the row, col address of the click that activated the popup - row = 0 - col = 0 - for r in range(0, stat_window.game.rows): - for c in range(0, stat_window.game.cols): - if stat_window.e_box[r][c] == parent: - row = r - col = c - break - -# figure out what popup format we're using - popup_format = "default" - for stat in stat_window.game.stats.keys(): - if stat_window.game.stats[stat].row == row and stat_window.game.stats[stat].col == col: - popup_format = stat_window.game.stats[stat].popup - break - -# get the list of stats to be presented from the config - stat_list = [] - for w in stat_window.parent.config.popup_windows.keys(): - if w == popup_format: - stat_list = stat_window.parent.config.popup_windows[w].pu_stats - break - -# get a database connection - db_connection = Database.Database(stat_window.parent.config, stat_window.parent.db_name, 'temp') - -# calculate the stat_dict and then create the text for the pu -# stat_dict = db_connection.get_stats_from_hand(stat_window.parent.hand, stat_window.player_id) - stat_dict = db_connection.get_stats_from_hand(stat_window.parent.hand) - db_connection.close_connection() - - pu_text = "" - for s in stat_list: - number = Stats.do_stat(stat_dict, player = int(stat_window.player_id), stat = s) - pu_text += number[3] + "\n" - - self.lab.set_text(pu_text) - self.window.show_all() - - self.window.set_transient_for(stat_window.main_window) - -# set_keep_above(1) for windows - if os.name == 'nt': self.topify_window(self.window) - - def button_press_cb(self, widget, event, *args): -# This handles all callbacks from button presses on the event boxes in -# the popup windows. There is a bit of an ugly kludge to separate single- -# and double-clicks. This is the same code as in the Stat_window class - if event.button == 1: # left button event - if event.type == gtk.gdk.BUTTON_PRESS: # left button single click - if self.sb_click > 0: return - self.sb_click = gobject.timeout_add(250, self.single_click, widget) - elif event.type == gtk.gdk._2BUTTON_PRESS: # left button double click - if self.sb_click > 0: - gobject.source_remove(self.sb_click) - self.sb_click = 0 - self.double_click(widget, event, *args) - - if event.button == 2: # middle button event - pass -# print "middle button clicked" - - if event.button == 3: # right button event - pass -# print "right button clicked" - - def single_click(self, widget): -# Callback from the timeout in the single-click finding part of the -# button press call back. This needs to be modified to get all the -# arguments from the call. - self.sb_click = 0 - self.window.destroy() - return False - - def double_click(self, widget, event, *args): - self.toggle_decorated(widget) - - def toggle_decorated(self, widget): - top = widget.get_toplevel() - (x, y) = top.get_position() - - if top.get_decorated(): - top.set_decorated(0) - top.move(x, y) - else: - top.set_decorated(1) - top.move(x, y) - - def topify_window(self, window): - """Set the specified gtk window to stayontop in MS Windows.""" - - def windowEnumerationHandler(hwnd, resultList): - '''Callback for win32gui.EnumWindows() to generate list of window handles.''' - resultList.append((hwnd, win32gui.GetWindowText(hwnd))) - - unique_name = 'unique name for finding this window' - real_name = window.get_title() - window.set_title(unique_name) - tl_windows = [] - win32gui.EnumWindows(windowEnumerationHandler, tl_windows) - - for w in tl_windows: - if w[1] == unique_name: -# win32gui.ShowWindow(w[0], win32con.SW_HIDE) -# style = win32gui.GetWindowLong(w[0], win32con.GWL_EXSTYLE) -# style |= win32con.WS_EX_TOOLWINDOW -# style &= ~win32con.WS_EX_APPWINDOW -# win32gui.SetWindowLong(w[0], win32con.GWL_EXSTYLE, style) -# win32gui.ShowWindow(w[0], win32con.SW_SHOW) - win32gui.SetWindowPos(w[0], win32con.HWND_TOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE|win32con.SWP_NOSIZE) - -# notify_id = (w[0], -# 0, -# win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP, -# win32con.WM_USER+20, -# 0, -# '') -# win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, notify_id) -# - window.set_title(real_name) - -if __name__== "__main__": - main_window = gtk.Window() - main_window.connect("destroy", destroy) - label = gtk.Label('Fake main window, blah blah, blah\nblah, blah') - main_window.add(label) - main_window.show_all() - - c = Configuration.Config() - #tables = Tables.discover(c) - t = Tables.discover_table_by_name(c, "Chelsea") - if t is None: - print "Table not found." - db = Database.Database(c, 'fpdb', 'holdem') - -# for t in tables: - win = Hud(t, 10, 'holdem', c, db) - win.create(1, c) -# t.get_details() - win.update(8300, db, c) - - gtk.main() +#!/usr/bin/env python +"""Hud.py + +Create and manage the hud overlays. +""" +# 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 + +######################################################################## +# Standard Library modules +import os +import sys + +# pyGTK modules +import pygtk +import gtk +import pango +import gobject + +# win32 modules -- only imported on windows systems +if os.name == 'nt': + import win32gui + import win32con + import win32api + +# FreePokerTools modules +import Tables # needed for testing only +import Configuration +import Stats +import Mucked +import Database +import HUD_main + +class Hud: + + def __init__(self, table, max, poker_game, config, db_name): + self.table = table + self.config = config + self.poker_game = poker_game + self.max = max + self.db_name = db_name + self.deleted = False + self.stacked = True + self.colors = config.get_default_colors(self.table.site) + + self.stat_windows = {} + self.popup_windows = {} + self.aux_windows = [] + self.font = pango.FontDescription("Sans 8") + +# Set up a main window for this this instance of the HUD + self.main_window = gtk.Window() +# self.window.set_decorated(0) + self.main_window.set_gravity(gtk.gdk.GRAVITY_STATIC) + self.main_window.set_title(table.name + " FPDBHUD") + self.main_window.connect("destroy", self.kill_hud) + self.main_window.set_decorated(False) + self.main_window.set_opacity(self.colors["hudopacity"]) + #self.main_window.set_transient_for(parent.get_toplevel()) + + self.ebox = gtk.EventBox() +# self.label = gtk.Label("Right click to close HUD for %s\nor Save Stat Positions." % (table.name)) + self.label = gtk.Label("FPDB Menu (Right Click)\nLeft-drag to move") + + self.label.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudbgcolor'])) + self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) + + self.main_window.add(self.ebox) + self.ebox.add(self.label) + self.ebox.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudbgcolor'])) + self.ebox.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) + + self.main_window.move(self.table.x, self.table.y) + +# A popup window for the main window + self.menu = gtk.Menu() + self.item1 = gtk.MenuItem('Kill this HUD') + self.menu.append(self.item1) + self.item1.connect("activate", self.kill_hud) + self.item1.show() + self.item2 = gtk.MenuItem('Save Layout') + self.menu.append(self.item2) + self.item2.connect("activate", self.save_layout) + self.item2.show() + self.item3 = gtk.MenuItem('Reposition Stats') + self.menu.append(self.item3) + self.item3.connect("activate", self.reposition_windows) + self.item3.show() + self.ebox.connect_object("button-press-event", self.on_button_press, self.menu) + + self.main_window.show_all() +# set_keep_above(1) for windows + if os.name == 'nt': + self.topify_window(self.main_window) + else: + self.main_window.parentgdkhandle = gtk.gdk.window_foreign_new(self.table.number) # gets a gdk handle for poker client + self.main_window.gdkhandle = gtk.gdk.window_foreign_new(self.main_window.window.xid) # gets a gdk handle for the hud table window + self.main_window.gdkhandle.set_transient_for(self.main_window.parentgdkhandle) # + + self.main_window.set_destroy_with_parent(True) + + def on_button_press(self, widget, event): + if event.button == 1: + self.main_window.begin_move_drag(event.button, int(event.x_root), int(event.y_root), event.time) + return True + if event.button == 3: + widget.popup(None, None, None, event.button, event.time) + return True + return False + + def kill_hud(self, *args): + for k in self.stat_windows.keys(): + self.stat_windows[k].window.destroy() + self.main_window.destroy() + self.deleted = True + + def reposition_windows(self, *args): + for w in self.stat_windows: + self.stat_windows[w].window.move(self.stat_windows[w].x, + self.stat_windows[w].y) + def save_layout(self, *args): + new_layout = [(0, 0)] * self.max +# todo: have the hud track the poker table's window position regularly, don't forget to update table.x and table.y. + for sw in self.stat_windows: + loc = self.stat_windows[sw].window.get_position() + new_loc = (loc[0] - self.table.x, loc[1] - self.table.y) + new_layout[self.stat_windows[sw].adj - 1] = new_loc + self.config.edit_layout(self.table.site, self.max, locations = new_layout) + self.config.save() + + def adj_seats(self, hand, config): + adj = range(0, self.max + 1) # default seat adjustments = no adjustment +# does the user have a fav_seat? + try: + if int(config.supported_sites[self.table.site].layout[self.max].fav_seat) > 0: + fav_seat = config.supported_sites[self.table.site].layout[self.max].fav_seat + db_connection = Database.Database(config, self.db_name, 'temp') + actual_seat = db_connection.get_actual_seat(hand, config.supported_sites[self.table.site].screen_name) + db_connection.close_connection() + for i in range(0, self.max + 1): + j = actual_seat + i + if j > self.max: j = j - self.max + adj[j] = fav_seat + i + if adj[j] > self.max: adj[j] = adj[j] - self.max + except: + pass + return adj + + def create(self, hand, config): +# update this hud, to the stats and players as of "hand" +# hand is the hand id of the most recent hand played at this table +# +# this method also manages the creating and destruction of stat +# windows via calls to the Stat_Window class + + adj = self.adj_seats(hand, config) + loc = self.config.get_locations(self.table.site, self.max) + +# create the stat windows + for i in range(1, self.max + 1): + (x, y) = loc[adj[i]] + if self.stat_windows.has_key(i): + self.stat_windows[i].relocate(x, y) + else: + self.stat_windows[i] = Stat_Window(game = config.supported_games[self.poker_game], + parent = self, + table = self.table, + x = x, + y = y, + seat = i, + adj = adj[i], + player_id = 'fake', + font = self.font) + + self.stats = [] + for i in range(0, config.supported_games[self.poker_game].rows + 1): + row_list = [''] * config.supported_games[self.poker_game].cols + self.stats.append(row_list) + for stat in config.supported_games[self.poker_game].stats.keys(): + self.stats[config.supported_games[self.poker_game].stats[stat].row] \ + [config.supported_games[self.poker_game].stats[stat].col] = \ + config.supported_games[self.poker_game].stats[stat].stat_name + + game_params = config.get_game_parameters(self.poker_game) + if not game_params['aux'] == "": + aux_params = config.get_aux_parameters(game_params['aux']) + self.aux_windows.append(eval("%s.%s(gtk.Window(), config, 'fpdb')" % (aux_params['module'], aux_params['class']))) + + def update(self, hand, config, stat_dict): + self.hand = hand # this is the last hand, so it is available later + for s in stat_dict.keys(): + try: + self.stat_windows[stat_dict[s]['seat']].player_id = stat_dict[s]['player_id'] + except: # omg, we have more seats than stat windows .. damn poker sites with incorrect max seating info .. let's force 10 here + self.max = 10 + self.create(hand, config) + self.stat_windows[stat_dict[s]['seat']].player_id = stat_dict[s]['player_id'] + + for r in range(0, config.supported_games[self.poker_game].rows): + for c in range(0, config.supported_games[self.poker_game].cols): + this_stat = config.supported_games[self.poker_game].stats[self.stats[r][c]] + number = Stats.do_stat(stat_dict, player = stat_dict[s]['player_id'], stat = self.stats[r][c]) + statstring = this_stat.hudprefix + str(number[1]) + this_stat.hudsuffix + self.stat_windows[stat_dict[s]['seat']].label[r][c].set_text(statstring) + tip = stat_dict[s]['screen_name'] + "\n" + number[5] + "\n" + \ + number[3] + ", " + number[4] + Stats.do_tip(self.stat_windows[stat_dict[s]['seat']].e_box[r][c], tip) +# for m in self.aux_windows: +# m.update_data(hand) +# m.update_gui(hand) + + def topify_window(self, window): + """Set the specified gtk window to stayontop in MS Windows.""" + + def windowEnumerationHandler(hwnd, resultList): + '''Callback for win32gui.EnumWindows() to generate list of window handles.''' + resultList.append((hwnd, win32gui.GetWindowText(hwnd))) + + unique_name = 'unique name for finding this window' + real_name = window.get_title() + window.set_title(unique_name) + tl_windows = [] + win32gui.EnumWindows(windowEnumerationHandler, tl_windows) + + for w in tl_windows: + if w[1] == unique_name: + #win32gui.ShowWindow(w[0], win32con.SW_HIDE) + window.parentgdkhandle = gtk.gdk.window_foreign_new(long(self.table.number)) + self.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0]) + self.main_window.gdkhandle.set_transient_for(window.parentgdkhandle) + #win32gui.ShowWindow(w[0], win32con.SW_SHOW) + + style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE) + #style |= win32con.WS_EX_TOOLWINDOW + #style &= ~win32con.WS_EX_APPWINDOW + style |= win32con.WS_CLIPCHILDREN + win32gui.SetWindowLong(self.table.number, win32con.GWL_EXSTYLE, style) + + + #win32gui.SetWindowPos(w[0], win32con.HWND_TOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE|win32con.SWP_NOSIZE) + +# notify_id = (w[0], +# 0, +# win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP, +# win32con.WM_USER+20, +# 0, +# '') +# win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, notify_id) +# + window.set_title(real_name) + +class Stat_Window: + + def button_press_cb(self, widget, event, *args): +# This handles all callbacks from button presses on the event boxes in +# the stat windows. There is a bit of an ugly kludge to separate single- +# and double-clicks. + + if event.button == 3: # right button event + if event.type == gtk.gdk.BUTTON_PRESS: # left button single click + if self.sb_click > 0: return + self.sb_click = gobject.timeout_add(250, self.single_click, widget) + elif event.type == gtk.gdk._2BUTTON_PRESS: # left button double click + if self.sb_click > 0: + gobject.source_remove(self.sb_click) + self.sb_click = 0 + self.double_click(widget, event, *args) + + if event.button == 2: # middle button event +# print "middle button clicked" + pass + + if event.button == 1: # left button event + if event.state & gtk.gdk.SHIFT_MASK: + self.window.begin_resize_drag(gtk.gdk.WINDOW_EDGE_SOUTH_EAST, event.button, int(event.x_root), int(event.y_root), event.time) + else: + self.window.begin_move_drag(event.button, int(event.x_root), int(event.y_root), event.time) + + def single_click(self, widget): +# Callback from the timeout in the single-click finding part of the +# button press call back. This needs to be modified to get all the +# arguments from the call. +# print "left button clicked" + self.sb_click = 0 + Popup_window(widget, self) + return False + + def double_click(self, widget, event, *args): + self.toggle_decorated(widget) + + def toggle_decorated(self, widget): + top = widget.get_toplevel() + (x, y) = top.get_position() + + if top.get_decorated(): + top.set_decorated(0) + top.move(x, y) + else: + top.set_decorated(1) + top.move(x, y) + + def relocate(self, x, y): + self.x = x + self.table.x + self.y = y + self.table.y + self.window.move(self.x, self.y) + + def __init__(self, parent, game, table, seat, adj, x, y, player_id, font): + self.parent = parent # Hud object that this stat window belongs to + self.game = game # Configuration object for the curren + self.table = table # Table object where this is going + self.seat = seat # seat number of his player + self.adj = adj # the adjusted seat number for this player + self.x = x + table.x # table.x and y are the location of the table + self.y = y + table.y # x and y are the location relative to table.x & y + self.player_id = player_id # looks like this isn't used ;) + self.sb_click = 0 # used to figure out button clicks + + self.window = gtk.Window() + self.window.set_decorated(0) + self.window.set_gravity(gtk.gdk.GRAVITY_STATIC) + + self.window.set_title("%s" % seat) + self.window.set_property("skip-taskbar-hint", True) + self.window.set_transient_for(parent.main_window) + + self.grid = gtk.Table(rows = self.game.rows, columns = self.game.cols, homogeneous = False) + self.window.add(self.grid) + + self.e_box = [] + self.frame = [] + self.label = [] + for r in range(self.game.rows): + self.e_box.append([]) + self.label.append([]) + for c in range(self.game.cols): + self.e_box[r].append( gtk.EventBox() ) + + self.e_box[r][c].modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(parent.colors['hudbgcolor'])) + self.e_box[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(parent.colors['hudfgcolor'])) + + Stats.do_tip(self.e_box[r][c], 'farts') + self.grid.attach(self.e_box[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0) + self.label[r].append( gtk.Label('xxx') ) + + self.label[r][c].modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(parent.colors['hudbgcolor'])) + self.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(parent.colors['hudfgcolor'])) + + self.e_box[r][c].add(self.label[r][c]) + self.e_box[r][c].connect("button_press_event", self.button_press_cb) +# font = pango.FontDescription("Sans 8") + self.label[r][c].modify_font(font) + +# if not os.name == 'nt': # seems to be a bug in opacity on windows + self.window.set_opacity(parent.colors['hudopacity']) + + self.window.realize + self.window.move(self.x, self.y) + self.window.show_all() +# set_keep_above(1) for windows + if os.name == 'nt': self.topify_window(self.window) + + def topify_window(self, window): + """Set the specified gtk window to stayontop in MS Windows.""" + + def windowEnumerationHandler(hwnd, resultList): + '''Callback for win32gui.EnumWindows() to generate list of window handles.''' + resultList.append((hwnd, win32gui.GetWindowText(hwnd))) + + unique_name = 'unique name for finding this window' + real_name = window.get_title() + window.set_title(unique_name) + tl_windows = [] + win32gui.EnumWindows(windowEnumerationHandler, tl_windows) + + for w in tl_windows: + if w[1] == unique_name: + + #win32gui.SetWindowPos(w[0], win32con.HWND_TOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE|win32con.SWP_NOSIZE) + +# style = win32gui.GetWindowLong(w[0], win32con.GWL_EXSTYLE) +# style |= win32con.WS_EX_TOOLWINDOW +# style &= ~win32con.WS_EX_APPWINDOW +# win32gui.SetWindowLong(w[0], win32con.GWL_EXSTYLE, style) + win32gui.ShowWindow(w[0], win32con.SW_SHOW) + window.set_title(real_name) + +def destroy(*args): # call back for terminating the main eventloop + gtk.main_quit() + +class Popup_window: + def __init__(self, parent, stat_window): + self.sb_click = 0 + +# create the popup window + self.window = gtk.Window() + self.window.set_decorated(0) + self.window.set_gravity(gtk.gdk.GRAVITY_STATIC) +# self.window.set_keep_above(1) + self.window.set_title("popup") + self.window.set_property("skip-taskbar-hint", True) + self.window.set_transient_for(parent.get_toplevel()) + + self.window.set_position(gtk.WIN_POS_CENTER_ON_PARENT) + + self.ebox = gtk.EventBox() + self.ebox.connect("button_press_event", self.button_press_cb) + self.lab = gtk.Label("stuff\nstuff\nstuff") + +# need an event box so we can respond to clicks + self.window.add(self.ebox) + self.ebox.add(self.lab) + + self.ebox.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(stat_window.parent.colors['hudbgcolor'])) + self.ebox.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(stat_window.parent.colors['hudfgcolor'])) + self.window.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(stat_window.parent.colors['hudbgcolor'])) + self.window.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(stat_window.parent.colors['hudfgcolor'])) + self.lab.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(stat_window.parent.colors['hudbgcolor'])) + self.lab.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(stat_window.parent.colors['hudfgcolor'])) + + self.window.realize + +# figure out the row, col address of the click that activated the popup + row = 0 + col = 0 + for r in range(0, stat_window.game.rows): + for c in range(0, stat_window.game.cols): + if stat_window.e_box[r][c] == parent: + row = r + col = c + break + +# figure out what popup format we're using + popup_format = "default" + for stat in stat_window.game.stats.keys(): + if stat_window.game.stats[stat].row == row and stat_window.game.stats[stat].col == col: + popup_format = stat_window.game.stats[stat].popup + break + +# get the list of stats to be presented from the config + stat_list = [] + for w in stat_window.parent.config.popup_windows.keys(): + if w == popup_format: + stat_list = stat_window.parent.config.popup_windows[w].pu_stats + break + +# get a database connection + db_connection = Database.Database(stat_window.parent.config, stat_window.parent.db_name, 'temp') + +# calculate the stat_dict and then create the text for the pu +# stat_dict = db_connection.get_stats_from_hand(stat_window.parent.hand, stat_window.player_id) + stat_dict = db_connection.get_stats_from_hand(stat_window.parent.hand) + db_connection.close_connection() + + pu_text = "" + for s in stat_list: + number = Stats.do_stat(stat_dict, player = int(stat_window.player_id), stat = s) + pu_text += number[3] + "\n" + + self.lab.set_text(pu_text) + self.window.show_all() + + self.window.set_transient_for(stat_window.window) + +# set_keep_above(1) for windows + if os.name == 'nt': self.topify_window(self.window) + + def button_press_cb(self, widget, event, *args): +# This handles all callbacks from button presses on the event boxes in +# the popup windows. There is a bit of an ugly kludge to separate single- +# and double-clicks. This is the same code as in the Stat_window class + if event.button == 1: # left button event + if event.type == gtk.gdk.BUTTON_PRESS: # left button single click + if self.sb_click > 0: return + self.sb_click = gobject.timeout_add(250, self.single_click, widget) + elif event.type == gtk.gdk._2BUTTON_PRESS: # left button double click + if self.sb_click > 0: + gobject.source_remove(self.sb_click) + self.sb_click = 0 + self.double_click(widget, event, *args) + + if event.button == 2: # middle button event + pass +# print "middle button clicked" + + if event.button == 3: # right button event + pass +# print "right button clicked" + + def single_click(self, widget): +# Callback from the timeout in the single-click finding part of the +# button press call back. This needs to be modified to get all the +# arguments from the call. + self.sb_click = 0 + self.window.destroy() + return False + + def double_click(self, widget, event, *args): + self.toggle_decorated(widget) + + def toggle_decorated(self, widget): + top = widget.get_toplevel() + (x, y) = top.get_position() + + if top.get_decorated(): + top.set_decorated(0) + top.move(x, y) + else: + top.set_decorated(1) + top.move(x, y) + + def topify_window(self, window): + """Set the specified gtk window to stayontop in MS Windows.""" + + def windowEnumerationHandler(hwnd, resultList): + '''Callback for win32gui.EnumWindows() to generate list of window handles.''' + resultList.append((hwnd, win32gui.GetWindowText(hwnd))) + + unique_name = 'unique name for finding this window' + real_name = window.get_title() + window.set_title(unique_name) + tl_windows = [] + win32gui.EnumWindows(windowEnumerationHandler, tl_windows) + + for w in tl_windows: + if w[1] == unique_name: +# win32gui.ShowWindow(w[0], win32con.SW_HIDE) +# style = win32gui.GetWindowLong(w[0], win32con.GWL_EXSTYLE) +# style |= win32con.WS_EX_TOOLWINDOW +# style &= ~win32con.WS_EX_APPWINDOW +# win32gui.SetWindowLong(w[0], win32con.GWL_EXSTYLE, style) +# win32gui.ShowWindow(w[0], win32con.SW_SHOW) + win32gui.SetWindowPos(w[0], win32con.HWND_TOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE|win32con.SWP_NOSIZE) + +# notify_id = (w[0], +# 0, +# win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP, +# win32con.WM_USER+20, +# 0, +# '') +# win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, notify_id) +# + window.set_title(real_name) + +if __name__== "__main__": + main_window = gtk.Window() + main_window.connect("destroy", destroy) + label = gtk.Label('Fake main window, blah blah, blah\nblah, blah') + main_window.add(label) + main_window.show_all() + + c = Configuration.Config() + #tables = Tables.discover(c) + t = Tables.discover_table_by_name(c, "Chelsea") + if t is None: + print "Table not found." + db = Database.Database(c, 'fpdb', 'holdem') + +# for t in tables: + win = Hud(t, 10, 'holdem', c, db) + win.create(1, c) +# t.get_details() + win.update(8300, db, c) + + gtk.main() diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 9bc125f6..7ff0b18c 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -229,14 +229,21 @@ class Sql: sum(street3CheckCallRaiseDone) AS ccr_3, sum(street4CheckCallRaiseChance) AS ccr_opp_4, sum(street4CheckCallRaiseDone) AS ccr_4 - FROM HudCache, Hands - WHERE HudCache.PlayerId in - (SELECT PlayerId FROM HandsPlayers - WHERE handId = %s) - AND Hands.id = %s - AND Hands.gametypeId = HudCache.gametypeId + FROM Hands + INNER JOIN HandsPlayers ON (HandsPlayers.handId = %s) + INNER JOIN HudCache ON ( HudCache.PlayerId = HandsPlayers.PlayerId+0 + AND HudCache.gametypeId+0 = Hands.gametypeId+0) + WHERE Hands.id = %s GROUP BY HudCache.PlayerId """ + +# FROM HudCache, Hands +# WHERE HudCache.PlayerId in +# (SELECT PlayerId FROM HandsPlayers +# WHERE handId = %s) +# AND Hands.id = %s +# AND Hands.gametypeId = HudCache.gametypeId + # AND PlayerId LIKE %s # HudCache.gametypeId AS gametypeId, # activeSeats AS n_active, diff --git a/pyfpdb/Stats.py b/pyfpdb/Stats.py index 7bb9a8c5..50a502e3 100644 --- a/pyfpdb/Stats.py +++ b/pyfpdb/Stats.py @@ -71,6 +71,7 @@ def do_stat(stat_dict, player = 24, stat = 'vpip'): # functions that return individual stats def playername(stat_dict, player): + """ Player Name.""" return (stat_dict[player]['screen_name'], stat_dict[player]['screen_name'], stat_dict[player]['screen_name'], @@ -98,6 +99,26 @@ def vpip(stat_dict, player): 'wtsd' ) +def vpip_0(stat_dict, player): + """ Voluntarily put $ in the pot (no decimals).""" + stat = 0.0 + try: + stat = float(stat_dict[player]['vpip'])/float(stat_dict[player]['n']) + return (stat, + '%2.0f' % (100*stat) + '%', + 'v=%2.0f' % (100*stat) + '%', + 'vpip=%2.0f' % (100*stat) + '%', + '(%d/%d)' % (stat_dict[player]['vpip'], stat_dict[player]['n']), + 'vpip' + ) + except: return (stat, + '%2.0f' % (0) + '%', + 'w=%2.0f' % (0) + '%', + 'wtsd=%2.0f' % (0) + '%', + '(%d/%d)' % (0, 0), + 'wtsd' + ) + def pfr(stat_dict, player): """ Preflop (3rd street) raise.""" stat = 0.0 @@ -119,6 +140,27 @@ def pfr(stat_dict, player): 'pfr' ) +def pfr_0(stat_dict, player): + """ Preflop (3rd street) raise (no decimals).""" + stat = 0.0 + try: + stat = float(stat_dict[player]['pfr'])/float(stat_dict[player]['n']) + return (stat, + '%2.0f' % (100*stat) + '%', + 'p=%2.0f' % (100*stat) + '%', + 'pfr=%2.0f' % (100*stat) + '%', + '(%d/%d)' % (stat_dict[player]['pfr'], stat_dict[player]['n']), + 'pfr' + ) + except: + return (stat, + '%2.0f' % (0) + '%', + 'p=%2.0f' % (0) + '%', + 'pfr=%2.0f' % (0) + '%', + '(%d/%d)' % (0, 0), + 'pfr' + ) + def wtsd(stat_dict, player): """ Went to SD when saw flop/4th.""" stat = 0.0 @@ -149,7 +191,7 @@ def wmsd(stat_dict, player): '%3.1f' % (100*stat) + '%', 'w=%3.1f' % (100*stat) + '%', 'wmsd=%3.1f' % (100*stat) + '%', - '(%f5.0/%d)' % (stat_dict[player]['wmsd'], stat_dict[player]['sd']), + '(%5.1f/%d)' % (float(stat_dict[player]['wmsd']), stat_dict[player]['sd']), '% won money at showdown' ) except: @@ -414,6 +456,61 @@ def a_freq_4(stat_dict, player): '(%d/%d)' % (0, 0), 'Aggression Freq flop/4th' ) + +def a_freq_123(stat_dict, player): + """ Post-Flop aggression frequency.""" + stat = 0.0 + try: + stat = float( stat_dict[player]['aggr_1'] + stat_dict[player]['aggr_2'] + stat_dict[player]['aggr_3'] + ) / float( stat_dict[player]['saw_1'] + stat_dict[player]['saw_2'] + stat_dict[player]['saw_3']); + return (stat, + '%3.1f' % (100*stat) + '%', + 'afq=%3.1f' % (100*stat) + '%', + 'postf_aggfq=%3.1f' % (100*stat) + '%', + '(%d/%d)' % ( stat_dict[player]['aggr_1'] + + stat_dict[player]['aggr_2'] + + stat_dict[player]['aggr_3'] + , stat_dict[player]['saw_1'] + + stat_dict[player]['saw_2'] + + stat_dict[player]['saw_3'] + ), + 'Post-Flop Aggression Freq' + ) + except: + return (stat, + '%2.0f' % (0) + '%', + 'a3=%2.0f' % (0) + '%', + 'a_fq_3=%2.0f' % (0) + '%', + '(%d/%d)' % (0, 0), + 'Post-Flop Aggression Freq' + ) + +def a_freq_123_0(stat_dict, player): + """ Post-Flop aggression frequency (no decimals).""" + stat = 0.0 + try: + stat = float( stat_dict[player]['aggr_1'] + stat_dict[player]['aggr_2'] + stat_dict[player]['aggr_3']) / float( stat_dict[player]['saw_1'] + stat_dict[player]['saw_2'] + stat_dict[player]['saw_3']); + return (stat, + '%2.0f' % (100*stat) + '%', + 'afq=%2.0f' % (100*stat) + '%', + 'postf_aggfq=%2.0f' % (100*stat) + '%', + '(%d/%d)' % ( stat_dict[player]['aggr_1'] + + stat_dict[player]['aggr_2'] + + stat_dict[player]['aggr_3'] + , stat_dict[player]['saw_1'] + + stat_dict[player]['saw_2'] + + stat_dict[player]['saw_3'] + ), + 'Post-Flop Aggression Freq' + ) + except: + return (stat, + '%2.0f' % (0) + '%', + 'a3=%2.0f' % (0) + '%', + 'a_fq_3=%2.0f' % (0) + '%', + '(%d/%d)' % (0, 0), + 'Post-Flop Aggression Freq' + ) def cb_1(stat_dict, player): """ Flop continuation bet.""" @@ -591,7 +688,9 @@ if __name__== "__main__": for player in stat_dict.keys(): print "player = ", player, do_stat(stat_dict, player = player, stat = 'vpip') + print "player = ", player, do_stat(stat_dict, player = player, stat = 'vpip_0') print "player = ", player, do_stat(stat_dict, player = player, stat = 'pfr') + print "player = ", player, do_stat(stat_dict, player = player, stat = 'pfr_0') print "player = ", player, do_stat(stat_dict, player = player, stat = 'wtsd') print "player = ", player, do_stat(stat_dict, player = player, stat = 'saw_f') print "player = ", player, do_stat(stat_dict, player = player, stat = 'n') @@ -606,6 +705,8 @@ if __name__== "__main__": print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_2') print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_3') print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_4') + print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_123') + print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_123_0') print "player = ", player, do_stat(stat_dict, player = player, stat = 'cb_1') print "player = ", player, do_stat(stat_dict, player = player, stat = 'cb_2') print "player = ", player, do_stat(stat_dict, player = player, stat = 'cb_3') @@ -613,7 +714,8 @@ if __name__== "__main__": print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_1') print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_2') print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_3') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_4') + print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_4') + print "\n" print "\n\nLegal stats:" for attr in dir(): @@ -621,8 +723,8 @@ if __name__== "__main__": if attr in ("Configuration", "Database", "GInitiallyUnowned", "gtk", "pygtk", "player", "c", "db_connection", "do_stat", "do_tip", "stat_dict", "h"): continue - print attr, eval("%s.__doc__" % (attr)) + print "%-14s %s" % (attr, eval("%s.__doc__" % (attr))) # print " " % (attr) - db_connection.close + db_connection.close_connection diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py old mode 100755 new mode 100644 index bec9be78..8b4af06f --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -1,449 +1,449 @@ -#!/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 -from optparse import OptionParser - - -parser = OptionParser() -parser.add_option("-x", "--errorsToConsole", action="store_true", - help="If passed error output will go to the console rather than .") -(options, sys.argv) = parser.parse_args() - -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 pygtk -pygtk.require('2.0') -import gtk - -import fpdb_db -import fpdb_simple -import GuiBulkImport -import GuiTableViewer -import GuiAutoImport -import GuiGraphViewer -import FpdbSQLQueries -import Configuration - -class fpdb: - def tab_clicked(self, widget, tab_name): - """called when a tab button is clicked to activate that tab""" - #print "start of tab_clicked" - self.display_tab(tab_name) - #end def tab_clicked - - def add_and_display_tab(self, new_tab, new_tab_name): - """just calls the component methods""" - self.add_tab(new_tab, new_tab_name) - self.display_tab(new_tab_name) - #end def add_and_display_tab - - def add_tab(self, new_tab, new_tab_name): - """adds a tab, namely creates the button and displays it and appends all the relevant arrays""" - #print "start of add_tab" - for i in self.tab_names: #todo: check this is valid - if i==new_tab_name: - raise fpdb_simple.FpdbError("duplicate tab_name not permitted") - - self.tabs.append(new_tab) - self.tab_names.append(new_tab_name) - - new_tab_sel_button=gtk.ToggleButton(new_tab_name) - new_tab_sel_button.connect("clicked", self.tab_clicked, new_tab_name) - self.tab_box.add(new_tab_sel_button) - new_tab_sel_button.show() - self.tab_buttons.append(new_tab_sel_button) - #end def add_tab - - def display_tab(self, new_tab_name): - """displays the indicated tab""" - #print "start of display_tab, len(self.tab_names):",len(self.tab_names) - tab_no=-1 - #if len(self.tab_names)>1: - for i in range(len(self.tab_names)): - #print "display_tab, new_tab_name:",new_tab_name," self.tab_names[i]:", self.tab_names[i] - if (new_tab_name==self.tab_names[i]): - tab_no=i - #self.tab_buttons[i].set_active(False) - #else: - # tab_no=0 - - #current_tab_no=-1 - for i in range(len(self.tab_names)): - if self.current_tab==self.tabs[i]: - #self.tab_buttons[i].set_active(False) - pass - - if tab_no==-1: - raise fpdb_simple.FpdbError("invalid tab_no") - else: - self.main_vbox.remove(self.current_tab) - #self.current_tab.destroy() - self.current_tab=self.tabs[tab_no] - self.main_vbox.add(self.current_tab) - self.tab_buttons[tab_no].set_active(True) - self.current_tab.show() - #end def display_tab - - def delete_event(self, widget, event, data=None): - return False - #end def delete_event - - def destroy(self, widget, data=None): - self.quit(widget, data) - #end def destroy - - def dia_about(self, widget, data): - print "todo: implement dia_about" - #end def dia_about - - def dia_create_del_database(self, widget, data): - print "todo: implement dia_create_del_database" - obtain_global_lock() - #end def dia_create_del_database - - def dia_create_del_user(self, widget, data): - print "todo: implement dia_create_del_user" - obtain_global_lock() - #end def dia_create_del_user - - def dia_database_stats(self, widget, data): - print "todo: implement dia_database_stats" - #string=fpdb_db.getDbStats(db, cursor) - #end def dia_database_stats - - def dia_delete_db_parts(self, widget, data): - print "todo: implement dia_delete_db_parts" - obtain_global_lock() - #end def dia_delete_db_parts - - def dia_edit_profile(self, widget=None, data=None, create_default=False, path=None): - print "todo: implement dia_edit_profile" - obtain_global_lock() - #end def dia_edit_profile - - def dia_export_db(self, widget, data): - print "todo: implement dia_export_db" - obtain_global_lock() - #end def dia_export_db - - def dia_get_db_root_credentials(self): - """obtains db root credentials from user""" - print "todo: implement dia_get_db_root_credentials" -# user, pw=None, None -# -# dialog=gtk.Dialog(title="DB Credentials needed", parent=None, flags=0, -# buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,"Connect and recreate",gtk.RESPONSE_OK)) -# -# label_warning1=gtk.Label("Please enter credentials for a database user for "+self.host+" that has permissions to create a database.") -# -# -# label_user=gtk.Label("Username") -# dialog.vbox.add(label_user) -# label_user.show() -# -# response=dialog.run() -# dialog.destroy() -# return (user, pw, response) - #end def dia_get_db_root_credentials - - def dia_import_db(self, widget, data): - print "todo: implement dia_import_db" - obtain_global_lock() - #end def dia_import_db - - def dia_licensing(self, widget, data): - print "todo: implement dia_licensing" - #end def dia_licensing - - def dia_load_profile(self, widget, data): - """Dialogue to select a file to load a profile from""" - self.obtain_global_lock() - chooser = gtk.FileChooserDialog(title="Please select a profile file to load", - action=gtk.FILE_CHOOSER_ACTION_OPEN, - buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) - chooser.set_filename(self.profile) - - response = chooser.run() - chooser.destroy() - if response == gtk.RESPONSE_OK: - self.load_profile(chooser.get_filename()) - elif response == gtk.RESPONSE_CANCEL: - print 'User cancelled loading profile' - #end def dia_load_profile - - def dia_recreate_tables(self, widget, data): - """Dialogue that asks user to confirm that he wants to delete and recreate the tables""" - self.obtain_global_lock() - dia_confirm=gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, - buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm deleting and recreating tables") - diastring=("Please confirm that you want to (re-)create the tables. If there already are tables in the database "+self.db.database+" on "+self.db.host+" they will be deleted.") - dia_confirm.format_secondary_text(diastring)#todo: make above string with bold for db, host and deleted - - response=dia_confirm.run() - dia_confirm.destroy() - if response == gtk.RESPONSE_YES: - self.db.recreate_tables() - elif response == gtk.RESPONSE_NO: - print 'User cancelled recreating tables' - #end def dia_recreate_tables - - def dia_regression_test(self, widget, data): - print "todo: implement dia_regression_test" - self.obtain_global_lock() - #end def dia_regression_test - - def dia_save_profile(self, widget, data): - print "todo: implement dia_save_profile" - #end def dia_save_profile - - def diaSetupWizard(self, path): - print "todo: implement setup wizard" - print "setup wizard not implemented - please create the default configuration file:", path - diaSetupWizard = gtk.Dialog(title="Fatal Error - Config File Missing", parent=None, flags=0, buttons=(gtk.STOCK_QUIT,gtk.RESPONSE_OK)) - - label = gtk.Label("Please copy the config file from the docs folder to:") - diaSetupWizard.vbox.add(label) - label.show() - - label = gtk.Label(path) - diaSetupWizard.vbox.add(label) - label.show() - - label = gtk.Label("and edit it according to the install documentation at http://fpdb.sourceforge.net") - diaSetupWizard.vbox.add(label) - label.show() - - response = diaSetupWizard.run() - sys.exit(1) - #end def diaSetupWizard - - def get_menu(self, window): - """returns the menu for this program""" - accel_group = gtk.AccelGroup() - self.item_factory = gtk.ItemFactory(gtk.MenuBar, "
", accel_group) - self.item_factory.create_items(self.menu_items) - window.add_accel_group(accel_group) - return self.item_factory.get_widget("
") - #end def get_menu - - def load_profile(self): - """Loads profile from the provided path name.""" - 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()) - - if self.db!=None: - self.db.disconnect() - - self.db = fpdb_db.fpdb_db() - #print "end of fpdb.load_profile, databaseName:",self.settings['db-databaseName'] - self.db.connect(self.settings['db-backend'], self.settings['db-host'], self.settings['db-databaseName'], self.settings['db-user'], self.settings['db-password']) - if self.db.wrongDbVersion: - diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) - - label = gtk.Label("An invalid DB version or missing tables have been detected.") - diaDbVersionWarning.vbox.add(label) - label.show() - - label = gtk.Label("This error is not necessarily fatal but it is strongly recommended that you recreate the tables by using the Database menu.") - diaDbVersionWarning.vbox.add(label) - label.show() - - label = gtk.Label("Not doing this will likely lead to misbehaviour including fpdb crashes, corrupt data etc.") - diaDbVersionWarning.vbox.add(label) - label.show() - - response = diaDbVersionWarning.run() - diaDbVersionWarning.destroy() - - # Database connected to successfully, load queries to pass on to other classes - self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) - #end def load_profile - - def not_implemented(self): - print "todo: called unimplemented menu entry (users: pls ignore this)"#remove this once more entries are implemented - #end def not_implemented - - def obtain_global_lock(self): - print "todo: implement obtain_global_lock (users: pls ignore this)" - #end def obtain_global_lock - - def quit(self, widget, data): - print "Quitting normally" - #check if current settings differ from profile, if so offer to save or abort - self.db.disconnect() - gtk.main_quit() - #end def quit_cliecked - - def release_global_lock(self): - print "todo: implement release_global_lock" - #end def release_global_lock - - def tab_abbreviations(self, widget, data): - print "todo: implement tab_abbreviations" - #end def tab_abbreviations - - def tab_auto_import(self, widget, data): - """opens the auto import tab""" - new_aimp_thread=GuiAutoImport.GuiAutoImport(self.settings, self.config) - self.threads.append(new_aimp_thread) - aimp_tab=new_aimp_thread.get_vbox() - self.add_and_display_tab(aimp_tab, "Auto Import") - #end def tab_auto_import - - def tab_bulk_import(self, widget, data): - """opens a tab for bulk importing""" - #print "start of tab_bulk_import" - new_import_thread=GuiBulkImport.GuiBulkImport(self.db, self.settings, self.config) - self.threads.append(new_import_thread) - bulk_tab=new_import_thread.get_vbox() - self.add_and_display_tab(bulk_tab, "Bulk Import") - #end def tab_bulk_import - - def tab_main_help(self, widget, data): - """Displays a tab with the main fpdb help screen""" - #print "start of tab_main_help" - mh_tab=gtk.Label("""Welcome to Fpdb! -For documentation please visit our website at http://fpdb.sourceforge.net/ or check the docs directory in the fpdb folder. -Please note that default.conf is no longer needed nor used, all configuration now happens in HUD_config.xml -This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") - self.add_and_display_tab(mh_tab, "Help") - #end def tab_main_help - - def tab_table_viewer(self, widget, data): - """opens a table viewer tab""" - #print "start of tab_table_viewer" - new_tv_thread=GuiTableViewer.GuiTableViewer(self.db, self.settings) - self.threads.append(new_tv_thread) - tv_tab=new_tv_thread.get_vbox() - self.add_and_display_tab(tv_tab, "Table Viewer") - #end def tab_table_viewer - - def tabGraphViewer(self, widget, data): - """opens a graph viewer tab""" - #print "start of tabGraphViewer" - new_gv_thread=GuiGraphViewer.GuiGraphViewer(self.db, self.settings, self.querydict, self.config) - self.threads.append(new_gv_thread) - gv_tab=new_gv_thread.get_vbox() - self.add_and_display_tab(gv_tab, "Graphs") - #end def tabGraphViewer - - def __init__(self): - self.threads=[] - self.db=None - self.config = Configuration.Config() - self.load_profile() - - self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) - self.window.connect("delete_event", self.delete_event) - self.window.connect("destroy", self.destroy) - self.window.set_title("Free Poker DB - version: alpha9+, p143 or higher") - self.window.set_border_width(1) - self.window.set_size_request(1020,400) - self.window.set_resizable(True) - - self.menu_items = ( - ( "/_Main", None, None, 0, "" ), - ( "/Main/_Load Profile (broken)", "L", self.dia_load_profile, 0, None ), - ( "/Main/_Edit Profile (todo)", "E", self.dia_edit_profile, 0, None ), - ( "/Main/_Save Profile (todo)", None, self.dia_save_profile, 0, None ), - ("/Main/sep1", None, None, 0, "" ), - ("/Main/_Quit", "Q", self.quit, 0, None ), - ("/_Import", None, None, 0, "" ), - ("/Import/_Bulk Import", "B", self.tab_bulk_import, 0, None ), - ("/Import/_Auto Import and HUD", "A", self.tab_auto_import, 0, None ), - ("/Import/Auto _Rating (todo)", "R", self.not_implemented, 0, None ), - ("/_Viewers", None, None, 0, "" ), - ("/_Viewers/_Auto Import and HUD", "A", self.tab_auto_import, 0, None ), - ("/Viewers/_Graphs", "G", self.tabGraphViewer, 0, None ), - ("/Viewers/Hand _Replayer (todo)", None, self.not_implemented, 0, None ), - ("/Viewers/Player _Details (todo)", None, self.not_implemented, 0, None ), - ("/Viewers/_Player Stats (tabulated view) (todo)", None, self.not_implemented, 0, None ), - ("/Viewers/Starting _Hands (todo)", None, self.not_implemented, 0, None ), - ("/Viewers/_Session Replayer (todo)", None, self.not_implemented, 0, None ), - ("/Viewers/Poker_table Viewer (mostly obselete)", "T", self.tab_table_viewer, 0, None ), - #( "/Viewers/Tourney Replayer - ( "/_Database", None, None, 0, "" ), - ( "/Database/Create or Delete _Database (todo)", None, self.dia_create_del_database, 0, None ), - ( "/Database/Create or Delete _User (todo)", None, self.dia_create_del_user, 0, None ), - ( "/Database/Create or Recreate _Tables", None, self.dia_recreate_tables, 0, None ), - ( "/Database/_Statistics (todo)", None, self.dia_database_stats, 0, None ), - ( "/D_ebugging", None, None, 0, "" ), - ( "/Debugging/_Delete Parts of Database (todo)", None, self.dia_delete_db_parts, 0, None ), - ( "/Debugging/_Export DB (todo)", None, self.dia_export_db, 0, None ), - ( "/Debugging/_Import DB (todo)", None, self.dia_import_db, 0, None ), - ( "/Debugging/_Regression test (todo)", None, self.dia_regression_test, 0, None ), - ( "/_Help", None, None, 0, "" ), - ( "/Help/_Main Help", "H", self.tab_main_help, 0, None ), - ( "/Help/_Abbrevations (todo)", None, self.tab_abbreviations, 0, None ), - ( "/Help/sep1", None, None, 0, "" ), - ( "/Help/A_bout (todo)", None, self.dia_about, 0, None ), - ( "/Help/_License and Copying (todo)", None, self.dia_licensing, 0, None ) - ) - - self.main_vbox = gtk.VBox(False, 1) - self.main_vbox.set_border_width(1) - self.window.add(self.main_vbox) - self.main_vbox.show() - - menubar = self.get_menu(self.window) - self.main_vbox.pack_start(menubar, False, True, 0) - menubar.show() - #done menubar - - self.tabs=[] - self.tab_names=[] - self.tab_buttons=[] - self.tab_box = gtk.HBox(False,1) - self.main_vbox.pack_start(self.tab_box, False, True, 0) - self.tab_box.show() - #done tab bar - - self.current_tab = gtk.VBox(False,1) - self.current_tab.set_border_width(1) - self.main_vbox.add(self.current_tab) - self.current_tab.show() - - self.tab_main_help(None, None) - - self.status_bar = gtk.Label("Status: Connected to "+self.db.get_backend_name()+" database named "+self.db.database+" on host "+self.db.host) - self.main_vbox.pack_end(self.status_bar, False, True, 0) - self.status_bar.show() - - self.window.show() - #end def __init__ - - def main(self): - gtk.main() - return 0 - #end def main - -if __name__ == "__main__": - me = fpdb() - me.main() +#!/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 +from optparse import OptionParser + + +parser = OptionParser() +parser.add_option("-x", "--errorsToConsole", action="store_true", + help="If passed error output will go to the console rather than .") +(options, sys.argv) = parser.parse_args() + +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 pygtk +pygtk.require('2.0') +import gtk + +import fpdb_db +import fpdb_simple +import GuiBulkImport +import GuiTableViewer +import GuiAutoImport +import GuiGraphViewer +import FpdbSQLQueries +import Configuration + +class fpdb: + def tab_clicked(self, widget, tab_name): + """called when a tab button is clicked to activate that tab""" + #print "start of tab_clicked" + self.display_tab(tab_name) + #end def tab_clicked + + def add_and_display_tab(self, new_tab, new_tab_name): + """just calls the component methods""" + self.add_tab(new_tab, new_tab_name) + self.display_tab(new_tab_name) + #end def add_and_display_tab + + def add_tab(self, new_tab, new_tab_name): + """adds a tab, namely creates the button and displays it and appends all the relevant arrays""" + #print "start of add_tab" + for i in self.tab_names: #todo: check this is valid + if i==new_tab_name: + raise fpdb_simple.FpdbError("duplicate tab_name not permitted") + + self.tabs.append(new_tab) + self.tab_names.append(new_tab_name) + + new_tab_sel_button=gtk.ToggleButton(new_tab_name) + new_tab_sel_button.connect("clicked", self.tab_clicked, new_tab_name) + self.tab_box.add(new_tab_sel_button) + new_tab_sel_button.show() + self.tab_buttons.append(new_tab_sel_button) + #end def add_tab + + def display_tab(self, new_tab_name): + """displays the indicated tab""" + #print "start of display_tab, len(self.tab_names):",len(self.tab_names) + tab_no=-1 + #if len(self.tab_names)>1: + for i in range(len(self.tab_names)): + #print "display_tab, new_tab_name:",new_tab_name," self.tab_names[i]:", self.tab_names[i] + if (new_tab_name==self.tab_names[i]): + tab_no=i + #self.tab_buttons[i].set_active(False) + #else: + # tab_no=0 + + #current_tab_no=-1 + for i in range(len(self.tab_names)): + if self.current_tab==self.tabs[i]: + #self.tab_buttons[i].set_active(False) + pass + + if tab_no==-1: + raise fpdb_simple.FpdbError("invalid tab_no") + else: + self.main_vbox.remove(self.current_tab) + #self.current_tab.destroy() + self.current_tab=self.tabs[tab_no] + self.main_vbox.add(self.current_tab) + self.tab_buttons[tab_no].set_active(True) + self.current_tab.show() + #end def display_tab + + def delete_event(self, widget, event, data=None): + return False + #end def delete_event + + def destroy(self, widget, data=None): + self.quit(widget, data) + #end def destroy + + def dia_about(self, widget, data): + print "todo: implement dia_about" + #end def dia_about + + def dia_create_del_database(self, widget, data): + print "todo: implement dia_create_del_database" + obtain_global_lock() + #end def dia_create_del_database + + def dia_create_del_user(self, widget, data): + print "todo: implement dia_create_del_user" + obtain_global_lock() + #end def dia_create_del_user + + def dia_database_stats(self, widget, data): + print "todo: implement dia_database_stats" + #string=fpdb_db.getDbStats(db, cursor) + #end def dia_database_stats + + def dia_delete_db_parts(self, widget, data): + print "todo: implement dia_delete_db_parts" + obtain_global_lock() + #end def dia_delete_db_parts + + def dia_edit_profile(self, widget=None, data=None, create_default=False, path=None): + print "todo: implement dia_edit_profile" + obtain_global_lock() + #end def dia_edit_profile + + def dia_export_db(self, widget, data): + print "todo: implement dia_export_db" + obtain_global_lock() + #end def dia_export_db + + def dia_get_db_root_credentials(self): + """obtains db root credentials from user""" + print "todo: implement dia_get_db_root_credentials" +# user, pw=None, None +# +# dialog=gtk.Dialog(title="DB Credentials needed", parent=None, flags=0, +# buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,"Connect and recreate",gtk.RESPONSE_OK)) +# +# label_warning1=gtk.Label("Please enter credentials for a database user for "+self.host+" that has permissions to create a database.") +# +# +# label_user=gtk.Label("Username") +# dialog.vbox.add(label_user) +# label_user.show() +# +# response=dialog.run() +# dialog.destroy() +# return (user, pw, response) + #end def dia_get_db_root_credentials + + def dia_import_db(self, widget, data): + print "todo: implement dia_import_db" + obtain_global_lock() + #end def dia_import_db + + def dia_licensing(self, widget, data): + print "todo: implement dia_licensing" + #end def dia_licensing + + def dia_load_profile(self, widget, data): + """Dialogue to select a file to load a profile from""" + self.obtain_global_lock() + chooser = gtk.FileChooserDialog(title="Please select a profile file to load", + action=gtk.FILE_CHOOSER_ACTION_OPEN, + buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) + chooser.set_filename(self.profile) + + response = chooser.run() + chooser.destroy() + if response == gtk.RESPONSE_OK: + self.load_profile(chooser.get_filename()) + elif response == gtk.RESPONSE_CANCEL: + print 'User cancelled loading profile' + #end def dia_load_profile + + def dia_recreate_tables(self, widget, data): + """Dialogue that asks user to confirm that he wants to delete and recreate the tables""" + self.obtain_global_lock() + dia_confirm=gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, + buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm deleting and recreating tables") + diastring=("Please confirm that you want to (re-)create the tables. If there already are tables in the database "+self.db.database+" on "+self.db.host+" they will be deleted.") + dia_confirm.format_secondary_text(diastring)#todo: make above string with bold for db, host and deleted + + response=dia_confirm.run() + dia_confirm.destroy() + if response == gtk.RESPONSE_YES: + self.db.recreate_tables() + elif response == gtk.RESPONSE_NO: + print 'User cancelled recreating tables' + #end def dia_recreate_tables + + def dia_regression_test(self, widget, data): + print "todo: implement dia_regression_test" + self.obtain_global_lock() + #end def dia_regression_test + + def dia_save_profile(self, widget, data): + print "todo: implement dia_save_profile" + #end def dia_save_profile + + def diaSetupWizard(self, path): + print "todo: implement setup wizard" + print "setup wizard not implemented - please create the default configuration file:", path + diaSetupWizard = gtk.Dialog(title="Fatal Error - Config File Missing", parent=None, flags=0, buttons=(gtk.STOCK_QUIT,gtk.RESPONSE_OK)) + + label = gtk.Label("Please copy the config file from the docs folder to:") + diaSetupWizard.vbox.add(label) + label.show() + + label = gtk.Label(path) + diaSetupWizard.vbox.add(label) + label.show() + + label = gtk.Label("and edit it according to the install documentation at http://fpdb.sourceforge.net") + diaSetupWizard.vbox.add(label) + label.show() + + response = diaSetupWizard.run() + sys.exit(1) + #end def diaSetupWizard + + def get_menu(self, window): + """returns the menu for this program""" + accel_group = gtk.AccelGroup() + self.item_factory = gtk.ItemFactory(gtk.MenuBar, "
", accel_group) + self.item_factory.create_items(self.menu_items) + window.add_accel_group(accel_group) + return self.item_factory.get_widget("
") + #end def get_menu + + def load_profile(self): + """Loads profile from the provided path name.""" + 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()) + + if self.db!=None: + self.db.disconnect() + + self.db = fpdb_db.fpdb_db() + #print "end of fpdb.load_profile, databaseName:",self.settings['db-databaseName'] + self.db.connect(self.settings['db-backend'], self.settings['db-host'], self.settings['db-databaseName'], self.settings['db-user'], self.settings['db-password']) + if self.db.wrongDbVersion: + diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) + + label = gtk.Label("An invalid DB version or missing tables have been detected.") + diaDbVersionWarning.vbox.add(label) + label.show() + + label = gtk.Label("This error is not necessarily fatal but it is strongly recommended that you recreate the tables by using the Database menu.") + diaDbVersionWarning.vbox.add(label) + label.show() + + label = gtk.Label("Not doing this will likely lead to misbehaviour including fpdb crashes, corrupt data etc.") + diaDbVersionWarning.vbox.add(label) + label.show() + + response = diaDbVersionWarning.run() + diaDbVersionWarning.destroy() + + # Database connected to successfully, load queries to pass on to other classes + self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) + #end def load_profile + + def not_implemented(self): + print "todo: called unimplemented menu entry (users: pls ignore this)"#remove this once more entries are implemented + #end def not_implemented + + def obtain_global_lock(self): + print "todo: implement obtain_global_lock (users: pls ignore this)" + #end def obtain_global_lock + + def quit(self, widget, data): + print "Quitting normally" + #check if current settings differ from profile, if so offer to save or abort + self.db.disconnect() + gtk.main_quit() + #end def quit_cliecked + + def release_global_lock(self): + print "todo: implement release_global_lock" + #end def release_global_lock + + def tab_abbreviations(self, widget, data): + print "todo: implement tab_abbreviations" + #end def tab_abbreviations + + def tab_auto_import(self, widget, data): + """opens the auto import tab""" + new_aimp_thread=GuiAutoImport.GuiAutoImport(self.settings, self.config) + self.threads.append(new_aimp_thread) + aimp_tab=new_aimp_thread.get_vbox() + self.add_and_display_tab(aimp_tab, "Auto Import") + #end def tab_auto_import + + def tab_bulk_import(self, widget, data): + """opens a tab for bulk importing""" + #print "start of tab_bulk_import" + new_import_thread=GuiBulkImport.GuiBulkImport(self.db, self.settings, self.config) + self.threads.append(new_import_thread) + bulk_tab=new_import_thread.get_vbox() + self.add_and_display_tab(bulk_tab, "Bulk Import") + #end def tab_bulk_import + + def tab_main_help(self, widget, data): + """Displays a tab with the main fpdb help screen""" + #print "start of tab_main_help" + mh_tab=gtk.Label("""Welcome to Fpdb! +For documentation please visit our website at http://fpdb.sourceforge.net/ or check the docs directory in the fpdb folder. +Please note that default.conf is no longer needed nor used, all configuration now happens in HUD_config.xml +This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") + self.add_and_display_tab(mh_tab, "Help") + #end def tab_main_help + + def tab_table_viewer(self, widget, data): + """opens a table viewer tab""" + #print "start of tab_table_viewer" + new_tv_thread=GuiTableViewer.GuiTableViewer(self.db, self.settings) + self.threads.append(new_tv_thread) + tv_tab=new_tv_thread.get_vbox() + self.add_and_display_tab(tv_tab, "Table Viewer") + #end def tab_table_viewer + + def tabGraphViewer(self, widget, data): + """opens a graph viewer tab""" + #print "start of tabGraphViewer" + new_gv_thread=GuiGraphViewer.GuiGraphViewer(self.db, self.settings, self.querydict, self.config) + self.threads.append(new_gv_thread) + gv_tab=new_gv_thread.get_vbox() + self.add_and_display_tab(gv_tab, "Graphs") + #end def tabGraphViewer + + def __init__(self): + self.threads=[] + self.db=None + self.config = Configuration.Config() + self.load_profile() + + self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) + self.window.connect("delete_event", self.delete_event) + self.window.connect("destroy", self.destroy) + self.window.set_title("Free Poker DB - version: alpha9+, p143 or higher") + self.window.set_border_width(1) + self.window.set_size_request(1020,400) + self.window.set_resizable(True) + + self.menu_items = ( + ( "/_Main", None, None, 0, "" ), + ( "/Main/_Load Profile (broken)", "L", self.dia_load_profile, 0, None ), + ( "/Main/_Edit Profile (todo)", "E", self.dia_edit_profile, 0, None ), + ( "/Main/_Save Profile (todo)", None, self.dia_save_profile, 0, None ), + ("/Main/sep1", None, None, 0, "" ), + ("/Main/_Quit", "Q", self.quit, 0, None ), + ("/_Import", None, None, 0, "" ), + ("/Import/_Bulk Import", "B", self.tab_bulk_import, 0, None ), + ("/Import/_Auto Import and HUD", "A", self.tab_auto_import, 0, None ), + ("/Import/Auto _Rating (todo)", "R", self.not_implemented, 0, None ), + ("/_Viewers", None, None, 0, "" ), + ("/_Viewers/_Auto Import and HUD", "A", self.tab_auto_import, 0, None ), + ("/Viewers/_Graphs", "G", self.tabGraphViewer, 0, None ), + ("/Viewers/Hand _Replayer (todo)", None, self.not_implemented, 0, None ), + ("/Viewers/Player _Details (todo)", None, self.not_implemented, 0, None ), + ("/Viewers/_Player Stats (tabulated view) (todo)", None, self.not_implemented, 0, None ), + ("/Viewers/Starting _Hands (todo)", None, self.not_implemented, 0, None ), + ("/Viewers/_Session Replayer (todo)", None, self.not_implemented, 0, None ), + ("/Viewers/Poker_table Viewer (mostly obselete)", "T", self.tab_table_viewer, 0, None ), + #( "/Viewers/Tourney Replayer + ( "/_Database", None, None, 0, "" ), + ( "/Database/Create or Delete _Database (todo)", None, self.dia_create_del_database, 0, None ), + ( "/Database/Create or Delete _User (todo)", None, self.dia_create_del_user, 0, None ), + ( "/Database/Create or Recreate _Tables", None, self.dia_recreate_tables, 0, None ), + ( "/Database/_Statistics (todo)", None, self.dia_database_stats, 0, None ), + ( "/D_ebugging", None, None, 0, "" ), + ( "/Debugging/_Delete Parts of Database (todo)", None, self.dia_delete_db_parts, 0, None ), + ( "/Debugging/_Export DB (todo)", None, self.dia_export_db, 0, None ), + ( "/Debugging/_Import DB (todo)", None, self.dia_import_db, 0, None ), + ( "/Debugging/_Regression test (todo)", None, self.dia_regression_test, 0, None ), + ( "/_Help", None, None, 0, "" ), + ( "/Help/_Main Help", "H", self.tab_main_help, 0, None ), + ( "/Help/_Abbrevations (todo)", None, self.tab_abbreviations, 0, None ), + ( "/Help/sep1", None, None, 0, "" ), + ( "/Help/A_bout (todo)", None, self.dia_about, 0, None ), + ( "/Help/_License and Copying (todo)", None, self.dia_licensing, 0, None ) + ) + + self.main_vbox = gtk.VBox(False, 1) + self.main_vbox.set_border_width(1) + self.window.add(self.main_vbox) + self.main_vbox.show() + + menubar = self.get_menu(self.window) + self.main_vbox.pack_start(menubar, False, True, 0) + menubar.show() + #done menubar + + self.tabs=[] + self.tab_names=[] + self.tab_buttons=[] + self.tab_box = gtk.HBox(False,1) + self.main_vbox.pack_start(self.tab_box, False, True, 0) + self.tab_box.show() + #done tab bar + + self.current_tab = gtk.VBox(False,1) + self.current_tab.set_border_width(1) + self.main_vbox.add(self.current_tab) + self.current_tab.show() + + self.tab_main_help(None, None) + + self.status_bar = gtk.Label("Status: Connected to "+self.db.get_backend_name()+" database named "+self.db.database+" on host "+self.db.host) + self.main_vbox.pack_end(self.status_bar, False, True, 0) + self.status_bar.show() + + self.window.show() + #end def __init__ + + def main(self): + gtk.main() + return 0 + #end def main + +if __name__ == "__main__": + me = fpdb() + me.main() diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py old mode 100755 new mode 100644 diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py old mode 100755 new mode 100644 index 3b0fb983..e2a2779e --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -1,298 +1,310 @@ -#!/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. - -#see status.txt for site/games support info - -import sys - -try: - import MySQLdb - mysqlLibFound=True -except: - pass - -try: - import psycopg2 - pgsqlLibFound=True -except: - pass - -import math -import os -import datetime -import re -import fpdb_simple -import fpdb_parse_logic -from time import time - -class Importer: - - def __init__(self, caller, settings): - """Constructor""" - self.settings=settings - self.caller=caller - self.db = None - self.cursor = None - self.filelist = {} - self.dirlist = {} - self.monitor = False - self.updated = {} #Time last import was run {file:mtime} - self.callHud = False - self.lines = None - self.faobs = None #File as one big string - self.pos_in_file = {} # dict to remember how far we have read in the file - #Set defaults - if not self.settings.has_key('imp-callFpdbHud'): - self.settings['imp-callFpdbHud'] = False - if not self.settings.has_key('minPrint'): - self.settings['minPrint'] = 30 - self.dbConnect() - - def dbConnect(self): - #connect to DB - if self.settings['db-backend'] == 2: - if not mysqlLibFound: - raise fpdb_simple.FpdbError("interface library MySQLdb not found but MySQL selected as backend - please install the library or change the config file") - self.db = MySQLdb.connect(self.settings['db-host'], self.settings['db-user'], - self.settings['db-password'], self.settings['db-databaseName']) - elif self.settings['db-backend'] == 3: - if not pgsqlLibFound: - raise fpdb_simple.FpdbError("interface library psycopg2 not found but PostgreSQL selected as backend - please install the library or change the config file") - print self.settings - self.db = psycopg2.connect(host = self.settings['db-host'], - user = self.settings['db-user'], - password = self.settings['db-password'], - database = self.settings['db-databaseName']) - elif self.settings['db-backend'] == 4: - pass - else: - pass - self.cursor = self.db.cursor() - - #Set functions - def setCallHud(self, value): - self.callHud = value - - def setMinPrint(self, value): - self.settings['minPrint'] = int(value) - - def setHandCount(self, value): - self.settings['handCount'] = int(value) - - def setQuiet(self, value): - self.settings['quiet'] = value - - def setFailOnError(self, value): - self.settings['failOnError'] = value - -# def setWatchTime(self): -# self.updated = time() - - def clearFileList(self): - self.filelist = {} - - #Add an individual file to filelist - def addImportFile(self, filename, site = "default", filter = "passthrough"): - #TODO: test it is a valid file - self.filelist[filename] = [site] + [filter] - - #Add a directory of files to filelist - #Only one import directory per site supported. - #dirlist is a hash of lists: - #dirlist{ 'PokerStars' => ["/path/to/import/", "filtername"] } - def addImportDirectory(self,dir,monitor = False, site = "default", filter = "passthrough"): - if os.path.isdir(dir): - if monitor == True: - self.monitor = True - self.dirlist[site] = [dir] + [filter] - - for file in os.listdir(dir): - self.addImportFile(os.path.join(dir, file), site, filter) - else: - print "Warning: Attempted to add: '" + str(dir) + "' as an import directory" - - #Run full import on filelist - def runImport(self): - for file in self.filelist: - self.import_file_dict(file) - - #Run import on updated files, then store latest update time. - def runUpdated(self): - #Check for new files in directory - #todo: make efficient - always checks for new file, should be able to use mtime of directory - # ^^ May not work on windows - for site in self.dirlist: - self.addImportDirectory(self.dirlist[site][0], False, site, self.dirlist[site][1]) - - for file in self.filelist: - stat_info = os.stat(file) - try: - lastupdate = self.updated[file] - if stat_info.st_mtime > lastupdate: - self.import_file_dict(file) - self.updated[file] = time() - except: - self.updated[file] = time() - # This codepath only runs first time the file is found, if modified in the last - # minute run an immediate import. - if (time() - stat_info.st_mtime) < 60: - self.import_file_dict(file) - - # This is now an internal function that should not be called directly. - def import_file_dict(self, file): - starttime = time() - last_read_hand=0 - loc = 0 - if (file=="stdin"): - inputFile=sys.stdin - else: - inputFile=open(file, "rU") - try: loc = self.pos_in_file[file] - except: pass - - # Read input file into class and close file - inputFile.seek(loc) - self.lines=fpdb_simple.removeTrailingEOL(inputFile.readlines()) - self.pos_in_file[file] = inputFile.tell() - inputFile.close() - - firstline = self.lines[0] - - if firstline.find("Tournament Summary")!=-1: - print "TODO: implement importing tournament summaries" - #self.faobs = readfile(inputFile) - #self.parseTourneyHistory() - return 0 - - site=fpdb_simple.recogniseSite(firstline) - category=fpdb_simple.recogniseCategory(firstline) - - startpos=0 - stored=0 #counter - duplicates=0 #counter - partial=0 #counter - errors=0 #counter - - for i in range (len(self.lines)): #main loop, iterates through the lines of a file and calls the appropriate parser method - if (len(self.lines[i])<2): - endpos=i - hand=self.lines[startpos:endpos] - - if (len(hand[0])<2): - hand=hand[1:] - - cancelled=False - damaged=False - if (site=="ftp"): - for i in range (len(hand)): - if (hand[i].endswith(" has been canceled")): #this is their typo. this is a typo, right? - cancelled=True - - seat1=hand[i].find("Seat ") #todo: make this recover by skipping this line - if (seat1!=-1): - if (hand[i].find("Seat ", seat1+3)!=-1): - damaged=True - - if (len(hand)<3): - pass - #todo: the above 2 lines are kind of a dirty hack, the mentioned circumstances should be handled elsewhere but that doesnt work with DOS/Win EOL. actually this doesnt work. - elif (hand[0].endswith(" (partial)")): #partial hand - do nothing - partial+=1 - elif (hand[1].find("Seat")==-1 and hand[2].find("Seat")==-1 and hand[3].find("Seat")==-1):#todo: should this be or instead of and? - partial+=1 - elif (cancelled or damaged): - partial+=1 - else: #normal processing - isTourney=fpdb_simple.isTourney(hand[0]) - if not isTourney: - fpdb_simple.filterAnteBlindFold(site,hand) - hand=fpdb_simple.filterCrap(site, hand, isTourney) - self.hand=hand - - try: - handsId=fpdb_parse_logic.mainParser(self.db, self.cursor, site, category, hand) - self.db.commit() - - stored+=1 - self.db.commit() -# if settings['imp-callFpdbHud'] and self.callHud and os.sep=='/': - if self.settings['imp-callFpdbHud'] and self.callHud: - #print "call to HUD here. handsId:",handsId - #pipe the Hands.id out to the HUD - self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep) - except fpdb_simple.DuplicateError: - duplicates+=1 - except (ValueError), fe: - errors+=1 - self.printEmailErrorMessage(errors, file, hand[0]) - - if (self.settings['failOnError']): - self.db.commit() #dont remove this, in case hand processing was cancelled. - raise - except (fpdb_simple.FpdbError), fe: - errors+=1 - self.printEmailErrorMessage(errors, file, hand[0]) - - #fe.printStackTrace() #todo: get stacktrace - self.db.rollback() - - if (self.settings['failOnError']): - self.db.commit() #dont remove this, in case hand processing was cancelled. - raise - if (self.settings['minPrint']!=0): - if ((stored+duplicates+partial+errors)%self.settings['minPrint']==0): - print "stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors - - if (self.settings['handCount']!=0): - if ((stored+duplicates+partial+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, "partial/damaged:", partial, "errors:", errors, " time:", (time() - starttime) - sys.exit(0) - startpos=endpos - print "Total stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors, " time:", (time() - starttime) - - if stored==0: - if duplicates>0: - for line_no in range(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 or partial - self.db.commit() - self.handsId=handsId - return handsId -#end def import_file_dict - - def parseTourneyHistory(self): - print "Tourney history parser stub" - #Find tournament boundaries. - #print self.foabs - - - def printEmailErrorMessage(self, errors, filename, line): - print "Error No.",errors,", please send the hand causing this to steffen@sycamoretest.info so I can fix it." - print "Filename:", filename - print "Here is the first line so you can identify it. Please mention that the error was a ValueError:" - print self.hand[0] - - -if __name__ == "__main__": - print "CLI for fpdb_import is now available as CliFpdb.py" +#!/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. + +#see status.txt for site/games support info + +import sys + +try: + import MySQLdb + mysqlLibFound=True +except: + pass + +try: + import psycopg2 + pgsqlLibFound=True +except: + pass + +import math +import os +import datetime +import re +import fpdb_simple +import fpdb_parse_logic +from time import time + +class Importer: + + def __init__(self, caller, settings, config): + """Constructor""" + self.settings=settings + self.caller=caller + self.config = config + self.db = None + self.cursor = None + self.filelist = {} + self.dirlist = {} + self.monitor = False + self.updated = {} #Time last import was run {file:mtime} + self.lines = None + self.faobs = None #File as one big string + self.pos_in_file = {} # dict to remember how far we have read in the file + #Set defaults + self.callHud = self.config.get_import_parameters().get("callFpdbHud") + if not self.settings.has_key('minPrint'): + self.settings['minPrint'] = 30 + self.dbConnect() + + def dbConnect(self): + #connect to DB + if self.settings['db-backend'] == 2: + if not mysqlLibFound: + raise fpdb_simple.FpdbError("interface library MySQLdb not found but MySQL selected as backend - please install the library or change the config file") + self.db = MySQLdb.connect(self.settings['db-host'], self.settings['db-user'], + self.settings['db-password'], self.settings['db-databaseName']) + elif self.settings['db-backend'] == 3: + if not pgsqlLibFound: + raise fpdb_simple.FpdbError("interface library psycopg2 not found but PostgreSQL selected as backend - please install the library or change the config file") + print self.settings + self.db = psycopg2.connect(host = self.settings['db-host'], + user = self.settings['db-user'], + password = self.settings['db-password'], + database = self.settings['db-databaseName']) + elif self.settings['db-backend'] == 4: + pass + else: + pass + self.cursor = self.db.cursor() + + #Set functions + def setCallHud(self, value): + self.callHud = value + + def setMinPrint(self, value): + self.settings['minPrint'] = int(value) + + def setHandCount(self, value): + self.settings['handCount'] = int(value) + + def setQuiet(self, value): + self.settings['quiet'] = value + + def setFailOnError(self, value): + self.settings['failOnError'] = value + +# def setWatchTime(self): +# self.updated = time() + + def clearFileList(self): + self.filelist = {} + + #Add an individual file to filelist + def addImportFile(self, filename, site = "default", filter = "passthrough"): + #TODO: test it is a valid file + self.filelist[filename] = [site] + [filter] + + #Add a directory of files to filelist + #Only one import directory per site supported. + #dirlist is a hash of lists: + #dirlist{ 'PokerStars' => ["/path/to/import/", "filtername"] } + def addImportDirectory(self, dir, monitor = False, site = "default", filter = "passthrough"): + if dir != "/dev/null" and dir.lower() != "none": + if os.path.isdir(dir): + if monitor == True: + self.monitor = True + self.dirlist[site] = [dir] + [filter] + + for file in os.listdir(dir): + self.addImportFile(os.path.join(dir, file), site, filter) + else: + print "Warning: Attempted to add: '" + str(dir) + "' as an import directory\n" + + #Run full import on filelist + def runImport(self): + for file in self.filelist: + self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1]) + + #Run import on updated files, then store latest update time. + def runUpdated(self): + #Check for new files in directory + #todo: make efficient - always checks for new file, should be able to use mtime of directory + # ^^ May not work on windows + for site in self.dirlist: + self.addImportDirectory(self.dirlist[site][0], False, site, self.dirlist[site][1]) + + for file in self.filelist: + stat_info = os.stat(file) + try: + lastupdate = self.updated[file] + if stat_info.st_mtime > lastupdate: + self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1]) + self.updated[file] = time() + except: + self.updated[file] = time() + # This codepath only runs first time the file is found, if modified in the last + # minute run an immediate import. + if (time() - stat_info.st_mtime) < 60: + self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1]) + + # This is now an internal function that should not be called directly. + def import_file_dict(self, file, site, filter): + if(filter == "passthrough"): + self.import_fpdb_file(file, site) + else: + #Load filter, and run filtered file though main importer + self.import_fpdb_file(file, site) + + + def import_fpdb_file(self, file, site): + starttime = time() + last_read_hand=0 + loc = 0 + if (file=="stdin"): + inputFile=sys.stdin + else: + inputFile=open(file, "rU") + try: loc = self.pos_in_file[file] + except: pass + + # Read input file into class and close file + inputFile.seek(loc) + self.lines=fpdb_simple.removeTrailingEOL(inputFile.readlines()) + self.pos_in_file[file] = inputFile.tell() + inputFile.close() + + try: # sometimes we seem to be getting an empty self.lines, in which case, we just want to return. + firstline = self.lines[0] + except: +# print "import_fpdb_file", file, site, self.lines, "\n" + return + + if firstline.find("Tournament Summary")!=-1: + print "TODO: implement importing tournament summaries" + #self.faobs = readfile(inputFile) + #self.parseTourneyHistory() + return 0 + + site=fpdb_simple.recogniseSite(firstline) + category=fpdb_simple.recogniseCategory(firstline) + + startpos=0 + stored=0 #counter + duplicates=0 #counter + partial=0 #counter + errors=0 #counter + + for i in range (len(self.lines)): #main loop, iterates through the lines of a file and calls the appropriate parser method + if (len(self.lines[i])<2): + endpos=i + hand=self.lines[startpos:endpos] + + if (len(hand[0])<2): + hand=hand[1:] + + cancelled=False + damaged=False + if (site=="ftp"): + for i in range (len(hand)): + if (hand[i].endswith(" has been canceled")): #this is their typo. this is a typo, right? + cancelled=True + + seat1=hand[i].find("Seat ") #todo: make this recover by skipping this line + if (seat1!=-1): + if (hand[i].find("Seat ", seat1+3)!=-1): + damaged=True + + if (len(hand)<3): + pass + #todo: the above 2 lines are kind of a dirty hack, the mentioned circumstances should be handled elsewhere but that doesnt work with DOS/Win EOL. actually this doesnt work. + elif (hand[0].endswith(" (partial)")): #partial hand - do nothing + partial+=1 + elif (hand[1].find("Seat")==-1 and hand[2].find("Seat")==-1 and hand[3].find("Seat")==-1):#todo: should this be or instead of and? + partial+=1 + elif (cancelled or damaged): + partial+=1 + else: #normal processing + isTourney=fpdb_simple.isTourney(hand[0]) + if not isTourney: + fpdb_simple.filterAnteBlindFold(site,hand) + hand=fpdb_simple.filterCrap(site, hand, isTourney) + self.hand=hand + + try: + handsId=fpdb_parse_logic.mainParser(self.db, self.cursor, site, category, hand) + self.db.commit() + + stored+=1 + self.db.commit() + if self.callHud: + #print "call to HUD here. handsId:",handsId + #pipe the Hands.id out to the HUD + self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep) + except fpdb_simple.DuplicateError: + duplicates+=1 + except (ValueError), fe: + errors+=1 + self.printEmailErrorMessage(errors, file, hand[0]) + + if (self.settings['failOnError']): + self.db.commit() #dont remove this, in case hand processing was cancelled. + raise + except (fpdb_simple.FpdbError), fe: + errors+=1 + self.printEmailErrorMessage(errors, file, hand[0]) + + #fe.printStackTrace() #todo: get stacktrace + self.db.rollback() + + if (self.settings['failOnError']): + self.db.commit() #dont remove this, in case hand processing was cancelled. + raise + if (self.settings['minPrint']!=0): + if ((stored+duplicates+partial+errors)%self.settings['minPrint']==0): + print "stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors + + if (self.settings['handCount']!=0): + if ((stored+duplicates+partial+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, "partial/damaged:", + partial, "errors:", errors, " time: %5.3f" % (time() - starttime) + sys.exit(0) + startpos=endpos + print "Total stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors, " time: %5.3f" % (time() - starttime) + + if stored==0: + if duplicates>0: + for line_no in range(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 or partial + self.db.commit() + self.handsId=handsId + return handsId +#end def import_file_dict + + def parseTourneyHistory(self): + print "Tourney history parser stub" + #Find tournament boundaries. + #print self.foabs + + + def printEmailErrorMessage(self, errors, filename, line): + print "Error No.",errors,", please send the hand causing this to steffen@sycamoretest.info so I can fix it." + print "Filename:", filename + print "Here is the first line so you can identify it. Please mention that the error was a ValueError:" + print self.hand[0] + + +if __name__ == "__main__": + print "CLI for fpdb_import is now available as CliFpdb.py" diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py index ec9a53f6..d704d811 100644 --- a/pyfpdb/fpdb_parse_logic.py +++ b/pyfpdb/fpdb_parse_logic.py @@ -46,7 +46,7 @@ def mainParser(db, cursor, site, category, hand): #print "found small blind line:",smallBlindLine break #print "small blind line:",smallBlindLine - gametypeID=fpdb_simple.recogniseGametypeID(cursor, hand[0], hand[smallBlindLine], siteID, category, isTourney) + gametypeID=fpdb_simple.recogniseGametypeID(db, cursor, hand[0], hand[smallBlindLine], siteID, category, isTourney) if isTourney: if site!="ps": raise fpdb_simple.FpdbError("tourneys are only supported on PS right now") @@ -142,18 +142,18 @@ def mainParser(db, cursor, site, category, hand): payin_amounts=fpdb_simple.calcPayin(len(names), buyin, fee) if base=="hold": - result = fpdb_save_to_db.tourney_holdem_omaha(cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteID, + result = fpdb_save_to_db.tourney_holdem_omaha(db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteID, siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, positions, cardValues, cardSuits, boardValues, boardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) elif base=="stud": - result = fpdb_save_to_db.tourney_stud(cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteID, + result = fpdb_save_to_db.tourney_stud(db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteID, siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, antes, cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) else: raise fpdb_simple.FpdbError ("unrecognised category") else: if base=="hold": - result = fpdb_save_to_db.ring_holdem_omaha(cursor, base, category, siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, positions, cardValues, cardSuits, boardValues, boardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) + result = fpdb_save_to_db.ring_holdem_omaha(db, cursor, base, category, siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, positions, cardValues, cardSuits, boardValues, boardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) elif base=="stud": - result = fpdb_save_to_db.ring_stud(cursor, base, category, siteHandNo, gametypeID, + result = fpdb_save_to_db.ring_stud(db, cursor, base, category, siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, antes, cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) else: diff --git a/pyfpdb/fpdb_save_to_db.py b/pyfpdb/fpdb_save_to_db.py index af6ab09d..d548eca5 100644 --- a/pyfpdb/fpdb_save_to_db.py +++ b/pyfpdb/fpdb_save_to_db.py @@ -21,13 +21,13 @@ import fpdb_simple #stores a stud/razz hand into the database -def ring_stud(cursor, base, category, site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes, action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): +def ring_stud(db, cursor, base, category, site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes, action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) - hands_id=fpdb_simple.storeHands(cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats) + hands_id=fpdb_simple.storeHands(db, cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats) #print "before calling store_hands_players_stud, antes:", antes - hands_players_ids=fpdb_simple.store_hands_players_stud(cursor, hands_id, player_ids, + hands_players_ids=fpdb_simple.store_hands_players_stud(db, cursor, hands_id, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes, seatNos) fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData) @@ -36,14 +36,14 @@ def ring_stud(cursor, base, category, site_hand_no, gametype_id, hand_start_time return hands_id #end def ring_stud -def ring_holdem_omaha(cursor, base, category, site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, positions, card_values, card_suits, board_values, board_suits, winnings, rakes, action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): +def ring_holdem_omaha(db, cursor, base, category, site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, positions, card_values, card_suits, board_values, board_suits, winnings, rakes, action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): """stores a holdem/omaha hand into the database""" fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) fpdb_simple.fill_board_cards(board_values, board_suits) - hands_id=fpdb_simple.storeHands(cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats) + hands_id=fpdb_simple.storeHands(db, cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats) - hands_players_ids=fpdb_simple.store_hands_players_holdem_omaha(cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos) + hands_players_ids=fpdb_simple.store_hands_players_holdem_omaha(db, cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos) fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData) @@ -53,7 +53,7 @@ def ring_holdem_omaha(cursor, base, category, site_hand_no, gametype_id, hand_st return hands_id #end def ring_holdem_omaha -def tourney_holdem_omaha(cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourney_start, payin_amounts, ranks, tourneyTypeId, siteId, #end of tourney specific params +def tourney_holdem_omaha(db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourney_start, payin_amounts, ranks, tourneyTypeId, siteId, #end of tourney specific params site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, positions, card_values, card_suits, board_values, board_suits, winnings, rakes, action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): """stores a tourney holdem/omaha hand into the database""" fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) @@ -62,9 +62,9 @@ def tourney_holdem_omaha(cursor, base, category, siteTourneyNo, buyin, fee, knoc tourney_id=fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourney_start) tourneys_players_ids=fpdb_simple.store_tourneys_players(cursor, tourney_id, player_ids, payin_amounts, ranks, winnings) - hands_id=fpdb_simple.storeHands(cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats) + hands_id=fpdb_simple.storeHands(db, cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats) - hands_players_ids=fpdb_simple.store_hands_players_holdem_omaha_tourney(cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids) + hands_players_ids=fpdb_simple.store_hands_players_holdem_omaha_tourney(db, cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids) fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData) @@ -74,7 +74,7 @@ def tourney_holdem_omaha(cursor, base, category, siteTourneyNo, buyin, fee, knoc return hands_id #end def tourney_holdem_omaha -def tourney_stud(cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteId, +def tourney_stud(db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteId, siteHandNo, gametypeId, handStartTime, names, playerIds, startCashes, antes, cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos): #stores a tourney stud/razz hand into the database fpdb_simple.fillCardArrays(len(names), base, category, cardValues, cardSuits) @@ -83,9 +83,9 @@ def tourney_stud(cursor, base, category, siteTourneyNo, buyin, fee, knockout, en tourneys_players_ids=fpdb_simple.store_tourneys_players(cursor, tourney_id, playerIds, payin_amounts, ranks, winnings) - hands_id=fpdb_simple.storeHands(cursor, siteHandNo, gametypeId, handStartTime, names, tableName, maxSeats) + hands_id=fpdb_simple.storeHands(db, cursor, siteHandNo, gametypeId, handStartTime, names, tableName, maxSeats) - hands_players_ids=fpdb_simple.store_hands_players_stud_tourney(cursor, hands_id, playerIds, startCashes, antes, cardValues, cardSuits, winnings, rakes, seatNos, tourneys_players_ids) + hands_players_ids=fpdb_simple.store_hands_players_stud_tourney(db, cursor, hands_id, playerIds, startCashes, antes, cardValues, cardSuits, winnings, rakes, seatNos, tourneys_players_ids) fpdb_simple.storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData) diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index d1b191de..ecd9def8 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -484,7 +484,8 @@ def isActionLine(line): #returns whether this is a duplicate def isAlreadyInDB(cursor, gametypeID, siteHandNo): - cursor.execute ("SELECT id FROM Hands WHERE gametypeId=%s AND siteHandNo=%s", (gametypeID, siteHandNo)) + #print "isAlreadyInDB gtid,shand:",gametypeID, siteHandNo + cursor.execute ("SELECT id FROM Hands WHERE gametypeId=%s AND siteHandNo=%s", (gametypeID, siteHandNo)) result=cursor.fetchall() if (len(result)>=1): raise DuplicateError ("dupl") @@ -1021,7 +1022,7 @@ def recogniseCategory(line): #end def recogniseCategory #returns the int for the gametype_id for the given line -def recogniseGametypeID(cursor, topline, smallBlindLine, site_id, category, isTourney):#todo: this method is messy +def recogniseGametypeID(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.") @@ -1072,7 +1073,10 @@ def recogniseGametypeID(cursor, topline, smallBlindLine, site_id, category, isTo else: 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)) result=cursor.fetchone() - #print "tried SELECTing gametypes.id, result:",result + #print "recgt1 result=",result + #ret=result[0] + #print "recgt1 ret=",ret + #print "tried SELECTing gametypes.id, result:",result try: len(result) @@ -1105,17 +1109,19 @@ def recogniseGametypeID(cursor, topline, smallBlindLine, site_id, category, isTo cursor.execute("""INSERT INTO Gametypes (siteId, type, base, category, limitType, hiLo, smallBlind, bigBlind, smallBet, bigBet) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", (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)) + #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: cursor.execute("""INSERT INTO Gametypes (siteId, type, base, category, limitType, hiLo, smallBlind, bigBlind, smallBet, bigBet) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", (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)) + #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)) - result=cursor.fetchone() + result=(db.insert_id(),) + #print "recgt2 result=",result #print "created new gametypes.id:",result - return result[0] + #print "recgt3: result=", result + return result[0] #end def recogniseGametypeID def recogniseTourneyTypeId(cursor, siteId, buyin, fee, knockout, rebuyOrAddon): @@ -1248,15 +1254,16 @@ def store_board_cards(cursor, hands_id, board_values, board_suits): board_values[4], board_suits[4])) #end def store_board_cards -def storeHands(cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats): +def storeHands(db, cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats): #stores into table hands cursor.execute ("INSERT INTO Hands (siteHandNo, gametypeId, handStart, seats, tableName, importTime, maxSeats) VALUES (%s, %s, %s, %s, %s, %s, %s)", (site_hand_no, gametype_id, hand_start_time, len(names), tableName, datetime.datetime.today(), maxSeats)) #todo: find a better way of doing this... - cursor.execute("SELECT id FROM Hands WHERE siteHandNo=%s AND gametypeId=%s", (site_hand_no, gametype_id)) - return cursor.fetchall()[0][0] + #cursor.execute("SELECT id FROM Hands WHERE siteHandNo=%s AND gametypeId=%s", (site_hand_no, gametype_id)) + #return cursor.fetchall()[0][0] + return db.insert_id() # mysql only #end def storeHands -def store_hands_players_holdem_omaha(cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos): +def store_hands_players_holdem_omaha(db, cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos): result=[] if (category=="holdem"): for i in range (len(player_ids)): @@ -1268,8 +1275,9 @@ def store_hands_players_holdem_omaha(cursor, category, hands_id, player_ids, sta (hands_id, player_ids[i], start_cashes[i], positions[i], card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], winnings[i], rakes[i], seatNos[i])) - cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId=%s", (hands_id, player_ids[i])) - result.append(cursor.fetchall()[0][0]) + #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId=%s", (hands_id, player_ids[i])) + #result.append(cursor.fetchall()[0][0]) + result.append( db.insert_id() ) # mysql only elif (category=="omahahi" or category=="omahahilo"): for i in range (len(player_ids)): cursor.execute ("""INSERT INTO HandsPlayers @@ -1281,14 +1289,15 @@ def store_hands_players_holdem_omaha(cursor, category, hands_id, player_ids, sta 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], winnings[i], rakes[i], seatNos[i])) - cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId=%s", (hands_id, player_ids[i])) - result.append(cursor.fetchall()[0][0]) + #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( db.insert_id() ) # mysql only else: raise FpdbError("invalid category") return result #end def store_hands_players_holdem_omaha -def store_hands_players_stud(cursor, hands_id, player_ids, start_cashes, antes, +def store_hands_players_stud(db, cursor, 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 result=[] @@ -1307,12 +1316,14 @@ def store_hands_players_stud(cursor, hands_id, player_ids, start_cashes, antes, 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], seatNos[i])) - cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId=%s", (hands_id, player_ids[i])) - result.append(cursor.fetchall()[0][0]) + #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( db.insert_id() ) # mysql only return result #end def store_hands_players_stud -def store_hands_players_holdem_omaha_tourney(cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids): +def store_hands_players_holdem_omaha_tourney(db, cursor, category, hands_id, player_ids, + start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids): #stores hands_players for tourney holdem/omaha hands result=[] for i in range (len(player_ids)): @@ -1338,13 +1349,14 @@ def store_hands_players_holdem_omaha_tourney(cursor, category, hands_id, player_ winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i])) else: raise FpdbError ("invalid card_values length:"+str(len(card_values[0]))) - cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId=%s", (hands_id, player_ids[i])) - result.append(cursor.fetchall()[0][0]) + #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( db.insert_id() ) # mysql only return result #end def store_hands_players_holdem_omaha_tourney -def store_hands_players_stud_tourney(cursor, hands_id, player_ids, start_cashes, +def store_hands_players_stud_tourney(db, cursor, hands_id, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids): #stores hands_players for tourney stud/razz hands result=[] @@ -1362,8 +1374,9 @@ def store_hands_players_stud_tourney(cursor, hands_id, player_ids, start_cashes, 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])) - cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId=%s", (hands_id, player_ids[i])) - result.append(cursor.fetchall()[0][0]) + #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( db.insert_id() ) # mysql only return result #end def store_hands_players_stud_tourney @@ -1949,9 +1962,9 @@ def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData): for player in range (len(playerIds)): if base=="hold": - cursor.execute("SELECT * FROM HudCache WHERE gametypeId=%s AND playerId=%s AND activeSeats=%s AND position=%s", (gametypeId, playerIds[player], len(playerIds), hudImportData['position'][player])) + cursor.execute("SELECT * FROM HudCache WHERE gametypeId+0=%s AND playerId=%s AND activeSeats=%s AND position=%s", (gametypeId, playerIds[player], len(playerIds), hudImportData['position'][player])) else: - cursor.execute("SELECT * FROM HudCache WHERE gametypeId=%s AND playerId=%s AND activeSeats=%s", (gametypeId, playerIds[player], len(playerIds))) + cursor.execute("SELECT * FROM HudCache WHERE gametypeId+0=%s AND playerId=%s AND activeSeats=%s", (gametypeId, playerIds[player], len(playerIds))) row=cursor.fetchone() #print "gametypeId:", gametypeId, "playerIds[player]",playerIds[player], "len(playerIds):",len(playerIds), "row:",row @@ -2097,7 +2110,7 @@ def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData): #end def storeHudCache def store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, startTime): - cursor.execute("SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId=%s", (siteTourneyNo, tourneyTypeId)) + cursor.execute("SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s", (siteTourneyNo, tourneyTypeId)) tmp=cursor.fetchone() #print "tried SELECTing tourneys.id, result:",tmp @@ -2107,7 +2120,7 @@ def store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, sta cursor.execute("""INSERT INTO Tourneys (tourneyTypeId, siteTourneyNo, entries, prizepool, startTime) VALUES (%s, %s, %s, %s, %s)""", (tourneyTypeId, siteTourneyNo, entries, prizepool, startTime)) - cursor.execute("SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId=%s", (siteTourneyNo, tourneyTypeId)) + cursor.execute("SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s", (siteTourneyNo, tourneyTypeId)) tmp=cursor.fetchone() #print "created new tourneys.id:",tmp return tmp[0] @@ -2121,7 +2134,7 @@ def store_tourneys_players(cursor, tourney_id, player_ids, payin_amounts, ranks, #print "ranks:",ranks #print "winnings:",winnings for i in range (len(player_ids)): - cursor.execute("SELECT id FROM TourneysPlayers WHERE tourneyId=%s AND playerId=%s", (tourney_id, player_ids[i])) + cursor.execute("SELECT id FROM TourneysPlayers WHERE tourneyId=%s AND playerId+0=%s", (tourney_id, player_ids[i])) tmp=cursor.fetchone() #print "tried SELECTing tourneys_players.id:",tmp @@ -2132,7 +2145,7 @@ def store_tourneys_players(cursor, tourney_id, player_ids, payin_amounts, ranks, (tourneyId, playerId, payinAmount, rank, winnings) VALUES (%s, %s, %s, %s, %s)""", (tourney_id, player_ids[i], payin_amounts[i], ranks[i], winnings[i])) - cursor.execute("SELECT id FROM TourneysPlayers WHERE tourneyId=%s AND playerId=%s", + cursor.execute("SELECT id FROM TourneysPlayers WHERE tourneyId=%s AND playerId+0=%s", (tourney_id, player_ids[i])) tmp=cursor.fetchone() #print "created new tourneys_players.id:",tmp From 3f86c54b17b30c95d0f7154779037c79de8f15c9 Mon Sep 17 00:00:00 2001 From: eblade Date: Tue, 2 Dec 2008 10:14:38 -0500 Subject: [PATCH 03/32] add "NA" to fold to steal stats for 0/0's --- pyfpdb/Stats.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/pyfpdb/Stats.py b/pyfpdb/Stats.py index 5ca42fe8..db2ada2e 100644 --- a/pyfpdb/Stats.py +++ b/pyfpdb/Stats.py @@ -261,12 +261,11 @@ def f_SB_steal(stat_dict, player): ) except: return (stat, - '%3.1f' % (0) + '%', - 'fSB=%3.1f' % (0) + '%', - 'fSB_s=%3.1f' % (0) + '%', - '(%d/%d)' % (0, 0), - '% folded SB to steal' - ) + 'NA', + 'fSB=NA', + 'fSB_s=NA', + '0/0', + '% folded SB to steal') def f_BB_steal(stat_dict, player): """ Folded BB to steal.""" @@ -282,12 +281,11 @@ def f_BB_steal(stat_dict, player): ) except: return (stat, - '%3.1f' % (0) + '%', - 'fBB=%3.1f' % (0) + '%', - 'fBB_s=%3.1f' % (0) + '%', - '(%d/%d)' % (0, 0), - '% folded BB to steal' - ) + 'NA', + 'fBB=NA', + 'fBB_s=NA', + '0/0', + '% folded BB to steal') def three_B_0(stat_dict, player): """ Three bet preflop/3rd.""" From 567d585a54af580aac54eb9faa0566ba8e52b116 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 2 Dec 2008 23:28:06 +0000 Subject: [PATCH 04/32] script to update index choices --- pyfpdb/upd_indexes.sql | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100755 pyfpdb/upd_indexes.sql diff --git a/pyfpdb/upd_indexes.sql b/pyfpdb/upd_indexes.sql new file mode 100755 index 00000000..e79f4bd4 --- /dev/null +++ b/pyfpdb/upd_indexes.sql @@ -0,0 +1,27 @@ + +# script to update indexes on mysql (+other?) database + +select '1. Dropping indexes' as ' '; +select 'Can''t drop messages indicate index already gone' as ' '; + +ALTER TABLE `fpdb`.`Settings` DROP INDEX `id`; +ALTER TABLE `fpdb`.`Sites` DROP INDEX `id`; +ALTER TABLE `fpdb`.`Gametypes` DROP INDEX `id`; +ALTER TABLE `fpdb`.`Players` DROP INDEX `id`; +ALTER TABLE `fpdb`.`Autorates` DROP INDEX `id`; +ALTER TABLE `fpdb`.`Hands` DROP INDEX `id`; +ALTER TABLE `fpdb`.`BoardCards` DROP INDEX `id`; +ALTER TABLE `fpdb`.`TourneyTypes` DROP INDEX `id`; +ALTER TABLE `fpdb`.`Tourneys` DROP INDEX `id`; +ALTER TABLE `fpdb`.`TourneysPlayers` DROP INDEX `id`; +ALTER TABLE `fpdb`.`HandsPlayers` DROP INDEX `id`; +ALTER TABLE `fpdb`.`HandsActions` DROP INDEX `id`; +ALTER TABLE `fpdb`.`HudCache` DROP INDEX `id`; + +select '2. Adding extra indexes on useful fields' as ' '; +select 'Duplicate key name messages indicate new indexes already there' as ' '; + +ALTER TABLE `fpdb`.`tourneys` ADD INDEX `siteTourneyNo`(`siteTourneyNo`); +ALTER TABLE `fpdb`.`hands` ADD INDEX `siteHandNo`(`siteHandNo`); +ALTER TABLE `fpdb`.`players` ADD INDEX `name`(`name`); + From cd858d6ade8fe2d0e72d9eb3f0d1eedbadab1c7f Mon Sep 17 00:00:00 2001 From: eblade Date: Wed, 3 Dec 2008 03:25:49 -0500 Subject: [PATCH 05/32] add "debug stat windows" to hud menu .. doesn't do anything useful yet, as i'm trying to figure out what part to actually debug --- pyfpdb/Hud.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 2960db30..3914f5ca 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -92,14 +92,22 @@ class Hud: self.menu.append(self.item1) self.item1.connect("activate", self.kill_hud) self.item1.show() + self.item2 = gtk.MenuItem('Save Layout') self.menu.append(self.item2) self.item2.connect("activate", self.save_layout) self.item2.show() + self.item3 = gtk.MenuItem('Reposition Stats') self.menu.append(self.item3) self.item3.connect("activate", self.reposition_windows) self.item3.show() + + self.item4 = gtk.MenuItem('Debug Stat Windows') + self.menu.append(self.item4) + self.item4.connect("activate", self.debug_stat_windows) + self.item4.show() + self.ebox.connect_object("button-press-event", self.on_button_press, self.menu) self.main_window.show_all() @@ -132,6 +140,12 @@ class Hud: for w in self.stat_windows: self.stat_windows[w].window.move(self.stat_windows[w].x, self.stat_windows[w].y) + + def debug_stat_windows(self, *args): + print self.table, "\n", self.main_window.window.get_transient_for() + for w in self.stat_windows: + print self.stat_windows[w].window.window.get_transient_for() + def save_layout(self, *args): new_layout = [(0, 0)] * self.max # todo: have the hud track the poker table's window position regularly, don't forget to update table.x and table.y. From 3be6453b4282ee2777d00ec8ac607de8f4dd8e35 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 3 Dec 2008 12:01:37 -0500 Subject: [PATCH 06/32] Minor bug in import parameters. --- pyfpdb/Configuration.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 91d74ff1..3bcaaa91 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -444,9 +444,9 @@ class Config: def get_import_parameters(self): imp = {} try: - imp['callFpdbHud'] = self.callFpdbHud - imp['interval'] = self.interval - imp['hhArchiveBase'] = self.hhArchiveBase + imp['callFpdbHud'] = self.imp.callFpdbHud + imp['interval'] = self.imp.interval + imp['hhArchiveBase'] = self.imp.hhArchiveBase except: # Default params imp['callFpdbHud'] = True imp['interval'] = 10 @@ -613,9 +613,7 @@ if __name__== "__main__": print "----------- END POPUP WINDOW FORMATS -----------" print "\n----------- IMPORT -----------" - tmp = c.get_import_parameters() - for param in tmp: - print " " + str(param) + ": " + str(tmp[param]) + print c.imp print "----------- END IMPORT -----------" print "\n----------- TABLE VIEW -----------" From 7063e03d6e8df06fe41cca9734f04cd35e9d31f0 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 3 Dec 2008 12:48:04 -0500 Subject: [PATCH 07/32] futile attempt to fix mystery crash --- pyfpdb/Mucked.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Mucked.py b/pyfpdb/Mucked.py index 6f1fadd0..45fe66bd 100644 --- a/pyfpdb/Mucked.py +++ b/pyfpdb/Mucked.py @@ -289,7 +289,7 @@ class Stud_cards: def clear(self): for r in range(0, self.rows): - self.grid_contents[(1, r)].set_text(" ") + self.grid_contents[(1, r)].set_text(" ") for c in range(0, 7): self.seen_cards[(c, r)].set_from_pixbuf(self.card_images[('B', 'S')]) self.eb[(c, r)].set_tooltip_text('') From 01861450653ce4fd9f1d1155b326270ea689e55d Mon Sep 17 00:00:00 2001 From: eblade Date: Wed, 3 Dec 2008 13:35:19 -0500 Subject: [PATCH 08/32] remove no-longer-needed "topify_window" for Stat_Window, removed some lines that were commented out due to no longer being needed, etc. Seems to fix the windows randomly re-attaching in Win32. --- pyfpdb/Hud.py | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 3914f5ca..80ec9a82 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -386,41 +386,12 @@ class Stat_Window: font = pango.FontDescription("Sans 7") self.label[r][c].modify_font(font) -# if not os.name == 'nt': # seems to be a bug in opacity on windows self.window.set_opacity(parent.colors['hudopacity']) -# self.window.realize() self.window.move(self.x, self.y) -# self.window.show_all() -# set_keep_above(1) for windows - if os.name == 'nt': self.topify_window(self.window) + self.window.hide() - def topify_window(self, window): - """Set the specified gtk window to stayontop in MS Windows.""" - - def windowEnumerationHandler(hwnd, resultList): - '''Callback for win32gui.EnumWindows() to generate list of window handles.''' - resultList.append((hwnd, win32gui.GetWindowText(hwnd))) - - unique_name = 'unique name for finding this window' - real_name = window.get_title() - window.set_title(unique_name) - tl_windows = [] - win32gui.EnumWindows(windowEnumerationHandler, tl_windows) - - for w in tl_windows: - if w[1] == unique_name: - - #win32gui.SetWindowPos(w[0], win32con.HWND_TOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE|win32con.SWP_NOSIZE) - -# style = win32gui.GetWindowLong(w[0], win32con.GWL_EXSTYLE) -# style |= win32con.WS_EX_TOOLWINDOW -# style &= ~win32con.WS_EX_APPWINDOW -# win32gui.SetWindowLong(w[0], win32con.GWL_EXSTYLE, style) - win32gui.ShowWindow(w[0], win32con.SW_SHOW) - window.set_title(real_name) - def destroy(*args): # call back for terminating the main eventloop gtk.main_quit() From 160db086897efe737700378065cef7f3a977dc6e Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 3 Dec 2008 23:14:03 +0000 Subject: [PATCH 09/32] calc totalprofit for hud --- pyfpdb/fpdb_parse_logic.py | 15 ++++++++++++--- pyfpdb/fpdb_simple.py | 31 +++++++++++++++++++++++++------ 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py index d704d811..6652ba1f 100644 --- a/pyfpdb/fpdb_parse_logic.py +++ b/pyfpdb/fpdb_parse_logic.py @@ -131,9 +131,13 @@ def mainParser(db, cursor, site, category, hand): totalWinnings+=winnings[i] if base=="hold": - hudImportData=fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes, allIns, actionTypeByNo, winnings, totalWinnings, positions) + hudImportData=fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes + , allIns, actionTypeByNo, winnings, totalWinnings, positions + , actionTypes, actionAmounts) else: - hudImportData=fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes, allIns, actionTypeByNo, winnings, totalWinnings, None) + hudImportData=fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes + , allIns, actionTypeByNo, winnings, totalWinnings, None + , actionTypes, actionAmounts) if isTourney: ranks=[] @@ -151,7 +155,12 @@ def mainParser(db, cursor, site, category, hand): raise fpdb_simple.FpdbError ("unrecognised category") else: if base=="hold": - result = fpdb_save_to_db.ring_holdem_omaha(db, cursor, base, category, siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, positions, cardValues, cardSuits, boardValues, boardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) + result = fpdb_save_to_db.ring_holdem_omaha(db, cursor, base, category, siteHandNo + ,gametypeID, handStartTime, names, playerIDs + ,startCashes, positions, cardValues, cardSuits + ,boardValues, boardSuits, winnings, rakes + ,actionTypes, allIns, actionAmounts, actionNos + ,hudImportData, maxSeats, tableName, seatNos) elif base=="stud": result = fpdb_save_to_db.ring_stud(db, cursor, base, category, siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, antes, cardValues, diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index ecd9def8..571223c4 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -1241,7 +1241,8 @@ def storeActions(cursor, handsPlayersIds, actionTypes, allIns, actionAmounts, ac for i in range (len(actionTypes)): #iterate through streets for j in range (len(actionTypes[i])): #iterate through names for k in range (len(actionTypes[i][j])): #iterate through individual actions of that player on that street - cursor.execute ("INSERT INTO HandsActions (handPlayerId, street, actionNo, action, allIn, amount) VALUES (%s, %s, %s, %s, %s, %s)", (handsPlayersIds[j], i, actionNos[i][j][k], actionTypes[i][j][k], allIns[i][j][k], actionAmounts[i][j][k])) + cursor.execute ("INSERT INTO HandsActions (handPlayerId, street, actionNo, action, allIn, amount) VALUES (%s, %s, %s, %s, %s, %s)" + , (handsPlayersIds[j], i, actionNos[i][j][k], actionTypes[i][j][k], allIns[i][j][k], actionAmounts[i][j][k])) #end def storeActions def store_board_cards(cursor, hands_id, board_values, board_suits): @@ -1380,8 +1381,12 @@ def store_hands_players_stud_tourney(db, cursor, hands_id, player_ids, start_cas return result #end def store_hands_players_stud_tourney -def generateHudCacheData(player_ids, base, category, action_types, allIns, actionTypeByNo, winnings, totalWinnings, positions): - """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""" +def generateHudCacheData(player_ids, base, category, action_types, allIns, actionTypeByNo + ,winnings, totalWinnings, positions, actionTypes, actionAmounts): + """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=[] @@ -1901,8 +1906,14 @@ def generateHudCacheData(player_ids, base, category, action_types, allIns, actio street3CheckCallRaiseDone=[] street4CheckCallRaiseChance=[] street4CheckCallRaiseDone=[] - for player in range (len(player_ids)): - myTotalProfit=0 + #print "b4 totprof calc, len(playerIds)=", len(player_ids) + for pl in range (len(player_ids)): + #print "pl=", pl + myTotalProfit=winnings[pl] # still need to deduct costs + for i in range (len(actionTypes)): #iterate through streets + #for j in range (len(actionTypes[i])): #iterate through names (using pl loop above) + for k in range (len(actionTypes[i][pl])): #iterate through individual actions of that player on that street + myTotalProfit -= actionAmounts[i][pl][k] myStreet1CheckCallRaiseChance=False myStreet1CheckCallRaiseDone=False @@ -1913,7 +1924,9 @@ def generateHudCacheData(player_ids, base, category, action_types, allIns, actio myStreet4CheckCallRaiseChance=False myStreet4CheckCallRaiseDone=False + #print "myTotalProfit=", myTotalProfit totalProfit.append(myTotalProfit) + #print "totalProfit[]=", totalProfit street1CheckCallRaiseChance.append(myStreet1CheckCallRaiseChance) street1CheckCallRaiseDone.append(myStreet1CheckCallRaiseDone) @@ -1925,6 +1938,7 @@ def generateHudCacheData(player_ids, base, category, action_types, allIns, actio street4CheckCallRaiseDone.append(myStreet4CheckCallRaiseDone) result['totalProfit']=totalProfit + #print "res[totalProfit]=", result['totalProfit'] result['street1CheckCallRaiseChance']=street1CheckCallRaiseChance result['street1CheckCallRaiseDone']=street1CheckCallRaiseDone @@ -1960,6 +1974,8 @@ def generateFoldToCB(street, playerIDs, didStreetCB, streetCBDone, foldToStreetC def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData): # if (category=="holdem" or category=="omahahi" or category=="omahahilo"): + #print "storeHudCache, len(playerIds)=", len(playerIds), " len(vpip)=" \ + #, len(hudImportData['street0VPI']), " len(totprof)=", len(hudImportData['totalProfit']) for player in range (len(playerIds)): if base=="hold": cursor.execute("SELECT * FROM HudCache WHERE gametypeId+0=%s AND playerId=%s AND activeSeats=%s AND position=%s", (gametypeId, playerIds[player], len(playerIds), hudImportData['position'][player])) @@ -2044,7 +2060,10 @@ def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData): if hudImportData['foldToStreet4CBChance'][player]: row[50]+=1 if hudImportData['foldToStreet4CBDone'][player]: row[51]+=1 - row[52]+=hudImportData['totalProfit'][player] + #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 From 1e9263f202bedbaf6ae78c333b7bd37566e61a32 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 5 Dec 2008 12:51:19 -0500 Subject: [PATCH 10/32] Fix width of left column. --- pyfpdb/Mucked.py | 1 + 1 file changed, 1 insertion(+) mode change 100644 => 100755 pyfpdb/Mucked.py diff --git a/pyfpdb/Mucked.py b/pyfpdb/Mucked.py old mode 100644 new mode 100755 index 45fe66bd..e220bf32 --- a/pyfpdb/Mucked.py +++ b/pyfpdb/Mucked.py @@ -170,6 +170,7 @@ class Stud_cards: for r in range(0, self.rows): self.grid_contents[( 0, r)] = gtk.Label("%d" % (r + 1)) self.grid_contents[( 1, r)] = gtk.Label("player %d" % (r + 1)) + self.grid_contents[( 1, r)].set_property("width-chars", 12) self.grid_contents[( 4, r)] = gtk.Label("-") self.grid_contents[( 9, r)] = gtk.Label("-") self.grid_contents[( 2, r)] = self.eb[( 0, r)] From 3eb1a1dd0bd8e552e8b45c9c0debb827e70d06e0 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Sat, 6 Dec 2008 13:41:39 +0200 Subject: [PATCH 11/32] Start to clean up psycopg2.connect() and surroundings --- pyfpdb/fpdb_db.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 8165211c..8435fc96 100755 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -43,7 +43,10 @@ class fpdb_db: self.db=MySQLdb.connect(host = host, user = user, passwd = password, db = database) elif backend==self.PGSQL: import psycopg2 - self.db = psycopg2.connect(host = host, user = user, password = password, database = database) + self.db = psycopg2.connect(host = host, + user = user, + password = password, + database = database) else: raise fpdb_simple.FpdbError("unrecognised database backend:"+backend) self.cursor=self.db.cursor() From 0f05d0886eb6c22743f0504155b4a34f41778a99 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Sat, 6 Dec 2008 14:10:50 +0200 Subject: [PATCH 12/32] Modify local HUD_config.xml, clean some places and change DB type to postgresql --- pyfpdb/HUD_config.xml | 229 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 pyfpdb/HUD_config.xml diff --git a/pyfpdb/HUD_config.xml b/pyfpdb/HUD_config.xml new file mode 100644 index 00000000..d640794d --- /dev/null +++ b/pyfpdb/HUD_config.xml @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From c9700fc1a7baeafdffa01fa6f266a6a100e6bef3 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Sat, 6 Dec 2008 14:34:44 +0200 Subject: [PATCH 13/32] Some debugs --- pyfpdb/fpdb.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index bec9be78..02829523 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -263,7 +263,11 @@ class fpdb: self.db = fpdb_db.fpdb_db() #print "end of fpdb.load_profile, databaseName:",self.settings['db-databaseName'] - self.db.connect(self.settings['db-backend'], self.settings['db-host'], self.settings['db-databaseName'], self.settings['db-user'], self.settings['db-password']) + self.db.connect(self.settings['db-backend'], + self.settings['db-host'], + self.settings['db-databaseName'], + self.settings['db-user'], + self.settings['db-password']) if self.db.wrongDbVersion: diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) From 7ecfac543756d1926a6eb9df02c2a4a0c0abb751 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Sat, 6 Dec 2008 14:40:04 +0200 Subject: [PATCH 14/32] Retab/whitespace demangle fpdb_db.py --- pyfpdb/fpdb_db.py | 281 +++++++++++++++++++++++----------------------- 1 file changed, 141 insertions(+), 140 deletions(-) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 8435fc96..b750b440 100755 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -21,159 +21,160 @@ import fpdb_simple import FpdbSQLQueries class fpdb_db: - def __init__(self): - """Simple constructor, doesnt really do anything""" - self.db=None - self.cursor=None - self.sql = {} - self.MYSQL_INNODB=2 - self.PGSQL=3 - self.SQLITE=4 - #end def __init__ - - def connect(self, backend, host, database, user, password): - """Connects a database with the given parameters""" - self.backend=backend - self.host=host - self.database=database - self.user=user - self.password=password - if backend==self.MYSQL_INNODB: - import MySQLdb - self.db=MySQLdb.connect(host = host, user = user, passwd = password, db = database) - elif backend==self.PGSQL: - import psycopg2 - self.db = psycopg2.connect(host = host, + def __init__(self): + """Simple constructor, doesnt really do anything""" + self.db=None + self.cursor=None + self.sql = {} + self.MYSQL_INNODB=2 + self.PGSQL=3 + self.SQLITE=4 + #end def __init__ + + def connect(self, backend, host, database, user, password): + """Connects a database with the given parameters""" + print backend, host, database, user, password + self.backend=backend + self.host=host + self.database=database + self.user=user + self.password=password + if backend==self.MYSQL_INNODB: + import MySQLdb + self.db=MySQLdb.connect(host = host, user = user, passwd = password, db = database) + elif backend==self.PGSQL: + import psycopg2 + self.db = psycopg2.connect(host = host, user = user, password = password, database = database) - else: - raise fpdb_simple.FpdbError("unrecognised database backend:"+backend) - self.cursor=self.db.cursor() - self.cursor.execute('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED') - # Set up query dictionary as early in the connection process as we can. - self.sql = FpdbSQLQueries.FpdbSQLQueries(self.get_backend_name()) - self.wrongDbVersion=False - try: - self.cursor.execute("SELECT * FROM Settings") - settings=self.cursor.fetchone() - if settings[0]!=118: - print "outdated or too new database version - please recreate tables" - self.wrongDbVersion=True - except:# _mysql_exceptions.ProgrammingError: - print "failed to read settings table - please recreate tables" - self.wrongDbVersion=True - #end def connect + else: + raise fpdb_simple.FpdbError("unrecognised database backend:"+backend) + self.cursor=self.db.cursor() + self.cursor.execute('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED') + # Set up query dictionary as early in the connection process as we can. + self.sql = FpdbSQLQueries.FpdbSQLQueries(self.get_backend_name()) + self.wrongDbVersion=False + try: + self.cursor.execute("SELECT * FROM Settings") + settings=self.cursor.fetchone() + if settings[0]!=118: + print "outdated or too new database version - please recreate tables" + self.wrongDbVersion=True + except:# _mysql_exceptions.ProgrammingError: + print "failed to read settings table - please recreate tables" + self.wrongDbVersion=True + #end def connect - def disconnect(self, due_to_error=False): - """Disconnects the DB""" - if due_to_error: - self.db.rollback() - else: - self.db.commit() - self.cursor.close() - self.db.close() - #end def disconnect - - def reconnect(self, due_to_error=False): - """Reconnects the DB""" - #print "started fpdb_db.reconnect" - self.disconnect(due_to_error) - self.connect(self.backend, self.host, self.database, self.user, self.password) + def disconnect(self, due_to_error=False): + """Disconnects the DB""" + if due_to_error: + self.db.rollback() + else: + self.db.commit() + self.cursor.close() + self.db.close() + #end def disconnect + + def reconnect(self, due_to_error=False): + """Reconnects the DB""" + #print "started fpdb_db.reconnect" + self.disconnect(due_to_error) + self.connect(self.backend, self.host, self.database, self.user, self.password) - def create_tables(self): - #todo: should detect and fail gracefully if tables already exist. - self.cursor.execute(self.sql.query['createSettingsTable']) - self.cursor.execute(self.sql.query['createSitesTable']) - self.cursor.execute(self.sql.query['createGametypesTable']) - self.cursor.execute(self.sql.query['createPlayersTable']) - self.cursor.execute(self.sql.query['createAutoratesTable']) - self.cursor.execute(self.sql.query['createHandsTable']) - self.cursor.execute(self.sql.query['createBoardCardsTable']) - self.cursor.execute(self.sql.query['createTourneyTypesTable']) - self.cursor.execute(self.sql.query['createTourneysTable']) - self.cursor.execute(self.sql.query['createTourneysPlayersTable']) - self.cursor.execute(self.sql.query['createHandsPlayersTable']) - self.cursor.execute(self.sql.query['createHandsActionsTable']) - self.cursor.execute(self.sql.query['createHudCacheTable']) - self.cursor.execute(self.sql.query['addTourneyIndex']) - self.cursor.execute(self.sql.query['addHandsIndex']) - self.cursor.execute(self.sql.query['addPlayersIndex']) - self.fillDefaultData() - self.db.commit() + def create_tables(self): + #todo: should detect and fail gracefully if tables already exist. + self.cursor.execute(self.sql.query['createSettingsTable']) + self.cursor.execute(self.sql.query['createSitesTable']) + self.cursor.execute(self.sql.query['createGametypesTable']) + self.cursor.execute(self.sql.query['createPlayersTable']) + self.cursor.execute(self.sql.query['createAutoratesTable']) + self.cursor.execute(self.sql.query['createHandsTable']) + self.cursor.execute(self.sql.query['createBoardCardsTable']) + self.cursor.execute(self.sql.query['createTourneyTypesTable']) + self.cursor.execute(self.sql.query['createTourneysTable']) + self.cursor.execute(self.sql.query['createTourneysPlayersTable']) + self.cursor.execute(self.sql.query['createHandsPlayersTable']) + self.cursor.execute(self.sql.query['createHandsActionsTable']) + self.cursor.execute(self.sql.query['createHudCacheTable']) + self.cursor.execute(self.sql.query['addTourneyIndex']) + self.cursor.execute(self.sql.query['addHandsIndex']) + self.cursor.execute(self.sql.query['addPlayersIndex']) + self.fillDefaultData() + self.db.commit() #end def disconnect - - def drop_tables(self): - """Drops the fpdb tables from the current db""" + + def drop_tables(self): + """Drops the fpdb tables from the current db""" - if(self.get_backend_name() == 'MySQL InnoDB'): - #Databases with FOREIGN KEY support need this switched of before you can drop tables - self.drop_referencial_integrity() + if(self.get_backend_name() == 'MySQL InnoDB'): + #Databases with FOREIGN KEY support need this switched of before you can drop tables + self.drop_referencial_integrity() - # Query the DB to see what tables exist - self.cursor.execute(self.sql.query['list_tables']) - for table in self.cursor: - self.cursor.execute(self.sql.query['drop_table'] + table[0]) - elif(self.get_backend_name() == 'PostgreSQL'): - self.db.commit()# I have no idea why this makes the query work--REB 07OCT2008 - self.cursor.execute(self.sql.query['list_tables']) - tables = self.cursor.fetchall() - for table in tables: - self.cursor.execute(self.sql.query['drop_table'] + table[0] + ' cascade') - elif(self.get_backend_name() == 'SQLite'): - #todo: sqlite version here - print "Empty function here" + # Query the DB to see what tables exist + self.cursor.execute(self.sql.query['list_tables']) + for table in self.cursor: + self.cursor.execute(self.sql.query['drop_table'] + table[0]) + elif(self.get_backend_name() == 'PostgreSQL'): + self.db.commit()# I have no idea why this makes the query work--REB 07OCT2008 + self.cursor.execute(self.sql.query['list_tables']) + tables = self.cursor.fetchall() + for table in tables: + self.cursor.execute(self.sql.query['drop_table'] + table[0] + ' cascade') + elif(self.get_backend_name() == 'SQLite'): + #todo: sqlite version here + print "Empty function here" - self.db.commit() - #end def drop_tables + self.db.commit() + #end def drop_tables - def drop_referencial_integrity(self): - """Update all tables to remove foreign keys""" + def drop_referencial_integrity(self): + """Update all tables to remove foreign keys""" - self.cursor.execute(self.sql.query['list_tables']) - result = self.cursor.fetchall() + self.cursor.execute(self.sql.query['list_tables']) + result = self.cursor.fetchall() - for i in range(len(result)): - self.cursor.execute("SHOW CREATE TABLE " + result[i][0]) - inner = self.cursor.fetchall() + for i in range(len(result)): + self.cursor.execute("SHOW CREATE TABLE " + result[i][0]) + inner = self.cursor.fetchall() - for j in range(len(inner)): - # result[i][0] - Table name - # result[i][1] - CREATE TABLE parameters - #Searching for CONSTRAINT `tablename_ibfk_1` - for m in re.finditer('(ibfk_[0-9]+)', inner[j][1]): - key = "`" + inner[j][0] + "_" + m.group() + "`" - self.cursor.execute("ALTER TABLE " + inner[j][0] + " DROP FOREIGN KEY " + key) + for j in range(len(inner)): + # result[i][0] - Table name + # result[i][1] - CREATE TABLE parameters + #Searching for CONSTRAINT `tablename_ibfk_1` + for m in re.finditer('(ibfk_[0-9]+)', inner[j][1]): + key = "`" + inner[j][0] + "_" + m.group() + "`" + self.cursor.execute("ALTER TABLE " + inner[j][0] + " DROP FOREIGN KEY " + key) self.db.commit() #end drop_referencial_inegrity - - def get_backend_name(self): - """Returns the name of the currently used backend""" - if self.backend==2: - return "MySQL InnoDB" - elif self.backend==3: - return "PostgreSQL" - else: - raise fpdb_simple.FpdbError("invalid backend") - #end def get_backend_name - - def get_db_info(self): - return (self.host, self.database, self.user, self.password) - #end def get_db_info - - def fillDefaultData(self): - self.cursor.execute("INSERT INTO Settings VALUES (118);") - self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'Full Tilt Poker', 'USD');") - self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'PokerStars', 'USD');") - self.cursor.execute("INSERT INTO TourneyTypes VALUES (DEFAULT, 1, 0, 0, 0, False);") - #end def fillDefaultData - - def recreate_tables(self): - """(Re-)creates the tables of the current DB""" - - self.drop_tables() - self.create_tables() - self.db.commit() - print "Finished recreating tables" - #end def recreate_tables + + def get_backend_name(self): + """Returns the name of the currently used backend""" + if self.backend==2: + return "MySQL InnoDB" + elif self.backend==3: + return "PostgreSQL" + else: + raise fpdb_simple.FpdbError("invalid backend") + #end def get_backend_name + + def get_db_info(self): + return (self.host, self.database, self.user, self.password) + #end def get_db_info + + def fillDefaultData(self): + self.cursor.execute("INSERT INTO Settings VALUES (118);") + self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'Full Tilt Poker', 'USD');") + self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'PokerStars', 'USD');") + self.cursor.execute("INSERT INTO TourneyTypes VALUES (DEFAULT, 1, 0, 0, 0, False);") + #end def fillDefaultData + + def recreate_tables(self): + """(Re-)creates the tables of the current DB""" + + self.drop_tables() + self.create_tables() + self.db.commit() + print "Finished recreating tables" + #end def recreate_tables #end class fpdb_db From dfb8a06686f3da5f6d5e505bf3bf1118e53b44db Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Sat, 6 Dec 2008 15:07:37 +0200 Subject: [PATCH 15/32] Allow to connect to local PostgreSQL via domain socket --- pyfpdb/fpdb_db.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index b750b440..2663224e 100755 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -31,23 +31,33 @@ class fpdb_db: self.SQLITE=4 #end def __init__ - def connect(self, backend, host, database, user, password): + def connect(self, backend=None, host=None, database=None, + user=None, password=None): """Connects a database with the given parameters""" - print backend, host, database, user, password + if backend is None: + raise FpdbError('Database backend not defined') self.backend=backend self.host=host - self.database=database self.user=user self.password=password + self.database=database if backend==self.MYSQL_INNODB: import MySQLdb self.db=MySQLdb.connect(host = host, user = user, passwd = password, db = database) elif backend==self.PGSQL: import psycopg2 - self.db = psycopg2.connect(host = host, + # If DB connection is made over TCP, then the variables + # host, user and password are required + if self.host or self.user: + self.db = psycopg2.connect(host = host, user = user, password = password, database = database) + # For local domain-socket connections, only DB name is + # needed, and everything else is in fact undefined and/or + # flat out wrong + else: + self.db = psycopg2.connect(database = database) else: raise fpdb_simple.FpdbError("unrecognised database backend:"+backend) self.cursor=self.db.cursor() From 6070066f8a09588b91021e4cfd7deaddb10708de Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Sat, 6 Dec 2008 15:16:55 +0200 Subject: [PATCH 16/32] obtain_global_lock() is a method, not top-level function --- pyfpdb/fpdb.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 02829523..6362c004 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -117,12 +117,12 @@ class fpdb: def dia_create_del_database(self, widget, data): print "todo: implement dia_create_del_database" - obtain_global_lock() + self.obtain_global_lock() #end def dia_create_del_database def dia_create_del_user(self, widget, data): print "todo: implement dia_create_del_user" - obtain_global_lock() + self.obtain_global_lock() #end def dia_create_del_user def dia_database_stats(self, widget, data): @@ -132,17 +132,17 @@ class fpdb: def dia_delete_db_parts(self, widget, data): print "todo: implement dia_delete_db_parts" - obtain_global_lock() + self.obtain_global_lock() #end def dia_delete_db_parts def dia_edit_profile(self, widget=None, data=None, create_default=False, path=None): print "todo: implement dia_edit_profile" - obtain_global_lock() + self.obtain_global_lock() #end def dia_edit_profile def dia_export_db(self, widget, data): print "todo: implement dia_export_db" - obtain_global_lock() + self.obtain_global_lock() #end def dia_export_db def dia_get_db_root_credentials(self): @@ -167,7 +167,7 @@ class fpdb: def dia_import_db(self, widget, data): print "todo: implement dia_import_db" - obtain_global_lock() + self.obtain_global_lock() #end def dia_import_db def dia_licensing(self, widget, data): From 19c0328955c339f502ae76e2c25fab25bed30f09 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Sat, 6 Dec 2008 21:14:39 +0200 Subject: [PATCH 17/32] Change syntax for CREATE INDEX... for postgresql --- pyfpdb/FpdbSQLQueries.py | 8 +- pyfpdb/HUD_config.xml | 229 --------------------------------------- 2 files changed, 4 insertions(+), 233 deletions(-) delete mode 100644 pyfpdb/HUD_config.xml diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index 11826018..c56e6de3 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -577,7 +577,7 @@ class FpdbSQLQueries: self.query['addTourneyIndex'] = """ALTER TABLE Tourneys ADD INDEX siteTourneyNo(siteTourneyNo)""" elif(self.dbname == 'PostgreSQL'): # FIXME: This query has a different syntax - self.query['addTourneyIndex'] = """ALTER TABLE Tourneys ADD INDEX siteTourneyNo(siteTourneyNo)""" + self.query['addTourneyIndex'] = """CREATE INDEX siteTourneyNo ON Tourneys (siteTourneyNo)""" elif(self.dbname == 'SQLite'): self.query['addHandsIndex'] = """ """ @@ -585,7 +585,7 @@ class FpdbSQLQueries: self.query['addHandsIndex'] = """ALTER TABLE Hands ADD INDEX siteHandNo(siteHandNo)""" elif(self.dbname == 'PostgreSQL'): # FIXME: This query has a different syntax - self.query['addHandsIndex'] = """ALTER TABLE Hands ADD INDEX siteHandNo(siteHandNo)""" + self.query['addHandsIndex'] = """CREATE INDEX siteHandNo ON Hands (siteHandNo)""" elif(self.dbname == 'SQLite'): self.query['addHandsIndex'] = """ """ @@ -593,9 +593,9 @@ class FpdbSQLQueries: self.query['addPlayersIndex'] = """ALTER TABLE Players ADD INDEX name(name)""" elif(self.dbname == 'PostgreSQL'): # FIXME: This query has a different syntax - self.query['addHandsIndex'] = """ALTER TABLE Hands ADD INDEX siteHandNo(siteHandNo)""" + self.query['addPlayersIndex'] = """CREATE INDEX name ON Players (name)""" elif(self.dbname == 'SQLite'): - self.query['addHandsIndex'] = """ """ + self.query['addPlayersIndex'] = """ """ ################################ # Queries used in GuiGraphViewer diff --git a/pyfpdb/HUD_config.xml b/pyfpdb/HUD_config.xml deleted file mode 100644 index d640794d..00000000 --- a/pyfpdb/HUD_config.xml +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 415eb4a3c62dbf648c3c10dc8ee8ff9abb3ac5d8 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Sat, 6 Dec 2008 21:50:40 +0200 Subject: [PATCH 18/32] Retab/whitespace demangly fpdb_import.py --- pyfpdb/fpdb_import.py | 502 +++++++++++++++++++++--------------------- 1 file changed, 252 insertions(+), 250 deletions(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 0ff8179c..7ce53edd 100755 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -20,16 +20,16 @@ import sys try: - import MySQLdb - mysqlLibFound=True + import MySQLdb + mysqlLibFound=True except: - pass - + pass + try: - import psycopg2 - pgsqlLibFound=True + import psycopg2 + pgsqlLibFound=True except: - pass + pass import traceback import math @@ -42,274 +42,276 @@ from time import time class Importer: - def __init__(self, caller, settings, config): - """Constructor""" - self.settings=settings - self.caller=caller - self.config = config - self.db = None - self.cursor = None - self.filelist = {} - self.dirlist = {} - self.monitor = False - self.updated = {} #Time last import was run {file:mtime} - self.lines = None - self.faobs = None #File as one big string - self.pos_in_file = {} # dict to remember how far we have read in the file - #Set defaults - self.callHud = self.config.get_import_parameters().get("callFpdbHud") - if not self.settings.has_key('minPrint'): - self.settings['minPrint'] = 30 - self.dbConnect() + def __init__(self, caller, settings, config): + """Constructor""" + self.settings=settings + self.caller=caller + self.config = config + self.db = None + self.cursor = None + self.filelist = {} + self.dirlist = {} + self.monitor = False + self.updated = {} #Time last import was run {file:mtime} + self.lines = None + self.faobs = None #File as one big string + self.pos_in_file = {} # dict to remember how far we have read in the file + #Set defaults + self.callHud = self.config.get_import_parameters().get("callFpdbHud") + if not self.settings.has_key('minPrint'): + self.settings['minPrint'] = 30 + self.dbConnect() - def dbConnect(self): - #connect to DB - if self.settings['db-backend'] == 2: - if not mysqlLibFound: - raise fpdb_simple.FpdbError("interface library MySQLdb not found but MySQL selected as backend - please install the library or change the config file") - self.db = MySQLdb.connect(self.settings['db-host'], self.settings['db-user'], - self.settings['db-password'], self.settings['db-databaseName']) - elif self.settings['db-backend'] == 3: - if not pgsqlLibFound: - raise fpdb_simple.FpdbError("interface library psycopg2 not found but PostgreSQL selected as backend - please install the library or change the config file") - print self.settings - self.db = psycopg2.connect(host = self.settings['db-host'], - user = self.settings['db-user'], - password = self.settings['db-password'], - database = self.settings['db-databaseName']) - elif self.settings['db-backend'] == 4: - pass - else: - pass - self.cursor = self.db.cursor() + # XXX: Why is this here, when fpdb_db.connect() already does the + # same? + def dbConnect(self): + #connect to DB + if self.settings['db-backend'] == 2: + if not mysqlLibFound: + raise fpdb_simple.FpdbError("interface library MySQLdb not found but MySQL selected as backend - please install the library or change the config file") + self.db = MySQLdb.connect(self.settings['db-host'], self.settings['db-user'], + self.settings['db-password'], self.settings['db-databaseName']) + elif self.settings['db-backend'] == 3: + if not pgsqlLibFound: + raise fpdb_simple.FpdbError("interface library psycopg2 not found but PostgreSQL selected as backend - please install the library or change the config file") + print self.settings + self.db = psycopg2.connect(host = self.settings['db-host'], + user = self.settings['db-user'], + password = self.settings['db-password'], + database = self.settings['db-databaseName']) + elif self.settings['db-backend'] == 4: + pass + else: + pass + self.cursor = self.db.cursor() - #Set functions - def setCallHud(self, value): - self.callHud = value + #Set functions + def setCallHud(self, value): + self.callHud = value - def setMinPrint(self, value): - self.settings['minPrint'] = int(value) + def setMinPrint(self, value): + self.settings['minPrint'] = int(value) - def setHandCount(self, value): - self.settings['handCount'] = int(value) + def setHandCount(self, value): + self.settings['handCount'] = int(value) - def setQuiet(self, value): - self.settings['quiet'] = value + def setQuiet(self, value): + self.settings['quiet'] = value - def setFailOnError(self, value): - self.settings['failOnError'] = value + def setFailOnError(self, value): + self.settings['failOnError'] = value -# def setWatchTime(self): -# self.updated = time() +# def setWatchTime(self): +# self.updated = time() - def clearFileList(self): - self.filelist = {} + def clearFileList(self): + self.filelist = {} - #Add an individual file to filelist - def addImportFile(self, filename, site = "default", filter = "passthrough"): - #TODO: test it is a valid file - self.filelist[filename] = [site] + [filter] + #Add an individual file to filelist + def addImportFile(self, filename, site = "default", filter = "passthrough"): + #TODO: test it is a valid file + self.filelist[filename] = [site] + [filter] - #Add a directory of files to filelist - #Only one import directory per site supported. - #dirlist is a hash of lists: - #dirlist{ 'PokerStars' => ["/path/to/import/", "filtername"] } - def addImportDirectory(self,dir,monitor = False, site = "default", filter = "passthrough"): - if os.path.isdir(dir): - if monitor == True: - self.monitor = True - self.dirlist[site] = [dir] + [filter] + #Add a directory of files to filelist + #Only one import directory per site supported. + #dirlist is a hash of lists: + #dirlist{ 'PokerStars' => ["/path/to/import/", "filtername"] } + def addImportDirectory(self,dir,monitor = False, site = "default", filter = "passthrough"): + if os.path.isdir(dir): + if monitor == True: + self.monitor = True + self.dirlist[site] = [dir] + [filter] - for file in os.listdir(dir): - self.addImportFile(os.path.join(dir, file), site, filter) - else: - print "Warning: Attempted to add: '" + str(dir) + "' as an import directory" + for file in os.listdir(dir): + self.addImportFile(os.path.join(dir, file), site, filter) + else: + print "Warning: Attempted to add: '" + str(dir) + "' as an import directory" - #Run full import on filelist - def runImport(self): - for file in self.filelist: - self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1]) + #Run full import on filelist + def runImport(self): + for file in self.filelist: + self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1]) - #Run import on updated files, then store latest update time. - def runUpdated(self): - #Check for new files in directory - #todo: make efficient - always checks for new file, should be able to use mtime of directory - # ^^ May not work on windows - for site in self.dirlist: - self.addImportDirectory(self.dirlist[site][0], False, site, self.dirlist[site][1]) + #Run import on updated files, then store latest update time. + def runUpdated(self): + #Check for new files in directory + #todo: make efficient - always checks for new file, should be able to use mtime of directory + # ^^ May not work on windows + for site in self.dirlist: + self.addImportDirectory(self.dirlist[site][0], False, site, self.dirlist[site][1]) - for file in self.filelist: - stat_info = os.stat(file) - try: - lastupdate = self.updated[file] - if stat_info.st_mtime > lastupdate: - self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1]) - self.updated[file] = time() - except: - self.updated[file] = time() - # This codepath only runs first time the file is found, if modified in the last - # minute run an immediate import. - if (time() - stat_info.st_mtime) < 60: - self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1]) + for file in self.filelist: + stat_info = os.stat(file) + try: + lastupdate = self.updated[file] + if stat_info.st_mtime > lastupdate: + self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1]) + self.updated[file] = time() + except: + self.updated[file] = time() + # This codepath only runs first time the file is found, if modified in the last + # minute run an immediate import. + if (time() - stat_info.st_mtime) < 60: + self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1]) - # This is now an internal function that should not be called directly. - def import_file_dict(self, file, site, filter): - if(filter == "passthrough"): - self.import_fpdb_file(file, site) - else: - #Load filter, and run filtered file though main importer - self.import_fpdb_file(file, site) + # This is now an internal function that should not be called directly. + def import_file_dict(self, file, site, filter): + if(filter == "passthrough"): + self.import_fpdb_file(file, site) + else: + #Load filter, and run filtered file though main importer + self.import_fpdb_file(file, site) - def import_fpdb_file(self, file, site): - starttime = time() - last_read_hand=0 - loc = 0 - if (file=="stdin"): - inputFile=sys.stdin - else: - inputFile=open(file, "rU") - try: loc = self.pos_in_file[file] - except: pass + def import_fpdb_file(self, file, site): + starttime = time() + last_read_hand=0 + loc = 0 + if (file=="stdin"): + inputFile=sys.stdin + else: + inputFile=open(file, "rU") + try: loc = self.pos_in_file[file] + except: pass - # Read input file into class and close file - inputFile.seek(loc) - self.lines=fpdb_simple.removeTrailingEOL(inputFile.readlines()) - self.pos_in_file[file] = inputFile.tell() - inputFile.close() + # Read input file into class and close file + inputFile.seek(loc) + self.lines=fpdb_simple.removeTrailingEOL(inputFile.readlines()) + self.pos_in_file[file] = inputFile.tell() + inputFile.close() - try: # sometimes we seem to be getting an empty self.lines, in which case, we just want to return. - firstline = self.lines[0] - except: -# print "import_fpdb_file", file, site, self.lines, "\n" - return + try: # sometimes we seem to be getting an empty self.lines, in which case, we just want to return. + firstline = self.lines[0] + except: +# print "import_fpdb_file", file, site, self.lines, "\n" + return - if firstline.find("Tournament Summary")!=-1: - print "TODO: implement importing tournament summaries" - #self.faobs = readfile(inputFile) - #self.parseTourneyHistory() - return 0 - - site=fpdb_simple.recogniseSite(firstline) - category=fpdb_simple.recogniseCategory(firstline) + if firstline.find("Tournament Summary")!=-1: + print "TODO: implement importing tournament summaries" + #self.faobs = readfile(inputFile) + #self.parseTourneyHistory() + return 0 + + site=fpdb_simple.recogniseSite(firstline) + category=fpdb_simple.recogniseCategory(firstline) - startpos=0 - stored=0 #counter - duplicates=0 #counter - partial=0 #counter - errors=0 #counter + startpos=0 + stored=0 #counter + duplicates=0 #counter + partial=0 #counter + errors=0 #counter - for i in range (len(self.lines)): #main loop, iterates through the lines of a file and calls the appropriate parser method - if (len(self.lines[i])<2): - endpos=i - hand=self.lines[startpos:endpos] - - if (len(hand[0])<2): - hand=hand[1:] - - cancelled=False - damaged=False - if (site=="ftp"): - for i in range (len(hand)): - if (hand[i].endswith(" has been canceled")): #this is their typo. this is a typo, right? - cancelled=True - - seat1=hand[i].find("Seat ") #todo: make this recover by skipping this line - if (seat1!=-1): - if (hand[i].find("Seat ", seat1+3)!=-1): - damaged=True - - if (len(hand)<3): - pass - #todo: the above 2 lines are kind of a dirty hack, the mentioned circumstances should be handled elsewhere but that doesnt work with DOS/Win EOL. actually this doesnt work. - elif (hand[0].endswith(" (partial)")): #partial hand - do nothing - partial+=1 - elif (hand[1].find("Seat")==-1 and hand[2].find("Seat")==-1 and hand[3].find("Seat")==-1):#todo: should this be or instead of and? - partial+=1 - elif (cancelled or damaged): - partial+=1 - else: #normal processing - isTourney=fpdb_simple.isTourney(hand[0]) - if not isTourney: - fpdb_simple.filterAnteBlindFold(site,hand) - hand=fpdb_simple.filterCrap(site, hand, isTourney) - self.hand=hand - - try: - handsId=fpdb_parse_logic.mainParser(self.db, self.cursor, site, category, hand) - self.db.commit() - - stored+=1 - self.db.commit() - if self.callHud: - #print "call to HUD here. handsId:",handsId - #pipe the Hands.id out to the HUD - self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep) - except fpdb_simple.DuplicateError: - duplicates+=1 - except (ValueError), fe: - errors+=1 - self.printEmailErrorMessage(errors, file, hand) - - if (self.settings['failOnError']): - self.db.commit() #dont remove this, in case hand processing was cancelled. - raise - except (fpdb_simple.FpdbError), fe: - errors+=1 - self.printEmailErrorMessage(errors, file, hand) + for i in range (len(self.lines)): #main loop, iterates through the lines of a file and calls the appropriate parser method + if (len(self.lines[i])<2): + endpos=i + hand=self.lines[startpos:endpos] + + if (len(hand[0])<2): + hand=hand[1:] + + cancelled=False + damaged=False + if (site=="ftp"): + for i in range (len(hand)): + if (hand[i].endswith(" has been canceled")): #this is their typo. this is a typo, right? + cancelled=True + + seat1=hand[i].find("Seat ") #todo: make this recover by skipping this line + if (seat1!=-1): + if (hand[i].find("Seat ", seat1+3)!=-1): + damaged=True + + if (len(hand)<3): + pass + #todo: the above 2 lines are kind of a dirty hack, the mentioned circumstances should be handled elsewhere but that doesnt work with DOS/Win EOL. actually this doesnt work. + elif (hand[0].endswith(" (partial)")): #partial hand - do nothing + partial+=1 + elif (hand[1].find("Seat")==-1 and hand[2].find("Seat")==-1 and hand[3].find("Seat")==-1):#todo: should this be or instead of and? + partial+=1 + elif (cancelled or damaged): + partial+=1 + else: #normal processing + isTourney=fpdb_simple.isTourney(hand[0]) + if not isTourney: + fpdb_simple.filterAnteBlindFold(site,hand) + hand=fpdb_simple.filterCrap(site, hand, isTourney) + self.hand=hand + + try: + handsId=fpdb_parse_logic.mainParser(self.db, self.cursor, site, category, hand) + self.db.commit() + + stored+=1 + self.db.commit() + if self.callHud: + #print "call to HUD here. handsId:",handsId + #pipe the Hands.id out to the HUD + self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep) + except fpdb_simple.DuplicateError: + duplicates+=1 + except (ValueError), fe: + errors+=1 + self.printEmailErrorMessage(errors, file, hand) + + if (self.settings['failOnError']): + self.db.commit() #dont remove this, in case hand processing was cancelled. + raise + except (fpdb_simple.FpdbError), fe: + errors+=1 + self.printEmailErrorMessage(errors, file, hand) - #fe.printStackTrace() #todo: get stacktrace - self.db.rollback() - - if (self.settings['failOnError']): - self.db.commit() #dont remove this, in case hand processing was cancelled. - raise - if (self.settings['minPrint']!=0): - if ((stored+duplicates+partial+errors)%self.settings['minPrint']==0): - print "stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors - - if (self.settings['handCount']!=0): - if ((stored+duplicates+partial+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, "partial/damaged:", partial, "errors:", errors, " time:", (time() - starttime) - sys.exit(0) - startpos=endpos - print "Total stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors, " time:", (time() - starttime) - - if stored==0: - if duplicates>0: - for line_no in range(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 or partial - self.db.commit() - self.handsId=handsId - return handsId + #fe.printStackTrace() #todo: get stacktrace + self.db.rollback() + + if (self.settings['failOnError']): + self.db.commit() #dont remove this, in case hand processing was cancelled. + raise + if (self.settings['minPrint']!=0): + if ((stored+duplicates+partial+errors)%self.settings['minPrint']==0): + print "stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors + + if (self.settings['handCount']!=0): + if ((stored+duplicates+partial+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, "partial/damaged:", partial, "errors:", errors, " time:", (time() - starttime) + sys.exit(0) + startpos=endpos + print "Total stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors, " time:", (time() - starttime) + + if stored==0: + if duplicates>0: + for line_no in range(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 or partial + self.db.commit() + self.handsId=handsId + return handsId #end def import_file_dict - def parseTourneyHistory(self): - print "Tourney history parser stub" - #Find tournament boundaries. - #print self.foabs - + def parseTourneyHistory(self): + print "Tourney history parser stub" + #Find tournament boundaries. + #print self.foabs + - 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." - print "Filename:", filename - print "Here is the first line so you can identify it. Please mention that the error was a ValueError:" - print self.hand[0] - print "Hand logged to hand-errors.txt" - logfile = open('hand-errors.txt', 'a') - for s in self.hand: - logfile.write(str(s) + "\n") - logfile.write("\n") - logfile.close() + 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." + print "Filename:", filename + print "Here is the first line so you can identify it. Please mention that the error was a ValueError:" + print self.hand[0] + print "Hand logged to hand-errors.txt" + logfile = open('hand-errors.txt', 'a') + for s in self.hand: + logfile.write(str(s) + "\n") + logfile.write("\n") + logfile.close() if __name__ == "__main__": - print "CLI for fpdb_import is now available as CliFpdb.py" + print "CLI for fpdb_import is now available as CliFpdb.py" From 90e348946f23e6c215526f3248e88fe99c3cd895 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Sat, 6 Dec 2008 21:59:58 +0200 Subject: [PATCH 19/32] First step at fixing the bulk importer with postgres --- pyfpdb/fpdb_import.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 7ce53edd..fd2a321f 100755 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -75,10 +75,15 @@ class Importer: if not pgsqlLibFound: raise fpdb_simple.FpdbError("interface library psycopg2 not found but PostgreSQL selected as backend - please install the library or change the config file") print self.settings - self.db = psycopg2.connect(host = self.settings['db-host'], + if not self.settings.has_key('db-host') or \ + not self.settings.has_key('db-user'): + self.db = psycopg2.connect(host = self.settings['db-host'], user = self.settings['db-user'], password = self.settings['db-password'], database = self.settings['db-databaseName']) + else: + dbname = self.settings['db-databaseName'] + self.db = psycopg2.connect(database = dbname) elif self.settings['db-backend'] == 4: pass else: From 977e954574799b6f02d36ba2d21975273d0735f2 Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 7 Dec 2008 17:06:01 +0900 Subject: [PATCH 20/32] Fixups to GuiPlayerStats Now sets up and obeys the radio buttons more correctly. Also reads the names from the text box, and replaces in the sql query. --- pyfpdb/FpdbSQLQueries.py | 13 +++++++------ pyfpdb/GuiPlayerStats.py | 34 +++++++++++++++++++++++++--------- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index c56e6de3..40d0ae6f 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -576,7 +576,6 @@ class FpdbSQLQueries: if(self.dbname == 'MySQL InnoDB'): self.query['addTourneyIndex'] = """ALTER TABLE Tourneys ADD INDEX siteTourneyNo(siteTourneyNo)""" elif(self.dbname == 'PostgreSQL'): - # FIXME: This query has a different syntax self.query['addTourneyIndex'] = """CREATE INDEX siteTourneyNo ON Tourneys (siteTourneyNo)""" elif(self.dbname == 'SQLite'): self.query['addHandsIndex'] = """ """ @@ -584,7 +583,6 @@ class FpdbSQLQueries: if(self.dbname == 'MySQL InnoDB'): self.query['addHandsIndex'] = """ALTER TABLE Hands ADD INDEX siteHandNo(siteHandNo)""" elif(self.dbname == 'PostgreSQL'): - # FIXME: This query has a different syntax self.query['addHandsIndex'] = """CREATE INDEX siteHandNo ON Hands (siteHandNo)""" elif(self.dbname == 'SQLite'): self.query['addHandsIndex'] = """ """ @@ -592,7 +590,6 @@ class FpdbSQLQueries: if(self.dbname == 'MySQL InnoDB'): self.query['addPlayersIndex'] = """ALTER TABLE Players ADD INDEX name(name)""" elif(self.dbname == 'PostgreSQL'): - # FIXME: This query has a different syntax self.query['addPlayersIndex'] = """CREATE INDEX name ON Players (name)""" elif(self.dbname == 'SQLite'): self.query['addPlayersIndex'] = """ """ @@ -633,6 +630,11 @@ class FpdbSQLQueries: WHERE Players.name = %s AND HandsPlayers.handId = %s AND Players.siteId = %s AND (tourneysPlayersId IS NULL)""" + if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'): + self.query['getPlayerId'] = """SELECT id from Players where name = %s""" + elif(self.dbname == 'SQLite'): + self.query['getPlayerId'] = """SELECT id from Players where name = %s""" + if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'): self.query['getRingProfitAllHandsPlayerIdSite'] = """ SELECT hp.handId, hp.winnings, SUM(ha.amount), hp.winnings - SUM(ha.amount) @@ -702,8 +704,7 @@ class FpdbSQLQueries: from Gametypes gt inner join Sites s on s.Id = gt.siteId inner join HudCache hc on hc.gameTypeId = gt.Id - where gt.limittype = 'nl' - and hc.playerId in (3) # use here? + where hc.playerId in # use here ? group by hc.gametypeId ) stats @@ -716,7 +717,7 @@ class FpdbSQLQueries: from HandsPlayers hp inner join Hands h ON h.id = hp.handId inner join HandsActions ha ON ha.handPlayerId = hp.id - where hp.playerId in (3) # use here? + where hp.playerId in # use here ? and hp.tourneysPlayersId IS NULL group by hp.handId, h.gameTypeId, hp.position, hp.winnings diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index b6733984..7d689228 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -31,7 +31,9 @@ class GuiPlayerStats (threading.Thread): return self.main_hbox def toggleCallback(self, widget, data=None): - print "%s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()]) +# print "%s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()]) + self.activesite = data + print "DEBUG: activesite set to %s" %(self.activesite) def refreshStats(self, widget, data): try: self.stats_table.destroy() @@ -39,7 +41,14 @@ class GuiPlayerStats (threading.Thread): self.fillStatsFrame(self.stats_frame) def fillStatsFrame(self, vbox): - self.cursor.execute(self.sql.query['playerStats']) + # Get currently active site and grab playerid + tmp = self.sql.query['playerStats'] + + result = self.cursor.execute(self.sql.query['getPlayerId'], self.heroes[self.activesite]) + result = self.db.cursor.fetchall() + pid = result[0][0] + tmp = tmp.replace("", "(" + str(pid) + ")") + self.cursor.execute(tmp) result = self.db.cursor.fetchall() cols = 18 rows = len(result)+1 # +1 for title row @@ -61,7 +70,6 @@ class GuiPlayerStats (threading.Thread): for row in range(rows-1): for col in range(cols): - print "result[%s][%s]: %s" %(row-1, col, result[row-1][col]) if(row%2 == 0): bgcolor = "white" else: @@ -92,10 +100,15 @@ class GuiPlayerStats (threading.Thread): hbox.show() def createPlayerLine(self, hbox, site, player): - button = gtk.RadioButton(None, site + " id:") + if(self.buttongroup == None): + button = gtk.RadioButton(None, site + " id:") + button.set_active(True) + self.buttongroup = button + self.activesite = site + else: + button = gtk.RadioButton(self.buttongroup, site + " id:") hbox.pack_start(button, True, True, 0) button.connect("toggled", self.toggleCallback, site) -# button.set_active(True) button.show() pname = gtk.Entry() @@ -119,6 +132,9 @@ class GuiPlayerStats (threading.Thread): self.sql = querylist + self.activesite = None + self.buttongroup = None + self.heroes = {} self.stat_table = None self.stats_frame = None @@ -138,11 +154,11 @@ class GuiPlayerStats (threading.Thread): statsFrame = gtk.Frame("Stats:") statsFrame.set_label_align(0.0, 0.0) statsFrame.show() - vbox = gtk.VBox(False, 0) - vbox.show() + self.stats_frame = gtk.VBox(False, 0) + self.stats_frame.show() - self.fillStatsFrame(vbox) - statsFrame.add(vbox) + self.fillStatsFrame(self.stats_frame) + statsFrame.add(self.stats_frame) self.main_hbox.pack_start(playerFrame) self.main_hbox.pack_start(statsFrame) From edd3d3ec0769660b7916811ea24e4454a8ddae39 Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 7 Dec 2008 17:35:37 +0900 Subject: [PATCH 21/32] White space churn to RegressionTester --- pyfpdb/RegressionTest.py | 114 +++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/pyfpdb/RegressionTest.py b/pyfpdb/RegressionTest.py index 26588ba0..2b09d248 100644 --- a/pyfpdb/RegressionTest.py +++ b/pyfpdb/RegressionTest.py @@ -35,72 +35,72 @@ import unittest class TestSequenceFunctions(unittest.TestCase): - def setUp(self): - """Configure MySQL settings/database and establish connection""" - self.c = Configuration.Config() - self.mysql_settings={ 'db-host':"localhost", - 'db-backend':2, - 'db-databaseName':"fpdbtest", - 'db-user':"fpdb", - 'db-password':"fpdb"} - self.mysql_db = fpdb_db.fpdb_db() - self.mysql_db.connect(self.mysql_settings['db-backend'], self.mysql_settings['db-host'], - self.mysql_settings['db-databaseName'], self.mysql_settings['db-user'], - self.mysql_settings['db-password']) - self.mysqldict = FpdbSQLQueries.FpdbSQLQueries('MySQL InnoDB') - self.mysqlimporter = fpdb_import.Importer(self, self.mysql_settings, self.c) - self.mysqlimporter.setCallHud(False) + def setUp(self): + """Configure MySQL settings/database and establish connection""" + self.c = Configuration.Config() + self.mysql_settings={ 'db-host':"localhost", + 'db-backend':2, + 'db-databaseName':"fpdbtest", + 'db-user':"fpdb", + 'db-password':"fpdb"} + self.mysql_db = fpdb_db.fpdb_db() + self.mysql_db.connect(self.mysql_settings['db-backend'], self.mysql_settings['db-host'], + self.mysql_settings['db-databaseName'], self.mysql_settings['db-user'], + self.mysql_settings['db-password']) + self.mysqldict = FpdbSQLQueries.FpdbSQLQueries('MySQL InnoDB') + self.mysqlimporter = fpdb_import.Importer(self, self.mysql_settings, self.c) + self.mysqlimporter.setCallHud(False) -# """Configure Postgres settings/database and establish connection""" -# self.pg_settings={ 'db-host':"localhost", 'db-backend':3, 'db-databaseName':"fpdbtest", 'db-user':"fpdb", 'db-password':"fpdb"} -# self.pg_db = fpdb_db.fpdb_db() -# self.pg_db.connect(self.pg_settings['db-backend'], self.pg_settings['db-host'], -# self.pg_settings['db-databaseName'], self.pg_settings['db-user'], -# self.pg_settings['db-password']) -# self.pgdict = FpdbSQLQueries.FpdbSQLQueries('PostgreSQL') +# """Configure Postgres settings/database and establish connection""" +# self.pg_settings={ 'db-host':"localhost", 'db-backend':3, 'db-databaseName':"fpdbtest", 'db-user':"fpdb", 'db-password':"fpdb"} +# self.pg_db = fpdb_db.fpdb_db() +# self.pg_db.connect(self.pg_settings['db-backend'], self.pg_settings['db-host'], +# self.pg_settings['db-databaseName'], self.pg_settings['db-user'], +# self.pg_settings['db-password']) +# self.pgdict = FpdbSQLQueries.FpdbSQLQueries('PostgreSQL') - def testDatabaseConnection(self): - """Test all supported DBs""" - self.result = self.mysql_db.cursor.execute(self.mysqldict.query['list_tables']) - self.failUnless(self.result==13, "Number of tables in database incorrect. Expected 13 got " + str(self.result)) + def testDatabaseConnection(self): + """Test all supported DBs""" + self.result = self.mysql_db.cursor.execute(self.mysqldict.query['list_tables']) + self.failUnless(self.result==13, "Number of tables in database incorrect. Expected 13 got " + str(self.result)) -# self.result = self.pg_db.cursor.execute(self.pgdict.query['list_tables']) -# self.failUnless(self.result==13, "Number of tables in database incorrect. Expected 13 got " + str(self.result)) +# self.result = self.pg_db.cursor.execute(self.pgdict.query['list_tables']) +# self.failUnless(self.result==13, "Number of tables in database incorrect. Expected 13 got " + str(self.result)) - def testMySQLRecreateTables(self): - """Test droping then recreating fpdb table schema""" - self.mysql_db.recreate_tables() - self.result = self.mysql_db.cursor.execute("SHOW TABLES") - self.failUnless(self.result==13, "Number of tables in database incorrect. Expected 13 got " + str(self.result)) + def testMySQLRecreateTables(self): + """Test droping then recreating fpdb table schema""" + self.mysql_db.recreate_tables() + self.result = self.mysql_db.cursor.execute("SHOW TABLES") + self.failUnless(self.result==13, "Number of tables in database incorrect. Expected 13 got " + str(self.result)) - def testPokerStarsHHDate(self): - latest = "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]" - previous = "PokerStars Game #21969660557: Hold'em No Limit ($0.50/$1.00) - 2008/08/17 - 01:14:43 (ET)" - older1 = "PokerStars Game #21969660557: Hold'em No Limit ($0.50/$1.00) - 2008/09/07 06:23:14 ET" + def testPokerStarsHHDate(self): + latest = "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]" + previous = "PokerStars Game #21969660557: Hold'em No Limit ($0.50/$1.00) - 2008/08/17 - 01:14:43 (ET)" + older1 = "PokerStars Game #21969660557: Hold'em No Limit ($0.50/$1.00) - 2008/09/07 06:23:14 ET" - result = fpdb_simple.parseHandStartTime(older1, "ps") - self.failUnless(result==datetime.datetime(2008,9,7,11,23,14), - "Date incorrect, expected: 2008-09-07 11:23:14 got: " + str(result)) - result = fpdb_simple.parseHandStartTime(latest, "ps") - self.failUnless(result==datetime.datetime(2008,11,12,15,00,48), - "Date incorrect, expected: 2008-11-12 15:00:48 got: " + str(result)) - result = fpdb_simple.parseHandStartTime(previous, "ps") - self.failUnless(result==datetime.datetime(2008,8,17,6,14,43), - "Date incorrect, expected: 2008-08-17 01:14:43 got: " + str(result)) + result = fpdb_simple.parseHandStartTime(older1, "ps") + self.failUnless(result==datetime.datetime(2008,9,7,11,23,14), + "Date incorrect, expected: 2008-09-07 11:23:14 got: " + str(result)) + result = fpdb_simple.parseHandStartTime(latest, "ps") + self.failUnless(result==datetime.datetime(2008,11,12,15,00,48), + "Date incorrect, expected: 2008-11-12 15:00:48 got: " + str(result)) + result = fpdb_simple.parseHandStartTime(previous, "ps") + self.failUnless(result==datetime.datetime(2008,8,17,6,14,43), + "Date incorrect, expected: 2008-08-17 01:14:43 got: " + str(result)) - def testImportHandHistoryFiles(self): - """Test import of single HH file""" - self.mysqlimporter.addImportFile("regression-test-files/hand-histories/ps-lhe-ring-3hands.txt") - self.mysqlimporter.runImport() - self.mysqlimporter.addImportDirectory("regression-test-files/hand-histories") - self.mysqlimporter.runImport() + def testImportHandHistoryFiles(self): + """Test import of single HH file""" + self.mysqlimporter.addImportFile("regression-test-files/hand-histories/ps-lhe-ring-3hands.txt") + self.mysqlimporter.runImport() + self.mysqlimporter.addImportDirectory("regression-test-files/hand-histories") + self.mysqlimporter.runImport() -# def testPostgresSQLRecreateTables(self): -# """Test droping then recreating fpdb table schema""" -# self.pg_db.recreate_tables() -# self.result = self.pg_db.cursor.execute(self.pgdict.query['list_tables']) -# self.failUnless(self.result==13, "Number of tables in database incorrect. Expected 13 got " + str(self.result)) +# def testPostgresSQLRecreateTables(self): +# """Test droping then recreating fpdb table schema""" +# self.pg_db.recreate_tables() +# self.result = self.pg_db.cursor.execute(self.pgdict.query['list_tables']) +# self.failUnless(self.result==13, "Number of tables in database incorrect. Expected 13 got " + str(self.result)) if __name__ == '__main__': unittest.main() From ec01f7ae4011f3046e25f8e90804bb11c57b6afd Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 7 Dec 2008 17:23:38 +0000 Subject: [PATCH 22/32] move code closer to carl's repo --- pyfpdb/FpdbSQLQueries.py | 1305 ++++++++++++++++++++++---------------- pyfpdb/fpdb_db.py | 247 ++++---- 2 files changed, 885 insertions(+), 667 deletions(-) diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index 9b791f5d..b3dbf8c7 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -26,585 +26,616 @@ import os class FpdbSQLQueries: - def __init__(self, db): - self.query = {} - self.dbname = db + def __init__(self, db): + self.query = {} + self.dbname = db -#Boilerplate code. -# if(self.dbname == 'MySQL InnoDB'): -# self.query[''] = """ """ -# elif(self.dbname == 'PostgreSQL'): -# elif(self.dbname == 'SQLite'): + ################################ + # List tables + ################################ + if(self.dbname == 'MySQL InnoDB'): + self.query['list_tables'] = """SHOW TABLES""" + elif(self.dbname == 'PostgreSQL'): + self.query['list_tables'] = """SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'""" + elif(self.dbname == 'SQLite'): + self.query['list_tables'] = """ """ + + ################################################################## + # Drop Tables - MySQL, PostgreSQL and SQLite all share same syntax + ################################################################## + + if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'): + self.query['drop_table'] = """DROP TABLE IF EXISTS """ - ################################ - # List tables - ################################ - if(self.dbname == 'MySQL InnoDB'): - self.query['list_tables'] = """SHOW TABLES""" - elif(self.dbname == 'PostgreSQL'): - self.query['list_tables'] = """SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'""" - elif(self.dbname == 'SQLite'): - self.query['list_tables'] = """ """ + ################################ + # Create Tables + ################################ - ################################################################## - # Drop Tables - MySQL, PostgreSQL and SQLite all share same syntax - ################################################################## + ################################ + # Create Settings + ################################ + if(self.dbname == 'MySQL InnoDB'): + self.query['createSettingsTable'] = """CREATE TABLE Settings ( + version SMALLINT NOT NULL) + ENGINE=INNODB""" + elif(self.dbname == 'PostgreSQL'): + self.query['createSettingsTable'] = """CREATE TABLE Settings (version SMALLINT)""" - if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'): - self.query['drop_table'] = """DROP TABLE IF EXISTS """ - - - ################################ - # Create Tables - ################################ - - ################################ - # Create Settings - ################################ - if(self.dbname == 'MySQL InnoDB'): - self.query['createSettingsTable'] = """CREATE TABLE Settings ( - version SMALLINT NOT NULL) - ENGINE=INNODB""" - elif(self.dbname == 'PostgreSQL'): - self.query['createSettingsTable'] = """CREATE TABLE Settings (version SMALLINT)""" - - elif(self.dbname == 'SQLite'): + elif(self.dbname == 'SQLite'): #Probably doesn't work. - self.query['createSettingsTable'] = """ """ + self.query['createSettingsTable'] = """ """ - ################################ - # Create Sites - ################################ + ################################ + # Create Sites + ################################ - if(self.dbname == 'MySQL InnoDB'): - self.query['createSitesTable'] = """CREATE TABLE Sites ( - id SMALLINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), - name varchar(32) NOT NULL, - currency char(3) NOT NULL) - ENGINE=INNODB""" - elif(self.dbname == 'PostgreSQL'): - self.query['createSitesTable'] = """CREATE TABLE Sites ( - id SERIAL UNIQUE, PRIMARY KEY (id), - name varchar(32), - currency char(3))""" - elif(self.dbname == 'SQLite'): - self.query['createSitesTable'] = """ """ + if(self.dbname == 'MySQL InnoDB'): + self.query['createSitesTable'] = """CREATE TABLE Sites ( + id SMALLINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + name varchar(32) NOT NULL, + currency char(3) NOT NULL) + ENGINE=INNODB""" + elif(self.dbname == 'PostgreSQL'): + self.query['createSitesTable'] = """CREATE TABLE Sites ( + id SERIAL, PRIMARY KEY (id), + name varchar(32), + currency char(3))""" + elif(self.dbname == 'SQLite'): + self.query['createSitesTable'] = """ """ - ################################ - # Create Gametypes - ################################ + ################################ + # Create Gametypes + ################################ - if(self.dbname == 'MySQL InnoDB'): - self.query['createGametypesTable'] = """CREATE TABLE Gametypes ( - id SMALLINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), - siteId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id), - type char(4) NOT NULL, - base char(4) NOT NULL, - category varchar(9) NOT NULL, - limitType char(2) NOT NULL, - hiLo char(1) NOT NULL, - smallBlind int, - bigBlind int, - smallBet int NOT NULL, - bigBet int NOT NULL) - ENGINE=INNODB""" - elif(self.dbname == 'PostgreSQL'): - self.query['createGametypesTable'] = """CREATE TABLE Gametypes ( - id SERIAL UNIQUE, PRIMARY KEY (id), - siteId INTEGER, FOREIGN KEY (siteId) REFERENCES Sites(id), - type char(4), - base char(4), - category varchar(9), - limitType char(2), - hiLo char(1), - smallBlind int, - bigBlind int, - smallBet int, - bigBet int)""" - elif(self.dbname == 'SQLite'): - self.query['createGametypesTable'] = """ """ + if(self.dbname == 'MySQL InnoDB'): + self.query['createGametypesTable'] = """CREATE TABLE Gametypes ( + id SMALLINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + siteId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id), + type char(4) NOT NULL, + base char(4) NOT NULL, + category varchar(9) NOT NULL, + limitType char(2) NOT NULL, + hiLo char(1) NOT NULL, + smallBlind int, + bigBlind int, + smallBet int NOT NULL, + bigBet int NOT NULL) + ENGINE=INNODB""" + elif(self.dbname == 'PostgreSQL'): + self.query['createGametypesTable'] = """CREATE TABLE Gametypes ( + id SERIAL, PRIMARY KEY (id), + siteId INTEGER, FOREIGN KEY (siteId) REFERENCES Sites(id), + type char(4), + base char(4), + category varchar(9), + limitType char(2), + hiLo char(1), + smallBlind int, + bigBlind int, + smallBet int, + bigBet int)""" + elif(self.dbname == 'SQLite'): + self.query['createGametypesTable'] = """ """ - ################################ - # Create Players - ################################ + ################################ + # Create Players + ################################ - if(self.dbname == 'MySQL InnoDB'): - self.query['createPlayersTable'] = """CREATE TABLE Players ( - id INT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), - name VARCHAR(32) CHARACTER SET utf8 NOT NULL, - siteId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id), - comment text, - commentTs DATETIME) - ENGINE=INNODB""" - elif(self.dbname == 'PostgreSQL'): - self.query['createPlayersTable'] = """CREATE TABLE Players ( - id SERIAL UNIQUE, PRIMARY KEY (id), - name VARCHAR(32), - siteId INTEGER, FOREIGN KEY (siteId) REFERENCES Sites(id), - comment text, - commentTs timestamp without time zone)""" - elif(self.dbname == 'SQLite'): - self.query['createPlayersTable'] = """ """ + if(self.dbname == 'MySQL InnoDB'): + self.query['createPlayersTable'] = """CREATE TABLE Players ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + name VARCHAR(32) CHARACTER SET utf8 NOT NULL, + siteId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id), + comment text, + commentTs DATETIME) + ENGINE=INNODB""" + elif(self.dbname == 'PostgreSQL'): + self.query['createPlayersTable'] = """CREATE TABLE Players ( + id SERIAL, PRIMARY KEY (id), + name VARCHAR(32), + siteId INTEGER, FOREIGN KEY (siteId) REFERENCES Sites(id), + comment text, + commentTs timestamp without time zone)""" + elif(self.dbname == 'SQLite'): + self.query['createPlayersTable'] = """ """ - ################################ - # Create Autorates - ################################ + ################################ + # Create Autorates + ################################ - if(self.dbname == 'MySQL InnoDB'): - self.query['createAutoratesTable'] = """CREATE TABLE Autorates ( - id BIGINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), - playerId INT UNSIGNED NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id), - gametypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), - description varchar(50) NOT NULL, - shortDesc char(8) NOT NULL, - ratingTime DATETIME NOT NULL, - handCount int NOT NULL) - ENGINE=INNODB""" - elif(self.dbname == 'PostgreSQL'): - self.query['createAutoratesTable'] = """CREATE TABLE Autorates ( - id BIGSERIAL UNIQUE, PRIMARY KEY (id), - playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id), - gametypeId INT, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), - description varchar(50), - shortDesc char(8), - ratingTime timestamp without time zone, - handCount int)""" - elif(self.dbname == 'SQLite'): - self.query['createAutoratesTable'] = """ """ + if(self.dbname == 'MySQL InnoDB'): + self.query['createAutoratesTable'] = """CREATE TABLE Autorates ( + id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + playerId INT UNSIGNED NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id), + gametypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), + description varchar(50) NOT NULL, + shortDesc char(8) NOT NULL, + ratingTime DATETIME NOT NULL, + handCount int NOT NULL) + ENGINE=INNODB""" + elif(self.dbname == 'PostgreSQL'): + self.query['createAutoratesTable'] = """CREATE TABLE Autorates ( + id BIGSERIAL, PRIMARY KEY (id), + playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id), + gametypeId INT, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), + description varchar(50), + shortDesc char(8), + ratingTime timestamp without time zone, + handCount int)""" + elif(self.dbname == 'SQLite'): + self.query['createAutoratesTable'] = """ """ - ################################ - # Create Hands - ################################ + ################################ + # Create Hands + ################################ - if(self.dbname == 'MySQL InnoDB'): - self.query['createHandsTable'] = """CREATE TABLE Hands ( - id BIGINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), - tableName VARCHAR(20) NOT NULL, - siteHandNo BIGINT NOT NULL, - gametypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), - handStart DATETIME NOT NULL, - importTime DATETIME NOT NULL, - seats SMALLINT NOT NULL, - maxSeats SMALLINT NOT NULL, - comment TEXT, - commentTs DATETIME) - ENGINE=INNODB""" - elif(self.dbname == 'PostgreSQL'): - self.query['createHandsTable'] = """CREATE TABLE Hands ( - id BIGSERIAL UNIQUE, PRIMARY KEY (id), - tableName VARCHAR(20), - siteHandNo BIGINT, - gametypeId INT, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), - handStart timestamp without time zone, - importTime timestamp without time zone, - seats SMALLINT, - maxSeats SMALLINT, - comment TEXT, - commentTs timestamp without time zone)""" - elif(self.dbname == 'SQLite'): - self.query['createHandsTable'] = """ """ + if(self.dbname == 'MySQL InnoDB'): + self.query['createHandsTable'] = """CREATE TABLE Hands ( + id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + tableName VARCHAR(20) NOT NULL, + siteHandNo BIGINT NOT NULL, + gametypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), + handStart DATETIME NOT NULL, + importTime DATETIME NOT NULL, + seats SMALLINT NOT NULL, + maxSeats SMALLINT NOT NULL, + comment TEXT, + commentTs DATETIME) + ENGINE=INNODB""" + elif(self.dbname == 'PostgreSQL'): + self.query['createHandsTable'] = """CREATE TABLE Hands ( + id BIGSERIAL, PRIMARY KEY (id), + tableName VARCHAR(20), + siteHandNo BIGINT, + gametypeId INT, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), + handStart timestamp without time zone, + importTime timestamp without time zone, + seats SMALLINT, + maxSeats SMALLINT, + comment TEXT, + commentTs timestamp without time zone)""" + elif(self.dbname == 'SQLite'): + self.query['createHandsTable'] = """ """ - ################################ - # Create Gametypes - ################################ + ################################ + # Create Gametypes + ################################ - if(self.dbname == 'MySQL InnoDB'): - self.query['createBoardCardsTable'] = """CREATE TABLE BoardCards ( - id BIGINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), - handId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handId) REFERENCES Hands(id), - card1Value smallint NOT NULL, - card1Suit char(1) NOT NULL, - card2Value smallint NOT NULL, - card2Suit char(1) NOT NULL, - card3Value smallint NOT NULL, - card3Suit char(1) NOT NULL, - card4Value smallint NOT NULL, - card4Suit char(1) NOT NULL, - card5Value smallint NOT NULL, - card5Suit char(1) NOT NULL) - ENGINE=INNODB""" - elif(self.dbname == 'PostgreSQL'): - self.query['createBoardCardsTable'] = """CREATE TABLE BoardCards ( - id BIGSERIAL UNIQUE, PRIMARY KEY (id), - handId BIGINT, FOREIGN KEY (handId) REFERENCES Hands(id), - card1Value smallint, - card1Suit char(1), - card2Value smallint, - card2Suit char(1), - card3Value smallint, - card3Suit char(1), - card4Value smallint, - card4Suit char(1), - card5Value smallint, - card5Suit char(1))""" - elif(self.dbname == 'SQLite'): - self.query['createBoardCardsTable'] = """ """ + if(self.dbname == 'MySQL InnoDB'): + self.query['createBoardCardsTable'] = """CREATE TABLE BoardCards ( + id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + handId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handId) REFERENCES Hands(id), + card1Value smallint NOT NULL, + card1Suit char(1) NOT NULL, + card2Value smallint NOT NULL, + card2Suit char(1) NOT NULL, + card3Value smallint NOT NULL, + card3Suit char(1) NOT NULL, + card4Value smallint NOT NULL, + card4Suit char(1) NOT NULL, + card5Value smallint NOT NULL, + card5Suit char(1) NOT NULL) + ENGINE=INNODB""" + elif(self.dbname == 'PostgreSQL'): + self.query['createBoardCardsTable'] = """CREATE TABLE BoardCards ( + id BIGSERIAL, PRIMARY KEY (id), + handId BIGINT, FOREIGN KEY (handId) REFERENCES Hands(id), + card1Value smallint, + card1Suit char(1), + card2Value smallint, + card2Suit char(1), + card3Value smallint, + card3Suit char(1), + card4Value smallint, + card4Suit char(1), + card5Value smallint, + card5Suit char(1))""" + elif(self.dbname == 'SQLite'): + self.query['createBoardCardsTable'] = """ """ - ################################ - # Create TourneyTypes - ################################ + ################################ + # Create TourneyTypes + ################################ - if(self.dbname == 'MySQL InnoDB'): - self.query['createTourneyTypesTable'] = """CREATE TABLE TourneyTypes ( - id SMALLINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), - siteId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id), - buyin INT NOT NULL, - fee INT NOT NULL, - knockout INT NOT NULL, - rebuyOrAddon BOOLEAN NOT NULL) - ENGINE=INNODB""" - elif(self.dbname == 'PostgreSQL'): - self.query['createTourneyTypesTable'] = """CREATE TABLE TourneyTypes ( - id SERIAL, PRIMARY KEY (id), - siteId INT, FOREIGN KEY (siteId) REFERENCES Sites(id), - buyin INT, - fee INT, - knockout INT, - rebuyOrAddon BOOLEAN)""" - elif(self.dbname == 'SQLite'): - self.query['createTourneyTypesTable'] = """ """ + if(self.dbname == 'MySQL InnoDB'): + self.query['createTourneyTypesTable'] = """CREATE TABLE TourneyTypes ( + id SMALLINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + siteId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id), + buyin INT NOT NULL, + fee INT NOT NULL, + knockout INT NOT NULL, + rebuyOrAddon BOOLEAN NOT NULL) + ENGINE=INNODB""" + elif(self.dbname == 'PostgreSQL'): + self.query['createTourneyTypesTable'] = """CREATE TABLE TourneyTypes ( + id SERIAL, PRIMARY KEY (id), + siteId INT, FOREIGN KEY (siteId) REFERENCES Sites(id), + buyin INT, + fee INT, + knockout INT, + rebuyOrAddon BOOLEAN)""" + elif(self.dbname == 'SQLite'): + self.query['createTourneyTypesTable'] = """ """ - ################################ - # Create Tourneys - ################################ + ################################ + # Create Tourneys + ################################ - if(self.dbname == 'MySQL InnoDB'): - self.query['createTourneysTable'] = """CREATE TABLE Tourneys ( - id INT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), - tourneyTypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), - siteTourneyNo BIGINT NOT NULL, - entries INT NOT NULL, - prizepool INT NOT NULL, - startTime DATETIME NOT NULL, - comment TEXT, - commentTs DATETIME) - ENGINE=INNODB""" - elif(self.dbname == 'PostgreSQL'): - self.query['createTourneysTable'] = """CREATE TABLE Tourneys ( - id SERIAL UNIQUE, PRIMARY KEY (id), - tourneyTypeId INT, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), - siteTourneyNo BIGINT, - entries INT, - prizepool INT, - startTime timestamp without time zone, - comment TEXT, - commentTs timestamp without time zone)""" - elif(self.dbname == 'SQLite'): - self.query['createTourneysTable'] = """ """ + if(self.dbname == 'MySQL InnoDB'): + self.query['createTourneysTable'] = """CREATE TABLE Tourneys ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + tourneyTypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), + siteTourneyNo BIGINT NOT NULL, + entries INT NOT NULL, + prizepool INT NOT NULL, + startTime DATETIME NOT NULL, + comment TEXT, + commentTs DATETIME) + ENGINE=INNODB""" + elif(self.dbname == 'PostgreSQL'): + self.query['createTourneysTable'] = """CREATE TABLE Tourneys ( + id SERIAL, PRIMARY KEY (id), + tourneyTypeId INT, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), + siteTourneyNo BIGINT, + entries INT, + prizepool INT, + startTime timestamp without time zone, + comment TEXT, + commentTs timestamp without time zone)""" + elif(self.dbname == 'SQLite'): + self.query['createTourneysTable'] = """ """ - ################################ - # Create HandsPlayers - ################################ + ################################ + # Create HandsPlayers + ################################ - if(self.dbname == 'MySQL InnoDB'): - self.query['createHandsPlayersTable'] = """CREATE TABLE HandsPlayers ( - id BIGINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), - handId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handId) REFERENCES Hands(id), - playerId INT UNSIGNED NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id), - startCash INT NOT NULL, - position CHAR(1), - seatNo SMALLINT NOT NULL, - ante INT, - - card1Value smallint NOT NULL, - card1Suit char(1) NOT NULL, - card2Value smallint NOT NULL, - card2Suit char(1) NOT NULL, - card3Value smallint, - card3Suit char(1), - card4Value smallint, - card4Suit char(1), - card5Value smallint, - card5Suit char(1), - card6Value smallint, - card6Suit char(1), - card7Value smallint, - card7Suit char(1), - - winnings int NOT NULL, - rake int NOT NULL, - comment text, - commentTs DATETIME, - - tourneysPlayersId BIGINT UNSIGNED, FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id)) - ENGINE=INNODB""" - elif(self.dbname == 'PostgreSQL'): - self.query['createHandsPlayersTable'] = """CREATE TABLE HandsPlayers ( - id BIGSERIAL UNIQUE, PRIMARY KEY (id), - handId BIGINT, FOREIGN KEY (handId) REFERENCES Hands(id), - playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id), - startCash INT, - position CHAR(1), - seatNo SMALLINT, - ante INT, + if(self.dbname == 'MySQL InnoDB'): + self.query['createHandsPlayersTable'] = """CREATE TABLE HandsPlayers ( + id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + handId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handId) REFERENCES Hands(id), + playerId INT UNSIGNED NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id), + startCash INT NOT NULL, + position CHAR(1), + seatNo SMALLINT NOT NULL, + ante INT, + + card1Value smallint NOT NULL, + card1Suit char(1) NOT NULL, + card2Value smallint NOT NULL, + card2Suit char(1) NOT NULL, + card3Value smallint, + card3Suit char(1), + card4Value smallint, + card4Suit char(1), + card5Value smallint, + card5Suit char(1), + card6Value smallint, + card6Suit char(1), + card7Value smallint, + card7Suit char(1), + + winnings int NOT NULL, + rake int NOT NULL, + comment text, + commentTs DATETIME, + + tourneysPlayersId BIGINT UNSIGNED, FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id)) + ENGINE=INNODB""" + elif(self.dbname == 'PostgreSQL'): + self.query['createHandsPlayersTable'] = """CREATE TABLE HandsPlayers ( + id BIGSERIAL, PRIMARY KEY (id), + handId BIGINT, FOREIGN KEY (handId) REFERENCES Hands(id), + playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id), + startCash INT, + position CHAR(1), + seatNo SMALLINT, + ante INT, - card1Value smallint, - card1Suit char(1), - card2Value smallint, - card2Suit char(1), - card3Value smallint, - card3Suit char(1), - card4Value smallint, - card4Suit char(1), - card5Value smallint, - card5Suit char(1), - card6Value smallint, - card6Suit char(1), - card7Value smallint, - card7Suit char(1), + card1Value smallint, + card1Suit char(1), + card2Value smallint, + card2Suit char(1), + card3Value smallint, + card3Suit char(1), + card4Value smallint, + card4Suit char(1), + card5Value smallint, + card5Suit char(1), + card6Value smallint, + card6Suit char(1), + card7Value smallint, + card7Suit char(1), - winnings int, - rake int, - comment text, - commentTs timestamp without time zone, - tourneysPlayersId BIGINT, FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id))""" - elif(self.dbname == 'SQLite'): - self.query['createHandsPlayersTable'] = """ """ + winnings int, + rake int, + comment text, + commentTs timestamp without time zone, + tourneysPlayersId BIGINT, FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id))""" + elif(self.dbname == 'SQLite'): + self.query['createHandsPlayersTable'] = """ """ - ################################ - # Create TourneysPlayers - ################################ + ################################ + # Create TourneysPlayers + ################################ - if(self.dbname == 'MySQL InnoDB'): - self.query['createTourneysPlayersTable'] = """CREATE TABLE TourneysPlayers ( - id BIGINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), - tourneyId INT UNSIGNED NOT NULL, FOREIGN KEY (tourneyId) REFERENCES Tourneys(id), - playerId INT UNSIGNED NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id), - payinAmount INT NOT NULL, - rank INT NOT NULL, - winnings INT NOT NULL, - comment TEXT, - commentTs DATETIME) - ENGINE=INNODB""" - elif(self.dbname == 'PostgreSQL'): - self.query['createTourneysPlayersTable'] = """CREATE TABLE TourneysPlayers ( - id BIGSERIAL UNIQUE, PRIMARY KEY (id), - tourneyId INT, FOREIGN KEY (tourneyId) REFERENCES Tourneys(id), - playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id), - payinAmount INT, - rank INT, - winnings INT, - comment TEXT, - commentTs timestamp without time zone)""" - elif(self.dbname == 'SQLite'): - self.query['createTourneysPlayersTable'] = """ """ + if(self.dbname == 'MySQL InnoDB'): + self.query['createTourneysPlayersTable'] = """CREATE TABLE TourneysPlayers ( + id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + tourneyId INT UNSIGNED NOT NULL, FOREIGN KEY (tourneyId) REFERENCES Tourneys(id), + playerId INT UNSIGNED NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id), + payinAmount INT NOT NULL, + rank INT NOT NULL, + winnings INT NOT NULL, + comment TEXT, + commentTs DATETIME) + ENGINE=INNODB""" + elif(self.dbname == 'PostgreSQL'): + self.query['createTourneysPlayersTable'] = """CREATE TABLE TourneysPlayers ( + id BIGSERIAL, PRIMARY KEY (id), + tourneyId INT, FOREIGN KEY (tourneyId) REFERENCES Tourneys(id), + playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id), + payinAmount INT, + rank INT, + winnings INT, + comment TEXT, + commentTs timestamp without time zone)""" + elif(self.dbname == 'SQLite'): + self.query['createTourneysPlayersTable'] = """ """ - ################################ - # Create HandsActions - ################################ + ################################ + # Create HandsActions + ################################ - if(self.dbname == 'MySQL InnoDB'): - self.query['createHandsActionsTable'] = """CREATE TABLE HandsActions ( - id BIGINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), - handPlayerId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handPlayerId) REFERENCES HandsPlayers(id), - street SMALLINT NOT NULL, - actionNo SMALLINT NOT NULL, - action CHAR(5) NOT NULL, - allIn BOOLEAN NOT NULL, - amount INT NOT NULL, - comment TEXT, - commentTs DATETIME) - ENGINE=INNODB""" - elif(self.dbname == 'PostgreSQL'): - self.query['createHandsActionsTable'] = """CREATE TABLE HandsActions ( - id BIGSERIAL UNIQUE, PRIMARY KEY (id), - handPlayerId BIGINT, FOREIGN KEY (handPlayerId) REFERENCES HandsPlayers(id), - street SMALLINT, - actionNo SMALLINT, - action CHAR(5), - allIn BOOLEAN, - amount INT, - comment TEXT, - commentTs timestamp without time zone)""" - elif(self.dbname == 'SQLite'): - self.query['createHandsActionsTable'] = """ """ + if(self.dbname == 'MySQL InnoDB'): + self.query['createHandsActionsTable'] = """CREATE TABLE HandsActions ( + id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + handPlayerId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handPlayerId) REFERENCES HandsPlayers(id), + street SMALLINT NOT NULL, + actionNo SMALLINT NOT NULL, + action CHAR(5) NOT NULL, + allIn BOOLEAN NOT NULL, + amount INT NOT NULL, + comment TEXT, + commentTs DATETIME) + ENGINE=INNODB""" + elif(self.dbname == 'PostgreSQL'): + self.query['createHandsActionsTable'] = """CREATE TABLE HandsActions ( + id BIGSERIAL, PRIMARY KEY (id), + handPlayerId BIGINT, FOREIGN KEY (handPlayerId) REFERENCES HandsPlayers(id), + street SMALLINT, + actionNo SMALLINT, + action CHAR(5), + allIn BOOLEAN, + amount INT, + comment TEXT, + commentTs timestamp without time zone)""" + elif(self.dbname == 'SQLite'): + self.query['createHandsActionsTable'] = """ """ - ################################ - # Create HudCache - ################################ + ################################ + # Create HudCache + ################################ - if(self.dbname == 'MySQL InnoDB'): - self.query['createHudCacheTable'] = """CREATE TABLE HudCache ( - id BIGINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), - gametypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), - playerId INT UNSIGNED NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id), - activeSeats SMALLINT NOT NULL, - position CHAR(1), - tourneyTypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), - - HDs INT NOT NULL, - street0VPI INT NOT NULL, - street0Aggr INT NOT NULL, - street0_3B4BChance INT NOT NULL, - street0_3B4BDone INT NOT NULL, - - street1Seen INT NOT NULL, - street2Seen INT NOT NULL, - street3Seen INT NOT NULL, - street4Seen INT NOT NULL, - sawShowdown INT NOT NULL, - - street1Aggr INT NOT NULL, - street2Aggr INT NOT NULL, - street3Aggr INT NOT NULL, - street4Aggr INT NOT NULL, - - otherRaisedStreet1 INT NOT NULL, - otherRaisedStreet2 INT NOT NULL, - otherRaisedStreet3 INT NOT NULL, - otherRaisedStreet4 INT NOT NULL, - foldToOtherRaisedStreet1 INT NOT NULL, - foldToOtherRaisedStreet2 INT NOT NULL, - foldToOtherRaisedStreet3 INT NOT NULL, - foldToOtherRaisedStreet4 INT NOT NULL, - wonWhenSeenStreet1 FLOAT NOT NULL, - wonAtSD FLOAT NOT NULL, - - stealAttemptChance INT NOT NULL, - stealAttempted INT NOT NULL, - foldBbToStealChance INT NOT NULL, - foldedBbToSteal INT NOT NULL, - foldSbToStealChance INT NOT NULL, - foldedSbToSteal INT NOT NULL, - - street1CBChance INT NOT NULL, - street1CBDone INT NOT NULL, - street2CBChance INT NOT NULL, - street2CBDone INT NOT NULL, - street3CBChance INT NOT NULL, - street3CBDone INT NOT NULL, - street4CBChance INT NOT NULL, - street4CBDone INT NOT NULL, - - foldToStreet1CBChance INT NOT NULL, - foldToStreet1CBDone INT NOT NULL, - foldToStreet2CBChance INT NOT NULL, - foldToStreet2CBDone INT NOT NULL, - foldToStreet3CBChance INT NOT NULL, - foldToStreet3CBDone INT NOT NULL, - foldToStreet4CBChance INT NOT NULL, - foldToStreet4CBDone INT NOT NULL, - - totalProfit INT NOT NULL, - - street1CheckCallRaiseChance INT NOT NULL, - street1CheckCallRaiseDone INT NOT NULL, - street2CheckCallRaiseChance INT NOT NULL, - street2CheckCallRaiseDone INT NOT NULL, - street3CheckCallRaiseChance INT NOT NULL, - street3CheckCallRaiseDone INT NOT NULL, - street4CheckCallRaiseChance INT NOT NULL, - street4CheckCallRaiseDone INT NOT NULL) - ENGINE=INNODB""" - elif(self.dbname == 'PostgreSQL'): - self.query['createHudCacheTable'] = """CREATE TABLE HudCache ( - id BIGSERIAL UNIQUE, PRIMARY KEY (id), - gametypeId INT, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), - playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id), - activeSeats SMALLINT, - position CHAR(1), - tourneyTypeId INT, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), + if(self.dbname == 'MySQL InnoDB'): + self.query['createHudCacheTable'] = """CREATE TABLE HudCache ( + id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + gametypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), + playerId INT UNSIGNED NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id), + activeSeats SMALLINT NOT NULL, + position CHAR(1), + tourneyTypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), + + HDs INT NOT NULL, + street0VPI INT NOT NULL, + street0Aggr INT NOT NULL, + street0_3B4BChance INT NOT NULL, + street0_3B4BDone INT NOT NULL, + + street1Seen INT NOT NULL, + street2Seen INT NOT NULL, + street3Seen INT NOT NULL, + street4Seen INT NOT NULL, + sawShowdown INT NOT NULL, + + street1Aggr INT NOT NULL, + street2Aggr INT NOT NULL, + street3Aggr INT NOT NULL, + street4Aggr INT NOT NULL, + + otherRaisedStreet1 INT NOT NULL, + otherRaisedStreet2 INT NOT NULL, + otherRaisedStreet3 INT NOT NULL, + otherRaisedStreet4 INT NOT NULL, + foldToOtherRaisedStreet1 INT NOT NULL, + foldToOtherRaisedStreet2 INT NOT NULL, + foldToOtherRaisedStreet3 INT NOT NULL, + foldToOtherRaisedStreet4 INT NOT NULL, + wonWhenSeenStreet1 FLOAT NOT NULL, + wonAtSD FLOAT NOT NULL, + + stealAttemptChance INT NOT NULL, + stealAttempted INT NOT NULL, + foldBbToStealChance INT NOT NULL, + foldedBbToSteal INT NOT NULL, + foldSbToStealChance INT NOT NULL, + foldedSbToSteal INT NOT NULL, + + street1CBChance INT NOT NULL, + street1CBDone INT NOT NULL, + street2CBChance INT NOT NULL, + street2CBDone INT NOT NULL, + street3CBChance INT NOT NULL, + street3CBDone INT NOT NULL, + street4CBChance INT NOT NULL, + street4CBDone INT NOT NULL, + + foldToStreet1CBChance INT NOT NULL, + foldToStreet1CBDone INT NOT NULL, + foldToStreet2CBChance INT NOT NULL, + foldToStreet2CBDone INT NOT NULL, + foldToStreet3CBChance INT NOT NULL, + foldToStreet3CBDone INT NOT NULL, + foldToStreet4CBChance INT NOT NULL, + foldToStreet4CBDone INT NOT NULL, + + totalProfit INT NOT NULL, + + street1CheckCallRaiseChance INT NOT NULL, + street1CheckCallRaiseDone INT NOT NULL, + street2CheckCallRaiseChance INT NOT NULL, + street2CheckCallRaiseDone INT NOT NULL, + street3CheckCallRaiseChance INT NOT NULL, + street3CheckCallRaiseDone INT NOT NULL, + street4CheckCallRaiseChance INT NOT NULL, + street4CheckCallRaiseDone INT NOT NULL) + ENGINE=INNODB""" + elif(self.dbname == 'PostgreSQL'): + self.query['createHudCacheTable'] = """CREATE TABLE HudCache ( + id BIGSERIAL, PRIMARY KEY (id), + gametypeId INT, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), + playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id), + activeSeats SMALLINT, + position CHAR(1), + tourneyTypeId INT, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), - HDs INT, - street0VPI INT, - street0Aggr INT, - street0_3B4BChance INT, - street0_3B4BDone INT, - street1Seen INT, - street2Seen INT, - street3Seen INT, - street4Seen INT, - sawShowdown INT, - street1Aggr INT, - street2Aggr INT, - street3Aggr INT, - street4Aggr INT, - otherRaisedStreet1 INT, - otherRaisedStreet2 INT, - otherRaisedStreet3 INT, - otherRaisedStreet4 INT, - foldToOtherRaisedStreet1 INT, - foldToOtherRaisedStreet2 INT, - foldToOtherRaisedStreet3 INT, - foldToOtherRaisedStreet4 INT, - wonWhenSeenStreet1 FLOAT, - wonAtSD FLOAT, + HDs INT, + street0VPI INT, + street0Aggr INT, + street0_3B4BChance INT, + street0_3B4BDone INT, + street1Seen INT, + street2Seen INT, + street3Seen INT, + street4Seen INT, + sawShowdown INT, + street1Aggr INT, + street2Aggr INT, + street3Aggr INT, + street4Aggr INT, + otherRaisedStreet1 INT, + otherRaisedStreet2 INT, + otherRaisedStreet3 INT, + otherRaisedStreet4 INT, + foldToOtherRaisedStreet1 INT, + foldToOtherRaisedStreet2 INT, + foldToOtherRaisedStreet3 INT, + foldToOtherRaisedStreet4 INT, + wonWhenSeenStreet1 FLOAT, + wonAtSD FLOAT, - stealAttemptChance INT, - stealAttempted INT, - foldBbToStealChance INT, - foldedBbToSteal INT, - foldSbToStealChance INT, - foldedSbToSteal INT, + stealAttemptChance INT, + stealAttempted INT, + foldBbToStealChance INT, + foldedBbToSteal INT, + foldSbToStealChance INT, + foldedSbToSteal INT, - street1CBChance INT, - street1CBDone INT, - street2CBChance INT, - street2CBDone INT, - street3CBChance INT, - street3CBDone INT, - street4CBChance INT, - street4CBDone INT, + street1CBChance INT, + street1CBDone INT, + street2CBChance INT, + street2CBDone INT, + street3CBChance INT, + street3CBDone INT, + street4CBChance INT, + street4CBDone INT, - foldToStreet1CBChance INT, - foldToStreet1CBDone INT, - foldToStreet2CBChance INT, - foldToStreet2CBDone INT, - foldToStreet3CBChance INT, - foldToStreet3CBDone INT, - foldToStreet4CBChance INT, - foldToStreet4CBDone INT, + foldToStreet1CBChance INT, + foldToStreet1CBDone INT, + foldToStreet2CBChance INT, + foldToStreet2CBDone INT, + foldToStreet3CBChance INT, + foldToStreet3CBDone INT, + foldToStreet4CBChance INT, + foldToStreet4CBDone INT, - totalProfit INT, + totalProfit INT, - street1CheckCallRaiseChance INT, - street1CheckCallRaiseDone INT, - street2CheckCallRaiseChance INT, - street2CheckCallRaiseDone INT, - street3CheckCallRaiseChance INT, - street3CheckCallRaiseDone INT, - street4CheckCallRaiseChance INT, - street4CheckCallRaiseDone INT)""" - elif(self.dbname == 'SQLite'): - self.query['createHudCacheTable'] = """ """ + street1CheckCallRaiseChance INT, + street1CheckCallRaiseDone INT, + street2CheckCallRaiseChance INT, + street2CheckCallRaiseDone INT, + street3CheckCallRaiseChance INT, + street3CheckCallRaiseDone INT, + street4CheckCallRaiseChance INT, + street4CheckCallRaiseDone INT)""" + elif(self.dbname == 'SQLite'): + self.query['createHudCacheTable'] = """ """ - ################################ - # Queries used in GuiGraphViewer - ################################ + if(self.dbname == 'MySQL InnoDB'): + self.query['addTourneyIndex'] = """ALTER TABLE Tourneys ADD INDEX siteTourneyNo(siteTourneyNo)""" + elif(self.dbname == 'PostgreSQL'): + # FIXME: This query has a different syntax + self.query['addTourneyIndex'] = """ALTER TABLE Tourneys ADD INDEX siteTourneyNo(siteTourneyNo)""" + elif(self.dbname == 'SQLite'): + self.query['addHandsIndex'] = """ """ + + if(self.dbname == 'MySQL InnoDB'): + self.query['addHandsIndex'] = """ALTER TABLE Hands ADD INDEX siteHandNo(siteHandNo)""" + elif(self.dbname == 'PostgreSQL'): + # FIXME: This query has a different syntax + self.query['addHandsIndex'] = """ALTER TABLE Hands ADD INDEX siteHandNo(siteHandNo)""" + elif(self.dbname == 'SQLite'): + self.query['addHandsIndex'] = """ """ + + if(self.dbname == 'MySQL InnoDB'): + self.query['addPlayersIndex'] = """ALTER TABLE Players ADD INDEX name(name)""" + elif(self.dbname == 'PostgreSQL'): + # FIXME: This query has a different syntax + self.query['addHandsIndex'] = """ALTER TABLE Hands ADD INDEX siteHandNo(siteHandNo)""" + elif(self.dbname == 'SQLite'): + self.query['addHandsIndex'] = """ """ + + ################################ + # Queries used in GuiGraphViewer + ################################ - # Returns all cash game handIds and the money won(winnings is the final pot) - # by the playerId for a single site. - if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'): - self.query['getRingWinningsAllGamesPlayerIdSite'] = """SELECT handId, winnings FROM HandsPlayers - INNER JOIN Players ON HandsPlayers.playerId = Players.id - INNER JOIN Hands ON Hands.id = HandsPlayers.handId - WHERE Players.name = %s AND Players.siteId = %s AND (tourneysPlayersId IS NULL) - ORDER BY handStart""" - elif(self.dbname == 'SQLite'): - #Probably doesn't work. - self.query['getRingWinningsAllGamesPlayerIdSite'] = """SELECT handId, winnings FROM HandsPlayers - INNER JOIN Players ON HandsPlayers.playerId = Players.id - INNER JOIN Hands ON Hands.id = HandsPlayers.handId - WHERE Players.name = %s AND Players.siteId = %s AND (tourneysPlayersId IS NULL) - ORDER BY handStart""" + # Returns all cash game handIds and the money won(winnings is the final pot) + # by the playerId for a single site. + if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'): + self.query['getRingWinningsAllGamesPlayerIdSite'] = """SELECT handId, winnings FROM HandsPlayers + INNER JOIN Players ON HandsPlayers.playerId = Players.id + INNER JOIN Hands ON Hands.id = HandsPlayers.handId + WHERE Players.name = %s AND Players.siteId = %s AND (tourneysPlayersId IS NULL) + ORDER BY handStart""" + elif(self.dbname == 'SQLite'): + #Probably doesn't work. + self.query['getRingWinningsAllGamesPlayerIdSite'] = """SELECT handId, winnings FROM HandsPlayers + INNER JOIN Players ON HandsPlayers.playerId = Players.id + INNER JOIN Hands ON Hands.id = HandsPlayers.handId + WHERE Players.name = %s AND Players.siteId = %s AND (tourneysPlayersId IS NULL) + ORDER BY handStart""" - # Returns the profit for all hands, Total pot - money invested by playerId - if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'): - self.query['getRingProfitAllHandsPlayerIdSite'] = """ - SELECT hp.handId, hp.winnings, SUM(ha.amount) costs, hp.winnings - SUM(ha.amount) profit + # Returns the profit for a given ring game handId, Total pot - money invested by playerId + if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'): + self.query['getRingProfitFromHandId'] = """SELECT SUM(amount) FROM HandsActions + INNER JOIN HandsPlayers ON HandsActions.handPlayerId = HandsPlayers.id + INNER JOIN Players ON HandsPlayers.playerId = Players.id + WHERE Players.name = %s AND HandsPlayers.handId = %s + AND Players.siteId = %s AND (tourneysPlayersId IS NULL)""" + elif(self.dbname == 'SQLite'): + #Probably doesn't work. + self.query['getRingProfitFromHandId'] = """SELECT SUM(amount) FROM HandsActions + INNER JOIN HandsPlayers ON HandsActions.handPlayerId = HandsPlayers.id + INNER JOIN Players ON HandsPlayers.playerId = Players.id + WHERE Players.name = %s AND HandsPlayers.handId = %s + AND Players.siteId = %s AND (tourneysPlayersId IS NULL)""" + + if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'): + self.query['getRingProfitAllHandsPlayerIdSite'] = """ + SELECT hp.handId, hp.winnings, SUM(ha.amount), hp.winnings - SUM(ha.amount) FROM HandsPlayers hp INNER JOIN Players pl ON hp.playerId = pl.id INNER JOIN Hands h ON h.id = hp.handId @@ -612,12 +643,12 @@ class FpdbSQLQueries: WHERE pl.name = %s AND pl.siteId = %s AND hp.tourneysPlayersId IS NULL - group by hp.handId, hp.winnings, h.handStart + GROUP BY hp.handId, hp.winnings, h.handStart ORDER BY h.handStart""" - elif(self.dbname == 'SQLite'): - #May not work. - self.query['getRingProfitAllHandsPlayerIdSite'] = """ - SELECT hp.handId, hp.winnings, SUM(ha.amount) costs, hp.winnings - SUM(ha.amount) profit + elif(self.dbname == 'SQLite'): + #Probably doesn't work. + self.query['getRingProfitAllHandsPlayerIdSite'] = """ + SELECT hp.handId, hp.winnings, SUM(ha.amount), hp.winnings - SUM(ha.amount) FROM HandsPlayers hp INNER JOIN Players pl ON hp.playerId = pl.id INNER JOIN Hands h ON h.id = hp.handId @@ -625,24 +656,206 @@ class FpdbSQLQueries: WHERE pl.name = %s AND pl.siteId = %s AND hp.tourneysPlayersId IS NULL - group by hp.handId, hp.winnings, h.handStart + GROUP BY hp.handId, hp.winnings, h.handStart ORDER BY h.handStart""" - # Returns the profit for a given ring game handId, Total pot - money invested by playerId - WRONG, returns players costs - if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'): - self.query['getRingProfitFromHandId'] = """SELECT SUM(amount) FROM HandsActions - INNER JOIN HandsPlayers ON HandsActions.handPlayerId = HandsPlayers.id - INNER JOIN Players ON HandsPlayers.playerId = Players.id - WHERE Players.name = %s AND HandsPlayers.handId = %s - AND Players.siteId = %s AND (tourneysPlayersId IS NULL)""" - elif(self.dbname == 'SQLite'): - #Probably doesn't work. - self.query['getRingProfitFromHandId'] = """SELECT SUM(amount) FROM HandsActions - INNER JOIN HandsPlayers ON HandsActions.handPlayerId = HandsPlayers.id - INNER JOIN Players ON HandsPlayers.playerId = Players.id - WHERE Players.name = %s AND HandsPlayers.handId = %s - AND Players.siteId = %s AND (tourneysPlayersId IS NULL)""" + # Returns the profit for a given ring game handId, Total pot - money invested by playerId - WRONG, returns players costs + if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'): + self.query['getRingProfitFromHandId'] = """SELECT SUM(amount) FROM HandsActions + INNER JOIN HandsPlayers ON HandsActions.handPlayerId = HandsPlayers.id + INNER JOIN Players ON HandsPlayers.playerId = Players.id + WHERE Players.name = %s AND HandsPlayers.handId = %s + AND Players.siteId = %s AND (tourneysPlayersId IS NULL)""" + elif(self.dbname == 'SQLite'): + #Probably doesn't work. + self.query['getRingProfitFromHandId'] = """SELECT SUM(amount) FROM HandsActions + INNER JOIN HandsPlayers ON HandsActions.handPlayerId = HandsPlayers.id + INNER JOIN Players ON HandsPlayers.playerId = Players.id + WHERE Players.name = %s AND HandsPlayers.handId = %s + AND Players.siteId = %s AND (tourneysPlayersId IS NULL)""" + # Returns a list of the tables in the database + if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'): + self.query['getTableList'] = """ + SELECT table_name + FROM information_schema.tables + WHERE table_type = 'BASE TABLE' + AND table_schema = %s + """ + elif(self.dbname == 'getTableList'): + #Probably doesn't work. + self.query['getTableList'] = """ + SELECT table_name + FROM information_schema.tables + WHERE table_type = 'BASE TABLE' + AND table_schema = %s + """ + + if(self.dbname == 'MySQL InnoDB'): + self.query['playerStats'] = """ + SELECT stats.gametypeId + ,stats.base + ,stats.limitType + ,stats.name + ,format(stats.bigBlind/100,2) as BigBlind + ,stats.n + ,stats.vpip + ,stats.pfr + ,stats.saw_f + ,stats.sawsd + ,stats.wtsdwsf + ,stats.wmsd + ,stats.FlAFq + ,stats.TuAFq + ,stats.RvAFq + ,stats.PFAFq + ,hprof2.sum_profit/100 as Net + ,(hprof2.sum_profit/stats.bigBlind)/(stats.n/100) as BBlPer100 + FROM + (select # stats from hudcache + gt.base + ,upper(gt.limitType) limitType + ,s.name + ,gt.bigBlind + ,hc.gametypeId + ,sum(HDs) as n + ,round(100*sum(street0VPI)/sum(HDs)) as vpip + ,round(100*sum(street0Aggr)/sum(HDs)) as pfr + ,round(100*sum(street1Seen)/sum(HDs)) AS saw_f + ,round(100*sum(sawShowdown)/sum(HDs)) AS sawsd + ,round(100*sum(sawShowdown)/sum(street1Seen)) AS wtsdwsf + ,round(100*sum(wonAtSD)/sum(sawShowdown)) AS wmsd + ,round(100*sum(street1Aggr)/sum(street1Seen)) AS FlAFq + ,round(100*sum(street2Aggr)/sum(street2Seen)) AS TuAFq + ,round(100*sum(street3Aggr)/sum(street3Seen)) AS RvAFq + ,round(100*(sum(street1Aggr)+sum(street2Aggr)+sum(street3Aggr)) + /(sum(street1Seen)+sum(street2Seen)+sum(street3Seen))) AS PFAFq + from Gametypes gt + inner join Sites s on s.Id = gt.siteId + inner join HudCache hc on hc.gameTypeId = gt.Id + where gt.limittype = 'nl' + and hc.playerId in (3) # use here? + # use here ? + group by hc.gametypeId + ) stats + inner join + ( select # profit from handsplayers/handsactions + hprof.gameTypeId, sum(hprof.profit) sum_profit + from + (select hp.handId, h.gameTypeId, hp.winnings, SUM(ha.amount) + costs, hp.winnings - SUM(ha.amount) profit + from HandsPlayers hp + inner join Hands h ON h.id = hp.handId + inner join HandsActions ha ON ha.handPlayerId = hp.id + where hp.playerId in (3) # use here? + # use here ? + and hp.tourneysPlayersId IS NULL + group by hp.handId, h.gameTypeId, hp.position, hp.winnings + ) hprof + group by hprof.gameTypeId + ) hprof2 + on hprof2.gameTypeId = stats.gameTypeId + order by stats.base, stats.limittype, stats.bigBlind""" + elif(self.dbname == 'PostgreSQL'): + self.query['playerStats'] = """ """ + elif(self.dbname == 'SQLite'): + self.query['playerStats'] = """ """ + + if(self.dbname == 'MySQL InnoDB'): + self.query['playerStatsByPosition'] = """ + SELECT stats.gametypeId + ,stats.base + ,stats.limitType + ,stats.name + ,format(stats.bigBlind/100,2) as BigBlind + ,p.name + ,stats.pl_position + ,stats.n + ,stats.vpip + ,stats.pfr + ,stats.saw_f + ,stats.sawsd + ,stats.wtsdwsf + ,stats.wmsd + ,stats.FlAFq + ,stats.TuAFq + ,stats.RvAFq + ,stats.PFAFq + ,hprof2.sum_profit/100 as Net + ,(hprof2.sum_profit/stats.bigBlind)/(stats.n/100) as BBlPer100 + # ... any other stats you want to add + FROM + (select # stats from hudcache + hc.playerId + ,gt.base + ,upper(gt.limitType) as limitType + ,s.name + ,gt.bigBlind + ,hc.gametypeId + ,case when hc.position = 'B' then -2 + when hc.position = 'S' then -1 + when hc.position = 'D' then 0 + when hc.position = 'C' then 1 + when hc.position = 'M' then 2 + when hc.position = 'E' then 5 + else 9 + end as pl_position + ,sum(HDs) as n + ,round(100*sum(street0VPI)/sum(HDs)) as vpip + ,round(100*sum(street0Aggr)/sum(HDs)) as pfr + ,round(100*sum(street1Seen)/sum(HDs)) AS saw_f + ,round(100*sum(sawShowdown)/sum(HDs)) AS sawsd + ,round(100*sum(sawShowdown)/sum(street1Seen)) AS wtsdwsf + ,round(100*sum(wonAtSD)/sum(sawShowdown)) AS wmsd + ,round(100*sum(street1Aggr)/sum(street1Seen)) AS FlAFq + ,round(100*sum(street2Aggr)/sum(street2Seen)) AS TuAFq + ,round(100*sum(street3Aggr)/sum(street3Seen)) AS RvAFq + ,round(100*(sum(street1Aggr)+sum(street2Aggr)+sum(street3Aggr)) + /(sum(street1Seen)+sum(street2Seen)+sum(street3Seen))) AS PFAFq + from Gametypes gt + inner join Sites s on (s.Id = gt.siteId) + inner join HudCache hc on (hc.gameTypeId = gt.Id) + where gt.limittype = 'nl' + and hc.playerId in (3) # always specify player for position stats + # use here + # use here + group by hc.playerId, hc.gametypeId, pl_position + ) stats + inner join + ( select # profit from handsplayers/handsactions + hprof.playerId + , hprof.gameTypeId + , case when hprof.position = 'B' then -2 + when hprof.position = 'S' then -1 + when hprof.position in ('3','4') then 2 + when hprof.position in ('6','7') then 5 + else hprof.position + end as pl_position + , sum(hprof.profit) as sum_profit + from + (select hp.playerId, hp.handId, h.gameTypeId, hp.position, hp.winnings + , SUM(ha.amount) costs, hp.winnings - SUM(ha.amount) profit + from HandsPlayers hp + inner join Hands h ON (h.id = hp.handId) + inner join HandsActions ha ON (ha.handPlayerId = hp.id) + where hp.playerId in (3) # always specify player for position stats + # use here + # use here + and hp.tourneysPlayersId IS NULL + group by hp.playerId, hp.handId, h.gameTypeId, hp.position, hp.winnings + ) hprof + group by hprof.playerId, hprof.gameTypeId, pl_position + ) hprof2 + on ( hprof2.gameTypeId = stats.gameTypeId + and hprof2.pl_position = stats.pl_position) + inner join Players p on (p.id = stats.playerId) + where 1 = 1 + order by stats.base, stats.limittype, stats.bigBlind, stats.pl_position, BBlPer100 desc + """ + elif(self.dbname == 'PostgreSQL'): + self.query['playerStatsByPosition'] = """ """ + elif(self.dbname == 'SQLite'): + self.query['playerStatsByPosition'] = """ """ if __name__== "__main__": from optparse import OptionParser diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 92a5ed86..1c5c97bb 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -21,65 +21,67 @@ import fpdb_simple import FpdbSQLQueries class fpdb_db: - def __init__(self): - """Simple constructor, doesnt really do anything""" - self.db=None - self.cursor=None - self.sql = {} - self.MYSQL_INNODB=2 - self.PGSQL=3 - self.SQLITE=4 - #end def __init__ - - def connect(self, backend, host, database, user, password): - """Connects a database with the given parameters""" - self.backend=backend - self.host=host - self.database=database - self.user=user - self.password=password - if backend==self.MYSQL_INNODB: - import MySQLdb - self.db=MySQLdb.connect(host = host, user = user, passwd = password, db = database) - elif backend==self.PGSQL: - import psycopg2 - self.db = psycopg2.connect(host = host, user = user, password = password, database = database) - else: - raise fpdb_simple.FpdbError("unrecognised database backend:"+backend) - self.cursor=self.db.cursor() - # Set up query dictionary as early in the connection process as we can. + def __init__(self): + """Simple constructor, doesnt really do anything""" + self.db=None + self.cursor=None + self.sql = {} + self.MYSQL_INNODB=2 + self.PGSQL=3 + self.SQLITE=4 + #end def __init__ + + def connect(self, backend, host, database, user, password): + """Connects a database with the given parameters""" + self.backend=backend + self.host=host + self.database=database + self.user=user + self.password=password + if backend==self.MYSQL_INNODB: + import MySQLdb + self.db=MySQLdb.connect(host = host, user = user, passwd = password, db = database) + elif backend==self.PGSQL: + import psycopg2 + self.db = psycopg2.connect(host = host, user = user, password = password, database = database) + else: + raise fpdb_simple.FpdbError("unrecognised database backend:"+backend) + self.cursor=self.db.cursor() + self.cursor.execute('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED') + + # Set up query dictionary as early in the connection process as we can. self.sql = FpdbSQLQueries.FpdbSQLQueries(self.get_backend_name()) - self.wrongDbVersion=False - try: - self.cursor.execute("SELECT * FROM Settings") - settings=self.cursor.fetchone() - if settings[0]!=118: - print "outdated or too new database version - please recreate tables" - self.wrongDbVersion=True - except:# _mysql_exceptions.ProgrammingError: - print "failed to read settings table - please recreate tables" - self.wrongDbVersion=True - #end def connect + self.wrongDbVersion=False + try: + self.cursor.execute("SELECT * FROM Settings") + settings=self.cursor.fetchone() + if settings[0]!=118: + print "outdated or too new database version - please recreate tables" + self.wrongDbVersion=True + except:# _mysql_exceptions.ProgrammingError: + print "failed to read settings table - please recreate tables" + self.wrongDbVersion=True + #end def connect - def disconnect(self, due_to_error=False): - """Disconnects the DB""" - if due_to_error: - self.db.rollback() - else: - self.db.commit() - self.cursor.close() - self.db.close() - #end def disconnect - - def reconnect(self, due_to_error=False): - """Reconnects the DB""" - #print "started fpdb_db.reconnect" - self.disconnect(due_to_error) - self.connect(self.backend, self.host, self.database, self.user, self.password) + def disconnect(self, due_to_error=False): + """Disconnects the DB""" + if due_to_error: + self.db.rollback() + else: + self.db.commit() + self.cursor.close() + self.db.close() + #end def disconnect + + def reconnect(self, due_to_error=False): + """Reconnects the DB""" + #print "started fpdb_db.reconnect" + self.disconnect(due_to_error) + self.connect(self.backend, self.host, self.database, self.user, self.password) - def create_tables(self): - #todo: should detect and fail gracefully if tables already exist. - self.cursor.execute(self.sql.query['createSettingsTable']) + def create_tables(self): + #todo: should detect and fail gracefully if tables already exist. + self.cursor.execute(self.sql.query['createSettingsTable']) self.cursor.execute(self.sql.query['createSitesTable']) self.cursor.execute(self.sql.query['createGametypesTable']) self.cursor.execute(self.sql.query['createPlayersTable']) @@ -92,81 +94,84 @@ class fpdb_db: self.cursor.execute(self.sql.query['createHandsPlayersTable']) self.cursor.execute(self.sql.query['createHandsActionsTable']) self.cursor.execute(self.sql.query['createHudCacheTable']) - self.fillDefaultData() + self.cursor.execute(self.sql.query['addTourneyIndex']) + self.cursor.execute(self.sql.query['addHandsIndex']) + self.cursor.execute(self.sql.query['addPlayersIndex']) + self.fillDefaultData() self.db.commit() #end def disconnect - - def drop_tables(self): - """Drops the fpdb tables from the current db""" + + def drop_tables(self): + """Drops the fpdb tables from the current db""" - if(self.get_backend_name() == 'MySQL InnoDB'): - #Databases with FOREIGN KEY support need this switched of before you can drop tables - self.drop_referencial_integrity() + if(self.get_backend_name() == 'MySQL InnoDB'): + #Databases with FOREIGN KEY support need this switched of before you can drop tables + self.drop_referencial_integrity() - # Query the DB to see what tables exist - self.cursor.execute(self.sql.query['list_tables']) - for table in self.cursor: - self.cursor.execute(self.sql.query['drop_table'] + table[0]) - elif(self.get_backend_name() == 'PostgreSQL'): - self.db.commit()# I have no idea why this makes the query work--REB 07OCT2008 - self.cursor.execute(self.sql.query['list_tables']) - tables = self.cursor.fetchall() - for table in tables: - self.cursor.execute(self.sql.query['drop_table'] + table[0] + ' cascade') - elif(self.get_backend_name() == 'SQLite'): - #todo: sqlite version here - print "Empty function here" + # Query the DB to see what tables exist + self.cursor.execute(self.sql.query['list_tables']) + for table in self.cursor: + self.cursor.execute(self.sql.query['drop_table'] + table[0]) + elif(self.get_backend_name() == 'PostgreSQL'): + self.db.commit()# I have no idea why this makes the query work--REB 07OCT2008 + self.cursor.execute(self.sql.query['list_tables']) + tables = self.cursor.fetchall() + for table in tables: + self.cursor.execute(self.sql.query['drop_table'] + table[0] + ' cascade') + elif(self.get_backend_name() == 'SQLite'): + #todo: sqlite version here + print "Empty function here" self.db.commit() - #end def drop_tables + #end def drop_tables - def drop_referencial_integrity(self): - """Update all tables to remove foreign keys""" + def drop_referencial_integrity(self): + """Update all tables to remove foreign keys""" - self.cursor.execute(self.sql.query['list_tables']) - result = self.cursor.fetchall() + self.cursor.execute(self.sql.query['list_tables']) + result = self.cursor.fetchall() - for i in range(len(result)): - self.cursor.execute("SHOW CREATE TABLE " + result[i][0]) - inner = self.cursor.fetchall() + for i in range(len(result)): + self.cursor.execute("SHOW CREATE TABLE " + result[i][0]) + inner = self.cursor.fetchall() - for j in range(len(inner)): - # result[i][0] - Table name - # result[i][1] - CREATE TABLE parameters - #Searching for CONSTRAINT `tablename_ibfk_1` - for m in re.finditer('(ibfk_[0-9]+)', inner[j][1]): - key = "`" + inner[j][0] + "_" + m.group() + "`" - self.cursor.execute("ALTER TABLE " + inner[j][0] + " DROP FOREIGN KEY " + key) + for j in range(len(inner)): + # result[i][0] - Table name + # result[i][1] - CREATE TABLE parameters + #Searching for CONSTRAINT `tablename_ibfk_1` + for m in re.finditer('(ibfk_[0-9]+)', inner[j][1]): + key = "`" + inner[j][0] + "_" + m.group() + "`" + self.cursor.execute("ALTER TABLE " + inner[j][0] + " DROP FOREIGN KEY " + key) self.db.commit() #end drop_referencial_inegrity - - def get_backend_name(self): - """Returns the name of the currently used backend""" - if self.backend==2: - return "MySQL InnoDB" - elif self.backend==3: - return "PostgreSQL" - else: - raise fpdb_simple.FpdbError("invalid backend") - #end def get_backend_name - - def get_db_info(self): - return (self.host, self.database, self.user, self.password) - #end def get_db_info - - def fillDefaultData(self): - self.cursor.execute("INSERT INTO Settings VALUES (118);") - self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'Full Tilt Poker', 'USD');") - self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'PokerStars', 'USD');") - self.cursor.execute("INSERT INTO TourneyTypes VALUES (DEFAULT, 1, 0, 0, 0, False);") - #end def fillDefaultData - - def recreate_tables(self): - """(Re-)creates the tables of the current DB""" - - self.drop_tables() - self.create_tables() - self.db.commit() - print "Finished recreating tables" - #end def recreate_tables + + def get_backend_name(self): + """Returns the name of the currently used backend""" + if self.backend==2: + return "MySQL InnoDB" + elif self.backend==3: + return "PostgreSQL" + else: + raise fpdb_simple.FpdbError("invalid backend") + #end def get_backend_name + + def get_db_info(self): + return (self.host, self.database, self.user, self.password) + #end def get_db_info + + def fillDefaultData(self): + self.cursor.execute("INSERT INTO Settings VALUES (118);") + self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'Full Tilt Poker', 'USD');") + self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'PokerStars', 'USD');") + self.cursor.execute("INSERT INTO TourneyTypes VALUES (DEFAULT, 1, 0, 0, 0, False);") + #end def fillDefaultData + + def recreate_tables(self): + """(Re-)creates the tables of the current DB""" + + self.drop_tables() + self.create_tables() + self.db.commit() + print "Finished recreating tables" + #end def recreate_tables #end class fpdb_db From 3ea95acb0cb63da7a1780c13dc4210f2fcf7e2f7 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 8 Dec 2008 00:55:03 +0000 Subject: [PATCH 23/32] add db param to allow insert_id() matching fpdb_parse_logic.py --- pyfpdb/fpdb_simple.py | 4332 +++++++++++++++++++++-------------------- 1 file changed, 2173 insertions(+), 2159 deletions(-) diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index 01247651..11a2a1ea 100755 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -1,2159 +1,2173 @@ -#!/usr/bin/python - -#Copyright 2008 Steffen Jobbagy-Felso -#This program is free software: you can redistribute it and/or modify -#it under the terms of the GNU Affero General Public License as published by -#the Free Software Foundation, version 3 of the License. -# -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU Affero General Public License -#along with this program. If not, see . -#In the "official" distribution you can find the license in -#agpl-3.0.txt in the docs folder of the package. - -#This file contains simple functions for fpdb - -import datetime -import re - -PS=1 -FTP=2 - -class DuplicateError(Exception): - def __init__(self, value): - self.value = value - def __str__(self): - return repr(self.value) - -class FpdbError(Exception): - def __init__(self, value): - self.value = value - def __str__(self): - return repr(self.value) - -#returns an array of the total money paid. intending to add rebuys/addons here -def calcPayin(count, buyin, fee): - result=[] - for i in range(count): - result.append (buyin+fee) - return result -#end def calcPayin - -def checkPositions(positions): - """verifies that these positions are valid""" - for i in range (len(positions)): - pos=positions[i] - try:#todo: use type recognition instead of error - if (len(pos)!=1): - raise FpdbError("invalid position found in checkPositions. i: "+str(i)+" position: "+pos) #dont need to str() here - except TypeError:#->not string->is int->fine - pass - - ### 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... - if not (pos == "B" or pos == "S" or (pos >= 0 and pos <= 9)): - raise FpdbError("invalid position found in checkPositions. i: "+str(i)+" position: "+str(pos)) -#end def fpdb_simple.checkPositions - -#classifies each line for further processing in later code. Manipulates the passed arrays. -def classifyLines(hand, category, lineTypes, lineStreets): - currentStreet="predeal" - done=False #set this to true once we reach the last relevant line (the summary, except rake, is all repeats) - for i in range (len(hand)): - if (done): - if (hand[i].find("[")==-1 or hand[i].find("mucked [")==-1): - lineTypes.append("ignore") - else: #it's storing a mucked card - lineTypes.append("cards") - elif (hand[i].startswith("Dealt to")): - lineTypes.append("cards") - elif (i==0): - lineTypes.append("header") - elif (hand[i].startswith("Seat ") and ((hand[i].find("in chips")!=-1) or (hand[i].find("($")!=-1))): - lineTypes.append("name") - elif (isActionLine(hand[i])): - lineTypes.append("action") - if (hand[i].find(" posts ")!=-1 or hand[i].find(" posts the ")!=-1):#need to set this here so the "action" of posting blinds is registered properly - currentStreet="preflop" - elif (isWinLine(hand[i])): - lineTypes.append("win") - elif (hand[i].startswith("Total pot ") and hand[i].find("Rake")!=-1): - lineTypes.append("rake") - done=True - elif (hand[i]=="*** SHOW DOWN ***" or hand[i]=="*** SUMMARY ***"): - lineTypes.append("ignore") - #print "in classifyLine, showdown or summary" - elif (hand[i].find(" antes ")!=-1 or hand[i].find(" posts the ante ")!=-1): - lineTypes.append("ante") - elif (hand[i].startswith("*** FLOP *** [")): - lineTypes.append("cards") - currentStreet="flop" - elif (hand[i].startswith("*** TURN *** [")): - lineTypes.append("cards") - currentStreet="turn" - elif (hand[i].startswith("*** RIVER *** [")): - lineTypes.append("cards") - currentStreet="river" - elif (hand[i].startswith("*** 3")): - lineTypes.append("ignore") - currentStreet=0 - elif (hand[i].startswith("*** 4")): - lineTypes.append("ignore") - currentStreet=1 - elif (hand[i].startswith("*** 5")): - lineTypes.append("ignore") - currentStreet=2 - elif (hand[i].startswith("*** 6")): - lineTypes.append("ignore") - currentStreet=3 - elif (hand[i].startswith("*** 7") or hand[i]=="*** RIVER ***"): - lineTypes.append("ignore") - currentStreet=4 - elif (hand[i].find(" shows [")!=-1): - lineTypes.append("cards") - elif (hand[i].startswith("Table '")): - lineTypes.append("table") - else: - raise FpdbError("unrecognised linetype in:"+hand[i]) - lineStreets.append(currentStreet) -#end def classifyLines - -def convert3B4B(site, category, limit_type, actionTypes, actionAmounts): - """calculates the actual bet amounts in the given amount array and changes it accordingly.""" - for i in range (len(actionTypes)): - for j in range (len(actionTypes[i])): - bets=[] - for k in range (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) - amount2=actionAmounts[bets[1][0]][bets[1][1]][bets[1][2]] - amount1=actionAmounts[bets[0][0]][bets[0][1]][bets[0][2]] - actionAmounts[bets[1][0]][bets[1][1]][bets[1][2]]=amount2-amount1 - elif (len(bets)>2): - fail=True - #todo: run correction for below - if (site=="ps" and category=="holdem" and limit_type=="nl" and len(bets)==3): - fail=False - if (site=="ftp" and category=="omahahi" and limit_type=="pl" and len(bets)==3): - fail=False - - if fail: - print "len(bets)>2 in convert3B4B, i didnt think this is possible. i:",i,"j:",j,"k:",k - print "actionTypes:",actionTypes - raise FpdbError ("too many bets in convert3B4B") - #print "actionAmounts postConvert",actionAmounts -#end def convert3B4B(actionTypes, actionAmounts) - -#Corrects the bet amount if the player had to pay blinds -def convertBlindBet(actionTypes, actionAmounts): - i=0#setting street to pre-flop - for j in range (len(actionTypes[i])):#playerloop - blinds=[] - bets=[] - for k in range (len(actionTypes[i][j])): - if (actionTypes[i][j][k]=="blind"): - blinds.append((i,j,k)) - - if (len(blinds)>0 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 -#end def convertBlindBet - -#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): - for i in range (len(arr)): - for j in range (len(arr[i])): - if (arr[i][j]=="A"): - arr[i][j]=14 - elif (arr[i][j]=="K"): - arr[i][j]=13 - elif (arr[i][j]=="Q"): - arr[i][j]=12 - elif (arr[i][j]=="J"): - arr[i][j]=11 - elif (arr[i][j]=="T"): - arr[i][j]=10 - else: - arr[i][j]=int(arr[i][j]) -#end def convertCardValues - -#converts the strings in the given array to ints (changes the passed array, no returning). see table design for conversion details -def convertCardValuesBoard(arr): - for i in range (len(arr)): - if (arr[i]=="A"): - arr[i]=14 - elif (arr[i]=="K"): - arr[i]=13 - elif (arr[i]=="Q"): - arr[i]=12 - elif (arr[i]=="J"): - arr[i]=11 - elif (arr[i]=="T"): - arr[i]=10 - else: - arr[i]=int(arr[i]) -#end def convertCardValuesBoard - -#this creates the 2D/3D arrays. manipulates the passed arrays instead of returning. -def createArrays(category, seats, card_values, card_suits, antes, winnings, rakes, action_types, allIns, action_amounts, actionNos, actionTypeByNo): - for i in range(seats):#create second dimension arrays - tmp=[] - card_values.append(tmp) - tmp=[] - card_suits.append(tmp) - antes.append(0) - winnings.append(0) - rakes.append(0) - - if (category=="holdem" or category=="omahahi" or category=="omahahilo"): - streetCount=4 - else: - streetCount=5 - - for i in range(streetCount): #build the first dimension array, for streets - tmp=[] - action_types.append(tmp) - tmp=[] - allIns.append(tmp) - tmp=[] - action_amounts.append(tmp) - tmp=[] - actionNos.append(tmp) - tmp=[] - actionTypeByNo.append(tmp) - for j in range (seats): #second dimension arrays: players - tmp=[] - action_types[i].append(tmp) - tmp=[] - allIns[i].append(tmp) - tmp=[] - action_amounts[i].append(tmp) - tmp=[] - actionNos[i].append(tmp) - if (category=="holdem" or category=="omahahi" or category=="omahahilo"): - pass - elif (category=="razz" or category=="studhi" or category=="studhilo"):#need to fill card arrays. - for i in range(seats): - for j in range (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") -#end def fill_board_cards - -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 fpdb_simple.FpdbError ("invalid category:", category) - - for i in range (player_count): - while (len(card_values[i])=1): - raise DuplicateError ("dupl") -#end isAlreadyInDB - -def isRebuyOrAddon(topline): - """isRebuyOrAddon not implemented yet""" - return False -#end def isRebuyOrAddon - -#returns whether the passed topline indicates a tournament or not -def isTourney(topline): - if (topline.find("Tournament")!=-1): - return True - else: - return False -#end def isTourney - -#returns boolean whether the passed line is a win line -def isWinLine(line): - if (line.find("wins the pot")!=-1): - return True - elif (line.find("ties for the high pot")!=-1): - return True - elif (line.find("ties for the high main pot")!=-1): - return True - elif (line.find("ties for the high side pot")!=-1): - return True - elif (line.find("ties for the low pot")!=-1): - return True - elif (line.find("ties for the low main pot")!=-1): - return True - elif (line.find("ties for the low side pot")!=-1): - return True - elif (line.find("ties for the main pot")!=-1): #for ftp tied main pot of split pot - return True - elif (line.find("ties for the pot")!=-1): #for ftp tie - return True - elif (line.find("ties for the side pot")!=-1): #for ftp tied split pots - return True - elif (line.find("wins side pot #")!=-1): #for ftp multi split pots - return True - elif (line.find("wins the low main pot")!=-1): - return True - elif (line.find("wins the low pot")!=-1): - return True - elif (line.find("wins the low side pot")!=-1): - return True - elif (line.find("wins the high main pot")!=-1): - return True - elif (line.find("wins the high pot")!=-1): - return True - elif (line.find("wins the high side pot")!=-1): - return True - elif (line.find("wins the main pot")!=-1): - return True - elif (line.find("wins the side pot")!=-1): #for ftp split pots - return True - elif (line.find("collected")!=-1): - return True - else: - return False #not raising error here, any unknown line wouldve been detected in isActionLine already -#end def isWinLine - -#returns the amount of cash/chips put into the put in the given action line -def parseActionAmount(line, atype, site, isTourney): - #if (line.endswith(" and is all-in")): - # line=line[:-14] - #elif (line.endswith(", and is all in")): - # line=line[:-15] - - if line.endswith(", and is capped"):#ideally we should recognise this as an all-in if category is capXl - line=line[:-15] - if line.endswith(" and is capped"): - line=line[:-14] - - - if (atype=="fold"): - amount=0 - elif (atype=="check"): - amount=0 - elif (atype=="unbet" and site=="ftp"): - pos1=line.find("$")+1 - pos2=line.find(" returned to") - amount=float2int(line[pos1:pos2]) - elif (atype=="unbet" and site=="ps"): - #print "ps unbet, line:",line - pos1=line.find("$")+1 - if pos1==0: - pos1=line.find("(")+1 - pos2=line.find(")") - amount=float2int(line[pos1:pos2]) - elif (atype=="bet" and site=="ps" and line.find(": raises $")!=-1 and line.find("to $")!=-1): - 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(site, 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 range(len(actionNos[street])): - for count in range(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, site, 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) -#end def parseActionLine - -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) -#end def goesAllInOnThisLine - -#returns the action type code (see table design) of the given action line -def parseActionType(line): - if (line.startswith("Uncalled bet")): - return "unbet" - elif (line.endswith("folds")): - return "fold" - elif (line.endswith("checks")): - return "check" - elif (line.find("calls")!=-1): - return "call" - elif (line.find("brings in for")!=-1): - return "blind" - elif (line.find("completes it to")!=-1): - return "bet" - #todo: what if someone completes instead of bringing in? - elif (line.find(" posts $")!=-1): - return "blind" - elif (line.find(" posts a dead ")!=-1): - return "blind" - elif (line.find(": posts small blind ")!=-1): - return "blind" - elif (line.find(" posts the small blind of $")!=-1): - return "blind" - elif (line.find(": posts big blind ")!=-1): - return "blind" - elif (line.find(" posts the big blind of $")!=-1): - return "blind" - elif (line.find(": posts small & big blinds $")!=-1): - return "blind" - #todo: seperately record voluntary blind payments made to join table out of turn - elif (line.find("bets")!=-1): - return "bet" - elif (line.find("raises")!=-1): - return "bet" - else: - raise FpdbError ("failed to recognise actiontype in parseActionLine in: "+line) -#end def parseActionType - -#parses the ante out of the given line and checks which player paid it, updates antes accordingly. -def parseAnteLine(line, site, isTourney, names, antes): - for i in range(len(names)): - if (line.startswith(names[i].encode("latin-1"))): #found the ante'er - pos=line.rfind("$")+1 - if not isTourney: - antes[i]+=float2int(line[pos:]) - else: - if line.find("all-in")==-1: - 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]) - #print "parseAnteLine line: ", line, "antes[i]", antes[i], "antes", antes -#end def parseAntes - -#returns the buyin of a tourney in cents -def parseBuyin(topline): - pos1=topline.find("$")+1 - pos2=topline.find("+") - return float2int(topline[pos1:pos2]) -#end def parseBuyin - -#parses a card line and changes the passed arrays accordingly -#todo: reorganise this messy method -def parseCardLine(site, category, street, line, names, cardValues, cardSuits, boardValues, boardSuits): - if (line.startswith("Dealt to ") or line.find(" shows [")!=-1 or line.find("mucked [")!=-1): - 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]: #two tests will do - 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 (line.find("shows")==-1 and line.find("mucked") == -1): - #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) -#end def parseCardLine - -def parseCashesAndSeatNos(lines, site): - """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 range (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 - if (site=="ftp"): - pos2=lines[i].rfind(")") - elif (site=="ps"): - pos2=lines[i].find(" in chips") - cashes.append(float2int(lines[i][pos1:pos2])) - return {'startCashes':cashes, 'seatNos':seatNos} -#end def parseCashesAndSeatNos - -#returns the buyin of a tourney in cents -def parseFee(topline): - pos1=topline.find("$")+1 - pos1=topline.find("$",pos1)+1 - pos2=topline.find(" ", pos1) - return float2int(topline[pos1:pos2]) -#end def parsefee - -#returns a datetime object with the starttime indicated in the given topline -def parseHandStartTime(topline, site): - #convert x:13:35 to 0x:13:35 - counter=0 - while (True): - pos=topline.find(" "+str(counter)+":") - if (pos!=-1): - topline=topline[0:pos+1]+"0"+topline[pos+1:] - counter+=1 - if counter==10: break - - isUTC=False - if site=="ftp": - pos = topline.find(" ", len(topline)-26)+1 - tmp = topline[pos:] - #print "year:", tmp[14:18], "month", tmp[19:21], "day", tmp[22:24], "hour", tmp[0:2], "minute", tmp[3:5], "second", tmp[6:8] - result = datetime.datetime(int(tmp[14:18]), int(tmp[19:21]), int(tmp[22:24]), int(tmp[0:2]), int(tmp[3:5]), int(tmp[6:8])) - elif site=="ps": - 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) - #print "year:", int(m.group('YEAR')), "month", int(m.group('MON')), "day", int(m.group('DAY')), "hour", int(m.group('HR')), "minute", int(m.group('MIN')), "second", int(m.group('SEC')) - 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'))) - else: - raise FpdbError("invalid site in parseHandStartTime") - - if (site=="ftp" or site=="ps") and not isUTC: #these use US ET - result+=datetime.timedelta(hours=5) - - return result -#end def parseHandStartTime - -#parses the names out of the given lines and returns them as an array -def parseNames(lines): - result = [] - for i in range (len(lines)): - pos1=lines[i].find(":")+2 - pos2=lines[i].rfind("(")-1 - tmp=lines[i][pos1:pos2] - #print "parseNames, tmp original:",tmp - tmp=unicode(tmp,"latin-1") - #print "parseNames, tmp after unicode latin-1 conversion:",tmp - result.append(tmp) - return result -#end def parseNames - -#returns an array with the positions of the respective players -def parsePositions (hand, names): - #prep array - positions=[] - for i in range(len(names)): - positions.append(-1) - - #find blinds - sb,bb=-1,-1 - for i in range (len(hand)): - if (sb==-1 and hand[i].find("small blind")!=-1 and hand[i].find("dead small blind")==-1): - sb=hand[i] - #print "sb:",sb - if (bb==-1 and hand[i].find("big blind")!=-1 and hand[i].find("dead big blind")==-1): - bb=hand[i] - #print "bb:",bb - - #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: - sbExists = False - sb = -1 - - #write blinds into array - if (sbExists): - positions[sb]="S" - positions[bb]="B" - - #fill up rest of array - if (sbExists): - arraypos=sb-1 - else: - arraypos=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" - if sbExists: - i = sb-1 - else: - i = 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 - - for i in range (len(names)): - if positions[i]==-1: - print "parsePositions names:",names - print "result:",positions - raise FpdbError ("failed to read positions") - #print str(positions), "\n" - return positions -#end def parsePositions - -#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 -#end def parseRake - -def parseSiteHandNo(topline): - """returns the hand no assigned by the poker site""" - pos1=topline.find("#")+1 - pos2=topline.find(":") - return topline[pos1:pos2] -#end def parseSiteHandNo - -def parseTableLine(site, base, line): - """returns a dictionary with maxSeats and tableName""" - if site=="ps": - 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]} - elif site=="ftp": - pos1=line.find("Table ")+6 - pos2=line.find("-")-1 - if base=="hold": - maxSeats=9 - elif base=="stud": - maxSeats=8 - - if line.find("6 max")!=-1: - maxSeats=6 - elif line.find("4 max")!=-1: - maxSeats=4 - elif line.find("heads up")!=-1: - maxSeats=2 - - return {'maxSeats':maxSeats, 'tableName':line[pos1:pos2]} - else: - raise FpdbError("invalid site ID") -#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] -#end def parseTourneyNo - -#parses a win/collect line. manipulates the passed array winnings, no explicit return -def parseWinLine(line, site, names, winnings, isTourney): - #print "parseWinLine: line:",line - for i in range(len(names)): - if (line.startswith(names[i].encode("latin-1"))): #found a winner - if isTourney: - pos1=line.rfind("collected ")+10 - if (site=="ftp"): - pos2=line.find(")", pos1) - elif (site=="ps"): - pos2=line.find(" ", pos1) - winnings[i]+=int(line[pos1:pos2]) - else: - pos1=line.rfind("$")+1 - if (site=="ftp"): - pos2=line.find(")", pos1) - elif (site=="ps"): - pos2=line.find(" ", pos1) - winnings[i]+=float2int(line[pos1:pos2]) -#end def parseWinLine - -#returns the category (as per database) string for the given line -def recogniseCategory(line): - if (line.find("Razz")!=-1): - return "razz" - elif (line.find("Hold'em")!=-1): - return "holdem" - elif (line.find("Omaha")!=-1 and line.find("Hi/Lo")==-1 and line.find("H/L")==-1): - return "omahahi" - elif (line.find("Omaha")!=-1 and (line.find("Hi/Lo")!=-1 or line.find("H/L")!=-1)): - return "omahahilo" - elif (line.find("Stud")!=-1 and line.find("Hi/Lo")==-1 and line.find("H/L")==-1): - return "studhi" - elif (line.find("Stud")!=-1 and (line.find("Hi/Lo")!=-1 or line.find("H/L")!=-1)): - return "studhilo" - else: - raise FpdbError("failed to recognise category, line:"+line) -#end def recogniseCategory - -#returns the int for the gametype_id for the given line -def recogniseGametypeID(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 - if (site_id==1): #ftp - pos2=topline.find(" ", pos1) - elif (site_id==2): #ps - 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 (topline.find("No Limit")!=-1): - limit_type="nl" - if (topline.find("Cap No")!=-1): - limit_type="cn" - elif (topline.find("Pot Limit")!=-1): - limit_type="pl" - if (topline.find("Cap Pot")!=-1): - limit_type="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 ("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: - 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)) - result=cursor.fetchone() - #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 - cursor.execute("""INSERT INTO Gametypes - (siteId, type, base, category, limitType, hiLo, smallBlind, bigBlind, smallBet, bigBet) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", (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: - cursor.execute("""INSERT INTO Gametypes - (siteId, type, base, category, limitType, hiLo, smallBlind, bigBlind, smallBet, bigBet) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", (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)) - - result=cursor.fetchone() - #print "created new gametypes.id:",result - - return result[0] -#end def recogniseGametypeID - -def recogniseTourneyTypeId(cursor, siteId, buyin, fee, knockout, rebuyOrAddon): - cursor.execute ("SELECT id FROM TourneyTypes WHERE siteId=%s AND buyin=%s AND fee=%s AND knockout=%s AND rebuyOrAddon=%s", (siteId, buyin, fee, knockout, rebuyOrAddon)) - result=cursor.fetchone() - #print "tried SELECTing gametypes.id, result:",result - - try: - len(result) - except TypeError:#this means we need to create a new entry - cursor.execute("""INSERT INTO TourneyTypes (siteId, buyin, fee, knockout, rebuyOrAddon) VALUES (%s, %s, %s, %s, %s)""", (siteId, buyin, fee, knockout, rebuyOrAddon)) - cursor.execute("SELECT id FROM TourneyTypes WHERE siteId=%s AND buyin=%s AND fee=%s AND knockout=%s AND rebuyOrAddon=%s", (siteId, buyin, fee, knockout, rebuyOrAddon)) - result=cursor.fetchone() - return result[0] -#end def recogniseTourneyTypeId - -#returns the SQL ids of the names given in an array -def recognisePlayerIDs(cursor, names, site_id): - result = [] - for i in range (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 -#end def recognisePlayerIDs - -#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 range (len(names)): - if (atype=="unbet"): - if (line.endswith(names[i].encode("latin-1"))): - 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(names[i].encode("latin-1"))): - return (i) - elif (line.startswith("Seat ")): - if (line.startswith("Seat 10")): - tmp=line[9:] - else: - tmp=line[8:] - - if (tmp.startswith(names[i].encode("latin-1"))): - return (i) - else: - if (line.startswith(names[i].encode("latin-1"))): - return (i) - #if we're here we mustve failed - raise FpdbError ("failed to recognise player in: "+line+" atype:"+atype) -#end def recognisePlayerNo - -#returns the site abbreviation for the given site -def recogniseSite(line): - if (line.startswith("Full Tilt Poker")): - return "ftp" - elif (line.startswith("PokerStars")): - return "ps" - else: - raise FpdbError("failed to recognise site, line:"+line) -#end def recogniseSite - -#returns the ID of the given site -def recogniseSiteID(cursor, site): - if (site=="ftp"): - return 1 - #cursor.execute("SELECT id FROM Sites WHERE name = ('Full Tilt Poker')") - elif (site=="ps"): - return 2 - #cursor.execute("SELECT id FROM Sites WHERE name = ('PokerStars')") - else: - raise FpdbError("invalid site in recogniseSiteID: "+site) - return cursor.fetchall()[0][0] -#end def recogniseSiteID - -#removes trailing \n from the given array -def removeTrailingEOL(arr): - for i in range(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 range(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 range(len(winnings)): - if winnings[i]!=0: - winPortion=winnings[i]/totalWin - rakes[i]=totalRake*winPortion -#end def splitRake - -def storeActions(cursor, handsPlayersIds, actionTypes, allIns, actionAmounts, actionNos): -#stores into table hands_actions - #print "start of storeActions, actionNos:",actionNos - #print " action_amounts:",action_amounts - for i in range (len(actionTypes)): #iterate through streets - for j in range (len(actionTypes[i])): #iterate through names - for k in range (len(actionTypes[i][j])): #iterate through individual actions of that player on that street - cursor.execute ("INSERT INTO HandsActions (handPlayerId, street, actionNo, action, allIn, amount) VALUES (%s, %s, %s, %s, %s, %s)", (handsPlayersIds[j], i, actionNos[i][j][k], actionTypes[i][j][k], allIns[i][j][k], actionAmounts[i][j][k])) -#end def storeActions - -def store_board_cards(cursor, hands_id, board_values, board_suits): -#stores into table board_cards - cursor.execute ("""INSERT INTO BoardCards (handId, card1Value, card1Suit, - card2Value, card2Suit, card3Value, card3Suit, card4Value, card4Suit, - card5Value, card5Suit) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", - (hands_id, board_values[0], board_suits[0], board_values[1], board_suits[1], - board_values[2], board_suits[2], board_values[3], board_suits[3], - board_values[4], board_suits[4])) -#end def store_board_cards - -def storeHands(cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats): -#stores into table hands - cursor.execute ("INSERT INTO Hands (siteHandNo, gametypeId, handStart, seats, tableName, importTime, maxSeats) VALUES (%s, %s, %s, %s, %s, %s, %s)", (site_hand_no, gametype_id, hand_start_time, len(names), tableName, datetime.datetime.today(), maxSeats)) - #todo: find a better way of doing this... - cursor.execute("SELECT id FROM Hands WHERE siteHandNo=%s AND gametypeId=%s", (site_hand_no, gametype_id)) - return cursor.fetchall()[0][0] -#end def storeHands - -def store_hands_players_holdem_omaha(cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos): - result=[] - if (category=="holdem"): - for i in range (len(player_ids)): - cursor.execute (""" - INSERT INTO HandsPlayers - (handId, playerId, startCash, position, - card1Value, card1Suit, card2Value, card2Suit, winnings, rake, seatNo) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", - (hands_id, player_ids[i], start_cashes[i], positions[i], - card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], - 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]) - elif (category=="omahahi" or category=="omahahilo"): - for i in range (len(player_ids)): - cursor.execute ("""INSERT INTO HandsPlayers - (handId, playerId, startCash, position, - card1Value, card1Suit, card2Value, card2Suit, - card3Value, card3Suit, card4Value, card4Suit, winnings, rake, seatNo) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", - (hands_id, player_ids[i], start_cashes[i], positions[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], - 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]) - else: - raise FpdbError("invalid category") - return result -#end def store_hands_players_holdem_omaha - -def store_hands_players_stud(cursor, 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 - result=[] - #print "before inserts in store_hands_players_stud, antes:", antes - for i in range (len(player_ids)): - cursor.execute ("""INSERT INTO HandsPlayers - (handId, playerId, startCash, ante, - card1Value, card1Suit, card2Value, card2Suit, - card3Value, card3Suit, card4Value, card4Suit, - card5Value, card5Suit, card6Value, card6Suit, - card7Value, card7Suit, winnings, rake, seatNo) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s)""", - (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], 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]) - return result -#end def store_hands_players_stud - -def store_hands_players_holdem_omaha_tourney(cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids): -#stores hands_players for tourney holdem/omaha hands - result=[] - for i in range (len(player_ids)): - if len(card_values[0])==2: - cursor.execute ("""INSERT INTO HandsPlayers - (handId, playerId, startCash, position, - card1Value, card1Suit, card2Value, card2Suit, - winnings, rake, tourneysPlayersId, seatNo) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", - (hands_id, player_ids[i], start_cashes[i], positions[i], - card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], - winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i])) - elif len(card_values[0])==4: - cursor.execute ("""INSERT INTO HandsPlayers - (handId, playerId, startCash, position, - card1Value, card1Suit, card2Value, card2Suit, - card3Value, card3Suit, card4Value, card4Suit, - winnings, rake, tourneysPlayersId, seatNo) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", - (hands_id, player_ids[i], start_cashes[i], positions[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], - winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i])) - else: - raise FpdbError ("invalid card_values length:"+str(len(card_values[0]))) - cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i])) - result.append(cursor.fetchall()[0][0]) - - return result -#end def store_hands_players_holdem_omaha_tourney - -def store_hands_players_stud_tourney(cursor, hands_id, player_ids, start_cashes, - antes, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids): -#stores hands_players for tourney stud/razz hands - result=[] - for i in range (len(player_ids)): - cursor.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) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s)""", - (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])) - cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId=%s", (hands_id, player_ids[i])) - result.append(cursor.fetchall()[0][0]) - return result -#end def store_hands_players_stud_tourney - -def generateHudCacheData(player_ids, base, category, action_types, allIns, actionTypeByNo, winnings, totalWinnings, positions): - """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""" - #setup subarrays of the result dictionary. - street0VPI=[] - street0Aggr=[] - street0_3B4BChance=[] - street0_3B4BDone=[] - street1Seen=[] - street2Seen=[] - street3Seen=[] - street4Seen=[] - sawShowdown=[] - street1Aggr=[] - street2Aggr=[] - street3Aggr=[] - street4Aggr=[] - otherRaisedStreet1=[] - otherRaisedStreet2=[] - otherRaisedStreet3=[] - otherRaisedStreet4=[] - foldToOtherRaisedStreet1=[] - foldToOtherRaisedStreet2=[] - foldToOtherRaisedStreet3=[] - foldToOtherRaisedStreet4=[] - wonWhenSeenStreet1=[] - - wonAtSD=[] - stealAttemptChance=[] - stealAttempted=[] - hudDataPositions=[] - - firstPfRaiseByNo=-1 - firstPfRaiserId=-1 - firstPfRaiserNo=-1 - firstPfCallByNo=-1 - firstPfCallerId=-1 - for i in range(len(actionTypeByNo[0])): - if actionTypeByNo[0][i][1]=="bet": - firstPfRaiseByNo=i - firstPfRaiserId=actionTypeByNo[0][i][0] - for j in range(len(player_ids)): - if player_ids[j]==firstPfRaiserId: - firstPfRaiserNo=j - break - break - for i in range(len(actionTypeByNo[0])): - if actionTypeByNo[0][i][1]=="call": - firstPfCallByNo=i - firstPfCallerId=actionTypeByNo[0][i][0] - break - - cutoffId=-1 - buttonId=-1 - sbId=-1 - bbId=-1 - if base=="hold": - for player in range(len(positions)): - if positions==1: - cutoffId=player_ids[player] - if positions==0: - buttonId=player_ids[player] - if positions=='S': - sbId=player_ids[player] - if positions=='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 range (len(player_ids)): - #set default values - myStreet0VPI=False - myStreet0Aggr=False - myStreet0_3B4BChance=False - myStreet0_3B4BDone=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 - - #calculate VPIP and PFR - street=0 - heroPfRaiseCount=0 - for count in range (len(action_types[street][player])):#finally individual actions - currentAction=action_types[street][player][count] - if currentAction=="bet": - myStreet0Aggr=True - if (currentAction=="bet" or currentAction=="call"): - myStreet0VPI=True - - #PF3B4BChance and PF3B4B - pfFold=-1 - pfRaise=-1 - if firstPfRaiseByNo!=-1: - for i in range(len(actionTypeByNo[0])): - if actionTypeByNo[0][i][0]==player_ids[player]: - if actionTypeByNo[0][i][1]=="bet" and pfRaise==-1 and i>firstPfRaiseByNo: - pfRaise=i - if actionTypeByNo[0][i][1]=="fold" and pfFold==-1: - pfFold=i - if pfFold==-1 or pfFold>firstPfRaiseByNo: - myStreet0_3B4BChance=True - if pfRaise>firstPfRaiseByNo: - myStreet0_3B4BDone=True - - #steal calculations - if base=="hold": - if len(player_ids)>=5: #no point otherwise - if positions[player]==1: - if firstPfRaiserId==player_ids[player]: - myStealAttemptChance=True - myStealAttempted=True - elif firstPfRaiserId==buttonId or firstPfRaiserId==sbId or firstPfRaiserId==bbId or firstPfRaiserId==-1: - myStealAttemptChance=True - if positions[player]==0: - if firstPfRaiserId==player_ids[player]: - myStealAttemptChance=True - myStealAttempted=True - elif firstPfRaiserId==sbId or firstPfRaiserId==bbId or firstPfRaiserId==-1: - myStealAttemptChance=True - if positions[player]=='S': - if firstPfRaiserId==player_ids[player]: - myStealAttemptChance=True - myStealAttempted=True - elif firstPfRaiserId==bbId or firstPfRaiserId==-1: - myStealAttemptChance=True - if positions[player]=='B': - pass - - if myStealAttempted: - someoneStole=True - - - #calculate saw* values - isAllIn=False - for i in range(len(allIns[0][player])): - if allIns[0][player][i]: - isAllIn=True - if (len(action_types[1][player])>0 or isAllIn): - myStreet1Seen=True - - for i in range(len(allIns[1][player])): - if allIns[1][player][i]: - isAllIn=True - if (len(action_types[2][player])>0 or isAllIn): - myStreet2Seen=True - - for i in range(len(allIns[2][player])): - if allIns[2][player][i]: - isAllIn=True - if (len(action_types[3][player])>0 or isAllIn): - myStreet3Seen=True - - #print "base:", base - if base=="hold": - mySawShowdown=True - for count in range (len(action_types[3][player])): - if action_types[3][player][count]=="fold": - mySawShowdown=False - else: - #print "in else" - for i in range(len(allIns[3][player])): - if allIns[3][player][i]: - isAllIn=True - if (len(action_types[4][player])>0 or isAllIn): - #print "in if" - myStreet4Seen=True - - mySawShowdown=True - for count in range (len(action_types[4][player])): - if action_types[4][player][count]=="fold": - mySawShowdown=False - - - #flop stuff - street=1 - if myStreet1Seen: - for count in range(len(action_types[street][player])): - if action_types[street][player][count]=="bet": - myStreet1Aggr=True - - for otherPlayer in range (len(player_ids)): - if player==otherPlayer: - pass - else: - for countOther in range (len(action_types[street][otherPlayer])): - if action_types[street][otherPlayer][countOther]=="bet": - myOtherRaisedStreet1=True - for countOtherFold in range (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: - for count in range(len(action_types[street][player])): - if action_types[street][player][count]=="bet": - myStreet2Aggr=True - - for otherPlayer in range (len(player_ids)): - if player==otherPlayer: - pass - else: - for countOther in range (len(action_types[street][otherPlayer])): - if action_types[street][otherPlayer][countOther]=="bet": - myOtherRaisedStreet2=True - for countOtherFold in range (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: - for count in range(len(action_types[street][player])): - if action_types[street][player][count]=="bet": - myStreet3Aggr=True - - for otherPlayer in range (len(player_ids)): - if player==otherPlayer: - pass - else: - for countOther in range (len(action_types[street][otherPlayer])): - if action_types[street][otherPlayer][countOther]=="bet": - myOtherRaisedStreet3=True - for countOtherFold in range (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: - for count in range(len(action_types[street][player])): - if action_types[street][player][count]=="bet": - myStreet4Aggr=True - - for otherPlayer in range (len(player_ids)): - if player==otherPlayer: - pass - else: - for countOther in range (len(action_types[street][otherPlayer])): - if action_types[street][otherPlayer][countOther]=="bet": - myOtherRaisedStreet4=True - for countOtherFold in range (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_3B4BChance.append(myStreet0_3B4BChance) - street0_3B4BDone.append(myStreet0_3B4BDone) - 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 - - #add each array to the to-be-returned dictionary - result={'street0VPI':street0VPI} - result['street0Aggr']=street0Aggr - result['street0_3B4BChance']=street0_3B4BChance - result['street0_3B4BDone']=street0_3B4BDone - 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 - - #now the various steal values - foldBbToStealChance=[] - foldedBbToSteal=[] - foldSbToStealChance=[] - foldedSbToSteal=[] - for player in range (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 range (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 range (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 range (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 range (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 range (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 range (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=[] - for player in range (len(player_ids)): - myTotalProfit=0 - - myStreet1CheckCallRaiseChance=False - myStreet1CheckCallRaiseDone=False - myStreet2CheckCallRaiseChance=False - myStreet2CheckCallRaiseDone=False - myStreet3CheckCallRaiseChance=False - myStreet3CheckCallRaiseDone=False - myStreet4CheckCallRaiseChance=False - myStreet4CheckCallRaiseDone=False - - totalProfit.append(myTotalProfit) - - 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 - - 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 range(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 range(len(playerIDs)): - if playerIDs[player]==action[0]: - foldToStreetCBChance[player]=True - if action[1]=="fold": - foldToStreetCBDone[player]=True -#end def generateFoldToCB - -def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData): -# if (category=="holdem" or category=="omahahi" or category=="omahahilo"): - - for player in range (len(playerIds)): - if base=="hold": - cursor.execute("SELECT * FROM HudCache WHERE gametypeId+0=%s AND playerId=%s AND activeSeats=%s AND position=%s", (gametypeId, playerIds[player], len(playerIds), hudImportData['position'][player])) - else: - cursor.execute("SELECT * FROM HudCache WHERE gametypeId+0=%s AND playerId=%s AND activeSeats=%s", (gametypeId, playerIds[player], len(playerIds))) - row=cursor.fetchone() - #print "gametypeId:", gametypeId, "playerIds[player]",playerIds[player], "len(playerIds):",len(playerIds), "row:",row - - try: len(row) - except TypeError: - row=[] - - if (len(row)==0): - #print "new huddata row" - doInsert=True - row=[] - row.append(0)#blank for id - row.append(gametypeId) - row.append(playerIds[player]) - row.append(len(playerIds))#seats - for i in range(len(hudImportData)+2): - row.append(0) - - else: - doInsert=False - newrow=[] - for i in range(len(row)): - newrow.append(row[i]) - row=newrow - - 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_3B4BChance'][player]: row[9]+=1 - if hudImportData['street0_3B4BDone'][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 - - 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 - - if doInsert: - #print "playerid before insert:",row[2] - cursor.execute("""INSERT INTO HudCache - (gametypeId, playerId, activeSeats, position, tourneyTypeId, - HDs, street0VPI, street0Aggr, street0_3B4BChance, street0_3B4BDone, - 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)""", (row[1], row[2], row[3], row[4], row[5], 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])) - else: - #print "storing updated hud data line" - cursor.execute("""UPDATE HudCache - SET HDs=%s, street0VPI=%s, street0Aggr=%s, street0_3B4BChance=%s, street0_3B4BDone=%s, - street1Seen=%s, street2Seen=%s, street3Seen=%s, street4Seen=%s, sawShowdown=%s, - street1Aggr=%s, street2Aggr=%s, street3Aggr=%s, street4Aggr=%s, otherRaisedStreet1=%s, - otherRaisedStreet2=%s, otherRaisedStreet3=%s, otherRaisedStreet4=%s, foldToOtherRaisedStreet1=%s, foldToOtherRaisedStreet2=%s, - foldToOtherRaisedStreet3=%s, foldToOtherRaisedStreet4=%s, wonWhenSeenStreet1=%s, wonAtSD=%s, stealAttemptChance=%s, - stealAttempted=%s, foldBbToStealChance=%s, foldedBbToSteal=%s, foldSbToStealChance=%s, foldedSbToSteal=%s, - street1CBChance=%s, street1CBDone=%s, street2CBChance=%s, street2CBDone=%s, street3CBChance=%s, - street3CBDone=%s, street4CBChance=%s, street4CBDone=%s, foldToStreet1CBChance=%s, foldToStreet1CBDone=%s, - foldToStreet2CBChance=%s, foldToStreet2CBDone=%s, foldToStreet3CBChance=%s, foldToStreet3CBDone=%s, foldToStreet4CBChance=%s, - foldToStreet4CBDone=%s, totalProfit=%s, street1CheckCallRaiseChance=%s, street1CheckCallRaiseDone=%s, street2CheckCallRaiseChance=%s, - street2CheckCallRaiseDone=%s, street3CheckCallRaiseChance=%s, street3CheckCallRaiseDone=%s, street4CheckCallRaiseChance=%s, street4CheckCallRaiseDone=%s - WHERE gametypeId=%s AND playerId=%s AND activeSeats=%s AND position=%s AND tourneyTypeId=%s""", (row[6], row[7], row[8], row[9], row[10], - row[11], row[12], row[13], row[14], row[15], - row[16], row[17], row[18], row[19], row[20], - row[21], row[22], row[23], row[24], row[25], - row[26], row[27], row[28], row[29], row[30], - row[31], row[32], row[33], row[34], row[35], row[36], row[37], row[38], row[39], row[40], - row[41], row[42], row[43], row[44], row[45], row[46], row[47], row[48], row[49], row[50], - row[51], row[52], row[53], row[54], row[55], row[56], row[57], row[58], row[59], row[60], - row[1], row[2], row[3], str(row[4]), row[5])) -# else: -# print "todo: implement storeHudCache for stud base" -#end def storeHudCache - -def store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, startTime): - cursor.execute("SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s", (siteTourneyNo, tourneyTypeId)) - tmp=cursor.fetchone() - #print "tried SELECTing tourneys.id, result:",tmp - - try: - len(tmp) - except TypeError:#means we have to create new one - cursor.execute("""INSERT INTO Tourneys - (tourneyTypeId, siteTourneyNo, entries, prizepool, startTime) - VALUES (%s, %s, %s, %s, %s)""", (tourneyTypeId, siteTourneyNo, entries, prizepool, startTime)) - cursor.execute("SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s", (siteTourneyNo, tourneyTypeId)) - tmp=cursor.fetchone() - #print "created new tourneys.id:",tmp - return tmp[0] -#end def store_tourneys - -def store_tourneys_players(cursor, tourney_id, player_ids, payin_amounts, ranks, winnings): - result=[] - #print "in store_tourneys_players. tourney_id:",tourney_id - #print "player_ids:",player_ids - #print "payin_amounts:",payin_amounts - #print "ranks:",ranks - #print "winnings:",winnings - for i in range (len(player_ids)): - cursor.execute("SELECT id FROM TourneysPlayers WHERE tourneyId=%s AND playerId+0=%s", (tourney_id, player_ids[i])) - tmp=cursor.fetchone() - #print "tried SELECTing tourneys_players.id:",tmp - - try: - len(tmp) - except TypeError: - cursor.execute("""INSERT INTO TourneysPlayers - (tourneyId, playerId, payinAmount, rank, winnings) VALUES (%s, %s, %s, %s, %s)""", - (tourney_id, player_ids[i], payin_amounts[i], ranks[i], winnings[i])) - - cursor.execute("SELECT id FROM TourneysPlayers WHERE tourneyId=%s AND playerId+0=%s", - (tourney_id, player_ids[i])) - tmp=cursor.fetchone() - #print "created new tourneys_players.id:",tmp - result.append(tmp[0]) - return result -#end def store_tourneys_players +#!/usr/bin/python + +#Copyright 2008 Steffen Jobbagy-Felso +#This program is free software: you can redistribute it and/or modify +#it under the terms of the GNU Affero General Public License as published by +#the Free Software Foundation, version 3 of the License. +# +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. +# +#You should have received a copy of the GNU Affero General Public License +#along with this program. If not, see . +#In the "official" distribution you can find the license in +#agpl-3.0.txt in the docs folder of the package. + +#This file contains simple functions for fpdb + +import datetime +import re + +PS=1 +FTP=2 + +class DuplicateError(Exception): + def __init__(self, value): + self.value = value + def __str__(self): + return repr(self.value) + +class FpdbError(Exception): + def __init__(self, value): + self.value = value + def __str__(self): + return repr(self.value) + +#returns an array of the total money paid. intending to add rebuys/addons here +def calcPayin(count, buyin, fee): + result=[] + for i in range(count): + result.append (buyin+fee) + return result +#end def calcPayin + +def checkPositions(positions): + """verifies that these positions are valid""" + for i in range (len(positions)): + pos=positions[i] + try:#todo: use type recognition instead of error + if (len(pos)!=1): + raise FpdbError("invalid position found in checkPositions. i: "+str(i)+" position: "+pos) #dont need to str() here + except TypeError:#->not string->is int->fine + pass + + ### RHH modified to allow for "position 9" here (pos==9 is when you're a dead hand before the BB + if (pos!="B" and pos!="S" and pos!=0 and pos!=1 and pos!=2 and pos!=3 and pos!=4 and pos!=5 and pos!=6 and pos!=7 and pos!=9): + raise FpdbError("invalid position found in checkPositions. i: "+str(i)+" position: "+str(pos)) +#end def fpdb_simple.checkPositions + +#classifies each line for further processing in later code. Manipulates the passed arrays. +def classifyLines(hand, category, lineTypes, lineStreets): + currentStreet="predeal" + done=False #set this to true once we reach the last relevant line (the summary, except rake, is all repeats) + for i in range (len(hand)): + if (done): + if (hand[i].find("[")==-1 or hand[i].find("mucked [")==-1): + lineTypes.append("ignore") + else: #it's storing a mucked card + lineTypes.append("cards") + elif (hand[i].startswith("Dealt to")): + lineTypes.append("cards") + elif (i==0): + lineTypes.append("header") + elif (hand[i].startswith("Seat ") and ((hand[i].find("in chips")!=-1) or (hand[i].find("($")!=-1))): + lineTypes.append("name") + elif (isActionLine(hand[i])): + lineTypes.append("action") + if (hand[i].find(" posts ")!=-1 or hand[i].find(" posts the ")!=-1):#need to set this here so the "action" of posting blinds is registered properly + currentStreet="preflop" + elif (isWinLine(hand[i])): + lineTypes.append("win") + elif (hand[i].startswith("Total pot ") and hand[i].find("Rake")!=-1): + lineTypes.append("rake") + done=True + elif (hand[i]=="*** SHOW DOWN ***" or hand[i]=="*** SUMMARY ***"): + lineTypes.append("ignore") + #print "in classifyLine, showdown or summary" + elif (hand[i].find(" antes ")!=-1 or hand[i].find(" posts the ante ")!=-1): + lineTypes.append("ante") + elif (hand[i].startswith("*** FLOP *** [")): + lineTypes.append("cards") + currentStreet="flop" + elif (hand[i].startswith("*** TURN *** [")): + lineTypes.append("cards") + currentStreet="turn" + elif (hand[i].startswith("*** RIVER *** [")): + lineTypes.append("cards") + currentStreet="river" + elif (hand[i].startswith("*** 3")): + lineTypes.append("ignore") + currentStreet=0 + elif (hand[i].startswith("*** 4")): + lineTypes.append("ignore") + currentStreet=1 + elif (hand[i].startswith("*** 5")): + lineTypes.append("ignore") + currentStreet=2 + elif (hand[i].startswith("*** 6")): + lineTypes.append("ignore") + currentStreet=3 + elif (hand[i].startswith("*** 7") or hand[i]=="*** RIVER ***"): + lineTypes.append("ignore") + currentStreet=4 + elif (hand[i].find(" shows [")!=-1): + lineTypes.append("cards") + elif (hand[i].startswith("Table '")): + lineTypes.append("table") + else: + raise FpdbError("unrecognised linetype in:"+hand[i]) + lineStreets.append(currentStreet) +#end def classifyLines + +def convert3B4B(site, category, limit_type, actionTypes, actionAmounts): + """calculates the actual bet amounts in the given amount array and changes it accordingly.""" + for i in range (len(actionTypes)): + for j in range (len(actionTypes[i])): + bets=[] + for k in range (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) + amount2=actionAmounts[bets[1][0]][bets[1][1]][bets[1][2]] + amount1=actionAmounts[bets[0][0]][bets[0][1]][bets[0][2]] + actionAmounts[bets[1][0]][bets[1][1]][bets[1][2]]=amount2-amount1 + elif (len(bets)>2): + fail=True + #todo: run correction for below + if (site=="ps" and category=="holdem" and limit_type=="nl" and len(bets)==3): + fail=False + if (site=="ftp" and category=="omahahi" and limit_type=="pl" and len(bets)==3): + fail=False + + if fail: + print "len(bets)>2 in convert3B4B, i didnt think this is possible. i:",i,"j:",j,"k:",k + print "actionTypes:",actionTypes + raise FpdbError ("too many bets in convert3B4B") + #print "actionAmounts postConvert",actionAmounts +#end def convert3B4B(actionTypes, actionAmounts) + +#Corrects the bet amount if the player had to pay blinds +def convertBlindBet(actionTypes, actionAmounts): + i=0#setting street to pre-flop + for j in range (len(actionTypes[i])):#playerloop + blinds=[] + bets=[] + for k in range (len(actionTypes[i][j])): + if (actionTypes[i][j][k]=="blind"): + blinds.append((i,j,k)) + + if (len(blinds)>0 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 +#end def convertBlindBet + +#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): + for i in range (len(arr)): + for j in range (len(arr[i])): + if (arr[i][j]=="A"): + arr[i][j]=14 + elif (arr[i][j]=="K"): + arr[i][j]=13 + elif (arr[i][j]=="Q"): + arr[i][j]=12 + elif (arr[i][j]=="J"): + arr[i][j]=11 + elif (arr[i][j]=="T"): + arr[i][j]=10 + else: + arr[i][j]=int(arr[i][j]) +#end def convertCardValues + +#converts the strings in the given array to ints (changes the passed array, no returning). see table design for conversion details +def convertCardValuesBoard(arr): + for i in range (len(arr)): + if (arr[i]=="A"): + arr[i]=14 + elif (arr[i]=="K"): + arr[i]=13 + elif (arr[i]=="Q"): + arr[i]=12 + elif (arr[i]=="J"): + arr[i]=11 + elif (arr[i]=="T"): + arr[i]=10 + else: + arr[i]=int(arr[i]) +#end def convertCardValuesBoard + +#this creates the 2D/3D arrays. manipulates the passed arrays instead of returning. +def createArrays(category, seats, card_values, card_suits, antes, winnings, rakes, action_types, allIns, action_amounts, actionNos, actionTypeByNo): + for i in range(seats):#create second dimension arrays + tmp=[] + card_values.append(tmp) + tmp=[] + card_suits.append(tmp) + antes.append(0) + winnings.append(0) + rakes.append(0) + + if (category=="holdem" or category=="omahahi" or category=="omahahilo"): + streetCount=4 + else: + streetCount=5 + + for i in range(streetCount): #build the first dimension array, for streets + tmp=[] + action_types.append(tmp) + tmp=[] + allIns.append(tmp) + tmp=[] + action_amounts.append(tmp) + tmp=[] + actionNos.append(tmp) + tmp=[] + actionTypeByNo.append(tmp) + for j in range (seats): #second dimension arrays: players + tmp=[] + action_types[i].append(tmp) + tmp=[] + allIns[i].append(tmp) + tmp=[] + action_amounts[i].append(tmp) + tmp=[] + actionNos[i].append(tmp) + if (category=="holdem" or category=="omahahi" or category=="omahahilo"): + pass + elif (category=="razz" or category=="studhi" or category=="studhilo"):#need to fill card arrays. + for i in range(seats): + for j in range (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") +#end def fill_board_cards + +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 fpdb_simple.FpdbError ("invalid category:", category) + + for i in range (player_count): + while (len(card_values[i])=1): + raise DuplicateError ("dupl") +#end isAlreadyInDB + +def isRebuyOrAddon(topline): + """isRebuyOrAddon not implemented yet""" + return False +#end def isRebuyOrAddon + +#returns whether the passed topline indicates a tournament or not +def isTourney(topline): + if (topline.find("Tournament")!=-1): + return True + else: + return False +#end def isTourney + +#returns boolean whether the passed line is a win line +def isWinLine(line): + if (line.find("wins the pot")!=-1): + return True + elif (line.find("ties for the high pot")!=-1): + return True + elif (line.find("ties for the high main pot")!=-1): + return True + elif (line.find("ties for the high side pot")!=-1): + return True + elif (line.find("ties for the low pot")!=-1): + return True + elif (line.find("ties for the low main pot")!=-1): + return True + elif (line.find("ties for the low side pot")!=-1): + return True + elif (line.find("ties for the main pot")!=-1): #for ftp tied main pot of split pot + return True + elif (line.find("ties for the pot")!=-1): #for ftp tie + return True + elif (line.find("ties for the side pot")!=-1): #for ftp tied split pots + return True + elif (line.find("wins side pot #")!=-1): #for ftp multi split pots + return True + elif (line.find("wins the low main pot")!=-1): + return True + elif (line.find("wins the low pot")!=-1): + return True + elif (line.find("wins the low side pot")!=-1): + return True + elif (line.find("wins the high main pot")!=-1): + return True + elif (line.find("wins the high pot")!=-1): + return True + elif (line.find("wins the high side pot")!=-1): + return True + elif (line.find("wins the main pot")!=-1): + return True + elif (line.find("wins the side pot")!=-1): #for ftp split pots + return True + elif (line.find("collected")!=-1): + return True + else: + return False #not raising error here, any unknown line wouldve been detected in isActionLine already +#end def isWinLine + +#returns the amount of cash/chips put into the put in the given action line +def parseActionAmount(line, atype, site, isTourney): + #if (line.endswith(" and is all-in")): + # line=line[:-14] + #elif (line.endswith(", and is all in")): + # line=line[:-15] + + if line.endswith(", and is capped"):#ideally we should recognise this as an all-in if category is capXl + line=line[:-15] + if line.endswith(" and is capped"): + line=line[:-14] + + + if (atype=="fold"): + amount=0 + elif (atype=="check"): + amount=0 + elif (atype=="unbet" and site=="ftp"): + pos1=line.find("$")+1 + pos2=line.find(" returned to") + amount=float2int(line[pos1:pos2]) + elif (atype=="unbet" and site=="ps"): + #print "ps unbet, line:",line + pos1=line.find("$")+1 + if pos1==0: + pos1=line.find("(")+1 + pos2=line.find(")") + amount=float2int(line[pos1:pos2]) + elif (atype=="bet" and site=="ps" and line.find(": raises $")!=-1 and line.find("to $")!=-1): + 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(site, 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 range(len(actionNos[street])): + for count in range(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, site, 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) +#end def parseActionLine + +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) +#end def goesAllInOnThisLine + +#returns the action type code (see table design) of the given action line +def parseActionType(line): + if (line.startswith("Uncalled bet")): + return "unbet" + elif (line.endswith("folds")): + return "fold" + elif (line.endswith("checks")): + return "check" + elif (line.find("calls")!=-1): + return "call" + elif (line.find("brings in for")!=-1): + return "blind" + elif (line.find("completes it to")!=-1): + return "bet" + #todo: what if someone completes instead of bringing in? + elif (line.find(" posts $")!=-1): + return "blind" + elif (line.find(" posts a dead ")!=-1): + return "blind" + elif (line.find(": posts small blind ")!=-1): + return "blind" + elif (line.find(" posts the small blind of $")!=-1): + return "blind" + elif (line.find(": posts big blind ")!=-1): + return "blind" + elif (line.find(" posts the big blind of $")!=-1): + return "blind" + elif (line.find(": posts small & big blinds $")!=-1): + return "blind" + #todo: seperately record voluntary blind payments made to join table out of turn + elif (line.find("bets")!=-1): + return "bet" + elif (line.find("raises")!=-1): + return "bet" + else: + raise FpdbError ("failed to recognise actiontype in parseActionLine in: "+line) +#end def parseActionType + +#parses the ante out of the given line and checks which player paid it, updates antes accordingly. +def parseAnteLine(line, site, isTourney, names, antes): + for i in range(len(names)): + if (line.startswith(names[i].encode("latin-1"))): #found the ante'er + pos=line.rfind("$")+1 + if not isTourney: + antes[i]+=float2int(line[pos:]) + else: + if line.find("all-in")==-1: + 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]) + #print "parseAnteLine line: ", line, "antes[i]", antes[i], "antes", antes +#end def parseAntes + +#returns the buyin of a tourney in cents +def parseBuyin(topline): + pos1=topline.find("$")+1 + pos2=topline.find("+") + return float2int(topline[pos1:pos2]) +#end def parseBuyin + +#parses a card line and changes the passed arrays accordingly +#todo: reorganise this messy method +def parseCardLine(site, category, street, line, names, cardValues, cardSuits, boardValues, boardSuits): + if (line.startswith("Dealt to ") or line.find(" shows [")!=-1 or line.find("mucked [")!=-1): + 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]: #two tests will do + 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 (line.find("shows")==-1): + #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) +#end def parseCardLine + +def parseCashesAndSeatNos(lines, site): + """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 range (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 + if (site=="ftp"): + pos2=lines[i].rfind(")") + elif (site=="ps"): + pos2=lines[i].find(" in chips") + cashes.append(float2int(lines[i][pos1:pos2])) + return {'startCashes':cashes, 'seatNos':seatNos} +#end def parseCashesAndSeatNos + +#returns the buyin of a tourney in cents +def parseFee(topline): + pos1=topline.find("$")+1 + pos1=topline.find("$",pos1)+1 + pos2=topline.find(" ", pos1) + return float2int(topline[pos1:pos2]) +#end def parsefee + +#returns a datetime object with the starttime indicated in the given topline +def parseHandStartTime(topline, site): + #convert x:13:35 to 0x:13:35 + counter=0 + while (True): + pos=topline.find(" "+str(counter)+":") + if (pos!=-1): + topline=topline[0:pos+1]+"0"+topline[pos+1:] + counter+=1 + if counter==10: break + + isUTC=False + if site=="ftp": + pos = topline.find(" ", len(topline)-26)+1 + tmp = topline[pos:] + #print "year:", tmp[14:18], "month", tmp[19:21], "day", tmp[22:24], "hour", tmp[0:2], "minute", tmp[3:5], "second", tmp[6:8] + result = datetime.datetime(int(tmp[14:18]), int(tmp[19:21]), int(tmp[22:24]), int(tmp[0:2]), int(tmp[3:5]), int(tmp[6:8])) + elif site=="ps": + if topline.find("UTC")!=-1: + pos1 = topline.find("-")+2 + pos2 = topline.find("UTC") + tmp=topline[pos1:pos2] + isUTC=True + else: + tmp=topline[-30:] + #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) + m = re.match('(?P[0-9]{4})\/(?P[0-9]{2})\/(?P[0-9]{2})[\- ]+(?P
[0-9]{2}):(?P[0-9]{2}):(?P[0-9]{2})',tmp) + #print "year:", int(m.group('YEAR')), "month", int(m.group('MON')), "day", int(m.group('DAY')), "hour", int(m.group('HR')), "minute", int(m.group('MIN')), "second", int(m.group('SEC')) + 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'))) + else: + raise FpdbError("invalid site in parseHandStartTime") + + if (site=="ftp" or site=="ps") and not isUTC: #these use US ET + result+=datetime.timedelta(hours=5) + + return result +#end def parseHandStartTime + +#parses the names out of the given lines and returns them as an array +def parseNames(lines): + result = [] + for i in range (len(lines)): + pos1=lines[i].find(":")+2 + pos2=lines[i].rfind("(")-1 + tmp=lines[i][pos1:pos2] + #print "parseNames, tmp original:",tmp + tmp=unicode(tmp,"latin-1") + #print "parseNames, tmp after unicode latin-1 conversion:",tmp + result.append(tmp) + return result +#end def parseNames + +#returns an array with the positions of the respective players +def parsePositions (hand, names): + #prep array + positions=[] + for i in range(len(names)): + positions.append(-1) + + #find blinds + sb,bb=-1,-1 + for i in range (len(hand)): + if (sb==-1 and hand[i].find("small blind")!=-1 and hand[i].find("dead small blind")==-1): + sb=hand[i] + #print "sb:",sb + if (bb==-1 and hand[i].find("big blind")!=-1 and hand[i].find("dead big blind")==-1): + bb=hand[i] + #print "bb:",bb + + #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") + + #write blinds into array + if (sbExists): + positions[sb]="S" + positions[bb]="B" + + #fill up rest of array + if (sbExists): + arraypos=sb-1 + else: + arraypos=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 + + ### RHH - Changed to set the null seats before BB to "9" + i=bb-1 + while positions[i] < 0: + positions[i]=9 + i-=1 + + arraypos=len(names)-1 + if (bb!=0 or (bb==0 and sbExists==False)): + while (arraypos>bb): + positions[arraypos]=distFromBtn + arraypos-=1 + distFromBtn+=1 + + for i in range (len(names)): + if positions[i]==-1: + print "parsePositions names:",names + print "result:",positions + raise FpdbError ("failed to read positions") + return positions +#end def parsePositions + +#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 +#end def parseRake + +def parseSiteHandNo(topline): + """returns the hand no assigned by the poker site""" + pos1=topline.find("#")+1 + pos2=topline.find(":") + return topline[pos1:pos2] +#end def parseSiteHandNo + +def parseTableLine(site, base, line): + """returns a dictionary with maxSeats and tableName""" + if site=="ps": + 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]} + elif site=="ftp": + pos1=line.find("Table ")+6 + pos2=line.find("-")-1 + if base=="hold": + maxSeats=9 + elif base=="stud": + maxSeats=8 + + if line.find("6 max")!=-1: + maxSeats=6 + elif line.find("4 max")!=-1: + maxSeats=4 + elif line.find("heads up")!=-1: + maxSeats=2 + + return {'maxSeats':maxSeats, 'tableName':line[pos1:pos2]} + else: + raise FpdbError("invalid site ID") +#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] +#end def parseTourneyNo + +#parses a win/collect line. manipulates the passed array winnings, no explicit return +def parseWinLine(line, site, names, winnings, isTourney): + #print "parseWinLine: line:",line + for i in range(len(names)): + if (line.startswith(names[i].encode("latin-1"))): #found a winner + if isTourney: + pos1=line.rfind("collected ")+10 + if (site=="ftp"): + pos2=line.find(")", pos1) + elif (site=="ps"): + pos2=line.find(" ", pos1) + winnings[i]+=int(line[pos1:pos2]) + else: + pos1=line.rfind("$")+1 + if (site=="ftp"): + pos2=line.find(")", pos1) + elif (site=="ps"): + pos2=line.find(" ", pos1) + winnings[i]+=float2int(line[pos1:pos2]) +#end def parseWinLine + +#returns the category (as per database) string for the given line +def recogniseCategory(line): + if (line.find("Razz")!=-1): + return "razz" + elif (line.find("Hold'em")!=-1): + return "holdem" + elif (line.find("Omaha")!=-1 and line.find("Hi/Lo")==-1 and line.find("H/L")==-1): + return "omahahi" + elif (line.find("Omaha")!=-1 and (line.find("Hi/Lo")!=-1 or line.find("H/L")!=-1)): + return "omahahilo" + elif (line.find("Stud")!=-1 and line.find("Hi/Lo")==-1 and line.find("H/L")==-1): + return "studhi" + elif (line.find("Stud")!=-1 and (line.find("Hi/Lo")!=-1 or line.find("H/L")!=-1)): + return "studhilo" + else: + raise FpdbError("failed to recognise category, line:"+line) +#end def recogniseCategory + +#returns the int for the gametype_id for the given line +def recogniseGametypeID(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 + if (site_id==1): #ftp + pos2=topline.find(" ", pos1) + elif (site_id==2): #ps + 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 (topline.find("No Limit")!=-1): + limit_type="nl" + if (topline.find("Cap No")!=-1): + limit_type="cn" + elif (topline.find("Pot Limit")!=-1): + limit_type="pl" + if (topline.find("Cap Pot")!=-1): + limit_type="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 ("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: + 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)) + 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 + cursor.execute("""INSERT INTO Gametypes + (siteId, type, base, category, limitType, hiLo, smallBlind, bigBlind, smallBet, bigBet) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", (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: + cursor.execute("""INSERT INTO Gametypes + (siteId, type, base, category, limitType, hiLo, smallBlind, bigBlind, smallBet, bigBet) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", (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)) + + result=(db.insert_id(),) + #print "recgt2 result=",result + #print "created new gametypes.id:",result + + #print "recgt3: result=", result + return result[0] +#end def recogniseGametypeID + +def recogniseTourneyTypeId(cursor, siteId, buyin, fee, knockout, rebuyOrAddon): + cursor.execute ("SELECT id FROM TourneyTypes WHERE siteId=%s AND buyin=%s AND fee=%s AND knockout=%s AND rebuyOrAddon=%s", (siteId, buyin, fee, knockout, rebuyOrAddon)) + result=cursor.fetchone() + #print "tried SELECTing gametypes.id, result:",result + + try: + len(result) + except TypeError:#this means we need to create a new entry + cursor.execute("""INSERT INTO TourneyTypes (siteId, buyin, fee, knockout, rebuyOrAddon) VALUES (%s, %s, %s, %s, %s)""", (siteId, buyin, fee, knockout, rebuyOrAddon)) + cursor.execute("SELECT id FROM TourneyTypes WHERE siteId=%s AND buyin=%s AND fee=%s AND knockout=%s AND rebuyOrAddon=%s", (siteId, buyin, fee, knockout, rebuyOrAddon)) + result=cursor.fetchone() + return result[0] +#end def recogniseTourneyTypeId + +#returns the SQL ids of the names given in an array +def recognisePlayerIDs(cursor, names, site_id): + result = [] + for i in range (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 +#end def recognisePlayerIDs + +#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 range (len(names)): + if (atype=="unbet"): + if (line.endswith(names[i].encode("latin-1"))): + 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(names[i].encode("latin-1"))): + return (i) + elif (line.startswith("Seat ")): + if (line.startswith("Seat 10")): + tmp=line[9:] + else: + tmp=line[8:] + + if (tmp.startswith(names[i].encode("latin-1"))): + return (i) + else: + if (line.startswith(names[i].encode("latin-1"))): + return (i) + #if we're here we mustve failed + raise FpdbError ("failed to recognise player in: "+line+" atype:"+atype) +#end def recognisePlayerNo + +#returns the site abbreviation for the given site +def recogniseSite(line): + if (line.startswith("Full Tilt Poker")): + return "ftp" + elif (line.startswith("PokerStars")): + return "ps" + else: + raise FpdbError("failed to recognise site, line:"+line) +#end def recogniseSite + +#returns the ID of the given site +def recogniseSiteID(cursor, site): + if (site=="ftp"): + return 1 + #cursor.execute("SELECT id FROM Sites WHERE name = ('Full Tilt Poker')") + elif (site=="ps"): + return 2 + #cursor.execute("SELECT id FROM Sites WHERE name = ('PokerStars')") + else: + raise FpdbError("invalid site in recogniseSiteID: "+site) + return cursor.fetchall()[0][0] +#end def recogniseSiteID + +#removes trailing \n from the given array +def removeTrailingEOL(arr): + for i in range(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 range(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 range(len(winnings)): + if winnings[i]!=0: + winPortion=winnings[i]/totalWin + rakes[i]=totalRake*winPortion +#end def splitRake + +def storeActions(cursor, handsPlayersIds, actionTypes, allIns, actionAmounts, actionNos): +#stores into table hands_actions + #print "start of storeActions, actionNos:",actionNos + #print " action_amounts:",action_amounts + for i in range (len(actionTypes)): #iterate through streets + for j in range (len(actionTypes[i])): #iterate through names + for k in range (len(actionTypes[i][j])): #iterate through individual actions of that player on that street + cursor.execute ("INSERT INTO HandsActions (handPlayerId, street, actionNo, action, allIn, amount) VALUES (%s, %s, %s, %s, %s, %s)" + , (handsPlayersIds[j], i, actionNos[i][j][k], actionTypes[i][j][k], allIns[i][j][k], actionAmounts[i][j][k])) +#end def storeActions + +def store_board_cards(cursor, hands_id, board_values, board_suits): +#stores into table board_cards + cursor.execute ("""INSERT INTO BoardCards (handId, card1Value, card1Suit, + card2Value, card2Suit, card3Value, card3Suit, card4Value, card4Suit, + card5Value, card5Suit) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", + (hands_id, board_values[0], board_suits[0], board_values[1], board_suits[1], + board_values[2], board_suits[2], board_values[3], board_suits[3], + board_values[4], board_suits[4])) +#end def store_board_cards + +def storeHands(db, cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats): +#stores into table hands + cursor.execute ("INSERT INTO Hands (siteHandNo, gametypeId, handStart, seats, tableName, importTime, maxSeats) VALUES (%s, %s, %s, %s, %s, %s, %s)", (site_hand_no, gametype_id, hand_start_time, len(names), tableName, datetime.datetime.today(), maxSeats)) + #todo: find a better way of doing this... + #cursor.execute("SELECT id FROM Hands WHERE siteHandNo=%s AND gametypeId=%s", (site_hand_no, gametype_id)) + #return cursor.fetchall()[0][0] + return db.insert_id() # mysql only +#end def storeHands + +def store_hands_players_holdem_omaha(db, cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos): + result=[] + if (category=="holdem"): + for i in range (len(player_ids)): + cursor.execute (""" + INSERT INTO HandsPlayers + (handId, playerId, startCash, position, + card1Value, card1Suit, card2Value, card2Suit, winnings, rake, seatNo) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", + (hands_id, player_ids[i], start_cashes[i], positions[i], + card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], + winnings[i], rakes[i], seatNos[i])) + #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId=%s", (hands_id, player_ids[i])) + #result.append(cursor.fetchall()[0][0]) + result.append( db.insert_id() ) # mysql only + elif (category=="omahahi" or category=="omahahilo"): + for i in range (len(player_ids)): + cursor.execute ("""INSERT INTO HandsPlayers + (handId, playerId, startCash, position, + card1Value, card1Suit, card2Value, card2Suit, + card3Value, card3Suit, card4Value, card4Suit, winnings, rake, seatNo) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", + (hands_id, player_ids[i], start_cashes[i], positions[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], + 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( db.insert_id() ) # mysql only + else: + raise FpdbError("invalid category") + return result +#end def store_hands_players_holdem_omaha + +def store_hands_players_stud(db, cursor, 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 + result=[] + #print "before inserts in store_hands_players_stud, antes:", antes + for i in range (len(player_ids)): + cursor.execute ("""INSERT INTO HandsPlayers + (handId, playerId, startCash, ante, + card1Value, card1Suit, card2Value, card2Suit, + card3Value, card3Suit, card4Value, card4Suit, + card5Value, card5Suit, card6Value, card6Suit, + card7Value, card7Suit, winnings, rake, seatNo) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, + %s, %s, %s, %s)""", + (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], 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( db.insert_id() ) # mysql only + return result +#end def store_hands_players_stud + +def store_hands_players_holdem_omaha_tourney(db, cursor, category, hands_id, player_ids, + start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids): +#stores hands_players for tourney holdem/omaha hands + result=[] + for i in range (len(player_ids)): + if len(card_values[0])==2: + cursor.execute ("""INSERT INTO HandsPlayers + (handId, playerId, startCash, position, + card1Value, card1Suit, card2Value, card2Suit, + winnings, rake, tourneysPlayersId, seatNo) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", + (hands_id, player_ids[i], start_cashes[i], positions[i], + card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], + winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i])) + elif len(card_values[0])==4: + cursor.execute ("""INSERT INTO HandsPlayers + (handId, playerId, startCash, position, + card1Value, card1Suit, card2Value, card2Suit, + card3Value, card3Suit, card4Value, card4Suit, + winnings, rake, tourneysPlayersId, seatNo) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", + (hands_id, player_ids[i], start_cashes[i], positions[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], + winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i])) + else: + raise FpdbError ("invalid card_values length:"+str(len(card_values[0]))) + #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( db.insert_id() ) # mysql only + + return result +#end def store_hands_players_holdem_omaha_tourney + +def store_hands_players_stud_tourney(db, cursor, hands_id, player_ids, start_cashes, + antes, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids): +#stores hands_players for tourney stud/razz hands + result=[] + for i in range (len(player_ids)): + cursor.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) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, %s)""", + (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])) + #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( db.insert_id() ) # mysql only + return result +#end def store_hands_players_stud_tourney + +def generateHudCacheData(player_ids, base, category, action_types, allIns, actionTypeByNo + ,winnings, totalWinnings, positions, actionTypes, actionAmounts): + """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_3B4BChance=[] + street0_3B4BDone=[] + street1Seen=[] + street2Seen=[] + street3Seen=[] + street4Seen=[] + sawShowdown=[] + street1Aggr=[] + street2Aggr=[] + street3Aggr=[] + street4Aggr=[] + otherRaisedStreet1=[] + otherRaisedStreet2=[] + otherRaisedStreet3=[] + otherRaisedStreet4=[] + foldToOtherRaisedStreet1=[] + foldToOtherRaisedStreet2=[] + foldToOtherRaisedStreet3=[] + foldToOtherRaisedStreet4=[] + wonWhenSeenStreet1=[] + + wonAtSD=[] + stealAttemptChance=[] + stealAttempted=[] + hudDataPositions=[] + + firstPfRaiseByNo=-1 + firstPfRaiserId=-1 + firstPfRaiserNo=-1 + firstPfCallByNo=-1 + firstPfCallerId=-1 + for i in range(len(actionTypeByNo[0])): + if actionTypeByNo[0][i][1]=="bet": + firstPfRaiseByNo=i + firstPfRaiserId=actionTypeByNo[0][i][0] + for j in range(len(player_ids)): + if player_ids[j]==firstPfRaiserId: + firstPfRaiserNo=j + break + break + for i in range(len(actionTypeByNo[0])): + if actionTypeByNo[0][i][1]=="call": + firstPfCallByNo=i + firstPfCallerId=actionTypeByNo[0][i][0] + break + + cutoffId=-1 + buttonId=-1 + sbId=-1 + bbId=-1 + if base=="hold": + for player in range(len(positions)): + if positions==1: + cutoffId=player_ids[player] + if positions==0: + buttonId=player_ids[player] + if positions=='S': + sbId=player_ids[player] + if positions=='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 range (len(player_ids)): + #set default values + myStreet0VPI=False + myStreet0Aggr=False + myStreet0_3B4BChance=False + myStreet0_3B4BDone=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 + + #calculate VPIP and PFR + street=0 + heroPfRaiseCount=0 + for count in range (len(action_types[street][player])):#finally individual actions + currentAction=action_types[street][player][count] + if currentAction=="bet": + myStreet0Aggr=True + if (currentAction=="bet" or currentAction=="call"): + myStreet0VPI=True + + #PF3B4BChance and PF3B4B + pfFold=-1 + pfRaise=-1 + if firstPfRaiseByNo!=-1: + for i in range(len(actionTypeByNo[0])): + if actionTypeByNo[0][i][0]==player_ids[player]: + if actionTypeByNo[0][i][1]=="bet" and pfRaise==-1 and i>firstPfRaiseByNo: + pfRaise=i + if actionTypeByNo[0][i][1]=="fold" and pfFold==-1: + pfFold=i + if pfFold==-1 or pfFold>firstPfRaiseByNo: + myStreet0_3B4BChance=True + if pfRaise>firstPfRaiseByNo: + myStreet0_3B4BDone=True + + #steal calculations + if base=="hold": + if len(player_ids)>=5: #no point otherwise + if positions[player]==1: + if firstPfRaiserId==player_ids[player]: + myStealAttemptChance=True + myStealAttempted=True + elif firstPfRaiserId==buttonId or firstPfRaiserId==sbId or firstPfRaiserId==bbId or firstPfRaiserId==-1: + myStealAttemptChance=True + if positions[player]==0: + if firstPfRaiserId==player_ids[player]: + myStealAttemptChance=True + myStealAttempted=True + elif firstPfRaiserId==sbId or firstPfRaiserId==bbId or firstPfRaiserId==-1: + myStealAttemptChance=True + if positions[player]=='S': + if firstPfRaiserId==player_ids[player]: + myStealAttemptChance=True + myStealAttempted=True + elif firstPfRaiserId==bbId or firstPfRaiserId==-1: + myStealAttemptChance=True + if positions[player]=='B': + pass + + if myStealAttempted: + someoneStole=True + + + #calculate saw* values + isAllIn=False + for i in range(len(allIns[0][player])): + if allIns[0][player][i]: + isAllIn=True + if (len(action_types[1][player])>0 or isAllIn): + myStreet1Seen=True + + for i in range(len(allIns[1][player])): + if allIns[1][player][i]: + isAllIn=True + if (len(action_types[2][player])>0 or isAllIn): + myStreet2Seen=True + + for i in range(len(allIns[2][player])): + if allIns[2][player][i]: + isAllIn=True + if (len(action_types[3][player])>0 or isAllIn): + myStreet3Seen=True + + #print "base:", base + if base=="hold": + mySawShowdown=True + for count in range (len(action_types[3][player])): + if action_types[3][player][count]=="fold": + mySawShowdown=False + else: + #print "in else" + for i in range(len(allIns[3][player])): + if allIns[3][player][i]: + isAllIn=True + if (len(action_types[4][player])>0 or isAllIn): + #print "in if" + myStreet4Seen=True + + mySawShowdown=True + for count in range (len(action_types[4][player])): + if action_types[4][player][count]=="fold": + mySawShowdown=False + + + #flop stuff + street=1 + if myStreet1Seen: + for count in range(len(action_types[street][player])): + if action_types[street][player][count]=="bet": + myStreet1Aggr=True + + for otherPlayer in range (len(player_ids)): + if player==otherPlayer: + pass + else: + for countOther in range (len(action_types[street][otherPlayer])): + if action_types[street][otherPlayer][countOther]=="bet": + myOtherRaisedStreet1=True + for countOtherFold in range (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: + for count in range(len(action_types[street][player])): + if action_types[street][player][count]=="bet": + myStreet2Aggr=True + + for otherPlayer in range (len(player_ids)): + if player==otherPlayer: + pass + else: + for countOther in range (len(action_types[street][otherPlayer])): + if action_types[street][otherPlayer][countOther]=="bet": + myOtherRaisedStreet2=True + for countOtherFold in range (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: + for count in range(len(action_types[street][player])): + if action_types[street][player][count]=="bet": + myStreet3Aggr=True + + for otherPlayer in range (len(player_ids)): + if player==otherPlayer: + pass + else: + for countOther in range (len(action_types[street][otherPlayer])): + if action_types[street][otherPlayer][countOther]=="bet": + myOtherRaisedStreet3=True + for countOtherFold in range (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: + for count in range(len(action_types[street][player])): + if action_types[street][player][count]=="bet": + myStreet4Aggr=True + + for otherPlayer in range (len(player_ids)): + if player==otherPlayer: + pass + else: + for countOther in range (len(action_types[street][otherPlayer])): + if action_types[street][otherPlayer][countOther]=="bet": + myOtherRaisedStreet4=True + for countOtherFold in range (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_3B4BChance.append(myStreet0_3B4BChance) + street0_3B4BDone.append(myStreet0_3B4BDone) + 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<=7: + 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 + + #add each array to the to-be-returned dictionary + result={'street0VPI':street0VPI} + result['street0Aggr']=street0Aggr + result['street0_3B4BChance']=street0_3B4BChance + result['street0_3B4BDone']=street0_3B4BDone + 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 + + #now the various steal values + foldBbToStealChance=[] + foldedBbToSteal=[] + foldSbToStealChance=[] + foldedSbToSteal=[] + for player in range (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 range (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 range (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 range (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 range (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 range (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 range (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 range (len(player_ids)): + #print "pl=", pl + myTotalProfit=winnings[pl] # still need to deduct costs + for i in range (len(actionTypes)): #iterate through streets + #for j in range (len(actionTypes[i])): #iterate through names (using pl loop above) + for k in range (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 range(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 range(len(playerIDs)): + if playerIDs[player]==action[0]: + foldToStreetCBChance[player]=True + if action[1]=="fold": + foldToStreetCBDone[player]=True +#end def generateFoldToCB + +def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData): +# if (category=="holdem" or category=="omahahi" or category=="omahahilo"): + + #print "storeHudCache, len(playerIds)=", len(playerIds), " len(vpip)=" \ + #, len(hudImportData['street0VPI']), " len(totprof)=", len(hudImportData['totalProfit']) + for player in range (len(playerIds)): + if base=="hold": + cursor.execute("SELECT * FROM HudCache WHERE gametypeId+0=%s AND playerId=%s AND activeSeats=%s AND position=%s", (gametypeId, playerIds[player], len(playerIds), hudImportData['position'][player])) + else: + cursor.execute("SELECT * FROM HudCache WHERE gametypeId+0=%s AND playerId=%s AND activeSeats=%s", (gametypeId, playerIds[player], len(playerIds))) + row=cursor.fetchone() + #print "gametypeId:", gametypeId, "playerIds[player]",playerIds[player], "len(playerIds):",len(playerIds), "row:",row + + try: len(row) + except TypeError: + row=[] + + if (len(row)==0): + #print "new huddata row" + doInsert=True + row=[] + row.append(0)#blank for id + row.append(gametypeId) + row.append(playerIds[player]) + row.append(len(playerIds))#seats + for i in range(len(hudImportData)+2): + row.append(0) + + else: + doInsert=False + newrow=[] + for i in range(len(row)): + newrow.append(row[i]) + row=newrow + + 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_3B4BChance'][player]: row[9]+=1 + if hudImportData['street0_3B4BDone'][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 + + if doInsert: + #print "playerid before insert:",row[2] + cursor.execute("""INSERT INTO HudCache + (gametypeId, playerId, activeSeats, position, tourneyTypeId, + HDs, street0VPI, street0Aggr, street0_3B4BChance, street0_3B4BDone, + 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)""", (row[1], row[2], row[3], row[4], row[5], 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])) + else: + #print "storing updated hud data line" + cursor.execute("""UPDATE HudCache + SET HDs=%s, street0VPI=%s, street0Aggr=%s, street0_3B4BChance=%s, street0_3B4BDone=%s, + street1Seen=%s, street2Seen=%s, street3Seen=%s, street4Seen=%s, sawShowdown=%s, + street1Aggr=%s, street2Aggr=%s, street3Aggr=%s, street4Aggr=%s, otherRaisedStreet1=%s, + otherRaisedStreet2=%s, otherRaisedStreet3=%s, otherRaisedStreet4=%s, foldToOtherRaisedStreet1=%s, foldToOtherRaisedStreet2=%s, + foldToOtherRaisedStreet3=%s, foldToOtherRaisedStreet4=%s, wonWhenSeenStreet1=%s, wonAtSD=%s, stealAttemptChance=%s, + stealAttempted=%s, foldBbToStealChance=%s, foldedBbToSteal=%s, foldSbToStealChance=%s, foldedSbToSteal=%s, + street1CBChance=%s, street1CBDone=%s, street2CBChance=%s, street2CBDone=%s, street3CBChance=%s, + street3CBDone=%s, street4CBChance=%s, street4CBDone=%s, foldToStreet1CBChance=%s, foldToStreet1CBDone=%s, + foldToStreet2CBChance=%s, foldToStreet2CBDone=%s, foldToStreet3CBChance=%s, foldToStreet3CBDone=%s, foldToStreet4CBChance=%s, + foldToStreet4CBDone=%s, totalProfit=%s, street1CheckCallRaiseChance=%s, street1CheckCallRaiseDone=%s, street2CheckCallRaiseChance=%s, + street2CheckCallRaiseDone=%s, street3CheckCallRaiseChance=%s, street3CheckCallRaiseDone=%s, street4CheckCallRaiseChance=%s, street4CheckCallRaiseDone=%s + WHERE gametypeId=%s AND playerId=%s AND activeSeats=%s AND position=%s AND tourneyTypeId=%s""", (row[6], row[7], row[8], row[9], row[10], + row[11], row[12], row[13], row[14], row[15], + row[16], row[17], row[18], row[19], row[20], + row[21], row[22], row[23], row[24], row[25], + row[26], row[27], row[28], row[29], row[30], + row[31], row[32], row[33], row[34], row[35], row[36], row[37], row[38], row[39], row[40], + row[41], row[42], row[43], row[44], row[45], row[46], row[47], row[48], row[49], row[50], + row[51], row[52], row[53], row[54], row[55], row[56], row[57], row[58], row[59], row[60], + row[1], row[2], row[3], str(row[4]), row[5])) +# else: +# print "todo: implement storeHudCache for stud base" +#end def storeHudCache + +def store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, startTime): + cursor.execute("SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s", (siteTourneyNo, tourneyTypeId)) + tmp=cursor.fetchone() + #print "tried SELECTing tourneys.id, result:",tmp + + try: + len(tmp) + except TypeError:#means we have to create new one + cursor.execute("""INSERT INTO Tourneys + (tourneyTypeId, siteTourneyNo, entries, prizepool, startTime) + VALUES (%s, %s, %s, %s, %s)""", (tourneyTypeId, siteTourneyNo, entries, prizepool, startTime)) + cursor.execute("SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s", (siteTourneyNo, tourneyTypeId)) + tmp=cursor.fetchone() + #print "created new tourneys.id:",tmp + return tmp[0] +#end def store_tourneys + +def store_tourneys_players(cursor, tourney_id, player_ids, payin_amounts, ranks, winnings): + result=[] + #print "in store_tourneys_players. tourney_id:",tourney_id + #print "player_ids:",player_ids + #print "payin_amounts:",payin_amounts + #print "ranks:",ranks + #print "winnings:",winnings + for i in range (len(player_ids)): + cursor.execute("SELECT id FROM TourneysPlayers WHERE tourneyId=%s AND playerId+0=%s", (tourney_id, player_ids[i])) + tmp=cursor.fetchone() + #print "tried SELECTing tourneys_players.id:",tmp + + try: + len(tmp) + except TypeError: + cursor.execute("""INSERT INTO TourneysPlayers + (tourneyId, playerId, payinAmount, rank, winnings) VALUES (%s, %s, %s, %s, %s)""", + (tourney_id, player_ids[i], payin_amounts[i], ranks[i], winnings[i])) + + cursor.execute("SELECT id FROM TourneysPlayers WHERE tourneyId=%s AND playerId+0=%s", + (tourney_id, player_ids[i])) + tmp=cursor.fetchone() + #print "created new tourneys_players.id:",tmp + result.append(tmp[0]) + return result +#end def store_tourneys_players From 30e61901d6604c8519a9f1e748e0c879a2452c0a Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 8 Dec 2008 01:38:06 +0000 Subject: [PATCH 24/32] use spaces not tabs and get first part of insert_id() code working again --- pyfpdb/fpdb_parse_logic.py | 274 ++++++++++++++++++------------------- pyfpdb/fpdb_simple.py | 8 +- 2 files changed, 141 insertions(+), 141 deletions(-) diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py index 8400af31..1d7d54a0 100644 --- a/pyfpdb/fpdb_parse_logic.py +++ b/pyfpdb/fpdb_parse_logic.py @@ -22,154 +22,154 @@ import fpdb_save_to_db #parses a holdem hand def mainParser(db, cursor, site, category, hand): - if (category=="holdem" or category=="omahahi" or category=="omahahilo"): - base="hold" - else: - base="stud" - #part 0: create the empty arrays - lineTypes=[] #char, valid values: header, name, cards, action, win, rake, ignore - lineStreets=[] #char, valid values: (predeal, preflop, flop, turn, river) + if (category=="holdem" or category=="omahahi" or category=="omahahilo"): + base="hold" + else: + base="stud" + #part 0: create the empty arrays + lineTypes=[] #char, valid values: header, name, cards, action, win, rake, ignore + lineStreets=[] #char, valid values: (predeal, preflop, flop, turn, river) - cardValues, cardSuits, boardValues, boardSuits, antes, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo, seatLines, winnings, rakes=[],[],[],[],[],[],[],[],[],[],[],[],[] + cardValues, cardSuits, boardValues, boardSuits, antes, actionTypes, allIns, actionAmounts, actionNos, 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], site) - siteID=fpdb_simple.recogniseSiteID(cursor, site) - #print "parse logic, siteID:",siteID,"site:",site - - isTourney=fpdb_simple.isTourney(hand[0]) - smallBlindLine=0 - for i in range(len(hand)): - if hand[i].find("posts small blind")!=-1 or hand[i].find("posts the small blind")!=-1: - if hand[i][-2:] == "$0": - continue - smallBlindLine=i - #print "found small blind line:",smallBlindLine - break - #print "small blind line:",smallBlindLine - gametypeID=fpdb_simple.recogniseGametypeID(db, cursor, hand[0], hand[smallBlindLine], siteID, category, isTourney) - if isTourney: - if site!="ps": - raise fpdb_simple.FpdbError("tourneys are only supported on PS right now") - 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=0 - tourneyStartTime=handStartTime #todo: read tourney start time - rebuyOrAddon=fpdb_simple.isRebuyOrAddon(hand[0]) + #part 1: read hand no and check for duplicate + siteHandNo=fpdb_simple.parseSiteHandNo(hand[0]) + handStartTime=fpdb_simple.parseHandStartTime(hand[0], site) + siteID=fpdb_simple.recogniseSiteID(cursor, site) + #print "parse logic, siteID:",siteID,"site:",site + + isTourney=fpdb_simple.isTourney(hand[0]) + smallBlindLine=0 + for i in range(len(hand)): + if hand[i].find("posts small blind")!=-1 or hand[i].find("posts the small blind")!=-1: + if hand[i][-2:] == "$0": + continue + smallBlindLine=i + #print "found small blind line:",smallBlindLine + break + #print "small blind line:",smallBlindLine + gametypeID=fpdb_simple.recogniseGametypeID(db, cursor, hand[0], hand[smallBlindLine], siteID, category, isTourney) + if isTourney: + if site!="ps": + raise fpdb_simple.FpdbError("tourneys are only supported on PS right now") + 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=0 + tourneyStartTime=handStartTime #todo: read tourney start time + rebuyOrAddon=fpdb_simple.isRebuyOrAddon(hand[0]) - tourneyTypeId=fpdb_simple.recogniseTourneyTypeId(cursor, siteID, buyin, fee, knockout, rebuyOrAddon) - fpdb_simple.isAlreadyInDB(cursor, gametypeID, siteHandNo) - - #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 in range (len(hand)): #todo: use maxseats+1 here. - if (lineTypes[i]=="name"): - seatLines.append(hand[i]) - names=fpdb_simple.parseNames(seatLines) - playerIDs = fpdb_simple.recognisePlayerIDs(cursor, names, siteID) - tmp=fpdb_simple.parseCashesAndSeatNos(seatLines, site) - 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 in range(len(hand)): - if (lineTypes[i]=="cards"): - fpdb_simple.parseCardLine (site, category, lineStreets[i], hand[i], 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 (site, base, isTourney, hand[i], lineStreets[i], playerIDs, names, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo) - elif (lineTypes[i]=="win"): - fpdb_simple.parseWinLine (hand[i], site, names, winnings, isTourney) - elif (lineTypes[i]=="rake"): - if isTourney: - totalRake=0 - else: - totalRake=fpdb_simple.parseRake(hand[i]) - 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(hand[i], site, isTourney, names, antes) - elif (lineTypes[i]=="table"): - tableResult=fpdb_simple.parseTableLine(site, base, hand[i]) - else: - raise fpdb_simple.FpdbError("unrecognised lineType:"+lineTypes[i]) - if site=="ftp": - tableResult=fpdb_simple.parseTableLine(site, base, hand[0]) - maxSeats=tableResult['maxSeats'] - tableName=tableResult['tableName'] - #print "before part5, antes:", antes - - #part 5: final preparations, then call fpdb_save_to_db.* 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) - - cursor.execute("SELECT limitType FROM Gametypes WHERE id=%s",(gametypeID, )) - limit_type=cursor.fetchone()[0] - fpdb_simple.convert3B4B(site, category, limit_type, actionTypes, actionAmounts) - - totalWinnings=0 - for i in range(len(winnings)): - totalWinnings+=winnings[i] - - if base=="hold": - hudImportData=fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes + tourneyTypeId=fpdb_simple.recogniseTourneyTypeId(cursor, siteID, buyin, fee, knockout, rebuyOrAddon) + fpdb_simple.isAlreadyInDB(cursor, gametypeID, siteHandNo) + + #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 in range (len(hand)): #todo: use maxseats+1 here. + if (lineTypes[i]=="name"): + seatLines.append(hand[i]) + names=fpdb_simple.parseNames(seatLines) + playerIDs = fpdb_simple.recognisePlayerIDs(cursor, names, siteID) + tmp=fpdb_simple.parseCashesAndSeatNos(seatLines, site) + 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 in range(len(hand)): + if (lineTypes[i]=="cards"): + fpdb_simple.parseCardLine (site, category, lineStreets[i], hand[i], 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 (site, base, isTourney, hand[i], lineStreets[i], playerIDs, names, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo) + elif (lineTypes[i]=="win"): + fpdb_simple.parseWinLine (hand[i], site, names, winnings, isTourney) + elif (lineTypes[i]=="rake"): + if isTourney: + totalRake=0 + else: + totalRake=fpdb_simple.parseRake(hand[i]) + 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(hand[i], site, isTourney, names, antes) + elif (lineTypes[i]=="table"): + tableResult=fpdb_simple.parseTableLine(site, base, hand[i]) + else: + raise fpdb_simple.FpdbError("unrecognised lineType:"+lineTypes[i]) + if site=="ftp": + tableResult=fpdb_simple.parseTableLine(site, base, hand[0]) + maxSeats=tableResult['maxSeats'] + tableName=tableResult['tableName'] + #print "before part5, antes:", antes + + #part 5: final preparations, then call fpdb_save_to_db.* 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) + + cursor.execute("SELECT limitType FROM Gametypes WHERE id=%s",(gametypeID, )) + limit_type=cursor.fetchone()[0] + fpdb_simple.convert3B4B(site, category, limit_type, actionTypes, actionAmounts) + + totalWinnings=0 + for i in range(len(winnings)): + totalWinnings+=winnings[i] + + if base=="hold": + hudImportData=fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes , allIns, actionTypeByNo, winnings, totalWinnings, positions , actionTypes, actionAmounts) - else: - hudImportData=fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes + else: + hudImportData=fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes , allIns, actionTypeByNo, winnings, totalWinnings, None , actionTypes, actionAmounts) - - if isTourney: - ranks=[] - for i in range (len(names)): - ranks.append(0) - payin_amounts=fpdb_simple.calcPayin(len(names), buyin, fee) - - if base=="hold": - result = fpdb_save_to_db.tourney_holdem_omaha(db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteID, - siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, positions, cardValues, cardSuits, boardValues, boardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) - elif base=="stud": - result = fpdb_save_to_db.tourney_stud(db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteID, - siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, antes, cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) - else: - raise fpdb_simple.FpdbError ("unrecognised category") - else: - if base=="hold": - result = fpdb_save_to_db.ring_holdem_omaha(db, cursor, base, category, siteHandNo + + if isTourney: + ranks=[] + for i in range (len(names)): + ranks.append(0) + payin_amounts=fpdb_simple.calcPayin(len(names), buyin, fee) + + if base=="hold": + result = fpdb_save_to_db.tourney_holdem_omaha(db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteID, + siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, positions, cardValues, cardSuits, boardValues, boardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) + elif base=="stud": + result = fpdb_save_to_db.tourney_stud(db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteID, + siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, antes, cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) + else: + raise fpdb_simple.FpdbError ("unrecognised category") + else: + if base=="hold": + result = fpdb_save_to_db.ring_holdem_omaha(db, cursor, base, category, siteHandNo ,gametypeID, handStartTime, names, playerIDs ,startCashes, positions, cardValues, cardSuits ,boardValues, boardSuits, winnings, rakes ,actionTypes, allIns, actionAmounts, actionNos ,hudImportData, maxSeats, tableName, seatNos) - elif base=="stud": - result = fpdb_save_to_db.ring_stud(db, cursor, base, category, siteHandNo, gametypeID, - handStartTime, names, playerIDs, startCashes, antes, cardValues, - cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) - else: - raise fpdb_simple.FpdbError ("unrecognised category") - db.commit() - return result + elif base=="stud": + result = fpdb_save_to_db.ring_stud(db, cursor, base, category, siteHandNo, gametypeID, + handStartTime, names, playerIDs, startCashes, antes, cardValues, + cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) + else: + raise fpdb_simple.FpdbError ("unrecognised category") + db.commit() + return result #end def mainParser diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index 11a2a1ea..c64f0030 100755 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -1074,9 +1074,9 @@ def recogniseGametypeID(db, cursor, topline, smallBlindLine, site_id, category, 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)) result=cursor.fetchone() #print "recgt1 result=",result - #ret=result[0] - #print "recgt1 ret=",ret - #print "tried SELECTing gametypes.id, result:",result + #ret=result[0] + #print "recgt1 ret=",ret + #print "tried SELECTing gametypes.id, result:",result try: len(result) @@ -1121,7 +1121,7 @@ def recogniseGametypeID(db, cursor, topline, smallBlindLine, site_id, category, #print "created new gametypes.id:",result #print "recgt3: result=", result - return result[0] + return result[0] #end def recogniseGametypeID def recogniseTourneyTypeId(cursor, siteId, buyin, fee, knockout, rebuyOrAddon): From 71a587facaf70ccab407352a1fd40c25dbd1125c Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 9 Dec 2008 00:29:39 +0000 Subject: [PATCH 25/32] mods to use insert_id() instead of repeated selects and get postgres working --- pyfpdb/fpdb_db.py | 3 +- pyfpdb/fpdb_import.py | 7 +- pyfpdb/fpdb_parse_logic.py | 46 +- pyfpdb/fpdb_save_to_db.py | 157 +- pyfpdb/fpdb_simple.py | 4390 ++++++++++++++++++------------------ 5 files changed, 2349 insertions(+), 2254 deletions(-) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 2663224e..e1c61c6d 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -48,7 +48,8 @@ class fpdb_db: import psycopg2 # If DB connection is made over TCP, then the variables # host, user and password are required - if self.host or self.user: + print "host=%s user=%s pass=%s." % (host, user, password) + if self.host and self.user and self.password: self.db = psycopg2.connect(host = host, user = user, password = password, diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index fd2a321f..2e88899c 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -75,8 +75,8 @@ class Importer: if not pgsqlLibFound: raise fpdb_simple.FpdbError("interface library psycopg2 not found but PostgreSQL selected as backend - please install the library or change the config file") print self.settings - if not self.settings.has_key('db-host') or \ - not self.settings.has_key('db-user'): + if self.settings.has_key('db-host') and \ + self.settings.has_key('db-user'): self.db = psycopg2.connect(host = self.settings['db-host'], user = self.settings['db-user'], password = self.settings['db-password'], @@ -243,7 +243,8 @@ class Importer: self.hand=hand try: - handsId=fpdb_parse_logic.mainParser(self.db, self.cursor, site, category, hand) + handsId=fpdb_parse_logic.mainParser(self.settings['db-backend'], self.db + ,self.cursor, site, category, hand) self.db.commit() stored+=1 diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py index 1d7d54a0..a345dc93 100644 --- a/pyfpdb/fpdb_parse_logic.py +++ b/pyfpdb/fpdb_parse_logic.py @@ -21,7 +21,7 @@ import fpdb_simple import fpdb_save_to_db #parses a holdem hand -def mainParser(db, cursor, site, category, hand): +def mainParser(backend, db, cursor, site, category, hand): if (category=="holdem" or category=="omahahi" or category=="omahahilo"): base="hold" else: @@ -48,7 +48,7 @@ def mainParser(db, cursor, site, category, hand): #print "found small blind line:",smallBlindLine break #print "small blind line:",smallBlindLine - gametypeID=fpdb_simple.recogniseGametypeID(db, cursor, hand[0], hand[smallBlindLine], siteID, category, isTourney) + gametypeID=fpdb_simple.recogniseGametypeID(backend, db, cursor, hand[0], hand[smallBlindLine], siteID, category, isTourney) if isTourney: if site!="ps": raise fpdb_simple.FpdbError("tourneys are only supported on PS right now") @@ -148,25 +148,41 @@ def mainParser(db, cursor, site, category, hand): payin_amounts=fpdb_simple.calcPayin(len(names), buyin, fee) if base=="hold": - result = fpdb_save_to_db.tourney_holdem_omaha(db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteID, - siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, positions, cardValues, cardSuits, boardValues, boardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) + result = fpdb_save_to_db.tourney_holdem_omaha( + backend, db, cursor, base, category, siteTourneyNo, buyin + , fee, knockout, entries, prizepool, tourneyStartTime + , payin_amounts, ranks, tourneyTypeId, siteID, siteHandNo + , gametypeID, handStartTime, names, playerIDs, startCashes + , positions, cardValues, cardSuits, boardValues, boardSuits + , winnings, rakes, actionTypes, allIns, actionAmounts + , actionNos, hudImportData, maxSeats, tableName, seatNos) elif base=="stud": - result = fpdb_save_to_db.tourney_stud(db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteID, - siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, antes, cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) + result = fpdb_save_to_db.tourney_stud( + backend, db, cursor, base, category, siteTourneyNo + , buyin, fee, knockout, entries, prizepool, tourneyStartTime + , payin_amounts, ranks, tourneyTypeId, siteID, siteHandNo + , gametypeID, handStartTime, names, playerIDs, startCashes + , antes, cardValues, cardSuits, winnings, rakes, actionTypes + , allIns, actionAmounts, actionNos, hudImportData, maxSeats + , tableName, seatNos) else: raise fpdb_simple.FpdbError ("unrecognised category") else: if base=="hold": - result = fpdb_save_to_db.ring_holdem_omaha(db, cursor, base, category, siteHandNo - ,gametypeID, handStartTime, names, playerIDs - ,startCashes, positions, cardValues, cardSuits - ,boardValues, boardSuits, winnings, rakes - ,actionTypes, allIns, actionAmounts, actionNos - ,hudImportData, maxSeats, tableName, seatNos) + result = fpdb_save_to_db.ring_holdem_omaha( + backend, db, cursor, base, category, siteHandNo + , gametypeID, handStartTime, names, playerIDs + , startCashes, positions, cardValues, cardSuits + , boardValues, boardSuits, winnings, rakes + , actionTypes, allIns, actionAmounts, actionNos + , hudImportData, maxSeats, tableName, seatNos) elif base=="stud": - result = fpdb_save_to_db.ring_stud(db, cursor, base, category, siteHandNo, gametypeID, - handStartTime, names, playerIDs, startCashes, antes, cardValues, - cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) + result = fpdb_save_to_db.ring_stud( + backend, db, cursor, base, category, siteHandNo, gametypeID + , handStartTime, names, playerIDs, startCashes, antes + , cardValues, cardSuits, winnings, rakes, actionTypes, allIns + , actionAmounts, actionNos, hudImportData, maxSeats, tableName + , seatNos) else: raise fpdb_simple.FpdbError ("unrecognised category") db.commit() diff --git a/pyfpdb/fpdb_save_to_db.py b/pyfpdb/fpdb_save_to_db.py index d548eca5..3a7989ca 100644 --- a/pyfpdb/fpdb_save_to_db.py +++ b/pyfpdb/fpdb_save_to_db.py @@ -18,77 +18,110 @@ #This file contains methods to store hands into the db. decides to move this #into a seperate file since its ugly, fairly long and just generally in the way. +from time import time + import fpdb_simple #stores a stud/razz hand into the database -def ring_stud(db, cursor, base, category, site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes, action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): - fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) - - hands_id=fpdb_simple.storeHands(db, cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats) - - #print "before calling store_hands_players_stud, antes:", antes - hands_players_ids=fpdb_simple.store_hands_players_stud(db, cursor, hands_id, player_ids, - start_cashes, antes, card_values, card_suits, winnings, rakes, seatNos) - - fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData) - - fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) - return hands_id +def ring_stud(backend, db, cursor, base, category, site_hand_no, gametype_id, hand_start_time + ,names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes + ,action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName + ,seatNos): + fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) + + hands_id=fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id + ,hand_start_time, names, tableName, maxSeats) + + #print "before calling store_hands_players_stud, antes:", antes + hands_players_ids=fpdb_simple.store_hands_players_stud(backend, db, cursor, hands_id, player_ids + ,start_cashes, antes, card_values + ,card_suits, winnings, rakes, seatNos) + + fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData) + + fpdb_simple.storeActions(cursor, hands_players_ids, action_types + ,allIns, action_amounts, actionNos) + return hands_id #end def ring_stud -def ring_holdem_omaha(db, cursor, base, category, site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, positions, card_values, card_suits, board_values, board_suits, winnings, rakes, action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): - """stores a holdem/omaha hand into the database""" - fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) - fpdb_simple.fill_board_cards(board_values, board_suits) +def ring_holdem_omaha(backend, db, cursor, base, category, site_hand_no, gametype_id + ,hand_start_time, names, player_ids, start_cashes, positions, card_values + ,card_suits, board_values, board_suits, winnings, rakes, action_types, allIns + ,action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): + """stores a holdem/omaha hand into the database""" + t0 = time() + fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) + t1 = time() + fpdb_simple.fill_board_cards(board_values, board_suits) + t2 = time() - hands_id=fpdb_simple.storeHands(db, cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats) - - hands_players_ids=fpdb_simple.store_hands_players_holdem_omaha(db, cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos) - - fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData) - - fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) - - fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) - return hands_id + hands_id=fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id + ,hand_start_time, names, tableName, maxSeats) + t3 = time() + hands_players_ids=fpdb_simple.store_hands_players_holdem_omaha( + backend, db, cursor, category, hands_id, player_ids, start_cashes + , positions, card_values, card_suits, winnings, rakes, seatNos) + t4 = time() + fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData) + t5 = time() + fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) + t6 = time() + fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) + t7 = time() + print "cards=%4.3f board=%4.3f hands=%4.3f plyrs=%4.3f hudcache=%4.3f board=%4.3f actions=%4.3f" \ + % (t1-t0, t2-t1, t3-t2, t4-t3, t5-t4, t6-t5, t7-t6) + return hands_id #end def ring_holdem_omaha -def tourney_holdem_omaha(db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourney_start, payin_amounts, ranks, tourneyTypeId, siteId, #end of tourney specific params - site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, positions, card_values, card_suits, board_values, board_suits, winnings, rakes, action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): - """stores a tourney holdem/omaha hand into the database""" - fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) - fpdb_simple.fill_board_cards(board_values, board_suits) - - tourney_id=fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourney_start) - tourneys_players_ids=fpdb_simple.store_tourneys_players(cursor, tourney_id, player_ids, payin_amounts, ranks, winnings) - - hands_id=fpdb_simple.storeHands(db, cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats) - - hands_players_ids=fpdb_simple.store_hands_players_holdem_omaha_tourney(db, cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids) - - fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData) - - fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) - - fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) - return hands_id +def tourney_holdem_omaha(backend, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout + ,entries, prizepool, tourney_start, payin_amounts, ranks, tourneyTypeId + ,siteId #end of tourney specific params + ,site_hand_no, gametype_id, hand_start_time, names, player_ids + ,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=fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourney_start) + tourneys_players_ids=fpdb_simple.store_tourneys_players(cursor, tourney_id, player_ids, payin_amounts, ranks, winnings) + + hands_id=fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id + ,hand_start_time, names, tableName, maxSeats) + + hands_players_ids=fpdb_simple.store_hands_players_holdem_omaha_tourney( + backend, db, cursor, category, hands_id, player_ids, start_cashes, positions + , card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids) + + fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData) + + fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) + + fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) + return hands_id #end def tourney_holdem_omaha -def tourney_stud(db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteId, - siteHandNo, gametypeId, handStartTime, names, playerIds, startCashes, antes, cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos): +def tourney_stud(backend, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries + ,prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteId + ,siteHandNo, gametypeId, handStartTime, names, playerIds, startCashes, antes + ,cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts + ,actionNos, hudImportData, maxSeats, tableName, seatNos): #stores a tourney stud/razz hand into the database - fpdb_simple.fillCardArrays(len(names), base, category, cardValues, cardSuits) - - tourney_id=fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourneyStartTime) - - tourneys_players_ids=fpdb_simple.store_tourneys_players(cursor, tourney_id, playerIds, payin_amounts, ranks, winnings) - - hands_id=fpdb_simple.storeHands(db, cursor, siteHandNo, gametypeId, handStartTime, names, tableName, maxSeats) - - hands_players_ids=fpdb_simple.store_hands_players_stud_tourney(db, cursor, hands_id, playerIds, startCashes, antes, cardValues, cardSuits, winnings, rakes, seatNos, tourneys_players_ids) - - fpdb_simple.storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData) - - fpdb_simple.storeActions(cursor, hands_players_ids, actionTypes, allIns, actionAmounts, actionNos) - return hands_id + fpdb_simple.fillCardArrays(len(names), base, category, cardValues, cardSuits) + + tourney_id=fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourneyStartTime) + + tourneys_players_ids=fpdb_simple.store_tourneys_players(cursor, tourney_id, playerIds, payin_amounts, ranks, winnings) + + hands_id=fpdb_simple.storeHands(backend, db, cursor, siteHandNo, gametypeId, handStartTime, names, tableName, maxSeats) + + hands_players_ids=fpdb_simple.store_hands_players_stud_tourney(backend, db, cursor, hands_id + , playerIds, startCashes, antes, cardValues, cardSuits + , winnings, rakes, seatNos, tourneys_players_ids) + + fpdb_simple.storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData) + + fpdb_simple.storeActions(cursor, hands_players_ids, actionTypes, allIns, actionAmounts, actionNos) + return hands_id #end def tourney_stud diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index c64f0030..dd7d56e8 100755 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -1,2173 +1,2217 @@ -#!/usr/bin/python - -#Copyright 2008 Steffen Jobbagy-Felso -#This program is free software: you can redistribute it and/or modify -#it under the terms of the GNU Affero General Public License as published by -#the Free Software Foundation, version 3 of the License. -# -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU Affero General Public License -#along with this program. If not, see . -#In the "official" distribution you can find the license in -#agpl-3.0.txt in the docs folder of the package. - -#This file contains simple functions for fpdb - -import datetime -import re - -PS=1 -FTP=2 - -class DuplicateError(Exception): - def __init__(self, value): - self.value = value - def __str__(self): - return repr(self.value) - -class FpdbError(Exception): - def __init__(self, value): - self.value = value - def __str__(self): - return repr(self.value) - -#returns an array of the total money paid. intending to add rebuys/addons here -def calcPayin(count, buyin, fee): - result=[] - for i in range(count): - result.append (buyin+fee) - return result -#end def calcPayin - -def checkPositions(positions): - """verifies that these positions are valid""" - for i in range (len(positions)): - pos=positions[i] - try:#todo: use type recognition instead of error - if (len(pos)!=1): - raise FpdbError("invalid position found in checkPositions. i: "+str(i)+" position: "+pos) #dont need to str() here - except TypeError:#->not string->is int->fine - pass - - ### RHH modified to allow for "position 9" here (pos==9 is when you're a dead hand before the BB - if (pos!="B" and pos!="S" and pos!=0 and pos!=1 and pos!=2 and pos!=3 and pos!=4 and pos!=5 and pos!=6 and pos!=7 and pos!=9): - raise FpdbError("invalid position found in checkPositions. i: "+str(i)+" position: "+str(pos)) -#end def fpdb_simple.checkPositions - -#classifies each line for further processing in later code. Manipulates the passed arrays. -def classifyLines(hand, category, lineTypes, lineStreets): - currentStreet="predeal" - done=False #set this to true once we reach the last relevant line (the summary, except rake, is all repeats) - for i in range (len(hand)): - if (done): - if (hand[i].find("[")==-1 or hand[i].find("mucked [")==-1): - lineTypes.append("ignore") - else: #it's storing a mucked card - lineTypes.append("cards") - elif (hand[i].startswith("Dealt to")): - lineTypes.append("cards") - elif (i==0): - lineTypes.append("header") - elif (hand[i].startswith("Seat ") and ((hand[i].find("in chips")!=-1) or (hand[i].find("($")!=-1))): - lineTypes.append("name") - elif (isActionLine(hand[i])): - lineTypes.append("action") - if (hand[i].find(" posts ")!=-1 or hand[i].find(" posts the ")!=-1):#need to set this here so the "action" of posting blinds is registered properly - currentStreet="preflop" - elif (isWinLine(hand[i])): - lineTypes.append("win") - elif (hand[i].startswith("Total pot ") and hand[i].find("Rake")!=-1): - lineTypes.append("rake") - done=True - elif (hand[i]=="*** SHOW DOWN ***" or hand[i]=="*** SUMMARY ***"): - lineTypes.append("ignore") - #print "in classifyLine, showdown or summary" - elif (hand[i].find(" antes ")!=-1 or hand[i].find(" posts the ante ")!=-1): - lineTypes.append("ante") - elif (hand[i].startswith("*** FLOP *** [")): - lineTypes.append("cards") - currentStreet="flop" - elif (hand[i].startswith("*** TURN *** [")): - lineTypes.append("cards") - currentStreet="turn" - elif (hand[i].startswith("*** RIVER *** [")): - lineTypes.append("cards") - currentStreet="river" - elif (hand[i].startswith("*** 3")): - lineTypes.append("ignore") - currentStreet=0 - elif (hand[i].startswith("*** 4")): - lineTypes.append("ignore") - currentStreet=1 - elif (hand[i].startswith("*** 5")): - lineTypes.append("ignore") - currentStreet=2 - elif (hand[i].startswith("*** 6")): - lineTypes.append("ignore") - currentStreet=3 - elif (hand[i].startswith("*** 7") or hand[i]=="*** RIVER ***"): - lineTypes.append("ignore") - currentStreet=4 - elif (hand[i].find(" shows [")!=-1): - lineTypes.append("cards") - elif (hand[i].startswith("Table '")): - lineTypes.append("table") - else: - raise FpdbError("unrecognised linetype in:"+hand[i]) - lineStreets.append(currentStreet) -#end def classifyLines - -def convert3B4B(site, category, limit_type, actionTypes, actionAmounts): - """calculates the actual bet amounts in the given amount array and changes it accordingly.""" - for i in range (len(actionTypes)): - for j in range (len(actionTypes[i])): - bets=[] - for k in range (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) - amount2=actionAmounts[bets[1][0]][bets[1][1]][bets[1][2]] - amount1=actionAmounts[bets[0][0]][bets[0][1]][bets[0][2]] - actionAmounts[bets[1][0]][bets[1][1]][bets[1][2]]=amount2-amount1 - elif (len(bets)>2): - fail=True - #todo: run correction for below - if (site=="ps" and category=="holdem" and limit_type=="nl" and len(bets)==3): - fail=False - if (site=="ftp" and category=="omahahi" and limit_type=="pl" and len(bets)==3): - fail=False - - if fail: - print "len(bets)>2 in convert3B4B, i didnt think this is possible. i:",i,"j:",j,"k:",k - print "actionTypes:",actionTypes - raise FpdbError ("too many bets in convert3B4B") - #print "actionAmounts postConvert",actionAmounts -#end def convert3B4B(actionTypes, actionAmounts) - -#Corrects the bet amount if the player had to pay blinds -def convertBlindBet(actionTypes, actionAmounts): - i=0#setting street to pre-flop - for j in range (len(actionTypes[i])):#playerloop - blinds=[] - bets=[] - for k in range (len(actionTypes[i][j])): - if (actionTypes[i][j][k]=="blind"): - blinds.append((i,j,k)) - - if (len(blinds)>0 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 -#end def convertBlindBet - -#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): - for i in range (len(arr)): - for j in range (len(arr[i])): - if (arr[i][j]=="A"): - arr[i][j]=14 - elif (arr[i][j]=="K"): - arr[i][j]=13 - elif (arr[i][j]=="Q"): - arr[i][j]=12 - elif (arr[i][j]=="J"): - arr[i][j]=11 - elif (arr[i][j]=="T"): - arr[i][j]=10 - else: - arr[i][j]=int(arr[i][j]) -#end def convertCardValues - -#converts the strings in the given array to ints (changes the passed array, no returning). see table design for conversion details -def convertCardValuesBoard(arr): - for i in range (len(arr)): - if (arr[i]=="A"): - arr[i]=14 - elif (arr[i]=="K"): - arr[i]=13 - elif (arr[i]=="Q"): - arr[i]=12 - elif (arr[i]=="J"): - arr[i]=11 - elif (arr[i]=="T"): - arr[i]=10 - else: - arr[i]=int(arr[i]) -#end def convertCardValuesBoard - -#this creates the 2D/3D arrays. manipulates the passed arrays instead of returning. -def createArrays(category, seats, card_values, card_suits, antes, winnings, rakes, action_types, allIns, action_amounts, actionNos, actionTypeByNo): - for i in range(seats):#create second dimension arrays - tmp=[] - card_values.append(tmp) - tmp=[] - card_suits.append(tmp) - antes.append(0) - winnings.append(0) - rakes.append(0) - - if (category=="holdem" or category=="omahahi" or category=="omahahilo"): - streetCount=4 - else: - streetCount=5 - - for i in range(streetCount): #build the first dimension array, for streets - tmp=[] - action_types.append(tmp) - tmp=[] - allIns.append(tmp) - tmp=[] - action_amounts.append(tmp) - tmp=[] - actionNos.append(tmp) - tmp=[] - actionTypeByNo.append(tmp) - for j in range (seats): #second dimension arrays: players - tmp=[] - action_types[i].append(tmp) - tmp=[] - allIns[i].append(tmp) - tmp=[] - action_amounts[i].append(tmp) - tmp=[] - actionNos[i].append(tmp) - if (category=="holdem" or category=="omahahi" or category=="omahahilo"): - pass - elif (category=="razz" or category=="studhi" or category=="studhilo"):#need to fill card arrays. - for i in range(seats): - for j in range (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") -#end def fill_board_cards - -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 fpdb_simple.FpdbError ("invalid category:", category) - - for i in range (player_count): - while (len(card_values[i])=1): - raise DuplicateError ("dupl") -#end isAlreadyInDB - -def isRebuyOrAddon(topline): - """isRebuyOrAddon not implemented yet""" - return False -#end def isRebuyOrAddon - -#returns whether the passed topline indicates a tournament or not -def isTourney(topline): - if (topline.find("Tournament")!=-1): - return True - else: - return False -#end def isTourney - -#returns boolean whether the passed line is a win line -def isWinLine(line): - if (line.find("wins the pot")!=-1): - return True - elif (line.find("ties for the high pot")!=-1): - return True - elif (line.find("ties for the high main pot")!=-1): - return True - elif (line.find("ties for the high side pot")!=-1): - return True - elif (line.find("ties for the low pot")!=-1): - return True - elif (line.find("ties for the low main pot")!=-1): - return True - elif (line.find("ties for the low side pot")!=-1): - return True - elif (line.find("ties for the main pot")!=-1): #for ftp tied main pot of split pot - return True - elif (line.find("ties for the pot")!=-1): #for ftp tie - return True - elif (line.find("ties for the side pot")!=-1): #for ftp tied split pots - return True - elif (line.find("wins side pot #")!=-1): #for ftp multi split pots - return True - elif (line.find("wins the low main pot")!=-1): - return True - elif (line.find("wins the low pot")!=-1): - return True - elif (line.find("wins the low side pot")!=-1): - return True - elif (line.find("wins the high main pot")!=-1): - return True - elif (line.find("wins the high pot")!=-1): - return True - elif (line.find("wins the high side pot")!=-1): - return True - elif (line.find("wins the main pot")!=-1): - return True - elif (line.find("wins the side pot")!=-1): #for ftp split pots - return True - elif (line.find("collected")!=-1): - return True - else: - return False #not raising error here, any unknown line wouldve been detected in isActionLine already -#end def isWinLine - -#returns the amount of cash/chips put into the put in the given action line -def parseActionAmount(line, atype, site, isTourney): - #if (line.endswith(" and is all-in")): - # line=line[:-14] - #elif (line.endswith(", and is all in")): - # line=line[:-15] - - if line.endswith(", and is capped"):#ideally we should recognise this as an all-in if category is capXl - line=line[:-15] - if line.endswith(" and is capped"): - line=line[:-14] - - - if (atype=="fold"): - amount=0 - elif (atype=="check"): - amount=0 - elif (atype=="unbet" and site=="ftp"): - pos1=line.find("$")+1 - pos2=line.find(" returned to") - amount=float2int(line[pos1:pos2]) - elif (atype=="unbet" and site=="ps"): - #print "ps unbet, line:",line - pos1=line.find("$")+1 - if pos1==0: - pos1=line.find("(")+1 - pos2=line.find(")") - amount=float2int(line[pos1:pos2]) - elif (atype=="bet" and site=="ps" and line.find(": raises $")!=-1 and line.find("to $")!=-1): - 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(site, 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 range(len(actionNos[street])): - for count in range(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, site, 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) -#end def parseActionLine - -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) -#end def goesAllInOnThisLine - -#returns the action type code (see table design) of the given action line -def parseActionType(line): - if (line.startswith("Uncalled bet")): - return "unbet" - elif (line.endswith("folds")): - return "fold" - elif (line.endswith("checks")): - return "check" - elif (line.find("calls")!=-1): - return "call" - elif (line.find("brings in for")!=-1): - return "blind" - elif (line.find("completes it to")!=-1): - return "bet" - #todo: what if someone completes instead of bringing in? - elif (line.find(" posts $")!=-1): - return "blind" - elif (line.find(" posts a dead ")!=-1): - return "blind" - elif (line.find(": posts small blind ")!=-1): - return "blind" - elif (line.find(" posts the small blind of $")!=-1): - return "blind" - elif (line.find(": posts big blind ")!=-1): - return "blind" - elif (line.find(" posts the big blind of $")!=-1): - return "blind" - elif (line.find(": posts small & big blinds $")!=-1): - return "blind" - #todo: seperately record voluntary blind payments made to join table out of turn - elif (line.find("bets")!=-1): - return "bet" - elif (line.find("raises")!=-1): - return "bet" - else: - raise FpdbError ("failed to recognise actiontype in parseActionLine in: "+line) -#end def parseActionType - -#parses the ante out of the given line and checks which player paid it, updates antes accordingly. -def parseAnteLine(line, site, isTourney, names, antes): - for i in range(len(names)): - if (line.startswith(names[i].encode("latin-1"))): #found the ante'er - pos=line.rfind("$")+1 - if not isTourney: - antes[i]+=float2int(line[pos:]) - else: - if line.find("all-in")==-1: - 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]) - #print "parseAnteLine line: ", line, "antes[i]", antes[i], "antes", antes -#end def parseAntes - -#returns the buyin of a tourney in cents -def parseBuyin(topline): - pos1=topline.find("$")+1 - pos2=topline.find("+") - return float2int(topline[pos1:pos2]) -#end def parseBuyin - -#parses a card line and changes the passed arrays accordingly -#todo: reorganise this messy method -def parseCardLine(site, category, street, line, names, cardValues, cardSuits, boardValues, boardSuits): - if (line.startswith("Dealt to ") or line.find(" shows [")!=-1 or line.find("mucked [")!=-1): - 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]: #two tests will do - 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 (line.find("shows")==-1): - #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) -#end def parseCardLine - -def parseCashesAndSeatNos(lines, site): - """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 range (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 - if (site=="ftp"): - pos2=lines[i].rfind(")") - elif (site=="ps"): - pos2=lines[i].find(" in chips") - cashes.append(float2int(lines[i][pos1:pos2])) - return {'startCashes':cashes, 'seatNos':seatNos} -#end def parseCashesAndSeatNos - -#returns the buyin of a tourney in cents -def parseFee(topline): - pos1=topline.find("$")+1 - pos1=topline.find("$",pos1)+1 - pos2=topline.find(" ", pos1) - return float2int(topline[pos1:pos2]) -#end def parsefee - -#returns a datetime object with the starttime indicated in the given topline -def parseHandStartTime(topline, site): - #convert x:13:35 to 0x:13:35 - counter=0 - while (True): - pos=topline.find(" "+str(counter)+":") - if (pos!=-1): - topline=topline[0:pos+1]+"0"+topline[pos+1:] - counter+=1 - if counter==10: break - - isUTC=False - if site=="ftp": - pos = topline.find(" ", len(topline)-26)+1 - tmp = topline[pos:] - #print "year:", tmp[14:18], "month", tmp[19:21], "day", tmp[22:24], "hour", tmp[0:2], "minute", tmp[3:5], "second", tmp[6:8] - result = datetime.datetime(int(tmp[14:18]), int(tmp[19:21]), int(tmp[22:24]), int(tmp[0:2]), int(tmp[3:5]), int(tmp[6:8])) - elif site=="ps": - if topline.find("UTC")!=-1: - pos1 = topline.find("-")+2 - pos2 = topline.find("UTC") - tmp=topline[pos1:pos2] - isUTC=True - else: - tmp=topline[-30:] - #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) - m = re.match('(?P[0-9]{4})\/(?P[0-9]{2})\/(?P[0-9]{2})[\- ]+(?P
[0-9]{2}):(?P[0-9]{2}):(?P[0-9]{2})',tmp) - #print "year:", int(m.group('YEAR')), "month", int(m.group('MON')), "day", int(m.group('DAY')), "hour", int(m.group('HR')), "minute", int(m.group('MIN')), "second", int(m.group('SEC')) - 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'))) - else: - raise FpdbError("invalid site in parseHandStartTime") - - if (site=="ftp" or site=="ps") and not isUTC: #these use US ET - result+=datetime.timedelta(hours=5) - - return result -#end def parseHandStartTime - -#parses the names out of the given lines and returns them as an array -def parseNames(lines): - result = [] - for i in range (len(lines)): - pos1=lines[i].find(":")+2 - pos2=lines[i].rfind("(")-1 - tmp=lines[i][pos1:pos2] - #print "parseNames, tmp original:",tmp - tmp=unicode(tmp,"latin-1") - #print "parseNames, tmp after unicode latin-1 conversion:",tmp - result.append(tmp) - return result -#end def parseNames - -#returns an array with the positions of the respective players -def parsePositions (hand, names): - #prep array - positions=[] - for i in range(len(names)): - positions.append(-1) - - #find blinds - sb,bb=-1,-1 - for i in range (len(hand)): - if (sb==-1 and hand[i].find("small blind")!=-1 and hand[i].find("dead small blind")==-1): - sb=hand[i] - #print "sb:",sb - if (bb==-1 and hand[i].find("big blind")!=-1 and hand[i].find("dead big blind")==-1): - bb=hand[i] - #print "bb:",bb - - #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") - - #write blinds into array - if (sbExists): - positions[sb]="S" - positions[bb]="B" - - #fill up rest of array - if (sbExists): - arraypos=sb-1 - else: - arraypos=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 - - ### RHH - Changed to set the null seats before BB to "9" - i=bb-1 - while positions[i] < 0: - positions[i]=9 - i-=1 - - arraypos=len(names)-1 - if (bb!=0 or (bb==0 and sbExists==False)): - while (arraypos>bb): - positions[arraypos]=distFromBtn - arraypos-=1 - distFromBtn+=1 - - for i in range (len(names)): - if positions[i]==-1: - print "parsePositions names:",names - print "result:",positions - raise FpdbError ("failed to read positions") - return positions -#end def parsePositions - -#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 -#end def parseRake - -def parseSiteHandNo(topline): - """returns the hand no assigned by the poker site""" - pos1=topline.find("#")+1 - pos2=topline.find(":") - return topline[pos1:pos2] -#end def parseSiteHandNo - -def parseTableLine(site, base, line): - """returns a dictionary with maxSeats and tableName""" - if site=="ps": - 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]} - elif site=="ftp": - pos1=line.find("Table ")+6 - pos2=line.find("-")-1 - if base=="hold": - maxSeats=9 - elif base=="stud": - maxSeats=8 - - if line.find("6 max")!=-1: - maxSeats=6 - elif line.find("4 max")!=-1: - maxSeats=4 - elif line.find("heads up")!=-1: - maxSeats=2 - - return {'maxSeats':maxSeats, 'tableName':line[pos1:pos2]} - else: - raise FpdbError("invalid site ID") -#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] -#end def parseTourneyNo - -#parses a win/collect line. manipulates the passed array winnings, no explicit return -def parseWinLine(line, site, names, winnings, isTourney): - #print "parseWinLine: line:",line - for i in range(len(names)): - if (line.startswith(names[i].encode("latin-1"))): #found a winner - if isTourney: - pos1=line.rfind("collected ")+10 - if (site=="ftp"): - pos2=line.find(")", pos1) - elif (site=="ps"): - pos2=line.find(" ", pos1) - winnings[i]+=int(line[pos1:pos2]) - else: - pos1=line.rfind("$")+1 - if (site=="ftp"): - pos2=line.find(")", pos1) - elif (site=="ps"): - pos2=line.find(" ", pos1) - winnings[i]+=float2int(line[pos1:pos2]) -#end def parseWinLine - -#returns the category (as per database) string for the given line -def recogniseCategory(line): - if (line.find("Razz")!=-1): - return "razz" - elif (line.find("Hold'em")!=-1): - return "holdem" - elif (line.find("Omaha")!=-1 and line.find("Hi/Lo")==-1 and line.find("H/L")==-1): - return "omahahi" - elif (line.find("Omaha")!=-1 and (line.find("Hi/Lo")!=-1 or line.find("H/L")!=-1)): - return "omahahilo" - elif (line.find("Stud")!=-1 and line.find("Hi/Lo")==-1 and line.find("H/L")==-1): - return "studhi" - elif (line.find("Stud")!=-1 and (line.find("Hi/Lo")!=-1 or line.find("H/L")!=-1)): - return "studhilo" - else: - raise FpdbError("failed to recognise category, line:"+line) -#end def recogniseCategory - -#returns the int for the gametype_id for the given line -def recogniseGametypeID(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 - if (site_id==1): #ftp - pos2=topline.find(" ", pos1) - elif (site_id==2): #ps - 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 (topline.find("No Limit")!=-1): - limit_type="nl" - if (topline.find("Cap No")!=-1): - limit_type="cn" - elif (topline.find("Pot Limit")!=-1): - limit_type="pl" - if (topline.find("Cap Pot")!=-1): - limit_type="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 ("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: - 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)) - 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 - cursor.execute("""INSERT INTO Gametypes - (siteId, type, base, category, limitType, hiLo, smallBlind, bigBlind, smallBet, bigBet) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", (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: - cursor.execute("""INSERT INTO Gametypes - (siteId, type, base, category, limitType, hiLo, smallBlind, bigBlind, smallBet, bigBet) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", (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)) - - result=(db.insert_id(),) - #print "recgt2 result=",result - #print "created new gametypes.id:",result - - #print "recgt3: result=", result - return result[0] -#end def recogniseGametypeID - -def recogniseTourneyTypeId(cursor, siteId, buyin, fee, knockout, rebuyOrAddon): - cursor.execute ("SELECT id FROM TourneyTypes WHERE siteId=%s AND buyin=%s AND fee=%s AND knockout=%s AND rebuyOrAddon=%s", (siteId, buyin, fee, knockout, rebuyOrAddon)) - result=cursor.fetchone() - #print "tried SELECTing gametypes.id, result:",result - - try: - len(result) - except TypeError:#this means we need to create a new entry - cursor.execute("""INSERT INTO TourneyTypes (siteId, buyin, fee, knockout, rebuyOrAddon) VALUES (%s, %s, %s, %s, %s)""", (siteId, buyin, fee, knockout, rebuyOrAddon)) - cursor.execute("SELECT id FROM TourneyTypes WHERE siteId=%s AND buyin=%s AND fee=%s AND knockout=%s AND rebuyOrAddon=%s", (siteId, buyin, fee, knockout, rebuyOrAddon)) - result=cursor.fetchone() - return result[0] -#end def recogniseTourneyTypeId - -#returns the SQL ids of the names given in an array -def recognisePlayerIDs(cursor, names, site_id): - result = [] - for i in range (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 -#end def recognisePlayerIDs - -#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 range (len(names)): - if (atype=="unbet"): - if (line.endswith(names[i].encode("latin-1"))): - 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(names[i].encode("latin-1"))): - return (i) - elif (line.startswith("Seat ")): - if (line.startswith("Seat 10")): - tmp=line[9:] - else: - tmp=line[8:] - - if (tmp.startswith(names[i].encode("latin-1"))): - return (i) - else: - if (line.startswith(names[i].encode("latin-1"))): - return (i) - #if we're here we mustve failed - raise FpdbError ("failed to recognise player in: "+line+" atype:"+atype) -#end def recognisePlayerNo - -#returns the site abbreviation for the given site -def recogniseSite(line): - if (line.startswith("Full Tilt Poker")): - return "ftp" - elif (line.startswith("PokerStars")): - return "ps" - else: - raise FpdbError("failed to recognise site, line:"+line) -#end def recogniseSite - -#returns the ID of the given site -def recogniseSiteID(cursor, site): - if (site=="ftp"): - return 1 - #cursor.execute("SELECT id FROM Sites WHERE name = ('Full Tilt Poker')") - elif (site=="ps"): - return 2 - #cursor.execute("SELECT id FROM Sites WHERE name = ('PokerStars')") - else: - raise FpdbError("invalid site in recogniseSiteID: "+site) - return cursor.fetchall()[0][0] -#end def recogniseSiteID - -#removes trailing \n from the given array -def removeTrailingEOL(arr): - for i in range(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 range(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 range(len(winnings)): - if winnings[i]!=0: - winPortion=winnings[i]/totalWin - rakes[i]=totalRake*winPortion -#end def splitRake - -def storeActions(cursor, handsPlayersIds, actionTypes, allIns, actionAmounts, actionNos): -#stores into table hands_actions - #print "start of storeActions, actionNos:",actionNos - #print " action_amounts:",action_amounts - for i in range (len(actionTypes)): #iterate through streets - for j in range (len(actionTypes[i])): #iterate through names - for k in range (len(actionTypes[i][j])): #iterate through individual actions of that player on that street - cursor.execute ("INSERT INTO HandsActions (handPlayerId, street, actionNo, action, allIn, amount) VALUES (%s, %s, %s, %s, %s, %s)" - , (handsPlayersIds[j], i, actionNos[i][j][k], actionTypes[i][j][k], allIns[i][j][k], actionAmounts[i][j][k])) -#end def storeActions - -def store_board_cards(cursor, hands_id, board_values, board_suits): -#stores into table board_cards - cursor.execute ("""INSERT INTO BoardCards (handId, card1Value, card1Suit, - card2Value, card2Suit, card3Value, card3Suit, card4Value, card4Suit, - card5Value, card5Suit) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", - (hands_id, board_values[0], board_suits[0], board_values[1], board_suits[1], - board_values[2], board_suits[2], board_values[3], board_suits[3], - board_values[4], board_suits[4])) -#end def store_board_cards - -def storeHands(db, cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats): -#stores into table hands - cursor.execute ("INSERT INTO Hands (siteHandNo, gametypeId, handStart, seats, tableName, importTime, maxSeats) VALUES (%s, %s, %s, %s, %s, %s, %s)", (site_hand_no, gametype_id, hand_start_time, len(names), tableName, datetime.datetime.today(), maxSeats)) - #todo: find a better way of doing this... - #cursor.execute("SELECT id FROM Hands WHERE siteHandNo=%s AND gametypeId=%s", (site_hand_no, gametype_id)) - #return cursor.fetchall()[0][0] - return db.insert_id() # mysql only -#end def storeHands - -def store_hands_players_holdem_omaha(db, cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos): - result=[] - if (category=="holdem"): - for i in range (len(player_ids)): - cursor.execute (""" - INSERT INTO HandsPlayers - (handId, playerId, startCash, position, - card1Value, card1Suit, card2Value, card2Suit, winnings, rake, seatNo) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", - (hands_id, player_ids[i], start_cashes[i], positions[i], - card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], - winnings[i], rakes[i], seatNos[i])) - #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId=%s", (hands_id, player_ids[i])) - #result.append(cursor.fetchall()[0][0]) - result.append( db.insert_id() ) # mysql only - elif (category=="omahahi" or category=="omahahilo"): - for i in range (len(player_ids)): - cursor.execute ("""INSERT INTO HandsPlayers - (handId, playerId, startCash, position, - card1Value, card1Suit, card2Value, card2Suit, - card3Value, card3Suit, card4Value, card4Suit, winnings, rake, seatNo) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", - (hands_id, player_ids[i], start_cashes[i], positions[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], - 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( db.insert_id() ) # mysql only - else: - raise FpdbError("invalid category") - return result -#end def store_hands_players_holdem_omaha - -def store_hands_players_stud(db, cursor, 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 - result=[] - #print "before inserts in store_hands_players_stud, antes:", antes - for i in range (len(player_ids)): - cursor.execute ("""INSERT INTO HandsPlayers - (handId, playerId, startCash, ante, - card1Value, card1Suit, card2Value, card2Suit, - card3Value, card3Suit, card4Value, card4Suit, - card5Value, card5Suit, card6Value, card6Suit, - card7Value, card7Suit, winnings, rake, seatNo) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s)""", - (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], 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( db.insert_id() ) # mysql only - return result -#end def store_hands_players_stud - -def store_hands_players_holdem_omaha_tourney(db, cursor, category, hands_id, player_ids, - start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids): -#stores hands_players for tourney holdem/omaha hands - result=[] - for i in range (len(player_ids)): - if len(card_values[0])==2: - cursor.execute ("""INSERT INTO HandsPlayers - (handId, playerId, startCash, position, - card1Value, card1Suit, card2Value, card2Suit, - winnings, rake, tourneysPlayersId, seatNo) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", - (hands_id, player_ids[i], start_cashes[i], positions[i], - card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], - winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i])) - elif len(card_values[0])==4: - cursor.execute ("""INSERT INTO HandsPlayers - (handId, playerId, startCash, position, - card1Value, card1Suit, card2Value, card2Suit, - card3Value, card3Suit, card4Value, card4Suit, - winnings, rake, tourneysPlayersId, seatNo) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", - (hands_id, player_ids[i], start_cashes[i], positions[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], - winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i])) - else: - raise FpdbError ("invalid card_values length:"+str(len(card_values[0]))) - #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( db.insert_id() ) # mysql only - - return result -#end def store_hands_players_holdem_omaha_tourney - -def store_hands_players_stud_tourney(db, cursor, hands_id, player_ids, start_cashes, - antes, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids): -#stores hands_players for tourney stud/razz hands - result=[] - for i in range (len(player_ids)): - cursor.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) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s)""", - (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])) - #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( db.insert_id() ) # mysql only - return result -#end def store_hands_players_stud_tourney - -def generateHudCacheData(player_ids, base, category, action_types, allIns, actionTypeByNo - ,winnings, totalWinnings, positions, actionTypes, actionAmounts): - """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_3B4BChance=[] - street0_3B4BDone=[] - street1Seen=[] - street2Seen=[] - street3Seen=[] - street4Seen=[] - sawShowdown=[] - street1Aggr=[] - street2Aggr=[] - street3Aggr=[] - street4Aggr=[] - otherRaisedStreet1=[] - otherRaisedStreet2=[] - otherRaisedStreet3=[] - otherRaisedStreet4=[] - foldToOtherRaisedStreet1=[] - foldToOtherRaisedStreet2=[] - foldToOtherRaisedStreet3=[] - foldToOtherRaisedStreet4=[] - wonWhenSeenStreet1=[] - - wonAtSD=[] - stealAttemptChance=[] - stealAttempted=[] - hudDataPositions=[] - - firstPfRaiseByNo=-1 - firstPfRaiserId=-1 - firstPfRaiserNo=-1 - firstPfCallByNo=-1 - firstPfCallerId=-1 - for i in range(len(actionTypeByNo[0])): - if actionTypeByNo[0][i][1]=="bet": - firstPfRaiseByNo=i - firstPfRaiserId=actionTypeByNo[0][i][0] - for j in range(len(player_ids)): - if player_ids[j]==firstPfRaiserId: - firstPfRaiserNo=j - break - break - for i in range(len(actionTypeByNo[0])): - if actionTypeByNo[0][i][1]=="call": - firstPfCallByNo=i - firstPfCallerId=actionTypeByNo[0][i][0] - break - - cutoffId=-1 - buttonId=-1 - sbId=-1 - bbId=-1 - if base=="hold": - for player in range(len(positions)): - if positions==1: - cutoffId=player_ids[player] - if positions==0: - buttonId=player_ids[player] - if positions=='S': - sbId=player_ids[player] - if positions=='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 range (len(player_ids)): - #set default values - myStreet0VPI=False - myStreet0Aggr=False - myStreet0_3B4BChance=False - myStreet0_3B4BDone=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 - - #calculate VPIP and PFR - street=0 - heroPfRaiseCount=0 - for count in range (len(action_types[street][player])):#finally individual actions - currentAction=action_types[street][player][count] - if currentAction=="bet": - myStreet0Aggr=True - if (currentAction=="bet" or currentAction=="call"): - myStreet0VPI=True - - #PF3B4BChance and PF3B4B - pfFold=-1 - pfRaise=-1 - if firstPfRaiseByNo!=-1: - for i in range(len(actionTypeByNo[0])): - if actionTypeByNo[0][i][0]==player_ids[player]: - if actionTypeByNo[0][i][1]=="bet" and pfRaise==-1 and i>firstPfRaiseByNo: - pfRaise=i - if actionTypeByNo[0][i][1]=="fold" and pfFold==-1: - pfFold=i - if pfFold==-1 or pfFold>firstPfRaiseByNo: - myStreet0_3B4BChance=True - if pfRaise>firstPfRaiseByNo: - myStreet0_3B4BDone=True - - #steal calculations - if base=="hold": - if len(player_ids)>=5: #no point otherwise - if positions[player]==1: - if firstPfRaiserId==player_ids[player]: - myStealAttemptChance=True - myStealAttempted=True - elif firstPfRaiserId==buttonId or firstPfRaiserId==sbId or firstPfRaiserId==bbId or firstPfRaiserId==-1: - myStealAttemptChance=True - if positions[player]==0: - if firstPfRaiserId==player_ids[player]: - myStealAttemptChance=True - myStealAttempted=True - elif firstPfRaiserId==sbId or firstPfRaiserId==bbId or firstPfRaiserId==-1: - myStealAttemptChance=True - if positions[player]=='S': - if firstPfRaiserId==player_ids[player]: - myStealAttemptChance=True - myStealAttempted=True - elif firstPfRaiserId==bbId or firstPfRaiserId==-1: - myStealAttemptChance=True - if positions[player]=='B': - pass - - if myStealAttempted: - someoneStole=True - - - #calculate saw* values - isAllIn=False - for i in range(len(allIns[0][player])): - if allIns[0][player][i]: - isAllIn=True - if (len(action_types[1][player])>0 or isAllIn): - myStreet1Seen=True - - for i in range(len(allIns[1][player])): - if allIns[1][player][i]: - isAllIn=True - if (len(action_types[2][player])>0 or isAllIn): - myStreet2Seen=True - - for i in range(len(allIns[2][player])): - if allIns[2][player][i]: - isAllIn=True - if (len(action_types[3][player])>0 or isAllIn): - myStreet3Seen=True - - #print "base:", base - if base=="hold": - mySawShowdown=True - for count in range (len(action_types[3][player])): - if action_types[3][player][count]=="fold": - mySawShowdown=False - else: - #print "in else" - for i in range(len(allIns[3][player])): - if allIns[3][player][i]: - isAllIn=True - if (len(action_types[4][player])>0 or isAllIn): - #print "in if" - myStreet4Seen=True - - mySawShowdown=True - for count in range (len(action_types[4][player])): - if action_types[4][player][count]=="fold": - mySawShowdown=False - - - #flop stuff - street=1 - if myStreet1Seen: - for count in range(len(action_types[street][player])): - if action_types[street][player][count]=="bet": - myStreet1Aggr=True - - for otherPlayer in range (len(player_ids)): - if player==otherPlayer: - pass - else: - for countOther in range (len(action_types[street][otherPlayer])): - if action_types[street][otherPlayer][countOther]=="bet": - myOtherRaisedStreet1=True - for countOtherFold in range (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: - for count in range(len(action_types[street][player])): - if action_types[street][player][count]=="bet": - myStreet2Aggr=True - - for otherPlayer in range (len(player_ids)): - if player==otherPlayer: - pass - else: - for countOther in range (len(action_types[street][otherPlayer])): - if action_types[street][otherPlayer][countOther]=="bet": - myOtherRaisedStreet2=True - for countOtherFold in range (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: - for count in range(len(action_types[street][player])): - if action_types[street][player][count]=="bet": - myStreet3Aggr=True - - for otherPlayer in range (len(player_ids)): - if player==otherPlayer: - pass - else: - for countOther in range (len(action_types[street][otherPlayer])): - if action_types[street][otherPlayer][countOther]=="bet": - myOtherRaisedStreet3=True - for countOtherFold in range (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: - for count in range(len(action_types[street][player])): - if action_types[street][player][count]=="bet": - myStreet4Aggr=True - - for otherPlayer in range (len(player_ids)): - if player==otherPlayer: - pass - else: - for countOther in range (len(action_types[street][otherPlayer])): - if action_types[street][otherPlayer][countOther]=="bet": - myOtherRaisedStreet4=True - for countOtherFold in range (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_3B4BChance.append(myStreet0_3B4BChance) - street0_3B4BDone.append(myStreet0_3B4BDone) - 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<=7: - 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 - - #add each array to the to-be-returned dictionary - result={'street0VPI':street0VPI} - result['street0Aggr']=street0Aggr - result['street0_3B4BChance']=street0_3B4BChance - result['street0_3B4BDone']=street0_3B4BDone - 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 - - #now the various steal values - foldBbToStealChance=[] - foldedBbToSteal=[] - foldSbToStealChance=[] - foldedSbToSteal=[] - for player in range (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 range (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 range (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 range (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 range (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 range (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 range (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 range (len(player_ids)): - #print "pl=", pl - myTotalProfit=winnings[pl] # still need to deduct costs - for i in range (len(actionTypes)): #iterate through streets - #for j in range (len(actionTypes[i])): #iterate through names (using pl loop above) - for k in range (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 range(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 range(len(playerIDs)): - if playerIDs[player]==action[0]: - foldToStreetCBChance[player]=True - if action[1]=="fold": - foldToStreetCBDone[player]=True -#end def generateFoldToCB - -def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData): -# if (category=="holdem" or category=="omahahi" or category=="omahahilo"): - - #print "storeHudCache, len(playerIds)=", len(playerIds), " len(vpip)=" \ - #, len(hudImportData['street0VPI']), " len(totprof)=", len(hudImportData['totalProfit']) - for player in range (len(playerIds)): - if base=="hold": - cursor.execute("SELECT * FROM HudCache WHERE gametypeId+0=%s AND playerId=%s AND activeSeats=%s AND position=%s", (gametypeId, playerIds[player], len(playerIds), hudImportData['position'][player])) - else: - cursor.execute("SELECT * FROM HudCache WHERE gametypeId+0=%s AND playerId=%s AND activeSeats=%s", (gametypeId, playerIds[player], len(playerIds))) - row=cursor.fetchone() - #print "gametypeId:", gametypeId, "playerIds[player]",playerIds[player], "len(playerIds):",len(playerIds), "row:",row - - try: len(row) - except TypeError: - row=[] - - if (len(row)==0): - #print "new huddata row" - doInsert=True - row=[] - row.append(0)#blank for id - row.append(gametypeId) - row.append(playerIds[player]) - row.append(len(playerIds))#seats - for i in range(len(hudImportData)+2): - row.append(0) - - else: - doInsert=False - newrow=[] - for i in range(len(row)): - newrow.append(row[i]) - row=newrow - - 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_3B4BChance'][player]: row[9]+=1 - if hudImportData['street0_3B4BDone'][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 - - if doInsert: - #print "playerid before insert:",row[2] - cursor.execute("""INSERT INTO HudCache - (gametypeId, playerId, activeSeats, position, tourneyTypeId, - HDs, street0VPI, street0Aggr, street0_3B4BChance, street0_3B4BDone, - 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)""", (row[1], row[2], row[3], row[4], row[5], 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])) - else: - #print "storing updated hud data line" - cursor.execute("""UPDATE HudCache - SET HDs=%s, street0VPI=%s, street0Aggr=%s, street0_3B4BChance=%s, street0_3B4BDone=%s, - street1Seen=%s, street2Seen=%s, street3Seen=%s, street4Seen=%s, sawShowdown=%s, - street1Aggr=%s, street2Aggr=%s, street3Aggr=%s, street4Aggr=%s, otherRaisedStreet1=%s, - otherRaisedStreet2=%s, otherRaisedStreet3=%s, otherRaisedStreet4=%s, foldToOtherRaisedStreet1=%s, foldToOtherRaisedStreet2=%s, - foldToOtherRaisedStreet3=%s, foldToOtherRaisedStreet4=%s, wonWhenSeenStreet1=%s, wonAtSD=%s, stealAttemptChance=%s, - stealAttempted=%s, foldBbToStealChance=%s, foldedBbToSteal=%s, foldSbToStealChance=%s, foldedSbToSteal=%s, - street1CBChance=%s, street1CBDone=%s, street2CBChance=%s, street2CBDone=%s, street3CBChance=%s, - street3CBDone=%s, street4CBChance=%s, street4CBDone=%s, foldToStreet1CBChance=%s, foldToStreet1CBDone=%s, - foldToStreet2CBChance=%s, foldToStreet2CBDone=%s, foldToStreet3CBChance=%s, foldToStreet3CBDone=%s, foldToStreet4CBChance=%s, - foldToStreet4CBDone=%s, totalProfit=%s, street1CheckCallRaiseChance=%s, street1CheckCallRaiseDone=%s, street2CheckCallRaiseChance=%s, - street2CheckCallRaiseDone=%s, street3CheckCallRaiseChance=%s, street3CheckCallRaiseDone=%s, street4CheckCallRaiseChance=%s, street4CheckCallRaiseDone=%s - WHERE gametypeId=%s AND playerId=%s AND activeSeats=%s AND position=%s AND tourneyTypeId=%s""", (row[6], row[7], row[8], row[9], row[10], - row[11], row[12], row[13], row[14], row[15], - row[16], row[17], row[18], row[19], row[20], - row[21], row[22], row[23], row[24], row[25], - row[26], row[27], row[28], row[29], row[30], - row[31], row[32], row[33], row[34], row[35], row[36], row[37], row[38], row[39], row[40], - row[41], row[42], row[43], row[44], row[45], row[46], row[47], row[48], row[49], row[50], - row[51], row[52], row[53], row[54], row[55], row[56], row[57], row[58], row[59], row[60], - row[1], row[2], row[3], str(row[4]), row[5])) -# else: -# print "todo: implement storeHudCache for stud base" -#end def storeHudCache - -def store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, startTime): - cursor.execute("SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s", (siteTourneyNo, tourneyTypeId)) - tmp=cursor.fetchone() - #print "tried SELECTing tourneys.id, result:",tmp - - try: - len(tmp) - except TypeError:#means we have to create new one - cursor.execute("""INSERT INTO Tourneys - (tourneyTypeId, siteTourneyNo, entries, prizepool, startTime) - VALUES (%s, %s, %s, %s, %s)""", (tourneyTypeId, siteTourneyNo, entries, prizepool, startTime)) - cursor.execute("SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s", (siteTourneyNo, tourneyTypeId)) - tmp=cursor.fetchone() - #print "created new tourneys.id:",tmp - return tmp[0] -#end def store_tourneys - -def store_tourneys_players(cursor, tourney_id, player_ids, payin_amounts, ranks, winnings): - result=[] - #print "in store_tourneys_players. tourney_id:",tourney_id - #print "player_ids:",player_ids - #print "payin_amounts:",payin_amounts - #print "ranks:",ranks - #print "winnings:",winnings - for i in range (len(player_ids)): - cursor.execute("SELECT id FROM TourneysPlayers WHERE tourneyId=%s AND playerId+0=%s", (tourney_id, player_ids[i])) - tmp=cursor.fetchone() - #print "tried SELECTing tourneys_players.id:",tmp - - try: - len(tmp) - except TypeError: - cursor.execute("""INSERT INTO TourneysPlayers - (tourneyId, playerId, payinAmount, rank, winnings) VALUES (%s, %s, %s, %s, %s)""", - (tourney_id, player_ids[i], payin_amounts[i], ranks[i], winnings[i])) - - cursor.execute("SELECT id FROM TourneysPlayers WHERE tourneyId=%s AND playerId+0=%s", - (tourney_id, player_ids[i])) - tmp=cursor.fetchone() - #print "created new tourneys_players.id:",tmp - result.append(tmp[0]) - return result -#end def store_tourneys_players +#!/usr/bin/python + +#Copyright 2008 Steffen Jobbagy-Felso +#This program is free software: you can redistribute it and/or modify +#it under the terms of the GNU Affero General Public License as published by +#the Free Software Foundation, version 3 of the License. +# +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. +# +#You should have received a copy of the GNU Affero General Public License +#along with this program. If not, see . +#In the "official" distribution you can find the license in +#agpl-3.0.txt in the docs folder of the package. + +#This file contains simple functions for fpdb + +import datetime +import re + +PS=1 +FTP=2 + +MYSQL_INNODB=2 +PGSQL=3 +SQLITE=4 + + +class DuplicateError(Exception): + def __init__(self, value): + self.value = value + def __str__(self): + return repr(self.value) + +class FpdbError(Exception): + def __init__(self, value): + self.value = value + def __str__(self): + return repr(self.value) + +# gets value for last auto-increment key generated +# returns -1 if a problem occurs +def getLastInsertId(backend, conn, cursor): + if backend == MYSQL_INNODB: + ret = conn.insert_id() + if ret < 1 or ret > 999999999: + print "getLastInsertId(): problem fetching insert_id? ret=", ret + ret = -1 + elif backend == PGSQL: + # some options: + # currval(hands_id_seq) - use name of implicit seq here + # lastval() - still needs sequences set up? + # insert ... returning is useful syntax (but postgres specific?) + # see rules (fancy trigger type things) + cursor.execute ("SELECT lastval()") + row = cursor.fetchone() + if not row: + print "getLastInsertId(%s): problem fetching lastval? row=" % seq, row + ret = -1 + else: + ret = row[0] + elif backend == SQLITE: + # don't know how to do this in sqlite + print "getLastInsertId(): not coded for sqlite yet" + ret = -1 + else: + print "getLastInsertId(): unknown backend ", backend + ret = -1 + return ret +#end def getLastInsertId + +#returns an array of the total money paid. intending to add rebuys/addons here +def calcPayin(count, buyin, fee): + result=[] + for i in range(count): + result.append (buyin+fee) + return result +#end def calcPayin + +def checkPositions(positions): + """verifies that these positions are valid""" + for i in range (len(positions)): + pos=positions[i] + try:#todo: use type recognition instead of error + if (len(pos)!=1): + raise FpdbError("invalid position found in checkPositions. i: "+str(i)+" position: "+pos) #dont need to str() here + except TypeError:#->not string->is int->fine + pass + + ### RHH modified to allow for "position 9" here (pos==9 is when you're a dead hand before the BB + if (pos!="B" and pos!="S" and pos!=0 and pos!=1 and pos!=2 and pos!=3 and pos!=4 and pos!=5 and pos!=6 and pos!=7 and pos!=9): + raise FpdbError("invalid position found in checkPositions. i: "+str(i)+" position: "+str(pos)) +#end def fpdb_simple.checkPositions + +#classifies each line for further processing in later code. Manipulates the passed arrays. +def classifyLines(hand, category, lineTypes, lineStreets): + currentStreet="predeal" + done=False #set this to true once we reach the last relevant line (the summary, except rake, is all repeats) + for i in range (len(hand)): + if (done): + if (hand[i].find("[")==-1 or hand[i].find("mucked [")==-1): + lineTypes.append("ignore") + else: #it's storing a mucked card + lineTypes.append("cards") + elif (hand[i].startswith("Dealt to")): + lineTypes.append("cards") + elif (i==0): + lineTypes.append("header") + elif (hand[i].startswith("Seat ") and ((hand[i].find("in chips")!=-1) or (hand[i].find("($")!=-1))): + lineTypes.append("name") + elif (isActionLine(hand[i])): + lineTypes.append("action") + if (hand[i].find(" posts ")!=-1 or hand[i].find(" posts the ")!=-1):#need to set this here so the "action" of posting blinds is registered properly + currentStreet="preflop" + elif (isWinLine(hand[i])): + lineTypes.append("win") + elif (hand[i].startswith("Total pot ") and hand[i].find("Rake")!=-1): + lineTypes.append("rake") + done=True + elif (hand[i]=="*** SHOW DOWN ***" or hand[i]=="*** SUMMARY ***"): + lineTypes.append("ignore") + #print "in classifyLine, showdown or summary" + elif (hand[i].find(" antes ")!=-1 or hand[i].find(" posts the ante ")!=-1): + lineTypes.append("ante") + elif (hand[i].startswith("*** FLOP *** [")): + lineTypes.append("cards") + currentStreet="flop" + elif (hand[i].startswith("*** TURN *** [")): + lineTypes.append("cards") + currentStreet="turn" + elif (hand[i].startswith("*** RIVER *** [")): + lineTypes.append("cards") + currentStreet="river" + elif (hand[i].startswith("*** 3")): + lineTypes.append("ignore") + currentStreet=0 + elif (hand[i].startswith("*** 4")): + lineTypes.append("ignore") + currentStreet=1 + elif (hand[i].startswith("*** 5")): + lineTypes.append("ignore") + currentStreet=2 + elif (hand[i].startswith("*** 6")): + lineTypes.append("ignore") + currentStreet=3 + elif (hand[i].startswith("*** 7") or hand[i]=="*** RIVER ***"): + lineTypes.append("ignore") + currentStreet=4 + elif (hand[i].find(" shows [")!=-1): + lineTypes.append("cards") + elif (hand[i].startswith("Table '")): + lineTypes.append("table") + else: + raise FpdbError("unrecognised linetype in:"+hand[i]) + lineStreets.append(currentStreet) +#end def classifyLines + +def convert3B4B(site, category, limit_type, actionTypes, actionAmounts): + """calculates the actual bet amounts in the given amount array and changes it accordingly.""" + for i in range (len(actionTypes)): + for j in range (len(actionTypes[i])): + bets=[] + for k in range (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) + amount2=actionAmounts[bets[1][0]][bets[1][1]][bets[1][2]] + amount1=actionAmounts[bets[0][0]][bets[0][1]][bets[0][2]] + actionAmounts[bets[1][0]][bets[1][1]][bets[1][2]]=amount2-amount1 + elif (len(bets)>2): + fail=True + #todo: run correction for below + if (site=="ps" and category=="holdem" and limit_type=="nl" and len(bets)==3): + fail=False + if (site=="ftp" and category=="omahahi" and limit_type=="pl" and len(bets)==3): + fail=False + + if fail: + print "len(bets)>2 in convert3B4B, i didnt think this is possible. i:",i,"j:",j,"k:",k + print "actionTypes:",actionTypes + raise FpdbError ("too many bets in convert3B4B") + #print "actionAmounts postConvert",actionAmounts +#end def convert3B4B(actionTypes, actionAmounts) + +#Corrects the bet amount if the player had to pay blinds +def convertBlindBet(actionTypes, actionAmounts): + i=0#setting street to pre-flop + for j in range (len(actionTypes[i])):#playerloop + blinds=[] + bets=[] + for k in range (len(actionTypes[i][j])): + if (actionTypes[i][j][k]=="blind"): + blinds.append((i,j,k)) + + if (len(blinds)>0 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 +#end def convertBlindBet + +#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): + for i in range (len(arr)): + for j in range (len(arr[i])): + if (arr[i][j]=="A"): + arr[i][j]=14 + elif (arr[i][j]=="K"): + arr[i][j]=13 + elif (arr[i][j]=="Q"): + arr[i][j]=12 + elif (arr[i][j]=="J"): + arr[i][j]=11 + elif (arr[i][j]=="T"): + arr[i][j]=10 + else: + arr[i][j]=int(arr[i][j]) +#end def convertCardValues + +#converts the strings in the given array to ints (changes the passed array, no returning). see table design for conversion details +def convertCardValuesBoard(arr): + for i in range (len(arr)): + if (arr[i]=="A"): + arr[i]=14 + elif (arr[i]=="K"): + arr[i]=13 + elif (arr[i]=="Q"): + arr[i]=12 + elif (arr[i]=="J"): + arr[i]=11 + elif (arr[i]=="T"): + arr[i]=10 + else: + arr[i]=int(arr[i]) +#end def convertCardValuesBoard + +#this creates the 2D/3D arrays. manipulates the passed arrays instead of returning. +def createArrays(category, seats, card_values, card_suits, antes, winnings, rakes, action_types, allIns, action_amounts, actionNos, actionTypeByNo): + for i in range(seats):#create second dimension arrays + tmp=[] + card_values.append(tmp) + tmp=[] + card_suits.append(tmp) + antes.append(0) + winnings.append(0) + rakes.append(0) + + if (category=="holdem" or category=="omahahi" or category=="omahahilo"): + streetCount=4 + else: + streetCount=5 + + for i in range(streetCount): #build the first dimension array, for streets + tmp=[] + action_types.append(tmp) + tmp=[] + allIns.append(tmp) + tmp=[] + action_amounts.append(tmp) + tmp=[] + actionNos.append(tmp) + tmp=[] + actionTypeByNo.append(tmp) + for j in range (seats): #second dimension arrays: players + tmp=[] + action_types[i].append(tmp) + tmp=[] + allIns[i].append(tmp) + tmp=[] + action_amounts[i].append(tmp) + tmp=[] + actionNos[i].append(tmp) + if (category=="holdem" or category=="omahahi" or category=="omahahilo"): + pass + elif (category=="razz" or category=="studhi" or category=="studhilo"):#need to fill card arrays. + for i in range(seats): + for j in range (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") +#end def fill_board_cards + +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 fpdb_simple.FpdbError ("invalid category:", category) + + for i in range (player_count): + while (len(card_values[i])=1): + raise DuplicateError ("dupl") +#end isAlreadyInDB + +def isRebuyOrAddon(topline): + """isRebuyOrAddon not implemented yet""" + return False +#end def isRebuyOrAddon + +#returns whether the passed topline indicates a tournament or not +def isTourney(topline): + if (topline.find("Tournament")!=-1): + return True + else: + return False +#end def isTourney + +#returns boolean whether the passed line is a win line +def isWinLine(line): + if (line.find("wins the pot")!=-1): + return True + elif (line.find("ties for the high pot")!=-1): + return True + elif (line.find("ties for the high main pot")!=-1): + return True + elif (line.find("ties for the high side pot")!=-1): + return True + elif (line.find("ties for the low pot")!=-1): + return True + elif (line.find("ties for the low main pot")!=-1): + return True + elif (line.find("ties for the low side pot")!=-1): + return True + elif (line.find("ties for the main pot")!=-1): #for ftp tied main pot of split pot + return True + elif (line.find("ties for the pot")!=-1): #for ftp tie + return True + elif (line.find("ties for the side pot")!=-1): #for ftp tied split pots + return True + elif (line.find("wins side pot #")!=-1): #for ftp multi split pots + return True + elif (line.find("wins the low main pot")!=-1): + return True + elif (line.find("wins the low pot")!=-1): + return True + elif (line.find("wins the low side pot")!=-1): + return True + elif (line.find("wins the high main pot")!=-1): + return True + elif (line.find("wins the high pot")!=-1): + return True + elif (line.find("wins the high side pot")!=-1): + return True + elif (line.find("wins the main pot")!=-1): + return True + elif (line.find("wins the side pot")!=-1): #for ftp split pots + return True + elif (line.find("collected")!=-1): + return True + else: + return False #not raising error here, any unknown line wouldve been detected in isActionLine already +#end def isWinLine + +#returns the amount of cash/chips put into the put in the given action line +def parseActionAmount(line, atype, site, isTourney): + #if (line.endswith(" and is all-in")): + # line=line[:-14] + #elif (line.endswith(", and is all in")): + # line=line[:-15] + + if line.endswith(", and is capped"):#ideally we should recognise this as an all-in if category is capXl + line=line[:-15] + if line.endswith(" and is capped"): + line=line[:-14] + + + if (atype=="fold"): + amount=0 + elif (atype=="check"): + amount=0 + elif (atype=="unbet" and site=="ftp"): + pos1=line.find("$")+1 + pos2=line.find(" returned to") + amount=float2int(line[pos1:pos2]) + elif (atype=="unbet" and site=="ps"): + #print "ps unbet, line:",line + pos1=line.find("$")+1 + if pos1==0: + pos1=line.find("(")+1 + pos2=line.find(")") + amount=float2int(line[pos1:pos2]) + elif (atype=="bet" and site=="ps" and line.find(": raises $")!=-1 and line.find("to $")!=-1): + 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(site, 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 range(len(actionNos[street])): + for count in range(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, site, 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) +#end def parseActionLine + +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) +#end def goesAllInOnThisLine + +#returns the action type code (see table design) of the given action line +def parseActionType(line): + if (line.startswith("Uncalled bet")): + return "unbet" + elif (line.endswith("folds")): + return "fold" + elif (line.endswith("checks")): + return "check" + elif (line.find("calls")!=-1): + return "call" + elif (line.find("brings in for")!=-1): + return "blind" + elif (line.find("completes it to")!=-1): + return "bet" + #todo: what if someone completes instead of bringing in? + elif (line.find(" posts $")!=-1): + return "blind" + elif (line.find(" posts a dead ")!=-1): + return "blind" + elif (line.find(": posts small blind ")!=-1): + return "blind" + elif (line.find(" posts the small blind of $")!=-1): + return "blind" + elif (line.find(": posts big blind ")!=-1): + return "blind" + elif (line.find(" posts the big blind of $")!=-1): + return "blind" + elif (line.find(": posts small & big blinds $")!=-1): + return "blind" + #todo: seperately record voluntary blind payments made to join table out of turn + elif (line.find("bets")!=-1): + return "bet" + elif (line.find("raises")!=-1): + return "bet" + else: + raise FpdbError ("failed to recognise actiontype in parseActionLine in: "+line) +#end def parseActionType + +#parses the ante out of the given line and checks which player paid it, updates antes accordingly. +def parseAnteLine(line, site, isTourney, names, antes): + for i in range(len(names)): + if (line.startswith(names[i].encode("latin-1"))): #found the ante'er + pos=line.rfind("$")+1 + if not isTourney: + antes[i]+=float2int(line[pos:]) + else: + if line.find("all-in")==-1: + 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]) + #print "parseAnteLine line: ", line, "antes[i]", antes[i], "antes", antes +#end def parseAntes + +#returns the buyin of a tourney in cents +def parseBuyin(topline): + pos1=topline.find("$")+1 + pos2=topline.find("+") + return float2int(topline[pos1:pos2]) +#end def parseBuyin + +#parses a card line and changes the passed arrays accordingly +#todo: reorganise this messy method +def parseCardLine(site, category, street, line, names, cardValues, cardSuits, boardValues, boardSuits): + if (line.startswith("Dealt to ") or line.find(" shows [")!=-1 or line.find("mucked [")!=-1): + 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]: #two tests will do + 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 (line.find("shows")==-1): + #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) +#end def parseCardLine + +def parseCashesAndSeatNos(lines, site): + """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 range (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 + if (site=="ftp"): + pos2=lines[i].rfind(")") + elif (site=="ps"): + pos2=lines[i].find(" in chips") + cashes.append(float2int(lines[i][pos1:pos2])) + return {'startCashes':cashes, 'seatNos':seatNos} +#end def parseCashesAndSeatNos + +#returns the buyin of a tourney in cents +def parseFee(topline): + pos1=topline.find("$")+1 + pos1=topline.find("$",pos1)+1 + pos2=topline.find(" ", pos1) + return float2int(topline[pos1:pos2]) +#end def parsefee + +#returns a datetime object with the starttime indicated in the given topline +def parseHandStartTime(topline, site): + #convert x:13:35 to 0x:13:35 + counter=0 + while (True): + pos=topline.find(" "+str(counter)+":") + if (pos!=-1): + topline=topline[0:pos+1]+"0"+topline[pos+1:] + counter+=1 + if counter==10: break + + isUTC=False + if site=="ftp": + pos = topline.find(" ", len(topline)-26)+1 + tmp = topline[pos:] + #print "year:", tmp[14:18], "month", tmp[19:21], "day", tmp[22:24], "hour", tmp[0:2], "minute", tmp[3:5], "second", tmp[6:8] + result = datetime.datetime(int(tmp[14:18]), int(tmp[19:21]), int(tmp[22:24]), int(tmp[0:2]), int(tmp[3:5]), int(tmp[6:8])) + elif site=="ps": + if topline.find("UTC")!=-1: + pos1 = topline.find("-")+2 + pos2 = topline.find("UTC") + tmp=topline[pos1:pos2] + isUTC=True + else: + tmp=topline[-30:] + #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) + m = re.match('(?P[0-9]{4})\/(?P[0-9]{2})\/(?P[0-9]{2})[\- ]+(?P
[0-9]{2}):(?P[0-9]{2}):(?P[0-9]{2})',tmp) + #print "year:", int(m.group('YEAR')), "month", int(m.group('MON')), "day", int(m.group('DAY')), "hour", int(m.group('HR')), "minute", int(m.group('MIN')), "second", int(m.group('SEC')) + 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'))) + else: + raise FpdbError("invalid site in parseHandStartTime") + + if (site=="ftp" or site=="ps") and not isUTC: #these use US ET + result+=datetime.timedelta(hours=5) + + return result +#end def parseHandStartTime + +#parses the names out of the given lines and returns them as an array +def parseNames(lines): + result = [] + for i in range (len(lines)): + pos1=lines[i].find(":")+2 + pos2=lines[i].rfind("(")-1 + tmp=lines[i][pos1:pos2] + #print "parseNames, tmp original:",tmp + tmp=unicode(tmp,"latin-1") + #print "parseNames, tmp after unicode latin-1 conversion:",tmp + result.append(tmp) + return result +#end def parseNames + +#returns an array with the positions of the respective players +def parsePositions (hand, names): + #prep array + positions=[] + for i in range(len(names)): + positions.append(-1) + + #find blinds + sb,bb=-1,-1 + for i in range (len(hand)): + if (sb==-1 and hand[i].find("small blind")!=-1 and hand[i].find("dead small blind")==-1): + sb=hand[i] + #print "sb:",sb + if (bb==-1 and hand[i].find("big blind")!=-1 and hand[i].find("dead big blind")==-1): + bb=hand[i] + #print "bb:",bb + + #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") + + #write blinds into array + if (sbExists): + positions[sb]="S" + positions[bb]="B" + + #fill up rest of array + if (sbExists): + arraypos=sb-1 + else: + arraypos=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 + + ### RHH - Changed to set the null seats before BB to "9" + i=bb-1 + while positions[i] < 0: + positions[i]=9 + i-=1 + + arraypos=len(names)-1 + if (bb!=0 or (bb==0 and sbExists==False)): + while (arraypos>bb): + positions[arraypos]=distFromBtn + arraypos-=1 + distFromBtn+=1 + + for i in range (len(names)): + if positions[i]==-1: + print "parsePositions names:",names + print "result:",positions + raise FpdbError ("failed to read positions") + return positions +#end def parsePositions + +#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 +#end def parseRake + +def parseSiteHandNo(topline): + """returns the hand no assigned by the poker site""" + pos1=topline.find("#")+1 + pos2=topline.find(":") + return topline[pos1:pos2] +#end def parseSiteHandNo + +def parseTableLine(site, base, line): + """returns a dictionary with maxSeats and tableName""" + if site=="ps": + 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]} + elif site=="ftp": + pos1=line.find("Table ")+6 + pos2=line.find("-")-1 + if base=="hold": + maxSeats=9 + elif base=="stud": + maxSeats=8 + + if line.find("6 max")!=-1: + maxSeats=6 + elif line.find("4 max")!=-1: + maxSeats=4 + elif line.find("heads up")!=-1: + maxSeats=2 + + return {'maxSeats':maxSeats, 'tableName':line[pos1:pos2]} + else: + raise FpdbError("invalid site ID") +#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] +#end def parseTourneyNo + +#parses a win/collect line. manipulates the passed array winnings, no explicit return +def parseWinLine(line, site, names, winnings, isTourney): + #print "parseWinLine: line:",line + for i in range(len(names)): + if (line.startswith(names[i].encode("latin-1"))): #found a winner + if isTourney: + pos1=line.rfind("collected ")+10 + if (site=="ftp"): + pos2=line.find(")", pos1) + elif (site=="ps"): + pos2=line.find(" ", pos1) + winnings[i]+=int(line[pos1:pos2]) + else: + pos1=line.rfind("$")+1 + if (site=="ftp"): + pos2=line.find(")", pos1) + elif (site=="ps"): + pos2=line.find(" ", pos1) + winnings[i]+=float2int(line[pos1:pos2]) +#end def parseWinLine + +#returns the category (as per database) string for the given line +def recogniseCategory(line): + if (line.find("Razz")!=-1): + return "razz" + elif (line.find("Hold'em")!=-1): + return "holdem" + elif (line.find("Omaha")!=-1 and line.find("Hi/Lo")==-1 and line.find("H/L")==-1): + return "omahahi" + elif (line.find("Omaha")!=-1 and (line.find("Hi/Lo")!=-1 or line.find("H/L")!=-1)): + return "omahahilo" + elif (line.find("Stud")!=-1 and line.find("Hi/Lo")==-1 and line.find("H/L")==-1): + return "studhi" + elif (line.find("Stud")!=-1 and (line.find("Hi/Lo")!=-1 or line.find("H/L")!=-1)): + return "studhilo" + else: + raise FpdbError("failed to recognise category, line:"+line) +#end def recogniseCategory + +#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 + if (site_id==1): #ftp + pos2=topline.find(" ", pos1) + elif (site_id==2): #ps + 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 (topline.find("No Limit")!=-1): + limit_type="nl" + if (topline.find("Cap No")!=-1): + limit_type="cn" + elif (topline.find("Pot Limit")!=-1): + limit_type="pl" + if (topline.find("Cap Pot")!=-1): + limit_type="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 ("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: + 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)) + 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 + cursor.execute( """INSERT INTO Gametypes(siteId, type, base, category, limitType + ,hiLo, smallBlind, bigBlind, smallBet, bigBet) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""" + , (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: + cursor.execute( """INSERT INTO Gametypes(siteId, type, base, category, limitType + ,hiLo, smallBlind, bigBlind, smallBet, bigBet) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""" + , (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)) + + #result=(db.insert_id(),) + result=(getLastInsertId(backend,db,cursor),) + + return result[0] +#end def recogniseGametypeID + +def recogniseTourneyTypeId(cursor, siteId, buyin, fee, knockout, rebuyOrAddon): + cursor.execute ("SELECT id FROM TourneyTypes WHERE siteId=%s AND buyin=%s AND fee=%s AND knockout=%s AND rebuyOrAddon=%s", (siteId, buyin, fee, knockout, rebuyOrAddon)) + result=cursor.fetchone() + #print "tried SELECTing gametypes.id, result:",result + + try: + len(result) + except TypeError:#this means we need to create a new entry + cursor.execute("""INSERT INTO TourneyTypes (siteId, buyin, fee, knockout, rebuyOrAddon) VALUES (%s, %s, %s, %s, %s)""", (siteId, buyin, fee, knockout, rebuyOrAddon)) + cursor.execute("SELECT id FROM TourneyTypes WHERE siteId=%s AND buyin=%s AND fee=%s AND knockout=%s AND rebuyOrAddon=%s", (siteId, buyin, fee, knockout, rebuyOrAddon)) + result=cursor.fetchone() + return result[0] +#end def recogniseTourneyTypeId + +#returns the SQL ids of the names given in an array +def recognisePlayerIDs(cursor, names, site_id): + result = [] + for i in range (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 +#end def recognisePlayerIDs + +#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 range (len(names)): + if (atype=="unbet"): + if (line.endswith(names[i].encode("latin-1"))): + 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(names[i].encode("latin-1"))): + return (i) + elif (line.startswith("Seat ")): + if (line.startswith("Seat 10")): + tmp=line[9:] + else: + tmp=line[8:] + + if (tmp.startswith(names[i].encode("latin-1"))): + return (i) + else: + if (line.startswith(names[i].encode("latin-1"))): + return (i) + #if we're here we mustve failed + raise FpdbError ("failed to recognise player in: "+line+" atype:"+atype) +#end def recognisePlayerNo + +#returns the site abbreviation for the given site +def recogniseSite(line): + if (line.startswith("Full Tilt Poker")): + return "ftp" + elif (line.startswith("PokerStars")): + return "ps" + else: + raise FpdbError("failed to recognise site, line:"+line) +#end def recogniseSite + +#returns the ID of the given site +def recogniseSiteID(cursor, site): + if (site=="ftp"): + return 1 + #cursor.execute("SELECT id FROM Sites WHERE name = ('Full Tilt Poker')") + elif (site=="ps"): + return 2 + #cursor.execute("SELECT id FROM Sites WHERE name = ('PokerStars')") + else: + raise FpdbError("invalid site in recogniseSiteID: "+site) + return cursor.fetchall()[0][0] +#end def recogniseSiteID + +#removes trailing \n from the given array +def removeTrailingEOL(arr): + for i in range(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 range(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 range(len(winnings)): + if winnings[i]!=0: + winPortion=winnings[i]/totalWin + rakes[i]=totalRake*winPortion +#end def splitRake + +def storeActions(cursor, handsPlayersIds, actionTypes, allIns, actionAmounts, actionNos): +#stores into table hands_actions + #print "start of storeActions, actionNos:",actionNos + #print " action_amounts:",action_amounts + for i in range (len(actionTypes)): #iterate through streets + for j in range (len(actionTypes[i])): #iterate through names + for k in range (len(actionTypes[i][j])): #iterate through individual actions of that player on that street + cursor.execute ("INSERT INTO HandsActions (handPlayerId, street, actionNo, action, allIn, amount) VALUES (%s, %s, %s, %s, %s, %s)" + , (handsPlayersIds[j], i, actionNos[i][j][k], actionTypes[i][j][k], allIns[i][j][k], actionAmounts[i][j][k])) +#end def storeActions + +def store_board_cards(cursor, hands_id, board_values, board_suits): +#stores into table board_cards + cursor.execute ("""INSERT INTO BoardCards (handId, card1Value, card1Suit, +card2Value, card2Suit, card3Value, card3Suit, card4Value, card4Suit, +card5Value, card5Suit) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", + (hands_id, board_values[0], board_suits[0], board_values[1], board_suits[1], + board_values[2], board_suits[2], board_values[3], board_suits[3], + board_values[4], board_suits[4])) +#end def store_board_cards + +def storeHands(backend, conn, cursor, site_hand_no, gametype_id + ,hand_start_time, names, tableName, maxSeats): +#stores into table hands + cursor.execute ("INSERT INTO Hands (siteHandNo, gametypeId, handStart, seats, tableName, importTime, maxSeats) VALUES (%s, %s, %s, %s, %s, %s, %s)", (site_hand_no, gametype_id, hand_start_time, len(names), tableName, datetime.datetime.today(), maxSeats)) + #todo: find a better way of doing this... + #cursor.execute("SELECT id FROM Hands WHERE siteHandNo=%s AND gametypeId=%s", (site_hand_no, gametype_id)) + #return cursor.fetchall()[0][0] + return getLastInsertId(backend, conn, cursor) + #return db.insert_id() # mysql only +#end def storeHands + +def store_hands_players_holdem_omaha(backend, conn, cursor, category, hands_id, player_ids, start_cashes + ,positions, card_values, card_suits, winnings, rakes, seatNos): + result=[] + if (category=="holdem"): + for i in range (len(player_ids)): + cursor.execute (""" +INSERT INTO HandsPlayers +(handId, playerId, startCash, position, +card1Value, card1Suit, card2Value, card2Suit, winnings, rake, seatNo) +VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", + (hands_id, player_ids[i], start_cashes[i], positions[i], + card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], + winnings[i], rakes[i], seatNos[i])) + #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId=%s", (hands_id, player_ids[i])) + #result.append(cursor.fetchall()[0][0]) + result.append( getLastInsertId(backend, conn, cursor) ) # mysql only + elif (category=="omahahi" or category=="omahahilo"): + for i in range (len(player_ids)): + cursor.execute ("""INSERT INTO HandsPlayers +(handId, playerId, startCash, position, +card1Value, card1Suit, card2Value, card2Suit, +card3Value, card3Suit, card4Value, card4Suit, winnings, rake, seatNo) +VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", + (hands_id, player_ids[i], start_cashes[i], positions[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], + 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( getLastInsertId(backend, conn, cursor) ) # mysql only + else: + raise FpdbError("invalid category") + return result +#end def store_hands_players_holdem_omaha + +def store_hands_players_stud(backend, conn, cursor, 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 + result=[] + #print "before inserts in store_hands_players_stud, antes:", antes + for i in range (len(player_ids)): + cursor.execute ("""INSERT INTO HandsPlayers +(handId, playerId, startCash, ante, +card1Value, card1Suit, card2Value, card2Suit, +card3Value, card3Suit, card4Value, card4Suit, +card5Value, card5Suit, card6Value, card6Suit, +card7Value, card7Suit, winnings, rake, seatNo) +VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, +%s, %s, %s, %s)""", + (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], 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( getLastInsertId(backend, conn, cursor) ) # mysql only + return result +#end def store_hands_players_stud + +def store_hands_players_holdem_omaha_tourney(backend, conn, cursor, category, hands_id, player_ids + ,start_cashes, positions, card_values, card_suits + , winnings, rakes, seatNos, tourneys_players_ids): + #stores hands_players for tourney holdem/omaha hands + result=[] + for i in range (len(player_ids)): + if len(card_values[0])==2: + cursor.execute ("""INSERT INTO HandsPlayers +(handId, playerId, startCash, position, +card1Value, card1Suit, card2Value, card2Suit, +winnings, rake, tourneysPlayersId, seatNo) +VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", + (hands_id, player_ids[i], start_cashes[i], positions[i], + card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], + winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i])) + elif len(card_values[0])==4: + cursor.execute ("""INSERT INTO HandsPlayers +(handId, playerId, startCash, position, +card1Value, card1Suit, card2Value, card2Suit, +card3Value, card3Suit, card4Value, card4Suit, +winnings, rake, tourneysPlayersId, seatNo) +VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", + (hands_id, player_ids[i], start_cashes[i], positions[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], + winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i])) + else: + raise FpdbError ("invalid card_values length:"+str(len(card_values[0]))) + #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( getLastInsertId(backend, conn, cursor) ) # mysql only + + return result +#end def store_hands_players_holdem_omaha_tourney + +def store_hands_players_stud_tourney(backend, conn, cursor, hands_id, player_ids, start_cashes, + antes, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids): +#stores hands_players for tourney stud/razz hands + result=[] + for i in range (len(player_ids)): + cursor.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) +VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, +%s, %s, %s, %s, %s, %s)""", + (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])) + #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( getLastInsertId(backend, conn, cursor) ) # mysql only + return result +#end def store_hands_players_stud_tourney + +def generateHudCacheData(player_ids, base, category, action_types, allIns, actionTypeByNo + ,winnings, totalWinnings, positions, actionTypes, actionAmounts): + """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_3B4BChance=[] + street0_3B4BDone=[] + street1Seen=[] + street2Seen=[] + street3Seen=[] + street4Seen=[] + sawShowdown=[] + street1Aggr=[] + street2Aggr=[] + street3Aggr=[] + street4Aggr=[] + otherRaisedStreet1=[] + otherRaisedStreet2=[] + otherRaisedStreet3=[] + otherRaisedStreet4=[] + foldToOtherRaisedStreet1=[] + foldToOtherRaisedStreet2=[] + foldToOtherRaisedStreet3=[] + foldToOtherRaisedStreet4=[] + wonWhenSeenStreet1=[] + + wonAtSD=[] + stealAttemptChance=[] + stealAttempted=[] + hudDataPositions=[] + + firstPfRaiseByNo=-1 + firstPfRaiserId=-1 + firstPfRaiserNo=-1 + firstPfCallByNo=-1 + firstPfCallerId=-1 + for i in range(len(actionTypeByNo[0])): + if actionTypeByNo[0][i][1]=="bet": + firstPfRaiseByNo=i + firstPfRaiserId=actionTypeByNo[0][i][0] + for j in range(len(player_ids)): + if player_ids[j]==firstPfRaiserId: + firstPfRaiserNo=j + break + break + for i in range(len(actionTypeByNo[0])): + if actionTypeByNo[0][i][1]=="call": + firstPfCallByNo=i + firstPfCallerId=actionTypeByNo[0][i][0] + break + + cutoffId=-1 + buttonId=-1 + sbId=-1 + bbId=-1 + if base=="hold": + for player in range(len(positions)): + if positions==1: + cutoffId=player_ids[player] + if positions==0: + buttonId=player_ids[player] + if positions=='S': + sbId=player_ids[player] + if positions=='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 range (len(player_ids)): + #set default values + myStreet0VPI=False + myStreet0Aggr=False + myStreet0_3B4BChance=False + myStreet0_3B4BDone=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 + + #calculate VPIP and PFR + street=0 + heroPfRaiseCount=0 + for count in range (len(action_types[street][player])):#finally individual actions + currentAction=action_types[street][player][count] + if currentAction=="bet": + myStreet0Aggr=True + if (currentAction=="bet" or currentAction=="call"): + myStreet0VPI=True + + #PF3B4BChance and PF3B4B + pfFold=-1 + pfRaise=-1 + if firstPfRaiseByNo!=-1: + for i in range(len(actionTypeByNo[0])): + if actionTypeByNo[0][i][0]==player_ids[player]: + if actionTypeByNo[0][i][1]=="bet" and pfRaise==-1 and i>firstPfRaiseByNo: + pfRaise=i + if actionTypeByNo[0][i][1]=="fold" and pfFold==-1: + pfFold=i + if pfFold==-1 or pfFold>firstPfRaiseByNo: + myStreet0_3B4BChance=True + if pfRaise>firstPfRaiseByNo: + myStreet0_3B4BDone=True + + #steal calculations + if base=="hold": + if len(player_ids)>=5: #no point otherwise + if positions[player]==1: + if firstPfRaiserId==player_ids[player]: + myStealAttemptChance=True + myStealAttempted=True + elif firstPfRaiserId==buttonId or firstPfRaiserId==sbId or firstPfRaiserId==bbId or firstPfRaiserId==-1: + myStealAttemptChance=True + if positions[player]==0: + if firstPfRaiserId==player_ids[player]: + myStealAttemptChance=True + myStealAttempted=True + elif firstPfRaiserId==sbId or firstPfRaiserId==bbId or firstPfRaiserId==-1: + myStealAttemptChance=True + if positions[player]=='S': + if firstPfRaiserId==player_ids[player]: + myStealAttemptChance=True + myStealAttempted=True + elif firstPfRaiserId==bbId or firstPfRaiserId==-1: + myStealAttemptChance=True + if positions[player]=='B': + pass + + if myStealAttempted: + someoneStole=True + + + #calculate saw* values + isAllIn=False + for i in range(len(allIns[0][player])): + if allIns[0][player][i]: + isAllIn=True + if (len(action_types[1][player])>0 or isAllIn): + myStreet1Seen=True + + for i in range(len(allIns[1][player])): + if allIns[1][player][i]: + isAllIn=True + if (len(action_types[2][player])>0 or isAllIn): + myStreet2Seen=True + + for i in range(len(allIns[2][player])): + if allIns[2][player][i]: + isAllIn=True + if (len(action_types[3][player])>0 or isAllIn): + myStreet3Seen=True + + #print "base:", base + if base=="hold": + mySawShowdown=True + for count in range (len(action_types[3][player])): + if action_types[3][player][count]=="fold": + mySawShowdown=False + else: + #print "in else" + for i in range(len(allIns[3][player])): + if allIns[3][player][i]: + isAllIn=True + if (len(action_types[4][player])>0 or isAllIn): + #print "in if" + myStreet4Seen=True + + mySawShowdown=True + for count in range (len(action_types[4][player])): + if action_types[4][player][count]=="fold": + mySawShowdown=False + + + #flop stuff + street=1 + if myStreet1Seen: + for count in range(len(action_types[street][player])): + if action_types[street][player][count]=="bet": + myStreet1Aggr=True + + for otherPlayer in range (len(player_ids)): + if player==otherPlayer: + pass + else: + for countOther in range (len(action_types[street][otherPlayer])): + if action_types[street][otherPlayer][countOther]=="bet": + myOtherRaisedStreet1=True + for countOtherFold in range (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: + for count in range(len(action_types[street][player])): + if action_types[street][player][count]=="bet": + myStreet2Aggr=True + + for otherPlayer in range (len(player_ids)): + if player==otherPlayer: + pass + else: + for countOther in range (len(action_types[street][otherPlayer])): + if action_types[street][otherPlayer][countOther]=="bet": + myOtherRaisedStreet2=True + for countOtherFold in range (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: + for count in range(len(action_types[street][player])): + if action_types[street][player][count]=="bet": + myStreet3Aggr=True + + for otherPlayer in range (len(player_ids)): + if player==otherPlayer: + pass + else: + for countOther in range (len(action_types[street][otherPlayer])): + if action_types[street][otherPlayer][countOther]=="bet": + myOtherRaisedStreet3=True + for countOtherFold in range (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: + for count in range(len(action_types[street][player])): + if action_types[street][player][count]=="bet": + myStreet4Aggr=True + + for otherPlayer in range (len(player_ids)): + if player==otherPlayer: + pass + else: + for countOther in range (len(action_types[street][otherPlayer])): + if action_types[street][otherPlayer][countOther]=="bet": + myOtherRaisedStreet4=True + for countOtherFold in range (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_3B4BChance.append(myStreet0_3B4BChance) + street0_3B4BDone.append(myStreet0_3B4BDone) + 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<=7: + 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 + + #add each array to the to-be-returned dictionary + result={'street0VPI':street0VPI} + result['street0Aggr']=street0Aggr + result['street0_3B4BChance']=street0_3B4BChance + result['street0_3B4BDone']=street0_3B4BDone + 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 + + #now the various steal values + foldBbToStealChance=[] + foldedBbToSteal=[] + foldSbToStealChance=[] + foldedSbToSteal=[] + for player in range (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 range (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 range (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 range (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 range (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 range (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 range (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 range (len(player_ids)): + #print "pl=", pl + myTotalProfit=winnings[pl] # still need to deduct costs + for i in range (len(actionTypes)): #iterate through streets + #for j in range (len(actionTypes[i])): #iterate through names (using pl loop above) + for k in range (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 range(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 range(len(playerIDs)): + if playerIDs[player]==action[0]: + foldToStreetCBChance[player]=True + if action[1]=="fold": + foldToStreetCBDone[player]=True +#end def generateFoldToCB + +def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData): +# if (category=="holdem" or category=="omahahi" or category=="omahahilo"): + + #print "storeHudCache, len(playerIds)=", len(playerIds), " len(vpip)=" \ + #, len(hudImportData['street0VPI']), " len(totprof)=", len(hudImportData['totalProfit']) + for player in range (len(playerIds)): + if base=="hold": + cursor.execute("SELECT * FROM HudCache WHERE gametypeId+0=%s AND playerId=%s AND activeSeats=%s AND position=%s", (gametypeId, playerIds[player], len(playerIds), hudImportData['position'][player])) + else: + cursor.execute("SELECT * FROM HudCache WHERE gametypeId+0=%s AND playerId=%s AND activeSeats=%s", (gametypeId, playerIds[player], len(playerIds))) + row=cursor.fetchone() + #print "gametypeId:", gametypeId, "playerIds[player]",playerIds[player], "len(playerIds):",len(playerIds), "row:",row + + try: len(row) + except TypeError: + row=[] + + if (len(row)==0): + #print "new huddata row" + doInsert=True + row=[] + row.append(0)#blank for id + row.append(gametypeId) + row.append(playerIds[player]) + row.append(len(playerIds))#seats + for i in range(len(hudImportData)+2): + row.append(0) + + else: + doInsert=False + newrow=[] + for i in range(len(row)): + newrow.append(row[i]) + row=newrow + + 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_3B4BChance'][player]: row[9]+=1 + if hudImportData['street0_3B4BDone'][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 + + if doInsert: + #print "playerid before insert:",row[2] + cursor.execute("""INSERT INTO HudCache +(gametypeId, playerId, activeSeats, position, tourneyTypeId, +HDs, street0VPI, street0Aggr, street0_3B4BChance, street0_3B4BDone, +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)""", (row[1], row[2], row[3], row[4], row[5], 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])) + else: + #print "storing updated hud data line" + cursor.execute("""UPDATE HudCache +SET HDs=%s, street0VPI=%s, street0Aggr=%s, street0_3B4BChance=%s, street0_3B4BDone=%s, +street1Seen=%s, street2Seen=%s, street3Seen=%s, street4Seen=%s, sawShowdown=%s, +street1Aggr=%s, street2Aggr=%s, street3Aggr=%s, street4Aggr=%s, otherRaisedStreet1=%s, +otherRaisedStreet2=%s, otherRaisedStreet3=%s, otherRaisedStreet4=%s, foldToOtherRaisedStreet1=%s, foldToOtherRaisedStreet2=%s, +foldToOtherRaisedStreet3=%s, foldToOtherRaisedStreet4=%s, wonWhenSeenStreet1=%s, wonAtSD=%s, stealAttemptChance=%s, +stealAttempted=%s, foldBbToStealChance=%s, foldedBbToSteal=%s, foldSbToStealChance=%s, foldedSbToSteal=%s, +street1CBChance=%s, street1CBDone=%s, street2CBChance=%s, street2CBDone=%s, street3CBChance=%s, +street3CBDone=%s, street4CBChance=%s, street4CBDone=%s, foldToStreet1CBChance=%s, foldToStreet1CBDone=%s, +foldToStreet2CBChance=%s, foldToStreet2CBDone=%s, foldToStreet3CBChance=%s, foldToStreet3CBDone=%s, foldToStreet4CBChance=%s, +foldToStreet4CBDone=%s, totalProfit=%s, street1CheckCallRaiseChance=%s, street1CheckCallRaiseDone=%s, street2CheckCallRaiseChance=%s, +street2CheckCallRaiseDone=%s, street3CheckCallRaiseChance=%s, street3CheckCallRaiseDone=%s, street4CheckCallRaiseChance=%s, street4CheckCallRaiseDone=%s +WHERE gametypeId=%s AND playerId=%s AND activeSeats=%s AND position=%s AND tourneyTypeId=%s""", (row[6], row[7], row[8], row[9], row[10], + row[11], row[12], row[13], row[14], row[15], + row[16], row[17], row[18], row[19], row[20], + row[21], row[22], row[23], row[24], row[25], + row[26], row[27], row[28], row[29], row[30], + row[31], row[32], row[33], row[34], row[35], row[36], row[37], row[38], row[39], row[40], + row[41], row[42], row[43], row[44], row[45], row[46], row[47], row[48], row[49], row[50], + row[51], row[52], row[53], row[54], row[55], row[56], row[57], row[58], row[59], row[60], + row[1], row[2], row[3], str(row[4]), row[5])) +# else: +# print "todo: implement storeHudCache for stud base" +#end def storeHudCache + +def store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, startTime): + cursor.execute("SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s", (siteTourneyNo, tourneyTypeId)) + tmp=cursor.fetchone() + #print "tried SELECTing tourneys.id, result:",tmp + + try: + len(tmp) + except TypeError:#means we have to create new one + cursor.execute("""INSERT INTO Tourneys +(tourneyTypeId, siteTourneyNo, entries, prizepool, startTime) +VALUES (%s, %s, %s, %s, %s)""", (tourneyTypeId, siteTourneyNo, entries, prizepool, startTime)) + cursor.execute("SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s", (siteTourneyNo, tourneyTypeId)) + tmp=cursor.fetchone() + #print "created new tourneys.id:",tmp + return tmp[0] +#end def store_tourneys + +def store_tourneys_players(cursor, tourney_id, player_ids, payin_amounts, ranks, winnings): + result=[] + #print "in store_tourneys_players. tourney_id:",tourney_id + #print "player_ids:",player_ids + #print "payin_amounts:",payin_amounts + #print "ranks:",ranks + #print "winnings:",winnings + for i in range (len(player_ids)): + cursor.execute("SELECT id FROM TourneysPlayers WHERE tourneyId=%s AND playerId+0=%s", (tourney_id, player_ids[i])) + tmp=cursor.fetchone() + #print "tried SELECTing tourneys_players.id:",tmp + + try: + len(tmp) + except TypeError: + cursor.execute("""INSERT INTO TourneysPlayers +(tourneyId, playerId, payinAmount, rank, winnings) VALUES (%s, %s, %s, %s, %s)""", + (tourney_id, player_ids[i], payin_amounts[i], ranks[i], winnings[i])) + + cursor.execute("SELECT id FROM TourneysPlayers WHERE tourneyId=%s AND playerId+0=%s", + (tourney_id, player_ids[i])) + tmp=cursor.fetchone() + #print "created new tourneys_players.id:",tmp + result.append(tmp[0]) + return result +#end def store_tourneys_players From 7d4bded3d5b7076ecf2074309bf9d6407160d3c4 Mon Sep 17 00:00:00 2001 From: eblade Date: Tue, 9 Dec 2008 01:43:13 -0500 Subject: [PATCH 26/32] make sure we close each handle opened by ProcessOpen in the win32 calls --- pyfpdb/Hud.py | 1 + pyfpdb/Tables.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 80ec9a82..aaa9b42d 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -307,6 +307,7 @@ class Stat_Window: pass if event.button == 1: # left button event + # TODO: make position saving save sizes as well? if event.state & gtk.gdk.SHIFT_MASK: self.window.begin_resize_drag(gtk.gdk.WINDOW_EDGE_SOUTH_EAST, event.button, int(event.x_root), int(event.y_root), event.time) else: diff --git a/pyfpdb/Tables.py b/pyfpdb/Tables.py index 9f5360e2..d2cb2a24 100755 --- a/pyfpdb/Tables.py +++ b/pyfpdb/Tables.py @@ -248,7 +248,9 @@ def get_nt_exe(hwnd): """Finds the name of the executable that the given window handle belongs to.""" processid = win32process.GetWindowThreadProcessId(hwnd) pshandle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ, False, processid[1]) - return win32process.GetModuleFileNameEx(pshandle, 0) + exename = win32process.GetModuleFileNameEx(pshandle, 0) + win32api.CloseHandle(pshandle) + return exename def decode_windows(c, title, hwnd): """Gets window parameters from the window title and handle--Windows.""" From 9dd6f36df635d4d02df5a286644ceddc7c9a8c8c Mon Sep 17 00:00:00 2001 From: eblade Date: Tue, 9 Dec 2008 07:51:41 -0500 Subject: [PATCH 27/32] add Hud::update_table_position(), tracks table.x and table.y, repositions all stat_windows within. triggered each update(), and when the Reposition Stats menu option is selected. fix windows code to use same gdkhandle variables as unix code --- pyfpdb/Hud.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index aaa9b42d..03ba1696 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -120,6 +120,19 @@ class Hud: self.main_window.gdkhandle.set_transient_for(self.main_window.parentgdkhandle) # self.main_window.set_destroy_with_parent(True) + + def update_table_position(self): + (x, y) = self.main_window.parentgdkhandle.get_origin() + if self.table.x != x or self.table.y != y: + self.table.x = x + self.table.y = y + self.main_window.move(x, y) + adj = self.adj_seats(self.hand, self.config) + loc = self.config.get_locations(self.table.site, self.max) + for i in range(1, self.max + 1): + (x, y) = loc[adj[i]] + if self.stat_windows.has_key(i): + self.stat_windows[i].relocate(x, y) def on_button_press(self, widget, event): if event.button == 1: @@ -137,9 +150,7 @@ class Hud: self.deleted = True def reposition_windows(self, *args): - for w in self.stat_windows: - self.stat_windows[w].window.move(self.stat_windows[w].x, - self.stat_windows[w].y) + self.update_table_position() def debug_stat_windows(self, *args): print self.table, "\n", self.main_window.window.get_transient_for() @@ -216,6 +227,7 @@ class Hud: def update(self, hand, config, stat_dict): self.hand = hand # this is the last hand, so it is available later + self.update_table_position() for s in stat_dict.keys(): try: self.stat_windows[stat_dict[s]['seat']].player_id = stat_dict[s]['player_id'] @@ -260,9 +272,9 @@ class Hud: for w in tl_windows: if w[1] == unique_name: #win32gui.ShowWindow(w[0], win32con.SW_HIDE) - window.parentgdkhandle = gtk.gdk.window_foreign_new(long(self.table.number)) + self.main_window.parentgdkhandle = gtk.gdk.window_foreign_new(long(self.table.number)) self.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0]) - self.main_window.gdkhandle.set_transient_for(window.parentgdkhandle) + self.main_window.gdkhandle.set_transient_for(self.main_window.parentgdkhandle) #win32gui.ShowWindow(w[0], win32con.SW_SHOW) style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE) From 7516d17a40999fdd0638221f8b9998c3ddc96b4d Mon Sep 17 00:00:00 2001 From: eblade Date: Tue, 9 Dec 2008 08:21:50 -0500 Subject: [PATCH 28/32] add 0.5 sec auto-timer to auto-run update_table_position --- pyfpdb/Hud.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 03ba1696..a98c1421 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -224,6 +224,8 @@ class Hud: if not game_params['aux'] == "": aux_params = config.get_aux_parameters(game_params['aux']) self.aux_windows.append(eval("%s.%s(gtk.Window(), config, 'fpdb')" % (aux_params['module'], aux_params['class']))) + + gobject.timeout_add(0.5, update_table_position) def update(self, hand, config, stat_dict): self.hand = hand # this is the last hand, so it is available later From 5e23b55361b855efb50efdd3ce802a5f44d60594 Mon Sep 17 00:00:00 2001 From: eblade Date: Tue, 9 Dec 2008 08:35:19 -0500 Subject: [PATCH 29/32] specify right function name to timer, duh --- pyfpdb/Hud.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index a98c1421..dcc7298c 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -225,7 +225,7 @@ class Hud: aux_params = config.get_aux_parameters(game_params['aux']) self.aux_windows.append(eval("%s.%s(gtk.Window(), config, 'fpdb')" % (aux_params['module'], aux_params['class']))) - gobject.timeout_add(0.5, update_table_position) + gobject.timeout_add(0.5, self.update_table_position) def update(self, hand, config, stat_dict): self.hand = hand # this is the last hand, so it is available later From 1a43ccf2da33afe0482d1178e935ff8384b77ead Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 9 Dec 2008 23:38:40 +0000 Subject: [PATCH 30/32] remove redundant unique keyword in create table statements --- pyfpdb/FpdbSQLQueries.py | 46 ++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index a3d918ac..f5b4f400 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -73,13 +73,13 @@ class FpdbSQLQueries: if(self.dbname == 'MySQL InnoDB'): self.query['createSitesTable'] = """CREATE TABLE Sites ( - id SMALLINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + id SMALLINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), name varchar(32) NOT NULL, currency char(3) NOT NULL) ENGINE=INNODB""" elif(self.dbname == 'PostgreSQL'): self.query['createSitesTable'] = """CREATE TABLE Sites ( - id SERIAL UNIQUE, PRIMARY KEY (id), + id SERIAL, PRIMARY KEY (id), name varchar(32), currency char(3))""" elif(self.dbname == 'SQLite'): @@ -92,7 +92,7 @@ class FpdbSQLQueries: if(self.dbname == 'MySQL InnoDB'): self.query['createGametypesTable'] = """CREATE TABLE Gametypes ( - id SMALLINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + id SMALLINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), siteId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id), type char(4) NOT NULL, base char(4) NOT NULL, @@ -106,7 +106,7 @@ class FpdbSQLQueries: ENGINE=INNODB""" elif(self.dbname == 'PostgreSQL'): self.query['createGametypesTable'] = """CREATE TABLE Gametypes ( - id SERIAL UNIQUE, PRIMARY KEY (id), + id SERIAL, PRIMARY KEY (id), siteId INTEGER, FOREIGN KEY (siteId) REFERENCES Sites(id), type char(4), base char(4), @@ -127,7 +127,7 @@ class FpdbSQLQueries: if(self.dbname == 'MySQL InnoDB'): self.query['createPlayersTable'] = """CREATE TABLE Players ( - id INT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + id INT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), name VARCHAR(32) CHARACTER SET utf8 NOT NULL, siteId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id), comment text, @@ -135,7 +135,7 @@ class FpdbSQLQueries: ENGINE=INNODB""" elif(self.dbname == 'PostgreSQL'): self.query['createPlayersTable'] = """CREATE TABLE Players ( - id SERIAL UNIQUE, PRIMARY KEY (id), + id SERIAL, PRIMARY KEY (id), name VARCHAR(32), siteId INTEGER, FOREIGN KEY (siteId) REFERENCES Sites(id), comment text, @@ -150,7 +150,7 @@ class FpdbSQLQueries: if(self.dbname == 'MySQL InnoDB'): self.query['createAutoratesTable'] = """CREATE TABLE Autorates ( - id BIGINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), playerId INT UNSIGNED NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id), gametypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), description varchar(50) NOT NULL, @@ -160,7 +160,7 @@ class FpdbSQLQueries: ENGINE=INNODB""" elif(self.dbname == 'PostgreSQL'): self.query['createAutoratesTable'] = """CREATE TABLE Autorates ( - id BIGSERIAL UNIQUE, PRIMARY KEY (id), + id BIGSERIAL, PRIMARY KEY (id), playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id), gametypeId INT, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), description varchar(50), @@ -177,7 +177,7 @@ class FpdbSQLQueries: if(self.dbname == 'MySQL InnoDB'): self.query['createHandsTable'] = """CREATE TABLE Hands ( - id BIGINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), tableName VARCHAR(20) NOT NULL, siteHandNo BIGINT NOT NULL, gametypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), @@ -190,7 +190,7 @@ class FpdbSQLQueries: ENGINE=INNODB""" elif(self.dbname == 'PostgreSQL'): self.query['createHandsTable'] = """CREATE TABLE Hands ( - id BIGSERIAL UNIQUE, PRIMARY KEY (id), + id BIGSERIAL, PRIMARY KEY (id), tableName VARCHAR(20), siteHandNo BIGINT, gametypeId INT, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), @@ -210,7 +210,7 @@ class FpdbSQLQueries: if(self.dbname == 'MySQL InnoDB'): self.query['createBoardCardsTable'] = """CREATE TABLE BoardCards ( - id BIGINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), handId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handId) REFERENCES Hands(id), card1Value smallint NOT NULL, card1Suit char(1) NOT NULL, @@ -225,7 +225,7 @@ class FpdbSQLQueries: ENGINE=INNODB""" elif(self.dbname == 'PostgreSQL'): self.query['createBoardCardsTable'] = """CREATE TABLE BoardCards ( - id BIGSERIAL UNIQUE, PRIMARY KEY (id), + id BIGSERIAL, PRIMARY KEY (id), handId BIGINT, FOREIGN KEY (handId) REFERENCES Hands(id), card1Value smallint, card1Suit char(1), @@ -247,7 +247,7 @@ class FpdbSQLQueries: if(self.dbname == 'MySQL InnoDB'): self.query['createTourneyTypesTable'] = """CREATE TABLE TourneyTypes ( - id SMALLINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + id SMALLINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), siteId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id), buyin INT NOT NULL, fee INT NOT NULL, @@ -272,7 +272,7 @@ class FpdbSQLQueries: if(self.dbname == 'MySQL InnoDB'): self.query['createTourneysTable'] = """CREATE TABLE Tourneys ( - id INT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + id INT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), tourneyTypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), siteTourneyNo BIGINT NOT NULL, entries INT NOT NULL, @@ -283,7 +283,7 @@ class FpdbSQLQueries: ENGINE=INNODB""" elif(self.dbname == 'PostgreSQL'): self.query['createTourneysTable'] = """CREATE TABLE Tourneys ( - id SERIAL UNIQUE, PRIMARY KEY (id), + id SERIAL, PRIMARY KEY (id), tourneyTypeId INT, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), siteTourneyNo BIGINT, entries INT, @@ -300,7 +300,7 @@ class FpdbSQLQueries: if(self.dbname == 'MySQL InnoDB'): self.query['createHandsPlayersTable'] = """CREATE TABLE HandsPlayers ( - id BIGINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), handId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handId) REFERENCES Hands(id), playerId INT UNSIGNED NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id), startCash INT NOT NULL, @@ -332,7 +332,7 @@ class FpdbSQLQueries: ENGINE=INNODB""" elif(self.dbname == 'PostgreSQL'): self.query['createHandsPlayersTable'] = """CREATE TABLE HandsPlayers ( - id BIGSERIAL UNIQUE, PRIMARY KEY (id), + id BIGSERIAL, PRIMARY KEY (id), handId BIGINT, FOREIGN KEY (handId) REFERENCES Hands(id), playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id), startCash INT, @@ -370,7 +370,7 @@ class FpdbSQLQueries: if(self.dbname == 'MySQL InnoDB'): self.query['createTourneysPlayersTable'] = """CREATE TABLE TourneysPlayers ( - id BIGINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), tourneyId INT UNSIGNED NOT NULL, FOREIGN KEY (tourneyId) REFERENCES Tourneys(id), playerId INT UNSIGNED NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id), payinAmount INT NOT NULL, @@ -381,7 +381,7 @@ class FpdbSQLQueries: ENGINE=INNODB""" elif(self.dbname == 'PostgreSQL'): self.query['createTourneysPlayersTable'] = """CREATE TABLE TourneysPlayers ( - id BIGSERIAL UNIQUE, PRIMARY KEY (id), + id BIGSERIAL, PRIMARY KEY (id), tourneyId INT, FOREIGN KEY (tourneyId) REFERENCES Tourneys(id), playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id), payinAmount INT, @@ -399,7 +399,7 @@ class FpdbSQLQueries: if(self.dbname == 'MySQL InnoDB'): self.query['createHandsActionsTable'] = """CREATE TABLE HandsActions ( - id BIGINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), handPlayerId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handPlayerId) REFERENCES HandsPlayers(id), street SMALLINT NOT NULL, actionNo SMALLINT NOT NULL, @@ -411,7 +411,7 @@ class FpdbSQLQueries: ENGINE=INNODB""" elif(self.dbname == 'PostgreSQL'): self.query['createHandsActionsTable'] = """CREATE TABLE HandsActions ( - id BIGSERIAL UNIQUE, PRIMARY KEY (id), + id BIGSERIAL, PRIMARY KEY (id), handPlayerId BIGINT, FOREIGN KEY (handPlayerId) REFERENCES HandsPlayers(id), street SMALLINT, actionNo SMALLINT, @@ -430,7 +430,7 @@ class FpdbSQLQueries: if(self.dbname == 'MySQL InnoDB'): self.query['createHudCacheTable'] = """CREATE TABLE HudCache ( - id BIGINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), gametypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), playerId INT UNSIGNED NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id), activeSeats SMALLINT NOT NULL, @@ -503,7 +503,7 @@ class FpdbSQLQueries: ENGINE=INNODB""" elif(self.dbname == 'PostgreSQL'): self.query['createHudCacheTable'] = """CREATE TABLE HudCache ( - id BIGSERIAL UNIQUE, PRIMARY KEY (id), + id BIGSERIAL, PRIMARY KEY (id), gametypeId INT, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id), activeSeats SMALLINT, From c8d12cfe612b8c5a53692a358c025a56c08b1ba6 Mon Sep 17 00:00:00 2001 From: steffen123 Date: Wed, 10 Dec 2008 03:55:12 +0000 Subject: [PATCH 31/32] p144 - updated table design after comments on draw tables --- create-release.sh | 4 ++-- docs/tabledesign.html | 20 +++++++++++++++----- pyfpdb/CliFpdb.py | 0 pyfpdb/Configuration.py | 0 pyfpdb/HUD_main.py | 0 pyfpdb/fpdb.py | 0 6 files changed, 17 insertions(+), 7 deletions(-) mode change 100644 => 100755 pyfpdb/CliFpdb.py mode change 100644 => 100755 pyfpdb/Configuration.py mode change 100644 => 100755 pyfpdb/HUD_main.py mode change 100644 => 100755 pyfpdb/fpdb.py diff --git a/create-release.sh b/create-release.sh index bdc4333a..9f28a7ac 100755 --- a/create-release.sh +++ b/create-release.sh @@ -29,8 +29,8 @@ cp -R regression-test fpdb-$1/ cp -R utils fpdb-$1/ cd fpdb-$1 -zip -r ../../fpdb-1.0_$1.zip * -tar -cf - * | bzip2 >> ../../fpdb-1.0_$1.tar.bz2 +zip -r releases/fpdb-1.0_$1.zip * +tar -cf - * | bzip2 >> releases/fpdb-1.0_$1.tar.bz2 cd .. rm -r fpdb-$1 diff --git a/docs/tabledesign.html b/docs/tabledesign.html index ce39d4bc..e148b9cf 100644 --- a/docs/tabledesign.html +++ b/docs/tabledesign.html @@ -312,11 +312,10 @@ The program itself is licensed under AGPLv3, see agpl-3.0.txt


Table HandsPlayers

-

cardX: can be 1 through 20, one for each card. In holdem only 1-2 of these are used, in omaha 1-4, in stud/razz 1-7, in single draw games 1-10 is used and in badugi 1-16 (4*4) is used.

-

For the draw games: the first 5 (badugi: 4) cards are the initial cards, the next 5 (badugi: 4) are after the first draw. If a player keeps some cards then those cards' spaces are filled with "k", short for "kept".
-Example 1: If a player gets 2-6 spades for his first five cards and decides to throw away the 4 and then gets a 7 of spades then the first 10 fields of cardXValue would be as follows: 2, 3, 4, 5, 6, k, k, 7, k, k
-Example 2: If a player gets 2, 3, 5, 8, J of spades for his first five cards and decides to throw away the 2 and the 3 and then gets a Q and K of spades then the first 10 fields of cardXValue would be as follows: 2, 3, 5, 8, J, Q, K, k, k, k
-Note that it will k in the space of which card was there previously, so in example 2 where the player kept the last 3 cards, the last 3 fields of the first draw (ie. card8-10Value) are replaced with k.

+

cardX: can be 1 through 20, one for each card. In holdem only 1-2 of these are used, in omaha 1-4, in stud/razz 1-7, in single draw 1-10, in tripple draw all 20 and in badugi 1-16 (4*4).

+

For the draw games: the first 5 (badugi: 4) cards are the initial cards, the next 5 (badugi: 4) are after the first draw, etc.
+Example 1: If a player gets 2-6 spades for his first five cards and decides to throw away the 4 and then gets a 7 of spades then the first 10 fields of cardXValue would be as follows: 2, 3, 4, 5, 6, 2, 3, 5, 6, 7
+Example 2: If a player gets 2, 3, 5, 8, J of spades for his first five cards and decides to throw away the 2 and the 3 and then gets a Q and K of spades then the first 10 fields of cardXValue would be as follows: 2, 3, 5, 8, J, 5, 8, J, Q, K.

I did not separate this into an extra table because I felt the lost space is not sufficiently large. Also the benefit for searching is far less relevant.

@@ -370,6 +369,17 @@ Note that it will k in the space of which card was there previously, so in examp + + + + + + + + + + diff --git a/pyfpdb/CliFpdb.py b/pyfpdb/CliFpdb.py old mode 100644 new mode 100755 diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py old mode 100644 new mode 100755 diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py old mode 100644 new mode 100755 diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py old mode 100644 new mode 100755 From 9ca0574d7854ec164c27ec0c36500e750d5bc0b0 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 10 Dec 2008 21:21:43 +0900 Subject: [PATCH 32/32] Really basic check that username exists --- pyfpdb/GuiPlayerStats.py | 65 ++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 7d689228..a4baea41 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -46,41 +46,42 @@ class GuiPlayerStats (threading.Thread): result = self.cursor.execute(self.sql.query['getPlayerId'], self.heroes[self.activesite]) result = self.db.cursor.fetchall() - pid = result[0][0] - tmp = tmp.replace("", "(" + str(pid) + ")") - self.cursor.execute(tmp) - result = self.db.cursor.fetchall() - cols = 18 - rows = len(result)+1 # +1 for title row - self.stats_table = gtk.Table(rows, cols, False) - self.stats_table.set_col_spacings(4) - self.stats_table.show() - vbox.add(self.stats_table) + if not result == (): + pid = result[0][0] + tmp = tmp.replace("", "(" + str(pid) + ")") + self.cursor.execute(tmp) + result = self.db.cursor.fetchall() + cols = 18 + rows = len(result)+1 # +1 for title row + self.stats_table = gtk.Table(rows, cols, False) + self.stats_table.set_col_spacings(4) + self.stats_table.show() + vbox.add(self.stats_table) - # Create header row - titles = ("GID", "base", "Style", "Site", "$BB", "Hands", "VPIP", "PFR", "saw_f", "sawsd", "wtsdwsf", "wmsd", "FlAFq", "TuAFq", "RvAFq", "PFAFq", "Net($)", "BB/100") + # Create header row + titles = ("GID", "base", "Style", "Site", "$BB", "Hands", "VPIP", "PFR", "saw_f", "sawsd", "wtsdwsf", "wmsd", "FlAFq", "TuAFq", "RvAFq", "PFAFq", "Net($)", "BB/100") - col = 0 - row = 0 - for t in titles: - l = gtk.Label(titles[col]) - l.show() - self.stats_table.attach(l, col, col+1, row, row+1) - col +=1 + col = 0 + row = 0 + for t in titles: + l = gtk.Label(titles[col]) + l.show() + self.stats_table.attach(l, col, col+1, row, row+1) + col +=1 - for row in range(rows-1): - for col in range(cols): - if(row%2 == 0): - bgcolor = "white" - else: - bgcolor = "lightgrey" - eb = gtk.EventBox() - eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) - l = gtk.Label(result[row-1][col]) - eb.add(l) - self.stats_table.attach(eb, col, col+1, row+1, row+2) - l.show() - eb.show() + for row in range(rows-1): + for col in range(cols): + if(row%2 == 0): + bgcolor = "white" + else: + bgcolor = "lightgrey" + eb = gtk.EventBox() + eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) + l = gtk.Label(result[row-1][col]) + eb.add(l) + self.stats_table.attach(eb, col, col+1, row+1, row+2) + l.show() + eb.show() def fillPlayerFrame(self, vbox):

char(1)

h=hearts, s=spades, d=diamonds, c=clubs, unknown/no card=x

cardXDiscarded

boolean

Whether the card was discarded (this only applies to draw games, X can be 1 through 15 since the final cards can obviously not be discarded).

DrawnX

smallint

X can be 1 through 3.
+ This field denotes how many cards the player has drawn on each draw.

winnings

int