Browse Source

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

master
gimick 13 years ago
parent
commit
ef384f28fb
  1. 112
      packaging/announce-0.22.txt
  2. 78
      packaging/announce-template.txt
  3. 12
      packaging/debian/changelog
  4. 42
      packaging/gentoo/current.ebuild
  5. 60
      packaging/gentoo/current_stable.ebuild
  6. 53
      packaging/gentoo/fpdb-9999.ebuild
  7. 4
      pyfpdb/AbsoluteToFpdb.py
  8. 134
      pyfpdb/AlchemyFacilities.py
  9. 485
      pyfpdb/AlchemyMappings.py
  10. 460
      pyfpdb/AlchemyTables.py
  11. 4
      pyfpdb/BetfairToFpdb.py
  12. 4
      pyfpdb/CarbonToFpdb.py
  13. 30
      pyfpdb/Card.py
  14. 18
      pyfpdb/Charset.py
  15. 53
      pyfpdb/Configuration.py
  16. 922
      pyfpdb/Database.py
  17. 44
      pyfpdb/DerivedStats.py
  18. 8
      pyfpdb/EverestToFpdb.py
  19. 67
      pyfpdb/EverleafToFpdb.py
  20. 17
      pyfpdb/FullTiltPokerSummary.py
  21. 128
      pyfpdb/FulltiltToFpdb.py
  22. 2
      pyfpdb/GuiImapFetcher.py
  23. 7
      pyfpdb/GuiTourneyImport.py
  24. 147
      pyfpdb/Hand.py
  25. 20
      pyfpdb/HandHistoryConverter.py
  26. 23
      pyfpdb/OnGameToFpdb.py
  27. 12
      pyfpdb/PacificPokerToFpdb.py
  28. 8
      pyfpdb/PartyPokerToFpdb.py
  29. 6
      pyfpdb/PkrToFpdb.py
  30. 10
      pyfpdb/PokerStarsSummary.py
  31. 45
      pyfpdb/PokerStarsToFpdb.py
  32. 595
      pyfpdb/SQL.py
  33. 4
      pyfpdb/SitenameSummary.py
  34. 32
      pyfpdb/TestHandsPlayers.py
  35. 18
      pyfpdb/TourneySummary.py
  36. 19
      pyfpdb/Win2dayToFpdb.py
  37. 4
      pyfpdb/WinamaxSummary.py
  38. 16
      pyfpdb/WinamaxToFpdb.py
  39. 18
      pyfpdb/fpdb.pyw
  40. 139
      pyfpdb/fpdb_import.py
  41. 4
      pyfpdb/iPokerToFpdb.py
  42. BIN
      pyfpdb/locale/de/LC_MESSAGES/fpdb.mo
  43. BIN
      pyfpdb/locale/es/LC_MESSAGES/fpdb.mo
  44. 1325
      pyfpdb/locale/fpdb-de_DE.po
  45. 1090
      pyfpdb/locale/fpdb-en_GB.pot
  46. 2089
      pyfpdb/locale/fpdb-es_ES.po
  47. 1625
      pyfpdb/locale/fpdb-fr_FR.po
  48. 1282
      pyfpdb/locale/fpdb-hu_HU.po
  49. 4225
      pyfpdb/locale/fpdb-it_IT.po
  50. 1152
      pyfpdb/locale/fpdb-pl_PL.po
  51. 4026
      pyfpdb/locale/fpdb-pt_BR.po
  52. 1778
      pyfpdb/locale/fpdb-ru_RU.po
  53. 3992
      pyfpdb/locale/fpdb-zh_CN.po
  54. BIN
      pyfpdb/locale/fr/LC_MESSAGES/fpdb.mo
  55. BIN
      pyfpdb/locale/hu/LC_MESSAGES/fpdb.mo
  56. BIN
      pyfpdb/locale/it/LC_MESSAGES/fpdb.mo
  57. 28
      pyfpdb/locale/localise.sh
  58. BIN
      pyfpdb/locale/pl/LC_MESSAGES/fpdb.mo
  59. BIN
      pyfpdb/locale/pt/LC_MESSAGES/fpdb.mo
  60. BIN
      pyfpdb/locale/ru/LC_MESSAGES/fpdb.mo
  61. BIN
      pyfpdb/locale/zh/LC_MESSAGES/fpdb.mo
  62. 104
      pyfpdb/regression-test-files/cash/Absolute/Flop/IHH20090610 Chile Way - Hold'em No Limit $0.02(Real Money) Table 9339866.txt.hp
  63. 104
      pyfpdb/regression-test-files/cash/Carbon/Flop/NLHE-9max-USD-0.25-0.50.200810.All.Streets.txt.hp
  64. 3
      pyfpdb/regression-test-files/cash/Everest/Flop/PLO-EUR-5-10-Unknown-Sample.txt.hands
  65. 26
      pyfpdb/regression-test-files/cash/Everest/Flop/PLO-EUR-5-10-Unknown-Sample.txt.hp
  66. 104
      pyfpdb/regression-test-files/cash/Everleaf/Flop/NLHE-10max-USD-0.01-0.02-201008.2Way.All-in.pre.txt.hp
  67. 48
      pyfpdb/regression-test-files/cash/Everleaf/Flop/NLHE-EUR-0.01-0.02-20091027.partouche.txt
  68. 90
      pyfpdb/regression-test-files/cash/FTP/Draw/3-Draw-Limit-USD-0.10-0.20-201011.txt.hp
  69. 3
      pyfpdb/regression-test-files/cash/FTP/Draw/3-Draw-Limit-USD-150-300-201012.txt.hands
  70. 77
      pyfpdb/regression-test-files/cash/FTP/Draw/3-Draw-Limit-USD-150-300-201012.txt.hp
  71. 65
      pyfpdb/regression-test-files/cash/FTP/Draw/3-Draw-Limit-USD-1500-3000-201101.FTP.Archive.sample.txt
  72. 3
      pyfpdb/regression-test-files/cash/FTP/Draw/3-Draw-Limit-USD-250-500-201011.Hero.sitting.out.but.not.listed.txt.hands
  73. 52
      pyfpdb/regression-test-files/cash/FTP/Draw/3-Draw-Limit-USD-250-500-201011.Hero.sitting.out.but.not.listed.txt.hp
  74. 3
      pyfpdb/regression-test-files/cash/FTP/Draw/5-Carddraw-Limit-USD-0.10-0.20-201011.Sample.Not.UTF16.txt.hands
  75. 77
      pyfpdb/regression-test-files/cash/FTP/Draw/5-Carddraw-Limit-USD-0.10-0.20-201011.Sample.Not.UTF16.txt.hp
  76. 3
      pyfpdb/regression-test-files/cash/FTP/Draw/5-Carddraw-NL-USD-0.10-0.20-201011.Saw.Showdown.Not.UTF16.txt.hands
  77. 90
      pyfpdb/regression-test-files/cash/FTP/Draw/5-Carddraw-NL-USD-0.10-0.20-201011.Saw.Showdown.Not.UTF16.txt.hp
  78. 3
      pyfpdb/regression-test-files/cash/FTP/Draw/5-Carddraw-PL-0.10-0.25-201011.Sample.Not.UTF16.txt.hands
  79. 68
      pyfpdb/regression-test-files/cash/FTP/Draw/5-Carddraw-PL-0.10-0.25-201011.Sample.Not.UTF16.txt.hp
  80. 3
      pyfpdb/regression-test-files/cash/FTP/Draw/Badugi-USD-0.05-0.10-201011.Sample.Not.UTF16.txt.hands
  81. 111
      pyfpdb/regression-test-files/cash/FTP/Draw/Badugi-USD-0.05-0.10-201011.Sample.Not.UTF16.txt.hp
  82. 3
      pyfpdb/regression-test-files/cash/FTP/Flop/LHE-9max-USD-1-2.201012.Button.Player4.Sitting.out.txt.hands
  83. 91
      pyfpdb/regression-test-files/cash/FTP/Flop/LHE-9max-USD-1-2.201012.Button.Player4.Sitting.out.txt.hp
  84. 3
      pyfpdb/regression-test-files/cash/FTP/Flop/LO8-6max-USD-200-400.200610.Observed.Hand.with.chat.txt.hands
  85. 67
      pyfpdb/regression-test-files/cash/FTP/Flop/LO8-6max-USD-200-400.200610.Observed.Hand.with.chat.txt.hp
  86. 3
      pyfpdb/regression-test-files/cash/FTP/Flop/NLHE-6max-EUR-0.01-0.02.201008.Weird.table.character.txt.hands
  87. 78
      pyfpdb/regression-test-files/cash/FTP/Flop/NLHE-6max-EUR-0.01-0.02.201008.Weird.table.character.txt.hp
  88. 3
      pyfpdb/regression-test-files/cash/FTP/Flop/NLHE-9max-USD-0.02-0.05.201007.Short.lived.date.format.txt.hands
  89. 117
      pyfpdb/regression-test-files/cash/FTP/Flop/NLHE-9max-USD-0.02-0.05.201007.Short.lived.date.format.txt.hp
  90. 3
      pyfpdb/regression-test-files/cash/FTP/Flop/PLO-6max-USD-0.01-0.02.201003.River.Showdown.txt.hands
  91. 78
      pyfpdb/regression-test-files/cash/FTP/Flop/PLO-6max-USD-0.01-0.02.201003.River.Showdown.txt.hp
  92. 91
      pyfpdb/regression-test-files/cash/FTP/Stud/7-Stud-USD-3-6-20106.Steal.from.Button.Failure.txt.hp
  93. 55
      pyfpdb/regression-test-files/cash/FTP/Stud/7-StudHL-USD-2-4-201103.Underscore.in.tablename.txt
  94. 3
      pyfpdb/regression-test-files/cash/FTP/Stud/Razz-USD-0.10-0.20-201012.CCT.and.ET.timeformat.txt.hands
  95. 91
      pyfpdb/regression-test-files/cash/FTP/Stud/Razz-USD-0.10-0.20-201012.CCT.and.ET.timeformat.txt.hp
  96. 3
      pyfpdb/regression-test-files/cash/FTP/Stud/Razz-USD-0.10-0.20-201012.Player6.listed.but.doesnt.act.txt.hands
  97. 104
      pyfpdb/regression-test-files/cash/FTP/Stud/Razz-USD-0.10-0.20-201012.Player6.listed.but.doesnt.act.txt.hp
  98. 65
      pyfpdb/regression-test-files/cash/OnGame/Flop/LHE-9max-USD-0.50-1.00-201008.All-in.with.showdown.txt.hp
  99. 3
      pyfpdb/regression-test-files/cash/OnGame/Flop/NLHE-10max-USD-0.02-0.04-201102.Speed.table.BWin.txt.hands
  100. 78
      pyfpdb/regression-test-files/cash/OnGame/Flop/NLHE-10max-USD-0.02-0.04-201102.Speed.table.BWin.txt.hp
  101. Some files were not shown because too many files have changed in this diff Show More

112
packaging/announce-0.22.txt

@ -0,0 +1,112 @@
Hello everyone,
The new fpdb release 0.22 is now available for download as source or as packages/installers for Debian, Gentoo, Ubuntu and Windows.
This version brings many improvements and bugfixes. A quick word on our version naming: We have decided to stop using the usual alpha/beta/rc release system as it doesn't suit fpdb's development style and resources. From now on all releases are created equal (ie. considered "testing"). If they proof themselves we declare them "stable" and make them the default download on sourceforge. If you wish to be notified of new releases or stabilisation please subscribe to the fpdb-announe mailing list (see Links further down). Since this version has been available for some time we consider it stable and recommend all users to update.
So... what is FPDB?
===================
FPDB (Free Poker Database) is a free/open source suite of steadily growing tools to track and analyse your online poker game. FPDB is able to import the hand histories that poker sites write to your computer and to store additional data from each hand in a database for use in later analysis.
FPDB is ambitious, intending to support all games. Currently we support flop based games (Hold’em, Omaha, Omaha Hi/Lo), stud games (7 Card Stud, 7 Card Stud Hi/Lo, and Razz) and draw games (Triple Draw Lowball, 5 Card Draw) on most major poker sites.
FPDB provides a Heads Up Display (HUD), Profit Grapher and Stats viewers with a list of features that is growing.
What's changed
==============
417 changesets (incl. merges) have gone in since 0.21-rc2. Some of the improvements are:
New stats:
Three bet: name="three_B" (note this stat was previously "three_B_0")
Four bet: name="four_B"
Cold four bet: name="cfour_B"
Squeeze bet preflop: name="squeeze"
Fold to three bet preflop: name="f_3bet"
Fold to four bet preflop: name="f_4bet"
Steal Success : name="s_steal"
Pokerstars Home Games now supported
Everest now supported
Winamax now supported
Translation progress:
Complete: English, Hungarian. If you notice an untranslated string in any output please let us know.
Partial: French (85%), German (32%), Polish (27%), Spanish (17%), Russian (6%).
Significant work on the underlying HUD code, including hud dragging and table closing
Problems where some stats became > 100% are now fixed
sqlite database performance improvements (sqlite is the default database for fpdb)
pokerstars.it tournament HUD now working
Cap games added to filter options
Initial work to support Rush poker - this will need further testing and improvement before we can release it. One or two testers would be welcome, please PM gimick if you want to help.
Various updates and fixes when importing Hand histories.
Party freeroll tournaments now recognised.
Stars 20/40 limit and FTP 1k/2k limit now recognised.
Initial work on a Stove function for holdem (see the viewers menu)
The windows exe has been upgraded from python 2.6 to python 2.7.
Where to get it
===============
Please note that you will have to either recreate your database or use a new one if you're updating from 0.21-rc2 or older. Fpdb will warn you if your database is incompatible and will not work unless you recreate or use a different one.
Config files from 0.20 and later should work. Please report if you have problems with config files from that version or later.
You can find checksums (MD5 and SHA512) in the download folder.
To download: http://sourceforge.net/projects/fpdb/files/fpdb/0.22/
Links
=====
To be notified by email of new versions you can subscribe to our announce mailing list here: https://lists.sourceforge.net/lists/listinfo/fpdb-announce
Link to fpdb website (wiki) http://fpdb.wiki.sourceforge.net/
Features page: http://sourceforge.net/apps/mediawiki/fpdb/index.php?title=Features
How to install&setup fpdb in 5 Minutes with the Windows installer: http://sf.net/projects/fpdb/files/fpdb/help/ Choose exe021install.avi (18mb, no sound)
Installation instructions are available from: http://sourceforge.net/apps/mediawiki/fpdb/index.php?title=Installation
Getting Started Instructions: http://sourceforge.net/apps/mediawiki/fpdb/index.php?title=Getting_Started
FAQ: http://sourceforge.net/apps/mediawiki/fpdb/index.php?title=FAQ
Screenshots: http://sourceforge.net/apps/mediawiki/fpdb/index.php?title=Screenshots
How to help
===========
Join us in IRC (see below) and say you want to do something :)
How to get help
===============
Please also see the "Bug reports" section below to enable us to help you.
These are listed in order of usefulness - the 2+2 thread in particular is rather chaotic so if we miss your post feel free to bring it up again
1) Chat/IRC
One of the developers is usually around, but it is IRC. Dont get discouraged because we didn't answer within 10 minutes, once we do you've probably got our full attention.
This link takes you to a website where you can talk to us directly: http://webchat.freenode.net/?channels=fpdb
Alternatively use can use any IRC client to connect to #fpdb on freenode.net
2) Mailing List
Visit http://lists.sourceforge.net/lists/listinfo/fpdb-main to subscribe to the development&support mailing list and send us an email
3) The monster 2+2 forum thread (registration required).
http://forumserver.twoplustwo.com/16...2009-a-273001/ Please dont let the size of the thread phase you. It is monitored and sends email notifications to some of the developers. (Note: If you play poker and don't frequent the 2+2 forums, you may want to become better acquainted. Its a bit daunting at first, but well worth the effort)
Bug reports
===========
When you do report issues, try to make it easier for us help you. We usually need at least the following information:
- Operating system and version (e.g. Ubuntu 10.10 or Windows XP)
- Database type (MySQL, SQLite, PostgreSQL)
- Install method (exe, tarball, deb, git, ebuild)
- Fpdb version
- Site name and gametype (e.g. $10 Pokerstars Razz SnG)
You can find most of these details for easy copy&paste in the Help menu under About.
Important known problems
========================
Hud will not work if using postgres database - fixed in 0.23
PKR is not working correctly
Special information for Windows installations
=============================================
First-time installs will need to download and install the C++ runtime executable from Microsoft.
Windows 7 and windows Vista users will need to set fpdb.exe and hud_main.exe to run as administrator (see http://sourceforge.net/apps/mediawiki/fpdb/index.php?title=Install_in_Windows)
Contributors
============
Code/translations: Worros, Donoban, Nutomatic, Steffen, Chaz Littlejohn, Scott Wolchok, tribumarchal, Erki Ferenc, Eric Blade, atinm, Mika Bostrom, Robert Wielinga, Chris Moore, Gerko de Roo, Gimick
Special shoutout to Eleatic Stranger who has written an initial converter for Carbon poker, without ever having played on the site!
Documentation: RSOAndrew, Buggernaut, ChazDazzle
Testers and everyone answering forum questions - xaviax, Dog, uncooper etc. You know who you are.
Hand History donations: Quite a few people on this list now. Every donation for alternate sites and various corner cases is appreciated.
And a particular thanks to all the libraries, interpreters etc. that we use to create fpdb!

78
packaging/announce-template.txt

@ -0,0 +1,78 @@
Replace all occurrences of XXX with the real values.
Remove or leave YYY(foobar)YYY sections as appropriate.
Hello everyone,
The new fpdb release XXX is now available for download as source or as packages/installers for Debian, Gentoo, Ubuntu and Windows.
This version brings many improvements and bugfixes. A quick word on our version naming: We have decided to stop using the usual alpha/beta/rc release system as it doesn't suit fpdb's development style and resources. From now on all releases are created equal (ie. considered "testing"). If they proof themselves we declare them "stable" and make them the default download on sourceforge. If you wish to be notified of new releases or stabilisation please subscribe to the fpdb-announe mailing list (see Links further down).
So... what is FPDB?
===================
FPDB (Free Poker Database) is a free/open source suite of steadily growing tools to track and analyse your online poker game. FPDB is able to import the hand histories that poker sites write to your computer and to store additional data from each hand in a database for use in later analysis.
FPDB is ambitious, intending to support all games. Currently we support flop based games (Hold’em, Omaha, Omaha Hi/Lo), stud games (7 Card Stud, 7 Card Stud Hi/Lo, and Razz) and draw games (Triple Draw Lowball, 5 Card Draw) on most major poker sites.
FPDB provides a Heads Up Display (HUD), Profit Grapher and Stats viewers with a list of features that is growing.
What's changed
==============
XXX changesets (incl. merges) have gone in since XXX. Some of the improvements are:
XXX
Where to get it
===============
Please note that you will have to either recreate your database or use a new one if you're updating from XXX or older. Fpdb will warn you if your database is incompatible and will not work unless you recreate or use a different one.
Config files from 0.20 and later should work. Please report if you have problems with config files from that version or later.
You can find checksums (MD5 and SHA512) in the download folder.
To download: http://sourceforge.net/projects/fpdb/files/fpdb/XXX/
Links
=====
To be notified by email of new versions you can subscribe to our announce mailing list here: https://lists.sourceforge.net/lists/listinfo/fpdb-announce
Link to fpdb website (wiki) http://fpdb.wiki.sourceforge.net/
Features page: http://sourceforge.net/apps/mediawiki/fpdb/index.php?title=Features
How to install&setup fpdb in 5 Minutes with the Windows installer: http://sf.net/projects/fpdb/files/fpdb/help/ Choose exe021install.avi (18mb, no sound)
Installation instructions are available from: http://sourceforge.net/apps/mediawiki/fpdb/index.php?title=Installation
Getting Started Instructions: http://sourceforge.net/apps/mediawiki/fpdb/index.php?title=Getting_Started
FAQ: http://sourceforge.net/apps/mediawiki/fpdb/index.php?title=FAQ
Screenshots: http://sourceforge.net/apps/mediawiki/fpdb/index.php?title=Screenshots
How to help
===========
Join us in IRC (see below) and say you want to do something :)
How to get help
===============
Please also see the "Bug reports" section below to enable us to help you.
These are listed in order of usefulness - the 2+2 thread in particular is rather chaotic so if we miss your post feel free to bring it up again
1) Chat/IRC
One of the developers is usually around, but it is IRC. Dont get discouraged because we didn't answer within 10 minutes, once we do you've probably got our full attention.
This link takes you to a website where you can talk to us directly: http://webchat.freenode.net/?channels=fpdb
Alternatively use can use any IRC client to connect to #fpdb on freenode.net
2) Mailing List
Visit http://lists.sourceforge.net/lists/listinfo/fpdb-main to subscribe to the development&support mailing list and send us an email
3) The monster 2+2 forum thread (registration required).
http://forumserver.twoplustwo.com/16...2009-a-273001/ Please dont let the size of the thread phase you. It is monitored and sends email notifications to some of the developers. (Note: If you play poker and don't frequent the 2+2 forums, you may want to become better acquainted. Its a bit daunting at first, but well worth the effort)
Bug reports
===========
When you do report issues, try to make it easier for us help you. We usually need at least the following information:
- Operating system and version (e.g. Ubuntu 10.10 or Windows XP)
- Database type (MySQL, SQLite, PostgreSQL)
- Install method (exe, tarball, deb, git, ebuild)
- Fpdb version
- Site name and gametype (e.g. $10 Pokerstars Razz SnG)
You can find most of these details for easy copy&paste in the Help menu under About.
Important known problems
========================
YYY(PKR is not working correctly)YYY
Special information for Windows installations
=============================================
YYY(First-time installs may need to download and install the C++ runtime executable from Microsoft.)YYY
YYY(Windows 7 and windows Vista users will need to set fpdb.exe and hud_main.exe to run as administrator (see http://sourceforge.net/apps/mediawiki/fpdb/index.php?title=Install_in_Windows))YYY
Contributors
============
For the latest list of contributors please see YYY(replace with link to git-web of contributors.txt)YYY

12
packaging/debian/changelog vendored

@ -1,3 +1,15 @@
free-poker-tools (0.22-1) unstable; urgency=low
* New release: 0.22
-- Mika Bostrom <bostik@iki.fi> Sun, 13 Mar 2011 05:15:24 +0200
free-poker-tools (0.21-1) unstable; urgency=low
* New release: 0.21
-- Mika Bostrom <bostik@iki.fi> Mon, 28 Feb 2011 04:09:57 +0200
free-poker-tools (0.21~rc2) unstable; urgency=low
* Second 0.21 release-candidate

42
packaging/gentoo/current_testing.ebuild → packaging/gentoo/current.ebuild

@ -10,14 +10,14 @@ inherit eutils games
DESCRIPTION="A free/open source tracker/HUD for use with online poker"
HOMEPAGE="http://fpdb.wiki.sourceforge.net/"
SRC_URI="mirror://sourceforge/${PN}/Snapshots/${P}.tar.bz2"
SRC_URI="mirror://sourceforge/${PN}/${PV}/${P}.tar.bz2"
LICENSE="AGPL-3"
SLOT="0"
KEYWORDS="~amd64 ~x86"
#note: this should work on other architectures too, please send me your experiences
#note: fpdb has only been tested on x86 and amd64, but should work on other arches, too
IUSE="graph mysql postgres sqlite linguas_de linguas_hu linguas_fr"
IUSE="graph mysql postgres sqlite linguas_de linguas_es linguas_fr linguas_hu linguas_it linguas_pl linguas_pt linguas_ru linguas_zh"
RDEPEND="
mysql? ( virtual/mysql
dev-python/mysql-python )
@ -39,8 +39,40 @@ src_install() {
doins -r gfx || die "failed to install gfx directory"
doins -r pyfpdb || die "failed to install pyfpdb directory"
if use linguas_de; then
msgfmt pyfpdb/locale/fpdb-de_DE.po -o pyfpdb/locale/de.mo || die "failed to create German mo file"
fi
if use linguas_es; then
msgfmt pyfpdb/locale/fpdb-es_ES.po -o pyfpdb/locale/es.mo || die "failed to create Spanish mo file"
fi
if use linguas_fr; then
msgfmt pyfpdb/locale/fpdb-fr_FR.po -o pyfpdb/locale/fr.mo || die "failed to create French mo file"
fi
if use linguas_hu; then
msgfmt pyfpdb/locale/fpdb-hu_HU.po -o pyfpdb/locale/hu.mo || die "failed to create hungarian mo file"
msgfmt pyfpdb/locale/fpdb-hu_HU.po -o pyfpdb/locale/hu.mo || die "failed to create Hungarian mo file"
fi
if use linguas_it; then
msgfmt pyfpdb/locale/fpdb-it_IT.po -o pyfpdb/locale/it.mo || die "failed to create Italian mo file"
fi
if use linguas_pl; then
msgfmt pyfpdb/locale/fpdb-pl_PL.po -o pyfpdb/locale/pl.mo || die "failed to create Polish mo file"
fi
if use linguas_pt; then
msgfmt pyfpdb/locale/fpdb-pt_BR.po -o pyfpdb/locale/pt.mo || die "failed to create Portuguese mo file"
fi
if use linguas_ru; then
msgfmt pyfpdb/locale/fpdb-ru_RU.po -o pyfpdb/locale/ru.mo || die "failed to create Russian mo file"
fi
if use linguas_zh; then
msgfmt pyfpdb/locale/fpdb-zh_CN.po -o pyfpdb/locale/zh.mo || die "failed to create Chinese mo file"
fi
domo pyfpdb/locale/*.mo || die "failed to install mo files"
@ -51,7 +83,7 @@ src_install() {
doexe run_fpdb.py || die "failed to install executable run_fpdb.py"
dodir "${GAMES_BINDIR}"
dosym "${GAMES_DATADIR}"/${PN}/run_fpdb.py "${GAMES_BINDIR}"/${PN} || die "failed to create symlink for starting fpdb"
dosym "${GAMES_DATADIR}"/${PN}/run_fpdb.py "${GAMES_BINDIR}"/${PN} || die "failed to create symlink for starting fpdb"
newicon gfx/fpdb-icon.png ${PN}.png || die "failed to install fpdb icon"
make_desktop_entry ${PN} || die "failed to create desktop entry"

60
packaging/gentoo/current_stable.ebuild

@ -1,60 +0,0 @@
# Copyright 1999-2011 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
#TODO: Header, add cdecimal
EAPI="2"
inherit eutils games
DESCRIPTION="A free/open source tracker/HUD for use with online poker"
HOMEPAGE="http://fpdb.wiki.sourceforge.net/"
SRC_URI="mirror://sourceforge/${PN}/${PV}/${P}.tar.bz2"
LICENSE="AGPL-3"
SLOT="0"
KEYWORDS="~amd64 ~x86"
#note: this should work on other architectures too, please send me your experiences
IUSE="graph mysql postgres sqlite"
RDEPEND="
mysql? ( virtual/mysql
dev-python/mysql-python )
postgres? ( dev-db/postgresql-server
dev-python/psycopg )
sqlite? ( dev-lang/python[sqlite]
dev-python/numpy )
>=x11-libs/gtk+-2.10
dev-python/pygtk
graph? ( dev-python/numpy
dev-python/matplotlib[gtk] )
dev-python/python-xlib
dev-python/pytz"
DEPEND="${RDEPEND}"
src_install() {
insinto "${GAMES_DATADIR}"/${PN}
doins -r gfx
doins -r pyfpdb
doins readme.txt
exeinto "${GAMES_DATADIR}"/${PN}
doexe run_fpdb.py
dodir "${GAMES_BINDIR}"
dosym "${GAMES_DATADIR}"/${PN}/run_fpdb.py "${GAMES_BINDIR}"/${PN}
newicon gfx/fpdb-icon.png ${PN}.png
make_desktop_entry ${PN}
fperms +x "${GAMES_DATADIR}"/${PN}/pyfpdb/*.pyw
prepgamesdirs
}
pkg_postinst() {
games_pkg_postinst
elog "Note that if you really want to use mysql or postgresql you will have to create"
elog "the database and user yourself and enter it into the fpdb config."
elog "You can find the instructions on the project's website."
}

53
packaging/gentoo/fpdb-9999.ebuild

@ -15,8 +15,9 @@ EGIT_REPO_URI="git://git.assembla.com/fpdb.git"
LICENSE="AGPL-3"
SLOT="0"
KEYWORDS=""
#note: fpdb has only been tested on x86 and amd64, but should work on other arches, too
IUSE="graph mysql postgres sqlite linguas_de linguas_hu linguas_fr"
IUSE="graph mysql postgres sqlite linguas_de linguas_es linguas_fr linguas_hu linguas_it linguas_pl linguas_pt linguas_ru linguas_zh"
RDEPEND="
mysql? ( virtual/mysql
dev-python/mysql-python )
@ -29,7 +30,7 @@ RDEPEND="
graph? ( dev-python/numpy
dev-python/matplotlib[gtk] )
dev-python/python-xlib
dev-python/pytz"
x11-apps/xwininfo"
DEPEND="${RDEPEND}"
src_unpack() {
@ -38,29 +39,57 @@ src_unpack() {
src_install() {
insinto "${GAMES_DATADIR}"/${PN}
doins -r gfx
doins -r pyfpdb
doins -r gfx || die "failed to install gfx directory"
doins -r pyfpdb || die "failed to install pyfpdb directory"
if use linguas_de; then
msgfmt pyfpdb/locale/fpdb-de_DE.po -o pyfpdb/locale/de.mo
msgfmt pyfpdb/locale/fpdb-de_DE.po -o pyfpdb/locale/de.mo || die "failed to create German mo file"
fi
if use linguas_es; then
msgfmt pyfpdb/locale/fpdb-es_ES.po -o pyfpdb/locale/es.mo || die "failed to create Spanish mo file"
fi
if use linguas_fr; then
msgfmt pyfpdb/locale/fpdb-fr_FR.po -o pyfpdb/locale/fr.mo || die "failed to create French mo file"
fi
if use linguas_hu; then
msgfmt pyfpdb/locale/fpdb-hu_HU.po -o pyfpdb/locale/hu.mo
msgfmt pyfpdb/locale/fpdb-hu_HU.po -o pyfpdb/locale/hu.mo || die "failed to create Hungarian mo file"
fi
if use linguas_it; then
msgfmt pyfpdb/locale/fpdb-it_IT.po -o pyfpdb/locale/it.mo || die "failed to create Italian mo file"
fi
if use linguas_pl; then
msgfmt pyfpdb/locale/fpdb-pl_PL.po -o pyfpdb/locale/pl.mo || die "failed to create Polish mo file"
fi
if use linguas_pt; then
msgfmt pyfpdb/locale/fpdb-pt_BR.po -o pyfpdb/locale/pt.mo || die "failed to create Portuguese mo file"
fi
if use linguas_ru; then
msgfmt pyfpdb/locale/fpdb-ru_RU.po -o pyfpdb/locale/ru.mo || die "failed to create Russian mo file"
fi
if use linguas_zh; then
msgfmt pyfpdb/locale/fpdb-zh_CN.po -o pyfpdb/locale/zh.mo || die "failed to create Chinese mo file"
fi
domo pyfpdb/locale/*.mo
domo pyfpdb/locale/*.mo || die "failed to install mo files"
doins readme.txt
doins readme.txt || die "failed to install readme.txt file"
exeinto "${GAMES_DATADIR}"/${PN}
doexe run_fpdb.py
doexe run_fpdb.py || die "failed to install executable run_fpdb.py"
dodir "${GAMES_BINDIR}"
dosym "${GAMES_DATADIR}"/${PN}/run_fpdb.py "${GAMES_BINDIR}"/${PN}
dosym "${GAMES_DATADIR}"/${PN}/run_fpdb.py "${GAMES_BINDIR}"/${PN} || die "failed to create symlink for starting fpdb"
newicon gfx/fpdb-icon.png ${PN}.png
make_desktop_entry ${PN}
newicon gfx/fpdb-icon.png ${PN}.png || die "failed to install fpdb icon"
make_desktop_entry ${PN} || die "failed to create desktop entry"
fperms +x "${GAMES_DATADIR}"/${PN}/pyfpdb/*.pyw
prepgamesdirs

4
pyfpdb/AbsoluteToFpdb.py

@ -138,7 +138,7 @@ class Absolute(HandHistoryConverter):
if not m:
tmp = handText[0:100]
log.error(_("Unable to recognise gametype from: '%s'") % tmp)
log.error(_("determineGameType: Raising FpdbParseError"))
log.error("determineGameType: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
@ -349,7 +349,7 @@ class Absolute(HandHistoryConverter):
bet = action.group('BET').replace(',', '')
hand.addComplete( street, action.group('PNAME'), bet)
else:
logging.debug(_("Unimplemented readAction: '%s' '%s'") % (action.group('PNAME'),action.group('ATYPE')))
logging.debug(_("Unimplemented readAction: '%s' '%s'") % (action.group('PNAME'), action.group('ATYPE')))
def readShowdownActions(self, hand):

134
pyfpdb/AlchemyFacilities.py

@ -1,134 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#Copyright 2009-2011 Grigorij Indigirkin
#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU Affero General Public License as published by
#the Free Software Foundation, version 3 of the License.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU Affero General Public License
#along with this program. If not, see <http://www.gnu.org/licenses/>.
#In the "official" distribution you can find the license in agpl-3.0.txt.
#TODO: gettextify if file is used again
from decimal_wrapper import Decimal
from sqlalchemy import types
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy.exc import IntegrityError
import Card
class CardColumn(types.TypeDecorator):
"""Stores cards as smallints
Automatically converts values like '9h' to smallint
>>> CardColumn().process_bind_param( 'Td', '' )
22
>>> CardColumn().process_bind_param( u'Td', '' )
22
>>> CardColumn().process_bind_param( 22, '' )
22
>>> CardColumn().process_result_value( 22, '' )
'Td'
"""
impl = types.SmallInteger
def process_bind_param(self, value, dialect):
if value is None or isinstance(value, int):
return value
elif isinstance(value, basestring) and len(value) == 2:
return Card.encodeCard(str(value))
else:
raise Exception, "Incorrect card value: " + repr(value)
def process_result_value(self, value, dialect):
return Card.valueSuitFromCard( value )
class MoneyColumn(types.TypeDecorator):
"""Stores money: bets, pots, etc
Understands:
Decimal as real amount
int as amount mupliplied by 100
string as decimal
Returns Decimal
>>> MoneyColumn().process_bind_param( 230, '' )
230
>>> MoneyColumn().process_bind_param( Decimal('2.30'), '' )
230
>>> MoneyColumn().process_bind_param( '2.30', '' )
230
>>> MoneyColumn().process_result_value( 230, '' )
Decimal('2.3')
"""
impl = types.Integer
def process_bind_param(self, value, dialect):
if value is None or isinstance(value, int):
return value
elif isinstance(value, basestring) or isinstance(value, Decimal):
return int(Decimal(value)*100)
else:
raise Exception, "Incorrect amount:" + repr(value)
def process_result_value(self, value, dialect):
if value is None:
return None
return Decimal(value)/100
class BigIntColumn(types.TypeDecorator, types.Integer):
"""Representing db-independent big integer """
# Integer inheritance required for auto_increment flag
impl = types.Integer
def load_dialect_impl(self, dialect):
from sqlalchemy import databases
if dialect.name == 'mysql':
return databases.mysql.MSBigInteger()
elif dialect.name == 'postgres':
return databases.mysql.PGBigInteger()
return types.Integer()
class MappedBase(object):
"""Provide dummy contrcutor"""
def __init__(self, **kwargs):
for k, v in kwargs.iteritems():
setattr(self, k, v)
def get_columns_names(self):
return [i.name for i in self._sa_class_manager.mapper.c]
def get_or_create(klass, session, **kwargs):
"""
Looks up an object with the given kwargs, creating one if necessary.
Returns a tuple of (object, created), where created is a boolean
specifying whether an object was created.
"""
assert kwargs, \
'get_or_create() must be passed at least one keyword argument'
try:
return session.query(klass).filter_by(**kwargs).one(), False
except NoResultFound:
try:
obj = klass(**kwargs)
session.add(obj)
session.flush()
return obj, True
except IntegrityError:
return session.query(klass).filter_by(**kwargs).one(), False

485
pyfpdb/AlchemyMappings.py

@ -1,485 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#Copyright 2009-2011 Grigorij Indigirkin
#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU Affero General Public License as published by
#the Free Software Foundation, version 3 of the License.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU Affero General Public License
#along with this program. If not, see <http://www.gnu.org/licenses/>.
#In the "official" distribution you can find the license in agpl-3.0.txt.
"""@package AlchemyMappings
This package contains all classes to be mapped and mappers themselves
"""
#TODO: gettextify if file is used again
import logging
import re
from decimal_wrapper import Decimal
from sqlalchemy.orm import mapper, relation, reconstructor
from sqlalchemy.sql import select
from collections import defaultdict
from AlchemyTables import *
from AlchemyFacilities import get_or_create, MappedBase
from DerivedStats import DerivedStats
from Exceptions import IncompleteHandError, FpdbError
class Player(MappedBase):
"""Class reflecting Players db table"""
@staticmethod
def get_or_create(session, siteId, name):
return get_or_create(Player, session, siteId=siteId, name=name)[0]
def __str__(self):
return '<Player "%s" on %s>' % (self.name, self.site and self.site.name)
class Gametype(MappedBase):
"""Class reflecting Gametypes db table"""
@staticmethod
def get_or_create(session, siteId, gametype):
map = zip(
['type', 'base', 'category', 'limitType', 'smallBlind', 'bigBlind', 'smallBet', 'bigBet', 'currency'],
['type', 'base', 'category', 'limitType', 'sb', 'bb', 'dummy', 'dummy', 'currency'])
gametype = dict([(new, gametype.get(old)) for new, old in map ])
hilo = "h"
if gametype['category'] in ('studhilo', 'omahahilo'):
hilo = "s"
elif gametype['category'] in ('razz','27_3draw','badugi'):
hilo = "l"
gametype['hiLo'] = hilo
for f in ['smallBlind', 'bigBlind', 'smallBet', 'bigBet']:
if gametype[f] is None:
gametype[f] = 0
gametype[f] = int(Decimal(gametype[f])*100)
gametype['siteId'] = siteId
return get_or_create(Gametype, session, **gametype)[0]
class HandActions(object):
"""Class reflecting HandsActions db table"""
def initFromImportedHand(self, hand, actions):
self.hand = hand
self.actions = {}
for street, street_actions in actions.iteritems():
self.actions[street] = []
for v in street_actions:
hp = hand.handplayers_by_name[v[0]]
self.actions[street].append({'street': street, 'pid': hp.id, 'seat': hp.seatNo, 'action':v})
@property
def flat_actions(self):
actions = []
for street in self.hand.allStreets:
actions += self.actions[street]
return actions
class HandInternal(DerivedStats):
"""Class reflecting Hands db table"""
def parseImportedHandStep1(self, hand):
"""Extracts values to insert into from hand returned by HHC. No db is needed he"""
hand.players = hand.getAlivePlayers()
# also save some data for step2. Those fields aren't in Hands table
self.siteId = hand.siteId
self.gametype_dict = hand.gametype
self.attachHandPlayers(hand)
self.attachActions(hand)
self.assembleHands(hand)
self.assembleHandsPlayers(hand)
def parseImportedHandStep2(self, session):
"""Fetching ids for gametypes and players"""
gametype = Gametype.get_or_create(session, self.siteId, self.gametype_dict)
self.gametypeId = gametype.id
for hp in self.handPlayers:
hp.playerId = Player.get_or_create(session, self.siteId, hp.name).id
def getPlayerByName(self, name):
if not hasattr(self, 'handplayers_by_name'):
self.handplayers_by_name = {}
for hp in self.handPlayers:
pname = getattr(hp, 'name', None) or hp.player.name
self.handplayers_by_name[pname] = hp
return self.handplayers_by_name[name]
def attachHandPlayers(self, hand):
"""Fill HandInternal.handPlayers list. Create self.handplayers_by_name"""
hand.noSb = getattr(hand, 'noSb', None)
if hand.noSb is None and self.gametype_dict['base']=='hold':
saw_sb = False
for action in hand.actions[hand.actionStreets[0]]: # blindsantes
if action[1] == 'posts' and action[2] == 'small blind' and action[0] is not None:
saw_sb = True
hand.noSb = saw_sb
self.handplayers_by_name = {}
for seat, name, chips in hand.players:
p = HandPlayer(hand = self, imported_hand=hand, seatNo=seat,
name=name, startCash=chips)
self.handplayers_by_name[name] = p
def attachActions(self, hand):
"""Create HandActions object"""
a = HandActions()
a.initFromImportedHand(self, hand.actions)
def parseImportedTournament(self, hand, session):
"""Fetching tourney, its type and players
Must be called after Step2
"""
if self.gametype_dict['type'] != 'tour': return
# check for consistense
for i in ('buyin', 'tourNo'):
if not hasattr(hand, i):
raise IncompleteHandError(
"Field '%s' required for tournaments" % i, self.id, hand )
# repair old-style buyin value
m = re.match('\$(\d+)\+\$(\d+)', hand.buyin)
if m is not None:
hand.buyin, self.fee = m.groups()
# fetch tourney type
tour_type_hand2db = {
'buyin': 'buyin',
'fee': 'fee',
'speed': 'speed',
'maxSeats': 'maxseats',
'knockout': 'isKO',
'rebuy': 'isRebuy',
'addOn': 'isAddOn',
'shootout': 'isShootout',
'matrix': 'isMatrix',
'sng': 'isSNG',
}
tour_type_index = dict([
( i_db, getattr(hand, i_hand, None) )
for i_db, i_hand in tour_type_hand2db.iteritems()
])
tour_type_index['siteId'] = self.siteId
tour_type = TourneyType.get_or_create(session, **tour_type_index)
# fetch and update tourney
tour = Tourney.get_or_create(session, hand.tourNo, tour_type.id)
cols = tour.get_columns_names()
for col in cols:
hand_val = getattr(hand, col, None)
if col in ('id', 'tourneyTypeId', 'comment', 'commentTs') or hand_val is None:
continue
db_val = getattr(tour, col, None)
if db_val is None:
setattr(tour, col, hand_val)
elif col == 'koBounty':
setattr(tour, col, max(db_val, hand_val))
elif col == 'tourStartTime' and hand.startTime:
setattr(tour, col, min(db_val, hand.startTime))
if tour.entries is None and tour_type.sng:
tour.entries = tour_type.maxSeats
# fetch and update tourney players
for hp in self.handPlayers:
tp = TourneysPlayer.get_or_create(session, tour.id, hp.playerId)
# FIXME: other TourneysPlayers should be added here
session.flush()
def isDuplicate(self, session):
"""Checks if current hand already exists in db
siteHandNo ans gametypeId have to be setted
"""
return session.query(HandInternal).filter_by(
siteHandNo=self.siteHandNo, gametypeId=self.gametypeId).count()!=0
def __str__(self):
s = list()
for i in self._sa_class_manager.mapper.c:
s.append('%25s %s' % (i, getattr(self, i.name)))
s+=['', '']
for i,p in enumerate(self.handPlayers):
s.append('%d. %s' % (i, p.name or '???'))
s.append(str(p))
return '\n'.join(s)
@property
def boardcards(self):
cards = []
for i in range(5):
cards.append(getattr(self, 'boardcard%d' % (i+1), None))
return filter(bool, cards)
@property
def HandClass(self):
"""Return HoldemOmahaHand or something like this"""
import Hand
if self.gametype.base == 'hold':
return Hand.HoldemOmahaHand
elif self.gametype.base == 'draw':
return Hand.DrawHand
elif self.gametype.base == 'stud':
return Hand.StudHand
raise Exception("Unknow gametype.base: '%s'" % self.gametype.base)
@property
def allStreets(self):
return self.HandClass.allStreets
@property
def actionStreets(self):
return self.HandClass.actionStreets
class HandPlayer(MappedBase):
"""Class reflecting HandsPlayers db table"""
def __init__(self, **kwargs):
if 'imported_hand' in kwargs and 'seatNo' in kwargs:
imported_hand = kwargs.pop('imported_hand')
self.position = self.getPosition(imported_hand, kwargs['seatNo'])
super(HandPlayer, self).__init__(**kwargs)
@reconstructor
def init_on_load(self):
self.name = self.player.name
@staticmethod
def getPosition(hand, seat):
"""Returns position value like 'B', 'S', '0', '1', ...
>>> class A(object): pass
...
>>> A.noSb = False
>>> A.maxseats = 6
>>> A.buttonpos = 2
>>> A.gametype = {'base': 'hold'}
>>> A.players = [(i, None, None) for i in (2, 4, 5, 6)]
>>> HandPlayer.getPosition(A, 6) # cut off
'1'
>>> HandPlayer.getPosition(A, 2) # button
'0'
>>> HandPlayer.getPosition(A, 4) # SB
'S'
>>> HandPlayer.getPosition(A, 5) # BB
'B'
>>> A.noSb = True
>>> HandPlayer.getPosition(A, 5) # MP3
'2'
>>> HandPlayer.getPosition(A, 6) # cut off
'1'
>>> HandPlayer.getPosition(A, 2) # button
'0'
>>> HandPlayer.getPosition(A, 4) # BB
'B'
"""
from itertools import chain
if hand.gametype['base'] == 'stud':
# FIXME: i've never played stud so plz check & del comment \\grindi
bringin = None
for action in chain(*[self.actions[street] for street in hand.allStreets]):
if action[1]=='bringin':
bringin = action[0]
break
if bringin is None:
raise Exception, "Cannot find bringin"
# name -> seat
bringin = int(filter(lambda p: p[1]==bringin, bringin)[0])
seat = (int(seat) - int(bringin))%int(hand.maxseats)
return str(seat)
else:
seats_occupied = sorted([seat_ for seat_, name, chips in hand.players], key=int)
if hand.buttonpos not in seats_occupied:
# i.e. something like
# Seat 3: PlayerX ($0), is sitting out
# The button is in seat #3
hand.buttonpos = max(seats_occupied,
key = lambda s: int(s)
if int(s) <= int(hand.buttonpos)
else int(s) - int(hand.maxseats)
)
seats_occupied = sorted(seats_occupied,
key = lambda seat_: (
- seats_occupied.index(seat_)
+ seats_occupied.index(hand.buttonpos)
+ 2) % len(seats_occupied)
)
# now (if SB presents) seats_occupied contains seats in order: BB, SB, BU, CO, MP3, ...
if hand.noSb:
# fix order in the case nosb
seats_occupied = seats_occupied[1:] + seats_occupied[0:1]
seats_occupied.insert(1, -1)
seat = seats_occupied.index(seat)
if seat == 0:
return 'B'
elif seat == 1:
return 'S'
else:
return str(seat-2)
@property
def cards(self):
cards = []
for i in range(7):
cards.append(getattr(self, 'card%d' % (i+1), None))
return filter(bool, cards)
def __str__(self):
s = list()
for i in self._sa_class_manager.mapper.c:
s.append('%45s %s' % (i, getattr(self, i.name)))
return '\n'.join(s)
class Site(object):
"""Class reflecting Players db table"""
INITIAL_DATA = [
(1 , 'Full Tilt Poker','FT'),
(2 , 'PokerStars', 'PS'),
(3 , 'Everleaf', 'EV'),
(4 , 'Win2day', 'W2'),
(5 , 'OnGame', 'OG'),
(6 , 'UltimateBet', 'UB'),
(7 , 'Betfair', 'BF'),
(8 , 'Absolute', 'AB'),
(9 , 'PartyPoker', 'PP'),
(10, 'Partouche', 'PA'),
(11, 'Carbon', 'CA'),
(12, 'PKR', 'PK'),
(13, 'PacificPoker', 'P8'),
]
INITIAL_DATA_KEYS = ('id', 'name', 'code')
INITIAL_DATA_DICTS = [ dict(zip(INITIAL_DATA_KEYS, datum)) for datum in INITIAL_DATA ]
@classmethod
def insert_initial(cls, connection):
connection.execute(sites_table.insert(), cls.INITIAL_DATA_DICTS)
class Tourney(MappedBase):
"""Class reflecting Tourneys db table"""
@classmethod
def get_or_create(cls, session, siteTourneyNo, tourneyTypeId):
"""Fetch tourney by index or creates one if none. """
return get_or_create(cls, session, siteTourneyNo=siteTourneyNo,
tourneyTypeId=tourneyTypeId)[0]
class TourneyType(MappedBase):
"""Class reflecting TourneyType db table"""
@classmethod
def get_or_create(cls, session, **kwargs):
"""Fetch tourney type by index or creates one if none
Required kwargs:
buyin fee speed maxSeats knockout
rebuy addOn shootout matrix sng currency
"""
return get_or_create(cls, session, **kwargs)[0]
class TourneysPlayer(MappedBase):
"""Class reflecting TourneysPlayers db table"""
@classmethod
def get_or_create(cls, session, tourneyId, playerId):
"""Fetch tourney player by index or creates one if none """
return get_or_create(cls, session, tourneyId=tourneyId, playerId=playerId)
class Version(object):
"""Provides read/write access for version var"""
CURRENT_VERSION = 120 # db version for current release
# 119 - first alchemy version
# 120 - add m_factor
conn = None
ver = None
def __init__(self, connection=None):
if self.__class__.conn is None:
self.__class__.conn = connection
@classmethod
def is_wrong(cls):
return cls.get() != cls.CURRENT_VERSION
@classmethod
def get(cls):
if cls.ver is None:
try:
cls.ver = cls.conn.execute(select(['version'], settings_table)).fetchone()[0]
except:
return None
return cls.ver
@classmethod
def set(cls, value):
if cls.conn.execute(settings_table.select()).rowcount==0:
cls.conn.execute(settings_table.insert(), version=value)
else:
cls.conn.execute(settings_table.update().values(version=value))
cls.ver = value
@classmethod
def set_initial(cls):
cls.set(cls.CURRENT_VERSION)
mapper (Gametype, gametypes_table, properties={
'hands': relation(HandInternal, backref='gametype'),
})
mapper (Player, players_table, properties={
'playerHands': relation(HandPlayer, backref='player'),
'playerTourney': relation(TourneysPlayer, backref='player'),
})
mapper (Site, sites_table, properties={
'gametypes': relation(Gametype, backref = 'site'),
'players': relation(Player, backref = 'site'),
'tourneyTypes': relation(TourneyType, backref = 'site'),
})
mapper (HandActions, hands_actions_table, properties={})
mapper (HandInternal, hands_table, properties={
'handPlayers': relation(HandPlayer, backref='hand'),
'actions_all': relation(HandActions, backref='hand', uselist=False),
})
mapper (HandPlayer, hands_players_table, properties={})
mapper (Tourney, tourneys_table)
mapper (TourneyType, tourney_types_table, properties={
'tourneys': relation(Tourney, backref='type'),
})
mapper (TourneysPlayer, tourneys_players_table)
class LambdaKeyDict(defaultdict):
"""Operates like defaultdict but passes key argument to the factory function"""
def __missing__(key):
return self.default_factory(key)

460
pyfpdb/AlchemyTables.py

@ -1,460 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#Copyright 2009-2011 Grigorij Indigirkin
#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU Affero General Public License as published by
#the Free Software Foundation, version 3 of the License.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU Affero General Public License
#along with this program. If not, see <http://www.gnu.org/licenses/>.
#In the "official" distribution you can find the license in agpl-3.0.txt.
"""@package AlchemyTables
Contains all sqlalchemy tables
"""
#TODO: gettextify if file is used again
from sqlalchemy import Table, Float, Column, Integer, String, MetaData, \
ForeignKey, Boolean, SmallInteger, DateTime, Text, Index, CHAR, \
PickleType, Unicode
from AlchemyFacilities import CardColumn, MoneyColumn, BigIntColumn
metadata = MetaData()
autorates_table = Table('Autorates', metadata,
Column('id', Integer, primary_key=True, nullable=False),
Column('playerId', Integer, ForeignKey("Players.id"), nullable=False),
Column('gametypeId', SmallInteger, ForeignKey("Gametypes.id"), nullable=False),
Column('description', String(50), nullable=False),
Column('shortDesc', CHAR(8), nullable=False),
Column('ratingTime', DateTime, nullable=False),
Column('handCount', Integer, nullable=False),
mysql_charset='utf8',
mysql_engine='InnoDB',
)
gametypes_table = Table('Gametypes', metadata,
Column('id', SmallInteger, primary_key=True),
Column('siteId', SmallInteger, ForeignKey("Sites.id"), nullable=False), # SMALLINT
Column('currency', String(4), nullable=False), # varchar(4) NOT NULL
Column('type', String(4), nullable=False), # char(4) NOT NULL
Column('base', String(4), nullable=False), # char(4) NOT NULL
Column('category', String(9), nullable=False), # varchar(9) NOT NULL
Column('limitType', CHAR(2), nullable=False), # char(2) NOT NULL
Column('hiLo', CHAR(1), nullable=False), # char(1) NOT NULL
Column('smallBlind', Integer(3)), # int
Column('bigBlind', Integer(3)), # int
Column('smallBet', Integer(3), nullable=False), # int NOT NULL
Column('bigBet', Integer(3), nullable=False), # int NOT NULL
mysql_charset='utf8',
mysql_engine='InnoDB',
)
hands_table = Table('Hands', metadata,
Column('id', BigIntColumn, primary_key=True),
Column('tableName', String(30), nullable=False),
Column('siteHandNo', BigIntColumn, nullable=False),
Column('gametypeId', SmallInteger, ForeignKey('Gametypes.id'), nullable=False),
Column('startTime', DateTime, nullable=False),
Column('importTime', DateTime, nullable=False),
Column('seats', SmallInteger, nullable=False),
Column('maxSeats', SmallInteger, nullable=False),
Column('boardcard1', CardColumn),
Column('boardcard2', CardColumn),
Column('boardcard3', CardColumn),
Column('boardcard4', CardColumn),
Column('boardcard5', CardColumn),
Column('texture', SmallInteger),
Column('playersVpi', SmallInteger, nullable=False),
Column('playersAtStreet1', SmallInteger, nullable=False, default=0),
Column('playersAtStreet2', SmallInteger, nullable=False, default=0),
Column('playersAtStreet3', SmallInteger, nullable=False, default=0),
Column('playersAtStreet4', SmallInteger, nullable=False, default=0),
Column('playersAtShowdown',SmallInteger, nullable=False),
Column('street0Raises', SmallInteger, nullable=False),
Column('street1Raises', SmallInteger, nullable=False),
Column('street2Raises', SmallInteger, nullable=False),
Column('street3Raises', SmallInteger, nullable=False),
Column('street4Raises', SmallInteger, nullable=False),
Column('street1Pot', MoneyColumn),
Column('street2Pot', MoneyColumn),
Column('street3Pot', MoneyColumn),
Column('street4Pot', MoneyColumn),
Column('showdownPot', MoneyColumn),
Column('comment', Text),
Column('commentTs', DateTime),
mysql_charset='utf8',
mysql_engine='InnoDB',
)
Index('siteHandNo', hands_table.c.siteHandNo, hands_table.c.gametypeId, unique=True)
hands_actions_table = Table('HandsActions', metadata,
Column('id', BigIntColumn, primary_key=True, nullable=False),
Column('handId', BigIntColumn, ForeignKey("Hands.id"), nullable=False),
Column('actions', PickleType, nullable=False),
mysql_charset='utf8',
mysql_engine='InnoDB',
)
hands_players_table = Table('HandsPlayers', metadata,
Column('id', BigIntColumn, primary_key=True),
Column('handId', BigIntColumn, ForeignKey("Hands.id"), nullable=False),
Column('playerId', Integer, ForeignKey("Players.id"), nullable=False),
Column('startCash', MoneyColumn),
Column('position', CHAR(1)), #CHAR(1)
Column('seatNo', SmallInteger, nullable=False), #SMALLINT NOT NULL
Column('card1', CardColumn), #smallint NOT NULL,
Column('card2', CardColumn), #smallint NOT NULL
Column('card3', CardColumn), #smallint
Column('card4', CardColumn), #smallint
Column('card5', CardColumn), #smallint
Column('card6', CardColumn), #smallint
Column('card7', CardColumn), #smallint
Column('startCards', SmallInteger), #smallint
Column('m_factor', Integer), # null for ring games
Column('ante', MoneyColumn), #INT
Column('winnings', MoneyColumn, nullable=False, default=0), #int NOT NULL
Column('rake', MoneyColumn, nullable=False, default=0), #int NOT NULL
Column('totalProfit', MoneyColumn), #INT
Column('comment', Text), #text
Column('commentTs', DateTime), #DATETIME
Column('tourneysPlayersId', BigIntColumn, ForeignKey("TourneysPlayers.id"),), #BIGINT UNSIGNED
Column('tourneyTypeId', Integer, ForeignKey("TourneyTypes.id"),), #SMALLINT UNSIGNED
Column('wonWhenSeenStreet1',Float), #FLOAT
Column('wonWhenSeenStreet2',Float), #FLOAT
Column('wonWhenSeenStreet3',Float), #FLOAT
Column('wonWhenSeenStreet4',Float), #FLOAT
Column('wonAtSD', Float), #FLOAT
Column('street0VPI', Boolean), #BOOLEAN
Column('street0Aggr', Boolean), #BOOLEAN
Column('street0_3BChance', Boolean), #BOOLEAN
Column('street0_3BDone', Boolean), #BOOLEAN
Column('street0_4BChance', Boolean), #BOOLEAN
Column('street0_4BDone', Boolean), #BOOLEAN
Column('other3BStreet0', Boolean), #BOOLEAN
Column('other4BStreet0', Boolean), #BOOLEAN
Column('street1Seen', Boolean), #BOOLEAN
Column('street2Seen', Boolean), #BOOLEAN
Column('street3Seen', Boolean), #BOOLEAN
Column('street4Seen', Boolean), #BOOLEAN
Column('sawShowdown', Boolean), #BOOLEAN
Column('street1Aggr', Boolean), #BOOLEAN
Column('street2Aggr', Boolean), #BOOLEAN
Column('street3Aggr', Boolean), #BOOLEAN
Column('street4Aggr', Boolean), #BOOLEAN
Column('otherRaisedStreet0',Boolean), #BOOLEAN
Column('otherRaisedStreet1',Boolean), #BOOLEAN
Column('otherRaisedStreet2',Boolean), #BOOLEAN
Column('otherRaisedStreet3',Boolean), #BOOLEAN
Column('otherRaisedStreet4',Boolean), #BOOLEAN
Column('foldToOtherRaisedStreet0', Boolean), #BOOLEAN
Column('foldToOtherRaisedStreet1', Boolean), #BOOLEAN
Column('foldToOtherRaisedStreet2', Boolean), #BOOLEAN
Column('foldToOtherRaisedStreet3', Boolean), #BOOLEAN
Column('foldToOtherRaisedStreet4', Boolean), #BOOLEAN
Column('stealAttemptChance', Boolean), #BOOLEAN
Column('stealAttempted', Boolean), #BOOLEAN
Column('foldBbToStealChance', Boolean), #BOOLEAN
Column('foldedBbToSteal', Boolean), #BOOLEAN
Column('foldSbToStealChance', Boolean), #BOOLEAN
Column('foldedSbToSteal', Boolean), #BOOLEAN
Column('street1CBChance', Boolean), #BOOLEAN
Column('street1CBDone', Boolean), #BOOLEAN
Column('street2CBChance', Boolean), #BOOLEAN
Column('street2CBDone', Boolean), #BOOLEAN
Column('street3CBChance', Boolean), #BOOLEAN
Column('street3CBDone', Boolean), #BOOLEAN
Column('street4CBChance', Boolean), #BOOLEAN
Column('street4CBDone', Boolean), #BOOLEAN
Column('foldToStreet1CBChance', Boolean), #BOOLEAN
Column('foldToStreet1CBDone', Boolean), #BOOLEAN
Column('foldToStreet2CBChance', Boolean), #BOOLEAN
Column('foldToStreet2CBDone', Boolean), #BOOLEAN
Column('foldToStreet3CBChance', Boolean), #BOOLEAN
Column('foldToStreet3CBDone', Boolean), #BOOLEAN
Column('foldToStreet4CBChance', Boolean), #BOOLEAN
Column('foldToStreet4CBDone', Boolean), #BOOLEAN
Column('street1CheckCallRaiseChance',Boolean), #BOOLEAN
Column('street1CheckCallRaiseDone', Boolean), #BOOLEAN
Column('street2CheckCallRaiseChance',Boolean), #BOOLEAN
Column('street2CheckCallRaiseDone', Boolean), #BOOLEAN
Column('street3CheckCallRaiseChance',Boolean), #BOOLEAN
Column('street3CheckCallRaiseDone', Boolean), #BOOLEAN
Column('street4CheckCallRaiseChance',Boolean), #BOOLEAN
Column('street4CheckCallRaiseDone', Boolean), #BOOLEAN
Column('street0Calls', SmallInteger), #TINYINT
Column('street1Calls', SmallInteger), #TINYINT
Column('street2Calls', SmallInteger), #TINYINT
Column('street3Calls', SmallInteger), #TINYINT
Column('street4Calls', SmallInteger), #TINYINT
Column('street0Bets', SmallInteger), #TINYINT
Column('street1Bets', SmallInteger), #TINYINT
Column('street2Bets', SmallInteger), #TINYINT
Column('street3Bets', SmallInteger), #TINYINT
Column('street4Bets', SmallInteger), #TINYINT
Column('street0Raises', SmallInteger), #TINYINT
Column('street1Raises', SmallInteger), #TINYINT
Column('street2Raises', SmallInteger), #TINYINT
Column('street3Raises', SmallInteger), #TINYINT
Column('street4Raises', SmallInteger), #TINYINT
Column('actionString', String(15)), #VARCHAR(15)
mysql_charset='utf8',
mysql_engine='InnoDB',
)
hud_cache_table = Table('HudCache', metadata,
Column('id', BigIntColumn, primary_key=True),
Column('gametypeId', SmallInteger, ForeignKey("Gametypes.id"), nullable=False), # SMALLINT
Column('playerId', Integer, ForeignKey("Players.id"), nullable=False), # SMALLINT
Column('activeSeats', SmallInteger, nullable=False), # SMALLINT NOT NULL
Column('position', CHAR(1)), # CHAR(1)
Column('tourneyTypeId', Integer, ForeignKey("TourneyTypes.id") ), # SMALLINT
Column('styleKey', CHAR(7), nullable=False), # CHAR(7) NOT NULL
Column('m_factor', Integer),
Column('HDs', Integer, nullable=False), # INT NOT NULL
Column('wonWhenSeenStreet1', Float), # FLOAT
Column('wonWhenSeenStreet2', Float), # FLOAT
Column('wonWhenSeenStreet3', Float), # FLOAT
Column('wonWhenSeenStreet4', Float), # FLOAT
Column('wonAtSD', Float), # FLOAT
Column('street0VPI', Integer), # INT
Column('street0Aggr', Integer), # INT
Column('street0_3BChance', Integer), # INT
Column('street0_3BDone', Integer), # INT
Column('street0_4BChance', Integer), # INT
Column('street0_4BDone', Integer), # INT
Column('other3BStreet0', Integer), # INT
Column('other4BStreet0', Integer), # INT
Column('street1Seen', Integer), # INT
Column('street2Seen', Integer), # INT
Column('street3Seen', Integer), # INT
Column('street4Seen', Integer), # INT
Column('sawShowdown', Integer), # INT
Column('street1Aggr', Integer), # INT
Column('street2Aggr', Integer), # INT
Column('street3Aggr', Integer), # INT
Column('street4Aggr', Integer), # INT
Column('otherRaisedStreet0', Integer), # INT
Column('otherRaisedStreet1', Integer), # INT
Column('otherRaisedStreet2', Integer), # INT
Column('otherRaisedStreet3', Integer), # INT
Column('otherRaisedStreet4', Integer), # INT
Column('foldToOtherRaisedStreet0', Integer), # INT
Column('foldToOtherRaisedStreet1', Integer), # INT
Column('foldToOtherRaisedStreet2', Integer), # INT
Column('foldToOtherRaisedStreet3', Integer), # INT
Column('foldToOtherRaisedStreet4', Integer), # INT
Column('stealAttemptChance', Integer), # INT
Column('stealAttempted', Integer), # INT
Column('foldBbToStealChance', Integer), # INT
Column('foldedBbToSteal', Integer), # INT
Column('foldSbToStealChance', Integer), # INT
Column('foldedSbToSteal', Integer), # INT
Column('street1CBChance', Integer), # INT
Column('street1CBDone', Integer), # INT
Column('street2CBChance', Integer), # INT
Column('street2CBDone', Integer), # INT
Column('street3CBChance', Integer), # INT
Column('street3CBDone', Integer), # INT
Column('street4CBChance', Integer), # INT
Column('street4CBDone', Integer), # INT
Column('foldToStreet1CBChance', Integer), # INT
Column('foldToStreet1CBDone', Integer), # INT
Column('foldToStreet2CBChance', Integer), # INT
Column('foldToStreet2CBDone', Integer), # INT
Column('foldToStreet3CBChance', Integer), # INT
Column('foldToStreet3CBDone', Integer), # INT
Column('foldToStreet4CBChance', Integer), # INT
Column('foldToStreet4CBDone', Integer), # INT
Column('totalProfit', Integer), # INT
Column('street1CheckCallRaiseChance', Integer), # INT
Column('street1CheckCallRaiseDone', Integer), # INT
Column('street2CheckCallRaiseChance', Integer), # INT
Column('street2CheckCallRaiseDone', Integer), # INT
Column('street3CheckCallRaiseChance', Integer), # INT
Column('street3CheckCallRaiseDone', Integer), # INT
Column('street4CheckCallRaiseChance', Integer), # INT
Column('street4CheckCallRaiseDone', Integer), # INT
Column('street0Calls', Integer), # INT
Column('street1Calls', Integer), # INT
Column('street2Calls', Integer), # INT
Column('street3Calls', Integer), # INT
Column('street4Calls', Integer), # INT
Column('street0Bets', Integer), # INT
Column('street1Bets', Integer), # INT
Column('street2Bets', Integer), # INT
Column('street3Bets', Integer), # INT
Column('street4Bets', Integer), # INT
Column('street0Raises', Integer), # INT
Column('street1Raises', Integer), # INT
Column('street2Raises', Integer), # INT
Column('street3Raises', Integer), # INT
Column('street4Raises', Integer), # INT
mysql_charset='utf8',
mysql_engine='InnoDB',
)
players_table = Table('Players', metadata,
Column('id', Integer, primary_key=True),
Column('name', Unicode(32), nullable=False), # VARCHAR(32) CHARACTER SET utf8 NOT NULL
Column('siteId', SmallInteger, ForeignKey("Sites.id"), nullable=False), # SMALLINT
Column('comment', Text), # text
Column('commentTs', DateTime), # DATETIME
mysql_charset='utf8',
mysql_engine='InnoDB',
)
Index('name', players_table.c.name, players_table.c.siteId, unique=True)
settings_table = Table('Settings', metadata,
Column('version', SmallInteger, nullable=False),
mysql_charset='utf8',
mysql_engine='InnoDB',
)
sites_table = Table('Sites', metadata,
Column('id', SmallInteger, primary_key=True),
Column('name', String(32), nullable=False), # varchar(32) NOT NULL
Column('code', String(2), nullable=False), # char(2) NOT NULL
mysql_charset='utf8',
mysql_engine='InnoDB',
)
tourneys_table = Table('Tourneys', metadata,
Column('id', Integer, primary_key=True),
Column('tourneyTypeId', Integer, ForeignKey("TourneyTypes.id"), nullable=False, default=1),
Column('siteTourneyNo', BigIntColumn, nullable=False), # BIGINT NOT NULL
Column('entries', Integer), # INT NOT NULL
Column('prizepool', Integer), # INT NOT NULL
Column('tourStartTime', DateTime), # DATETIME NOT NULL
Column('tourEndTime', DateTime), # DATETIME
Column('tourneyName', String(40)), # varchar(40)
# Mask use : 1=Positionnal Winnings|2=Match1|4=Match2|...|pow(2,n)=Matchn
Column('matrixIdProcessed',SmallInteger, default=0), # TINYINT UNSIGNED DEFAULT 0
Column('totalRebuyCount', Integer, default=0), # INT DEFAULT 0
Column('totalAddOnCount', Integer, default=0), # INT DEFAULT 0
Column('comment', Text), # TEXT
Column('commentTs', DateTime), # DATETIME
mysql_charset='utf8',
mysql_engine='InnoDB',
)
Index('siteTourneyNo', tourneys_table.c.siteTourneyNo, tourneys_table.c.tourneyTypeId, unique=True)
tourney_types_table = Table('TourneyTypes', metadata,
Column('id', Integer, primary_key=True),
Column('siteId', SmallInteger, ForeignKey("Sites.id"), nullable=False),
Column('currency', String(4), nullable=False), # varchar(4) NOT NULL
Column('buyin', Integer, nullable=False), # INT NOT NULL
Column('fee', Integer, nullable=False), # INT NOT NULL
Column('buyInChips', Integer, nullable=False), # INT NOT NULL
Column('maxSeats', Boolean, nullable=False, default=-1), # INT NOT NULL DEFAULT -1
Column('rebuy', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False
Column('rebuyCost', Integer), # INT
Column('rebuyChips', Integer), # INT
Column('addOn', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False
Column('addOnCost', Integer), # INT
Column('addOnChips', Integer), # INT
Column('knockout', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False
Column('koBounty', Integer), # INT
Column('speed', String(10)), # varchar(10)
Column('shootout', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False
Column('matrix', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False
Column('sng', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False
Column('satellite', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False
Column('doubleOrNothing', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False
Column('guarantee', Integer, nullable=False, default=0), # INT NOT NULL DEFAULT 0
mysql_charset='utf8',
mysql_engine='InnoDB',
)
Index('tourneyTypes_all',
tourney_types_table.c.siteId, tourney_types_table.c.buyin, tourney_types_table.c.fee,
tourney_types_table.c.maxSeats, tourney_types_table.c.knockout, tourney_types_table.c.rebuy,
tourney_types_table.c.addOn, tourney_types_table.c.speed,
tourney_types_table.c.shootout, tourney_types_table.c.matrix, tourney_types_table.c.sng)
tourneys_players_table = Table('TourneysPlayers', metadata,
Column('id', BigIntColumn, primary_key=True),
Column('tourneyId', Integer, ForeignKey("Tourneys.id"), nullable=False),
Column('playerId', Integer, ForeignKey("Players.id"), nullable=False),
Column('rank', Integer), # INT NOT NULL
Column('winnings', Integer), # INT NOT NULL
Column('winningsCurrency', Text), # TEXT
Column('rebuyCount', Integer, default=0), # INT DEFAULT 0
Column('addOnCount', Integer, default=0), # INT DEFAULT 0
Column('koCount', Integer, default=0), # INT DEFAULT 0
Column('comment', Text), # TEXT
Column('commentTs', DateTime), # DATETIME
mysql_charset='utf8',
mysql_engine='InnoDB',
)
Index('tourneyId', tourneys_players_table.c.tourneyId, tourneys_players_table.c.playerId, unique=True)
def sss():
"Debug function. Returns (config, sql, db)"
import Configuration, SQL, Database, os
class Dummy(object):
pass
self = Dummy()
self.config = Configuration.Config()
self.settings = {}
if (os.sep=="/"):
self.settings['os']="linuxmac"
else:
self.settings['os']="windows"
self.settings.update(self.config.get_db_parameters())
self.settings.update(self.config.get_import_parameters())
self.settings.update(self.config.get_default_paths())
self.sql = SQL.Sql( db_server = self.settings['db-server'])
self.db = Database.Database(self.config, sql = self.sql)
return self.config, self.sql, self.db

4
pyfpdb/BetfairToFpdb.py

@ -74,7 +74,7 @@ class Betfair(HandHistoryConverter):
if not m:
tmp = handText[0:100]
log.error(_("Unable to recognise gametype from: '%s'") % tmp)
log.error(_("determineGameType: Raising FpdbParseError"))
log.error("determineGameType: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
mg = m.groupdict()
@ -196,7 +196,7 @@ class Betfair(HandHistoryConverter):
elif action.group('ATYPE') == 'checks':
hand.addCheck( street, action.group('PNAME'))
else:
sys.stderr.write(_("DEBUG: ") + _("Unimplemented readAction: '%s' '%s'") % (action.group('PNAME'),action.group('ATYPE')))
sys.stderr.write(_("DEBUG: ") + _("Unimplemented readAction: '%s' '%s'") % (action.group('PNAME'), action.group('ATYPE')))
def readShowdownActions(self, hand):

4
pyfpdb/CarbonToFpdb.py

@ -128,7 +128,7 @@ or None if we fail to get the info """
except AttributeError:
tmp = handText[0:100]
log.error(_("Unable to recognise gametype from: '%s'") % tmp)
log.error(_("determineGameType: Raising FpdbParseError"))
log.error("determineGameType: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
self.info = {}
@ -264,7 +264,7 @@ or None if we fail to get the info """
elif action.group('ATYPE') == 'ALL_IN':
hand.addAllIn(street, player, action.group('BET'))
else:
logging.debug(_("Unimplemented readAction: '%s' '%s'") % (action.group('PSEAT'),action.group('ATYPE')))
logging.debug(_("Unimplemented readAction: '%s' '%s'") % (action.group('PSEAT'), action.group('ATYPE')))
def readShowdownActions(self, hand):
for shows in self.re_ShowdownAction.finditer(hand.handText):

30
pyfpdb/Card.py

@ -101,36 +101,6 @@ def twoStartCardString(card):
#print "twoStartCardString(", card ,") = " + ret
return ret
def fourStartCards(value1, suit1, value2, suit2, value3, suit3, value4, suit4):
""" Function to convert 4 value,suit pairs into a Omaha style starting hand,
haven't decided how to encode this yet """
# This doesn't actually do anything yet - CG
# What combinations do we need to store? just cards: AA23? some suits as well e.g. when
# double suited ATcKTd? Lots more possible combos than holdem :-( 270K vs 1326? not sure
# Probably need to use this field as a key into some other table - sc
#AAKKds
#AAKKs
#AAKKr
# Is probably what we are looking for
# mct:
# my maths says there are 4 classes of suitedness
# SSSS SSSx SSxy SSHH
# encode them as follows:
# SSSS (K, J, 6, 3)
# - 13C4 = 715 possibilities
# SSSx (K, J, 6),(3)
# - 13C3 * 13 = 3718 possibilities
# SSxy (K, J),(6),(3)
# - 13C2 * 13*13 = 13182 possibilities
# SSHH (K, J),(6, 3)
# - 13C2 * 13C2 = 6084 possibilities
# Needless to say they won't fit on a 13x13 grid.
# The actual number of hands in each class is far greater
return(0)
def cardFromValueSuit(value, suit):
""" 0=none, 1-13=2-Ah 14-26=2-Ad 27-39=2-Ac 40-52=2-As """
if suit == 'h': return(value-1)

18
pyfpdb/Charset.py

@ -26,9 +26,7 @@ import Configuration
encoder_to_utf = codecs.lookup('utf-8')
encoder_to_sys = codecs.lookup(Configuration.LOCALE_ENCODING)
coder_hex = codecs.lookup('hex_codec')
hex_coding = False #FIXME: Should only be on if db is not UTF8 - test in Database.py?
# I'm saving a few cycles with this one
not_needed1, not_needed2, not_needed3 = False, False, False
if Configuration.LOCALE_ENCODING == 'UTF8':
@ -77,19 +75,3 @@ def to_gui(s):
except UnicodeEncodeError:
sys.stderr.write(_('Could not encode: "%s"\n') % s)
raise
def to_hex(s):
try:
out = coder_hex.encode(s)[0]
return out
except UnicodeDecodeError:
sys.stderr.write(_('Could not convert: "%s"\n') % s)
return s
def from_hex(s):
try:
out = coder_hex.decode(s)[0]
return out
except UnicodeDecodeError:
sys.stderr.write(_('Could not convert: "%s"\n') % s)
return s

53
pyfpdb/Configuration.py

@ -123,7 +123,7 @@ def get_config(file_name, fallback = True):
# OK, fall back to the .example file, should be in the start dir
elif os.path.exists(file_name + ".example"):
try:
print ""
#print ""
example_path = file_name + ".example"
check_dir(default_dir)
if not config_found and fallback:
@ -173,7 +173,7 @@ def get_logger(file_name, config = "config", fallback = False, log_dir=None, log
log = logging.getLogger()
# but it looks like default is no output :-( maybe because all the calls name a module?
log.debug(_("Default logger initialised for %s") % file)
print(_("Default logger initialised for %s") % file)
#print(_("Default logger initialised for %s") % file)
return log
def check_dir(path, create = True):
@ -207,9 +207,8 @@ DATABASE_TYPES = (
DATABASE_TYPE_MYSQL,
)
#LOCALE_ENCODING = locale.getdefaultlocale()[1]
LOCALE_ENCODING = locale.getpreferredencoding()
if LOCALE_ENCODING == "US-ASCII":
if LOCALE_ENCODING in ("US-ASCII", "", None):
print _("Default encoding set to US-ASCII, defaulting to CP1252 instead -- If you're not on a Mac, please report this problem.")
LOCALE_ENCODING = "cp1252"
@ -314,8 +313,6 @@ class Site:
self.layout = {}
self.emails = {}
print _("Loading site"), self.site_name
for layout_node in node.getElementsByTagName('layout'):
lo = Layout(layout_node)
self.layout[lo.max] = lo
@ -488,16 +485,16 @@ class Popup:
class Import:
def __init__(self, node):
self.node = node
self.interval = node.getAttribute("interval")
self.callFpdbHud = node.getAttribute("callFpdbHud")
self.ResultsDirectory = node.getAttribute("ResultsDirectory")
self.hhBulkPath = node.getAttribute("hhBulkPath")
self.saveActions = string_to_bool(node.getAttribute("saveActions"), default=False)
self.cacheSessions = string_to_bool(node.getAttribute("cacheSessions"), default=False)
self.sessionTimeout = string_to_bool(node.getAttribute("sessionTimeout"), default=30)
self.fastStoreHudCache = string_to_bool(node.getAttribute("fastStoreHudCache"), default=False)
self.saveStarsHH = string_to_bool(node.getAttribute("saveStarsHH"), default=False)
self.node = node
self.interval = node.getAttribute("interval")
self.sessionTimeout = node.getAttribute("sessionTimeout")
self.ResultsDirectory = node.getAttribute("ResultsDirectory")
self.hhBulkPath = node.getAttribute("hhBulkPath")
self.saveActions = string_to_bool(node.getAttribute("saveActions") , default=False)
self.cacheSessions = string_to_bool(node.getAttribute("cacheSessions") , default=False)
self.callFpdbHud = string_to_bool(node.getAttribute("callFpdbHud") , default=False)
self.fastStoreHudCache = string_to_bool(node.getAttribute("fastStoreHudCache"), default=False)
self.saveStarsHH = string_to_bool(node.getAttribute("saveStarsHH") , default=False)
def __str__(self):
return " interval = %s\n callFpdbHud = %s\n saveActions = %s\n fastStoreHudCache = %s\nResultsDirectory = %s" \
@ -631,20 +628,20 @@ class RawHands:
if node==None:
self.save="error"
self.compression="none"
print _("missing config section raw_hands")
#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\"")
print (_("Invalid config value for %s, defaulting to %s") % (raw_hands.save, "\"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\"")
print (_("Invalid config value for %s, defaulting to %s") % (raw_hands.compression, "\"none\""))
self.compression="none"
#end def __init__
@ -657,20 +654,20 @@ class RawTourneys:
if node==None:
self.save="error"
self.compression="none"
print _("missing config section raw_tourneys")
#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\"")
print (_("Invalid config value for %s, defaulting to %s") % (raw_tourneys.save, "\"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\"")
print (_("Invalid config value for %s, defaulting to %s") % (raw_tourneys.compression, "\"none\""))
self.compression="none"
#end def __init__
@ -688,8 +685,8 @@ class Config:
if file is not None: # config file path passed in
file = os.path.expanduser(file)
if not os.path.exists(file):
print _("Configuration file %s not found. Using defaults.") % (file)
sys.stderr.write(_("Configuration file %s not found. Using defaults.") % (file))
print _("Configuration file %s not found. Using defaults.") % (file)
sys.stderr.write(_("Configuration file %s not found. Using defaults.") % (file))
file = None
self.example_copy,example_file = True,None
@ -720,13 +717,13 @@ class Config:
while added > 0 and n < 2:
n = n + 1
log.info(_("Reading configuration file %s") % file)
print (("\n"+_("Reading configuration file %s")+"\n") % file)
#print (("\n"+_("Reading configuration file %s")+"\n") % file)
try:
doc = xml.dom.minidom.parse(file)
self.doc = doc
self.file_error = None
except:
log.error(_("Error parsing %s. See error log file.") % (file))
log.error((_("Error parsing %s.") % (file)) + _("See error log file."))
traceback.print_exc(file=sys.stderr)
self.file_error = sys.exc_info()[1]
# we could add a parameter to decide whether to return or read a line and exit?
@ -829,7 +826,7 @@ class Config:
for raw_tourneys_node in doc.getElementsByTagName('raw_tourneys'):
self.raw_tourneys = RawTourneys(raw_tourneys_node)
print ""
#print ""
#end def __init__
def add_missing_elements(self, doc, example_file):
@ -842,7 +839,7 @@ class Config:
try:
example_doc = xml.dom.minidom.parse(example_file)
except:
log.error(_("Error parsing example configuration file %s. See error log file.") % (example_file))
log.error((_("Error parsing example configuration file %s.") % (example_file)) + _("See error log file."))
return nodes_added
for cnode in doc.getElementsByTagName("FreePokerToolsConfig"):

922
pyfpdb/Database.py

File diff suppressed because it is too large Load Diff

44
pyfpdb/DerivedStats.py

@ -43,6 +43,7 @@ class DerivedStats():
init['street4Aggr'] = False
init['wonWhenSeenStreet1'] = 0.0
init['sawShowdown'] = False
init['showed'] = False
init['wonAtSD'] = 0.0
init['startCards'] = 0
init['position'] = 2
@ -119,16 +120,17 @@ class DerivedStats():
return self.handsactions
def assembleHands(self, hand):
self.hands['tableName'] = hand.tablename
self.hands['siteHandNo'] = hand.handid
self.hands['gametypeId'] = None # Leave None, handled later after checking db
self.hands['sessionId'] = None # Leave None, added later if caching sessions
self.hands['startTime'] = hand.startTime # format this!
self.hands['importTime'] = None
self.hands['seats'] = self.countPlayers(hand)
self.hands['maxSeats'] = hand.maxseats
self.hands['texture'] = None # No calculation done for this yet.
self.hands['tourneyId'] = hand.tourneyId
self.hands['tableName'] = hand.tablename
self.hands['siteHandNo'] = hand.handid
self.hands['gametypeId'] = None # Leave None, handled later after checking db
self.hands['sessionId'] = None # Leave None, added later if caching sessions
self.hands['gameSessionId'] = None # Leave None, added later if caching sessions
self.hands['startTime'] = hand.startTime # format this!
self.hands['importTime'] = None
self.hands['seats'] = self.countPlayers(hand)
self.hands['maxSeats'] = hand.maxseats
self.hands['texture'] = None # No calculation done for this yet.
self.hands['tourneyId'] = hand.tourneyId
# This (i think...) is correct for both stud and flop games, as hand.board['street'] disappears, and
# those values remain default in stud.
@ -142,6 +144,20 @@ class DerivedStats():
self.hands['boardcard3'] = cards[2]
self.hands['boardcard4'] = cards[3]
self.hands['boardcard5'] = cards[4]
self.hands['boards'] = []
self.hands['runIt'] = False
for i in range(hand.runItTimes):
self.hands['runIt'] = True
boardcards = []
for street in hand.communityStreets:
boardId = i+1
street_i = street + str(boardId)
if street_i in hand.board:
boardcards += hand.board[street_i]
boardcards = [u'0x', u'0x', u'0x', u'0x', u'0x'] + boardcards
cards = [Card.encodeCard(c) for c in boardcards[-5:]]
self.hands['boards'] += [[boardId] + cards]
#print "DEBUG: self.getStreetTotals = (%s, %s, %s, %s, %s)" % hand.getStreetTotals()
totals = hand.getStreetTotals()
@ -172,6 +188,8 @@ class DerivedStats():
self.handsplayers[player[1]]['tourneysPlayersIds'] = hand.tourneysPlayersIds[player[1]]
else:
self.handsplayers[player[1]]['tourneysPlayersIds'] = None
if player[1] in hand.shown:
self.handsplayers[player[1]]['showed'] = True
#### seen now processed in playersAtStreetX()
# XXX: enumerate(list, start=x) is python 2.6 syntax; 'start'
@ -213,10 +231,10 @@ class DerivedStats():
for player in hand.players:
hcs = hand.join_holecards(player[1], asList=True)
hcs = hcs + [u'0x', u'0x', u'0x', u'0x', u'0x']
#for i, card in enumerate(hcs[:7], 1): #Python 2.6 syntax
hcs = hcs + [u'0x']*18
#for i, card in enumerate(hcs[:20, 1): #Python 2.6 syntax
# self.handsplayers[player[1]]['card%s' % i] = Card.encodeCard(card)
for i, card in enumerate(hcs[:7]):
for i, card in enumerate(hcs[:20]):
self.handsplayers[player[1]]['card%s' % (i+1)] = Card.encodeCard(card)
self.handsplayers[player[1]]['startCards'] = Card.calcStartCards(hand, player[1])

8
pyfpdb/EverestToFpdb.py

@ -99,12 +99,12 @@ class Everest(HandHistoryConverter):
except AttributeError:
tmp = handText[0:100]
log.error(_("Unable to recognise gametype from: '%s'") % tmp)
log.error(_("determineGameType: Raising FpdbParseError"))
log.error("determineGameType: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
if not m2:
tmp = handText[0:100]
log.error(_("determineGameType: Raising FpdbParseError"))
log.error("determineGameType: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise handinfo from: '%s'") % tmp)
self.info = {}
@ -231,8 +231,8 @@ class Everest(HandHistoryConverter):
elif action.group('ATYPE') in ('FOLD', 'SIT_OUT'):
hand.addFold(street, player)
else:
print (_("Unimplemented readAction: '%s' '%s'") % (action.group('PSEAT'),action.group('ATYPE')))
logging.debug(_("Unimplemented readAction: '%s' '%s'") % (action.group('PSEAT'),action.group('ATYPE')))
print (_("Unimplemented readAction: '%s' '%s'") % (action.group('PSEAT'), action.group('ATYPE')))
logging.debug(_("Unimplemented readAction: '%s' '%s'") % (action.group('PSEAT'), action.group('ATYPE')))
def readShowdownActions(self, hand):
for shows in self.re_ShowdownAction.finditer(hand.handText):

67
pyfpdb/EverleafToFpdb.py

@ -33,15 +33,34 @@ class Everleaf(HandHistoryConverter):
filetype = "text"
codepage = "cp1252"
siteId = 3 # Needs to match id entry in Sites database
substitutions = {
'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
'LS' : u"\$|\u20AC|\xe2\x82\xac|\x80|", # legal currency symbols - Euro(cp1252, utf-8) #TODO change \x80 to \x20\x80, update all regexes accordingly
'TAB' : u"-\u2013'\s\da-zA-Z#_", # legal characters for tablename
'NUM' : u".,\d", # legal characters in number format
}
# Static regexes
re_SplitHands = re.compile(r"\n\n\n+")
re_TailSplitHands = re.compile(r"(\n\n\n+)")
re_GameInfo = re.compile(ur"^(Blinds )?(?P<CURRENCY>[$€]?)(?P<SB>[.0-9]+)/[$€]?(?P<BB>[.0-9]+) (?P<LIMIT>NL|PL|) ?(?P<GAME>(Hold\'em|Omaha|7 Card Stud))", re.MULTILINE)
#re.compile(ur"^(Blinds )?(?P<CURRENCY>\$| €|)(?P<SB>[.0-9]+)/(?:\$| €)?(?P<BB>[.0-9]+) (?P<LIMIT>NL|PL|) ?(?P<GAME>(Hold\'em|Omaha|7 Card Stud))", re.MULTILINE)
re_HandInfo = re.compile(ur".*#(?P<HID>[0-9]+)\n.*\n(Blinds )?(?P<CURRENCY>[$€])?(?P<SB>[.0-9]+)/(?:[$€])?(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<DATETIME>\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P<TABLE>.+$)", re.MULTILINE)
re_GameInfo = re.compile(ur"^(Blinds )? ?(?P<CURRENCY>[%(LS)s]?)(?P<SB>[.0-9]+) ?/ ? ?[%(LS)s]?(?P<BB>[.0-9]+) (?P<LIMIT>NL|PL|) ?(?P<GAME>(Hold\'em|Omaha|7 Card Stud))" % substitutions, re.MULTILINE)
#re_HandInfo = re.compile(ur".*#(?P<HID>[0-9]+)\n.*\n(Blinds )?(?P<CURRENCY>[$€])?(?P<SB>[.0-9]+)/(?:[$€])?(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<DATETIME>\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P<TABLE>.+$)", re.MULTILINE)
re_HandInfo = re.compile(ur".*\n(.*#|.* partie )(?P<HID>[0-9]+).*(\n|\n\n)(Blinds )? ?(?P<CURRENCY>[%(LS)s])?(?P<SB>[.0-9]+) ?/ ?(?:[%(LS)s])?(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<DATETIME>\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P<TABLE>.+$)" % substitutions, re.MULTILINE)
#
#re_HandInfo = re.compile(ur"(.*#|.*\n.* partie )(?P<HID>[0-9]+).*(\n|\n\n)(Blinds )?(?:\$| €|)(?P<SB>[.0-9]+)/(?:\$| €|)(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<DATETIME>\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P<TABLE>.+$)", re.MULTILINE)
re_Button = re.compile(ur"^Seat (?P<BUTTON>\d+) is the button$", re.MULTILINE)
re_PlayerInfo = re.compile(ur"^Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\s+([$€]? (?P<CASH>[.0-9]+) (USD|EURO|Chips)|new player|All-in) \)$", re.MULTILINE)
re_PlayerInfo = re.compile(ur"""^Seat\s(?P<SEAT>[0-9]+):\s(?P<PNAME>.*)\s+
\(
\s+[%(LS)s]?\s?(?P<CASH>[.0-9]+)
(\s(USD|EURO|EUR|Chips)?(new\splayer|All-in)?)?
\s?\)$
""" % substitutions, re.MULTILINE|re.VERBOSE)
re_Board = re.compile(ur"\[ (?P<CARDS>.+) \]")
re_TourneyInfoFromFilename = re.compile(ur".*TID_(?P<TOURNO>[0-9]+)-(?P<TABLE>[0-9]+)\.txt")
@ -53,16 +72,16 @@ class Everleaf(HandHistoryConverter):
self.compiledPlayers = players
player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")"
logging.debug("player_re: "+ player_re)
self.re_PostSB = re.compile(ur"^%s: posts small blind \[[$€]? (?P<SB>[.0-9]+)\s.*\]$" % player_re, re.MULTILINE)
self.re_PostBB = re.compile(ur"^%s: posts big blind \[[$€]? (?P<BB>[.0-9]+)\s.*\]$" % player_re, re.MULTILINE)
self.re_PostBoth = re.compile(ur"^%s: posts both blinds \[[$€]? (?P<SBBB>[.0-9]+)\s.*\]$" % player_re, re.MULTILINE)
self.re_Antes = re.compile(ur"^%s: posts ante \[[$€]? (?P<ANTE>[.0-9]+)\s.*\]$" % player_re, re.MULTILINE)
self.re_BringIn = re.compile(ur"^%s posts bring-in [$€]? (?P<BRINGIN>[.0-9]+)\." % player_re, re.MULTILINE)
self.re_PostSB = re.compile(ur"^%s: posts small blind \[ ?[%s]? (?P<SB>[.0-9]+)\s.*\]$" % (player_re, self.substitutions["LS"]), re.MULTILINE)
self.re_PostBB = re.compile(ur"^%s: posts big blind \[ ?[%s]? (?P<BB>[.0-9]+)\s.*\]$" % (player_re, self.substitutions["LS"]), re.MULTILINE)
self.re_PostBoth = re.compile(ur"^%s: posts both blinds \[ ?[%s]? (?P<SBBB>[.0-9]+)\s.*\]$" % (player_re, self.substitutions["LS"]), re.MULTILINE)
self.re_Antes = re.compile(ur"^%s: posts ante \[ ?[%s]? (?P<ANTE>[.0-9]+)\s.*\]$" % (player_re, self.substitutions["LS"]), re.MULTILINE)
self.re_BringIn = re.compile(ur"^%s posts bring-in ?[%s]? (?P<BRINGIN>[.0-9]+)\." % (player_re, self.substitutions["LS"]), re.MULTILINE)
self.re_HeroCards = re.compile(ur"^Dealt to %s \[ (?P<CARDS>.*) \]$" % player_re, re.MULTILINE)
# ^%s(?P<ATYPE>: bets| checks| raises| calls| folds)(\s\[(?:\$| €|) (?P<BET>[.,\d]+) (USD|EURO|Chips)\])?
self.re_Action = re.compile(ur"^%s(?P<ATYPE>: bets| checks| raises| calls| folds)(\s\[(?:[$€]?) (?P<BET>[.,\d]+)\s?(USD|EURO|Chips|)\])?" % player_re, re.MULTILINE)
# ^%s(?P<ATYPE>: bets| checks| raises| calls| folds)(\s\[(?:\$| €|) (?P<BET>[.,\d]+) (USD|EURO|EUR|Chips)\])?
self.re_Action = re.compile(ur"^%s(?P<ATYPE>: bets| checks| raises| calls| folds)(\s\[(?: ?[%s]?) (?P<BET>[.,\d]+)\s?(USD|EURO|EUR|Chips|)\])?" % (player_re, self.substitutions["LS"]), re.MULTILINE)
self.re_ShowdownAction = re.compile(ur"^%s shows \[ (?P<CARDS>.*) \]" % player_re, re.MULTILINE)
self.re_CollectPot = re.compile(ur"^%s wins (?:[$€]?)\s?(?P<POT>[.\d]+) (USD|EURO|chips)(.*?\[ (?P<CARDS>.*?) \])?" % player_re, re.MULTILINE)
self.re_CollectPot = re.compile(ur"^%s wins ?(?: ?[%s]?)\s?(?P<POT>[.\d]+) (USD|EURO|EUR|chips)(.*?\[ (?P<CARDS>.*?) \])?" % (player_re, self.substitutions["LS"]), re.MULTILINE)
self.re_SitsOut = re.compile(ur"^%s sits out" % player_re, re.MULTILINE)
def readSupportedGames(self):
@ -91,8 +110,6 @@ class Everleaf(HandHistoryConverter):
'bigBet'
'currency' in ('USD', 'EUR', 'T$', <countrycode>)
or None if we fail to get the info """
#(TODO: which parts are optional/required?)
# Blinds $0.50/$1 PL Omaha - 2008/12/07 - 21:59:48
# Blinds $0.05/$0.10 NL Hold'em - 2009/02/21 - 11:21:57
# $0.25/$0.50 7 Card Stud - 2008/12/05 - 21:43:59
@ -103,12 +120,13 @@ or None if we fail to get the info """
# Blinds 10/20 NL Hold'em - 2009/02/25 - 17:30:32
# Table 2
info = {'type':'ring'}
m = self.re_GameInfo.search(handText)
if not m:
tmp = handText[0:100]
tmp = handText[0:150]
log.error(_("Unable to recognise gametype from: '%s'") % tmp)
log.error(_("determineGameType: Raising FpdbParseError"))
log.error("determineGameType: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
mg = m.groupdict()
@ -164,11 +182,6 @@ or None if we fail to get the info """
# https://www.poker4ever.com/tourney/%TOURNEY_NUMBER%
# Believe Everleaf time is GMT/UTC, no transation necessary
# Stars format (Nov 10 2008): 2008/11/07 12:38:49 CET [2008/11/07 7:38:49 ET]
# or : 2008/11/07 12:38:49 ET
# Not getting it in my HH files yet, so using
# 2008/11/10 3:58:52 ET
#TODO: Need some date functions to convert to different timezones (Date::Manip for perl rocked for this)
hand.startTime = datetime.datetime.strptime(m.group('DATETIME'), "%Y/%m/%d - %H:%M:%S")
return
@ -187,9 +200,6 @@ or None if we fail to get the info """
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.
#m = re.search('(\*\* Dealing down cards \*\*\n)(?P<PREFLOP>.*?\n\*\*)?( Dealing Flop \*\* \[ (?P<FLOP1>\S\S), (?P<FLOP2>\S\S), (?P<FLOP3>\S\S) \])?(?P<FLOP>.*?\*\*)?( Dealing Turn \*\* \[ (?P<TURN1>\S\S) \])?(?P<TURN>.*?\*\*)?( Dealing River \*\* \[ (?P<RIVER1>\S\S) \])?(?P<RIVER>.*)', hand.handText,re.DOTALL)
if hand.gametype['base'] == 'hold':
m = re.search(r"\*\* Dealing down cards \*\*(?P<PREFLOP>.+(?=\*\* Dealing Flop \*\*)|.+)"
r"(\*\* Dealing Flop \*\*(?P<FLOP> \[ \S\S, \S\S, \S\S \].+(?=\*\* Dealing Turn \*\*)|.+))?"
@ -261,10 +271,7 @@ or None if we fail to get the info """
def readStudPlayerCards(self, hand, street):
# lol. see Plymouth.txt
logging.warning(_("Everleaf readStudPlayerCards is only a stub."))
#~ if street in ('THIRD', 'FOURTH', 'FIFTH', 'SIXTH'):
#~ hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = [], open = [])
def readAction(self, hand, street):
@ -285,7 +292,7 @@ or None if we fail to get the info """
elif action.group('ATYPE') == ' complete to':
hand.addComplete( street, action.group('PNAME'), action.group('BET'))
else:
logging.debug(_("Unimplemented readAction: %s %s") % (action.group('PNAME'),action.group('ATYPE')))
logging.debug(_("Unimplemented readAction: '%s' '%s'") % (action.group('PNAME'), action.group('ATYPE')))
def readShowdownActions(self, hand):

17
pyfpdb/FullTiltPokerSummary.py

@ -25,7 +25,6 @@ import datetime
from Exceptions import FpdbParseError
from HandHistoryConverter import *
import PokerStarsToFpdb
from TourneySummary import *
class FullTiltPokerSummary(TourneySummary):
@ -45,10 +44,10 @@ class FullTiltPokerSummary(TourneySummary):
}
substitutions = {
'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
'LS' : "\$|\xe2\x82\xac|", # legal currency symbols - Euro(cp1252, utf-8)
'TAB' : u"-\u2013'\s\da-zA-Z", # legal characters for tablename
'NUM' : u".,\d", # legal characters in number format
'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
'LS' : u"\$|\xe2\x82\xac|\u20ac|", # legal currency symbols - Euro(cp1252, utf-8)
'TAB' : u"-\u2013'\s\da-zA-Z", # legal characters for tablename
'NUM' : u".,\d", # legal characters in number format
}
re_SplitTourneys = re.compile("^Full Tilt Poker Tournament Summary")
@ -90,8 +89,8 @@ class FullTiltPokerSummary(TourneySummary):
m = self.re_TourneyInfo.search(self.summaryText[:2000])
if m == None:
tmp = self.summaryText[0:200]
log.error(_("parseSummary: Unable to recognise Tourney Info: '%s'") % tmp)
log.error(_("parseSummary: Raising FpdbParseError"))
log.error("parseSummary: " + _("Unable to recognise Tourney Info: '%s'") % tmp)
log.error("parseSummary: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise Tourney Info: '%s'") % tmp)
#print "DEBUG: m.groupdict(): %s" % m.groupdict()
@ -116,8 +115,8 @@ class FullTiltPokerSummary(TourneySummary):
m = self.re_Currency.search(self.summaryText)
if m == None:
log.error(_("parseSummary: Unable to locate currency"))
log.error(_("parseSummary: Raising FpdbParseError"))
log.error("parseSummary: " + _("Unable to locate currency"))
log.error("parseSummary: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Unable to locate currency"))
#print "DEBUG: m.groupdict(): %s" % m.groupdict()

128
pyfpdb/FulltiltToFpdb.py

@ -37,7 +37,7 @@ class Fulltilt(HandHistoryConverter):
substitutions = {
'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
'LS' : u"\$|\u20AC|\xe2\x82\xac|", # legal currency symbols - Euro(cp1252, utf-8)
'TAB' : u"-\u2013'\s\da-zA-Z", # legal characters for tablename
'TAB' : u"-\u2013'\s\da-zA-Z#_", # legal characters for tablename
'NUM' : u".,\d", # legal characters in number format
}
@ -46,6 +46,7 @@ class Fulltilt(HandHistoryConverter):
'1.00': ('0.25', '0.50'), '1': ('0.25', '0.50'),
'2.00': ('0.50', '1.00'), '2': ('0.50', '1.00'),
'4.00': ('1.00', '2.00'), '4': ('1.00', '2.00'),
'5.00': ('1.25', '2.50'), '5': ('1.25', '2.50'),
'6.00': ('1.00', '3.00'), '6': ('1.00', '3.00'),
'8.00': ('2.00', '4.00'), '8': ('2.00', '4.00'),
'10.00': ('2.00', '5.00'), '10': ('2.00', '5.00'),
@ -61,7 +62,9 @@ class Fulltilt(HandHistoryConverter):
'400.00': ('100.00', '200.00'), '400': ('100.00', '200.00'),
'500.00': ('125.00', '250.00'), '500': ('125.00', '250.00'),
'800.00': ('200.00', '400.00'), '800': ('200.00', '400.00'),
'1000.00': ('250.00', '500.00'),'1000': ('250.00', '500.00')
'1000.00': ('250.00', '500.00'),'1000': ('250.00', '500.00'),
'2000.00': ('500.00', '750.00'),'2000': ('500.00', '1000.00'),
'3000.00': ('750.00', '1500.00'),'3000': ('750.00', '1500.00'),
}
# Static regexes
@ -145,17 +148,11 @@ class Fulltilt(HandHistoryConverter):
##Total Prize Pool: 1,500 Play Chips
# These regexes are for FTP only
re_Mixed = re.compile(r'\s\-\s(?P<MIXED>HA|HORSE|HOSE)\s\-\s', re.VERBOSE)
re_Mixed = re.compile(r'\s\-\s(?P<MIXED>7\-Game|8\-Game|9\-Game|10\-Game|HA|HEROS|HO|HOE|HORSE|HOSE|OA|OE|SE)\s\-\s', re.VERBOSE)
re_Max = re.compile("(?P<MAX>\d+)( max)?", re.MULTILINE)
# NB: if we ever match "Full Tilt Poker" we should also match "FullTiltPoker", which PT Stud erroneously exports.
re_DateTime = re.compile("""((?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)\s(?P<TZ>\w+)\s-\s(?P<Y>[0-9]{4})\/(?P<M>[0-9]{2})\/(?P<D>[0-9]{2})|(?P<H2>[0-9]+):(?P<MIN2>[0-9]+)\s(?P<TZ2>\w+)\s-\s\w+\,\s(?P<M2>\w+)\s(?P<D2>\d+)\,\s(?P<Y2>[0-9]{4}))(?P<PARTIAL>\s\(partial\))?""", re.MULTILINE)
mixes = { 'HORSE': 'horse', '7-Game': '7game', 'HOSE': 'hose', 'HA': 'ha'}
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'
@ -169,14 +166,15 @@ class Fulltilt(HandHistoryConverter):
self.re_PostDead = re.compile(r"^%(PLAYERS)s posts a dead small blind of [%(LS)s]?(?P<SB>[%(NUM)s]+)" % self.substitutions, re.MULTILINE)
self.re_PostBB = re.compile(r"^%(PLAYERS)s posts (the big blind of )?[%(LS)s]?(?P<BB>[%(NUM)s]+)" % self.substitutions, re.MULTILINE)
self.re_Antes = re.compile(r"^%(PLAYERS)s antes [%(LS)s]?(?P<ANTE>[%(NUM)s]+)" % self.substitutions, re.MULTILINE)
self.re_ReturnsAnte = re.compile(r"^Ante of [%(LS)s]?[%(NUM)s]+ returned to %(PLAYERS)s" % self.substitutions, re.MULTILINE)
self.re_BringIn = re.compile(r"^%(PLAYERS)s brings in for [%(LS)s]?(?P<BRINGIN>[%(NUM)s]+)" % self.substitutions, re.MULTILINE)
self.re_PostBoth = re.compile(r"^%(PLAYERS)s posts small \& big blinds \[[%(LS)s]? (?P<SBBB>[%(NUM)s]+)" % self.substitutions, re.MULTILINE)
self.re_HeroCards = re.compile(r"^Dealt to %s(?: \[(?P<OLDCARDS>.+?)\])?( \[(?P<NEWCARDS>.+?)\])" % player_re, re.MULTILINE)
self.re_Action = re.compile(r"^%(PLAYERS)s(?P<ATYPE> bets| checks| raises to| completes it to| calls| folds)( [%(LS)s]?(?P<BET>[%(NUM)s]+))?" % self.substitutions, re.MULTILINE)
self.re_Action = re.compile(r"^%(PLAYERS)s(?P<ATYPE> bets| checks| raises to| completes it to| calls| folds| discards| stands pat)( [%(LS)s]?(?P<BET>[%(NUM)s]+))?(\son|\scards?)?(\s\[(?P<CARDS>.+?)\])?" % self.substitutions, re.MULTILINE)
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]+): %(PLAYERS)s (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \([%(LS)s]?(?P<POT>[%(NUM)s]+)\)(, mucked| with.*)?" % self.substitutions, re.MULTILINE)
self.re_SitsOut = re.compile(r"^%s sits out" % player_re, re.MULTILINE)
self.re_ShownCards = re.compile(r"^Seat (?P<SEAT>[0-9]+): %s (\(button\) |\(small blind\) |\(big blind\) )?(?P<ACT>showed|mucked) \[(?P<CARDS>.*)\].*" % player_re, re.MULTILINE)
self.re_ShownCards = re.compile(r"^Seat (?P<SEAT>[0-9]+): %s (\(button\) |\(small blind\) |\(big blind\) )?(?P<SHOWED>showed|mucked) \[(?P<CARDS>.*)\](( and won \(.*\) with | and lost with | \- )(?P<STRING>.*))?" % player_re, re.MULTILINE)
def readSupportedGames(self):
return [["ring", "hold", "nl"],
@ -193,9 +191,14 @@ class Fulltilt(HandHistoryConverter):
["tour", "hold", "nl"],
["tour", "hold", "pl"],
["tour", "hold", "fl"],
["tour", "hold", "cn"],
["tour", "stud", "fl"],
]
["tour", "draw", "fl"],
["tour", "draw", "pl"],
["tour", "draw", "nl"],
]
def determineGameType(self, handText):
info = {'type':'ring'}
@ -204,7 +207,7 @@ class Fulltilt(HandHistoryConverter):
if not m:
tmp = handText[0:100]
log.error(_("Unable to recognise gametype from: '%s'") % tmp)
log.error(_("determineGameType: Raising FpdbParseError for file '%s'") % self.in_path)
log.error("determineGameType: " + _("Raising FpdbParseError for file '%s'") % self.in_path)
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
mg = m.groupdict()
@ -224,6 +227,21 @@ class Fulltilt(HandHistoryConverter):
'Badugi' : ('draw','badugi'),
'2-7 Single Draw' : ('draw','27_1draw')
}
mixes = {
'7-Game' : '7game',
'8-Game' : '8game',
'9-Game' : '9game',
'10-Game' : '10game',
'HA' : 'ha',
'HEROS' : 'heros',
'HO' : 'ho',
'HOE' : 'hoe',
'HORSE' : 'horse',
'HOSE' : 'hose',
'OA' : 'oa',
'OE' : 'oe',
'SE' : 'se'
}
currencies = { u'':'EUR', '$':'USD', '':'T$' }
if 'SB' in mg:
@ -242,11 +260,12 @@ class Fulltilt(HandHistoryConverter):
if info['limitType'] == 'fl' and info['bb'] is not None and info['type'] == 'ring':
try:
info['sb'] = self.Lim_Blinds[mg['BB']][0]
info['bb'] = self.Lim_Blinds[mg['BB']][1]
bb = self.clearMoneyString(mg['BB'])
info['sb'] = self.Lim_Blinds[bb][0]
info['bb'] = self.Lim_Blinds[bb][1]
except KeyError:
log.error(_("Lim_Blinds has no lookup for '%s'") % mg['BB'])
log.error(_("determineGameType: Raising FpdbParseError"))
log.error("determineGameType: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Lim_Blinds has no lookup for '%s'") % mg['BB'])
if mg['GAME'] is not None:
@ -254,6 +273,9 @@ class Fulltilt(HandHistoryConverter):
if mg['CURRENCY'] is not None:
info['currency'] = currencies[mg['CURRENCY']]
# NB: SB, BB must be interpreted as blinds or bets depending on limit type.
m = self.re_Mixed.search(self.in_path)
if m: info['mix'] = mixes[m.groupdict()['MIXED']]
return info
def readHandInfo(self, hand):
@ -353,8 +375,9 @@ class Fulltilt(HandHistoryConverter):
# Remove any listed as sitting out in the summary as start of hand info unreliable
n = self.re_SummarySitout.finditer(post)
for b in n:
del plist[b.group('PNAME')]
#print "DEBUG: Deleting '%s' from player dict" %(b.group('PNAME'))
if b.group('PNAME') in plist:
#print "DEBUG: Deleting '%s' from player dict" %(b.group('PNAME'))
del plist[b.group('PNAME')]
# Add remaining players
for a in plist:
@ -363,16 +386,22 @@ class Fulltilt(HandHistoryConverter):
if plist == {}:
#No players! The hand is either missing stacks or everyone is sitting out
raise FpdbParseError(_("FTP: readPlayerStacks: No players detected (hand #%s)") % hand.handid)
raise FpdbParseError(_("readPlayerStacks: No players detected (hand #%s)") % hand.handid)
def markStreets(self, hand):
if hand.gametype['base'] == 'hold':
m = re.search(r"\*\*\* HOLE CARDS \*\*\*(?P<PREFLOP>.+(?=\*\*\* FLOP \*\*\*)|.+)"
r"(\*\*\* FLOP \*\*\*(?P<FLOP> \[\S\S \S\S \S\S\].+(?=\*\*\* TURN \*\*\*)|.+))?"
r"(\*\*\* TURN \*\*\* \[\S\S \S\S \S\S] (?P<TURN>\[\S\S\].+(?=\*\*\* RIVER \*\*\*)|.+))?"
r"(\*\*\* RIVER \*\*\* \[\S\S \S\S \S\S \S\S] (?P<RIVER>\[\S\S\].+))?", hand.handText,re.DOTALL)
m = re.search(r"\*\*\* HOLE CARDS \*\*\*(?P<PREFLOP>.+(?=\*\*\* FLOP (1\s)?\*\*\*)|.+)"
r"(\*\*\* FLOP \*\*\*(?P<FLOP> \[\S\S \S\S \S\S\].+(?=\*\*\* TURN (1\s)?\*\*\*)|.+))?"
r"(\*\*\* TURN \*\*\* \[\S\S \S\S \S\S] (?P<TURN>\[\S\S\].+(?=\*\*\* RIVER (1\s)?\*\*\*)|.+))?"
r"(\*\*\* RIVER \*\*\* \[\S\S \S\S \S\S \S\S] (?P<RIVER>\[\S\S\].+))?"
r"(\*\*\* FLOP 1 \*\*\*(?P<FLOP1> \[\S\S \S\S \S\S\].+(?=\*\*\* TURN 1 \*\*\*)|.+))?"
r"(\*\*\* TURN 1 \*\*\* \[\S\S \S\S \S\S] (?P<TURN1>\[\S\S\].+(?=\*\*\* RIVER 1 \*\*\*)|.+))?"
r"(\*\*\* RIVER 1 \*\*\* \[\S\S \S\S \S\S \S\S] (?P<RIVER1>\[\S\S\].))?"
r"(\*\*\* FLOP 2 \*\*\*(?P<FLOP2> \[\S\S \S\S \S\S\].+(?=\*\*\* TURN 2 \*\*\*)|.+))?"
r"(\*\*\* TURN 2 \*\*\* \[\S\S \S\S \S\S] (?P<TURN2>\[\S\S\].+(?=\*\*\* RIVER 2 \*\*\*)|.+))?"
r"(\*\*\* RIVER 2 \*\*\* \[\S\S \S\S \S\S \S\S] (?P<RIVER2>\[\S\S\].+))?", hand.handText,re.DOTALL)
elif hand.gametype['base'] == "stud":
m = re.search(r"(?P<ANTES>.+(?=\*\*\* 3RD STREET \*\*\*)|.+)"
r"(\*\*\* 3RD STREET \*\*\*(?P<THIRD>.+(?=\*\*\* 4TH STREET \*\*\*)|.+))?"
@ -391,10 +420,13 @@ class Fulltilt(HandHistoryConverter):
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)
#print "DEBUG readCommunityCards:", street, hand.streets[street]
m = self.re_Board.search(hand.streets[street])
hand.setCommunityCards(street, m.group('CARDS').split(' '))
if street in ('FLOP1', 'TURN1', 'RIVER1', 'FLOP2', 'TURN2', 'RIVER2'):
m = self.re_Board.search(hand.streets[street])
hand.setCommunityCards(street, m.group('CARDS').split(' '))
hand.runItTimes = 2
def readBlinds(self, hand):
try:
@ -411,11 +443,16 @@ class Fulltilt(HandHistoryConverter):
def readAntes(self, hand):
logging.debug(_("reading antes"))
slist = []
n = self.re_ReturnsAnte.finditer(hand.handText)
for player in n:
#If a player has their ante returned, then they timed out and are actually sitting out
slist.append(player.group('PNAME'))
m = self.re_Antes.finditer(hand.handText)
for player in m:
logging.debug("hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE')))
# if player.group() !=
hand.addAnte(player.group('PNAME'), player.group('ANTE'))
if player.group('PNAME') not in slist:
hand.addAnte(player.group('PNAME'), player.group('ANTE'))
def readBringIn(self, hand):
m = self.re_BringIn.search(hand.handText,re.DOTALL)
@ -430,7 +467,7 @@ class Fulltilt(HandHistoryConverter):
hand.buttonpos = int(self.re_Button.search(hand.handText).group('BUTTON'))
except AttributeError, e:
# FTP has no indication that a hand is cancelled.
raise FpdbParseError(_("FTP: readButton: Failed to detect button (hand #%s cancelled?)") % hand.handid)
raise FpdbParseError(_("readButton: Failed to detect button (hand #%s cancelled?)") % hand.handid)
def readHeroCards(self, hand):
# streets PREFLOP, PREDRAW, and THIRD are special cases beacause
@ -483,8 +520,12 @@ class Fulltilt(HandHistoryConverter):
hand.addFold( street, action.group('PNAME'))
elif action.group('ATYPE') == ' checks':
hand.addCheck( street, action.group('PNAME'))
elif action.group('ATYPE') == ' discards':
hand.addDiscard(street, action.group('PNAME'), action.group('BET'), action.group('CARDS'))
elif action.group('ATYPE') == ' stands pat':
hand.addStandsPat( street, action.group('PNAME'), action.group('CARDS'))
else:
print _("FullTilt: DEBUG: unimplemented readAction: '%s' '%s'") %(action.group('PNAME'),action.group('ATYPE'),)
print (_("DEBUG: ") + " " + _("Unimplemented readAction: '%s' '%s'") % (action.group('PNAME'), action.group('ATYPE')))
def readShowdownActions(self, hand):
@ -500,10 +541,16 @@ class Fulltilt(HandHistoryConverter):
def readShownCards(self,hand):
for m in self.re_ShownCards.finditer(hand.handText):
if m.group('CARDS') is not None:
if m.group('ACT'):
hand.addShownCards(cards=m.group('CARDS').split(' '), player=m.group('PNAME'), shown = False, mucked = True)
else:
hand.addShownCards(cards=m.group('CARDS').split(' '), player=m.group('PNAME'), shown = True, mucked = False)
cards = m.group('CARDS')
cards = cards.split(' ') # needs to be a list, not a set--stud needs the order
string = m.group('STRING')
(shown, mucked) = (False, False)
if m.group('SHOWED') == "showed": shown = True
elif m.group('SHOWED') == "mucked": mucked = True
#print "DEBUG: hand.addShownCards(%s, %s, %s, %s)" %(cards, m.group('PNAME'), shown, mucked)
hand.addShownCards(cards=cards, player=m.group('PNAME'), shown=shown, mucked=mucked, string=string)
def guessMaxSeats(self, hand):
"""Return a guess at max_seats when not specified in HH."""
@ -523,13 +570,6 @@ class Fulltilt(HandHistoryConverter):
if mo <= 6: return 6
return 9
def readOther(self, hand):
m = self.re_Mixed.search(self.in_path)
if m is None:
hand.mixed = None
else:
hand.mixed = self.mixes[m.groupdict()['MIXED']]
def readSummaryInfo(self, summaryInfoList):
self.status = True
@ -761,7 +801,7 @@ class Fulltilt(HandHistoryConverter):
tourney.addPlayer(rank, a.group('PNAME'), winnings, "USD", 0, 0, 0) #TODO: make it store actual winnings currency
else:
print (_("FullTilt: Player finishing stats unreadable : %s") % a)
print (_("Player finishing stats unreadable : %s") % a)
# Find Hero
n = self.re_TourneyHeroFinishingP.search(playersText)
@ -770,9 +810,9 @@ class Fulltilt(HandHistoryConverter):
tourney.hero = heroName
# Is this really useful ?
if heroName not in tourney.ranks:
print (_("FullTilt: %s not found in tourney.ranks ...") % heroName)
print (_("%s not found in tourney.ranks ...") % heroName)
elif (tourney.ranks[heroName] != Decimal(n.group('HERO_FINISHING_POS'))):
print (_("FullTilt: Bad parsing : finish position incoherent : %s / %s") % (tourney.ranks[heroName], n.group('HERO_FINISHING_POS')))
print (_("Bad parsing : finish position incoherent : %s / %s") % (tourney.ranks[heroName], n.group('HERO_FINISHING_POS')))
return True

2
pyfpdb/GuiImapFetcher.py

@ -107,7 +107,7 @@ class GuiImapFetcher (threading.Thread):
def displayConfig(self):
box=gtk.HBox(homogeneous=True)
for text in (_("Site"), _("Fetch Type"), _("Mailserver"), _("Username"), _("Password"), _("Mail Folder"), _("Use SSL")):
for text in (_("Site"), _("Fetch Type"), _("Mail Server"), _("Username"), _("Password"), _("Mail Folder"), _("Use SSL")):
label=gtk.Label(text)
box.add(label)
self.mainVBox.pack_start(box, expand=False)

7
pyfpdb/GuiTourneyImport.py

@ -223,13 +223,18 @@ class SummaryImporter:
print "Found %s summaries" %(len(summaryTexts))
errors = 0
imported = 0
####Lock Placeholder####
for j, summaryText in enumerate(summaryTexts, start=1):
sc, gsc = {'bk': []}, {'bk': []}
doinsert = len(summaryTexts)==j
try:
conv = obj(db=None, config=self.config, siteName=site, summaryText=summaryText, builtFrom = "IMAP")
conv = obj(db=self.database, config=self.config, siteName=site, summaryText=summaryText, builtFrom = "IMAP")
sc, gsc = conv.updateSessionsCache(sc, gsc, None, doinsert)
except FpdbParseError, e:
errors += 1
print _("Finished importing %s/%s tournament summaries") %(j, len(summaryTexts))
imported = j
####Lock Placeholder####
return (imported - errors, errors)
def clearFileList(self):

147
pyfpdb/Hand.py

@ -57,6 +57,7 @@ class Hand(object):
#log.debug( _("Hand.init(): handText is ") + str(handText) )
self.config = config
self.saveActions = self.config.get_import_parameters().get('saveActions')
self.callHud = self.config.get_import_parameters().get("callFpdbHud")
self.cacheSessions = self.config.get_import_parameters().get("cacheSessions")
#log = Configuration.get_logger("logging.conf", "db", log_dir=self.config.dir_log)
self.sitename = sitename
@ -76,6 +77,7 @@ class Hand(object):
self.maxseats = None
self.counted_seats = 0
self.buttonpos = 0
self.runItTimes = 0
#tourney stuff
self.tourNo = None
@ -101,7 +103,7 @@ class Hand(object):
self.seating = []
self.players = []
self.posted = []
self.tourneysPlayersIds = []
self.tourneysPlayersIds = {}
# Collections indexed by street names
self.bets = {}
@ -111,6 +113,7 @@ class Hand(object):
self.board = {} # dict from street names to community cards
self.holecards = {}
self.discards = {}
self.showdownStrings = {}
for street in self.allStreets:
self.streets[street] = "" # portions of the handText, filled by markStreets()
self.actions[street] = []
@ -232,9 +235,8 @@ dealt whether they were seen in a 'dealt to' line
# Players, Gametypes, TourneyTypes are all shared functions that are needed for additional tables
# These functions are intended for prep insert eventually
#####
# Players - base playerid and siteid tuple
self.dbid_pids = db.getSqlPlayerIDs([p[1] for p in self.players], self.siteId)
self.dbid_gt = db.getGameTypeId(self.siteId, self.gametype, printdata = printtest)
#Gametypes
hilo = "h"
if self.gametype['category'] in ['studhilo', 'omahahilo']:
@ -249,61 +251,71 @@ dealt whether they were seen in a 'dealt to' line
# Note: the above data is calculated in db.getGameTypeId
# Only being calculated above so we can grab the testdata
self.dbid_gt = db.getGameTypeId(self.siteId, self.gametype, printdata = printtest)
if self.tourNo!=None:
self.tourneyTypeId = db.createTourneyType(self)
db.commit()
self.tourneyId = db.createOrUpdateTourney(self, "HHC")
db.commit()
self.tourneysPlayersIds = db.createOrUpdateTourneysPlayers(self, "HHC")
db.commit()
#end def prepInsert
def insert(self, db, hp_data = None, ha_data = None, insert_data=False, printtest = False):
""" Function to insert Hand into database
Should not commit, and do minimal selects. Callers may want to cache commits
db: a connected Database object"""
#db.commit() #commit these transactions'
def assembleHand(self):
self.stats.getStats(self)
#####
# End prep functions
#####
hh = self.stats.getHands()
hp_inserts, ha_inserts = [], []
if not db.isDuplicate(self.dbid_gt, hh['siteHandNo']):
# Hands - Summary information of hand indexed by handId - gameinfo
hh['gametypeId'] = self.dbid_gt
# seats TINYINT NOT NULL,
hh['seats'] = len(self.dbid_pids)
hp = self.stats.getHandsPlayers()
if self.cacheSessions:
hh['sessionId'] = db.storeSessionsCache(self.dbid_pids, self.startTime, self.gametype, hp)
self.dbid_hands = db.storeHand(hh, printdata = printtest)
hp_inserts = db.storeHandsPlayers(self.dbid_hands, self.dbid_pids, hp,
insert=insert_data, hp_bulk = hp_data, printdata = printtest)
if self.saveActions:
ha_inserts = db.storeHandsActions(self.dbid_hands, self.dbid_pids, self.stats.getHandsActions(),
insert=insert_data, ha_bulk = ha_data, printdata = printtest)
else:
log.info(_("Hand.insert(): hid #: %s is a duplicate") % hh['siteHandNo'])
self.is_duplicate = True # i.e. don't update hudcache
raise FpdbHandDuplicate(hh['siteHandNo'])
self.hands = self.stats.getHands()
self.handsplayers = self.stats.getHandsPlayers()
return hp_inserts, ha_inserts
def getHandId(self, db, id):
if db.isDuplicate(self.dbid_gt, self.hands['siteHandNo']):
#log.info(_("Hand.insert(): hid #: %s is a duplicate") % hh['siteHandNo'])
self.is_duplicate = True # i.e. don't update hudcache
next = id
raise FpdbHandDuplicate(self.hands['siteHandNo'])
else:
self.dbid_hands = id
self.hands['id'] = self.dbid_hands
next = id +1
return next
def updateHudCache(self, db):
db.storeHudCache(self.dbid_gt, self.dbid_pids, self.startTime, self.stats.getHandsPlayers())
def insertHands(self, db, hbulk, fileId, doinsert = False, printtest = False):
""" Function to insert Hand into database
Should not commit, and do minimal selects. Callers may want to cache commits
db: a connected Database object"""
self.hands['gametypeId'] = self.dbid_gt
self.hands['seats'] = len(self.dbid_pids)
self.hands['fileId'] = fileId
hbulk = db.storeHand(self.hands, hbulk, doinsert, printtest)
return hbulk
def insertHandsPlayers(self, db, hpbulk, doinsert = False, printtest = False):
""" Function to inserts HandsPlayers into database"""
hpbulk = db.storeHandsPlayers(self.dbid_hands, self.dbid_pids, self.handsplayers, hpbulk, doinsert, printtest)
return hpbulk
def insertHandsActions(self, db, habulk, doinsert = False, printtest = False):
""" Function to inserts HandsActions into database"""
handsactions = self.stats.getHandsActions()
habulk = db.storeHandsActions(self.dbid_hands, self.dbid_pids, handsactions, habulk, doinsert, printtest)
return habulk
def updateHudCache(self, db, hcbulk, doinsert = False):
""" Function to update the HudCache"""
if self.callHud:
hcbulk = db.storeHudCache(self.dbid_gt, self.dbid_pids, self.startTime, self.handsplayers, hcbulk, doinsert)
return hcbulk
def updateSessionsCache(self, db):
db.storeSessionsCache(self.dbid_pids, self.startTime, self.gametype, self.stats.getHandsPlayers())
def updateSessionsCache(self, db, sc, gsc, tz, doinsert = False):
""" Function to update the SessionsCache"""
if self.cacheSessions:
self.heros = db.getHeroIds(self.dbid_pids, self.sitename)
sc = db.prepSessionsCache(self.dbid_hands, self.dbid_pids, self.startTime, sc, self.heros, doinsert)
gsc = db.storeSessionsCache(self.dbid_hands, self.dbid_pids, self.startTime, self.gametype
,self.dbid_gt, self.handsplayers, sc, gsc, tz, self.heros, doinsert)
if doinsert and sc['bk'] and gsc['bk']:
self.hands['sc'] = sc
self.hands['gsc'] = gsc
else:
self.hands['sc'] = None
self.hands['gsc'] = None
return sc, gsc
def select(self, db, handId):
""" Function to create Hand object from database """
@ -666,10 +678,13 @@ Add a raise on [street] by [player] to [amountTo]
self.pot.addMoney(player, amount)
def addStandsPat(self, street, player):
def addStandsPat(self, street, player, cards):
self.checkPlayerExists(player)
act = (player, 'stands pat')
self.actions[street].append(act)
if cards:
cards = cards.split(' ')
self.addHoleCards(street, player, open=[], closed=cards)
def addFold(self, street, player):
@ -697,7 +712,7 @@ Add a raise on [street] by [player] to [amountTo]
self.collectees[player] += Decimal(pot)
def addShownCards(self, cards, player, holeandboard=None, shown=True, mucked=False):
def addShownCards(self, cards, player, holeandboard=None, shown=True, mucked=False, string=None):
"""\
For when a player shows cards for any reason (for showdown or out of choice).
Card ranks will be uppercased
@ -705,6 +720,8 @@ Card ranks will be uppercased
log.debug(_("addShownCards %s hole=%s all=%s") % (player, cards, holeandboard))
if cards is not None:
self.addHoleCards(cards,player,shown, mucked)
if string is not None:
self.showdownStrings[player] = string
elif holeandboard is not None:
holeandboard = set([self.card(c) for c in holeandboard])
board = set([c for s in self.board.values() for c in s])
@ -874,9 +891,8 @@ class HoldemOmahaHand(Hand):
hhc.readHeroCards(self)
hhc.readShowdownActions(self)
# Read actions in street order
for street in self.communityStreets:
if self.streets[street]:
hhc.readCommunityCards(self, street)
for street, text in self.streets.iteritems():
if text: hhc.readCommunityCards(self, street)
for street in self.actionStreets:
if self.streets[street]:
hhc.readAction(self, street)
@ -900,7 +916,7 @@ class HoldemOmahaHand(Hand):
pass
def addShownCards(self, cards, player, shown=True, mucked=False, dealt=False):
def addShownCards(self, cards, player, shown=True, mucked=False, dealt=False, string=None):
if player == self.hero: # we have hero's cards just update shown/mucked
if shown: self.shown.add(player)
if mucked: self.mucked.add(player)
@ -913,6 +929,8 @@ class HoldemOmahaHand(Hand):
diff = filter( lambda x: x not in self.board['FLOP']+self.board['TURN']+self.board['RIVER'], cards )
if len(diff) == 2 and self.gametype['category'] in ('holdem'):
self.addHoleCards('PREFLOP', player, open=[], closed=diff, shown=shown, mucked=mucked, dealt=dealt)
if string is not None:
self.showdownStrings[player] = string
def getStreetTotals(self):
# street1Pot INT, /* pot size at flop/street4 */
@ -1188,13 +1206,15 @@ class DrawHand(Hand):
elif builtFrom == "DB":
self.select("dummy") # Will need a handId
def addShownCards(self, cards, player, shown=True, mucked=False, dealt=False):
def addShownCards(self, cards, player, shown=True, mucked=False, dealt=False, string=None):
if player == self.hero: # we have hero's cards just update shown/mucked
if shown: self.shown.add(player)
if mucked: self.mucked.add(player)
else:
# TODO: Probably better to find the last street with action and add the hole cards to that street
self.addHoleCards('DRAWTHREE', player, open=[], closed=cards, shown=shown, mucked=mucked, dealt=dealt)
if string is not None:
self.showdownStrings[player] = string
def discardDrawHoleCards(self, cards, player, street):
@ -1229,7 +1249,14 @@ class DrawHand(Hand):
def join_holecards(self, player, asList=False):
"""With asList = True it returns the set cards for a player including down cards if they aren't know"""
# FIXME: This should actually return
holecards = [u'0x', u'0x', u'0x', u'0x', u'0x']
holecards = [u'0x']*20
for i, street in enumerate(self.holeStreets):
if player in self.holecards[street].keys():
allhole = self.holecards[street][player][1] + self.holecards[street][player][0]
for c in range(len(allhole)):
idx = c + (i*5)
holecards[idx] = allhole[c]
if asList == False:
return " ".join(holecards)
@ -1359,7 +1386,7 @@ class StudHand(Hand):
elif builtFrom == "DB":
self.select("dummy") # Will need a handId
def addShownCards(self, cards, player, shown=True, mucked=False, dealt=False):
def addShownCards(self, cards, player, shown=True, mucked=False, dealt=False, string=None):
if player == self.hero: # we have hero's cards just update shown/mucked
if shown: self.shown.add(player)
if mucked: self.mucked.add(player)
@ -1370,6 +1397,8 @@ class StudHand(Hand):
self.addHoleCards('SIXTH', player, open=[cards[5]], closed=cards[2:5], shown=shown, mucked=mucked)
if len(cards) > 6:
self.addHoleCards('SEVENTH', player, open=[], closed=[cards[6]], shown=shown, mucked=mucked)
if string is not None:
self.showdownStrings[player] = string
def addPlayerCards(self, player, street, open=[], closed=[]):

20
pyfpdb/HandHistoryConverter.py

@ -50,9 +50,6 @@ import Hand
from Exceptions import FpdbParseError
import Configuration
import pygtk
import gtk
class HandHistoryConverter():
READ_CHUNK_SIZE = 10000 # bytes to read at a time from file in tail mode
@ -71,7 +68,7 @@ class HandHistoryConverter():
# maybe archive params should be one archive param, then call method in specific converter. if archive: convert_archive()
def __init__( self, config, in_path = '-', out_path = '-', follow=False, index=0
, autostart=True, starsArchive=False, ftpArchive=False, sitename="PokerStars" ):
, autostart=True, starsArchive=False, ftpArchive=False, sitename="PokerStars"):
"""\
in_path (default '-' = sys.stdin)
out_path (default '-' = sys.stdout)
@ -128,9 +125,6 @@ If in follow mode, wait for more data to turn up.
Otherwise, finish at EOF.
"""
while gtk.events_pending():
gtk.main_iteration(False)
starttime = time.time()
if not self.sanityCheck():
log.warning(_("Failed sanity check"))
@ -182,7 +176,12 @@ Otherwise, finish at EOF.
finally:
if self.out_fh != sys.stdout:
self.out_fh.close()
def progressNotify(self):
"A callback to the interface while events are pending"
import gtk, pygtk
while gtk.events_pending():
gtk.main_iteration(False)
def tailHands(self):
"""Generator of handTexts from a tailed file:
@ -290,6 +289,7 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py.
self.numErrors += 1
else:
# See if gametype is supported.
if 'mix' not in gametype: gametype['mix'] = 'none'
type = gametype['type']
base = gametype['base']
limit = gametype['limitType']
@ -333,6 +333,7 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py.
'base' in ('hold', 'stud', 'draw')
'category' in ('holdem', 'omahahi', omahahilo', 'razz', 'studhi', 'studhilo', 'fivedraw', '27_1draw', '27_3draw', 'badugi')
'hilo' in ('h','l','s')
'mix' in (site specific, or 'none')
'smallBlind' int?
'bigBlind' int?
'smallBet'
@ -446,7 +447,8 @@ or None if we fail to get the info """
def readAction(self, hand, street): abstract
def readCollectPot(self, hand): abstract
def readShownCards(self, hand): abstract
# EDIT: readOther is depreciated
# Some sites do odd stuff that doesn't fall in to the normal HH parsing.
# e.g., FTP doesn't put mixed game info in the HH, but puts in in the
# file name. Use readOther() to clean up those messes.

23
pyfpdb/OnGameToFpdb.py

@ -42,10 +42,10 @@ class OnGame(HandHistoryConverter):
siteId = 5 # Needs to match id entry in Sites database
mixes = { } # Legal mixed games
sym = {'USD': "\$", 'CAD': "\$", 'T$': "", "EUR": u"\u20ac", "GBP": "\xa3"} # ADD Euro, Sterling, etc HERE
sym = {'USD': "\$", 'CAD': "\$", 'T$': "", "EUR": u"\u20ac", "GBP": "\xa3"}
substitutions = {
'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
'LS' : u"\$|\xe2\x82\xac|\u20ac" # legal currency symbols - Euro(cp1252, utf-8)
'LS' : u"\$|\xe2\x82\xac|\u20ac" # legal currency symbols - Euro(cp1252, utf-8)
}
currencies = { u'\u20ac':'EUR', u'\xe2\x82\xac':'EUR', '$':'USD', '':'T$' }
@ -71,9 +71,11 @@ class OnGame(HandHistoryConverter):
#TODO: detect play money
# "Play money" rather than "Real money" and set currency accordingly
re_HandInfo = re.compile(u"""
\*\*\*\*\*\sHistory\sfor\shand\s(?P<HID>[-A-Z\d]+).*
\*\*\*\*\*\sHistory\sfor\shand\s(?P<HID>[-A-Z\d]+)
(\s\(TOURNAMENT:\s"[a-zA-Z ]+",\s(?P<TID>[-A-Z\d]+),\sbuy-in:\s[%(LS)s](?P<BUYIN>\d+))?
.*
Start\shand:\s(?P<DATETIME>.*)
Table:\s(\[SPEED\]\s)?(?P<TABLE>[-\'\w\s\.]+)\s\[\d+\]\s\(
Table:\s(\[SPEED\]\s)?(?P<TABLE>[-\'\w\#\s\.]+)\s\[\d+\]\s\(
(
(?P<LIMIT>NO_LIMIT|Limit|LIMIT|Pot\sLimit|POT_LIMIT)\s
(?P<GAME>TEXAS_HOLDEM|OMAHA_HI|SEVEN_CARD_STUD|SEVEN_CARD_STUD_HI_LO|RAZZ|FIVE_CARD_DRAW)\s
@ -99,6 +101,7 @@ class OnGame(HandHistoryConverter):
#Seat 1: .Lucchess ($4.17 in chips)
#Seat 1: phantomaas ($27.11)
#Seat 5: mleo17 ($9.37)
#Seat 2: Montferat (1500)
re_PlayerInfo = re.compile(u'Seat (?P<SEAT>[0-9]+):\s(?P<PNAME>.*)\s\((%(LS)s)?(?P<CASH>[.0-9]+)\)' % substitutions)
def compilePlayerRegexs(self, hand):
@ -146,6 +149,7 @@ class OnGame(HandHistoryConverter):
["ring", "hold", "nl"],
["ring", "stud", "fl"],
["ring", "draw", "fl"],
["tour", "hold", "nl"],
]
def determineGameType(self, handText):
@ -157,13 +161,16 @@ class OnGame(HandHistoryConverter):
if not m:
tmp = handText[0:100]
log.error(_("Unable to recognise gametype from: '%s'") % tmp)
log.error(_("determineGameType: Raising FpdbParseError"))
log.error("determineGameType: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
mg = m.groupdict()
#print "DEBUG: mg: %s" % mg
info['type'] = 'ring'
if mg['TID'] != None:
info['type'] = 'tour'
if 'CURRENCY' in mg:
info['currency'] = self.currencies[mg['CURRENCY']]
@ -173,7 +180,7 @@ class OnGame(HandHistoryConverter):
else:
tmp = handText[0:100]
log.error(_("limit not found in self.limits(%s). hand: '%s'") % (str(mg),tmp))
log.error(_("determineGameType: Raising FpdbParseError"))
log.error("determineGameType: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("limit not found in self.limits(%s). hand: '%s'") % (str(mg),tmp))
if 'GAME' in mg:
(info['base'], info['category']) = self.games[mg['GAME']]
@ -216,6 +223,10 @@ class OnGame(HandHistoryConverter):
# Need to remove non-alphanumerics for MySQL
hand.handid = hand.handid.replace('R','')
hand.handid = hand.handid.replace('-','')
if key == 'TID':
hand.tourNo = info[key]
if key == 'BUYIN':
hand.buyin = info[key]
if key == 'TABLE':
hand.tablename = info[key]

12
pyfpdb/PacificPokerToFpdb.py

@ -41,8 +41,8 @@ class PacificPoker(HandHistoryConverter):
mixes = { 'HORSE': 'horse', '8-Game': '8game', 'HOSE': 'hose'} # Legal mixed games
sym = {'USD': "\$", 'CAD': "\$", 'T$': "", "EUR": "\xe2\x82\xac", "GBP": "\xa3", "play": ""} # ADD Euro, Sterling, etc HERE
substitutions = {
'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
'LS' : "\$|\xe2\x82\xac|" # legal currency symbols - Euro(cp1252, utf-8)
'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
'LS' : u"\$|\xe2\x82\xac|\u20ac|" # legal currency symbols - Euro(cp1252, utf-8)
}
# translations from captured groups to fpdb info strings
@ -171,7 +171,7 @@ class PacificPoker(HandHistoryConverter):
if not m:
tmp = handText[0:120]
log.error(_("Unable to recognise gametype from: '%s'") % tmp)
log.error(_("determineGameType: Raising FpdbParseError"))
log.error("determineGameType: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
mg = m.groupdict()
@ -202,7 +202,7 @@ class PacificPoker(HandHistoryConverter):
info['bb'] = self.Lim_Blinds[mg['BB']][1]
except KeyError:
log.error(_("Lim_Blinds has no lookup for '%s'") % mg['BB'])
log.error(_("determineGameType: Raising FpdbParseError"))
log.error("determineGameType: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Lim_Blinds has no lookup for '%s'") % mg['BB'])
return info
@ -255,7 +255,7 @@ class PacificPoker(HandHistoryConverter):
hand.buyinCurrency="PSFP"
else:
#FIXME: handle other currencies, FPP, play money
raise FpdbParseError(_("Failed to detect currency. Hand ID: %s: '%s'") % (hand.handid, info[key]))
raise FpdbParseError(_("Failed to detect currency.") + " " + _("Hand ID: %s: '%s'") % (hand.handid, info[key]))
info['BIAMT'] = info['BIAMT'].strip(u'$€FPP')
@ -426,7 +426,7 @@ class PacificPoker(HandHistoryConverter):
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'),)
print (_("DEBUG: ") + _("Unimplemented readAction: '%s' '%s'") % (action.group('PNAME'), action.group('ATYPE')))
def readShowdownActions(self, hand):

8
pyfpdb/PartyPokerToFpdb.py

@ -195,7 +195,7 @@ class PartyPoker(HandHistoryConverter):
if m is None:
tmp = handText[0:100]
log.error(_("Unable to recognise gametype from: '%s'") % tmp)
log.error(_("determineGameType: Raising FpdbParseError"))
log.error("determineGameType: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
mg = m.groupdict()
@ -345,7 +345,7 @@ class PartyPoker(HandHistoryConverter):
elif info[key].find(u"")!=-1:
hand.buyinCurrency="EUR"
else:
raise FpdbParseError(_("Failed to detect currency. Hand ID: %s: '%s'") % (hand.handid, info[key]))
raise FpdbParseError(_("Failed to detect currency.") + " " + _("Hand ID: %s: '%s'") % (hand.handid, info[key]))
info[key] = info[key].strip(u'$€')
hand.buyin = int(100*Decimal(info[key]))
if key == 'LEVEL':
@ -532,9 +532,7 @@ class PartyPoker(HandHistoryConverter):
elif actionType == 'checks':
hand.addCheck( street, playerName )
else:
raise FpdbParseError(
_("Unimplemented readAction: '%s' '%s'") % (playerName,actionType,),
hid = hand.hid, )
raise FpdbParseError(_("Unimplemented readAction: '%s' '%s'") % (playerName,actionType), hid = hand.hid)
def readShowdownActions(self, hand):
# all action in readShownCards

6
pyfpdb/PkrToFpdb.py

@ -126,7 +126,7 @@ class Pkr(HandHistoryConverter):
if not m:
tmp = handText[0:100]
log.error(_("Unable to recognise gametype from: '%s'") % tmp)
log.error(_("determineGameType: Raising FpdbParseError"))
log.error("determineGameType: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
mg = m.groupdict()
@ -151,7 +151,7 @@ class Pkr(HandHistoryConverter):
info['bb'] = self.Lim_Blinds[mg['BB']][1]
except KeyError:
log.error(_("Lim_Blinds has no lookup for '%s'") % mg['BB'])
log.error(_("determineGameType: Raising FpdbParseError"))
log.error("determineGameType: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Lim_Blinds has no lookup for '%s'") % mg['BB'])
return info
@ -348,7 +348,7 @@ class Pkr(HandHistoryConverter):
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'),)
print (_("DEBUG: ") + _("Unimplemented readAction: '%s' '%s'") % (action.group('PNAME'), action.group('ATYPE')))
def readShowdownActions(self, hand):

10
pyfpdb/PokerStarsSummary.py

@ -68,7 +68,7 @@ class PokerStarsSummary(TourneySummary):
re_Currency = re.compile(u"""(?P<CURRENCY>[%(LS)s]|FPP)""" % substitutions)
re_Player = re.compile(u"""(?P<RANK>[0-9]+):\s(?P<NAME>.*)\s\(.*\),(\s)?(\$(?P<WINNINGS>[0-9]+\.[0-9]+))?(?P<STILLPLAYING>still\splaying)?((?P<TICKET>Tournament\sTicket)\s\(WSOP\sStep\s(?P<LEVEL>\d)\))?(\s+)?""")
re_Player = re.compile(u"""(?P<RANK>[0-9]+):\s(?P<NAME>.*)\s\(.*\),(\s)?([%(LS)s](?P<WINNINGS>[0-9]+\.[0-9]+))?(?P<STILLPLAYING>still\splaying)?((?P<TICKET>Tournament\sTicket)\s\(WSOP\sStep\s(?P<LEVEL>\d)\))?(\s+)?""" % substitutions)
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]+)")
@ -78,8 +78,8 @@ class PokerStarsSummary(TourneySummary):
m = self.re_TourneyInfo.search(self.summaryText)
if m == None:
tmp = self.summaryText[0:200]
log.error(_("parseSummary: Unable to recognise Tourney Info: '%s'") % tmp)
log.error(_("parseSummary: Raising FpdbParseError"))
log.error("parseSummary: " + _("Unable to recognise Tourney Info: '%s'") % tmp)
log.error("parseSummary: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise Tourney Info: '%s'") % tmp)
#print "DEBUG: m.groupdict(): %s" % m.groupdict()
@ -104,8 +104,8 @@ class PokerStarsSummary(TourneySummary):
m = self.re_Currency.search(self.summaryText)
if m == None:
log.error(_("parseSummary: Unable to locate currency"))
log.error(_("parseSummary: Raising FpdbParseError"))
log.error("parseSummary: " + _("Unable to locate currency"))
log.error("parseSummary: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Unable to locate currency"))
#print "DEBUG: m.groupdict(): %s" % m.groupdict()

45
pyfpdb/PokerStarsToFpdb.py

@ -37,12 +37,10 @@ class PokerStars(HandHistoryConverter):
filetype = "text"
codepage = ("utf8", "cp1252")
siteId = 2 # Needs to match id entry in Sites database
mixes = { 'HORSE': 'horse', '8-Game': '8game', 'HOSE': 'hose'} # Legal mixed games
sym = {'USD': "\$", 'CAD': "\$", 'T$': "", "EUR": "\xe2\x82\xac", "GBP": "\xa3", "play": ""} # ADD Euro, Sterling, etc HERE
substitutions = {
'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
'LS' : "\$|\xe2\x82\xac|" # legal currency symbols - Euro(cp1252, utf-8)
'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
'LS' : u"\$|\xe2\x82\xac|\u20ac|" # legal currency symbols - Euro(cp1252, utf-8)
}
# translations from captured groups to fpdb info strings
@ -80,6 +78,15 @@ class PokerStars(HandHistoryConverter):
'Single Draw 2-7 Lowball' : ('draw','27_1draw'),
'5 Card Draw' : ('draw','fivedraw')
}
mixes = {
'HORSE': 'horse',
'8-Game': '8game',
'HOSE': 'hose',
'Mixed PLH/PLO': 'plh_plo',
'Mixed Omaha H/L': 'plo_lo',
'Mixed Hold\'em': 'mholdem',
'Triple Stud': '3stud'
} # Legal mixed games
currencies = { u'':'EUR', '$':'USD', '':'T$' }
# Static regexes
@ -90,7 +97,7 @@ class PokerStars(HandHistoryConverter):
# here's how I plan to use LS
(?P<BUYIN>(?P<BIAMT>[%(LS)s\d\.]+)?\+?(?P<BIRAKE>[%(LS)s\d\.]+)?\+?(?P<BOUNTY>[%(LS)s\d\.]+)?\s?(?P<TOUR_ISO>%(LEGAL_ISO)s)?|Freeroll)\s+)?
# close paren of tournament info
(?P<MIXED>HORSE|8\-Game|HOSE|Mixed PLH/PLO)?\s?\(?
(?P<MIXED>HORSE|8\-Game|HOSE|Mixed\sOmaha\sH/L|Mixed\sHold\'em|Mixed\sPLH/PLO|Triple\sStud)?\s?\(?
(?P<GAME>Hold\'em|Razz|RAZZ|7\sCard\sStud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball|Single\sDraw\s2\-7\sLowball|5\sCard\sDraw)\s
(?P<LIMIT>No\sLimit|Limit|LIMIT|Pot\sLimit)\)?,?\s
(-\s)?
@ -145,11 +152,12 @@ class PokerStars(HandHistoryConverter):
(\s(%(CUR)s)?(?P<BET>[.\d]+))?(\sto\s%(CUR)s(?P<BETTO>[.\d]+))? # the number discarded goes in <BET>
\s*(and\sis\sall.in)?
(and\shas\sreached\sthe\s[%(CUR)s\d\.]+\scap)?
(\scards?(\s\[(?P<DISCARDED>.+?)\])?)?\s*$"""
(\son|\scards?)?
(\s\[(?P<CARDS>.+?)\])?\s*$"""
% short_subst, re.MULTILINE|re.VERBOSE)
re_ShowdownAction = re.compile(r"^%s: shows \[(?P<CARDS>.*)\]" % short_subst['PLYR'], re.MULTILINE)
re_sitsOut = re.compile("^%s sits out" % short_subst['PLYR'], re.MULTILINE)
re_ShownCards = re.compile("^Seat (?P<SEAT>[0-9]+): %s (\(.*\) )?(?P<SHOWED>showed|mucked) \[(?P<CARDS>.*)\].*" % short_subst['PLYR'], re.MULTILINE)
re_ShownCards = re.compile("^Seat (?P<SEAT>[0-9]+): %s (\(.*\) )?(?P<SHOWED>showed|mucked) \[(?P<CARDS>.*)\]( and won \([.\d]+\) with (?P<STRING>.*))?" % short_subst['PLYR'], re.MULTILINE)
re_CollectPot = re.compile(r"Seat (?P<SEAT>[0-9]+): %(PLYR)s (\(button\) |\(small blind\) |\(big blind\) |\(button\) \(small blind\) |\(button\) \(big blind\) )?(collected|showed \[.*\] and won) \(%(CUR)s(?P<POT>[.\d]+)\)(, mucked| with.*|)" % short_subst, re.MULTILINE)
def compilePlayerRegexs(self, hand):
@ -181,9 +189,9 @@ class PokerStars(HandHistoryConverter):
info = {}
m = self.re_GameInfo.search(handText)
if not m:
tmp = handText[0:100]
tmp = handText[0:150]
log.error(_("Unable to recognise gametype from: '%s'") % tmp)
log.error(_("determineGameType: Raising FpdbParseError"))
log.error("determineGameType: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
mg = m.groupdict()
@ -197,7 +205,9 @@ class PokerStars(HandHistoryConverter):
info['bb'] = mg['BB']
if 'CURRENCY' in mg:
info['currency'] = self.currencies[mg['CURRENCY']]
if 'MIXED' in mg:
if mg['MIXED'] is not None: info['mix'] = self.mixes[mg['MIXED']]
if 'TOURNO' in mg and mg['TOURNO'] is None:
info['type'] = 'ring'
else:
@ -209,7 +219,7 @@ class PokerStars(HandHistoryConverter):
info['bb'] = self.Lim_Blinds[mg['BB']][1]
except KeyError:
log.error(_("Lim_Blinds has no lookup for '%s'") % mg['BB'])
log.error(_("determineGameType: Raising FpdbParseError"))
log.error("determineGameType: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Lim_Blinds has no lookup for '%s'") % mg['BB'])
return info
@ -262,7 +272,7 @@ class PokerStars(HandHistoryConverter):
hand.buyinCurrency="PSFP"
else:
#FIXME: handle other currencies, play money
raise FpdbParseError(_("Failed to detect currency. Hand ID: %s: '%s'") % (hand.handid, info[key]))
raise FpdbParseError(_("Failed to detect currency.") + " " + _("Hand ID: %s: '%s'") % (hand.handid, info[key]))
info['BIAMT'] = info['BIAMT'].strip(u'$€FPP')
@ -298,8 +308,6 @@ class PokerStars(HandHistoryConverter):
if key == 'MAX' and info[key] != None:
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'
@ -432,11 +440,11 @@ class PokerStars(HandHistoryConverter):
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'))
hand.addDiscard(street, action.group('PNAME'), action.group('BET'), action.group('CARDS'))
elif action.group('ATYPE') == ' stands pat':
hand.addStandsPat( street, action.group('PNAME'))
hand.addStandsPat( street, action.group('PNAME'), action.group('CARDS'))
else:
print (_("DEBUG: ") + _("Unimplemented readAction: '%s' '%s'") % (action.group('PNAME'),action.group('ATYPE')))
print (_("DEBUG: ") + _("Unimplemented readAction: '%s' '%s'") % (action.group('PNAME'), action.group('ATYPE')))
def readShowdownActions(self, hand):
@ -454,13 +462,14 @@ class PokerStars(HandHistoryConverter):
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
string = m.group('STRING')
(shown, mucked) = (False, False)
if m.group('SHOWED') == "showed": shown = True
elif m.group('SHOWED') == "mucked": mucked = True
#print "DEBUG: hand.addShownCards(%s, %s, %s, %s)" %(cards, m.group('PNAME'), shown, mucked)
hand.addShownCards(cards=cards, player=m.group('PNAME'), shown=shown, mucked=mucked)
hand.addShownCards(cards=cards, player=m.group('PNAME'), shown=shown, mucked=mucked, string=string)
if __name__ == "__main__":
parser = OptionParser()

595
pyfpdb/SQL.py

@ -107,6 +107,15 @@ class Sql:
elif db_server == 'sqlite':
self.query['createSettingsTable'] = """CREATE TABLE Settings
(version INTEGER NOT NULL) """
################################
# Create InsertLock
################################
if db_server == 'mysql':
self.query['createLockTable'] = """CREATE TABLE InsertLock (
id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
locked BOOLEAN NOT NULL DEFAULT FALSE)
ENGINE=INNODB"""
################################
# Create RawHands (this table is all but identical with RawTourneys)
@ -236,6 +245,7 @@ class Sql:
category varchar(9) NOT NULL,
limitType char(2) NOT NULL,
hiLo char(1) NOT NULL,
mix varchar(9) NOT NULL,
smallBlind int,
bigBlind int,
smallBet int NOT NULL,
@ -243,32 +253,34 @@ class Sql:
ENGINE=INNODB"""
elif db_server == 'postgresql':
self.query['createGametypesTable'] = """CREATE TABLE Gametypes (
id SERIAL, PRIMARY KEY (id),
siteId INTEGER, FOREIGN KEY (siteId) REFERENCES Sites(id),
currency varchar(4),
type char(4),
base char(4),
category varchar(9),
limitType char(2),
hiLo char(1),
id SERIAL NOT NULL, PRIMARY KEY (id),
siteId INTEGER NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id),
currency varchar(4) NOT NULL,
type char(4) NOT NULL,
base char(4) NOT NULL,
category varchar(9) NOT NULL,
limitType char(2) NOT NULL,
hiLo char(1) NOT NULL,
mix char(9) NOT NULL,
smallBlind int,
bigBlind int,
smallBet int,
bigBet int)"""
smallBet int NOT NULL,
bigBet int NOT NULL)"""
elif db_server == 'sqlite':
self.query['createGametypesTable'] = """CREATE TABLE Gametypes (
id INTEGER PRIMARY KEY,
siteId INTEGER,
currency TEXT,
type TEXT,
base TEXT,
category TEXT,
limitType TEXT,
hiLo TEXT,
id INTEGER PRIMARY KEY NOT NULL,
siteId INTEGER NOT NULL,
currency TEXT NOT NULL,
type TEXT NOT NULL,
base TEXT NOT NULL,
category TEXT NOT NULL,
limitType TEXT NOT NULL,
hiLo TEXT NOT NULL,
mix TEXT NOT NULL,
smallBlind INTEGER,
bigBlind INTEGER,
smallBet INTEGER,
bigBet INTEGER,
smallBet INTEGER NOT NULL,
bigBet INTEGER NOT NULL,
FOREIGN KEY(siteId) REFERENCES Sites(id) ON DELETE CASCADE)"""
@ -278,11 +290,11 @@ class Sql:
if db_server == 'mysql':
self.query['createPlayersTable'] = """CREATE TABLE Players (
id INT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
name VARCHAR(32) CHARACTER SET utf8 NOT NULL,
siteId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id),
comment text,
commentTs DATETIME)
id INT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
name VARCHAR(32) NOT NULL,
siteId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id),
comment text,
commentTs DATETIME)
ENGINE=INNODB"""
elif db_server == 'postgresql':
self.query['createPlayersTable'] = """CREATE TABLE Players (
@ -346,7 +358,9 @@ class Sql:
siteHandNo BIGINT NOT NULL,
tourneyId INT UNSIGNED,
gametypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id),
sessionId INT UNSIGNED,
sessionId INT UNSIGNED,
gameSessionId INT UNSIGNED,
fileId INT(10) UNSIGNED NOT NULL, FOREIGN KEY (fileId) REFERENCES Files(id),
startTime DATETIME NOT NULL,
importTime DATETIME NOT NULL,
seats TINYINT NOT NULL,
@ -358,6 +372,7 @@ class Sql:
boardcard4 smallint,
boardcard5 smallint,
texture smallint,
runIt BOOLEAN,
playersVpi SMALLINT NOT NULL, /* num of players vpi */
playersAtStreet1 SMALLINT NOT NULL, /* num of players seeing flop/street4 */
playersAtStreet2 SMALLINT NOT NULL,
@ -385,6 +400,8 @@ class Sql:
tourneyId INT,
gametypeId INT NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id),
sessionId INT,
gameSessionId INT,
fileId BIGINT NOT NULL, FOREIGN KEY (fileId) REFERENCES Files(id),
startTime timestamp without time zone NOT NULL,
importTime timestamp without time zone NOT NULL,
seats SMALLINT NOT NULL,
@ -396,6 +413,7 @@ class Sql:
boardcard4 smallint,
boardcard5 smallint,
texture smallint,
runIt BOOLEAN,
playersVpi SMALLINT NOT NULL, /* num of players vpi */
playersAtStreet1 SMALLINT NOT NULL, /* num of players seeing flop/street4 */
playersAtStreet2 SMALLINT NOT NULL,
@ -422,6 +440,8 @@ class Sql:
tourneyId INT,
gametypeId INT NOT NULL,
sessionId INT,
gameSessionId INT,
fileId INT NOT NULL,
startTime REAL NOT NULL,
importTime REAL NOT NULL,
seats INT NOT NULL,
@ -433,6 +453,7 @@ class Sql:
boardcard4 INT,
boardcard5 INT,
texture INT,
runIt BOOLEAN,
playersVpi INT NOT NULL, /* num of players vpi */
playersAtStreet1 INT NOT NULL, /* num of players seeing flop/street4 */
playersAtStreet2 INT NOT NULL,
@ -451,6 +472,42 @@ class Sql:
showdownPot INT, /* pot size at sd/street7 */
comment TEXT,
commentTs REAL)"""
################################
# Create Hands
################################
if db_server == 'mysql':
self.query['createBoardsTable'] = """CREATE TABLE Boards (
id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
handId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handId) REFERENCES Hands(id),
boardId smallint,
boardcard1 smallint, /* 0=none, 1-13=2-Ah 14-26=2-Ad 27-39=2-Ac 40-52=2-As */
boardcard2 smallint,
boardcard3 smallint,
boardcard4 smallint,
boardcard5 smallint)
ENGINE=INNODB"""
elif db_server == 'postgresql':
self.query['createBoardsTable'] = """CREATE TABLE Boards (
id BIGSERIAL, PRIMARY KEY (id),
handId BIGINT NOT NULL, FOREIGN KEY (handId) REFERENCES Hands(id),
boardId smallint,
boardcard1 smallint, /* 0=none, 1-13=2-Ah 14-26=2-Ad 27-39=2-Ac 40-52=2-As */
boardcard2 smallint,
boardcard3 smallint,
boardcard4 smallint,
boardcard5 smallint)"""
elif db_server == 'sqlite':
self.query['createBoardsTable'] = """CREATE TABLE Boards (
id INTEGER PRIMARY KEY,
handId INT NOT NULL,
boardId INT,
boardcard1 INT, /* 0=none, 1-13=2-Ah 14-26=2-Ad 27-39=2-Ac 40-52=2-As */
boardcard2 INT,
boardcard3 INT,
boardcard4 INT,
boardcard5 INT)"""
################################
@ -621,6 +678,19 @@ class Sql:
card5 smallint,
card6 smallint,
card7 smallint,
card8 smallint, /* cards 8-20 for draw hands */
card9 smallint,
card10 smallint,
card11 smallint,
card12 smallint,
card13 smallint,
card14 smallint,
card15 smallint,
card16 smallint,
card17 smallint,
card18 smallint,
card19 smallint,
card20 smallint,
startCards smallint,
ante INT,
@ -661,6 +731,7 @@ class Sql:
street3Seen BOOLEAN,
street4Seen BOOLEAN,
sawShowdown BOOLEAN,
showed BOOLEAN,
street1Aggr BOOLEAN,
street2Aggr BOOLEAN,
@ -748,6 +819,19 @@ class Sql:
card5 smallint,
card6 smallint,
card7 smallint,
card8 smallint, /* cards 8-20 for draw hands */
card9 smallint,
card10 smallint,
card11 smallint,
card12 smallint,
card13 smallint,
card14 smallint,
card15 smallint,
card16 smallint,
card17 smallint,
card18 smallint,
card19 smallint,
card20 smallint,
startCards smallint,
ante INT,
@ -788,6 +872,7 @@ class Sql:
street3Seen BOOLEAN,
street4Seen BOOLEAN,
sawShowdown BOOLEAN,
showed BOOLEAN,
street1Aggr BOOLEAN,
street2Aggr BOOLEAN,
@ -874,6 +959,19 @@ class Sql:
card5 INT,
card6 INT,
card7 INT,
card8 INT, /* cards 8-20 for draw hands */
card9 INT,
card10 INT,
card11 INT,
card12 INT,
card13 INT,
card14 INT,
card15 INT,
card16 INT,
card17 INT,
card18 INT,
card19 INT,
card20 INT,
startCards INT,
ante INT,
@ -914,6 +1012,7 @@ class Sql:
street3Seen INT,
street4Seen INT,
sawShowdown INT,
showed INT,
street1Aggr INT,
street2Aggr INT,
@ -1084,7 +1183,61 @@ class Sql:
cardsDiscarded TEXT,
allIn BOOLEAN
)"""
################################
# Create Files
################################
if db_server == 'mysql':
self.query['createFilesTable'] = """CREATE TABLE Files (
id INT(10) UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
file text NOT NULL,
site VARCHAR(32),
type VARCHAR(7),
startTime DATETIME NOT NULL,
lastUpdate DATETIME NOT NULL,
endTime DATETIME,
hands INT,
stored INT,
dups INT,
partial INT,
errs INT,
ttime100 INT,
finished BOOLEAN)
ENGINE=INNODB"""
elif db_server == 'postgresql':
self.query['createFilesTable'] = """CREATE TABLE Files (
id BIGSERIAL, PRIMARY KEY (id),
file TEXT NOT NULL,
site VARCHAR(32),
type VARCHAR(7),
startTime timestamp without time zone NOT NULL,
lastUpdate timestamp without time zone NOT NULL,
endTime timestamp without time zone,
hands INT,
stored INT,
dups INT,
partial INT,
errs INT,
ttime100 INT,
finished BOOLEAN)"""
elif db_server == 'sqlite':
self.query['createFilesTable'] = """CREATE TABLE Files (
id INTEGER PRIMARY KEY,
file TEXT NOT NULL,
site VARCHAR(32),
type VARCHAR(7),
startTime timestamp NOT NULL,
lastUpdate timestamp NOT NULL,
endTime timestamp,
hands INT,
stored INT,
dups INT,
partial INT,
errs INT,
ttime100 INT,
finished BOOLEAN
)"""
################################
# Create HudCache
@ -1430,32 +1583,61 @@ class Sql:
id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
sessionStart DATETIME NOT NULL,
sessionEnd DATETIME NOT NULL,
ringHDs INT NOT NULL,
tourHDs INT NOT NULL,
ringProfitUSD INT NOT NULL,
ringProfitEUR INT NOT NULL)
ENGINE=INNODB"""
gameStart DATETIME NOT NULL,
gameEnd DATETIME NOT NULL,
sessionId BIGINT,
date CHAR(7) NOT NULL, /* 1st char is style (A/T/H/S), other 6 are the key */
type char(7) NOT NULL,
gametypeId SMALLINT UNSIGNED, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id),
tourneyTypeId SMALLINT UNSIGNED, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
playerId INT UNSIGNED NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id),
hands INT NOT NULL,
tourneys INT NOT NULL,
totalProfit INT)
ENGINE=INNODB
"""
elif db_server == 'postgresql':
self.query['createSessionsCacheTable'] = """CREATE TABLE SessionsCache (
id BIGSERIAL, PRIMARY KEY (id),
sessionStart REAL NOT NULL,
sessionEnd REAL NOT NULL,
ringHDs INT NOT NULL,
tourHDs INT NOT NULL,
ringProfitUSD INT NOT NULL,
ringProfitEUR INT NOT NULL)
sessionStart timestamp without time zone NOT NULL,
sessionEnd timestamp without time zone NOT NULL,
gameStart timestamp without time zone NOT NULL,
gameEnd timestamp without time zone NOT NULL,
sessionId INT,
date CHAR(7) NOT NULL, /* 1st char is style (A/T/H/S), other 6 are the key */
type char(7),
gametypeId INT, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id),
tourneyTypeId INT, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id),
hands INT,
tourneys INT,
totalProfit INT)
"""
elif db_server == 'sqlite':
self.query['createSessionsCacheTable'] = """CREATE TABLE SessionsCache (
id INTEGER PRIMARY KEY,
sessionStart REAL NOT NULL,
sessionEnd REAL NOT NULL,
ringHDs INT NOT NULL,
tourHDs INT NOT NULL,
ringProfitUSD INT NOT NULL,
ringProfitEUR INT NOT NULL)
sessionStart timestamp NOT NULL,
sessionEnd timestamp NOT NULL,
gameStart timestamp NOT NULL,
gameEnd timestamp NOT NULL,
sessionId INT,
date TEXT NOT NULL, /* 1st char is style (A/T/H/S), other 6 are the key */
type TEXT,
gametypeId INT,
tourneyTypeId INT,
playerId INT,
hands INT,
tourneys INT,
totalProfit INT)
"""
self.query['addSessionIdIndex'] = """CREATE INDEX index_SessionId ON SessionsCache (sessionId)"""
self.query['addHandsSessionIdIndex'] = """CREATE INDEX index_handsSessionId ON Hands (sessionId)"""
self.query['addHandsGameSessionIdIndex'] = """CREATE INDEX index_handsGameSessionId ON Hands (gameSessionId)"""
if db_server == 'mysql':
self.query['addTourneyIndex'] = """ALTER TABLE Tourneys ADD UNIQUE INDEX siteTourneyNo(siteTourneyNo, tourneyTypeId)"""
@ -1479,7 +1661,7 @@ class Sql:
self.query['addPlayersIndex'] = """CREATE UNIQUE INDEX name ON Players (name, siteId)"""
if db_server == 'mysql':
self.query['addTPlayersIndex'] = """ALTER TABLE TourneysPlayers ADD UNIQUE INDEX tourneyId(tourneyId, playerId)"""
self.query['addTPlayersIndex'] = """ALTER TABLE TourneysPlayers ADD UNIQUE INDEX _tourneyId(tourneyId, playerId)"""
elif db_server == 'postgresql':
self.query['addTPlayersIndex'] = """CREATE UNIQUE INDEX tourneyId ON TourneysPlayers (tourneyId, playerId)"""
elif db_server == 'sqlite':
@ -3401,7 +3583,7 @@ class Sql:
<limit_test>
<game_test>
AND hp.tourneysPlayersId IS NULL
GROUP BY h.startTime, hp.handId, hp.sawShowdown, ( hp.totalProfit / ( gt.bigBlind * 2 ) ) * 100
GROUP BY h.startTime, hp.handId, hp.sawShowdown, hp.totalProfit
ORDER BY h.startTime"""
self.query['getRingProfitAllHandsPlayerIdSiteInDollars'] = """
@ -4142,7 +4324,7 @@ class Sql:
"""
self.query['insert_hudcache'] = """
INSERT INTO HudCache (
insert into HudCache (
gametypeId,
playerId,
activeSeats,
@ -4237,7 +4419,7 @@ class Sql:
street2Raises,
street3Raises,
street4Raises)
VALUES (%s, %s, %s, %s, %s,
values (%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s,
@ -4363,96 +4545,136 @@ class Sql:
####################################
# Queries to rebuild/modify sessionscache
####################################
self.query['select_sessionscache'] = """
SELECT id,
sessionStart,
sessionEnd,
ringHDs,
tourHDs,
ringProfitUSD,
ringProfitEUR
FROM SessionsCache
WHERE sessionEnd>=%s
AND sessionStart<=%s"""
self.query['select_sessionscache_mid'] = """
SELECT sessionStart,
sessionEnd,
ringHDs,
tourHDs,
ringProfitUSD,
ringProfitEUR
FROM SessionsCache
WHERE sessionEnd>=%s
AND sessionStart<=%s"""
self.query['clearSessionsCache'] = """DELETE FROM SessionsCache"""
self.query['select_sessionscache_start'] = """
SELECT sessionStart,
sessionEnd,
ringHDs,
tourHDs,
ringProfitUSD,
ringProfitEUR
FROM SessionsCache
WHERE sessionStart>%s
AND sessionEnd>=%s
AND sessionStart<=%s"""
self.query['update_sessionscache_mid'] = """
UPDATE SessionsCache SET
ringHDs=ringHDs+%s,
tourHDs=tourHDs+%s,
ringProfitUSD=ringProfitUSD+%s,
ringProfitEUR=ringProfitEUR+%s
WHERE sessionStart<=%s
AND sessionEnd>=%s"""
self.query['update_sessionscache_start'] = """
UPDATE SessionsCache SET
sessionStart=%s,
ringHDs=ringHDs+%s,
tourHDs=tourHDs+%s,
ringProfitUSD=ringProfitUSD+%s,
ringProfitEUR=ringProfitEUR+%s
WHERE sessionStart>%s
AND sessionEnd>=%s
AND sessionStart<=%s"""
self.query['update_sessionscache_end'] = """
UPDATE SessionsCache SET
sessionEnd=%s,
ringHDs=ringHDs+%s,
tourHDs=tourHDs+%s,
ringProfitUSD=ringProfitUSD+%s,
ringProfitEUR=ringProfitEUR+%s
WHERE sessionEnd<%s
AND sessionEnd>=%s
AND sessionStart<=%s"""
self.query['insert_sessionscache'] = """
INSERT INTO SessionsCache (
sessionStart,
sessionEnd,
ringHDs,
tourHDs,
ringProfitUSD,
ringProfitEUR)
VALUES (%s, %s, %s, %s, %s, %s)"""
self.query['merge_sessionscache'] = """
SELECT min(sessionStart), max(sessionEnd), sum(ringHDs), sum(tourHDs), sum(ringProfitUSD), sum(ringProfitEUR)
FROM SessionsCache
WHERE (case when id=%s or id=%s then 1 else 0 end)=1"""
self.query['delete_sessions'] = """
DELETE FROM SessionsCache
WHERE id=%s"""
self.query['update_hands_sessionid'] = """
UPDATE Hands SET
sessionId=%s
WHERE (case when sessionId=%s or sessionId=%s then 1 else 0 end)=1"""
self.query['rebuildSessionsCache'] = """
SELECT Hands.id as id,
Hands.startTime as startTime,
HandsPlayers.playerId as playerId,
Hands.gametypeId as gametypeId,
Gametypes.type as game,
HandsPlayers.totalProfit as totalProfit,
Tourneys.tourneyTypeId as tourneyTypeId
FROM Gametypes, HandsPlayers, Hands
LEFT JOIN Tourneys ON Hands.tourneyId = Tourneys.tourneyTypeId
WHERE HandsPlayers.handId = Hands.id
AND Hands.gametypeId = Gametypes.id
AND (case when HandsPlayers.playerId = <where_clause> then 1 else 0 end) = 1
ORDER BY Hands.startTime ASC"""
self.query['rebuildSessionsCacheSum'] = """
SELECT Tourneys.id as id,
Tourneys.startTime as startTime,
TourneysPlayers.playerId,
TourneyTypes.id as tourneyTypeId,
TourneysPlayers.winnings as winnings,
TourneysPlayers.winningsCurrency as winningsCurrency,
TourneyTypes.currency as buyinCurrency,
TourneyTypes.buyIn as buyIn,
TourneyTypes.fee as fee,
case when TourneyTypes.rebuy then TourneyTypes.rebuyCost else 0 end as rebuyCost,
case when TourneyTypes.rebuy then TourneyTypes.rebuyFee else 0 end as rebuyFee,
case when TourneyTypes.addOn then TourneyTypes.addOnCost else 0 end as addOnCost,
case when TourneyTypes.addOn then TourneyTypes.addOnFee else 0 end as addOnFee,
case when TourneyTypes.knockout then TourneyTypes.koBounty else 0 end as koBounty
FROM Tourneys, TourneyTypes, TourneysPlayers
WHERE Tourneys.tourneyTypeId = TourneyTypes.id
AND Tourneys.id = TourneysPlayers.tourneyId
AND (case when TourneysPlayers.playerId = <where_clause> then 1 else 0 end) = 1
ORDER BY Tourneys.startTime ASC"""
self.query['select_prepSC'] = """
SELECT sessionId as id,
sessionStart,
sessionEnd,
count(sessionId) as count
FROM SessionsCache
WHERE sessionEnd>=%s
AND sessionStart<=%s
GROUP BY sessionId, sessionStart, sessionEnd"""
self.query['update_prepSC'] = """
UPDATE SessionsCache SET
sessionStart=%s,
sessionEnd=%s
WHERE sessionId=%s"""
self.query['update_SC'] = """
UPDATE SessionsCache SET
sessionStart=%s,
sessionEnd=%s,
gameStart=%s,
gameEnd=%s,
hands=hands+%s,
tourneys=tourneys+%s,
totalProfit=totalProfit+%s
WHERE id=%s"""
self.query['select_SC'] = """
SELECT id,
sessionStart,
sessionEnd,
gameStart,
gameEnd,
sessionId,
date,
type,
gametypeId,
tourneyTypeId,
playerId,
hands,
tourneys,
totalProfit
FROM SessionsCache
WHERE gameEnd>=%s
AND gameStart<=%s
AND date=%s
AND type=%s
AND (case when gametypeId is NULL then 1 else
(case when gametypeId=%s then 1 else 0 end) end)=1
AND (case when tourneyTypeId is NULL then 1 else
(case when tourneyTypeId=%s then 1 else 0 end) end)=1
AND playerId=%s"""
self.query['insert_SC'] = """
insert into SessionsCache (
sessionStart,
sessionEnd,
gameStart,
gameEnd,
sessionId,
date,
type,
gametypeId,
tourneyTypeId,
playerId,
hands,
tourneys,
totalProfit)
values (%s, %s, %s, %s, %s, %s, %s,
%s, %s, %s, %s, %s, %s)"""
self.query['update_Hands_gsid'] = """
UPDATE Hands SET
gameSessionId=%s
WHERE gameSessionId=%s"""
self.query['update_Hands_sid'] = """
UPDATE Hands SET
sessionId=%s
WHERE sessionId=%s"""
self.query['update_SC_sid'] = """
UPDATE SessionsCache SET
sessionStart=%s,
sessionEnd=%s,
sessionId=%s
WHERE sessionId=%s"""
self.query['delete_SC'] = """
DELETE FROM SessionsCache
WHERE id=%s"""
####################################
# Database management queries
@ -4467,6 +4689,25 @@ class Sql:
self.query['analyze'] = "analyze"
elif db_server == 'sqlite':
self.query['analyze'] = "analyze"
if db_server == 'mysql':
self.query['selectLock'] = """
SELECT locked
FROM InsertLock
WHERE locked=True
LOCK IN SHARE MODE"""
if db_server == 'mysql':
self.query['switchLock'] = """
UPDATE InsertLock SET
locked=%s
WHERE id=%s"""
if db_server == 'mysql':
self.query['missedLock'] = """
UPDATE InsertLock SET
missed=missed+%s
WHERE id=%s"""
if db_server == 'mysql':
self.query['lockForInsert'] = """
@ -4506,14 +4747,15 @@ class Sql:
AND category=%s
AND limitType=%s
AND currency=%s
AND mix=%s
AND smallBlind=%s
AND bigBlind=%s
"""
self.query['insertGameTypes'] = """INSERT INTO Gametypes
(siteId, currency, type, base, category, limitType
,hiLo, smallBlind, bigBlind, smallBet, bigBet)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"""
,hiLo, mix, smallBlind, bigBlind, smallBet, bigBet)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"""
self.query['isAlreadyInDB'] = """SELECT id FROM Hands
WHERE gametypeId=%s AND siteHandNo=%s
@ -4652,6 +4894,8 @@ class Sql:
tourneyId,
gametypeid,
sessionId,
gameSessionId,
fileId,
startTime,
importtime,
seats,
@ -4663,6 +4907,7 @@ class Sql:
boardcard3,
boardcard4,
boardcard5,
runIt,
playersAtStreet1,
playersAtStreet2,
playersAtStreet3,
@ -4682,7 +4927,8 @@ class Sql:
values
(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
%s, %s, %s, %s, %s, %s, %s, %s, %s)"""
%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
%s)"""
self.query['store_hands_players'] = """insert into HandsPlayers (
@ -4698,6 +4944,19 @@ class Sql:
card5,
card6,
card7,
card8,
card9,
card10,
card11,
card12,
card13,
card14,
card15,
card16,
card17,
card18,
card19,
card20,
winnings,
rake,
totalProfit,
@ -4707,6 +4966,7 @@ class Sql:
street3Seen,
street4Seen,
sawShowdown,
showed,
wonAtSD,
street0Aggr,
street1Aggr,
@ -4812,7 +5072,10 @@ class Sql:
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s,
%s, %s, %s, %s
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s,
%s, %s, %s
)"""
self.query['store_hands_actions'] = """insert into HandsActions (
@ -4834,6 +5097,56 @@ class Sql:
%s, %s, %s, %s, %s,
%s, %s
)"""
self.query['store_boards'] = """insert into Boards (
handId,
boardId,
boardcard1,
boardcard2,
boardcard3,
boardcard4,
boardcard5
)
values (
%s, %s, %s, %s, %s,
%s, %s
)"""
################################
# queries for Files Table
################################
self.query['store_file'] = """ insert into Files (
file,
site,
startTime,
lastUpdate,
hands,
stored,
dups,
partial,
errs,
ttime100,
finished)
values (
%s, %s, %s, %s, %s,
%s, %s, %s, %s, %s,
%s
)"""
self.query['update_file'] = """
UPDATE Files SET
type=%s,
lastUpdate=%s,
endTime=%s,
hands=hands+%s,
stored=stored+%s,
dups=dups+%s,
partial=partial+%s,
errs=errs+%s,
ttime100=ttime100+%s,
finished=%s
WHERE id=%s"""
################################
# Counts for DB stats window

4
pyfpdb/SitenameSummary.py

@ -78,8 +78,8 @@ class Sitename(TourneySummary):
m = self.re_TourneyInfo.search(self.summaryText)
if m == None:
tmp = self.summaryText[0:200]
log.error(_("parseSummary: Unable to recognise Tourney Info: '%s'") % tmp)
log.error(_("parseSummary: Raising FpdbParseError"))
log.error("parseSummary: " + _("Unable to recognise Tourney Info: '%s'") % tmp)
log.error("parseSummary: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise Tourney Info: '%s'") % tmp)
print "DEBUG: m.groupdict(): %s" % m.groupdict()

32
pyfpdb/TestHandsPlayers.py

@ -21,8 +21,6 @@
import sys
import os
import codecs
import pprint
import PokerStarsToFpdb
from Hand import *
import Configuration
import Database
@ -31,6 +29,10 @@ import fpdb_import
import Options
import datetime
import pytz
import pprint
pp = pprint.PrettyPrinter(indent=4)
DEBUG = False
class FpdbError:
@ -125,7 +127,7 @@ def compare_handsplayers_file(filename, importer, errors):
# The stats match - continue
pass
else:
if stat == 'tourneyTypeId' or stat == 'tourneysPlayersIds':
if stat == 'tourneyTypeId' or stat == 'tourneysPlayersIds' or stat == 'showed':
# Not and error
pass
else:
@ -147,6 +149,11 @@ def compare_hands_file(filename, importer, errors):
for hand in handlist:
ghash = hand.stats.getHands()
# Delete unused data from hash
del ghash['gsc']
del ghash['sc']
del ghash['id']
del ghash['board']
for datum in ghash:
#print "DEBUG: hand: '%s'" % datum
try:
@ -155,7 +162,12 @@ def compare_hands_file(filename, importer, errors):
pass
else:
# Stats don't match.
if datum == "gametypeId" or datum == 'sessionId' or datum == 'tourneyId':
if (datum == "gametypeId"
or datum == 'sessionId'
or datum == 'tourneyId'
or datum == 'gameSessionId'
or datum == 'fileId'
or datum == 'runIt'):
# Not an error. gametypeIds are dependent on the order added to the db.
#print "DEBUG: Skipping mismatched gamtypeId"
pass
@ -172,8 +184,8 @@ def compare(leaf, importer, errors, site):
# Test if this is a hand history file
if filename.endswith('.txt'):
# test if there is a .hp version of the file
print "Site: %s" % site
print "Filename: %s" % filename
if DEBUG: print "Site: %s" % site
if DEBUG: print "Filename: %s" % filename
importer.addBulkImportImportFileOrDir(filename, site=site)
(stored, dups, partial, errs, ttime) = importer.runImport()
@ -332,6 +344,7 @@ def main(argv=None):
walk_testfiles(options.filename, compare, importer, BetfairErrors, "Betfair")
if sites['OnGame'] == True and not single_file_test:
walk_testfiles("regression-test-files/cash/OnGame/", compare, importer, OnGameErrors, "OnGame")
walk_testfiles("regression-test-files/tour/ongame/", compare, importer, OnGameErrors, "OnGame")
elif sites['OnGame'] == True and single_file_test:
walk_testfiles(options.filename, compare, importer, OnGameErrors, "OnGame")
if sites['Absolute'] == True and not single_file_test:
@ -345,6 +358,7 @@ def main(argv=None):
walk_testfiles(options.filename, compare, importer, UltimateBetErrors, "Absolute")
if sites['Everleaf'] == True and not single_file_test:
walk_testfiles("regression-test-files/cash/Everleaf/", compare, importer, EverleafErrors, "Everleaf")
walk_testfiles("regression-test-files/tour/Everleaf/", compare, importer, EverleafErrors, "Everleaf")
elif sites['Everleaf'] == True and single_file_test:
walk_testfiles(options.filename, compare, importer, EverleafErrors, "Everleaf")
if sites['Carbon'] == True and not single_file_test:
@ -372,9 +386,6 @@ def main(argv=None):
for i, site in enumerate(ErrorsList):
totalerrors += ErrorsList[i].errorcount
print "---------------------"
print "Total Errors: %d" % totalerrors
print "---------------------"
for i, site in enumerate(ErrorsList):
ErrorsList[i].print_histogram()
@ -399,6 +410,9 @@ def main(argv=None):
for num, stat in sortedstats:
print "(%3d) : %s" %(num, stat)
print "---------------------"
print "Total Errors: %d" % totalerrors
print "---------------------"
if __name__ == '__main__':
sys.exit(main())

18
pyfpdb/TourneySummary.py

@ -287,6 +287,24 @@ winnings (int) the money the player ended the tourney with (can be 0, or -1 i
if player not in [p[1] for p in self.players]:
print "checkPlayerExists", player, "fail"
raise FpdbParseError
def updateSessionsCache(self, sc, gsc, tz, doinsert):
self.heros = self.db.getHeroIds(self.dbid_pids, self.siteName)
sc = self.db.prepSessionsCache(self.tourNo, self.dbid_pids, self.startTime, sc , self.heros, doinsert)
gsc = self.db.storeSessionsCache(self.tourNo, self.dbid_pids, self.startTime, {'type': 'summary'}
,None, self.assembleInfo(), sc, gsc, tz, self.heros, doinsert)
return sc, gsc
def assembleInfo(self):
info = {}
info['tourneyTypeId'] = self.tourneyTypeId
info['winnings'] = self.winnings
info['winningsCurrency'] = self.winningsCurrency
info['buyinCurrency'] = self.buyinCurrency
info['buyin'] = self.buyin
info['fee'] = self.fee
return info
def writeSummary(self, fh=sys.__stdout__):
print >>fh, "Override me"

19
pyfpdb/Win2dayToFpdb.py

@ -35,10 +35,16 @@ class Win2day(HandHistoryConverter):
siteID = 4
# Static regexes
#<HISTORY ID="102271403" SESSION="session31237702.xml" TABLE="Innsbruck 3" GAME="GAME_THM" GAMETYPE="GAMETYPE_REAL" GAMEKIND="GAMEKIND_CASH" TABLECURRENCY="EUR" LIMIT="NL" STAKES="0.25/0.50" DATE="1246909773" WIN="0.00" LOSS="0.50">
#'^<HISTORY ID="(?P<HID>[0-9]+)" SESSION="session[0-9]+\.xml" TABLE="(?P<TABLE>[- a-zA-Z0-9]+)" GAME="(?P<GAME>[_A-Z]+)" GAMETYPE="[_a-zA-Z]+" GAMEKIND="[_a-zA-Z]+" TABLECURRENCY="(?P<CURRENCY>[A-Z]+)" LIMIT="(?P<LIMIT>NL|PL)" STAKES="(?P<SB>[.0-9]+)/(?P<BB>[.0-9]+)" DATE="(?P<DATETIME>[0-9]+)" WIN="[.0-9]+" LOSS="[.0-9]+">$'
re_GameInfo = re.compile('<HISTORY ID="(?P<HID>[0-9]+)" SESSION="session[0-9]+\.xml" TABLE="(?P<TABLE>[- a-zA-Z0-9\xc0-\xfc/.]+)" GAME="(?P<GAME>[_A-Z]+)" GAMETYPE="[_a-zA-Z]+" GAMEKIND="[_a-zA-Z]+" TABLECURRENCY="(?P<CURRENCY>[A-Z]+)" LIMIT="(?P<LIMIT>NL|PL)" STAKES="(?P<SB>[.0-9]+)/(?P<BB>[.0-9]+)" DATE="(?P<DATETIME>[0-9]+)" WIN="[.0-9]+" LOSS="[.0-9]+">', re.MULTILINE)
re_GameInfo = re.compile("""<HISTORY\sID="(?P<HID>[0-9]+)"\sSESSION="session[0-9]+\.xml"\s
TABLE="(?P<TABLE>[-\sa-zA-Z0-9\xc0-\xfc/.]+)"\s
GAME="(?P<GAME>[_A-Z]+)"\sGAMETYPE="[_a-zA-Z]+"\sGAMEKIND="[_a-zA-Z]+"\s
TABLECURRENCY="(?P<CURRENCY>[A-Z]+)"\s
LIMIT="(?P<LIMIT>NL|PL)"\s
STAKES="(?P<SB>[.0-9]+)/(?P<BB>[.0-9]+)"\s
DATE="(?P<DATETIME>[0-9]+)"\s
(TABLETOURNEYID=""\s)?
WIN="[.0-9]+"\sLOSS="[.0-9]+"
""", re.MULTILINE| re.VERBOSE)
re_SplitHands = re.compile('</HISTORY>')
re_HandInfo = re.compile("^Table \'(?P<TABLE>[- a-zA-Z]+)\'(?P<TABLEATTRIBUTES>.+?$)?", re.MULTILINE)
re_Button = re.compile('<ACTION TYPE="HAND_DEAL" PLAYER="(?P<BUTTON>[^"]+)">\n<CARD LINK="[0-9b]+"></CARD>\n<CARD LINK="[0-9b]+"></CARD></ACTION>\n<ACTION TYPE="ACTION_', re.MULTILINE)
@ -93,10 +99,11 @@ class Win2day(HandHistoryConverter):
if not m:
tmp = handText[0:1000]
log.error(_("Unable to recognise gametype from: '%s'") % tmp)
log.error(_("determineGameType: Raising FpdbParseError"))
log.error("determineGameType: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
mg = m.groupdict()
#print "DEBUG: mg: %s" % mg
# translations from captured groups to our info strings
#limits = { 'NL':'nl', 'PL':'pl', 'Limit':'fl' }
@ -338,7 +345,7 @@ class Win2day(HandHistoryConverter):
elif action.group('ATYPE') == 'ACTION_STAND':
hand.addStandsPat( street, action.group('PNAME'))
else:
print (_("DEBUG: ") + _("unimplemented readAction: '%s' '%s'") % (action.group('PNAME'), action.group('ATYPE')))
print (_("DEBUG: ") + _("Unimplemented readAction: '%s' '%s'") % (action.group('PNAME'), action.group('ATYPE')))
def readShowdownActions(self, hand):

4
pyfpdb/WinamaxSummary.py

@ -44,8 +44,8 @@ class WinamaxSummary(TourneySummary):
}
substitutions = {
'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
'LS' : u"\$|\xe2\x82\xac|\u20AC|" # legal currency symbols
'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
'LS' : u"\$|\xe2\x82\xac|\u20ac|" # legal currency symbols
}
re_GameType = re.compile("""<h1>((?P<LIMIT>No Limit|Pot Limit) (?P<GAME>Hold\'em))</h1>""")

16
pyfpdb/WinamaxToFpdb.py

@ -52,10 +52,10 @@ class Winamax(HandHistoryConverter):
siteId = 14 # Needs to match id entry in Sites database
mixes = { } # Legal mixed games
sym = {'USD': "\$", 'CAD': "\$", 'T$': "", "EUR": "\xe2\x82\xac", "GBP": "\xa3"} # ADD Euro, Sterling, etc HERE
sym = {'USD': "\$", 'CAD': "\$", 'T$': "", "EUR": u"\xe2\x82\xac|\u20ac", "GBP": "\xa3"} # ADD Euro, Sterling, etc HERE
substitutions = {
'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
'LS' : "\$|\xe2\x82\xac|" # legal currency symbols - Euro(cp1252, utf-8)
'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
'LS' : u"\$|\xe2\x82\xac|\u20ac|" # legal currency symbols - Euro(cp1252, utf-8)
}
limits = { 'no limit':'nl', 'pot limit' : 'pl','LIMIT':'fl'}
@ -170,7 +170,7 @@ class Winamax(HandHistoryConverter):
if not m:
tmp = handText[0:100]
log.error(_("Unable to recognise gametype from: '%s'") % tmp)
log.error(_("determineGameType: Raising FpdbParseError"))
log.error("determineGameType: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
mg = m.groupdict()
@ -188,7 +188,7 @@ class Winamax(HandHistoryConverter):
else:
tmp = handText[0:100]
log.error(_("limit not found in self.limits(%s). hand: '%s'") % (str(mg),tmp))
log.error(_("determineGameType: Raising FpdbParseError"))
log.error("determineGameType: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("limit not found in self.limits(%s). hand: '%s'") % (str(mg),tmp))
if 'GAME' in mg:
(info['base'], info['category']) = self.games[mg['GAME']]
@ -260,7 +260,7 @@ class Winamax(HandHistoryConverter):
hand.buyinCurrency="PSFP"
else:
#FIXME: handle other currencies (are there other currencies?)
raise FpdbParseError(_("Failed to detect currency. Hand ID: %s: '%s'") % (hand.handid, info[key]))
raise FpdbParseError(_("Failed to detect currency.") + " " + _("Hand ID: %s: '%s'") % (hand.handid, info[key]))
info['BIAMT'] = info['BIAMT'].strip(u'$€FPP')
@ -403,13 +403,13 @@ class Winamax(HandHistoryConverter):
elif action.group('ATYPE') == ' stands pat':
hand.addStandsPat( street, action.group('PNAME'))
else:
log.fatal(_("DEBUG: ") + _("unimplemented readAction: '%s' '%s'") % (action.group('PNAME'),action.group('ATYPE')))
log.fatal(_("DEBUG: ") + _("Unimplemented readAction: '%s' '%s'") % (action.group('PNAME'), action.group('ATYPE')))
# print "Processed %s"%acts
# print "committed=",hand.pot.committed
def readShowdownActions(self, hand):
for shows in self.re_ShowdownAction.finditer(hand.handText):
log.debug(_("add show actions %s") % shows)
#log.debug(_("add show actions %s") % shows)
cards = shows.group('CARDS')
cards = cards.split(' ')
# print "DEBUG: addShownCards(%s, %s)" %(cards, shows.group('PNAME'))

18
pyfpdb/fpdb.pyw

@ -265,11 +265,16 @@ class fpdb:
dia.set_authors(['Steffen', 'Eratosthenes', 'Carl Gherardi',
'Eric Blade', '_mt', 'sqlcoder', 'Bostik', _('and others')])
dia.set_program_name("Free Poker Database (FPDB)")
db_version = ""
#if self.db is not None:
# db_version = self.db.get_version()
nums = [(_('Operating System'), os.name),
if (os.name=="posix"):
os_text=str(os.uname())
elif (os.name=="nt"):
import platform
os_text=("Windows" + " " + str(platform.win32_ver()))
else:
os_text="Unknown"
nums = [(_('Operating System'), os_text),
('Python', sys.version[0:3]),
('GTK+', '.'.join([str(x) for x in gtk.gtk_version])),
('PyGTK', '.'.join([str(x) for x in gtk.pygtk_version])),
@ -281,7 +286,7 @@ class fpdb:
]
versions = gtk.TextBuffer()
w = 20 # width used for module names and version numbers
versions.set_text('\n'.join([x[0].rjust(w) + ' ' + x[1].ljust(w) for x in nums]))
versions.set_text('\n'.join([x[0].rjust(w) + ': ' + x[1].ljust(w) for x in nums]))
view = gtk.TextView(versions)
view.set_editable(False)
view.set_justification(gtk.JUSTIFY_CENTER)
@ -1221,7 +1226,6 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an
self.window.set_icon_from_file('/usr/share/pixmaps/fpdb-cards.png')
else:
self.statusIcon.set_from_stock(gtk.STOCK_HOME)
self.window.set_icon_stock(gtk.STOCK_HOME)
self.statusIcon.set_tooltip("Free Poker Database")
self.statusIcon.connect('activate', self.statusicon_activate)
self.statusMenu = gtk.Menu()

139
pyfpdb/fpdb_import.py

@ -165,15 +165,28 @@ class Importer:
self.database.disconnect()
for i in xrange(len(self.writerdbs)):
self.writerdbs[i].disconnect()
def logImport(self, type, file, stored, dups, partial, errs, ttime, id):
hands = stored + dups + partial + errs
now = datetime.datetime.utcnow()
ttime100 = ttime * 100
self.database.updateFile([type, now, now, hands, stored, dups, partial, errs, ttime100, True, id])
def addFileToList(self, file, site, filter):
now = datetime.datetime.utcnow()
file = os.path.splitext(os.path.basename(file))[0]
id = self.database.storeFile([file, site, now, now, 0, 0, 0, 0, 0, 0, False])
self.database.commit()
return [site] + [filter] + [id]
#Add an individual file to filelist
def addImportFile(self, filename, site = "default", filter = "passthrough"):
#TODO: test it is a valid file -> put that in config!!
#print "addimportfile: filename is a", filename.__class__
# filename now comes in as unicode
# filename not guaranteed to be unicode
if filename in self.filelist or not os.path.exists(filename):
return
self.filelist[filename] = [site] + [filter]
self.filelist[filename] = self.addFileToList(filename, site, filter)
if site not in self.siteIds:
# Get id from Sites table in DB
result = self.database.get_site_id(site)
@ -196,11 +209,10 @@ class Importer:
if os.path.isdir(inputPath):
for subdir in os.walk(inputPath):
for file in subdir[2]:
self.addImportFile(unicode(os.path.join(subdir[0], file),'utf-8'),
site=site, filter=filter)
self.addImportFile(os.path.join(subdir[0], file), site=site, filter=filter)
else:
self.addImportFile(unicode(inputPath,'utf-8'), site=site, filter=filter)
self.addImportFile(inputPath, site=site, filter=filter)
#Add a directory of files to filelist
#Only one import directory per site supported.
#dirlist is a hash of lists:
@ -242,7 +254,7 @@ class Importer:
#print "dropInd =", self.settings['dropIndexes'], " dropHudCache =", self.settings['dropHudCache']
if self.settings['threads'] <= 0:
(totstored, totdups, totpartial, toterrors) = self.importFiles(self.database, None)
(totstored, totdups, totpartial, toterrors) = self.importFiles(None)
else:
# create queue (will probably change to deque at some point):
self.writeq = Queue.Queue( self.settings['writeQSize'] )
@ -254,7 +266,7 @@ class Importer:
t.setDaemon(True)
t.start()
# read hands and write to q:
(totstored, totdups, totpartial, toterrors) = self.importFiles(self.database, self.writeq)
(totstored, totdups, totpartial, toterrors) = self.importFiles(self.writeq)
if self.writeq.empty():
print _("writers finished already")
@ -286,7 +298,7 @@ class Importer:
return (totstored, totdups, totpartial, toterrors, endtime-starttime)
# end def runImport
def importFiles(self, db, q):
def importFiles(self, q):
""""Read filenames in self.filelist and pass to import_file_dict().
Uses a separate database connection if created as a thread (caller
passes None or no param as db)."""
@ -304,13 +316,15 @@ class Importer:
ProgressDialog.progress_update(file)
(stored, duplicates, partial, errors, ttime) = self.import_file_dict(db, file
,self.filelist[file][0], self.filelist[file][1], q)
(stored, duplicates, partial, errors, ttime) = self.import_file_dict(file, self.filelist[file][0]
,self.filelist[file][1], self.filelist[file][2], q)
totstored += stored
totdups += duplicates
totpartial += partial
toterrors += errors
self.logImport('bulk', file, stored, duplicates, partial, errors, ttime, self.filelist[file][2])
self.database.commit()
del ProgressDialog
for i in xrange( self.settings['threads'] ):
@ -395,7 +409,9 @@ class Importer:
self.caller.addText("\n"+os.path.basename(file))
except KeyError: # TODO: What error happens here?
pass
(stored, duplicates, partial, errors, ttime) = self.import_file_dict(self.database, file, self.filelist[file][0], self.filelist[file][1], None)
(stored, duplicates, partial, errors, ttime) = self.import_file_dict(file, self.filelist[file][0]
,self.filelist[file][1], self.filelist[file][2], None)
self.logImport('auto', file, stored, duplicates, partial, errors, ttime, self.filelist[file][2])
try:
if not os.path.isdir(file): # Note: This assumes that whatever calls us has an "addText" func
self.caller.addText(" %d stored, %d duplicates, %d partial, %d errors (time = %f)" % (stored, duplicates, partial, errors, ttime))
@ -426,75 +442,78 @@ class Importer:
#rulog.close()
# This is now an internal function that should not be called directly.
def import_file_dict(self, db, file, site, filter, q=None):
#print "import_file_dict"
def import_file_dict(self, file, site, filter, fileId, q=None):
if os.path.isdir(file):
self.addToDirList[file] = [site] + [filter]
return (0,0,0,0,0)
conv = None
(stored, duplicates, partial, errors, ttime) = (0, 0, 0, 0, time())
# sc: is there any need to decode this? maybe easier to skip it than guess at the encoding?
#file = file.decode("utf-8") #(Configuration.LOCALE_ENCODING)
# Load filter, process file, pass returned filename to import_fpdb_file
if self.settings['threads'] > 0 and self.writeq is not None:
log.info((_("Converting %s") % file) + " (" + str(q.qsize()) + ")")
else:
log.info(_("Converting %s") % file)
log.info((_("Converting %s") % file) + " (" + str(q.qsize()) + ")")
else: log.info(_("Converting %s") % file)
filter_name = filter.replace("ToFpdb", "")
mod = __import__(filter)
obj = getattr(mod, filter_name, None)
if callable(obj):
idx = 0
if file in self.pos_in_file:
idx = self.pos_in_file[file]
else:
self.pos_in_file[file] = 0
hhc = obj( self.config, in_path = file, index = idx, starsArchive = self.settings['starsArchive'], ftpArchive = self.settings['ftpArchive'], sitename = site )
if file in self.pos_in_file: idx = self.pos_in_file[file]
else: self.pos_in_file[file], idx = 0, 0
hhc = obj( self.config, in_path = file, index = idx
,starsArchive = self.settings['starsArchive']
,ftpArchive = self.settings['ftpArchive']
,sitename = site)
if hhc.getStatus():
if self.caller: hhc.progressNotify()
handlist = hhc.getProcessedHands()
self.pos_in_file[file] = hhc.getLastCharacterRead()
to_hud = []
hp_bulk = []
ha_bulk = []
i = 0
(hbulk, hpbulk, habulk, hcbulk, phands, ihands, to_hud) = ([], [], [], [], [], [], [])
sc, gsc = {'bk': []}, {'bk': []}
####Lock Placeholder####
for hand in handlist:
i += 1
if hand is not None:
hand.prepInsert(self.database, printtest = self.settings['testData'])
try:
hp_inserts, ha_inserts = hand.insert(self.database, hp_data = hp_bulk,
ha_data = ha_bulk, insert_data = len(handlist)==i,
printtest = self.settings['testData'])
hp_bulk += hp_inserts
ha_bulk += ha_inserts
except Exceptions.FpdbHandDuplicate:
duplicates += 1
else:
if self.callHud and hand.dbid_hands != 0:
to_hud.append(hand.dbid_hands)
else: # TODO: Treat empty as an error, or just ignore?
log.error(_("Hand processed but empty"))
# Call hudcache update if not in bulk import mode
# FIXME: Need to test for bulk import that isn't rebuilding the cache
if self.callHud:
for hand in handlist:
if hand is not None and not hand.is_duplicate:
hand.updateHudCache(self.database)
hand.prepInsert(self.database, printtest = self.settings['testData'])
self.database.commit()
phands.append(hand)
####Lock Placeholder####
for hand in phands:
hand.assembleHand()
####Lock Placeholder####
id = self.database.nextHandId()
for i in range(len(phands)):
doinsert = len(phands)==i+1
hand = phands[i]
try:
id = hand.getHandId(self.database, id)
sc, gsc = hand.updateSessionsCache(self.database, sc, gsc, None, doinsert)
hbulk = hand.insertHands(self.database, hbulk, fileId, doinsert, self.settings['testData'])
hcbulk = hand.updateHudCache(self.database, hcbulk, doinsert)
ihands.append(hand)
to_hud.append(hand.dbid_hands)
except Exceptions.FpdbHandDuplicate:
duplicates += 1
self.database.commit()
####Lock Placeholder####
for i in range(len(ihands)):
doinsert = len(ihands)==i+1
hand = ihands[i]
hpbulk = hand.insertHandsPlayers(self.database, hpbulk, doinsert, self.settings['testData'])
habulk = hand.insertHandsActions(self.database, habulk, doinsert, self.settings['testData'])
self.database.commit()
#pipe the Hands.id out to the HUD
if self.caller:
if self.callHud:
for hid in to_hud:
try:
print _("fpdb_import: sending hand to hud"), hand.dbid_hands, "pipe =", self.caller.pipe_to_hud
print _("fpdb_import: sending hand to hud"), hid, "pipe =", self.caller.pipe_to_hud
self.caller.pipe_to_hud.stdin.write("%s" % (hid) + os.linesep)
except IOError, e:
log.error(_("Failed to send hand to HUD: %s") % e)

4
pyfpdb/iPokerToFpdb.py

@ -120,7 +120,7 @@ or None if we fail to get the info """
except AttributeError:
tmp = handText[0:100]
log.error(_("Unable to recognise gametype from: '%s'") % tmp)
log.error(_("determineGameType: Raising FpdbParseError"))
log.error("determineGameType: " + _("Raising FpdbParseError"))
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
self.info = {}
@ -258,7 +258,7 @@ or None if we fail to get the info """
#print "DEBUG: addBringIn(%s, %s)" %(action.group('PNAME'), action.group('BET'))
hand.addBringIn(action.group('PNAME'), action.group('BET'))
else:
logging.error(_("Unimplemented readAction: %s") % (ag))
logging.error(_("DEBUG: ") + _("Unimplemented readAction: '%s' '%s'") % (action.group('PNAME'), action.group('ATYPE')))
def readShowdownActions(self, hand):
for shows in self.re_ShowdownAction.finditer(hand.handText):

BIN
pyfpdb/locale/de/LC_MESSAGES/fpdb.mo

Binary file not shown.

BIN
pyfpdb/locale/es/LC_MESSAGES/fpdb.mo

Binary file not shown.

1325
pyfpdb/locale/fpdb-de_DE.po

File diff suppressed because it is too large Load Diff

1090
pyfpdb/locale/fpdb-en_GB.pot

File diff suppressed because it is too large Load Diff

2089
pyfpdb/locale/fpdb-es_ES.po

File diff suppressed because it is too large Load Diff

1625
pyfpdb/locale/fpdb-fr_FR.po

File diff suppressed because it is too large Load Diff

1282
pyfpdb/locale/fpdb-hu_HU.po

File diff suppressed because it is too large Load Diff

4225
pyfpdb/locale/fpdb-it_IT.po

File diff suppressed because it is too large Load Diff

1152
pyfpdb/locale/fpdb-pl_PL.po

File diff suppressed because it is too large Load Diff

4026
pyfpdb/locale/fpdb-pt_BR.po

File diff suppressed because it is too large Load Diff

1778
pyfpdb/locale/fpdb-ru_RU.po

File diff suppressed because it is too large Load Diff

3992
pyfpdb/locale/fpdb-zh_CN.po

File diff suppressed because it is too large Load Diff

BIN
pyfpdb/locale/fr/LC_MESSAGES/fpdb.mo

Binary file not shown.

BIN
pyfpdb/locale/hu/LC_MESSAGES/fpdb.mo

Binary file not shown.

BIN
pyfpdb/locale/it/LC_MESSAGES/fpdb.mo

Binary file not shown.

28
pyfpdb/locale/localise.sh

@ -5,26 +5,42 @@ echo "creating template po file"
python /usr/share/doc/python-2.*/examples/Tools/i18n/pygettext.py --output-dir=locale --default-domain=fpdb --output=fpdb-en_GB.pot *.py *.pyw
echo "merging template with existing translations"
#msgmerge --update locale/fpdb-.po locale/fpdb-en_GB.pot
msgmerge --update locale/fpdb-de_DE.po locale/fpdb-en_GB.pot
msgmerge --update locale/fpdb-es_ES.po locale/fpdb-en_GB.pot
msgmerge --update locale/fpdb-fr_FR.po locale/fpdb-en_GB.pot
msgmerge --update locale/fpdb-hu_HU.po locale/fpdb-en_GB.pot
msgmerge --update locale/fpdb-it_IT.po locale/fpdb-en_GB.pot
msgmerge --update locale/fpdb-pl_PL.po locale/fpdb-en_GB.pot
msgmerge --update locale/fpdb-pt_BR.po locale/fpdb-en_GB.pot
msgmerge --update locale/fpdb-ru_RU.po locale/fpdb-en_GB.pot
msgmerge --update locale/fpdb-zh_CN.po locale/fpdb-en_GB.pot
msgfmt -c locale/fpdb-de_DE.po
msgfmt -c locale/fpdb-es_ES.po
msgfmt -c locale/fpdb-fr_FR.po
msgfmt -c locale/fpdb-hu_HU.po
msgfmt -c locale/fpdb-pl_PL.po
msgfmt -c locale/fpdb-ru_RU.po
echo "checking translated files"
#msgfmt -c --check-accelerators locale/fpdb-.po
msgfmt -c --check-accelerators locale/fpdb-de_DE.po
msgfmt -c --check-accelerators locale/fpdb-es_ES.po
msgfmt -c --check-accelerators locale/fpdb-fr_FR.po
msgfmt -c --check-accelerators locale/fpdb-hu_HU.po
msgfmt -c --check-accelerators locale/fpdb-it_IT.po
msgfmt -c --check-accelerators locale/fpdb-pl_PL.po
msgfmt -c --check-accelerators locale/fpdb-pt_BR.po
msgfmt -c --check-accelerators locale/fpdb-ru_RU.po
msgfmt -c --check-accelerators locale/fpdb-zh_CN.po
echo "check the following output for misplaced \\\\"
grep "[\\][\\]" locale/*.po
echo "compiling mo files"
#python /usr/share/doc/python-2.*/examples/Tools/i18n/msgfmt.py --output-file=locale//LC_MESSAGES/fpdb.mo locale/fpdb-.po
python /usr/share/doc/python-2.*/examples/Tools/i18n/msgfmt.py --output-file=locale/de/LC_MESSAGES/fpdb.mo locale/fpdb-de_DE.po
python /usr/share/doc/python-2.*/examples/Tools/i18n/msgfmt.py --output-file=locale/es/LC_MESSAGES/fpdb.mo locale/fpdb-es_ES.po
python /usr/share/doc/python-2.*/examples/Tools/i18n/msgfmt.py --output-file=locale/fr/LC_MESSAGES/fpdb.mo locale/fpdb-fr_FR.po
python /usr/share/doc/python-2.*/examples/Tools/i18n/msgfmt.py --output-file=locale/hu/LC_MESSAGES/fpdb.mo locale/fpdb-hu_HU.po
python /usr/share/doc/python-2.*/examples/Tools/i18n/msgfmt.py --output-file=locale/it/LC_MESSAGES/fpdb.mo locale/fpdb-it_IT.po
python /usr/share/doc/python-2.*/examples/Tools/i18n/msgfmt.py --output-file=locale/pl/LC_MESSAGES/fpdb.mo locale/fpdb-pl_PL.po
python /usr/share/doc/python-2.*/examples/Tools/i18n/msgfmt.py --output-file=locale/pt/LC_MESSAGES/fpdb.mo locale/fpdb-pt_BR.po
python /usr/share/doc/python-2.*/examples/Tools/i18n/msgfmt.py --output-file=locale/ru/LC_MESSAGES/fpdb.mo locale/fpdb-ru_RU.po
python /usr/share/doc/python-2.*/examples/Tools/i18n/msgfmt.py --output-file=locale/zh/LC_MESSAGES/fpdb.mo locale/fpdb-zh_CN.po
pocount locale/*.po

BIN
pyfpdb/locale/pl/LC_MESSAGES/fpdb.mo

Binary file not shown.

BIN
pyfpdb/locale/pt/LC_MESSAGES/fpdb.mo

Binary file not shown.

BIN
pyfpdb/locale/ru/LC_MESSAGES/fpdb.mo

Binary file not shown.

BIN
pyfpdb/locale/zh/LC_MESSAGES/fpdb.mo

Binary file not shown.

104
pyfpdb/regression-test-files/cash/Absolute/Flop/IHH20090610 Chile Way - Hold'em No Limit $0.02(Real Money) Table 9339866.txt.hp

@ -1,10 +1,23 @@
{ u'Hero': { 'card1': 34,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 32,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -104,12 +117,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'PLAYER1': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -209,12 +235,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'PLAYER2': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -314,12 +353,25 @@
'wonWhenSeenStreet3': 1.0,
'wonWhenSeenStreet4': 0.0},
u'PLAYER3': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -419,12 +471,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'PLAYER4': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -524,12 +589,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'PLAYER5': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -629,12 +707,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'PLAYER6': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -734,12 +825,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'PLAYER7': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,

104
pyfpdb/regression-test-files/cash/Carbon/Flop/NLHE-9max-USD-0.25-0.50.200810.All.Streets.txt.hp

@ -1,10 +1,23 @@
{ u'Hero': { 'card1': 13,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 46,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -104,12 +117,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player1': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -209,12 +235,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player3': { 'card1': 26,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 41,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -314,12 +353,25 @@
'wonWhenSeenStreet3': 1.0,
'wonWhenSeenStreet4': 0.0},
u'Player4': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -419,12 +471,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player5': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -524,12 +589,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player7': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -629,12 +707,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player8': { 'card1': 24,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 50,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -734,12 +825,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player9': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,

3
pyfpdb/regression-test-files/cash/Everest/Flop/PLO-EUR-5-10-Unknown-Sample.txt.hands

@ -3,6 +3,7 @@
'boardcard3': 0,
'boardcard4': 5,
'boardcard5': 29,
'gameSessionId': 1,
'gametypeId': 1,
'importTime': None,
'maxSeats': 10,
@ -28,4 +29,4 @@
'street4Raises': 0,
'tableName': u'Toulouse-2',
'texture': None,
'tourneyId': None}
'tourneyId': None}

26
pyfpdb/regression-test-files/cash/Everest/Flop/PLO-EUR-5-10-Unknown-Sample.txt.hp

@ -1,10 +1,23 @@
{ u'Hero': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -104,12 +117,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Villain': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': True,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,

104
pyfpdb/regression-test-files/cash/Everleaf/Flop/NLHE-10max-USD-0.01-0.02-201008.2Way.All-in.pre.txt.hp

@ -1,10 +1,23 @@
{ u'Player1': { 'card1': 29,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 16,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -104,12 +117,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player2': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -209,12 +235,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player3': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -314,12 +353,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player4': { 'card1': 33,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 7,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -419,12 +471,25 @@
'wonWhenSeenStreet3': 1.0,
'wonWhenSeenStreet4': 0.0},
u'Player5': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -524,12 +589,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player6': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -629,12 +707,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player7': { 'card1': 43,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 22,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -734,12 +825,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player8': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,

48
pyfpdb/regression-test-files/cash/Everleaf/Flop/NLHE-EUR-0.01-0.02-20091027.partouche.txt

@ -0,0 +1,48 @@
Partouche Poker Gibraltar
*** Historique des Mains pour la partie 25324991 ***
Blinds €0.01/ €0.02 NL Hold'em - 2009/10/27 - 19:04:57
Table Andernos 2
Seat 1 is the button
Total number of players: 6
Seat 1: player1 ( € 0.76 EUR )
Seat 2: player2 ( € 1.83 EUR )
Seat 3: player3 ( € 0.81 EUR )
Seat 4: player4 ( € 2 EUR )
Seat 5: player5 ( € 1.39 EUR )
Seat 6: player6 ( new player )
player2: posts small blind [ € 0.01 EUR]
player3: posts big blind [ € 0.02 EUR]
player4: posts big blind [ € 0.02 EUR]
** Dealing down cards **
Dealt to player4 [ 5s, 4s ]
player4 checks
player5 raises [ € 0.04 EUR]
player1 folds
player2 calls [ € 0.03 EUR]
player3 est déconnecté et dispose de 20 secondes supplémentaires pour agir
player3 calls [ € 0.02 EUR]
player4 calls [ € 0.02 EUR]
** Dealing Flop ** [ Qs, 8s, 7c ]
player3 est déconnecté et dispose de 20 secondes supplémentaires pour agir
player2 checks
player3 est déconnecté et dispose de 20 secondes supplémentaires pour agir
player3 checks
player4: bets [ € 0.08 EUR]
player5 raises [ € 0.16 EUR]
player2 folds
player3 calls [ € 0.16 EUR]
player4 calls [ € 0.08 EUR]
** Dealing Turn ** [ Th ]
player3 checks
player4 checks
player5: bets [ € 0.64 EUR]
player3 folds
player4 calls [ € 0.64 EUR]
** Dealing River ** [ Tc ]
player4: bets [ € 1.16 EUR]
player5 calls [ € 0.55 EUR]
player4 shows [ 5s, 4s ]a pair of tens
player5 shows [ Qh, Ad ]two pairs, queens and tens
player5 wins € 2.72 EUR from main pot with two pairs, queens and tens [ Ad, Qh, Qs, Th, Tc ]

90
pyfpdb/regression-test-files/cash/FTP/Draw/3-Draw-Limit-USD-0.10-0.20-201011.txt.hp

@ -1,10 +1,23 @@
{ u'Hero': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
{ u'Hero': { 'card1': 9,
'card2': 17,
'card3': 13,
'card4': 48,
'card5': 37,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card20': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -110,6 +123,19 @@
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 32,
'card17': 31,
'card18': 29,
'card19': 15,
'card20': 14,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -209,12 +235,25 @@
'wonWhenSeenStreet3': 1.0,
'wonWhenSeenStreet4': 0.0},
u'Player2': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -320,6 +359,19 @@
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 21,
'card17': 7,
'card18': 6,
'card19': 30,
'card20': 40,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -419,12 +471,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player4': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -524,12 +589,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player5': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -627,4 +705,4 @@
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0}}
'wonWhenSeenStreet4': 0.0}}

3
pyfpdb/regression-test-files/cash/FTP/Draw/3-Draw-Limit-USD-150-300-201012.txt.hands

@ -3,6 +3,7 @@
'boardcard3': 0,
'boardcard4': 0,
'boardcard5': 0,
'gameSessionId': 1,
'gametypeId': 12,
'importTime': None,
'maxSeats': 6,
@ -28,4 +29,4 @@
'street4Raises': 0,
'tableName': u"David's Draw",
'texture': None,
'tourneyId': None}
'tourneyId': None}

77
pyfpdb/regression-test-files/cash/FTP/Draw/3-Draw-Limit-USD-150-300-201012.txt.hp

@ -1,10 +1,23 @@
{ u'Hero': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
{ u'Hero': { 'card1': 1,
'card2': 24,
'card3': 42,
'card4': 35,
'card5': 27,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card20': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -104,12 +117,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player1': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -209,12 +235,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player4': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -314,12 +353,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player5': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 6,
'card17': 32,
'card18': 33,
'card19': 17,
'card20': 15,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -419,12 +471,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player6': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 49,
'card17': 19,
'card18': 30,
'card19': 28,
'card20': 14,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -522,4 +587,4 @@
'wonWhenSeenStreet1': 1.0,
'wonWhenSeenStreet2': 1.0,
'wonWhenSeenStreet3': 1.0,
'wonWhenSeenStreet4': 0.0}}
'wonWhenSeenStreet4': 0.0}}

65
pyfpdb/regression-test-files/cash/FTP/Draw/3-Draw-Limit-USD-1500-3000-201101.FTP.Archive.sample.txt

@ -0,0 +1,65 @@
FullTiltPoker Game #27088270000: Table harrington25 (6 max) - $1,500/$3,000 - Limit 2-7 Triple Draw - 11:00:00 ET - 2011/01/08
Seat 1: Player1 ($103,461)
Seat 2: Player2 ($120,106)
Seat 4: Hero ($57,750)
Seat 6: Player6 ($46,497.50)
Player1 posts the small blind of $750
Player2 posts the big blind of $1,500
The button is in seat #6
*** HOLE CARDS ***
Dealt to Hero [5s 3h 4c Qs 8d]
Hero raises to $3,000
Player6 raises to $4,500
Player1 folds
Player2 has 15 seconds left to act
Player2 raises to $6,000
Hero calls $3,000
Player6 calls $1,500
*** FIRST DRAW ***
Player2 discards 1 card
Hero discards 1 card [Qs]
Player6 discards 2 cards
Player2 is dealt 1 card
Dealt to Hero [5s 3h 4c 8d] [2h]
Player6 is dealt 2 cards
Player2 checks
Hero bets $1,500
Player6 raises to $3,000
Player2 calls $3,000
Hero raises to $4,500
Player6 raises to $6,000
Player2 calls $3,000
Hero calls $1,500
*** SECOND DRAW ***
Player2 discards 1 card
Hero stands pat on [5s 3h 4c 8d 2h]
Player6 has 15 seconds left to act
Player6 has requested TIME
Player6 stands pat
Player2 is dealt 1 card
Player2 checks
Hero checks
Player6 checks
*** THIRD DRAW ***
Player2 discards 1 card
Hero stands pat on [5s 3h 4c 8d 2h]
Player6 stands pat
Player2 is dealt 1 card
Player2 bets $3,000
Hero calls $3,000
Player6 folds
*** SHOW DOWN ***
Player2 shows [8s 6d 4s 3d 2c] 8,6,4,3,2
Hero shows [8d 5s 4c 3h 2h] 8,5,4,3,2
Hero wins the pot ($42,748) with 8,5,4,3,2
*** SUMMARY ***
Duration 106s
Total pot $42,750 | Rake $2
Seat 1: Player1 (small blind) folded before the draw
Seat 2: Player2 (big blind) showed [8s 6d 4s 3d 2c] and lost with 8,6,4,3,2
Seat 4: Hero showed [8d 5s 4c 3h 2h] and won ($42,748) with 8,5,4,3,2
Seat 6: Player6 (button) folded after the 3rd Draw

3
pyfpdb/regression-test-files/cash/FTP/Draw/3-Draw-Limit-USD-250-500-201011.Hero.sitting.out.but.not.listed.txt.hands

@ -3,6 +3,7 @@
'boardcard3': 0,
'boardcard4': 0,
'boardcard5': 0,
'gameSessionId': 1,
'gametypeId': 1,
'importTime': None,
'maxSeats': 6,
@ -29,4 +30,4 @@
'street4Raises': 0,
'tableName': u'Rocky Cliff',
'texture': None,
'tourneyId': None}
'tourneyId': None}

52
pyfpdb/regression-test-files/cash/FTP/Draw/3-Draw-Limit-USD-250-500-201011.Hero.sitting.out.but.not.listed.txt.hp

@ -1,10 +1,23 @@
{ u'Player3': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': True,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -104,12 +117,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player4': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': True,
'foldToOtherRaisedStreet0': False,
@ -209,12 +235,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player5': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -314,12 +353,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player6': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,

3
pyfpdb/regression-test-files/cash/FTP/Draw/5-Carddraw-Limit-USD-0.10-0.20-201011.Sample.Not.UTF16.txt.hands

@ -3,6 +3,7 @@
'boardcard3': 0,
'boardcard4': 0,
'boardcard5': 0,
'gameSessionId': 1,
'gametypeId': 1,
'importTime': None,
'maxSeats': 6,
@ -28,4 +29,4 @@
'street4Raises': 0,
'tableName': u'Shady Oak',
'texture': None,
'tourneyId': None}
'tourneyId': None}

77
pyfpdb/regression-test-files/cash/FTP/Draw/5-Carddraw-Limit-USD-0.10-0.20-201011.Sample.Not.UTF16.txt.hp

@ -1,10 +1,23 @@
{ u'Hero': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
{ u'Hero': { 'card1': 48,
'card2': 17,
'card3': 44,
'card4': 14,
'card5': 7,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card20': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -110,6 +123,19 @@
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 6,
'card17': 19,
'card18': 45,
'card19': 11,
'card20': 50,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -215,6 +241,19 @@
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 13,
'card17': 52,
'card18': 23,
'card19': 49,
'card20': 2,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -320,6 +359,19 @@
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 10,
'card17': 36,
'card18': 40,
'card19': 1,
'card20': 12,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -419,12 +471,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player4': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -522,4 +587,4 @@
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0}}
'wonWhenSeenStreet4': 0.0}}

3
pyfpdb/regression-test-files/cash/FTP/Draw/5-Carddraw-NL-USD-0.10-0.20-201011.Saw.Showdown.Not.UTF16.txt.hands

@ -3,6 +3,7 @@
'boardcard3': 0,
'boardcard4': 0,
'boardcard5': 0,
'gameSessionId': 1,
'gametypeId': 117,
'importTime': None,
'maxSeats': 6,
@ -28,4 +29,4 @@
'street4Raises': 0,
'tableName': u'Calla Lily',
'texture': None,
'tourneyId': None}
'tourneyId': None}

90
pyfpdb/regression-test-files/cash/FTP/Draw/5-Carddraw-NL-USD-0.10-0.20-201011.Saw.Showdown.Not.UTF16.txt.hp

@ -1,10 +1,23 @@
{ u'Hero': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
{ u'Hero': { 'card1': 7,
'card2': 6,
'card3': 32,
'card4': 50,
'card5': 10,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card20': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -110,6 +123,19 @@
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 38,
'card17': 37,
'card18': 30,
'card19': 29,
'card20': 28,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -215,6 +241,19 @@
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 49,
'card17': 36,
'card18': 21,
'card19': 47,
'card20': 43,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -314,12 +353,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player3': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -419,12 +471,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player4': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -524,12 +589,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player6': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -627,4 +705,4 @@
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0}}
'wonWhenSeenStreet4': 0.0}}

3
pyfpdb/regression-test-files/cash/FTP/Draw/5-Carddraw-PL-0.10-0.25-201011.Sample.Not.UTF16.txt.hands

@ -3,6 +3,7 @@
'boardcard3': 0,
'boardcard4': 0,
'boardcard5': 0,
'gameSessionId': 1,
'gametypeId': 1,
'importTime': None,
'maxSeats': 6,
@ -28,4 +29,4 @@
'street4Raises': 0,
'tableName': u'Axe Handle',
'texture': None,
'tourneyId': None}
'tourneyId': None}

68
pyfpdb/regression-test-files/cash/FTP/Draw/5-Carddraw-PL-0.10-0.25-201011.Sample.Not.UTF16.txt.hp

@ -1,10 +1,23 @@
{ u'Hero': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
{ u'Hero': { 'card1': 24,
'card2': 10,
'card3': 38,
'card4': 11,
'card5': 41,
'card6': 24,
'card7': 11,
'card8': 32,
'card9': 26,
'card10': 28,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card20': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -104,12 +117,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player2': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -215,6 +241,19 @@
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 34,
'card17': 47,
'card18': 21,
'card19': 39,
'card20': 40,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -314,12 +353,25 @@
'wonWhenSeenStreet3': 1.0,
'wonWhenSeenStreet4': 0.0},
u'Player6': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -417,4 +469,4 @@
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0}}
'wonWhenSeenStreet4': 0.0}}

3
pyfpdb/regression-test-files/cash/FTP/Draw/Badugi-USD-0.05-0.10-201011.Sample.Not.UTF16.txt.hands

@ -3,6 +3,7 @@
'boardcard3': 0,
'boardcard4': 0,
'boardcard5': 0,
'gameSessionId': 1,
'gametypeId': 2,
'importTime': None,
'maxSeats': 7,
@ -28,4 +29,4 @@
'street4Raises': 0,
'tableName': u'Laurelvale',
'texture': None,
'tourneyId': None}
'tourneyId': None}

111
pyfpdb/regression-test-files/cash/FTP/Draw/Badugi-USD-0.05-0.10-201011.Sample.Not.UTF16.txt.hp

@ -1,10 +1,23 @@
{ u'Hero': { 'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
{ u'Hero': { 'card1': 13,
'card2': 50,
'card3': 41,
'card4': 36,
'card5': 0,
'card6': 0,
'card7': 0,
'card6': 13,
'card7': 41,
'card8': 10,
'card9': 33,
'card10': 0,
'card11': 13,
'card12': 41,
'card13': 33,
'card14': 46,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card20': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -104,12 +117,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player2': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -209,12 +235,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player3': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -313,13 +352,27 @@
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player4': { 'card1': 0,
u'Player4': {
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 24,
'card17': 42,
'card18': 2,
'card19': 27,
'card20': 0,
'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -418,13 +471,27 @@
'wonWhenSeenStreet2': 1.0,
'wonWhenSeenStreet3': 1.0,
'wonWhenSeenStreet4': 0.0},
u'Player5': { 'card1': 0,
u'Player5': {
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 43,
'card17': 3,
'card18': 26,
'card19': 49,
'card20': 0,
'card1': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -524,12 +591,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player6': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -629,12 +709,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player7': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 29,
'card17': 15,
'card18': 40,
'card19': 18,
'card20': 0,
'card2': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -732,4 +825,4 @@
'wonWhenSeenStreet1': 0.0,
'wonWhenSeenStreet2': 0.0,
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0}}
'wonWhenSeenStreet4': 0.0}}

3
pyfpdb/regression-test-files/cash/FTP/Flop/LHE-9max-USD-1-2.201012.Button.Player4.Sitting.out.txt.hands

@ -3,6 +3,7 @@
'boardcard3': 52,
'boardcard4': 17,
'boardcard5': 29,
'gameSessionId': 1,
'gametypeId': 99,
'importTime': None,
'maxSeats': 9,
@ -28,4 +29,4 @@
'street4Raises': 0,
'tableName': u'Slaw',
'texture': None,
'tourneyId': None}
'tourneyId': None}

91
pyfpdb/regression-test-files/cash/FTP/Flop/LHE-9max-USD-1-2.201012.Button.Player4.Sitting.out.txt.hp

@ -1,10 +1,23 @@
{ u'Hero': { 'card1': 47,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 9,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -104,12 +117,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player1': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -209,12 +235,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player2': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -314,12 +353,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player3': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -419,12 +471,25 @@
'wonWhenSeenStreet3': 1.0,
'wonWhenSeenStreet4': 0.0},
u'Player6': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -524,12 +589,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player7': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -629,12 +707,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player8': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,

3
pyfpdb/regression-test-files/cash/FTP/Flop/LO8-6max-USD-200-400.200610.Observed.Hand.with.chat.txt.hands

@ -3,6 +3,7 @@
'boardcard3': 41,
'boardcard4': 42,
'boardcard5': 13,
'gameSessionId': 1,
'gametypeId': 21,
'importTime': None,
'maxSeats': 6,
@ -28,4 +29,4 @@
'street4Raises': 0,
'tableName': u'Vero',
'texture': None,
'tourneyId': None}
'tourneyId': None}

67
pyfpdb/regression-test-files/cash/FTP/Flop/LO8-6max-USD-200-400.200610.Observed.Hand.with.chat.txt.hp

@ -1,10 +1,23 @@
{ u'AllenCunningham': { 'card1': 19,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 27,
'card20': 0,
'card3': 51,
'card4': 26,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -104,12 +117,25 @@
'wonWhenSeenStreet3': 1.0,
'wonWhenSeenStreet4': 0.0},
u'Erick Lindgren': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -209,12 +235,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Shoe Lab': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -314,12 +353,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'TexasLimitDonk': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -419,12 +471,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'zbubop': { 'card1': 28,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 8,
'card20': 0,
'card3': 52,
'card4': 50,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -522,4 +587,4 @@
'wonWhenSeenStreet1': 1.0,
'wonWhenSeenStreet2': 1.0,
'wonWhenSeenStreet3': 1.0,
'wonWhenSeenStreet4': 0.0}}
'wonWhenSeenStreet4': 0.0}}

3
pyfpdb/regression-test-files/cash/FTP/Flop/NLHE-6max-EUR-0.01-0.02.201008.Weird.table.character.txt.hands

@ -3,6 +3,7 @@
'boardcard3': 0,
'boardcard4': 0,
'boardcard5': 0,
'gameSessionId': 1,
'gametypeId': 7,
'importTime': None,
'maxSeats': 6,
@ -28,4 +29,4 @@
'street4Raises': 0,
'tableName': u'Douai\u2013Lens',
'texture': None,
'tourneyId': None}
'tourneyId': None}

78
pyfpdb/regression-test-files/cash/FTP/Flop/NLHE-6max-EUR-0.01-0.02.201008.Weird.table.character.txt.hp

@ -1,10 +1,23 @@
{ u'Hero': { 'card1': 1,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 34,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': True,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -104,12 +117,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player1': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -209,12 +235,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player2': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -314,12 +353,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player3': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -419,12 +471,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player4': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': True,
'foldToOtherRaisedStreet0': False,
@ -524,12 +589,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player6': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,

3
pyfpdb/regression-test-files/cash/FTP/Flop/NLHE-9max-USD-0.02-0.05.201007.Short.lived.date.format.txt.hands

@ -3,6 +3,7 @@
'boardcard3': 0,
'boardcard4': 0,
'boardcard5': 0,
'gameSessionId': 1,
'gametypeId': 6,
'importTime': None,
'maxSeats': 9,
@ -28,4 +29,4 @@
'street4Raises': 0,
'tableName': u'Flash',
'texture': None,
'tourneyId': None}
'tourneyId': None}

117
pyfpdb/regression-test-files/cash/FTP/Flop/NLHE-9max-USD-0.02-0.05.201007.Short.lived.date.format.txt.hp

@ -1,10 +1,23 @@
{ u'Hero': { 'card1': 50,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 16,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -104,12 +117,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'MANUTD': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -209,12 +235,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'T0r3x': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -314,12 +353,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'proud2Bwhack': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -419,12 +471,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'ronaldd1969': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -524,12 +589,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'shleekom': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -629,12 +707,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'stark00': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -734,12 +825,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'vision': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -839,12 +943,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'yrthligar': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,

3
pyfpdb/regression-test-files/cash/FTP/Flop/PLO-6max-USD-0.01-0.02.201003.River.Showdown.txt.hands

@ -3,6 +3,7 @@
'boardcard3': 8,
'boardcard4': 51,
'boardcard5': 5,
'gameSessionId': 1,
'gametypeId': 8,
'importTime': None,
'maxSeats': 6,
@ -28,4 +29,4 @@
'street4Raises': 0,
'tableName': u'Gaines',
'texture': None,
'tourneyId': None}
'tourneyId': None}

78
pyfpdb/regression-test-files/cash/FTP/Flop/PLO-6max-USD-0.01-0.02.201003.River.Showdown.txt.hp

@ -1,10 +1,23 @@
{ u'B_Isreal22': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -104,12 +117,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'DrZartinger': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -209,12 +235,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Hero': { 'card1': 15,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 10,
'card20': 0,
'card3': 42,
'card4': 25,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -314,12 +353,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'ShaDiv': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -419,12 +471,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Timoha777': { 'card1': 24,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 23,
'card20': 0,
'card3': 16,
'card4': 50,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -524,12 +589,25 @@
'wonWhenSeenStreet3': 1.0,
'wonWhenSeenStreet4': 0.0},
u'rockinalex': { 'card1': 49,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 31,
'card20': 0,
'card3': 19,
'card4': 39,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,

91
pyfpdb/regression-test-files/cash/FTP/Stud/7-Stud-USD-3-6-20106.Steal.from.Button.Failure.txt.hp

@ -1,10 +1,23 @@
{ u'FILL A RACK': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 26,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -104,12 +117,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Hero': { 'card1': 43,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 1,
'card20': 0,
'card3': 9,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -209,12 +235,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'arjun1111': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 52,
'card4': 2,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -314,12 +353,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'chasrigg': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 10,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -419,12 +471,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'goulartarm': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 50,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -524,12 +589,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'kwuiyhw': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 34,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -629,12 +707,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'thebear666': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 45,
'card4': 11,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': True,
'foldToOtherRaisedStreet0': False,

55
pyfpdb/regression-test-files/cash/FTP/Stud/7-StudHL-USD-2-4-201103.Underscore.in.tablename.txt

@ -0,0 +1,55 @@
Full Tilt Poker Game #29408130000: Table XGod_Of_WarX - $2/$4 Ante $0.40 - Limit Stud H/L - 01:12:00 ET - 2011/03/28
Seat 1: Player1 ($17.70)
Seat 2: Hero ($82.30)
Seat 3: Player3 ($81.70)
Seat 5: Player5 ($95.45)
Seat 6: Player6 ($43.60), is sitting out
Seat 7: Player7 ($435.15)
Seat 8: Player8 ($20.60)
Player5 antes $0.40
Player7 antes $0.40
Player1 antes $0.40
Hero antes $0.40
Player8 antes $0.40
Player3 antes $0.40
*** 3RD STREET ***
Dealt to Player1 [3c]
Dealt to Hero [5d Ah] [Ad]
Dealt to Player3 [7h]
Dealt to Player5 [4c]
Dealt to Player7 [8h]
Dealt to Player8 [5s]
Player1 is low with [3c]
Player1 brings in for $0.50
Hero completes it to $2
Player3 folds
Player5 calls $2
Player7 folds
Player7 is sitting out
Player8 folds
Player1 folds
*** 4TH STREET ***
Dealt to Hero [5d Ah Ad] [6h]
Dealt to Player5 [4c] [7c]
Hero bets $2
Player5 calls $2
*** 5TH STREET ***
Dealt to Hero [5d Ah Ad 6h] [5c]
Dealt to Player5 [4c 7c] [Tc]
Hero bets $4
Player5 folds
Uncalled bet of $4 returned to Hero
Hero mucks
Hero wins the pot ($10.90)
*** SUMMARY ***
Total pot $10.90 | Rake $0
Seat 1: Player1 folded on 3rd St.
Seat 2: Hero collected ($10.90), mucked
Seat 3: Player3 folded on 3rd St.
Seat 5: Player5 folded on 5th St.
Seat 6: Player6 is sitting out
Seat 7: Player7 folded on 3rd St.
Seat 8: Player8 folded on 3rd St.

3
pyfpdb/regression-test-files/cash/FTP/Stud/Razz-USD-0.10-0.20-201012.CCT.and.ET.timeformat.txt.hands

@ -3,6 +3,7 @@
'boardcard3': 0,
'boardcard4': 0,
'boardcard5': 0,
'gameSessionId': 1,
'gametypeId': 5,
'importTime': None,
'maxSeats': 8,
@ -28,4 +29,4 @@
'street4Raises': 0,
'tableName': u'Mart',
'texture': None,
'tourneyId': None}
'tourneyId': None}

91
pyfpdb/regression-test-files/cash/FTP/Stud/Razz-USD-0.10-0.20-201012.CCT.and.ET.timeformat.txt.hp

@ -1,10 +1,23 @@
{ u'Hero': { 'card1': 18,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 25,
'card20': 0,
'card3': 42,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -104,12 +117,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player2': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 40,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -209,12 +235,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player3': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 4,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -314,12 +353,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player4': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 32,
'card4': 33,
'card5': 16,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -419,12 +471,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player5': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 51,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -524,12 +589,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player7': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 5,
'card4': 8,
'card5': 30,
'card6': 14,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -629,12 +707,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player8': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 45,
'card4': 26,
'card5': 7,
'card6': 28,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,

3
pyfpdb/regression-test-files/cash/FTP/Stud/Razz-USD-0.10-0.20-201012.Player6.listed.but.doesnt.act.txt.hands

@ -3,6 +3,7 @@
'boardcard3': 0,
'boardcard4': 0,
'boardcard5': 0,
'gameSessionId': 1,
'gametypeId': 1,
'importTime': None,
'maxSeats': 8,
@ -28,4 +29,4 @@
'street4Raises': 0,
'tableName': u'Mart',
'texture': None,
'tourneyId': None}
'tourneyId': None}

104
pyfpdb/regression-test-files/cash/FTP/Stud/Razz-USD-0.10-0.20-201012.Player6.listed.but.doesnt.act.txt.hp

@ -1,10 +1,23 @@
{ u'Hero': { 'card1': 36,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 14,
'card20': 0,
'card3': 44,
'card4': 8,
'card5': 34,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -104,12 +117,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player2': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 23,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -209,12 +235,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player3': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 26,
'card4': 10,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -314,12 +353,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player4': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 41,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -419,12 +471,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player5': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 6,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -524,12 +589,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player6': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -629,12 +707,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player7': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 52,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -734,12 +825,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player8': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 37,
'card4': 46,
'card5': 18,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,

65
pyfpdb/regression-test-files/cash/OnGame/Flop/LHE-9max-USD-0.50-1.00-201008.All-in.with.showdown.txt.hp

@ -1,10 +1,23 @@
{ u'Hero': { 'card1': 25,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 51,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -104,12 +117,25 @@
'wonWhenSeenStreet3': 1.0,
'wonWhenSeenStreet4': 0.0},
u'player1': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -209,12 +235,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'player2': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -314,12 +353,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'player4': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -419,12 +471,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'player5': { 'card1': 24,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 11,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,

3
pyfpdb/regression-test-files/cash/OnGame/Flop/NLHE-10max-USD-0.02-0.04-201102.Speed.table.BWin.txt.hands

@ -3,6 +3,7 @@
'boardcard3': 50,
'boardcard4': 49,
'boardcard5': 48,
'gameSessionId': 1,
'gametypeId': 1,
'importTime': None,
'maxSeats': 10,
@ -28,4 +29,4 @@
'street4Raises': 0,
'tableName': u'Dijon',
'texture': None,
'tourneyId': None}
'tourneyId': None}

78
pyfpdb/regression-test-files/cash/OnGame/Flop/NLHE-10max-USD-0.02-0.04-201102.Speed.table.BWin.txt.hp

@ -1,10 +1,23 @@
{ u'Hero': { 'card1': 19,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 22,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -104,12 +117,25 @@
'wonWhenSeenStreet3': 1.0,
'wonWhenSeenStreet4': 0.0},
u'Player10': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -209,12 +235,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player2': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -314,12 +353,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player5': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -419,12 +471,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player7': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,
@ -524,12 +589,25 @@
'wonWhenSeenStreet3': 0.0,
'wonWhenSeenStreet4': 0.0},
u'Player8': { 'card1': 0,
'card10': 0,
'card11': 0,
'card12': 0,
'card13': 0,
'card14': 0,
'card15': 0,
'card16': 0,
'card17': 0,
'card18': 0,
'card19': 0,
'card2': 0,
'card20': 0,
'card3': 0,
'card4': 0,
'card5': 0,
'card6': 0,
'card7': 0,
'card8': 0,
'card9': 0,
'foldBbToStealChance': False,
'foldSbToStealChance': False,
'foldToOtherRaisedStreet0': False,

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save