p80 - a great many updates from Ray
This commit is contained in:
parent
2c251d94f2
commit
7b13331331
|
@ -22,6 +22,8 @@ rm pyfpdb/*.pyc
|
||||||
mkdir fpdb-$1
|
mkdir fpdb-$1
|
||||||
cp -R docs fpdb-$1/
|
cp -R docs fpdb-$1/
|
||||||
cp -R pyfpdb fpdb-$1/
|
cp -R pyfpdb fpdb-$1/
|
||||||
|
rm fpdb-$1/HUD_config.*
|
||||||
|
cp pyfpdb/HUD_config.xml.example fpdb-$1/
|
||||||
cp -R regression-test fpdb-$1/
|
cp -R regression-test fpdb-$1/
|
||||||
cp -R utils fpdb-$1/
|
cp -R utils fpdb-$1/
|
||||||
cd fpdb-$1
|
cd fpdb-$1
|
||||||
|
|
|
@ -2,9 +2,8 @@ todolist (db=database, imp=importer, tv=tableviewer)
|
||||||
Everything is subject to change and the order does not indicate priority. Patches for any of these or other features are very welcome, see readme-overview.txt for contacts.
|
Everything is subject to change and the order does not indicate priority. Patches for any of these or other features are very welcome, see readme-overview.txt for contacts.
|
||||||
Please also see db-todo.txt
|
Please also see db-todo.txt
|
||||||
|
|
||||||
alpha3 (release 1-2Sep?)
|
alpha3 (release 15Sep)
|
||||||
======
|
======
|
||||||
(fixed by ray) auto import only runs on one file per start
|
|
||||||
find correct sf logo link
|
find correct sf logo link
|
||||||
|
|
||||||
windows integrated installer
|
windows integrated installer
|
||||||
|
@ -20,7 +19,7 @@ fill check-/call-raise cache fields
|
||||||
|
|
||||||
printhand each and the 2/3 relevant printplayerflags respectively on ps-lhe-ring-successful-steal-by-cutoff.txt and ps-lhe-ring-call-3B-preflop-cb-no2b.txt
|
printhand each and the 2/3 relevant printplayerflags respectively on ps-lhe-ring-successful-steal-by-cutoff.txt and ps-lhe-ring-call-3B-preflop-cb-no2b.txt
|
||||||
|
|
||||||
alpha4 (release 8Sep?)
|
alpha4 (release 22-29Sep)
|
||||||
======
|
======
|
||||||
change to savannah?
|
change to savannah?
|
||||||
implement steal and positions in stud
|
implement steal and positions in stud
|
||||||
|
@ -33,9 +32,25 @@ change tabledesign VALIGN
|
||||||
finish updating filelist
|
finish updating filelist
|
||||||
finish todos in git instructions
|
finish todos in git instructions
|
||||||
debian/ubuntu package http://www.debian.org/doc/maint-guide/ch-start.en.html
|
debian/ubuntu package http://www.debian.org/doc/maint-guide/ch-start.en.html
|
||||||
|
howto remote DB
|
||||||
|
move all user docs to webpage
|
||||||
|
|
||||||
before beta
|
before beta
|
||||||
===========
|
===========
|
||||||
|
No Full Tilt support in HUD
|
||||||
|
No river stats for stud games
|
||||||
|
hole/board cards are not correctly stored in the db for stud games
|
||||||
|
HORSE (and presumably other mixed games) hand history files not handled correctly
|
||||||
|
HUD stat windows are too big on Windows
|
||||||
|
HUD task bar entries on Windows won't go away
|
||||||
|
Some MTTs won't import (rebuys??)
|
||||||
|
Many STTs won't import
|
||||||
|
MTT/STT not tested in HUD
|
||||||
|
HUD stats not aggregated
|
||||||
|
Player names with non-Latin chars throw warnings in HUD
|
||||||
|
HUD doesn't start when fpdb is started from the Windows "Start Menu"
|
||||||
|
Exiting HUD on Windows doesn't properly clean up stat windows
|
||||||
|
|
||||||
finish bringing back tourney
|
finish bringing back tourney
|
||||||
ebuild: USE gtk, set permissions in it, copy docs to correct place, use games eclass or whatever to get games group notice, git-ebuild, get it into sunrise
|
ebuild: USE gtk, set permissions in it, copy docs to correct place, use games eclass or whatever to get games group notice, git-ebuild, get it into sunrise
|
||||||
make hud display W$SD etc as fraction.
|
make hud display W$SD etc as fraction.
|
||||||
|
@ -49,6 +64,7 @@ split hud data generation into separate for loops and make it more efficient
|
||||||
fix bug that sawFlop/Turn/River/CBChance/etc gets miscalculated if someone is allin - might as well add all-in recognition for this
|
fix bug that sawFlop/Turn/River/CBChance/etc gets miscalculated if someone is allin - might as well add all-in recognition for this
|
||||||
make 3 default HUD configs (easy (4-5 fields), advanced (10ish fields), crazy (20 or so))
|
make 3 default HUD configs (easy (4-5 fields), advanced (10ish fields), crazy (20 or so))
|
||||||
make it work with postgres
|
make it work with postgres
|
||||||
|
gentoo ebuild: USE postgresql
|
||||||
expand instructions for profile file
|
expand instructions for profile file
|
||||||
maybe remove siteId from gametypes
|
maybe remove siteId from gametypes
|
||||||
?change most cache fields to bigint to allow extremely big databases in excess of 2 or 4 million hands per stake and position?
|
?change most cache fields to bigint to allow extremely big databases in excess of 2 or 4 million hands per stake and position?
|
||||||
|
|
72
pyfpdb/Configuration.py
Normal file → Executable file
72
pyfpdb/Configuration.py
Normal file → Executable file
|
@ -23,6 +23,7 @@ Handles HUD configuration files.
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
||||||
# Standard Library modules
|
# Standard Library modules
|
||||||
|
import shutil
|
||||||
import xml.dom.minidom
|
import xml.dom.minidom
|
||||||
from xml.dom.minidom import Node
|
from xml.dom.minidom import Node
|
||||||
|
|
||||||
|
@ -38,7 +39,7 @@ class Layout:
|
||||||
for i in range(1, len(self.location)):
|
for i in range(1, len(self.location)):
|
||||||
temp = temp + "(%d,%d)" % self.location[i]
|
temp = temp + "(%d,%d)" % self.location[i]
|
||||||
|
|
||||||
return temp
|
return temp + "\n"
|
||||||
|
|
||||||
class Site:
|
class Site:
|
||||||
def __init__(self, node):
|
def __init__(self, node):
|
||||||
|
@ -81,7 +82,7 @@ class Stat:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
temp = " stat_name = %s, row = %d, col = %d, tip = %s, click = %s\n" % (self.stat_name, self.row, self.col, self.tip, self.click)
|
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
|
return temp
|
||||||
|
|
||||||
class Game:
|
class Game:
|
||||||
|
@ -99,6 +100,7 @@ class Game:
|
||||||
stat.col = int( stat_node.getAttribute("col") )
|
stat.col = int( stat_node.getAttribute("col") )
|
||||||
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")
|
||||||
|
|
||||||
self.stats[stat.stat_name] = stat
|
self.stats[stat.stat_name] = stat
|
||||||
|
|
||||||
|
@ -150,15 +152,31 @@ class Mucked:
|
||||||
temp = temp + ' ' + key + " = " + value + "\n"
|
temp = temp + ' ' + key + " = " + value + "\n"
|
||||||
return temp
|
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 Config:
|
class Config:
|
||||||
def __init__(self, file = 'HUD_config.xml'):
|
def __init__(self, file = 'HUD_config.xml'):
|
||||||
|
|
||||||
doc = xml.dom.minidom.parse(file)
|
doc = xml.dom.minidom.parse(file)
|
||||||
|
|
||||||
|
self.doc = doc
|
||||||
|
self.file = file
|
||||||
self.supported_sites = {}
|
self.supported_sites = {}
|
||||||
self.supported_games = {}
|
self.supported_games = {}
|
||||||
self.supported_databases = {}
|
self.supported_databases = {}
|
||||||
self.mucked_windows = {}
|
self.mucked_windows = {}
|
||||||
|
self.popup_windows = {}
|
||||||
|
|
||||||
# s_sites = doc.getElementsByTagName("supported_sites")
|
# s_sites = doc.getElementsByTagName("supported_sites")
|
||||||
for site_node in doc.getElementsByTagName("site"):
|
for site_node in doc.getElementsByTagName("site"):
|
||||||
|
@ -180,6 +198,47 @@ class Config:
|
||||||
mw = Mucked(node = mw_node)
|
mw = Mucked(node = mw_node)
|
||||||
self.mucked_windows[mw.name] = mw
|
self.mucked_windows[mw.name] = mw
|
||||||
|
|
||||||
|
s_dbs = doc.getElementsByTagName("popup_windows")
|
||||||
|
for pu_node in doc.getElementsByTagName("pu"):
|
||||||
|
pu = Popup(node = pu_node)
|
||||||
|
self.popup_windows[pu.name] = pu
|
||||||
|
|
||||||
|
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_layout_node(self, site_node, layout):
|
||||||
|
for layout_node in site_node.getElementsByTagName("layout"):
|
||||||
|
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)
|
||||||
|
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] )
|
||||||
|
|
||||||
if __name__== "__main__":
|
if __name__== "__main__":
|
||||||
c = Config()
|
c = Config()
|
||||||
|
|
||||||
|
@ -208,3 +267,12 @@ if __name__== "__main__":
|
||||||
print c.mucked_windows[w]
|
print c.mucked_windows[w]
|
||||||
|
|
||||||
print "----------- END MUCKED WINDOW FORMATS -----------"
|
print "----------- END MUCKED WINDOW FORMATS -----------"
|
||||||
|
|
||||||
|
print "\n----------- POPUP WINDOW FORMATS -----------"
|
||||||
|
for w in c.popup_windows.keys():
|
||||||
|
print c.popup_windows[w]
|
||||||
|
|
||||||
|
print "----------- END MUCKED WINDOW FORMATS -----------"
|
||||||
|
|
||||||
|
c.edit_layout("PokerStars", 6, locations=( (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6) ))
|
||||||
|
c.save(file="testout.xml")
|
|
@ -24,6 +24,7 @@ Create and manage the database objects.
|
||||||
# postmaster -D /var/lib/pgsql/data
|
# postmaster -D /var/lib/pgsql/data
|
||||||
|
|
||||||
# Standard Library modules
|
# Standard Library modules
|
||||||
|
import sys
|
||||||
|
|
||||||
# pyGTK modules
|
# pyGTK modules
|
||||||
|
|
||||||
|
@ -32,7 +33,7 @@ import Configuration
|
||||||
import SQL
|
import SQL
|
||||||
|
|
||||||
# pgdb database module for posgres via DB-API
|
# pgdb database module for posgres via DB-API
|
||||||
#import pgdb
|
import psycopg2
|
||||||
# pgdb uses pyformat. is that fixed or an option?
|
# pgdb uses pyformat. is that fixed or an option?
|
||||||
|
|
||||||
# mysql bindings
|
# mysql bindings
|
||||||
|
@ -41,7 +42,7 @@ import MySQLdb
|
||||||
class Database:
|
class Database:
|
||||||
def __init__(self, c, db_name, game):
|
def __init__(self, c, db_name, game):
|
||||||
if c.supported_databases[db_name].db_server == 'postgresql':
|
if c.supported_databases[db_name].db_server == 'postgresql':
|
||||||
self.connection = pgdb.connect(dsn = c.supported_databases[db_name].db_ip,
|
self.connection = psycopg2.connect(host = c.supported_databases[db_name].db_ip,
|
||||||
user = c.supported_databases[db_name].db_user,
|
user = c.supported_databases[db_name].db_user,
|
||||||
password = c.supported_databases[db_name].db_pass,
|
password = c.supported_databases[db_name].db_pass,
|
||||||
database = c.supported_databases[db_name].db_name)
|
database = c.supported_databases[db_name].db_name)
|
||||||
|
@ -59,12 +60,12 @@ class Database:
|
||||||
self.type = c.supported_databases[db_name].db_type
|
self.type = c.supported_databases[db_name].db_type
|
||||||
self.sql = SQL.Sql(game = game, type = self.type)
|
self.sql = SQL.Sql(game = game, type = self.type)
|
||||||
|
|
||||||
def close(self):
|
def close_connection(self):
|
||||||
self.connection.close
|
self.connection.close()
|
||||||
|
|
||||||
def get_table_name(self, hand_id):
|
def get_table_name(self, hand_id):
|
||||||
c = self.connection.cursor()
|
c = self.connection.cursor()
|
||||||
c.execute(self.sql.query['get_table_name'], (hand_id))
|
c.execute(self.sql.query['get_table_name'], (hand_id, ))
|
||||||
row = c.fetchone()
|
row = c.fetchone()
|
||||||
return row
|
return row
|
||||||
|
|
||||||
|
@ -90,7 +91,21 @@ class Database:
|
||||||
c.execute(self.sql.query['get_hand_info'], new_hand_id)
|
c.execute(self.sql.query['get_hand_info'], new_hand_id)
|
||||||
return c.fetchall()
|
return c.fetchall()
|
||||||
|
|
||||||
|
# def get_cards(self, hand):
|
||||||
|
# this version is for the PTrackSv2 db
|
||||||
|
# c = self.connection.cursor()
|
||||||
|
# c.execute(self.sql.query['get_cards'], hand)
|
||||||
|
# colnames = [desc[0] for desc in c.description]
|
||||||
|
# cards = {}
|
||||||
|
# for row in c.fetchall():
|
||||||
|
# s_dict = {}
|
||||||
|
# for name, val in zip(colnames, row):
|
||||||
|
# s_dict[name] = val
|
||||||
|
# cards[s_dict['seat_number']] = s_dict
|
||||||
|
# return (cards)
|
||||||
|
|
||||||
def get_cards(self, hand):
|
def get_cards(self, hand):
|
||||||
|
# this version is for the fpdb db
|
||||||
c = self.connection.cursor()
|
c = self.connection.cursor()
|
||||||
c.execute(self.sql.query['get_cards'], hand)
|
c.execute(self.sql.query['get_cards'], hand)
|
||||||
colnames = [desc[0] for desc in c.description]
|
colnames = [desc[0] for desc in c.description]
|
||||||
|
@ -102,11 +117,13 @@ class Database:
|
||||||
cards[s_dict['seat_number']] = s_dict
|
cards[s_dict['seat_number']] = s_dict
|
||||||
return (cards)
|
return (cards)
|
||||||
|
|
||||||
def get_stats_from_hand(self, hand, hero):
|
def get_stats_from_hand(self, hand, player_id = False):
|
||||||
c = self.connection.cursor()
|
c = self.connection.cursor()
|
||||||
|
|
||||||
|
if not player_id: player_id = "%"
|
||||||
# get the players in the hand and their seats
|
# get the players in the hand and their seats
|
||||||
c.execute(self.sql.query['get_players_from_hand'], (hand))
|
# c.execute(self.sql.query['get_players_from_hand'], (hand, player_id))
|
||||||
|
c.execute(self.sql.query['get_players_from_hand'], (hand, ))
|
||||||
names = {}
|
names = {}
|
||||||
seats = {}
|
seats = {}
|
||||||
for row in c.fetchall():
|
for row in c.fetchall():
|
||||||
|
@ -114,6 +131,7 @@ class Database:
|
||||||
seats[row[0]] = row[1]
|
seats[row[0]] = row[1]
|
||||||
|
|
||||||
# now get the stats
|
# 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['get_stats_from_hand'], (hand, hand))
|
||||||
colnames = [desc[0] for desc in c.description]
|
colnames = [desc[0] for desc in c.description]
|
||||||
stat_dict = {}
|
stat_dict = {}
|
||||||
|
@ -137,7 +155,8 @@ class Database:
|
||||||
if __name__=="__main__":
|
if __name__=="__main__":
|
||||||
c = Configuration.Config()
|
c = Configuration.Config()
|
||||||
|
|
||||||
db_connection = Database(c, 'fpdb', 'holdem') # mysql fpdb holdem
|
# db_connection = Database(c, 'fpdb', 'holdem') # mysql fpdb holdem
|
||||||
|
db_connection = Database(c, 'fpdb-p', 'test') # mysql fpdb holdem
|
||||||
# db_connection = Database(c, 'PTrackSv2', 'razz') # mysql razz
|
# db_connection = Database(c, 'PTrackSv2', 'razz') # mysql razz
|
||||||
# db_connection = Database(c, 'ptracks', 'razz') # postgres
|
# db_connection = Database(c, 'ptracks', 'razz') # postgres
|
||||||
print "database connection object = ", db_connection.connection
|
print "database connection object = ", db_connection.connection
|
||||||
|
@ -149,7 +168,16 @@ if __name__=="__main__":
|
||||||
hero = db_connection.get_player_id(c, 'PokerStars', 'nutOmatic')
|
hero = db_connection.get_player_id(c, 'PokerStars', 'nutOmatic')
|
||||||
print "nutOmatic is id_player = %d" % hero
|
print "nutOmatic is id_player = %d" % hero
|
||||||
|
|
||||||
|
stat_dict = db_connection.get_stats_from_hand(h)
|
||||||
|
for p in stat_dict.keys():
|
||||||
|
print p, " ", stat_dict[p]
|
||||||
|
|
||||||
|
print "nutOmatics stats:"
|
||||||
stat_dict = db_connection.get_stats_from_hand(h, hero)
|
stat_dict = db_connection.get_stats_from_hand(h, hero)
|
||||||
for p in stat_dict.keys():
|
for p in stat_dict.keys():
|
||||||
print p, " ", stat_dict[p]
|
print p, " ", stat_dict[p]
|
||||||
db_connection.close
|
|
||||||
|
db_connection.close_connection
|
||||||
|
|
||||||
|
print "press enter to continue"
|
||||||
|
sys.stdin.readline()
|
||||||
|
|
|
@ -33,7 +33,7 @@ class GuiAutoImport (threading.Thread):
|
||||||
current_path=self.pathTBuffer.get_text(self.pathTBuffer.get_start_iter(), self.pathTBuffer.get_end_iter())
|
current_path=self.pathTBuffer.get_text(self.pathTBuffer.get_start_iter(), self.pathTBuffer.get_end_iter())
|
||||||
|
|
||||||
dia_chooser = gtk.FileChooserDialog(title="Please choose the path that you want to auto import",
|
dia_chooser = gtk.FileChooserDialog(title="Please choose the path that you want to auto import",
|
||||||
action=gtk.FILE_CHOOSER_ACTION_OPEN,
|
action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
||||||
buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
|
buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
|
||||||
#dia_chooser.set_current_folder(pathname)
|
#dia_chooser.set_current_folder(pathname)
|
||||||
dia_chooser.set_filename(current_path)
|
dia_chooser.set_filename(current_path)
|
||||||
|
@ -50,8 +50,18 @@ class GuiAutoImport (threading.Thread):
|
||||||
|
|
||||||
def do_import(self):
|
def do_import(self):
|
||||||
"""Callback for timer to do an import iteration."""
|
"""Callback for timer to do an import iteration."""
|
||||||
fpdb_import.import_file_dict(self, self.settings)
|
for file in os.listdir(self.path):
|
||||||
return(1)
|
if os.path.isdir(file):
|
||||||
|
print "AutoImport is not recursive - please select the final directory in which the history files are"
|
||||||
|
else:
|
||||||
|
self.inputFile = os.path.join(self.path, file)
|
||||||
|
stat_info = os.stat(self.inputFile)
|
||||||
|
if not self.import_files.has_key(self.inputFile) or stat_info.st_mtime > self.import_files[self.inputFile]:
|
||||||
|
fpdb_import.import_file_dict(self, self.settings, callHud = True)
|
||||||
|
self.import_files[self.inputFile] = stat_info.st_mtime
|
||||||
|
|
||||||
|
print "GuiAutoImport.import_dir done"
|
||||||
|
return True
|
||||||
|
|
||||||
def startClicked(self, widget, data):
|
def startClicked(self, widget, data):
|
||||||
"""runs when user clicks start on auto import tab"""
|
"""runs when user clicks start on auto import tab"""
|
||||||
|
@ -59,24 +69,48 @@ class GuiAutoImport (threading.Thread):
|
||||||
# Check to see if we have an open file handle to the HUD and open one if we do not.
|
# Check to see if we have an open file handle to the HUD and open one if we do not.
|
||||||
# bufsize = 1 means unbuffered
|
# bufsize = 1 means unbuffered
|
||||||
# We need to close this file handle sometime.
|
# We need to close this file handle sometime.
|
||||||
|
|
||||||
|
# TODO: Allow for importing from multiple dirs - REB 29AUG2008
|
||||||
|
# As presently written this function does nothing if there is already a pipe open.
|
||||||
|
# That is not correct. It should open another dir for importing while piping the
|
||||||
|
# results to the same pipe. This means that self.path should be a a list of dirs
|
||||||
|
# to watch.
|
||||||
try: #uhhh, I don't this this is the best way to check for the existence of an attr
|
try: #uhhh, I don't this this is the best way to check for the existence of an attr
|
||||||
getattr(self, "pipe_to_hud")
|
getattr(self, "pipe_to_hud")
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
cwd = os.getcwd()
|
if os.name == 'nt':
|
||||||
command = os.path.join(cwd, 'HUD_main.py')
|
command = "python HUD_main.py" + " %s" % (self.database)
|
||||||
self.pipe_to_hud = subprocess.Popen(command, bufsize = 1, stdin = subprocess.PIPE)
|
bs = 0 # windows is not happy with line buffing here
|
||||||
|
self.pipe_to_hud = subprocess.Popen(command, bufsize = bs, stdin = subprocess.PIPE,
|
||||||
self.path=self.pathTBuffer.get_text(self.pathTBuffer.get_start_iter(), self.pathTBuffer.get_end_iter())
|
universal_newlines=True)
|
||||||
for file in os.listdir(self.path):
|
|
||||||
if os.path.isdir(file):
|
|
||||||
print "AutoImport is not recursive - please select the final directory in which the history files are"
|
|
||||||
else:
|
else:
|
||||||
self.inputFile=self.path+os.sep+file
|
cwd = os.getcwd()
|
||||||
self.do_import()
|
command = os.path.join(cwd, 'HUD_main.py')
|
||||||
print "GuiAutoImport.import_dir done"
|
bs = 1
|
||||||
|
self.pipe_to_hud = subprocess.Popen((command, self.database), bufsize = bs, stdin = subprocess.PIPE,
|
||||||
|
universal_newlines=True)
|
||||||
|
# self.pipe_to_hud = subprocess.Popen((command, self.database), bufsize = bs, stdin = subprocess.PIPE,
|
||||||
|
# universal_newlines=True)
|
||||||
|
# command = command + " %s" % (self.database)
|
||||||
|
# print "command = ", command
|
||||||
|
# self.pipe_to_hud = os.popen(command, 'w')
|
||||||
|
self.path=self.pathTBuffer.get_text(self.pathTBuffer.get_start_iter(), self.pathTBuffer.get_end_iter())
|
||||||
|
|
||||||
interval=int(self.intervalTBuffer.get_text(self.intervalTBuffer.get_start_iter(), self.intervalTBuffer.get_end_iter()))
|
# Iniitally populate the self.import_files dict, which keeps mtimes for the files watched
|
||||||
gobject.timeout_add(interval*1000, self.do_import)
|
|
||||||
|
self.import_files = {}
|
||||||
|
for file in os.listdir(self.path):
|
||||||
|
if os.path.isdir(file):
|
||||||
|
pass # skip subdirs for now
|
||||||
|
else:
|
||||||
|
inputFile = os.path.join(self.path, file)
|
||||||
|
stat_info = os.stat(inputFile)
|
||||||
|
self.import_files[inputFile] = stat_info.st_mtime
|
||||||
|
|
||||||
|
self.do_import()
|
||||||
|
|
||||||
|
interval=int(self.intervalTBuffer.get_text(self.intervalTBuffer.get_start_iter(), self.intervalTBuffer.get_end_iter()))
|
||||||
|
gobject.timeout_add(interval*1000, self.do_import)
|
||||||
#end def GuiAutoImport.browseClicked
|
#end def GuiAutoImport.browseClicked
|
||||||
|
|
||||||
def get_vbox(self):
|
def get_vbox(self):
|
||||||
|
@ -140,3 +174,22 @@ class GuiAutoImport (threading.Thread):
|
||||||
self.mainVBox.add(self.startButton)
|
self.mainVBox.add(self.startButton)
|
||||||
self.startButton.show()
|
self.startButton.show()
|
||||||
#end of GuiAutoImport.__init__
|
#end of GuiAutoImport.__init__
|
||||||
|
if __name__== "__main__":
|
||||||
|
def destroy(*args): # call back for terminating the main eventloop
|
||||||
|
gtk.main_quit()
|
||||||
|
|
||||||
|
settings = {}
|
||||||
|
settings['db-host'] = "192.168.1.100"
|
||||||
|
settings['db-user'] = "mythtv"
|
||||||
|
settings['db-password'] = "mythtv"
|
||||||
|
settings['db-databaseName'] = "fpdb"
|
||||||
|
settings['hud-defaultInterval'] = 10
|
||||||
|
settings['hud-defaultPath'] = 'C:/Program Files/PokerStars/HandHistory/nutOmatic'
|
||||||
|
settings['imp-callFpdbHud'] = True
|
||||||
|
|
||||||
|
i = GuiAutoImport(settings)
|
||||||
|
main_window = gtk.Window()
|
||||||
|
main_window.connect("destroy", destroy)
|
||||||
|
main_window.add(i.mainVBox)
|
||||||
|
main_window.show()
|
||||||
|
gtk.main()
|
||||||
|
|
|
@ -26,15 +26,17 @@ Main for FreePokerTools HUD.
|
||||||
# to do adjust for preferred seat
|
# to do adjust for preferred seat
|
||||||
# to do allow window resizing
|
# to do allow window resizing
|
||||||
# to do hud to echo, but ignore non numbers
|
# to do hud to echo, but ignore non numbers
|
||||||
# to do kill a hud
|
|
||||||
# to do no hud window for hero
|
# to do no hud window for hero
|
||||||
# to do single click to display detailed stats
|
|
||||||
# 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
|
||||||
|
|
||||||
# Standard Library modules
|
# Standard Library modules
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
import thread
|
||||||
|
import Queue
|
||||||
|
|
||||||
# pyGTK modules
|
# pyGTK modules
|
||||||
import pygtk
|
import pygtk
|
||||||
|
@ -49,19 +51,23 @@ import Hud
|
||||||
|
|
||||||
# global dict for keeping the huds
|
# global dict for keeping the huds
|
||||||
hud_dict = {}
|
hud_dict = {}
|
||||||
|
|
||||||
db_connection = 0;
|
db_connection = 0;
|
||||||
config = 0;
|
config = 0;
|
||||||
|
|
||||||
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()
|
||||||
|
|
||||||
def process_new_hand(source, condition):
|
def process_new_hand(new_hand_id, db_name):
|
||||||
# there is a new hand_id to be processed
|
# there is a new hand_id to be processed
|
||||||
# read the hand_id from stdin and strip whitespace
|
# read the hand_id from stdin and strip whitespace
|
||||||
new_hand_id = sys.stdin.readline()
|
global hud_dict
|
||||||
new_hand_id = new_hand_id.rstrip()
|
|
||||||
db_connection = Database.Database(config, 'fpdb', 'holdem')
|
|
||||||
|
|
||||||
|
for h in hud_dict.keys():
|
||||||
|
if hud_dict[h].deleted:
|
||||||
|
del(hud_dict[h])
|
||||||
|
|
||||||
|
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)
|
||||||
# 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):
|
||||||
|
@ -71,29 +77,61 @@ def process_new_hand(source, condition):
|
||||||
table_windows = Tables.discover(config)
|
table_windows = Tables.discover(config)
|
||||||
for t in table_windows.keys():
|
for t in table_windows.keys():
|
||||||
if table_windows[t].name == table_name:
|
if table_windows[t].name == table_name:
|
||||||
hud_dict[table_name] = Hud.Hud(table_windows[t], max, poker_game, config, db_connection)
|
hud_dict[table_name] = Hud.Hud(table_windows[t], max, poker_game, config, db_name)
|
||||||
hud_dict[table_name].create(new_hand_id, config)
|
hud_dict[table_name].create(new_hand_id, config)
|
||||||
hud_dict[table_name].update(new_hand_id, db_connection, config)
|
hud_dict[table_name].update(new_hand_id, db_connection, config)
|
||||||
break
|
break
|
||||||
# print "table name \"%s\" not identified, no hud created" % (table_name)
|
# print "table name \"%s\" not identified, no hud created" % (table_name)
|
||||||
|
db_connection.close_connection()
|
||||||
return(1)
|
return(1)
|
||||||
|
|
||||||
if __name__== "__main__":
|
def check_stdin(db_name):
|
||||||
|
try:
|
||||||
|
hand_no = dataQueue.get(block=False)
|
||||||
|
process_new_hand(hand_no, db_name)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
if not os.name == 'posix':
|
return True
|
||||||
print "This version of the HUD only works with Linux or compatible.\nHUD exiting."
|
|
||||||
|
def read_stdin(source, condition, db_name):
|
||||||
|
new_hand_id = sys.stdin.readline()
|
||||||
|
process_new_hand(new_hand_id, db_name)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def producer(): # This is the thread function
|
||||||
|
while True:
|
||||||
|
hand_no = sys.stdin.readline() # reads stdin
|
||||||
|
dataQueue.put(hand_no) # and puts result on the queue
|
||||||
|
|
||||||
|
if __name__== "__main__":
|
||||||
|
print "HUD_main starting"
|
||||||
|
|
||||||
|
try:
|
||||||
|
db_name = sys.argv[1]
|
||||||
|
except:
|
||||||
|
db_name = 'fpdb-p'
|
||||||
|
print "Using db name = ", db_name
|
||||||
|
|
||||||
|
config = Configuration.Config()
|
||||||
|
# db_connection = Database.Database(config, 'fpdb', 'holdem')
|
||||||
|
|
||||||
|
if os.name == 'posix':
|
||||||
|
s_id = gobject.io_add_watch(sys.stdin, gobject.IO_IN, read_stdin, db_name)
|
||||||
|
elif os.name == 'nt':
|
||||||
|
dataQueue = Queue.Queue() # shared global. infinite size
|
||||||
|
gobject.threads_init() # this is required
|
||||||
|
thread.start_new_thread(producer, ()) # starts the thread
|
||||||
|
gobject.timeout_add(1000, check_stdin, db_name)
|
||||||
|
else:
|
||||||
|
print "Sorry your operating system is not supported."
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
main_window = gtk.Window()
|
main_window = gtk.Window()
|
||||||
main_window.connect("destroy", destroy)
|
main_window.connect("destroy", destroy)
|
||||||
label = gtk.Label('Fake main window, blah blah, blah\nblah, blah')
|
label = gtk.Label('Closing this window will exit from the HUD.')
|
||||||
main_window.add(label)
|
main_window.add(label)
|
||||||
|
main_window.set_title("HUD Main Window")
|
||||||
main_window.show_all()
|
main_window.show_all()
|
||||||
|
|
||||||
config = Configuration.Config()
|
|
||||||
|
|
||||||
db_connection = Database.Database(config, 'fpdb', 'holdem')
|
|
||||||
|
|
||||||
s_id = gobject.io_add_watch(sys.stdin, gobject.IO_IN, process_new_hand)
|
|
||||||
|
|
||||||
gtk.main()
|
gtk.main()
|
||||||
|
|
299
pyfpdb/Hud.py
Normal file → Executable file
299
pyfpdb/Hud.py
Normal file → Executable file
|
@ -22,6 +22,7 @@ Create and manage the hud overlays.
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# Standard Library modules
|
# Standard Library modules
|
||||||
|
import os
|
||||||
|
|
||||||
# pyGTK modules
|
# pyGTK modules
|
||||||
import pygtk
|
import pygtk
|
||||||
|
@ -29,25 +30,84 @@ import gtk
|
||||||
import pango
|
import pango
|
||||||
import gobject
|
import gobject
|
||||||
|
|
||||||
|
# win32 modules -- only imported on windows systems
|
||||||
|
if os.name == 'nt':
|
||||||
|
import win32gui
|
||||||
|
import win32con
|
||||||
|
|
||||||
# FreePokerTools modules
|
# FreePokerTools modules
|
||||||
import Tables # needed for testing only
|
import Tables # needed for testing only
|
||||||
import Configuration
|
import Configuration
|
||||||
import Stats
|
import Stats
|
||||||
import Mucked
|
import Mucked
|
||||||
import Database
|
import Database
|
||||||
|
import HUD_main
|
||||||
|
|
||||||
class Hud:
|
class Hud:
|
||||||
|
|
||||||
def __init__(self, table, max, poker_game, config, db_connection):
|
def __init__(self, table, max, poker_game, config, db_name):
|
||||||
self.table = table
|
self.table = table
|
||||||
self.config = config
|
self.config = config
|
||||||
self.poker_game = poker_game
|
self.poker_game = poker_game
|
||||||
self.max = max
|
self.max = max
|
||||||
self.db_connection = db_connection
|
self.db_name = db_name
|
||||||
|
self.deleted = False
|
||||||
|
|
||||||
self.stat_windows = {}
|
self.stat_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
|
||||||
|
self.main_window = gtk.Window()
|
||||||
|
# self.window.set_decorated(0)
|
||||||
|
self.main_window.set_gravity(gtk.gdk.GRAVITY_STATIC)
|
||||||
|
self.main_window.set_keep_above(1)
|
||||||
|
self.main_window.set_title(table.name)
|
||||||
|
self.main_window.connect("destroy", self.kill_hud)
|
||||||
|
|
||||||
|
self.ebox = gtk.EventBox()
|
||||||
|
self.label = gtk.Label("Close this window to\nkill the HUD for\n %s" % (table.name))
|
||||||
|
self.main_window.add(self.ebox)
|
||||||
|
self.ebox.add(self.label)
|
||||||
|
self.main_window.move(self.table.x, self.table.y)
|
||||||
|
|
||||||
|
# A popup window for the main window
|
||||||
|
self.menu = gtk.Menu()
|
||||||
|
self.item1 = gtk.MenuItem('Kill this HUD')
|
||||||
|
self.menu.append(self.item1)
|
||||||
|
self.item1.connect("activate", self.kill_hud)
|
||||||
|
self.item1.show()
|
||||||
|
self.item2 = gtk.MenuItem('Save Layout')
|
||||||
|
self.menu.append(self.item2)
|
||||||
|
self.item2.connect("activate", self.save_layout)
|
||||||
|
self.item2.show()
|
||||||
|
self.ebox.connect_object("button-press-event", self.on_button_press, self.menu)
|
||||||
|
|
||||||
|
self.main_window.show_all()
|
||||||
|
# set_keep_above(1) for windows
|
||||||
|
if os.name == 'nt': self.topify_window(self.main_window)
|
||||||
|
|
||||||
|
def on_button_press(self, widget, event):
|
||||||
|
if event.button == 3:
|
||||||
|
widget.popup(None, None, None, event.button, event.time)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def kill_hud(self, args):
|
||||||
|
for k in self.stat_windows.keys():
|
||||||
|
self.stat_windows[k].window.destroy()
|
||||||
|
self.main_window.destroy()
|
||||||
|
self.deleted = True
|
||||||
|
|
||||||
|
def save_layout(self, *args):
|
||||||
|
new_layout = []
|
||||||
|
for sw in self.stat_windows:
|
||||||
|
loc = self.stat_windows[sw].window.get_position()
|
||||||
|
new_loc = (loc[0] - self.table.x, loc[1] - self.table.y)
|
||||||
|
new_layout.append(new_loc)
|
||||||
|
print new_layout
|
||||||
|
self.config.edit_layout(self.table.site, self.table.max, locations = new_layout)
|
||||||
|
self.config.save()
|
||||||
|
|
||||||
def create(self, hand, config):
|
def create(self, hand, config):
|
||||||
# update this hud, to the stats and players as of "hand"
|
# update this hud, to the stats and players as of "hand"
|
||||||
|
@ -58,6 +118,7 @@ class Hud:
|
||||||
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[i]
|
(x, y) = config.supported_sites[self.table.site].layout[self.max].location[i]
|
||||||
self.stat_windows[i] = Stat_Window(game = config.supported_games[self.poker_game],
|
self.stat_windows[i] = Stat_Window(game = config.supported_games[self.poker_game],
|
||||||
|
parent = self,
|
||||||
table = self.table,
|
table = self.table,
|
||||||
x = x,
|
x = x,
|
||||||
y = y,
|
y = y,
|
||||||
|
@ -79,10 +140,10 @@ class Hud:
|
||||||
# self.mucked_window.show_all()
|
# self.mucked_window.show_all()
|
||||||
|
|
||||||
def update(self, hand, db, config):
|
def update(self, hand, db, config):
|
||||||
stat_dict = db.get_stats_from_hand(hand, 3)
|
self.hand = hand # this is the last hand, so it is available later
|
||||||
|
stat_dict = db.get_stats_from_hand(hand)
|
||||||
for s in stat_dict.keys():
|
for s in stat_dict.keys():
|
||||||
# for r in range(0, 2):
|
self.stat_windows[stat_dict[s]['seat']].player_id = stat_dict[s]['player_id']
|
||||||
# for c in range(0, 3):
|
|
||||||
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):
|
||||||
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])
|
||||||
|
@ -92,6 +153,32 @@ class Hud:
|
||||||
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)
|
||||||
# self.m.update(hand)
|
# self.m.update(hand)
|
||||||
|
|
||||||
|
def topify_window(self, window):
|
||||||
|
"""Set the specified gtk window to stayontop in MS Windows."""
|
||||||
|
|
||||||
|
def windowEnumerationHandler(hwnd, resultList):
|
||||||
|
'''Callback for win32gui.EnumWindows() to generate list of window handles.'''
|
||||||
|
resultList.append((hwnd, win32gui.GetWindowText(hwnd)))
|
||||||
|
|
||||||
|
unique_name = 'unique name for finding this window'
|
||||||
|
real_name = window.get_title()
|
||||||
|
window.set_title(unique_name)
|
||||||
|
tl_windows = []
|
||||||
|
win32gui.EnumWindows(windowEnumerationHandler, tl_windows)
|
||||||
|
|
||||||
|
for w in tl_windows:
|
||||||
|
if w[1] == unique_name:
|
||||||
|
win32gui.SetWindowPos(w[0], win32con.HWND_TOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE|win32con.SWP_NOSIZE)
|
||||||
|
# notify_id = (w[0],
|
||||||
|
# 0,
|
||||||
|
# win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP,
|
||||||
|
# win32con.WM_USER+20,
|
||||||
|
# 0,
|
||||||
|
# '')
|
||||||
|
# win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, notify_id)
|
||||||
|
#
|
||||||
|
window.set_title(real_name)
|
||||||
|
|
||||||
class Stat_Window:
|
class Stat_Window:
|
||||||
|
|
||||||
def button_press_cb(self, widget, event, *args):
|
def button_press_cb(self, widget, event, *args):
|
||||||
|
@ -101,7 +188,7 @@ class Stat_Window:
|
||||||
if event.button == 1: # left button event
|
if event.button == 1: # left button event
|
||||||
if event.type == gtk.gdk.BUTTON_PRESS: # left button single click
|
if event.type == gtk.gdk.BUTTON_PRESS: # left button single click
|
||||||
if self.sb_click > 0: return
|
if self.sb_click > 0: return
|
||||||
self.sb_click = gobject.timeout_add(250, self.single_click)
|
self.sb_click = gobject.timeout_add(250, self.single_click, widget)
|
||||||
elif event.type == gtk.gdk._2BUTTON_PRESS: # left button double click
|
elif event.type == gtk.gdk._2BUTTON_PRESS: # left button double click
|
||||||
if self.sb_click > 0:
|
if self.sb_click > 0:
|
||||||
gobject.source_remove(self.sb_click)
|
gobject.source_remove(self.sb_click)
|
||||||
|
@ -109,17 +196,20 @@ class Stat_Window:
|
||||||
self.double_click(widget, event, *args)
|
self.double_click(widget, event, *args)
|
||||||
|
|
||||||
if event.button == 2: # middle button event
|
if event.button == 2: # middle button event
|
||||||
print "middle button clicked"
|
pass
|
||||||
|
# print "middle button clicked"
|
||||||
|
|
||||||
if event.button == 3: # right button event
|
if event.button == 3: # right button event
|
||||||
print "right button clicked"
|
pass
|
||||||
|
# print "right button clicked"
|
||||||
|
|
||||||
def single_click(self):
|
def single_click(self, widget):
|
||||||
# Callback from the timeout in the single-click finding part of the
|
# Callback from the timeout in the single-click finding part of the
|
||||||
# button press call back. This needs to be modified to get all the
|
# button press call back. This needs to be modified to get all the
|
||||||
# arguments from the call.
|
# arguments from the call.
|
||||||
print "left button clicked"
|
# print "left button clicked"
|
||||||
self.sb_click = 0
|
self.sb_click = 0
|
||||||
|
Popup_window(widget, self)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def double_click(self, widget, event, *args):
|
def double_click(self, widget, event, *args):
|
||||||
|
@ -136,13 +226,14 @@ class Stat_Window:
|
||||||
top.set_decorated(1)
|
top.set_decorated(1)
|
||||||
top.move(x, y)
|
top.move(x, y)
|
||||||
|
|
||||||
def __init__(self, game, table, seat, x, y, player_id, font):
|
def __init__(self, parent, game, table, seat, x, y, player_id, font):
|
||||||
self.game = game
|
self.parent = parent # Hud object that this stat window belongs to
|
||||||
self.table = table
|
self.game = game # Configuration object for the curren
|
||||||
self.x = x + table.x
|
self.table = table # Table object where this is going
|
||||||
self.y = y + table.y
|
self.x = x + table.x # table.x and y are the location of the table
|
||||||
self.player_id = player_id
|
self.y = y + table.y # x and y are the location relative to table.x & y
|
||||||
self.sb_click = 0
|
self.player_id = player_id # looks like this isn't used ;)
|
||||||
|
self.sb_click = 0 # used to figure out button clicks
|
||||||
|
|
||||||
self.window = gtk.Window()
|
self.window = gtk.Window()
|
||||||
self.window.set_decorated(0)
|
self.window.set_decorated(0)
|
||||||
|
@ -163,7 +254,7 @@ class Stat_Window:
|
||||||
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() )
|
||||||
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 = 1, ypadding = 1)
|
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.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)
|
||||||
|
@ -172,10 +263,173 @@ class Stat_Window:
|
||||||
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()
|
||||||
|
# set_keep_above(1) for windows
|
||||||
|
if os.name == 'nt': self.topify_window(self.window)
|
||||||
|
|
||||||
|
def topify_window(self, window):
|
||||||
|
"""Set the specified gtk window to stayontop in MS Windows."""
|
||||||
|
|
||||||
|
def windowEnumerationHandler(hwnd, resultList):
|
||||||
|
'''Callback for win32gui.EnumWindows() to generate list of window handles.'''
|
||||||
|
resultList.append((hwnd, win32gui.GetWindowText(hwnd)))
|
||||||
|
|
||||||
|
unique_name = 'unique name for finding this window'
|
||||||
|
real_name = window.get_title()
|
||||||
|
window.set_title(unique_name)
|
||||||
|
tl_windows = []
|
||||||
|
win32gui.EnumWindows(windowEnumerationHandler, tl_windows)
|
||||||
|
|
||||||
|
for w in tl_windows:
|
||||||
|
if w[1] == unique_name:
|
||||||
|
win32gui.SetWindowPos(w[0], win32con.HWND_TOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE|win32con.SWP_NOSIZE)
|
||||||
|
# notify_id = (w[0],
|
||||||
|
# 0,
|
||||||
|
# win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP,
|
||||||
|
# win32con.WM_USER+20,
|
||||||
|
# 0,
|
||||||
|
# '')
|
||||||
|
# win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, notify_id)
|
||||||
|
#
|
||||||
|
window.set_title(real_name)
|
||||||
|
|
||||||
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()
|
||||||
|
|
||||||
|
class Popup_window:
|
||||||
|
def __init__(self, parent, stat_window):
|
||||||
|
self.sb_click = 0
|
||||||
|
|
||||||
|
# create the popup window
|
||||||
|
self.window = gtk.Window()
|
||||||
|
self.window.set_decorated(0)
|
||||||
|
self.window.set_gravity(gtk.gdk.GRAVITY_STATIC)
|
||||||
|
self.window.set_keep_above(1)
|
||||||
|
self.window.set_title("popup")
|
||||||
|
self.window.set_property("skip-taskbar-hint", True)
|
||||||
|
self.window.set_transient_for(parent.get_toplevel())
|
||||||
|
self.window.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
|
||||||
|
|
||||||
|
self.ebox = gtk.EventBox()
|
||||||
|
self.ebox.connect("button_press_event", self.button_press_cb)
|
||||||
|
self.lab = gtk.Label("stuff\nstuff\nstuff")
|
||||||
|
|
||||||
|
# need an event box so we can respond to clicks
|
||||||
|
self.window.add(self.ebox)
|
||||||
|
self.ebox.add(self.lab)
|
||||||
|
self.window.realize
|
||||||
|
|
||||||
|
# figure out the row, col address of the click that activated the popup
|
||||||
|
row = 0
|
||||||
|
col = 0
|
||||||
|
for r in range(0, stat_window.game.rows):
|
||||||
|
for c in range(0, stat_window.game.cols):
|
||||||
|
if stat_window.e_box[r][c] == parent:
|
||||||
|
row = r
|
||||||
|
col = c
|
||||||
|
break
|
||||||
|
|
||||||
|
# figure out what popup format we're using
|
||||||
|
popup_format = "default"
|
||||||
|
for stat in stat_window.game.stats.keys():
|
||||||
|
if stat_window.game.stats[stat].row == row and stat_window.game.stats[stat].col == col:
|
||||||
|
popup_format = stat_window.game.stats[stat].popup
|
||||||
|
break
|
||||||
|
|
||||||
|
# get the list of stats to be presented from the config
|
||||||
|
stat_list = []
|
||||||
|
for w in stat_window.parent.config.popup_windows.keys():
|
||||||
|
if w == popup_format:
|
||||||
|
stat_list = stat_window.parent.config.popup_windows[w].pu_stats
|
||||||
|
break
|
||||||
|
|
||||||
|
# get a database connection
|
||||||
|
db_connection = Database.Database(stat_window.parent.config, stat_window.parent.db_name, 'temp')
|
||||||
|
|
||||||
|
# calculate the stat_dict and then create the text for the pu
|
||||||
|
# stat_dict = db_connection.get_stats_from_hand(stat_window.parent.hand, stat_window.player_id)
|
||||||
|
stat_dict = db_connection.get_stats_from_hand(stat_window.parent.hand)
|
||||||
|
db_connection.close_connection()
|
||||||
|
|
||||||
|
pu_text = ""
|
||||||
|
for s in stat_list:
|
||||||
|
number = Stats.do_stat(stat_dict, player = int(stat_window.player_id), stat = s)
|
||||||
|
pu_text += number[3] + "\n"
|
||||||
|
|
||||||
|
self.lab.set_text(pu_text)
|
||||||
|
self.window.show_all()
|
||||||
|
# set_keep_above(1) for windows
|
||||||
|
if os.name == 'nt': self.topify_window(self.window)
|
||||||
|
|
||||||
|
def button_press_cb(self, widget, event, *args):
|
||||||
|
# This handles all callbacks from button presses on the event boxes in
|
||||||
|
# the popup windows. There is a bit of an ugly kludge to separate single-
|
||||||
|
# and double-clicks. This is the same code as in the Stat_window class
|
||||||
|
if event.button == 1: # left button event
|
||||||
|
if event.type == gtk.gdk.BUTTON_PRESS: # left button single click
|
||||||
|
if self.sb_click > 0: return
|
||||||
|
self.sb_click = gobject.timeout_add(250, self.single_click, widget)
|
||||||
|
elif event.type == gtk.gdk._2BUTTON_PRESS: # left button double click
|
||||||
|
if self.sb_click > 0:
|
||||||
|
gobject.source_remove(self.sb_click)
|
||||||
|
self.sb_click = 0
|
||||||
|
self.double_click(widget, event, *args)
|
||||||
|
|
||||||
|
if event.button == 2: # middle button event
|
||||||
|
pass
|
||||||
|
# print "middle button clicked"
|
||||||
|
|
||||||
|
if event.button == 3: # right button event
|
||||||
|
pass
|
||||||
|
# print "right button clicked"
|
||||||
|
|
||||||
|
def single_click(self, widget):
|
||||||
|
# Callback from the timeout in the single-click finding part of the
|
||||||
|
# button press call back. This needs to be modified to get all the
|
||||||
|
# arguments from the call.
|
||||||
|
self.sb_click = 0
|
||||||
|
self.window.destroy()
|
||||||
|
return False
|
||||||
|
|
||||||
|
def double_click(self, widget, event, *args):
|
||||||
|
self.toggle_decorated(widget)
|
||||||
|
|
||||||
|
def toggle_decorated(self, widget):
|
||||||
|
top = widget.get_toplevel()
|
||||||
|
(x, y) = top.get_position()
|
||||||
|
|
||||||
|
if top.get_decorated():
|
||||||
|
top.set_decorated(0)
|
||||||
|
top.move(x, y)
|
||||||
|
else:
|
||||||
|
top.set_decorated(1)
|
||||||
|
top.move(x, y)
|
||||||
|
|
||||||
|
def topify_window(self, window):
|
||||||
|
"""Set the specified gtk window to stayontop in MS Windows."""
|
||||||
|
|
||||||
|
def windowEnumerationHandler(hwnd, resultList):
|
||||||
|
'''Callback for win32gui.EnumWindows() to generate list of window handles.'''
|
||||||
|
resultList.append((hwnd, win32gui.GetWindowText(hwnd)))
|
||||||
|
|
||||||
|
unique_name = 'unique name for finding this window'
|
||||||
|
real_name = window.get_title()
|
||||||
|
window.set_title(unique_name)
|
||||||
|
tl_windows = []
|
||||||
|
win32gui.EnumWindows(windowEnumerationHandler, tl_windows)
|
||||||
|
|
||||||
|
for w in tl_windows:
|
||||||
|
if w[1] == unique_name:
|
||||||
|
win32gui.SetWindowPos(w[0], win32con.HWND_TOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE|win32con.SWP_NOSIZE)
|
||||||
|
# notify_id = (w[0],
|
||||||
|
# 0,
|
||||||
|
# win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP,
|
||||||
|
# win32con.WM_USER+20,
|
||||||
|
# 0,
|
||||||
|
# '')
|
||||||
|
# win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, notify_id)
|
||||||
|
#
|
||||||
|
window.set_title(real_name)
|
||||||
|
|
||||||
if __name__== "__main__":
|
if __name__== "__main__":
|
||||||
main_window = gtk.Window()
|
main_window = gtk.Window()
|
||||||
main_window.connect("destroy", destroy)
|
main_window.connect("destroy", destroy)
|
||||||
|
@ -187,15 +441,6 @@ if __name__== "__main__":
|
||||||
tables = Tables.discover(c)
|
tables = Tables.discover(c)
|
||||||
db = Database.Database(c, 'fpdb', 'holdem')
|
db = Database.Database(c, 'fpdb', 'holdem')
|
||||||
|
|
||||||
for attr in dir(Stats):
|
|
||||||
if attr.startswith('__'): continue
|
|
||||||
if attr == 'Configuration' or attr == 'Database': continue
|
|
||||||
if attr == 'GInitiallyUnowned': continue
|
|
||||||
# print Stats.attr.__doc__
|
|
||||||
|
|
||||||
print Stats.vpip.__doc__
|
|
||||||
|
|
||||||
|
|
||||||
for t in tables:
|
for t in tables:
|
||||||
win = Hud(t, 8, c, db)
|
win = Hud(t, 8, c, db)
|
||||||
# t.get_details()
|
# t.get_details()
|
||||||
|
|
|
@ -105,7 +105,8 @@ class MuckedList:
|
||||||
self.mucked_cards.update(model.get_value(iter, 0))
|
self.mucked_cards.update(model.get_value(iter, 0))
|
||||||
|
|
||||||
def update(self, new_hand_id):
|
def update(self, new_hand_id):
|
||||||
info_row = self.db_connection.get_hand_info(new_hand_id)
|
# info_row = self.db_connection.get_hand_info(new_hand_id)
|
||||||
|
info_row = ((new_hand_id, "xxxx", 0), )
|
||||||
iter = self.liststore.append(info_row[0])
|
iter = self.liststore.append(info_row[0])
|
||||||
sel = self.treeview.get_selection()
|
sel = self.treeview.get_selection()
|
||||||
sel.select_iter(iter)
|
sel.select_iter(iter)
|
||||||
|
@ -157,10 +158,14 @@ class MuckedCards:
|
||||||
|
|
||||||
self.parent.add(self.grid)
|
self.parent.add(self.grid)
|
||||||
|
|
||||||
|
def translate_cards(self, old_cards):
|
||||||
|
pass
|
||||||
|
|
||||||
def update(self, new_hand_id):
|
def update(self, new_hand_id):
|
||||||
cards = self.db_connection.get_cards(new_hand_id)
|
cards = self.db_connection.get_cards(new_hand_id)
|
||||||
self.clear()
|
self.clear()
|
||||||
|
|
||||||
|
cards = self.translate_cards(cards)
|
||||||
for c in cards.keys():
|
for c in cards.keys():
|
||||||
self.grid_contents[(1, cards[c]['seat_number'] - 1)].set_text(cards[c]['screen_name'])
|
self.grid_contents[(1, cards[c]['seat_number'] - 1)].set_text(cards[c]['screen_name'])
|
||||||
|
|
||||||
|
@ -224,7 +229,7 @@ if __name__== "__main__":
|
||||||
return(True)
|
return(True)
|
||||||
|
|
||||||
config = Configuration.Config()
|
config = Configuration.Config()
|
||||||
db_connection = Database.Database(config, 'PTrackSv2', 'razz')
|
db_connection = Database.Database(config, 'fpdb', '')
|
||||||
|
|
||||||
main_window = gtk.Window()
|
main_window = gtk.Window()
|
||||||
main_window.set_keep_above(True)
|
main_window.set_keep_above(True)
|
||||||
|
@ -236,4 +241,3 @@ if __name__== "__main__":
|
||||||
s_id = gobject.io_add_watch(sys.stdin, gobject.IO_IN, process_new_hand)
|
s_id = gobject.io_add_watch(sys.stdin, gobject.IO_IN, process_new_hand)
|
||||||
|
|
||||||
gtk.main()
|
gtk.main()
|
||||||
|
|
||||||
|
|
|
@ -173,10 +173,6 @@ class Sql:
|
||||||
|
|
||||||
self.query['get_stats_from_hand'] = """
|
self.query['get_stats_from_hand'] = """
|
||||||
SELECT HudCache.playerId AS player_id,
|
SELECT HudCache.playerId AS player_id,
|
||||||
HudCache.gametypeId AS gametypeId,
|
|
||||||
activeSeats AS n_active,
|
|
||||||
position AS position,
|
|
||||||
HudCache.tourneyTypeId AS tourneyTypeId,
|
|
||||||
sum(HDs) AS n,
|
sum(HDs) AS n,
|
||||||
sum(street0VPI) AS vpip,
|
sum(street0VPI) AS vpip,
|
||||||
sum(street0Aggr) AS pfr,
|
sum(street0Aggr) AS pfr,
|
||||||
|
@ -241,12 +237,18 @@ class Sql:
|
||||||
AND Hands.gametypeId = HudCache.gametypeId
|
AND Hands.gametypeId = HudCache.gametypeId
|
||||||
GROUP BY HudCache.PlayerId
|
GROUP BY HudCache.PlayerId
|
||||||
"""
|
"""
|
||||||
|
# AND PlayerId LIKE %s
|
||||||
|
# HudCache.gametypeId AS gametypeId,
|
||||||
|
# activeSeats AS n_active,
|
||||||
|
# position AS position,
|
||||||
|
# HudCache.tourneyTypeId AS tourneyTypeId,
|
||||||
|
|
||||||
self.query['get_players_from_hand'] = """
|
self.query['get_players_from_hand'] = """
|
||||||
SELECT HandsPlayers.playerId, seatNo, name
|
SELECT HandsPlayers.playerId, seatNo, name
|
||||||
FROM HandsPlayers INNER JOIN Players ON (HandsPlayers.playerId = Players.id)
|
FROM HandsPlayers INNER JOIN Players ON (HandsPlayers.playerId = Players.id)
|
||||||
WHERE handId = %s
|
WHERE handId = %s
|
||||||
"""
|
"""
|
||||||
|
# WHERE handId = %s AND Players.id LIKE %s
|
||||||
|
|
||||||
self.query['get_table_name'] = """
|
self.query['get_table_name'] = """
|
||||||
select tableName, maxSeats, category
|
select tableName, maxSeats, category
|
||||||
|
@ -255,6 +257,31 @@ class Sql:
|
||||||
and Gametypes.id = Hands.gametypeId
|
and Gametypes.id = Hands.gametypeId
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
self.query['get_cards'] = """
|
||||||
|
select
|
||||||
|
seatNo AS seat_number,
|
||||||
|
name AS screen_name,
|
||||||
|
card1Value, card1Suit,
|
||||||
|
card2Value, card2Suit,
|
||||||
|
card3Value, card3Suit,
|
||||||
|
card4Value, card4Suit,
|
||||||
|
card5Value, card5Suit,
|
||||||
|
card6Value, card6Suit,
|
||||||
|
card7Value, card7Suit
|
||||||
|
from HandsPlayers, Players
|
||||||
|
where handID = %s and HandsPlayers.playerId = Players.id
|
||||||
|
order by seatNo
|
||||||
|
"""
|
||||||
|
|
||||||
|
# self.query['get_hand_info'] = """
|
||||||
|
# SELECT
|
||||||
|
# game_id,
|
||||||
|
# CONCAT(hole_card_1, hole_card_2, hole_card_3, hole_card_4, hole_card_5, hole_card_6, hole_card_7) AS hand,
|
||||||
|
# total_won-total_bet AS net
|
||||||
|
# FROM game_players
|
||||||
|
# WHERE game_id = %s AND player_id = 3
|
||||||
|
# """
|
||||||
|
|
||||||
if __name__== "__main__":
|
if __name__== "__main__":
|
||||||
# just print the default queries and exit
|
# just print the default queries and exit
|
||||||
s = Sql(game = 'razz', type = 'ptracks')
|
s = Sql(game = 'razz', type = 'ptracks')
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
# 6 For each stat you make add a line to the __main__ function to test it.
|
# 6 For each stat you make add a line to the __main__ function to test it.
|
||||||
|
|
||||||
# Standard Library modules
|
# Standard Library modules
|
||||||
|
#import sys
|
||||||
|
|
||||||
# pyGTK modules
|
# pyGTK modules
|
||||||
import pygtk
|
import pygtk
|
||||||
|
@ -55,10 +56,6 @@ import Database
|
||||||
def do_tip(widget, tip):
|
def do_tip(widget, tip):
|
||||||
widget.set_tooltip_text(tip)
|
widget.set_tooltip_text(tip)
|
||||||
|
|
||||||
def list_stats():
|
|
||||||
for key in dir():
|
|
||||||
print key
|
|
||||||
|
|
||||||
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:
|
||||||
|
@ -72,9 +69,7 @@ def do_stat(stat_dict, player = 24, stat = 'vpip'):
|
||||||
###########################################
|
###########################################
|
||||||
# functions that return individual stats
|
# functions that return individual stats
|
||||||
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
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['vpip'])/float(stat_dict[player]['n'])
|
stat = float(stat_dict[player]['vpip'])/float(stat_dict[player]['n'])
|
||||||
|
@ -94,6 +89,7 @@ def vpip(stat_dict, player):
|
||||||
)
|
)
|
||||||
|
|
||||||
def pfr(stat_dict, player):
|
def pfr(stat_dict, player):
|
||||||
|
""" Preflop (3rd street) raise."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['pfr'])/float(stat_dict[player]['n'])
|
stat = float(stat_dict[player]['pfr'])/float(stat_dict[player]['n'])
|
||||||
|
@ -114,6 +110,7 @@ def pfr(stat_dict, player):
|
||||||
)
|
)
|
||||||
|
|
||||||
def wtsd(stat_dict, player):
|
def wtsd(stat_dict, player):
|
||||||
|
""" Went to SD when saw flop/4th."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['sd'])/float(stat_dict[player]['saw_f'])
|
stat = float(stat_dict[player]['sd'])/float(stat_dict[player]['saw_f'])
|
||||||
|
@ -134,6 +131,7 @@ def wtsd(stat_dict, player):
|
||||||
)
|
)
|
||||||
|
|
||||||
def wmsd(stat_dict, player):
|
def wmsd(stat_dict, player):
|
||||||
|
""" Won $ at showdown."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['wmsd'])/float(stat_dict[player]['sd'])
|
stat = float(stat_dict[player]['wmsd'])/float(stat_dict[player]['sd'])
|
||||||
|
@ -141,7 +139,7 @@ def wmsd(stat_dict, player):
|
||||||
'%3.1f' % (100*stat) + '%',
|
'%3.1f' % (100*stat) + '%',
|
||||||
'w=%3.1f' % (100*stat) + '%',
|
'w=%3.1f' % (100*stat) + '%',
|
||||||
'wmsd=%3.1f' % (100*stat) + '%',
|
'wmsd=%3.1f' % (100*stat) + '%',
|
||||||
'(%d/%d)' % (stat_dict[player]['wmsd'], stat_dict[player]['sd']),
|
'(%f5.0/%d)' % (stat_dict[player]['wmsd'], stat_dict[player]['sd']),
|
||||||
'% won money at showdown'
|
'% won money at showdown'
|
||||||
)
|
)
|
||||||
except:
|
except:
|
||||||
|
@ -154,6 +152,7 @@ def wmsd(stat_dict, player):
|
||||||
)
|
)
|
||||||
|
|
||||||
def saw_f(stat_dict, player):
|
def saw_f(stat_dict, player):
|
||||||
|
""" Saw flop/4th."""
|
||||||
try:
|
try:
|
||||||
num = float(stat_dict[player]['saw_f'])
|
num = float(stat_dict[player]['saw_f'])
|
||||||
den = float(stat_dict[player]['n'])
|
den = float(stat_dict[player]['n'])
|
||||||
|
@ -178,6 +177,7 @@ def saw_f(stat_dict, player):
|
||||||
)
|
)
|
||||||
|
|
||||||
def n(stat_dict, player):
|
def n(stat_dict, player):
|
||||||
|
""" Number of hands played."""
|
||||||
try:
|
try:
|
||||||
return (stat_dict[player]['n'],
|
return (stat_dict[player]['n'],
|
||||||
'%d' % (stat_dict[player]['n']),
|
'%d' % (stat_dict[player]['n']),
|
||||||
|
@ -187,15 +187,16 @@ def n(stat_dict, player):
|
||||||
'number hands seen'
|
'number hands seen'
|
||||||
)
|
)
|
||||||
except:
|
except:
|
||||||
return (stat_dict[player][0],
|
return (0,
|
||||||
'%d' % (stat_dict[player][0]),
|
'%d' % (0),
|
||||||
'n=%d' % (stat_dict[player][0]),
|
'n=%d' % (0),
|
||||||
'n=%d' % (stat_dict[player][0]),
|
'n=%d' % (0),
|
||||||
'(%d)' % (stat_dict[player][0]),
|
'(%d)' % (0),
|
||||||
'number hands seen'
|
'number hands seen'
|
||||||
)
|
)
|
||||||
|
|
||||||
def fold_f(stat_dict, player):
|
def fold_f(stat_dict, player):
|
||||||
|
""" Folded flop/4th."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['fold_2'])/fold(stat_dict[player]['saw_f'])
|
stat = float(stat_dict[player]['fold_2'])/fold(stat_dict[player]['saw_f'])
|
||||||
|
@ -216,6 +217,7 @@ def fold_f(stat_dict, player):
|
||||||
)
|
)
|
||||||
|
|
||||||
def steal(stat_dict, player):
|
def steal(stat_dict, player):
|
||||||
|
""" Steal %."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['steal'])/float(stat_dict[player]['steal_opp'])
|
stat = float(stat_dict[player]['steal'])/float(stat_dict[player]['steal_opp'])
|
||||||
|
@ -236,6 +238,7 @@ def steal(stat_dict, player):
|
||||||
)
|
)
|
||||||
|
|
||||||
def f_SB_steal(stat_dict, player):
|
def f_SB_steal(stat_dict, player):
|
||||||
|
""" Folded SB to steal."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['SBnotDef'])/float(stat_dict[player]['SBstolen'])
|
stat = float(stat_dict[player]['SBnotDef'])/float(stat_dict[player]['SBstolen'])
|
||||||
|
@ -256,6 +259,7 @@ def f_SB_steal(stat_dict, player):
|
||||||
)
|
)
|
||||||
|
|
||||||
def f_BB_steal(stat_dict, player):
|
def f_BB_steal(stat_dict, player):
|
||||||
|
""" Folded BB to steal."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['BBnotDef'])/float(stat_dict[player]['BBstolen'])
|
stat = float(stat_dict[player]['BBnotDef'])/float(stat_dict[player]['BBstolen'])
|
||||||
|
@ -276,6 +280,7 @@ def f_BB_steal(stat_dict, player):
|
||||||
)
|
)
|
||||||
|
|
||||||
def three_B_0(stat_dict, player):
|
def three_B_0(stat_dict, player):
|
||||||
|
""" Three bet preflop/3rd."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['TB_0'])/float(stat_dict[player]['TB_opp_0'])
|
stat = float(stat_dict[player]['TB_0'])/float(stat_dict[player]['TB_opp_0'])
|
||||||
|
@ -296,6 +301,7 @@ def three_B_0(stat_dict, player):
|
||||||
)
|
)
|
||||||
|
|
||||||
def WMsF(stat_dict, player):
|
def WMsF(stat_dict, player):
|
||||||
|
""" Won $ when saw flop/4th."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['w_w_s_1'])/float(stat_dict[player]['saw_1'])
|
stat = float(stat_dict[player]['w_w_s_1'])/float(stat_dict[player]['saw_1'])
|
||||||
|
@ -316,6 +322,7 @@ def WMsF(stat_dict, player):
|
||||||
)
|
)
|
||||||
|
|
||||||
def a_freq_1(stat_dict, player):
|
def a_freq_1(stat_dict, player):
|
||||||
|
""" Flop/4th aggression frequency."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['aggr_1'])/float(stat_dict[player]['saw_f'])
|
stat = float(stat_dict[player]['aggr_1'])/float(stat_dict[player]['saw_f'])
|
||||||
|
@ -336,6 +343,7 @@ def a_freq_1(stat_dict, player):
|
||||||
)
|
)
|
||||||
|
|
||||||
def a_freq_2(stat_dict, player):
|
def a_freq_2(stat_dict, player):
|
||||||
|
""" Turn/5th aggression frequency."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['aggr_2'])/float(stat_dict[player]['saw_2'])
|
stat = float(stat_dict[player]['aggr_2'])/float(stat_dict[player]['saw_2'])
|
||||||
|
@ -356,6 +364,7 @@ def a_freq_2(stat_dict, player):
|
||||||
)
|
)
|
||||||
|
|
||||||
def a_freq_3(stat_dict, player):
|
def a_freq_3(stat_dict, player):
|
||||||
|
""" River/6th aggression frequency."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['aggr_3'])/float(stat_dict[player]['saw_3'])
|
stat = float(stat_dict[player]['aggr_3'])/float(stat_dict[player]['saw_3'])
|
||||||
|
@ -376,6 +385,7 @@ def a_freq_3(stat_dict, player):
|
||||||
)
|
)
|
||||||
|
|
||||||
def a_freq_4(stat_dict, player):
|
def a_freq_4(stat_dict, player):
|
||||||
|
""" 7th street aggression frequency."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['aggr_4'])/float(stat_dict[player]['saw_4'])
|
stat = float(stat_dict[player]['aggr_4'])/float(stat_dict[player]['saw_4'])
|
||||||
|
@ -389,13 +399,14 @@ def a_freq_4(stat_dict, player):
|
||||||
except:
|
except:
|
||||||
return (stat,
|
return (stat,
|
||||||
'%3.1f' % (0) + '%',
|
'%3.1f' % (0) + '%',
|
||||||
'a1=%3.1f' % (0) + '%',
|
'a4=%3.1f' % (0) + '%',
|
||||||
'a_fq_1=%3.1f' % (0) + '%',
|
'a_fq_4=%3.1f' % (0) + '%',
|
||||||
'(%d/%d)' % (0, 0),
|
'(%d/%d)' % (0, 0),
|
||||||
'Aggression Freq flop/4th'
|
'Aggression Freq flop/4th'
|
||||||
)
|
)
|
||||||
|
|
||||||
def cb_1(stat_dict, player):
|
def cb_1(stat_dict, player):
|
||||||
|
""" Flop continuation bet."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['CB_1'])/float(stat_dict[player]['CB_opp_1'])
|
stat = float(stat_dict[player]['CB_1'])/float(stat_dict[player]['CB_opp_1'])
|
||||||
|
@ -416,6 +427,7 @@ def cb_1(stat_dict, player):
|
||||||
)
|
)
|
||||||
|
|
||||||
def cb_2(stat_dict, player):
|
def cb_2(stat_dict, player):
|
||||||
|
""" Turn continuation bet."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['CB_2'])/float(stat_dict[player]['CB_opp_2'])
|
stat = float(stat_dict[player]['CB_2'])/float(stat_dict[player]['CB_opp_2'])
|
||||||
|
@ -436,6 +448,7 @@ def cb_2(stat_dict, player):
|
||||||
)
|
)
|
||||||
|
|
||||||
def cb_3(stat_dict, player):
|
def cb_3(stat_dict, player):
|
||||||
|
""" River continuation bet."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['CB_3'])/float(stat_dict[player]['CB_opp_3'])
|
stat = float(stat_dict[player]['CB_3'])/float(stat_dict[player]['CB_opp_3'])
|
||||||
|
@ -456,6 +469,7 @@ def cb_3(stat_dict, player):
|
||||||
)
|
)
|
||||||
|
|
||||||
def cb_4(stat_dict, player):
|
def cb_4(stat_dict, player):
|
||||||
|
""" 7th street continuation bet."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['CB_4'])/float(stat_dict[player]['CB_opp_4'])
|
stat = float(stat_dict[player]['CB_4'])/float(stat_dict[player]['CB_opp_4'])
|
||||||
|
@ -476,6 +490,7 @@ def cb_4(stat_dict, player):
|
||||||
)
|
)
|
||||||
|
|
||||||
def ffreq_1(stat_dict, player):
|
def ffreq_1(stat_dict, player):
|
||||||
|
""" Flop/4th fold frequency."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['f_freq_1'])/float(stat_dict[player]['was_raised_1'])
|
stat = float(stat_dict[player]['f_freq_1'])/float(stat_dict[player]['was_raised_1'])
|
||||||
|
@ -496,6 +511,7 @@ def ffreq_1(stat_dict, player):
|
||||||
)
|
)
|
||||||
|
|
||||||
def ffreq_2(stat_dict, player):
|
def ffreq_2(stat_dict, player):
|
||||||
|
""" Turn/5th fold frequency."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['f_freq_2'])/float(stat_dict[player]['was_raised_2'])
|
stat = float(stat_dict[player]['f_freq_2'])/float(stat_dict[player]['was_raised_2'])
|
||||||
|
@ -516,6 +532,7 @@ def ffreq_2(stat_dict, player):
|
||||||
)
|
)
|
||||||
|
|
||||||
def ffreq_3(stat_dict, player):
|
def ffreq_3(stat_dict, player):
|
||||||
|
""" River/6th fold frequency."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['f_freq_3'])/float(stat_dict[player]['was_raised_3'])
|
stat = float(stat_dict[player]['f_freq_3'])/float(stat_dict[player]['was_raised_3'])
|
||||||
|
@ -536,6 +553,7 @@ def ffreq_3(stat_dict, player):
|
||||||
)
|
)
|
||||||
|
|
||||||
def ffreq_4(stat_dict, player):
|
def ffreq_4(stat_dict, player):
|
||||||
|
""" 7th fold frequency."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
try:
|
try:
|
||||||
stat = float(stat_dict[player]['f_freq_4'])/float(stat_dict[player]['was_raised_4'])
|
stat = float(stat_dict[player]['f_freq_4'])/float(stat_dict[player]['was_raised_4'])
|
||||||
|
@ -559,7 +577,7 @@ if __name__== "__main__":
|
||||||
c = Configuration.Config()
|
c = Configuration.Config()
|
||||||
db_connection = Database.Database(c, 'fpdb', 'holdem')
|
db_connection = Database.Database(c, 'fpdb', 'holdem')
|
||||||
h = db_connection.get_last_hand()
|
h = db_connection.get_last_hand()
|
||||||
stat_dict = db_connection.get_stats_from_hand(h, 0)
|
stat_dict = db_connection.get_stats_from_hand(h)
|
||||||
|
|
||||||
for player in stat_dict.keys():
|
for player in stat_dict.keys():
|
||||||
print "player = ", player, do_stat(stat_dict, player = player, stat = 'vpip')
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'vpip')
|
||||||
|
@ -587,13 +605,14 @@ if __name__== "__main__":
|
||||||
print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_3')
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_3')
|
||||||
print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_4')
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_4')
|
||||||
|
|
||||||
# print "\n\nLegal stats:"
|
print "\n\nLegal stats:"
|
||||||
# for attr in dir():
|
for attr in dir():
|
||||||
# if attr.startswith('__'): continue
|
if attr.startswith('__'): continue
|
||||||
# if attr == 'Configuration' or attr == 'Database': continue
|
if attr in ("Configuration", "Database", "GInitiallyUnowned", "gtk", "pygtk",
|
||||||
# if attr == 'GInitiallyUnowned': continue
|
"player", "c", "db_connection", "do_stat", "do_tip", "stat_dict",
|
||||||
# print attr.__doc__
|
"h"): continue
|
||||||
#
|
print attr, eval("%s.__doc__" % (attr))
|
||||||
# print vpip.__doc__
|
# print " <pu_stat pu_stat_name = \"%s\"> </pu_stat>" % (attr)
|
||||||
|
|
||||||
db_connection.close
|
db_connection.close
|
||||||
|
|
||||||
|
|
100
pyfpdb/Tables.py
100
pyfpdb/Tables.py
|
@ -26,8 +26,14 @@ of Table_Window objects representing the windows found.
|
||||||
|
|
||||||
# Standard Library modules
|
# Standard Library modules
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
# Win32 modules
|
||||||
|
|
||||||
|
if os.name == 'nt':
|
||||||
|
import win32gui
|
||||||
|
|
||||||
# FreePokerTools modules
|
# FreePokerTools modules
|
||||||
import Configuration
|
import Configuration
|
||||||
|
|
||||||
|
@ -49,8 +55,24 @@ class Table_Window:
|
||||||
table.tournament = 0
|
table.tournament = 0
|
||||||
|
|
||||||
def discover(c):
|
def discover(c):
|
||||||
|
if os.name == 'posix':
|
||||||
|
tables = discover_posix(c)
|
||||||
|
return tables
|
||||||
|
elif os.name == 'nt':
|
||||||
|
tables = discover_nt(c)
|
||||||
|
return tables
|
||||||
|
elif ox.name == 'mac':
|
||||||
|
tables = discover_mac(c)
|
||||||
|
return tables
|
||||||
|
else: tables = {}
|
||||||
|
|
||||||
|
return(tables)
|
||||||
|
|
||||||
|
def discover_posix(c):
|
||||||
|
""" Poker client table window finder for posix/Linux = XWindows."""
|
||||||
tables = {}
|
tables = {}
|
||||||
for listing in os.popen('xwininfo -root -tree').readlines():
|
for listing in os.popen('xwininfo -root -tree').readlines():
|
||||||
|
# xwininfo -root -tree -id 0xnnnnn gets the info on a single window
|
||||||
if re.search('Lobby', listing): continue
|
if re.search('Lobby', listing): continue
|
||||||
if re.search('Instant Hand History', listing): continue
|
if re.search('Instant Hand History', listing): continue
|
||||||
if not re.search('Logged In as ', listing): continue
|
if not re.search('Logged In as ', listing): continue
|
||||||
|
@ -75,6 +97,68 @@ def discover(c):
|
||||||
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
|
||||||
|
#
|
||||||
|
# The discover_xx functions query the system and report on the poker clients
|
||||||
|
# currently displayed on the screen. The discover_posix should give you
|
||||||
|
# some idea how to support other systems.
|
||||||
|
#
|
||||||
|
# discover_xx() returns a dict of TableWindow objects--one TableWindow
|
||||||
|
# object for each poker client table on the screen.
|
||||||
|
#
|
||||||
|
# Each TableWindow object must have the following attributes correctly populated:
|
||||||
|
# tw.site = the site name, e.g. PokerStars, FullTilt. This must match the site
|
||||||
|
# name specified in the config file.
|
||||||
|
# tw.number = This is the system id number for the client table window in the
|
||||||
|
# format that the system presents it.
|
||||||
|
# tw.title = The full title from the window title bar.
|
||||||
|
# tw.width, tw.height = The width and height of the window in pixels. This is
|
||||||
|
# the internal width and height, not including the title bar and
|
||||||
|
# window borders.
|
||||||
|
# tw.x, tw.y = The x, y (horizontal, vertical) location of the window relative
|
||||||
|
# to the top left of the display screen. This also does not include the
|
||||||
|
# title bar and window borders. To put it another way, this is the
|
||||||
|
# screen location of (0, 0) in the working window.
|
||||||
|
|
||||||
|
def win_enum_handler(hwnd, titles):
|
||||||
|
titles[hwnd] = win32gui.GetWindowText(hwnd)
|
||||||
|
|
||||||
|
def child_enum_handler(hwnd, children):
|
||||||
|
print hwnd, win32.GetWindowRect(hwnd)
|
||||||
|
|
||||||
|
def discover_nt(c):
|
||||||
|
""" Poker client table window finder for Windows."""
|
||||||
|
#
|
||||||
|
# I cannot figure out how to get the inside dimensions of the poker table
|
||||||
|
# windows. So I just assume all borders are 3 thick and all title bars
|
||||||
|
# are 29 high. No doubt this will be off when used with certain themes.
|
||||||
|
#
|
||||||
|
b_width = 3
|
||||||
|
tb_height = 29
|
||||||
|
titles = {}
|
||||||
|
tables = {}
|
||||||
|
win32gui.EnumWindows(win_enum_handler, titles)
|
||||||
|
for hwnd in titles.keys():
|
||||||
|
if re.search('Logged In as', titles[hwnd]) and not re.search('Lobby', titles[hwnd]):
|
||||||
|
tw = Table_Window()
|
||||||
|
# tw.site = c.supported_sites[s].site_name
|
||||||
|
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
|
||||||
|
eval("%s(tw)" % "pokerstars_decode_table")
|
||||||
|
tw.site = "PokerStars"
|
||||||
|
|
||||||
|
|
||||||
|
tables[tw.name] = tw
|
||||||
|
return tables
|
||||||
|
|
||||||
|
def discover_mac(c):
|
||||||
|
""" Poker client table window finder for Macintosh."""
|
||||||
|
tables = {}
|
||||||
|
return tables
|
||||||
|
|
||||||
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
|
||||||
|
@ -95,18 +179,6 @@ def pokerstars_decode_table(tw):
|
||||||
|
|
||||||
mo = re.search('(Razz|Stud H/L|Stud|Omaha H/L|Omaha|Hold\'em|5-Card Draw|Triple Draw 2-7 Lowball)', tw.title)
|
mo = re.search('(Razz|Stud H/L|Stud|Omaha H/L|Omaha|Hold\'em|5-Card Draw|Triple Draw 2-7 Lowball)', tw.title)
|
||||||
|
|
||||||
#Traceback (most recent call last):
|
|
||||||
# File "/home/fatray/razz-poker-productio/HUD_main.py", line 41, in process_new_hand
|
|
||||||
# table_windows = Tables.discover(config)
|
|
||||||
# File "/home/fatray/razz-poker-productio/Tables.py", line 58, in discover
|
|
||||||
# eval("%s(tw)" % c.supported_sites[s].decoder)
|
|
||||||
# File "<string>", line 1, in <module>
|
|
||||||
# File "/home/fatray/razz-poker-productio/Tables.py", line 80, in pokerstars_decode_table
|
|
||||||
# tw.game = mo.group(1).lower()
|
|
||||||
#AttributeError: 'NoneType' object has no attribute 'group'
|
|
||||||
#
|
|
||||||
#This problem happens with observed windows!!
|
|
||||||
|
|
||||||
tw.game = mo.group(1).lower()
|
tw.game = mo.group(1).lower()
|
||||||
tw.game = re.sub('\'', '', tw.game)
|
tw.game = re.sub('\'', '', tw.game)
|
||||||
tw.game = re.sub('h/l', 'hi/lo', tw.game)
|
tw.game = re.sub('h/l', 'hi/lo', tw.game)
|
||||||
|
@ -132,4 +204,8 @@ if __name__=="__main__":
|
||||||
tables = discover(c)
|
tables = discover(c)
|
||||||
|
|
||||||
for t in tables.keys():
|
for t in tables.keys():
|
||||||
|
print "t = ", t
|
||||||
print tables[t]
|
print tables[t]
|
||||||
|
|
||||||
|
print "press enter to continue"
|
||||||
|
sys.stdin.readline()
|
||||||
|
|
|
@ -407,7 +407,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
|
||||||
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
||||||
self.window.connect("delete_event", self.delete_event)
|
self.window.connect("delete_event", self.delete_event)
|
||||||
self.window.connect("destroy", self.destroy)
|
self.window.connect("destroy", self.destroy)
|
||||||
self.window.set_title("Free Poker DB - version: alpha2+, p78")
|
self.window.set_title("Free Poker DB - version: alpha3, p80")
|
||||||
self.window.set_border_width(1)
|
self.window.set_border_width(1)
|
||||||
self.window.set_size_request(1020,400)
|
self.window.set_size_request(1020,400)
|
||||||
self.window.set_resizable(True)
|
self.window.set_resizable(True)
|
||||||
|
|
|
@ -25,6 +25,7 @@ class fpdb_db:
|
||||||
self.cursor=None
|
self.cursor=None
|
||||||
self.MYSQL_INNODB=2
|
self.MYSQL_INNODB=2
|
||||||
self.PGSQL=3
|
self.PGSQL=3
|
||||||
|
self.SQLITE=4
|
||||||
#end def __init__
|
#end def __init__
|
||||||
|
|
||||||
def connect(self, backend, host, database, user, password):
|
def connect(self, backend, host, database, user, password):
|
||||||
|
@ -39,8 +40,10 @@ class fpdb_db:
|
||||||
import MySQLdb
|
import MySQLdb
|
||||||
self.db=MySQLdb.connect(host = host, user = user, passwd = password, db = database)
|
self.db=MySQLdb.connect(host = host, user = user, passwd = password, db = database)
|
||||||
elif backend==self.PGSQL:
|
elif backend==self.PGSQL:
|
||||||
import pgdb
|
# import pgdb
|
||||||
self.db = pgdb.connect(dsn=host+":"+database, user='postgres', password=password)
|
# self.db = pgdb.connect(dsn=host+":"+database, user='postgres', password=password)
|
||||||
|
import psycopg2
|
||||||
|
self.db = psycopg2.connect(host = host, user = user, password = password, database = database)
|
||||||
else:
|
else:
|
||||||
raise fpdb_simple.FpdbError("unrecognised database backend:"+backend)
|
raise fpdb_simple.FpdbError("unrecognised database backend:"+backend)
|
||||||
self.cursor=self.db.cursor()
|
self.cursor=self.db.cursor()
|
||||||
|
@ -153,6 +156,24 @@ class fpdb_db:
|
||||||
|
|
||||||
def recreate_tables(self):
|
def recreate_tables(self):
|
||||||
"""(Re-)creates the tables of the current DB"""
|
"""(Re-)creates the tables of the current DB"""
|
||||||
|
|
||||||
|
if self.backend == 3:
|
||||||
|
# postgresql
|
||||||
|
print "recreating tables in postgres db"
|
||||||
|
schema_file = open('schema.postgres.sql', 'r')
|
||||||
|
schema = schema_file.read()
|
||||||
|
schema_file.close()
|
||||||
|
curse = self.db.cursor()
|
||||||
|
# curse.executemany(schema, [1, 2])
|
||||||
|
for sql in schema.split(';'):
|
||||||
|
sql = sql.rstrip()
|
||||||
|
if sql == '':
|
||||||
|
continue
|
||||||
|
curse.execute(sql)
|
||||||
|
self.db.commit()
|
||||||
|
curse.close()
|
||||||
|
return
|
||||||
|
|
||||||
self.drop_tables()
|
self.drop_tables()
|
||||||
|
|
||||||
self.create_table("""Settings (
|
self.create_table("""Settings (
|
||||||
|
|
21
pyfpdb/fpdb_import.py
Executable file → Normal file
21
pyfpdb/fpdb_import.py
Executable file → Normal file
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import MySQLdb
|
import MySQLdb
|
||||||
|
import psycopg2
|
||||||
#import pgdb
|
#import pgdb
|
||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
|
@ -37,7 +38,7 @@ def import_file(server, database, user, password, inputFile):
|
||||||
self.settings={'imp-callFpdbHud':False}
|
self.settings={'imp-callFpdbHud':False}
|
||||||
import_file_dict(self, settings)
|
import_file_dict(self, settings)
|
||||||
|
|
||||||
def import_file_dict(options, settings, callHud=True):
|
def import_file_dict(options, settings, callHud=False):
|
||||||
last_read_hand=0
|
last_read_hand=0
|
||||||
if (options.inputFile=="stdin"):
|
if (options.inputFile=="stdin"):
|
||||||
inputFile=sys.stdin
|
inputFile=sys.stdin
|
||||||
|
@ -45,8 +46,16 @@ def import_file_dict(options, settings, callHud=True):
|
||||||
inputFile=open(options.inputFile, "rU")
|
inputFile=open(options.inputFile, "rU")
|
||||||
|
|
||||||
#connect to DB
|
#connect to DB
|
||||||
db = MySQLdb.connect(host = options.server, user = options.user,
|
if options.settings['db-backend'] == 2:
|
||||||
|
db = MySQLdb.connect(host = options.server, user = options.user,
|
||||||
passwd = options.password, db = options.database)
|
passwd = options.password, db = options.database)
|
||||||
|
elif options.settings['db-backend'] == 3:
|
||||||
|
db = psycopg2.connect(host = options.server, user = options.user,
|
||||||
|
password = options.password, database = options.database)
|
||||||
|
elif options.settings['db-backend'] == 4:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
pass
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
|
|
||||||
if (not options.quiet):
|
if (not options.quiet):
|
||||||
|
@ -104,11 +113,13 @@ def import_file_dict(options, settings, callHud=True):
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
stored+=1
|
stored+=1
|
||||||
if settings['imp-callFpdbHud'] and callHud and os.sep=='/':
|
db.commit()
|
||||||
|
# if settings['imp-callFpdbHud'] and callHud and os.sep=='/':
|
||||||
|
if settings['imp-callFpdbHud'] and callHud:
|
||||||
#print "call to HUD here. handsId:",handsId
|
#print "call to HUD here. handsId:",handsId
|
||||||
#pipe the Hands.id out to the HUD
|
#pipe the Hands.id out to the HUD
|
||||||
options.pipe_to_hud.stdin.write("%s\n" % (handsId))
|
# options.pipe_to_hud.write("%s" % (handsId) + os.linesep)
|
||||||
db.commit()
|
options.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep)
|
||||||
except fpdb_simple.DuplicateError:
|
except fpdb_simple.DuplicateError:
|
||||||
duplicates+=1
|
duplicates+=1
|
||||||
except (ValueError), fe:
|
except (ValueError), fe:
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#This file contains simple functions for fpdb
|
#This file contains simple functions for fpdb
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
import re
|
||||||
|
|
||||||
PS=1
|
PS=1
|
||||||
FTP=2
|
FTP=2
|
||||||
|
@ -781,8 +782,10 @@ def parseHandStartTime(topline, site):
|
||||||
#print "parsehandStartTime, tmp:", tmp
|
#print "parsehandStartTime, tmp:", tmp
|
||||||
pos = tmp.find("-")+2
|
pos = tmp.find("-")+2
|
||||||
tmp = tmp[pos:]
|
tmp = tmp[pos:]
|
||||||
#print "year:", tmp[0:4], "month", tmp[5:7], "day", tmp[8:10], "hour", tmp[13:15], "minute", tmp[16:18], "second", tmp[19:21]
|
if re.search('\(ET\)', tmp): # the old datetime format at ps
|
||||||
result = datetime.datetime(int(tmp[0:4]), int(tmp[5:7]), int(tmp[8:10]), int(tmp[13:15]), int(tmp[16:18]), int(tmp[19:21]))
|
result = datetime.datetime(int(tmp[0:4]), int(tmp[5:7]), int(tmp[8:10]), int(tmp[13:15]), int(tmp[16:18]), int(tmp[19:21]))
|
||||||
|
else: # new format
|
||||||
|
result = datetime.datetime(int(tmp[0:4]), int(tmp[5:7]), int(tmp[8:10]), int(tmp[11:13]), int(tmp[14:16]), int(tmp[17:19]))
|
||||||
else:
|
else:
|
||||||
raise FpdbError("invalid site in parseHandStartTime")
|
raise FpdbError("invalid site in parseHandStartTime")
|
||||||
|
|
||||||
|
@ -1951,7 +1954,7 @@ def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData):
|
||||||
row[31], row[32], row[33], row[34], row[35], row[36], row[37], row[38], row[39], row[40],
|
row[31], row[32], row[33], row[34], row[35], row[36], row[37], row[38], row[39], row[40],
|
||||||
row[41], row[42], row[43], row[44], row[45], row[46], row[47], row[48], row[49], row[50],
|
row[41], row[42], row[43], row[44], row[45], row[46], row[47], row[48], row[49], row[50],
|
||||||
row[51], row[52], row[53], row[54], row[55], row[56], row[57], row[58], row[59], row[60],
|
row[51], row[52], row[53], row[54], row[55], row[56], row[57], row[58], row[59], row[60],
|
||||||
row[1], row[2], row[3], row[4], row[5]))
|
row[1], row[2], row[3], str(row[4]), row[5]))
|
||||||
# else:
|
# else:
|
||||||
# print "todo: implement storeHudCache for stud base"
|
# print "todo: implement storeHudCache for stud base"
|
||||||
#end def storeHudCache
|
#end def storeHudCache
|
||||||
|
|
217
pyfpdb/schema.postgres.sql
Normal file
217
pyfpdb/schema.postgres.sql
Normal file
|
@ -0,0 +1,217 @@
|
||||||
|
|
||||||
|
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),
|
||||||
|
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 (76);
|
||||||
|
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);
|
Loading…
Reference in New Issue
Block a user