diff --git a/ignore-me_perl6/LibFpdbImport.pm b/ignore-me_perl6/LibFpdbImport.pm
deleted file mode 100644
index ac7db336..00000000
--- a/ignore-me_perl6/LibFpdbImport.pm
+++ /dev/null
@@ -1,178 +0,0 @@
-#!/usr/bin/pugs
-
-#Copyright 2008 Steffen Jobbagy-Felso
-#This program is free software: you can redistribute it and/or modify
-#it under the terms of the GNU Affero General Public License as published by
-#the Free Software Foundation, version 3 of the License.
-#
-#This program is distributed in the hope that it will be useful,
-#but WITHOUT ANY WARRANTY; without even the implied warranty of
-#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-#GNU General Public License for more details.
-#
-#You should have received a copy of the GNU Affero General Public License
-#along with this program. If not, see .
-#In the "official" distribution you can find the license in
-#agpl-3.0.txt in the docs folder of the package.
-
-module LibFpdbImport;
-use v6;
-#use strict;
-use LibFpdbShared;
-#use LibFpdbImport2;
-
-class Player {
- has Str $name;
- has Int $start_cash;
- has Card @.cards;
- has Char $position;
-
- submethod BUILD (Str @strings) {
- say "todo: implement Player.BUILD";
- }#end Player.BUILD
-
- our Player method find_players(@strings) {
- #todo: i think this should be sub since its a class method not an instance method
- say "todo: implement Player.find_players";
- }
-}#end class Player
-
-class Line {
- has Str $line;
- has Bool $processed;
-
- our protected submethod BUILD() {
- say "todo: implement Line.BUILD?"
- }#end Line.BUILD
-
- our Line method recognise_and_parse(@strings) {
- #todo: i think this should be sub since its a class method not an instance method
- say "todo: implement Line.recognise_and_parse";
- }#end Line.recognise_and_parse
-}#end class Line
-
-class ActionLine is Line {
- has Player $player;
- has Str $type;
- has Int $amount;
- has Bool $all_in;
- has Int $action_no;
-}#end class ActionLine
-
-class WinLine is Line {
- has Player $player;
- has Int $amount;
-}#end class WinLine
-
-class RakeLine is Line {
- has Int $amount;
-}#end class RakeLine
-
-class CardLine is Line {
- has Bool $board_line;
- has Player $player;
- has Card @cards;
-}#end class CardLine
-
-#for useless lines
-class CrapLine is Line {
- has Str $type;
-}#end class CrapLine
-
-class Hand {
- has Line @.lines;
- #has Str @strings;
- has Site $site;
- has Str $currency;
-
- has Str $type;
- has Str $category;
- has Str $limit_type;#todo: above ; missing causes error, but that doesnt list ; as a possibility
- has Player @.players;
- has Card @.board;
- has Int $db_id;
-
- submethod BUILD(Str @strings) {
- Util.debug("running Hand.BUILD");
- say "strings:",@strings;
- #this contructor automatically parses the hand. call .store for storing
-
- @.players=Player.find_players(@strings);
- @.lines=Line.recognise_and_parse(@strings);
-
- for @strings -> $line {
- if class_of(line)==CardLine {
- if line.board {
- board=line.cards;
- } else {
- for player in players {
- if line.player==player {
- player.cards=line.cards;
- }
- }
- }
- }
- }
- }#end Hand.BUILD
-
- our Bool method is_holdem(){
- if category==("holdem"|"omahahi"|"omahahilo") {
- return True;
- } else {
- return False;
- }
- }#end Hand.is_holdem
-
- our Bool method is_stud(){
- return not is_holdem();
- }#end Hand.is_stud
-
- our Bool method store($db) {
- say "todo: Hand.store";
- }#end Hand.store
-}#end class Hand
-
-class Importer {
-#todo: be Thread?
- submethod BUILD (Database $db, Str $filename) {
- Util.debug("running Importer.BUILD");
- if (not ($db.is_connected())) {
- Util.fatal("not connected to DB");
- }
-
- my IO $?filehandle=$filename;
- #for =$filehandle -> $line {say $line}
- my Str @lines =$filehandle;
-
- my Int $hand_start=0;
- my Int $hand_end=0;
- my Int $loopcount=0;
- loop {#one loop of this per hand
- $loopcount++;
- say "loopcount", $loopcount;
- my Int $current_line_index=$hand_end+1; #previous hand end is new hand start
- for (my Int $i, $i<5, $i++) {#remove blank hands
- if (@lines[$current_line_index].bytes) < 6 {
- $current_line_index++;
- } else {
- $hand_start=$current_line_index;
- break;
- }
- }
- my Bool $continue=True; #todo: this is dumb, find out correct loop
- while $continue {#loop through the lines to find end of hand
- $current_line_index++;
- if (@lines[$current_line_index].bytes) < 6 {
- $hand_end=$current_line_index;
- $continue=False;
- }
- }#end of find end of hand loop
- my Str @handlines=@lines[$hand_start..$hand_end];
- my Hand $hand .= new(:lines(@handlines));
- $hand.store($db);
- say "todo: record \$db_id";
- say "todo: terminate on EOF";
- }
- }#end new Importer
-}#end class Importer
-
diff --git a/ignore-me_perl6/LibFpdbShared.pm b/ignore-me_perl6/LibFpdbShared.pm
deleted file mode 100644
index abf2eb69..00000000
--- a/ignore-me_perl6/LibFpdbShared.pm
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/usr/bin/pugs
-
-#Copyright 2008 Steffen Jobbagy-Felso
-#This program is free software: you can redistribute it and/or modify
-#it under the terms of the GNU Affero General Public License as published by
-#the Free Software Foundation, version 3 of the License.
-#
-#This program is distributed in the hope that it will be useful,
-#but WITHOUT ANY WARRANTY; without even the implied warranty of
-#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-#GNU General Public License for more details.
-#
-#You should have received a copy of the GNU Affero General Public License
-#along with this program. If not, see .
-#In the "official" distribution you can find the license in
-#agpl-3.0.txt in the docs folder of the package.
-
-module LibFpdbShared;
-use v6;
-#use strict;
-
-class Util {
- method debug(Str $string) {
- #todo: i think this should be sub since its a class method not an instance method
- say "debug notice: ", $string;
- }#end debug_msg
-
- sub warn(Str $string) {
- say "todo: Util.warning";
- }#end warning
-
- sub fatal(Str $string, Database $db) {
- say "todo: Util.fatal_error";
- }#end fatal_error
-}#end class Util
-
-class Database {
- has Str $backend;
- has Str $host;
- has Str $name;
- has Str $user;
- my Str $password;
- submethod BUILD (Str $!backend, Str $!host, Str $!name, Str $!user, Str $!password) {
- Util.debug("running Database.BUILD");
- self.connect();
- }#end new Database
-
- our method connect() {
- say "todo: db.connect";
- }#end connect
-
- method disconnect() {
- say "todo: db.disconnect";
- }#end disconnect
-
- method cancel_import() {
- say "todo: db.cancel_import";
- }#end cancel_import
-
- my method drop_tables() {
- #todo: make this one private
- say "todo: db.drop_tables";
- }#end drop_tables
-
- method recreate_tables() {
- say "todo: db.recreate_tables";
- }#end recreate_tables
-
- #returns the id of the insert
- our Int method insert(Str $sql_command) {
- #todo: is it a bug that i need the "our" above?
- say "todo: db.insert";
- return 0;
- }#end insert
-
- our Str method fetch(Str $sql_command) {
- say "todo: db.fetch";
- }#end fetch
-
- our Bool method is_connected() {
- say "todo: db.is_connected";
- }#end
-}#end class Database
-
diff --git a/ignore-me_perl6/LibFpdbView.pm b/ignore-me_perl6/LibFpdbView.pm
deleted file mode 100644
index e4f994d1..00000000
--- a/ignore-me_perl6/LibFpdbView.pm
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/pugs
-
-#Copyright 2008 Steffen Jobbagy-Felso
-#This program is free software: you can redistribute it and/or modify
-#it under the terms of the GNU Affero General Public License as published by
-#the Free Software Foundation, version 3 of the License.
-#
-#This program is distributed in the hope that it will be useful,
-#but WITHOUT ANY WARRANTY; without even the implied warranty of
-#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-#GNU General Public License for more details.
-#
-#You should have received a copy of the GNU Affero General Public License
-#along with this program. If not, see .
-#In the "official" distribution you can find the license in
-#agpl-3.0.txt in the docs folder of the package.
-
diff --git a/ignore-me_perl6/RunFpdbCLI.perl6 b/ignore-me_perl6/RunFpdbCLI.perl6
deleted file mode 100644
index dbbad9a7..00000000
--- a/ignore-me_perl6/RunFpdbCLI.perl6
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/pugs
-
-#Copyright 2008 Steffen Jobbagy-Felso
-#This program is free software: you can redistribute it and/or modify
-#it under the terms of the GNU Affero General Public License as published by
-#the Free Software Foundation, version 3 of the License.
-#
-#This program is distributed in the hope that it will be useful,
-#but WITHOUT ANY WARRANTY; without even the implied warranty of
-#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-#GNU General Public License for more details.
-#
-#You should have received a copy of the GNU Affero General Public License
-#along with this program. If not, see .
-#In the "official" distribution you can find the license in
-#agpl-3.0.txt in the docs folder of the package.
-
-use v6;
-#use strict;
-use LibFpdbImport;
-use LibFpdbShared;
-
-
-my Database $db .= new(:backend, :host, :database, :user, :password);
-#todo: below doesnt work
-my Importer $imp .= new(:db($db), :filename);
-#perlbug?: adding another named argument that isnt listed in the constructor gave very weird error.
-say $imp;
-
diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py
index 06d4f5d8..1d93f3f1 100755
--- a/pyfpdb/Configuration.py
+++ b/pyfpdb/Configuration.py
@@ -485,6 +485,9 @@ class Config:
try: db['db-server'] = self.supported_databases[name].db_server
except: pass
+ try: db['db-type'] = self.supported_databases[name].db_type
+ except: pass
+
if string.lower(self.supported_databases[name].db_server) == 'mysql':
db['db-backend'] = 2
elif string.lower(self.supported_databases[name].db_server) == 'postgresql':
diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py
index ca4e5996..76052d54 100644
--- a/pyfpdb/Database.py
+++ b/pyfpdb/Database.py
@@ -27,6 +27,7 @@ Create and manage the database objects.
import sys
import traceback
from datetime import datetime, date, time, timedelta
+import string
# pyGTK modules
@@ -37,15 +38,21 @@ import Card
class Database:
def __init__(self, c, db_name, game):
- if c.supported_databases[db_name].db_server == 'postgresql':
- # psycopg2 database module for posgres via DB-API
- import psycopg2
+ db_params = c.get_db_parameters()
+ if (string.lower(db_params['db-server']) == 'postgresql' or
+ string.lower(db_params['db-server']) == 'postgres'):
+ import psycopg2 # posgres via DB-API
+ import psycopg2.extensions
+ psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
try:
- self.connection = psycopg2.connect(host = c.supported_databases[db_name].db_ip,
- user = c.supported_databases[db_name].db_user,
- password = c.supported_databases[db_name].db_pass,
- database = c.supported_databases[db_name].db_name)
+ if db_params['db-host'] == 'localhost' or db_params['db-host'] == '127.0.0.1':
+ self.connection = psycopg2.connect(database = db_params['db-databaseName'])
+ else:
+ self.connection = psycopg2.connect(host = db_params['db-host'],
+ user = db_params['db-user'],
+ password = db_params['db-password'],
+ database = db_params['db-databaseName'])
except:
print "Error opening database connection %s. See error log file." % (file)
traceback.print_exc(file=sys.stderr)
@@ -53,14 +60,13 @@ class Database:
sys.stdin.readline()
sys.exit()
- elif c.supported_databases[db_name].db_server == 'mysql':
- # mysql bindings
- import MySQLdb
+ elif string.lower(db_params['db-server']) == 'mysql':
+ import MySQLdb # mysql bindings
try:
- self.connection = MySQLdb.connect(host = c.supported_databases[db_name].db_ip,
- user = c.supported_databases[db_name].db_user,
- passwd = c.supported_databases[db_name].db_pass,
- db = c.supported_databases[db_name].db_name)
+ self.connection = MySQLdb.connect(host = db_params['db-host'],
+ user = db_params['db-user'],
+ passwd = db_params['db-password'],
+ db = db_params['db-databaseName'])
cur_iso = self.connection.cursor()
cur_iso.execute('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED')
cur_iso.close()
@@ -78,11 +84,10 @@ class Database:
print "press enter to continue"
sys.exit()
- self.db_server = c.supported_databases[db_name].db_server
- self.type = c.supported_databases[db_name].db_type
- self.sql = SQL.Sql(game = game, type = self.type, db_server = self.db_server)
+ self.type = db_params['db-type']
+ self.sql = SQL.Sql(game = game, type = self.type)
self.connection.rollback()
-
+
# To add to config:
self.hud_style = 'T' # A=All-time
# S=Session
@@ -193,20 +198,20 @@ class Database:
# cards += "xx"
# else:
# cards += ranks[d['card' + str(i) + 'Value']] + d['card' +str(i) + 'Suit']
- cv = "card%dValue" % i
+ cv = "card%dvalue" % i
if cv not in d or d[cv] == None:
break
elif d[cv] == 0:
cards += "xx"
else:
- cs = "card%dSuit" % i
+ cs = "card%dsuit" % i
cards = "%s%s%s" % (cards, ranks[d[cv]], d[cs])
return cards
def get_action_from_hand(self, hand_no):
action = [ [], [], [], [], [] ]
c = self.connection.cursor()
- c.execute(self.sql.query['get_action_from_hand'], (hand_no))
+ c.execute(self.sql.query['get_action_from_hand'], (hand_no, ))
for row in c.fetchall():
street = row[0]
act = row[1:]
@@ -217,7 +222,7 @@ class Database:
"""Returns a hash of winners:amount won, given a hand number."""
winners = {}
c = self.connection.cursor()
- c.execute(self.sql.query['get_winners_from_hand'], (hand))
+ c.execute(self.sql.query['get_winners_from_hand'], (hand, ))
for row in c.fetchall():
winners[row[0]] = row[1]
return winners
@@ -299,7 +304,6 @@ class Database:
return stat_dict
def get_player_id(self, config, site, player_name):
- print "site = %s, player name = %s" % (site, player_name)
c = self.connection.cursor()
c.execute(self.sql.query['get_player_id'], {'player': player_name, 'site': site})
row = c.fetchone()
@@ -329,12 +333,13 @@ if __name__=="__main__":
for p in stat_dict.keys():
print p, " ", stat_dict[p]
- #print "nutOmatics stats:"
- #stat_dict = db_connection.get_stats_from_hand(h, hero)
- #for p in stat_dict.keys():
- # print p, " ", stat_dict[p]
+# print "nutOmatics stats:"
+# stat_dict = db_connection.get_stats_from_hand(h, hero)
+# for p in stat_dict.keys():
+# print p, " ", stat_dict[p]
+>>>>>>> 7ef6a533ec6c73d5815ace42168067a6f8c26e3a:pyfpdb/Database.py
- print "cards =", db_connection.get_cards(73525)
+ print "cards =", db_connection.get_cards(u'1')
db_connection.close_connection
print "press enter to continue"
diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py
index 6ed2b6ba..ee4942f1 100755
--- a/pyfpdb/EverleafToFpdb.py
+++ b/pyfpdb/EverleafToFpdb.py
@@ -158,7 +158,7 @@ or None if we fail to get the info """
# 2008/11/10 3:58:52 ET
#TODO: Do conversion from GMT to ET
#TODO: Need some date functions to convert to different timezones (Date::Manip for perl rocked for this)
- hand.starttime = time.strptime(m.group('DATETIME'), "%Y/%m/%d - %H:%M:%S")
+ hand.starttime = datetime.datetime.strptime(m.group('DATETIME'), "%Y/%m/%d - %H:%M:%S")
return
def readPlayerStacks(self, hand):
diff --git a/pyfpdb/FulltiltToFpdb.py b/pyfpdb/FulltiltToFpdb.py
index a84f683c..f7b834a6 100755
--- a/pyfpdb/FulltiltToFpdb.py
+++ b/pyfpdb/FulltiltToFpdb.py
@@ -124,7 +124,7 @@ follow : whether to tail -f the input"""
hand.handid = m.group('HID')
hand.tablename = m.group('TABLE')
- hand.starttime = time.strptime(m.group('DATETIME'), "%H:%M:%S ET - %Y/%m/%d")
+ hand.starttime = datetime.datetime.strptime(m.group('DATETIME'), "%H:%M:%S ET - %Y/%m/%d")
hand.maxseats = 8 # assume 8-max until we see otherwise
if m.group('TABLEATTRIBUTES'):
m2 = re.search("(deep )?(\d+)( max)?", m.group('TABLEATTRIBUTES'))
diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py
index 5d34e409..64cafaf8 100755
--- a/pyfpdb/HUD_main.py
+++ b/pyfpdb/HUD_main.py
@@ -148,7 +148,6 @@ class HUD_main(object):
if new_hand_id == "": # blank line means quit
self.destroy()
break # this thread is not always killed immediately with gtk.main_quit()
-
# get basic info about the new hand from the db
# if there is a db error, complain, skip hand, and proceed
try:
diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py
index 9bad1918..a36f812d 100644
--- a/pyfpdb/SQL.py
+++ b/pyfpdb/SQL.py
@@ -543,11 +543,16 @@ class Sql:
self.query['get_common_cards'] = """
select
- card1Value, card1Suit,
- card2Value, card2Suit,
- card3Value, card3Suit,
- card4Value, card4Suit,
- card5Value, card5Suit
+ card1Value AS card1value,
+ card1Suit AS card1suit,
+ card2Value AS card2value,
+ card2Suit AS card2suit,
+ card3Value AS card3value,
+ card3Suit AS card3suit,
+ card4Value AS card4value,
+ card4Suit AS card4suit,
+ card5Value AS card5value,
+ card5Suit AS card5suit
from BoardCards
where handId = %s
"""
diff --git a/pyfpdb/Stats.py b/pyfpdb/Stats.py
old mode 100644
new mode 100755
diff --git a/pyfpdb/TableWindow.py b/pyfpdb/TableWindow.py
new file mode 100644
index 00000000..bf62a69c
--- /dev/null
+++ b/pyfpdb/TableWindow.py
@@ -0,0 +1,154 @@
+#!/usr/bin/env python
+"""Discover_TableWindow.py
+
+Inspects the currently open windows and finds those of interest to us--that is
+poker table windows from supported sites. Returns a list
+of Table_Window objects representing the windows found.
+"""
+# Copyright 2008 - 2009, Ray E. Barker
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+########################################################################
+
+# Standard Library modules
+import os
+import sys
+
+# pyGTK modules
+import pygtk
+import gtk
+import gobject
+
+# FreePokerTools modules
+import Configuration
+#if os.name == "posix":
+# import XTables
+#elif os.name == "nt":
+# import WinTables
+
+# Global used for figuring out the current game being played from the title
+# The dict key is the fpdb name for the game
+# The list is the names for those games used by the supported poker sites
+# This is currently only used for HORSE, so it only needs to support those
+# games on PokerStars and Full Tilt.
+game_names = { #fpdb name Stars Name FTP Name
+ "holdem" : ("Hold\'em" , ),
+ "omahahilo" : ("Omaha H/L" , ),
+ "studhilo" : ("Stud H/L" , ),
+ "razz" : ("Razz" , ),
+ "studhi" : ("Stud" , "Stud Hi")
+ }
+
+# A window title might have our table name + one of theses words/
+# phrases. If it has this word in the title, it is not a table.
+bad_words = ('History for table:', 'HUD:', 'Chat:')
+
+# Here are the custom signals we define for allowing the 'client watcher'
+# thread to communicate with the gui thread. Any time a poker client is
+# is moved, resized, or closed on of these signals is emitted to the
+# HUD main window.
+gobject.signal_new("client_moved", gtk.Window,
+ gobject.SIGNAL_RUN_LAST,
+ gobject.TYPE_NONE,
+ (gobject.TYPE_PYOBJECT,))
+
+gobject.signal_new("client_resized", gtk.Window,
+ gobject.SIGNAL_RUN_LAST,
+ gobject.TYPE_NONE,
+ (gobject.TYPE_PYOBJECT,))
+
+gobject.signal_new("client_destroyed", gtk.Window,
+ gobject.SIGNAL_RUN_LAST,
+ gobject.TYPE_NONE,
+ (gobject.TYPE_PYOBJECT,))
+
+# Each TableWindow object must have the following attributes correctly populated:
+# tw.name = the table name from the title bar, which must to match the table name
+# from the corresponding hand history.
+# 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. This is Xid in Xwindows and
+# hwnd in Microsoft Windows.
+# 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.
+
+class Table_Window(object):
+ def __init__(self, table_name = None, tournament = None, table_number = None):
+
+ if table_name != None:
+ search_string = table_name
+ self.name = table_name
+ self.tournament = None
+ self.table = None
+ elif tournament != None and table_number != None:
+ print "tournament %s, table %s" % (tournament, table_number)
+ self.tournament = int(tournament)
+ self.table = int(table_number)
+ self.name = "%s - %s" % (self.tournament, self.table)
+ search_string = "%s.+Table\s%s" % (tournament, table_number)
+ else:
+ return None
+
+ self.find_table_parameters(search_string)
+
+ def __str__(self):
+# __str__ method for testing
+ temp = 'TableWindow object\n'
+ temp = temp + " name = %s\n site = %s\n number = %s\n title = %s\n" % (self.name, self.site, self.number, self.title)
+# temp = temp + " game = %s\n structure = %s\n max = %s\n" % (self.game, self.structure, self.max)
+ temp = temp + " width = %d\n height = %d\n x = %d\n y = %d\n" % (self.width, self.height, self.x, self.y)
+ if getattr(self, 'tournament', 0):
+ temp = temp + " tournament = %d\n table = %d" % (self.tournament, self.table)
+ return temp
+
+ def get_game(self):
+ title = self.get_window_title()
+ print title
+ for game, names in game_names.iteritems():
+ for name in names:
+ if name in title:
+ return game
+ return None
+
+ def check_geometry(self):
+ new_geo = self.get_geometry()
+
+ if new_geo == None: # window destroyed
+ return "client_destroyed"
+
+ elif self.x != new_geo['x'] or self.y != new_geo['y']: # window moved
+ self.x = new_geo['x']
+ self.y = new_geo['y']
+ return "client_moved"
+
+ elif self.width != new_geo['width'] or self.height != new_geo['height']: # window resized
+ self.width = new_geo['width']
+ self.height = new_geo['height']
+ return "client_resized"
+
+ else: return False # window not changed
+
+ def check_bad_words(self, title):
+ for word in bad_words:
+ if word in title: return True
+ return False
\ No newline at end of file
diff --git a/pyfpdb/Tables_Demo.py b/pyfpdb/Tables_Demo.py
new file mode 100644
index 00000000..ffc8d412
--- /dev/null
+++ b/pyfpdb/Tables_Demo.py
@@ -0,0 +1,97 @@
+#!/usr/bin/env python
+"""Tables_Demo.py
+
+Main program module to test/demo the Tables subclasses.
+"""
+# Copyright 2008 - 2009, Ray E. Barker
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+########################################################################
+
+# Standard Library modules
+import sys
+import os
+import re
+
+# pyGTK modules
+import pygtk
+import gtk
+import gobject
+
+# fpdb/free poker tools modules
+# get the correct module for the current os
+if os.name == 'posix':
+ import XTables as Tables
+elif os.name == 'nt':
+ import WinTables as Tables
+
+# Main function used for testing
+if __name__=="__main__":
+# c = Configuration.Config()
+
+ class fake_hud(object):
+ def __init__(self, table, dx = 100, dy = 100):
+ self.table = table
+ self.dx = dx
+ self.dy = dy
+
+ self.main_window = gtk.Window()
+ self.main_window.connect("destroy", self.client_destroyed)
+ self.label = gtk.Label('Fake Fake Fake Fake\nFake\nFake\nFake')
+ self.main_window.add(self.label)
+ self.main_window.set_title("Fake HUD Main Window")
+ self.main_window.move(table.x + dx, table.y + dy)
+ self.main_window.show_all()
+ table.topify(self)
+ self.main_window.connect("client_moved", self.client_moved)
+ self.main_window.connect("client_resized", self.client_resized)
+ self.main_window.connect("client_destroyed", self.client_destroyed)
+
+ def client_moved(self, widget, hud):
+ self.main_window.move(self.table.x + self.dx, self.table.y + self.dy)
+
+ def client_resized(self, *args):
+ print "client resized"
+
+ def client_destroyed(self, *args): # call back for terminating the main eventloop
+ gtk.main_quit()
+
+ def check_on_table(table, hud):
+ result = table.check_geometry()
+ if result != False:
+ hud.main_window.emit(result, hud)
+ return True
+
+ print "enter table name to find: ",
+ table_name = sys.stdin.readline()
+ if "," in table_name: # tournament
+ print "tournament"
+ (tour_no, tab_no) = table_name.split(",", 1)
+ tour_no = tour_no.rstrip()
+ tab_no = tab_no.rstrip()
+ table = Tables.Table(tournament = tour_no, table_number = tab_no)
+ else: # not a tournament
+ print "cash game"
+ table_name = table_name.rstrip()
+ table = Tables.Table(table_name = table_name)
+
+ print "table =", table
+ print "game =", table.get_game()
+
+ fake = fake_hud(table)
+ gobject.timeout_add(100, check_on_table, table, fake)
+ gtk.main()
+
diff --git a/pyfpdb/WinTables.py b/pyfpdb/WinTables.py
new file mode 100644
index 00000000..1b064eef
--- /dev/null
+++ b/pyfpdb/WinTables.py
@@ -0,0 +1,143 @@
+#!/usr/bin/env python
+"""WinTables.py
+
+Routines for detecting and handling poker client windows for MS Windows.
+"""
+# Copyright 2008 - 2009, Ray E. Barker
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+########################################################################
+
+# Standard Library modules
+import re
+
+# pyGTK modules
+import pygtk
+import gtk
+
+# Other Library modules
+import win32gui
+import win32process
+import win32api
+import win32con
+import win32security
+
+# FreePokerTools modules
+from TableWindow import Table_Window
+
+# We don't know the border width or title bar height
+# so we guess here. We can probably get these from a windows call.
+b_width = 3
+tb_height = 29
+
+class Table(Table_Window):
+
+ def find_table_parameters(self, search_string):
+ """Finds poker client window with the given table name."""
+ titles = {}
+ win32gui.EnumWindows(win_enum_handler, titles)
+ for hwnd in titles:
+ if re.search(search_string, titles[hwnd]):
+ if 'History for table:' in titles[hwnd]: continue # Everleaf Network HH viewer window
+ if 'HUD:' in titles[hwnd]: continue # FPDB HUD window
+ if 'Chat:' in titles[hwnd]: continue # Some sites (FTP? PS? Others?) have seperable or seperately constructed chat windows
+ self.window = hwnd
+ break
+
+ if self.window == None:
+ print "Window %s not found. Skipping." % search_string
+ return None
+
+ (x, y, width, height) = win32gui.GetWindowRect(hwnd)
+ print "x = %s y = %s width = %s height = %s" % (x, y, width, height)
+ self.x = int(x) + b_width
+ self.y = int(y) + tb_height
+ self.height = int(height) - b_width - tb_height
+ self.width = int(width) - 2*b_width
+
+ self.exe = self.get_nt_exe(hwnd)
+ self.title = titles[hwnd]
+ self.site = ""
+ self.hud = None
+ self.number = gtk.gdk.window_foreign_new(long(self.window))
+
+ def get_geometry(self):
+
+ if not win32gui.IsWindow(self.window): # window closed
+ return None
+
+ try:
+ (x, y, width, height) = win32gui.GetWindowRect(hwnd)
+ return {'x' : int(x) + b_width,
+ 'y' : int(y) + tb_height,
+ 'width' : int(height) - b_width - tb_height,
+ 'height' : int(width) - 2*b_width
+ }
+ except:
+ return None
+
+ def get_window_title(self):
+ return win32gui.GetWindowText(self.window)
+
+ def get_nt_exe(self, hwnd):
+ """Finds the name of the executable that the given window handle belongs to."""
+
+ # Request privileges to enable "debug process", so we can later use PROCESS_VM_READ, retardedly required to GetModuleFileNameEx()
+ priv_flags = win32security.TOKEN_ADJUST_PRIVILEGES | win32security.TOKEN_QUERY
+ hToken = win32security.OpenProcessToken (win32api.GetCurrentProcess(), priv_flags)
+ # enable "debug process"
+ privilege_id = win32security.LookupPrivilegeValue (None, win32security.SE_DEBUG_NAME)
+ old_privs = win32security.AdjustTokenPrivileges (hToken, 0, [(privilege_id, win32security.SE_PRIVILEGE_ENABLED)])
+
+ # Open the process, and query it's filename
+ processid = win32process.GetWindowThreadProcessId(hwnd)
+ pshandle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ, False, processid[1])
+ exename = win32process.GetModuleFileNameEx(pshandle, 0)
+
+ # clean up
+ win32api.CloseHandle(pshandle)
+ win32api.CloseHandle(hToken)
+
+ return exename
+def win_enum_handler(hwnd, titles):
+ titles[hwnd] = win32gui.GetWindowText(hwnd)
+
+def topify_window(hud, 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:
+ hud.main_window.parentgdkhandle = gtk.gdk.window_foreign_new(long(hud.table.number))
+ hud.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0])
+ hud.main_window.gdkhandle.set_transient_for(hud.main_window.parentgdkhandle)
+
+ style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE)
+ style |= win32con.WS_CLIPCHILDREN
+ win32gui.SetWindowLong(hud.table.number, win32con.GWL_EXSTYLE, style)
+ break
+
+ window.set_title(real_name)
+
diff --git a/pyfpdb/XTables.py b/pyfpdb/XTables.py
new file mode 100644
index 00000000..1e692209
--- /dev/null
+++ b/pyfpdb/XTables.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+"""Discover_Tables.py
+
+Inspects the currently open windows and finds those of interest to us--that is
+poker table windows from supported sites. Returns a list
+of Table_Window objects representing the windows found.
+"""
+# Copyright 2008 - 2009, Ray E. Barker
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+########################################################################
+
+# Standard Library modules
+import re
+
+# pyGTK modules
+import pygtk
+import gtk
+
+# Other Library modules
+import Xlib
+import Xlib.display
+
+# FreePokerTools modules
+from TableWindow import Table_Window
+
+# We might as well do this once and make them globals
+disp = Xlib.display.Display()
+root = disp.screen().root
+
+class Table(Table_Window):
+
+ def find_table_parameters(self, search_string):
+ self.window = None
+ done_looping = False
+ for outside in root.query_tree().children:
+ for inside in outside.query_tree().children:
+ if done_looping: break
+ if inside.get_wm_name() and re.search(search_string, inside.get_wm_name()):
+ if self.check_bad_words(inside.get_wm_name()): continue
+ self.window = inside
+ self.parent = outside
+ done_looping = True
+ break
+
+ if self.window == None or self.parent == None:
+ print "Window %s not found. Skipping." % search_string
+ return None
+
+ my_geo = self.window.get_geometry()
+ pa_geo = self.parent.get_geometry()
+
+ self.x = pa_geo.x + my_geo.x
+ self.y = pa_geo.y + my_geo.y
+ self.width = my_geo.width
+ self.height = my_geo.height
+ self.exe = self.window.get_wm_class()[0]
+ self.title = self.window.get_wm_name()
+ self.site = ""
+ self.hud = None
+
+ window_string = str(self.window)
+ mo = re.match('Xlib\.display\.Window\(([\dxabcdef]+)', window_string)
+ if not mo:
+ print "Not matched"
+ self.gdk_handle = None
+ else:
+ self.number = int( mo.group(1), 0)
+ self.gdk_handle = gtk.gdk.window_foreign_new(int(self.number))
+
+ def get_geometry(self):
+ try:
+ my_geo = self.window.get_geometry()
+ pa_geo = self.parent.get_geometry()
+ return {'x' : pa_geo.x + my_geo.x,
+ 'y' : pa_geo.y + my_geo.y,
+ 'width' : my_geo.width,
+ 'height' : my_geo.height
+ }
+ except:
+ return None
+
+ def get_window_title(self):
+ return self.window.get_wm_name()
+
+ def topify(self, hud):
+ hud.main_window.gdkhandle = gtk.gdk.window_foreign_new(hud.main_window.window.xid)
+ hud.main_window.gdkhandle.set_transient_for(self.gdk_handle)
diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py
index 583ecfc8..e0ccd813 100644
--- a/pyfpdb/fpdb_db.py
+++ b/pyfpdb/fpdb_db.py
@@ -172,27 +172,20 @@ class fpdb_db:
raise fpdb_simple.FpdbError("MySQL connection failed")
elif backend==self.PGSQL:
import psycopg2
- import psycopg2.extensions
+ import psycopg2.extensions
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
# If DB connection is made over TCP, then the variables
# host, user and password are required
- # print "host=%s user=%s pass=%s." % (host, user, password)
- if self.host and self.user and self.password:
- try:
- self.db = psycopg2.connect(host = host,
- user = user,
- password = password,
- database = database)
- except:
- raise fpdb_simple.FpdbError("PostgreSQL connection failed")
# For local domain-socket connections, only DB name is
# needed, and everything else is in fact undefined and/or
# flat out wrong
+ if self.host == "localhost" or self.host == "127.0.0.1":
+ self.db = psycopg2.connect(database = database)
else:
- try:
- self.db = psycopg2.connect(database = database)
- except:
- raise fpdb_simple.FpdbError("PostgreSQL connection failed")
+ self.db = psycopg2.connect(host = host,
+ user = user,
+ password = password,
+ database = database)
else:
raise fpdb_simple.FpdbError("unrecognised database backend:"+backend)
self.cursor=self.db.cursor()
diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py
index cffe8598..9b779574 100644
--- a/pyfpdb/fpdb_import.py
+++ b/pyfpdb/fpdb_import.py
@@ -44,6 +44,9 @@ except:
try:
import psycopg2
pgsqlLibFound=True
+ import psycopg2.extensions
+ psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
+
except:
pass
diff --git a/pyfpdb/fpdb_save_to_db.py b/pyfpdb/fpdb_save_to_db.py
index 0dbcbf61..3c99d084 100644
--- a/pyfpdb/fpdb_save_to_db.py
+++ b/pyfpdb/fpdb_save_to_db.py
@@ -26,13 +26,14 @@ MYSQL_INNODB = 2
PGSQL = 3
SQLITE = 4
-fastStoreHudCache = False # set this to True to test the new storeHudCache routine
+#fastStoreHudCache = False # set this to True to test the new storeHudCache routine
+#
+#saveActions = True # set this to False to avoid storing action data
+# # Pros: speeds up imports
+# # Cons: no action data is saved, so you need to keep the hand histories
+# # variance not available on stats page
+# # no graphs
-saveActions = True # set this to False to avoid storing action data
- # Pros: speeds up imports
- # Cons: no action data is saved, so you need to keep the hand histories
- # variance not available on stats page
- # : No graphs
#stores a stud/razz hand into the database
def ring_stud(config, backend, db, cursor, base, category, site_hand_no, gametype_id, hand_start_time
,names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes
diff --git a/utils/create-release.sh b/utils/create-release.sh
index 21696c1a..0b720157 100755
--- a/utils/create-release.sh
+++ b/utils/create-release.sh
@@ -1,6 +1,7 @@
#!/bin/sh
#Copyright 2008 Steffen Jobbagy-Felso
+#Copyright 2009 Ray E. Barker
#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU Affero General Public License as published by
#the Free Software Foundation, version 3 of the License.
@@ -15,10 +16,22 @@
#In the "official" distribution you can find the license in
#agpl-3.0.txt in the docs folder of the package.
+# This script prepares the compressed distribution files for
+# uploading to sourceforge.
+#
+# Run from the root of your git repo (the folder that has .git in it)
+
+# USAGE: $ utils/create-release.sh V
+# where V is the current version. e.g. utils/create-release.sh 0.55
+
#get rid of extraneous stuff
rm regression-test/*.found.txt
rm regression-test/*.pyc
rm pyfpdb/*.pyc
+rm pyfpdb/*~
+rm pyfpdb/fpdb-error-log.txt
+rm pyfpdb/HUD-error.txt
+rm pyfpdb/hand-errors.txt
# make the fpdb_$1.zip file for windows
echo "*** making zip file"