Merge commit 'carl/master'

This commit is contained in:
Matt Turnbull 2009-03-09 22:28:47 +00:00
commit 250505f13b
17 changed files with 1186 additions and 616 deletions

View File

@ -3,7 +3,7 @@
Handles HUD configuration files. Handles HUD configuration files.
""" """
# Copyright 2008, Ray E. Barker # Copyright 2008, 2009, Ray E. Barker
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
@ -33,15 +33,31 @@ import xml.dom.minidom
from xml.dom.minidom import Node from xml.dom.minidom import Node
class Layout: class Layout:
def __init__(self, max): def __init__(self, node):
self.max = int(max)
self.max = int( node.getAttribute('max') )
if node.hasAttribute('fav_seat'): self.fav_seat = int( node.getAttribute('fav_seat') )
self.width = int( node.getAttribute('width') )
self.height = int( node.getAttribute('height') )
self.location = [] self.location = []
for i in range(self.max + 1): self.location.append(None) self.location = map(lambda x: None, range(self.max+1)) # there must be a better way to do this?
for location_node in node.getElementsByTagName('location'):
if location_node.getAttribute('seat') != "":
self.location[int( location_node.getAttribute('seat') )] = (int( location_node.getAttribute('x') ), int( location_node.getAttribute('y')))
elif location_node.getAttribute('common') != "":
self.common = (int( location_node.getAttribute('x') ), int( location_node.getAttribute('y')))
def __str__(self): def __str__(self):
temp = " Layout = %d max, width= %d, height = %d, fav_seat = %d\n" % (self.max, self.width, self.height, self.fav_seat) temp = " Layout = %d max, width= %d, height = %d" % (self.max, self.width, self.height)
if hasattr(self, 'fav_seat'): temp = temp + ", fav_seat = %d\n" % self.fav_seat
else: temp = temp + "\n"
if hasattr(self, "common"):
temp = temp + " Common = (%d, %d)\n" % (self.common[0], self.common[1])
temp = temp + " Locations = " temp = temp + " Locations = "
for i in range(1, len(self.location)): for i in xrange(1, len(self.location)):
temp = temp + "(%d,%d)" % self.location[i] temp = temp + "(%d,%d)" % self.location[i]
return temp + "\n" return temp + "\n"
@ -66,28 +82,21 @@ class Site:
self.layout = {} self.layout = {}
for layout_node in node.getElementsByTagName('layout'): for layout_node in node.getElementsByTagName('layout'):
max = int( layout_node.getAttribute('max') ) lo = Layout(layout_node)
lo = Layout(max)
lo.fav_seat = int( layout_node.getAttribute('fav_seat') )
lo.width = int( layout_node.getAttribute('width') )
lo.height = int( layout_node.getAttribute('height') )
for location_node in layout_node.getElementsByTagName('location'):
lo.location[int( location_node.getAttribute('seat') )] = (int( location_node.getAttribute('x') ), int( location_node.getAttribute('y')))
self.layout[lo.max] = lo self.layout[lo.max] = lo
def __str__(self): def __str__(self):
temp = "Site = " + self.site_name + "\n" temp = "Site = %s\n" % self.site_name
for key in dir(self): for key in dir(self):
if key.startswith('__'): continue if key.startswith('__'): continue
if key == 'layout': continue if key == 'layout': continue
value = getattr(self, key) value = getattr(self, key)
if callable(value): continue if callable(value): continue
temp = "%s %s = %s\n" % (temp, key, str(value))
temp = temp + ' ' + key + " = " + str(value) + "\n" temp = temp + ' ' + key + " = " + str(value) + "\n"
for layout in self.layout: for layout in self.layout:
temp = temp + "%s" % self.layout[layout] temp = "%s%s" % (temp, self.layout[layout])
return temp return temp
@ -105,7 +114,12 @@ class Game:
self.db = node.getAttribute("db") self.db = node.getAttribute("db")
self.rows = int( node.getAttribute("rows") ) self.rows = int( node.getAttribute("rows") )
self.cols = int( node.getAttribute("cols") ) self.cols = int( node.getAttribute("cols") )
self.aux = node.getAttribute("aux")
aux_text = node.getAttribute("aux")
aux_list = aux_text.split(',')
for i in range(0, len(aux_list)):
aux_list[i] = aux_list[i].strip()
self.aux = aux_list
self.stats = {} self.stats = {}
for stat_node in node.getElementsByTagName('stat'): for stat_node in node.getElementsByTagName('stat'):
@ -123,14 +137,10 @@ class Game:
self.stats[stat.stat_name] = stat self.stats[stat.stat_name] = stat
def __str__(self): def __str__(self):
temp = "Game = " + self.game_name + "\n" temp = "Game = %s\n db = %s\n rows = %d\n cols = %d\n aux = %s\n" % (self.game_name, self.db, self.rows, self.cols, self.aux)
temp = temp + " db = %s\n" % self.db
temp = temp + " rows = %d\n" % self.rows
temp = temp + " cols = %d\n" % self.cols
temp = temp + " aux = %s\n" % self.aux
for stat in self.stats.keys(): for stat in self.stats.keys():
temp = temp + "%s" % self.stats[stat] temp = "%s%s" % (temp, self.stats[stat])
return temp return temp
@ -156,21 +166,23 @@ class Aux_window:
def __init__(self, node): def __init__(self, node):
for (name, value) in node.attributes.items(): for (name, value) in node.attributes.items():
setattr(self, name, value) setattr(self, name, value)
# self.name = node.getAttribute("mw_name")
# self.cards = node.getAttribute("deck") self.layout = {}
# self.card_wd = node.getAttribute("card_wd") for layout_node in node.getElementsByTagName('layout'):
# self.card_ht = node.getAttribute("card_ht") lo = Layout(layout_node)
# self.rows = node.getAttribute("rows") self.layout[lo.max] = lo
# self.cols = node.getAttribute("cols")
# self.format = node.getAttribute("stud")
def __str__(self): def __str__(self):
temp = 'Aux = ' + self.name + "\n" temp = 'Aux = ' + self.name + "\n"
for key in dir(self): for key in dir(self):
if key.startswith('__'): continue if key.startswith('__'): continue
if key == 'layout': continue
value = getattr(self, key) value = getattr(self, key)
if callable(value): continue if callable(value): continue
temp = temp + ' ' + key + " = " + value + "\n" temp = temp + ' ' + key + " = " + value + "\n"
for layout in self.layout:
temp = temp + "%s" % self.layout[layout]
return temp return temp
class Popup: class Popup:
@ -392,7 +404,7 @@ class Config:
site_node = self.get_site_node(site_name) site_node = self.get_site_node(site_name)
layout_node = self.get_layout_node(site_node, max) layout_node = self.get_layout_node(site_node, max)
if layout_node == None: return if layout_node == None: return
for i in range(1, max + 1): for i in xrange(1, max + 1):
location_node = self.get_location_node(layout_node, i) location_node = self.get_location_node(layout_node, i)
location_node.setAttribute("x", str( locations[i-1][0] )) location_node.setAttribute("x", str( locations[i-1][0] ))
location_node.setAttribute("y", str( locations[i-1][1] )) location_node.setAttribute("y", str( locations[i-1][1] ))
@ -472,35 +484,17 @@ class Config:
def get_default_colors(self, site = "PokerStars"): def get_default_colors(self, site = "PokerStars"):
colors = {} colors = {}
if self.supported_sites[site].hudopacity == "": colors['hudopacity'] = float(self.supported_sites[site].hudopacity) if self.supported_sites[site].hudopacity != "" else 0.90
colors['hudopacity'] = 0.90 colors['hudbgcolor'] = self.supported_sites[site].hudbgcolor if self.supported_sites[site].hudbgcolor != "" else "#FFFFFF"
else: colors['hudfgcolor'] = self.supported_sites[site].hudfgcolor if self.supported_sites[site].hudfgcolor != "" else "#000000"
colors['hudopacity'] = float(self.supported_sites[site].hudopacity)
if self.supported_sites[site].hudbgcolor == "":
colors['hudbgcolor'] = "#FFFFFF"
else:
colors['hudbgcolor'] = self.supported_sites[site].hudbgcolor
if self.supported_sites[site].hudfgcolor == "":
colors['hudfgcolor'] = "#000000"
else:
colors['hudfgcolor'] = self.supported_sites[site].hudfgcolor
return colors return colors
def get_default_font(self, site = 'PokerStars'): def get_default_font(self, site = 'PokerStars'):
(font, font_size) = ("Sans", "8") font = self.supported_sites[site].font if self.supported_sites[site].font != "" else "Sans"
if self.supported_sites[site].font == "": font_size = self.supported_sites[site].font_size if self.supported_sites[site].font != "" else "8"
font = "Sans"
else:
font = self.supported_sites[site].font
if self.supported_sites[site].font_size == "":
font_size = "8"
else:
font_size = self.supported_sites[site].font_size
return (font, font_size) return (font, font_size)
def get_locations(self, site = "PokerStars", max = "8"): def get_locations(self, site = "PokerStars", max = "8"):
try: try:
locations = self.supported_sites[site].layout[max].location locations = self.supported_sites[site].layout[max].location
except: except:
@ -509,6 +503,16 @@ class Config:
( 0, 280), (121, 280), ( 46, 30) ) ( 0, 280), (121, 280), ( 46, 30) )
return locations return locations
def get_aux_locations(self, aux = "mucked", max = "9"):
try:
locations = self.aux_windows[aux].layout[max].location
except:
locations = ( ( 0, 0), (684, 61), (689, 239), (692, 346),
(586, 393), (421, 440), (267, 440), ( 0, 361),
( 0, 280), (121, 280), ( 46, 30) )
return locations
def get_supported_sites(self): def get_supported_sites(self):
"""Returns the list of supported sites.""" """Returns the list of supported sites."""
return self.supported_sites.keys() return self.supported_sites.keys()
@ -579,7 +583,7 @@ class Config:
def get_aux_parameters(self, name): def get_aux_parameters(self, name):
"""Gets a dict of mucked window parameters from the named mw.""" """Gets a dict of mucked window parameters from the named mw."""
param = {} param = {}
if self.aux_windows.has_key(name): if name in self.aux_windows:
for key in dir(self.aux_windows[name]): for key in dir(self.aux_windows[name]):
if key.startswith('__'): continue if key.startswith('__'): continue
value = getattr(self.aux_windows[name], key) value = getattr(self.aux_windows[name], key)
@ -592,7 +596,7 @@ class Config:
def get_game_parameters(self, name): def get_game_parameters(self, name):
"""Get the configuration parameters for the named game.""" """Get the configuration parameters for the named game."""
param = {} param = {}
if self.supported_games.has_key(name): if name in self.supported_games:
param['game_name'] = self.supported_games[name].game_name param['game_name'] = self.supported_games[name].game_name
param['db'] = self.supported_games[name].db param['db'] = self.supported_games[name].db
param['rows'] = self.supported_games[name].rows param['rows'] = self.supported_games[name].rows
@ -603,7 +607,7 @@ class Config:
def get_supported_games(self): def get_supported_games(self):
"""Get the list of supported games.""" """Get the list of supported games."""
sg = [] sg = []
for game in c.supported_games.keys(): for game in c.supported_games:
sg.append(c.supported_games[game].game_name) sg.append(c.supported_games[game].game_name)
return sg return sg
@ -661,6 +665,8 @@ if __name__== "__main__":
for mw in c.get_aux_windows(): for mw in c.get_aux_windows():
print c.get_aux_parameters(mw) print c.get_aux_parameters(mw)
print "mucked locations =", c.get_aux_locations('mucked', 9)
for site in c.supported_sites.keys(): for site in c.supported_sites.keys():
print "site = ", site, print "site = ", site,
print c.get_site_parameters(site) print c.get_site_parameters(site)

View File

@ -132,13 +132,15 @@ class Database:
def convert_cards(self, d): def convert_cards(self, d):
ranks = ('', '', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A') ranks = ('', '', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A')
cards = "" cards = ""
for i in range(1, 8): for i in xrange(1, 8):
if d['card' + str(i) + 'Value'] == None: cv = "card%dValue" % i
if d[cv] == None:
break break
elif d['card' + str(i) + 'Value'] == 0: elif d[cv] == 0:
cards += "xx" cards = "%sxx" % cards
else: else:
cards += ranks[d['card' + str(i) + 'Value']] + d['card' +str(i) + 'Suit'] cs = "card%dSuit" % i
cards = "%s%s%s" % (cards, ranks[d[cv]], cs)
return cards return cards
def get_action_from_hand(self, hand_no): def get_action_from_hand(self, hand_no):

View File

@ -18,9 +18,9 @@
######################################################################## ########################################################################
import sys import sys
import logging
from HandHistoryConverter import * from HandHistoryConverter import *
# Class for converting Everleaf HH format. # Class for converting Everleaf HH format.
class Everleaf(HandHistoryConverter): class Everleaf(HandHistoryConverter):
@ -29,8 +29,6 @@ class Everleaf(HandHistoryConverter):
re_SplitHands = re.compile(r"\n\n+") re_SplitHands = re.compile(r"\n\n+")
re_GameInfo = re.compile(u"^(Blinds )?(?P<currency>\$| €|)(?P<sb>[.0-9]+)/(?:\$| €)?(?P<bb>[.0-9]+) (?P<limit>NL|PL|) (?P<game>(Hold\'em|Omaha|7 Card Stud))", re.MULTILINE) re_GameInfo = re.compile(u"^(Blinds )?(?P<currency>\$| €|)(?P<sb>[.0-9]+)/(?:\$| €)?(?P<bb>[.0-9]+) (?P<limit>NL|PL|) (?P<game>(Hold\'em|Omaha|7 Card Stud))", re.MULTILINE)
re_HandInfo = re.compile(u".*#(?P<HID>[0-9]+)\n.*\n(Blinds )?(?:\$| €|)(?P<SB>[.0-9]+)/(?:\$| €|)(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<DATETIME>\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P<TABLE>[- a-zA-Z]+)") re_HandInfo = re.compile(u".*#(?P<HID>[0-9]+)\n.*\n(Blinds )?(?:\$| €|)(?P<SB>[.0-9]+)/(?:\$| €|)(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<DATETIME>\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P<TABLE>[- a-zA-Z]+)")
# re_GameInfo = re.compile(r".*Blinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<LTYPE>(NL|PL)) (?P<GAME>(Hold\'em|Omaha|7 Card Stud))")
#re_HandInfo = re.compile(r".*#(?P<HID>[0-9]+)\n.*\nBlinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<DATETIME>\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P<TABLE>[- a-zA-Z]+)", re.MULTILINE)
re_Button = re.compile(r"^Seat (?P<BUTTON>\d+) is the button", re.MULTILINE) re_Button = re.compile(r"^Seat (?P<BUTTON>\d+) is the button", re.MULTILINE)
re_PlayerInfo = re.compile(u"^Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\s+((?:\$| €|) (?P<CASH>[.0-9]+) (USD|EUR|)|new player|All-in) \)", re.MULTILINE) re_PlayerInfo = re.compile(u"^Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\s+((?:\$| €|) (?P<CASH>[.0-9]+) (USD|EUR|)|new player|All-in) \)", re.MULTILINE)
re_Board = re.compile(r"\[ (?P<CARDS>.+) \]") re_Board = re.compile(r"\[ (?P<CARDS>.+) \]")
@ -48,7 +46,7 @@ follow : whether to tail -f the input"""
if autostart: if autostart:
self.start() self.start()
def compilePlayerRegexs(self, hand): def compilePlayerRegexs(self, hand):
players = set([player[1] for player in hand.players]) players = set([player[1] for player in hand.players])
if not players <= self.compiledPlayers: # x <= y means 'x is subset of y' if not players <= self.compiledPlayers: # x <= y means 'x is subset of y'
# we need to recompile the player regexs. # we need to recompile the player regexs.
@ -179,7 +177,6 @@ follow : whether to tail -f the input"""
hand.addStreets(m) hand.addStreets(m)
def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand
# If this has been called, street is a street which gets dealt community cards by type hand # If this has been called, street is a street which gets dealt community cards by type hand
# but it might be worth checking somehow. # but it might be worth checking somehow.
@ -265,7 +262,7 @@ follow : whether to tail -f the input"""
if __name__ == "__main__": if __name__ == "__main__":
parser = OptionParser() parser = OptionParser()
parser.add_option("-i", "--input", dest="ipath", help="parse input hand history", default="regression-test-files/everleaf/Speed_Kuala_full.txt") parser.add_option("-i", "--input", dest="ipath", help="parse input hand history", default="regression-test-files/everleaf/plo/Naos.txt")
parser.add_option("-o", "--output", dest="opath", help="output translation to", default="-") parser.add_option("-o", "--output", dest="opath", help="output translation to", default="-")
parser.add_option("-f", "--follow", dest="follow", help="follow (tail -f) the input", action="store_true", default=False) parser.add_option("-f", "--follow", dest="follow", help="follow (tail -f) the input", action="store_true", default=False)
parser.add_option("-q", "--quiet", parser.add_option("-q", "--quiet",
@ -282,4 +279,3 @@ if __name__ == "__main__":
e = Everleaf(in_path = options.ipath, out_path = options.opath, follow = options.follow) e = Everleaf(in_path = options.ipath, out_path = options.opath, follow = options.follow)

View File

@ -1054,6 +1054,137 @@ class FpdbSQLQueries:
elif(self.dbname == 'SQLite'): elif(self.dbname == 'SQLite'):
self.query['playerStatsByPosition'] = """ """ self.query['playerStatsByPosition'] = """ """
if(self.dbname == 'MySQL InnoDB'):
self.query['playerStatsByPositionAndHoleCards'] = """
SELECT
concat(upper(stats.limitType), ' '
,concat(upper(substring(stats.category,1,1)),substring(stats.category,2) ), ' '
,stats.name, ' $'
,cast(trim(leading ' ' from
case when stats.bigBlind < 100 then format(stats.bigBlind/100.0,2)
else format(stats.bigBlind/100.0,0)
end ) as char)
) AS Game
,case when stats.PlPosition = -2 then 'BB'
when stats.PlPosition = -1 then 'SB'
when stats.PlPosition = 0 then 'Btn'
when stats.PlPosition = 1 then 'CO'
when stats.PlPosition = 2 then 'MP'
when stats.PlPosition = 5 then 'EP'
else '??'
end AS PlPosition
/*,stats.n*/,hprof2.n
/*,stats.vpip*/,0
/*,stats.pfr*/,0
/*,stats.saw_f*/,0
/*,stats.sawsd*/,0
/*,stats.wtsdwsf*/,0
/*,stats.wmsd*/,0
/*,stats.FlAFq*/,0
/*,stats.TuAFq*/,0
/*,stats.RvAFq*/,0
/*,stats.PoFAFq*/,0
/* if you have handsactions data the next 3 fields should give same answer as
following 3 commented out fields */
/*,stats.Net
,stats.BBper100
,stats.Profitperhand*/
,format(hprof2.sum_profit/100.0,2) AS Net
/*,format((hprof2.sum_profit/(stats.bigBlind+0.0)) / (stats.n/100.0),2)*/,0
AS BBlPer100
,hprof2.profitperhand AS Profitperhand
,format(hprof2.variance,2) AS Variance
FROM
(select /* stats from hudcache */
gt.base
,gt.category
,upper(gt.limitType) as limitType
,s.name
,gt.bigBlind
,hc.gametypeId
,case when hc.position = 'B' then -2
when hc.position = 'S' then -1
when hc.position = 'D' then 0
when hc.position = 'C' then 1
when hc.position = 'M' then 2
when hc.position = 'E' then 5
else 9
end as PlPosition
,sum(HDs) AS n
,format(100.0*sum(street0VPI)/sum(HDs),1) AS vpip
,format(100.0*sum(street0Aggr)/sum(HDs),1) AS pfr
,format(100.0*sum(street1Seen)/sum(HDs),1) AS saw_f
,format(100.0*sum(sawShowdown)/sum(HDs),1) AS sawsd
,case when sum(street1Seen) = 0 then 'oo'
else format(100.0*sum(sawShowdown)/sum(street1Seen),1)
end AS wtsdwsf
,case when sum(sawShowdown) = 0 then 'oo'
end AS wtsdwsf
,case when sum(sawShowdown) = 0 then 'oo'
else format(100.0*sum(wonAtSD)/sum(sawShowdown),1)
end AS wmsd
,case when sum(street1Seen) = 0 then 'oo'
else format(100.0*sum(street1Aggr)/sum(street1Seen),1)
end AS FlAFq
,case when sum(street2Seen) = 0 then 'oo'
else format(100.0*sum(street2Aggr)/sum(street2Seen),1)
end AS TuAFq
,case when sum(street3Seen) = 0 then 'oo'
else format(100.0*sum(street3Aggr)/sum(street3Seen),1)
end AS RvAFq
,case when sum(street1Seen)+sum(street2Seen)+sum(street3Seen) = 0 then 'oo'
else format(100.0*(sum(street1Aggr)+sum(street2Aggr)+sum(street3Aggr))
/(sum(street1Seen)+sum(street2Seen)+sum(street3Seen)),1)
end AS PoFAFq
,format(sum(totalProfit)/100.0,2) AS Net
,format((sum(totalProfit)/(gt.bigBlind+0.0)) / (sum(HDs)/100.0),2)
AS BBper100
,format( (sum(totalProfit)/100.0) / sum(HDs), 4) AS Profitperhand
from Gametypes gt
inner join Sites s on s.Id = gt.siteId
inner join HudCache hc on hc.gameTypeId = gt.Id
where hc.playerId in <player_test>
# use <gametype_test> here ?
group by gt.base
,gt.category
,upper(gt.limitType)
,s.name
,gt.bigBlind
,hc.gametypeId
,PlPosition
) stats
inner join
( select # profit from handsplayers/handsactions
hprof.gameTypeId,
case when hprof.position = 'B' then -2
when hprof.position = 'S' then -1
when hprof.position in ('3','4') then 2
when hprof.position in ('6','7') then 5
else hprof.position
end as PlPosition,
sum(hprof.profit) as sum_profit,
avg(hprof.profit/100.0) as profitperhand,
variance(hprof.profit/100.0) as variance,
count(*) as n
from
(select hp.handId, h.gameTypeId, hp.position, hp.winnings, SUM(ha.amount)
costs, hp.winnings - SUM(ha.amount) profit
from HandsPlayers hp
inner join Hands h ON h.id = hp.handId
left join HandsActions ha ON ha.handPlayerId = hp.id
where hp.playerId in <player_test>
# use <gametype_test> here ?
and hp.tourneysPlayersId IS NULL
and ((hp.card1Value = <first_card> and hp.card2Value = <second_card>) or (hp.card1Value = <second_card> and hp.card2Value = <first_card>))
group by hp.handId, h.gameTypeId, hp.position, hp.winnings
) hprof
group by hprof.gameTypeId, PlPosition
) hprof2
on ( hprof2.gameTypeId = stats.gameTypeId
and hprof2.PlPosition = stats.PlPosition)
order by stats.category, stats.limittype, stats.bigBlind, cast(stats.PlPosition as signed)
"""
if __name__== "__main__": if __name__== "__main__":
from optparse import OptionParser from optparse import OptionParser

View File

@ -17,6 +17,7 @@
######################################################################## ########################################################################
import sys import sys
import logging
from HandHistoryConverter import * from HandHistoryConverter import *
# FullTilt HH Format converter # FullTilt HH Format converter
@ -43,8 +44,7 @@ follow : whether to tail -f the input"""
if autostart: if autostart:
self.start() self.start()
def compilePlayerRegexs(self, players):
def compilePlayerRegexs(self, players):
if not players <= self.compiledPlayers: # x <= y means 'x is subset of y' if not players <= self.compiledPlayers: # x <= y means 'x is subset of y'
# we need to recompile the player regexs. # we need to recompile the player regexs.
self.compiledPlayers = players self.compiledPlayers = players
@ -172,7 +172,8 @@ follow : whether to tail -f the input"""
def readBringIn(self, hand): def readBringIn(self, hand):
m = self.re_BringIn.search(hand.handText,re.DOTALL) m = self.re_BringIn.search(hand.handText,re.DOTALL)
print "DEBUG: Player bringing in: %s for %s" %(m.group('PNAME'), m.group('BRINGIN')) logging.debug("Player bringing in: %s for %s" %(m.group('PNAME'), m.group('BRINGIN')))
hand.addBringIn(m.group('PNAME'), m.group('BRINGIN')) hand.addBringIn(m.group('PNAME'), m.group('BRINGIN'))
def readButton(self, hand): def readButton(self, hand):

View File

@ -46,9 +46,15 @@ class GuiGraphViewer (threading.Thread):
return self.mainHBox return self.mainHBox
#end def get_vbox #end def get_vbox
def clearGraphData(self):
self.fig.clf()
if self.canvas is not None:
self.canvas.destroy()
self.canvas = FigureCanvas(self.fig) # a gtk.DrawingArea
def generateGraph(self, widget, data): def generateGraph(self, widget, data):
try: self.canvas.destroy() self.clearGraphData()
except AttributeError: pass
sitenos = [] sitenos = []
playerids = [] playerids = []
@ -72,7 +78,6 @@ class GuiGraphViewer (threading.Thread):
print "No player ids found" print "No player ids found"
return return
self.fig = Figure(figsize=(5,4), dpi=100)
#Set graph properties #Set graph properties
self.ax = self.fig.add_subplot(111) self.ax = self.fig.add_subplot(111)
@ -104,7 +109,6 @@ class GuiGraphViewer (threading.Thread):
#Draw plot #Draw plot
self.ax.plot(line,) self.ax.plot(line,)
self.canvas = FigureCanvas(self.fig) # a gtk.DrawingArea
self.graphBox.add(self.canvas) self.graphBox.add(self.canvas)
self.canvas.show() self.canvas.show()
#end of def showClicked #end of def showClicked
@ -376,6 +380,9 @@ class GuiGraphViewer (threading.Thread):
self.leftPanelBox.show() self.leftPanelBox.show()
self.graphBox.show() self.graphBox.show()
self.fig = Figure(figsize=(5,4), dpi=100)
self.canvas = None
################################# #################################
# #
# self.db.cursor.execute("""select UNIX_TIMESTAMP(handStart) as time, id from Hands ORDER BY time""") # self.db.cursor.execute("""select UNIX_TIMESTAMP(handStart) as time, id from Hands ORDER BY time""")

View File

@ -0,0 +1,211 @@
#!/usr/bin/python
#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 <http://www.gnu.org/licenses/>.
#In the "official" distribution you can find the license in
#agpl-3.0.txt in the docs folder of the package.
import threading
import pygtk
pygtk.require('2.0')
import gtk
import os
import fpdb_import
import fpdb_db
import FpdbSQLQueries
class GuiPositionalStats (threading.Thread):
def get_vbox(self):
"""returns the vbox of this thread"""
return self.main_hbox
def toggleCallback(self, widget, data=None):
# print "%s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()])
self.activesite = data
print "DEBUG: activesite set to %s" %(self.activesite)
def cardCallback(self, widget, data=None):
print "DEBUG: %s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()])
def refreshStats(self, widget, data):
try: self.stats_table.destroy()
except AttributeError: pass
self.fillStatsFrame(self.stats_frame)
def fillStatsFrame(self, vbox):
# Get currently active site and grab playerid
print "DEBUG: attempting to fill stats frame"
tmp = self.sql.query['playerStatsByPosition']
result = self.cursor.execute(self.sql.query['getPlayerId'], (self.heroes[self.activesite],))
result = self.cursor.fetchall()
if not result == ():
pid = result[0][0]
pid = result[0][0]
tmp = tmp.replace("<player_test>", "(" + str(pid) + ")")
self.cursor.execute(tmp)
result = self.cursor.fetchall()
cols = 16
rows = len(result)+1 # +1 for title row
self.stats_table = gtk.Table(rows, cols, False)
self.stats_table.set_col_spacings(4)
self.stats_table.show()
vbox.add(self.stats_table)
# Create header row
titles = ("Game", "Position", "#", "VPIP", "PFR", "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq", "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance")
col = 0
row = 0
for t in titles:
l = gtk.Label(titles[col])
l.show()
self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK)
col +=1
for row in range(rows-1):
if(row%2 == 0):
bgcolor = "white"
else:
bgcolor = "lightgrey"
for col in range(cols):
eb = gtk.EventBox()
eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor))
if result[row][col]:
l = gtk.Label(result[row][col])
else:
l = gtk.Label(' ')
if col == 0:
l.set_alignment(xalign=0.0, yalign=0.5)
else:
l.set_alignment(xalign=1.0, yalign=0.5)
eb.add(l)
self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK)
l.show()
eb.show()
self.fdb.db.commit()
#end def fillStatsFrame(self, vbox):
def fillPlayerFrame(self, vbox):
for site in self.conf.supported_sites.keys():
hbox = gtk.HBox(False, 0)
vbox.pack_start(hbox, False, True, 0)
hbox.show()
player = self.conf.supported_sites[site].screen_name
self.createPlayerLine(hbox, site, player)
hbox = gtk.HBox(False, 0)
button = gtk.Button("Refresh")
button.connect("clicked", self.refreshStats, False)
button.show()
hbox.add(button)
vbox.pack_start(hbox, False, True, 0)
hbox.show()
def fillCardsFrame(self, vbox):
hbox1 = gtk.HBox(True,0)
hbox1.show()
vbox.pack_start(hbox1, True, True, 0)
cards = [ "A", "K","Q","J","T","9","8","7","6","5","4","3","2" ]
for j in range(0, len(cards)):
hbox1 = gtk.HBox(True,0)
hbox1.show()
vbox.pack_start(hbox1, True, True, 0)
for i in range(0, len(cards)):
if i < (j + 1):
suit = "o"
else:
suit = "s"
button = gtk.ToggleButton("%s%s%s" %(cards[i], cards[j], suit))
button.connect("toggled", self.cardCallback, "%s%s%s" %(cards[i], cards[j], suit))
hbox1.pack_start(button, True, True, 0)
button.show()
def createPlayerLine(self, hbox, site, player):
if(self.buttongroup == None):
button = gtk.RadioButton(None, site + " id:")
button.set_active(True)
self.buttongroup = button
self.activesite = site
else:
button = gtk.RadioButton(self.buttongroup, site + " id:")
hbox.pack_start(button, True, True, 0)
button.connect("toggled", self.toggleCallback, site)
button.show()
pname = gtk.Entry()
pname.set_text(player)
pname.set_width_chars(20)
hbox.pack_start(pname, False, True, 0)
pname.connect("changed", self.__set_hero_name, site)
#TODO: Look at GtkCompletion - to fill out usernames
pname.show()
self.__set_hero_name(pname, site)
def __set_hero_name(self, w, site):
self.heroes[site] = w.get_text()
def __init__(self, db, config, querylist, debug=True):
self.debug=debug
self.conf=config
# create new db connection to avoid conflicts with other threads
self.fdb = fpdb_db.fpdb_db()
self.fdb.do_connect(self.conf)
self.cursor=self.fdb.cursor
self.sql = querylist
self.activesite = None
self.buttongroup = None
self.heroes = {}
self.stat_table = None
self.stats_frame = None
self.main_hbox = gtk.HBox(False, 0)
self.main_hbox.show()
playerFrame = gtk.Frame("Hero:")
playerFrame.set_label_align(0.0, 0.0)
playerFrame.show()
vbox = gtk.VBox(False, 0)
vbox.show()
self.fillPlayerFrame(vbox)
playerFrame.add(vbox)
cardsFrame = gtk.Frame("Cards:")
cardsFrame.set_label_align(0.0, 0.0)
cardsFrame.show()
vbox = gtk.VBox(False, 0)
vbox.show()
self.fillCardsFrame(vbox)
cardsFrame.add(vbox)
statsFrame = gtk.Frame("Stats:")
statsFrame.set_label_align(0.0, 0.0)
statsFrame.show()
self.stats_frame = gtk.VBox(False, 0)
self.stats_frame.show()
self.fillStatsFrame(self.stats_frame)
statsFrame.add(self.stats_frame)
self.main_hbox.pack_start(playerFrame)
self.main_hbox.pack_start(statsFrame)

View File

@ -4,7 +4,7 @@
Main for FreePokerTools HUD. Main for FreePokerTools HUD.
""" """
# Copyright 2008, Ray E. Barker # Copyright 2008, 2009, Ray E. Barker
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -83,6 +83,7 @@ class HUD_main(object):
self.hud_dict[table].main_window.destroy() self.hud_dict[table].main_window.destroy()
self.vb.remove(self.hud_dict[table].tablehudlabel) self.vb.remove(self.hud_dict[table].tablehudlabel)
del(self.hud_dict[table]) del(self.hud_dict[table])
self.main_window.resize(1,1)
def create_HUD(self, new_hand_id, table, table_name, max, poker_game, is_tournament, stat_dict, cards): def create_HUD(self, new_hand_id, table, table_name, max, poker_game, is_tournament, stat_dict, cards):
@ -93,11 +94,12 @@ class HUD_main(object):
newlabel = gtk.Label(table.site + " - " + table_name) newlabel = gtk.Label(table.site + " - " + table_name)
self.vb.add(newlabel) self.vb.add(newlabel)
newlabel.show() newlabel.show()
self.main_window.resize_children()
self.hud_dict[table_name].tablehudlabel = newlabel self.hud_dict[table_name].tablehudlabel = newlabel
self.hud_dict[table_name].create(new_hand_id, self.config, stat_dict, cards) self.hud_dict[table_name].create(new_hand_id, self.config, stat_dict, cards)
for m in self.hud_dict[table_name].aux_windows: for m in self.hud_dict[table_name].aux_windows:
m.update_data(new_hand_id, self.db_connection) m.create()
m.update_gui(new_hand_id) m.update_gui(new_hand_id)
self.hud_dict[table_name].update(new_hand_id, self.config) self.hud_dict[table_name].update(new_hand_id, self.config)
self.hud_dict[table_name].reposition_windows() self.hud_dict[table_name].reposition_windows()
@ -106,6 +108,10 @@ class HUD_main(object):
gtk.gdk.threads_leave() gtk.gdk.threads_leave()
self.hud_dict[table_name] = Hud.Hud(self, table, max, poker_game, self.config, self.db_connection) self.hud_dict[table_name] = Hud.Hud(self, table, max, poker_game, self.config, self.db_connection)
self.hud_dict[table_name].stat_dict = stat_dict
self.hud_dict[table_name].cards = cards
for aw in self.hud_dict[table_name].aux_windows:
aw.update_data(new_hand_id, self.db_connection)
gobject.idle_add(idle_func) gobject.idle_add(idle_func)
def update_HUD(self, new_hand_id, table_name, config): def update_HUD(self, new_hand_id, table_name, config):
@ -117,8 +123,7 @@ class HUD_main(object):
gtk.gdk.threads_enter() gtk.gdk.threads_enter()
try: try:
self.hud_dict[table_name].update(new_hand_id, config) self.hud_dict[table_name].update(new_hand_id, config)
for m in self.hud_dict[table_name].aux_windows: map(lambda aw: aw.update_gui(new_hand_id), self.hud_dict[table_name].aux_windows)
m.update_gui(new_hand_id)
return False return False
finally: finally:
gtk.gdk.threads_leave() gtk.gdk.threads_leave()
@ -134,7 +139,7 @@ class HUD_main(object):
self.db_connection = Database.Database(self.config, self.db_name, 'temp') self.db_connection = Database.Database(self.config, self.db_name, 'temp')
tourny_finder = re.compile('(\d+) (\d+)') tourny_finder = re.compile('(\d+) (\d+)')
while True: # wait for a new hand number on stdin while 1: # wait for a new hand number on stdin
new_hand_id = sys.stdin.readline() new_hand_id = sys.stdin.readline()
new_hand_id = string.rstrip(new_hand_id) new_hand_id = string.rstrip(new_hand_id)
if new_hand_id == "": # blank line means quit if new_hand_id == "": # blank line means quit
@ -181,7 +186,7 @@ class HUD_main(object):
if tablewindow == None: if tablewindow == None:
# If no client window is found on the screen, complain and continue # If no client window is found on the screen, complain and continue
if is_tournament: if is_tournament:
table_name = tour_number + " " + tab_number table_name = "%s %s" % (tour_number, tab_number)
sys.stderr.write("table name "+table_name+" not found, skipping.\n") sys.stderr.write("table name "+table_name+" not found, skipping.\n")
else: else:
self.create_HUD(new_hand_id, tablewindow, temp_key, max, poker_game, is_tournament, stat_dict, cards) self.create_HUD(new_hand_id, tablewindow, temp_key, max, poker_game, is_tournament, stat_dict, cards)

View File

@ -44,7 +44,6 @@ class Hand:
self.posted = [] self.posted = []
self.involved = True self.involved = True
# Collections indexed by street names # Collections indexed by street names
self.bets = {} self.bets = {}
self.lastBet = {} self.lastBet = {}
@ -103,7 +102,6 @@ If a player has None chips he won't be added."""
else: else:
logging.error("markstreets didn't match") logging.error("markstreets didn't match")
#def addHoleCards -- to Holdem subclass #def addHoleCards -- to Holdem subclass
@ -142,7 +140,6 @@ If a player has None chips he won't be added."""
# - this is a call of 1 sb and a raise to 1 bb # - this is a call of 1 sb and a raise to 1 bb
# #
logging.debug("addBlind: %s posts %s, %s" % (player, blindtype, amount)) logging.debug("addBlind: %s posts %s, %s" % (player, blindtype, amount))
if player is not None: if player is not None:
self.bets['PREFLOP'][player].append(Decimal(amount)) self.bets['PREFLOP'][player].append(Decimal(amount))
@ -161,7 +158,6 @@ If a player has None chips he won't be added."""
def addCall(self, street, player=None, amount=None): def addCall(self, street, player=None, amount=None):
# Potentially calculate the amount of the call if not supplied # Potentially calculate the amount of the call if not supplied
# corner cases include if player would be all in # corner cases include if player would be all in
@ -695,8 +691,6 @@ closed likewise, but known only to player
class Pot(object): class Pot(object):

View File

@ -172,7 +172,7 @@ class HandHistoryConverter(threading.Thread):
return return
self.obs = self.obs.replace('\r\n', '\n') self.obs = self.obs.replace('\r\n', '\n')
self.gametype = self.determineGameType() self.gametype = self.determineGameType(self.obs)
if self.gametype == None: if self.gametype == None:
print "Unknown game type from file, aborting on this file." print "Unknown game type from file, aborting on this file."
return return
@ -208,7 +208,7 @@ class HandHistoryConverter(threading.Thread):
# Read actions in street order # Read actions in street order
for street in hand.streetList: # go through them in order for street in hand.streetList: # go through them in order
print "DEBUG: ", street # print "DEBUG: ", street
if hand.streets.group(street) is not None: if hand.streets.group(street) is not None:
if self.gametype[1] == "hold" or self.gametype[1] == "omahahi": if self.gametype[1] == "hold" or self.gametype[1] == "omahahi":
self.readCommunityCards(hand, street) # read community cards self.readCommunityCards(hand, street) # read community cards
@ -247,7 +247,7 @@ class HandHistoryConverter(threading.Thread):
# type base limit # type base limit
# [ ring, hold, nl , sb, bb ] # [ ring, hold, nl , sb, bb ]
# Valid types specified in docs/tabledesign.html in Gametypes # Valid types specified in docs/tabledesign.html in Gametypes
def determineGameType(self): abstract def determineGameType(self, handText): abstract
# Read any of: # Read any of:
# HID HandID # HID HandID
@ -331,7 +331,7 @@ class HandHistoryConverter(threading.Thread):
return hands return hands
def readFile(self): def readFile(self):
"""Read in_path into self.obs or self.doc""" """Read in path into self.obs or self.doc"""
if(self.filetype == "text"): if(self.filetype == "text"):
if self.in_path == '-': if self.in_path == '-':

101
pyfpdb/Hello.py Normal file
View File

@ -0,0 +1,101 @@
#!/usr/bin/env python
"""Hello.py
Hello World demostration for Aux_Window.
"""
# 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
########################################################################
# to do
# add another class that demonstrates querying the db
# Standard Library modules
import sys
# pyGTK modules
import pygtk
import gtk
import gobject
# FreePokerTools modules
from Mucked import Aux_Window
class Hello(Aux_Window):
"""A 'Hello World' Aux_Window demo."""
def create(self):
# This demo simply creates a label in a window.
self.container = gtk.Window()
self.container.add(gtk.Label("Hello World"))
# and shows it. There is no functionality.
self.container.show_all()
class Hello_plus(Aux_Window):
"""A slightly more complex 'Hello World demo."""
def __init__(self, hud, config, params):
"""Initialize a new aux_window object."""
# Initialize the aux_window object. Do not interact with the gui
# in this function.
self.hud = hud # hud object that this aux window supports
self.config = config # configuration object for this aux window to use
self.params = params # hash aux params from config
self.hands_played = 0 # initialize the hands played counter
# get the site we are playing from the HUD
self.site = hud.site
print "site =", hud.site # print it to the terminal, to make sure
# now get our screen name for that site from the configuration
# wrap it in a try/except in case screen name isn't set up in the config file
try:
site_params = self.config.get_site_parameters(self.hud.site)
self.hero = site_params['screen_name']
except:
self.hero = 'YOUR NAME HERE'
print "hero =", self.hero
def create(self):
"""Creates the gui."""
self.container = gtk.Window() # create a gtk window for our container
self.label = gtk.Label("") # create a blank label to write in update_gui
self.container.add(self.label) # add it to our container
self.container.show_all() # show the container and its contents
def update_data(self, new_hand_id, db_connection):
"""Increment the hands.played attribute."""
# This function will be called from the main program, in a thread separate from
# the gui. Therefore complex calculations can be done without slowing down the
# HUD. Long-running calculations will delay the appearance or updating of the HUD.
# This function should NOT interact with the gui--that will cause unpredictable
# results on some systems.
# This long running calculation is incrementing the number of hands played.
self.hands_played = self.hands_played + 1
def update_gui(self, new_hand_id):
"""Update the aux_window gui."""
# This function runs inside the gui thread and should only be used for
# interacting with the gui. Long-running calculations should not be done
# in this function--they will prevent HUD interaction until they are
# complete.
# Here, we just update the label in our aux_window from the number of
# hands played that was updated in the "update_data()" function.
self.label.set_text("Hello %s\nYou have played %d hands\n on %s." % (self.hero, self.hands_played, self.site))

View File

@ -3,7 +3,7 @@
Create and manage the hud overlays. Create and manage the hud overlays.
""" """
# Copyright 2008, Ray E. Barker # Copyright 2008, 2009 Ray E. Barker
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
@ -45,6 +45,15 @@ import Mucked
import Database import Database
import HUD_main import HUD_main
def importName(module_name, name):
"""Import a named object 'name' from module 'module_name'."""
# Recipe 16.3 in the Python Cookbook, 2nd ed. Thanks!!!!
try:
module = __import__(module_name, globals(), locals(), [name])
except:
return None
return(getattr(module, name))
class Hud: class Hud:
def __init__(self, parent, table, max, poker_game, config, db_connection): def __init__(self, parent, table, max, poker_game, config, db_connection):
@ -75,13 +84,21 @@ class Hud:
self.font = pango.FontDescription(font + " " + font_size) self.font = pango.FontDescription(font + " " + font_size)
# do we need to add some sort of condition here for dealing with a request for a font that doesn't exist? # do we need to add some sort of condition here for dealing with a request for a font that doesn't exist?
game_params = config.get_game_parameters(self.poker_game)
if not game_params['aux'] == [""]:
for aux in game_params['aux']:
aux_params = config.get_aux_parameters(aux)
my_import = importName(aux_params['module'], aux_params['class'])
if my_import == None:
continue
self.aux_windows.append(my_import(self, config, aux_params))
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() self.main_window = gtk.Window()
self.main_window.set_gravity(gtk.gdk.GRAVITY_STATIC) self.main_window.set_gravity(gtk.gdk.GRAVITY_STATIC)
self.main_window.set_title(self.table.name + " FPDBHUD") self.main_window.set_title("%s FPDBHUD" % (self.table.name))
# self.main_window.destroyhandler = self.main_window.connect("destroy", self.kill_hud)
self.main_window.set_decorated(False) self.main_window.set_decorated(False)
self.main_window.set_opacity(self.colors["hudopacity"]) self.main_window.set_opacity(self.colors["hudopacity"])
@ -135,7 +152,7 @@ class Hud:
if os.name == 'nt': if os.name == 'nt':
self.topify_window(self.main_window) self.topify_window(self.main_window)
else: else:
self.main_window.parentgdkhandle = gtk.gdk.window_foreign_new(self.table.number) # gets a gdk handle for poker client 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 = gtk.gdk.window_foreign_new(self.main_window.window.xid) # gets a gdk handle for the hud table window
self.main_window.gdkhandle.set_transient_for(self.main_window.parentgdkhandle) # self.main_window.gdkhandle.set_transient_for(self.main_window.parentgdkhandle) #
@ -153,7 +170,7 @@ class Hud:
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)
for i in range(1, self.max + 1): for i in xrange(1, self.max + 1):
(x, y) = loc[adj[i]] (x, y) = loc[adj[i]]
if i in self.stat_windows: if i in self.stat_windows:
self.stat_windows[i].relocate(x, y) self.stat_windows[i].relocate(x, y)
@ -172,18 +189,15 @@ class Hud:
# kill all stat_windows, popups and aux_windows in this HUD # kill all stat_windows, popups and aux_windows in this HUD
# heap dead, burnt bodies, blood 'n guts, veins between my teeth # heap dead, burnt bodies, blood 'n guts, veins between my teeth
for s in self.stat_windows.itervalues(): for s in self.stat_windows.itervalues():
for p in s.popups: s.kill_popups()
s.kill_popup(p)
s.window.destroy() s.window.destroy()
self.stat_windows = {} self.stat_windows = {}
# also kill any aux windows # also kill any aux windows
for m in self.aux_windows: map(lambda m: m.destroy(), self.aux_windows)
m.destroy()
self.aux_windows = [] self.aux_windows = []
def reposition_windows(self, *args): def reposition_windows(self, *args):
for w in self.stat_windows: map(lambda x: x.window.move(x.x, x.y), self.stat_windows)
self.stat_windows[w].window.move(self.stat_windows[w].x, self.stat_windows[w].y)
return True return True
def debug_stat_windows(self, *args): def debug_stat_windows(self, *args):
@ -202,7 +216,7 @@ class Hud:
def adj_seats(self, hand, config): def adj_seats(self, hand, config):
adj = range(0, self.max + 1) # default seat adjustments = no adjustment adj = xrange(0, self.max + 1) # default seat adjustments = no adjustment
# does the user have a fav_seat? # does the user have a fav_seat?
try: try:
sys.stderr.write("site = %s, max = %d, fav seat = %d\n" % (self.table.site, self.max, config.supported_sites[self.table.site].layout[self.max].fav_seat)) sys.stderr.write("site = %s, max = %d, fav seat = %d\n" % (self.table.site, self.max, config.supported_sites[self.table.site].layout[self.max].fav_seat))
@ -212,7 +226,7 @@ class Hud:
# actual_seat = self.db_connection.get_actual_seat(hand, config.supported_sites[self.table.site].screen_name) # actual_seat = self.db_connection.get_actual_seat(hand, config.supported_sites[self.table.site].screen_name)
actual_seat = self.get_actual_seat(config.supported_sites[self.table.site].screen_name) actual_seat = self.get_actual_seat(config.supported_sites[self.table.site].screen_name)
sys.stderr.write("found actual seat = %d\n" % actual_seat) sys.stderr.write("found actual seat = %d\n" % actual_seat)
for i in range(0, self.max + 1): for i in xrange(0, self.max + 1):
j = actual_seat + i j = actual_seat + i
if j > self.max: j = j - self.max if j > self.max: j = j - self.max
adj[j] = fav_seat + i adj[j] = fav_seat + i
@ -223,7 +237,7 @@ class Hud:
return adj return adj
def get_actual_seat(self, name): def get_actual_seat(self, name):
for key in self.stat_dict.keys(): for key in self.stat_dict:
if self.stat_dict[key]['screen_name'] == name: if self.stat_dict[key]['screen_name'] == name:
return self.stat_dict[key]['seat'] return self.stat_dict[key]['seat']
sys.stderr.write("Error finding actual seat.\n") sys.stderr.write("Error finding actual seat.\n")
@ -245,7 +259,7 @@ class Hud:
loc = self.config.get_locations(self.table.site, self.max) loc = self.config.get_locations(self.table.site, self.max)
# create the stat windows # create the stat windows
for i in range(1, self.max + 1): for i in xrange(1, self.max + 1):
(x, y) = loc[adj[i]] (x, y) = loc[adj[i]]
if i in self.stat_windows: if i in self.stat_windows:
self.stat_windows[i].relocate(x, y) self.stat_windows[i].relocate(x, y)
@ -262,7 +276,7 @@ class Hud:
font = self.font) font = self.font)
self.stats = [] self.stats = []
for i in range(0, config.supported_games[self.poker_game].rows + 1): for i in xrange(0, config.supported_games[self.poker_game].rows + 1):
row_list = [''] * config.supported_games[self.poker_game].cols row_list = [''] * config.supported_games[self.poker_game].cols
self.stats.append(row_list) self.stats.append(row_list)
for stat in config.supported_games[self.poker_game].stats: for stat in config.supported_games[self.poker_game].stats:
@ -270,11 +284,6 @@ class Hud:
[config.supported_games[self.poker_game].stats[stat].col] = \ [config.supported_games[self.poker_game].stats[stat].col] = \
config.supported_games[self.poker_game].stats[stat].stat_name config.supported_games[self.poker_game].stats[stat].stat_name
game_params = config.get_game_parameters(self.poker_game)
if not game_params['aux'] == "":
aux_params = config.get_aux_parameters(game_params['aux'])
self.aux_windows.append(eval("%s.%s(gtk.Window(), self, config, aux_params)" % (aux_params['module'], aux_params['class'])))
if os.name == "nt": if os.name == "nt":
gobject.timeout_add(500, self.update_table_position) gobject.timeout_add(500, self.update_table_position)
@ -291,8 +300,8 @@ class Hud:
self.create(hand, config, self.stat_dict, self.cards) self.create(hand, config, self.stat_dict, self.cards)
self.stat_windows[self.stat_dict[s]['seat']].player_id = self.stat_dict[s]['player_id'] self.stat_windows[self.stat_dict[s]['seat']].player_id = self.stat_dict[s]['player_id']
for r in range(0, config.supported_games[self.poker_game].rows): for r in xrange(0, config.supported_games[self.poker_game].rows):
for c in range(0, config.supported_games[self.poker_game].cols): for c in xrange(0, config.supported_games[self.poker_game].cols):
this_stat = config.supported_games[self.poker_game].stats[self.stats[r][c]] this_stat = config.supported_games[self.poker_game].stats[self.stats[r][c]]
number = Stats.do_stat(self.stat_dict, player = self.stat_dict[s]['player_id'], stat = self.stats[r][c]) number = Stats.do_stat(self.stat_dict, player = self.stat_dict[s]['player_id'], stat = self.stats[r][c])
statstring = this_stat.hudprefix + str(number[1]) + this_stat.hudsuffix statstring = this_stat.hudprefix + str(number[1]) + this_stat.hudsuffix
@ -357,6 +366,10 @@ class Stat_Window:
popup.window.destroy() popup.window.destroy()
self.popups.remove(popup) self.popups.remove(popup)
def kill_popups(self):
map(lambda x: x.window.destroy(), self.popups)
self.popups = { }
def relocate(self, x, y): def relocate(self, x, y):
self.x = x + self.table.x self.x = x + self.table.x
self.y = y + self.table.y self.y = y + self.table.y
@ -390,35 +403,38 @@ class Stat_Window:
self.e_box = [] self.e_box = []
self.frame = [] self.frame = []
self.label = [] self.label = []
for r in range(self.game.rows): usegtkframes = self.useframes
if self.useframes: e_box = self.e_box
label = self.label
for r in xrange(self.game.rows):
if usegtkframes:
self.frame.append([]) self.frame.append([])
self.e_box.append([]) e_box.append([])
self.label.append([]) label.append([])
for c in range(self.game.cols): for c in xrange(self.game.cols):
if self.useframes: if usegtkframes:
self.frame[r].append( gtk.Frame() ) self.frame[r].append( gtk.Frame() )
self.e_box[r].append( gtk.EventBox() ) e_box[r].append( gtk.EventBox() )
self.e_box[r][c].modify_bg(gtk.STATE_NORMAL, parent.backgroundcolor) e_box[r][c].modify_bg(gtk.STATE_NORMAL, parent.backgroundcolor)
self.e_box[r][c].modify_fg(gtk.STATE_NORMAL, parent.foregroundcolor) e_box[r][c].modify_fg(gtk.STATE_NORMAL, parent.foregroundcolor)
Stats.do_tip(self.e_box[r][c], 'stuff') Stats.do_tip(e_box[r][c], 'stuff')
if self.useframes: if usegtkframes:
self.grid.attach(self.frame[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0) self.grid.attach(self.frame[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0)
self.frame[r][c].add(self.e_box[r][c]) self.frame[r][c].add(e_box[r][c])
else: else:
self.grid.attach(self.e_box[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0) self.grid.attach(e_box[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0)
self.label[r].append( gtk.Label('xxx') ) label[r].append( gtk.Label('xxx') )
if self.useframes: if usegtkframes:
self.frame[r][c].modify_bg(gtk.STATE_NORMAL, parent.backgroundcolor) self.frame[r][c].modify_bg(gtk.STATE_NORMAL, parent.backgroundcolor)
self.label[r][c].modify_bg(gtk.STATE_NORMAL, parent.backgroundcolor) label[r][c].modify_bg(gtk.STATE_NORMAL, parent.backgroundcolor)
self.label[r][c].modify_fg(gtk.STATE_NORMAL, parent.foregroundcolor) label[r][c].modify_fg(gtk.STATE_NORMAL, parent.foregroundcolor)
self.e_box[r][c].add(self.label[r][c]) e_box[r][c].add(self.label[r][c])
self.e_box[r][c].connect("button_press_event", self.button_press_cb) e_box[r][c].connect("button_press_event", self.button_press_cb)
self.label[r][c].modify_font(font) label[r][c].modify_font(font)
self.window.set_opacity(parent.colors['hudopacity']) self.window.set_opacity(parent.colors['hudopacity'])
@ -462,8 +478,8 @@ class Popup_window:
# figure out the row, col address of the click that activated the popup # figure out the row, col address of the click that activated the popup
row = 0 row = 0
col = 0 col = 0
for r in range(0, stat_window.game.rows): for r in xrange(0, stat_window.game.rows):
for c in range(0, stat_window.game.cols): for c in xrange(0, stat_window.game.cols):
if stat_window.e_box[r][c] == parent: if stat_window.e_box[r][c] == parent:
row = r row = r
col = c col = c
@ -544,7 +560,10 @@ class Popup_window:
for w in tl_windows: for w in tl_windows:
if w[1] == unique_name: if w[1] == unique_name:
win32gui.SetWindowPos(w[0], win32con.HWND_TOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE|win32con.SWP_NOSIZE) window.set_transient_for(self.parent.main_window)
style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE)
style |= win32con.WS_CLIPCHILDREN
win32gui.SetWindowLong(self.table.number, win32con.GWL_EXSTYLE, style)
window.set_title(real_name) window.set_title(real_name)

View File

@ -3,7 +3,7 @@
Mucked cards display for FreePokerTools HUD. Mucked cards display for FreePokerTools HUD.
""" """
# Copyright 2008, Ray E. Barker # Copyright 2008, 2009, Ray E. Barker
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -36,29 +36,53 @@ import Configuration
import Database import Database
class Aux_Window: class Aux_Window:
def __init__(self, container, hud, params, config): def __init__(self, hud, params, config):
self.config = hud self.config = hud
self.config = config self.config = config
self.container = container
self.vbox = gtk.VBox() def update_data(self, *parms):
self.container.add(self.vbox)
def update_data(self):
pass pass
def update_gui(self): def update_gui(self, *parms):
pass
def create(self, *parms):
pass pass
def destroy(self): def destroy(self):
self.container.destroy() self.container.destroy()
############################################################################
# Some utility routines useful for Aux_Windows
#
def get_card_images(self):
card_images = {}
suits = ('S', 'H', 'D', 'C')
ranks = ('A', 'K', 'Q', 'J', 'T', '9', '8', '7', '6', '5', '4', '3', '2', 'B')
pb = gtk.gdk.pixbuf_new_from_file(self.config.execution_path(self.params['deck']))
for j in range(0, 14):
for i in range(0, 4):
temp_pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, pb.get_has_alpha(), pb.get_bits_per_sample(), 30, 42)
pb.copy_area(30*j, 42*i, 30, 42, temp_pb, 0, 0)
card_images[(ranks[j], suits[i])] = temp_pb
return(card_images)
# cards are 30 wide x 42 high
def split_cards(self, card):
if card == 'xx': return ('B', 'S')
return (card[0], card[1].upper())
def has_cards(self, cards):
for c in cards:
if c in set('shdc'): return True
return False
class Stud_mucked(Aux_Window): class Stud_mucked(Aux_Window):
def __init__(self, container, hud, config, params): def __init__(self, hud, config, params):
self.hud = hud # hud object that this aux window supports self.hud = hud # hud object that this aux window supports
self.config = config # configuration object for this aux window to use self.config = config # configuration object for this aux window to use
self.container = container # parent container for this aux window widget
self.params = params # hash aux params from config self.params = params # hash aux params from config
try: try:
@ -67,12 +91,18 @@ class Stud_mucked(Aux_Window):
except: except:
self.hero = '' self.hero = ''
self.mucked_list = Stud_list(self, params, config, self.hero)
self.mucked_cards = Stud_cards(self, params, config)
self.mucked_list.mucked_cards = self.mucked_cards
def create(self):
self.container =gtk.Window()
self.vbox = gtk.VBox() self.vbox = gtk.VBox()
self.container.add(self.vbox) self.container.add(self.vbox)
self.mucked_list = Stud_list(self.vbox, self, params, config, self.hero) self.mucked_list.create(self.vbox)
self.mucked_cards = Stud_cards(self.vbox, self, params, config) self.mucked_cards.create(self.vbox)
self.mucked_list.mucked_cards = self.mucked_cards
self.container.show_all() self.container.show_all()
def update_data(self, new_hand_id, db_connection): def update_data(self, new_hand_id, db_connection):
@ -84,16 +114,16 @@ class Stud_mucked(Aux_Window):
self.mucked_list.update_gui(new_hand_id) self.mucked_list.update_gui(new_hand_id)
class Stud_list: class Stud_list:
def __init__(self, container, parent, params, config, hero): def __init__(self, parent, params, config, hero):
self.container = container
self.parent = parent self.parent = parent
self.params = params self.params = params
self.config = config self.config = config
self.hero = hero self.hero = hero
# self.db_name = db_name
def create(self, container):
# set up a scrolled window to hold the listbox # set up a scrolled window to hold the listbox
self.container = container
self.scrolled_window = gtk.ScrolledWindow() self.scrolled_window = gtk.ScrolledWindow()
self.scrolled_window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS) self.scrolled_window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
self.container.add(self.scrolled_window) self.container.add(self.scrolled_window)
@ -178,9 +208,8 @@ class Stud_list:
vadj.set_value(vadj.upper) vadj.set_value(vadj.upper)
class Stud_cards: class Stud_cards:
def __init__(self, container, parent, params, config): def __init__(self, parent, params, config):
self.container = container #this is the parent container of the mucked cards widget
self.parent = parent self.parent = parent
self.params = params self.params = params
self.config = config self.config = config
@ -193,6 +222,9 @@ class Stud_cards:
self.rows = 8 self.rows = 8
self.cols = 7 self.cols = 7
def create(self, container):
self.container = container
self.grid = gtk.Table(self.rows, self.cols + 4, homogeneous = False) self.grid = gtk.Table(self.rows, self.cols + 4, homogeneous = False)
for r in range(0, self.rows): for r in range(0, self.rows):
@ -267,9 +299,6 @@ class Stud_cards:
return self.parent.hud.stat_dict[k]['screen_name'] return self.parent.hud.stat_dict[k]['screen_name']
return "No Name" return "No Name"
def split_cards(self, card):
return (card[0], card[1].upper())
def clear(self): def clear(self):
for r in range(0, self.rows): for r in range(0, self.rows):
self.grid_contents[(1, r)].set_text(" ") self.grid_contents[(1, r)].set_text(" ")
@ -277,20 +306,80 @@ class Stud_cards:
self.seen_cards[(c, r)].set_from_pixbuf(self.card_images[('B', 'S')]) self.seen_cards[(c, r)].set_from_pixbuf(self.card_images[('B', 'S')])
self.eb[(c, r)].set_tooltip_text('') self.eb[(c, r)].set_tooltip_text('')
def get_card_images(self): class Flop_Mucked(Aux_Window):
card_images = {} """Aux_Window class for displaying mucked cards for flop games."""
suits = ('S', 'H', 'D', 'C')
ranks = ('A', 'K', 'Q', 'J', 'T', '9', '8', '7', '6', '5', '4', '3', '2', 'B')
pb = gtk.gdk.pixbuf_new_from_file(self.config.execution_path(self.params['deck']))
for j in range(0, 14): def __init__(self, hud, config, params):
for i in range(0, 4): self.hud = hud # hud object that this aux window supports
temp_pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, pb.get_has_alpha(), pb.get_bits_per_sample(), 30, 42) self.config = config # configuration object for this aux window to use
pb.copy_area(30*j, 42*i, 30, 42, temp_pb, 0, 0) self.params = params # hash aux params from config
card_images[(ranks[j], suits[i])] = temp_pb self.card_images = self.get_card_images()
return(card_images)
# cards are 30 wide x 42 high def create(self):
adj = self.hud.adj_seats(0, self.config)
loc = self.config.get_aux_locations(self.params['name'], int(self.hud.max))
# make a scratch pixbuf 7 cards wide for creating our images
self.scratch = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8,
7* int(self.params['card_wd']), int(self.params['card_ht']))
# create the stat windows
self.m_windows = {} # windows to put the card images
self.eb = {} # event boxes so we can interact with the mucked cards
self.seen_cards = {} # pixbufs to stash the cards in
for i in range(1, self.hud.max + 1):
(x, y) = loc[adj[i]]
self.m_windows[i] = gtk.Window()
self.m_windows[i].set_decorated(0)
self.m_windows[i].set_property("skip-taskbar-hint", True)
self.m_windows[i].set_transient_for(self.hud.main_window)
self.eb[i] = gtk.EventBox()
self.m_windows[i].add(self.eb[i])
self.seen_cards[i] = gtk.image_new_from_pixbuf(self.card_images[('B', 'H')])
self.eb[i].add(self.seen_cards[i])
self.m_windows[i].move(int(x) + self.hud.table.x, int(y) + self.hud.table.y)
self.m_windows[i].set_opacity(float(self.params['opacity']))
self.m_windows[i].show_all()
self.m_windows[i].hide()
def update_data(self, new_hand_id, db_connection):
pass
def update_gui(self, new_hand_id):
"""Prepare and show the mucked cards."""
for (i, cards) in self.hud.cards.iteritems():
pos = self.m_windows[i].get_position() # need this to reposition later
if self.has_cards(cards):
# scratch is a working pixbuf, used to assemble the image
scratch = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8,
int(self.params['card_wd'])*len(cards)/2,
int(self.params['card_ht']))
x = 0 # x coord where the next card starts in scratch
for card in [cards[k:k+2] for k in xrange(0, len(cards), 2)]:
# concatenate each card image to scratch
self.card_images[self.split_cards(card)].copy_area(0, 0,
int(self.params['card_wd']), int(self.params['card_ht']),
scratch, x, 0)
x = x + int(self.params['card_wd'])
self.seen_cards[i].set_from_pixbuf(scratch)
self.m_windows[i].move(pos[0], pos[1]) # I don't know why I need this
self.m_windows[i].show_all()
gobject.timeout_add(int(1000*float(self.params['timeout'])), self.hide_mucked_cards)
def destroy(self):
"""Destroy all of the mucked windows."""
for w in self.m_windows.values():
w.destroy()
def hide_mucked_cards(self):
"""Hide the mucked card windows."""
# this is the callback from the timeout
for w in self.m_windows.values():
w.hide()
return False # this tells the system to NOT run this timeout again
if __name__== "__main__": if __name__== "__main__":

View File

@ -22,13 +22,13 @@ from optparse import OptionParser
parser = OptionParser() parser = OptionParser()
parser.add_option("-x", "--errorsToConsole", action="store_true", parser.add_option("-x", "--errorsToConsole", action="store_true",
help="If passed error output will go to the console rather than .") help="If passed error output will go to the console rather than .")
(options, sys.argv) = parser.parse_args() (options, sys.argv) = parser.parse_args()
if not options.errorsToConsole: if not options.errorsToConsole:
print "Note: error output is being diverted to fpdb-error-log.txt and HUD-error.txt. Any major error will be reported there _only_." print "Note: error output is being diverted to fpdb-error-log.txt and HUD-error.txt. Any major error will be reported there _only_."
errorFile = open('fpdb-error-log.txt', 'w', 0) errorFile = open('fpdb-error-log.txt', 'w', 0)
sys.stderr = errorFile sys.stderr = errorFile
import pygtk import pygtk
pygtk.require('2.0') pygtk.require('2.0')
@ -38,6 +38,7 @@ import fpdb_db
import fpdb_simple import fpdb_simple
import GuiBulkImport import GuiBulkImport
import GuiPlayerStats import GuiPlayerStats
import GuiPositionalStats
import GuiTableViewer import GuiTableViewer
import GuiAutoImport import GuiAutoImport
import GuiGraphViewer import GuiGraphViewer
@ -47,419 +48,426 @@ import Configuration
VERSION = "0.10" VERSION = "0.10"
class fpdb: class fpdb:
def tab_clicked(self, widget, tab_name): def tab_clicked(self, widget, tab_name):
"""called when a tab button is clicked to activate that tab""" """called when a tab button is clicked to activate that tab"""
#print "start of tab_clicked" #print "start of tab_clicked"
self.display_tab(tab_name) self.display_tab(tab_name)
#end def tab_clicked #end def tab_clicked
def add_and_display_tab(self, new_tab, new_tab_name): def add_and_display_tab(self, new_tab, new_tab_name):
"""just calls the component methods""" """just calls the component methods"""
self.add_tab(new_tab, new_tab_name) self.add_tab(new_tab, new_tab_name)
self.display_tab(new_tab_name) self.display_tab(new_tab_name)
#end def add_and_display_tab #end def add_and_display_tab
def add_tab(self, new_tab, new_tab_name): def add_tab(self, new_tab, new_tab_name):
"""adds a tab, namely creates the button and displays it and appends all the relevant arrays""" """adds a tab, namely creates the button and displays it and appends all the relevant arrays"""
#print "start of add_tab" #print "start of add_tab"
for i in self.tab_names: #todo: check this is valid for i in self.tab_names: #todo: check this is valid
if i==new_tab_name: if i==new_tab_name:
return # we depend on this to not create duplicate tabs, there's no reason to raise an error here? return # we depend on this to not create duplicate tabs, there's no reason to raise an error here?
# raise fpdb_simple.FpdbError("duplicate tab_name not permitted") # raise fpdb_simple.FpdbError("duplicate tab_name not permitted")
self.tabs.append(new_tab) self.tabs.append(new_tab)
self.tab_names.append(new_tab_name) self.tab_names.append(new_tab_name)
new_tab_sel_button=gtk.ToggleButton(new_tab_name) new_tab_sel_button=gtk.ToggleButton(new_tab_name)
new_tab_sel_button.connect("clicked", self.tab_clicked, new_tab_name) new_tab_sel_button.connect("clicked", self.tab_clicked, new_tab_name)
self.tab_box.add(new_tab_sel_button) self.tab_box.add(new_tab_sel_button)
new_tab_sel_button.show() new_tab_sel_button.show()
self.tab_buttons.append(new_tab_sel_button) self.tab_buttons.append(new_tab_sel_button)
#end def add_tab #end def add_tab
def display_tab(self, new_tab_name): def display_tab(self, new_tab_name):
"""displays the indicated tab""" """displays the indicated tab"""
#print "start of display_tab, len(self.tab_names):",len(self.tab_names) #print "start of display_tab, len(self.tab_names):",len(self.tab_names)
tab_no=-1 tab_no=-1
#if len(self.tab_names)>1: #if len(self.tab_names)>1:
for i in range(len(self.tab_names)): for i in range(len(self.tab_names)):
#print "display_tab, new_tab_name:",new_tab_name," self.tab_names[i]:", self.tab_names[i] #print "display_tab, new_tab_name:",new_tab_name," self.tab_names[i]:", self.tab_names[i]
if (new_tab_name==self.tab_names[i]): if (new_tab_name==self.tab_names[i]):
tab_no=i tab_no=i
#self.tab_buttons[i].set_active(False) #self.tab_buttons[i].set_active(False)
#else: #else:
# tab_no=0 # tab_no=0
#current_tab_no=-1 #current_tab_no=-1
for i in range(len(self.tab_names)): for i in range(len(self.tab_names)):
if self.current_tab==self.tabs[i]: if self.current_tab==self.tabs[i]:
#self.tab_buttons[i].set_active(False) #self.tab_buttons[i].set_active(False)
pass pass
if tab_no==-1: if tab_no==-1:
raise fpdb_simple.FpdbError("invalid tab_no") raise fpdb_simple.FpdbError("invalid tab_no")
else: else:
self.main_vbox.remove(self.current_tab) self.main_vbox.remove(self.current_tab)
#self.current_tab.destroy() #self.current_tab.destroy()
self.current_tab=self.tabs[tab_no] self.current_tab=self.tabs[tab_no]
self.main_vbox.add(self.current_tab) self.main_vbox.add(self.current_tab)
self.tab_buttons[tab_no].set_active(True) self.tab_buttons[tab_no].set_active(True)
self.current_tab.show() self.current_tab.show()
#end def display_tab #end def display_tab
def delete_event(self, widget, event, data=None): def delete_event(self, widget, event, data=None):
return False return False
#end def delete_event #end def delete_event
def destroy(self, widget, data=None): def destroy(self, widget, data=None):
self.quit(widget, data) self.quit(widget, data)
#end def destroy #end def destroy
def dia_about(self, widget, data): def dia_about(self, widget, data):
print "todo: implement dia_about", print "todo: implement dia_about",
print " version = %s, requires database version %s" % (VERSION, "118") print " version = %s, requires database version %s" % (VERSION, "118")
#end def dia_about #end def dia_about
def dia_create_del_database(self, widget, data): def dia_create_del_database(self, widget, data):
print "todo: implement dia_create_del_database" print "todo: implement dia_create_del_database"
self.obtain_global_lock() self.obtain_global_lock()
#end def dia_create_del_database #end def dia_create_del_database
def dia_create_del_user(self, widget, data): def dia_create_del_user(self, widget, data):
print "todo: implement dia_create_del_user" print "todo: implement dia_create_del_user"
self.obtain_global_lock() self.obtain_global_lock()
#end def dia_create_del_user #end def dia_create_del_user
def dia_database_stats(self, widget, data): def dia_database_stats(self, widget, data):
print "todo: implement dia_database_stats" print "todo: implement dia_database_stats"
#string=fpdb_db.getDbStats(db, cursor) #string=fpdb_db.getDbStats(db, cursor)
#end def dia_database_stats #end def dia_database_stats
def dia_delete_db_parts(self, widget, data): def dia_delete_db_parts(self, widget, data):
print "todo: implement dia_delete_db_parts" print "todo: implement dia_delete_db_parts"
self.obtain_global_lock() self.obtain_global_lock()
#end def dia_delete_db_parts #end def dia_delete_db_parts
def dia_edit_profile(self, widget=None, data=None, create_default=False, path=None): def dia_edit_profile(self, widget=None, data=None, create_default=False, path=None):
print "todo: implement dia_edit_profile" print "todo: implement dia_edit_profile"
self.obtain_global_lock() self.obtain_global_lock()
#end def dia_edit_profile #end def dia_edit_profile
def dia_export_db(self, widget, data): def dia_export_db(self, widget, data):
print "todo: implement dia_export_db" print "todo: implement dia_export_db"
self.obtain_global_lock() self.obtain_global_lock()
#end def dia_export_db #end def dia_export_db
def dia_get_db_root_credentials(self): def dia_get_db_root_credentials(self):
"""obtains db root credentials from user""" """obtains db root credentials from user"""
print "todo: implement dia_get_db_root_credentials" print "todo: implement dia_get_db_root_credentials"
# user, pw=None, None # user, pw=None, None
# #
# dialog=gtk.Dialog(title="DB Credentials needed", parent=None, flags=0, # dialog=gtk.Dialog(title="DB Credentials needed", parent=None, flags=0,
# buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,"Connect and recreate",gtk.RESPONSE_OK)) # buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,"Connect and recreate",gtk.RESPONSE_OK))
# #
# label_warning1=gtk.Label("Please enter credentials for a database user for "+self.host+" that has permissions to create a database.") # label_warning1=gtk.Label("Please enter credentials for a database user for "+self.host+" that has permissions to create a database.")
# #
# #
# label_user=gtk.Label("Username") # label_user=gtk.Label("Username")
# dialog.vbox.add(label_user) # dialog.vbox.add(label_user)
# label_user.show() # label_user.show()
# #
# response=dialog.run() # response=dialog.run()
# dialog.destroy() # dialog.destroy()
# return (user, pw, response) # return (user, pw, response)
#end def dia_get_db_root_credentials #end def dia_get_db_root_credentials
def dia_import_db(self, widget, data): def dia_import_db(self, widget, data):
print "todo: implement dia_import_db" print "todo: implement dia_import_db"
self.obtain_global_lock() self.obtain_global_lock()
#end def dia_import_db #end def dia_import_db
def dia_licensing(self, widget, data): def dia_licensing(self, widget, data):
print "todo: implement dia_licensing" print "todo: implement dia_licensing"
#end def dia_licensing #end def dia_licensing
def dia_load_profile(self, widget, data): def dia_load_profile(self, widget, data):
"""Dialogue to select a file to load a profile from""" """Dialogue to select a file to load a profile from"""
self.obtain_global_lock() self.obtain_global_lock()
chooser = gtk.FileChooserDialog(title="Please select a profile file to load", chooser = gtk.FileChooserDialog(title="Please select a profile file to load",
action=gtk.FILE_CHOOSER_ACTION_OPEN, action=gtk.FILE_CHOOSER_ACTION_OPEN,
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))
chooser.set_filename(self.profile) chooser.set_filename(self.profile)
response = chooser.run() response = chooser.run()
chooser.destroy() chooser.destroy()
if response == gtk.RESPONSE_OK: if response == gtk.RESPONSE_OK:
self.load_profile(chooser.get_filename()) self.load_profile(chooser.get_filename())
elif response == gtk.RESPONSE_CANCEL: elif response == gtk.RESPONSE_CANCEL:
print 'User cancelled loading profile' print 'User cancelled loading profile'
#end def dia_load_profile #end def dia_load_profile
def dia_recreate_tables(self, widget, data): def dia_recreate_tables(self, widget, data):
"""Dialogue that asks user to confirm that he wants to delete and recreate the tables""" """Dialogue that asks user to confirm that he wants to delete and recreate the tables"""
self.obtain_global_lock() self.obtain_global_lock()
dia_confirm=gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, dia_confirm=gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING,
buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm deleting and recreating tables") buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm deleting and recreating tables")
diastring=("Please confirm that you want to (re-)create the tables. If there already are tables in the database "+self.db.database+" on "+self.db.host+" they will be deleted.") diastring=("Please confirm that you want to (re-)create the tables. If there already are tables in the database "+self.db.database+" on "+self.db.host+" they will be deleted.")
dia_confirm.format_secondary_text(diastring)#todo: make above string with bold for db, host and deleted dia_confirm.format_secondary_text(diastring)#todo: make above string with bold for db, host and deleted
response=dia_confirm.run() response=dia_confirm.run()
dia_confirm.destroy() dia_confirm.destroy()
if response == gtk.RESPONSE_YES: if response == gtk.RESPONSE_YES:
self.db.recreate_tables() self.db.recreate_tables()
elif response == gtk.RESPONSE_NO: elif response == gtk.RESPONSE_NO:
print 'User cancelled recreating tables' print 'User cancelled recreating tables'
#end def dia_recreate_tables #end def dia_recreate_tables
def dia_regression_test(self, widget, data): def dia_regression_test(self, widget, data):
print "todo: implement dia_regression_test" print "todo: implement dia_regression_test"
self.obtain_global_lock() self.obtain_global_lock()
#end def dia_regression_test #end def dia_regression_test
def dia_save_profile(self, widget, data): def dia_save_profile(self, widget, data):
print "todo: implement dia_save_profile" print "todo: implement dia_save_profile"
#end def dia_save_profile #end def dia_save_profile
def diaSetupWizard(self, path): def diaSetupWizard(self, path):
print "todo: implement setup wizard" print "todo: implement setup wizard"
print "setup wizard not implemented - please create the default configuration file:", path print "setup wizard not implemented - please create the default configuration file:", path
diaSetupWizard = gtk.Dialog(title="Fatal Error - Config File Missing", parent=None, flags=0, buttons=(gtk.STOCK_QUIT,gtk.RESPONSE_OK)) diaSetupWizard = gtk.Dialog(title="Fatal Error - Config File Missing", parent=None, flags=0, buttons=(gtk.STOCK_QUIT,gtk.RESPONSE_OK))
label = gtk.Label("Please copy the config file from the docs folder to:") label = gtk.Label("Please copy the config file from the docs folder to:")
diaSetupWizard.vbox.add(label) diaSetupWizard.vbox.add(label)
label.show() label.show()
label = gtk.Label(path) label = gtk.Label(path)
diaSetupWizard.vbox.add(label) diaSetupWizard.vbox.add(label)
label.show() label.show()
label = gtk.Label("and edit it according to the install documentation at http://fpdb.sourceforge.net") label = gtk.Label("and edit it according to the install documentation at http://fpdb.sourceforge.net")
diaSetupWizard.vbox.add(label) diaSetupWizard.vbox.add(label)
label.show() label.show()
response = diaSetupWizard.run() response = diaSetupWizard.run()
sys.exit(1) sys.exit(1)
#end def diaSetupWizard #end def diaSetupWizard
def get_menu(self, window): def get_menu(self, window):
"""returns the menu for this program""" """returns the menu for this program"""
accel_group = gtk.AccelGroup() accel_group = gtk.AccelGroup()
self.item_factory = gtk.ItemFactory(gtk.MenuBar, "<main>", accel_group) self.item_factory = gtk.ItemFactory(gtk.MenuBar, "<main>", accel_group)
self.item_factory.create_items(self.menu_items) self.item_factory.create_items(self.menu_items)
window.add_accel_group(accel_group) window.add_accel_group(accel_group)
return self.item_factory.get_widget("<main>") return self.item_factory.get_widget("<main>")
#end def get_menu #end def get_menu
def load_profile(self): def load_profile(self):
"""Loads profile from the provided path name.""" """Loads profile from the provided path name."""
self.settings = {} self.settings = {}
if (os.sep=="/"): if (os.sep=="/"):
self.settings['os']="linuxmac" self.settings['os']="linuxmac"
else: else:
self.settings['os']="windows" self.settings['os']="windows"
self.settings.update(self.config.get_db_parameters()) self.settings.update(self.config.get_db_parameters())
self.settings.update(self.config.get_tv_parameters()) self.settings.update(self.config.get_tv_parameters())
self.settings.update(self.config.get_import_parameters()) self.settings.update(self.config.get_import_parameters())
self.settings.update(self.config.get_default_paths()) self.settings.update(self.config.get_default_paths())
if self.db!=None: if self.db!=None:
self.db.disconnect() self.db.disconnect()
self.db = fpdb_db.fpdb_db() self.db = fpdb_db.fpdb_db()
#print "end of fpdb.load_profile, databaseName:",self.settings['db-databaseName'] #print "end of fpdb.load_profile, databaseName:",self.settings['db-databaseName']
self.db.connect(self.settings['db-backend'], self.db.connect(self.settings['db-backend'],
self.settings['db-host'], self.settings['db-host'],
self.settings['db-databaseName'], self.settings['db-databaseName'],
self.settings['db-user'], self.settings['db-user'],
self.settings['db-password']) self.settings['db-password'])
if self.db.wrongDbVersion: if self.db.wrongDbVersion:
diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK))
label = gtk.Label("An invalid DB version or missing tables have been detected.") label = gtk.Label("An invalid DB version or missing tables have been detected.")
diaDbVersionWarning.vbox.add(label) diaDbVersionWarning.vbox.add(label)
label.show() label.show()
label = gtk.Label("This error is not necessarily fatal but it is strongly recommended that you recreate the tables by using the Database menu.") label = gtk.Label("This error is not necessarily fatal but it is strongly recommended that you recreate the tables by using the Database menu.")
diaDbVersionWarning.vbox.add(label) diaDbVersionWarning.vbox.add(label)
label.show() label.show()
label = gtk.Label("Not doing this will likely lead to misbehaviour including fpdb crashes, corrupt data etc.") label = gtk.Label("Not doing this will likely lead to misbehaviour including fpdb crashes, corrupt data etc.")
diaDbVersionWarning.vbox.add(label) diaDbVersionWarning.vbox.add(label)
label.show() label.show()
response = diaDbVersionWarning.run() response = diaDbVersionWarning.run()
diaDbVersionWarning.destroy() diaDbVersionWarning.destroy()
# Database connected to successfully, load queries to pass on to other classes # Database connected to successfully, load queries to pass on to other classes
self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name())
#end def load_profile #end def load_profile
def not_implemented(self): def not_implemented(self):
print "todo: called unimplemented menu entry (users: pls ignore this)"#remove this once more entries are implemented print "todo: called unimplemented menu entry (users: pls ignore this)"#remove this once more entries are implemented
#end def not_implemented #end def not_implemented
def obtain_global_lock(self): def obtain_global_lock(self):
print "todo: implement obtain_global_lock (users: pls ignore this)" print "todo: implement obtain_global_lock (users: pls ignore this)"
#end def obtain_global_lock #end def obtain_global_lock
def quit(self, widget, data): def quit(self, widget, data):
print "Quitting normally" print "Quitting normally"
#check if current settings differ from profile, if so offer to save or abort #check if current settings differ from profile, if so offer to save or abort
self.db.disconnect() self.db.disconnect()
gtk.main_quit() gtk.main_quit()
#end def quit_cliecked #end def quit_cliecked
def release_global_lock(self): def release_global_lock(self):
print "todo: implement release_global_lock" print "todo: implement release_global_lock"
#end def release_global_lock #end def release_global_lock
def tab_abbreviations(self, widget, data): def tab_abbreviations(self, widget, data):
print "todo: implement tab_abbreviations" print "todo: implement tab_abbreviations"
#end def tab_abbreviations #end def tab_abbreviations
def tab_auto_import(self, widget, data): def tab_auto_import(self, widget, data):
"""opens the auto import tab""" """opens the auto import tab"""
new_aimp_thread=GuiAutoImport.GuiAutoImport(self.settings, self.config) new_aimp_thread=GuiAutoImport.GuiAutoImport(self.settings, self.config)
self.threads.append(new_aimp_thread) self.threads.append(new_aimp_thread)
aimp_tab=new_aimp_thread.get_vbox() aimp_tab=new_aimp_thread.get_vbox()
self.add_and_display_tab(aimp_tab, "Auto Import") self.add_and_display_tab(aimp_tab, "Auto Import")
#end def tab_auto_import #end def tab_auto_import
def tab_bulk_import(self, widget, data): def tab_bulk_import(self, widget, data):
"""opens a tab for bulk importing""" """opens a tab for bulk importing"""
#print "start of tab_bulk_import" #print "start of tab_bulk_import"
new_import_thread=GuiBulkImport.GuiBulkImport(self.db, self.settings, self.config) new_import_thread=GuiBulkImport.GuiBulkImport(self.db, self.settings, self.config)
self.threads.append(new_import_thread) self.threads.append(new_import_thread)
bulk_tab=new_import_thread.get_vbox() bulk_tab=new_import_thread.get_vbox()
self.add_and_display_tab(bulk_tab, "Bulk Import") self.add_and_display_tab(bulk_tab, "Bulk Import")
#end def tab_bulk_import #end def tab_bulk_import
def tab_player_stats(self, widget, data): def tab_player_stats(self, widget, data):
new_ps_thread=GuiPlayerStats.GuiPlayerStats(self.db, self.config, self.querydict) new_ps_thread=GuiPlayerStats.GuiPlayerStats(self.db, self.config, self.querydict)
self.threads.append(new_ps_thread) self.threads.append(new_ps_thread)
ps_tab=new_ps_thread.get_vbox() ps_tab=new_ps_thread.get_vbox()
self.add_and_display_tab(ps_tab, "Player Stats") self.add_and_display_tab(ps_tab, "Player Stats")
def tab_positional_stats(self, widget, data):
new_ps_thread=GuiPositionalStats.GuiPositionalStats(self.db, self.config, self.querydict)
self.threads.append(new_ps_thread)
ps_tab=new_ps_thread.get_vbox()
self.add_and_display_tab(ps_tab, "Ppositional Stats")
def tab_main_help(self, widget, data): def tab_main_help(self, widget, data):
"""Displays a tab with the main fpdb help screen""" """Displays a tab with the main fpdb help screen"""
#print "start of tab_main_help" #print "start of tab_main_help"
mh_tab=gtk.Label("""Welcome to Fpdb! mh_tab=gtk.Label("""Welcome to Fpdb!
For documentation please visit our website at http://fpdb.sourceforge.net/ or check the docs directory in the fpdb folder. For documentation please visit our website at http://fpdb.sourceforge.net/ or check the docs directory in the fpdb folder.
Please note that default.conf is no longer needed nor used, all configuration now happens in HUD_config.xml Please note that default.conf is no longer needed nor used, all configuration now happens in HUD_config.xml
This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
self.add_and_display_tab(mh_tab, "Help") self.add_and_display_tab(mh_tab, "Help")
#end def tab_main_help #end def tab_main_help
def tab_table_viewer(self, widget, data): def tab_table_viewer(self, widget, data):
"""opens a table viewer tab""" """opens a table viewer tab"""
#print "start of tab_table_viewer" #print "start of tab_table_viewer"
new_tv_thread=GuiTableViewer.GuiTableViewer(self.db, self.settings) new_tv_thread=GuiTableViewer.GuiTableViewer(self.db, self.settings)
self.threads.append(new_tv_thread) self.threads.append(new_tv_thread)
tv_tab=new_tv_thread.get_vbox() tv_tab=new_tv_thread.get_vbox()
self.add_and_display_tab(tv_tab, "Table Viewer") self.add_and_display_tab(tv_tab, "Table Viewer")
#end def tab_table_viewer #end def tab_table_viewer
def tabGraphViewer(self, widget, data): def tabGraphViewer(self, widget, data):
"""opens a graph viewer tab""" """opens a graph viewer tab"""
#print "start of tabGraphViewer" #print "start of tabGraphViewer"
new_gv_thread=GuiGraphViewer.GuiGraphViewer(self.db, self.settings, self.querydict, self.config) new_gv_thread=GuiGraphViewer.GuiGraphViewer(self.db, self.settings, self.querydict, self.config)
self.threads.append(new_gv_thread) self.threads.append(new_gv_thread)
gv_tab=new_gv_thread.get_vbox() gv_tab=new_gv_thread.get_vbox()
self.add_and_display_tab(gv_tab, "Graphs") self.add_and_display_tab(gv_tab, "Graphs")
#end def tabGraphViewer #end def tabGraphViewer
def __init__(self): def __init__(self):
self.threads=[] self.threads=[]
self.db=None self.db=None
self.config = Configuration.Config() self.config = Configuration.Config()
self.load_profile() self.load_profile()
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 - v%s or higher" % (VERSION, )) self.window.set_title("Free Poker DB - v%s or higher" % (VERSION, ))
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)
self.menu_items = ( self.menu_items = (
( "/_Main", None, None, 0, "<Branch>" ), ( "/_Main", None, None, 0, "<Branch>" ),
( "/Main/_Load Profile (broken)", "<control>L", self.dia_load_profile, 0, None ), ( "/Main/_Load Profile (broken)", "<control>L", self.dia_load_profile, 0, None ),
( "/Main/_Edit Profile (todo)", "<control>E", self.dia_edit_profile, 0, None ), ( "/Main/_Edit Profile (todo)", "<control>E", self.dia_edit_profile, 0, None ),
( "/Main/_Save Profile (todo)", None, self.dia_save_profile, 0, None ), ( "/Main/_Save Profile (todo)", None, self.dia_save_profile, 0, None ),
("/Main/sep1", None, None, 0, "<Separator>" ), ("/Main/sep1", None, None, 0, "<Separator>" ),
("/Main/_Quit", "<control>Q", self.quit, 0, None ), ("/Main/_Quit", "<control>Q", self.quit, 0, None ),
("/_Import", None, None, 0, "<Branch>" ), ("/_Import", None, None, 0, "<Branch>" ),
("/Import/_Bulk Import", "<control>B", self.tab_bulk_import, 0, None ), ("/Import/_Bulk Import", "<control>B", self.tab_bulk_import, 0, None ),
("/Import/_Auto Import and HUD", "<control>A", self.tab_auto_import, 0, None ), ("/Import/_Auto Import and HUD", "<control>A", self.tab_auto_import, 0, None ),
("/Import/Auto _Rating (todo)", "<control>R", self.not_implemented, 0, None ), ("/Import/Auto _Rating (todo)", "<control>R", self.not_implemented, 0, None ),
("/_Viewers", None, None, 0, "<Branch>" ), ("/_Viewers", None, None, 0, "<Branch>" ),
("/_Viewers/_Auto Import and HUD", "<control>A", self.tab_auto_import, 0, None ), ("/_Viewers/_Auto Import and HUD", "<control>A", self.tab_auto_import, 0, None ),
("/Viewers/_Graphs", "<control>G", self.tabGraphViewer, 0, None ), ("/Viewers/_Graphs", "<control>G", self.tabGraphViewer, 0, None ),
("/Viewers/Hand _Replayer (todo)", None, self.not_implemented, 0, None ), ("/Viewers/Hand _Replayer (todo)", None, self.not_implemented, 0, None ),
("/Viewers/Player _Details (todo)", None, self.not_implemented, 0, None ), ("/Viewers/Player _Details (todo)", None, self.not_implemented, 0, None ),
("/Viewers/_Player Stats (tabulated view)", None, self.tab_player_stats, 0, None ), ("/Viewers/_Player Stats (tabulated view)", None, self.tab_player_stats, 0, None ),
("/Viewers/Starting _Hands (todo)", None, self.not_implemented, 0, None ), ("/Viewers/Positional Stats (tabulated view)", None, self.tab_positional_stats, 0, None ),
("/Viewers/_Session Replayer (todo)", None, self.not_implemented, 0, None ), ("/Viewers/Starting _Hands (todo)", None, self.not_implemented, 0, None ),
("/Viewers/Poker_table Viewer (mostly obselete)", "<control>T", self.tab_table_viewer, 0, None ), ("/Viewers/_Session Replayer (todo)", None, self.not_implemented, 0, None ),
#( "/Viewers/Tourney Replayer ("/Viewers/Poker_table Viewer (mostly obselete)", "<control>T", self.tab_table_viewer, 0, None ),
( "/_Database", None, None, 0, "<Branch>" ), #( "/Viewers/Tourney Replayer
( "/Database/Create or Delete _Database (todo)", None, self.dia_create_del_database, 0, None ), ( "/_Database", None, None, 0, "<Branch>" ),
( "/Database/Create or Delete _User (todo)", None, self.dia_create_del_user, 0, None ), ( "/Database/Create or Delete _Database (todo)", None, self.dia_create_del_database, 0, None ),
( "/Database/Create or Recreate _Tables", None, self.dia_recreate_tables, 0, None ), ( "/Database/Create or Delete _User (todo)", None, self.dia_create_del_user, 0, None ),
( "/Database/_Statistics (todo)", None, self.dia_database_stats, 0, None ), ( "/Database/Create or Recreate _Tables", None, self.dia_recreate_tables, 0, None ),
( "/D_ebugging", None, None, 0, "<Branch>" ), ( "/Database/_Statistics (todo)", None, self.dia_database_stats, 0, None ),
( "/Debugging/_Delete Parts of Database (todo)", None, self.dia_delete_db_parts, 0, None ), ( "/D_ebugging", None, None, 0, "<Branch>" ),
( "/Debugging/_Export DB (todo)", None, self.dia_export_db, 0, None ), ( "/Debugging/_Delete Parts of Database (todo)", None, self.dia_delete_db_parts, 0, None ),
( "/Debugging/_Import DB (todo)", None, self.dia_import_db, 0, None ), ( "/Debugging/_Export DB (todo)", None, self.dia_export_db, 0, None ),
( "/Debugging/_Regression test (todo)", None, self.dia_regression_test, 0, None ), ( "/Debugging/_Import DB (todo)", None, self.dia_import_db, 0, None ),
( "/_Help", None, None, 0, "<LastBranch>" ), ( "/Debugging/_Regression test (todo)", None, self.dia_regression_test, 0, None ),
( "/Help/_Main Help", "<control>H", self.tab_main_help, 0, None ), ( "/_Help", None, None, 0, "<LastBranch>" ),
( "/Help/_Abbrevations (todo)", None, self.tab_abbreviations, 0, None ), ( "/Help/_Main Help", "<control>H", self.tab_main_help, 0, None ),
( "/Help/sep1", None, None, 0, "<Separator>" ), ( "/Help/_Abbrevations (todo)", None, self.tab_abbreviations, 0, None ),
( "/Help/A_bout (todo)", None, self.dia_about, 0, None ), ( "/Help/sep1", None, None, 0, "<Separator>" ),
( "/Help/_License and Copying (todo)", None, self.dia_licensing, 0, None ) ( "/Help/A_bout (todo)", None, self.dia_about, 0, None ),
) ( "/Help/_License and Copying (todo)", None, self.dia_licensing, 0, None )
)
self.main_vbox = gtk.VBox(False, 1) self.main_vbox = gtk.VBox(False, 1)
self.main_vbox.set_border_width(1) self.main_vbox.set_border_width(1)
self.window.add(self.main_vbox) self.window.add(self.main_vbox)
self.main_vbox.show() self.main_vbox.show()
menubar = self.get_menu(self.window) menubar = self.get_menu(self.window)
self.main_vbox.pack_start(menubar, False, True, 0) self.main_vbox.pack_start(menubar, False, True, 0)
menubar.show() menubar.show()
#done menubar #done menubar
self.tabs=[] self.tabs=[]
self.tab_names=[] self.tab_names=[]
self.tab_buttons=[] self.tab_buttons=[]
self.tab_box = gtk.HBox(False,1) self.tab_box = gtk.HBox(False,1)
self.main_vbox.pack_start(self.tab_box, False, True, 0) self.main_vbox.pack_start(self.tab_box, False, True, 0)
self.tab_box.show() self.tab_box.show()
#done tab bar #done tab bar
self.current_tab = gtk.VBox(False,1) self.current_tab = gtk.VBox(False,1)
self.current_tab.set_border_width(1) self.current_tab.set_border_width(1)
self.main_vbox.add(self.current_tab) self.main_vbox.add(self.current_tab)
self.current_tab.show() self.current_tab.show()
self.tab_main_help(None, None) self.tab_main_help(None, None)
self.status_bar = gtk.Label("Status: Connected to "+self.db.get_backend_name()+" database named "+self.db.database+" on host "+self.db.host) self.status_bar = gtk.Label("Status: Connected to "+self.db.get_backend_name()+" database named "+self.db.database+" on host "+self.db.host)
self.main_vbox.pack_end(self.status_bar, False, True, 0) self.main_vbox.pack_end(self.status_bar, False, True, 0)
self.status_bar.show() self.status_bar.show()
self.window.show() self.window.show()
#end def __init__ #end def __init__
def main(self): def main(self):
gtk.main() gtk.main()
return 0 return 0
#end def main #end def main
if __name__ == "__main__": if __name__ == "__main__":
me = fpdb() me = fpdb()
me.main() me.main()

View File

@ -208,8 +208,7 @@ class Importer:
#if os.path.isdir(file): #if os.path.isdir(file):
#self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1]) #self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1])
for dir in self.addToDirList: self.addToDirList = filter(lambda x: self.addImportDirectory(x, True, self.addToDirList[x][0], self.addToDirList[x][1]), self.addToDirList)
self.addImportDirectory(dir, True, self.addToDirList[dir][0], self.addToDirList[dir][1])
for file in self.removeFromFileList: for file in self.removeFromFileList:
if file in self.filelist: if file in self.filelist:
@ -309,7 +308,7 @@ class Importer:
partial=0 #counter partial=0 #counter
errors=0 #counter errors=0 #counter
for i in range (len(self.lines)): #main loop, iterates through the lines of a file and calls the appropriate parser method for i in xrange (len(self.lines)): #main loop, iterates through the lines of a file and calls the appropriate parser method
if (len(self.lines[i])<2): if (len(self.lines[i])<2):
endpos=i endpos=i
hand=self.lines[startpos:endpos] hand=self.lines[startpos:endpos]

View File

@ -22,6 +22,7 @@ import fpdb_save_to_db
#parses a holdem hand #parses a holdem hand
def mainParser(backend, db, cursor, site, category, hand): def mainParser(backend, db, cursor, site, category, hand):
category=fpdb_simple.recogniseCategory(hand[0])
if (category=="holdem" or category=="omahahi" or category=="omahahilo"): if (category=="holdem" or category=="omahahi" or category=="omahahilo"):
base="hold" base="hold"
else: else:

View File

@ -399,59 +399,59 @@ def checkPositions(positions):
def classifyLines(hand, category, lineTypes, lineStreets): def classifyLines(hand, category, lineTypes, lineStreets):
currentStreet="predeal" currentStreet="predeal"
done=False #set this to true once we reach the last relevant line (the summary, except rake, is all repeats) done=False #set this to true once we reach the last relevant line (the summary, except rake, is all repeats)
for i in range (len(hand)): for i, line in enumerate(hand):
if (done): if done:
if (hand[i].find("[")==-1 or hand[i].find("mucked [")==-1): if "[" not in line or "mucked [" not in line:
lineTypes.append("ignore") lineTypes.append("ignore")
else: #it's storing a mucked card else:
lineTypes.append("cards") lineTypes.append("cards")
elif (hand[i].startswith("Dealt to")): elif line.startswith("Dealt to"):
lineTypes.append("cards") lineTypes.append("cards")
elif (i==0): elif i == 0:
lineTypes.append("header") lineTypes.append("header")
elif (hand[i].startswith("Seat ") and ((hand[i].find("in chips")!=-1) or (hand[i].find("($")!=-1))): elif line.startswith("Seat ") and ( ("in chips" in line) or "($" in line):
lineTypes.append("name") lineTypes.append("name")
elif (isActionLine(hand[i])): elif isActionLine(line):
lineTypes.append("action") lineTypes.append("action")
if (hand[i].find(" posts ")!=-1 or hand[i].find(" posts the ")!=-1):#need to set this here so the "action" of posting blinds is registered properly if " posts " in line or " posts the " in line:
currentStreet="preflop" currentStreet="preflop"
elif (isWinLine(hand[i])): elif isWinLine(line):
lineTypes.append("win") lineTypes.append("win")
elif (hand[i].startswith("Total pot ") and hand[i].find("Rake")!=-1): elif line.startswith("Total pot ") and "Rake" in line:
lineTypes.append("rake") lineTypes.append("rake")
done=True done=True
elif (hand[i]=="*** SHOW DOWN ***" or hand[i]=="*** SUMMARY ***"): elif "*** SHOW DOWN ***" in line or "*** SUMMARY ***" in line:
lineTypes.append("ignore") lineTypes.append("ignore")
#print "in classifyLine, showdown or summary" #print "in classifyLine, showdown or summary"
elif (hand[i].find(" antes ")!=-1 or hand[i].find(" posts the ante ")!=-1): elif " antes " in line or " posts the ante " in line:
lineTypes.append("ante") lineTypes.append("ante")
elif (hand[i].startswith("*** FLOP *** [")): elif line.startswith("*** FLOP *** ["):
lineTypes.append("cards") lineTypes.append("cards")
currentStreet="flop" currentStreet="flop"
elif (hand[i].startswith("*** TURN *** [")): elif line.startswith("*** TURN *** ["):
lineTypes.append("cards") lineTypes.append("cards")
currentStreet="turn" currentStreet="turn"
elif (hand[i].startswith("*** RIVER *** [")): elif line.startswith("*** RIVER *** ["):
lineTypes.append("cards") lineTypes.append("cards")
currentStreet="river" currentStreet="river"
elif (hand[i].startswith("*** 3")): elif line.startswith("*** 3"):
lineTypes.append("ignore") lineTypes.append("ignore")
currentStreet=0 currentStreet=0
elif (hand[i].startswith("*** 4")): elif line.startswith("*** 4"):
lineTypes.append("ignore") lineTypes.append("ignore")
currentStreet=1 currentStreet=1
elif (hand[i].startswith("*** 5")): elif line.startswith("*** 5"):
lineTypes.append("ignore") lineTypes.append("ignore")
currentStreet=2 currentStreet=2
elif (hand[i].startswith("*** 6")): elif line.startswith("*** 6"):
lineTypes.append("ignore") lineTypes.append("ignore")
currentStreet=3 currentStreet=3
elif (hand[i].startswith("*** 7") or hand[i]=="*** RIVER ***"): elif line.startswith("*** 7") or line == "*** RIVER ***":
lineTypes.append("ignore") lineTypes.append("ignore")
currentStreet=4 currentStreet=4
elif (hand[i].find(" shows [")!=-1): elif " shows [" in line:
lineTypes.append("cards") lineTypes.append("cards")
elif (hand[i].startswith("Table '")): elif line.startswith("Table '"):
lineTypes.append("table") lineTypes.append("table")
else: else:
raise FpdbError("unrecognised linetype in:"+hand[i]) raise FpdbError("unrecognised linetype in:"+hand[i])