Merge branch 'master' of git://git.assembla.com/fpdboz.git

This commit is contained in:
Gerko de Roo 2010-08-01 13:29:08 +02:00
commit 0c3c8a3805
22 changed files with 510 additions and 949 deletions

View File

@ -1,3 +1,34 @@
free-poker-tools (0.20.902-1) unstable; urgency=low
* New snapshot release; .901 was broken for FTP
-- Mika Bostrom <bostik@iki.fi> Sat, 24 Jul 2010 09:05:57 +0300
free-poker-tools (0.20.901-1) unstable; urgency=low
* Snapshot release before oncoming 0.21
-- Mika Bostrom <bostik@iki.fi> Thu, 22 Jul 2010 23:32:47 +0300
free-poker-tools (0.20.1-1) unstable; urgency=low
* 0.20.1 release
-- Mika Bostrom <bostik@iki.fi> Thu, 22 Jul 2010 08:47:39 +0300
free-poker-tools (0.20-2) unstable; urgency=low
* Fix executable script shebangs: there is no /usr/bin/python2 (nor
/usr/bin/python3) symlink on Debian or Ubuntu
-- Mika Bostrom <bostik+fpdb@bostik.iki.fi> Thu, 08 Jul 2010 21:29:40 +0300
free-poker-tools (0.20-1) unstable; urgency=low
* 0.20 release
-- Mika Bostrom <bostik+fpdb@bostik.iki.fi> Thu, 08 Jul 2010 11:25:36 +0300
free-poker-tools (0.20~git20100630) unstable; urgency=low
* Snapshot release

View File

@ -10,7 +10,7 @@ NEED_PYTHON=2.5
DESCRIPTION="A free/open source tracker/HUD for use with online poker"
HOMEPAGE="http://fpdb.wiki.sourceforge.net/"
SRC_URI="mirror://sourceforge/${PN}/${PV}/${P}.tar.gz"
SRC_URI="mirror://sourceforge/${PN}/${PV}/${P}.tar.bz2"
LICENSE="AGPL-3"
SLOT="0"
@ -29,7 +29,8 @@ RDEPEND="
dev-python/pygtk
graph? ( dev-python/numpy
dev-python/matplotlib[gtk] )
dev-python/python-xlib"
dev-python/python-xlib
dev-python/pytz"
DEPEND="${RDEPEND}"
src_install() {
@ -53,9 +54,7 @@ src_install() {
pkg_postinst() {
games_pkg_postinst
echo
elog "Note that if you really want to use mysql or postgresql you will have to create"
elog "the database and user yourself and enter it into the fpdb config."
elog "You can find the instructions on the project's website."
echo
}

View File

@ -1,57 +0,0 @@
# Copyright 1999-2010 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# created by Steffen Schaumburg, steffen@schaumburger.info
EAPI="2"
NEED_PYTHON=2.5
#inherit distutils
DESCRIPTION="A database program to track your online poker games"
HOMEPAGE="http://fpdb.sourceforge.net/"
#SRC_URI="mirror://sourceforge/fpdb/${MY_P}.tar.bz2"
LICENSE="AGPL-3"
SLOT="0"
KEYWORDS="~amd64 ~x86"
#note: this should work on other architectures too, please send me your experiences
IUSE="graphing mysql postgres sqlite"
RDEPEND="
mysql? ( virtual/mysql
dev-python/mysql-python )
postgres? ( dev-db/postgresql-server
dev-python/psycopg )
sqlite? ( dev-lang/python[sqlite]
dev-python/numpy )
>=x11-libs/gtk+-2.10
dev-python/pygtk
graphing? ( dev-python/numpy
dev-python/matplotlib[gtk] )
dev-python/python-xlib"
DEPEND="${RDEPEND}"
#src_install() {
# DIRINST="${D}usr/share/games/fpdb/"
# mkdir -p "${DIRINST}"
# cp -R * "${DIRINST}" || die
#
# DIRBIN="${D}usr/games/bin/"
# mkdir -p "${DIRBIN}"
# #echo "pathes"
# #echo "${DIRINST}pyfpdb/fpdb.py"
# #echo "${DIRBIN}fpdb.py"
# #echo
# echo "cd /usr/share/games/fpdb/pyfpdb/ && python fpdb.py" > "${DIRBIN}fpdb" || die
# chmod 755 "${DIRBIN}fpdb" || die
#}
#src_test() {
#}
pkg_postinst() {
elog "Fpdb's dependencies have been installed. Please visit fpdb.sourceforge.net"
elog "and download and unpack the archive.You can then start fpdb by running run_fpdb.py."
elog "Note that if you really want to use mysql or postgresql you will have to create"
elog "the database and user yourself and enter it into the fpdb config."
}

View File

@ -1,59 +0,0 @@
# Copyright 1999-2010 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# created by Steffen Schaumburg, steffen@schaumburger.info
EAPI="2"
NEED_PYTHON=2.5
DESCRIPTION="Fpdb is a free/open source tracker/HUD for use with online poker"
HOMEPAGE="http://fpdb.wiki.sourceforge.net/"
SRC_URI="mirror://sourceforge/${PN}/${PV}/${P}.tar.gz"
LICENSE="AGPL-3"
SLOT="0"
KEYWORDS="~amd64 ~x86"
#note: this should work on other architectures too, please send me your experiences
IUSE="graphing mysql postgres sqlite"
RDEPEND="
mysql? ( virtual/mysql
dev-python/mysql-python )
postgres? ( dev-db/postgresql-server
dev-python/psycopg )
sqlite? ( dev-lang/python[sqlite]
dev-python/numpy )
>=x11-libs/gtk+-2.10
dev-python/pygtk
graphing? ( dev-python/numpy
dev-python/matplotlib[gtk] )
dev-python/python-xlib"
DEPEND="${RDEPEND}"
src_install() {
dodir /usr/share/games/fpdb
exeinto /usr/share/games/fpdb
doexe run_fpdb.py
dosym /usr/share/games/fpdb/run_fpdb.py /usr/bin/fpdb
insinto /usr/share/games/fpdb
doins readme.txt
insinto /usr/share/games/fpdb/files
doins files/*
insinto /usr/share/games/fpdb/gfx
doins gfx/*
insinto /usr/share/games/fpdb/pyfpdb
doins pyfpdb/*
# pyfpdb/regression-test-files dir is missing for now; cp -r ??
}
pkg_postinst() {
elog "Note that if you really want to use mysql or postgresql you will have to create"
elog "the database and user yourself and enter it into the fpdb config."
elog "You can find the instructions on the project's website."
}

View File

@ -0,0 +1,2 @@
To use the ebuild please simply copy it into your local portage tree and rename it to fpdb-version.ebuild, for example fpdb-0.20.1.ebuild or fpdb-0.20.902.ebuild.
Here's a little howto on how to utilise 3rd party ebuilds such as this one: http://www.gentoo-wiki.info/HOWTO_Installing_3rd_Party_Ebuilds

View File

@ -42,10 +42,10 @@ class Absolute(HandHistoryConverter):
#Seat 6 - FETS63 ($0.75 in chips)
#Board [10s 5d Kh Qh 8c]
re_GameInfo = re.compile(ur"^Stage #([0-9]+): (?P<GAME>Holdem|HORSE)(?: \(1 on 1\)|)? ?(?P<LIMIT>No Limit|Pot Limit|Normal|)? ?(?P<CURRENCY>\$| €|)(?P<SB>[.0-9]+)/?(?:\$| €|)(?P<BB>[.0-9]+)?", re.MULTILINE)
re_GameInfo = re.compile(ur"^Stage #(C?[0-9]+): (?P<GAME>Holdem|HORSE)(?: \(1 on 1\)|)? ?(?P<LIMIT>No Limit|Pot Limit|Normal|)? ?(?P<CURRENCY>\$| €|)(?P<SB>[.0-9]+)/?(?:\$| €|)(?P<BB>[.0-9]+)?", re.MULTILINE)
re_HorseGameInfo = re.compile(ur"^Game Type: (?P<LIMIT>Limit) (?P<GAME>Holdem)", re.MULTILINE)
# TODO: can set max seats via (1 on 1) to a known 2 ..
re_HandInfo = re.compile(ur"^Stage #(?P<HID>[0-9]+): .*(?P<DATETIME>\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d).*\n(Table: (?P<TABLE>.*) \(Real Money\))?", re.MULTILINE)
re_HandInfo = re.compile(ur"^Stage #C?(?P<HID>[0-9]+): .*(?P<DATETIME>\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d).*\n(Table: (?P<TABLE>.*) \(Real Money\))?", re.MULTILINE)
re_TableFromFilename = re.compile(ur".*IHH([0-9]+) (?P<TABLE>.*) -") # on HORSE STUD games, the table name isn't in the hand info!
re_Button = re.compile(ur"Seat #(?P<BUTTON>[0-9]) is the ?[dead]* dealer$", re.MULTILINE) # TODO: that's not the right way to match for "dead" dealer is it?
re_PlayerInfo = re.compile(ur"^Seat (?P<SEAT>[0-9]) - (?P<PNAME>.*) \((?:\$| €|)(?P<CASH>[0-9]*[.0-9]+) in chips\)", re.MULTILINE)
@ -106,6 +106,7 @@ class Absolute(HandHistoryConverter):
'smallBet'
'bigBet'
'currency' in ('USD', 'EUR', 'T$', <countrycode>)
or None if we fail to get the info """
info = {'type':'ring'}
@ -329,6 +330,9 @@ def validCard(card):
return card
if __name__ == "__main__":
import Configuration
config = Configuration.Config(None)
parser = OptionParser()
parser.add_option("-i", "--input", dest="ipath", help="parse input hand history", default="-")
parser.add_option("-o", "--output", dest="opath", help="output translation to", default="-")
@ -345,5 +349,5 @@ if __name__ == "__main__":
LOG_FILENAME = './logging.out'
logging.basicConfig(filename=LOG_FILENAME,level=options.verbosity)
e = Absolute(in_path = options.ipath, out_path = options.opath, follow = options.follow, autostart=True, debugging=True)
e = Absolute(config, in_path = options.ipath, out_path = options.opath, follow = options.follow, autostart=True)

View File

@ -52,8 +52,13 @@ def get_default_config_path():
if os.name == 'posix':
config_path = os.path.join(os.path.expanduser("~"), '.fpdb')
elif os.name == 'nt':
config_path = os.path.join(os.environ["APPDATA"], 'fpdb')
config_path = os.path.join(unicode(os.environ[u"APPDATA"], "latin-1"), u"fpdb")
#print u"path after joining in get_default_config_path:",config_path
else: config_path = False
try: os.mkdir(config_path)
except: pass
return config_path
def get_exec_path():
@ -110,7 +115,7 @@ def get_logger(file_name, config = "config", fallback = False, log_dir=None, log
(conf_file,copied) = get_config(file_name, fallback = fallback)
if log_dir is None:
log_dir = os.path.join(get_exec_path(), 'log')
log_dir = os.path.join(get_exec_path(), u'log')
#print "\nget_logger: checking log_dir:", log_dir
check_dir(log_dir)
if log_file is None:
@ -147,7 +152,7 @@ def check_dir(path, create = True):
msg = "Creating directory: '%s'" % (path)
print msg
log.info(msg)
os.mkdir(path)
os.mkdir(path)#, "utf-8"))
else:
return False
@ -520,9 +525,9 @@ class Config:
self.dir_self = get_exec_path()
# self.dir_config = os.path.dirname(self.file)
self.dir_config = get_default_config_path()
self.dir_log = os.path.join(self.dir_config, 'log')
self.dir_database = os.path.join(self.dir_config, 'database')
self.log_file = os.path.join(self.dir_log, 'fpdb-log.txt')
self.dir_log = os.path.join(self.dir_config, u'log')
self.dir_database = os.path.join(self.dir_config, u'database')
self.log_file = os.path.join(self.dir_log, u'fpdb-log.txt')
log = get_logger("logging.conf", "config", log_dir=self.dir_log)
# Parse even if there was no real config file found and we are using the example

View File

@ -74,7 +74,7 @@ except ImportError:
use_numpy = False
DB_VERSION = 137
DB_VERSION = 139
# Variance created as sqlite has a bunch of undefined aggregate functions.
@ -1651,8 +1651,8 @@ class Database:
pdata[p]['foldToOtherRaisedStreet2'],
pdata[p]['foldToOtherRaisedStreet3'],
pdata[p]['foldToOtherRaisedStreet4'],
pdata[p]['stealAttemptChance'],
pdata[p]['stealAttempted'],
pdata[p]['raiseFirstInChance'],
pdata[p]['raisedFirstIn'],
pdata[p]['foldBbToStealChance'],
pdata[p]['foldedBbToSteal'],
pdata[p]['foldSbToStealChance'],
@ -1732,8 +1732,8 @@ class Database:
if pdata[p]['foldToOtherRaisedStreet4']: line[21] = 1
line[22] = pdata[p]['wonWhenSeenStreet1']
line[23] = pdata[p]['wonAtSD']
if pdata[p]['stealAttemptChance']: line[24] = 1
if pdata[p]['stealAttempted']: line[25] = 1
if pdata[p]['raiseFirstInChance']: line[24] = 1
if pdata[p]['raisedFirstIn']: line[25] = 1
if pdata[p]['foldBbToStealChance']: line[26] = 1
if pdata[p]['foldedBbToSteal']: line[27] = 1
if pdata[p]['foldSbToStealChance']: line[28] = 1

View File

@ -53,12 +53,13 @@ class DerivedStats():
self.handsplayers[player[1]]['street0_3BDone'] = False
self.handsplayers[player[1]]['street0_4BChance'] = False
self.handsplayers[player[1]]['street0_4BDone'] = False
self.handsplayers[player[1]]['stealAttemptChance'] = False
self.handsplayers[player[1]]['stealAttempted'] = False
self.handsplayers[player[1]]['raiseFirstInChance'] = False
self.handsplayers[player[1]]['raisedFirstIn'] = False
self.handsplayers[player[1]]['foldBbToStealChance'] = False
self.handsplayers[player[1]]['foldSbToStealChance'] = False
self.handsplayers[player[1]]['foldedSbToSteal'] = False
self.handsplayers[player[1]]['foldedBbToSteal'] = False
self.handsplayers[player[1]]['tourneyTypeId'] = None
for i in range(5):
self.handsplayers[player[1]]['street%dCalls' % i] = 0
@ -142,6 +143,7 @@ class DerivedStats():
self.handsplayers[player[1]]['startCash'] = int(100 * Decimal(player[2]))
self.handsplayers[player[1]]['sitout'] = False #TODO: implement actual sitout detection
if hand.gametype["type"]=="tour":
self.handsplayers[player[1]]['tourneyTypeId']=hand.tourneyTypeId
self.handsplayers[player[1]]['tourneysPlayersIds'] = hand.tourneysPlayersIds[player[1]]
else:
self.handsplayers[player[1]]['tourneysPlayersIds'] = None
@ -288,7 +290,9 @@ class DerivedStats():
# print "p_actions:", self.pfba(actions), "p_folds:", self.pfba(actions, l=('folds',)), "alliners:", alliners
# pas = set.union(self.pfba(actions) - self.pfba(actions, l=('folds',)), alliners)
p_in = set(x[1] for x in hand.players)
# hand.players includes people that are sitting out on some sites.
# Those that posted an ante should have been deal cards.
p_in = set([x[0] for x in hand.actions['BLINDSANTES']])
for (i, street) in enumerate(hand.actionStreets):
actions = hand.actions[street]
p_in = p_in - self.pfba(actions, l=('folds',))
@ -313,13 +317,14 @@ class DerivedStats():
self.hands['street%dRaises' % i] = len(filter( lambda action: action[1] in ('raises','bets'), hand.actions[street]))
def calcSteals(self, hand):
"""Fills stealAttempt(Chance|ed, fold(Bb|Sb)ToSteal(Chance|)
"""Fills raiseFirstInChance|raisedFirstIn, fold(Bb|Sb)ToSteal(Chance|)
Steal attempt - open raise on positions 1 0 S - i.e. MP3, CO, BU, SB
Steal attempt - open raise on positions 1 0 S - i.e. CO, BU, SB
(note: I don't think PT2 counts SB steals in HU hands, maybe we shouldn't?)
Fold to steal - folding blind after steal attemp wo any other callers or raisers
"""
steal_attempt = False
raised = False
steal_positions = (1, 0, 'S')
if hand.gametype['base'] == 'stud':
steal_positions = (2, 1, 0)
@ -339,10 +344,12 @@ class DerivedStats():
if steal_attempt and act != 'folds':
break
if posn in steal_positions and not steal_attempt:
self.handsplayers[pname]['stealAttemptChance'] = True
if not steal_attempt and not raised: # if posn in steal_positions and not steal_attempt:
self.handsplayers[pname]['raiseFirstInChance'] = True
if act in ('bets', 'raises'):
self.handsplayers[pname]['stealAttempted'] = True
self.handsplayers[pname]['raisedFirstIn'] = True
raised = True
if posn in steal_positions:
steal_attempt = True
if act == 'calls':
break

View File

@ -146,13 +146,14 @@ or None if we fail to get the info """
tourno = t.group('TOURNO')
hand.tourNo = tourno
hand.tablename = t.group('TABLE')
#TODO we should fetch info including buyincurrency, buyin and fee from URL:
# https://www.poker4ever.com/tourney/%TOURNEY_NUMBER%
# Believe Everleaf time is GMT/UTC, no transation necessary
# Stars format (Nov 10 2008): 2008/11/07 12:38:49 CET [2008/11/07 7:38:49 ET]
# or : 2008/11/07 12:38:49 ET
# Not getting it in my HH files yet, so using
# 2008/11/10 3:58:52 ET
#TODO: Do conversion from GMT to ET
#TODO: Need some date functions to convert to different timezones (Date::Manip for perl rocked for this)
hand.startTime = datetime.datetime.strptime(m.group('DATETIME'), "%Y/%m/%d - %H:%M:%S")
return

View File

@ -229,12 +229,21 @@ class Filters(threading.Thread):
return self.numHands
#end def getNumHands
def getNumTourneys(self):
return self.numTourneys
#end def getNumTourneys
def getSites(self):
return self.sites
#end def getSites
def getTourneyTypes(self):
return self.tourneyTypes
#end def getTourneyTypes
def getGames(self):
return self.games
#end def getGames
def getSiteIds(self):
return self.siteid
@ -316,6 +325,7 @@ class Filters(threading.Thread):
liststore.append(_nt)
self.__set_hero_name(pname, site)
#end def createPlayerLine
def __set_hero_name(self, w, site):
_name = w.get_text()
@ -338,6 +348,20 @@ class Filters(threading.Thread):
cb.connect('clicked', self.__set_site_select, site)
cb.set_active(True)
hbox.pack_start(cb, False, False, 0)
#end def createSiteLine
def __set_tourney_type_select(self, w, tourneyType):
#print w.get_active()
self.tourneyTypes[tourneyType] = w.get_active()
log.debug("self.tourney_types[%s] set to %s" %(tourneyType, self.tourneyTypes[tourneyType]))
#end def __set_tourney_type_select
def createTourneyTypeLine(self, hbox, tourneyType):
cb = gtk.CheckButton(str(tourneyType))
cb.connect('clicked', self.__set_tourney_type_select, tourneyType)
hbox.pack_start(cb, False, False, 0)
cb.set_active(True)
#end def createTourneyTypeLine
def createGameLine(self, hbox, game):
cb = gtk.CheckButton(game)
@ -357,6 +381,7 @@ class Filters(threading.Thread):
#print w.get_active()
self.sites[site] = w.get_active()
log.debug("self.sites[%s] set to %s" %(site, self.sites[site]))
#end def __set_site_select
def __set_game_select(self, w, game):
#print w.get_active()
@ -505,6 +530,7 @@ class Filters(threading.Thread):
#print "__set_seat_select: seat =", seat, "active =", w.get_active()
self.seats[seat] = w.get_active()
log.debug( "self.seats[%s] set to %s" %(seat, self.seats[seat]) )
#end def __set_seat_select
def __set_group_select(self, w, group):
#print "__set_seat_select: seat =", seat, "active =", w.get_active()
@ -552,6 +578,7 @@ class Filters(threading.Thread):
hbox.pack_start(phands, False, False, 0)
phands.connect("changed", self.__set_num_hands, site)
top_hbox.pack_start(showb, expand=False, padding=1)
#end def fillPlayerFrame
def fillSitesFrame(self, vbox):
top_hbox = gtk.HBox(False, 0)
@ -583,6 +610,33 @@ class Filters(threading.Thread):
# self.siteid[site] = result[0][0]
#else:
# print "Either 0 or more than one site matched - EEK"
#end def fillSitesFrame
def fillTourneyTypesFrame(self, vbox):
top_hbox = gtk.HBox(False, 0)
vbox.pack_start(top_hbox, False, False, 0)
lbl_title = gtk.Label(self.filterText['tourneyTypesTitle'])
lbl_title.set_alignment(xalign=0.0, yalign=0.5)
top_hbox.pack_start(lbl_title, expand=True, padding=3)
showb = gtk.Button(label="hide", stock=None, use_underline=True)
showb.set_alignment(xalign=1.0, yalign=0.5)
showb.connect('clicked', self.__toggle_box, 'tourneyTypes')
top_hbox.pack_start(showb, expand=False, padding=1)
vbox1 = gtk.VBox(False, 0)
vbox.pack_start(vbox1, False, False, 0)
self.boxes['tourneyTypes'] = vbox1
result = self.db.getTourneyTypesIds()
if len(result) >= 1:
for line in result:
hbox = gtk.HBox(False, 0)
vbox1.pack_start(hbox, False, True, 0)
self.createTourneyTypeLine(hbox, line[0])
else:
print "INFO: No tourney types returned from database"
log.info("No tourney types returned from database")
#end def fillTourneyTypesFrame
def fillGamesFrame(self, vbox):
top_hbox = gtk.HBox(False, 0)
@ -859,6 +913,7 @@ class Filters(threading.Thread):
for w in self.mainVBox.get_children():
w.destroy()
self.make_filter()
#end def __refresh
def __toggle_box(self, widget, entry):
if self.boxes[entry].props.visible:

View File

@ -54,7 +54,7 @@ class Fulltilt(HandHistoryConverter):
\$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)\s(Ante\s\$?(?P<ANTE>[.0-9]+)\s)?-\s
\$?(?P<CAP>[.0-9]+\sCap\s)?
(?P<GAMETYPE>[a-zA-Z\/\'\s]+)\s-\s
(?P<DATETIME>\d+:\d+:\d+\s\w+\s-\s\d+/\d+/\d+|\d+:\d+\s\w+\s-\s\w+\,\s\w+\s\d+\,\s\d+)
(?P<DATETIME>\d+:\d+:\d+\s(?P<TZ1>\w+)\s-\s\d+/\d+/\d+|\d+:\d+\s(?P<TZ2>\w+)\s-\s\w+\,\s\w+\s\d+\,\s\d+)
(?P<PARTIAL>\(partial\))?\n
(?:.*?\n(?P<CANCELLED>Hand\s\#(?P=HID)\shas\sbeen\scanceled))?
''', re.VERBOSE|re.DOTALL)
@ -202,12 +202,17 @@ class Fulltilt(HandHistoryConverter):
hand.handid = m.group('HID')
hand.tablename = m.group('TABLE')
timezone = "ET"
if m.group('TZ1') == "CET" or m.group('TZ2') == "CET":
timezone = "CET"
try:
hand.startTime = datetime.datetime.strptime(m.group('DATETIME'), "%H:%M:%S ET - %Y/%m/%d")
stringformat = "%H:%M:%S " + m.group('TZ1') + " - %Y/%m/%d"
hand.startTime = datetime.datetime.strptime(m.group('DATETIME'), stringformat)
except:
hand.startTime = datetime.datetime.strptime(m.group('DATETIME'), "%H:%M ET - %a, %B %d, %Y")
stringformat = "%H:%M " + m.group('TZ2') + " - %a, %B %d, %Y"
hand.startTime = datetime.datetime.strptime(m.group('DATETIME'), stringformat)
hand.startTime = HandHistoryConverter.changeTimezone(hand.startTime, "ET", "UTC")
hand.startTime = HandHistoryConverter.changeTimezone(hand.startTime, timezone, "UTC")
if m.group("CANCELLED") or m.group("PARTIAL"):
raise FpdbParseError(hid=m.group('HID'))

View File

@ -31,7 +31,7 @@ import Filters
import Charset
import GuiPlayerStats
colalias,colshow,colheading,colxalign,colformat,coltype = 0,1,2,3,4,5
colalias,colshowsumm,colshowposn,colheading,colxalign,colformat,coltype = 0,1,2,3,4,5,6
ranks = {'x':0, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9, 'T':10, 'J':11, 'Q':12, 'K':13, 'A':14}
class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats):
@ -88,33 +88,34 @@ class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats):
# ToDo: store in config
# ToDo: create popup to adjust column config
# columns to display, keys match column name returned by sql, values in tuple are:
# is column displayed, column heading, xalignment, formatting, celltype
self.columns = [ ["game", True, "Game", 0.0, "%s", "str"]
, ["hand", False, "Hand", 0.0, "%s", "str"] # true not allowed for this line
, ["plposition", False, "Posn", 1.0, "%s", "str"] # true not allowed for this line (set in code)
, ["pname", False, "Name", 0.0, "%s", "str"] # true not allowed for this line (set in code)
, ["n", True, "Hds", 1.0, "%1.0f", "str"]
, ["avgseats", False, "Seats", 1.0, "%3.1f", "str"]
, ["vpip", True, "VPIP", 1.0, "%3.1f", "str"]
, ["pfr", True, "PFR", 1.0, "%3.1f", "str"]
, ["pf3", True, "PF3", 1.0, "%3.1f", "str"]
, ["aggfac", True, "AggFac", 1.0, "%2.2f", "str"]
, ["aggfrq", True, "AggFreq", 1.0, "%3.1f", "str"]
, ["conbet", True, "ContBet", 1.0, "%3.1f", "str"]
, ["steals", True, "Steals", 1.0, "%3.1f", "str"]
, ["saw_f", True, "Saw_F", 1.0, "%3.1f", "str"]
, ["sawsd", True, "SawSD", 1.0, "%3.1f", "str"]
, ["wtsdwsf", True, "WtSDwsF", 1.0, "%3.1f", "str"]
, ["wmsd", True, "W$SD", 1.0, "%3.1f", "str"]
, ["flafq", True, "FlAFq", 1.0, "%3.1f", "str"]
, ["tuafq", True, "TuAFq", 1.0, "%3.1f", "str"]
, ["rvafq", True, "RvAFq", 1.0, "%3.1f", "str"]
, ["pofafq", False, "PoFAFq", 1.0, "%3.1f", "str"]
, ["net", True, "Net($)", 1.0, "%6.2f", "cash"]
, ["bbper100", True, "bb/100", 1.0, "%4.2f", "str"]
, ["rake", True, "Rake($)", 1.0, "%6.2f", "cash"]
, ["bb100xr", True, "bbxr/100", 1.0, "%4.2f", "str"]
, ["variance", True, "Variance", 1.0, "%5.2f", "str"]
# is column displayed(summary then position), column heading, xalignment, formatting, celltype
self.columns = [ ["game", True, True, "Game", 0.0, "%s", "str"]
, ["hand", False, False, "Hand", 0.0, "%s", "str"] # true not allowed for this line
, ["plposition", False, False, "Posn", 1.0, "%s", "str"] # true not allowed for this line (set in code)
, ["pname", False, False, "Name", 0.0, "%s", "str"] # true not allowed for this line (set in code)
, ["n", True, True, "Hds", 1.0, "%1.0f", "str"]
, ["avgseats", False, False, "Seats", 1.0, "%3.1f", "str"]
, ["vpip", True, True, "VPIP", 1.0, "%3.1f", "str"]
, ["pfr", True, True, "PFR", 1.0, "%3.1f", "str"]
, ["pf3", True, True, "PF3", 1.0, "%3.1f", "str"]
, ["aggfac", True, True, "AggFac", 1.0, "%2.2f", "str"]
, ["aggfrq", True, True, "AggFreq", 1.0, "%3.1f", "str"]
, ["conbet", True, True, "ContBet", 1.0, "%3.1f", "str"]
, ["rfi", True, True, "RFI", 1.0, "%3.1f", "str"]
, ["steals", True, True, "Steals", 1.0, "%3.1f", "str"]
, ["saw_f", True, True, "Saw_F", 1.0, "%3.1f", "str"]
, ["sawsd", True, True, "SawSD", 1.0, "%3.1f", "str"]
, ["wtsdwsf", True, True, "WtSDwsF", 1.0, "%3.1f", "str"]
, ["wmsd", True, True, "W$SD", 1.0, "%3.1f", "str"]
, ["flafq", True, True, "FlAFq", 1.0, "%3.1f", "str"]
, ["tuafq", True, True, "TuAFq", 1.0, "%3.1f", "str"]
, ["rvafq", True, True, "RvAFq", 1.0, "%3.1f", "str"]
, ["pofafq", False, False, "PoFAFq", 1.0, "%3.1f", "str"]
, ["net", True, True, "Net($)", 1.0, "%6.2f", "cash"]
, ["bbper100", True, True, "bb/100", 1.0, "%4.2f", "str"]
, ["rake", True, True, "Rake($)", 1.0, "%6.2f", "cash"]
, ["bb100xr", True, True, "bbxr/100", 1.0, "%4.2f", "str"]
, ["variance", True, True, "Variance", 1.0, "%5.2f", "str"]
]
# Detail filters: This holds the data used in the popup window, extra values are
@ -149,6 +150,8 @@ class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats):
self.stats_vbox = gtk.VPaned()
self.stats_vbox.show()
self.stats_frame.add(self.stats_vbox)
self.top_pane_height = 0
self.height_inc = None
# self.fillStatsFrame(self.stats_vbox)
#self.main_hbox.pack_start(self.filters.get_vbox())
@ -158,7 +161,17 @@ class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats):
self.main_hbox.show()
# make sure Hand column is not displayed
[x for x in self.columns if x[0] == 'hand'][0][1] = False
[x for x in self.columns if x[0] == 'hand'][0][colshowsumm] = False
[x for x in self.columns if x[0] == 'hand'][0][colshowposn] = False
# if rfi and steal both on for summaries, turn rfi off
if ( [x for x in self.columns if x[0] == 'rfi'][0][colshowsumm]
and [x for x in self.columns if x[0] == 'steals'][0][colshowsumm]):
[x for x in self.columns if x[0] == 'rfi'][0][colshowsumm] = False
# if rfi and steal both on for position breakdowns, turn steals off:
if ( [x for x in self.columns if x[0] == 'rfi'][0][colshowposn]
and [x for x in self.columns if x[0] == 'steals'][0][colshowposn]):
[x for x in self.columns if x[0] == 'steals'][0][colshowposn] = False
self.last_pos = -1
@ -168,18 +181,33 @@ class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats):
#end def get_vbox
def refreshStats(self, widget, data):
self.last_pos = self.stats_vbox.get_position()
#self.last_pos = self.stats_vbox.get_position()
self.height_inc = None
#old_len = 0
#if self.liststore:
# old_len = len(self.liststore[0])
try: self.stats_vbox.destroy()
except AttributeError: pass
self.liststore = []
self.listcols = []
#self.stats_vbox = gtk.VBox(False, 0)
self.stats_vbox = gtk.VPaned()
self.stats_vbox.show()
self.stats_frame.add(self.stats_vbox)
self.fillStatsFrame(self.stats_vbox)
if self.last_pos > 0:
self.stats_vbox.set_position(self.last_pos)
# set height of top pane
# (tried 2 ways, guesstimate using ratio of old to new number of rows and sum of
# heights of parts)
new_len = 0
if self.liststore:
#new_len = len(self.liststore[0])
#print "setting to", self.top_pane_height + self.height_inc
self.stats_vbox.set_position(self.top_pane_height + self.height_inc)
#if self.last_pos > 0:
# if old_len > 0 and new_len > 0 and new_len <= 10:
# self.stats_vbox.set_position(self.last_pos * (new_len+1.9)/(old_len+1.9))
# else:
# self.stats_vbox.set_position(self.last_pos)
#end def refreshStats
def fillStatsFrame(self, vbox):
@ -225,8 +253,8 @@ class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats):
# Scrolled window for summary table
swin = gtk.ScrolledWindow(hadjustment=None, vadjustment=None)
swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
swin.show()
vbox.pack1(swin)
vbox.pack1(swin) #, resize=True) don't use resize, self.height_inc relies on initial
# height of pane being correct for one row
# Display summary table at top of page
# 3rd parameter passes extra flags, currently includes:
@ -236,6 +264,7 @@ class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats):
flags = [False, self.filters.getNumHands(), 0]
self.addGrid(swin, 'playerDetailedStats', flags, playerids
,sitenos, limits, type, seats, groups, dates, games)
swin.show()
if 'allplayers' in groups and groups['allplayers']:
# can't currently do this combination so skip detailed table
@ -249,19 +278,32 @@ class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats):
vbox2.pack_start(heading, expand=False, padding=3)
# Scrolled window for detailed table (display by hand)
swin = gtk.ScrolledWindow(hadjustment=None, vadjustment=None)
swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
swin.show()
vbox2.pack_start(swin, expand=True, padding=3)
swin2 = gtk.ScrolledWindow(hadjustment=None, vadjustment=None)
swin2.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
swin2.show()
vbox2.pack_start(swin2, expand=True, padding=3)
vbox.pack2(vbox2)
vbox2.show()
# Detailed table
flags[0] = True
flags[2] = 1
self.addGrid(swin, 'playerDetailedStats', flags, playerids
self.addGrid(swin2, 'playerDetailedStats', flags, playerids
,sitenos, limits, type, seats, groups, dates, games)
if self.height_inc is None:
self.height_inc = 0
# need this to check whether scrollbar is visible:
while gtk.events_pending(): # see http://faq.pygtk.org/index.py?req=index for more hints (3.7)
gtk.main_iteration(False)
hs = swin.get_hscrollbar()
if hs is not None:
#print "hs vis", hs.get_property('visible'), hs.get_property('visible').__class__
if hs.get_property('visible'):
self.height_inc = hs.size_request()[1] + swin.style_get_property('scrollbar-spacing')
#print "hh set to", self.height_inc
self.stats_vbox.set_position(self.top_pane_height + self.height_inc)
self.db.rollback()
print "Stats page displayed in %4.2f seconds" % (time() - startTime)
#end def createStatsTable
@ -350,6 +392,8 @@ class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats):
colnames = [desc[0].lower() for desc in self.cursor.description]
# pre-fetch some constant values:
colshow = colshowsumm
if groups['posn']: colshow = colshowposn
self.cols_to_show = [x for x in self.columns if x[colshow]]
hgametypeid_idx = colnames.index('hgametypeid')
@ -445,6 +489,11 @@ class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats):
sqlrow += 1
row += 1
vbox.show_all()
view.show()
if len(self.liststore) == 1:
#print "view hieght is ", view.get_allocation().height, view.size_request(), view.get_visible_rect().height, view.get_vadjustment().get_value()
self.top_pane_height = view.size_request()[1]
#print "saved ", self.top_pane_height
#end def addGrid
def refineQuery(self, query, flags, playerids, sitenos, limits, type, seats, groups, dates, games):
@ -455,20 +504,22 @@ class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats):
else:
holecards = flags[0]
numhands = flags[1]
colshow = colshowsumm
if groups['posn']: colshow = colshowposn
if 'allplayers' in groups and groups['allplayers']:
nametest = "(hp.playerId)"
if holecards or groups['posn']:
pname = "'all players'"
# set flag in self.columns to not show player name column
[x for x in self.columns if x[0] == 'pname'][0][1] = False
[x for x in self.columns if x[0] == 'pname'][0][colshow] = False
# can't do this yet (re-write doing more maths in python instead of sql?)
if numhands:
nametest = "(-1)"
else:
pname = "p.name"
# set flag in self.columns to show player name column
[x for x in self.columns if x[0] == 'pname'][0][1] = True
[x for x in self.columns if x[0] == 'pname'][0][colshow] = True
if numhands:
having = ' and count(1) > %d ' % (numhands,)
else:
@ -480,7 +531,7 @@ class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats):
nametest = "1 = 2"
pname = "p.name"
# set flag in self.columns to not show player name column
[x for x in self.columns if x[0] == 'pname'][0][1] = False
[x for x in self.columns if x[0] == 'pname'][0][colshow] = False
query = query.replace("<player_test>", nametest)
query = query.replace("<playerName>", pname)
query = query.replace("<havingclause>", having)
@ -603,11 +654,11 @@ class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats):
#query = query.replace("<position>", "case hp.position when '0' then 'Btn' else hp.position end")
query = query.replace("<position>", "hp.position")
# set flag in self.columns to show posn column
[x for x in self.columns if x[0] == 'plposition'][0][1] = True
[x for x in self.columns if x[0] == 'plposition'][0][colshow] = True
else:
query = query.replace("<position>", "gt.base")
# unset flag in self.columns to hide posn column
[x for x in self.columns if x[0] == 'plposition'][0][1] = False
[x for x in self.columns if x[0] == 'plposition'][0][colshow] = False
#print "query =\n", query
return(query)

View File

@ -1,290 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#Copyright 2008-2010 Steffen Schaumburg
#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.
import threading
import pygtk
pygtk.require('2.0')
import gtk
import os
import fpdb_import
from Exceptions import *
class GuiTableViewer (threading.Thread):
def hudDivide (self, a, b):
if b==0:
return "n/a"
else:
return str(int((a/float(b))*100))+"%"
#end def hudDivide
def browse_clicked(self, widget, data):
"""runs when user clicks browse on tv tab"""
#print "start of table_viewer.browser_clicked"
current_path=self.filename_tbuffer.get_text(self.filename_tbuffer.get_start_iter(), self.filename_tbuffer.get_end_iter())
dia_chooser = gtk.FileChooserDialog(title="Please choose the file for which you want to open the Table Viewer",
action=gtk.FILE_CHOOSER_ACTION_OPEN,
buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
#dia_chooser.set_current_folder(pathname)
dia_chooser.set_filename(current_path)
#dia_chooser.set_select_multiple(select_multiple) #not in tv, but want this in bulk import
response = dia_chooser.run()
if response == gtk.RESPONSE_OK:
#print dia_chooser.get_filename(), 'selected'
self.filename_tbuffer.set_text(dia_chooser.get_filename())
elif response == gtk.RESPONSE_CANCEL:
print 'Closed, no files selected'
dia_chooser.destroy()
#end def table_viewer.browse_clicked
def prepare_data(self):
"""prepares the data for display by refresh_clicked, returns a 2D array"""
#print "start of prepare_data"
arr=[]
#first prepare the header row
if (self.category=="holdem" or self.category=="omahahi" or self.category=="omahahilo"):
tmp=("Name", "HDs", "VPIP", "PFR", "PF3B", "ST")
tmp+=("FS", "FB")
tmp+=("CB", )
tmp+=("2B", "3B")
tmp+=("AF", "FF", "AT", "FT", "AR", "FR")
tmp+=("WtSD", "W$wsF", "W$SD")
else:
raise FpdbError("reimplement stud")
arr.append(tmp)
#then the data rows
for player in range(len(self.player_names)):
tmp=[]
p_name = Charset.to_gui(self.player_names[player][0])
tmp.append(p_name)
seatCount=len(self.player_names)
if seatCount>=8:
minSeats,maxSeats=7,10
elif seatCount==7:
minSeats,maxSeats=6,10
elif seatCount==6 or seatCount==5:
minSeats,maxSeats=seatCount-1,seatCount+1
elif seatCount==4:
minSeats,maxSeats=4,5
elif seatCount==2 or seatCount==3:
minSeats,maxSeats=seatCount,seatCount
else:
FpdbError("invalid seatCount")
self.cursor.execute("SELECT * FROM HudCache WHERE gametypeId=%s AND playerId=%s AND activeSeats>=%s AND activeSeats<=%s", (self.gametype_id, self.player_ids[player][0], minSeats, maxSeats))
rows=self.cursor.fetchall()
row=[]
for field_no in range(len(rows[0])):
row.append(rows[0][field_no])
for row_no in range(len(rows)):
if row_no==0:
pass
else:
for field_no in range(len(rows[row_no])):
if field_no<=3:
pass
else:
#print "in prep data, row_no:",row_no,"field_no:",field_no
row[field_no]+=rows[row_no][field_no]
tmp.append(str(row[6]))#Hands
tmp.append(self.hudDivide(row[7],row[6])) #VPIP
tmp.append(self.hudDivide(row[8],row[6])) #PFR
tmp.append(self.hudDivide(row[10],row[9])+" ("+str(row[9])+")") #PF3B
tmp.append(self.hudDivide(row[31],row[30])+" ("+str(row[30])+")") #ST
tmp.append(self.hudDivide(row[35],row[34])+" ("+str(row[34])+")") #FS
tmp.append(self.hudDivide(row[33],row[32])+" ("+str(row[32])+")") #FB
tmp.append(self.hudDivide(row[37],row[36])+" ("+str(row[36])+")") #CB
tmp.append(self.hudDivide(row[39],row[38])+" ("+str(row[38])+")") #2B
tmp.append(self.hudDivide(row[41],row[40])+" ("+str(row[40])+")") #3B
tmp.append(self.hudDivide(row[16],row[11])+" ("+str(row[11])+")") #AF
tmp.append(self.hudDivide(row[24],row[20])+" ("+str(row[20])+")") #FF
tmp.append(self.hudDivide(row[17],row[12])+" ("+str(row[12])+")") #AT
tmp.append(self.hudDivide(row[25],row[21])+" ("+str(row[21])+")") #FT
tmp.append(self.hudDivide(row[18],row[13])+" ("+str(row[13])+")") #AR
tmp.append(self.hudDivide(row[26],row[22])+" ("+str(row[22])+")") #FR
tmp.append(self.hudDivide(row[15],row[11])) #WtSD
tmp.append(self.hudDivide(row[28],row[11])) #W$wSF
tmp.append(self.hudDivide(row[29],row[15])+" ("+str(row[15])+")") #W$@SD
arr.append(tmp)
return arr
#end def table_viewer.prepare_data
def refresh_clicked(self, widget, data):
"""runs when user clicks refresh"""
#print "start of table_viewer.refresh_clicked"
arr=self.prepare_data()
try: self.data_table.destroy()
except AttributeError: pass
self.data_table=gtk.Table(rows=len(arr), columns=len(arr[0]), homogeneous=False)
self.main_vbox.pack_start(self.data_table)
self.data_table.show()
for row in range(len(arr)):
for column in range (len(arr[row])):
eventBox=gtk.EventBox()
new_label=gtk.Label(arr[row][column])
if row%2==0: #
bg_col="white"
if column==0 or (column>=5 and column<=10):
bg_col="lightgrey"
else:
bg_col="lightgrey"
if column==0 or (column>=5 and column<=10):
bg_col="grey"
#style = eventBox.get_style()
#style.font.height=8
#eventBox.set_style(style)
eventBox.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bg_col))
eventBox.add(new_label)
self.data_table.attach(child=eventBox, left_attach=column, right_attach=column+1, top_attach=row, bottom_attach=row+1)
eventBox.show()
new_label.show()
#end def table_viewer.refresh_clicked
def read_names_clicked(self, widget, data):
"""runs when user clicks read names"""
#print "start of table_viewer.read_names_clicked"
self.db.reconnect()
self.cursor=self.db.get_cursor()
#self.hands_id=self.last_read_hand_id
self.cursor.execute("SELECT gametypeId FROM Hands WHERE id=%s", (self.hands_id, ))
self.gametype_id=self.cursor.fetchone()[0]
self.cursor.execute("SELECT category FROM Gametypes WHERE id=%s", (self.gametype_id, ))
self.category=self.cursor.fetchone()[0]
#print "self.gametype_id", self.gametype_id," category:", self.category, " self.hands_id:", self.hands_id
self.cursor.execute("""SELECT DISTINCT Players.id FROM HandsPlayers
INNER JOIN Players ON HandsPlayers.playerId=Players.id
WHERE handId=%s""", (self.hands_id, ))
self.player_ids=self.cursor.fetchall()
#print "self.player_ids:",self.player_ids
self.cursor.execute("""SELECT DISTINCT Players.name FROM HandsPlayers
INNER JOIN Players ON HandsPlayers.playerId=Players.id
WHERE handId=%s""", (self.hands_id, ))
self.player_names=self.cursor.fetchall()
#print "self.player_names:",self.player_names
#end def table_viewer.read_names_clicked
def import_clicked(self, widget, data):
"""runs when user clicks import"""
#print "start of table_viewer.import_clicked"
self.inputFile=self.filename_tbuffer.get_text(self.filename_tbuffer.get_start_iter(), self.filename_tbuffer.get_end_iter())
self.importer = fpdb_import.Importer(self, self.settings, self.config)
self.importer.setMinPrint(0)
self.importer.setQuiet(False)
self.importer.setFailOnError(False)
self.importer.setHandCount(0)
self.importer.addImportFile(self.inputFile)
self.importer.runImport()
self.hands_id=self.importer.handsId
#end def table_viewer.import_clicked
def all_clicked(self, widget, data):
"""runs when user clicks all"""
#print "start of table_viewer.all_clicked"
self.import_clicked(widget, data)
self.read_names_clicked(widget, data)
self.refresh_clicked(widget, data)
#end def table_viewer.all_clicked
def get_vbox(self):
"""returns the vbox of this thread"""
return self.main_vbox
#end def get_vbox
def __init__(self, db, settings, config=None, debug=True):
"""Constructor for table_viewer"""
self.debug=debug
#print "start of table_viewer constructor"
self.db = db
self.cursor = db.get_cursor()
self.settings = settings
self.config = config
self.main_vbox = gtk.VBox(False, 0)
self.main_vbox.show()
self.settings_hbox = gtk.HBox(False, 0)
self.main_vbox.pack_end(self.settings_hbox, False, True, 0)
self.settings_hbox.show()
self.filename_label = gtk.Label("Path of history file")
self.settings_hbox.pack_start(self.filename_label, False, False)
self.filename_label.show()
self.filename_tbuffer=gtk.TextBuffer()
self.filename_tbuffer.set_text(self.settings['hud-defaultPath'])
self.filename_tview=gtk.TextView(self.filename_tbuffer)
self.settings_hbox.pack_start(self.filename_tview, True, True, padding=5)
self.filename_tview.show()
self.browse_button=gtk.Button("Browse...")
self.browse_button.connect("clicked", self.browse_clicked, "Browse clicked")
self.settings_hbox.pack_start(self.browse_button, False, False)
self.browse_button.show()
self.button_hbox = gtk.HBox(False, 0)
self.main_vbox.pack_end(self.button_hbox, False, True, 0)
self.button_hbox.show()
#self.import_button = gtk.Button("Import")
#self.import_button.connect("clicked", self.import_clicked, "Import clicked")
#self.button_hbox.add(self.import_button)
#self.import_button.show()
#self.read_names_button = gtk.Button("Read Names")
#self.read_names_button.connect("clicked", self.read_names_clicked, "Read clicked")
#self.button_hbox.add(self.read_names_button)
#self.read_names_button.show()
#self.refresh_button = gtk.Button("Show/Refresh data")
#self.refresh_button.connect("clicked", self.refresh_clicked, "Refresh clicked")
#self.button_hbox.add(self.refresh_button)
#self.refresh_button.show()
self.all_button = gtk.Button("Import&Read&Refresh")
self.all_button.connect("clicked", self.all_clicked, "All clicked")
self.button_hbox.add(self.all_button)
self.all_button.show()
#end of table_viewer.__init__

View File

@ -26,8 +26,11 @@ import codecs
from decimal import Decimal
import operator
from xml.dom.minidom import Node
import time
import datetime
from pytz import timezone
import pytz
import logging
# logging has been set up in fpdb.py or HUD_main.py, use their settings:
@ -497,19 +500,68 @@ or None if we fail to get the info """
@staticmethod
def changeTimezone(time, givenTimezone, wantedTimezone):
if givenTimezone=="ET" and wantedTimezone=="UTC":
# approximate rules for ET daylight savings time:
if ( time.month == 12 # all of Dec
or (time.month == 11 and time.day > 4) # and most of November
or time.month < 3 # and all of Jan/Feb
or (time.month == 3 and time.day < 11) ): # and 1st 10 days of March
offset = datetime.timedelta(hours=5) # are EST: assume 5 hour offset (ET without daylight saving)
#print "raw time:",time, "given TZ:", givenTimezone
if wantedTimezone=="UTC":
wantedTimezone = pytz.utc
else:
offset = datetime.timedelta(hours=4) # rest is EDT: assume 4 hour offset (ET with daylight saving)
# adjust time into UTC:
time = time + offset
#print " tz = %s start = %s" % (tz, str(hand.starttime))
return time
raise Error #TODO raise appropriate error
if givenTimezone=="ET":
givenTimezone = timezone('US/Eastern')
elif givenTimezone=="CET":
givenTimezone = timezone('Europe/Berlin')
#Note: Daylight Saving Time is standardised across the EU so this should be fine
elif givenTimezone == 'HST': # Hawaiian Standard Time
pass
elif givenTimezone == 'AKT': # Alaska Time
pass
elif givenTimezone == 'PT': # Pacific Time
pass
elif givenTimezone == 'MT': # Mountain Time
pass
elif givenTimezone == 'CT': # Central Time
pass
elif givenTimezone == 'AT': # Atlantic Time
pass
elif givenTimezone == 'NT': # Newfoundland Time
pass
elif givenTimezone == 'ART': # Argentinian Time
pass
elif givenTimezone == 'BRT': # Brasilia Time
pass
elif givenTimezone == 'AKT': # Alaska Time
pass
elif givenTimezone == 'WET': # Western European Time
pass
elif givenTimezone == 'EET': # Eastern European Time
pass
elif givenTimezone == 'MSK': # Moscow Standard Time
pass
elif givenTimezone == 'IST': # India Standard Time
pass
elif givenTimezone == 'CCT': # China Coast Time
pass
elif givenTimezone == 'JST': # Japan Standard Time
pass
elif givenTimezone == 'AWST': # Australian Western Standard Time
givenTimezone = timezone('Australia/West')
elif givenTimezone == 'ACST': # Australian Central Standard Time
givenTimezone = timezone('Australia/Darwin')
elif givenTimezone == 'AEST': # Australian Eastern Standard Time
# Each State on the East Coast has different DSTs.
# Melbournce is out because I don't like AFL, Queensland doesn't have DST
# ACT is full of politicians and Tasmania will never notice.
# Using Sydney.
givenTimezone = timezone('Australia/Sydney')
elif givenTimezone == 'NZT': # New Zealand Time
pass
else:
raise Error #TODO raise appropriate error
localisedTime = givenTimezone.localize(time)
utcTime = localisedTime.astimezone(wantedTimezone)
#print "utcTime:",utcTime
return utcTime
#end @staticmethod def changeTimezone
@staticmethod

View File

@ -72,7 +72,7 @@ class PokerStars(HandHistoryConverter):
(Tournament\s\# # open paren of tournament info
(?P<TOURNO>\d+),\s
# here's how I plan to use LS
(?P<BUYIN>([%(LS)s\+\d\.]+\s?(?P<TOUR_ISO>%(LEGAL_ISO)s)?)|Freeroll)\s+)?
(?P<BUYIN>(?P<BIAMT>[%(LS)s\d\.]+)\+(?P<BOUNTY>[%(LS)s\d\.]+)?\+(?P<BIRAKE>[%(LS)s\d\.]+)\s?(?P<TOUR_ISO>%(LEGAL_ISO)s)|Freeroll)\s+)?
# close paren of tournament info
(?P<MIXED>HORSE|8\-Game|HOSE)?\s?\(?
(?P<GAME>Hold\'em|Razz|RAZZ|7\sCard\sStud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball|5\sCard\sDraw)\s
@ -206,15 +206,12 @@ class PokerStars(HandHistoryConverter):
m = self.re_HandInfo.search(hand.handText,re.DOTALL)
if m:
info.update(m.groupdict())
# hand.maxseats = int(m2.group(1))
else:
pass # throw an exception here, eh?
m = self.re_GameInfo.search(hand.handText)
if m:
info.update(m.groupdict())
# m = self.re_Button.search(hand.handText)
# if m: info.update(m.groupdict())
# TODO : I rather like the idea of just having this dict as hand.info
log.debug("readHandInfo: %s" % info)
for key in info:
if key == 'DATETIME':
@ -222,8 +219,7 @@ class PokerStars(HandHistoryConverter):
#2008/08/17 - 01:14:43 (ET)
#2008/09/07 06:23:14 ET
m1 = self.re_DateTime.finditer(info[key])
# m2 = re.search("(?P<Y>[0-9]{4})\/(?P<M>[0-9]{2})\/(?P<D>[0-9]{2})[\- ]+(?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)", info[key])
datetimestr = "2000/01/01 00:00:00" # default used if time not found (stops import crashing, but startTime will be wrong)
datetimestr = "2000/01/01 00:00:00" # default used if time not found
for a in m1:
datetimestr = "%s/%s/%s %s:%s:%s" % (a.group('Y'), a.group('M'),a.group('D'),a.group('H'),a.group('MIN'),a.group('S'))
#tz = a.group('TZ') # just assume ET??
@ -236,12 +232,15 @@ class PokerStars(HandHistoryConverter):
hand.tourNo = info[key]
if key == 'BUYIN':
if hand.tourNo!=None:
#print "DEBUG: info['BUYIN']: %s" % info['BUYIN']
#print "DEBUG: info['BIAMT']: %s" % info['BIAMT']
#print "DEBUG: info['BIRAKE']: %s" % info['BIRAKE']
#print "DEBUG: info['BOUNTY']: %s" % info['BOUNTY']
if info[key] == 'Freeroll':
hand.buyin = 0
hand.fee = 0
hand.buyinCurrency = "FREE"
else:
#print "info[key]:",info[key]
if info[key].find("$")!=-1:
hand.buyinCurrency="USD"
elif info[key].find(u"")!=-1:
@ -249,13 +248,13 @@ class PokerStars(HandHistoryConverter):
elif info[key].find("FPP")!=-1:
hand.buyinCurrency="PSFP"
else:
raise FpdbParseError("failed to detect currency") #FIXME: handle other currencies, FPP, play money
#FIXME: handle other currencies, FPP, play money
raise FpdbParseError("failed to detect currency")
if hand.buyinCurrency=="USD" or hand.buyinCurrency=="EUR":
info[key]=info[key][:-4]
middle=info[key].find("+")
hand.buyin = int(100*Decimal(info[key][1:middle]))
hand.fee = int(100*Decimal(info[key][middle+2:]))
hand.buyin = int(100*Decimal(info['BIAMT'][1:]))
hand.fee = int(100*Decimal(info['BIRAKE'][1:]))
# TODO: Bounty is in key 'BOUNTY'
elif hand.buyinCurrency=="PSFP":
hand.buyin = int(Decimal(info[key][0:-3]))
hand.fee = 0

View File

@ -392,9 +392,9 @@ class Sql:
self.query['createTourneyTypesTable'] = """CREATE TABLE TourneyTypes (
id SMALLINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
siteId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id),
currency varchar(4) NOT NULL,
buyIn INT NOT NULL,
fee INT NOT NULL,
currency varchar(4),
buyIn INT,
fee INT,
category varchar(9) NOT NULL,
limitType char(2) NOT NULL,
buyInChips INT,
@ -423,9 +423,9 @@ class Sql:
self.query['createTourneyTypesTable'] = """CREATE TABLE TourneyTypes (
id SERIAL, PRIMARY KEY (id),
siteId INT NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id),
currency varchar(4) NOT NULL,
buyin INT NOT NULL,
fee INT NOT NULL,
currency varchar(4),
buyin INT,
fee INT,
category varchar(9),
limitType char(2),
buyInChips INT,
@ -453,9 +453,9 @@ class Sql:
self.query['createTourneyTypesTable'] = """CREATE TABLE TourneyTypes (
id INTEGER PRIMARY KEY,
siteId INT NOT NULL,
currency VARCHAR(4) NOT NULL,
buyin INT NOT NULL,
fee INT NOT NULL,
currency VARCHAR(4),
buyin INT,
fee INT,
category TEXT,
limitType TEXT,
buyInChips INT,
@ -598,8 +598,8 @@ class Sql:
foldToOtherRaisedStreet3 BOOLEAN,
foldToOtherRaisedStreet4 BOOLEAN,
stealAttemptChance BOOLEAN,
stealAttempted BOOLEAN,
raiseFirstInChance BOOLEAN,
raisedFirstIn BOOLEAN,
foldBbToStealChance BOOLEAN,
foldedBbToSteal BOOLEAN,
foldSbToStealChance BOOLEAN,
@ -714,8 +714,8 @@ class Sql:
foldToOtherRaisedStreet3 BOOLEAN,
foldToOtherRaisedStreet4 BOOLEAN,
stealAttemptChance BOOLEAN,
stealAttempted BOOLEAN,
raiseFirstInChance BOOLEAN,
raisedFirstIn BOOLEAN,
foldBbToStealChance BOOLEAN,
foldedBbToSteal BOOLEAN,
foldSbToStealChance BOOLEAN,
@ -829,8 +829,8 @@ class Sql:
foldToOtherRaisedStreet3 INT,
foldToOtherRaisedStreet4 INT,
stealAttemptChance INT,
stealAttempted INT,
raiseFirstInChance INT,
raisedFirstIn INT,
foldBbToStealChance INT,
foldedBbToSteal INT,
foldSbToStealChance INT,
@ -1025,8 +1025,8 @@ class Sql:
foldToOtherRaisedStreet3 INT,
foldToOtherRaisedStreet4 INT,
stealAttemptChance INT,
stealAttempted INT,
raiseFirstInChance INT,
raisedFirstIn INT,
foldBbToStealChance INT,
foldedBbToSteal INT,
foldSbToStealChance INT,
@ -1125,8 +1125,8 @@ class Sql:
foldToOtherRaisedStreet3 INT,
foldToOtherRaisedStreet4 INT,
stealAttemptChance INT,
stealAttempted INT,
raiseFirstInChance INT,
raisedFirstIn INT,
foldBbToStealChance INT,
foldedBbToSteal INT,
foldSbToStealChance INT,
@ -1224,8 +1224,8 @@ class Sql:
foldToOtherRaisedStreet3 INT,
foldToOtherRaisedStreet4 INT,
stealAttemptChance INT,
stealAttempted INT,
raiseFirstInChance INT,
raisedFirstIn INT,
foldBbToStealChance INT,
foldedBbToSteal INT,
foldSbToStealChance INT,
@ -1364,8 +1364,18 @@ class Sql:
sum(hc.foldToOtherRaisedStreet4) AS f_freq_4,
sum(hc.wonWhenSeenStreet1) AS w_w_s_1,
sum(hc.wonAtSD) AS wmsd,
sum(hc.stealAttemptChance) AS steal_opp,
sum(hc.stealAttempted) AS steal,
sum(case hc.position
when 'S' then hc.raiseFirstInChance
when '0' then hc.raiseFirstInChance
when '1' then hc.raiseFirstInChance
else 0
) AS steal_opp,
sum(case hc.position
when 'S' then hc.raisedFirstIn
when '0' then hc.raisedFirstIn
when '1' then hc.raisedFirstIn
else 0
) AS steal,
sum(hc.foldSbToStealChance) AS SBstolen,
sum(hc.foldedSbToSteal) AS SBnotDef,
sum(hc.foldBbToStealChance) AS BBstolen,
@ -1463,8 +1473,8 @@ class Sql:
sum(hc.foldToOtherRaisedStreet4) AS f_freq_4,
sum(hc.wonWhenSeenStreet1) AS w_w_s_1,
sum(hc.wonAtSD) AS wmsd,
sum(hc.stealAttemptChance) AS steal_opp,
sum(hc.stealAttempted) AS steal,
sum(hc.raiseFirstInChance) AS steal_opp,
sum(hc.raisedFirstIn) AS steal,
sum(hc.foldSbToStealChance) AS SBstolen,
sum(hc.foldedSbToSteal) AS SBnotDef,
sum(hc.foldBbToStealChance) AS BBstolen,
@ -1589,8 +1599,8 @@ class Sql:
cast(hp2.foldToOtherRaisedStreet4 as <signed>integer) AS f_freq_4,
cast(hp2.wonWhenSeenStreet1 as <signed>integer) AS w_w_s_1,
cast(hp2.wonAtSD as <signed>integer) AS wmsd,
cast(hp2.stealAttemptChance as <signed>integer) AS steal_opp,
cast(hp2.stealAttempted as <signed>integer) AS steal,
cast(hp2.raiseFirstInChance as <signed>integer) AS steal_opp,
cast(hp2.raisedFirstIn as <signed>integer) AS steal,
cast(hp2.foldSbToStealChance as <signed>integer) AS SBstolen,
cast(hp2.foldedSbToSteal as <signed>integer) AS SBnotDef,
cast(hp2.foldBbToStealChance as <signed>integer) AS BBstolen,
@ -1691,8 +1701,8 @@ class Sql:
cast(hp2.foldToOtherRaisedStreet4 as <signed>integer) AS f_freq_4,
cast(hp2.wonWhenSeenStreet1 as <signed>integer) AS w_w_s_1,
cast(hp2.wonAtSD as <signed>integer) AS wmsd,
cast(hp2.stealAttemptChance as <signed>integer) AS steal_opp,
cast(hp2.stealAttempted as <signed>integer) AS steal,
cast(hp2.raiseFirstInChance as <signed>integer) AS steal_opp,
cast(hp2.raisedFirstIn as <signed>integer) AS steal,
cast(hp2.foldSbToStealChance as <signed>integer) AS SBstolen,
cast(hp2.foldedSbToSteal as <signed>integer) AS SBnotDef,
cast(hp2.foldBbToStealChance as <signed>integer) AS BBstolen,
@ -1794,8 +1804,8 @@ class Sql:
cast(hp2.foldToOtherRaisedStreet4 as <signed>integer) AS f_freq_4,
cast(hp2.wonWhenSeenStreet1 as <signed>integer) AS w_w_s_1,
cast(hp2.wonAtSD as <signed>integer) AS wmsd,
cast(hp2.stealAttemptChance as <signed>integer) AS steal_opp,
cast(hp2.stealAttempted as <signed>integer) AS steal,
cast(hp2.raiseFirstInChance as <signed>integer) AS steal_opp,
cast(hp2.raisedFirstIn as <signed>integer) AS steal,
cast(hp2.foldSbToStealChance as <signed>integer) AS SBstolen,
cast(hp2.foldedSbToSteal as <signed>integer) AS SBnotDef,
cast(hp2.foldBbToStealChance as <signed>integer) AS BBstolen,
@ -2026,8 +2036,32 @@ class Sql:
,case when sum(cast(hp.street0_3Bchance as <signed>integer)) = 0 then -999
else 100.0*sum(cast(hp.street0_3Bdone as <signed>integer))/sum(cast(hp.street0_3Bchance as <signed>integer))
end AS pf3
,case when sum(cast(hp.stealattemptchance as <signed>integer)) = 0 then -999
else 100.0*sum(cast(hp.stealattempted as <signed>integer))/sum(cast(hp.stealattemptchance as <signed>integer))
,case when sum(cast(hp.raiseFirstInChance as <signed>integer)) = 0 then -999
else 100.0 * sum(cast(hp.raisedFirstIn as <signed>integer)) /
sum(cast(hp.raiseFirstInChance as <signed>integer))
end AS rfi
,case when sum(case hp.position
when 'S' then cast(hp.raiseFirstInChance as <signed>integer)
when '0' then cast(hp.raiseFirstInChance as <signed>integer)
when '1' then cast(hp.raiseFirstInChance as <signed>integer)
else 0
end
) = 0 then -999
else 100.0 *
sum(case hp.position
when 'S' then cast(hp.raisedFirstIn as <signed>integer)
when '0' then cast(hp.raisedFirstIn as <signed>integer)
when '1' then cast(hp.raisedFirstIn as <signed>integer)
else 0
end
) /
sum(case hp.position
when 'S' then cast(hp.raiseFirstInChance as <signed>integer)
when '0' then cast(hp.raiseFirstInChance as <signed>integer)
when '1' then cast(hp.raiseFirstInChance as <signed>integer)
else 0
end
)
end AS steals
,100.0*sum(cast(hp.street1Seen as <signed>integer))/count(1) AS saw_f
,100.0*sum(cast(hp.sawShowdown as <signed>integer))/count(1) AS sawsd
@ -2123,8 +2157,32 @@ class Sql:
,case when sum(cast(hp.street0_3Bchance as <signed>integer)) = 0 then -999
else 100.0*sum(cast(hp.street0_3Bdone as <signed>integer))/sum(cast(hp.street0_3Bchance as <signed>integer))
end AS pf3
,case when sum(cast(hp.stealattemptchance as <signed>integer)) = 0 then -999
else 100.0*sum(cast(hp.stealattempted as <signed>integer))/sum(cast(hp.stealattemptchance as <signed>integer))
,case when sum(cast(hp.raiseFirstInChance as <signed>integer)) = 0 then -999
else 100.0 * sum(cast(hp.raisedFirstIn as <signed>integer)) /
sum(cast(hp.raiseFirstInChance as <signed>integer))
end AS rfi
,case when sum(case hp.position
when 'S' then cast(hp.raiseFirstInChance as <signed>integer)
when '0' then cast(hp.raiseFirstInChance as <signed>integer)
when '1' then cast(hp.raiseFirstInChance as <signed>integer)
else 0
end
) = 0 then -999
else 100.0 *
sum(case hp.position
when 'S' then cast(hp.raisedFirstIn as <signed>integer)
when '0' then cast(hp.raisedFirstIn as <signed>integer)
when '1' then cast(hp.raisedFirstIn as <signed>integer)
else 0
end
) /
sum(case hp.position
when 'S' then cast(hp.raiseFirstInChance as <signed>integer)
when '0' then cast(hp.raiseFirstInChance as <signed>integer)
when '1' then cast(hp.raiseFirstInChance as <signed>integer)
else 0
end
)
end AS steals
,100.0*sum(cast(hp.street1Seen as <signed>integer))/count(1) AS saw_f
,100.0*sum(cast(hp.sawShowdown as <signed>integer))/count(1) AS sawsd
@ -2221,8 +2279,32 @@ class Sql:
,case when sum(cast(hp.street0_3Bchance as <signed>integer)) = 0 then -999
else 100.0*sum(cast(hp.street0_3Bdone as <signed>integer))/sum(cast(hp.street0_3Bchance as <signed>integer))
end AS pf3
,case when sum(cast(hp.stealattemptchance as <signed>integer)) = 0 then -999
else 100.0*sum(cast(hp.stealattempted as <signed>integer))/sum(cast(hp.stealattemptchance as <signed>integer))
,case when sum(cast(hp.raiseFirstInChance as <signed>integer)) = 0 then -999
else 100.0 * sum(cast(hp.raisedFirstIn as <signed>integer)) /
sum(cast(hp.raiseFirstInChance as <signed>integer))
end AS rfi
,case when sum(case hp.position
when 'S' then cast(hp.raiseFirstInChance as <signed>integer)
when '0' then cast(hp.raiseFirstInChance as <signed>integer)
when '1' then cast(hp.raiseFirstInChance as <signed>integer)
else 0
end
) = 0 then -999
else 100.0 *
sum(case hp.position
when 'S' then cast(hp.raisedFirstIn as <signed>integer)
when '0' then cast(hp.raisedFirstIn as <signed>integer)
when '1' then cast(hp.raisedFirstIn as <signed>integer)
else 0
end
) /
sum(case hp.position
when 'S' then cast(hp.raiseFirstInChance as <signed>integer)
when '0' then cast(hp.raiseFirstInChance as <signed>integer)
when '1' then cast(hp.raiseFirstInChance as <signed>integer)
else 0
end
)
end AS steals
,100.0*sum(cast(hp.street1Seen as <signed>integer))/count(1) AS saw_f
,100.0*sum(cast(hp.sawShowdown as <signed>integer))/count(1) AS sawsd
@ -2380,8 +2462,8 @@ class Sql:
,case when sum(street0_3Bchance) = 0 then '0'
else format(100.0*sum(street0_3Bdone)/sum(street0_3Bchance),1)
end AS pf3
,case when sum(stealattemptchance) = 0 then '-'
else format(100.0*sum(stealattempted)/sum(stealattemptchance),1)
,case when sum(raiseFirstInChance) = 0 then '-'
else format(100.0*sum(raisedFirstIn)/sum(raiseFirstInChance),1)
end AS steals
,format(100.0*sum(street1Seen)/sum(HDs),1) AS saw_f
,format(100.0*sum(sawShowdown)/sum(HDs),1) AS sawsd
@ -2444,6 +2526,8 @@ class Sql:
) hprof2
on hprof2.gtId = stats.gtId
order by stats.category, stats.limittype, stats.bigBlindDesc desc <orderbyseats>"""
#elif db_server == 'sqlite': #TODO
# self.query['playerStats'] = """ """
else: # assume postgres
self.query['playerStats'] = """
SELECT upper(stats.limitType) || ' '
@ -2483,8 +2567,8 @@ class Sql:
,case when sum(street0_3Bchance) = 0 then '0'
else to_char(100.0*sum(street0_3Bdone)/sum(street0_3Bchance),'90D0')
end AS pf3
,case when sum(stealattemptchance) = 0 then '-'
else to_char(100.0*sum(stealattempted)/sum(stealattemptchance),'90D0')
,case when sum(raiseFirstInChance) = 0 then '-'
else to_char(100.0*sum(raisedFirstIn)/sum(raiseFirstInChance),'90D0')
end AS steals
,to_char(100.0*sum(street1Seen)/sum(HDs),'90D0') AS saw_f
,to_char(100.0*sum(sawShowdown)/sum(HDs),'90D0') AS sawsd
@ -2547,8 +2631,6 @@ class Sql:
) hprof2
on hprof2.gtId = stats.gtId
order by stats.base, stats.limittype, stats.bigBlindDesc desc <orderbyseats>"""
#elif db_server == 'sqlite':
# self.query['playerStats'] = """ """
if db_server == 'mysql':
self.query['playerStatsByPosition'] = """
@ -2608,8 +2690,8 @@ class Sql:
,case when sum(street0_3Bchance) = 0 then '0'
else format(100.0*sum(street0_3Bdone)/sum(street0_3Bchance),1)
end AS pf3
,case when sum(stealattemptchance) = 0 then '-'
else format(100.0*sum(stealattempted)/sum(stealattemptchance),1)
,case when sum(raiseFirstInChance) = 0 then '-'
else format(100.0*sum(raisedFirstIn)/sum(raiseFirstInChance),1)
end AS steals
,format(100.0*sum(street1Seen)/sum(HDs),1) AS saw_f
,format(100.0*sum(sawShowdown)/sum(HDs),1) AS sawsd
@ -2742,8 +2824,8 @@ class Sql:
,case when sum(street0_3Bchance) = 0 then '0'
else to_char(100.0*sum(street0_3Bdone)/sum(street0_3Bchance),'90D0')
end AS pf3
,case when sum(stealattemptchance) = 0 then '-'
else to_char(100.0*sum(stealattempted)/sum(stealattemptchance),'90D0')
,case when sum(raiseFirstInChance) = 0 then '-'
else to_char(100.0*sum(raisedFirstIn)/sum(raiseFirstInChance),'90D0')
end AS steals
,to_char(round(100.0*sum(street1Seen)/sum(HDs)),'90D0') AS saw_f
,to_char(round(100.0*sum(sawShowdown)/sum(HDs)),'90D0') AS sawsd
@ -2922,8 +3004,8 @@ class Sql:
,foldToOtherRaisedStreet2
,foldToOtherRaisedStreet3
,foldToOtherRaisedStreet4
,stealAttemptChance
,stealAttempted
,raiseFirstInChance
,raisedFirstIn
,foldBbToStealChance
,foldedBbToSteal
,foldSbToStealChance
@ -3012,8 +3094,8 @@ class Sql:
,sum(foldToOtherRaisedStreet2)
,sum(foldToOtherRaisedStreet3)
,sum(foldToOtherRaisedStreet4)
,sum(stealAttemptChance)
,sum(stealAttempted)
,sum(raiseFirstInChance)
,sum(raisedFirstIn)
,sum(foldBbToStealChance)
,sum(foldedBbToSteal)
,sum(foldSbToStealChance)
@ -3103,8 +3185,8 @@ class Sql:
,foldToOtherRaisedStreet2
,foldToOtherRaisedStreet3
,foldToOtherRaisedStreet4
,stealAttemptChance
,stealAttempted
,raiseFirstInChance
,raisedFirstIn
,foldBbToStealChance
,foldedBbToSteal
,foldSbToStealChance
@ -3193,8 +3275,8 @@ class Sql:
,sum(CAST(foldToOtherRaisedStreet2 as integer))
,sum(CAST(foldToOtherRaisedStreet3 as integer))
,sum(CAST(foldToOtherRaisedStreet4 as integer))
,sum(CAST(stealAttemptChance as integer))
,sum(CAST(stealAttempted as integer))
,sum(CAST(raisedFirstInChance as integer))
,sum(CAST(raisedFirstIn as integer))
,sum(CAST(foldBbToStealChance as integer))
,sum(CAST(foldedBbToSteal as integer))
,sum(CAST(foldSbToStealChance as integer))
@ -3284,8 +3366,8 @@ class Sql:
,foldToOtherRaisedStreet2
,foldToOtherRaisedStreet3
,foldToOtherRaisedStreet4
,stealAttemptChance
,stealAttempted
,raiseFirstInChance
,raisedFirstIn
,foldBbToStealChance
,foldedBbToSteal
,foldSbToStealChance
@ -3374,8 +3456,8 @@ class Sql:
,sum(CAST(foldToOtherRaisedStreet2 as integer))
,sum(CAST(foldToOtherRaisedStreet3 as integer))
,sum(CAST(foldToOtherRaisedStreet4 as integer))
,sum(CAST(stealAttemptChance as integer))
,sum(CAST(stealAttempted as integer))
,sum(CAST(raiseFirstInChance as integer))
,sum(CAST(raisedFirstIn as integer))
,sum(CAST(foldBbToStealChance as integer))
,sum(CAST(foldedBbToSteal as integer))
,sum(CAST(foldSbToStealChance as integer))
@ -3465,8 +3547,8 @@ class Sql:
foldToOtherRaisedStreet4,
wonWhenSeenStreet1,
wonAtSD,
stealAttemptChance,
stealAttempted,
raiseFirstInChance,
raisedFirstIn,
foldBbToStealChance,
foldedBbToSteal,
foldSbToStealChance,
@ -3554,8 +3636,8 @@ class Sql:
foldToOtherRaisedStreet4=foldToOtherRaisedStreet4+%s,
wonWhenSeenStreet1=wonWhenSeenStreet1+%s,
wonAtSD=wonAtSD+%s,
stealAttemptChance=stealAttemptChance+%s,
stealAttempted=stealAttempted+%s,
raiseFirstInChance=raiseFirstInChance+%s,
raisedFirstIn=raisedFirstIn+%s,
foldBbToStealChance=foldBbToStealChance+%s,
foldedBbToSteal=foldedBbToSteal+%s,
foldSbToStealChance=foldSbToStealChance+%s,
@ -3873,8 +3955,8 @@ class Sql:
foldToOtherRaisedStreet2,
foldToOtherRaisedStreet3,
foldToOtherRaisedStreet4,
stealAttemptChance,
stealAttempted,
raiseFirstInChance,
raisedFirstIn,
foldBbToStealChance,
foldedBbToSteal,
foldSbToStealChance,

View File

@ -351,6 +351,29 @@ def f_BB_steal(stat_dict, player):
'(0/0)',
'% folded BB to steal')
def f_steal(stat_dict, player):
""" Folded blind to steal."""
stat = 0.0
try:
folded_blind = stat_dict[player]['sbnotdef'] + stat_dict[player]['bbnotdef']
blind_stolen = stat_dict[player]['sbstolen'] + stat_dict[player]['bbstolen']
stat = float(folded_blind)/float(blind_stolen)
return (stat,
'%3.1f' % (100*stat) + '%',
'fB=%3.1f' % (100*stat) + '%',
'fB_s=%3.1f' % (100*stat) + '%',
'(%d/%d)' % (folded_blind, blind_stolen),
'% folded blind to steal'
)
except:
return (stat,
'NA',
'fB=NA',
'fB_s=NA',
'(0/0)',
'% folded blind to steal')
def three_B(stat_dict, player):
""" Three bet preflop/3rd."""
stat = 0.0
@ -777,6 +800,7 @@ if __name__== "__main__":
#print "player = ", player, do_stat(stat_dict, player = player, stat = 'steal')
#print "player = ", player, do_stat(stat_dict, player = player, stat = 'f_SB_steal')
#print "player = ", player, do_stat(stat_dict, player = player, stat = 'f_BB_steal')
#print "player = ", player, do_stat(stat_dict, player = player, stat = 'f_steal')
#print "player = ", player, do_stat(stat_dict, player = player, stat = 'three_B')
#print "player = ", player, do_stat(stat_dict, player = player, stat = 'WMsF')
#print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq1')

View File

@ -63,68 +63,12 @@ class TourneyFilters(Filters.Filters):
self.make_filter()
#end def __init__
def __calendar_dialog(self, widget, entry):
d = gtk.Window(gtk.WINDOW_TOPLEVEL)
d.set_title('Pick a date')
vb = gtk.VBox()
cal = gtk.Calendar()
vb.pack_start(cal, expand=False, padding=0)
btn = gtk.Button('Done')
btn.connect('clicked', self.__get_date, cal, entry, d)
vb.pack_start(btn, expand=False, padding=4)
d.add(vb)
d.set_position(gtk.WIN_POS_MOUSE)
d.show_all()
#end def __calendar_dialog
def __clear_dates(self, w):
self.start_date.set_text('')
self.end_date.set_text('')
#end def __clear_dates
def __get_dates(self):
# self.day_start gives user's start of day in hours
offset = int(self.day_start * 3600) # calc day_start in seconds
t1 = self.start_date.get_text()
t2 = self.end_date.get_text()
if t1 == '':
t1 = '1970-01-02'
if t2 == '':
t2 = '2020-12-12'
s1 = strptime(t1, "%Y-%m-%d") # make time_struct
s2 = strptime(t2, "%Y-%m-%d")
e1 = mktime(s1) + offset # s1 is localtime, but returned time since epoch is UTC, then add the
e2 = mktime(s2) + offset # s2 is localtime, but returned time since epoch is UTC
e2 = e2 + 24 * 3600 - 1 # date test is inclusive, so add 23h 59m 59s to e2
adj_t1 = strftime("%Y-%m-%d %H:%M:%S", gmtime(e1)) # make adjusted string including time
adj_t2 = strftime("%Y-%m-%d %H:%M:%S", gmtime(e2))
log.info("t1="+t1+" adj_t1="+adj_t1+'.')
return (adj_t1, adj_t2)
#end def __get_dates
def __refresh(self, widget, entry):
def __refresh(self, widget, entry): #identical with Filters
for w in self.mainVBox.get_children():
w.destroy()
self.make_filter()
#end def __refresh
def __set_hero_name(self, w, site):
_name = w.get_text()
# get_text() returns a str but we want internal variables to be unicode:
_guiname = unicode(_name)
self.heroes[site] = _guiname
#log.debug("setting heroes[%s]: %s"%(site, self.heroes[site]))
#end def __set_hero_name
def __set_num_tourneys(self, w, val):
try:
self.numTourneys = int(w.get_text())
@ -133,25 +77,7 @@ class TourneyFilters(Filters.Filters):
print "setting numTourneys:", self.numTourneys
#end def __set_num_tourneys
def __set_seat_select(self, w, seat):
#print "__set_seat_select: seat =", seat, "active =", w.get_active()
self.seats[seat] = w.get_active()
log.debug( "self.seats[%s] set to %s" %(seat, self.seats[seat]) )
#end def __set_seat_select
def __set_site_select(self, w, site):
#print w.get_active()
self.sites[site] = w.get_active()
log.debug("self.sites[%s] set to %s" %(site, self.sites[site]))
#end def __set_site_select
def __set_tourney_type_select(self, w, tourneyType):
#print w.get_active()
self.tourneyTypes[tourneyType] = w.get_active()
log.debug("self.tourney_types[%s] set to %s" %(tourneyType, self.tourneyTypes[tourneyType]))
#end def __set_tourney_type_select
def __toggle_box(self, widget, entry):
def __toggle_box(self, widget, entry): #identical with Filters
if self.boxes[entry].props.visible:
self.boxes[entry].hide()
widget.set_label("show")
@ -160,259 +86,6 @@ class TourneyFilters(Filters.Filters):
widget.set_label("hide")
#end def __toggle_box
def createPlayerLine(self, hbox, site, player):
log.debug('add:"%s"' % player)
label = gtk.Label(site +" id:")
hbox.pack_start(label, False, False, 3)
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)
# Added EntryCompletion but maybe comboBoxEntry is more flexible? (e.g. multiple choices)
completion = gtk.EntryCompletion()
pname.set_completion(completion)
liststore = gtk.ListStore(gobject.TYPE_STRING)
completion.set_model(liststore)
completion.set_text_column(0)
names = self.db.get_player_names(self.conf, self.siteid[site]) # (config=self.conf, site_id=None, like_player_name="%")
for n in names: # list of single-element "tuples"
_n = Charset.to_gui(n[0])
_nt = (_n, )
liststore.append(_nt)
self.__set_hero_name(pname, site)
#end def createPlayerLine
def createSiteLine(self, hbox, site):
cb = gtk.CheckButton(site)
cb.connect('clicked', self.__set_site_select, site)
cb.set_active(True)
hbox.pack_start(cb, False, False, 0)
#end def createSiteLine
def createTourneyTypeLine(self, hbox, tourneyType):
cb = gtk.CheckButton(str(tourneyType))
cb.connect('clicked', self.__set_tourney_type_select, tourneyType)
hbox.pack_start(cb, False, False, 0)
cb.set_active(True)
#end def createTourneyTypeLine
def fillDateFrame(self, vbox):
# Hat tip to Mika Bostrom - calendar code comes from PokerStats
top_hbox = gtk.HBox(False, 0)
vbox.pack_start(top_hbox, False, False, 0)
lbl_title = gtk.Label(self.filterText['datestitle'])
lbl_title.set_alignment(xalign=0.0, yalign=0.5)
top_hbox.pack_start(lbl_title, expand=True, padding=3)
showb = gtk.Button(label="hide", stock=None, use_underline=True)
showb.set_alignment(xalign=1.0, yalign=0.5)
showb.connect('clicked', self.__toggle_box, 'dates')
top_hbox.pack_start(showb, expand=False, padding=1)
vbox1 = gtk.VBox(False, 0)
vbox.pack_start(vbox1, False, False, 0)
self.boxes['dates'] = vbox1
hbox = gtk.HBox()
vbox1.pack_start(hbox, False, True, 0)
lbl_start = gtk.Label('From:')
btn_start = gtk.Button()
btn_start.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON))
btn_start.connect('clicked', self.__calendar_dialog, self.start_date)
hbox.pack_start(lbl_start, expand=False, padding=3)
hbox.pack_start(btn_start, expand=False, padding=3)
hbox.pack_start(self.start_date, expand=False, padding=2)
#New row for end date
hbox = gtk.HBox()
vbox1.pack_start(hbox, False, True, 0)
lbl_end = gtk.Label(' To:')
btn_end = gtk.Button()
btn_end.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON))
btn_end.connect('clicked', self.__calendar_dialog, self.end_date)
btn_clear = gtk.Button(label=' Clear Dates ')
btn_clear.connect('clicked', self.__clear_dates)
hbox.pack_start(lbl_end, expand=False, padding=3)
hbox.pack_start(btn_end, expand=False, padding=3)
hbox.pack_start(self.end_date, expand=False, padding=2)
hbox.pack_start(btn_clear, expand=False, padding=15)
#end def fillDateFrame
def fillPlayerFrame(self, vbox, display):
top_hbox = gtk.HBox(False, 0)
vbox.pack_start(top_hbox, False, False, 0)
lbl_title = gtk.Label(self.filterText['playerstitle'])
lbl_title.set_alignment(xalign=0.0, yalign=0.5)
top_hbox.pack_start(lbl_title, expand=True, padding=3)
showb = gtk.Button(label="refresh", stock=None, use_underline=True)
showb.set_alignment(xalign=1.0, yalign=0.5)
showb.connect('clicked', self.__refresh, 'players')
vbox1 = gtk.VBox(False, 0)
vbox.pack_start(vbox1, False, False, 0)
self.boxes['players'] = vbox1
for site in self.conf.get_supported_sites():
hBox = gtk.HBox(False, 0)
vbox1.pack_start(hBox, False, True, 0)
player = self.conf.supported_sites[site].screen_name
_pname = Charset.to_gui(player)
self.createPlayerLine(hBox, site, _pname)
hbox = gtk.HBox(False, 0)
vbox1.pack_start(hbox, False, False, 0)
#cb = gtk.CheckButton(self.filterText['groupsall'])
#cb.connect('clicked', self.__set_group_select, 'allplayers')
#hbox.pack_start(cb, False, False, 0)
#self.sbGroups['allplayers'] = cb
#self.groups['allplayers'] = False
#lbl = gtk.Label('Min # Hands:')
#lbl.set_alignment(xalign=1.0, yalign=0.5)
#hbox.pack_start(lbl, expand=True, padding=3)
#phands = gtk.Entry()
#phands.set_text('0')
#phands.set_width_chars(8)
#hbox.pack_start(phands, False, False, 0)
#phands.connect("changed", self.__set_num_hands, site)
top_hbox.pack_start(showb, expand=False, padding=1)
#end def fillPlayerFrame
def fillSeatsFrame(self, vbox, display):
hbox = gtk.HBox(False, 0)
vbox.pack_start(hbox, False, False, 0)
lbl_title = gtk.Label(self.filterText['seatstitle'])
lbl_title.set_alignment(xalign=0.0, yalign=0.5)
hbox.pack_start(lbl_title, expand=True, padding=3)
showb = gtk.Button(label="hide", stock=None, use_underline=True)
showb.set_alignment(xalign=1.0, yalign=0.5)
showb.connect('clicked', self.__toggle_box, 'seats')
hbox.pack_start(showb, expand=False, padding=1)
vbox1 = gtk.VBox(False, 0)
vbox.pack_start(vbox1, False, False, 0)
self.boxes['seats'] = vbox1
hbox = gtk.HBox(False, 0)
vbox1.pack_start(hbox, False, True, 0)
lbl_from = gtk.Label(self.filterText['seatsbetween'])
lbl_to = gtk.Label(self.filterText['seatsand'])
adj1 = gtk.Adjustment(value=2, lower=2, upper=10, step_incr=1, page_incr=1, page_size=0)
sb1 = gtk.SpinButton(adjustment=adj1, climb_rate=0.0, digits=0)
adj2 = gtk.Adjustment(value=10, lower=2, upper=10, step_incr=1, page_incr=1, page_size=0)
sb2 = gtk.SpinButton(adjustment=adj2, climb_rate=0.0, digits=0)
hbox.pack_start(lbl_from, expand=False, padding=3)
hbox.pack_start(sb1, False, False, 0)
hbox.pack_start(lbl_to, expand=False, padding=3)
hbox.pack_start(sb2, False, False, 0)
self.sbSeats['from'] = sb1
self.sbSeats['to'] = sb2
#end def fillSeatsFrame
def fillSitesFrame(self, vbox):
top_hbox = gtk.HBox(False, 0)
top_hbox.show()
vbox.pack_start(top_hbox, False, False, 0)
lbl_title = gtk.Label(self.filterText['sitestitle'])
lbl_title.set_alignment(xalign=0.0, yalign=0.5)
top_hbox.pack_start(lbl_title, expand=True, padding=3)
showb = gtk.Button(label="hide", stock=None, use_underline=True)
showb.set_alignment(xalign=1.0, yalign=0.5)
showb.connect('clicked', self.__toggle_box, 'sites')
showb.show()
top_hbox.pack_start(showb, expand=False, padding=1)
vbox1 = gtk.VBox(False, 0)
self.boxes['sites'] = vbox1
vbox.pack_start(vbox1, False, False, 0)
for site in self.conf.get_supported_sites():
hbox = gtk.HBox(False, 0)
vbox1.pack_start(hbox, False, True, 0)
self.createSiteLine(hbox, site)
#end def fillSitesFrame
def fillTourneyTypesFrame(self, vbox):
top_hbox = gtk.HBox(False, 0)
vbox.pack_start(top_hbox, False, False, 0)
lbl_title = gtk.Label(self.filterText['tourneyTypesTitle'])
lbl_title.set_alignment(xalign=0.0, yalign=0.5)
top_hbox.pack_start(lbl_title, expand=True, padding=3)
showb = gtk.Button(label="hide", stock=None, use_underline=True)
showb.set_alignment(xalign=1.0, yalign=0.5)
showb.connect('clicked', self.__toggle_box, 'tourneyTypes')
top_hbox.pack_start(showb, expand=False, padding=1)
vbox1 = gtk.VBox(False, 0)
vbox.pack_start(vbox1, False, False, 0)
self.boxes['tourneyTypes'] = vbox1
result = self.db.getTourneyTypesIds()
if len(result) >= 1:
for line in result:
hbox = gtk.HBox(False, 0)
vbox1.pack_start(hbox, False, True, 0)
self.createTourneyTypeLine(hbox, line[0])
else:
print "INFO: No tourney types returned from database"
log.info("No tourney types returned from database")
#end def fillTourneyTypesFrame
def getDates(self):
return self.__get_dates()
#end def getDates
def getHeroes(self):
return self.heroes
#end def getHeroes
def getNumTourneys(self):
return self.numTourneys
#end def getNumTourneys
def getSeats(self):
if 'from' in self.sbSeats:
self.seats['from'] = self.sbSeats['from'].get_value_as_int()
if 'to' in self.sbSeats:
self.seats['to'] = self.sbSeats['to'].get_value_as_int()
return self.seats
#end def getSeats
def getSiteIds(self):
return self.siteid
#end def getSiteIds
def getSites(self):
return self.sites
#end def getSites
def getTourneyTypes(self):
return self.tourneyTypes
#end def getTourneyTypes
def get_vbox(self):
"""returns the vbox of this thread"""
return self.mainVBox
#end def get_vbox
def make_filter(self):
self.tourneyTypes = {}
#self.tourneys = {}
@ -526,15 +199,4 @@ class TourneyFilters(Filters.Filters):
# make sure any locks on db are released:
self.db.rollback()
#end def make_filter
def registerButton2Name(self, title):
self.Button2.set_label(title)
self.label['button2'] = title
#end def registerButton2Name
def registerButton2Callback(self, callback):
self.Button2.connect("clicked", callback, "clicked")
self.Button2.set_sensitive(True)
self.callback['button2'] = callback
#end def registerButton2Callback
#end class TourneyFilters

View File

@ -70,7 +70,7 @@ class Table(Table_Window):
for listing in os.popen('xwininfo -root -tree').readlines():
if re.search(search_string, listing):
# print listing
mo = re.match('\s+([\dxabcdef]+) (.+):\s\(\"([a-zA-Z.]+)\".+ (\d+)x(\d+)\+\d+\+\d+ \+(\d+)\+(\d+)', listing)
mo = re.match('\s+([\dxabcdef]+) (.+):\s\(\"([a-zA-Z0-9\-.]+)\".+ (\d+)x(\d+)\+\d+\+\d+ \+(\d+)\+(\d+)', listing)
self.number = int( mo.group(1), 0)
self.width = int( mo.group(4) )
self.height = int( mo.group(5) )

View File

@ -107,7 +107,6 @@ import ImapFetcher
import GuiRingPlayerStats
import GuiTourneyPlayerStats
import GuiPositionalStats
import GuiTableViewer
import GuiAutoImport
import GuiGraphViewer
import GuiSessionViewer
@ -117,7 +116,7 @@ import Configuration
import Exceptions
import Stats
VERSION = "0.20.901"
VERSION = "0.20.902 plus git"
class fpdb:
@ -798,7 +797,6 @@ class fpdb:
<menuitem action="tourneyplayerstats"/>
<menuitem action="posnstats"/>
<menuitem action="sessionstats"/>
<menuitem action="tableviewer"/>
</menu>
<menu action="database">
<menuitem action="maintaindbs"/>
@ -839,7 +837,6 @@ class fpdb:
('tourneyplayerstats', None, '_Tourney Player Stats (tabulated view, mysql only)', '<control>T', 'Tourney Player Stats (tabulated view, mysql only)', self.tab_tourney_player_stats),
('posnstats', None, 'P_ositional Stats (tabulated view)', '<control>O', 'Positional Stats (tabulated view)', self.tab_positional_stats),
('sessionstats', None, 'Session Stats', None, 'Session Stats', self.tab_session_stats),
('tableviewer', None, 'Poker_table Viewer (mostly obselete)', None, 'Poker_table Viewer (mostly obselete)', self.tab_table_viewer),
('database', None, '_Database'),
('maintaindbs', None, '_Maintain Databases', None, 'Maintain Databases', self.dia_maintain_dbs),
('createtabs', None, 'Create or Recreate _Tables', None, 'Create or Recreate Tables ', self.dia_recreate_tables),
@ -1068,13 +1065,6 @@ This program is free/libre open source software licensed partially under the AGP
You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt and gpl-3.0.txt in the fpdb installation directory.""")
self.add_and_display_tab(mh_tab, "Help")
def tab_table_viewer(self, widget, data=None):
"""opens a table viewer tab"""
new_tv_thread = GuiTableViewer.GuiTableViewer(self.db, self.settings, self.config)
self.threads.append(new_tv_thread)
tv_tab = new_tv_thread.get_vbox()
self.add_and_display_tab(tv_tab, "Table Viewer")
def tabGraphViewer(self, widget, data=None):
"""opens a graph viewer tab"""
new_gv_thread = GuiGraphViewer.GuiGraphViewer(self.sql, self.config, self.window)

View File

@ -13,14 +13,12 @@ from distutils.core import setup
setup(name = 'fpdb',
description = 'Free Poker Database',
version = '0.12',
version = '0.20',
author = 'FPDB team',
author_email = 'fpdb-main@lists.sourceforge.net',
packages = ['fpdb'],
package_dir = { 'fpdb' : 'pyfpdb' },
data_files = [
('/usr/share/doc/python-fpdb',
['THANKS.txt']),
('/usr/share/pixmaps',
['gfx/fpdb-icon.png', 'gfx/fpdb-icon2.png',
'gfx/fpdb-cards.png'