merge from Steffen/Carl

This commit is contained in:
sqlcoder 2010-08-29 00:05:22 +01:00
commit 536adad477
47 changed files with 6366 additions and 1896 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
pyfpdb/HUD_config.xml.example -crlf

View 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

View File

@ -1,6 +1,7 @@
# Copyright 1999-2010 Gentoo Foundation # Copyright 1999-2010 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2 # Distributed under the terms of the GNU General Public License v2
# created by Steffen Schaumburg, steffen@schaumburger.info and Erki Ferenc, erkiferenc@gmail.com # $Header: $
EAPI="2" EAPI="2"
inherit eutils inherit eutils

View File

@ -1,6 +1,7 @@
# Copyright 1999-2010 Gentoo Foundation # Copyright 1999-2010 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2 # Distributed under the terms of the GNU General Public License v2
# created by Steffen Schaumburg, steffen@schaumburger.info and Erki Ferenc, erkiferenc@gmail.com # $Header: $
EAPI="2" EAPI="2"
inherit eutils inherit eutils
@ -17,7 +18,7 @@ SLOT="0"
KEYWORDS="~amd64 ~x86" KEYWORDS="~amd64 ~x86"
#note: this should work on other architectures too, please send me your experiences #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 linguas_it"
RDEPEND=" RDEPEND="
mysql? ( virtual/mysql mysql? ( virtual/mysql
dev-python/mysql-python ) dev-python/mysql-python )
@ -37,6 +38,15 @@ src_install() {
insinto "${GAMES_DATADIR}"/${PN} insinto "${GAMES_DATADIR}"/${PN}
doins -r gfx doins -r gfx
doins -r pyfpdb doins -r pyfpdb
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
if use linguas_it; then
dosym "${GAMES_DATADIR}"/${PN}/pyfpdb/locale/it/LC_MESSAGES/${PN}.mo /usr/share/locale/it/LC_MESSAGES/${PN}.mo
fi
doins readme.txt doins readme.txt
exeinto "${GAMES_DATADIR}"/${PN} exeinto "${GAMES_DATADIR}"/${PN}

View File

@ -1,6 +1,7 @@
# Copyright 1999-2010 Gentoo Foundation # Copyright 1999-2010 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2 # Distributed under the terms of the GNU General Public License v2
# created by Steffen Schaumburg, steffen@schaumburger.info and Erki Ferenc, erkiferenc@gmail.com # $Header: $
EAPI="2" EAPI="2"
inherit eutils inherit eutils
@ -18,7 +19,7 @@ SLOT="0"
KEYWORDS="" KEYWORDS=""
#note: this should work on other architectures too, please send me your experiences #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 linguas_it"
RDEPEND=" RDEPEND="
mysql? ( virtual/mysql mysql? ( virtual/mysql
dev-python/mysql-python ) dev-python/mysql-python )
@ -42,6 +43,15 @@ src_install() {
insinto "${GAMES_DATADIR}"/${PN} insinto "${GAMES_DATADIR}"/${PN}
doins -r gfx doins -r gfx
doins -r pyfpdb doins -r pyfpdb
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
if use linguas_it; then
dosym "${GAMES_DATADIR}"/${PN}/pyfpdb/locale/it/LC_MESSAGES/${PN}.mo /usr/share/locale/it/LC_MESSAGES/${PN}.mo
fi
doins readme.txt doins readme.txt
exeinto "${GAMES_DATADIR}"/${PN} exeinto "${GAMES_DATADIR}"/${PN}

View File

@ -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.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 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 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 dos> c:\python26\python.exe py2exe_setup.py py2exe
wait a while, watch lots of copying and whatever. 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. 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 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.2/ In explorer...tools...folder options...View uncheck "Hide extensions for known file types"
9.3/ Double click run_fpdb.bat 9.3/ Double click run_fpdb.bat
9.4/ check the contents of pyfpdb\fpdb.exe.log, deal with any errors thrown 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 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 Step 13 Compress to executable archive

View File

@ -32,14 +32,10 @@ Py2exe script for fpdb.
#HOW TO USE this script: #HOW TO USE this script:
# #
#- cd to the folder where this script is stored, usually .../pyfpdb. #- cd to the folder where this script is stored, usually ...packaging/windows
# [If there are build and dist subfolders present , delete them to get #- Run the script with python "py2exe_setup.py py2exe"
# rid of earlier builds. Update: script now does this for you] #- You will frequently get messages about missing .dll files.just assume other
#- Run the script with "py2exe_setup.py py2exe" # person will have them? we have copyright issues including some dll's
#- 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?)
#- If it works, you'll have a new dir fpdb-YYYYMMDD-exe which should #- If it works, you'll have a new dir fpdb-YYYYMMDD-exe which should
# contain 2 dirs; gfx and pyfpdb and run_fpdb.bat # contain 2 dirs; gfx and pyfpdb and run_fpdb.bat
#- [ This bit is now automated: #- [ 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 #- 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) # 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 # 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 # 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 os
import sys import sys
@ -86,33 +66,14 @@ import py2exe
import glob import glob
import matplotlib import matplotlib
import shutil import shutil
from datetime import date #from datetime import date
origIsSystemDLL = py2exe.build_exe.isSystemDLL
def isSystemDLL(pathname): def isSystemDLL(pathname):
#dwmapi appears to be vista-specific file, not XP #dwmapi appears to be vista-specific file, not XP
if os.path.basename(pathname).lower() in ("dwmapi.dll"): if os.path.basename(pathname).lower() in ("dwmapi.dll"):
return 0 return 0
return origIsSystemDLL(pathname) 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): def test_and_remove(top):
if os.path.exists(top): if os.path.exists(top):
@ -121,31 +82,64 @@ def test_and_remove(top):
else: else:
print "Unexpected file '"+top+"' found. Exiting." print "Unexpected file '"+top+"' found. Exiting."
exit() exit()
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)
today = date.today().strftime('%Y%m%d') def copy_tree(source,destination):
print "\n" + r"Output will be created in \pyfpdb\ and \fpdb_"+today+'\\' source = source.replace('\\', '\\\\')
#print "Enter value for XXX (any length): ", # the comma means no newline destination = destination.replace('\\', '\\\\')
#xxx = sys.stdin.readline().rstrip() print "*** Copying " + source + " to " + destination + " ***"
dist_dirname = r'fpdb-' + today + '-exe' shutil.copytree( source, destination )
dist_dir = r'..\fpdb-' + today + '-exe'
print
# remove build and dist dirs if they exist 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('dist')
test_and_remove('build') 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( setup(
name = 'fpdb', name = 'fpdb',
description = 'Free Poker DataBase', description = 'Free Poker DataBase',
version = '0.20.903', version = fpdbver,
windows = [ {'script': 'fpdb.pyw', "icon_resources": [(1, "../gfx/fpdb_large_icon.ico")]}, windows = [ {'script': pydir+'fpdb.pyw', "icon_resources": [(1, gfxdir+"fpdb_large_icon.ico")]},
{'script': 'HUD_main.pyw', }, {'script': pydir+'HUD_main.pyw', },
{'script': 'Configuration.py', } {'script': pydir+'Configuration.py', }
], ],
options = {'py2exe': { options = {'py2exe': {
@ -158,74 +152,56 @@ setup(
,'PartyPokerToFpdb', 'PokerStarsToFpdb' ,'PartyPokerToFpdb', 'PokerStarsToFpdb'
,'UltimateBetToFpdb', 'Win2dayToFpdb' ,'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' '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 , '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 # 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 # this code will not walk a tree
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']) # Note: cwd for 1st value is packaging/windows/dist (this is confusing BTW)
,(dist_dir, [r'..\run_fpdb.bat']) # Note: only include files here which are to be put into the package pyfpdb folder or subfolders
,( dist_dir + r'\gfx', glob.glob(r'..\gfx\*.*') )
# line below has problem with fonts subdir ('not a regular file') data_files = [('', glob.glob(rootdir+'*.txt'))
#,(r'matplotlibdata', glob.glob(r'c:\python25\Lib\site-packages\matplotlib\mpl-data\*')) ,('', [pydir+'HUD_config.xml.example',pydir+'Cards01.png', pydir+'logging.conf'])
] + matplotlib.get_py2exe_datafiles() ] + matplotlib.get_py2exe_datafiles()
) )
# rename completed output package as pyfpdb # ,(distdir, [rootdir+'run_fpdb.bat'])
os.rename('dist', 'pyfpdb') # ,(distdir+r'\gfx', glob.glob(gfxdir+'*.*'))
# ] +
print "*** py2exe build phase complete ***"
# pull pytz zoneinfo into pyfpdb package folder # copy zone info and fpdb translation folders
src_dir = r'c:\python26\Lib\site-packages\pytz\zoneinfo' copy_tree (r'c:\python26\Lib\site-packages\pytz\zoneinfo', os.path.join(r'dist', 'zoneinfo'))
src_dir = src_dir.replace('\\', '\\\\') copy_tree (pydir+r'locale', os.path.join(r'dist', 'locale'))
dest_dir = os.path.join(r'pyfpdb', 'zoneinfo')
shutil.copytree( src_dir, dest_dir )
# shunt pyfpdb package over to the distribution folder # create distribution folder and populate with gfx + bat
dest = os.path.join(dist_dirname, 'pyfpdb') copy_tree (gfxdir, os.path.join(distdir, 'gfx'))
# print "try renaming pyfpdb to", dest copy_file (rootdir+'run_fpdb.bat', distdir)
dest = dest.replace('\\', '\\\\')
# print "dest is now", dest
os.rename( 'pyfpdb', dest )
# 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 = "" gtk_dir = ""
while not os.path.exists(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() gtk_dir = sys.stdin.readline().rstrip()
print "\ncopying files and dirs from ", gtk_dir, "to", dest.replace('\\\\', '\\'), "..." print "*** copying GTK runtime ***"
src = os.path.join(gtk_dir, 'bin', 'libgdk-win32-2.0-0.dll') dest = os.path.join(distdir, 'pyfpdb')
src = src.replace('\\', '\\\\') copy_file(os.path.join(gtk_dir, 'bin', 'libgdk-win32-2.0-0.dll'), dest )
shutil.copy( src, 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') print "*** All done! ***"
src = src.replace('\\', '\\\\') test_and_remove('build')
shutil.copy( src, dest ) print distdir+" is in the pyfpdb dir"
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 """ print """
The following dirs can probably removed to make the final package smaller: 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! Use 7-zip to zip up the distribution and create a self extracting archive and that's it!
""" """

View File

@ -450,7 +450,6 @@ def sss():
self.settings['os']="windows" self.settings['os']="windows"
self.settings.update(self.config.get_db_parameters()) self.settings.update(self.config.get_db_parameters())
self.settings.update(self.config.get_tv_parameters())
self.settings.update(self.config.get_import_parameters()) self.settings.update(self.config.get_import_parameters())
self.settings.update(self.config.get_default_paths()) self.settings.update(self.config.get_default_paths())

View File

@ -44,9 +44,8 @@ class Betfair(HandHistoryConverter):
siteId = 7 # Needs to match id entry in Sites database siteId = 7 # Needs to match id entry in Sites database
# Static regexes # 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_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_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_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]+)) \)") re_PlayerInfo = re.compile("Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*)\s\(\s(\$(?P<CASH>[.0-9]+)) \)")

View File

@ -110,7 +110,7 @@ def get_config(file_name, fallback = True):
example_path = '/usr/share/python-fpdb/' + file_name + '.example' example_path = '/usr/share/python-fpdb/' + file_name + '.example'
try: try:
shutil.copyfile(example_path, config_path) 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) logging.info(msg)
return (config_path,False) return (config_path,False)
except IOError: except IOError:
@ -256,6 +256,20 @@ class Layout:
return temp + "\n" 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: class Site:
def __init__(self, node): def __init__(self, node):
def normalizePath(path): def normalizePath(path):
@ -284,12 +298,17 @@ class Site:
self.xshift = node.getAttribute("xshift") self.xshift = node.getAttribute("xshift")
self.yshift = node.getAttribute("yshift") self.yshift = node.getAttribute("yshift")
self.layout = {} self.layout = {}
self.emails = {}
print _("Loading site"), self.site_name print _("Loading site"), self.site_name
for layout_node in node.getElementsByTagName('layout'): for layout_node in node.getElementsByTagName('layout'):
lo = Layout(layout_node) lo = Layout(layout_node)
self.layout[lo.max] = lo self.layout[lo.max] = lo
for email_node in node.getElementsByTagName('email'):
email = Email(email_node)
self.emails[email.fetchType] = email
# Site defaults # Site defaults
self.xpad = 1 if self.xpad == "" else int(self.xpad) self.xpad = 1 if self.xpad == "" else int(self.xpad)
@ -467,21 +486,6 @@ class Import:
return " interval = %s\n callFpdbHud = %s\n hhArchiveBase = %s\n saveActions = %s\n fastStoreHudCache = %s\n" \ 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) % (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: class HudUI:
def __init__(self, node): def __init__(self, node):
self.node = node self.node = node
@ -504,16 +508,6 @@ class HudUI:
return " label = %s\n" % self.label 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): class General(dict):
def __init__(self): def __init__(self):
super(General, self).__init__() super(General, self).__init__()
@ -525,6 +519,20 @@ class General(dict):
for (name, value) in node.attributes.items(): for (name, value) in node.attributes.items():
log.debug(_("config.general: adding %s = %s") % (name,value)) log.debug(_("config.general: adding %s = %s") % (name,value))
self[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): def __str__(self):
s = "" s = ""
@ -600,6 +608,58 @@ class GUICashStats(list):
# s = s + " %s = %s\n" % (k, self[k]) # s = s + " %s = %s\n" % (k, self[k])
# return(s) # 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: class Config:
def __init__(self, file = None, dbname = ''): def __init__(self, file = None, dbname = ''):
# "file" is a path to an xml file with the fpdb/HUD configuration # "file" is a path to an xml file with the fpdb/HUD configuration
@ -653,11 +713,12 @@ class Config:
self.hhcs = {} self.hhcs = {}
self.popup_windows = {} self.popup_windows = {}
self.db_selected = None # database the user would like to use self.db_selected = None # database the user would like to use
self.tv = None
self.general = General() self.general = General()
self.emails = {} self.emails = {}
self.gui_cash_stats = GUICashStats() self.gui_cash_stats = GUICashStats()
if doc.getElementsByTagName("general") == []:
self.general.get_defaults()
for gen_node in doc.getElementsByTagName("general"): for gen_node in doc.getElementsByTagName("general"):
self.general.add_elements(node=gen_node) # add/overwrite elements in self.general self.general.add_elements(node=gen_node) # add/overwrite elements in self.general
@ -717,18 +778,10 @@ class Config:
imp = Import(node = imp_node) imp = Import(node = imp_node)
self.imp = imp 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'): for hui_node in doc.getElementsByTagName('hud_ui'):
hui = HudUI(node = hui_node) hui = HudUI(node = hui_node)
self.ui = hui self.ui = hui
for tv_node in doc.getElementsByTagName("tv"):
self.tv = Tv(node = tv_node)
db = self.get_db_parameters() db = self.get_db_parameters()
if db['db-password'] == 'YOUR MYSQL PASSWORD': if db['db-password'] == 'YOUR MYSQL PASSWORD':
df_file = self.find_default_conf() df_file = self.find_default_conf()
@ -740,8 +793,19 @@ class Config:
db_user = df_parms['db-user'], db_user = df_parms['db-user'],
db_pass = df_parms['db-password']) db_pass = df_parms['db-password'])
self.save(file=os.path.join(self.default_config_path, "HUD_config.xml")) 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 "" print ""
#end def __init__
def set_hhArchiveBase(self, path): def set_hhArchiveBase(self, path):
self.imp.node.setAttribute("hhArchiveBase", path) self.imp.node.setAttribute("hhArchiveBase", path)
@ -768,9 +832,12 @@ class Config:
return site_node return site_node
def getEmailNode(self, siteName, fetchType): def getEmailNode(self, siteName, fetchType):
for emailNode in self.doc.getElementsByTagName("email"): siteNode = self.get_site_node(siteName)
if emailNode.getAttribute("siteName") == siteName and emailNode.getAttribute("fetchType") == fetchType: for emailNode in siteNode.getElementsByTagName("email"):
if emailNode.getAttribute("fetchType") == fetchType:
print "found emailNode"
return emailNode return emailNode
break
#end def getEmailNode #end def getEmailNode
def getGameNode(self,gameName): def getGameNode(self,gameName):
@ -1073,15 +1140,6 @@ class Config:
return site_name return site_name
return None 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 # Allow to change the menu appearance
def get_hud_ui_parameters(self): def get_hud_ui_parameters(self):
hui = {} hui = {}
@ -1374,15 +1432,10 @@ if __name__== "__main__":
print c.imp print c.imp
print "----------- END IMPORT -----------" 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.edit_layout("PokerStars", 6, locations=( (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6) ))
c.save(file="testout.xml") c.save(file="testout.xml")
print "db = ", c.get_db_parameters() print "db = ", c.get_db_parameters()
# print "tv = ", c.get_tv_parameters()
# print "imp = ", c.get_import_parameters() # print "imp = ", c.get_import_parameters()
print "paths = ", c.get_default_paths("PokerStars") print "paths = ", c.get_default_paths("PokerStars")
print "colors = ", c.get_default_colors("PokerStars") print "colors = ", c.get_default_colors("PokerStars")

View File

@ -321,7 +321,12 @@ class Database:
else: else:
for row in rows: for row in rows:
for columnNumber in range(len(columnNames)): 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"
result+="\n" result+="\n"
return result 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 "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']) #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']), 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.siteId, hand.buyinCurrency, hand.buyin, hand.fee, hand.gametype['category'],
hand.isRebuy, hand.isAddOn, hand.speed, hand.isShootout, hand.isMatrix) #TODO: add koamount hand.gametype['limitType'], hand.maxseats, hand.isKO,
hand.isRebuy, hand.isAddOn, hand.speed, hand.isShootout, hand.isMatrix)
) )
result=cursor.fetchone() result=cursor.fetchone()
#print "result of fetching TT by details:",result #print "result of fetching TT by details:",result
@ -2072,7 +2078,8 @@ class Database:
tourneyTypeId = result[0] tourneyTypeId = result[0]
except TypeError: #this means we need to create a new entry except TypeError: #this means we need to create a new entry
cursor.execute (self.sql.query['insertTourneyType'].replace('%s', self.sql.query['placeholder']), 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.buyInChips, hand.isKO, hand.koBounty, hand.isRebuy,
hand.isAddOn, hand.speed, hand.isShootout, hand.isMatrix, hand.added, hand.addedCurrency) hand.isAddOn, hand.speed, hand.isShootout, hand.isMatrix, hand.added, hand.addedCurrency)
) )

View File

@ -260,8 +260,8 @@ class Fulltilt(HandHistoryConverter):
hand.isRebuy = True hand.isRebuy = True
if special == "KO": if special == "KO":
hand.isKO = True hand.isKO = True
if special == "Head's Up": if special == "Head's Up" or special == "Heads Up":
hand.maxSeats = 2 hand.maxseats = 2
if re.search("Matrix", special): if re.search("Matrix", special):
hand.isMatrix = True hand.isMatrix = True
if special == "Shootout": if special == "Shootout":

View File

@ -334,7 +334,6 @@ if __name__== "__main__":
else: settings['os'] = 'linuxmac' else: settings['os'] = 'linuxmac'
settings.update(config.get_db_parameters('fpdb')) settings.update(config.get_db_parameters('fpdb'))
settings.update(config.get_tv_parameters())
settings.update(config.get_import_parameters()) settings.update(config.get_import_parameters())
settings.update(config.get_default_paths()) settings.update(config.get_default_paths())

View File

@ -378,7 +378,6 @@ def main(argv=None):
else: settings['os'] = 'linuxmac' else: settings['os'] = 'linuxmac'
settings.update(config.get_db_parameters()) settings.update(config.get_db_parameters())
settings.update(config.get_tv_parameters())
settings.update(config.get_import_parameters()) settings.update(config.get_import_parameters())
settings.update(config.get_default_paths()) settings.update(config.get_default_paths())

View File

@ -72,19 +72,14 @@ class GuiImapFetcher (threading.Thread):
siteName=columns[0].get_text() siteName=columns[0].get_text()
fetchType=columns[1].get_text() fetchType=columns[1].get_text()
code=siteName+"_"+fetchType
for email in self.config.emails: toSave=self.config.supported_sites[siteName].emails[fetchType]
toSave=self.config.emails[email]
break
toSave.siteName=siteName
toSave.fetchType=fetchType
toSave.host=columns[2].get_text() toSave.host=columns[2].get_text()
toSave.username=columns[3].get_text() toSave.username=columns[3].get_text()
if columns[4].get_text()=="***": if columns[4].get_text()=="***":
toSave.password=self.passwords[code] toSave.password=self.passwords[siteName+fetchType]
else: else:
toSave.password=columns[4].get_text() toSave.password=columns[4].get_text()
@ -101,16 +96,17 @@ class GuiImapFetcher (threading.Thread):
def importAllClicked(self, widget, data=None): def importAllClicked(self, widget, data=None):
self.statusLabel.set_label(_("Starting import. Please wait.")) #FIXME: why doesnt this one show? self.statusLabel.set_label(_("Starting import. Please wait.")) #FIXME: why doesnt this one show?
for email in self.config.emails: for siteName in self.config.supported_sites:
try: for fetchType in self.config.supported_sites[siteName].emails:
result=ImapFetcher.run(self.config.emails[email], self.db) try:
self.statusLabel.set_label(_("Finished import without error.")) result=ImapFetcher.run(self.config.supported_sites[siteName].emails[fetchType], self.db)
except IMAP4.error as error: self.statusLabel.set_label(_("Finished import without error."))
if str(error)=="[AUTHENTICATIONFAILED] Authentication failed.": except IMAP4.error as error:
self.statusLabel.set_label(_("Login to mailserver failed: please check mailserver, username and password")) if str(error)=="[AUTHENTICATIONFAILED] Authentication failed.":
except gaierror as error: self.statusLabel.set_label(_("Login to mailserver failed: please check mailserver, username and password"))
if str(error)=="[Errno -2] Name or service not known": except gaierror as error:
self.statusLabel.set_label(_("Could not connect to mailserver: check mailserver and use SSL settings and internet connectivity")) 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 importAllClicked
def get_vbox(self): def get_vbox(self):
@ -128,38 +124,42 @@ class GuiImapFetcher (threading.Thread):
self.rowVBox = gtk.VBox() self.rowVBox = gtk.VBox()
self.mainVBox.add(self.rowVBox) self.mainVBox.add(self.rowVBox)
for email in self.config.emails: for siteName in self.config.supported_sites:
config=self.config.emails[email] for fetchType in self.config.supported_sites[siteName].emails:
box=gtk.HBox(homogeneous=True) config=self.config.supported_sites[siteName].emails[fetchType]
box=gtk.HBox(homogeneous=True)
for field in (config.siteName, config.fetchType):
label=gtk.Label(field) for field in (siteName, config.fetchType):
box.add(label) label=gtk.Label(field)
box.add(label)
for field in (config.host, config.username):
for field in (config.host, config.username):
entry=gtk.Entry()
entry.set_text(field)
box.add(entry)
entry=gtk.Entry() entry=gtk.Entry()
entry.set_text(field) self.passwords[siteName+fetchType]=config.password
entry.set_text("***")
box.add(entry) box.add(entry)
entry=gtk.Entry() entry=gtk.Entry()
self.passwords[email]=config.password entry.set_text(config.folder)
entry.set_text("***") box.add(entry)
box.add(entry)
sslBox = gtk.combo_box_new_text()
entry=gtk.Entry() sslBox.append_text(_("Yes"))
entry.set_text(config.folder) sslBox.append_text(_("No"))
box.add(entry) if config.useSsl:
sslBox.set_active(0)
sslBox = gtk.combo_box_new_text() else:
sslBox.append_text(_("Yes")) sslBox.set_active(1)
sslBox.append_text(_("No")) box.add(sslBox)
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() self.mainVBox.show_all()
#end def displayConfig #end def displayConfig

View File

@ -53,7 +53,6 @@ class GuiPositionalStats (threading.Thread):
settings = {} settings = {}
settings.update(self.conf.get_db_parameters()) 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_import_parameters())
settings.update(self.conf.get_default_paths()) settings.update(self.conf.get_default_paths())

View File

@ -69,7 +69,6 @@ class GuiRingPlayerStats (GuiPlayerStats.GuiPlayerStats):
settings = {} settings = {}
settings.update(self.conf.get_db_parameters()) 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_import_parameters())
settings.update(self.conf.get_default_paths()) settings.update(self.conf.get_default_paths())

View File

@ -82,7 +82,6 @@ class GuiSessionViewer (threading.Thread):
settings = {} settings = {}
settings.update(self.conf.get_db_parameters()) 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_import_parameters())
settings.update(self.conf.get_default_paths()) settings.update(self.conf.get_default_paths())

File diff suppressed because it is too large Load Diff

View File

@ -58,7 +58,7 @@ class Hand(object):
LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'} LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'}
SYMBOL = {'USD': '$', 'EUR': u'$', 'T$': '', 'play': ''} SYMBOL = {'USD': '$', 'EUR': u'$', 'T$': '', 'play': ''}
MS = {'horse' : 'HORSE', '8game' : '8-Game', 'hose' : 'HOSE', 'ha': 'HA'} 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"): def __init__(self, config, sitename, gametype, handText, builtFrom = "HHC"):
@ -321,10 +321,8 @@ If a player has None chips he won't be added."""
def checkPlayerExists(self,player): def checkPlayerExists(self,player):
if player not in [p[1] for p in self.players]: if player not in [p[1] for p in self.players]:
print _("DEBUG: checkPlayerExists %s fail") % player print (_("DEBUG: checkPlayerExists %s fail on hand number %s") % (player, self.handid))
raise FpdbParseError(_("checkPlayerExists: '%s' failed.") % player) raise FpdbParseError(_("checkPlayerExists: '%s fail on hand number %s") % (player, self.handid))
def setCommunityCards(self, street, cards): def setCommunityCards(self, street, cards):
log.debug("setCommunityCards %s %s" %(street, cards)) log.debug("setCommunityCards %s %s" %(street, cards))

View File

@ -587,6 +587,7 @@ or None if we fail to get the info """
offset = int(givenTimezone[-5:]) offset = int(givenTimezone[-5:])
givenTimezone = givenTimezone[0:-5] givenTimezone = givenTimezone[0:-5]
log.debug( _("changeTimeZone: offset=") + str(offset) ) log.debug( _("changeTimeZone: offset=") + str(offset) )
else: offset=0
if givenTimezone=="ET": if givenTimezone=="ET":
givenTZ = timezone('US/Eastern') givenTZ = timezone('US/Eastern')

View File

@ -96,7 +96,7 @@ class OnGame(HandHistoryConverter):
Start\shand:\s(?P<DATETIME>.*) Start\shand:\s(?P<DATETIME>.*)
Table:\s(?P<TABLE>[\'\w\s]+)\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<GAME>TEXAS_HOLDEM|RAZZ)\s
(%(LS)s)?(?P<SB>[.0-9]+)/ (%(LS)s)?(?P<SB>[.0-9]+)/
(%(LS)s)?(?P<BB>[.0-9]+) (%(LS)s)?(?P<BB>[.0-9]+)
@ -142,7 +142,7 @@ class OnGame(HandHistoryConverter):
self.re_Antes = re.compile(r"^%(PLYR)s: posts the ante (%(CUR)s)?(?P<ANTE>[\.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_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 \( (%(CUR)s)?(?P<SBBB>[\.0-9]+)\)' % subst) self.re_PostBoth = re.compile('.*\n(?P<PNAME>.*): posts small \& big blinds \( (%(CUR)s)?(?P<SBBB>[\.0-9]+)\)' % subst)
self.re_HeroCards = re.compile('.*\nDealt\sto\s(?P<PNAME>.*)\s\[ (?P<CARDS>.*) \]') self.re_HeroCards = re.compile('Dealing\sto\s%(PLYR)s:\s\[(?P<CARDS>.*)\]' % subst)
#lopllopl checks, Eurolll checks, .Lucchess checks. #lopllopl checks, Eurolll checks, .Lucchess checks.
#chumley. calls $0.25 #chumley. calls $0.25
@ -152,9 +152,6 @@ class OnGame(HandHistoryConverter):
#Uchilka shows [ KC,JD ] #Uchilka shows [ KC,JD ]
self.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
#like this:
#Main pot: $3.57 won by mleo17 ($3.40) #Main pot: $3.57 won by mleo17 ($3.40)
#Side pot 1: $3.26 won by maac_5 ($3.10) #Side pot 1: $3.26 won by maac_5 ($3.10)
#Main pot: $2.87 won by maac_5 ($1.37), sagi34 ($1.36) #Main pot: $2.87 won by maac_5 ($1.37), sagi34 ($1.36)
@ -309,35 +306,15 @@ class OnGame(HandHistoryConverter):
hand.addBringIn(m.group('PNAME'), m.group('BRINGIN')) hand.addBringIn(m.group('PNAME'), m.group('BRINGIN'))
def readHeroCards(self, hand): def readHeroCards(self, hand):
m = self.re_HeroCards.search(hand.handText) # streets PREFLOP, PREDRAW, and THIRD are special cases beacause
if(m == None): # we need to grab hero's cards
#Not involved in hand for street in ('PREFLOP', 'DEAL'):
hand.involved = False if street in hand.streets.keys():
else: m = self.re_HeroCards.finditer(hand.streets[street])
hand.hero = m.group('PNAME') for found in m:
# "2c, qh" -> set(["2c","qc"]) hand.hero = found.group('PNAME')
# Also works with Omaha hands. newcards = found.group('CARDS').split(', ')
cards = m.group('CARDS') hand.addHoleCards(street, hand.hero, closed=newcards, shown=False, mucked=False, dealt=True)
cards = set(cards.split(','))
hand.addHoleCards(cards, m.group('PNAME'))
def readAction_old(self, hand, street):
m = self.re_Action.finditer(hand.streets.group(street))
for action in m:
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'))
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.
def readAction(self, hand, street): def readAction(self, hand, street):
m = self.re_Action.finditer(hand.streets[street]) m = self.re_Action.finditer(hand.streets[street])

390
pyfpdb/PkrToFpdb.py Executable file
View 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)

View File

@ -3968,6 +3968,7 @@ class Sql:
AND fee=%s AND fee=%s
AND category=%s AND category=%s
AND limitType=%s AND limitType=%s
AND maxSeats=%s
AND knockout=%s AND knockout=%s
AND rebuy=%s AND rebuy=%s
AND addOn=%s AND addOn=%s
@ -3977,9 +3978,9 @@ class Sql:
""" """
self.query['insertTourneyType'] = """INSERT INTO TourneyTypes 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) 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.* self.query['getTourneyByTourneyNo'] = """SELECT t.*

View File

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
import sys import sys
import os import os
import codecs import codecs
@ -9,13 +10,29 @@ import Database
import SQL import SQL
import fpdb_import 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):
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):
for f in self.histogram:
idx = f.find('regression')
print "(%3d) : %s" %(self.histogram[f], f[idx:])
def compare(leaf, importer, errors):
filename = leaf filename = leaf
#print "DEBUG: fileanme: %s" % filename #print "DEBUG: fileanme: %s" % filename
@ -51,21 +68,21 @@ def compare(leaf, importer):
pass pass
else: else:
# Stats don't match - Doh! # Stats don't match - Doh!
error_report(filename, hand, stat, ghash, testhash, p) errors.error_report(filename, hand, stat, ghash, testhash, p)
importer.clearFileList() 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 """ """Walks a directory, and executes a callback on each file """
dir = os.path.abspath(dir) dir = os.path.abspath(dir)
for file in [file for file in os.listdir(dir) if not file in [".",".."]]: for file in [file for file in os.listdir(dir) if not file in [".",".."]]:
nfile = os.path.join(dir,file) nfile = os.path.join(dir,file)
if os.path.isdir(nfile): if os.path.isdir(nfile):
walk_testfiles(nfile, compare, importer) walk_testfiles(nfile, compare, importer, errors)
else: else:
compare(nfile, importer) compare(nfile, importer, errors)
def main(argv=None): def main(argv=None):
if argv is None: if argv is None:
@ -76,7 +93,6 @@ def main(argv=None):
sql = SQL.Sql(db_server = 'sqlite') sql = SQL.Sql(db_server = 'sqlite')
settings = {} settings = {}
settings.update(config.get_db_parameters()) settings.update(config.get_db_parameters())
settings.update(config.get_tv_parameters())
settings.update(config.get_import_parameters()) settings.update(config.get_import_parameters())
settings.update(config.get_default_paths()) settings.update(config.get_default_paths())
db.recreate_tables() db.recreate_tables()
@ -86,8 +102,15 @@ def main(argv=None):
importer.setThreads(-1) importer.setThreads(-1)
importer.setCallHud(False) importer.setCallHud(False)
importer.setFakeCacheHHC(True) importer.setFakeCacheHHC(True)
errors = FpdbError()
walk_testfiles("regression-test-files/cash/Stars/", compare, importer) walk_testfiles("regression-test-files/cash/Stars/", compare, importer, errors)
print "---------------------"
print "Total Errors: %d" % errors.errorcount
print "---------------------"
errors.print_histogram()
if __name__ == '__main__': if __name__ == '__main__':
sys.exit(main()) sys.exit(main())

View File

@ -77,7 +77,7 @@ class TourneySummary(object):
self.buyin = None self.buyin = None
self.fee = None self.fee = None
self.hero = None self.hero = None
self.maxseats = None self.maxseats = 0
self.entries = 0 self.entries = 0
self.speed = "Normal" self.speed = "Normal"
self.prizepool = 0 # Make it a dict in order to deal (eventually later) with non-money winnings : {'MONEY' : amount, 'OTHER' : Value ??} self.prizepool = 0 # Make it a dict in order to deal (eventually later) with non-money winnings : {'MONEY' : amount, 'OTHER' : Value ??}

View File

@ -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

View File

@ -129,7 +129,7 @@ import Configuration
import Exceptions import Exceptions
import Stats import Stats
VERSION = "0.20.904 plus git" VERSION = "0.20.906"
class fpdb: class fpdb:
@ -264,7 +264,8 @@ class fpdb:
, ('numpy', numpy_version) , ('numpy', numpy_version)
, ('sqlite3', sqlite3_version) , ('sqlite3', sqlite3_version)
, ('sqlite', sqlite_version) , ('sqlite', sqlite_version)
, ('database', self.settings['db-server'] + db_version) , ('fpdb version', VERSION)
, ('database used', self.settings['db-server'])
] ]
versions = gtk.TextBuffer() versions = gtk.TextBuffer()
w = 20 # width used for module names and version numbers w = 20 # width used for module names and version numbers
@ -786,7 +787,6 @@ class fpdb:
<menuitem action="Quit"/> <menuitem action="Quit"/>
</menu> </menu>
<menu action="import"> <menu action="import">
<menuitem action="sethharchive"/>
<menuitem action="bulkimp"/> <menuitem action="bulkimp"/>
<menuitem action="imapimport"/> <menuitem action="imapimport"/>
<menuitem action="autoimp"/> <menuitem action="autoimp"/>
@ -828,15 +828,14 @@ class fpdb:
('SaveProf', None, _('_Save Profile (todo)'), _('<control>S'), 'Save your profile', self.dia_save_profile), ('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), ('Preferences', None, _('Pre_ferences'), _('<control>F'), 'Edit your preferences', self.dia_preferences),
('import', None, _('_Import')), ('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), ('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), ('imapimport', None, _('_Import through eMail/IMAP'), _('<control>I'), 'Import through eMail/IMAP', self.tab_imap_import),
('viewers', None, _('_Viewers')), ('viewers', None, _('_Viewers')),
('autoimp', None, _('_Auto Import and HUD'), _('<control>A'), 'Auto Import and HUD', self.tab_auto_import), ('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), ('hudConfigurator', None, _('_HUD Configurator'), _('<control>H'), 'HUD Configurator', self.diaHudConfigurator),
('graphs', None, _('_Graphs'), _('<control>G'), 'Graphs', self.tabGraphViewer), ('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), ('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)'), _('<control>T'), 'Tourney Player Stats (tabulated view, mysql only)', self.tab_tourney_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), ('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), ('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), ('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({'cl_options': cl_options})
self.settings.update(self.config.get_db_parameters()) self.settings.update(self.config.get_db_parameters())
self.settings.update(self.config.get_tv_parameters())
self.settings.update(self.config.get_import_parameters()) self.settings.update(self.config.get_import_parameters())
self.settings.update(self.config.get_default_paths()) self.settings.update(self.config.get_default_paths())
@ -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: elif response == gtk.RESPONSE_NO:
self.select_hhArchiveBase() 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): def main(self):
gtk.main() gtk.main()
return 0 return 0

View File

@ -10,6 +10,18 @@ import time
import signal import signal
import base64 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 InterProcessLock = None
""" """

View 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

View File

@ -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* 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

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.

View File

@ -1,2 +1,3 @@
msgmerge --update fpdb-hu_HU.po fpdb-en_GB.po msgmerge --update fpdb-hu_HU.po fpdb-en_GB.po
msgmerge --update fpdb-de_DE.po fpdb-en_GB.po

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -1,5 +1,5 @@
fpdb database dump fpdb database dump
DB version=142 DB version=143
################### ###################
Table Autorates Table Autorates
@ -1644,10 +1644,20 @@ Table Players
commentTs=None commentTs=None
###################
Table RawHands
###################
empty table
###################
Table RawTourneys
###################
empty table
################### ###################
Table Settings Table Settings
################### ###################
version=142 version=143
################### ###################

View File

@ -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}}

View File

@ -1,5 +1,5 @@
fpdb database dump fpdb database dump
DB version=142 DB version=143
################### ###################
Table Autorates Table Autorates
@ -41,10 +41,20 @@ Table Players
################### ###################
empty table empty table
###################
Table RawHands
###################
empty table
###################
Table RawTourneys
###################
empty table
################### ###################
Table Settings Table Settings
################### ###################
version=142 version=143
################### ###################

View File

@ -1,5 +1,5 @@
fpdb database dump fpdb database dump
DB version=142 DB version=143
################### ###################
Table Autorates Table Autorates
@ -1857,7 +1857,6 @@ Table HandsPlayers
street4Raises=0 street4Raises=0
actionString=None actionString=None
!!!verified to here
################### ###################
Table HudCache Table HudCache
################### ###################
@ -2557,6 +2556,7 @@ Table HudCache
street3Raises=0 street3Raises=0
street4Raises=0 street4Raises=0
!!!verified to here
id=9 id=9
gametypeId=2 gametypeId=2
playerId=1 playerId=1
@ -3441,10 +3441,20 @@ Table Players
commentTs=None commentTs=None
###################
Table RawHands
###################
empty table
###################
Table RawTourneys
###################
empty table
################### ###################
Table Settings Table Settings
################### ###################
version=142 version=143
################### ###################

View File

@ -30,7 +30,6 @@ sql = SQL.Sql(db_server = 'sqlite')
settings = {} settings = {}
settings.update(config.get_db_parameters()) settings.update(config.get_db_parameters())
settings.update(config.get_tv_parameters())
settings.update(config.get_import_parameters()) settings.update(config.get_import_parameters())
settings.update(config.get_default_paths()) settings.update(config.get_default_paths())

View File

@ -30,7 +30,6 @@ sql = SQL.Sql(db_server = 'sqlite')
settings = {} settings = {}
settings.update(config.get_db_parameters()) settings.update(config.get_db_parameters())
settings.update(config.get_tv_parameters())
settings.update(config.get_import_parameters()) settings.update(config.get_import_parameters())
settings.update(config.get_default_paths()) settings.update(config.get_default_paths())

View File

@ -10,6 +10,36 @@
# Python packaging for fpdb # Python packaging for fpdb
from distutils.core import setup 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', setup(name = 'fpdb',
description = 'Free Poker Database', description = 'Free Poker Database',
@ -18,6 +48,7 @@ setup(name = 'fpdb',
author_email = 'fpdb-main@lists.sourceforge.net', author_email = 'fpdb-main@lists.sourceforge.net',
packages = ['fpdb'], packages = ['fpdb'],
package_dir = { 'fpdb' : 'pyfpdb' }, package_dir = { 'fpdb' : 'pyfpdb' },
cmdclass = commands,
data_files = [ data_files = [
('/usr/share/pixmaps', ('/usr/share/pixmaps',
['gfx/fpdb-icon.png', 'gfx/fpdb-icon2.png', ['gfx/fpdb-icon.png', 'gfx/fpdb-icon2.png',