Merge branch 'master' of git://git.assembla.com/fpdboz.git
This commit is contained in:
commit
62892c80dc
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
pyfpdb/HUD_config.xml.example -crlf
|
||||
|
32
packaging/announce-0.20.905.txt
Normal file
32
packaging/announce-0.20.905.txt
Normal file
|
@ -0,0 +1,32 @@
|
|||
Hello everyone,
|
||||
The new snapshot 0.20.905 is now available for download as source or as packages/installers for Debian, Gentoo, Ubuntu and Windows.
|
||||
This version brings many improvements and bugfixes, updating is recommended for users of previous snapshots. If you're using a stable version like 0.20 or 0.20.1 please consider trying this version and report any bugs, and in particular regressions, so we can fix them. This snapshot will hopefully be the last, next step is one or more release candidates, and then the next stable release.
|
||||
|
||||
We are still looking for translators! You can find some information about what languages we are still missing here: http://sourceforge.net/apps/mediawiki/fpdb/index.php?title=Translation
|
||||
|
||||
188 changesets (excl. merges) have gone in since 0.20.904.
|
||||
Please note that you will have to either recreate your database or use a new one if you're updating from 0.20.904 or older.
|
||||
Config files from 0.20 and later should work. Please report if you have problems with config files from that version or later.
|
||||
|
||||
What's changed:
|
||||
- Fpdb now supports running in languages other than English, Erki supplied a translation for Hungarian. French, Spanish and Italian are in progress by new contributors. Fpdb will use the system-configured language, a configuration option will be added before the next stable release. Note that this is about the user interface language, non-English history file parsing is a seperate topic.
|
||||
- Much improved testing to improve the recording of data, especially corner cases and non-trivial stats
|
||||
- OnGame network (which now includes Betfair) is now properly supported
|
||||
- FTP.fr importing now works. We don't know if the HUD works yet, give it a go and let us know
|
||||
- We noticed that fpdb already supports PS.fr
|
||||
- PokerStars should support all limits now
|
||||
- The Debian package now handles a missing config file properly
|
||||
- Many minor improvements to the Gentoo ebuilds for the upcoming submission to the sunrise overlay
|
||||
- We changed how email import is configured. Either delete your old config or see the HUD_config.xml.example file for how to add the section to the right place
|
||||
- fpdb should now be able to run with any config file from 0.20 or later, including all 0.20.9* snapshots
|
||||
- Some more fixes to window visibility and the minimise to tray icon feature
|
||||
- Various other small cleanups, fixes and improvements. See the git changelog for full details
|
||||
|
||||
To download:
|
||||
- Debian/Ubuntu Linux: http://sourceforge.net/projects/fpdb/files/fpdb/Snapshots/python-fpdb_0.20.905-1_all.deb/download
|
||||
- Gentoo Linux: http://sourceforge.net/projects/fpdb/files/fpdb/Snapshots/fpdb-0.20.905.ebuild/download
|
||||
- Windows: http://sourceforge.net/projects/fpdb/files/fpdb/Snapshots/fpdb-0.20.905anyCPU.exe/download
|
||||
- Source version for those who installed the dependencies manually: http://sourceforge.net/projects/fpdb/files/fpdb/Snapshots/fpdb-0.20.905.tar.bz2/download
|
||||
|
||||
Thanks to everyone who contributed code, translations, testing and bug reports!
|
||||
The fpdb team
|
|
@ -1,3 +1,16 @@
|
|||
free-poker-tools (0.20.906-1) unstable; urgency=low
|
||||
|
||||
* New snapshot
|
||||
|
||||
-- Mika Bostrom <bostik@iki.fi> Fri, 27 Aug 2010 08:26:05 +0300
|
||||
|
||||
free-poker-tools (0.20.905-1) unstable; urgency=low
|
||||
|
||||
* New snapshot
|
||||
* Hungarian translation
|
||||
|
||||
-- Mika Bostrom <bostik@iki.fi> Wed, 25 Aug 2010 10:05:36 +0300
|
||||
|
||||
free-poker-tools (0.20.904-2) unstable; urgency=low
|
||||
|
||||
* On fpdb start, copy example HUD_config.xml in place if none is present
|
||||
|
|
|
@ -26,8 +26,7 @@ install: build
|
|||
# Copy *.pyw manually in packaging tree
|
||||
cp pyfpdb/*.pyw debian/$(PACKAGE)/usr/lib/python2.6/site-packages/fpdb/
|
||||
# Remove scripts that are only useful in win32
|
||||
rm debian/$(PACKAGE)/usr/lib/python2.6/site-packages/fpdb//windows_make_bats.py
|
||||
rm debian/$(PACKAGE)/usr/lib/python2.6/site-packages/fpdb/py2exe_setup.py
|
||||
rm debian/$(PACKAGE)/usr/lib/python2.6/site-packages/fpdb/windows_make_bats.py
|
||||
|
||||
|
||||
binary-indep: build install
|
||||
|
|
|
@ -17,44 +17,49 @@ SLOT="0"
|
|||
KEYWORDS="~amd64 ~x86"
|
||||
#note: this should work on other architectures too, please send me your experiences
|
||||
|
||||
IUSE="graph mysql postgres sqlite"
|
||||
IUSE="graph mysql postgres sqlite linguas_hu"
|
||||
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
|
||||
graph? ( dev-python/numpy
|
||||
dev-python/matplotlib[gtk] )
|
||||
dev-python/python-xlib
|
||||
dev-python/pytz"
|
||||
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
|
||||
graph? ( dev-python/numpy
|
||||
dev-python/matplotlib[gtk] )
|
||||
dev-python/python-xlib
|
||||
dev-python/pytz"
|
||||
DEPEND="${RDEPEND}"
|
||||
|
||||
src_install() {
|
||||
insinto "${GAMES_DATADIR}"/${PN}
|
||||
doins -r gfx
|
||||
doins -r pyfpdb
|
||||
doins readme.txt
|
||||
insinto "${GAMES_DATADIR}"/${PN}
|
||||
doins -r gfx
|
||||
doins -r pyfpdb
|
||||
|
||||
exeinto "${GAMES_DATADIR}"/${PN}
|
||||
doexe run_fpdb.py
|
||||
if use linguas_hu; then
|
||||
dosym "${GAMES_DATADIR}"/${PN}/pyfpdb/locale/hu/LC_MESSAGES/${PN}.mo /usr/share/locale/hu/LC_MESSAGES/${PN}.mo
|
||||
fi
|
||||
|
||||
dodir "${GAMES_BINDIR}"
|
||||
dosym "${GAMES_DATADIR}"/${PN}/run_fpdb.py "${GAMES_BINDIR}"/${PN}
|
||||
doins readme.txt
|
||||
|
||||
newicon gfx/fpdb-icon.png ${PN}.png
|
||||
make_desktop_entry ${PN}
|
||||
exeinto "${GAMES_DATADIR}"/${PN}
|
||||
doexe run_fpdb.py
|
||||
|
||||
chmod +x "${D}/${GAMES_DATADIR}"/${PN}/pyfpdb/*.pyw
|
||||
prepgamesdirs
|
||||
dodir "${GAMES_BINDIR}"
|
||||
dosym "${GAMES_DATADIR}"/${PN}/run_fpdb.py "${GAMES_BINDIR}"/${PN}
|
||||
|
||||
newicon gfx/fpdb-icon.png ${PN}.png
|
||||
make_desktop_entry ${PN}
|
||||
|
||||
chmod +x "${D}/${GAMES_DATADIR}"/${PN}/pyfpdb/*.pyw
|
||||
prepgamesdirs
|
||||
}
|
||||
|
||||
pkg_postinst() {
|
||||
games_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."
|
||||
games_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."
|
||||
}
|
||||
|
|
|
@ -18,48 +18,53 @@ SLOT="0"
|
|||
KEYWORDS=""
|
||||
#note: this should work on other architectures too, please send me your experiences
|
||||
|
||||
IUSE="graph mysql postgres sqlite"
|
||||
IUSE="graph mysql postgres sqlite linguas_hu"
|
||||
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
|
||||
graph? ( dev-python/numpy
|
||||
dev-python/matplotlib[gtk] )
|
||||
dev-python/python-xlib
|
||||
dev-python/pytz"
|
||||
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
|
||||
graph? ( dev-python/numpy
|
||||
dev-python/matplotlib[gtk] )
|
||||
dev-python/python-xlib
|
||||
dev-python/pytz"
|
||||
DEPEND="${RDEPEND}"
|
||||
|
||||
src_unpack() {
|
||||
git_src_unpack
|
||||
git_src_unpack
|
||||
}
|
||||
|
||||
src_install() {
|
||||
insinto "${GAMES_DATADIR}"/${PN}
|
||||
doins -r gfx
|
||||
doins -r pyfpdb
|
||||
doins readme.txt
|
||||
insinto "${GAMES_DATADIR}"/${PN}
|
||||
doins -r gfx
|
||||
doins -r pyfpdb
|
||||
|
||||
exeinto "${GAMES_DATADIR}"/${PN}
|
||||
doexe run_fpdb.py
|
||||
if use linguas_hu; then
|
||||
dosym "${GAMES_DATADIR}"/${PN}/pyfpdb/locale/hu/LC_MESSAGES/${PN}.mo /usr/share/locale/hu/LC_MESSAGES/${PN}.mo
|
||||
fi
|
||||
|
||||
dodir "${GAMES_BINDIR}"
|
||||
dosym "${GAMES_DATADIR}"/${PN}/run_fpdb.py "${GAMES_BINDIR}"/${PN}
|
||||
doins readme.txt
|
||||
|
||||
newicon gfx/fpdb-icon.png ${PN}.png
|
||||
make_desktop_entry ${PN}
|
||||
exeinto "${GAMES_DATADIR}"/${PN}
|
||||
doexe run_fpdb.py
|
||||
|
||||
chmod +x "${D}/${GAMES_DATADIR}"/${PN}/pyfpdb/*.pyw
|
||||
prepgamesdirs
|
||||
dodir "${GAMES_BINDIR}"
|
||||
dosym "${GAMES_DATADIR}"/${PN}/run_fpdb.py "${GAMES_BINDIR}"/${PN}
|
||||
|
||||
newicon gfx/fpdb-icon.png ${PN}.png
|
||||
make_desktop_entry ${PN}
|
||||
|
||||
chmod +x "${D}/${GAMES_DATADIR}"/${PN}/pyfpdb/*.pyw
|
||||
prepgamesdirs
|
||||
}
|
||||
|
||||
pkg_postinst() {
|
||||
games_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."
|
||||
games_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."
|
||||
}
|
||||
|
|
|
@ -103,6 +103,7 @@ Step 4 Get the fpdb GIT tree
|
|||
----------------------------
|
||||
|
||||
4.1/ Best to take a copy to work with; following steps will assume that the fpdb folder is on the Desktop
|
||||
4.2/ Edit the script in packaging/windows/py2exe_setup.py to set the fpdbver variable for this release
|
||||
|
||||
|
||||
5.3/ Install correct Numpy for this build
|
||||
|
@ -158,7 +159,7 @@ Step 6 Run py2exe to generate fpdb.exe
|
|||
|
||||
6.1/ Run the script to create the fpdb.exe bundle
|
||||
|
||||
dos> cd Desktop\fpdb\pyfpdb
|
||||
dos> cd Desktop\fpdb\packaging\windows
|
||||
dos> c:\python26\python.exe py2exe_setup.py py2exe
|
||||
|
||||
wait a while, watch lots of copying and whatever.
|
||||
|
@ -183,16 +184,14 @@ Step 8 Drag out the completed bundle
|
|||
------------------------------------
|
||||
|
||||
py2exe creates a new folder for the created software bundle, drag this out to the desktop for ease of working.
|
||||
As far as I know you cannot rerun the build if the fpdb-yyyymmdd-exe exists in the tree, so dragging this out
|
||||
also allows the build to re-run at step 6.
|
||||
|
||||
8.1/ Drag Desktop\fpdb\pyfpdb\fpdb-yyyymmdd-exe to Desktop\
|
||||
8.1/ Drag Desktop\fpdb\packaging\windows\fpdb-n.nn.nnn to Desktop\
|
||||
|
||||
|
||||
Step 9 Initial run
|
||||
------------------
|
||||
|
||||
9.1/ Open the Desktop\fpdb-yyyymmdd-exe folder
|
||||
9.1/ Open the Desktop\fpdb-n.nn.nnn folder
|
||||
9.2/ In explorer...tools...folder options...View uncheck "Hide extensions for known file types"
|
||||
9.3/ Double click run_fpdb.bat
|
||||
9.4/ check the contents of pyfpdb\fpdb.exe.log, deal with any errors thrown
|
||||
|
@ -222,7 +221,7 @@ pyfpdb/share/man
|
|||
Step 12 rename folder
|
||||
---------------------
|
||||
|
||||
Rename the folder to something meaningful to the community. If you have built for NoSSE, append anyCPU to the directory name.
|
||||
If needed, rename the folder to something meaningful to the community. If you have built for NoSSE, append anyCPU to the directory name.
|
||||
|
||||
|
||||
Step 13 Compress to executable archive
|
||||
|
|
|
@ -32,14 +32,10 @@ Py2exe script for fpdb.
|
|||
|
||||
#HOW TO USE this script:
|
||||
#
|
||||
#- cd to the folder where this script is stored, usually .../pyfpdb.
|
||||
# [If there are build and dist subfolders present , delete them to get
|
||||
# rid of earlier builds. Update: script now does this for you]
|
||||
#- Run the script with "py2exe_setup.py py2exe"
|
||||
#- You will frequently get messages about missing .dll files. E. g.,
|
||||
# MSVCP90.dll. These are somewhere in your windows install, so you
|
||||
# can just copy them to your working folder. (or just assume other
|
||||
# person will have them? any copyright issues with including them?)
|
||||
#- cd to the folder where this script is stored, usually ...packaging/windows
|
||||
#- Run the script with python "py2exe_setup.py py2exe"
|
||||
#- You will frequently get messages about missing .dll files.just assume other
|
||||
# person will have them? we have copyright issues including some dll's
|
||||
#- If it works, you'll have a new dir fpdb-YYYYMMDD-exe which should
|
||||
# contain 2 dirs; gfx and pyfpdb and run_fpdb.bat
|
||||
#- [ This bit is now automated:
|
||||
|
@ -49,27 +45,11 @@ Py2exe script for fpdb.
|
|||
#- You can (should) then prune the etc/, lib/ and share/ folders to
|
||||
# remove components we don't need. (see output at end of program run)
|
||||
|
||||
# sqlcoder notes: this worked for me with the following notes:
|
||||
#- I used the following versions:
|
||||
# python 2.5.4
|
||||
# gtk+ 2.14.7 (gtk_2.14.7-20090119)
|
||||
# pycairo 1.4.12-2
|
||||
# pygobject 2.14.2-2
|
||||
# pygtk 2.12.1-3
|
||||
# matplotlib 0.98.3
|
||||
# numpy 1.4.0
|
||||
# py2exe-0.6.9 for python 2.5
|
||||
#
|
||||
#- I also copied these dlls manually from <gtk>/bin to /dist :
|
||||
#
|
||||
# libgobject-2.0-0.dll
|
||||
# libgdk-win32-2.0-0.dll
|
||||
#
|
||||
# Now updated to work with python 2.6 + related dependencies
|
||||
# See walkthrough in packaging directory for versions used
|
||||
# Updates to this script have broken python 2.5 compatibility (gio module, msvcr71 references now msvcp90)
|
||||
|
||||
# steffeN: Doesnt seem necessary to gettext-ify this, but feel free to if you disagree
|
||||
# Gimick: restructure to allow script to run from packaging/windows directory, and not to write to source pyfpdb
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
@ -86,33 +66,14 @@ import py2exe
|
|||
import glob
|
||||
import matplotlib
|
||||
import shutil
|
||||
from datetime import date
|
||||
#from datetime import date
|
||||
|
||||
|
||||
origIsSystemDLL = py2exe.build_exe.isSystemDLL
|
||||
def isSystemDLL(pathname):
|
||||
#dwmapi appears to be vista-specific file, not XP
|
||||
if os.path.basename(pathname).lower() in ("dwmapi.dll"):
|
||||
return 0
|
||||
return origIsSystemDLL(pathname)
|
||||
py2exe.build_exe.isSystemDLL = isSystemDLL
|
||||
|
||||
|
||||
def remove_tree(top):
|
||||
# Delete everything reachable from the directory named in 'top',
|
||||
# assuming there are no symbolic links.
|
||||
# CAUTION: This is dangerous! For example, if top == '/', it
|
||||
# could delete all your disk files.
|
||||
# sc: Nicked this from somewhere, added the if statement to try
|
||||
# make it a bit safer
|
||||
if top in ('build','dist','pyfpdb',dist_dirname) and os.path.basename(os.getcwd()) == 'pyfpdb':
|
||||
#print "removing directory '"+top+"' ..."
|
||||
for root, dirs, files in os.walk(top, topdown=False):
|
||||
for name in files:
|
||||
os.remove(os.path.join(root, name))
|
||||
for name in dirs:
|
||||
os.rmdir(os.path.join(root, name))
|
||||
os.rmdir(top)
|
||||
|
||||
def test_and_remove(top):
|
||||
if os.path.exists(top):
|
||||
|
@ -122,30 +83,63 @@ def test_and_remove(top):
|
|||
print "Unexpected file '"+top+"' found. Exiting."
|
||||
exit()
|
||||
|
||||
today = date.today().strftime('%Y%m%d')
|
||||
print "\n" + r"Output will be created in \pyfpdb\ and \fpdb_"+today+'\\'
|
||||
#print "Enter value for XXX (any length): ", # the comma means no newline
|
||||
#xxx = sys.stdin.readline().rstrip()
|
||||
dist_dirname = r'fpdb-' + today + '-exe'
|
||||
dist_dir = r'..\fpdb-' + today + '-exe'
|
||||
print
|
||||
def remove_tree(top):
|
||||
# Delete everything reachable from the directory named in 'top',
|
||||
# assuming there are no symbolic links.
|
||||
# CAUTION: This is dangerous! For example, if top == '/', it
|
||||
# could delete all your disk files.
|
||||
# sc: Nicked this from somewhere, added the if statement to try
|
||||
# make it a bit safer
|
||||
if top in ('build','dist',distdir) and os.path.basename(os.getcwd()) == 'windows':
|
||||
#print "removing directory '"+top+"' ..."
|
||||
for root, dirs, files in os.walk(top, topdown=False):
|
||||
for name in files:
|
||||
os.remove(os.path.join(root, name))
|
||||
for name in dirs:
|
||||
os.rmdir(os.path.join(root, name))
|
||||
os.rmdir(top)
|
||||
|
||||
# remove build and dist dirs if they exist
|
||||
def copy_tree(source,destination):
|
||||
source = source.replace('\\', '\\\\')
|
||||
destination = destination.replace('\\', '\\\\')
|
||||
print "*** Copying " + source + " to " + destination + " ***"
|
||||
shutil.copytree( source, destination )
|
||||
|
||||
def copy_file(source,destination):
|
||||
source = source.replace('\\', '\\\\')
|
||||
destination = destination.replace('\\', '\\\\')
|
||||
print "*** Copying " + source + " to " + destination + " ***"
|
||||
shutil.copy( source, destination )
|
||||
|
||||
|
||||
fpdbver = '0.20.906'
|
||||
|
||||
distdir = r'fpdb-' + fpdbver
|
||||
rootdir = r'../../' #cwd is normally /packaging/windows
|
||||
pydir = rootdir+'pyfpdb/'
|
||||
gfxdir = rootdir+'gfx/'
|
||||
sys.path.append( pydir ) # allows fpdb modules to be found by options/includes below
|
||||
|
||||
print "\n" + r"Output will be created in "+distdir
|
||||
|
||||
print "*** Cleaning working folders ***"
|
||||
test_and_remove('dist')
|
||||
test_and_remove('build')
|
||||
test_and_remove('pyfpdb')
|
||||
test_and_remove(distdir)
|
||||
|
||||
test_and_remove(dist_dirname)
|
||||
print "*** Building now in dist folder ***"
|
||||
|
||||
origIsSystemDLL = py2exe.build_exe.isSystemDLL
|
||||
py2exe.build_exe.isSystemDLL = isSystemDLL
|
||||
|
||||
setup(
|
||||
name = 'fpdb',
|
||||
description = 'Free Poker DataBase',
|
||||
version = '0.20.903',
|
||||
version = fpdbver,
|
||||
|
||||
windows = [ {'script': 'fpdb.pyw', "icon_resources": [(1, "../gfx/fpdb_large_icon.ico")]},
|
||||
{'script': 'HUD_main.pyw', },
|
||||
{'script': 'Configuration.py', }
|
||||
windows = [ {'script': pydir+'fpdb.pyw', "icon_resources": [(1, gfxdir+"fpdb_large_icon.ico")]},
|
||||
{'script': pydir+'HUD_main.pyw', },
|
||||
{'script': pydir+'Configuration.py', }
|
||||
],
|
||||
|
||||
options = {'py2exe': {
|
||||
|
@ -158,74 +152,56 @@ setup(
|
|||
,'PartyPokerToFpdb', 'PokerStarsToFpdb'
|
||||
,'UltimateBetToFpdb', 'Win2dayToFpdb'
|
||||
],
|
||||
'excludes' : ['_tkagg', '_agg2', 'cocoaagg', 'fltkagg'], # surely we need this? '_gtkagg'
|
||||
'excludes' : ['_tkagg', '_agg2', 'cocoaagg', 'fltkagg'],
|
||||
'dll_excludes': ['libglade-2.0-0.dll', 'libgdk-win32-2.0-0.dll', 'libgobject-2.0-0.dll'
|
||||
, 'msvcr90.dll', 'MSVCP90.dll', 'MSVCR90.dll','msvcr90.dll'], # these are vis c / c++ runtimes, and must not be redistributed
|
||||
}
|
||||
},
|
||||
|
||||
# files in 2nd value in tuple are moved to dir named in 1st value
|
||||
#data_files updated for new locations of licences + readme nolonger exists
|
||||
data_files = [('', ['HUD_config.xml.example', 'Cards01.png', 'logging.conf', '../agpl-3.0.txt', '../fdl-1.2.txt', '../gpl-3.0.txt', '../gpl-2.0.txt', '../mit.txt', '../readme.txt'])
|
||||
,(dist_dir, [r'..\run_fpdb.bat'])
|
||||
,( dist_dir + r'\gfx', glob.glob(r'..\gfx\*.*') )
|
||||
# line below has problem with fonts subdir ('not a regular file')
|
||||
#,(r'matplotlibdata', glob.glob(r'c:\python25\Lib\site-packages\matplotlib\mpl-data\*'))
|
||||
# this code will not walk a tree
|
||||
# Note: cwd for 1st value is packaging/windows/dist (this is confusing BTW)
|
||||
# Note: only include files here which are to be put into the package pyfpdb folder or subfolders
|
||||
|
||||
data_files = [('', glob.glob(rootdir+'*.txt'))
|
||||
,('', [pydir+'HUD_config.xml.example',pydir+'Cards01.png', pydir+'logging.conf'])
|
||||
] + matplotlib.get_py2exe_datafiles()
|
||||
)
|
||||
|
||||
# rename completed output package as pyfpdb
|
||||
os.rename('dist', 'pyfpdb')
|
||||
# ,(distdir, [rootdir+'run_fpdb.bat'])
|
||||
# ,(distdir+r'\gfx', glob.glob(gfxdir+'*.*'))
|
||||
# ] +
|
||||
print "*** py2exe build phase complete ***"
|
||||
|
||||
# pull pytz zoneinfo into pyfpdb package folder
|
||||
src_dir = r'c:\python26\Lib\site-packages\pytz\zoneinfo'
|
||||
src_dir = src_dir.replace('\\', '\\\\')
|
||||
dest_dir = os.path.join(r'pyfpdb', 'zoneinfo')
|
||||
shutil.copytree( src_dir, dest_dir )
|
||||
# copy zone info and fpdb translation folders
|
||||
copy_tree (r'c:\python26\Lib\site-packages\pytz\zoneinfo', os.path.join(r'dist', 'zoneinfo'))
|
||||
copy_tree (pydir+r'locale', os.path.join(r'dist', 'locale'))
|
||||
|
||||
# shunt pyfpdb package over to the distribution folder
|
||||
dest = os.path.join(dist_dirname, 'pyfpdb')
|
||||
# print "try renaming pyfpdb to", dest
|
||||
dest = dest.replace('\\', '\\\\')
|
||||
# print "dest is now", dest
|
||||
os.rename( 'pyfpdb', dest )
|
||||
# create distribution folder and populate with gfx + bat
|
||||
copy_tree (gfxdir, os.path.join(distdir, 'gfx'))
|
||||
copy_file (rootdir+'run_fpdb.bat', distdir)
|
||||
|
||||
# prompt for gtk location
|
||||
print "*** Renaming dist folder as distribution pyfpdb folder ***"
|
||||
dest = os.path.join(distdir, 'pyfpdb')
|
||||
os.rename( 'dist', dest )
|
||||
|
||||
print "*** copying GTK runtime ***"
|
||||
gtk_dir = ""
|
||||
while not os.path.exists(gtk_dir):
|
||||
print "Enter directory name for GTK (e.g. c:\code\gtk_2.14.7-20090119)\n: ", # the comma means no newline
|
||||
print "Enter directory name for GTK (e.g. c:/gtk) : ", # the comma means no newline
|
||||
gtk_dir = sys.stdin.readline().rstrip()
|
||||
|
||||
print "\ncopying files and dirs from ", gtk_dir, "to", dest.replace('\\\\', '\\'), "..."
|
||||
src = os.path.join(gtk_dir, 'bin', 'libgdk-win32-2.0-0.dll')
|
||||
src = src.replace('\\', '\\\\')
|
||||
shutil.copy( src, dest )
|
||||
print "*** copying GTK runtime ***"
|
||||
dest = os.path.join(distdir, 'pyfpdb')
|
||||
copy_file(os.path.join(gtk_dir, 'bin', 'libgdk-win32-2.0-0.dll'), dest )
|
||||
copy_file(os.path.join(gtk_dir, 'bin', 'libgobject-2.0-0.dll'), dest)
|
||||
copy_tree(os.path.join(gtk_dir, 'etc'), os.path.join(dest, 'etc'))
|
||||
copy_tree(os.path.join(gtk_dir, 'lib'), os.path.join(dest, 'lib'))
|
||||
copy_tree(os.path.join(gtk_dir, 'share'), os.path.join(dest, 'share'))
|
||||
|
||||
src = os.path.join(gtk_dir, 'bin', 'libgobject-2.0-0.dll')
|
||||
src = src.replace('\\', '\\\\')
|
||||
shutil.copy( src, dest )
|
||||
|
||||
src_dir = os.path.join(gtk_dir, 'etc')
|
||||
src_dir = src_dir.replace('\\', '\\\\')
|
||||
dest_dir = os.path.join(dest, 'etc')
|
||||
dest_dir = dest_dir.replace('\\', '\\\\')
|
||||
shutil.copytree( src_dir, dest_dir )
|
||||
|
||||
src_dir = os.path.join(gtk_dir, 'lib')
|
||||
src_dir = src_dir.replace('\\', '\\\\')
|
||||
dest_dir = os.path.join(dest, 'lib')
|
||||
dest_dir = dest_dir.replace('\\', '\\\\')
|
||||
shutil.copytree( src_dir, dest_dir )
|
||||
|
||||
src_dir = os.path.join(gtk_dir, 'share')
|
||||
src_dir = src_dir.replace('\\', '\\\\')
|
||||
dest_dir = os.path.join(dest, 'share')
|
||||
dest_dir = dest_dir.replace('\\', '\\\\')
|
||||
shutil.copytree( src_dir, dest_dir )
|
||||
|
||||
print "\nIf py2exe was successful you should now have a new dir"
|
||||
print dist_dirname+" in your pyfpdb dir"
|
||||
print "*** All done! ***"
|
||||
test_and_remove('build')
|
||||
print distdir+" is in the pyfpdb dir"
|
||||
print """
|
||||
The following dirs can probably removed to make the final package smaller:
|
||||
|
||||
|
@ -243,5 +219,3 @@ pyfpdb/share/themes/Default
|
|||
|
||||
Use 7-zip to zip up the distribution and create a self extracting archive and that's it!
|
||||
"""
|
||||
|
||||
|
|
@ -450,7 +450,6 @@ def sss():
|
|||
self.settings['os']="windows"
|
||||
|
||||
self.settings.update(self.config.get_db_parameters())
|
||||
self.settings.update(self.config.get_tv_parameters())
|
||||
self.settings.update(self.config.get_import_parameters())
|
||||
self.settings.update(self.config.get_default_paths())
|
||||
|
||||
|
|
|
@ -44,9 +44,8 @@ class Betfair(HandHistoryConverter):
|
|||
siteId = 7 # Needs to match id entry in Sites database
|
||||
|
||||
# Static regexes
|
||||
#re_SplitHands = re.compile(r'\n\n+') # Betfair 1.0 version
|
||||
re_GameInfo = re.compile("^(?P<LIMIT>NL|PL|) (?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAME>(Texas Hold\'em|Omaha Hi|Razz))", re.MULTILINE)
|
||||
re_SplitHands = re.compile(r'End of hand .{2}-\d{7,9}-\d+ \*\*\*\*\*\n')
|
||||
re_SplitHands = re.compile(r'\n\n+')
|
||||
re_HandInfo = re.compile("\*\*\*\*\* Betfair Poker Hand History for Game (?P<HID>[0-9]+) \*\*\*\*\*\n(?P<LIMIT>NL|PL|) (?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAMETYPE>(Texas Hold\'em|Omaha Hi|Razz)) - (?P<DATETIME>[a-zA-Z]+, [a-zA-Z]+ \d+, \d\d:\d\d:\d\d GMT \d\d\d\d)\nTable (?P<TABLE>[ a-zA-Z0-9]+) \d-max \(Real Money\)\nSeat (?P<BUTTON>[0-9]+)", re.MULTILINE)
|
||||
re_Button = re.compile(ur"^Seat (?P<BUTTON>\d+) is the button", re.MULTILINE)
|
||||
re_PlayerInfo = re.compile("Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*)\s\(\s(\$(?P<CASH>[.0-9]+)) \)")
|
||||
|
|
|
@ -110,7 +110,7 @@ def get_config(file_name, fallback = True):
|
|||
example_path = '/usr/share/python-fpdb/' + file_name + '.example'
|
||||
try:
|
||||
shutil.copyfile(example_path, config_path)
|
||||
msg = 'Configuration file created: %s\n' % config_path
|
||||
msg = _("Config file has been created at %s.\n") % config_path
|
||||
logging.info(msg)
|
||||
return (config_path,False)
|
||||
except IOError:
|
||||
|
@ -256,6 +256,20 @@ class Layout:
|
|||
|
||||
return temp + "\n"
|
||||
|
||||
class Email:
|
||||
def __init__(self, node):
|
||||
self.node = node
|
||||
self.host= node.getAttribute("host")
|
||||
self.username = node.getAttribute("username")
|
||||
self.password = node.getAttribute("password")
|
||||
self.useSsl = node.getAttribute("useSsl")
|
||||
self.folder = node.getAttribute("folder")
|
||||
self.fetchType = node.getAttribute("fetchType")
|
||||
|
||||
def __str__(self):
|
||||
return " fetchType=%s\n host = %s\n username = %s\n password = %s\n useSsl = %s\n folder = %s\n" \
|
||||
% (self.fetchType, self.host, self.username, self.password, self.useSsl, self.folder)
|
||||
|
||||
class Site:
|
||||
def __init__(self, node):
|
||||
def normalizePath(path):
|
||||
|
@ -284,6 +298,7 @@ class Site:
|
|||
self.xshift = node.getAttribute("xshift")
|
||||
self.yshift = node.getAttribute("yshift")
|
||||
self.layout = {}
|
||||
self.emails = {}
|
||||
|
||||
print _("Loading site"), self.site_name
|
||||
|
||||
|
@ -291,6 +306,10 @@ class Site:
|
|||
lo = Layout(layout_node)
|
||||
self.layout[lo.max] = lo
|
||||
|
||||
for email_node in node.getElementsByTagName('email'):
|
||||
email = Email(email_node)
|
||||
self.emails[email.fetchType] = email
|
||||
|
||||
# Site defaults
|
||||
self.xpad = 1 if self.xpad == "" else int(self.xpad)
|
||||
self.ypad = 0 if self.ypad == "" else int(self.ypad)
|
||||
|
@ -467,21 +486,6 @@ class Import:
|
|||
return " interval = %s\n callFpdbHud = %s\n hhArchiveBase = %s\n saveActions = %s\n fastStoreHudCache = %s\n" \
|
||||
% (self.interval, self.callFpdbHud, self.hhArchiveBase, self.saveActions, self.fastStoreHudCache)
|
||||
|
||||
class Email:
|
||||
def __init__(self, node):
|
||||
self.node = node
|
||||
self.host= node.getAttribute("host")
|
||||
self.username = node.getAttribute("username")
|
||||
self.password = node.getAttribute("password")
|
||||
self.useSsl = node.getAttribute("useSsl")
|
||||
self.folder = node.getAttribute("folder")
|
||||
self.siteName = node.getAttribute("siteName")
|
||||
self.fetchType = node.getAttribute("fetchType")
|
||||
|
||||
def __str__(self):
|
||||
return " siteName=%s\n fetchType=%s\n host = %s\n username = %s\n password = %s\n useSsl = %s\n folder = %s\n" \
|
||||
% (self.siteName, self.fetchType, self.host, self.username, self.password, self.useSsl, self.folder)
|
||||
|
||||
class HudUI:
|
||||
def __init__(self, node):
|
||||
self.node = node
|
||||
|
@ -504,16 +508,6 @@ class HudUI:
|
|||
return " label = %s\n" % self.label
|
||||
|
||||
|
||||
class Tv:
|
||||
def __init__(self, node):
|
||||
self.combinedStealFold = string_to_bool(node.getAttribute("combinedStealFold"), default=True)
|
||||
self.combined2B3B = string_to_bool(node.getAttribute("combined2B3B"), default=True)
|
||||
self.combinedPostflop = string_to_bool(node.getAttribute("combinedPostflop"), default=True)
|
||||
|
||||
def __str__(self):
|
||||
return (" combinedStealFold = %s\n combined2B3B = %s\n combinedPostflop = %s\n" %
|
||||
(self.combinedStealFold, self.combined2B3B, self.combinedPostflop) )
|
||||
|
||||
class General(dict):
|
||||
def __init__(self):
|
||||
super(General, self).__init__()
|
||||
|
@ -526,6 +520,20 @@ class General(dict):
|
|||
log.debug(_("config.general: adding %s = %s") % (name,value))
|
||||
self[name] = value
|
||||
|
||||
try:
|
||||
self["version"]=int(self["version"])
|
||||
except KeyError:
|
||||
self["version"]=0
|
||||
self["ui_language"]="system"
|
||||
self["config_difficulty"]="expert"
|
||||
|
||||
def get_defaults(self):
|
||||
self["version"]=0
|
||||
self["ui_language"]="system"
|
||||
self["config_difficulty"]="expert"
|
||||
self["config_wrap_len"]="-1"
|
||||
self["day_start"]="5"
|
||||
|
||||
def __str__(self):
|
||||
s = ""
|
||||
for k in self:
|
||||
|
@ -600,6 +608,58 @@ class GUICashStats(list):
|
|||
# s = s + " %s = %s\n" % (k, self[k])
|
||||
# return(s)
|
||||
|
||||
class RawHands:
|
||||
def __init__(self, node=None):
|
||||
if node==None:
|
||||
self.save="error"
|
||||
self.compression="none"
|
||||
print _("missing config section raw_hands")
|
||||
else:
|
||||
save=node.getAttribute("save")
|
||||
if save in ("none", "error", "all"):
|
||||
self.save=save
|
||||
else:
|
||||
print _("Invalid config value for raw_hands.save, defaulting to \"error\"")
|
||||
self.save="error"
|
||||
|
||||
compression=node.getAttribute("compression")
|
||||
if save in ("none", "gzip", "bzip2"):
|
||||
self.compression=compression
|
||||
else:
|
||||
print _("Invalid config value for raw_hands.compression, defaulting to \"none\"")
|
||||
self.compression="none"
|
||||
#end def __init__
|
||||
|
||||
def __str__(self):
|
||||
return " save= %s, compression= %s\n" % (self.save, self.compression)
|
||||
#end class RawHands
|
||||
|
||||
class RawTourneys:
|
||||
def __init__(self, node=None):
|
||||
if node==None:
|
||||
self.save="error"
|
||||
self.compression="none"
|
||||
print _("missing config section raw_tourneys")
|
||||
else:
|
||||
save=node.getAttribute("save")
|
||||
if save in ("none", "error", "all"):
|
||||
self.save=save
|
||||
else:
|
||||
print _("Invalid config value for raw_tourneys.save, defaulting to \"error\"")
|
||||
self.save="error"
|
||||
|
||||
compression=node.getAttribute("compression")
|
||||
if save in ("none", "gzip", "bzip2"):
|
||||
self.compression=compression
|
||||
else:
|
||||
print _("Invalid config value for raw_tourneys.compression, defaulting to \"none\"")
|
||||
self.compression="none"
|
||||
#end def __init__
|
||||
|
||||
def __str__(self):
|
||||
return " save= %s, compression= %s\n" % (self.save, self.compression)
|
||||
#end class RawTourneys
|
||||
|
||||
class Config:
|
||||
def __init__(self, file = None, dbname = ''):
|
||||
# "file" is a path to an xml file with the fpdb/HUD configuration
|
||||
|
@ -653,11 +713,12 @@ class Config:
|
|||
self.hhcs = {}
|
||||
self.popup_windows = {}
|
||||
self.db_selected = None # database the user would like to use
|
||||
self.tv = None
|
||||
self.general = General()
|
||||
self.emails = {}
|
||||
self.gui_cash_stats = GUICashStats()
|
||||
|
||||
if doc.getElementsByTagName("general") == []:
|
||||
self.general.get_defaults()
|
||||
for gen_node in doc.getElementsByTagName("general"):
|
||||
self.general.add_elements(node=gen_node) # add/overwrite elements in self.general
|
||||
|
||||
|
@ -716,18 +777,10 @@ class Config:
|
|||
imp = Import(node = imp_node)
|
||||
self.imp = imp
|
||||
|
||||
for email_node in doc.getElementsByTagName("email"):
|
||||
email = Email(node = email_node)
|
||||
if email.siteName!="": #FIXME: Why on earth is this needed?
|
||||
self.emails[email.siteName+"_"+email.fetchType]=email
|
||||
|
||||
for hui_node in doc.getElementsByTagName('hud_ui'):
|
||||
hui = HudUI(node = hui_node)
|
||||
self.ui = hui
|
||||
|
||||
for tv_node in doc.getElementsByTagName("tv"):
|
||||
self.tv = Tv(node = tv_node)
|
||||
|
||||
db = self.get_db_parameters()
|
||||
if db['db-password'] == 'YOUR MYSQL PASSWORD':
|
||||
df_file = self.find_default_conf()
|
||||
|
@ -740,7 +793,18 @@ class Config:
|
|||
db_pass = df_parms['db-password'])
|
||||
self.save(file=os.path.join(self.default_config_path, "HUD_config.xml"))
|
||||
|
||||
if doc.getElementsByTagName("raw_hands") == []:
|
||||
self.raw_hands = RawHands()
|
||||
for raw_hands_node in doc.getElementsByTagName('raw_hands'):
|
||||
self.raw_hands = RawHands(raw_hands_node)
|
||||
|
||||
if doc.getElementsByTagName("raw_tourneys") == []:
|
||||
self.raw_tourneys = RawTourneys()
|
||||
for raw_tourneys_node in doc.getElementsByTagName('raw_tourneys'):
|
||||
self.raw_tourneys = RawTourneys(raw_tourneys_node)
|
||||
|
||||
print ""
|
||||
#end def __init__
|
||||
|
||||
def set_hhArchiveBase(self, path):
|
||||
self.imp.node.setAttribute("hhArchiveBase", path)
|
||||
|
@ -767,9 +831,12 @@ class Config:
|
|||
return site_node
|
||||
|
||||
def getEmailNode(self, siteName, fetchType):
|
||||
for emailNode in self.doc.getElementsByTagName("email"):
|
||||
if emailNode.getAttribute("siteName") == siteName and emailNode.getAttribute("fetchType") == fetchType:
|
||||
siteNode = self.get_site_node(siteName)
|
||||
for emailNode in siteNode.getElementsByTagName("email"):
|
||||
if emailNode.getAttribute("fetchType") == fetchType:
|
||||
print "found emailNode"
|
||||
return emailNode
|
||||
break
|
||||
#end def getEmailNode
|
||||
|
||||
def getGameNode(self,gameName):
|
||||
|
@ -1010,15 +1077,6 @@ class Config:
|
|||
return site_name
|
||||
return None
|
||||
|
||||
def get_tv_parameters(self):
|
||||
if self.tv is not None:
|
||||
return {
|
||||
'combinedStealFold': self.tv.combinedStealFold,
|
||||
'combined2B3B': self.tv.combined2B3B,
|
||||
'combinedPostflop': self.tv.combinedPostflop
|
||||
}
|
||||
return {}
|
||||
|
||||
# Allow to change the menu appearance
|
||||
def get_hud_ui_parameters(self):
|
||||
hui = {}
|
||||
|
@ -1311,15 +1369,10 @@ if __name__== "__main__":
|
|||
print c.imp
|
||||
print "----------- END IMPORT -----------"
|
||||
|
||||
print "\n----------- TABLE VIEW -----------"
|
||||
# print c.tv
|
||||
print "----------- END TABLE VIEW -----------"
|
||||
|
||||
c.edit_layout("PokerStars", 6, locations=( (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6) ))
|
||||
c.save(file="testout.xml")
|
||||
|
||||
print "db = ", c.get_db_parameters()
|
||||
# print "tv = ", c.get_tv_parameters()
|
||||
# print "imp = ", c.get_import_parameters()
|
||||
print "paths = ", c.get_default_paths("PokerStars")
|
||||
print "colors = ", c.get_default_colors("PokerStars")
|
||||
|
|
|
@ -321,7 +321,12 @@ class Database:
|
|||
else:
|
||||
for row in rows:
|
||||
for columnNumber in range(len(columnNames)):
|
||||
result+=(" "+columnNames[columnNumber][0]+"="+str(row[columnNumber])+"\n")
|
||||
if columnNames[columnNumber][0]=="importTime":
|
||||
result+=(" "+columnNames[columnNumber][0]+"=ignore\n")
|
||||
elif columnNames[columnNumber][0]=="styleKey":
|
||||
result+=(" "+columnNames[columnNumber][0]+"=ignore\n")
|
||||
else:
|
||||
result+=(" "+columnNames[columnNumber][0]+"="+str(row[columnNumber])+"\n")
|
||||
result+="\n"
|
||||
result+="\n"
|
||||
return result
|
||||
|
@ -2062,8 +2067,9 @@ class Database:
|
|||
#print "info that we use to get TT by detail:", hand.siteId, hand.buyinCurrency, hand.buyin, hand.fee, hand.gametype['category'], hand.gametype['limitType'], hand.isKO, hand.isRebuy, hand.isAddOn, hand.speed, hand.isShootout, hand.isMatrix
|
||||
#print "the query:",self.sql.query['getTourneyTypeId'].replace('%s', self.sql.query['placeholder'])
|
||||
cursor.execute (self.sql.query['getTourneyTypeId'].replace('%s', self.sql.query['placeholder']),
|
||||
(hand.siteId, hand.buyinCurrency, hand.buyin, hand.fee, hand.gametype['category'], hand.gametype['limitType'], hand.isKO,
|
||||
hand.isRebuy, hand.isAddOn, hand.speed, hand.isShootout, hand.isMatrix) #TODO: add koamount
|
||||
(hand.siteId, hand.buyinCurrency, hand.buyin, hand.fee, hand.gametype['category'],
|
||||
hand.gametype['limitType'], hand.maxseats, hand.isKO,
|
||||
hand.isRebuy, hand.isAddOn, hand.speed, hand.isShootout, hand.isMatrix)
|
||||
)
|
||||
result=cursor.fetchone()
|
||||
#print "result of fetching TT by details:",result
|
||||
|
@ -2072,7 +2078,8 @@ class Database:
|
|||
tourneyTypeId = result[0]
|
||||
except TypeError: #this means we need to create a new entry
|
||||
cursor.execute (self.sql.query['insertTourneyType'].replace('%s', self.sql.query['placeholder']),
|
||||
(hand.siteId, hand.buyinCurrency, hand.buyin, hand.fee, hand.gametype['category'], hand.gametype['limitType'],
|
||||
(hand.siteId, hand.buyinCurrency, hand.buyin, hand.fee, hand.gametype['category'],
|
||||
hand.gametype['limitType'], hand.maxseats,
|
||||
hand.buyInChips, hand.isKO, hand.koBounty, hand.isRebuy,
|
||||
hand.isAddOn, hand.speed, hand.isShootout, hand.isMatrix, hand.added, hand.addedCurrency)
|
||||
)
|
||||
|
|
|
@ -208,8 +208,7 @@ class Fulltilt(HandHistoryConverter):
|
|||
if m is None:
|
||||
logging.info("Didn't match re_HandInfo")
|
||||
logging.info(hand.handText)
|
||||
# Should this throw an exception? - CG
|
||||
return None
|
||||
raise FpdbParseError("No match in readHandInfo.")
|
||||
hand.handid = m.group('HID')
|
||||
hand.tablename = m.group('TABLE')
|
||||
|
||||
|
@ -260,8 +259,8 @@ class Fulltilt(HandHistoryConverter):
|
|||
hand.isRebuy = True
|
||||
if special == "KO":
|
||||
hand.isKO = True
|
||||
if special == "Head's Up":
|
||||
hand.maxSeats = 2
|
||||
if special == "Head's Up" or special == "Heads Up":
|
||||
hand.maxseats = 2
|
||||
if re.search("Matrix", special):
|
||||
hand.isMatrix = True
|
||||
if special == "Shootout":
|
||||
|
|
|
@ -334,7 +334,6 @@ if __name__== "__main__":
|
|||
else: settings['os'] = 'linuxmac'
|
||||
|
||||
settings.update(config.get_db_parameters('fpdb'))
|
||||
settings.update(config.get_tv_parameters())
|
||||
settings.update(config.get_import_parameters())
|
||||
settings.update(config.get_default_paths())
|
||||
|
||||
|
|
|
@ -294,7 +294,7 @@ class GuiBulkImport():
|
|||
self.cb_drophudcache.show()
|
||||
|
||||
# button - Import
|
||||
self.load_button = gtk.Button(_('Import')) # todo: rename variables to import too
|
||||
self.load_button = gtk.Button(_('_Bulk Import')) # todo: rename variables to import too
|
||||
self.load_button.connect('clicked', self.load_clicked,
|
||||
_('Import clicked'))
|
||||
self.table.attach(self.load_button, 2, 3, 4, 5, xpadding=0, ypadding=0,
|
||||
|
@ -378,7 +378,6 @@ def main(argv=None):
|
|||
else: settings['os'] = 'linuxmac'
|
||||
|
||||
settings.update(config.get_db_parameters())
|
||||
settings.update(config.get_tv_parameters())
|
||||
settings.update(config.get_import_parameters())
|
||||
settings.update(config.get_default_paths())
|
||||
|
||||
|
|
|
@ -72,19 +72,14 @@ class GuiImapFetcher (threading.Thread):
|
|||
|
||||
siteName=columns[0].get_text()
|
||||
fetchType=columns[1].get_text()
|
||||
code=siteName+"_"+fetchType
|
||||
|
||||
for email in self.config.emails:
|
||||
toSave=self.config.emails[email]
|
||||
break
|
||||
toSave.siteName=siteName
|
||||
toSave.fetchType=fetchType
|
||||
toSave=self.config.supported_sites[siteName].emails[fetchType]
|
||||
|
||||
toSave.host=columns[2].get_text()
|
||||
toSave.username=columns[3].get_text()
|
||||
|
||||
if columns[4].get_text()=="***":
|
||||
toSave.password=self.passwords[code]
|
||||
toSave.password=self.passwords[siteName+fetchType]
|
||||
else:
|
||||
toSave.password=columns[4].get_text()
|
||||
|
||||
|
@ -101,16 +96,17 @@ class GuiImapFetcher (threading.Thread):
|
|||
|
||||
def importAllClicked(self, widget, data=None):
|
||||
self.statusLabel.set_label(_("Starting import. Please wait.")) #FIXME: why doesnt this one show?
|
||||
for email in self.config.emails:
|
||||
try:
|
||||
result=ImapFetcher.run(self.config.emails[email], self.db)
|
||||
self.statusLabel.set_label(_("Finished import without error."))
|
||||
except IMAP4.error as error:
|
||||
if str(error)=="[AUTHENTICATIONFAILED] Authentication failed.":
|
||||
self.statusLabel.set_label(_("Login to mailserver failed: please check mailserver, username and password"))
|
||||
except gaierror as error:
|
||||
if str(error)=="[Errno -2] Name or service not known":
|
||||
self.statusLabel.set_label(_("Could not connect to mailserver: check mailserver and use SSL settings and internet connectivity"))
|
||||
for siteName in self.config.supported_sites:
|
||||
for fetchType in self.config.supported_sites[siteName].emails:
|
||||
try:
|
||||
result=ImapFetcher.run(self.config.supported_sites[siteName].emails[fetchType], self.db)
|
||||
self.statusLabel.set_label(_("Finished import without error."))
|
||||
except IMAP4.error as error:
|
||||
if str(error)=="[AUTHENTICATIONFAILED] Authentication failed.":
|
||||
self.statusLabel.set_label(_("Login to mailserver failed: please check mailserver, username and password"))
|
||||
except gaierror as error:
|
||||
if str(error)=="[Errno -2] Name or service not known":
|
||||
self.statusLabel.set_label(_("Could not connect to mailserver: check mailserver and use SSL settings and internet connectivity"))
|
||||
#def importAllClicked
|
||||
|
||||
def get_vbox(self):
|
||||
|
@ -128,38 +124,42 @@ class GuiImapFetcher (threading.Thread):
|
|||
self.rowVBox = gtk.VBox()
|
||||
self.mainVBox.add(self.rowVBox)
|
||||
|
||||
for email in self.config.emails:
|
||||
config=self.config.emails[email]
|
||||
box=gtk.HBox(homogeneous=True)
|
||||
for siteName in self.config.supported_sites:
|
||||
for fetchType in self.config.supported_sites[siteName].emails:
|
||||
config=self.config.supported_sites[siteName].emails[fetchType]
|
||||
box=gtk.HBox(homogeneous=True)
|
||||
|
||||
for field in (config.siteName, config.fetchType):
|
||||
label=gtk.Label(field)
|
||||
box.add(label)
|
||||
for field in (siteName, config.fetchType):
|
||||
label=gtk.Label(field)
|
||||
box.add(label)
|
||||
|
||||
for field in (config.host, config.username):
|
||||
entry=gtk.Entry()
|
||||
entry.set_text(field)
|
||||
box.add(entry)
|
||||
|
||||
for field in (config.host, config.username):
|
||||
entry=gtk.Entry()
|
||||
entry.set_text(field)
|
||||
self.passwords[siteName+fetchType]=config.password
|
||||
entry.set_text("***")
|
||||
box.add(entry)
|
||||
|
||||
entry=gtk.Entry()
|
||||
self.passwords[email]=config.password
|
||||
entry.set_text("***")
|
||||
box.add(entry)
|
||||
entry=gtk.Entry()
|
||||
entry.set_text(config.folder)
|
||||
box.add(entry)
|
||||
|
||||
entry=gtk.Entry()
|
||||
entry.set_text(config.folder)
|
||||
box.add(entry)
|
||||
sslBox = gtk.combo_box_new_text()
|
||||
sslBox.append_text(_("Yes"))
|
||||
sslBox.append_text(_("No"))
|
||||
if config.useSsl:
|
||||
sslBox.set_active(0)
|
||||
else:
|
||||
sslBox.set_active(1)
|
||||
box.add(sslBox)
|
||||
|
||||
sslBox = gtk.combo_box_new_text()
|
||||
sslBox.append_text(_("Yes"))
|
||||
sslBox.append_text(_("No"))
|
||||
sslBox.set_active(0)
|
||||
box.add(sslBox)
|
||||
#TODO: "run just this one" button
|
||||
|
||||
#TODO: "run just this one" button
|
||||
|
||||
self.rowVBox.pack_start(box, expand=False)
|
||||
#print
|
||||
self.rowVBox.pack_start(box, expand=False)
|
||||
#print
|
||||
|
||||
self.mainVBox.show_all()
|
||||
#end def displayConfig
|
||||
|
|
|
@ -53,7 +53,6 @@ class GuiPositionalStats (threading.Thread):
|
|||
|
||||
settings = {}
|
||||
settings.update(self.conf.get_db_parameters())
|
||||
settings.update(self.conf.get_tv_parameters())
|
||||
settings.update(self.conf.get_import_parameters())
|
||||
settings.update(self.conf.get_default_paths())
|
||||
|
||||
|
|
|
@ -69,7 +69,6 @@ class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats):
|
|||
|
||||
settings = {}
|
||||
settings.update(self.conf.get_db_parameters())
|
||||
settings.update(self.conf.get_tv_parameters())
|
||||
settings.update(self.conf.get_import_parameters())
|
||||
settings.update(self.conf.get_default_paths())
|
||||
|
||||
|
|
|
@ -82,7 +82,6 @@ class GuiSessionViewer (threading.Thread):
|
|||
|
||||
settings = {}
|
||||
settings.update(self.conf.get_db_parameters())
|
||||
settings.update(self.conf.get_tv_parameters())
|
||||
settings.update(self.conf.get_import_parameters())
|
||||
settings.update(self.conf.get_default_paths())
|
||||
|
||||
|
|
|
@ -5,8 +5,11 @@
|
|||
<!-- config_wrap_len is preferred max line length in this file, -1 means no max
|
||||
day_start is time that logical day starts, e.g. 5 means that any play
|
||||
between 00:00 and 04:59:59 counts as being on the previous day -->
|
||||
<general config_wrap_len="-1"
|
||||
<general version="1"
|
||||
config_wrap_len="-1"
|
||||
day_start="5"
|
||||
ui_language="system"
|
||||
config_difficulty="expert"
|
||||
/>
|
||||
|
||||
<import callFpdbHud = "True" interval = "10" fastStoreHudCache="False" hhArchiveBase="~/.fpdb/HandHistories/" saveActions="True"></import>
|
||||
|
@ -156,6 +159,7 @@ Left-Drag to Move"
|
|||
xshift="0"
|
||||
yshift="0"
|
||||
supported_games="holdem,razz,omahahi,omahahilo,studhi,studhilo">
|
||||
<email fetchType="request-summary" host="YOUR_EMAIL_SERVER" username="YOUR_EMAIL_USERNAME" password="YOUR_EMAIL_PASSWORD" useSsl="True" folder="INBOX"/>
|
||||
<layout max="8" width="792" height="546" fav_seat="0">
|
||||
<location seat="1" x="684" y="61"> </location>
|
||||
<location seat="2" x="689" y="239"> </location>
|
||||
|
@ -439,16 +443,7 @@ Left-Drag to Move"
|
|||
</layout>
|
||||
</site>
|
||||
|
||||
|
||||
<site enabled="False"
|
||||
site_name="Betfair"
|
||||
table_finder="Betfair Poker.exe"
|
||||
screen_name="YOUR SCREEN NAME HERE"
|
||||
site_path="C:/Program Files/Betfair/Betfair Poker/"
|
||||
HH_path="C:/Program Files/Betfair/Betfair Poker/HandHistory/YOUR SCREEN NAME HERE/"
|
||||
decoder="everleaf_decode_table"
|
||||
converter="BetfairToFpdb"
|
||||
supported_games="holdem">
|
||||
<site HH_path="C:/Program Files/Carbon Poker/HandHistory/YOUR SCREEN NAME HERE/" converter="CarbonToFpdb" decoder="everleaf_decode_table" enabled="True" screen_name="YOUR SCREEN NAME HERE" site_name="Carbon" site_path="C:/Program Files/Carbin/" supported_games="holdem" table_finder="Carbon Poker.exe">
|
||||
<layout fav_seat="0" height="547" max="8" width="794">
|
||||
<location seat="1" x="640" y="64"> </location>
|
||||
<location seat="2" x="650" y="230"> </location>
|
||||
|
@ -469,7 +464,7 @@ Left-Drag to Move"
|
|||
</layout>
|
||||
<layout fav_seat="0" height="547" max="2" width="794">
|
||||
<location seat="1" x="651" y="288"> </location>
|
||||
<location seat="2" x="10" y="288"> </location>
|
||||
<location seat="2" x="10" y="288"> </location>
|
||||
</layout>
|
||||
<layout fav_seat="0" height="547" max="9" width="794">
|
||||
<location seat="1" x="634" y="38"> </location>
|
||||
|
@ -484,8 +479,7 @@ Left-Drag to Move"
|
|||
</layout>
|
||||
</site>
|
||||
|
||||
|
||||
<site HH_path="C:/Program Files/Carbon Poker/HandHistory/YOUR SCREEN NAME HERE/" converter="CarbonToFpdb" decoder="everleaf_decode_table" enabled="True" screen_name="YOUR SCREEN NAME HERE" site_name="Carbon" site_path="C:/Program Files/Carbin/" supported_games="holdem" table_finder="Carbon Poker.exe">
|
||||
<site HH_path="C:/Program Files/OnGame Sking/HandHistory/YOUR SCREEN NAME HERE/" converter="OnGameToFpdb" decoder="everleaf_decode_table" enabled="False" screen_name="YOUR SCREEN NAME HERE" site_name="OnGame" site_path="C:/Program Files/OnGame/" supported_games="holdem" table_finder="OnGame.exe">
|
||||
<layout fav_seat="0" height="547" max="8" width="794">
|
||||
<location seat="1" x="640" y="64"> </location>
|
||||
<location seat="2" x="650" y="230"> </location>
|
||||
|
@ -673,45 +667,14 @@ Left-Drag to Move"
|
|||
<hhc site="OnGame" converter="OnGameToFpdb"/>
|
||||
</hhcs>
|
||||
|
||||
<!-- attribute names chosen to be in alphabetic order so that order can be set when retrieved -->
|
||||
<gui_cash_stats>
|
||||
<col col_name="game" col_title="Game" disp_all="True" disp_posn="True" field_format="%s" field_type="str" xalignment="0.0"/>
|
||||
<col col_name="hand" col_title="Hand" disp_all="False" disp_posn="False" field_format="%s" field_type="str" xalignment="0.0"/>
|
||||
<col col_name="plposition" col_title="Posn" disp_all="False" disp_posn="False" field_format="%s" field_type="str" xalignment="1.0"/>
|
||||
<col col_name="pname" col_title="Name" disp_all="False" disp_posn="False" field_format="%s" field_type="str" xalignment="0.0"/>
|
||||
<col col_name="n" col_title="Hds" disp_all="True" disp_posn="True" field_format="%1.0f" field_type="str" xalignment="1.0"/>
|
||||
<col col_name="avgseats" col_title="Seats" disp_all="False" disp_posn="False" field_format="%3.1f" field_type="str" xalignment="1.0"/>
|
||||
<col col_name="vpip" col_title="VPIP" disp_all="True" disp_posn="True" field_format="%3.1f" field_type="str" xalignment="1.0"/>
|
||||
<col col_name="pfr" col_title="PFR" disp_all="True" disp_posn="True" field_format="%3.1f" field_type="str" xalignment="1.0"/>
|
||||
<col col_name="pf3" col_title="PF3" disp_all="True" disp_posn="True" field_format="%3.1f" field_type="str" xalignment="1.0"/>
|
||||
<col col_name="aggfac" col_title="AggFac" disp_all="True" disp_posn="True" field_format="%2.2f" field_type="str" xalignment="1.0"/>
|
||||
<col col_name="aggfrq" col_title="AggFreq" disp_all="True" disp_posn="True" field_format="%3.1f" field_type="str" xalignment="1.0"/>
|
||||
<col col_name="conbet" col_title="ContBet" disp_all="False" disp_posn="True" field_format="%3.1f" field_type="str" xalignment="1.0"/>
|
||||
<col col_name="rfi" col_title="RFI" disp_all="True" disp_posn="True" field_format="%3.1f" field_type="str" xalignment="1.0"/>
|
||||
<col col_name="steals" col_title="Steals" disp_all="True" disp_posn="True" field_format="%3.1f" field_type="str" xalignment="1.0"/>
|
||||
<col col_name="saw_f" col_title="Saw_F" disp_all="True" disp_posn="True" field_format="%3.1f" field_type="str" xalignment="1.0"/>
|
||||
<col col_name="sawsd" col_title="SawSD" disp_all="True" disp_posn="True" field_format="%3.1f" field_type="str" xalignment="1.0"/>
|
||||
<col col_name="wtsdwsf" col_title="WtSDwsF" disp_all="True" disp_posn="True" field_format="%3.1f" field_type="str" xalignment="1.0"/>
|
||||
<col col_name="wmsd" col_title="W$SD" disp_all="True" disp_posn="True" field_format="%3.1f" field_type="str" xalignment="1.0"/>
|
||||
<col col_name="flafq" col_title="FlAFq" disp_all="True" disp_posn="True" field_format="%3.1f" field_type="str" xalignment="1.0"/>
|
||||
<col col_name="tuafq" col_title="TuAFq" disp_all="True" disp_posn="True" field_format="%3.1f" field_type="str" xalignment="1.0"/>
|
||||
<col col_name="rvafq" col_title="RvAFq" disp_all="True" disp_posn="True" field_format="%3.1f" field_type="str" xalignment="1.0"/>
|
||||
<col col_name="pofafq" col_title="PoFAFq" disp_all="False" disp_posn="False" field_format="%3.1f" field_type="str" xalignment="1.0"/>
|
||||
<col col_name="net" col_title="Net($)" disp_all="True" disp_posn="True" field_format="%6.2f" field_type="cash" xalignment="1.0"/>
|
||||
<col col_name="bbper100" col_title="bb/100" disp_all="True" disp_posn="True" field_format="%4.2f" field_type="str" xalignment="1.0"/>
|
||||
<col col_name="rake" col_title="Rake($)" disp_all="True" disp_posn="True" field_format="%6.2f" field_type="cash" xalignment="1.0"/>
|
||||
<col col_name="bb100xr" col_title="bbxr/100" disp_all="True" disp_posn="True" field_format="%4.2f" field_type="str" xalignment="1.0"/>
|
||||
<col col_name="variance" col_title="Variance" disp_all="True" disp_posn="True" field_format="%5.2f" field_type="str" xalignment="1.0"/>
|
||||
</gui_cash_stats>
|
||||
<raw_hands save="none" compression="none"/>
|
||||
|
||||
<raw_tourneys save="none" compression="none"/>
|
||||
|
||||
<supported_databases>
|
||||
<!-- <database db_name="fpdb" db_server="mysql" db_ip="localhost" db_user="fpdb" db_pass="YOUR MYSQL PASSWORD"></database> -->
|
||||
<database db_ip="localhost" db_server="sqlite" db_name="fpdb.db3" db_user="fpdb" db_pass="fpdb"/>
|
||||
</supported_databases>
|
||||
|
||||
<email>
|
||||
<email siteName="PokerStars" fetchType="request-summary" host="YOUR_EMAIL_SERVER" username="YOUR_EMAIL_USERNAME" password="YOUR_EMAIL_PASSWORD" useSsl="True" folder="INBOX"/>
|
||||
</email>
|
||||
</FreePokerToolsConfig>
|
||||
<!-- IMPORTANT: Please note that fpdb stores your email password in clear text.
|
||||
So do not post a config containing a password on the Internet or anywhere else without removing the password! -->
|
||||
|
|
|
@ -58,7 +58,7 @@ class Hand(object):
|
|||
LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'}
|
||||
SYMBOL = {'USD': '$', 'EUR': u'$', 'T$': '', 'play': ''}
|
||||
MS = {'horse' : 'HORSE', '8game' : '8-Game', 'hose' : 'HOSE', 'ha': 'HA'}
|
||||
SITEIDS = {'Fulltilt':1, 'PokerStars':2, 'Everleaf':3, 'Win2day':4, 'OnGame':5, 'UltimateBet':6, 'Betfair':7, 'Absolute':8, 'PartyPoker':9, 'Partouche':10, 'Carbon':11 }
|
||||
SITEIDS = {'Fulltilt':1, 'PokerStars':2, 'Everleaf':3, 'Win2day':4, 'OnGame':5, 'UltimateBet':6, 'Betfair':7, 'Absolute':8, 'PartyPoker':9, 'Partouche':10, 'Carbon':11, 'PKR':12 }
|
||||
|
||||
|
||||
def __init__(self, config, sitename, gametype, handText, builtFrom = "HHC"):
|
||||
|
@ -320,10 +320,8 @@ If a player has None chips he won't be added."""
|
|||
|
||||
def checkPlayerExists(self,player):
|
||||
if player not in [p[1] for p in self.players]:
|
||||
print _("DEBUG: checkPlayerExists %s fail") % player
|
||||
raise FpdbParseError(_("checkPlayerExists: '%s' failed.") % player)
|
||||
|
||||
|
||||
print (_("DEBUG: checkPlayerExists %s fail on hand number %s") % (player, self.handid))
|
||||
raise FpdbParseError(_("checkPlayerExists: '%s fail on hand number %s") % (player, self.handid))
|
||||
|
||||
def setCommunityCards(self, street, cards):
|
||||
log.debug("setCommunityCards %s %s" %(street, cards))
|
||||
|
|
|
@ -70,6 +70,7 @@ class HandHistoryConverter():
|
|||
# "utf_8" is more likely if there are funny characters
|
||||
codepage = "cp1252"
|
||||
|
||||
re_tzOffset = re.compile('^\w+[+-]\d{4}$')
|
||||
|
||||
def __init__(self, config, in_path = '-', out_path = '-', follow=False, index=0, autostart=True, starsArchive=False, ftpArchive=False):
|
||||
"""\
|
||||
|
@ -150,6 +151,7 @@ Otherwise, finish at EOF.
|
|||
log.debug(handText)
|
||||
else:
|
||||
handsList = self.allHandsAsList()
|
||||
log.debug( _("handsList is ") + str(handsList) )
|
||||
log.info("Parsing %d hands" % len(handsList))
|
||||
# Determine if we're dealing with a HH file or a Summary file
|
||||
# quick fix : empty files make the handsList[0] fail ==> If empty file, go on with HH parsing
|
||||
|
@ -568,17 +570,32 @@ or None if we fail to get the info """
|
|||
|
||||
@staticmethod
|
||||
def changeTimezone(time, givenTimezone, wantedTimezone):
|
||||
#print "raw time:",time, "given TZ:", givenTimezone
|
||||
"""Takes a givenTimezone in format AAA or AAA+HHMM where AAA is a standard timezone
|
||||
and +HHMM is an optional offset (+/-) in hours (HH) and minutes (MM)
|
||||
(See OnGameToFpdb.py for example use of the +HHMM part)
|
||||
Tries to convert the time parameter (with no timezone) from the givenTimezone to
|
||||
the wantedTimeZone (currently only allows "UTC")
|
||||
"""
|
||||
log.debug( _("raw time:")+str(time) + _(" given TZ:")+str(givenTimezone) )
|
||||
if wantedTimezone=="UTC":
|
||||
wantedTimezone = pytz.utc
|
||||
else:
|
||||
raise Error #TODO raise appropriate error
|
||||
|
||||
givenTZ = None
|
||||
if HandHistoryConverter.re_tzOffset.match(givenTimezone):
|
||||
offset = int(givenTimezone[-5:])
|
||||
givenTimezone = givenTimezone[0:-5]
|
||||
log.debug( _("changeTimeZone: offset=") + str(offset) )
|
||||
else: offset=0
|
||||
|
||||
if givenTimezone=="ET":
|
||||
givenTimezone = timezone('US/Eastern')
|
||||
givenTZ = timezone('US/Eastern')
|
||||
elif givenTimezone=="CET":
|
||||
givenTimezone = timezone('Europe/Berlin')
|
||||
givenTZ = timezone('Europe/Berlin')
|
||||
#Note: Daylight Saving Time is standardised across the EU so this should be fine
|
||||
elif givenTimezone == 'GMT': # Greenwich Mean Time (same as UTC - no change to time)
|
||||
givenTZ = timezone('GMT')
|
||||
elif givenTimezone == 'HST': # Hawaiian Standard Time
|
||||
pass
|
||||
elif givenTimezone == 'AKT': # Alaska Time
|
||||
|
@ -612,23 +629,27 @@ or None if we fail to get the info """
|
|||
elif givenTimezone == 'JST': # Japan Standard Time
|
||||
pass
|
||||
elif givenTimezone == 'AWST': # Australian Western Standard Time
|
||||
givenTimezone = timezone('Australia/West')
|
||||
givenTZ = timezone('Australia/West')
|
||||
elif givenTimezone == 'ACST': # Australian Central Standard Time
|
||||
givenTimezone = timezone('Australia/Darwin')
|
||||
givenTZ = 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')
|
||||
givenTZ = 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
|
||||
if givenTZ is None:
|
||||
raise Error #TODO raise appropriate error
|
||||
# (or just return time unchanged?)
|
||||
|
||||
localisedTime = givenTZ.localize(time)
|
||||
utcTime = localisedTime.astimezone(wantedTimezone) + datetime.timedelta(seconds=-3600*(offset/100)-60*(offset%100))
|
||||
log.debug( _("utcTime:")+str(utcTime) )
|
||||
return utcTime
|
||||
#end @staticmethod def changeTimezone
|
||||
|
||||
|
|
|
@ -55,7 +55,6 @@ else:
|
|||
def _(string): return string
|
||||
|
||||
# FreePokerTools modules
|
||||
import Tables # needed for testing only
|
||||
import Configuration
|
||||
import Stats
|
||||
import Mucked
|
||||
|
@ -950,26 +949,3 @@ class Popup_window:
|
|||
# window.present()
|
||||
|
||||
|
||||
if __name__== "__main__":
|
||||
main_window = gtk.Window()
|
||||
main_window.connect("destroy", destroy)
|
||||
label = gtk.Label(_('Fake main window, blah blah, blah\nblah, blah'))
|
||||
main_window.add(label)
|
||||
main_window.show_all()
|
||||
|
||||
c = Configuration.Config()
|
||||
#tables = Tables.discover(c)
|
||||
t = Tables.discover_table_by_name(c, "Corona")
|
||||
if t is None:
|
||||
print _("Table not found.")
|
||||
db = Database.Database(c, 'fpdb', 'holdem')
|
||||
|
||||
stat_dict = db.get_stats_from_hand(1)
|
||||
|
||||
# for t in tables:
|
||||
win = Hud(None, t, 10, 'holdem', c, db) # parent, table, max, poker_game, config, db_connection
|
||||
win.create(1, c, stat_dict, None) # hand, config, stat_dict, cards):
|
||||
# t.get_details()
|
||||
win.update(8300, c) # self, hand, config):
|
||||
|
||||
gtk.main()
|
||||
|
|
|
@ -43,6 +43,8 @@ class OnGame(HandHistoryConverter):
|
|||
codepage = ("utf8", "cp1252")
|
||||
siteId = 5 # Needs to match id entry in Sites database
|
||||
|
||||
mixes = { } # Legal mixed games
|
||||
sym = {'USD': "\$", 'CAD': "\$", 'T$': "", "EUR": "\xe2\x82\xac", "GBP": "\xa3"} # ADD Euro, Sterling, etc HERE
|
||||
substitutions = {
|
||||
'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
|
||||
'LS' : "\$|\xe2\x82\xac|" # legal currency symbols - Euro(cp1252, utf-8)
|
||||
|
@ -65,7 +67,8 @@ class OnGame(HandHistoryConverter):
|
|||
|
||||
#self.rexx.setGameInfoRegex('.*Blinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)')
|
||||
# Static regexes
|
||||
re_SplitHands = re.compile(r'End of hand .{2}-\d{7,9}-\d+ \*\*\*\*\*\n')
|
||||
# ***** End of hand R5-75443872-57 *****
|
||||
re_SplitHands = re.compile(u'\*\*\*\*\*\sEnd\sof\shand\s[-A-Z\d]+.*\n(?=\*)')
|
||||
|
||||
# ***** History for hand R5-75443872-57 *****
|
||||
# Start hand: Wed Aug 18 19:29:10 GMT+0100 2010
|
||||
|
@ -73,29 +76,33 @@ class OnGame(HandHistoryConverter):
|
|||
re_HandInfo = re.compile(u"""
|
||||
\*\*\*\*\*\sHistory\sfor\shand\s(?P<HID>[-A-Z\d]+).*
|
||||
Start\shand:\s(?P<DATETIME>.*)
|
||||
Table:\s(?P<TABLE>[\'\w]+)\s\[\d+\]\s\(
|
||||
Table:\s(?P<TABLE>[\'\w\s]+)\s\[\d+\]\s\(
|
||||
(
|
||||
(?P<LIMIT>No\sLimit|Limit|LIMIT|Pot\sLimit)\s
|
||||
(?P<LIMIT>NO_LIMIT|Limit|LIMIT|Pot\sLimit)\s
|
||||
(?P<GAME>TEXAS_HOLDEM|RAZZ)\s
|
||||
(?P<SB>[.0-9]+)/
|
||||
(?P<BB>[.0-9]+)
|
||||
)?
|
||||
""" % substitutions, re.MULTILINE|re.DOTALL|re.VERBOSE)
|
||||
|
||||
re_TailSplitHands = re.compile(u'(\*\*\*\*\*\sEnd\sof\shand\s[-A-Z\d]+.*\n)(?=\*)')
|
||||
re_Button = re.compile('Button: seat (?P<BUTTON>\d+)', re.MULTILINE) # Button: seat 2
|
||||
re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
|
||||
|
||||
# Wed Aug 18 19:45:30 GMT+0100 2010
|
||||
re_DateTime = re.compile("""
|
||||
[a-zA-Z]{3}\s
|
||||
(?P<M>[a-zA-Z]{3})\s
|
||||
(?P<D>[0-9]{2})\s
|
||||
(?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)\sGMT
|
||||
(?P<OFFSET>[-+]\d+)\s
|
||||
(?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)\s
|
||||
(?P<OFFSET>\w+[-+]\d+)\s
|
||||
(?P<Y>[0-9]{4})
|
||||
""", re.MULTILINE|re.VERBOSE)
|
||||
|
||||
# self.rexx.button_re = re.compile('#SUMMARY\nDealer: (?P<BUTTONPNAME>.*)\n')
|
||||
|
||||
#Seat 1: .Lucchess ($4.17 in chips)
|
||||
re_PlayerInfo = re.compile(u'Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \((?P<CASH>[.0-9]+) \)')
|
||||
re_PlayerInfo = re.compile(u'Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \((?P<CASH>[.0-9]+)\)')
|
||||
|
||||
def compilePlayerRegexs(self, hand):
|
||||
players = set([player[1] for player in hand.players])
|
||||
|
@ -104,29 +111,30 @@ class OnGame(HandHistoryConverter):
|
|||
# TODO: should probably rename re_HeroCards and corresponding method,
|
||||
# since they are used to find all cards on lines starting with "Dealt to:"
|
||||
# They still identify the hero.
|
||||
self.compiledPlayers = players
|
||||
|
||||
#ANTES/BLINDS
|
||||
#helander2222 posts blind ($0.25), lopllopl posts blind ($0.50).
|
||||
player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")"
|
||||
subst = {'PLYR': player_re, 'CUR': self.sym[hand.gametype['currency']]}
|
||||
re_PostSB = re.compile('(?P<PNAME>.*) posts blind \(\$?(?P<SB>[.0-9]+)\), ')
|
||||
re_PostBB = re.compile('\), (?P<PNAME>.*) posts blind \(\$?(?P<BB>[.0-9]+)\).')
|
||||
re_Antes = re.compile(r"^%(PLYR)s: posts the ante %(CUR)s(?P<ANTE>[.0-9]+)" % subst, re.MULTILINE)
|
||||
re_BringIn = re.compile(r"^%(PLYR)s: brings[- ]in( low|) for %(CUR)s(?P<BRINGIN>[.0-9]+)" % subst, re.MULTILINE)
|
||||
re_PostBoth = re.compile('.*\n(?P<PNAME>.*): posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)')
|
||||
re_HeroCards = re.compile('.*\nDealt\sto\s(?P<PNAME>.*)\s\[ (?P<CARDS>.*) \]')
|
||||
self.re_PostSB = re.compile('(?P<PNAME>.*) posts small blind \(\$?(?P<SB>[.0-9]+)\)')
|
||||
self.re_PostBB = re.compile('\), (?P<PNAME>.*) posts big blind \(\$?(?P<BB>[.0-9]+)\)')
|
||||
self.re_Antes = re.compile(r"^%(PLYR)s: posts the ante %(CUR)s(?P<ANTE>[.0-9]+)" % subst, re.MULTILINE)
|
||||
self.re_BringIn = re.compile(r"^%(PLYR)s: brings[- ]in( low|) for %(CUR)s(?P<BRINGIN>[.0-9]+)" % subst, re.MULTILINE)
|
||||
self.re_PostBoth = re.compile('.*\n(?P<PNAME>.*): posts small \& big blinds \(\$? (?P<SBBB>[.0-9]+)\)')
|
||||
self.re_HeroCards = re.compile('Dealing\sto\s%(PLYR)s:\s\[(?P<CARDS>.*)\]' % subst)
|
||||
|
||||
#lopllopl checks, Eurolll checks, .Lucchess checks.
|
||||
re_Action = re.compile('(, )?(?P<PNAME>.*?)(?P<ATYPE> bets| checks| raises| calls| folds)( \$(?P<BET>\d*\.?\d*))?( and is all-in)?')
|
||||
re_Board = re.compile(r"\[board cards (?P<CARDS>.+) \]")
|
||||
self.re_Action = re.compile('(, )?(?P<PNAME>.*?)(?P<ATYPE> bets| checks| raises| calls| folds)( (?P<BET>\d*\.?\d*))?( and is all-in)?')
|
||||
#self.re_Board = re.compile(r"\[board cards (?P<CARDS>.+) \]")
|
||||
|
||||
#Uchilka shows [ KC,JD ]
|
||||
re_ShowdownAction = re.compile('(?P<PNAME>.*) shows \[ (?P<CARDS>.+) \]')
|
||||
self.re_ShowdownAction = re.compile('(?P<PNAME>.*) shows \[ (?P<CARDS>.+) \]')
|
||||
|
||||
# TODO: read SUMMARY correctly for collected pot stuff.
|
||||
#Uchilka, bets $11.75, collects $23.04, net $11.29
|
||||
re_CollectPot = re.compile('(?P<PNAME>.*), bets.+, collects \$(?P<POT>\d*\.?\d*), net.* ')
|
||||
re_sitsOut = re.compile('(?P<PNAME>.*) sits out')
|
||||
# Main pot: 6.75 won by player3 (6.45)
|
||||
self.re_CollectPot = re.compile('Main pot: (?P<POT>\d*\.?\d*) won by %(PLYR)s' % subst)
|
||||
self.re_sitsOut = re.compile('(?P<PNAME>.*) sits out')
|
||||
|
||||
def readSupportedGames(self):
|
||||
return [
|
||||
|
@ -179,9 +187,11 @@ class OnGame(HandHistoryConverter):
|
|||
# So we need to re-interpret te string to be useful
|
||||
m1 = self.re_DateTime.finditer(info[key])
|
||||
for a in m1:
|
||||
datetimestr = "%s %s %s %s:%s:%s" % (a.group('M'),a.group('D'), a.group('Y'), a.group('H'),a.group('MIN'),a.group('S'))
|
||||
hand.startTime = time.strptime(datetimestr, "%b %d %Y %H:%M:%S")
|
||||
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'))
|
||||
tzoffset = a.group('OFFSET')
|
||||
# TODO: Manually adjust time against OFFSET
|
||||
hand.startTime = datetime.datetime.strptime(datetimestr, "%Y/%b/%d %H:%M:%S") # also timezone at end, e.g. " ET"
|
||||
hand.startTime = HandHistoryConverter.changeTimezone(hand.startTime, tzoffset, "UTC")
|
||||
if key == 'HID':
|
||||
hand.handid = info[key]
|
||||
if key == 'TABLE':
|
||||
|
@ -206,10 +216,10 @@ class OnGame(HandHistoryConverter):
|
|||
#elif hand.gametype['base'] in ("stud"):
|
||||
#elif hand.gametype['base'] in ("draw"):
|
||||
# only holdem so far:
|
||||
m = re.search(r"pocket cards(?P<PREFLOP>.+(?=flop)|.+(?=Summary))"
|
||||
r"(flop (?P<FLOP>\[\S\S, \S\S, \S\S\].+(?=turn)|.+(?=Summary)))?"
|
||||
r"(turn (?P<TURN>\[\S\S, \S\S, \S\S\, \S\S\].+(?=river)|.+(?=Summary)))?"
|
||||
r"(river (?P<RIVER>\[\S\S, \S\S, \S\S\, \S\S, \S\S\].+(?=Summary)))?", hand.handText, re.DOTALL)
|
||||
m = re.search(r"pocket cards(?P<PREFLOP>.+(?= Dealing flop )|.+(?=Summary))"
|
||||
r"( Dealing flop (?P<FLOP>\[\S\S, \S\S, \S\S\].+(?= Dealing turn)|.+(?=Summary)))?"
|
||||
r"( Dealing turn (?P<TURN>\[\S\S\].+(?= Dealing river)|.+(?=Summary)))?"
|
||||
r"( Dealing river (?P<RIVER>\[\S\S\].+(?=Summary)))?", hand.handText, re.DOTALL)
|
||||
|
||||
hand.addStreets(m)
|
||||
|
||||
|
@ -224,17 +234,27 @@ class OnGame(HandHistoryConverter):
|
|||
else:
|
||||
log.info(_('readButton: not found'))
|
||||
|
||||
def readCommunityCards(self, hand, street):
|
||||
print hand.streets.group(street)
|
||||
# def readCommunityCards(self, hand, street):
|
||||
# #print hand.streets.group(street)
|
||||
# if street in ('FLOP','TURN','RIVER'): # a list of streets which get dealt community cards (i.e. all but PREFLOP)
|
||||
# m = self.re_Board.search(hand.streets.group(street))
|
||||
# hand.setCommunityCards(street, m.group('CARDS').split(','))
|
||||
|
||||
def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand
|
||||
if street in ('FLOP','TURN','RIVER'): # a list of streets which get dealt community cards (i.e. all but PREFLOP)
|
||||
m = self.re_Board.search(hand.streets.group(street))
|
||||
hand.setCommunityCards(street, m.group('CARDS').split(','))
|
||||
#print "DEBUG readCommunityCards:", street, hand.streets.group(street)
|
||||
m = self.re_Board.search(hand.streets[street])
|
||||
hand.setCommunityCards(street, m.group('CARDS').split(', '))
|
||||
|
||||
def readBlinds(self, hand):
|
||||
log.debug( _("readBlinds starting") )
|
||||
try:
|
||||
m = self.re_PostSB.search(hand.handText)
|
||||
if m is None:
|
||||
log.debug( _("re_postSB failed, hand=") + hand.handText )
|
||||
hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB'))
|
||||
except: # no small blind
|
||||
log.debug( _("readBlinds in noSB exception")+str(sys.exc_info()) )
|
||||
hand.addBlind(None, None, None)
|
||||
for a in self.re_PostBB.finditer(hand.handText):
|
||||
hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB'))
|
||||
|
@ -255,23 +275,23 @@ class OnGame(HandHistoryConverter):
|
|||
hand.addBringIn(m.group('PNAME'), m.group('BRINGIN'))
|
||||
|
||||
def readHeroCards(self, hand):
|
||||
m = self.re_HeroCards.search(hand.handText)
|
||||
if(m == None):
|
||||
#Not involved in hand
|
||||
hand.involved = False
|
||||
else:
|
||||
hand.hero = m.group('PNAME')
|
||||
# "2c, qh" -> set(["2c","qc"])
|
||||
# Also works with Omaha hands.
|
||||
cards = m.group('CARDS')
|
||||
cards = set(cards.split(','))
|
||||
hand.addHoleCards(cards, m.group('PNAME'))
|
||||
# streets PREFLOP, PREDRAW, and THIRD are special cases beacause
|
||||
# we need to grab hero's cards
|
||||
for street in ('PREFLOP', 'DEAL'):
|
||||
if street in hand.streets.keys():
|
||||
m = self.re_HeroCards.finditer(hand.streets[street])
|
||||
for found in m:
|
||||
hand.hero = found.group('PNAME')
|
||||
newcards = found.group('CARDS').split(', ')
|
||||
hand.addHoleCards(street, hand.hero, closed=newcards, shown=False, mucked=False, dealt=True)
|
||||
|
||||
def readAction(self, hand, street):
|
||||
m = self.re_Action.finditer(hand.streets.group(street))
|
||||
m = self.re_Action.finditer(hand.streets[street])
|
||||
for action in m:
|
||||
acts = action.groupdict()
|
||||
#print "DEBUG: acts: %s" %acts
|
||||
if action.group('ATYPE') == ' raises':
|
||||
hand.addRaiseTo( street, action.group('PNAME'), action.group('BET') )
|
||||
hand.addRaiseBy( street, action.group('PNAME'), action.group('BET') )
|
||||
elif action.group('ATYPE') == ' calls':
|
||||
hand.addCall( street, action.group('PNAME'), action.group('BET') )
|
||||
elif action.group('ATYPE') == ' bets':
|
||||
|
@ -280,10 +300,12 @@ class OnGame(HandHistoryConverter):
|
|||
hand.addFold( street, action.group('PNAME'))
|
||||
elif action.group('ATYPE') == ' checks':
|
||||
hand.addCheck( street, action.group('PNAME'))
|
||||
elif action.group('ATYPE') == ' discards':
|
||||
hand.addDiscard(street, action.group('PNAME'), action.group('BET'), action.group('DISCARDED'))
|
||||
elif action.group('ATYPE') == ' stands pat':
|
||||
hand.addStandsPat( street, action.group('PNAME'))
|
||||
else:
|
||||
print "DEBUG: unimplemented readAction: %s %s" %(action.group('PNAME'),action.group('ATYPE'),)
|
||||
#hand.actions[street] += [[action.group('PNAME'), action.group('ATYPE')]]
|
||||
# TODO: Everleaf does not record uncalled bets.
|
||||
print _("DEBUG: unimplemented readAction: '%s' '%s'") %(action.group('PNAME'),action.group('ATYPE'),)
|
||||
|
||||
def readShowdownActions(self, hand):
|
||||
for shows in self.re_ShowdownAction.finditer(hand.handText):
|
||||
|
|
390
pyfpdb/PkrToFpdb.py
Executable file
390
pyfpdb/PkrToFpdb.py
Executable file
|
@ -0,0 +1,390 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010, Carl Gherardi
|
||||
#
|
||||
# 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
|
||||
########################################################################
|
||||
|
||||
|
||||
import sys
|
||||
from HandHistoryConverter import *
|
||||
|
||||
import locale
|
||||
lang=locale.getdefaultlocale()[0][0:2]
|
||||
if lang=="en":
|
||||
def _(string): return string
|
||||
else:
|
||||
import gettext
|
||||
try:
|
||||
trans = gettext.translation("fpdb", localedir="locale", languages=[lang])
|
||||
trans.install()
|
||||
except IOError:
|
||||
def _(string): return string
|
||||
|
||||
|
||||
class Pkr(HandHistoryConverter):
|
||||
|
||||
# Class Variables
|
||||
|
||||
sitename = "PKR"
|
||||
filetype = "text"
|
||||
codepage = ("utf8", "cp1252")
|
||||
siteId = 12 # Needs to match id entry in Sites database
|
||||
|
||||
mixes = { 'HORSE': 'horse', '8-Game': '8game', 'HOSE': 'hose'} # Legal mixed games
|
||||
sym = {'USD': "\$"} # ADD Euro, Sterling, etc HERE
|
||||
substitutions = {
|
||||
'LEGAL_ISO' : "USD", # legal ISO currency codes
|
||||
'LS' : "\$|" # legal currency symbols - Euro(cp1252, utf-8)
|
||||
}
|
||||
|
||||
limits = { 'NO LIMIT':'nl', 'POT LIMIT':'pl', 'LIMIT':'fl' }
|
||||
games = { # base, category
|
||||
"HOLD'EM" : ('hold','holdem'),
|
||||
'FIXMEOmaha' : ('hold','omahahi'),
|
||||
'FIXMEOmaha Hi/Lo' : ('hold','omahahilo'),
|
||||
'FIXME5 Card Draw' : ('draw','fivedraw')
|
||||
}
|
||||
currencies = { u'€':'EUR', '$':'USD', '':'T$' }
|
||||
|
||||
# Static regexes
|
||||
re_GameInfo = re.compile(u"""
|
||||
Table\s\#\d+\s\-\s(?P<TABLE>[a-zA-Z\ \d]+)\s
|
||||
Starting\sHand\s\#(?P<HID>[0-9]+)\s
|
||||
Start\stime\sof\shand:\s(?P<DATETIME>.*)\s
|
||||
Last\sHand\s\#[0-9]+\s
|
||||
Game\sType:\s(?P<GAME>HOLD'EM|5\sCard\sDraw)\s
|
||||
Limit\sType:\s(?P<LIMIT>NO\sLIMIT|LIMIT|POT\sLIMIT)\s
|
||||
Table\sType\:\sRING\s
|
||||
Money\sType:\sREAL\sMONEY\s
|
||||
Blinds\sare\snow\s(?P<CURRENCY>%(LS)s|)?
|
||||
(?P<SB>[.0-9]+)/(%(LS)s)?
|
||||
(?P<BB>[.0-9]+)
|
||||
""" % substitutions, re.MULTILINE|re.VERBOSE)
|
||||
|
||||
re_PlayerInfo = re.compile(u"""
|
||||
^Seat\s(?P<SEAT>[0-9]+):\s
|
||||
(?P<PNAME>.*)\s-\s
|
||||
(%(LS)s)?(?P<CASH>[.0-9]+)
|
||||
""" % substitutions, re.MULTILINE|re.VERBOSE)
|
||||
|
||||
re_HandInfo = re.compile("""
|
||||
^Table\s\'(?P<TABLE>[-\ a-zA-Z\d]+)\'\s
|
||||
((?P<MAX>\d+)-max\s)?
|
||||
(?P<PLAY>\(Play\sMoney\)\s)?
|
||||
(Seat\s\#(?P<BUTTON>\d+)\sis\sthe\sbutton)?""",
|
||||
re.MULTILINE|re.VERBOSE)
|
||||
|
||||
re_SplitHands = re.compile('\n\n+')
|
||||
re_TailSplitHands = re.compile('(\n\n\n+)')
|
||||
re_Button = re.compile('Seat #(?P<BUTTON>\d+) is the button', re.MULTILINE)
|
||||
re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
|
||||
# self.re_setHandInfoRegex('.*#(?P<HID>[0-9]+): Table (?P<TABLE>[ a-zA-Z]+) - \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) - (?P<GAMETYPE>.*) - (?P<HR>[0-9]+):(?P<MIN>[0-9]+) ET - (?P<YEAR>[0-9]+)/(?P<MON>[0-9]+)/(?P<DAY>[0-9]+)Table (?P<TABLE>[ a-zA-Z]+)\nSeat (?P<BUTTON>[0-9]+)')
|
||||
|
||||
re_DateTime = re.compile("""(?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]+)""", re.MULTILINE)
|
||||
|
||||
def compilePlayerRegexs(self, hand):
|
||||
players = set([player[1] for player in hand.players])
|
||||
if not players <= self.compiledPlayers: # x <= y means 'x is subset of y'
|
||||
# we need to recompile the player regexs.
|
||||
self.compiledPlayers = players
|
||||
player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")"
|
||||
subst = {'PLYR': player_re, 'CUR': self.sym[hand.gametype['currency']]}
|
||||
log.debug("player_re: " + player_re)
|
||||
self.re_PostSB = re.compile(r"^%(PLYR)s posts small blind %(CUR)s(?P<SB>[.0-9]+)" % subst, re.MULTILINE)
|
||||
# FIXME: Sionel posts $0.04 is a second big blind in a different format.
|
||||
self.re_PostBB = re.compile(r"^%(PLYR)s posts big blind %(CUR)s(?P<BB>[.0-9]+)" % subst, re.MULTILINE)
|
||||
self.re_Antes = re.compile(r"^%(PLYR)s: posts the ante %(CUR)s(?P<ANTE>[.0-9]+)" % subst, re.MULTILINE)
|
||||
self.re_BringIn = re.compile(r"^%(PLYR)s: brings[- ]in( low|) for %(CUR)s(?P<BRINGIN>[.0-9]+)" % subst, re.MULTILINE)
|
||||
self.re_PostBoth = re.compile(r"^%(PLYR)s: posts small \& big blinds %(CUR)s(?P<SBBB>[.0-9]+)" % subst, re.MULTILINE)
|
||||
self.re_HeroCards = re.compile(r"^Dealing( \[(?P<OLDCARDS>.+?)\])?( \[(?P<NEWCARDS>.+?)\]) to %(PLYR)s" % subst, re.MULTILINE)
|
||||
self.re_Action = re.compile(r"""
|
||||
^%(PLYR)s(?P<ATYPE>\sbets|\schecks|\sraises|\scalls|\sfolds)(\sto)?
|
||||
(\s(%(CUR)s)?(?P<BET>[.\d]+))?
|
||||
""" % subst, re.MULTILINE|re.VERBOSE)
|
||||
self.re_ShowdownAction = re.compile(r"^%s: shows \[(?P<CARDS>.*)\]" % player_re, re.MULTILINE)
|
||||
self.re_CollectPot = re.compile(r"Seat (?P<SEAT>[0-9]+): %(PLYR)s (\(button\) |\(small blind\) |\(big blind\) |\(button\) \(small blind\) )?(collected|showed \[.*\] and won) \(%(CUR)s(?P<POT>[.\d]+)\)(, mucked| with.*|)" % subst, re.MULTILINE)
|
||||
self.re_sitsOut = re.compile("^%s sits out" % player_re, re.MULTILINE)
|
||||
self.re_ShownCards = re.compile("^Seat (?P<SEAT>[0-9]+): %s (\(.*\) )?(?P<SHOWED>showed|mucked) \[(?P<CARDS>.*)\].*" % player_re, re.MULTILINE)
|
||||
|
||||
def readSupportedGames(self):
|
||||
return [["ring", "hold", "nl"],
|
||||
["ring", "hold", "pl"],
|
||||
["ring", "hold", "fl"],
|
||||
|
||||
["ring", "stud", "fl"],
|
||||
|
||||
["ring", "draw", "fl"],
|
||||
|
||||
["tour", "hold", "nl"],
|
||||
["tour", "hold", "pl"],
|
||||
["tour", "hold", "fl"],
|
||||
|
||||
["tour", "stud", "fl"],
|
||||
]
|
||||
|
||||
def determineGameType(self, handText):
|
||||
info = {}
|
||||
m = self.re_GameInfo.search(handText)
|
||||
if not m:
|
||||
tmp = handText[0:100]
|
||||
log.error(_("determineGameType: Unable to recognise gametype from: '%s'") % tmp)
|
||||
log.error(_("determineGameType: Raising FpdbParseError"))
|
||||
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
|
||||
|
||||
mg = m.groupdict()
|
||||
#print "DEBUG: %s" % mg
|
||||
|
||||
if 'LIMIT' in mg:
|
||||
info['limitType'] = self.limits[mg['LIMIT']]
|
||||
if 'GAME' in mg:
|
||||
(info['base'], info['category']) = self.games[mg['GAME']]
|
||||
if 'SB' in mg:
|
||||
info['sb'] = mg['SB']
|
||||
if 'BB' in mg:
|
||||
info['bb'] = mg['BB']
|
||||
if 'CURRENCY' in mg:
|
||||
info['currency'] = self.currencies[mg['CURRENCY']]
|
||||
|
||||
if 'TOURNO' in mg and mg['TOURNO'] is None:
|
||||
info['type'] = 'ring'
|
||||
else:
|
||||
info['type'] = 'tour'
|
||||
|
||||
if info['limitType'] == 'fl' and info['bb'] is not None and info['type'] == 'ring' and info['base'] != 'stud':
|
||||
try:
|
||||
info['sb'] = self.Lim_Blinds[mg['BB']][0]
|
||||
info['bb'] = self.Lim_Blinds[mg['BB']][1]
|
||||
except KeyError:
|
||||
log.error(_("determineGameType: Lim_Blinds has no lookup for '%s'" % mg['BB']))
|
||||
log.error(_("determineGameType: Raising FpdbParseError"))
|
||||
raise FpdbParseError(_("Lim_Blinds has no lookup for '%s'") % mg['BB'])
|
||||
|
||||
return info
|
||||
|
||||
def readHandInfo(self, hand):
|
||||
info = {}
|
||||
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':
|
||||
#2008/11/12 10:00:48 CET [2008/11/12 4:00:48 ET]
|
||||
#2008/08/17 - 01:14:43 (ET)
|
||||
#2008/09/07 06:23:14 ET
|
||||
m1 = self.re_DateTime.finditer(info[key])
|
||||
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'))
|
||||
hand.startTime = datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S")
|
||||
if key == 'HID':
|
||||
hand.handid = info[key]
|
||||
if key == 'TOURNO':
|
||||
hand.tourNo = info[key]
|
||||
if key == 'BUYIN':
|
||||
if info[key] == 'Freeroll':
|
||||
hand.buyin = '$0+$0'
|
||||
else:
|
||||
#FIXME: The key looks like: '€0.82+€0.18 EUR'
|
||||
# This should be parsed properly and used
|
||||
hand.buyin = info[key]
|
||||
if key == 'LEVEL':
|
||||
hand.level = info[key]
|
||||
|
||||
if key == 'TABLE':
|
||||
if hand.tourNo != None:
|
||||
hand.tablename = re.split(" ", info[key])[1]
|
||||
else:
|
||||
hand.tablename = info[key]
|
||||
if key == 'BUTTON':
|
||||
hand.buttonpos = info[key]
|
||||
if key == 'MAX':
|
||||
hand.maxseats = int(info[key])
|
||||
|
||||
if key == 'MIXED':
|
||||
hand.mixed = self.mixes[info[key]] if info[key] is not None else None
|
||||
if key == 'PLAY' and info['PLAY'] is not None:
|
||||
# hand.currency = 'play' # overrides previously set value
|
||||
hand.gametype['currency'] = 'play'
|
||||
|
||||
def readButton(self, hand):
|
||||
m = self.re_Button.search(hand.handText)
|
||||
if m:
|
||||
hand.buttonpos = int(m.group('BUTTON'))
|
||||
else:
|
||||
log.info('readButton: not found')
|
||||
|
||||
def readPlayerStacks(self, hand):
|
||||
log.debug("readPlayerStacks")
|
||||
m = self.re_PlayerInfo.finditer(hand.handText)
|
||||
for a in m:
|
||||
hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH'))
|
||||
|
||||
def markStreets(self, hand):
|
||||
# PREFLOP = ** Dealing down cards **
|
||||
# This re fails if, say, river is missing; then we don't get the ** that starts the river.
|
||||
if hand.gametype['base'] in ("hold"):
|
||||
m = re.search(r"Dealing Cards(?P<PREFLOP>.+(?=Dealing Flop)|.+)"
|
||||
r"(Dealing Flop(?P<FLOP> \[\S\S \S\S \S\S\].+(?=Dealing Turn)|.+))?"
|
||||
r"(Dealing Turn (?P<TURN>\[\S\S\].+(?=Dealing River)|.+))?"
|
||||
r"(Dealing River (?P<RIVER>\[\S\S\].+))?", hand.handText,re.DOTALL)
|
||||
elif hand.gametype['base'] in ("stud"):
|
||||
m = re.search(r"(?P<ANTES>.+(?=\*\*\* 3rd STREET \*\*\*)|.+)"
|
||||
r"(\*\*\* 3rd STREET \*\*\*(?P<THIRD>.+(?=\*\*\* 4th STREET \*\*\*)|.+))?"
|
||||
r"(\*\*\* 4th STREET \*\*\*(?P<FOURTH>.+(?=\*\*\* 5th STREET \*\*\*)|.+))?"
|
||||
r"(\*\*\* 5th STREET \*\*\*(?P<FIFTH>.+(?=\*\*\* 6th STREET \*\*\*)|.+))?"
|
||||
r"(\*\*\* 6th STREET \*\*\*(?P<SIXTH>.+(?=\*\*\* RIVER \*\*\*)|.+))?"
|
||||
r"(\*\*\* RIVER \*\*\*(?P<SEVENTH>.+))?", hand.handText,re.DOTALL)
|
||||
elif hand.gametype['base'] in ("draw"):
|
||||
m = re.search(r"(?P<PREDEAL>.+(?=\*\*\* DEALING HANDS \*\*\*)|.+)"
|
||||
r"(\*\*\* DEALING HANDS \*\*\*(?P<DEAL>.+(?=\*\*\* FIRST DRAW \*\*\*)|.+))?"
|
||||
r"(\*\*\* FIRST DRAW \*\*\*(?P<DRAWONE>.+(?=\*\*\* SECOND DRAW \*\*\*)|.+))?"
|
||||
r"(\*\*\* SECOND DRAW \*\*\*(?P<DRAWTWO>.+(?=\*\*\* THIRD DRAW \*\*\*)|.+))?"
|
||||
r"(\*\*\* THIRD DRAW \*\*\*(?P<DRAWTHREE>.+))?", hand.handText,re.DOTALL)
|
||||
hand.addStreets(m)
|
||||
|
||||
def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand
|
||||
if street in ('FLOP','TURN','RIVER'): # a list of streets which get dealt community cards (i.e. all but PREFLOP)
|
||||
#print "DEBUG readCommunityCards:", street, hand.streets.group(street)
|
||||
m = self.re_Board.search(hand.streets[street])
|
||||
hand.setCommunityCards(street, m.group('CARDS').split(' '))
|
||||
|
||||
def readAntes(self, hand):
|
||||
log.debug("reading antes")
|
||||
m = self.re_Antes.finditer(hand.handText)
|
||||
for player in m:
|
||||
#~ logging.debug("hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE')))
|
||||
hand.addAnte(player.group('PNAME'), player.group('ANTE'))
|
||||
|
||||
def readBringIn(self, hand):
|
||||
m = self.re_BringIn.search(hand.handText,re.DOTALL)
|
||||
if m:
|
||||
#~ logging.debug("readBringIn: %s for %s" %(m.group('PNAME'), m.group('BRINGIN')))
|
||||
hand.addBringIn(m.group('PNAME'), m.group('BRINGIN'))
|
||||
|
||||
def readBlinds(self, hand):
|
||||
try:
|
||||
m = self.re_PostSB.search(hand.handText)
|
||||
hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB'))
|
||||
except: # no small blind
|
||||
hand.addBlind(None, None, None)
|
||||
for a in self.re_PostBB.finditer(hand.handText):
|
||||
hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB'))
|
||||
for a in self.re_PostBoth.finditer(hand.handText):
|
||||
hand.addBlind(a.group('PNAME'), 'both', a.group('SBBB'))
|
||||
|
||||
def readHeroCards(self, hand):
|
||||
# streets PREFLOP, PREDRAW, and THIRD are special cases beacause
|
||||
# we need to grab hero's cards
|
||||
for street in ('PREFLOP', 'DEAL'):
|
||||
if street in hand.streets.keys():
|
||||
m = self.re_HeroCards.finditer(hand.streets[street])
|
||||
for found in m:
|
||||
# if m == None:
|
||||
# hand.involved = False
|
||||
# else:
|
||||
hand.hero = found.group('PNAME')
|
||||
newcards = found.group('NEWCARDS').split(' ')
|
||||
hand.addHoleCards(street, hand.hero, closed=newcards, shown=False, mucked=False, dealt=True)
|
||||
|
||||
for street, text in hand.streets.iteritems():
|
||||
if not text or street in ('PREFLOP', 'DEAL'): continue # already done these
|
||||
m = self.re_HeroCards.finditer(hand.streets[street])
|
||||
for found in m:
|
||||
player = found.group('PNAME')
|
||||
if found.group('NEWCARDS') is None:
|
||||
newcards = []
|
||||
else:
|
||||
newcards = found.group('NEWCARDS').split(' ')
|
||||
if found.group('OLDCARDS') is None:
|
||||
oldcards = []
|
||||
else:
|
||||
oldcards = found.group('OLDCARDS').split(' ')
|
||||
|
||||
if street == 'THIRD' and len(newcards) == 3: # hero in stud game
|
||||
hand.hero = player
|
||||
hand.dealt.add(player) # need this for stud??
|
||||
hand.addHoleCards(street, player, closed=newcards[0:2], open=[newcards[2]], shown=False, mucked=False, dealt=False)
|
||||
else:
|
||||
hand.addHoleCards(street, player, open=newcards, closed=oldcards, shown=False, mucked=False, dealt=False)
|
||||
|
||||
|
||||
def readAction(self, hand, street):
|
||||
m = self.re_Action.finditer(hand.streets[street])
|
||||
for action in m:
|
||||
acts = action.groupdict()
|
||||
if action.group('ATYPE') == ' raises':
|
||||
hand.addRaiseTo( street, action.group('PNAME'), action.group('BET') )
|
||||
elif action.group('ATYPE') == ' calls':
|
||||
hand.addCall( street, action.group('PNAME'), action.group('BET') )
|
||||
elif action.group('ATYPE') == ' bets':
|
||||
hand.addBet( street, action.group('PNAME'), action.group('BET') )
|
||||
elif action.group('ATYPE') == ' folds':
|
||||
hand.addFold( street, action.group('PNAME'))
|
||||
elif action.group('ATYPE') == ' checks':
|
||||
hand.addCheck( street, action.group('PNAME'))
|
||||
elif action.group('ATYPE') == ' discards':
|
||||
hand.addDiscard(street, action.group('PNAME'), action.group('BET'), action.group('DISCARDED'))
|
||||
elif action.group('ATYPE') == ' stands pat':
|
||||
hand.addStandsPat( street, action.group('PNAME'))
|
||||
else:
|
||||
print "DEBUG: unimplemented readAction: '%s' '%s'" %(action.group('PNAME'),action.group('ATYPE'),)
|
||||
|
||||
|
||||
def readShowdownActions(self, hand):
|
||||
# TODO: pick up mucks also??
|
||||
for shows in self.re_ShowdownAction.finditer(hand.handText):
|
||||
cards = shows.group('CARDS').split(' ')
|
||||
hand.addShownCards(cards, shows.group('PNAME'))
|
||||
|
||||
def readCollectPot(self,hand):
|
||||
for m in self.re_CollectPot.finditer(hand.handText):
|
||||
hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT'))
|
||||
|
||||
def readShownCards(self,hand):
|
||||
for m in self.re_ShownCards.finditer(hand.handText):
|
||||
if m.group('CARDS') is not None:
|
||||
cards = m.group('CARDS')
|
||||
cards = cards.split(' ') # needs to be a list, not a set--stud needs the order
|
||||
|
||||
(shown, mucked) = (False, False)
|
||||
if m.group('SHOWED') == "showed": shown = True
|
||||
elif m.group('SHOWED') == "mucked": mucked = True
|
||||
|
||||
hand.addShownCards(cards=cards, player=m.group('PNAME'), shown=shown, mucked=mucked)
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = OptionParser()
|
||||
parser.add_option("-i", "--input", dest="ipath", help="parse input hand history", default="regression-test-files/stars/horse/HH20090226 Natalie V - $0.10-$0.20 - HORSE.txt")
|
||||
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("-q", "--quiet", action="store_const", const=logging.CRITICAL, dest="verbosity", default=logging.INFO)
|
||||
#parser.add_option("-v", "--verbose", action="store_const", const=logging.INFO, dest="verbosity")
|
||||
#parser.add_option("--vv", action="store_const", const=logging.DEBUG, dest="verbosity")
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
e = PokerStars(in_path = options.ipath, out_path = options.opath, follow = options.follow)
|
|
@ -224,14 +224,15 @@ class PokerStars(HandHistoryConverter):
|
|||
|
||||
def readHandInfo(self, hand):
|
||||
info = {}
|
||||
m = self.re_HandInfo.search(hand.handText,re.DOTALL)
|
||||
if m:
|
||||
info.update(m.groupdict())
|
||||
else:
|
||||
pass # throw an exception here, eh?
|
||||
m = self.re_GameInfo.search(hand.handText)
|
||||
if m:
|
||||
info.update(m.groupdict())
|
||||
m = self.re_HandInfo.search(hand.handText,re.DOTALL)
|
||||
m2 = self.re_GameInfo.search(hand.handText)
|
||||
if m is None or m2 is None:
|
||||
logging.info("Didn't match re_HandInfo")
|
||||
logging.info(hand.handText)
|
||||
raise FpdbParseError("No match in readHandInfo.")
|
||||
|
||||
info.update(m.groupdict())
|
||||
info.update(m2.groupdict())
|
||||
|
||||
log.debug("readHandInfo: %s" % info)
|
||||
for key in info:
|
||||
|
|
|
@ -3968,6 +3968,7 @@ class Sql:
|
|||
AND fee=%s
|
||||
AND category=%s
|
||||
AND limitType=%s
|
||||
AND maxSeats=%s
|
||||
AND knockout=%s
|
||||
AND rebuy=%s
|
||||
AND addOn=%s
|
||||
|
@ -3977,9 +3978,9 @@ class Sql:
|
|||
"""
|
||||
|
||||
self.query['insertTourneyType'] = """INSERT INTO TourneyTypes
|
||||
(siteId, currency, buyin, fee, category, limitType, buyInChips, knockout, koBounty, rebuy,
|
||||
(siteId, currency, buyin, fee, category, limitType, maxSeats, buyInChips, knockout, koBounty, rebuy,
|
||||
addOn ,speed, shootout, matrix, added, addedCurrency)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||
"""
|
||||
|
||||
self.query['getTourneyByTourneyNo'] = """SELECT t.*
|
||||
|
|
449
pyfpdb/Tables.py
449
pyfpdb/Tables.py
|
@ -1,449 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Discover_Tables.py
|
||||
|
||||
Inspects the currently open windows and finds those of interest to us--that is
|
||||
poker table windows from supported sites. Returns a list
|
||||
of Table_Window objects representing the windows found.
|
||||
"""
|
||||
# Copyright 2008-2010, Ray E. Barker
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
########################################################################
|
||||
|
||||
# Standard Library modules
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
|
||||
import locale
|
||||
lang=locale.getdefaultlocale()[0][0:2]
|
||||
if lang=="en":
|
||||
def _(string): return string
|
||||
else:
|
||||
import gettext
|
||||
try:
|
||||
trans = gettext.translation("fpdb", localedir="locale", languages=[lang])
|
||||
trans.install()
|
||||
except IOError:
|
||||
def _(string): return string
|
||||
|
||||
# Win32 modules
|
||||
if os.name == 'nt':
|
||||
import win32gui
|
||||
import win32process
|
||||
import win32api
|
||||
import win32con
|
||||
import win32security
|
||||
|
||||
# FreePokerTools modules
|
||||
import Configuration
|
||||
|
||||
# Each TableWindow object must have the following attributes correctly populated:
|
||||
# tw.name = the table name from the title bar, which must to match the table name
|
||||
# from the corresponding hand history.
|
||||
# tw.site = the site name, e.g. PokerStars, FullTilt. This must match the site
|
||||
# name specified in the config file.
|
||||
# tw.number = This is the system id number for the client table window in the
|
||||
# format that the system presents it. This is Xid in Xwindows and
|
||||
# hwnd in Microsoft Windows.
|
||||
# tw.title = The full title from the window title bar.
|
||||
# tw.width, tw.height = The width and height of the window in pixels. This is
|
||||
# the internal width and height, not including the title bar and
|
||||
# window borders.
|
||||
# tw.x, tw.y = The x, y (horizontal, vertical) location of the window relative
|
||||
# to the top left of the display screen. This also does not include the
|
||||
# title bar and window borders. To put it another way, this is the
|
||||
# screen location of (0, 0) in the working window.
|
||||
|
||||
class Table_Window:
|
||||
def __init__(self, info = {}):
|
||||
if 'number' in info: self.number = info['number']
|
||||
if 'exe' in info: self.exe = info['exe']
|
||||
if 'width' in info: self.width = info['width']
|
||||
if 'height' in info: self.height = info['height']
|
||||
if 'x' in info: self.x = info['x']
|
||||
if 'y' in info: self.y = info['y']
|
||||
if 'site' in info: self.site = info['site']
|
||||
if 'title' in info: self.title = info['title']
|
||||
if 'name' in info: self.name = info['name']
|
||||
self.gdkhandle = None
|
||||
|
||||
def __str__(self):
|
||||
# __str__ method for testing
|
||||
temp = 'TableWindow object\n'
|
||||
temp = temp + " name = %s\n site = %s\n number = %s\n title = %s\n" % (self.name, self.site, self.number, self.title)
|
||||
# temp = temp + " game = %s\n structure = %s\n max = %s\n" % (self.game, self.structure, self.max)
|
||||
temp = temp + " width = %d\n height = %d\n x = %d\n y = %d\n" % (self.width, self.height, self.x, self.y)
|
||||
if getattr(self, 'tournament', 0):
|
||||
temp = temp + " tournament = %d\n table = %d" % (self.tournament, self.table)
|
||||
return temp
|
||||
|
||||
############################################################################
|
||||
# Top-level discovery routines--these are the modules interface
|
||||
def discover(c):
|
||||
"""Dispatch routine for finding all potential poker client windows."""
|
||||
if os.name == 'posix':
|
||||
tables = discover_posix(c)
|
||||
elif os.name == 'nt':
|
||||
tables = discover_nt(c)
|
||||
elif os.name == 'mac':
|
||||
tables = discover_mac(c)
|
||||
else:
|
||||
tables = {}
|
||||
return tables
|
||||
|
||||
def discover_table_by_name(c, tablename):
|
||||
"""Dispatch routine for finding poker client windows with the given name."""
|
||||
if os.name == 'posix':
|
||||
info = discover_posix_by_name(c, tablename)
|
||||
elif os.name == 'nt':
|
||||
info = discover_nt_by_name(c, tablename)
|
||||
elif os.name == 'mac':
|
||||
info = discover_mac_by_name(c, tablename)
|
||||
else:
|
||||
return None
|
||||
if info is None:
|
||||
return None
|
||||
return Table_Window(info)
|
||||
|
||||
def discover_tournament_table(c, tour_number, tab_number):
|
||||
"""Dispatch routine for finding poker clients with tour and table number."""
|
||||
if os.name == 'posix':
|
||||
info = discover_posix_tournament(c, tour_number, tab_number)
|
||||
elif os.name == 'nt':
|
||||
info = discover_nt_tournament(c, tour_number, tab_number)
|
||||
elif os.name == 'mac':
|
||||
info = discover_mac_tournament(c, tour_number, tab_number)
|
||||
else:
|
||||
return None
|
||||
if info:
|
||||
return Table_Window(info)
|
||||
return None
|
||||
|
||||
#############################################################################
|
||||
# Posix (= XWindows) specific routines
|
||||
def discover_posix(c):
|
||||
"""Poker client table window finder for posix/Linux = XWindows."""
|
||||
tables = {}
|
||||
for listing in os.popen('xwininfo -root -tree').readlines():
|
||||
# xwininfo -root -tree -id 0xnnnnn gets the info on a single window
|
||||
for s in c.get_supported_sites():
|
||||
params = c.get_site_parameters(s)
|
||||
|
||||
# TODO: We need to make a list of phrases, shared between the WIndows and Unix code!!!!!!
|
||||
if re.search(params['table_finder'], listing):
|
||||
if 'Lobby' in listing: continue
|
||||
if 'Instant Hand History' in listing: continue
|
||||
# if '\"Full Tilt Poker\"' in listing: continue
|
||||
if 'History for table:' in listing: continue
|
||||
if 'has no name' in listing: continue
|
||||
info = decode_xwininfo(c, listing)
|
||||
if info['site'] is None: continue
|
||||
if info['title'] == info['exe']: continue
|
||||
# this appears to be a poker client, so make a table object for it
|
||||
tw = Table_Window(info)
|
||||
eval("%s(tw)" % params['decoder'])
|
||||
tables[tw.name] = tw
|
||||
return tables
|
||||
|
||||
def discover_posix_by_name(c, tablename):
|
||||
"""Find an XWindows poker client of the given name."""
|
||||
for listing in os.popen('xwininfo -root -tree').readlines():
|
||||
if tablename in listing:
|
||||
if 'History for table:' in listing: continue
|
||||
info = decode_xwininfo(c, listing)
|
||||
if not info['name'] == tablename: continue
|
||||
return info
|
||||
return None
|
||||
|
||||
def discover_posix_tournament(c, t_number, s_number):
|
||||
"""Finds the X window for a client, given tournament and table nos."""
|
||||
search_string = "%s.+Table.+%s" % (t_number, s_number)
|
||||
for listing in os.popen('xwininfo -root -tree').readlines():
|
||||
if re.search(search_string, listing):
|
||||
return decode_xwininfo(c, listing)
|
||||
return None
|
||||
|
||||
def decode_xwininfo(c, info_string):
|
||||
"""Gets window parameters from xwinifo string--XWindows."""
|
||||
info = {}
|
||||
mo = re.match('\s+([\dxabcdef]+) (.+):\s\(\"([a-zA-Z.]+)\".+ (\d+)x(\d+)\+\d+\+\d+ \+(\d+)\+(\d+)', info_string)
|
||||
if not mo:
|
||||
return None
|
||||
else:
|
||||
info['number'] = int( mo.group(1), 0)
|
||||
info['exe'] = mo.group(3)
|
||||
info['width'] = int( mo.group(4) )
|
||||
info['height'] = int( mo.group(5) )
|
||||
info['x'] = int( mo.group(6) )
|
||||
info['y'] = int( mo.group(7) )
|
||||
info['site'] = get_site_from_exe(c, info['exe'])
|
||||
info['title'] = re.sub('\"', '', mo.group(2))
|
||||
title_bits = re.split(' - ', info['title'])
|
||||
info['name'] = clean_title(title_bits[0])
|
||||
return info
|
||||
|
||||
##############################################################################
|
||||
# NT (= Windows) specific routines
|
||||
def discover_nt(c):
|
||||
""" Poker client table window finder for Windows."""
|
||||
#
|
||||
# I cannot figure out how to get the inside dimensions of the poker table
|
||||
# windows. So I just assume all borders are 3 thick and all title bars
|
||||
# are 29 high. No doubt this will be off when used with certain themes.
|
||||
#
|
||||
b_width = 3
|
||||
tb_height = 29
|
||||
titles = {}
|
||||
tables = {}
|
||||
win32gui.EnumWindows(win_enum_handler, titles)
|
||||
for hwnd in titles:
|
||||
if 'Logged In as' in titles[hwnd] and not 'Lobby' in titles[hwnd]:
|
||||
if 'Full Tilt Poker' in titles[hwnd]:
|
||||
continue
|
||||
tw = Table_Window()
|
||||
tw.number = hwnd
|
||||
(x, y, width, height) = win32gui.GetWindowRect(hwnd)
|
||||
tw.title = titles[hwnd]
|
||||
tw.width = int( width ) - 2*b_width
|
||||
tw.height = int( height ) - b_width - tb_height
|
||||
tw.x = int( x ) + b_width
|
||||
tw.y = int( y ) + tb_height
|
||||
|
||||
# TODO: Isn't the site being determined by the EXE name it belongs to? is this section of code even useful? cleaning it anyway
|
||||
if 'Logged In as' in titles[hwnd]:
|
||||
tw.site = "PokerStars"
|
||||
elif 'Logged In As' in titles[hwnd]:
|
||||
tw.site = "Full Tilt"
|
||||
else:
|
||||
tw.site = "Unknown"
|
||||
sys.stderr.write(_("Found unknown table = %s") % tw.title)
|
||||
if tw.site != "Unknown":
|
||||
eval("%s(tw)" % c.supported_sites[tw.site].decoder)
|
||||
else:
|
||||
tw.name = "Unknown"
|
||||
tables[len(tables)] = tw
|
||||
return tables
|
||||
|
||||
def discover_nt_by_name(c, tablename):
|
||||
"""Finds poker client window with the given table name."""
|
||||
titles = {}
|
||||
win32gui.EnumWindows(win_enum_handler, titles)
|
||||
|
||||
for hwnd in titles:
|
||||
#print "Tables.py: tablename =", tablename, "title =", titles[hwnd]
|
||||
try:
|
||||
# maybe it's better to make global titles[hwnd] decoding?
|
||||
# this can blow up in XP on some windows, eg firefox displaying http://docs.python.org/tutorial/classes.html
|
||||
if not tablename.lower() in titles[hwnd].decode(Configuration.LOCALE_ENCODING).lower():
|
||||
continue
|
||||
except:
|
||||
continue
|
||||
if 'History for table:' in titles[hwnd]: continue # Everleaf Network HH viewer window
|
||||
if 'HUD:' in titles[hwnd]: continue # FPDB HUD window
|
||||
if 'Chat:' in titles[hwnd]: continue # Some sites (FTP? PS? Others?) have seperable or seperately constructed chat windows
|
||||
if ' - Table ' in titles[hwnd]: continue # Absolute table Chat window.. sigh. TODO: Can we tell what site we're trying to discover for somehow in here, so i can limit this check just to AP searches?
|
||||
temp = decode_windows(c, titles[hwnd], hwnd)
|
||||
print _("attach to window"), temp
|
||||
return temp
|
||||
return None
|
||||
|
||||
def discover_nt_tournament(c, tour_number, tab_number):
|
||||
"""Finds the Windows window handle for the given tournament/table."""
|
||||
search_string = "%s.+%s" % (tour_number, tab_number)
|
||||
|
||||
titles ={}
|
||||
win32gui.EnumWindows(win_enum_handler, titles)
|
||||
for hwnd in titles:
|
||||
# Some sites (FTP? PS? Others?) have seperable or seperately constructed chat windows
|
||||
if 'Chat:' in titles[hwnd]: continue
|
||||
# Everleaf Network HH viewer window
|
||||
if 'History for table:' in titles[hwnd]: continue
|
||||
# FPDB HUD window
|
||||
if 'HUD:' in titles[hwnd]: continue
|
||||
|
||||
if re.search(search_string, titles[hwnd]):
|
||||
return decode_windows(c, titles[hwnd], hwnd)
|
||||
return None
|
||||
|
||||
def get_nt_exe(hwnd):
|
||||
"""Finds the name of the executable that the given window handle belongs to."""
|
||||
|
||||
# Request privileges to enable "debug process", so we can later use
|
||||
# PROCESS_VM_READ, retardedly required to GetModuleFileNameEx()
|
||||
priv_flags = win32security.TOKEN_ADJUST_PRIVILEGES | win32security.TOKEN_QUERY
|
||||
hToken = win32security.OpenProcessToken (win32api.GetCurrentProcess(),
|
||||
priv_flags)
|
||||
# enable "debug process"
|
||||
privilege_id = win32security.LookupPrivilegeValue(None,
|
||||
win32security.SE_DEBUG_NAME)
|
||||
old_privs = win32security.AdjustTokenPrivileges(hToken, 0,
|
||||
[(privilege_id,
|
||||
win32security.SE_PRIVILEGE_ENABLED)])
|
||||
|
||||
# Open the process, and query it's filename
|
||||
processid = win32process.GetWindowThreadProcessId(hwnd)
|
||||
pshandle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION |
|
||||
win32con.PROCESS_VM_READ, False,
|
||||
processid[1])
|
||||
try:
|
||||
exename = win32process.GetModuleFileNameEx(pshandle, 0)
|
||||
except pywintypes.error:
|
||||
# insert code to call GetProcessImageName if we can find it..
|
||||
# returning None from here will hopefully break all following code
|
||||
exename = None
|
||||
finally:
|
||||
# clean up
|
||||
win32api.CloseHandle(pshandle)
|
||||
win32api.CloseHandle(hToken)
|
||||
|
||||
return exename
|
||||
|
||||
def decode_windows(c, title, hwnd):
|
||||
"""Gets window parameters from the window title and handle--Windows."""
|
||||
|
||||
# I cannot figure out how to get the inside dimensions of the poker table
|
||||
# windows. So I just assume all borders are 3 thick and all title bars
|
||||
# are 29 high. No doubt this will be off when used with certain themes.
|
||||
b_width = 3
|
||||
tb_height = 29
|
||||
|
||||
info = {}
|
||||
info['number'] = hwnd
|
||||
info['title'] = re.sub('\"', '', title)
|
||||
(x, y, width, height) = win32gui.GetWindowRect(hwnd)
|
||||
|
||||
info['x'] = int(x) + b_width
|
||||
info['y'] = int( y ) + tb_height
|
||||
info['width'] = int( width ) - 2*b_width
|
||||
info['height'] = int( height ) - b_width - tb_height
|
||||
info['exe'] = get_nt_exe(hwnd)
|
||||
print "get_nt_exe returned ", info['exe']
|
||||
# TODO: 'width' here is all sorts of screwed up.
|
||||
|
||||
title_bits = re.split(' - ', info['title'])
|
||||
info['name'] = title_bits[0]
|
||||
info['site'] = get_site_from_exe(c, info['exe'])
|
||||
|
||||
return info
|
||||
|
||||
def win_enum_handler(hwnd, titles):
|
||||
str = win32gui.GetWindowText(hwnd)
|
||||
if str != "":
|
||||
titles[hwnd] = win32gui.GetWindowText(hwnd)
|
||||
|
||||
###################################################################
|
||||
# Utility routines used by all the discoverers.
|
||||
def get_site_from_exe(c, exe):
|
||||
"""Look up the site from config, given the exe."""
|
||||
for s in c.get_supported_sites():
|
||||
params = c.get_site_parameters(s)
|
||||
if re.search(params['table_finder'], exe):
|
||||
return params['site_name']
|
||||
return None
|
||||
|
||||
def everleaf_decode_table(tw):
|
||||
# 2 - Tournament ID: 573256 - NL Hold'em - 150/300 blinds - Good luck <username>! - [Connection is ...]
|
||||
pass
|
||||
|
||||
def pokerstars_decode_table(tw):
|
||||
# Extract poker information from the window title. This is not needed for
|
||||
# fpdb, since all that information is available in the db via new_hand_number.
|
||||
# This is needed only when using the HUD with a backend less integrated.
|
||||
title_bits = re.split(' - ', tw.title)
|
||||
name = title_bits[0]
|
||||
mo = re.search('Tournament (\d+) Table (\d+)', name)
|
||||
if mo:
|
||||
tw.tournament = int( mo.group(1) )
|
||||
tw.table = int( mo.group(2) )
|
||||
tw.name = name
|
||||
else:
|
||||
tw.tournament = None
|
||||
tw.name = clean_title(name)
|
||||
mo = re.search('(Razz|Stud H/L|Stud|Omaha H/L|Omaha|Hold\'em|5-Card Draw|Triple Draw 2-7 Lowball|Badugi)', tw.title)
|
||||
|
||||
tw.game = mo.group(1).lower()
|
||||
tw.game = re.sub('\'', '', tw.game)
|
||||
tw.game = re.sub('h/l', 'hi/lo', tw.game)
|
||||
|
||||
mo = re.search('(No Limit|Pot Limit)', tw.title)
|
||||
if mo:
|
||||
tw.structure = mo.group(1).lower()
|
||||
else:
|
||||
tw.structure = 'limit'
|
||||
|
||||
tw.max = None
|
||||
if tw.game in ('razz', 'stud', 'stud hi/lo'):
|
||||
tw.max = 8
|
||||
elif tw.game in ('5-card draw', 'triple draw 2-7 lowball'):
|
||||
tw.max = 6
|
||||
elif tw.game == 'holdem':
|
||||
pass
|
||||
elif tw.game in ('omaha', 'omaha hi/lo'):
|
||||
pass
|
||||
|
||||
def fulltilt_decode_table(tw):
|
||||
# Extract poker information from the window title. This is not needed for
|
||||
# fpdb, since all that information is available in the db via new_hand_number.
|
||||
# This is needed only when using the HUD with a backend less integrated.
|
||||
title_bits = re.split(' - ', tw.title)
|
||||
name = title_bits[0]
|
||||
tw.tournament = None
|
||||
tw.name = clean_title(name)
|
||||
|
||||
def clean_title(name):
|
||||
"""Clean the little info strings from the table name."""
|
||||
# these strings could go in a config file
|
||||
for pattern in [' \(6 max\)', ' \(heads up\)', ' \(deep\)',
|
||||
' \(deep hu\)', ' \(deep 6\)', '\(6 max, deep\)', ' \(2\)',
|
||||
' \(edu\)', ' \(edu, 6 max\)', ' \(6\)',
|
||||
' \(speed\)', 'special', 'newVPP',
|
||||
' no all-in', ' fast', ',', ' 50BB min', '50bb min', '\s+$']:
|
||||
name = re.sub(pattern, '', name)
|
||||
name = name.rstrip()
|
||||
return name
|
||||
|
||||
###########################################################################
|
||||
# Mac specific routines....all stubs for now
|
||||
def discover_mac_tournament(c, tour_number, tab_number):
|
||||
"""Mac users need help."""
|
||||
return None
|
||||
|
||||
def discover_mac(c):
|
||||
"""Poker client table window finder for Macintosh."""
|
||||
tables = {}
|
||||
return tables
|
||||
|
||||
def discover_mac_by_name(c, tablename):
|
||||
"""Oh, the humanity."""
|
||||
# again, i have no mac to test this on, sorry -eric
|
||||
return None
|
||||
|
||||
###########################################################################
|
||||
# Main function used for testing
|
||||
if __name__=="__main__":
|
||||
c = Configuration.Config()
|
||||
|
||||
print discover_table_by_name(c, "Torino")
|
||||
# print discover_tournament_table(c, "118942908", "3")
|
||||
|
||||
tables = discover(c)
|
||||
for t in tables.keys():
|
||||
print tables[t]
|
||||
|
||||
print _("press enter to continue")
|
||||
sys.stdin.readline()
|
|
@ -1,3 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import sys
|
||||
import os
|
||||
import codecs
|
||||
|
@ -9,13 +10,31 @@ import Database
|
|||
import SQL
|
||||
import fpdb_import
|
||||
|
||||
def error_report( filename, hand, stat, ghash, testhash, player):
|
||||
print "Regression Test Error:"
|
||||
print "\tFile: %s" % filename
|
||||
print "\tStat: %s" % stat
|
||||
print "\tPlayer: %s" % player
|
||||
|
||||
def compare(leaf, importer):
|
||||
class FpdbError:
|
||||
def __init__(self, sitename):
|
||||
self.site = sitename
|
||||
self.errorcount = 0
|
||||
self.histogram = {}
|
||||
|
||||
def error_report(self, filename, hand, stat, ghash, testhash, player):
|
||||
print "Regression Test Error:"
|
||||
print "\tFile: %s" % filename
|
||||
print "\tStat: %s" % stat
|
||||
print "\tPlayer: %s" % player
|
||||
if filename in self.histogram:
|
||||
self.histogram[filename] += 1
|
||||
else:
|
||||
self.histogram[filename] = 1
|
||||
self.errorcount += 1
|
||||
|
||||
def print_histogram(self):
|
||||
print "%s:" % self.site
|
||||
for f in self.histogram:
|
||||
idx = f.find('regression')
|
||||
print "(%3d) : %s" %(self.histogram[f], f[idx:])
|
||||
|
||||
def compare(leaf, importer, errors):
|
||||
filename = leaf
|
||||
#print "DEBUG: fileanme: %s" % filename
|
||||
|
||||
|
@ -51,21 +70,21 @@ def compare(leaf, importer):
|
|||
pass
|
||||
else:
|
||||
# Stats don't match - Doh!
|
||||
error_report(filename, hand, stat, ghash, testhash, p)
|
||||
errors.error_report(filename, hand, stat, ghash, testhash, p)
|
||||
|
||||
importer.clearFileList()
|
||||
|
||||
|
||||
|
||||
def walk_testfiles(dir, function, importer):
|
||||
def walk_testfiles(dir, function, importer, errors):
|
||||
"""Walks a directory, and executes a callback on each file """
|
||||
dir = os.path.abspath(dir)
|
||||
for file in [file for file in os.listdir(dir) if not file in [".",".."]]:
|
||||
nfile = os.path.join(dir,file)
|
||||
if os.path.isdir(nfile):
|
||||
walk_testfiles(nfile, compare, importer)
|
||||
walk_testfiles(nfile, compare, importer, errors)
|
||||
else:
|
||||
compare(nfile, importer)
|
||||
compare(nfile, importer, errors)
|
||||
|
||||
def main(argv=None):
|
||||
if argv is None:
|
||||
|
@ -76,7 +95,6 @@ def main(argv=None):
|
|||
sql = SQL.Sql(db_server = 'sqlite')
|
||||
settings = {}
|
||||
settings.update(config.get_db_parameters())
|
||||
settings.update(config.get_tv_parameters())
|
||||
settings.update(config.get_import_parameters())
|
||||
settings.update(config.get_default_paths())
|
||||
db.recreate_tables()
|
||||
|
@ -87,7 +105,25 @@ def main(argv=None):
|
|||
importer.setCallHud(False)
|
||||
importer.setFakeCacheHHC(True)
|
||||
|
||||
walk_testfiles("regression-test-files/cash/Stars/", compare, importer)
|
||||
PokerStarsErrors = FpdbError('PokerStars')
|
||||
FTPErrors = FpdbError('Full Tilt Poker')
|
||||
PartyPokerErrors = FpdbError('Party Poker')
|
||||
BetfairErrors = FpdbError('Betfair')
|
||||
|
||||
walk_testfiles("regression-test-files/cash/Stars/", compare, importer, PokerStarsErrors)
|
||||
walk_testfiles("regression-test-files/cash/FTP/", compare, importer, FTPErrors)
|
||||
walk_testfiles("regression-test-files/cash/PartyPoker/", compare, importer, PartyPokerErrors)
|
||||
walk_testfiles("regression-test-files/cash/Betfair/", compare, importer, BetfairErrors)
|
||||
|
||||
totalerrors = PokerStarsErrors.errorcount + FTPErrors.errorcount + PartyPokerErrors.errorcount + BetfairErrors.errorcount
|
||||
|
||||
print "---------------------"
|
||||
print "Total Errors: %d" % totalerrors
|
||||
print "---------------------"
|
||||
PokerStarsErrors.print_histogram()
|
||||
FTPErrors.print_histogram()
|
||||
PartyPokerErrors.print_histogram()
|
||||
BetfairErrors.print_histogram()
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
|
|
@ -77,7 +77,7 @@ class TourneySummary(object):
|
|||
self.buyin = None
|
||||
self.fee = None
|
||||
self.hero = None
|
||||
self.maxseats = None
|
||||
self.maxseats = 0
|
||||
self.entries = 0
|
||||
self.speed = "Normal"
|
||||
self.prizepool = 0 # Make it a dict in order to deal (eventually later) with non-money winnings : {'MONEY' : amount, 'OTHER' : Value ??}
|
||||
|
|
|
@ -40,6 +40,18 @@ import win32api
|
|||
import win32con
|
||||
import win32security
|
||||
|
||||
import locale
|
||||
lang=locale.getdefaultlocale()[0][0:2]
|
||||
if lang=="en":
|
||||
def _(string): return string
|
||||
else:
|
||||
import gettext
|
||||
try:
|
||||
trans = gettext.translation("fpdb", localedir="locale", languages=[lang])
|
||||
trans.install()
|
||||
except IOError:
|
||||
def _(string): return string
|
||||
|
||||
# FreePokerTools modules
|
||||
from TableWindow import Table_Window
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
python /usr/share/doc/python-2.7/examples/Tools/i18n/msgfmt.py --output-file=locale/hu/LC_MESSAGES/fpdb.mo locale/fpdb-hu_HU.po
|
|
@ -129,7 +129,7 @@ import Configuration
|
|||
import Exceptions
|
||||
import Stats
|
||||
|
||||
VERSION = "0.20.904 plus git"
|
||||
VERSION = "0.20.906"
|
||||
|
||||
|
||||
class fpdb:
|
||||
|
@ -264,7 +264,8 @@ class fpdb:
|
|||
, ('numpy', numpy_version)
|
||||
, ('sqlite3', sqlite3_version)
|
||||
, ('sqlite', sqlite_version)
|
||||
, ('database', self.settings['db-server'] + db_version)
|
||||
, ('fpdb version', VERSION)
|
||||
, ('database used', self.settings['db-server'])
|
||||
]
|
||||
versions = gtk.TextBuffer()
|
||||
w = 20 # width used for module names and version numbers
|
||||
|
@ -786,7 +787,6 @@ class fpdb:
|
|||
<menuitem action="Quit"/>
|
||||
</menu>
|
||||
<menu action="import">
|
||||
<menuitem action="sethharchive"/>
|
||||
<menuitem action="bulkimp"/>
|
||||
<menuitem action="imapimport"/>
|
||||
<menuitem action="autoimp"/>
|
||||
|
@ -828,15 +828,14 @@ class fpdb:
|
|||
('SaveProf', None, _('_Save Profile (todo)'), _('<control>S'), 'Save your profile', self.dia_save_profile),
|
||||
('Preferences', None, _('Pre_ferences'), _('<control>F'), 'Edit your preferences', self.dia_preferences),
|
||||
('import', None, _('_Import')),
|
||||
('sethharchive', None, _('_Set HandHistory Archive Directory'), None, 'Set HandHistory Archive Directory', self.select_hhArchiveBase),
|
||||
('bulkimp', None, _('_Bulk Import'), _('<control>B'), 'Bulk Import', self.tab_bulk_import),
|
||||
('imapimport', None, _('_Import through eMail/IMAP'), _('<control>I'), 'Import through eMail/IMAP', self.tab_imap_import),
|
||||
('viewers', None, _('_Viewers')),
|
||||
('autoimp', None, _('_Auto Import and HUD'), _('<control>A'), 'Auto Import and HUD', self.tab_auto_import),
|
||||
('hudConfigurator', None, _('_HUD Configurator'), _('<control>H'), 'HUD Configurator', self.diaHudConfigurator),
|
||||
('graphs', None, _('_Graphs'), _('<control>G'), 'Graphs', self.tabGraphViewer),
|
||||
('ringplayerstats', None, _('Ring _Player Stats (tabulated view)'), _('<control>P'), 'Ring Player Stats (tabulated view)', self.tab_ring_player_stats),
|
||||
('tourneyplayerstats', None, _('_Tourney Player Stats (tabulated view)'), _('<control>T'), 'Tourney Player Stats (tabulated view, mysql only)', self.tab_tourney_player_stats),
|
||||
('ringplayerstats', None, _('Ring _Player Stats (tabulated view, not on pgsql)'), _('<control>P'), 'Ring Player Stats (tabulated view)', self.tab_ring_player_stats),
|
||||
('tourneyplayerstats', None, _('_Tourney Player Stats (tabulated view, not on pgsql)'), _('<control>T'), 'Tourney Player Stats (tabulated view, mysql only)', self.tab_tourney_player_stats),
|
||||
('tourneyviewer', None, _('Tourney _Viewer'), None, 'Tourney Viewer)', self.tab_tourney_viewer_stats),
|
||||
('posnstats', None, _('P_ositional Stats (tabulated view, not on sqlite)'), _('<control>O'), 'Positional Stats (tabulated view)', self.tab_positional_stats),
|
||||
('sessionstats', None, _('Session Stats'), None, 'Session Stats', self.tab_session_stats),
|
||||
|
@ -888,7 +887,6 @@ class fpdb:
|
|||
|
||||
self.settings.update({'cl_options': cl_options})
|
||||
self.settings.update(self.config.get_db_parameters())
|
||||
self.settings.update(self.config.get_tv_parameters())
|
||||
self.settings.update(self.config.get_import_parameters())
|
||||
self.settings.update(self.config.get_default_paths())
|
||||
|
||||
|
@ -1253,16 +1251,6 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an
|
|||
elif response == gtk.RESPONSE_NO:
|
||||
self.select_hhArchiveBase()
|
||||
|
||||
def select_hhArchiveBase(self, widget=None):
|
||||
fc = gtk.FileChooserDialog(title=_("Select HH Output Directory"), parent=None, action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, buttons=(gtk.STOCK_OPEN,gtk.RESPONSE_OK), backend=None)
|
||||
fc.run()
|
||||
# TODO: We need to put in a Cancel button, and handle if the user presses that or the "Close" box without selecting anything as a cancel, and return to the prior setting
|
||||
#self.warning_box("You selected %s" % fc.get_filename())
|
||||
self.config.set_hhArchiveBase(fc.get_filename())
|
||||
self.config.save()
|
||||
self.load_profile() # we can't do this at the end of this func because load_profile calls this func
|
||||
fc.destroy() # TODO: loop this to make sure we get valid data back from it, because the open directory thing in GTK lets you select files and not select things and other stupid bullshit
|
||||
|
||||
def main(self):
|
||||
gtk.main()
|
||||
return 0
|
||||
|
|
|
@ -10,6 +10,18 @@ import time
|
|||
import signal
|
||||
import base64
|
||||
|
||||
import locale
|
||||
lang=locale.getdefaultlocale()[0][0:2]
|
||||
if lang=="en":
|
||||
def _(string): return string
|
||||
else:
|
||||
import gettext
|
||||
try:
|
||||
trans = gettext.translation("fpdb", localedir="locale", languages=[lang])
|
||||
trans.install()
|
||||
except IOError:
|
||||
def _(string): return string
|
||||
|
||||
InterProcessLock = None
|
||||
|
||||
"""
|
||||
|
|
4
pyfpdb/locale/create-mo-files.sh
Executable file
4
pyfpdb/locale/create-mo-files.sh
Executable file
|
@ -0,0 +1,4 @@
|
|||
cd ..
|
||||
python /usr/share/doc/python-2.7/examples/Tools/i18n/msgfmt.py --output-file=locale/hu/LC_MESSAGES/fpdb.mo locale/fpdb-hu_HU.po
|
||||
python /usr/share/doc/python-2.7/examples/Tools/i18n/msgfmt.py --output-file=locale/de/LC_MESSAGES/fpdb.mo locale/fpdb-de_DE.po
|
||||
|
|
@ -1,2 +1,3 @@
|
|||
cd ..
|
||||
python /usr/share/doc/python-2.7/examples/Tools/i18n/pygettext.py --output-dir=locale --default-domain=fpdb --output=fpdb-en_GB.po *.py*
|
||||
|
Binary file not shown.
3102
pyfpdb/locale/fpdb-de_DE.po
Normal file
3102
pyfpdb/locale/fpdb-de_DE.po
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -1,2 +1,3 @@
|
|||
msgmerge --update fpdb-hu_HU.po fpdb-en_GB.po
|
||||
msgmerge --update fpdb-de_DE.po fpdb-en_GB.po
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
Game #9485557849 starts.
|
||||
|
||||
#Game No : 9485557849
|
||||
***** Hand History for Game 9485557849 *****
|
||||
$0.80 USD NL Texas Hold'em - Saturday, July 31, 13:52:16 EDT 2010
|
||||
Table 20BB Min Speed #1770998 (Real Money)
|
||||
Seat 1 is the button
|
||||
Total number of players : 4/9
|
||||
Seat 3: Player1 ( $1.64 USD )
|
||||
Seat 5: Player2 ( $0.01 USD )
|
||||
Seat 9: Player3 ( $1.02 USD )
|
||||
Seat 1: Player4 ( $1.20 USD )
|
||||
Player1 posts small blind [$0.01 USD].
|
||||
Player2 posts big blind [$0.01 USD].
|
||||
** Dealing down cards **
|
||||
Dealt to Player1 [ 8h Kc ]
|
||||
Player3 folds
|
||||
Player4 calls [$0.02 USD]
|
||||
Player1 calls [$0.01 USD]
|
||||
** Dealing Flop ** [ Td, 7c, 9h ]
|
||||
Player1 checks
|
||||
Player4 checks
|
||||
** Dealing Turn ** [ 3h ]
|
||||
Player1 checks
|
||||
Player4 checks
|
||||
** Dealing River ** [ Jc ]
|
||||
Player1 bets [$0.04 USD]
|
||||
Player4 folds
|
||||
Player1 shows [ 8h, Kc ]a straight, Seven to Jack.
|
||||
Player2 doesn't show [ Ts, Jd ]two pairs, Jacks and Tens.
|
||||
Player1 wins $0.06 USD from the side pot 1 with a straight, Seven to Jack.
|
||||
Player1 wins $0.03 USD from the main pot with a straight, Seven to Jack.
|
||||
Player2 has left the table.
|
|
@ -1,63 +0,0 @@
|
|||
Game #9485557849 starts.
|
||||
|
||||
#Game No : 9485557849
|
||||
***** Hand History for Game 9485557849 *****
|
||||
$0.80 USD NL Texas Hold'em - Saturday, July 31, 13:52:16 EDT 2010
|
||||
Table 20BB Min Speed #1770998 (Real Money)
|
||||
Seat 1 is the button
|
||||
Total number of players : 4/9
|
||||
Seat 3: FErki84 ( $1.64 USD )
|
||||
Seat 5: Vandercasses ( $0.01 USD )
|
||||
Seat 9: jeremyho888 ( $1.02 USD )
|
||||
Seat 1: sergeodem ( $1.20 USD )
|
||||
FErki84 posts small blind [$0.01 USD].
|
||||
Vandercasses posts big blind [$0.01 USD].
|
||||
** Dealing down cards **
|
||||
Dealt to FErki84 [ 8h Kc ]
|
||||
jeremyho888 folds
|
||||
sergeodem calls [$0.02 USD]
|
||||
FErki84 calls [$0.01 USD]
|
||||
** Dealing Flop ** [ Td, 7c, 9h ]
|
||||
FErki84 checks
|
||||
sergeodem checks
|
||||
** Dealing Turn ** [ 3h ]
|
||||
FErki84 checks
|
||||
sergeodem checks
|
||||
** Dealing River ** [ Jc ]
|
||||
FErki84 bets [$0.04 USD]
|
||||
sergeodem folds
|
||||
FErki84 shows [ 8h, Kc ]a straight, Seven to Jack.
|
||||
Vandercasses doesn't show [ Ts, Jd ]two pairs, Jacks and Tens.
|
||||
FErki84 wins $0.06 USD from the side pot 1 with a straight, Seven to Jack.
|
||||
FErki84 wins $0.03 USD from the main pot with a straight, Seven to Jack.
|
||||
Vandercasses has left the table.
|
||||
|
||||
Game #9498788316 starts.
|
||||
|
||||
#Game No : 9498788316
|
||||
***** Hand History for Game 9498788316 *****
|
||||
$1.60 USD NL Texas Hold'em - Wednesday, August 04, 15:02:33 EDT 2010
|
||||
Table 20BB Min #1847547 (No DP) (Real Money)
|
||||
Seat 2 is the button
|
||||
Total number of players : 5/6
|
||||
Seat 5: CepguTbIu999 ( $1.60 USD )
|
||||
Seat 1: Daytona_955 ( $2.45 USD )
|
||||
Seat 4: FErki84 ( $2.18 USD )
|
||||
Seat 2: anjl2009 ( $2.80 USD )
|
||||
Seat 3: lukeman2 ( $0.01 USD )
|
||||
lukeman2 posts small blind [$0.01 USD].
|
||||
FErki84 posts big blind [$0.04 USD].
|
||||
** Dealing down cards **
|
||||
Dealt to FErki84 [ 6s 2c ]
|
||||
CepguTbIu999 folds
|
||||
Daytona_955 folds
|
||||
anjl2009 folds
|
||||
** Dealing Flop ** [ 9d, Ah, 3h ]
|
||||
** Dealing Turn ** [ Js ]
|
||||
** Dealing River ** [ Kc ]
|
||||
lukeman2 shows [ 5h, 5s ]a pair of Fives.
|
||||
FErki84 shows [ 6s, 2c ]high card Ace.
|
||||
FErki84 wins $0.03 USD from the side pot 1 with high card, Ace.
|
||||
lukeman2 wins $0.02 USD from the main pot with a pair of Fives.
|
||||
lukeman2 has left the table.
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
Game #9498788316 starts.
|
||||
|
||||
#Game No : 9498788316
|
||||
***** Hand History for Game 9498788316 *****
|
||||
$1.60 USD NL Texas Hold'em - Wednesday, August 04, 15:02:33 EDT 2010
|
||||
Table 20BB Min #1847547 (No DP) (Real Money)
|
||||
Seat 2 is the button
|
||||
Total number of players : 5/6
|
||||
Seat 5: Player1 ( $1.60 USD )
|
||||
Seat 1: Player2 ( $2.45 USD )
|
||||
Seat 4: Player3 ( $2.18 USD )
|
||||
Seat 2: Player4 ( $2.80 USD )
|
||||
Seat 3: Player5 ( $0.01 USD )
|
||||
Player5 posts small blind [$0.01 USD].
|
||||
Player3 posts big blind [$0.04 USD].
|
||||
** Dealing down cards **
|
||||
Dealt to Player3 [ 6s 2c ]
|
||||
Player1 folds
|
||||
Player2 folds
|
||||
Player4 folds
|
||||
** Dealing Flop ** [ 9d, Ah, 3h ]
|
||||
** Dealing Turn ** [ Js ]
|
||||
** Dealing River ** [ Kc ]
|
||||
Player5 shows [ 5h, 5s ]a pair of Fives.
|
||||
Player3 shows [ 6s, 2c ]high card Ace.
|
||||
Player3 wins $0.03 USD from the side pot 1 with high card, Ace.
|
||||
Player5 wins $0.02 USD from the main pot with a pair of Fives.
|
||||
Player5 has left the table.
|
|
@ -1,5 +1,5 @@
|
|||
fpdb database dump
|
||||
DB version=142
|
||||
DB version=143
|
||||
|
||||
###################
|
||||
Table Autorates
|
||||
|
@ -1644,10 +1644,20 @@ Table Players
|
|||
commentTs=None
|
||||
|
||||
|
||||
###################
|
||||
Table RawHands
|
||||
###################
|
||||
empty table
|
||||
|
||||
###################
|
||||
Table RawTourneys
|
||||
###################
|
||||
empty table
|
||||
|
||||
###################
|
||||
Table Settings
|
||||
###################
|
||||
version=142
|
||||
version=143
|
||||
|
||||
|
||||
###################
|
||||
|
|
|
@ -0,0 +1,752 @@
|
|||
{ u'123smoothie': { 'card1': 0,
|
||||
'card2': 0,
|
||||
'card3': 29,
|
||||
'card4': 28,
|
||||
'card5': 47,
|
||||
'card6': 0,
|
||||
'card7': 0,
|
||||
'foldBbToStealChance': False,
|
||||
'foldSbToStealChance': False,
|
||||
'foldToOtherRaisedStreet0': False,
|
||||
'foldToOtherRaisedStreet1': False,
|
||||
'foldToOtherRaisedStreet2': True,
|
||||
'foldToOtherRaisedStreet3': False,
|
||||
'foldToOtherRaisedStreet4': False,
|
||||
'foldToStreet1CBChance': False,
|
||||
'foldToStreet1CBDone': False,
|
||||
'foldToStreet2CBChance': False,
|
||||
'foldToStreet2CBDone': False,
|
||||
'foldToStreet3CBChance': False,
|
||||
'foldToStreet3CBDone': False,
|
||||
'foldToStreet4CBChance': False,
|
||||
'foldToStreet4CBDone': False,
|
||||
'foldedBbToSteal': False,
|
||||
'foldedSbToSteal': False,
|
||||
'other3BStreet0': False,
|
||||
'other4BStreet0': False,
|
||||
'otherRaisedStreet0': False,
|
||||
'otherRaisedStreet1': False,
|
||||
'otherRaisedStreet2': True,
|
||||
'otherRaisedStreet3': False,
|
||||
'otherRaisedStreet4': False,
|
||||
'position': 1,
|
||||
'raiseFirstInChance': False,
|
||||
'raisedFirstIn': False,
|
||||
'rake': 0,
|
||||
'sawShowdown': False,
|
||||
'seatNo': 2,
|
||||
'sitout': False,
|
||||
'startCards': 0,
|
||||
'startCash': 99,
|
||||
'street0Aggr': False,
|
||||
'street0Bets': 0,
|
||||
'street0Calls': 1,
|
||||
'street0Raises': 0,
|
||||
'street0VPI': True,
|
||||
'street0_3BChance': False,
|
||||
'street0_3BDone': False,
|
||||
'street0_4BChance': False,
|
||||
'street0_4BDone': False,
|
||||
'street1Aggr': False,
|
||||
'street1Bets': 0,
|
||||
'street1CBChance': False,
|
||||
'street1CBDone': False,
|
||||
'street1Calls': 0,
|
||||
'street1CheckCallRaiseChance': False,
|
||||
'street1CheckCallRaiseDone': False,
|
||||
'street1Raises': 0,
|
||||
'street1Seen': True,
|
||||
'street2Aggr': False,
|
||||
'street2Bets': 0,
|
||||
'street2CBChance': False,
|
||||
'street2CBDone': False,
|
||||
'street2Calls': 0,
|
||||
'street2CheckCallRaiseChance': False,
|
||||
'street2CheckCallRaiseDone': False,
|
||||
'street2Raises': 0,
|
||||
'street2Seen': True,
|
||||
'street3Aggr': False,
|
||||
'street3Bets': 0,
|
||||
'street3CBChance': False,
|
||||
'street3CBDone': False,
|
||||
'street3Calls': 0,
|
||||
'street3CheckCallRaiseChance': True,
|
||||
'street3CheckCallRaiseDone': False,
|
||||
'street3Raises': 0,
|
||||
'street3Seen': False,
|
||||
'street4Aggr': False,
|
||||
'street4Bets': 0,
|
||||
'street4CBChance': False,
|
||||
'street4CBDone': False,
|
||||
'street4Calls': 0,
|
||||
'street4CheckCallRaiseChance': False,
|
||||
'street4CheckCallRaiseDone': False,
|
||||
'street4Raises': 0,
|
||||
'street4Seen': False,
|
||||
'totalProfit': -3,
|
||||
'tourneyTypeId': None,
|
||||
'tourneysPlayersIds': None,
|
||||
'winnings': 0,
|
||||
'wonAtSD': 0.0,
|
||||
'wonWhenSeenStreet1': 0.0,
|
||||
'wonWhenSeenStreet2': 0.0,
|
||||
'wonWhenSeenStreet3': 0.0,
|
||||
'wonWhenSeenStreet4': 0.0},
|
||||
u'Soroka69': { 'card1': 0,
|
||||
'card2': 0,
|
||||
'card3': 19,
|
||||
'card4': 43,
|
||||
'card5': 30,
|
||||
'card6': 40,
|
||||
'card7': 0,
|
||||
'foldBbToStealChance': False,
|
||||
'foldSbToStealChance': False,
|
||||
'foldToOtherRaisedStreet0': False,
|
||||
'foldToOtherRaisedStreet1': False,
|
||||
'foldToOtherRaisedStreet2': False,
|
||||
'foldToOtherRaisedStreet3': False,
|
||||
'foldToOtherRaisedStreet4': True,
|
||||
'foldToStreet1CBChance': False,
|
||||
'foldToStreet1CBDone': False,
|
||||
'foldToStreet2CBChance': False,
|
||||
'foldToStreet2CBDone': False,
|
||||
'foldToStreet3CBChance': False,
|
||||
'foldToStreet3CBDone': False,
|
||||
'foldToStreet4CBChance': False,
|
||||
'foldToStreet4CBDone': False,
|
||||
'foldedBbToSteal': False,
|
||||
'foldedSbToSteal': False,
|
||||
'other3BStreet0': False,
|
||||
'other4BStreet0': False,
|
||||
'otherRaisedStreet0': False,
|
||||
'otherRaisedStreet1': False,
|
||||
'otherRaisedStreet2': True,
|
||||
'otherRaisedStreet3': True,
|
||||
'otherRaisedStreet4': True,
|
||||
'position': 4,
|
||||
'raiseFirstInChance': False,
|
||||
'raisedFirstIn': False,
|
||||
'rake': 0,
|
||||
'sawShowdown': False,
|
||||
'seatNo': 7,
|
||||
'sitout': False,
|
||||
'startCards': 0,
|
||||
'startCash': 83,
|
||||
'street0Aggr': False,
|
||||
'street0Bets': 0,
|
||||
'street0Calls': 1,
|
||||
'street0Raises': 0,
|
||||
'street0VPI': True,
|
||||
'street0_3BChance': False,
|
||||
'street0_3BDone': False,
|
||||
'street0_4BChance': False,
|
||||
'street0_4BDone': False,
|
||||
'street1Aggr': False,
|
||||
'street1Bets': 0,
|
||||
'street1CBChance': False,
|
||||
'street1CBDone': False,
|
||||
'street1Calls': 0,
|
||||
'street1CheckCallRaiseChance': False,
|
||||
'street1CheckCallRaiseDone': False,
|
||||
'street1Raises': 0,
|
||||
'street1Seen': True,
|
||||
'street2Aggr': False,
|
||||
'street2Bets': 0,
|
||||
'street2CBChance': False,
|
||||
'street2CBDone': False,
|
||||
'street2Calls': 1,
|
||||
'street2CheckCallRaiseChance': False,
|
||||
'street2CheckCallRaiseDone': False,
|
||||
'street2Raises': 0,
|
||||
'street2Seen': True,
|
||||
'street3Aggr': False,
|
||||
'street3Bets': 0,
|
||||
'street3CBChance': False,
|
||||
'street3CBDone': False,
|
||||
'street3Calls': 1,
|
||||
'street3CheckCallRaiseChance': True,
|
||||
'street3CheckCallRaiseDone': True,
|
||||
'street3Raises': 0,
|
||||
'street3Seen': True,
|
||||
'street4Aggr': False,
|
||||
'street4Bets': 0,
|
||||
'street4CBChance': False,
|
||||
'street4CBDone': False,
|
||||
'street4Calls': 0,
|
||||
'street4CheckCallRaiseChance': True,
|
||||
'street4CheckCallRaiseDone': True,
|
||||
'street4Raises': 0,
|
||||
'street4Seen': True,
|
||||
'totalProfit': -19,
|
||||
'tourneyTypeId': None,
|
||||
'tourneysPlayersIds': None,
|
||||
'winnings': 0,
|
||||
'wonAtSD': 0.0,
|
||||
'wonWhenSeenStreet1': 0.0,
|
||||
'wonWhenSeenStreet2': 0.0,
|
||||
'wonWhenSeenStreet3': 0.0,
|
||||
'wonWhenSeenStreet4': 0.0},
|
||||
u'TomSludge': { 'card1': 0,
|
||||
'card2': 0,
|
||||
'card3': 46,
|
||||
'card4': 0,
|
||||
'card5': 0,
|
||||
'card6': 0,
|
||||
'card7': 0,
|
||||
'foldBbToStealChance': False,
|
||||
'foldSbToStealChance': False,
|
||||
'foldToOtherRaisedStreet0': False,
|
||||
'foldToOtherRaisedStreet1': False,
|
||||
'foldToOtherRaisedStreet2': False,
|
||||
'foldToOtherRaisedStreet3': False,
|
||||
'foldToOtherRaisedStreet4': False,
|
||||
'foldToStreet1CBChance': False,
|
||||
'foldToStreet1CBDone': False,
|
||||
'foldToStreet2CBChance': False,
|
||||
'foldToStreet2CBDone': False,
|
||||
'foldToStreet3CBChance': False,
|
||||
'foldToStreet3CBDone': False,
|
||||
'foldToStreet4CBChance': False,
|
||||
'foldToStreet4CBDone': False,
|
||||
'foldedBbToSteal': False,
|
||||
'foldedSbToSteal': False,
|
||||
'other3BStreet0': False,
|
||||
'other4BStreet0': False,
|
||||
'otherRaisedStreet0': False,
|
||||
'otherRaisedStreet1': False,
|
||||
'otherRaisedStreet2': False,
|
||||
'otherRaisedStreet3': False,
|
||||
'otherRaisedStreet4': False,
|
||||
'position': 5,
|
||||
'raiseFirstInChance': False,
|
||||
'raisedFirstIn': False,
|
||||
'rake': 0,
|
||||
'sawShowdown': False,
|
||||
'seatNo': 6,
|
||||
'sitout': False,
|
||||
'startCards': 0,
|
||||
'startCash': 158,
|
||||
'street0Aggr': False,
|
||||
'street0Bets': 0,
|
||||
'street0Calls': 0,
|
||||
'street0Raises': 0,
|
||||
'street0VPI': False,
|
||||
'street0_3BChance': False,
|
||||
'street0_3BDone': False,
|
||||
'street0_4BChance': False,
|
||||
'street0_4BDone': False,
|
||||
'street1Aggr': False,
|
||||
'street1Bets': 0,
|
||||
'street1CBChance': False,
|
||||
'street1CBDone': False,
|
||||
'street1Calls': 0,
|
||||
'street1CheckCallRaiseChance': False,
|
||||
'street1CheckCallRaiseDone': False,
|
||||
'street1Raises': 0,
|
||||
'street1Seen': False,
|
||||
'street2Aggr': False,
|
||||
'street2Bets': 0,
|
||||
'street2CBChance': False,
|
||||
'street2CBDone': False,
|
||||
'street2Calls': 0,
|
||||
'street2CheckCallRaiseChance': False,
|
||||
'street2CheckCallRaiseDone': False,
|
||||
'street2Raises': 0,
|
||||
'street2Seen': False,
|
||||
'street3Aggr': False,
|
||||
'street3Bets': 0,
|
||||
'street3CBChance': False,
|
||||
'street3CBDone': False,
|
||||
'street3Calls': 0,
|
||||
'street3CheckCallRaiseChance': False,
|
||||
'street3CheckCallRaiseDone': False,
|
||||
'street3Raises': 0,
|
||||
'street3Seen': False,
|
||||
'street4Aggr': False,
|
||||
'street4Bets': 0,
|
||||
'street4CBChance': False,
|
||||
'street4CBDone': False,
|
||||
'street4Calls': 0,
|
||||
'street4CheckCallRaiseChance': False,
|
||||
'street4CheckCallRaiseDone': False,
|
||||
'street4Raises': 0,
|
||||
'street4Seen': False,
|
||||
'totalProfit': -1,
|
||||
'tourneyTypeId': None,
|
||||
'tourneysPlayersIds': None,
|
||||
'winnings': 0,
|
||||
'wonAtSD': 0.0,
|
||||
'wonWhenSeenStreet1': 0.0,
|
||||
'wonWhenSeenStreet2': 0.0,
|
||||
'wonWhenSeenStreet3': 0.0,
|
||||
'wonWhenSeenStreet4': 0.0},
|
||||
u'denny501': { 'card1': 0,
|
||||
'card2': 0,
|
||||
'card3': 27,
|
||||
'card4': 45,
|
||||
'card5': 0,
|
||||
'card6': 0,
|
||||
'card7': 0,
|
||||
'foldBbToStealChance': False,
|
||||
'foldSbToStealChance': False,
|
||||
'foldToOtherRaisedStreet0': False,
|
||||
'foldToOtherRaisedStreet1': False,
|
||||
'foldToOtherRaisedStreet2': False,
|
||||
'foldToOtherRaisedStreet3': False,
|
||||
'foldToOtherRaisedStreet4': False,
|
||||
'foldToStreet1CBChance': False,
|
||||
'foldToStreet1CBDone': False,
|
||||
'foldToStreet2CBChance': False,
|
||||
'foldToStreet2CBDone': False,
|
||||
'foldToStreet3CBChance': False,
|
||||
'foldToStreet3CBDone': False,
|
||||
'foldToStreet4CBChance': False,
|
||||
'foldToStreet4CBDone': False,
|
||||
'foldedBbToSteal': False,
|
||||
'foldedSbToSteal': False,
|
||||
'other3BStreet0': False,
|
||||
'other4BStreet0': False,
|
||||
'otherRaisedStreet0': False,
|
||||
'otherRaisedStreet1': False,
|
||||
'otherRaisedStreet2': False,
|
||||
'otherRaisedStreet3': False,
|
||||
'otherRaisedStreet4': False,
|
||||
'position': 'S',
|
||||
'raiseFirstInChance': True,
|
||||
'raisedFirstIn': False,
|
||||
'rake': 0,
|
||||
'sawShowdown': False,
|
||||
'seatNo': 4,
|
||||
'sitout': False,
|
||||
'startCards': 0,
|
||||
'startCash': 71,
|
||||
'street0Aggr': False,
|
||||
'street0Bets': 0,
|
||||
'street0Calls': 0,
|
||||
'street0Raises': 0,
|
||||
'street0VPI': False,
|
||||
'street0_3BChance': False,
|
||||
'street0_3BDone': False,
|
||||
'street0_4BChance': False,
|
||||
'street0_4BDone': False,
|
||||
'street1Aggr': False,
|
||||
'street1Bets': 0,
|
||||
'street1CBChance': False,
|
||||
'street1CBDone': False,
|
||||
'street1Calls': 0,
|
||||
'street1CheckCallRaiseChance': False,
|
||||
'street1CheckCallRaiseDone': False,
|
||||
'street1Raises': 0,
|
||||
'street1Seen': True,
|
||||
'street2Aggr': False,
|
||||
'street2Bets': 0,
|
||||
'street2CBChance': False,
|
||||
'street2CBDone': False,
|
||||
'street2Calls': 0,
|
||||
'street2CheckCallRaiseChance': False,
|
||||
'street2CheckCallRaiseDone': False,
|
||||
'street2Raises': 0,
|
||||
'street2Seen': False,
|
||||
'street3Aggr': False,
|
||||
'street3Bets': 0,
|
||||
'street3CBChance': False,
|
||||
'street3CBDone': False,
|
||||
'street3Calls': 0,
|
||||
'street3CheckCallRaiseChance': False,
|
||||
'street3CheckCallRaiseDone': False,
|
||||
'street3Raises': 0,
|
||||
'street3Seen': False,
|
||||
'street4Aggr': False,
|
||||
'street4Bets': 0,
|
||||
'street4CBChance': False,
|
||||
'street4CBDone': False,
|
||||
'street4Calls': 0,
|
||||
'street4CheckCallRaiseChance': False,
|
||||
'street4CheckCallRaiseDone': False,
|
||||
'street4Raises': 0,
|
||||
'street4Seen': False,
|
||||
'totalProfit': -3,
|
||||
'tourneyTypeId': None,
|
||||
'tourneysPlayersIds': None,
|
||||
'winnings': 0,
|
||||
'wonAtSD': 0.0,
|
||||
'wonWhenSeenStreet1': 0.0,
|
||||
'wonWhenSeenStreet2': 0.0,
|
||||
'wonWhenSeenStreet3': 0.0,
|
||||
'wonWhenSeenStreet4': 0.0},
|
||||
u'gashpor': { 'card1': 3,
|
||||
'card2': 15,
|
||||
'card3': 17,
|
||||
'card4': 24,
|
||||
'card5': 23,
|
||||
'card6': 21,
|
||||
'card7': 5,
|
||||
'foldBbToStealChance': False,
|
||||
'foldSbToStealChance': False,
|
||||
'foldToOtherRaisedStreet0': False,
|
||||
'foldToOtherRaisedStreet1': False,
|
||||
'foldToOtherRaisedStreet2': False,
|
||||
'foldToOtherRaisedStreet3': False,
|
||||
'foldToOtherRaisedStreet4': False,
|
||||
'foldToStreet1CBChance': False,
|
||||
'foldToStreet1CBDone': False,
|
||||
'foldToStreet2CBChance': False,
|
||||
'foldToStreet2CBDone': False,
|
||||
'foldToStreet3CBChance': False,
|
||||
'foldToStreet3CBDone': False,
|
||||
'foldToStreet4CBChance': False,
|
||||
'foldToStreet4CBDone': False,
|
||||
'foldedBbToSteal': False,
|
||||
'foldedSbToSteal': False,
|
||||
'other3BStreet0': False,
|
||||
'other4BStreet0': False,
|
||||
'otherRaisedStreet0': False,
|
||||
'otherRaisedStreet1': False,
|
||||
'otherRaisedStreet2': False,
|
||||
'otherRaisedStreet3': False,
|
||||
'otherRaisedStreet4': False,
|
||||
'position': 0,
|
||||
'raiseFirstInChance': False,
|
||||
'raisedFirstIn': False,
|
||||
'rake': 2,
|
||||
'sawShowdown': True,
|
||||
'seatNo': 3,
|
||||
'sitout': False,
|
||||
'startCards': 0,
|
||||
'startCash': 140,
|
||||
'street0Aggr': False,
|
||||
'street0Bets': 0,
|
||||
'street0Calls': 1,
|
||||
'street0Raises': 0,
|
||||
'street0VPI': True,
|
||||
'street0_3BChance': False,
|
||||
'street0_3BDone': False,
|
||||
'street0_4BChance': False,
|
||||
'street0_4BDone': False,
|
||||
'street1Aggr': False,
|
||||
'street1Bets': 0,
|
||||
'street1CBChance': False,
|
||||
'street1CBDone': False,
|
||||
'street1Calls': 0,
|
||||
'street1CheckCallRaiseChance': False,
|
||||
'street1CheckCallRaiseDone': False,
|
||||
'street1Raises': 0,
|
||||
'street1Seen': True,
|
||||
'street2Aggr': True,
|
||||
'street2Bets': 1,
|
||||
'street2CBChance': False,
|
||||
'street2CBDone': False,
|
||||
'street2Calls': 0,
|
||||
'street2CheckCallRaiseChance': False,
|
||||
'street2CheckCallRaiseDone': False,
|
||||
'street2Raises': 0,
|
||||
'street2Seen': True,
|
||||
'street3Aggr': True,
|
||||
'street3Bets': 1,
|
||||
'street3CBChance': True,
|
||||
'street3CBDone': True,
|
||||
'street3Calls': 0,
|
||||
'street3CheckCallRaiseChance': False,
|
||||
'street3CheckCallRaiseDone': False,
|
||||
'street3Raises': 0,
|
||||
'street3Seen': True,
|
||||
'street4Aggr': True,
|
||||
'street4Bets': 1,
|
||||
'street4CBChance': True,
|
||||
'street4CBDone': True,
|
||||
'street4Calls': 0,
|
||||
'street4CheckCallRaiseChance': False,
|
||||
'street4CheckCallRaiseDone': False,
|
||||
'street4Raises': 0,
|
||||
'street4Seen': True,
|
||||
'totalProfit': 13,
|
||||
'tourneyTypeId': None,
|
||||
'tourneysPlayersIds': None,
|
||||
'winnings': 40,
|
||||
'wonAtSD': 1.0,
|
||||
'wonWhenSeenStreet1': 1.0,
|
||||
'wonWhenSeenStreet2': 0.0,
|
||||
'wonWhenSeenStreet3': 0.0,
|
||||
'wonWhenSeenStreet4': 0.0},
|
||||
u'rdiezchang': { 'card1': 0,
|
||||
'card2': 0,
|
||||
'card3': 26,
|
||||
'card4': 49,
|
||||
'card5': 48,
|
||||
'card6': 0,
|
||||
'card7': 0,
|
||||
'foldBbToStealChance': False,
|
||||
'foldSbToStealChance': False,
|
||||
'foldToOtherRaisedStreet0': False,
|
||||
'foldToOtherRaisedStreet1': False,
|
||||
'foldToOtherRaisedStreet2': True,
|
||||
'foldToOtherRaisedStreet3': False,
|
||||
'foldToOtherRaisedStreet4': False,
|
||||
'foldToStreet1CBChance': False,
|
||||
'foldToStreet1CBDone': False,
|
||||
'foldToStreet2CBChance': False,
|
||||
'foldToStreet2CBDone': False,
|
||||
'foldToStreet3CBChance': False,
|
||||
'foldToStreet3CBDone': False,
|
||||
'foldToStreet4CBChance': False,
|
||||
'foldToStreet4CBDone': False,
|
||||
'foldedBbToSteal': False,
|
||||
'foldedSbToSteal': False,
|
||||
'other3BStreet0': False,
|
||||
'other4BStreet0': False,
|
||||
'otherRaisedStreet0': False,
|
||||
'otherRaisedStreet1': False,
|
||||
'otherRaisedStreet2': True,
|
||||
'otherRaisedStreet3': False,
|
||||
'otherRaisedStreet4': False,
|
||||
'position': 3,
|
||||
'raiseFirstInChance': False,
|
||||
'raisedFirstIn': False,
|
||||
'rake': 0,
|
||||
'sawShowdown': False,
|
||||
'seatNo': 8,
|
||||
'sitout': False,
|
||||
'startCards': 0,
|
||||
'startCash': 205,
|
||||
'street0Aggr': False,
|
||||
'street0Bets': 0,
|
||||
'street0Calls': 1,
|
||||
'street0Raises': 0,
|
||||
'street0VPI': True,
|
||||
'street0_3BChance': False,
|
||||
'street0_3BDone': False,
|
||||
'street0_4BChance': False,
|
||||
'street0_4BDone': False,
|
||||
'street1Aggr': False,
|
||||
'street1Bets': 0,
|
||||
'street1CBChance': False,
|
||||
'street1CBDone': False,
|
||||
'street1Calls': 0,
|
||||
'street1CheckCallRaiseChance': False,
|
||||
'street1CheckCallRaiseDone': False,
|
||||
'street1Raises': 0,
|
||||
'street1Seen': True,
|
||||
'street2Aggr': False,
|
||||
'street2Bets': 0,
|
||||
'street2CBChance': False,
|
||||
'street2CBDone': False,
|
||||
'street2Calls': 0,
|
||||
'street2CheckCallRaiseChance': False,
|
||||
'street2CheckCallRaiseDone': False,
|
||||
'street2Raises': 0,
|
||||
'street2Seen': True,
|
||||
'street3Aggr': False,
|
||||
'street3Bets': 0,
|
||||
'street3CBChance': False,
|
||||
'street3CBDone': False,
|
||||
'street3Calls': 0,
|
||||
'street3CheckCallRaiseChance': True,
|
||||
'street3CheckCallRaiseDone': False,
|
||||
'street3Raises': 0,
|
||||
'street3Seen': False,
|
||||
'street4Aggr': False,
|
||||
'street4Bets': 0,
|
||||
'street4CBChance': False,
|
||||
'street4CBDone': False,
|
||||
'street4Calls': 0,
|
||||
'street4CheckCallRaiseChance': False,
|
||||
'street4CheckCallRaiseDone': False,
|
||||
'street4Raises': 0,
|
||||
'street4Seen': False,
|
||||
'totalProfit': -3,
|
||||
'tourneyTypeId': None,
|
||||
'tourneysPlayersIds': None,
|
||||
'winnings': 0,
|
||||
'wonAtSD': 0.0,
|
||||
'wonWhenSeenStreet1': 0.0,
|
||||
'wonWhenSeenStreet2': 0.0,
|
||||
'wonWhenSeenStreet3': 0.0,
|
||||
'wonWhenSeenStreet4': 0.0},
|
||||
u's0rrow': { 'card1': 32,
|
||||
'card2': 41,
|
||||
'card3': 4,
|
||||
'card4': 37,
|
||||
'card5': 38,
|
||||
'card6': 18,
|
||||
'card7': 16,
|
||||
'foldBbToStealChance': False,
|
||||
'foldSbToStealChance': False,
|
||||
'foldToOtherRaisedStreet0': False,
|
||||
'foldToOtherRaisedStreet1': False,
|
||||
'foldToOtherRaisedStreet2': False,
|
||||
'foldToOtherRaisedStreet3': False,
|
||||
'foldToOtherRaisedStreet4': False,
|
||||
'foldToStreet1CBChance': False,
|
||||
'foldToStreet1CBDone': False,
|
||||
'foldToStreet2CBChance': False,
|
||||
'foldToStreet2CBDone': False,
|
||||
'foldToStreet3CBChance': False,
|
||||
'foldToStreet3CBDone': False,
|
||||
'foldToStreet4CBChance': False,
|
||||
'foldToStreet4CBDone': False,
|
||||
'foldedBbToSteal': False,
|
||||
'foldedSbToSteal': False,
|
||||
'other3BStreet0': False,
|
||||
'other4BStreet0': False,
|
||||
'otherRaisedStreet0': False,
|
||||
'otherRaisedStreet1': False,
|
||||
'otherRaisedStreet2': True,
|
||||
'otherRaisedStreet3': True,
|
||||
'otherRaisedStreet4': True,
|
||||
'position': 6,
|
||||
'raiseFirstInChance': False,
|
||||
'raisedFirstIn': False,
|
||||
'rake': 2,
|
||||
'sawShowdown': True,
|
||||
'seatNo': 5,
|
||||
'sitout': False,
|
||||
'startCards': 0,
|
||||
'startCash': 152,
|
||||
'street0Aggr': False,
|
||||
'street0Bets': 0,
|
||||
'street0Calls': 1,
|
||||
'street0Raises': 0,
|
||||
'street0VPI': True,
|
||||
'street0_3BChance': False,
|
||||
'street0_3BDone': False,
|
||||
'street0_4BChance': False,
|
||||
'street0_4BDone': False,
|
||||
'street1Aggr': False,
|
||||
'street1Bets': 0,
|
||||
'street1CBChance': False,
|
||||
'street1CBDone': False,
|
||||
'street1Calls': 0,
|
||||
'street1CheckCallRaiseChance': False,
|
||||
'street1CheckCallRaiseDone': False,
|
||||
'street1Raises': 0,
|
||||
'street1Seen': True,
|
||||
'street2Aggr': False,
|
||||
'street2Bets': 0,
|
||||
'street2CBChance': False,
|
||||
'street2CBDone': False,
|
||||
'street2Calls': 1,
|
||||
'street2CheckCallRaiseChance': False,
|
||||
'street2CheckCallRaiseDone': False,
|
||||
'street2Raises': 0,
|
||||
'street2Seen': True,
|
||||
'street3Aggr': False,
|
||||
'street3Bets': 0,
|
||||
'street3CBChance': False,
|
||||
'street3CBDone': False,
|
||||
'street3Calls': 1,
|
||||
'street3CheckCallRaiseChance': False,
|
||||
'street3CheckCallRaiseDone': False,
|
||||
'street3Raises': 0,
|
||||
'street3Seen': True,
|
||||
'street4Aggr': False,
|
||||
'street4Bets': 0,
|
||||
'street4CBChance': False,
|
||||
'street4CBDone': False,
|
||||
'street4Calls': 1,
|
||||
'street4CheckCallRaiseChance': False,
|
||||
'street4CheckCallRaiseDone': False,
|
||||
'street4Raises': 0,
|
||||
'street4Seen': True,
|
||||
'totalProfit': 13,
|
||||
'tourneyTypeId': None,
|
||||
'tourneysPlayersIds': None,
|
||||
'winnings': 40,
|
||||
'wonAtSD': 1.0,
|
||||
'wonWhenSeenStreet1': 1.0,
|
||||
'wonWhenSeenStreet2': 0.0,
|
||||
'wonWhenSeenStreet3': 0.0,
|
||||
'wonWhenSeenStreet4': 0.0},
|
||||
u'u.pressure': { 'card1': 0,
|
||||
'card2': 0,
|
||||
'card3': 22,
|
||||
'card4': 0,
|
||||
'card5': 0,
|
||||
'card6': 0,
|
||||
'card7': 0,
|
||||
'foldBbToStealChance': False,
|
||||
'foldSbToStealChance': False,
|
||||
'foldToOtherRaisedStreet0': False,
|
||||
'foldToOtherRaisedStreet1': False,
|
||||
'foldToOtherRaisedStreet2': False,
|
||||
'foldToOtherRaisedStreet3': False,
|
||||
'foldToOtherRaisedStreet4': False,
|
||||
'foldToStreet1CBChance': False,
|
||||
'foldToStreet1CBDone': False,
|
||||
'foldToStreet2CBChance': False,
|
||||
'foldToStreet2CBDone': False,
|
||||
'foldToStreet3CBChance': False,
|
||||
'foldToStreet3CBDone': False,
|
||||
'foldToStreet4CBChance': False,
|
||||
'foldToStreet4CBDone': False,
|
||||
'foldedBbToSteal': False,
|
||||
'foldedSbToSteal': False,
|
||||
'other3BStreet0': False,
|
||||
'other4BStreet0': False,
|
||||
'otherRaisedStreet0': False,
|
||||
'otherRaisedStreet1': False,
|
||||
'otherRaisedStreet2': False,
|
||||
'otherRaisedStreet3': False,
|
||||
'otherRaisedStreet4': False,
|
||||
'position': 2,
|
||||
'raiseFirstInChance': False,
|
||||
'raisedFirstIn': False,
|
||||
'rake': 0,
|
||||
'sawShowdown': False,
|
||||
'seatNo': 1,
|
||||
'sitout': False,
|
||||
'startCards': 0,
|
||||
'startCash': 1117,
|
||||
'street0Aggr': False,
|
||||
'street0Bets': 0,
|
||||
'street0Calls': 0,
|
||||
'street0Raises': 0,
|
||||
'street0VPI': False,
|
||||
'street0_3BChance': False,
|
||||
'street0_3BDone': False,
|
||||
'street0_4BChance': False,
|
||||
'street0_4BDone': False,
|
||||
'street1Aggr': False,
|
||||
'street1Bets': 0,
|
||||
'street1CBChance': False,
|
||||
'street1CBDone': False,
|
||||
'street1Calls': 0,
|
||||
'street1CheckCallRaiseChance': False,
|
||||
'street1CheckCallRaiseDone': False,
|
||||
'street1Raises': 0,
|
||||
'street1Seen': False,
|
||||
'street2Aggr': False,
|
||||
'street2Bets': 0,
|
||||
'street2CBChance': False,
|
||||
'street2CBDone': False,
|
||||
'street2Calls': 0,
|
||||
'street2CheckCallRaiseChance': False,
|
||||
'street2CheckCallRaiseDone': False,
|
||||
'street2Raises': 0,
|
||||
'street2Seen': False,
|
||||
'street3Aggr': False,
|
||||
'street3Bets': 0,
|
||||
'street3CBChance': False,
|
||||
'street3CBDone': False,
|
||||
'street3Calls': 0,
|
||||
'street3CheckCallRaiseChance': False,
|
||||
'street3CheckCallRaiseDone': False,
|
||||
'street3Raises': 0,
|
||||
'street3Seen': False,
|
||||
'street4Aggr': False,
|
||||
'street4Bets': 0,
|
||||
'street4CBChance': False,
|
||||
'street4CBDone': False,
|
||||
'street4Calls': 0,
|
||||
'street4CheckCallRaiseChance': False,
|
||||
'street4CheckCallRaiseDone': False,
|
||||
'street4Raises': 0,
|
||||
'street4Seen': False,
|
||||
'totalProfit': -1,
|
||||
'tourneyTypeId': None,
|
||||
'tourneysPlayersIds': None,
|
||||
'winnings': 0,
|
||||
'wonAtSD': 0.0,
|
||||
'wonWhenSeenStreet1': 0.0,
|
||||
'wonWhenSeenStreet2': 0.0,
|
||||
'wonWhenSeenStreet3': 0.0,
|
||||
'wonWhenSeenStreet4': 0.0}}
|
|
@ -1,5 +1,5 @@
|
|||
fpdb database dump
|
||||
DB version=142
|
||||
DB version=143
|
||||
|
||||
###################
|
||||
Table Autorates
|
||||
|
@ -41,10 +41,20 @@ Table Players
|
|||
###################
|
||||
empty table
|
||||
|
||||
###################
|
||||
Table RawHands
|
||||
###################
|
||||
empty table
|
||||
|
||||
###################
|
||||
Table RawTourneys
|
||||
###################
|
||||
empty table
|
||||
|
||||
###################
|
||||
Table Settings
|
||||
###################
|
||||
version=142
|
||||
version=143
|
||||
|
||||
|
||||
###################
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
fpdb database dump
|
||||
DB version=142
|
||||
DB version=143
|
||||
|
||||
###################
|
||||
Table Autorates
|
||||
|
@ -1857,7 +1857,6 @@ Table HandsPlayers
|
|||
street4Raises=0
|
||||
actionString=None
|
||||
|
||||
!!!verified to here
|
||||
###################
|
||||
Table HudCache
|
||||
###################
|
||||
|
@ -2557,6 +2556,7 @@ Table HudCache
|
|||
street3Raises=0
|
||||
street4Raises=0
|
||||
|
||||
!!!verified to here
|
||||
id=9
|
||||
gametypeId=2
|
||||
playerId=1
|
||||
|
@ -3441,10 +3441,20 @@ Table Players
|
|||
commentTs=None
|
||||
|
||||
|
||||
###################
|
||||
Table RawHands
|
||||
###################
|
||||
empty table
|
||||
|
||||
###################
|
||||
Table RawTourneys
|
||||
###################
|
||||
empty table
|
||||
|
||||
###################
|
||||
Table Settings
|
||||
###################
|
||||
version=142
|
||||
version=143
|
||||
|
||||
|
||||
###################
|
||||
|
|
|
@ -30,7 +30,6 @@ sql = SQL.Sql(db_server = 'sqlite')
|
|||
|
||||
settings = {}
|
||||
settings.update(config.get_db_parameters())
|
||||
settings.update(config.get_tv_parameters())
|
||||
settings.update(config.get_import_parameters())
|
||||
settings.update(config.get_default_paths())
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@ sql = SQL.Sql(db_server = 'sqlite')
|
|||
|
||||
settings = {}
|
||||
settings.update(config.get_db_parameters())
|
||||
settings.update(config.get_tv_parameters())
|
||||
settings.update(config.get_import_parameters())
|
||||
settings.update(config.get_default_paths())
|
||||
|
||||
|
|
31
setup.py
31
setup.py
|
@ -10,6 +10,36 @@
|
|||
# Python packaging for fpdb
|
||||
|
||||
from distutils.core import setup
|
||||
from distutils.command.install_data import install_data as INST
|
||||
|
||||
import glob, string, os
|
||||
|
||||
|
||||
class inst_translations(INST):
|
||||
|
||||
# Return triples for installations
|
||||
def __locales(self, rootdir):
|
||||
_globstr = '%s/*/*/*.mo' % rootdir
|
||||
paths = glob.glob(_globstr)
|
||||
_locales = []
|
||||
for p in paths:
|
||||
rp = string.split(p, '/', 2)
|
||||
(lang, loc, mo) = string.split(rp[2], '/')
|
||||
_locales.append( (lang, loc, mo) )
|
||||
return _locales
|
||||
|
||||
def run(self):
|
||||
locales = self.__locales('pyfpdb/locale')
|
||||
for (lang, loc, mo_file) in locales:
|
||||
lang_dir = os.path.join('share', 'locale', lang, loc)
|
||||
lang_file = os.path.join('pyfpdb/locale', lang, loc, mo_file)
|
||||
self.data_files.append( (lang_dir, [lang_file]) )
|
||||
INST.run(self)
|
||||
|
||||
|
||||
commands = {
|
||||
'install_data': inst_translations
|
||||
}
|
||||
|
||||
setup(name = 'fpdb',
|
||||
description = 'Free Poker Database',
|
||||
|
@ -18,6 +48,7 @@ setup(name = 'fpdb',
|
|||
author_email = 'fpdb-main@lists.sourceforge.net',
|
||||
packages = ['fpdb'],
|
||||
package_dir = { 'fpdb' : 'pyfpdb' },
|
||||
cmdclass = commands,
|
||||
data_files = [
|
||||
('/usr/share/pixmaps',
|
||||
['gfx/fpdb-icon.png', 'gfx/fpdb-icon2.png',
|
||||
|
|
Loading…
Reference in New Issue
Block a user