From a5ead615fc05e81ee05b2a84e2fb20f415429cc2 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 8 Nov 2008 22:41:06 +1000 Subject: [PATCH 01/19] Add parameter for base path to store HH's --- pyfpdb/HUD_config.xml.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index 3a595fe2..5a943044 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -187,7 +187,7 @@ - + From c215360a922f48958b94d9fff8c13f32cd1597fb Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 8 Nov 2008 23:01:07 +1000 Subject: [PATCH 02/19] Read new parameter in config --- pyfpdb/Configuration.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index adc950ca..b84dd934 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -178,11 +178,12 @@ class Popup: class Import: def __init__(self, node): - self.interval = node.getAttribute("interval") - self.callFpdbHud = node.getAttribute("callFpdbHud") + self.interval = node.getAttribute("interval") + self.callFpdbHud = node.getAttribute("callFpdbHud") + self.hhArchiveBase = node.getAttribute("hhArchiveBase") def __str__(self): - return " interval = %s\n callFpdbHud = %s\n" % (self.interval, self.callFpdbHud) + return " interval = %s\n callFpdbHud = %s\n hhArchiveBase = %s" % (self.interval, self.callFpdbHud, self.hhArchiveBase) class Tv: def __init__(self, node): From 4f64464df3f58c2814759c8143d1c05ab0bdbd15 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 8 Nov 2008 23:45:14 +1000 Subject: [PATCH 03/19] Fix accessor method to import params in Coonfig. Make cli print using accessor --- pyfpdb/Configuration.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index b84dd934..0c88e2fd 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -439,11 +439,13 @@ class Config: def get_import_parameters(self): imp = {} try: - imp['imp-callFpdbHud'] = self.imp.callFpdbHud - imp['hud-defaultInterval'] = int(self.imp.interval) - except: # Default import parameters - imp['imp-callFpdbHud'] = True - imp['hud-defaultInterval'] = 10 + imp['callFpdbHud'] = self.callFpdbHud + imp['interval'] = self.interval + imp['hhArchiveBase'] = self.hhArchiveBase + except: # Default params + imp['callFpdbHud'] = 10 + imp['interval'] = True + imp['hhArchiveBase'] = "~/.fpdb/HandHistories/" return imp def get_default_paths(self, site = "PokerStars"): @@ -562,7 +564,9 @@ if __name__== "__main__": print "----------- END MUCKED WINDOW FORMATS -----------" print "\n----------- IMPORT -----------" -# print c.imp + tmp = c.get_import_parameters() + for param in tmp: + print " " + str(param) + ": " + str(tmp[param]) print "----------- END IMPORT -----------" print "\n----------- TABLE VIEW -----------" From 7df572895bd11f0100b846b12febbb0a7f112c40 Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 9 Nov 2008 09:49:05 +1000 Subject: [PATCH 04/19] Work on plugin initialisation, add Carbon poker plugin --- pyfpdb/CarbonToFpdb.py | 75 ++++++++++++++++++++++++++++++++++ pyfpdb/EverleafToFpdb.py | 12 +++++- pyfpdb/HandHistoryConverter.py | 56 +++++++++++++++++++++++-- 3 files changed, 138 insertions(+), 5 deletions(-) create mode 100644 pyfpdb/CarbonToFpdb.py diff --git a/pyfpdb/CarbonToFpdb.py b/pyfpdb/CarbonToFpdb.py new file mode 100644 index 00000000..0dc7dfaf --- /dev/null +++ b/pyfpdb/CarbonToFpdb.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python +# Copyright 2008, Carl Gherardi + +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +######################################################################## + +# Standard Library modules +import Configuration +import traceback +import xml.dom.minidom +from xml.dom.minidom import Node +from HandHistoryConverter import HandHistoryConverter + +# Carbon format looks like: + +# 1) +# 2) +# 3) +# +# ... +# 4) +# +# +# 5) +# +# 6) +# +# .... +# + +# The full sequence for a NHLE cash game is: +# BLINDS, PREFLOP, POSTFLOP, POSTTURN, POSTRIVER, SHOWDOWN, END_OF_GAME +# This sequence can be terminated after BLINDS at any time by END_OF_FOLDED_GAME + + +class CarbonPoker(HandHistoryConverter): + def __init__(self, config, filename): + print "Initialising Carbon Poker converter class" + HandHistoryConverter.__init__(self, config, filename) # Call super class init + self.sitename = "Carbon" + self.setFileType("xml") + + def readSupportedGames(self): + pass + def determineGameType(self): + desc_node = doc.getElementsByTagName("description") + type = desc_node.getAttribute("type") + stakes = desc_node.getAttribute("stakes") + + def readPlayerStacks(self): + pass + def readBlinds(self): + pass + def readAction(self): + pass + + +if __name__ == "__main__": + c = Configuration.Config() + e = CarbonPoker(c, "regression-test-files/carbon-poker/Niagara Falls (15245216).xml") + print str(e) diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index 9f6b760b..515f28d7 100644 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -16,11 +16,16 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ######################################################################## +import Configuration from HandHistoryConverter import HandHistoryConverter class Everleaf(HandHistoryConverter): - def __init__(self): + def __init__(self, config, file): print "Initialising Everleaf converter class" + HandHistoryConverter.__init__(self, config, file) # Call super class init. + self.sitename = "Everleaf" + self.setFileType("text") + def readSupportedGames(self): pass @@ -37,4 +42,7 @@ class Everleaf(HandHistoryConverter): pass if __name__ == "__main__": - e = Everleaf() + c = Configuration.Config() + e = Everleaf(c, "regression-test-files/everleaf/Speed_Kuala.txt") + print str(e) + diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 9a62776c..731b2bb5 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -16,8 +16,22 @@ #agpl-3.0.txt in the docs folder of the package. class HandHistoryConverter: - def __init__(self): - pass + def __init__(self, config, file): + print "HandHistory init called" + self.c = config + self.sitename = "" + self.obs = "" # One big string + self.filetype = "text" + self.doc = None # For XML based HH files + self.file = file + self.hhbase = self.c.get_import_parameters().get("hhArchiveBase") + + def __str__(self): + tmp = "HandHistoryConverter: '%s'\n" % (self.sitename) + tmp = tmp + "\thhbase: %s\n" % (self.hhbase) + tmp = tmp + "\tfiletype: %s\n" % (self.filetype) + return tmp + # Functions to be implemented in the inheriting class def readSupportedGames(self): abstract def determineGameType(self): abstract @@ -25,11 +39,47 @@ class HandHistoryConverter: def readBlinds(self): abstract def readAction(self): abstract + # Functions not necessary to implement in sub class + def setFileType(self, filetype = "text"): + self.filetype = filetype + + def processFile(self): + self.readFile() + def readFile(self, filename): """Read file""" + if(self.filetype == "text"): + infile=open(filename, "rU") + self.obs = readfile(inputFile) + inputFile.close() + elif(self.filetype == "xml"): + try: + doc = xml.dom.minidom.parse(filename) + self.doc = doc + except: + traceback.print_exc(file=sys.stderr) def writeStars(self): """Write out parsed data""" - +# print sitename + " Game #" + handid + ": " + gametype + " (" + sb + "/" + bb + " - " + starttime +# print "Table '" + tablename + "' " + maxseats + "-max Seat #" + buttonpos + " is the button" +# +# counter = 1 +# for player in seating: +# print "Seat " + counter + ": " + playername + "($" + playermoney + " in chips" +# +# print playername + ": posts small blind " + sb +# print playername + ": posts big blind " + bb +# +# print "*** HOLE CARDS ***" +# print "Dealt to " + hero + " [" + holecards + "]" +# +## ACTION STUFF +# +# print "*** SUMMARY ***" +# print "Total pot $" + totalpot + " | Rake $" + rake +# print "Board [" + boardcards + "]" +# +## SUMMARY STUFF From 328bba2d238d66afb419265205e384359f3c9a87 Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 9 Nov 2008 10:46:14 +1000 Subject: [PATCH 05/19] Updates - change HH object init call. - override carbon readFile function and hack so minidom can read it --- pyfpdb/CarbonToFpdb.py | 19 +++++++++++++++++-- pyfpdb/EverleafToFpdb.py | 3 ++- pyfpdb/HandHistoryConverter.py | 24 +++++++++++++++++------- 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/pyfpdb/CarbonToFpdb.py b/pyfpdb/CarbonToFpdb.py index 0dc7dfaf..8282b3f2 100644 --- a/pyfpdb/CarbonToFpdb.py +++ b/pyfpdb/CarbonToFpdb.py @@ -21,6 +21,7 @@ # Standard Library modules import Configuration import traceback +import sys import xml.dom.minidom from xml.dom.minidom import Node from HandHistoryConverter import HandHistoryConverter @@ -50,8 +51,7 @@ from HandHistoryConverter import HandHistoryConverter class CarbonPoker(HandHistoryConverter): def __init__(self, config, filename): print "Initialising Carbon Poker converter class" - HandHistoryConverter.__init__(self, config, filename) # Call super class init - self.sitename = "Carbon" + HandHistoryConverter.__init__(self, config, filename, "Carbon") # Call super class init self.setFileType("xml") def readSupportedGames(self): @@ -68,8 +68,23 @@ class CarbonPoker(HandHistoryConverter): def readAction(self): pass + # Override read function as xml.minidom barfs on the Carbon layout + # This is pretty dodgy + def readFile(self, filename): + print "Carbon: Reading file: '%s'" %(filename) + infile=open(filename, "rU") + self.obs = infile.read() + infile.close() + self.obs = "\n" + self.obs + "" + try: + doc = xml.dom.minidom.parseString(self.obs) + self.doc = doc + except: + traceback.print_exc(file=sys.stderr) if __name__ == "__main__": c = Configuration.Config() e = CarbonPoker(c, "regression-test-files/carbon-poker/Niagara Falls (15245216).xml") + e.processFile() print str(e) + diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index 515f28d7..fe01c887 100644 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -22,7 +22,7 @@ from HandHistoryConverter import HandHistoryConverter class Everleaf(HandHistoryConverter): def __init__(self, config, file): print "Initialising Everleaf converter class" - HandHistoryConverter.__init__(self, config, file) # Call super class init. + HandHistoryConverter.__init__(self, config, file, "Everleaf") # Call super class init. self.sitename = "Everleaf" self.setFileType("text") @@ -44,5 +44,6 @@ class Everleaf(HandHistoryConverter): if __name__ == "__main__": c = Configuration.Config() e = Everleaf(c, "regression-test-files/everleaf/Speed_Kuala.txt") + e.processFile() print str(e) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 731b2bb5..6d1bf4a9 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -15,21 +15,30 @@ #In the "official" distribution you can find the license in #agpl-3.0.txt in the docs folder of the package. +import Configuration +import sys +import traceback +import xml.dom.minidom +from xml.dom.minidom import Node + class HandHistoryConverter: - def __init__(self, config, file): + def __init__(self, config, file, sitename): print "HandHistory init called" self.c = config - self.sitename = "" + self.sitename = sitename self.obs = "" # One big string self.filetype = "text" self.doc = None # For XML based HH files self.file = file self.hhbase = self.c.get_import_parameters().get("hhArchiveBase") + self.hhdir = self.hhbase + sitename def __str__(self): tmp = "HandHistoryConverter: '%s'\n" % (self.sitename) - tmp = tmp + "\thhbase: %s\n" % (self.hhbase) - tmp = tmp + "\tfiletype: %s\n" % (self.filetype) + tmp = tmp + "\thhbase: '%s'\n" % (self.hhbase) + tmp = tmp + "\thhdir: '%s'\n" % (self.hhdir) + tmp = tmp + "\tfiletype: '%s'\n" % (self.filetype) + tmp = tmp + "\tinfile: '%s'\n" % (self.file) return tmp # Functions to be implemented in the inheriting class @@ -45,14 +54,15 @@ class HandHistoryConverter: self.filetype = filetype def processFile(self): - self.readFile() + self.readFile(self.file) def readFile(self, filename): """Read file""" + print "Reading file: '%s'" %(filename) if(self.filetype == "text"): infile=open(filename, "rU") - self.obs = readfile(inputFile) - inputFile.close() + self.obs = infile.read() + infile.close() elif(self.filetype == "xml"): try: doc = xml.dom.minidom.parse(filename) From f3224f87cca37b4828eec5824d71afc9bd6ba3ca Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 9 Nov 2008 12:58:46 +1000 Subject: [PATCH 06/19] Add sanity check function, creates ~/.fpdb/HandHistories/ if it doens't exist. Fixes hhbase and hhdir interpretation. --- pyfpdb/HandHistoryConverter.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 6d1bf4a9..16de1cd9 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -18,6 +18,8 @@ import Configuration import sys import traceback +import os +import os.path import xml.dom.minidom from xml.dom.minidom import Node @@ -31,7 +33,8 @@ class HandHistoryConverter: self.doc = None # For XML based HH files self.file = file self.hhbase = self.c.get_import_parameters().get("hhArchiveBase") - self.hhdir = self.hhbase + sitename + self.hhbase = os.path.expanduser(self.hhbase) + self.hhdir = os.path.join(self.hhbase,sitename) def __str__(self): tmp = "HandHistoryConverter: '%s'\n" % (self.sitename) @@ -48,12 +51,35 @@ class HandHistoryConverter: def readBlinds(self): abstract def readAction(self): abstract + def sanityCheck(self): + sane = False + base_w = False + #Check if hhbase exists and is writable + #Note: Will not try to create the base HH directory + if not (os.access(self.hhbase, os.W_OK) and os.path.isdir(self.hhbase)): + print "HH Sanity Check: Directory hhbase '" + self.hhbase + "' doesn't exist or is not writable" + else: + #Check if hhdir exists and is writable + if not os.path.isdir(self.hhdir): + # In first pass, dir may not exist. Attempt to create dir + print "Creating directory: '%s'" % (self.hhdir) + os.mkdir(self.hhdir) + sane = True + elif os.access(self.hhdir, os.W_OK): + sane = True + else: + print "HH Sanity Check: Directory hhdir '" + self.hhdir + "' or its parent directory are not writable" + + return sane # Functions not necessary to implement in sub class def setFileType(self, filetype = "text"): self.filetype = filetype def processFile(self): + if not self.sanityCheck(): + print "Cowardly refusing to continue after failed sanity check" + return self.readFile(self.file) def readFile(self, filename): From 7bc686c8597fbd041b350596debb8fcb97fb2da6 Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 9 Nov 2008 13:29:58 +1000 Subject: [PATCH 07/19] Add Regex file pokerstars_cash.py from pokerstats package (http://bostik.iki.fi/pokerstats/) Intend to turn into a class plugins can subclass and override the various regexes --- pyfpdb/FpdbRegex.py | 79 ++++++++++++++++++++++++++++++++++ pyfpdb/HandHistoryConverter.py | 3 ++ 2 files changed, 82 insertions(+) create mode 100644 pyfpdb/FpdbRegex.py diff --git a/pyfpdb/FpdbRegex.py b/pyfpdb/FpdbRegex.py new file mode 100644 index 00000000..bf16e864 --- /dev/null +++ b/pyfpdb/FpdbRegex.py @@ -0,0 +1,79 @@ +# pokerstars_cash.py +# -*- coding: iso-8859-15 +# +# PokerStats, an online poker statistics tracking software for Linux +# Copyright (C) 2007-2008 Mika Boström +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +from errors import * +import re +import regex + +# These are PokerStars specific; +# More importantly, they are currently valid for cash game only. +##### +# XXX: There was a weird problem with saved hand histories in PokerStars +# client 2.491; if a user was present on the table (and thus anywhere in +# the hand history), with non-standard characters in their username, the +# client would prepend a literal Ctrl-P (ASCII 16, 0x10) character to +# the hand history title line. Hence, to allow these strangely saved +# hands to be parsed and imported, there is a conditional "one extra +# character" allowed at the start of the new hand regex. +__NEW_HAND_REGEX='^.?PokerStars Game #\d+:\s+Hold\'em' +__HAND_INFO_REGEX='^.*#(\d+):\s+(\S+)\s([\s\S]+)\s\(\$?([.0-9]+)/\$?([.0-9]+)\)\s-\s(\S+)\s-?\s?(\S+)\s\(?(\w+)\)?' +__TABLE_INFO_REGEX='^\S+\s+\'.*\'\s+(\d+)-max\s+Seat\s#(\d+)' +__PLAYER_INFO_REGEX='^Seat\s(\d+):\s(.*)\s\(\$?([.\d]+)\s' +__POST_SB_REGEX='^(.*):\sposts small blind' +__POST_BB_REGEX='^(.*):\sposts big blind' +__POST_BOTH_REGEX='^(.*):\sposts small & big blinds' +__HAND_STAGE_REGEX='^\*{3}\s(.*)\s\*{3}' +__HOLE_CARD_REGEX='^\*{3}\sHOLE CARDS' +__FLOP_CARD_REGEX='^\*{3}\sFLOP\s\*{3}\s\[(\S{2})\s(\S{2})\s(\S{2})\]' +__TURN_CARD_REGEX='^\*{3}\sTURN\s\*{3}\s\[\S{2}\s\S{2}\s\S{2}\]\s\[(\S{2})\]' +__RIVER_CARD_REGEX='^\*{3}\sRIVER\s\*{3}\s\[\S{2}\s\S{2}\s\S{2}\s\S{2}\]\s\[(\S{2})\]' +__SHOWDOWN_REGEX='^\*{3}\sSHOW DOWN' +__SUMMARY_REGEX='^\*{3}\sSUMMARY' +__UNCALLED_BET_REGEX='^Uncalled bet \(\$([.\d]+)\) returned to (.*)' +__POT_AND_RAKE_REGEX='^Total\spot\s\$([.\d]+).*\|\sRake\s\$([.\d]+)' +__COLLECT_POT_REGEX='^(.*)\scollected\s\$([.\d]+)\sfrom\s((main|side)\s)?pot' +__POCKET_CARDS_REGEX='^Dealt\sto\s(.*)\s\[(\S{2})\s(\S{2})\]' +__SHOWN_CARDS_REGEX='^(.*):\sshows\s\[(\S{2})\s(\S{2})\]' +__ACTION_STEP_REGEX='^(.*):\s(bets|checks|raises|calls|folds)((\s\$([.\d]+))?(\sto\s\$([.\d]+))?)?' + +__SHOWDOWN_ACTION_REGEX='^(.*):\s(shows|mucks)' +__SUMMARY_CARDS_REGEX='^Seat\s\d+:\s(.*)\s(showed|mucked)\s\[(\S{2})\s(\S{2})\]' +__SUMMARY_CARDS_EXTRA_REGEX='^Seat\s\d+:\s(.*)\s(\(.*\)\s)(showed|mucked)\s\[(\S{2})\s(\S{2})\]' + + +def regexes(): + m = regex.RegexMatch() +### Compile the regexes + m.hand_start_re = re.compile(__NEW_HAND_REGEX) + m.hand_info_re = re.compile(__HAND_INFO_REGEX) + m.table_info_re = re.compile(__TABLE_INFO_REGEX) + m.player_info_re = re.compile(__PLAYER_INFO_REGEX) + m.small_blind_re = re.compile(__POST_SB_REGEX) + m.big_blind_re = re.compile(__POST_BB_REGEX) + m.both_blinds_re = re.compile(__POST_BOTH_REGEX) + m.hand_stage_re = re.compile(__HAND_STAGE_REGEX) + m.hole_cards_re = re.compile(__HOLE_CARD_REGEX) + m.flop_cards_re = re.compile(__FLOP_CARD_REGEX) + m.turn_card_re = re.compile(__TURN_CARD_REGEX) + m.river_card_re = re.compile(__RIVER_CARD_REGEX) + m.showdown_re = re.compile(__SHOWDOWN_REGEX) + m.summary_re = re.compile(__SUMMARY_REGEX) + m.uncalled_bet_re = re.compile(__UNCALLED_BET_REGEX) + m.collect_pot_re = re.compile(__COLLECT_POT_REGEX) + m.pocket_cards_re = re.compile(__POCKET_CARDS_REGEX) + m.cards_shown_re = re.compile(__SHOWN_CARDS_REGEX) + m.summary_cards_re = re.compile(__SUMMARY_CARDS_REGEX) + m.summary_cards_extra_re = re.compile(__SUMMARY_CARDS_EXTRA_REGEX) + m.action_re = re.compile(__ACTION_STEP_REGEX) + m.rake_re = re.compile(__POT_AND_RAKE_REGEX) + m.showdown_action_re = re.compile(__SHOWDOWN_ACTION_REGEX) +### + return m + diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 16de1cd9..6261637b 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -35,6 +35,7 @@ class HandHistoryConverter: self.hhbase = self.c.get_import_parameters().get("hhArchiveBase") self.hhbase = os.path.expanduser(self.hhbase) self.hhdir = os.path.join(self.hhbase,sitename) +# self.ofile = os.path.join(self.hhdir,file) def __str__(self): tmp = "HandHistoryConverter: '%s'\n" % (self.sitename) @@ -42,6 +43,7 @@ class HandHistoryConverter: tmp = tmp + "\thhdir: '%s'\n" % (self.hhdir) tmp = tmp + "\tfiletype: '%s'\n" % (self.filetype) tmp = tmp + "\tinfile: '%s'\n" % (self.file) +# tmp = tmp + "\toutfile: '%s'\n" % (self.ofile) return tmp # Functions to be implemented in the inheriting class @@ -81,6 +83,7 @@ class HandHistoryConverter: print "Cowardly refusing to continue after failed sanity check" return self.readFile(self.file) + self.determineGameType() def readFile(self, filename): """Read file""" From d6706a5bdf28518446f41744f98b713a4f08451f Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 9 Nov 2008 14:00:39 +1000 Subject: [PATCH 08/19] First pass at turning file from pokerstats into class --- pyfpdb/FpdbRegex.py | 182 +++++++++++++++++++++++++++++++------------- 1 file changed, 130 insertions(+), 52 deletions(-) diff --git a/pyfpdb/FpdbRegex.py b/pyfpdb/FpdbRegex.py index bf16e864..ffe3a03b 100644 --- a/pyfpdb/FpdbRegex.py +++ b/pyfpdb/FpdbRegex.py @@ -8,6 +8,9 @@ # it under the terms of the GNU General Public License as published by # the Free Software Foundation, version 3 of the License. # + +# Modified for use in fpdb by Carl Gherardi + from errors import * import re import regex @@ -22,58 +25,133 @@ import regex # the hand history title line. Hence, to allow these strangely saved # hands to be parsed and imported, there is a conditional "one extra # character" allowed at the start of the new hand regex. -__NEW_HAND_REGEX='^.?PokerStars Game #\d+:\s+Hold\'em' -__HAND_INFO_REGEX='^.*#(\d+):\s+(\S+)\s([\s\S]+)\s\(\$?([.0-9]+)/\$?([.0-9]+)\)\s-\s(\S+)\s-?\s?(\S+)\s\(?(\w+)\)?' -__TABLE_INFO_REGEX='^\S+\s+\'.*\'\s+(\d+)-max\s+Seat\s#(\d+)' -__PLAYER_INFO_REGEX='^Seat\s(\d+):\s(.*)\s\(\$?([.\d]+)\s' -__POST_SB_REGEX='^(.*):\sposts small blind' -__POST_BB_REGEX='^(.*):\sposts big blind' -__POST_BOTH_REGEX='^(.*):\sposts small & big blinds' -__HAND_STAGE_REGEX='^\*{3}\s(.*)\s\*{3}' -__HOLE_CARD_REGEX='^\*{3}\sHOLE CARDS' -__FLOP_CARD_REGEX='^\*{3}\sFLOP\s\*{3}\s\[(\S{2})\s(\S{2})\s(\S{2})\]' -__TURN_CARD_REGEX='^\*{3}\sTURN\s\*{3}\s\[\S{2}\s\S{2}\s\S{2}\]\s\[(\S{2})\]' -__RIVER_CARD_REGEX='^\*{3}\sRIVER\s\*{3}\s\[\S{2}\s\S{2}\s\S{2}\s\S{2}\]\s\[(\S{2})\]' -__SHOWDOWN_REGEX='^\*{3}\sSHOW DOWN' -__SUMMARY_REGEX='^\*{3}\sSUMMARY' -__UNCALLED_BET_REGEX='^Uncalled bet \(\$([.\d]+)\) returned to (.*)' -__POT_AND_RAKE_REGEX='^Total\spot\s\$([.\d]+).*\|\sRake\s\$([.\d]+)' -__COLLECT_POT_REGEX='^(.*)\scollected\s\$([.\d]+)\sfrom\s((main|side)\s)?pot' -__POCKET_CARDS_REGEX='^Dealt\sto\s(.*)\s\[(\S{2})\s(\S{2})\]' -__SHOWN_CARDS_REGEX='^(.*):\sshows\s\[(\S{2})\s(\S{2})\]' -__ACTION_STEP_REGEX='^(.*):\s(bets|checks|raises|calls|folds)((\s\$([.\d]+))?(\sto\s\$([.\d]+))?)?' - -__SHOWDOWN_ACTION_REGEX='^(.*):\s(shows|mucks)' -__SUMMARY_CARDS_REGEX='^Seat\s\d+:\s(.*)\s(showed|mucked)\s\[(\S{2})\s(\S{2})\]' -__SUMMARY_CARDS_EXTRA_REGEX='^Seat\s\d+:\s(.*)\s(\(.*\)\s)(showed|mucked)\s\[(\S{2})\s(\S{2})\]' -def regexes(): - m = regex.RegexMatch() -### Compile the regexes - m.hand_start_re = re.compile(__NEW_HAND_REGEX) - m.hand_info_re = re.compile(__HAND_INFO_REGEX) - m.table_info_re = re.compile(__TABLE_INFO_REGEX) - m.player_info_re = re.compile(__PLAYER_INFO_REGEX) - m.small_blind_re = re.compile(__POST_SB_REGEX) - m.big_blind_re = re.compile(__POST_BB_REGEX) - m.both_blinds_re = re.compile(__POST_BOTH_REGEX) - m.hand_stage_re = re.compile(__HAND_STAGE_REGEX) - m.hole_cards_re = re.compile(__HOLE_CARD_REGEX) - m.flop_cards_re = re.compile(__FLOP_CARD_REGEX) - m.turn_card_re = re.compile(__TURN_CARD_REGEX) - m.river_card_re = re.compile(__RIVER_CARD_REGEX) - m.showdown_re = re.compile(__SHOWDOWN_REGEX) - m.summary_re = re.compile(__SUMMARY_REGEX) - m.uncalled_bet_re = re.compile(__UNCALLED_BET_REGEX) - m.collect_pot_re = re.compile(__COLLECT_POT_REGEX) - m.pocket_cards_re = re.compile(__POCKET_CARDS_REGEX) - m.cards_shown_re = re.compile(__SHOWN_CARDS_REGEX) - m.summary_cards_re = re.compile(__SUMMARY_CARDS_REGEX) - m.summary_cards_extra_re = re.compile(__SUMMARY_CARDS_EXTRA_REGEX) - m.action_re = re.compile(__ACTION_STEP_REGEX) - m.rake_re = re.compile(__POT_AND_RAKE_REGEX) - m.showdown_action_re = re.compile(__SHOWDOWN_ACTION_REGEX) -### - return m +class FpdbRegex: + def __init__(self): + __NEW_HAND_REGEX='^.?PokerStars Game #\d+:\s+Hold\'em' + __HAND_INFO_REGEX='^.*#(\d+):\s+(\S+)\s([\s\S]+)\s\(\$?([.0-9]+)/\$?([.0-9]+)\)\s-\s(\S+)\s-?\s?(\S+)\s\(?(\w+)\)?' + __TABLE_INFO_REGEX='^\S+\s+\'.*\'\s+(\d+)-max\s+Seat\s#(\d+)' + __PLAYER_INFO_REGEX='^Seat\s(\d+):\s(.*)\s\(\$?([.\d]+)\s' + __POST_SB_REGEX='^(.*):\sposts small blind' + __POST_BB_REGEX='^(.*):\sposts big blind' + __POST_BOTH_REGEX='^(.*):\sposts small & big blinds' + __HAND_STAGE_REGEX='^\*{3}\s(.*)\s\*{3}' + __HOLE_CARD_REGEX='^\*{3}\sHOLE CARDS' + __FLOP_CARD_REGEX='^\*{3}\sFLOP\s\*{3}\s\[(\S{2})\s(\S{2})\s(\S{2})\]' + __TURN_CARD_REGEX='^\*{3}\sTURN\s\*{3}\s\[\S{2}\s\S{2}\s\S{2}\]\s\[(\S{2})\]' + __RIVER_CARD_REGEX='^\*{3}\sRIVER\s\*{3}\s\[\S{2}\s\S{2}\s\S{2}\s\S{2}\]\s\[(\S{2})\]' + __SHOWDOWN_REGEX='^\*{3}\sSHOW DOWN' + __SUMMARY_REGEX='^\*{3}\sSUMMARY' + __UNCALLED_BET_REGEX='^Uncalled bet \(\$([.\d]+)\) returned to (.*)' + __POT_AND_RAKE_REGEX='^Total\spot\s\$([.\d]+).*\|\sRake\s\$([.\d]+)' + __COLLECT_POT_REGEX='^(.*)\scollected\s\$([.\d]+)\sfrom\s((main|side)\s)?pot' + __POCKET_CARDS_REGEX='^Dealt\sto\s(.*)\s\[(\S{2})\s(\S{2})\]' + __SHOWN_CARDS_REGEX='^(.*):\sshows\s\[(\S{2})\s(\S{2})\]' + __ACTION_STEP_REGEX='^(.*):\s(bets|checks|raises|calls|folds)((\s\$([.\d]+))?(\sto\s\$([.\d]+))?)?' + + __SHOWDOWN_ACTION_REGEX='^(.*):\s(shows|mucks)' + __SUMMARY_CARDS_REGEX='^Seat\s\d+:\s(.*)\s(showed|mucked)\s\[(\S{2})\s(\S{2})\]' + __SUMMARY_CARDS_EXTRA_REGEX='^Seat\s\d+:\s(.*)\s(\(.*\)\s)(showed|mucked)\s\[(\S{2})\s(\S{2})\]' + self.m = regex.RegexMatch() + + def getRegexes(): + return self.m + + def compileRegexes(): + ### Compile the regexes + m.hand_start_re = re.compile(__NEW_HAND_REGEX) + m.hand_info_re = re.compile(__HAND_INFO_REGEX) + m.table_info_re = re.compile(__TABLE_INFO_REGEX) + m.player_info_re = re.compile(__PLAYER_INFO_REGEX) + m.small_blind_re = re.compile(__POST_SB_REGEX) + m.big_blind_re = re.compile(__POST_BB_REGEX) + m.both_blinds_re = re.compile(__POST_BOTH_REGEX) + m.hand_stage_re = re.compile(__HAND_STAGE_REGEX) + m.hole_cards_re = re.compile(__HOLE_CARD_REGEX) + m.flop_cards_re = re.compile(__FLOP_CARD_REGEX) + m.turn_card_re = re.compile(__TURN_CARD_REGEX) + m.river_card_re = re.compile(__RIVER_CARD_REGEX) + m.showdown_re = re.compile(__SHOWDOWN_REGEX) + m.summary_re = re.compile(__SUMMARY_REGEX) + m.uncalled_bet_re = re.compile(__UNCALLED_BET_REGEX) + m.collect_pot_re = re.compile(__COLLECT_POT_REGEX) + m.pocket_cards_re = re.compile(__POCKET_CARDS_REGEX) + m.cards_shown_re = re.compile(__SHOWN_CARDS_REGEX) + m.summary_cards_re = re.compile(__SUMMARY_CARDS_REGEX) + m.summary_cards_extra_re = re.compile(__SUMMARY_CARDS_EXTRA_REGEX) + m.action_re = re.compile(__ACTION_STEP_REGEX) + m.rake_re = re.compile(__POT_AND_RAKE_REGEX) + m.showdown_action_re = re.compile(__SHOWDOWN_ACTION_REGEX) + + # Set methods for plugins to override + + def setNewHandRegex(self, string): + __NEW_HAND_REGEX = string + + def setHandInfoRegex(self, string): + __HAND_INFO_REGEX = string + + def setTableInfoRegex(self, string): + __TABLE_INFO_REGEX = string + + def setPlayerInfoRegex(self, string): + __PLAYER_INFO_REGEX = string + + def setPostSbRegex(self, string): + __POST_SB_REGEX = string + + def setPostBbRegex(self, string): + __POST_BB_REGEX = string + + def setPostBothRegex(self, string): + __POST_BOTH_REGEX = string + + def setHandStageRegex(self, string): + __HAND_STAGE_REGEX = string + + def setHoleCardRegex(self, string): + __HOLE_CARD_REGEX = string + + def setFlopCardRegex(self, string): + __FLOP_CARD_REGEX = string + + def setTurnCardRegex(self, string): + __TURN_CARD_REGEX = string + + def setRiverCardRegex(self, string): + __RIVER_CARD_REGEX = string + + def setShowdownRegex(self, string): + __SHOWDOWN_REGEX = string + + def setSummaryRegex(self, string): + __SUMMARY_REGEX = string + + def setUncalledBetRegex(self, string): + __UNCALLED_BET_REGEX = string + + def setCollectPotRegex(self, string): + __COLLECT_POT_REGEX = string + + def setPocketCardsRegex(self, string): + __POCKET_CARDS_REGEX = string + + def setShownCardsRegex(self, string): + __SHOWN_CARDS_REGEX = string + + def setSummaryCardsRegex(self, string): + __SUMMARY_CARDS_REGEX = string + + def setSummaryCardsExtraRegex(self, string): + __SUMMARY_CARDS_EXTRA_REGEX = string + + def setActionStepRegex(self, string): + __ACTION_STEP_REGEX = string + + def setPotAndRakeRegex(self, string): + __POT_AND_RAKE_REGEX = string + + def setShowdownActionRegex(self, string): + __SHOWDOWN_ACTION_REGEX = string From 669382aa0179bcb5a23138476024882f59fab9ed Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 9 Nov 2008 15:30:57 +1000 Subject: [PATCH 09/19] Remove errors import --- pyfpdb/FpdbRegex.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyfpdb/FpdbRegex.py b/pyfpdb/FpdbRegex.py index ffe3a03b..cc5f3ae9 100644 --- a/pyfpdb/FpdbRegex.py +++ b/pyfpdb/FpdbRegex.py @@ -11,7 +11,6 @@ # Modified for use in fpdb by Carl Gherardi -from errors import * import re import regex From 43f8620deaee932e8170702d4e6f1fa80c2aa99c Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 9 Nov 2008 15:33:42 +1000 Subject: [PATCH 10/19] Remove FpdbRegex until functional --- pyfpdb/HandHistoryConverter.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 6261637b..6b7c8a76 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -16,6 +16,7 @@ #agpl-3.0.txt in the docs folder of the package. import Configuration +#import FpdbRegex import sys import traceback import os @@ -35,6 +36,7 @@ class HandHistoryConverter: self.hhbase = self.c.get_import_parameters().get("hhArchiveBase") self.hhbase = os.path.expanduser(self.hhbase) self.hhdir = os.path.join(self.hhbase,sitename) + self.gametype = [] # self.ofile = os.path.join(self.hhdir,file) def __str__(self): @@ -44,10 +46,19 @@ class HandHistoryConverter: tmp = tmp + "\tfiletype: '%s'\n" % (self.filetype) tmp = tmp + "\tinfile: '%s'\n" % (self.file) # tmp = tmp + "\toutfile: '%s'\n" % (self.ofile) + tmp = tmp + "\tgametype: '%s'\n" % (self.gametype[0]) + tmp = tmp + "\tgamebase: '%s'\n" % (self.gametype[1]) + tmp = tmp + "\tlimit: '%s'\n" % (self.gametype[2]) + tmp = tmp + "\tsb/bb: '%s'\n" % (self.gametype[3], self.gametype[4]) return tmp # Functions to be implemented in the inheriting class def readSupportedGames(self): abstract + + # should return a list + # type base limit + # [ ring, hold, nl , sb, bb ] + # Valid types specified in docs/tabledesign.html in Gametypes def determineGameType(self): abstract def readPlayerStacks(self): abstract def readBlinds(self): abstract @@ -83,7 +94,7 @@ class HandHistoryConverter: print "Cowardly refusing to continue after failed sanity check" return self.readFile(self.file) - self.determineGameType() + gametype = self.determineGameType() def readFile(self, filename): """Read file""" From c53d78491ae31de50de5135f575240e2e277069b Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 9 Nov 2008 16:27:27 +1000 Subject: [PATCH 11/19] Minor update to Carbon poker - read gametype + sb/bb --- pyfpdb/CarbonToFpdb.py | 29 ++++++++++++++++++++++++----- pyfpdb/HandHistoryConverter.py | 19 +++++++++++++++++-- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/pyfpdb/CarbonToFpdb.py b/pyfpdb/CarbonToFpdb.py index 8282b3f2..cf9fc8d3 100644 --- a/pyfpdb/CarbonToFpdb.py +++ b/pyfpdb/CarbonToFpdb.py @@ -22,6 +22,7 @@ import Configuration import traceback import sys +import re import xml.dom.minidom from xml.dom.minidom import Node from HandHistoryConverter import HandHistoryConverter @@ -56,11 +57,29 @@ class CarbonPoker(HandHistoryConverter): def readSupportedGames(self): pass - def determineGameType(self): - desc_node = doc.getElementsByTagName("description") - type = desc_node.getAttribute("type") - stakes = desc_node.getAttribute("stakes") - + def determineGameType(self): + gametype = [] + desc_node = self.doc.getElementsByTagName("description") + #TODO: no examples of non ring type yet + gametype = gametype + ["ring"] + type = desc_node[0].getAttribute("type") + if(type == "Holdem"): + gametype = gametype + ["hold"] + else: + print "Unknown gametype: '%s'" % (type) + + stakes = desc_node[0].getAttribute("stakes") + #TODO: no examples of anything except nlhe + m = re.match('(?PNo Limit)\s\(\$?(?P[.0-9]+)/\$?(?P[.0-9]+)\)', stakes) + + if(m.group('LIMIT') == "No Limit"): + gametype = gametype + ["nl"] + + gametype = gametype + [self.float2int(m.group('SB'))] + gametype = gametype + [self.float2int(m.group('BB'))] + + return gametype + def readPlayerStacks(self): pass def readBlinds(self): diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 6b7c8a76..ec1308cd 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -49,7 +49,7 @@ class HandHistoryConverter: tmp = tmp + "\tgametype: '%s'\n" % (self.gametype[0]) tmp = tmp + "\tgamebase: '%s'\n" % (self.gametype[1]) tmp = tmp + "\tlimit: '%s'\n" % (self.gametype[2]) - tmp = tmp + "\tsb/bb: '%s'\n" % (self.gametype[3], self.gametype[4]) + tmp = tmp + "\tsb/bb: '%s/%s'\n" % (self.gametype[3], self.gametype[4]) return tmp # Functions to be implemented in the inheriting class @@ -94,7 +94,7 @@ class HandHistoryConverter: print "Cowardly refusing to continue after failed sanity check" return self.readFile(self.file) - gametype = self.determineGameType() + self.gametype = self.determineGameType() def readFile(self, filename): """Read file""" @@ -133,3 +133,18 @@ class HandHistoryConverter: # ## SUMMARY STUFF +#takes a poker float (including , for thousand seperator and converts it to an int + def float2int (self, string): + pos=string.find(",") + if (pos!=-1): #remove , the thousand seperator + string=string[0:pos]+string[pos+1:] + + pos=string.find(".") + if (pos!=-1): #remove decimal point + string=string[0:pos]+string[pos+1:] + + result = int(string) + if pos==-1: #no decimal point - was in full dollars - need to multiply with 100 + result*=100 + return result +#end def float2int From d0218363c6fad08d277bf76900692acb5da76aa2 Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 9 Nov 2008 20:57:42 +1000 Subject: [PATCH 12/19] Fix GuiAutoImport startup after I deleted the default setting in a previous patch. Setting now comes from config --- pyfpdb/GuiAutoImport.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py index f8f4d8c1..9e65f6b6 100644 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -60,7 +60,7 @@ class GuiAutoImport (threading.Thread): self.intervalLabel.show() self.intervalEntry=gtk.Entry() - self.intervalEntry.set_text(str(self.settings['hud-defaultInterval'])) + self.intervalEntry.set_text(str(self.config.get_import_parameters().get("interval"))) self.settingsHBox.pack_start(self.intervalEntry) self.intervalEntry.show() From d4038c3f192c6d08cd2bc4dea5bac67cc62cea8b Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 9 Nov 2008 21:57:58 +1000 Subject: [PATCH 13/19] Lots of changes. Fixes the hud for auto-import - at least for me. Does configer Importer to use the Config class. --- pyfpdb/CliFpdb.py | 2 +- pyfpdb/Configuration.py | 4 +- pyfpdb/EverleafToFpdb.py | 44 +++++++++- pyfpdb/FpdbRegex.py | 150 ++++++++++++++++----------------- pyfpdb/GuiAutoImport.py | 9 +- pyfpdb/GuiBulkImport.py | 2 +- pyfpdb/HandHistoryConverter.py | 33 +++++++- pyfpdb/fpdb_import.py | 10 +-- 8 files changed, 162 insertions(+), 92 deletions(-) diff --git a/pyfpdb/CliFpdb.py b/pyfpdb/CliFpdb.py index 47649728..4e2a4361 100755 --- a/pyfpdb/CliFpdb.py +++ b/pyfpdb/CliFpdb.py @@ -53,7 +53,7 @@ if __name__ == "__main__": (options, sys.argv) = parser.parse_args() - settings={'imp-callFpdbHud':False, 'db-backend':2} + settings={'callFpdbHud':False, 'db-backend':2} settings['db-host']=options.server settings['db-user']=options.user settings['db-password']=options.password diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 0c88e2fd..b587d7b0 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -443,8 +443,8 @@ class Config: imp['interval'] = self.interval imp['hhArchiveBase'] = self.hhArchiveBase except: # Default params - imp['callFpdbHud'] = 10 - imp['interval'] = True + imp['callFpdbHud'] = True + imp['interval'] = 10 imp['hhArchiveBase'] = "~/.fpdb/HandHistories/" return imp diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index fe01c887..b81117c4 100644 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -17,7 +17,41 @@ ######################################################################## import Configuration -from HandHistoryConverter import HandHistoryConverter +from HandHistoryConverter import * + +# Everleaf HH format + +#Everleaf Gaming Game #55198191 +#***** Hand history for game #55198191 ***** +#Blinds $0.50/$1 NL Hold'em - 2008/09/01 - 10:02:11 +#Table Speed Kuala +#Seat 8 is the button +#Total number of players: 10 +#Seat 1: spicybum ( $ 77.50 USD ) +#Seat 2: harrydebeng ( new player ) +#Seat 3: EricBlade ( new player ) +#Seat 4: dollar_hecht ( $ 16.40 USD ) +#Seat 5: Apolon76 ( $ 154.10 USD ) +#Seat 6: dogge ( new player ) +#Seat 7: RonKoro ( $ 25.53 USD ) +#Seat 8: jay68w ( $ 48.50 USD ) +#Seat 9: KillerQueen1 ( $ 51.28 USD ) +#Seat 10: Cheburashka ( $ 49.61 USD ) +#KillerQueen1: posts small blind [$ 0.50 USD] +#Cheburashka: posts big blind [$ 1 USD] +#** Dealing down cards ** +#spicybum folds +#dollar_hecht calls [$ 1 USD] +#Apolon76 folds +#RonKoro folds +#jay68w raises [$ 4.50 USD] +#KillerQueen1 folds +#Cheburashka folds +#dollar_hecht folds +#jay68w does not show cards +#jay68w wins $ 3.50 USD from main pot + + class Everleaf(HandHistoryConverter): def __init__(self, config, file): @@ -25,12 +59,16 @@ class Everleaf(HandHistoryConverter): HandHistoryConverter.__init__(self, config, file, "Everleaf") # Call super class init. self.sitename = "Everleaf" self.setFileType("text") + self.rexx.setSplitHandRegex("\n\n\n") + self.rexx.compileRegexes() def readSupportedGames(self): pass def determineGameType(self): - pass + gametype = ["ring", "hold", "nl"] + + return gametype def readPlayerStacks(self): pass @@ -45,5 +83,5 @@ if __name__ == "__main__": c = Configuration.Config() e = Everleaf(c, "regression-test-files/everleaf/Speed_Kuala.txt") e.processFile() - print str(e) +# print str(e) diff --git a/pyfpdb/FpdbRegex.py b/pyfpdb/FpdbRegex.py index cc5f3ae9..f287c2f6 100644 --- a/pyfpdb/FpdbRegex.py +++ b/pyfpdb/FpdbRegex.py @@ -12,7 +12,6 @@ # Modified for use in fpdb by Carl Gherardi import re -import regex # These are PokerStars specific; # More importantly, they are currently valid for cash game only. @@ -28,129 +27,130 @@ import regex class FpdbRegex: def __init__(self): - __NEW_HAND_REGEX='^.?PokerStars Game #\d+:\s+Hold\'em' - __HAND_INFO_REGEX='^.*#(\d+):\s+(\S+)\s([\s\S]+)\s\(\$?([.0-9]+)/\$?([.0-9]+)\)\s-\s(\S+)\s-?\s?(\S+)\s\(?(\w+)\)?' - __TABLE_INFO_REGEX='^\S+\s+\'.*\'\s+(\d+)-max\s+Seat\s#(\d+)' - __PLAYER_INFO_REGEX='^Seat\s(\d+):\s(.*)\s\(\$?([.\d]+)\s' - __POST_SB_REGEX='^(.*):\sposts small blind' - __POST_BB_REGEX='^(.*):\sposts big blind' - __POST_BOTH_REGEX='^(.*):\sposts small & big blinds' - __HAND_STAGE_REGEX='^\*{3}\s(.*)\s\*{3}' - __HOLE_CARD_REGEX='^\*{3}\sHOLE CARDS' - __FLOP_CARD_REGEX='^\*{3}\sFLOP\s\*{3}\s\[(\S{2})\s(\S{2})\s(\S{2})\]' - __TURN_CARD_REGEX='^\*{3}\sTURN\s\*{3}\s\[\S{2}\s\S{2}\s\S{2}\]\s\[(\S{2})\]' - __RIVER_CARD_REGEX='^\*{3}\sRIVER\s\*{3}\s\[\S{2}\s\S{2}\s\S{2}\s\S{2}\]\s\[(\S{2})\]' - __SHOWDOWN_REGEX='^\*{3}\sSHOW DOWN' - __SUMMARY_REGEX='^\*{3}\sSUMMARY' - __UNCALLED_BET_REGEX='^Uncalled bet \(\$([.\d]+)\) returned to (.*)' - __POT_AND_RAKE_REGEX='^Total\spot\s\$([.\d]+).*\|\sRake\s\$([.\d]+)' - __COLLECT_POT_REGEX='^(.*)\scollected\s\$([.\d]+)\sfrom\s((main|side)\s)?pot' - __POCKET_CARDS_REGEX='^Dealt\sto\s(.*)\s\[(\S{2})\s(\S{2})\]' - __SHOWN_CARDS_REGEX='^(.*):\sshows\s\[(\S{2})\s(\S{2})\]' - __ACTION_STEP_REGEX='^(.*):\s(bets|checks|raises|calls|folds)((\s\$([.\d]+))?(\sto\s\$([.\d]+))?)?' + self.__SPLIT_HAND_REGEX='\n\n\n' + self.__NEW_HAND_REGEX='^.?PokerStars Game #\d+:\s+Hold\'em' + self.__HAND_INFO_REGEX='^.*#(\d+):\s+(\S+)\s([\s\S]+)\s\(\$?([.0-9]+)/\$?([.0-9]+)\)\s-\s(\S+)\s-?\s?(\S+)\s\(?(\w+)\)?' + self.__TABLE_INFO_REGEX='^\S+\s+\'.*\'\s+(\d+)-max\s+Seat\s#(\d+)' + self.__PLAYER_INFO_REGEX='^Seat\s(\d+):\s(.*)\s\(\$?([.\d]+)\s' + self.__POST_SB_REGEX='^(.*):\sposts small blind' + self.__POST_BB_REGEX='^(.*):\sposts big blind' + self.__POST_BOTH_REGEX='^(.*):\sposts small & big blinds' + self.__HAND_STAGE_REGEX='^\*{3}\s(.*)\s\*{3}' + self.__HOLE_CARD_REGEX='^\*{3}\sHOLE CARDS' + self.__FLOP_CARD_REGEX='^\*{3}\sFLOP\s\*{3}\s\[(\S{2})\s(\S{2})\s(\S{2})\]' + self.__TURN_CARD_REGEX='^\*{3}\sTURN\s\*{3}\s\[\S{2}\s\S{2}\s\S{2}\]\s\[(\S{2})\]' + self.__RIVER_CARD_REGEX='^\*{3}\sRIVER\s\*{3}\s\[\S{2}\s\S{2}\s\S{2}\s\S{2}\]\s\[(\S{2})\]' + self.__SHOWDOWN_REGEX='^\*{3}\sSHOW DOWN' + self.__SUMMARY_REGEX='^\*{3}\sSUMMARY' + self.__UNCALLED_BET_REGEX='^Uncalled bet \(\$([.\d]+)\) returned to (.*)' + self.__POT_AND_RAKE_REGEX='^Total\spot\s\$([.\d]+).*\|\sRake\s\$([.\d]+)' + self.__COLLECT_POT_REGEX='^(.*)\scollected\s\$([.\d]+)\sfrom\s((main|side)\s)?pot' + self.__POCKET_CARDS_REGEX='^Dealt\sto\s(.*)\s\[(\S{2})\s(\S{2})\]' + self.__SHOWN_CARDS_REGEX='^(.*):\sshows\s\[(\S{2})\s(\S{2})\]' + self.__ACTION_STEP_REGEX='^(.*):\s(bets|checks|raises|calls|folds)((\s\$([.\d]+))?(\sto\s\$([.\d]+))?)?' - __SHOWDOWN_ACTION_REGEX='^(.*):\s(shows|mucks)' - __SUMMARY_CARDS_REGEX='^Seat\s\d+:\s(.*)\s(showed|mucked)\s\[(\S{2})\s(\S{2})\]' - __SUMMARY_CARDS_EXTRA_REGEX='^Seat\s\d+:\s(.*)\s(\(.*\)\s)(showed|mucked)\s\[(\S{2})\s(\S{2})\]' - self.m = regex.RegexMatch() + self.__SHOWDOWN_ACTION_REGEX='^(.*):\s(shows|mucks)' + self.__SUMMARY_CARDS_REGEX='^Seat\s\d+:\s(.*)\s(showed|mucked)\s\[(\S{2})\s(\S{2})\]' + self.__SUMMARY_CARDS_EXTRA_REGEX='^Seat\s\d+:\s(.*)\s(\(.*\)\s)(showed|mucked)\s\[(\S{2})\s(\S{2})\]' - def getRegexes(): - return self.m - - def compileRegexes(): + def compileRegexes(self): ### Compile the regexes - m.hand_start_re = re.compile(__NEW_HAND_REGEX) - m.hand_info_re = re.compile(__HAND_INFO_REGEX) - m.table_info_re = re.compile(__TABLE_INFO_REGEX) - m.player_info_re = re.compile(__PLAYER_INFO_REGEX) - m.small_blind_re = re.compile(__POST_SB_REGEX) - m.big_blind_re = re.compile(__POST_BB_REGEX) - m.both_blinds_re = re.compile(__POST_BOTH_REGEX) - m.hand_stage_re = re.compile(__HAND_STAGE_REGEX) - m.hole_cards_re = re.compile(__HOLE_CARD_REGEX) - m.flop_cards_re = re.compile(__FLOP_CARD_REGEX) - m.turn_card_re = re.compile(__TURN_CARD_REGEX) - m.river_card_re = re.compile(__RIVER_CARD_REGEX) - m.showdown_re = re.compile(__SHOWDOWN_REGEX) - m.summary_re = re.compile(__SUMMARY_REGEX) - m.uncalled_bet_re = re.compile(__UNCALLED_BET_REGEX) - m.collect_pot_re = re.compile(__COLLECT_POT_REGEX) - m.pocket_cards_re = re.compile(__POCKET_CARDS_REGEX) - m.cards_shown_re = re.compile(__SHOWN_CARDS_REGEX) - m.summary_cards_re = re.compile(__SUMMARY_CARDS_REGEX) - m.summary_cards_extra_re = re.compile(__SUMMARY_CARDS_EXTRA_REGEX) - m.action_re = re.compile(__ACTION_STEP_REGEX) - m.rake_re = re.compile(__POT_AND_RAKE_REGEX) - m.showdown_action_re = re.compile(__SHOWDOWN_ACTION_REGEX) + self.split_hand_re = re.compile(self.__SPLIT_HAND_REGEX) + self.hand_start_re = re.compile(self.__NEW_HAND_REGEX) + self.hand_info_re = re.compile(self.__HAND_INFO_REGEX) + self.table_info_re = re.compile(self.__TABLE_INFO_REGEX) + self.player_info_re = re.compile(self.__PLAYER_INFO_REGEX) + self.small_blind_re = re.compile(self.__POST_SB_REGEX) + self.big_blind_re = re.compile(self.__POST_BB_REGEX) + self.both_blinds_re = re.compile(self.__POST_BOTH_REGEX) + self.hand_stage_re = re.compile(self.__HAND_STAGE_REGEX) + self.hole_cards_re = re.compile(self.__HOLE_CARD_REGEX) + self.flop_cards_re = re.compile(self.__FLOP_CARD_REGEX) + self.turn_card_re = re.compile(self.__TURN_CARD_REGEX) + self.river_card_re = re.compile(self.__RIVER_CARD_REGEX) + self.showdown_re = re.compile(self.__SHOWDOWN_REGEX) + self.summary_re = re.compile(self.__SUMMARY_REGEX) + self.uncalled_bet_re = re.compile(self.__UNCALLED_BET_REGEX) + self.collect_pot_re = re.compile(self.__COLLECT_POT_REGEX) + self.pocket_cards_re = re.compile(self.__POCKET_CARDS_REGEX) + self.cards_shown_re = re.compile(self.__SHOWN_CARDS_REGEX) + self.summary_cards_re = re.compile(self.__SUMMARY_CARDS_REGEX) + self.summary_cards_extra_re = re.compile(self.__SUMMARY_CARDS_EXTRA_REGEX) + self.action_re = re.compile(self.__ACTION_STEP_REGEX) + self.rake_re = re.compile(self.__POT_AND_RAKE_REGEX) + self.showdown_action_re = re.compile(self.__SHOWDOWN_ACTION_REGEX) # Set methods for plugins to override + def setSplitHandRegex(self, string): + self.__SPLIT_HAND_REGEX = string + def setNewHandRegex(self, string): - __NEW_HAND_REGEX = string + self.__NEW_HAND_REGEX = string def setHandInfoRegex(self, string): - __HAND_INFO_REGEX = string + self.__HAND_INFO_REGEX = string def setTableInfoRegex(self, string): - __TABLE_INFO_REGEX = string + self.__TABLE_INFO_REGEX = string def setPlayerInfoRegex(self, string): - __PLAYER_INFO_REGEX = string + self.__PLAYER_INFO_REGEX = string def setPostSbRegex(self, string): - __POST_SB_REGEX = string + self.__POST_SB_REGEX = string def setPostBbRegex(self, string): - __POST_BB_REGEX = string + self.__POST_BB_REGEX = string def setPostBothRegex(self, string): - __POST_BOTH_REGEX = string + self.__POST_BOTH_REGEX = string def setHandStageRegex(self, string): - __HAND_STAGE_REGEX = string + self.__HAND_STAGE_REGEX = string def setHoleCardRegex(self, string): - __HOLE_CARD_REGEX = string + self.__HOLE_CARD_REGEX = string def setFlopCardRegex(self, string): - __FLOP_CARD_REGEX = string + self.__FLOP_CARD_REGEX = string def setTurnCardRegex(self, string): - __TURN_CARD_REGEX = string + self.__TURN_CARD_REGEX = string def setRiverCardRegex(self, string): - __RIVER_CARD_REGEX = string + self.__RIVER_CARD_REGEX = string def setShowdownRegex(self, string): - __SHOWDOWN_REGEX = string + self.__SHOWDOWN_REGEX = string def setSummaryRegex(self, string): - __SUMMARY_REGEX = string + self.__SUMMARY_REGEX = string def setUncalledBetRegex(self, string): - __UNCALLED_BET_REGEX = string + self.__UNCALLED_BET_REGEX = string def setCollectPotRegex(self, string): - __COLLECT_POT_REGEX = string + self.__COLLECT_POT_REGEX = string def setPocketCardsRegex(self, string): - __POCKET_CARDS_REGEX = string + self.__POCKET_CARDS_REGEX = string def setShownCardsRegex(self, string): - __SHOWN_CARDS_REGEX = string + self.__SHOWN_CARDS_REGEX = string def setSummaryCardsRegex(self, string): - __SUMMARY_CARDS_REGEX = string + self.__SUMMARY_CARDS_REGEX = string def setSummaryCardsExtraRegex(self, string): - __SUMMARY_CARDS_EXTRA_REGEX = string + self.__SUMMARY_CARDS_EXTRA_REGEX = string def setActionStepRegex(self, string): - __ACTION_STEP_REGEX = string + self.__ACTION_STEP_REGEX = string def setPotAndRakeRegex(self, string): - __POT_AND_RAKE_REGEX = string + self.__POT_AND_RAKE_REGEX = string def setShowdownActionRegex(self, string): - __SHOWDOWN_ACTION_REGEX = string + self.__SHOWDOWN_ACTION_REGEX = string diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py index 9e65f6b6..e33976cf 100644 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -33,9 +33,14 @@ class GuiAutoImport (threading.Thread): self.settings=settings self.config=config + imp = self.config.get_import_parameters() + + print "Import parameters" + print imp + self.input_settings = {} - self.importer = fpdb_import.Importer(self,self.settings) + self.importer = fpdb_import.Importer(self,self.settings, self.config) self.importer.setCallHud(True) self.importer.setMinPrint(30) self.importer.setQuiet(False) @@ -195,7 +200,7 @@ if __name__== "__main__": settings['db-databaseName'] = "fpdb" settings['hud-defaultInterval'] = 10 settings['hud-defaultPath'] = 'C:/Program Files/PokerStars/HandHistory/nutOmatic' - settings['imp-callFpdbHud'] = True + settings['callFpdbHud'] = True i = GuiAutoImport(settings) main_window = gtk.Window() diff --git a/pyfpdb/GuiBulkImport.py b/pyfpdb/GuiBulkImport.py index ee5af2c6..9087cc79 100644 --- a/pyfpdb/GuiBulkImport.py +++ b/pyfpdb/GuiBulkImport.py @@ -80,7 +80,7 @@ class GuiBulkImport (threading.Thread): self.db=db self.settings=settings self.config=config - self.importer = fpdb_import.Importer(self,self.settings) + self.importer = fpdb_import.Importer(self,self.settings, config) self.vbox=gtk.VBox(False,1) self.vbox.show() diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index ec1308cd..181273ce 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -16,7 +16,8 @@ #agpl-3.0.txt in the docs folder of the package. import Configuration -#import FpdbRegex +import FpdbRegex +import re import sys import traceback import os @@ -38,6 +39,7 @@ class HandHistoryConverter: self.hhdir = os.path.join(self.hhbase,sitename) self.gametype = [] # self.ofile = os.path.join(self.hhdir,file) + self.rexx = FpdbRegex.FpdbRegex() def __str__(self): tmp = "HandHistoryConverter: '%s'\n" % (self.sitename) @@ -95,6 +97,13 @@ class HandHistoryConverter: return self.readFile(self.file) self.gametype = self.determineGameType() + self.splitFileIntoHands() + + def splitFileIntoHands(self): + hands = [] + list = self.rexx.split_hand_re.split(self.obs) + for l in list: + hands = hands + [Hand(l)] def readFile(self, filename): """Read file""" @@ -110,7 +119,7 @@ class HandHistoryConverter: except: traceback.print_exc(file=sys.stderr) - def writeStars(self): + def writeHand(self, file, hand): """Write out parsed data""" # print sitename + " Game #" + handid + ": " + gametype + " (" + sb + "/" + bb + " - " + starttime # print "Table '" + tablename + "' " + maxseats + "-max Seat #" + buttonpos + " is the button" @@ -148,3 +157,23 @@ class HandHistoryConverter: result*=100 return result #end def float2int + +class Hand: +# def __init__(self, sitename, gametype, sb, bb, string): + def __init__(self, string): +# self.sitename = sitename +# self.gametype = gametype +# self.sb = sb +# self.bb = bb + self.string = string + print string + + self.handid = None + self.tablename = "Slartibartfast" + self.maxseats = 10 + self.counted_seats = 0 + self.buttonpos = 0 + self.seating = [] + self.players = [] + self.action = [] + diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index b505a6ca..0f73e40e 100755 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -41,23 +41,22 @@ from time import time class Importer: - def __init__(self, caller, settings): + def __init__(self, caller, settings, config): """Constructor""" self.settings=settings self.caller=caller + self.config = config self.db = None self.cursor = None self.filelist = {} self.dirlist = {} self.monitor = False self.updated = {} #Time last import was run {file:mtime} - self.callHud = False self.lines = None self.faobs = None #File as one big string self.pos_in_file = {} # dict to remember how far we have read in the file #Set defaults - if not self.settings.has_key('imp-callFpdbHud'): - self.settings['imp-callFpdbHud'] = False + self.callHud = self.config.get_import_parameters().get("callFpdbHud") if not self.settings.has_key('minPrint'): self.settings['minPrint'] = 30 self.dbConnect() @@ -237,8 +236,7 @@ class Importer: stored+=1 self.db.commit() -# if settings['imp-callFpdbHud'] and self.callHud and os.sep=='/': - if self.settings['imp-callFpdbHud'] and self.callHud: + if self.callHud: #print "call to HUD here. handsId:",handsId #pipe the Hands.id out to the HUD self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep) From 0bbf801d898b1dac64f35eff1aebd290ae36c547 Mon Sep 17 00:00:00 2001 From: Worros Date: Mon, 10 Nov 2008 16:41:04 +1000 Subject: [PATCH 14/19] Bit more Everleaf --- pyfpdb/EverleafToFpdb.py | 10 ++++++++-- pyfpdb/FpdbRegex.py | 5 +++++ pyfpdb/HandHistoryConverter.py | 28 +++++++++++++--------------- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index b81117c4..f09c67d1 100644 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -59,14 +59,20 @@ class Everleaf(HandHistoryConverter): HandHistoryConverter.__init__(self, config, file, "Everleaf") # Call super class init. self.sitename = "Everleaf" self.setFileType("text") - self.rexx.setSplitHandRegex("\n\n\n") + self.rexx.setGameInfoRegex('.*Blinds \$?(?P[.0-9]+)/\$?(?P[.0-9]+)') + self.rexx.setSplitHandRegex('\n\n\n') self.rexx.compileRegexes() def readSupportedGames(self): pass def determineGameType(self): + # Cheating with this regex, only support nlhe at the moment gametype = ["ring", "hold", "nl"] + + m = self.rexx.game_info_re.search(self.obs) + gametype = gametype + [self.float2int(m.group('SB'))] + gametype = gametype + [self.float2int(m.group('BB'))] return gametype @@ -83,5 +89,5 @@ if __name__ == "__main__": c = Configuration.Config() e = Everleaf(c, "regression-test-files/everleaf/Speed_Kuala.txt") e.processFile() -# print str(e) + print str(e) diff --git a/pyfpdb/FpdbRegex.py b/pyfpdb/FpdbRegex.py index f287c2f6..311a309f 100644 --- a/pyfpdb/FpdbRegex.py +++ b/pyfpdb/FpdbRegex.py @@ -27,6 +27,7 @@ import re class FpdbRegex: def __init__(self): + self.__GAME_INFO_REGEX='' self.__SPLIT_HAND_REGEX='\n\n\n' self.__NEW_HAND_REGEX='^.?PokerStars Game #\d+:\s+Hold\'em' self.__HAND_INFO_REGEX='^.*#(\d+):\s+(\S+)\s([\s\S]+)\s\(\$?([.0-9]+)/\$?([.0-9]+)\)\s-\s(\S+)\s-?\s?(\S+)\s\(?(\w+)\)?' @@ -55,6 +56,7 @@ class FpdbRegex: def compileRegexes(self): ### Compile the regexes + self.game_info_re = re.compile(self.__GAME_INFO_REGEX) self.split_hand_re = re.compile(self.__SPLIT_HAND_REGEX) self.hand_start_re = re.compile(self.__NEW_HAND_REGEX) self.hand_info_re = re.compile(self.__HAND_INFO_REGEX) @@ -82,6 +84,9 @@ class FpdbRegex: # Set methods for plugins to override + def setGameInfoRegex(self, string): + self.__GAME_INFO_REGEX = string + def setSplitHandRegex(self, string): self.__SPLIT_HAND_REGEX = string diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 181273ce..508e253c 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -54,6 +54,14 @@ class HandHistoryConverter: tmp = tmp + "\tsb/bb: '%s/%s'\n" % (self.gametype[3], self.gametype[4]) return tmp + def processFile(self): + if not self.sanityCheck(): + print "Cowardly refusing to continue after failed sanity check" + return + self.readFile(self.file) + self.gametype = self.determineGameType() + self.hands = self.splitFileIntoHands() + # Functions to be implemented in the inheriting class def readSupportedGames(self): abstract @@ -91,19 +99,12 @@ class HandHistoryConverter: def setFileType(self, filetype = "text"): self.filetype = filetype - def processFile(self): - if not self.sanityCheck(): - print "Cowardly refusing to continue after failed sanity check" - return - self.readFile(self.file) - self.gametype = self.determineGameType() - self.splitFileIntoHands() - def splitFileIntoHands(self): hands = [] list = self.rexx.split_hand_re.split(self.obs) for l in list: - hands = hands + [Hand(l)] + hands = hands + [Hand(self.sitename, self.gametype, l)] + return hands def readFile(self, filename): """Read file""" @@ -160,13 +161,10 @@ class HandHistoryConverter: class Hand: # def __init__(self, sitename, gametype, sb, bb, string): - def __init__(self, string): -# self.sitename = sitename -# self.gametype = gametype -# self.sb = sb -# self.bb = bb + def __init__(self, sitename, gametype, string): + self.sitename = sitename + self.gametype = gametype self.string = string - print string self.handid = None self.tablename = "Slartibartfast" From 816a9e3b581ba56319018e0bb2f16dc3a9a11031 Mon Sep 17 00:00:00 2001 From: Worros Date: Mon, 10 Nov 2008 23:02:56 +1000 Subject: [PATCH 15/19] More Everleaf converter updates, now parsing some hand info --- pyfpdb/EverleafToFpdb.py | 22 +++++++++++++++++++++- pyfpdb/HandHistoryConverter.py | 18 +++++++++++++----- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index f09c67d1..61e32d85 100644 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -60,7 +60,8 @@ class Everleaf(HandHistoryConverter): self.sitename = "Everleaf" self.setFileType("text") self.rexx.setGameInfoRegex('.*Blinds \$?(?P[.0-9]+)/\$?(?P[.0-9]+)') - self.rexx.setSplitHandRegex('\n\n\n') + self.rexx.setSplitHandRegex('\n\n\n\n') + self.rexx.setHandInfoRegex('.*#(?P[0-9]+)\n.*\nBlinds \$?(?P[.0-9]+)/\$?(?P[.0-9]+) (?P.*) - (?P[0-9]+)/(?P[0-9]+)/(?P[0-9]+) - (?P
[0-9]+):(?P[0-9]+):(?P[0-9]+)\nTable (?P[ a-zA-Z]+)') self.rexx.compileRegexes() def readSupportedGames(self): @@ -76,6 +77,25 @@ class Everleaf(HandHistoryConverter): return gametype + def readHandInfo(self, hand): + m = self.rexx.hand_info_re.search(hand.string) + hand.handid = m.group('HID') + hand.tablename = m.group('GAMETYPE') +# These work, but the info is already in the Hand class - should be usecd for tourneys though. +# m.group('SB') +# m.group('BB') +# m.group('GAMETYPE') + +# Believe Everleaf time is GMT/UTC, no transation necessary +# Stars format (Nov 10 2008): 2008/11/07 12:38:49 UTC [2008/11/07 7:38:49 ET] +# Not getting it in my HH files yet, so using +# 2008/11/10 3:58:52 ET +#TODO: Do conversion from GMT to ET +#TODO: Need some date functions to convert to different timezones (Date::Manip for perl rocked for this) + hand.starttime = "%d/%02d/%02d %d:%02d:%02d ET" %(int(m.group('YEAR')), int(m.group('MON')), int(m.group('DAY')), + int(m.group('HR')), int(m.group('MIN')), int(m.group('SEC'))) + + def readPlayerStacks(self): pass diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 508e253c..9a8fd456 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -61,6 +61,9 @@ class HandHistoryConverter: self.readFile(self.file) self.gametype = self.determineGameType() self.hands = self.splitFileIntoHands() + for hand in self.hands: + self.readHandInfo(hand) + self.writeHand("output file", hand) # Functions to be implemented in the inheriting class def readSupportedGames(self): abstract @@ -70,6 +73,7 @@ class HandHistoryConverter: # [ ring, hold, nl , sb, bb ] # Valid types specified in docs/tabledesign.html in Gametypes def determineGameType(self): abstract + def readHandInfo(self, hand): abstract def readPlayerStacks(self): abstract def readBlinds(self): abstract def readAction(self): abstract @@ -102,7 +106,9 @@ class HandHistoryConverter: def splitFileIntoHands(self): hands = [] list = self.rexx.split_hand_re.split(self.obs) + list.pop() #Last entry is empty for l in list: +# print "'" + l + "'" hands = hands + [Hand(self.sitename, self.gametype, l)] return hands @@ -122,8 +128,8 @@ class HandHistoryConverter: def writeHand(self, file, hand): """Write out parsed data""" -# print sitename + " Game #" + handid + ": " + gametype + " (" + sb + "/" + bb + " - " + starttime -# print "Table '" + tablename + "' " + maxseats + "-max Seat #" + buttonpos + " is the button" + print "%s Game #%s: %s (%d/%d) - %s" %(hand.sitename, hand.handid, "XXXXhand.gametype", hand.sb, hand.bb, hand.starttime) + print "Table '%s' %d-max Seat #%s is the button" %(hand.tablename, hand.maxseats, "XXXXhand.buttonpos") # # counter = 1 # for player in seating: @@ -132,12 +138,12 @@ class HandHistoryConverter: # print playername + ": posts small blind " + sb # print playername + ": posts big blind " + bb # -# print "*** HOLE CARDS ***" + print "*** HOLE CARDS ***" # print "Dealt to " + hero + " [" + holecards + "]" # ## ACTION STUFF # -# print "*** SUMMARY ***" + print "*** SUMMARY ***" # print "Total pot $" + totalpot + " | Rake $" + rake # print "Board [" + boardcards + "]" # @@ -166,7 +172,9 @@ class Hand: self.gametype = gametype self.string = string - self.handid = None + self.handid = 0 + self.sb = gametype[3] + self.bb = gametype[4] self.tablename = "Slartibartfast" self.maxseats = 10 self.counted_seats = 0 From da83795e5a295f5814eec3d7dd01d090080bf78a Mon Sep 17 00:00:00 2001 From: Worros Date: Mon, 10 Nov 2008 23:29:49 +1000 Subject: [PATCH 16/19] Fix 'duh' error and grab button position --- pyfpdb/EverleafToFpdb.py | 6 +++--- pyfpdb/HandHistoryConverter.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index 61e32d85..5e702dbb 100644 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -61,7 +61,7 @@ class Everleaf(HandHistoryConverter): self.setFileType("text") self.rexx.setGameInfoRegex('.*Blinds \$?(?P[.0-9]+)/\$?(?P[.0-9]+)') self.rexx.setSplitHandRegex('\n\n\n\n') - self.rexx.setHandInfoRegex('.*#(?P[0-9]+)\n.*\nBlinds \$?(?P[.0-9]+)/\$?(?P[.0-9]+) (?P.*) - (?P[0-9]+)/(?P[0-9]+)/(?P[0-9]+) - (?P
[0-9]+):(?P[0-9]+):(?P[0-9]+)\nTable (?P
[ a-zA-Z]+)') + self.rexx.setHandInfoRegex('.*#(?P[0-9]+)\n.*\nBlinds \$?(?P[.0-9]+)/\$?(?P[.0-9]+) (?P.*) - (?P[0-9]+)/(?P[0-9]+)/(?P[0-9]+) - (?P
[0-9]+):(?P[0-9]+):(?P[0-9]+)\nTable (?P
[ a-zA-Z]+)\nSeat (?P
[ a-zA-Z]+)\nSeat (?P
[ a-zA-Z]+)\nSeat (?P