From 0acaa8cb6df0ec67093100647dc5464150b73d47 Mon Sep 17 00:00:00 2001 From: gimick Date: Tue, 28 Dec 2010 03:20:49 +0000 Subject: [PATCH 01/83] GUI: RingPlayerStats correct the description of w$sd --- pyfpdb/GuiRingPlayerStats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/GuiRingPlayerStats.py b/pyfpdb/GuiRingPlayerStats.py index 86ba1aad..c19f0f1d 100644 --- a/pyfpdb/GuiRingPlayerStats.py +++ b/pyfpdb/GuiRingPlayerStats.py @@ -58,7 +58,7 @@ onlinehelp = {'Game':_('Type of Game'), 'Saw_F':_('% Saw Flop vs hands dealt'), 'SawSD':_('Saw Show Down / River'), 'WtSDwsF':_('Went To Show Down When Saw Flop'), - 'W$SD':_('Amount Won when Show Down seen'), + 'W$SD':_('% Times Won when Show Down seen'), 'FlAFq':_('Flop Aggression\n% Bet or Raise after seeing Flop'), 'TuAFq':_('Turn Aggression\n% Bet or Raise after seeing Turn'), 'RvAFq':_('River Aggression\n% Bet or Raise after seeing River'), From 95b496e9f477fff9e9310cdc808f8d05348e1ff8 Mon Sep 17 00:00:00 2001 From: gimick Date: Tue, 28 Dec 2010 13:35:24 +0000 Subject: [PATCH 02/83] GUI: another w$sd description change --- pyfpdb/GuiRingPlayerStats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/GuiRingPlayerStats.py b/pyfpdb/GuiRingPlayerStats.py index c19f0f1d..f061322e 100644 --- a/pyfpdb/GuiRingPlayerStats.py +++ b/pyfpdb/GuiRingPlayerStats.py @@ -58,7 +58,7 @@ onlinehelp = {'Game':_('Type of Game'), 'Saw_F':_('% Saw Flop vs hands dealt'), 'SawSD':_('Saw Show Down / River'), 'WtSDwsF':_('Went To Show Down When Saw Flop'), - 'W$SD':_('% Times Won when Show Down seen'), + 'W$SD':_('% Won some money at showdown'), 'FlAFq':_('Flop Aggression\n% Bet or Raise after seeing Flop'), 'TuAFq':_('Turn Aggression\n% Bet or Raise after seeing Turn'), 'RvAFq':_('River Aggression\n% Bet or Raise after seeing River'), From 0a256f18a36196566c469323af9083ea98be9c1b Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Tue, 28 Dec 2010 18:38:33 +0200 Subject: [PATCH 03/83] Update debian/changelog for 0.21-rc2 --- packaging/debian/changelog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packaging/debian/changelog b/packaging/debian/changelog index 8ebf2bcd..4c48b057 100644 --- a/packaging/debian/changelog +++ b/packaging/debian/changelog @@ -1,3 +1,9 @@ +free-poker-tools (0.21~rc2) unstable; urgency=low + + * Second 0.21 release-candidate + + -- Mika Bostrom Tue, 28 Dec 2010 18:37:47 +0200 + free-poker-tools (0.21~rc1) unstable; urgency=low * First 0.21 release candidate From 744e5292eff4095752d65d920c1518269284d6ff Mon Sep 17 00:00:00 2001 From: gimick Date: Tue, 28 Dec 2010 18:29:23 +0000 Subject: [PATCH 04/83] py2exe: update walkthrough (suppress popup error message on exit) --- .../windows/py2exeWalkthroughPython26.txt | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/packaging/windows/py2exeWalkthroughPython26.txt b/packaging/windows/py2exeWalkthroughPython26.txt index 7ad865c0..2762699e 100644 --- a/packaging/windows/py2exeWalkthroughPython26.txt +++ b/packaging/windows/py2exeWalkthroughPython26.txt @@ -33,6 +33,7 @@ psycopg2 ... http://www.stickpeople.com/projects/python/win-psycopg/psycopg2-2.2 (py)pokereval v138 ... http://sourceforge.net/projects/fpdb/files/fpdb/pypoker-eval-win32/pokereval-138.win32.exe/download (Note: There are no official windows builds, this installer is built from source. A walkthrough is in the same directory as this walkthrough. + 1.2/ MySQL Install the following file: @@ -67,6 +68,26 @@ with this line: 1.3.4/ Save and exit +1.4/ Patch py2exe to stop popup runtime error message + +see http://www.py2exe.org/index.cgi/StderrLog for technical info. + +1.4.1/ + +dos> write C:\Python26\Lib\site-packages\py2exe\boot_common.py + +replace: + atexit.register(alert, 0, + "See the logfile '%s' for details" % fname, + "Errors occurred") +with: + #atexit.register(alert, 0, + # "See the logfile '%s' for details" % fname, + # "Errors occurred") + +1.4.2/ save and exit + + Step 2 Setup GTK ----------------- From 7abcca345f1b95ea24334e6f2f5c031e9f0dbd1b Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Tue, 28 Dec 2010 23:43:15 -0500 Subject: [PATCH 05/83] Fix table finding for PokerStars.it tournaments. Still needs work. --- pyfpdb/HandHistoryConverter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 62383beb..a3e48bf4 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -673,7 +673,7 @@ or None if we fail to get the info """ "Returns string to search window title for tournament table no." # Full Tilt: $30 + $3 Tournament (181398949), Table 1 - 600/1200 Ante 100 - Limit Razz # PokerStars: WCOOP 2nd Chance 02: $1,050 NLHE - Tournament 307521826 Table 1 - Blinds $30/$60 - return "%s.+Table (\d+)" % (tournament, ) + return "%s.+(?:Table|Torneo) (\d+)" % (tournament, ) def getTableTitleRe(config, sitename, *args, **kwargs): "Returns string to search in windows titles for current site" From 071a3715de0fa7100d10fab2dfde724a8b96361e Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 4 Jan 2011 12:57:08 +0800 Subject: [PATCH 06/83] Regression: Winamax PLO Verify and correct Winamax all-in pre PLO hand with sidepots. Adjusts street2/3seen and wonWhenSeenStreet2/3 in the .hp file. This increases the number of errors in THP from 22 to 32 --- ...09.Real.side.pot.with.bad.collected.txt.hp | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pyfpdb/regression-test-files/cash/Winamax/Flop/PLO-FR-EUR-0.02-0.05-201009.Real.side.pot.with.bad.collected.txt.hp b/pyfpdb/regression-test-files/cash/Winamax/Flop/PLO-FR-EUR-0.02-0.05-201009.Real.side.pot.with.bad.collected.txt.hp index 1fcb2468..6e859733 100644 --- a/pyfpdb/regression-test-files/cash/Winamax/Flop/PLO-FR-EUR-0.02-0.05-201009.Real.side.pot.with.bad.collected.txt.hp +++ b/pyfpdb/regression-test-files/cash/Winamax/Flop/PLO-FR-EUR-0.02-0.05-201009.Real.side.pot.with.bad.collected.txt.hp @@ -64,7 +64,7 @@ 'street2CheckCallRaiseChance': False, 'street2CheckCallRaiseDone': False, 'street2Raises': 0, - 'street2Seen': False, + 'street2Seen': True, 'street3Aggr': False, 'street3Bets': 0, 'street3CBChance': False, @@ -73,7 +73,7 @@ 'street3CheckCallRaiseChance': False, 'street3CheckCallRaiseDone': False, 'street3Raises': 0, - 'street3Seen': False, + 'street3Seen': True, 'street4Aggr': False, 'street4Bets': 0, 'street4CBChance': False, @@ -628,7 +628,7 @@ 'street2CheckCallRaiseChance': False, 'street2CheckCallRaiseDone': False, 'street2Raises': 0, - 'street2Seen': False, + 'street2Seen': True, 'street3Aggr': False, 'street3Bets': 0, 'street3CBChance': False, @@ -637,7 +637,7 @@ 'street3CheckCallRaiseChance': False, 'street3CheckCallRaiseDone': False, 'street3Raises': 0, - 'street3Seen': False, + 'street3Seen': True, 'street4Aggr': False, 'street4Bets': 0, 'street4CBChance': False, @@ -653,8 +653,8 @@ 'winnings': 88, 'wonAtSD': 1.0, 'wonWhenSeenStreet1': 1.0, - 'wonWhenSeenStreet2': 0.0, - 'wonWhenSeenStreet3': 0.0, + 'wonWhenSeenStreet2': 1.0, + 'wonWhenSeenStreet3': 1.0, 'wonWhenSeenStreet4': 0.0}, u'Player5': { 'card1': 0, 'card2': 0, @@ -816,7 +816,7 @@ 'street2CheckCallRaiseChance': True, 'street2CheckCallRaiseDone': True, 'street2Raises': 0, - 'street2Seen': False, + 'street2Seen': True, 'street3Aggr': False, 'street3Bets': 0, 'street3CBChance': False, @@ -825,7 +825,7 @@ 'street3CheckCallRaiseChance': False, 'street3CheckCallRaiseDone': False, 'street3Raises': 0, - 'street3Seen': False, + 'street3Seen': True, 'street4Aggr': False, 'street4Bets': 0, 'street4CBChance': False, @@ -841,6 +841,6 @@ 'winnings': 338, 'wonAtSD': 1.0, 'wonWhenSeenStreet1': 1.0, - 'wonWhenSeenStreet2': 0.0, - 'wonWhenSeenStreet3': 0.0, + 'wonWhenSeenStreet2': 1.0, + 'wonWhenSeenStreet3': 1.0, 'wonWhenSeenStreet4': 0.0}} From de01acade90567fa0e16b54a51a7e215d81c12b4 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 4 Jan 2011 13:17:57 +0800 Subject: [PATCH 07/83] Regression: Carbon streetXseen .hp values Verify that both Player3 and Player8 saw the river (all-in on turn) Increases THP count by 2 - Total 34 --- .../Flop/NLHE-9max-USD-0.25-0.50.200810.All.Streets.txt.hp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/regression-test-files/cash/Carbon/Flop/NLHE-9max-USD-0.25-0.50.200810.All.Streets.txt.hp b/pyfpdb/regression-test-files/cash/Carbon/Flop/NLHE-9max-USD-0.25-0.50.200810.All.Streets.txt.hp index fff0dbf6..c16c6d63 100644 --- a/pyfpdb/regression-test-files/cash/Carbon/Flop/NLHE-9max-USD-0.25-0.50.200810.All.Streets.txt.hp +++ b/pyfpdb/regression-test-files/cash/Carbon/Flop/NLHE-9max-USD-0.25-0.50.200810.All.Streets.txt.hp @@ -261,7 +261,7 @@ 'street3CheckCallRaiseChance': False, 'street3CheckCallRaiseDone': False, 'street3Raises': 0, - 'street3Seen': False, + 'street3Seen': True, 'street4Aggr': False, 'street4Bets': 0, 'street4CBChance': False, @@ -637,7 +637,7 @@ 'street3CheckCallRaiseChance': False, 'street3CheckCallRaiseDone': False, 'street3Raises': 0, - 'street3Seen': False, + 'street3Seen': True, 'street4Aggr': False, 'street4Bets': 0, 'street4CBChance': False, From 0ec976bc78f2a1dabd7165e8c5738ec3f6748fa1 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 4 Jan 2011 13:53:18 +0800 Subject: [PATCH 08/83] Regression: OnGame streetXseen and wonWhenSeenStreetX fixes Verify and correct OnGame all-in pre/flop hand with Hero win. Adds 9 new errors to THP - Total 43 --- ....50-1.00-201008.All-in.with.showdown.txt.hp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pyfpdb/regression-test-files/cash/OnGame/Flop/LHE-9max-USD-0.50-1.00-201008.All-in.with.showdown.txt.hp b/pyfpdb/regression-test-files/cash/OnGame/Flop/LHE-9max-USD-0.50-1.00-201008.All-in.with.showdown.txt.hp index 0c129875..6a9111e6 100644 --- a/pyfpdb/regression-test-files/cash/OnGame/Flop/LHE-9max-USD-0.50-1.00-201008.All-in.with.showdown.txt.hp +++ b/pyfpdb/regression-test-files/cash/OnGame/Flop/LHE-9max-USD-0.50-1.00-201008.All-in.with.showdown.txt.hp @@ -243,7 +243,7 @@ 'street1CheckCallRaiseChance': False, 'street1CheckCallRaiseDone': False, 'street1Raises': 0, - 'street1Seen': False, + 'street1Seen': True, 'street2Aggr': False, 'street2Bets': 0, 'street2CBChance': False, @@ -252,7 +252,7 @@ 'street2CheckCallRaiseChance': False, 'street2CheckCallRaiseDone': False, 'street2Raises': 0, - 'street2Seen': False, + 'street2Seen': True, 'street3Aggr': False, 'street3Bets': 0, 'street3CBChance': False, @@ -261,7 +261,7 @@ 'street3CheckCallRaiseChance': False, 'street3CheckCallRaiseDone': False, 'street3Raises': 0, - 'street3Seen': False, + 'street3Seen': True, 'street4Aggr': False, 'street4Bets': 0, 'street4CBChance': False, @@ -276,9 +276,9 @@ 'tourneysPlayersIds': None, 'winnings': 325, 'wonAtSD': 1.0, - 'wonWhenSeenStreet1': 0.0, - 'wonWhenSeenStreet2': 0.0, - 'wonWhenSeenStreet3': 0.0, + 'wonWhenSeenStreet1': 1.0, + 'wonWhenSeenStreet2': 1.0, + 'wonWhenSeenStreet3': 1.0, 'wonWhenSeenStreet4': 0.0}, u'player4': { 'card1': 0, 'card2': 0, @@ -431,7 +431,7 @@ 'street1CheckCallRaiseChance': False, 'street1CheckCallRaiseDone': False, 'street1Raises': 0, - 'street1Seen': False, + 'street1Seen': True, 'street2Aggr': False, 'street2Bets': 0, 'street2CBChance': False, @@ -440,7 +440,7 @@ 'street2CheckCallRaiseChance': False, 'street2CheckCallRaiseDone': False, 'street2Raises': 0, - 'street2Seen': False, + 'street2Seen': True, 'street3Aggr': False, 'street3Bets': 0, 'street3CBChance': False, @@ -449,7 +449,7 @@ 'street3CheckCallRaiseChance': False, 'street3CheckCallRaiseDone': False, 'street3Raises': 0, - 'street3Seen': False, + 'street3Seen': True, 'street4Aggr': False, 'street4Bets': 0, 'street4CBChance': False, From 0075d00020680961ca28082cbfbd056bce339ae7 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 4 Jan 2011 14:48:18 +0800 Subject: [PATCH 09/83] Regression: Everleaf streetXseen and wonWhenSeenStreetX fixes Verify and correct 3way aipf hand Adds 12 new errors for Everleaf - Total 55 --- ...SD-0.01-0.02-201008.2Way.All-in.pre.txt.hp | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/pyfpdb/regression-test-files/cash/Everleaf/Flop/NLHE-10max-USD-0.01-0.02-201008.2Way.All-in.pre.txt.hp b/pyfpdb/regression-test-files/cash/Everleaf/Flop/NLHE-10max-USD-0.01-0.02-201008.2Way.All-in.pre.txt.hp index e14f853c..53d34e60 100644 --- a/pyfpdb/regression-test-files/cash/Everleaf/Flop/NLHE-10max-USD-0.01-0.02-201008.2Way.All-in.pre.txt.hp +++ b/pyfpdb/regression-test-files/cash/Everleaf/Flop/NLHE-10max-USD-0.01-0.02-201008.2Way.All-in.pre.txt.hp @@ -55,7 +55,7 @@ 'street1CheckCallRaiseChance': False, 'street1CheckCallRaiseDone': False, 'street1Raises': 0, - 'street1Seen': False, + 'street1Seen': True, 'street2Aggr': False, 'street2Bets': 0, 'street2CBChance': False, @@ -64,7 +64,7 @@ 'street2CheckCallRaiseChance': False, 'street2CheckCallRaiseDone': False, 'street2Raises': 0, - 'street2Seen': False, + 'street2Seen': True, 'street3Aggr': False, 'street3Bets': 0, 'street3CBChance': False, @@ -73,7 +73,7 @@ 'street3CheckCallRaiseChance': False, 'street3CheckCallRaiseDone': False, 'street3Raises': 0, - 'street3Seen': False, + 'street3Seen': True, 'street4Aggr': False, 'street4Bets': 0, 'street4CBChance': False, @@ -337,7 +337,7 @@ 'street1CheckCallRaiseChance': False, 'street1CheckCallRaiseDone': False, 'street1Raises': 0, - 'street1Seen': False, + 'street1Seen': True, 'street2Aggr': False, 'street2Bets': 0, 'street2CBChance': False, @@ -346,7 +346,7 @@ 'street2CheckCallRaiseChance': False, 'street2CheckCallRaiseDone': False, 'street2Raises': 0, - 'street2Seen': False, + 'street2Seen': True, 'street3Aggr': False, 'street3Bets': 0, 'street3CBChance': False, @@ -355,7 +355,7 @@ 'street3CheckCallRaiseChance': False, 'street3CheckCallRaiseDone': False, 'street3Raises': 0, - 'street3Seen': False, + 'street3Seen': True, 'street4Aggr': False, 'street4Bets': 0, 'street4CBChance': False, @@ -370,9 +370,9 @@ 'tourneysPlayersIds': None, 'winnings': 194, 'wonAtSD': 1.0, - 'wonWhenSeenStreet1': 0.0, - 'wonWhenSeenStreet2': 0.0, - 'wonWhenSeenStreet3': 0.0, + 'wonWhenSeenStreet1': 1.0, + 'wonWhenSeenStreet2': 1.0, + 'wonWhenSeenStreet3': 1.0, 'wonWhenSeenStreet4': 0.0}, u'Player5': { 'card1': 0, 'card2': 0, @@ -619,7 +619,7 @@ 'street1CheckCallRaiseChance': False, 'street1CheckCallRaiseDone': False, 'street1Raises': 0, - 'street1Seen': False, + 'street1Seen': True, 'street2Aggr': False, 'street2Bets': 0, 'street2CBChance': False, @@ -628,7 +628,7 @@ 'street2CheckCallRaiseChance': False, 'street2CheckCallRaiseDone': False, 'street2Raises': 0, - 'street2Seen': False, + 'street2Seen': True, 'street3Aggr': False, 'street3Bets': 0, 'street3CBChance': False, @@ -637,7 +637,7 @@ 'street3CheckCallRaiseChance': False, 'street3CheckCallRaiseDone': False, 'street3Raises': 0, - 'street3Seen': False, + 'street3Seen': True, 'street4Aggr': False, 'street4Bets': 0, 'street4CBChance': False, From 1dffbbc81a2ba6a53d36c0e35edc592131fcf744 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 5 Jan 2011 11:29:46 +0800 Subject: [PATCH 10/83] Win2day: Fix addBlind string for SBBB --- pyfpdb/Win2dayToFpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Win2dayToFpdb.py b/pyfpdb/Win2dayToFpdb.py index e704e11b..4d2c442f 100755 --- a/pyfpdb/Win2dayToFpdb.py +++ b/pyfpdb/Win2dayToFpdb.py @@ -221,7 +221,7 @@ class Win2day(HandHistoryConverter): for a in self.re_PostBB.finditer(hand.handText): hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB')) for a in self.re_PostBoth.finditer(hand.handText): - hand.addBlind(a.group('PNAME'), 'small & big blinds', a.group('SBBB')) + hand.addBlind(a.group('PNAME'), 'both', a.group('SBBB')) def readHeroCards(self, hand): # streets PREFLOP, PREDRAW, and THIRD are special cases beacause From c2e553751e0db87b053fb26726c0b4e37d0af8fe Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 5 Jan 2011 14:26:49 +0800 Subject: [PATCH 11/83] FTPSummary: Fix 'Daily Dollar' summary file Also comment out some noisy debug --- pyfpdb/FullTiltPokerSummary.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pyfpdb/FullTiltPokerSummary.py b/pyfpdb/FullTiltPokerSummary.py index d3bcf191..7c65a82f 100644 --- a/pyfpdb/FullTiltPokerSummary.py +++ b/pyfpdb/FullTiltPokerSummary.py @@ -57,7 +57,7 @@ class FullTiltPokerSummary(TourneySummary): re_TourneyInfo = re.compile(u""" \s.* - (?PTournament|Sit\s\&\sGo|\(Rebuy\))\s\((?P[0-9]+)\)(\s+)? + (?PTournament|Sit\s\&\sGo|\(Rebuy\)|)\s\((?P[0-9]+)\)(\s+)? (?PHold\'em|Razz|RAZZ|7\sCard\sStud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball|5\sCard\sDraw)\s+ (?PNo\sLimit|Limit|LIMIT|Pot\sLimit)\s+ (Buy-In:\s\$(?P[.\d]+)(\s\+\s\$(?P[.\d]+))?\s+)? @@ -86,14 +86,14 @@ class FullTiltPokerSummary(TourneySummary): codepage = ["utf-16", "cp1252", "utf-8"] def parseSummary(self): - m = self.re_TourneyInfo.search(self.summaryText) + 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")) raise FpdbParseError(_("Unable to recognise Tourney Info: '%s'") % tmp) - print "DEBUG: m.groupdict(): %s" % m.groupdict() + #print "DEBUG: m.groupdict(): %s" % m.groupdict() mg = m.groupdict() if 'TOURNO' in mg: self.tourNo = mg['TOURNO'] @@ -128,7 +128,7 @@ class FullTiltPokerSummary(TourneySummary): m = self.re_Player.finditer(self.summaryText) for a in m: mg = a.groupdict() - print "DEBUG: a.groupdict(): %s" % mg + #print "DEBUG: a.groupdict(): %s" % mg name = mg['NAME'] rank = mg['RANK'] winnings = 0 From 7f9f4c80cbe1f91012396d54b1f36a820c7d54b5 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 5 Jan 2011 14:27:44 +0800 Subject: [PATCH 12/83] Regression: Add FTP 'Daily Dollary' summary file --- .../FTP/NLHE-USD-MTT-1-201012.No.rake.txt | Bin 0 -> 327666 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 pyfpdb/regression-test-files/summaries/FTP/NLHE-USD-MTT-1-201012.No.rake.txt diff --git a/pyfpdb/regression-test-files/summaries/FTP/NLHE-USD-MTT-1-201012.No.rake.txt b/pyfpdb/regression-test-files/summaries/FTP/NLHE-USD-MTT-1-201012.No.rake.txt new file mode 100644 index 0000000000000000000000000000000000000000..338e26667302768ed9a045e14890111d4c3a3ed0 GIT binary patch literal 327666 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

OYj?)>Lv{y66T_tv38xc9%EsK%a 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 Date: Wed, 5 Jan 2011 14:33:44 +0800 Subject: [PATCH 13/83] Regression: Add failing 'Daily Euro' Summary file --- .../summaries/FTP/NLHE-EUR-MTT-1-201012.txt | Bin 0 -> 32934 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 pyfpdb/regression-test-files/summaries/FTP/NLHE-EUR-MTT-1-201012.txt diff --git a/pyfpdb/regression-test-files/summaries/FTP/NLHE-EUR-MTT-1-201012.txt b/pyfpdb/regression-test-files/summaries/FTP/NLHE-EUR-MTT-1-201012.txt new file mode 100644 index 0000000000000000000000000000000000000000..e6d925cc14cc31e3c02353f049b98121e42a0bfc GIT binary patch literal 32934 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 literal 0 HcmV?d00001 From b0faf02d2801ba1614e86c74adfbca904876ae80 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 5 Jan 2011 14:52:35 +0800 Subject: [PATCH 14/83] Regression: Add FTP Rush rebuy MTT summary file --- .../FTP/NLHE-USD-Rush-MTT-1-201012.No.cash.txt | Bin 0 -> 952 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 pyfpdb/regression-test-files/summaries/FTP/NLHE-USD-Rush-MTT-1-201012.No.cash.txt diff --git a/pyfpdb/regression-test-files/summaries/FTP/NLHE-USD-Rush-MTT-1-201012.No.cash.txt b/pyfpdb/regression-test-files/summaries/FTP/NLHE-USD-Rush-MTT-1-201012.No.cash.txt new file mode 100644 index 0000000000000000000000000000000000000000..fcea192f71d28b2e49755b5bef407cd169573b3e GIT binary patch literal 952 zcmaKrPfr3d5XIlw#P869i5f+rh$1&7_$M(+l$-H@vP2>aWET(k;nm;Ntc%5vre${e zX6DVC^7VP4ca2$2J&pLCV|6vvn-XQgI|Y$xqP|jmlYn@@m$LfYEI@6krmFVYww&&{ z&-IFRiDf9K9lVL2`Ce!@e0#7bMAp^N5vv;fS5zNspl#48xLdxRZeW+P=i1bU&O?@p zuHn<-*6KU$1*@uqz{YTA@qH2;o;P# z;}NlW;8de4QzPaP<4lDDSLTmV%h~EWCc^l1!aOpnCRDXbJvh%%+$Or*eaXqAcZ@9S z7C4)XXC^VSiy|X^Q19oR*sKZ-8@zxfF{i&#t1l-H>@rSM)grBbdp(Dop3~Ev!>(~_ zowkBHrbnCZoF4y)XoNgIis*oUTEk^XClj{4)b(tPqw#2Rdgi*Gjqx}A{zjB+Ow;nM Z#VlN4WeS* Date: Wed, 5 Jan 2011 15:21:03 +0800 Subject: [PATCH 15/83] Regression: Stars Cap streetXseen and wonWhenSeenStreetX values Adds 9 new failures to THP - Total 64 --- ...-USD-0.25-0.50-201011.Capped.preflop.txt.hp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-CAP-9max-USD-0.25-0.50-201011.Capped.preflop.txt.hp b/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-CAP-9max-USD-0.25-0.50-201011.Capped.preflop.txt.hp index d2231a26..3e134e68 100644 --- a/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-CAP-9max-USD-0.25-0.50-201011.Capped.preflop.txt.hp +++ b/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-CAP-9max-USD-0.25-0.50-201011.Capped.preflop.txt.hp @@ -55,7 +55,7 @@ 'street1CheckCallRaiseChance': False, 'street1CheckCallRaiseDone': False, 'street1Raises': 0, - 'street1Seen': False, + 'street1Seen': True, 'street2Aggr': False, 'street2Bets': 0, 'street2CBChance': False, @@ -64,7 +64,7 @@ 'street2CheckCallRaiseChance': False, 'street2CheckCallRaiseDone': False, 'street2Raises': 0, - 'street2Seen': False, + 'street2Seen': True, 'street3Aggr': False, 'street3Bets': 0, 'street3CBChance': False, @@ -73,7 +73,7 @@ 'street3CheckCallRaiseChance': False, 'street3CheckCallRaiseDone': False, 'street3Raises': 0, - 'street3Seen': False, + 'street3Seen': True, 'street4Aggr': False, 'street4Bets': 0, 'street4CBChance': False, @@ -619,7 +619,7 @@ 'street1CheckCallRaiseChance': False, 'street1CheckCallRaiseDone': False, 'street1Raises': 0, - 'street1Seen': False, + 'street1Seen': True, 'street2Aggr': False, 'street2Bets': 0, 'street2CBChance': False, @@ -628,7 +628,7 @@ 'street2CheckCallRaiseChance': False, 'street2CheckCallRaiseDone': False, 'street2Raises': 0, - 'street2Seen': False, + 'street2Seen': True, 'street3Aggr': False, 'street3Bets': 0, 'street3CBChance': False, @@ -637,7 +637,7 @@ 'street3CheckCallRaiseChance': False, 'street3CheckCallRaiseDone': False, 'street3Raises': 0, - 'street3Seen': False, + 'street3Seen': True, 'street4Aggr': False, 'street4Bets': 0, 'street4CBChance': False, @@ -652,7 +652,7 @@ 'tourneysPlayersIds': None, 'winnings': 1900, 'wonAtSD': 1.0, - 'wonWhenSeenStreet1': 0.0, - 'wonWhenSeenStreet2': 0.0, - 'wonWhenSeenStreet3': 0.0, + 'wonWhenSeenStreet1': 1.0, + 'wonWhenSeenStreet2': 1.0, + 'wonWhenSeenStreet3': 1.0, 'wonWhenSeenStreet4': 0.0}} From a9a1be2e09d174eb6234bab11c133a6d62768db5 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 5 Jan 2011 15:42:34 +0800 Subject: [PATCH 16/83] Regression: Stars streetXseen and wonWhenSeenStreetX test data Verified the file and fixed the values. Adds 9 THP failures. Total 73 --- .../NLHE-FR-USD-0.01-0.02-201004.4betPF.txt.hp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-FR-USD-0.01-0.02-201004.4betPF.txt.hp b/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-FR-USD-0.01-0.02-201004.4betPF.txt.hp index 50638df3..811945de 100644 --- a/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-FR-USD-0.01-0.02-201004.4betPF.txt.hp +++ b/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-FR-USD-0.01-0.02-201004.4betPF.txt.hp @@ -243,7 +243,7 @@ 'street1CheckCallRaiseChance': False, 'street1CheckCallRaiseDone': False, 'street1Raises': 0, - 'street1Seen': False, + 'street1Seen': True, 'street2Aggr': False, 'street2Bets': 0, 'street2CBChance': False, @@ -252,7 +252,7 @@ 'street2CheckCallRaiseChance': False, 'street2CheckCallRaiseDone': False, 'street2Raises': 0, - 'street2Seen': False, + 'street2Seen': True, 'street3Aggr': False, 'street3Bets': 0, 'street3CBChance': False, @@ -261,7 +261,7 @@ 'street3CheckCallRaiseChance': False, 'street3CheckCallRaiseDone': False, 'street3Raises': 0, - 'street3Seen': False, + 'street3Seen': True, 'street4Aggr': False, 'street4Bets': 0, 'street4CBChance': False, @@ -431,7 +431,7 @@ 'street1CheckCallRaiseChance': False, 'street1CheckCallRaiseDone': False, 'street1Raises': 0, - 'street1Seen': False, + 'street1Seen': True, 'street2Aggr': False, 'street2Bets': 0, 'street2CBChance': False, @@ -440,7 +440,7 @@ 'street2CheckCallRaiseChance': False, 'street2CheckCallRaiseDone': False, 'street2Raises': 0, - 'street2Seen': False, + 'street2Seen': True, 'street3Aggr': False, 'street3Bets': 0, 'street3CBChance': False, @@ -449,7 +449,7 @@ 'street3CheckCallRaiseChance': False, 'street3CheckCallRaiseDone': False, 'street3Raises': 0, - 'street3Seen': False, + 'street3Seen': True, 'street4Aggr': False, 'street4Bets': 0, 'street4CBChance': False, @@ -464,9 +464,9 @@ 'tourneysPlayersIds': None, 'winnings': 279, 'wonAtSD': 1.0, - 'wonWhenSeenStreet1': 0.0, - 'wonWhenSeenStreet2': 0.0, - 'wonWhenSeenStreet3': 0.0, + 'wonWhenSeenStreet1': 1.0, + 'wonWhenSeenStreet2': 1.0, + 'wonWhenSeenStreet3': 1.0, 'wonWhenSeenStreet4': 0.0}, u'Player5': { 'card1': 0, 'card2': 0, From b1703a95ecb0e876a082ecda9ea0affcf8126735 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 5 Jan 2011 15:55:17 +0800 Subject: [PATCH 17/83] Regression: Stars wonWhenSeenStreetX test file fixes. Adds 3 THP failures - Total 76 --- .../Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt.hp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt.hp b/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt.hp index a073d0c1..390b2e99 100644 --- a/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt.hp +++ b/pyfpdb/regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Allin-pre.txt.hp @@ -88,9 +88,9 @@ 'tourneysPlayersIds': None, 'winnings': 3935, 'wonAtSD': 1.0, - 'wonWhenSeenStreet1': 0.0, - 'wonWhenSeenStreet2': 0.0, - 'wonWhenSeenStreet3': 0.0, + 'wonWhenSeenStreet1': 1.0, + 'wonWhenSeenStreet2': 1.0, + 'wonWhenSeenStreet3': 1.0, 'wonWhenSeenStreet4': 0.0}, u'Arbaz': { 'card1': 0, 'card2': 0, From f12bc7bfaa399880627f240583d2098d2b99894a Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 7 Jan 2011 13:58:15 +0800 Subject: [PATCH 18/83] Add printdata capability for Gametype info. --- pyfpdb/Database.py | 16 ++++++++++++---- pyfpdb/Hand.py | 4 ++-- pyfpdb/fpdb_import.py | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 8ed0e3bc..e3a8e82e 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -2169,7 +2169,7 @@ class Database: dup = True return dup - def getGameTypeId(self, siteid, game): + def getGameTypeId(self, siteid, game, printdata = False): c = self.get_cursor() #FIXME: Fixed for NL at the moment c.execute(self.sql.query['getGametypeNL'], (siteid, game['type'], game['category'], game['limitType'], game['currency'], @@ -2181,14 +2181,22 @@ class Database: hilo = "s" elif game['category'] in ['razz','27_3draw','badugi', '27_1draw']: hilo = "l" + #FIXME: recognise currency + #TODO: this wont work for non-standard structures tmp = self.insertGameTypes( (siteid, game['currency'], game['type'], game['base'], game['category'], game['limitType'], hilo, int(Decimal(game['sb'])*100), int(Decimal(game['bb'])*100), - int(Decimal(game['bb'])*100), int(Decimal(game['bb'])*200)) ) #TODO: this wont work for non-standard structures - #FIXME: recognise currency + int(Decimal(game['bb'])*100), int(Decimal(game['bb'])*200)), printdata = printdata) return tmp[0] - def insertGameTypes(self, row): + def insertGameTypes(self, row, printdata = False): + if printdata: + print _("######## Gametype ##########") + import pprint + pp = pprint.PrettyPrinter(indent=4) + pp.pprint(row) + print _("###### End Gametype ########") + c = self.get_cursor() c.execute( self.sql.query['insertGameTypes'], row ) return [self.get_last_insert_id(c)] diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 405a56e5..0556cc9e 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -226,7 +226,7 @@ dealt whether they were seen in a 'dealt to' line self.holecards[street][player] = [open, closed] - def prepInsert(self, db): + def prepInsert(self, db, printtest = False): ##### # Players, Gametypes, TourneyTypes are all shared functions that are needed for additional tables # These functions are intended for prep insert eventually @@ -235,7 +235,7 @@ dealt whether they were seen in a 'dealt to' line self.dbid_pids = db.getSqlPlayerIDs([p[1] for p in self.players], self.siteId) #Gametypes - self.dbid_gt = db.getGameTypeId(self.siteId, self.gametype) + self.dbid_gt = db.getGameTypeId(self.siteId, self.gametype, printdata = printtest) if self.tourNo!=None: self.tourneyTypeId = db.createTourneyType(self) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index ba1251ac..5fb43632 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -477,7 +477,7 @@ class Importer: for hand in handlist: if hand is not None: - hand.prepInsert(self.database) + hand.prepInsert(self.database, printtest = self.settings['testData']) try: hand.insert(self.database, printtest = self.settings['testData']) except Exceptions.FpdbHandDuplicate: From 503c00e1b03417fd8f53d7b3c139f1ebfbfab672 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 7 Jan 2011 16:08:31 +0800 Subject: [PATCH 19/83] Remove unused minPrint option --- pyfpdb/GuiAutoImport.py | 4 ---- pyfpdb/GuiBulkImport.py | 4 ---- pyfpdb/fpdb_import.py | 4 ---- 3 files changed, 12 deletions(-) diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py index 03bec89d..70a12215 100755 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -59,7 +59,6 @@ class GuiAutoImport (threading.Thread): self.importer = fpdb_import.Importer(self, self.settings, self.config, self.sql) self.importer.setCallHud(True) - self.importer.setMinPrint(settings['minPrint']) self.importer.setQuiet(False) self.importer.setFailOnError(False) self.importer.setHandCount(0) @@ -338,14 +337,11 @@ if __name__== "__main__": parser = OptionParser() parser.add_option("-q", "--quiet", action="store_false", dest="gui", default=True, help="don't start gui") - parser.add_option("-m", "--minPrint", "--status", dest="minPrint", default="0", type="int", - help=_("How often to print a one-line status report (0 (default) means never)")) (options, argv) = parser.parse_args() config = Configuration.Config() settings = {} - settings['minPrint'] = options.minPrint if os.name == 'nt': settings['os'] = 'windows' else: settings['os'] = 'linuxmac' diff --git a/pyfpdb/GuiBulkImport.py b/pyfpdb/GuiBulkImport.py index 5ea0a24b..ba6c1123 100755 --- a/pyfpdb/GuiBulkImport.py +++ b/pyfpdb/GuiBulkImport.py @@ -68,7 +68,6 @@ class GuiBulkImport(): # get the import settings from the gui and save in the importer self.importer.setHandCount(int(self.spin_hands.get_text())) - self.importer.setMinPrint(int(self.spin_hands.get_text())) self.importer.setQuiet(self.chk_st_st.get_active()) self.importer.setFailOnError(self.chk_fail.get_active()) self.importer.setThreads(int(self.spin_threads.get_text())) @@ -344,8 +343,6 @@ def main(argv=None): help=_("Conversion filter (*Full Tilt Poker, PokerStars, Everleaf, Absolute)")) parser.add_option("-x", "--failOnError", action="store_true", default=False, help=_("If this option is passed it quits when it encounters any error")) - parser.add_option("-m", "--minPrint", "--status", dest="minPrint", default="0", type="int", - help=_("How often to print a one-line status report (0 (default) means never)")) parser.add_option("-u", "--usage", action="store_true", dest="usage", default=False, help=_("Print some useful one liners")) parser.add_option("-s", "--starsarchive", action="store_true", dest="starsArchive", default=False, @@ -369,7 +366,6 @@ def main(argv=None): config = Configuration.Config() settings = {} - settings['minPrint'] = options.minPrint if os.name == 'nt': settings['os'] = 'windows' else: settings['os'] = 'linuxmac' diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 5fb43632..ee43ce8e 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -86,7 +86,6 @@ class Importer: self.cacheSessions = self.config.get_import_parameters().get("cacheSessions") # CONFIGURATION OPTIONS - self.settings.setdefault("minPrint", 30) self.settings.setdefault("handCount", 0) #self.settings.setdefault("allowHudcacheRebuild", True) # NOT USED NOW #self.settings.setdefault("forceThreads", 2) # NOT USED NOW @@ -115,9 +114,6 @@ class Importer: def setCacheSessions(self, value): self.cacheSessions = value - def setMinPrint(self, value): - self.settings['minPrint'] = int(value) - def setHandCount(self, value): self.settings['handCount'] = int(value) From 36e2ef3f35613ec19197bb99fecef0a11cf94ffc Mon Sep 17 00:00:00 2001 From: gimick Date: Thu, 30 Dec 2010 23:49:39 +0000 Subject: [PATCH 20/83] rushnotes: initial commit (for testing and eval only) --- pyfpdb/RushNotesAux.py | 216 +++++++++++++++++++++++++++++++++++++ pyfpdb/RushNotesMerge.py | 122 +++++++++++++++++++++ pyfpdb/RushNotesReadMe.txt | 166 ++++++++++++++++++++++++++++ 3 files changed, 504 insertions(+) create mode 100644 pyfpdb/RushNotesAux.py create mode 100755 pyfpdb/RushNotesMerge.py create mode 100644 pyfpdb/RushNotesReadMe.txt diff --git a/pyfpdb/RushNotesAux.py b/pyfpdb/RushNotesAux.py new file mode 100644 index 00000000..bb1ff506 --- /dev/null +++ b/pyfpdb/RushNotesAux.py @@ -0,0 +1,216 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +"""RushNotesAux.py + + EXPERIMENTAL - USE WITH CARE + +Auxilliary process to push HUD data into the FullTilt player notes XML +This will allow a rudimentary "HUD" in rush games + +The existing notes file will be altered by this function +""" +# Copyright 2010, "Gimick" of the FPDB project fpdb.sourceforge.net +# +#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 . +#In the "official" distribution you can find the license in agpl-3.0.txt. + +######################################################################## + +##########for each hand processed, attempts to update hero.xml player notes for FullTilt +##########based upon the AW howto notes written by Ray E. Barker (nutomatic) at fpdb.sourceforge.net + +#to do +### think about seeding +### multiple huds firing at the same xml +### same player / two levels / only one xml +### http://www.faqs.org/docs/diveintopython/kgp_search.html + +#debugmode will write logfiles for the __init__ and update_data methods +debugmode = False + +# Standard Library modules +import os +from xml.dom import minidom +from datetime import datetime +from time import * + +# FreePokerDatabase modules +from Mucked import Aux_Window +from Mucked import Seat_Window +from Mucked import Aux_Seats +import Stats + +class RushNotes(Aux_Window): + + def __init__(self, hud, config, params): + + self.hud = hud + self.config = config + + # + # following line makes all the site params magically available (thanks Ray!) + # + site_params_dict = self.hud.config.get_site_parameters(self.hud.site) + + heroname = site_params_dict['screen_name'] + sitename = site_params_dict['site_name'] + notepath = site_params_dict['site_path'] # this is a temporary hijack of site-path + notepath = r"/home/steve/.wine/drive_c/Program Files/Full Tilt Poker/" + self.heroid = self.hud.db_connection.get_player_id(self.config, sitename, heroname) + self.notefile = notepath + "/" + heroname + ".xml" + + # + # read in existing notefile and backup with date/time in name + # todo change to not use dom + # + now = datetime.now() + notefilebackup = self.notefile + ".backup." + now.strftime("%Y%m%d%H%M%S") + xmlnotefile = minidom.parse(self.notefile) + outputfile = open(notefilebackup, 'w') + xmlnotefile.writexml(outputfile) + outputfile.close() + xmlnotefile.unlink + + # Create a fresh queue file with skeleton XML + # + self.queuefile = self.notefile + ".queue" + queuedom = minidom.Document() + # Create the minidom document + +# Create the base element + pld=queuedom.createElement("PLAYERDATA") + queuedom.appendChild(pld) + + nts=queuedom.createElement("NOTES") + pld.appendChild(nts) + + nte = queuedom.createElement("NOTE") + nte = queuedom.createTextNode("\n") + nts.insertBefore(nte,None) + + outputfile = open(self.queuefile, 'w') + queuedom.writexml(outputfile) + outputfile.close() + queuedom.unlink + + if (debugmode): + #initialise logfiles + debugfile=open("~Rushdebug.init", "w") + debugfile.write("conf="+str(config)+"\n") + debugfile.write("spdi="+str(site_params_dict)+"\n") + debugfile.write("para="+str(params)+"\n") + debugfile.write("hero="+heroname+" "+str(self.heroid)+"\n") + debugfile.write("back="+notefilebackup+"\n") + debugfile.write("queu="+self.queuefile+"\n") + debugfile.close() + + open("~Rushdebug.data", "w").close() + + + def update_data(self, new_hand_id, db_connection): + #this method called once for every hand processed + # self.hud.stat_dict contains the stats information for this hand + + + + if (debugmode): + debugfile=open("~Rushdebug.data", "a") + debugfile.write(new_hand_id+"\n") + now = datetime.now() + debugfile.write(now.strftime("%Y%m%d%H%M%S")+ " update_data begins"+ "\n") + debugfile.write("hero="+str(self.heroid)+"\n") + #debugfile.write(str(self.hud.stat_dict)+"\n") + debugfile.write(self.hud.table.name+"\n") + debugfile.write(str(self.hud.stat_dict.keys())+"\n") + + if self.hud.table.name not in {"Mach 10", "Lightning", "Celerity", "Flash", "Zoom"} + return + # + # Grab a list of player id's + # + handplayers = self.hud.stat_dict.keys() + + # + # build a dictionary of stats text for each player in the hand (excluding the hero) + # xmlqueuedict contains {playername : stats text} + # + xmlqueuedict = {} + for playerid in handplayers: + # ignore hero, no notes available for hero at Full Tilt + if playerid == self.heroid: continue + + playername=unicode(str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'playername')[1])) + # Use index[3] which is a short description + n=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'n')[3] + " ") + vpip=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'vpip')[3] + " ") + pfr=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'pfr')[3] + " ") + three_B=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'three_B')[3] + " ") + cbet=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'cbet')[3] + " ") + steal=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'steal')[3] + " ") + ffreq1=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'ffreq1')[3] + " ") + agg_freq=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'agg_freq')[3] + " ") + BBper100=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'BBper100')[3] + " ") + + xmlqueuedict[playername] = "~fpdb~" + n + vpip + pfr + three_B + cbet + steal + ffreq1 + agg_freq + BBper100 + "~ends~" + + if (debugmode): + now = datetime.now() + debugfile.write(now.strftime("%Y%m%d%H%M%S")+" villain data has been processed" + "\n") + debugfile.write(str(xmlqueuedict)+"\n") + + # + # delaying processing of xml until now. Grab current queuefile contents and + # read each existing NOTE element in turn, if matched to a player in xmlqueuedict + # update their text in the xml and delete the dictionary item + # + xmlnotefile = minidom.parse(self.queuefile) + notelist = xmlnotefile.getElementsByTagName('NOTE') + + for noteentry in notelist: #for each note in turn + noteplayer = noteentry.getAttribute("PlayerId") #extract the playername from xml + if noteplayer in xmlqueuedict: # does that player exist in the queue? + noteentry.setAttribute("Text",xmlqueuedict[noteplayer]) + del xmlqueuedict[noteplayer] #remove from list, does not need to be added later on + + # + #create entries for new players (those remaining in the dictionary) + # + if len(xmlqueuedict) > 0: + playerdata=xmlnotefile.lastChild #move to the PLAYERDATA node (assume last one in the list) + notesnode=playerdata.childNodes[0] #Find NOTES node + + for newplayer in xmlqueuedict: + newentry = xmlnotefile.createElement("NOTE") + newentry.setAttribute("PlayerId", newplayer) + newentry.setAttribute("Text", xmlqueuedict[newplayer]) + notesnode.insertBefore(newentry,None) + newentry = xmlnotefile.createTextNode("\n") + notesnode.insertBefore(newentry,None) + + if (debugmode): + now = datetime.now() + debugfile.write(now.strftime("%Y%m%d%H%M%S")+" xml pre-processing complete"+ "\n") + + # + # OverWrite existing xml file with updated DOM and cleanup + # + updatednotes = open(self.queuefile, 'w') + xmlnotefile.writexml(updatednotes) + updatednotes.close() + + xmlnotefile.unlink + + if (debugmode): + now = datetime.now() + debugfile.write(now.strftime("%Y%m%d%H%M%S")+" dom written, process finished"+ "\n") + debugfile.close() diff --git a/pyfpdb/RushNotesMerge.py b/pyfpdb/RushNotesMerge.py new file mode 100755 index 00000000..ec8896d1 --- /dev/null +++ b/pyfpdb/RushNotesMerge.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +"""RushNotesMerge.py + + EXPERIMENTAL - USE WITH CARE + +Merge .queue file with hero's note to generate fresh .merge file + +normal usage +$> ./pyfpdb/RushNotesMerge.py "/home/steve/.wine/drive_c/Program Files/Full Tilt Poker/heroname.xml" + +The generated file can then replace heroname.xml (if all is well). + + +""" +# Copyright 2010, "Gimick" of the FPDB project fpdb.sourceforge.net +# +#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 . +#In the "official" distribution you can find the license in agpl-3.0.txt. + +######################################################################## + + +# Standard Library modules +import os +import sys +from xml.dom import minidom + +statqueue=0 +statupdated=0 +statadded=0 + +def cleannote(textin): + if textin.find("~fpdb~") == -1: return textin + if textin.find("~ends~") == -1: return textin + if textin.find("~fpdb~") > textin.find("~ends~"): return textin + return textin[0:textin.find("~fpdb~")] + textin[textin.find("~ends~")+6:] +# get out now if parameter not passed +try: + sys.argv[1] <> "" +except: + print "A parameter is required, quitting now" + quit() + +if not os.path.isfile(sys.argv[1]): + print "Hero notes file not found, quitting" + quit() + +if not os.path.isfile((sys.argv[1]+".queue")): + print "Nothing queued, quitting" + quit() + +print "reading from: ", sys.argv[1] +print "merging with: ", sys.argv[1]+".queue" + +#read queue and turn into a dict +queuedict = {} +xmlqueue = minidom.parse(sys.argv[1]+".queue") +notelist = xmlqueue.getElementsByTagName('NOTE') + +for noteentry in notelist: + noteplayer = noteentry.getAttribute("PlayerId") + notetext = noteentry.getAttribute("Text") + queuedict[noteplayer] = notetext + statqueue = statqueue + 1 + +#read existing player note file + +xmlnotefile = minidom.parse(sys.argv[1]) +notelist = xmlnotefile.getElementsByTagName('NOTE') + +# +#for existing players, empty out existing fpdbtext and refill +# +for noteentry in notelist: + noteplayer = noteentry.getAttribute("PlayerId") + if noteplayer in queuedict: + existingnote = noteentry.getAttribute("Text") + newnote=cleannote(existingnote) + newnote = newnote + queuedict[noteplayer] + noteentry.setAttribute("Text",newnote) + statupdated = statupdated + 1 + del queuedict[noteplayer] + +# +#create entries for new players (those remaining in the dictionary) +# +if len(queuedict) > 0: + playerdata=xmlnotefile.lastChild #move to the PLAYERDATA node (assume last one in the list) + notesnode=playerdata.childNodes[1] #Find NOTES node + +for newplayer in queuedict: + newentry = xmlnotefile.createElement("NOTE") + newentry.setAttribute("PlayerId", newplayer) + newentry.setAttribute("Text", queuedict[newplayer]) + notesnode.insertBefore(newentry,None) + newentry = xmlnotefile.createTextNode("\n") + notesnode.insertBefore(newentry,None) + statadded=statadded+1 + +#print xmlnotefile.toprettyxml() + +mergednotes = open(sys.argv[1]+".merged", 'w') +xmlnotefile.writexml(mergednotes) +mergednotes.close() + +xmlnotefile.unlink + +print "new file has been written to: ", sys.argv[1]+".merged" +print "number in queue: ", statqueue +print "existing players updated: ", statupdated +print "new players added: ", statadded diff --git a/pyfpdb/RushNotesReadMe.txt b/pyfpdb/RushNotesReadMe.txt new file mode 100644 index 00000000..595b5adb --- /dev/null +++ b/pyfpdb/RushNotesReadMe.txt @@ -0,0 +1,166 @@ +aux to write fpdb data to player notes on Full Tilt +--------------------------------------------------- + +by Gimick 30th Dec 2010 + +RushNotesAux - auxillary processed attached to the full tilt hud + builds up fpdb notes "queue" for each villain met while the autoimport is running + uses HUD aggregation stats to do this + +RushNotesMerge - stand alone process to merge the existing ftp notes, together with queue + produced by Aux. + the output file can then be renamed to become the new ftp notes file + +Important info: +The Merge process can only be run when ftp client is shutdown - otherwise ftp overwrites the xml on exit. + +Restarting the autoimport will empty the notes"queue" so avoid restarting autoimport until the previous +notes "queue" has been merged. + +Existing ftp notes _SHOULD_ be preserved, but this isn't guaranteed, you have been warned +Existing colour codings should be preserved, this process should not change colourcodings. + +Copies of the live ftp notes file are preserved everytime RushNotesAux is started, just in case. + +The AW is hard-coded with just the table names of Micro Rush Poker, and should ignore all other hands. + +Getting started: +--------------- + +1. Set the Hero aggregation to alltime. hero_stat_range="A" + This overcomes a sqlite "bug" which has nothing to do with auxillary windows - not doing this + will slow processing down to about 1 hand per minute. + +2. Set the site_path to be the folder containing the FTP notes xml file +(on wine this is normally site_path="/home/blah/.wine/Program Files/Full Tilt Poker/") + + +Wire-up the aux process: +----------------------- + + + + +or whatever works for you. + +Start Autoimport, and rearrange the on-screen stats out of the way + (killing the HUD kills the AW updates) + +Play some poker + +Stop the autoimport +Exit the Full tilt poker client (ensure it has fully stopped with ps -A) + +execute the following: + +./pyfpdb/RushNotesMerge.py "/home/foo/.wine/drive_c/Program Files/Full Tilt Poker/myname.xml" + +A revised notes file (blah.merge) should automagically appear in the full tilt root directory. +If you are happy with it, replace the existing (myname.xml file) + + +Summary +------ + +This is very rough and ready, but it does what I set-out to achieve. + +All feedback welcome, and if this is useful as a basis for general notes processing, then thats great. + +As I find bugs and make improvements, I will push to the git branch. + + +Much more information below: +---------------------------- + +Background +---------- + +When playing rush poker, some sort of rudimentary HUD would answer simple questions +like "is this allin overbet being made by a nit, or a maniac". Although some +notes may have been made previously, some statistics would help to backup the decision. + +Currently fpdb cannot support rush because the HUD is always 1 hand or more +behind the current action. + +The only way to do this at the moment is to switch to GuiPlayerStats and make a quick +enquiry by player name. However, this effectively times you out of all other +action if multitabling. + +Full Tilt situation +------------------- + +Full Tilt notes are stored in xml format ("hero.xml"). Previously these could +be updated while the game was in progress, however, FullTilt now cache the +notes and write them out when the application exits. This makes it impossible +to use the notes as a real-time HUD, and therefore real-time huds are now +forced to screen-scrape or poke around in the client memory. + +Accepting this a limitation, this implementation updates the notes only once +the FullTilt client has been closed. Obviously, the villain HUD stats are only +as at the end of the last session, however, it is hoped this is significantly +better than having nothing at all. As the hero's hand history increases, the +notes should progressively mature in accuracy. + +Preamble +-------- + +Note that this implementation was written purely to be "good enough" to work +for the author, and is not intended as package or production quality. It +is contributed as a starting point for others, or for experimental use. + +Thanks to Ray Barker who gave a great deal of help throughout. + + +The implementation +------------------- + +RushNotesAux is an fpdb auxilliary process, and is called for every hand +processed by autoimport. Each villain has a note prepared based on the current +fpdb data, and this note (in XML format) is stored in a queue file. + +Auxilliary windows were chosen because +a) the author has limited fpdb and programming skill +b) the auxillary windows handler is well documented and supported +c) any code created has access to the full range of stats with little or no extra work +d) runs within the HUD, so the aggregation parameters are already available + + +Limitations +----------- + +The notes are only regenerated if a hand is played against the villain. The +process does not "bulk load" notes based upon all the player stats in FPDB. + +It is hoped that due to the relatively large hand volume and relatively small + player pools, this limitation will be largely overcome after a few sessions +although there will obviously be a number of players with no fpdb note. + +The aggregation parameters used for the notes are based upon the HUD parameters. + +Stopping and starting the HUD will erase the previously created notes holding file. + +The HUD must run, so the individual player popups need to be manually relocated. + +Although hard-coded for micro RUSH tablenames, the auxilliary window will +probably happily update notes of all cash and tournament players. + +Process overview +---------------- + +1/ The HUD process is started. +1.1/ when the first hand is received, h fresh holding file is created, and +a copy of the current live xml note file is created as a security backup. +2/ For every hand played, the auxillary window is called +3/ Based upon the players in the hand, fpdb will be interrogated +and key stats are formatted in xml-style and written out to a holding file. +4/ At the end of the session, the HUD is stopped and the poker client closed + +5/ The user can then review the contents of the holding file. +6/ A process is begun to "merge" the holding file into the existing player notes +7/ A new "merged" file is created. The process attempts to preserve any +existing notes, but this cannot be guaranteed. +8/ The user can review this merged file, and if they are happy, +they replace the existing note file. +9/ Note that this process never updates the live notes file in situ, but +there is a risk that something goes wrong, and that existing notes could be destroyed. + From afaaee1fcf69c82982f97b8aad41549f8aa0d729 Mon Sep 17 00:00:00 2001 From: gimick Date: Fri, 31 Dec 2010 00:19:52 +0000 Subject: [PATCH 21/83] rushnotes: fix typo, switch off debug mode --- pyfpdb/RushNotesAux.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/RushNotesAux.py b/pyfpdb/RushNotesAux.py index bb1ff506..1a87fd78 100644 --- a/pyfpdb/RushNotesAux.py +++ b/pyfpdb/RushNotesAux.py @@ -133,7 +133,7 @@ class RushNotes(Aux_Window): debugfile.write(self.hud.table.name+"\n") debugfile.write(str(self.hud.stat_dict.keys())+"\n") - if self.hud.table.name not in {"Mach 10", "Lightning", "Celerity", "Flash", "Zoom"} + if self.hud.table.name not in ("Mach 10", "Lightning", "Celerity", "Flash", "Zoom"): return # # Grab a list of player id's From ba3883d0b75ef4aeb8bf1b92f94ee14a55c25b4f Mon Sep 17 00:00:00 2001 From: gimick Date: Sat, 1 Jan 2011 18:53:53 +0000 Subject: [PATCH 22/83] rushnotes: tweaks + overcome "lf" bug in minidom + place HUD on multiline --- pyfpdb/RushNotesAux.py | 66 +++++++++++++++++++++++++++++++++++++--- pyfpdb/RushNotesMerge.py | 42 +++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 5 deletions(-) diff --git a/pyfpdb/RushNotesAux.py b/pyfpdb/RushNotesAux.py index 1a87fd78..28e3aaaa 100644 --- a/pyfpdb/RushNotesAux.py +++ b/pyfpdb/RushNotesAux.py @@ -36,10 +36,11 @@ The existing notes file will be altered by this function ### http://www.faqs.org/docs/diveintopython/kgp_search.html #debugmode will write logfiles for the __init__ and update_data methods -debugmode = False +debugmode = True # Standard Library modules import os +import sys from xml.dom import minidom from datetime import datetime from time import * @@ -50,6 +51,48 @@ from Mucked import Seat_Window from Mucked import Aux_Seats import Stats +# +# overload minidom methods to fix bug where \n is parsed as " ". +# described here: http://bugs.python.org/issue7139 +# + +def _write_data(writer, data, isAttrib=False): + "Writes datachars to writer." + if isAttrib: + data = data.replace("\r", " ").replace("\n", " ") + data = data.replace("\t", " ") + writer.write(data) +minidom._write_data = _write_data + +def writexml(self, writer, indent="", addindent="", newl=""): + # indent = current indentation + # addindent = indentation to add to higher levels + # newl = newline string + writer.write(indent+"<" + self.tagName) + + attrs = self._get_attributes() + a_names = attrs.keys() + a_names.sort() + + for a_name in a_names: + writer.write(" %s=\"" % a_name) + _write_data(writer, attrs[a_name].value, isAttrib=True) + writer.write("\"") + if self.childNodes: + writer.write(">%s"%(newl)) + for node in self.childNodes: + node.writexml(writer,indent+addindent,addindent,newl) + writer.write("%s%s" % (indent,self.tagName,newl)) + else: + writer.write("/>%s"%(newl)) +# For an introduction to overriding instance methods, see +# http://irrepupavel.com/documents/python/instancemethod/ +instancemethod = type(minidom.Element.writexml) +minidom.Element.writexml = instancemethod( + writexml, None, minidom.Element) + + + class RushNotes(Aux_Window): def __init__(self, hud, config, params): @@ -65,9 +108,14 @@ class RushNotes(Aux_Window): heroname = site_params_dict['screen_name'] sitename = site_params_dict['site_name'] notepath = site_params_dict['site_path'] # this is a temporary hijack of site-path - notepath = r"/home/steve/.wine/drive_c/Program Files/Full Tilt Poker/" self.heroid = self.hud.db_connection.get_player_id(self.config, sitename, heroname) self.notefile = notepath + "/" + heroname + ".xml" + + if not os.path.isfile(self.notefile): + self.active = False + return + else: + self.active = True # # read in existing notefile and backup with date/time in name @@ -121,7 +169,8 @@ class RushNotes(Aux_Window): #this method called once for every hand processed # self.hud.stat_dict contains the stats information for this hand - + if not self.active: + return if (debugmode): debugfile=open("~Rushdebug.data", "a") @@ -156,13 +205,15 @@ class RushNotes(Aux_Window): pfr=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'pfr')[3] + " ") three_B=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'three_B')[3] + " ") cbet=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'cbet')[3] + " ") + fbbsteal=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'f_BB_steal')[3] + " ") + steal=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'steal')[3] + " ") ffreq1=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'ffreq1')[3] + " ") agg_freq=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'agg_freq')[3] + " ") BBper100=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'BBper100')[3] + " ") - xmlqueuedict[playername] = "~fpdb~" + n + vpip + pfr + three_B + cbet + steal + ffreq1 + agg_freq + BBper100 + "~ends~" - + xmlqueuedict[playername] = "~fpdb~" + n + vpip + pfr + three_B + fbbsteal + "\n" + steal + cbet + ffreq1 + "\n" + agg_freq + BBper100 + "~ends~" + if (debugmode): now = datetime.now() debugfile.write(now.strftime("%Y%m%d%H%M%S")+" villain data has been processed" + "\n") @@ -214,3 +265,8 @@ class RushNotes(Aux_Window): now = datetime.now() debugfile.write(now.strftime("%Y%m%d%H%M%S")+" dom written, process finished"+ "\n") debugfile.close() + + + + + diff --git a/pyfpdb/RushNotesMerge.py b/pyfpdb/RushNotesMerge.py index ec8896d1..8d46c3fa 100755 --- a/pyfpdb/RushNotesMerge.py +++ b/pyfpdb/RushNotesMerge.py @@ -36,6 +36,48 @@ import os import sys from xml.dom import minidom +# +# overload minidom methods to fix bug where \n is parsed as " ". +# described here: http://bugs.python.org/issue7139 +# + +def _write_data(writer, data, isAttrib=False): + "Writes datachars to writer." + if isAttrib: + data = data.replace("\r", " ").replace("\n", " ") + data = data.replace("\t", " ") + writer.write(data) +minidom._write_data = _write_data + +def writexml(self, writer, indent="", addindent="", newl=""): + # indent = current indentation + # addindent = indentation to add to higher levels + # newl = newline string + writer.write(indent+"<" + self.tagName) + + attrs = self._get_attributes() + a_names = attrs.keys() + a_names.sort() + + for a_name in a_names: + writer.write(" %s=\"" % a_name) + _write_data(writer, attrs[a_name].value, isAttrib=True) + writer.write("\"") + if self.childNodes: + writer.write(">%s"%(newl)) + for node in self.childNodes: + node.writexml(writer,indent+addindent,addindent,newl) + writer.write("%s%s" % (indent,self.tagName,newl)) + else: + writer.write("/>%s"%(newl)) +# For an introduction to overriding instance methods, see +# http://irrepupavel.com/documents/python/instancemethod/ +instancemethod = type(minidom.Element.writexml) +minidom.Element.writexml = instancemethod( + writexml, None, minidom.Element) + + + statqueue=0 statupdated=0 statadded=0 From 96275f9f1e0685019ef77e8fdfffde72c7bfd478 Mon Sep 17 00:00:00 2001 From: gimick Date: Wed, 5 Jan 2011 22:35:42 +0000 Subject: [PATCH 23/83] rushnotes: more tweaks - add LF's and brackets for negative BB100 --- pyfpdb/RushNotesAux.py | 11 ++++++++--- pyfpdb/RushNotesMerge.py | 19 ++++++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/pyfpdb/RushNotesAux.py b/pyfpdb/RushNotesAux.py index 28e3aaaa..3a445a0f 100644 --- a/pyfpdb/RushNotesAux.py +++ b/pyfpdb/RushNotesAux.py @@ -36,7 +36,7 @@ The existing notes file will be altered by this function ### http://www.faqs.org/docs/diveintopython/kgp_search.html #debugmode will write logfiles for the __init__ and update_data methods -debugmode = True +debugmode = False # Standard Library modules import os @@ -210,9 +210,14 @@ class RushNotes(Aux_Window): steal=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'steal')[3] + " ") ffreq1=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'ffreq1')[3] + " ") agg_freq=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'agg_freq')[3] + " ") - BBper100=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'BBper100')[3] + " ") + BBper100=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'BBper100')[3]) + if BBper100[6] == "-": BBper100=BBper100[0:6] + "(" + BBper100[7:] + ")" - xmlqueuedict[playername] = "~fpdb~" + n + vpip + pfr + three_B + fbbsteal + "\n" + steal + cbet + ffreq1 + "\n" + agg_freq + BBper100 + "~ends~" + xmlqueuedict[playername] = ("~fpdb~" + "\n" + + n + vpip + pfr + three_B + fbbsteal + "\n" + + steal + cbet + ffreq1 + "\n" + + agg_freq + BBper100 + "\n" + + "~ends~") if (debugmode): now = datetime.now() diff --git a/pyfpdb/RushNotesMerge.py b/pyfpdb/RushNotesMerge.py index 8d46c3fa..f22b67ab 100755 --- a/pyfpdb/RushNotesMerge.py +++ b/pyfpdb/RushNotesMerge.py @@ -102,8 +102,15 @@ if not os.path.isfile((sys.argv[1]+".queue")): print "Nothing queued, quitting" quit() -print "reading from: ", sys.argv[1] -print "merging with: ", sys.argv[1]+".queue" +print "***************************************************************" +print "IMPORTANT: *** Before running this merge: ***" +print "Closedown the FullTiltClient and wait for it to completely stop" +print "If FullTiltClient was running, run the merge again once it" +print "has stopped completely" +print "***************************************************************" +print +print "read from: ", sys.argv[1] +print "merge with: ", sys.argv[1]+".queue" #read queue and turn into a dict queuedict = {} @@ -158,7 +165,13 @@ mergednotes.close() xmlnotefile.unlink -print "new file has been written to: ", sys.argv[1]+".merged" +print "Merged file has been written to: ", sys.argv[1]+".merged" +print "" print "number in queue: ", statqueue print "existing players updated: ", statupdated print "new players added: ", statadded +print "\n" +print "Use a viewer to check the contents of the merge file." +print "If you are happy, carry out the following steps:" +print "1 Rename or delete the existing notes file (normally .xml" +print "2 Rename the .merged file to become the new notes file" From ae7f983591008d339844dcea1e926eb23bd51eed Mon Sep 17 00:00:00 2001 From: gimick Date: Sat, 8 Jan 2011 23:28:41 +0000 Subject: [PATCH 24/83] rushnotes: major update, show villain ranges in HUD + other tweaks --- pyfpdb/RushNotesAux.py | 128 ++++++++++++++++++++++++++----------- pyfpdb/RushNotesMerge.py | 12 +++- pyfpdb/RushNotesReadMe.txt | 60 ++++++++++++----- 3 files changed, 145 insertions(+), 55 deletions(-) diff --git a/pyfpdb/RushNotesAux.py b/pyfpdb/RushNotesAux.py index 3a445a0f..312de6d5 100644 --- a/pyfpdb/RushNotesAux.py +++ b/pyfpdb/RushNotesAux.py @@ -26,16 +26,14 @@ The existing notes file will be altered by this function ######################################################################## -##########for each hand processed, attempts to update hero.xml player notes for FullTilt +##########for each hand processed, attempts to create update for player notes in FullTilt ##########based upon the AW howto notes written by Ray E. Barker (nutomatic) at fpdb.sourceforge.net +##########Huge thanks to Ray for his guidance and encouragement to create this !! -#to do -### think about seeding -### multiple huds firing at the same xml -### same player / two levels / only one xml -### http://www.faqs.org/docs/diveintopython/kgp_search.html - +# #debugmode will write logfiles for the __init__ and update_data methods +# writes into ./pyfpdb/~Rushdebug.* +# debugmode = False # Standard Library modules @@ -50,9 +48,10 @@ from Mucked import Aux_Window from Mucked import Seat_Window from Mucked import Aux_Seats import Stats +import Card # -# overload minidom methods to fix bug where \n is parsed as " ". +# overload minidom methods to fix bug where \n is parsed as " ". # described here: http://bugs.python.org/issue7139 # @@ -110,7 +109,8 @@ class RushNotes(Aux_Window): notepath = site_params_dict['site_path'] # this is a temporary hijack of site-path self.heroid = self.hud.db_connection.get_player_id(self.config, sitename, heroname) self.notefile = notepath + "/" + heroname + ".xml" - + self.rushtables = ("Mach 10", "Lightning", "Celerity", "Flash", "Zoom") + if not os.path.isfile(self.notefile): self.active = False return @@ -129,28 +129,27 @@ class RushNotes(Aux_Window): outputfile.close() xmlnotefile.unlink + # # Create a fresh queue file with skeleton XML - # + # self.queuefile = self.notefile + ".queue" - queuedom = minidom.Document() - # Create the minidom document + queuedom = minidom.Document() -# Create the base element pld=queuedom.createElement("PLAYERDATA") queuedom.appendChild(pld) nts=queuedom.createElement("NOTES") pld.appendChild(nts) - + nte = queuedom.createElement("NOTE") nte = queuedom.createTextNode("\n") - nts.insertBefore(nte,None) - + nts.insertBefore(nte,None) + outputfile = open(self.queuefile, 'w') queuedom.writexml(outputfile) outputfile.close() queuedom.unlink - + if (debugmode): #initialise logfiles debugfile=open("~Rushdebug.init", "w") @@ -159,19 +158,19 @@ class RushNotes(Aux_Window): debugfile.write("para="+str(params)+"\n") debugfile.write("hero="+heroname+" "+str(self.heroid)+"\n") debugfile.write("back="+notefilebackup+"\n") - debugfile.write("queu="+self.queuefile+"\n") + debugfile.write("queu="+self.queuefile+"\n") debugfile.close() - + open("~Rushdebug.data", "w").close() - + def update_data(self, new_hand_id, db_connection): #this method called once for every hand processed # self.hud.stat_dict contains the stats information for this hand - + if not self.active: return - + if (debugmode): debugfile=open("~Rushdebug.data", "a") debugfile.write(new_hand_id+"\n") @@ -179,10 +178,11 @@ class RushNotes(Aux_Window): debugfile.write(now.strftime("%Y%m%d%H%M%S")+ " update_data begins"+ "\n") debugfile.write("hero="+str(self.heroid)+"\n") #debugfile.write(str(self.hud.stat_dict)+"\n") - debugfile.write(self.hud.table.name+"\n") - debugfile.write(str(self.hud.stat_dict.keys())+"\n") + debugfile.write("table="+self.hud.table.name+"\n") + debugfile.write("players="+str(self.hud.stat_dict.keys())+"\n") + debugfile.write("db="+str(db_connection)+"\n") - if self.hud.table.name not in ("Mach 10", "Lightning", "Celerity", "Flash", "Zoom"): + if self.hud.table.name not in self.rushtables: return # # Grab a list of player id's @@ -212,18 +212,74 @@ class RushNotes(Aux_Window): agg_freq=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'agg_freq')[3] + " ") BBper100=str(Stats.do_stat(self.hud.stat_dict, player = playerid, stat = 'BBper100')[3]) if BBper100[6] == "-": BBper100=BBper100[0:6] + "(" + BBper100[7:] + ")" - - xmlqueuedict[playername] = ("~fpdb~" + "\n" + - n + vpip + pfr + three_B + fbbsteal + "\n" + - steal + cbet + ffreq1 + "\n" + - agg_freq + BBper100 + "\n" + + + + # + # grab villain known starting hands + # only those where they VPIP'd, so limp in the BB will not be shown + # sort by hand strength. Output will show position too, + # so KK.1 is KK from late posn etc. + # ignore non-rush hands (check against known rushtablenames) + # cards decoding is hard-coded for holdem, so that's tuff atm + # three categories of known hands are shown: + # agression preflop hands + # non-aggression preflop hands + # bigblind called to defend hands + # + # This isn't perfect, but it isn't too bad a starting point + # + + PFcall="PFcall" + PFaggr="PFaggr" + PFdefend="PFdefend" + + c = db_connection.get_cursor() + c.execute(("SELECT handId, position, startCards, street0Aggr, tableName " + + "FROM hands, handsPlayers " + + "WHERE handsplayers.handId = hands.id " + + "AND street0VPI = 1 " + + "AND startCards > 0 " + + "AND playerId = %d " + + "ORDER BY startCards DESC " + + ";") + % int(playerid)) + + for (qid, qposition, qstartcards, qstreet0Aggr, qtablename) in c.fetchall(): + if (debugmode): + debugfile.write("pid, hid, pos, cards, aggr, table player"+ + str(playerid)+"/"+str(qid)+"/"+str(qposition)+"/"+ + str(qstartcards)+"/"+str(qstreet0Aggr)+"/"+ + str(qtablename)+"/"+str(playername)+ + "\n") + + humancards = Card.decodeStartHandValue("holdem", qstartcards) + + if qtablename not in self.rushtables: + pass + elif qposition == "B" and qstreet0Aggr == False: + PFdefend=PFdefend+"/"+humancards + elif qstreet0Aggr == True: + PFaggr=PFaggr+"/"+humancards+"."+qposition + else: + PFcall=PFcall+"/"+humancards+"."+qposition + c.close + + # + # build up final text package (top/tail with ~fpdb~ ~ends~ + # for later search/replace by Merge module + # + xmlqueuedict[playername] = ("~fpdb~" + "\n" + + n + vpip + pfr + three_B + fbbsteal + "\n" + + steal + cbet + ffreq1 + "\n" + + agg_freq + BBper100 + "\n" + + PFcall+"\n"+PFaggr+"\n"+PFdefend +"\n" "~ends~") if (debugmode): now = datetime.now() debugfile.write(now.strftime("%Y%m%d%H%M%S")+" villain data has been processed" + "\n") debugfile.write(str(xmlqueuedict)+"\n") - + # # delaying processing of xml until now. Grab current queuefile contents and # read each existing NOTE element in turn, if matched to a player in xmlqueuedict @@ -244,26 +300,26 @@ class RushNotes(Aux_Window): if len(xmlqueuedict) > 0: playerdata=xmlnotefile.lastChild #move to the PLAYERDATA node (assume last one in the list) notesnode=playerdata.childNodes[0] #Find NOTES node - + for newplayer in xmlqueuedict: newentry = xmlnotefile.createElement("NOTE") newentry.setAttribute("PlayerId", newplayer) - newentry.setAttribute("Text", xmlqueuedict[newplayer]) + newentry.setAttribute("Text", xmlqueuedict[newplayer]) notesnode.insertBefore(newentry,None) newentry = xmlnotefile.createTextNode("\n") notesnode.insertBefore(newentry,None) - + if (debugmode): now = datetime.now() debugfile.write(now.strftime("%Y%m%d%H%M%S")+" xml pre-processing complete"+ "\n") - + # # OverWrite existing xml file with updated DOM and cleanup # updatednotes = open(self.queuefile, 'w') xmlnotefile.writexml(updatednotes) updatednotes.close() - + xmlnotefile.unlink if (debugmode): diff --git a/pyfpdb/RushNotesMerge.py b/pyfpdb/RushNotesMerge.py index f22b67ab..7bfec3df 100755 --- a/pyfpdb/RushNotesMerge.py +++ b/pyfpdb/RushNotesMerge.py @@ -7,7 +7,7 @@ Merge .queue file with hero's note to generate fresh .merge file normal usage -$> ./pyfpdb/RushNotesMerge.py "/home/steve/.wine/drive_c/Program Files/Full Tilt Poker/heroname.xml" +$> ./pyfpdb/RushNotesMerge.py "/home/foo/.wine/drive_c/Program Files/Full Tilt Poker/heroname.xml" The generated file can then replace heroname.xml (if all is well). @@ -37,7 +37,7 @@ import sys from xml.dom import minidom # -# overload minidom methods to fix bug where \n is parsed as " ". +# overload minidom methods to fix bug where \n is parsed as " ". # described here: http://bugs.python.org/issue7139 # @@ -92,14 +92,20 @@ try: sys.argv[1] <> "" except: print "A parameter is required, quitting now" + print "normal usage is something like:" + print '$> ./pyfpdb/RushNotesMerge.py "/home/foo/.wine/drive_c/Program Files/Full Tilt Poker/myhero.xml"' quit() if not os.path.isfile(sys.argv[1]): print "Hero notes file not found, quitting" + print "normal usage is something like:" + print '$> ./pyfpdb/RushNotesMerge.py "/home/foo/.wine/drive_c/Program Files/Full Tilt Poker/myhero.xml"' quit() if not os.path.isfile((sys.argv[1]+".queue")): - print "Nothing queued, quitting" + print "Nothing found to merge, quitting" + print "Did the HUD not get started during the last session?" + print "Has the HUD been stopped and started without merging?" quit() print "***************************************************************" diff --git a/pyfpdb/RushNotesReadMe.txt b/pyfpdb/RushNotesReadMe.txt index 595b5adb..43475536 100644 --- a/pyfpdb/RushNotesReadMe.txt +++ b/pyfpdb/RushNotesReadMe.txt @@ -12,24 +12,40 @@ RushNotesMerge - stand alone process to merge the existing ftp notes, together w the output file can then be renamed to become the new ftp notes file Important info: -The Merge process can only be run when ftp client is shutdown - otherwise ftp overwrites the xml on exit. +The Merge process can only be run when ftp client is shutdown + - otherwise ftp overwrites the xml on exit. -Restarting the autoimport will empty the notes"queue" so avoid restarting autoimport until the previous -notes "queue" has been merged. +Restarting the autoimport will empty the notes"queue" so avoid restarting + autoimport until the previous notes "queue" has been merged. You will + lose all the queued notes, but these will be regenerated the next time + the villian is at your table, so it isn't the end of the world. -Existing ftp notes _SHOULD_ be preserved, but this isn't guaranteed, you have been warned -Existing colour codings should be preserved, this process should not change colourcodings. +Existing ftp notes _SHOULD_ be preserved, but this isn't guaranteed, + you have been warned! + +Existing colour codings should be preserved, + this process does not change or set colourcodings. -Copies of the live ftp notes file are preserved everytime RushNotesAux is started, just in case. +Copies of the live ftp notes file should be preserved everytime + RushNotesAux (i.e. the HUD is started) -The AW is hard-coded with just the table names of Micro Rush Poker, and should ignore all other hands. +The AW is hard-coded with just the table names of Micro Rush Poker, + and should ignore all other hands. +What might not work? +-------------------- + +This isn't tested with Windows, and probably won't work, feedback welcome. +Hasn't been tested for co-existance with other sites, feedback welcome. +Whenever FTP change their notes file format, this will all break rather spectacularly, + you have been warned! + Getting started: --------------- 1. Set the Hero aggregation to alltime. hero_stat_range="A" - This overcomes a sqlite "bug" which has nothing to do with auxillary windows - not doing this - will slow processing down to about 1 hand per minute. + This overcomes a sqlite "bug" which has nothing to do with auxillary windows + not doing this will slow processing down to about 1 hand per minute. 2. Set the site_path to be the folder containing the FTP notes xml file (on wine this is normally site_path="/home/blah/.wine/Program Files/Full Tilt Poker/") @@ -43,12 +59,17 @@ Wire-up the aux process: or whatever works for you. -Start Autoimport, and rearrange the on-screen stats out of the way - (killing the HUD kills the AW updates) Play some poker +--------------- + +Start Autoimport, and rearrange the on-screen stats out of the way + (the full HUD must run, killing the HUD kills the AW updates) + +Play whatever you want Stop the autoimport + Exit the Full tilt poker client (ensure it has fully stopped with ps -A) execute the following: @@ -59,14 +80,20 @@ A revised notes file (blah.merge) should automagically appear in the full tilt r If you are happy with it, replace the existing (myname.xml file) +Since the updates aren't real time, it would be ok to play the rush + session with fpdb inactive, but before quitting any of the tables, + start the HUD and wait for it to catch-up processing all the hands played. + + Summary ------- +------- This is very rough and ready, but it does what I set-out to achieve. -All feedback welcome, and if this is useful as a basis for general notes processing, then thats great. +All feedback welcome, and if this is useful as a basis for general notes + processing in future, then thats great. -As I find bugs and make improvements, I will push to the git branch. +As I find bugs and make improvements, I will push to git. Much more information below: @@ -136,12 +163,13 @@ It is hoped that due to the relatively large hand volume and relatively small although there will obviously be a number of players with no fpdb note. The aggregation parameters used for the notes are based upon the HUD parameters. + (with the exception of the hand-ranges, which uses its' own criteria (see source) -Stopping and starting the HUD will erase the previously created notes holding file. +Stopping and starting the HUD will erase the previously created notes queue file. The HUD must run, so the individual player popups need to be manually relocated. -Although hard-coded for micro RUSH tablenames, the auxilliary window will +Although hard-coded for micro RUSH tablenames, the auxilliary window could probably happily update notes of all cash and tournament players. Process overview From 927184a3f249372cb9545490cf2730013799f0fa Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 12 Jan 2011 11:45:38 +0800 Subject: [PATCH 25/83] Regression: Add FTP crasher. FTP hand that contains all the prelim information, but is actually a cancelled hand. Crashes in readButton --- .../3-Draw-Limit-USD-10-20-201101.Dead.hand.txt | Bin 0 -> 732 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 pyfpdb/regression-test-files/cash/FTP/Draw/3-Draw-Limit-USD-10-20-201101.Dead.hand.txt diff --git a/pyfpdb/regression-test-files/cash/FTP/Draw/3-Draw-Limit-USD-10-20-201101.Dead.hand.txt b/pyfpdb/regression-test-files/cash/FTP/Draw/3-Draw-Limit-USD-10-20-201101.Dead.hand.txt new file mode 100644 index 0000000000000000000000000000000000000000..ef7f5815c8abf858e40c1a05614fff905dc4016f GIT binary patch literal 732 zcmaiyUrRzk5XH}P(05qK2MtQSWQA`*We){W7W8<{{z%#t@0DKq?A7n=DxwfF?9S}& z%$YOi-rt`~%{9h?`WoRYqFWXE(2HioJ>{AZ2kj}-u}-lgwbdbRMeD}eTm!0|*NZr= znSoa5le@a!Ip-RxK1wBUAV^Bv6#x?Ma*3f!>7W1#-d Date: Wed, 12 Jan 2011 11:47:42 +0800 Subject: [PATCH 26/83] FTP: Add exception handler to readButton Fix crasher in FTP (see 927184a3f249372c) --- pyfpdb/FulltiltToFpdb.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyfpdb/FulltiltToFpdb.py b/pyfpdb/FulltiltToFpdb.py index 955b55b9..761fd669 100755 --- a/pyfpdb/FulltiltToFpdb.py +++ b/pyfpdb/FulltiltToFpdb.py @@ -367,7 +367,11 @@ class Fulltilt(HandHistoryConverter): logging.warning(_("No bringin found, handid =%s") % hand.handid) def readButton(self, hand): - hand.buttonpos = int(self.re_Button.search(hand.handText).group('BUTTON')) + try: + 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) def readHeroCards(self, hand): # streets PREFLOP, PREDRAW, and THIRD are special cases beacause From be83ab0713262cc6288e38e37ecb1c90f7ec53c7 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 12 Jan 2011 15:09:27 +0800 Subject: [PATCH 27/83] Stars: Add 20/40 limit to table --- pyfpdb/PokerStarsToFpdb.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index a46b2298..b9e1cb3e 100644 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -56,6 +56,7 @@ class PokerStars(HandHistoryConverter): '10.00': ('2.00', '5.00'), '10': ('2.00', '5.00'), '20.00': ('5.00', '10.00'), '20': ('5.00', '10.00'), '30.00': ('10.00', '15.00'), '30': ('10.00', '15.00'), + '40.00': ('10.00', '20.00'), '40': ('10.00', '20.00'), '60.00': ('15.00', '30.00'), '60': ('15.00', '30.00'), '80.00': ('20.00', '40.00'), '80': ('20.00', '40.00'), '100.00': ('25.00', '50.00'), '100': ('25.00', '50.00'), From bd5d848934a322cdd117d3ee28273dc28247edbf Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 12 Jan 2011 17:41:03 +0800 Subject: [PATCH 28/83] FTP: Refine how players are counted as playing. Players can be noted as sitting out, but act within the hand. The summary info contains more accurate information, so use that to cull the list. --- pyfpdb/FulltiltToFpdb.py | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/pyfpdb/FulltiltToFpdb.py b/pyfpdb/FulltiltToFpdb.py index 761fd669..7a0437fe 100755 --- a/pyfpdb/FulltiltToFpdb.py +++ b/pyfpdb/FulltiltToFpdb.py @@ -76,8 +76,8 @@ class Fulltilt(HandHistoryConverter): (\s\((?PTurbo)\))?)|(?P.+)) ''' % substitutions, re.VERBOSE) re_Button = re.compile('^The button is in seat #(?P