Merge branch 'master' of git://git.assembla.com/fpdb-eric

This commit is contained in:
Worros 2009-09-03 21:37:57 +08:00
commit b52ceb3f90
5 changed files with 188 additions and 133 deletions

View File

@ -32,6 +32,7 @@ class Absolute(HandHistoryConverter):
filetype = "text" filetype = "text"
codepage = "cp1252" codepage = "cp1252"
siteid = 8 siteid = 8
HORSEHand = False
# Static regexes # Static regexes
re_SplitHands = re.compile(r"\n\n\n+") re_SplitHands = re.compile(r"\n\n\n+")
@ -41,9 +42,11 @@ class Absolute(HandHistoryConverter):
#Seat 6 - FETS63 ($0.75 in chips) #Seat 6 - FETS63 ($0.75 in chips)
#Board [10s 5d Kh Qh 8c] #Board [10s 5d Kh Qh 8c]
re_GameInfo = re.compile(ur"^Stage #([0-9]+): (?P<GAME>Holdem|)(?: \(1 on 1\)|)? (?P<LIMIT>No Limit|Pot Limit|Normal) (?P<CURRENCY>\$| €|)(?P<SB>[.0-9]+)/?(?:\$| €|)(?P<BB>[.0-9]+)?", re.MULTILINE) re_GameInfo = re.compile(ur"^Stage #([0-9]+): (?P<GAME>Holdem|HORSE)(?: \(1 on 1\)|)? ?(?P<LIMIT>No Limit|Pot Limit|Normal|)? ?(?P<CURRENCY>\$| €|)(?P<SB>[.0-9]+)/?(?:\$| €|)(?P<BB>[.0-9]+)?", re.MULTILINE)
re_HorseGameInfo = re.compile(ur"^Game Type: (?P<LIMIT>Limit) (?P<GAME>Holdem)", re.MULTILINE)
# TODO: can set max seats via (1 on 1) to a known 2 .. # TODO: can set max seats via (1 on 1) to a known 2 ..
re_HandInfo = re.compile(ur"^Stage #(?P<HID>[0-9]+): .*(?P<DATETIME>\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d).*\nTable: (?P<TABLE>.*) \(Real Money\)", re.MULTILINE) re_HandInfo = re.compile(ur"^Stage #(?P<HID>[0-9]+): .*(?P<DATETIME>\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d).*\n(Table: (?P<TABLE>.*) \(Real Money\))?", re.MULTILINE)
re_TableFromFilename = re.compile(ur".*IHH([0-9]+) (?P<TABLE>.*) -") # on HORSE STUD games, the table name isn't in the hand info!
re_Button = re.compile(ur"Seat #(?P<BUTTON>[0-9]) is the ?[dead]* dealer$", re.MULTILINE) # TODO: that's not the right way to match for "dead" dealer is it? re_Button = re.compile(ur"Seat #(?P<BUTTON>[0-9]) is the ?[dead]* dealer$", re.MULTILINE) # TODO: that's not the right way to match for "dead" dealer is it?
re_PlayerInfo = re.compile(ur"^Seat (?P<SEAT>[0-9]) - (?P<PNAME>.*) \((?:\$| €|)(?P<CASH>[0-9]*[.0-9]+) in chips\)", re.MULTILINE) re_PlayerInfo = re.compile(ur"^Seat (?P<SEAT>[0-9]) - (?P<PNAME>.*) \((?:\$| €|)(?P<CASH>[0-9]*[.0-9]+) in chips\)", re.MULTILINE)
re_Board = re.compile(ur"\[(?P<CARDS>[^\]]*)\]? *$", re.MULTILINE) re_Board = re.compile(ur"\[(?P<CARDS>[^\]]*)\]? *$", re.MULTILINE)
@ -113,7 +116,7 @@ or None if we fail to get the info """
mg = m.groupdict() mg = m.groupdict()
# translations from captured groups to our info strings # translations from captured groups to our info strings
limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Normal':'fl' } limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Normal':'fl', 'Limit':'fl'}
games = { # base, category games = { # base, category
"Holdem" : ('hold','holdem'), "Holdem" : ('hold','holdem'),
'Omaha' : ('hold','omahahi'), 'Omaha' : ('hold','omahahi'),
@ -121,10 +124,22 @@ or None if we fail to get the info """
'7 Card Stud' : ('stud','studhi') '7 Card Stud' : ('stud','studhi')
} }
currencies = { u'':'EUR', '$':'USD', '':'T$' } currencies = { u'':'EUR', '$':'USD', '':'T$' }
if 'LIMIT' in mg: if 'GAME' in mg and mg['GAME'] == "HORSE": # if we're a HORSE game, the game type is on the next line
info['limitType'] = limits[mg['LIMIT']] self.HORSEHand = True
m = self.re_HorseGameInfo.search(handText)
if not m:
return None # it's a HORSE game and we don't understand the game type
temp = m.groupdict()
#print "AP HORSE processing"
if 'GAME' not in temp or 'LIMIT' not in temp:
return None # sort of understood it but not really
#print "temp=", temp
mg['GAME'] = temp['GAME']
mg['LIMIT'] = temp['LIMIT']
if 'GAME' in mg: if 'GAME' in mg:
(info['base'], info['category']) = games[mg['GAME']] (info['base'], info['category']) = games[mg['GAME']]
if 'LIMIT' in mg:
info['limitType'] = limits[mg['LIMIT']]
if 'SB' in mg: if 'SB' in mg:
info['sb'] = mg['SB'] info['sb'] = mg['SB']
else: else:
@ -153,9 +168,15 @@ or None if we fail to get the info """
return None return None
logging.debug("HID %s, Table %s" % (m.group('HID'), m.group('TABLE'))) logging.debug("HID %s, Table %s" % (m.group('HID'), m.group('TABLE')))
hand.handid = m.group('HID') hand.handid = m.group('HID')
hand.tablename = m.group('TABLE') if m.group('TABLE'):
hand.tablename = m.group('TABLE')
else:
t = self.re_TableFromFilename.search(self.in_path)
hand.tablename = t.group('TABLE')
hand.maxseats = 6 # assume 6-max unless we have proof it's a larger/smaller game, since absolute doesn't give seat max info hand.maxseats = 6 # assume 6-max unless we have proof it's a larger/smaller game, since absolute doesn't give seat max info
# TODO: (1-on-1) does have that info in the game type line
if self.HORSEHand:
hand.maxseats = 8
hand.starttime = datetime.datetime.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 return

View File

@ -583,8 +583,15 @@ Map the tuple self.gametype onto the pokerstars string describing it
else: # non-mixed cash games else: # non-mixed cash games
gs = gs + " %s (%s) - " % (self.getGameTypeAsString(), self.getStakesAsString()) gs = gs + " %s (%s) - " % (self.getGameTypeAsString(), self.getStakesAsString())
return gs + datetime.datetime.strftime(self.starttime,'%Y/%m/%d %H:%M:%S ET') try:
timestr = datetime.datetime.strftime(self.starttime, '%Y/%m/%d %H:%M:%S ET')
except TypeError:
print "*** ERROR - HAND: calling writeGameLine with unexpected STARTTIME value, expecting datetime.date object, received:", self.starttime
print "*** Make sure your HandHistoryConverter is setting hand.starttime properly!"
print "*** Game String:", gs
return gs
else:
return gs + timestr
def writeTableLine(self): def writeTableLine(self):
table_string = "Table \'%s\' %s-max" % (self.tablename, self.maxseats) table_string = "Table \'%s\' %s-max" % (self.tablename, self.maxseats)

View File

@ -80,6 +80,10 @@ class Hud:
(font, font_size) = config.get_default_font(self.table.site) (font, font_size) = config.get_default_font(self.table.site)
self.colors = config.get_default_colors(self.table.site) self.colors = config.get_default_colors(self.table.site)
self.backgroundcolor = gtk.gdk.color_parse(self.colors['hudbgcolor'])
self.foregroundcolor = gtk.gdk.color_parse(self.colors['hudfgcolor'])
if font == None: if font == None:
font = "Sans" font = "Sans"
@ -102,85 +106,66 @@ class Hud:
def create_mw(self): def create_mw(self):
# Set up a main window for this this instance of the HUD # Set up a main window for this this instance of the HUD
self.main_window = gtk.Window() win = gtk.Window()
self.main_window.set_gravity(gtk.gdk.GRAVITY_STATIC) win.set_gravity(gtk.gdk.GRAVITY_STATIC)
self.main_window.set_title("%s FPDBHUD" % (self.table.name)) win.set_title("%s FPDBHUD" % (self.table.name))
self.main_window.set_decorated(False) win.set_decorated(False)
self.main_window.set_opacity(self.colors["hudopacity"]) win.set_opacity(self.colors["hudopacity"])
self.main_window.set_focus_on_map(False)
eventbox = gtk.EventBox()
self.ebox = gtk.EventBox() label = gtk.Label("FPDB Menu - Right click\nLeft-Drag to Move")
self.label = gtk.Label("FPDB Menu (Right Click)\nLeft-drag to move")
win.add(eventbox)
self.backgroundcolor = gtk.gdk.color_parse(self.colors['hudbgcolor']) eventbox.add(label)
self.foregroundcolor = gtk.gdk.color_parse(self.colors['hudfgcolor'])
label.modify_bg(gtk.STATE_NORMAL, self.backgroundcolor)
self.label.modify_bg(gtk.STATE_NORMAL, self.backgroundcolor) label.modify_fg(gtk.STATE_NORMAL, self.foregroundcolor)
self.label.modify_fg(gtk.STATE_NORMAL, self.foregroundcolor)
eventbox.modify_bg(gtk.STATE_NORMAL, self.backgroundcolor)
self.main_window.add(self.ebox) eventbox.modify_fg(gtk.STATE_NORMAL, self.foregroundcolor)
self.ebox.add(self.label)
self.ebox.modify_bg(gtk.STATE_NORMAL, self.backgroundcolor)
self.ebox.modify_fg(gtk.STATE_NORMAL, self.foregroundcolor)
self.main_window = win
self.main_window.move(self.table.x, self.table.y) self.main_window.move(self.table.x, self.table.y)
# A popup menu for the main window # A popup menu for the main window
self.menu = gtk.Menu() menu = gtk.Menu()
self.item1 = gtk.MenuItem('Kill this HUD')
self.menu.append(self.item1) killitem = gtk.MenuItem('Kill This HUD')
menu.append(killitem)
if self.parent != None: if self.parent != None:
self.item1.connect("activate", self.parent.kill_hud, self.table_name) killitem.connect("activate", self.parent.kill_hud, self.table_name)
self.item1.show()
self.item2 = gtk.MenuItem('Save Layout') saveitem = gtk.MenuItem('Save HUD Layout')
self.menu.append(self.item2) menu.append(saveitem)
self.item2.connect("activate", self.save_layout) saveitem.connect("activate", self.save_layout)
self.item2.show()
self.item3 = gtk.MenuItem('Reposition Stats') repositem = gtk.MenuItem('Reposition StatWindows')
self.menu.append(self.item3) menu.append(repositem)
self.item3.connect("activate", self.reposition_windows) repositem.connect("activate", self.reposition_windows)
self.item3.show()
self.item4 = gtk.MenuItem('Debug Stat Windows') debugitem = gtk.MenuItem('Debug StatWindows')
self.menu.append(self.item4) menu.append(debugitem)
self.item4.connect("activate", self.debug_stat_windows) debugitem.connect("activate", self.debug_stat_windows)
self.item4.show()
item5 = gtk.MenuItem('Set max seats')
self.item5 = gtk.MenuItem('Set max seats') menu.append(item5)
self.menu.append(self.item5) maxSeatsMenu = gtk.Menu()
self.item5.show() item5.set_submenu(maxSeatsMenu)
self.maxSeatsMenu = gtk.Menu()
self.item5.set_submenu(self.maxSeatsMenu)
for i in range(2, 11, 1): for i in range(2, 11, 1):
item = gtk.MenuItem('%d-max' % i) item = gtk.MenuItem('%d-max' % i)
item.ms = i item.ms = i
self.maxSeatsMenu.append(item) maxSeatsMenu.append(item)
item.connect("activate", self.change_max_seats) item.connect("activate", self.change_max_seats)
item.show()
setattr(self, 'maxSeatsMenuItem%d' % (i-1), item) setattr(self, 'maxSeatsMenuItem%d' % (i-1), item)
eventbox.connect_object("button-press-event", self.on_button_press, menu)
self.ebox.connect_object("button-press-event", self.on_button_press, self.menu)
self.main_window.show_all()
self.mw_created = True self.mw_created = True
self.label = label
# TODO: fold all uses of this type of 'topify' code into a single function, if the differences between the versions don't menu.show_all()
# create adverse effects? self.main_window.show_all()
self.topify_window(self.main_window)
if os.name == 'nt':
self.topify_window(self.main_window)
else:
self.main_window.parentgdkhandle = gtk.gdk.window_foreign_new(int(self.table.number)) # gets a gdk handle for poker client
self.main_window.gdkhandle = gtk.gdk.window_foreign_new(self.main_window.window.xid) # gets a gdk handle for the hud table window
self.main_window.gdkhandle.set_transient_for(self.main_window.parentgdkhandle) #
self.update_table_position()
def change_max_seats(self, widget): def change_max_seats(self, widget):
if self.max != widget.ms: if self.max != widget.ms:
print 'change_max_seats', widget.ms print 'change_max_seats', widget.ms
@ -199,18 +184,18 @@ class Hud:
self.parent.kill_hud(self, self.table.name) self.parent.kill_hud(self, self.table.name)
return False return False
# anyone know how to do this in unix, or better yet, trap the X11 error that is triggered when executing the get_origin() for a closed window? # anyone know how to do this in unix, or better yet, trap the X11 error that is triggered when executing the get_origin() for a closed window?
if self.table.gdkhandle is not None:
(x, y) = self.main_window.parentgdkhandle.get_origin() (x, y) = self.table.gdkhandle.get_origin()
if self.table.x != x or self.table.y != y: if self.table.x != x or self.table.y != y:
self.table.x = x self.table.x = x
self.table.y = y self.table.y = y
self.main_window.move(x, y) self.main_window.move(x, y)
adj = self.adj_seats(self.hand, self.config) adj = self.adj_seats(self.hand, self.config)
loc = self.config.get_locations(self.table.site, self.max) loc = self.config.get_locations(self.table.site, self.max)
# TODO: is stat_windows getting converted somewhere from a list to a dict, for no good reason? # TODO: is stat_windows getting converted somewhere from a list to a dict, for no good reason?
for i, w in enumerate(self.stat_windows.itervalues()): for i, w in enumerate(self.stat_windows.itervalues()):
(x, y) = loc[adj[i+1]] (x, y) = loc[adj[i+1]]
w.relocate(x, y) w.relocate(x, y)
# While we're at it, fix the positions of mucked cards too # While we're at it, fix the positions of mucked cards too
for aux in self.aux_windows: for aux in self.aux_windows:
@ -374,30 +359,15 @@ class Hud:
Stats.do_tip(window.e_box[r][c], tip) Stats.do_tip(window.e_box[r][c], tip)
def topify_window(self, window): def topify_window(self, window):
# """Set the specified gtk window to stayontop in MS Windows.""" window.set_focus_on_map(False)
# window.set_accept_focus(False)
# def windowEnumerationHandler(hwnd, resultList):
# '''Callback for win32gui.EnumWindows() to generate list of window handles.''' if not self.table.gdkhandle:
# resultList.append((hwnd, win32gui.GetWindowText(hwnd))) self.table.gdkhandle = gtk.gdk.window_foreign_new(int(self.table.number)) # gtk handle to poker window
# unique_name = 'unique name for finding this window' # window.window.reparent(self.table.gdkhandle, 0, 0)
# real_name = window.get_title() window.window.set_transient_for(self.table.gdkhandle)
# window.set_title(unique_name) # window.present()
# tl_windows = []
# win32gui.EnumWindows(windowEnumerationHandler, tl_windows)
#
# for w in tl_windows:
# if w[1] == unique_name:
self.main_window.parentgdkhandle = gtk.gdk.window_foreign_new(long(self.table.number))
# self.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0])
self.main_window.gdkhandle = self.main_window.window
self.main_window.gdkhandle.set_transient_for(self.main_window.parentgdkhandle)
style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE)
style |= win32con.WS_CLIPCHILDREN
win32gui.SetWindowLong(self.table.number, win32con.GWL_EXSTYLE, style)
# break
# window.set_title(real_name)
class Stat_Window: class Stat_Window:
@ -419,6 +389,7 @@ class Stat_Window:
if event.button == 1: # left button event if event.button == 1: # left button event
# TODO: make position saving save sizes as well? # TODO: make position saving save sizes as well?
self.window.show_all()
if event.state & gtk.gdk.SHIFT_MASK: if event.state & gtk.gdk.SHIFT_MASK:
self.window.begin_resize_drag(gtk.gdk.WINDOW_EDGE_SOUTH_EAST, event.button, int(event.x_root), int(event.y_root), event.time) self.window.begin_resize_drag(gtk.gdk.WINDOW_EDGE_SOUTH_EAST, event.button, int(event.x_root), int(event.y_root), event.time)
else: else:
@ -462,7 +433,6 @@ class Stat_Window:
self.window.set_title("%s" % seat) self.window.set_title("%s" % seat)
self.window.set_property("skip-taskbar-hint", True) self.window.set_property("skip-taskbar-hint", True)
self.window.set_transient_for(parent.main_window)
self.window.set_focus_on_map(False) self.window.set_focus_on_map(False)
grid = gtk.Table(rows = game.rows, columns = game.cols, homogeneous = False) grid = gtk.Table(rows = game.rows, columns = game.cols, homogeneous = False)
@ -514,10 +484,25 @@ class Stat_Window:
self.window.connect("focus-in-event", self.noop) self.window.connect("focus-in-event", self.noop)
self.window.connect("focus-out-event", self.noop) self.window.connect("focus-out-event", self.noop)
self.window.connect("button_press_event", self.button_press_cb) self.window.connect("button_press_event", self.button_press_cb)
self.window.set_focus_on_map(False)
self.window.set_accept_focus(False)
self.window.move(self.x, self.y) self.window.move(self.x, self.y)
self.window.show_all() # window must be mapped before it has a gdkwindow so we can attach it to the table window.. i hate gtk.
self.topify_window(self.window)
self.window.hide() self.window.hide()
def topify_window(self, window):
window.set_focus_on_map(False)
window.set_accept_focus(False)
if not self.table.gdkhandle:
self.table.gdkhandle = gtk.gdk.window_foreign_new(int(self.table.number)) # gtk handle to poker window
# window.window.reparent(self.table.gdkhandle, 0, 0)
window.window.set_transient_for(self.table.gdkhandle)
# window.present()
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()
@ -534,6 +519,8 @@ class Popup_window:
self.window.set_gravity(gtk.gdk.GRAVITY_STATIC) self.window.set_gravity(gtk.gdk.GRAVITY_STATIC)
self.window.set_title("popup") self.window.set_title("popup")
self.window.set_property("skip-taskbar-hint", True) self.window.set_property("skip-taskbar-hint", True)
self.window.set_focus_on_map(False)
self.window.set_accept_focus(False)
self.window.set_transient_for(parent.get_toplevel()) self.window.set_transient_for(parent.get_toplevel())
self.window.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self.window.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
@ -599,9 +586,6 @@ class Popup_window:
self.window.set_transient_for(stat_window.window) self.window.set_transient_for(stat_window.window)
# if os.name == 'nt':
# self.topify_window(self.window)
def button_press_cb(self, widget, event, *args): def button_press_cb(self, widget, event, *args):
# This handles all callbacks from button presses on the event boxes in # 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- # the popup windows. There is a bit of an ugly kludge to separate single-
@ -630,27 +614,15 @@ class Popup_window:
top.move(x, y) top.move(x, y)
def topify_window(self, window): def topify_window(self, window):
"""Set the specified gtk window to stayontop in MS Windows.""" window.set_focus_on_map(False)
window.set_accept_focus(False)
# def windowEnumerationHandler(hwnd, resultList):
# '''Callback for win32gui.EnumWindows() to generate list of window handles.''' if not self.table.gdkhandle:
# resultList.append((hwnd, win32gui.GetWindowText(hwnd))) self.table.gdkhandle = gtk.gdk.window_foreign_new(int(self.table.number)) # gtk handle to poker window
# window.window.reparent(self.table.gdkhandle, 0, 0)
# unique_name = 'unique name for finding this window' window.window.set_transient_for(self.table.gdkhandle)
# real_name = window.get_title() # window.present()
# window.set_title(unique_name)
# tl_windows = []
# win32gui.EnumWindows(windowEnumerationHandler, tl_windows)
# for w in tl_windows:
# if w[1] == unique_name:
# window.set_transient_for(self.parent.window)
style = win32gui.GetWindowLong(self.parent.table.number, win32con.GWL_EXSTYLE)
style |= win32con.WS_CLIPCHILDREN
win32gui.SetWindowLong(self.parent.table.number, win32con.GWL_EXSTYLE, style)
# break
# window.set_title(real_name)
if __name__== "__main__": if __name__== "__main__":
main_window = gtk.Window() main_window = gtk.Window()
@ -661,7 +633,7 @@ if __name__== "__main__":
c = Configuration.Config() c = Configuration.Config()
#tables = Tables.discover(c) #tables = Tables.discover(c)
t = Tables.discover_table_by_name(c, "Patriot Dr") t = Tables.discover_table_by_name(c, "Motorway")
if t is None: if t is None:
print "Table not found." print "Table not found."
db = Database.Database(c, 'fpdb', 'holdem') db = Database.Database(c, 'fpdb', 'holdem')

View File

@ -69,6 +69,7 @@ class Table_Window:
if 'site' in info: self.site = info['site'] if 'site' in info: self.site = info['site']
if 'title' in info: self.title = info['title'] if 'title' in info: self.title = info['title']
if 'name' in info: self.name = info['name'] if 'name' in info: self.name = info['name']
self.gdkhandle = None
def __str__(self): def __str__(self):
# __str__ method for testing # __str__ method for testing

54
pyfpdb/py2exe_setup.py Normal file
View File

@ -0,0 +1,54 @@
#!/usr/bin/env python
"""setup.py
Py2exe script for fpdb.
"""
# Copyright 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
########################################################################
#TODO: change GuiAutoImport so that it knows to start HUD_main.exe, when appropriate
# include the lib needed to handle png files in mucked
# get rid of all the uneeded libraries (e.g., pyQT)
# think about an installer
from distutils.core import setup
import py2exe
setup(
name = 'fpdb',
description = 'Free Poker DataBase',
version = '0.12',
console = [ {'script': 'fpdb.py', },
{'script': 'HUD_main.py', }
],
options = {'py2exe': {
'packages' :'encodings',
'includes' : 'cairo, pango, pangocairo, atk, gobject, PokerStarsToFpdb',
'excludes' : '_tkagg, _agg2, cocoaagg, fltkagg',
'dll_excludes': 'libglade-2.0-0.dll',
}
},
data_files = ['HUD_config.xml',
'Cards01.png'
]
)