Merge git://git.assembla.com/free_poker_tools

This commit is contained in:
steffen123 2008-11-07 00:00:00 +00:00
commit 93b6f9ddaa
12 changed files with 471 additions and 328 deletions

View File

@ -53,6 +53,10 @@ class Site:
self.site_path = node.getAttribute("site_path") self.site_path = node.getAttribute("site_path")
self.HH_path = node.getAttribute("HH_path") self.HH_path = node.getAttribute("HH_path")
self.decoder = node.getAttribute("decoder") 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 = {} self.layout = {}
for layout_node in node.getElementsByTagName('layout'): for layout_node in node.getElementsByTagName('layout'):
@ -74,7 +78,7 @@ class Site:
if key == 'layout': continue if key == 'layout': continue
value = getattr(self, key) value = getattr(self, key)
if callable(value): continue if callable(value): continue
temp = temp + ' ' + key + " = " + value + "\n" temp = temp + ' ' + key + " = " + str(value) + "\n"
for layout in self.layout: for layout in self.layout:
temp = temp + "%s" % self.layout[layout] temp = temp + "%s" % self.layout[layout]
@ -105,6 +109,8 @@ class Game:
stat.tip = stat_node.getAttribute("tip") stat.tip = stat_node.getAttribute("tip")
stat.click = stat_node.getAttribute("click") stat.click = stat_node.getAttribute("click")
stat.popup = stat_node.getAttribute("popup") stat.popup = stat_node.getAttribute("popup")
stat.hudprefix = stat_node.getAttribute("hudprefix")
stat.hudsuffix = stat_node.getAttribute("hudsuffix")
self.stats[stat.stat_name] = stat self.stats[stat.stat_name] = stat
@ -193,30 +199,28 @@ class Config:
# "file" is a path to an xml file with the fpdb/HUD configuration # "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 # 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 file == None: # configuration file path has been passed
if not os.path.exists(file): if not os.path.exists(file):
print "Configuration file %s not found. Using defaults." % (file) print "Configuration file %s not found. Using defaults." % (file)
sys.stderr.write("Configuration file %s not found. Using defaults." % (file)) sys.stderr.write("Configuration file %s not found. Using defaults." % (file))
file = None file = None
# if "file" is invalid or None, we look for a HUD_config in the cwd
if file == None: # configuration file path not passed or invalid if file == None: # configuration file path not passed or invalid
if os.path.exists('HUD_config.xml'): # there is a HUD_config in the cwd file = self.find_config() #Look for a config file in the normal places
file = 'HUD_config.xml' # so we use it
else: # no HUD_config in the cwd, look where it should be in the first place if file == None: # no config file in the normal places
# find the path to the default HUD_config for the current os file = self.find_example_config() #Look for an example file to edit
if os.name == 'posix': if not file == None:
config_path = os.path.join(os.path.expanduser("~"), '.fpdb', 'HUD_config.xml') pass
elif os.name == 'nt':
config_path = os.path.join(os.environ["APPDATA"], 'fpdb', 'HUD_config.xml') if file == None: # that didn't work either, just die
else: config_path = False print "No HUD_config_xml found. Exiting"
sys.stderr.write("No HUD_config_xml found. Exiting")
if config_path and os.path.exists(config_path): sys.exit()
file = config_path
else: # Parse even if there was no real config file found and we are using the example
print "No HUD_config_xml found. Exiting" # If using the example, we'll edit it later
sys.stderr.write("No HUD_config_xml found. Exiting")
sys.exit()
try: try:
print "Reading configuration file %s\n" % (file) print "Reading configuration file %s\n" % (file)
doc = xml.dom.minidom.parse(file) doc = xml.dom.minidom.parse(file)
@ -268,11 +272,86 @@ class Config:
tv = Tv(node = tv_node) tv = Tv(node = tv_node)
self.tv = tv 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): def get_site_node(self, site):
for site_node in self.doc.getElementsByTagName("site"): for site_node in self.doc.getElementsByTagName("site"):
if site_node.getAttribute("site_name") == site: if site_node.getAttribute("site_name") == site:
return site_node 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): def get_layout_node(self, site_node, layout):
for layout_node in site_node.getElementsByTagName("layout"): for layout_node in site_node.getElementsByTagName("layout"):
if layout_node.getAttribute("max") == None: if layout_node.getAttribute("max") == None:
@ -326,6 +405,23 @@ class Config:
pass pass
return db 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): def get_tv_parameters(self):
tv = {} tv = {}
try: try:
@ -358,6 +454,78 @@ class Config:
paths['bulkImport-defaultPath'] = "default" paths['bulkImport-defaultPath'] = "default"
return paths 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__": if __name__== "__main__":
c = Config() c = Config()
@ -389,17 +557,22 @@ if __name__== "__main__":
print "----------- END MUCKED WINDOW FORMATS -----------" print "----------- END MUCKED WINDOW FORMATS -----------"
print "\n----------- IMPORT -----------" print "\n----------- IMPORT -----------"
print c.imp # print c.imp
print "----------- END IMPORT -----------" print "----------- END IMPORT -----------"
print "\n----------- TABLE VIEW -----------" print "\n----------- TABLE VIEW -----------"
print c.tv # print c.tv
print "----------- END TABLE VIEW -----------" print "----------- END TABLE VIEW -----------"
c.edit_layout("PokerStars", 6, locations=( (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6) )) c.edit_layout("PokerStars", 6, locations=( (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6) ))
c.save(file="testout.xml") c.save(file="testout.xml")
print "db = ", c.get_db_parameters() print "db = ", c.get_db_parameters()
print "tv = ", c.get_tv_parameters() # print "tv = ", c.get_tv_parameters()
print "imp = ", c.get_import_parameters() # print "imp = ", c.get_import_parameters()
print "paths = ", c.get_default_paths("PokerStars") 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)

View File

@ -59,6 +59,10 @@ class Database:
user = c.supported_databases[db_name].db_user, user = c.supported_databases[db_name].db_user,
passwd = c.supported_databases[db_name].db_pass, passwd = c.supported_databases[db_name].db_pass,
db = c.supported_databases[db_name].db_name) db = c.supported_databases[db_name].db_name)
cur_iso = self.connection.cursor()
cur_iso.execute('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED')
cur_iso.close()
except: except:
print "Error opening database connection %s. See error log file." % (file) print "Error opening database connection %s. See error log file." % (file)
traceback.print_exc(file=sys.stderr) traceback.print_exc(file=sys.stderr)

View File

@ -110,8 +110,8 @@ class GuiAutoImport (threading.Thread):
self.tiltpath=self.tiltDirPath.get_text() self.tiltpath=self.tiltDirPath.get_text()
# Add directory to importer object. # Add directory to importer object.
self.importer.addImportDirectory(self.starspath, True) self.importer.addImportDirectory(self.starspath, True, "PokerStars", "passthrough")
self.importer.addImportDirectory(self.tiltpath, True) self.importer.addImportDirectory(self.tiltpath, True, "FullTilt", "passthrough")
self.do_import() self.do_import()
interval=int(self.intervalEntry.get_text()) interval=int(self.intervalEntry.get_text())

View File

@ -2,7 +2,7 @@
<FreePokerToolsConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FreePokerToolsConfig.xsd"> <FreePokerToolsConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FreePokerToolsConfig.xsd">
<supported_sites> <supported_sites>
<site site_name="PokerStars" table_finder="PokerStars" screen_name="DO NOT NEED THIS YET" site_path="~/.wine/drive_c/Program Files/PokerStars/" HH_path="~/.wine/drive_c/Program Files/PokerStars/HandHistory/abc/" decoder="pokerstars_decode_table"> <site enabled="True" site_name="PokerStars" table_finder="PokerStars.exe" screen_name="DO NOT NEED THIS YET" site_path="~/.wine/drive_c/Program Files/PokerStars/" HH_path="~/.wine/drive_c/Program Files/PokerStars/HandHistory/abc/" decoder="pokerstars_decode_table" converter="passthrough" supported_games="holdem,razz,omahahi,omahahilo,studhi,studhilo">
<layout max="8" width="792" height="546" fav_seat="0"> <layout max="8" width="792" height="546" fav_seat="0">
<location seat="1" x="684" y="61"> </location> <location seat="1" x="684" y="61"> </location>
<location seat="2" x="689" y="239"> </location> <location seat="2" x="689" y="239"> </location>
@ -49,7 +49,7 @@
<location seat="2" x="10" y="288"> </location> <location seat="2" x="10" y="288"> </location>
</layout> </layout>
</site> </site>
<site screen_name="PokerMonk" site_name="Full Tilt" table_finder="FullTiltPoker.exe" decoder="fulltilt_decode_table"> <site enabled="True" site_name="Full Tilt" table_finder="FullTiltPoker.exe" screen_name="DO NOT NEED THIS YET" site_path="~/.wine/drive_c/Program Files/Full Tilt Poker/" HH_path="~/.wine/drive_c/Program Files/Full Tilt Poker/HandHistory/abc/" decoder="fulltilt_decode_table" converter="passthrough" supported_games="holdem,razz,omahahi,omahahilo,studhi,studhilo">
<layout fav_seat="0" height="547" max="8" width="794"> <layout fav_seat="0" height="547" max="8" width="794">
<location seat="1" x="640" y="64"> </location> <location seat="1" x="640" y="64"> </location>
<location seat="2" x="650" y="230"> </location> <location seat="2" x="650" y="230"> </location>
@ -84,6 +84,32 @@
<location seat="9" x="70" y="53"> </location> <location seat="9" x="70" y="53"> </location>
</layout> </layout>
</site> </site>
<site enabled="False" site_name="Everleaf" table_finder="Poker.exe" screen_name="DO NOT NEED THIS YET" site_path="" HH_path="" decoder="Unknown" converter="EverleafToFpdb" supported_games="holdem,razz,omahahi,omahahilo,studhi" fgcolor="#48D1CC" bgcolor="#000000">
<layout fav_seat="0" height="546" max="6" width="792">
<location seat="1" x="581" y="109"> </location>
<location seat="2" x="605" y="287"> </location>
<location seat="3" x="544" y="423"> </location>
<location seat="4" x="80" y="393"> </location>
<location seat="5" x="5" y="284"> </location>
<location seat="6" x="38" y="108"> </location>
</layout>
<layout fav_seat="0" height="546" max="10" width="792">
<location seat="1" x="473" y="78"> </location>
<location seat="2" x="650" y="93"> </location>
<location seat="3" x="670" y="219"> </location>
<location seat="4" x="633" y="358"> </location>
<location seat="5" x="437" y="393"> </location>
<location seat="6" x="249" y="396"> </location>
<location seat="7" x="42" y="357"> </location>
<location seat="8" x="8" y="218"> </location>
<location seat="9" x="35" y="89"> </location>
<location seat="10" x="217" y="78"> </location>
</layout>
<layout fav_seat="0" height="546" max="2" width="792">
<location seat="1" x="651" y="288"> </location>
<location seat="2" x="10" y="288"> </location>
</layout>
</site>
</supported_sites> </supported_sites>
<supported_games> <supported_games>
<game cols="3" db="fpdb" game_name="holdem" rows="2"> <game cols="3" db="fpdb" game_name="holdem" rows="2">

View File

@ -29,7 +29,6 @@ Main for FreePokerTools HUD.
# to do no hud window for hero # to do no hud window for hero
# to do things to add to config.xml # to do things to add to config.xml
# to do font and size # to do font and size
# to do bg and fg color
# to do opacity # to do opacity
# Standard Library modules # Standard Library modules
@ -90,6 +89,7 @@ def update_HUD(new_hand_id, table_name, config, stat_dict):
def read_stdin(): # This is the thread function def read_stdin(): # This is the thread function
global hud_dict global hud_dict
db_connection = Database.Database(config, db_name, 'temp')
while True: # wait for a new hand number on stdin while True: # wait for a new hand number on stdin
new_hand_id = sys.stdin.readline() new_hand_id = sys.stdin.readline()
new_hand_id = string.rstrip(new_hand_id) new_hand_id = string.rstrip(new_hand_id)
@ -102,21 +102,19 @@ def read_stdin(): # This is the thread function
del(hud_dict[h]) del(hud_dict[h])
# connect to the db and get basic info about the new hand # connect to the db and get basic info about the new hand
db_connection = Database.Database(config, db_name, 'temp')
(table_name, max, poker_game) = db_connection.get_table_name(new_hand_id) (table_name, max, poker_game) = db_connection.get_table_name(new_hand_id)
stat_dict = db_connection.get_stats_from_hand(new_hand_id) stat_dict = db_connection.get_stats_from_hand(new_hand_id)
db_connection.close_connection()
# if a hud for this table exists, just update it # if a hud for this table exists, just update it
if hud_dict.has_key(table_name): if hud_dict.has_key(table_name):
update_HUD(new_hand_id, table_name, config, stat_dict) update_HUD(new_hand_id, table_name, config, stat_dict)
# otherwise create a new hud # otherwise create a new hud
else: else:
table_windows = Tables.discover(config) tablewindow = Tables.discover_table_by_name(config, table_name)
for t in table_windows.keys(): if tablewindow == None:
if table_windows[t].name == table_name: sys.stderr.write("table name "+table_name+" not found\n")
create_HUD(new_hand_id, table_windows[t], db_name, table_name, max, poker_game, db_connection, config, stat_dict) else:
break create_HUD(new_hand_id, tablewindow, db_name, table_name, max, poker_game, db_connection, config, stat_dict)
if __name__== "__main__": if __name__== "__main__":
sys.stderr.write("HUD_main starting\n") sys.stderr.write("HUD_main starting\n")
@ -142,3 +140,4 @@ if __name__== "__main__":
main_window.show_all() main_window.show_all()
gtk.main() gtk.main()

View File

@ -23,6 +23,7 @@ Create and manage the hud overlays.
######################################################################## ########################################################################
# Standard Library modules # Standard Library modules
import os import os
import sys
# pyGTK modules # pyGTK modules
import pygtk import pygtk
@ -34,6 +35,7 @@ import gobject
if os.name == 'nt': if os.name == 'nt':
import win32gui import win32gui
import win32con import win32con
import win32api
# FreePokerTools modules # FreePokerTools modules
import Tables # needed for testing only import Tables # needed for testing only
@ -41,7 +43,7 @@ import Configuration
import Stats import Stats
import Mucked import Mucked
import Database import Database
import HUD_main import HUD_main
class Hud: class Hud:
@ -53,27 +55,32 @@ class Hud:
self.db_name = db_name self.db_name = db_name
self.deleted = False self.deleted = False
self.stacked = True self.stacked = True
self.colors = config.get_default_colors(self.table.site)
self.stat_windows = {} self.stat_windows = {}
self.popup_windows = {} self.popup_windows = {}
self.font = pango.FontDescription("Sans 8") self.font = pango.FontDescription("Sans 8")
# Set up a main window for this this instance of the HUD # Set up a main window for this this instance of the HUD
self.main_window = gtk.Window() self.main_window = gtk.Window()
# self.window.set_decorated(0) # self.window.set_decorated(0)
self.main_window.set_gravity(gtk.gdk.GRAVITY_STATIC) self.main_window.set_gravity(gtk.gdk.GRAVITY_STATIC)
self.main_window.set_keep_above(1) self.main_window.set_title(table.name + " FPDBHUD")
self.main_window.set_title(table.name)
self.main_window.connect("destroy", self.kill_hud) self.main_window.connect("destroy", self.kill_hud)
if self.stacked: self.main_window.set_decorated(False)
self.main_window.connect("window-state-event", self.on_window_event) #self.main_window.set_transient_for(parent.get_toplevel())
self.ebox = gtk.EventBox() self.ebox = gtk.EventBox()
self.label = gtk.Label("Close this window to\nkill the HUD for\n %s\nMinimizing it hides stats." % self.label = gtk.Label("Right click to close HUD for %s\nor Save Stat Positions." % (table.name))
(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.main_window.add(self.ebox)
self.ebox.add(self.label) 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) self.main_window.move(self.table.x, self.table.y)
# A popup window for the main window # A popup window for the main window
@ -90,7 +97,14 @@ class Hud:
self.main_window.show_all() self.main_window.show_all()
# set_keep_above(1) for windows # set_keep_above(1) for windows
if os.name == 'nt': self.topify_window(self.main_window) 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): def on_button_press(self, widget, event):
if event.button == 3: if event.button == 3:
@ -98,16 +112,6 @@ class Hud:
return True return True
return False return False
def on_window_event(self, widget, event):
if self.stacked:
if event.new_window_state & gtk.gdk.WINDOW_STATE_ICONIFIED:
for sw in self.stat_windows.keys():
self.stat_windows[sw].window.iconify()
else:
for sw in self.stat_windows:
self.stat_windows[sw].window.deiconify()
def kill_hud(self, args): def kill_hud(self, args):
for k in self.stat_windows.keys(): for k in self.stat_windows.keys():
self.stat_windows[k].window.destroy() self.stat_windows[k].window.destroy()
@ -116,6 +120,7 @@ class Hud:
def save_layout(self, *args): def save_layout(self, *args):
new_layout = [] 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: for sw in self.stat_windows:
loc = self.stat_windows[sw].window.get_position() loc = self.stat_windows[sw].window.get_position()
new_loc = (loc[0] - self.table.x, loc[1] - self.table.y) new_loc = (loc[0] - self.table.x, loc[1] - self.table.y)
@ -150,10 +155,15 @@ class Hud:
# windows via calls to the Stat_Window class # windows via calls to the Stat_Window class
adj = self.adj_seats(hand, config) adj = self.adj_seats(hand, config)
loc = self.config.get_locations(self.table.site, self.max)
# create the stat windows # create the stat windows
for i in range(1, self.max + 1): for i in range(1, self.max + 1):
(x, y) = config.supported_sites[self.table.site].layout[self.max].location[adj[i]] (x, y) = loc[adj[i]]
self.stat_windows[i] = Stat_Window(game = config.supported_games[self.poker_game], 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, parent = self,
table = self.table, table = self.table,
x = x, x = x,
@ -178,11 +188,19 @@ class Hud:
def update(self, hand, config, stat_dict): def update(self, hand, config, stat_dict):
self.hand = hand # this is the last hand, so it is available later self.hand = hand # this is the last hand, so it is available later
for s in stat_dict.keys(): for s in stat_dict.keys():
self.stat_windows[stat_dict[s]['seat']].player_id = stat_dict[s]['player_id'] 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 r in range(0, config.supported_games[self.poker_game].rows):
for c in range(0, config.supported_games[self.poker_game].cols): 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]) number = Stats.do_stat(stat_dict, player = stat_dict[s]['player_id'], stat = self.stats[r][c])
self.stat_windows[stat_dict[s]['seat']].label[r][c].set_text(number[1]) 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" + \ tip = stat_dict[s]['screen_name'] + "\n" + number[5] + "\n" + \
number[3] + ", " + number[4] number[3] + ", " + number[4]
Stats.do_tip(self.stat_windows[stat_dict[s]['seat']].e_box[r][c], tip) Stats.do_tip(self.stat_windows[stat_dict[s]['seat']].e_box[r][c], tip)
@ -203,7 +221,21 @@ class Hud:
for w in tl_windows: for w in tl_windows:
if w[1] == unique_name: if w[1] == unique_name:
win32gui.SetWindowPos(w[0], win32con.HWND_TOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE|win32con.SWP_NOSIZE) #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], # notify_id = (w[0],
# 0, # 0,
# win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP, # win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP,
@ -247,7 +279,7 @@ class Stat_Window:
Popup_window(widget, self) Popup_window(widget, self)
return False return False
def double_click(self, widget, event, *args): def double_click(self, widget, event, *args):
self.toggle_decorated(widget) self.toggle_decorated(widget)
def toggle_decorated(self, widget): def toggle_decorated(self, widget):
@ -260,6 +292,11 @@ class Stat_Window:
else: else:
top.set_decorated(1) top.set_decorated(1)
top.move(x, y) 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): def __init__(self, parent, game, table, seat, x, y, player_id, font):
self.parent = parent # Hud object that this stat window belongs to self.parent = parent # Hud object that this stat window belongs to
@ -273,9 +310,10 @@ class Stat_Window:
self.window = gtk.Window() self.window = gtk.Window()
self.window.set_decorated(0) self.window.set_decorated(0)
self.window.set_gravity(gtk.gdk.GRAVITY_STATIC) self.window.set_gravity(gtk.gdk.GRAVITY_STATIC)
self.window.set_keep_above(1)
self.window.set_title("%s" % seat) self.window.set_title("%s" % seat)
self.window.set_property("skip-taskbar-hint", True) 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.grid = gtk.Table(rows = self.game.rows, columns = self.game.cols, homogeneous = False)
self.window.add(self.grid) self.window.add(self.grid)
@ -288,13 +326,23 @@ class Stat_Window:
self.label.append([]) self.label.append([])
for c in range(self.game.cols): for c in range(self.game.cols):
self.e_box[r].append( gtk.EventBox() ) 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') 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.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].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].add(self.label[r][c])
self.e_box[r][c].connect("button_press_event", self.button_press_cb) self.e_box[r][c].connect("button_press_event", self.button_press_cb)
# font = pango.FontDescription("Sans 8") # font = pango.FontDescription("Sans 8")
self.label[r][c].modify_font(font) self.label[r][c].modify_font(font)
self.window.set_opacity(parent.colors['hudopacity'])
self.window.realize self.window.realize
self.window.move(self.x, self.y) self.window.move(self.x, self.y)
self.window.show_all() self.window.show_all()
@ -316,16 +364,15 @@ class Stat_Window:
for w in tl_windows: for w in tl_windows:
if w[1] == unique_name: if w[1] == unique_name:
win32gui.SetWindowPos(w[0], win32con.HWND_TOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE|win32con.SWP_NOSIZE)
# notify_id = (w[0], #win32gui.SetWindowPos(w[0], win32con.HWND_TOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE|win32con.SWP_NOSIZE)
# 0,
# win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP, # style = win32gui.GetWindowLong(w[0], win32con.GWL_EXSTYLE)
# win32con.WM_USER+20, # style |= win32con.WS_EX_TOOLWINDOW
# 0, # style &= ~win32con.WS_EX_APPWINDOW
# '') # win32gui.SetWindowLong(w[0], win32con.GWL_EXSTYLE, style)
# win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, notify_id) win32gui.ShowWindow(w[0], win32con.SW_SHOW)
# window.set_title(real_name)
window.set_title(real_name)
def destroy(*args): # call back for terminating the main eventloop def destroy(*args): # call back for terminating the main eventloop
gtk.main_quit() gtk.main_quit()
@ -338,10 +385,11 @@ class Popup_window:
self.window = gtk.Window() self.window = gtk.Window()
self.window.set_decorated(0) self.window.set_decorated(0)
self.window.set_gravity(gtk.gdk.GRAVITY_STATIC) self.window.set_gravity(gtk.gdk.GRAVITY_STATIC)
self.window.set_keep_above(1) # self.window.set_keep_above(1)
self.window.set_title("popup") self.window.set_title("popup")
self.window.set_property("skip-taskbar-hint", True) self.window.set_property("skip-taskbar-hint", True)
self.window.set_transient_for(parent.get_toplevel()) self.window.set_transient_for(parent.get_toplevel())
self.window.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self.window.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
self.ebox = gtk.EventBox() self.ebox = gtk.EventBox()
@ -351,6 +399,14 @@ class Popup_window:
# need an event box so we can respond to clicks # need an event box so we can respond to clicks
self.window.add(self.ebox) self.window.add(self.ebox)
self.ebox.add(self.lab) 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 self.window.realize
# figure out the row, col address of the click that activated the popup # figure out the row, col address of the click that activated the popup
@ -392,6 +448,9 @@ class Popup_window:
self.lab.set_text(pu_text) self.lab.set_text(pu_text)
self.window.show_all() self.window.show_all()
self.window.set_transient_for(stat_window.main_window)
# set_keep_above(1) for windows # set_keep_above(1) for windows
if os.name == 'nt': self.topify_window(self.window) if os.name == 'nt': self.topify_window(self.window)
@ -454,7 +513,14 @@ class Popup_window:
for w in tl_windows: for w in tl_windows:
if w[1] == unique_name: if w[1] == unique_name:
win32gui.SetWindowPos(w[0], win32con.HWND_TOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE|win32con.SWP_NOSIZE) # 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], # notify_id = (w[0],
# 0, # 0,
# win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP, # win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP,
@ -473,12 +539,16 @@ if __name__== "__main__":
main_window.show_all() main_window.show_all()
c = Configuration.Config() c = Configuration.Config()
tables = Tables.discover(c) #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') db = Database.Database(c, 'fpdb', 'holdem')
for t in tables: # for t in tables:
win = Hud(t, 8, c, db) win = Hud(t, 10, 'holdem', c, db)
win.create(1, c)
# t.get_details() # t.get_details()
win.update(8300, db, c) win.update(8300, db, c)
gtk.main() gtk.main()

View File

@ -58,6 +58,7 @@ def do_tip(widget, tip):
def do_stat(stat_dict, player = 24, stat = 'vpip'): def do_stat(stat_dict, player = 24, stat = 'vpip'):
return eval("%(stat)s(stat_dict, %(player)d)" % {'stat': stat, 'player': player}) return eval("%(stat)s(stat_dict, %(player)d)" % {'stat': stat, 'player': player})
# OK, for reference the tuple returned by the stat is: # OK, for reference the tuple returned by the stat is:
# 0 - The stat, raw, no formating, eg 0.33333333 # 0 - The stat, raw, no formating, eg 0.33333333
# 1 - formatted stat with appropriate precision and punctuation, eg 33% # 1 - formatted stat with appropriate precision and punctuation, eg 33%
@ -68,6 +69,15 @@ def do_stat(stat_dict, player = 24, stat = 'vpip'):
########################################### ###########################################
# functions that return individual stats # functions that return individual stats
def playername(stat_dict, player):
return (stat_dict[player]['screen_name'],
stat_dict[player]['screen_name'],
stat_dict[player]['screen_name'],
stat_dict[player]['screen_name'],
stat_dict[player]['screen_name'],
stat_dict[player]['screen_name'])
def vpip(stat_dict, player): def vpip(stat_dict, player):
""" Voluntarily put $ in the pot.""" """ Voluntarily put $ in the pot."""
stat = 0.0 stat = 0.0
@ -372,7 +382,7 @@ def a_freq_3(stat_dict, player):
'%3.1f' % (100*stat) + '%', '%3.1f' % (100*stat) + '%',
'a3=%3.1f' % (100*stat) + '%', 'a3=%3.1f' % (100*stat) + '%',
'a_fq_3=%3.1f' % (100*stat) + '%', 'a_fq_3=%3.1f' % (100*stat) + '%',
'(%d/%d)' % (stat_dict[player]['aggr_1'], stat_dict[player]['saw_1']), '(%d/%d)' % (stat_dict[player]['aggr_3'], stat_dict[player]['saw_3']),
'Aggression Freq river/6th' 'Aggression Freq river/6th'
) )
except: except:

View File

@ -33,6 +33,9 @@ import re
if os.name == 'nt': if os.name == 'nt':
import win32gui import win32gui
import win32process
import win32api
import win32con
# FreePokerTools modules # FreePokerTools modules
import Configuration import Configuration
@ -57,17 +60,26 @@ class Table_Window:
def discover(c): def discover(c):
if os.name == 'posix': if os.name == 'posix':
tables = discover_posix(c) tables = discover_posix(c)
return tables
elif os.name == 'nt': elif os.name == 'nt':
tables = discover_nt(c) tables = discover_nt(c)
return tables
elif os.name == 'mac': elif os.name == 'mac':
tables = discover_mac(c) tables = discover_mac(c)
return tables else:
else: tables = {} tables = {}
return(tables) return(tables)
def discover_table_by_name(c, tablename):
if os.name == 'posix':
table = discover_posix_by_name(c, tablename)
elif os.name == 'nt':
table = discover_nt_by_name(c, tablename)
elif os.name == 'mac':
table = discover_mac_by_name(c, tablename)
else:
table = None
return(table)
def discover_posix(c): def discover_posix(c):
""" Poker client table window finder for posix/Linux = XWindows.""" """ Poker client table window finder for posix/Linux = XWindows."""
tables = {} tables = {}
@ -84,7 +96,7 @@ def discover_posix(c):
if re.match('[\(\)\d\s]+', mo.group(2)): continue # this is a popup if re.match('[\(\)\d\s]+', mo.group(2)): continue # this is a popup
tw = Table_Window() tw = Table_Window()
tw.site = c.supported_sites[s].site_name tw.site = c.supported_sites[s].site_name
tw.number = mo.group(1) tw.number = int(mo.group(1), 0)
tw.title = mo.group(2) tw.title = mo.group(2)
tw.width = int( mo.group(3) ) tw.width = int( mo.group(3) )
tw.height = int( mo.group(4) ) tw.height = int( mo.group(4) )
@ -94,8 +106,17 @@ def discover_posix(c):
# use this eval thingie to call the title bar decoder specified in the config file # use this eval thingie to call the title bar decoder specified in the config file
eval("%s(tw)" % c.supported_sites[s].decoder) eval("%s(tw)" % c.supported_sites[s].decoder)
tables[tw.name] = tw tables[tw.name] = tw
return tables return tables
def discover_posix_by_name(c, tablename):
tables = discover_posix(c)
for t in tables:
if tables[t].name.find(tablename) > -1:
return tables[t]
return None
# #
# The discover_xx functions query the system and report on the poker clients # The discover_xx functions query the system and report on the poker clients
# currently displayed on the screen. The discover_posix should give you # currently displayed on the screen. The discover_posix should give you
@ -120,6 +141,7 @@ def discover_posix(c):
def win_enum_handler(hwnd, titles): def win_enum_handler(hwnd, titles):
titles[hwnd] = win32gui.GetWindowText(hwnd) titles[hwnd] = win32gui.GetWindowText(hwnd)
def child_enum_handler(hwnd, children): def child_enum_handler(hwnd, children):
print hwnd, win32.GetWindowRect(hwnd) print hwnd, win32.GetWindowRect(hwnd)
@ -150,7 +172,7 @@ def discover_nt(c):
tw.y = int( y ) + tb_height tw.y = int( y ) + tb_height
if re.search('Logged In as', titles[hwnd]): if re.search('Logged In as', titles[hwnd]):
tw.site = "PokerStars" tw.site = "PokerStars"
elif re.search('Logged In As', titles[hwnd]): elif re.search('Logged In As', titles[hwnd]): #wait, what??!
tw.site = "Full Tilt" tw.site = "Full Tilt"
else: else:
tw.site = "Unknown" tw.site = "Unknown"
@ -159,14 +181,73 @@ def discover_nt(c):
eval("%s(tw)" % c.supported_sites[tw.site].decoder) eval("%s(tw)" % c.supported_sites[tw.site].decoder)
else: else:
tw.name = "Unknown" tw.name = "Unknown"
tables[tw.name] = tw tables[len(tables)] = tw
return tables return tables
def discover_nt_by_name(c, tablename):
# this is pretty much identical to the 'search all windows for all poker sites' code, but made to dig just for a specific table name
# it could be implemented a bunch better - and we need to not assume the width/height thing that (steffen?) assumed above, we should
# be able to dig up the window's titlebar handle and get it's information, and such .. but.. for now, i guess this will work.
# - eric
b_width = 3
tb_height = 29
titles = {}
# tables = discover_nt(c)
win32gui.EnumWindows(win_enum_handler, titles)
for s in c.supported_sites.keys():
for hwnd in titles.keys():
processid = win32process.GetWindowThreadProcessId(hwnd)
pshandle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ, False, processid[1])
exe = win32process.GetModuleFileNameEx(pshandle, 0)
if exe.find(c.supported_sites[s].table_finder) == -1:
continue
if titles[hwnd].find(tablename) > -1:
if titles[hwnd].find("History for table:") > -1 or titles[hwnd].find("FPDBHUD") > -1:
continue
tw = Table_Window()
tw.number = hwnd
(x, y, width, height) = win32gui.GetWindowRect(hwnd)
tw.title = titles[hwnd]
tw.width = int(width) - 2 * b_width
tw.height = int(height) - b_width - tb_height
tw.x = int(x) + b_width
tw.y = int(y) + tb_height
tw.site = c.supported_sites[s].site_name
if not tw.site == "Unknown" and not c.supported_sites[tw.site].decoder == "Unknown":
eval("%s(tw)" % c.supported_sites[tw.site].decoder)
else:
tw.name = tablename
return tw
# if we don't find anything by process name, let's search one more time, and call it Unknown ?
for hwnd in titles.keys():
if titles[hwnd].find(tablename) > -1:
if titles[hwnd].find("History for table:") > -1 or titles[hwnd].find("FPDBHUD") > -1:
continue
tw = Table_Window()
tw.number = hwnd
(x, y, width, height) = win32gui.GetWindowRect(hwnd)
tw.title = titles[hwnd]
tw.width = int(width) - 2 * b_width
tw.height = int(height) - b_width - tb_height
tw.x = int(x) + b_width
tw.y = int(y) + tb_height
tw.site = "Unknown"
tw.name = tablename
return tw
return None
def discover_mac(c): def discover_mac(c):
""" Poker client table window finder for Macintosh.""" """ Poker client table window finder for Macintosh."""
tables = {} tables = {}
return tables return tables
def discover_mac_by_name(c, tablename):
# again, i have no mac to test this on, sorry -eric
return discover_mac(c)
def pokerstars_decode_table(tw): def pokerstars_decode_table(tw):
# extract the table name OR the tournament number and table name from the title # extract the table name OR the tournament number and table name from the title
# other info in title is redundant with data in the database # other info in title is redundant with data in the database
@ -221,6 +302,7 @@ def fulltilt_decode_table(tw):
if __name__=="__main__": if __name__=="__main__":
c = Configuration.Config() c = Configuration.Config()
print discover_table_by_name(c, "Catacaos")
tables = discover(c) tables = discover(c)
for t in tables.keys(): for t in tables.keys():

0
pyfpdb/fpdb_db.py Normal file → Executable file
View File

View File

@ -47,8 +47,8 @@ class Importer:
self.caller=caller self.caller=caller
self.db = None self.db = None
self.cursor = None self.cursor = None
self.filelist = [] self.filelist = {}
self.dirlist = [] self.dirlist = {}
self.monitor = False self.monitor = False
self.updated = {} #Time last import was run {file:mtime} self.updated = {} #Time last import was run {file:mtime}
self.callHud = False self.callHud = False
@ -100,29 +100,25 @@ class Importer:
# self.updated = time() # self.updated = time()
def clearFileList(self): def clearFileList(self):
self.filelist = [] self.filelist = {}
#Add an individual file to filelist #Add an individual file to filelist
def addImportFile(self, filename): def addImportFile(self, filename, site = "default", filter = "passthrough"):
#TODO: test it is a valid file #TODO: test it is a valid file
self.filelist = self.filelist + [filename] self.filelist[filename] = [site] + [filter]
#Remove duplicates
self.filelist = list(set(self.filelist))
#Add a directory of files to filelist #Add a directory of files to filelist
def addImportDirectory(self,dir,monitor = False): #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 os.path.isdir(dir):
if monitor == True: if monitor == True:
self.monitor = True self.monitor = True
self.dirlist = self.dirlist + [dir] self.dirlist[site] = [dir] + [filter]
for file in os.listdir(dir): for file in os.listdir(dir):
if os.path.isdir(file): self.addImportFile(os.path.join(dir, file), site, filter)
print "BulkImport is not recursive - please select the final directory in which the history files are"
else:
self.filelist = self.filelist + [os.path.join(dir, file)]
#Remove duplicates
self.filelist = list(set(self.filelist))
else: else:
print "Warning: Attempted to add: '" + str(dir) + "' as an import directory" print "Warning: Attempted to add: '" + str(dir) + "' as an import directory"
@ -136,23 +132,22 @@ class Importer:
#Check for new files in directory #Check for new files in directory
#todo: make efficient - always checks for new file, should be able to use mtime of directory #todo: make efficient - always checks for new file, should be able to use mtime of directory
# ^^ May not work on windows # ^^ May not work on windows
for dir in self.dirlist: for site in self.dirlist:
for file in os.listdir(dir): self.addImportDirectory(self.dirlist[site][0], False, site, self.dirlist[site][1])
self.filelist = self.filelist + [dir+os.sep+file]
self.filelist = list(set(self.filelist))
for file in self.filelist: for file in self.filelist:
stat_info = os.stat(file) stat_info = os.stat(file)
try: try:
lastupdate = self.updated[file] lastupdate = self.updated[file]
# print "Is " + str(stat_info.st_mtime) + " > " + str(lastupdate)
if stat_info.st_mtime > lastupdate: if stat_info.st_mtime > lastupdate:
self.import_file_dict(file) self.import_file_dict(file)
self.updated[file] = time() self.updated[file] = time()
except: except:
# print "Adding " + str(file) + " at approx " + str(time())
self.updated[file] = time() 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. # This is now an internal function that should not be called directly.
def import_file_dict(self, file): def import_file_dict(self, file):

View File

@ -330,6 +330,8 @@ def filterCrap(site, hand, isTourney):
toRemove.append(hand[i]) toRemove.append(hand[i])
elif (hand[i].find(" out of hand ")!=-1): elif (hand[i].find(" out of hand ")!=-1):
hand[i]=hand[i][:-56] hand[i]=hand[i][:-56]
elif (hand[i].find("($0 in chips)") != -1):
toRemove.append(hand[i])
elif (hand[i]=="*** HOLE CARDS ***"): elif (hand[i]=="*** HOLE CARDS ***"):
toRemove.append(hand[i]) toRemove.append(hand[i])
elif (hand[i].endswith("has been disconnected")): elif (hand[i].endswith("has been disconnected")):

View File

@ -1,218 +0,0 @@
DROP TABLE IF EXISTS Settings CASCADE;
CREATE TABLE Settings (version SMALLINT);
DROP TABLE IF EXISTS Sites CASCADE;
CREATE TABLE Sites (
id SERIAL UNIQUE, PRIMARY KEY (id),
name varchar(32),
currency char(3));
DROP TABLE IF EXISTS Gametypes CASCADE;
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);
DROP TABLE IF EXISTS Players CASCADE;
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);
DROP TABLE IF EXISTS Autorates CASCADE;
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);
DROP TABLE IF EXISTS Hands CASCADE;
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);
DROP TABLE IF EXISTS BoardCards CASCADE;
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));
DROP TABLE IF EXISTS TourneyTypes CASCADE;
CREATE TABLE TourneyTypes (
id SERIAL, PRIMARY KEY (id),
siteId INT, FOREIGN KEY (siteId) REFERENCES Sites(id),
buyin INT,
fee INT,
knockout INT,
rebuyOrAddon BOOLEAN);
DROP TABLE IF EXISTS Tourneys CASCADE;
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);
DROP TABLE IF EXISTS TourneysPlayers CASCADE;
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);
DROP TABLE IF EXISTS HandsPlayers CASCADE;
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,
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));
DROP TABLE IF EXISTS HandsActions CASCADE;
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);
DROP TABLE IF EXISTS HudCache CASCADE;
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),
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,
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,
totalProfit INT,
street1CheckCallRaiseChance INT,
street1CheckCallRaiseDone INT,
street2CheckCallRaiseChance INT,
street2CheckCallRaiseDone INT,
street3CheckCallRaiseChance INT,
street3CheckCallRaiseDone INT,
street4CheckCallRaiseChance INT,
street4CheckCallRaiseDone INT);
INSERT INTO Settings VALUES (118);
INSERT INTO Sites ("name", currency) VALUES ('Full Tilt Poker', 'USD');
INSERT INTO Sites ("name", currency) VALUES ('PokerStars', 'USD');
INSERT INTO TourneyTypes (buyin, fee, knockout, rebuyOrAddon) VALUES (0, 0, 0, FALSE);