diff --git a/docs/readme-dev.txt b/docs/readme-dev.txt index 25e013bd..c8b5cd3f 100644 --- a/docs/readme-dev.txt +++ b/docs/readme-dev.txt @@ -1,67 +1,67 @@ -Hi, -This document is to serve as a little overview (later: full technical doc) for current and prospective developers with: -a) introduction into the code structure -b) organisational/legal things - -What to do? -=========== -- Anything you want. -- The most useful (because it's the most boring) would be to update print_hand.py, update the expected files (testdata/*.found.txt) and create more .found.txt to ensure import processing is running correctly. -- There's a list of various bugs, deficiencies and important missing features in known_bugs_and_planned_features.txt. -- In the main GUI there's various menu points marked with todo - all of these will have to be done eventually. - -If you want to take a look at coding-style.txt. -Ideally use git (see git-instructions.txt for some commands) and let me know where to pull from, alternatively feel free to send patches or even just changed file in whatever code layout or naming convention you like best. I will, of course, still give you full credit. - -Contact/Communication -===================== -If you start working on something please open a bug or feature request at sf to avoid someone else from doing the same -Please see readme-overview - -Dependencies -============ -Please let me know before you add any new dependencies and ensure that they are source-compatible between *nix and Windows - -Code/File/Class Structure -========================= -Basically the code runs like this - -fpdb.py -> bulk importer tab (import_threaded.py) -> fpdb_import.py -> fpdb_parse_logic.py -> fpdb_save_to_db.py -or -fpdb.py -> table viewer tab (table_viewer.py) (todo: -> libTableViewer) - -All files call the simple methods that I just collected in fpdb_simple.py, to abstract the other files off the nitty gritty details as I was learning python. -I'm currently working on (amongst other things) integrating everything into the fpdb.py GUI with a view to allow easy creation of a CLI client, too. - -Also see filelist.txt. - -How to Commit -============= -Please make sure you read and accept the copyright policy as stated in this file. Then see git-instructions.txt. Don't get me wrong, I hate all this legalese, but unfortunately it's kinda necessary. - -Copyright/Licensing -=================== -Copyright by default is handled on a per-file basis. If you send in a patch or make a commit to an existing file it is done on the understanding that you transfer all rights (as far as legally possible in your jurisdiction) to the current copyright holder of that file, unless otherwise stated. If you create a new file please ensure to include a copyright and license statement. - -The licenses used by this project are the AGPL3 for code and FDL1.2 for documentation. See readme-overview.txt for reasons and if you wish to use fpdb with different licensing. - -Preferred File Formats -====================== -Preferred: Where possible simple text-based formats, e.g. plain text (with Unix end of line char) or (X)HTML. Preferred picture format is PNG. IE-compability for HTML files is optional as IE was never meant to be a real web browser, if it were they would've implemented web standards. - -Also good: Other free and open formats, e.g. ODF. - -Not good: Any format that doesn't have full documentation freely and publicly available with a proper license for anyone to implement it. Sadly, Microsoft has chosen not fulfil these requirements for ISO MS OOXML to become a truly open standard. - -License (of this file) -======= -Trademarks of third parties have been used under Fair Use or similar laws. - -Copyright 2008 Steffen Jobbagy-Felso -Permission is granted to copy, distribute and/or modify this -document under the terms of the GNU Free Documentation License, -Version 1.2 as published by the Free Software Foundation; with -no Invariant Sections, no Front-Cover Texts, and with no Back-Cover -Texts. A copy of the license can be found in fdl-1.2.txt - -The program itself is licensed under AGPLv3, see agpl-3.0.txt +Hi, +This document is to serve as a little overview (later: full technical doc) for current and prospective developers with: +a) introduction into the code structure +b) organisational/legal things + +What to do? +=========== +- Anything you want. +- The most useful (because it's the most boring) would be to update print_hand.py, update the expected files (testdata/*.found.txt) and create more .found.txt to ensure import processing is running correctly. +- There's a list of various bugs, deficiencies and important missing features in known_bugs_and_planned_features.txt. +- In the main GUI there's various menu points marked with todo - all of these will have to be done eventually. + +If you want to take a look at coding-style.txt. +Ideally use git (see git-instructions.txt for some commands) and let me know where to pull from, alternatively feel free to send patches or even just changed file in whatever code layout or naming convention you like best. I will, of course, still give you full credit. + +Contact/Communication +===================== +If you start working on something please open a bug or feature request at sf to avoid someone else from doing the same +Please see readme-overview + +Dependencies +============ +Please let me know before you add any new dependencies and ensure that they are source-compatible between *nix and Windows + +Code/File/Class Structure +========================= +Basically the code runs like this + +fpdb.py -> bulk importer tab (import_threaded.py) -> fpdb_import.py -> fpdb_parse_logic.py -> fpdb_save_to_db.py +or +fpdb.py -> table viewer tab (table_viewer.py) (todo: -> libTableViewer) + +All files call the simple methods that I just collected in fpdb_simple.py, to abstract the other files off the nitty gritty details as I was learning python. +I'm currently working on (amongst other things) integrating everything into the fpdb.py GUI with a view to allow easy creation of a CLI client, too. + +Also see filelist.txt. + +How to Commit +============= +Please make sure you read and accept the copyright policy as stated in this file. Then see git-instructions.txt. Don't get me wrong, I hate all this legalese, but unfortunately it's kinda necessary. + +Copyright/Licensing +=================== +Copyright by default is handled on a per-file basis. If you send in a patch or make a commit to an existing file it is done on the understanding that you transfer all rights (as far as legally possible in your jurisdiction) to the current copyright holder of that file, unless otherwise stated. If you create a new file please ensure to include a copyright and license statement. + +The licenses used by this project are the AGPL3 for code and FDL1.2 for documentation. See readme-overview.txt for reasons and if you wish to use fpdb with different licensing. + +Preferred File Formats +====================== +Preferred: Where possible simple text-based formats, e.g. plain text (with Unix end of line char) or (X)HTML. Preferred picture format is PNG. IE-compability for HTML files is optional as IE was never meant to be a real web browser, if it were they would've implemented web standards. + +Also good: Other free and open formats, e.g. ODF. + +Not good: Any format that doesn't have full documentation freely and publicly available with a proper license for anyone to implement it. Sadly, Microsoft has chosen not fulfil these requirements for ISO MS OOXML to become a truly open standard. + +License (of this file) +======= +Trademarks of third parties have been used under Fair Use or similar laws. + +Copyright 2008 Steffen Jobbagy-Felso +Permission is granted to copy, distribute and/or modify this +document under the terms of the GNU Free Documentation License, +Version 1.2 as published by the Free Software Foundation; with +no Invariant Sections, no Front-Cover Texts, and with no Back-Cover +Texts. A copy of the license can be found in fdl-1.2.txt + +The program itself is licensed under AGPLv3, see agpl-3.0.txt diff --git a/ignore-me_perl6/RunFpdbCLI.perl6 b/ignore-me_perl6/RunFpdbCLI.perl6 index 90401cdf..dbbad9a7 100644 --- a/ignore-me_perl6/RunFpdbCLI.perl6 +++ b/ignore-me_perl6/RunFpdbCLI.perl6 @@ -1,29 +1,29 @@ -#!/usr/bin/pugs - -#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. - -use v6; -#use strict; -use LibFpdbImport; -use LibFpdbShared; - - -my Database $db .= new(:backend, :host, :database, :user, :password); -#todo: below doesnt work -my Importer $imp .= new(:db($db), :filename); -#perlbug?: adding another named argument that isnt listed in the constructor gave very weird error. -say $imp; - +#!/usr/bin/pugs + +#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. + +use v6; +#use strict; +use LibFpdbImport; +use LibFpdbShared; + + +my Database $db .= new(:backend, :host, :database, :user, :password); +#todo: below doesnt work +my Importer $imp .= new(:db($db), :filename); +#perlbug?: adding another named argument that isnt listed in the constructor gave very weird error. +say $imp; + diff --git a/pyfpdb/CarbonToFpdb.py b/pyfpdb/CarbonToFpdb.py new file mode 100644 index 00000000..cf9fc8d3 --- /dev/null +++ b/pyfpdb/CarbonToFpdb.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python +# Copyright 2008, Carl Gherardi + +# +# 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 Configuration +import traceback +import sys +import re +import xml.dom.minidom +from xml.dom.minidom import Node +from HandHistoryConverter import HandHistoryConverter + +# Carbon format looks like: + +# 1) +# 2) +# 3) +# +# ... +# 4) +# +# +# 5) +# +# 6) +# +# .... +# + +# The full sequence for a NHLE cash game is: +# BLINDS, PREFLOP, POSTFLOP, POSTTURN, POSTRIVER, SHOWDOWN, END_OF_GAME +# This sequence can be terminated after BLINDS at any time by END_OF_FOLDED_GAME + + +class CarbonPoker(HandHistoryConverter): + def __init__(self, config, filename): + print "Initialising Carbon Poker converter class" + HandHistoryConverter.__init__(self, config, filename, "Carbon") # Call super class init + self.setFileType("xml") + + def readSupportedGames(self): + pass + def determineGameType(self): + gametype = [] + desc_node = self.doc.getElementsByTagName("description") + #TODO: no examples of non ring type yet + gametype = gametype + ["ring"] + type = desc_node[0].getAttribute("type") + if(type == "Holdem"): + gametype = gametype + ["hold"] + else: + print "Unknown gametype: '%s'" % (type) + + stakes = desc_node[0].getAttribute("stakes") + #TODO: no examples of anything except nlhe + m = re.match('(?PNo Limit)\s\(\$?(?P[.0-9]+)/\$?(?P[.0-9]+)\)', stakes) + + if(m.group('LIMIT') == "No Limit"): + gametype = gametype + ["nl"] + + gametype = gametype + [self.float2int(m.group('SB'))] + gametype = gametype + [self.float2int(m.group('BB'))] + + return gametype + + def readPlayerStacks(self): + pass + def readBlinds(self): + pass + def readAction(self): + pass + + # Override read function as xml.minidom barfs on the Carbon layout + # This is pretty dodgy + def readFile(self, filename): + print "Carbon: Reading file: '%s'" %(filename) + infile=open(filename, "rU") + self.obs = infile.read() + infile.close() + self.obs = "\n" + self.obs + "" + try: + doc = xml.dom.minidom.parseString(self.obs) + self.doc = doc + except: + traceback.print_exc(file=sys.stderr) + +if __name__ == "__main__": + c = Configuration.Config() + e = CarbonPoker(c, "regression-test-files/carbon-poker/Niagara Falls (15245216).xml") + e.processFile() + print str(e) + diff --git a/pyfpdb/CliFpdb.py b/pyfpdb/CliFpdb.py index 47649728..4e2a4361 100644 --- a/pyfpdb/CliFpdb.py +++ b/pyfpdb/CliFpdb.py @@ -53,7 +53,7 @@ if __name__ == "__main__": (options, sys.argv) = parser.parse_args() - settings={'imp-callFpdbHud':False, 'db-backend':2} + settings={'callFpdbHud':False, 'db-backend':2} settings['db-host']=options.server settings['db-user']=options.user settings['db-password']=options.password diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 3b5c6d70..3bcaaa91 100644 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -1,641 +1,640 @@ -#!/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) +#!/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") + stat.hudcolor = stat_node.getAttribute("hudcolor") + + 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.imp.callFpdbHud + imp['interval'] = self.imp.interval + imp['hhArchiveBase'] = self.imp.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 -----------" + 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 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/Database.py b/pyfpdb/Database.py index 4039b256..95abdd71 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -142,12 +142,27 @@ class Database: cards[s_dict['seat_number']] = s_dict return (cards) - def get_stats_from_hand(self, hand, player_id = False): + def get_action_from_hand(self, hand_no): + action = [ [], [], [], [], [] ] + c = self.connection.cursor() + c.execute(self.sql.query['get_action_from_hand'], (hand_no)) + for row in c.fetchall(): + street = row[0] + act = row[1:] + action[street].append(act) + return action + + def get_stats_from_hand(self, hand, aggregate = False): c = self.connection.cursor() - if not player_id: player_id = "%" + if aggregate: + query = 'get_stats_from_hand' + subs = (hand, hand) + else: + query = 'get_stats_from_hand_aggregated' + subs = (hand, hand, hand) + # get the players in the hand and their seats -# c.execute(self.sql.query['get_players_from_hand'], (hand, player_id)) c.execute(self.sql.query['get_players_from_hand'], (hand, )) names = {} seats = {} @@ -156,8 +171,7 @@ class Database: seats[row[0]] = row[1] # now get the stats -# c.execute(self.sql.query['get_stats_from_hand'], (hand, hand, player_id)) - c.execute(self.sql.query['get_stats_from_hand'], (hand, hand)) + c.execute(self.sql.query[query], subs) colnames = [desc[0] for desc in c.description] stat_dict = {} for row in c.fetchall(): diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py new file mode 100755 index 00000000..d60211b6 --- /dev/null +++ b/pyfpdb/EverleafToFpdb.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python +# Copyright 2008, Carl Gherardi +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +######################################################################## + +import sys +import Configuration +from HandHistoryConverter import * + +# Everleaf HH format + +# Everleaf Gaming Game #55208539 +# ***** Hand history for game #55208539 ***** +# Blinds $0.50/$1 NL Hold'em - 2008/09/01 - 13:35:01 +# Table Speed Kuala +# Seat 1 is the button +# Total number of players: 9 +# Seat 1: BadBeatBox ( $ 98.97 USD ) +# Seat 3: EricBlade ( $ 73.96 USD ) +# Seat 4: randy888 ( $ 196.50 USD ) +# Seat 5: BaronSengir ( $ 182.80 USD ) +# Seat 6: dogge ( $ 186.06 USD ) +# Seat 7: wings ( $ 50 USD ) +# Seat 8: schoffeltje ( $ 282.05 USD ) +# Seat 9: harrydebeng ( $ 109.45 USD ) +# Seat 10: smaragdar ( $ 96.50 USD ) +# EricBlade: posts small blind [$ 0.50 USD] +# randy888: posts big blind [$ 1 USD] +# wings: posts big blind [$ 1 USD] +# ** Dealing down cards ** +# Dealt to EricBlade [ qc, 3c ] +# BaronSengir folds +# dogge folds +# wings raises [$ 2.50 USD] +# schoffeltje folds +# harrydebeng calls [$ 3.50 USD] +# smaragdar raises [$ 15.50 USD] +# BadBeatBox folds +# EricBlade folds +# randy888 folds +# wings calls [$ 12 USD] +# harrydebeng folds +# ** Dealing Flop ** [ qs, 3d, 8h ] +# wings: bets [$ 34.50 USD] +# smaragdar calls [$ 34.50 USD] +# ** Dealing Turn ** [ 2d ] +# ** Dealing River ** [ 6c ] +# dogge shows [ 9h, 9c ]a pair of nines +# spicybum shows [ 5d, 6d ]a straight, eight high +# harrydebeng does not show cards +# smaragdar wins $ 102 USD from main pot with a pair of aces [ ad, ah, qs, 8h, 6c ] + +class Everleaf(HandHistoryConverter): + def __init__(self, config, file): + print "Initialising Everleaf converter class" + HandHistoryConverter.__init__(self, config, file, "Everleaf") # Call super class init. + self.sitename = "Everleaf" + self.setFileType("text") + self.rexx.setGameInfoRegex('.*Blinds \$?(?P[.0-9]+)/\$?(?P[.0-9]+)') + self.rexx.setSplitHandRegex('\n\n\n\n') + self.rexx.setHandInfoRegex('.*#(?P[0-9]+)\n.*\nBlinds \$?(?P[.0-9]+)/\$?(?P[.0-9]+) (?P.*) - (?P[0-9]+)/(?P[0-9]+)/(?P[0-9]+) - (?P
[0-9]+):(?P[0-9]+):(?P[0-9]+)\nTable (?P[ a-zA-Z]+)\nSeat (?P