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

This commit is contained in:
Ray 2009-03-04 20:08:20 -05:00
commit 6667f4cddb
10 changed files with 771 additions and 503 deletions

View File

@ -18,6 +18,7 @@
######################################################################## ########################################################################
import sys import sys
import logging
import Configuration import Configuration
from HandHistoryConverter import * from HandHistoryConverter import *
from time import strftime from time import strftime
@ -28,13 +29,12 @@ class Everleaf(HandHistoryConverter):
# Static regexes # Static regexes
re_SplitHands = re.compile(r"\n\n+") re_SplitHands = re.compile(r"\n\n+")
re_GameInfo = re.compile(r".*Blinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<LTYPE>(NL|PL)) (?P<GAME>(Hold\'em|Omaha|7 Card Stud))") re_GameInfo = re.compile(r"^(Blinds )?\$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) ((?P<LTYPE>NL|PL) )?(?P<GAME>(Hold\'em|Omaha|7 Card Stud))", re.MULTILINE)
re_HandInfo = re.compile(r".*#(?P<HID>[0-9]+)\n.*\nBlinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<DATETIME>\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P<TABLE>[- a-zA-Z]+)") re_HandInfo = re.compile(r".*#(?P<HID>[0-9]+)\n.*\n(Blinds )?\$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<DATETIME>\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P<TABLE>[- a-zA-Z]+)")
re_Button = re.compile(r"^Seat (?P<BUTTON>\d+) is the button", re.MULTILINE) re_Button = re.compile(r"^Seat (?P<BUTTON>\d+) is the button", re.MULTILINE)
re_PlayerInfo = re.compile(r"^Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\s+(\$ (?P<CASH>[.0-9]+) USD|new player|All-in) \)", re.MULTILINE) re_PlayerInfo = re.compile(r"^Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\s+(\$ (?P<CASH>[.0-9]+) USD|new player|All-in) \)", re.MULTILINE)
re_Board = re.compile(r"\[ (?P<CARDS>.+) \]") re_Board = re.compile(r"\[ (?P<CARDS>.+) \]")
def __init__(self, config, file): def __init__(self, config, file):
print "Initialising Everleaf converter class" print "Initialising Everleaf converter class"
HandHistoryConverter.__init__(self, config, file, sitename="Everleaf") # Call super class init. HandHistoryConverter.__init__(self, config, file, sitename="Everleaf") # Call super class init.
@ -62,10 +62,11 @@ class Everleaf(HandHistoryConverter):
def readSupportedGames(self): def readSupportedGames(self):
return [["ring", "hold", "nl"], return [["ring", "hold", "nl"],
["ring", "hold", "pl"], ["ring", "hold", "pl"],
["ring", "omaha", "pl"] ["ring", "hold", "fl"],
["ring", "omahahi", "pl"]
] ]
def determineGameType(self): def determineGameType(self, handText):
# Cheating with this regex, only support nlhe at the moment # Cheating with this regex, only support nlhe at the moment
# Blinds $0.50/$1 PL Omaha - 2008/12/07 - 21:59:48 # Blinds $0.50/$1 PL Omaha - 2008/12/07 - 21:59:48
# Blinds $0.05/$0.10 NL Hold'em - 2009/02/21 - 11:21:57 # Blinds $0.05/$0.10 NL Hold'em - 2009/02/21 - 11:21:57
@ -80,8 +81,9 @@ class Everleaf(HandHistoryConverter):
structure = "" # nl, pl, cn, cp, fl structure = "" # nl, pl, cn, cp, fl
game = "" game = ""
m = self.re_GameInfo.search(self.obs) m = self.re_GameInfo.search(handText)
if m == None: if m == None:
logging.debug("Gametype didn't match")
return None return None
if m.group('LTYPE') == "NL": if m.group('LTYPE') == "NL":
structure = "nl" structure = "nl"
@ -102,45 +104,45 @@ class Everleaf(HandHistoryConverter):
return gametype return gametype
def readHandInfo(self, hand): def readHandInfo(self, hand):
m = self.re_HandInfo.search(hand.string) m = self.re_HandInfo.search(hand.handText)
if(m == None): if(m == None):
print "DEBUG: re_HandInfo.search failed: '%s'" %(hand.string) logging.info("Didn't match re_HandInfo")
hand.handid = m.group('HID') logging.info(hand.handtext)
return None
logging.debug("HID %s, Table %s" % (m.group('HID'), m.group('TABLE')))
hand.handid = m.group('HID')
hand.tablename = m.group('TABLE') hand.tablename = m.group('TABLE')
hand.max_seats = 6 # assume 6-max unless we have proof it's a larger/smaller game, since everleaf doesn't give seat max info hand.maxseats = 6 # assume 6-max unless we have proof it's a larger/smaller game, since everleaf doesn't give seat max info
# These work, but the info is already in the Hand class - should be used for tourneys though.
# m.group('SB')
# m.group('BB')
# m.group('GAMETYPE')
# Believe Everleaf time is GMT/UTC, no transation necessary # Believe Everleaf time is GMT/UTC, no transation necessary
# Stars format (Nov 10 2008): 2008/11/07 12:38:49 CET [2008/11/07 7:38:49 ET] # Stars format (Nov 10 2008): 2008/11/07 12:38:49 CET [2008/11/07 7:38:49 ET]
# or : 2008/11/07 12:38:49 ET # or : 2008/11/07 12:38:49 ET
# Not getting it in my HH files yet, so using # Not getting it in my HH files yet, so using
# 2008/11/10 3:58:52 ET # 2008/11/10 3:58:52 ET
#TODO: Do conversion from GMT to 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) #TODO: Need some date functions to convert to different timezones (Date::Manip for perl rocked for this)
hand.starttime = time.strptime(m.group('DATETIME'), "%Y/%m/%d - %H:%M:%S") hand.starttime = time.strptime(m.group('DATETIME'), "%Y/%m/%d - %H:%M:%S")
return
def readPlayerStacks(self, hand): def readPlayerStacks(self, hand):
m = self.re_PlayerInfo.finditer(hand.string) m = self.re_PlayerInfo.finditer(hand.handText)
for a in m: for a in m:
seatnum = int(a.group('SEAT')) seatnum = int(a.group('SEAT'))
hand.addPlayer(seatnum, a.group('PNAME'), a.group('CASH')) hand.addPlayer(seatnum, a.group('PNAME'), a.group('CASH'))
if seatnum > 6: if seatnum > 6:
hand.max_seats = 10 # everleaf currently does 2/6/10 games, so if seats > 6 are in use, it must be 10-max. hand.maxseats = 10 # everleaf currently does 2/6/10 games, so if seats > 6 are in use, it must be 10-max.
# TODO: implement lookup list by table-name to determine maxes, then fall back to 6 default/10 here, if there's no entry in the list? # TODO: implement lookup list by table-name to determine maxes, then fall back to 6 default/10 here, if there's no entry in the list?
def markStreets(self, hand): def markStreets(self, hand):
# PREFLOP = ** Dealing down cards ** # PREFLOP = ** Dealing down cards **
# This re fails if, say, river is missing; then we don't get the ** that starts the river. # This re fails if, say, river is missing; then we don't get the ** that starts the river.
#m = re.search('(\*\* Dealing down cards \*\*\n)(?P<PREFLOP>.*?\n\*\*)?( Dealing Flop \*\* \[ (?P<FLOP1>\S\S), (?P<FLOP2>\S\S), (?P<FLOP3>\S\S) \])?(?P<FLOP>.*?\*\*)?( Dealing Turn \*\* \[ (?P<TURN1>\S\S) \])?(?P<TURN>.*?\*\*)?( Dealing River \*\* \[ (?P<RIVER1>\S\S) \])?(?P<RIVER>.*)', hand.string,re.DOTALL) #m = re.search('(\*\* Dealing down cards \*\*\n)(?P<PREFLOP>.*?\n\*\*)?( Dealing Flop \*\* \[ (?P<FLOP1>\S\S), (?P<FLOP2>\S\S), (?P<FLOP3>\S\S) \])?(?P<FLOP>.*?\*\*)?( Dealing Turn \*\* \[ (?P<TURN1>\S\S) \])?(?P<TURN>.*?\*\*)?( Dealing River \*\* \[ (?P<RIVER1>\S\S) \])?(?P<RIVER>.*)', hand.handText,re.DOTALL)
m = re.search(r"\*\* Dealing down cards \*\*(?P<PREFLOP>.+(?=\*\* Dealing Flop \*\*)|.+)" m = re.search(r"\*\* Dealing down cards \*\*(?P<PREFLOP>.+(?=\*\* Dealing Flop \*\*)|.+)"
r"(\*\* Dealing Flop \*\*(?P<FLOP> \[ \S\S, \S\S, \S\S \].+(?=\*\* Dealing Turn \*\*)|.+))?" r"(\*\* Dealing Flop \*\*(?P<FLOP> \[ \S\S, \S\S, \S\S \].+(?=\*\* Dealing Turn \*\*)|.+))?"
r"(\*\* Dealing Turn \*\*(?P<TURN> \[ \S\S \].+(?=\*\* Dealing River \*\*)|.+))?" r"(\*\* Dealing Turn \*\*(?P<TURN> \[ \S\S \].+(?=\*\* Dealing River \*\*)|.+))?"
r"(\*\* Dealing River \*\*(?P<RIVER> \[ \S\S \].+))?", hand.string,re.DOTALL) r"(\*\* Dealing River \*\*(?P<RIVER> \[ \S\S \].+))?", hand.handText,re.DOTALL)
hand.addStreets(m) hand.addStreets(m)
@ -153,34 +155,35 @@ class Everleaf(HandHistoryConverter):
hand.setCommunityCards(street, m.group('CARDS').split(', ')) hand.setCommunityCards(street, m.group('CARDS').split(', '))
def readBlinds(self, hand): def readBlinds(self, hand):
try: m = self.re_PostSB.search(hand.handText)
m = self.re_PostSB.search(hand.string) if m is not None:
hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB')) hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB'))
except Exception, e: # no small blind else:
#print e logging.debug("No small blind")
hand.addBlind(None, None, None) hand.addBlind(None, None, None)
for a in self.re_PostBB.finditer(hand.string): for a in self.re_PostBB.finditer(hand.handText):
hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB')) hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB'))
for a in self.re_PostBoth.finditer(hand.string): for a in self.re_PostBoth.finditer(hand.handText):
hand.addBlind(a.group('PNAME'), 'both', a.group('SBBB')) hand.addBlind(a.group('PNAME'), 'both', a.group('SBBB'))
def readButton(self, hand): def readButton(self, hand):
hand.buttonpos = int(self.re_Button.search(hand.string).group('BUTTON')) hand.buttonpos = int(self.re_Button.search(hand.handText).group('BUTTON'))
def readHeroCards(self, hand): def readHeroCards(self, hand):
m = self.re_HeroCards.search(hand.string) m = self.re_HeroCards.search(hand.handText)
if(m == None): if m:
#Not involved in hand
hand.involved = False
else:
hand.hero = m.group('PNAME') hand.hero = m.group('PNAME')
# "2c, qh" -> set(["2c","qc"]) # "2c, qh" -> ["2c","qc"]
# Also works with Omaha hands. # Also works with Omaha hands.
cards = m.group('CARDS') cards = m.group('CARDS')
cards = cards.split(', ') cards = cards.split(', ')
hand.addHoleCards(cards, m.group('PNAME')) hand.addHoleCards(cards, m.group('PNAME'))
else:
#Not involved in hand
hand.involved = False
def readAction(self, hand, street): def readAction(self, hand, street):
logging.debug("readAction (%s)" % street)
m = self.re_Action.finditer(hand.streets.group(street)) m = self.re_Action.finditer(hand.streets.group(street))
for action in m: for action in m:
if action.group('ATYPE') == ' raises': if action.group('ATYPE') == ' raises':
@ -194,26 +197,30 @@ class Everleaf(HandHistoryConverter):
elif action.group('ATYPE') == ' checks': elif action.group('ATYPE') == ' checks':
hand.addCheck( street, action.group('PNAME')) hand.addCheck( street, action.group('PNAME'))
else: else:
print "DEBUG: unimplemented readAction: %s %s" %(action.group('PNAME'),action.group('ATYPE'),) logging.debug("Unimplemented readAction: %s %s" %(action.group('PNAME'),action.group('ATYPE'),))
def readShowdownActions(self, hand): def readShowdownActions(self, hand):
"""Reads lines where holecards are reported in a showdown""" """Reads lines where holecards are reported in a showdown"""
for shows in self.re_ShowdownAction.finditer(hand.string): logging.debug("readShowdownActions")
for shows in self.re_ShowdownAction.finditer(hand.handText):
cards = shows.group('CARDS') cards = shows.group('CARDS')
cards = cards.split(', ') cards = cards.split(', ')
logging.debug("readShowdownActions %s %s" %(cards, shows.group('PNAME')))
hand.addShownCards(cards, shows.group('PNAME')) hand.addShownCards(cards, shows.group('PNAME'))
def readCollectPot(self,hand): def readCollectPot(self,hand):
for m in self.re_CollectPot.finditer(hand.string): for m in self.re_CollectPot.finditer(hand.handText):
hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT')) hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT'))
def readShownCards(self,hand): def readShownCards(self,hand):
"""Reads lines where hole & board cards are mixed to form a hand (summary lines)""" """Reads lines where hole & board cards are mixed to form a hand (summary lines)"""
for m in self.re_CollectPot.finditer(hand.string): for m in self.re_CollectPot.finditer(hand.handText):
if m.group('CARDS') is not None: if m.group('CARDS') is not None:
cards = m.group('CARDS') cards = m.group('CARDS')
cards = cards.split(', ') cards = cards.split(', ')
player = m.group('PNAME')
logging.debug("readShownCards %s cards=%s" % (player, cards))
hand.addShownCards(cards=None, player=m.group('PNAME'), holeandboard=cards) hand.addShownCards(cards=None, player=m.group('PNAME'), holeandboard=cards)
@ -221,7 +228,7 @@ class Everleaf(HandHistoryConverter):
if __name__ == "__main__": if __name__ == "__main__":
c = Configuration.Config() c = Configuration.Config()
if len(sys.argv) == 1: if len(sys.argv) == 1:
testfile = "regression-test-files/everleaf/Speed_Kuala_full.txt" testfile = "regression-test-files/everleaf/plo/Naos.txt"
else: else:
testfile = sys.argv[1] testfile = sys.argv[1]
e = Everleaf(c, testfile) e = Everleaf(c, testfile)

View File

@ -17,6 +17,7 @@
######################################################################## ########################################################################
import sys import sys
import logging
import Configuration import Configuration
from HandHistoryConverter import * from HandHistoryConverter import *
@ -61,16 +62,17 @@ class FullTilt(HandHistoryConverter):
["ring", "omaha", "pl"] ["ring", "omaha", "pl"]
] ]
def determineGameType(self): def determineGameType(self, handText):
# Cheating with this regex, only support nlhe at the moment # Cheating with this regex, only support nlhe at the moment
# Full Tilt Poker Game #10777181585: Table Deerfly (deep 6) - $0.01/$0.02 - Pot Limit Omaha Hi - 2:24:44 ET - 2009/02/22 # Full Tilt Poker Game #10777181585: Table Deerfly (deep 6) - $0.01/$0.02 - Pot Limit Omaha Hi - 2:24:44 ET - 2009/02/22
# Full Tilt Poker Game #10773265574: Table Butte (6 max) - $0.01/$0.02 - Pot Limit Hold'em - 21:33:46 ET - 2009/02/21 # Full Tilt Poker Game #10773265574: Table Butte (6 max) - $0.01/$0.02 - Pot Limit Hold'em - 21:33:46 ET - 2009/02/21
# Full Tilt Poker Game #9403951181: Table CR - tay - $0.05/$0.10 - No Limit Hold'em - 9:40:20 ET - 2008/12/09 # Full Tilt Poker Game #9403951181: Table CR - tay - $0.05/$0.10 - No Limit Hold'em - 9:40:20 ET - 2008/12/09
# Full Tilt Poker Game #10809877615: Table Danville - $0.50/$1 Ante $0.10 - Limit Razz - 21:47:27 ET - 2009/02/23
structure = "" # nl, pl, cn, cp, fl structure = "" # nl, pl, cn, cp, fl
game = "" game = ""
m = self.re_GameInfo.search(self.obs) m = self.re_GameInfo.search(handText)
if m.group('LTYPE') == "No ": if m.group('LTYPE') == "No ":
structure = "nl" structure = "nl"
elif m.group('LTYPE') == "Pot ": elif m.group('LTYPE') == "Pot ":
@ -85,22 +87,22 @@ class FullTilt(HandHistoryConverter):
elif m.group('GAME') == "Razz": elif m.group('GAME') == "Razz":
game = "razz" game = "razz"
print m.groups() logging.debug("HandInfo: %s", m.groupdict())
gametype = ["ring", game, structure, m.group('SB'), m.group('BB')] gametype = ["ring", game, structure, m.group('SB'), m.group('BB')]
return gametype return gametype
def readHandInfo(self, hand): def readHandInfo(self, hand):
m = self.re_HandInfo.search(hand.string,re.DOTALL) m = self.re_HandInfo.search(hand.handText,re.DOTALL)
#print m.groups() #print m.groups()
hand.handid = m.group('HID') hand.handid = m.group('HID')
hand.tablename = m.group('TABLE') hand.tablename = m.group('TABLE')
hand.starttime = time.strptime(m.group('DATETIME'), "%H:%M:%S ET - %Y/%m/%d") hand.starttime = time.strptime(m.group('DATETIME'), "%H:%M:%S ET - %Y/%m/%d")
# These work, but the info is already in the Hand class - should be used for tourneys though. # These work, but the info is already in the Hand class - should be used for tourneys though.
# m.group('SB') # m.group('SB')
# m.group('BB') # m.group('BB')
# m.group('GAMETYPE') # m.group('GAMETYPE')
# Stars format (Nov 10 2008): 2008/11/07 12:38:49 CET [2008/11/07 7:38:49 ET] # Stars format (Nov 10 2008): 2008/11/07 12:38:49 CET [2008/11/07 7:38:49 ET]
# or : 2008/11/07 12:38:49 ET # or : 2008/11/07 12:38:49 ET
@ -113,7 +115,7 @@ class FullTilt(HandHistoryConverter):
#FIXME: hand.buttonpos = int(m.group('BUTTON')) #FIXME: hand.buttonpos = int(m.group('BUTTON'))
def readPlayerStacks(self, hand): def readPlayerStacks(self, hand):
m = self.re_PlayerInfo.finditer(hand.string) m = self.re_PlayerInfo.finditer(hand.handText)
players = [] players = []
for a in m: for a in m:
hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH')) hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH'))
@ -126,14 +128,14 @@ class FullTilt(HandHistoryConverter):
m = re.search(r"\*\*\* HOLE CARDS \*\*\*(?P<PREFLOP>.+(?=\*\*\* FLOP \*\*\*)|.+)" m = re.search(r"\*\*\* HOLE CARDS \*\*\*(?P<PREFLOP>.+(?=\*\*\* FLOP \*\*\*)|.+)"
r"(\*\*\* FLOP \*\*\*(?P<FLOP> \[\S\S \S\S \S\S\].+(?=\*\*\* TURN \*\*\*)|.+))?" r"(\*\*\* FLOP \*\*\*(?P<FLOP> \[\S\S \S\S \S\S\].+(?=\*\*\* TURN \*\*\*)|.+))?"
r"(\*\*\* TURN \*\*\* \[\S\S \S\S \S\S] (?P<TURN>\[\S\S\].+(?=\*\*\* RIVER \*\*\*)|.+))?" r"(\*\*\* TURN \*\*\* \[\S\S \S\S \S\S] (?P<TURN>\[\S\S\].+(?=\*\*\* RIVER \*\*\*)|.+))?"
r"(\*\*\* RIVER \*\*\* \[\S\S \S\S \S\S \S\S] (?P<RIVER>\[\S\S\].+))?", hand.string,re.DOTALL) r"(\*\*\* RIVER \*\*\* \[\S\S \S\S \S\S \S\S] (?P<RIVER>\[\S\S\].+))?", hand.handText,re.DOTALL)
elif self.gametype[1] == "razz": elif self.gametype[1] == "razz":
m = re.search(r"(?P<ANTES>.+(?=\*\*\* 3RD STREET \*\*\*)|.+)" m = re.search(r"(?P<ANTES>.+(?=\*\*\* 3RD STREET \*\*\*)|.+)"
r"(\*\*\* 3RD STREET \*\*\*(?P<THIRD>.+(?=\*\*\* 4TH STREET \*\*\*)|.+))?" r"(\*\*\* 3RD STREET \*\*\*(?P<THIRD>.+(?=\*\*\* 4TH STREET \*\*\*)|.+))?"
r"(\*\*\* 4TH STREET \*\*\*(?P<FOURTH>.+(?=\*\*\* 5TH STREET \*\*\*)|.+))?" r"(\*\*\* 4TH STREET \*\*\*(?P<FOURTH>.+(?=\*\*\* 5TH STREET \*\*\*)|.+))?"
r"(\*\*\* 5TH STREET \*\*\*(?P<FIFTH>.+(?=\*\*\* 6TH STREET \*\*\*)|.+))?" r"(\*\*\* 5TH STREET \*\*\*(?P<FIFTH>.+(?=\*\*\* 6TH STREET \*\*\*)|.+))?"
r"(\*\*\* 6TH STREET \*\*\*(?P<SIXTH>.+(?=\*\*\* 7TH STREET \*\*\*)|.+))?" r"(\*\*\* 6TH STREET \*\*\*(?P<SIXTH>.+(?=\*\*\* 7TH STREET \*\*\*)|.+))?"
r"(\*\*\* 7TH STREET \*\*\*(?P<SEVENTH>.+))?", hand.string,re.DOTALL) r"(\*\*\* 7TH STREET \*\*\*(?P<SEVENTH>.+))?", hand.handText,re.DOTALL)
hand.addStreets(m) hand.addStreets(m)
def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand
@ -145,34 +147,32 @@ class FullTilt(HandHistoryConverter):
def readBlinds(self, hand): def readBlinds(self, hand):
try: try:
m = self.re_PostSB.search(hand.string) m = self.re_PostSB.search(hand.handText)
hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB')) hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB'))
except: # no small blind except: # no small blind
hand.addBlind(None, None, None) hand.addBlind(None, None, None)
for a in self.re_PostBB.finditer(hand.string): for a in self.re_PostBB.finditer(hand.handText):
hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB')) hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB'))
for a in self.re_PostBoth.finditer(hand.string): 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'), 'small & big blinds', a.group('SBBB'))
def readAntes(self, hand): def readAntes(self, hand):
print "DEBUG: reading antes" logging.debug("reading antes")
m = self.re_Antes.finditer(hand.string) m = self.re_Antes.finditer(hand.handText)
for player in m: for player in m:
print "DEBUG: hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE')) logging.debug("hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE')))
hand.addAnte(player.group('PNAME'), player.group('ANTE')) hand.addAnte(player.group('PNAME'), player.group('ANTE'))
def readBringIn(self, hand): def readBringIn(self, hand):
print "DEBUG: reading bring in" m = self.re_BringIn.search(hand.handText,re.DOTALL)
# print hand.string logging.debug("Player bringing in: %s for %s" %(m.group('PNAME'), m.group('BRINGIN')))
m = self.re_BringIn.search(hand.string,re.DOTALL)
print "DEBUG: Player bringing in: %s for %s" %(m.group('PNAME'), m.group('BRINGIN'))
hand.addBringIn(m.group('PNAME'), m.group('BRINGIN')) hand.addBringIn(m.group('PNAME'), m.group('BRINGIN'))
def readButton(self, hand): def readButton(self, hand):
hand.buttonpos = int(self.re_Button.search(hand.string).group('BUTTON')) hand.buttonpos = int(self.re_Button.search(hand.handText).group('BUTTON'))
def readHeroCards(self, hand): def readHeroCards(self, hand):
m = self.re_HeroCards.search(hand.string) m = self.re_HeroCards.search(hand.handText)
if(m == None): if(m == None):
#Not involved in hand #Not involved in hand
hand.involved = False hand.involved = False
@ -181,7 +181,7 @@ class FullTilt(HandHistoryConverter):
# "2c, qh" -> set(["2c","qc"]) # "2c, qh" -> set(["2c","qc"])
# Also works with Omaha hands. # Also works with Omaha hands.
cards = m.group('CARDS') cards = m.group('CARDS')
cards = set(cards.split(' ')) cards = cards.split(' ')
hand.addHoleCards(cards, m.group('PNAME')) hand.addHoleCards(cards, m.group('PNAME'))
def readPlayerCards(self, hand, street): def readPlayerCards(self, hand, street):
@ -190,12 +190,12 @@ class FullTilt(HandHistoryConverter):
print "DEBUG: razz/stud readPlayerCards" print "DEBUG: razz/stud readPlayerCards"
print hand.streets.group(street) print hand.streets.group(street)
for player in m: for player in m:
print player.groups() logging.debug(player.groupdict())
cards = player.group('CARDS') cards = player.group('CARDS')
if player.group('NEWCARD') != None: if player.group('NEWCARD') != None:
print cards print cards
cards = cards + " " + player.group('NEWCARD') cards = cards + " " + player.group('NEWCARD')
cards = set(cards.split(' ')) cards = cards.split(' ')
hand.addPlayerCards(cards, player.group('PNAME')) hand.addPlayerCards(cards, player.group('PNAME'))
def readAction(self, hand, street): def readAction(self, hand, street):
@ -216,20 +216,20 @@ class FullTilt(HandHistoryConverter):
def readShowdownActions(self, hand): def readShowdownActions(self, hand):
for shows in self.re_ShowdownAction.finditer(hand.string): for shows in self.re_ShowdownAction.finditer(hand.handText):
cards = shows.group('CARDS') cards = shows.group('CARDS')
cards = set(cards.split(' ')) cards = cards.split(' ')
hand.addShownCards(cards, shows.group('PNAME')) hand.addShownCards(cards, shows.group('PNAME'))
def readCollectPot(self,hand): def readCollectPot(self,hand):
for m in self.re_CollectPot.finditer(hand.string): for m in self.re_CollectPot.finditer(hand.handText):
hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT')) hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT'))
def readShownCards(self,hand): def readShownCards(self,hand):
for m in self.re_ShownCards.finditer(hand.string): for m in self.re_ShownCards.finditer(hand.handText):
if m.group('CARDS') is not None: if m.group('CARDS') is not None:
cards = m.group('CARDS') cards = m.group('CARDS')
cards = set(cards.split(' ')) cards = cards.split(' ')
hand.addShownCards(cards=cards, player=m.group('PNAME')) hand.addShownCards(cards=cards, player=m.group('PNAME'))

View File

@ -44,7 +44,7 @@ class GuiBulkImport():
starttime = time() starttime = time()
if not self.importer.settings['threads'] > 1: if not self.importer.settings['threads'] > 1:
(stored, dups, partial, errs, ttime) = self.importer.runImport() (stored, dups, partial, errs, ttime) = self.importer.runImport()
print 'GuiBulkImport.import_dir done: Stored: %d Duplicates: %d Partial: %d Errors: %d in %s seconds - %d/sec'\ print 'GuiBulkImport.import_dir done: Stored: %d \tDuplicates: %d \tPartial: %d \tErrors: %d in %s seconds - %d/sec'\
% (stored, dups, partial, errs, ttime, stored / ttime) % (stored, dups, partial, errs, ttime, stored / ttime)
else: else:
self.importer.RunImportThreaded() self.importer.RunImportThreaded()
@ -73,7 +73,7 @@ class GuiBulkImport():
self.importer.setCallHud(False) self.importer.setCallHud(False)
starttime = time() starttime = time()
(stored, dups, partial, errs, ttime) = self.importer.runImport() (stored, dups, partial, errs, ttime) = self.importer.runImport()
print 'GuiBulkImport.import_dir done: Stored: %d Duplicates: %d Partial: %d Errors: %d in %s seconds - %d/sec'\ print 'GuiBulkImport.import_dir done: Stored: %d \tDuplicates: %d \tPartial: %d \tErrors: %d in %s seconds - %d/sec'\
% (stored, dups, partial, errs, ttime, stored / ttime) % (stored, dups, partial, errs, ttime, stored / ttime)
self.importer.clearFileList() self.importer.clearFileList()

View File

@ -0,0 +1,178 @@
#!/usr/bin/python
#Copyright 2008 Steffen Jobbagy-Felso
#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU Affero General Public License as published by
#the Free Software Foundation, version 3 of the License.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU Affero General Public License
#along with this program. If not, see <http://www.gnu.org/licenses/>.
#In the "official" distribution you can find the license in
#agpl-3.0.txt in the docs folder of the package.
import threading
import pygtk
pygtk.require('2.0')
import gtk
import os
import fpdb_import
import fpdb_db
import FpdbSQLQueries
class GuiPositionalStats (threading.Thread):
def get_vbox(self):
"""returns the vbox of this thread"""
return self.main_hbox
def toggleCallback(self, widget, data=None):
# print "%s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()])
self.activesite = data
print "DEBUG: activesite set to %s" %(self.activesite)
def refreshStats(self, widget, data):
try: self.stats_table.destroy()
except AttributeError: pass
self.fillStatsFrame(self.stats_frame)
def fillStatsFrame(self, vbox):
# Get currently active site and grab playerid
print "DEBUG: attempting to fill stats frame"
tmp = self.sql.query['playerStatsByPosition']
result = self.cursor.execute(self.sql.query['getPlayerId'], (self.heroes[self.activesite],))
result = self.cursor.fetchall()
if not result == ():
pid = result[0][0]
pid = result[0][0]
tmp = tmp.replace("<player_test>", "(" + str(pid) + ")")
self.cursor.execute(tmp)
result = self.cursor.fetchall()
cols = 16
rows = len(result)+1 # +1 for title row
self.stats_table = gtk.Table(rows, cols, False)
self.stats_table.set_col_spacings(4)
self.stats_table.show()
vbox.add(self.stats_table)
# Create header row
titles = ("Game", "Position", "#", "VPIP", "PFR", "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq", "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance")
col = 0
row = 0
for t in titles:
l = gtk.Label(titles[col])
l.show()
self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK)
col +=1
for row in range(rows-1):
if(row%2 == 0):
bgcolor = "white"
else:
bgcolor = "lightgrey"
for col in range(cols):
eb = gtk.EventBox()
eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor))
if result[row][col]:
l = gtk.Label(result[row][col])
else:
l = gtk.Label(' ')
if col == 0:
l.set_alignment(xalign=0.0, yalign=0.5)
else:
l.set_alignment(xalign=1.0, yalign=0.5)
eb.add(l)
self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK)
l.show()
eb.show()
self.fdb.db.commit()
#end def fillStatsFrame(self, vbox):
def fillPlayerFrame(self, vbox):
for site in self.conf.supported_sites.keys():
hbox = gtk.HBox(False, 0)
vbox.pack_start(hbox, False, True, 0)
hbox.show()
player = self.conf.supported_sites[site].screen_name
self.createPlayerLine(hbox, site, player)
hbox = gtk.HBox(False, 0)
button = gtk.Button("Refresh")
button.connect("clicked", self.refreshStats, False)
button.show()
hbox.add(button)
vbox.pack_start(hbox, False, True, 0)
hbox.show()
def createPlayerLine(self, hbox, site, player):
if(self.buttongroup == None):
button = gtk.RadioButton(None, site + " id:")
button.set_active(True)
self.buttongroup = button
self.activesite = site
else:
button = gtk.RadioButton(self.buttongroup, site + " id:")
hbox.pack_start(button, True, True, 0)
button.connect("toggled", self.toggleCallback, site)
button.show()
pname = gtk.Entry()
pname.set_text(player)
pname.set_width_chars(20)
hbox.pack_start(pname, False, True, 0)
pname.connect("changed", self.__set_hero_name, site)
#TODO: Look at GtkCompletion - to fill out usernames
pname.show()
self.__set_hero_name(pname, site)
def __set_hero_name(self, w, site):
self.heroes[site] = w.get_text()
def __init__(self, db, config, querylist, debug=True):
self.debug=debug
self.conf=config
# create new db connection to avoid conflicts with other threads
self.fdb = fpdb_db.fpdb_db()
self.fdb.do_connect(self.conf)
self.cursor=self.fdb.cursor
self.sql = querylist
self.activesite = None
self.buttongroup = None
self.heroes = {}
self.stat_table = None
self.stats_frame = None
self.main_hbox = gtk.HBox(False, 0)
self.main_hbox.show()
playerFrame = gtk.Frame("Hero:")
playerFrame.set_label_align(0.0, 0.0)
playerFrame.show()
vbox = gtk.VBox(False, 0)
vbox.show()
self.fillPlayerFrame(vbox)
playerFrame.add(vbox)
statsFrame = gtk.Frame("Stats:")
statsFrame.set_label_align(0.0, 0.0)
statsFrame.show()
self.stats_frame = gtk.VBox(False, 0)
self.stats_frame.show()
self.fillStatsFrame(self.stats_frame)
statsFrame.add(self.stats_frame)
self.main_hbox.pack_start(playerFrame)
self.main_hbox.pack_start(statsFrame)

View File

@ -83,6 +83,7 @@ class HUD_main(object):
self.hud_dict[table].main_window.destroy() self.hud_dict[table].main_window.destroy()
self.vb.remove(self.hud_dict[table].tablehudlabel) self.vb.remove(self.hud_dict[table].tablehudlabel)
del(self.hud_dict[table]) del(self.hud_dict[table])
self.main_window.resize(1,1)
def create_HUD(self, new_hand_id, table, table_name, max, poker_game, is_tournament, stat_dict, cards): def create_HUD(self, new_hand_id, table, table_name, max, poker_game, is_tournament, stat_dict, cards):
@ -93,6 +94,7 @@ class HUD_main(object):
newlabel = gtk.Label(table.site + " - " + table_name) newlabel = gtk.Label(table.site + " - " + table_name)
self.vb.add(newlabel) self.vb.add(newlabel)
newlabel.show() newlabel.show()
self.main_window.resize_children()
self.hud_dict[table_name].tablehudlabel = newlabel self.hud_dict[table_name].tablehudlabel = newlabel
self.hud_dict[table_name].create(new_hand_id, self.config, stat_dict, cards) self.hud_dict[table_name].create(new_hand_id, self.config, stat_dict, cards)

View File

@ -21,6 +21,7 @@ import Hand
import re import re
import sys import sys
import traceback import traceback
import logging
import os import os
import os.path import os.path
import xml.dom.minidom import xml.dom.minidom
@ -34,12 +35,12 @@ class Hand:
# def __init__(self, sitename, gametype, sb, bb, string): # def __init__(self, sitename, gametype, sb, bb, string):
UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K', 'S':'s', 'C':'c', 'H':'h', 'D':'d'} UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K', 'S':'s', 'C':'c', 'H':'h', 'D':'d'}
def __init__(self, sitename, gametype, string): def __init__(self, sitename, gametype, handText):
self.sitename = sitename self.sitename = sitename
self.gametype = gametype self.gametype = gametype
self.string = string self.handText = handText
if gametype[1] == "hold" or self.gametype[1] == "omaha": if gametype[1] == "hold" or self.gametype[1] == "omahahi":
self.streetList = ['PREFLOP','FLOP','TURN','RIVER'] # a list of the observed street names in order self.streetList = ['PREFLOP','FLOP','TURN','RIVER'] # a list of the observed street names in order
elif self.gametype[1] == "razz" or self.gametype[1] == "stud" or self.gametype[1] == "stud8": elif self.gametype[1] == "razz" or self.gametype[1] == "stud" or self.gametype[1] == "stud8":
self.streetList = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] # a list of the observed street names in order self.streetList = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] # a list of the observed street names in order
@ -123,14 +124,13 @@ If a player has None chips he won't be added."""
def addStreets(self, match): def addStreets(self, match):
# go through m and initialise actions to empty list for each street. # go through m and initialise actions to empty list for each street.
if match is not None: if match:
self.streets = match self.streets = match
for street in match.groupdict(): for street in match.groupdict():
if match.group(street) is not None: if match.group(street) is not None:
self.actions[street] = [] self.actions[street] = []
else: else:
print "empty markStreets match" # better to raise exception and put process hand in a try block logging.error("markstreets didn't match")
def addHoleCards(self, cards, player): def addHoleCards(self, cards, player):
"""\ """\
@ -193,6 +193,7 @@ Card ranks will be uppercased
print "[ERROR] discardHoleCard tried to discard a card %s didn't have" % (player,) print "[ERROR] discardHoleCard tried to discard a card %s didn't have" % (player,)
def setCommunityCards(self, street, cards): def setCommunityCards(self, street, cards):
logging.debug("setCommunityCards %s %s" %(street, cards))
self.board[street] = [self.card(c) for c in cards] self.board[street] = [self.card(c) for c in cards]
def card(self,c): def card(self,c):
@ -216,12 +217,12 @@ Card ranks will be uppercased
# Player in small blind posts # Player in small blind posts
# - this is a bet of 1 sb, as yet uncalled. # - this is a bet of 1 sb, as yet uncalled.
# Player in the big blind posts # Player in the big blind posts
# - this is a bet of 1 bb and is the new uncalled # - this is a call of 1 bb and is the new uncalled
# #
# If a player posts a big & small blind # If a player posts a big & small blind
# - FIXME: We dont record this for later printing yet # - FIXME: We dont record this for later printing yet
#print "DEBUG addBlind: %s posts %s, %s" % (player, blindtype, amount) logging.debug("addBlind: %s posts %s, %s" % (player, blindtype, amount))
if player is not None: if player is not None:
self.bets['PREFLOP'][player].append(Decimal(amount)) self.bets['PREFLOP'][player].append(Decimal(amount))
self.stacks[player] -= Decimal(amount) self.stacks[player] -= Decimal(amount)
@ -397,13 +398,31 @@ Map the tuple self.gametype onto the pokerstars string describing it
"cp" : "Cap Pot Limit" "cp" : "Cap Pot Limit"
} }
print "DEBUG: self.gametype: %s" %(self.gametype) logging.debug("gametype: %s" %(self.gametype))
string = "%s %s" %(gs[self.gametype[1]], ls[self.gametype[2]]) retstring = "%s %s" %(gs[self.gametype[1]], ls[self.gametype[2]])
return retstring
def lookupLimitBetSize(self):
#Lookup table for limit games
betlist = {
"Everleaf" : { "0.10" : ("0.02", "0.05"),
"0.20" : ("0.05", "0.10"),
"0.50" : ("0.10", "0.25"),
"1.00" : ("0.25", "0.50")
},
"FullTilt" : { "0.10" : ("0.02", "0.05"),
"0.20" : ("0.05", "0.10"),
"1" : ("0.25", "0.50"),
"2" : ("0.50", "1"),
"4" : ("1", "2")
}
}
return betlist[self.sitename][self.bb]
return string
def writeHand(self, fh=sys.__stdout__): def writeHand(self, fh=sys.__stdout__):
if self.gametype[1] == "hold" or self.gametype[1] == "omaha": if self.gametype[1] == "hold" or self.gametype[1] == "omahahi":
self.writeHoldemHand(fh) self.writeHoldemHand(fh)
else: else:
self.writeStudHand(fh) self.writeStudHand(fh)
@ -424,13 +443,19 @@ Map the tuple self.gametype onto the pokerstars string describing it
#May be more than 1 bb posting #May be more than 1 bb posting
if self.gametype[2] == "fl":
(smallbet, bigbet) = self.lookupLimitBetSize()
else:
smallbet = self.sb
bigbet = self.bb
for a in self.posted: for a in self.posted:
if(a[1] == "small blind"): if(a[1] == "small blind"):
print >>fh, _("%s: posts small blind $%s" %(a[0], self.sb)) print >>fh, _("%s: posts small blind $%s" %(a[0], smallbet))
if(a[1] == "big blind"): if(a[1] == "big blind"):
print >>fh, _("%s: posts big blind $%s" %(a[0], self.bb)) print >>fh, _("%s: posts big blind $%s" %(a[0], bigbet))
if(a[1] == "both"): if(a[1] == "both"):
print >>fh, _("%s: posts small & big blinds $%.2f" %(a[0], (Decimal(self.sb) + Decimal(self.bb)))) print >>fh, _("%s: posts small & big blinds $%.2f" %(a[0], (Decimal(smallbet) + Decimal(bigbet))))
print >>fh, _("*** HOLE CARDS ***") print >>fh, _("*** HOLE CARDS ***")
if self.involved: if self.involved:
@ -461,7 +486,7 @@ Map the tuple self.gametype onto the pokerstars string describing it
# we probably don't need a showdown section in pseudo stars format for our filtering purposes # we probably don't need a showdown section in pseudo stars format for our filtering purposes
if 'SHOWDOWN' in self.actions: if 'SHOWDOWN' in self.actions:
print >>fh, _("*** SHOW DOWN ***") print >>fh, _("*** SHOW DOWN ***")
#TODO: Complete SHOWDOWN #TODO: Complete SHOWDOWN
# Current PS format has the lines: # Current PS format has the lines:
# Uncalled bet ($111.25) returned to s0rrow # Uncalled bet ($111.25) returned to s0rrow
@ -565,7 +590,7 @@ Map the tuple self.gametype onto the pokerstars string describing it
# we probably don't need a showdown section in pseudo stars format for our filtering purposes # we probably don't need a showdown section in pseudo stars format for our filtering purposes
if 'SHOWDOWN' in self.actions: if 'SHOWDOWN' in self.actions:
print >>fh, _("*** SHOW DOWN ***") print >>fh, _("*** SHOW DOWN ***")
# print >>fh, "DEBUG: what do they show" # TODO: print showdown lines.
# Current PS format has the lines: # Current PS format has the lines:
# Uncalled bet ($111.25) returned to s0rrow # Uncalled bet ($111.25) returned to s0rrow
@ -749,4 +774,3 @@ class Pot(object):
return _("too many pots.. no small blind and walk in bb?. self.pots: %s" %(self.pots)) return _("too many pots.. no small blind and walk in bb?. self.pots: %s" %(self.pots))
# I don't know stars format for a walk in the bb when sb doesn't post. # I don't know stars format for a walk in the bb when sb doesn't post.
# The thing to do here is raise a Hand error like fpdb import does and file it into errors.txt # The thing to do here is raise a Hand error like fpdb import does and file it into errors.txt

View File

@ -21,6 +21,7 @@ import Hand
import re import re
import sys import sys
import traceback import traceback
import logging
import os import os
import os.path import os.path
import xml.dom.minidom import xml.dom.minidom
@ -74,9 +75,9 @@ gettext.install('myapplication')
class HandHistoryConverter: class HandHistoryConverter:
# eval = PokerEval()
def __init__(self, config, file, sitename): def __init__(self, config, file, sitename):
print "HandHistory init called" logging.info("HandHistory init called")
self.c = config self.c = config
self.sitename = sitename self.sitename = sitename
self.obs = "" # One big string self.obs = "" # One big string
@ -124,7 +125,7 @@ class HandHistoryConverter:
self.hands = self.splitFileIntoHands() self.hands = self.splitFileIntoHands()
outfile = open(self.ofile, 'w') outfile = open(self.ofile, 'w')
for hand in self.hands: for hand in self.hands:
#print "\nDEBUG: Input:\n"+hand.string #print "\nDEBUG: Input:\n"+hand.handText
self.readHandInfo(hand) self.readHandInfo(hand)
self.readPlayerStacks(hand) self.readPlayerStacks(hand)
@ -141,7 +142,7 @@ class HandHistoryConverter:
self.markStreets(hand) self.markStreets(hand)
# Different calls if stud or holdem like # Different calls if stud or holdem like
if self.gametype[1] == "hold" or self.gametype[1] == "omaha": if self.gametype[1] == "hold" or self.gametype[1] == "omahahi":
self.readBlinds(hand) self.readBlinds(hand)
self.readButton(hand) self.readButton(hand)
self.readHeroCards(hand) # want to generalise to draw games self.readHeroCards(hand) # want to generalise to draw games
@ -155,7 +156,7 @@ class HandHistoryConverter:
for street in hand.streetList: # go through them in order for street in hand.streetList: # go through them in order
print "DEBUG: ", street print "DEBUG: ", street
if hand.streets.group(street) is not None: if hand.streets.group(street) is not None:
if self.gametype[1] == "hold" or self.gametype[1] == "omaha": if self.gametype[1] == "hold" or self.gametype[1] == "omahahi":
self.readCommunityCards(hand, street) # read community cards self.readCommunityCards(hand, street) # read community cards
elif self.gametype[1] == "razz" or self.gametype[1] == "stud" or self.gametype[1] == "stud8": elif self.gametype[1] == "razz" or self.gametype[1] == "stud" or self.gametype[1] == "stud8":
self.readPlayerCards(hand, street) self.readPlayerCards(hand, street)
@ -272,7 +273,7 @@ class HandHistoryConverter:
list = self.re_SplitHands.split(self.obs) list = self.re_SplitHands.split(self.obs)
list.pop() #Last entry is empty list.pop() #Last entry is empty
for l in list: for l in list:
# print "'" + l + "'" # print "'" + l + "'"
hands = hands + [Hand.Hand(self.sitename, self.gametype, l)] hands = hands + [Hand.Hand(self.sitename, self.gametype, l)]
return hands return hands

View File

@ -30,6 +30,7 @@ import fpdb_db
import fpdb_import import fpdb_import
import fpdb_simple import fpdb_simple
import FpdbSQLQueries import FpdbSQLQueries
import EverleafToFpdb
import Tables import Tables
import unittest import unittest
@ -52,6 +53,8 @@ class TestSequenceFunctions(unittest.TestCase):
self.mysqlimporter = fpdb_import.Importer(self, self.mysql_settings, self.c) self.mysqlimporter = fpdb_import.Importer(self, self.mysql_settings, self.c)
self.mysqlimporter.setCallHud(False) self.mysqlimporter.setCallHud(False)
self.everleaf = EverleafToFpdb.Everleaf(self.c, "Nofile")
# """Configure Postgres settings/database and establish connection""" # """Configure Postgres settings/database and establish connection"""
# self.pg_settings={ 'db-host':"localhost", 'db-backend':3, 'db-databaseName':"fpdbtest", 'db-user':"fpdb", 'db-password':"fpdb"} # self.pg_settings={ 'db-host':"localhost", 'db-backend':3, 'db-databaseName':"fpdbtest", 'db-user':"fpdb", 'db-password':"fpdb"}
# self.pg_db = fpdb_db.fpdb_db() # self.pg_db = fpdb_db.fpdb_db()
@ -110,12 +113,57 @@ class TestSequenceFunctions(unittest.TestCase):
self.failUnless(result == "French", "French (deep) parsed incorrectly. Expected 'French' got: " + str(result)) self.failUnless(result == "French", "French (deep) parsed incorrectly. Expected 'French' got: " + str(result))
# result = ("French (deep) - $0.25/$0.50 - No Limit Hold'em - Logged In As xxxx") # result = ("French (deep) - $0.25/$0.50 - No Limit Hold'em - Logged In As xxxx")
def testImportHandHistoryFiles(self): def testEverleafGameInfoRegex(self):
"""Test import of single HH file""" cash_nlhe = """Everleaf Gaming Game #55198191
self.mysqlimporter.addImportFile("regression-test-files/hand-histories/ps-lhe-ring-3hands.txt") ***** Hand history for game #55198191 *****
self.mysqlimporter.runImport() Blinds $0.50/$1 NL Hold'em - 2008/09/01 - 10:02:11
self.mysqlimporter.addImportDirectory("regression-test-files/hand-histories") Table Speed Kuala
self.mysqlimporter.runImport() Seat 8 is the button
Total number of players: 10"""
cash_plo = """Everleaf Gaming Game #65295370
***** Hand history for game #65295370 *****
Blinds $0.50/$1 PL Omaha - 2008/12/07 - 21:59:48
Table Guanajuato
Seat 5 is the button
Total number of players: 6"""
cash_flhe = """Everleaf Gaming Game #55809022
***** Hand history for game #55809022 *****
$1/$2 Hold'em - 2008/09/07 - 08:04:36
Table Jeonju
Seat 4 is the button
Total number of players: 5
"""
#NLHE
m = self.everleaf.re_GameInfo.search(cash_nlhe)
sb = m.group('SB')
bb = m.group('BB')
ltype = m.group('LTYPE')
game = m.group('GAME')
self.failUnless(sb == "0.50", "SB incorrect, expected: 0.50 got: '" + sb + "'")
self.failUnless(bb == "1", "BB incorrect, expected: 1 got: '" + bb + "'")
self.failUnless(ltype == "NL", "LTYPE incorrect, expected: NL got: '" + ltype + "'")
self.failUnless(game == "Hold\'em", "GAME incorrect, expected: Hold\'em got: '" + game + "'")
#FLHE
m = self.everleaf.re_GameInfo.search(cash_flhe)
sb = m.group('SB')
bb = m.group('BB')
ltype = m.group('LTYPE')
game = m.group('GAME')
print m.groups()
self.failUnless(sb == "1", "SB incorrect, expected: 1 got: '" + sb + "'")
self.failUnless(bb == "2", "BB incorrect, expected: 2 got: '" + bb + "'")
self.failUnless(ltype == None, "LTYPE incorrect, expected: NL got: '%s'" %(ltype))
self.failUnless(game == "Hold\'em", "GAME incorrect, expected: Hold\'em got: '" + game + "'")
# def testImportHandHistoryFiles(self):
# """Test import of single HH file"""
# self.mysqlimporter.addImportFile("regression-test-files/hand-histories/ps-lhe-ring-3hands.txt")
# self.mysqlimporter.runImport()
# self.mysqlimporter.addImportDirectory("regression-test-files/hand-histories")
# self.mysqlimporter.runImport()
# def testPostgresSQLRecreateTables(self): # def testPostgresSQLRecreateTables(self):
# """Test droping then recreating fpdb table schema""" # """Test droping then recreating fpdb table schema"""

View File

@ -75,7 +75,7 @@ def totalprofit(stat_dict, player):
if stat_dict[player]['net'] != 0: if stat_dict[player]['net'] != 0:
stat = float(stat_dict[player]['net']) / 100 stat = float(stat_dict[player]['net']) / 100
return (stat, '$%.2f' % stat, 'tp=$%.2f' % stat, 'totalprofit=$%.2f' % stat, str(stat), 'Total Profit') return (stat, '$%.2f' % stat, 'tp=$%.2f' % stat, 'totalprofit=$%.2f' % stat, str(stat), 'Total Profit')
return ('0', '0', '0', '0', 'Total Profit') return ('0', '$0.00', 'tp=0', 'totalprofit=0', '0', 'Total Profit')
def playername(stat_dict, player): def playername(stat_dict, player):
""" Player Name.""" """ Player Name."""

View File

@ -22,13 +22,13 @@ from optparse import OptionParser
parser = OptionParser() parser = OptionParser()
parser.add_option("-x", "--errorsToConsole", action="store_true", parser.add_option("-x", "--errorsToConsole", action="store_true",
help="If passed error output will go to the console rather than .") help="If passed error output will go to the console rather than .")
(options, sys.argv) = parser.parse_args() (options, sys.argv) = parser.parse_args()
if not options.errorsToConsole: if not options.errorsToConsole:
print "Note: error output is being diverted to fpdb-error-log.txt and HUD-error.txt. Any major error will be reported there _only_." print "Note: error output is being diverted to fpdb-error-log.txt and HUD-error.txt. Any major error will be reported there _only_."
errorFile = open('fpdb-error-log.txt', 'w', 0) errorFile = open('fpdb-error-log.txt', 'w', 0)
sys.stderr = errorFile sys.stderr = errorFile
import pygtk import pygtk
pygtk.require('2.0') pygtk.require('2.0')
@ -38,6 +38,7 @@ import fpdb_db
import fpdb_simple import fpdb_simple
import GuiBulkImport import GuiBulkImport
import GuiPlayerStats import GuiPlayerStats
import GuiPositionalStats
import GuiTableViewer import GuiTableViewer
import GuiAutoImport import GuiAutoImport
import GuiGraphViewer import GuiGraphViewer
@ -47,419 +48,426 @@ import Configuration
VERSION = "0.10" VERSION = "0.10"
class fpdb: class fpdb:
def tab_clicked(self, widget, tab_name): def tab_clicked(self, widget, tab_name):
"""called when a tab button is clicked to activate that tab""" """called when a tab button is clicked to activate that tab"""
#print "start of tab_clicked" #print "start of tab_clicked"
self.display_tab(tab_name) self.display_tab(tab_name)
#end def tab_clicked #end def tab_clicked
def add_and_display_tab(self, new_tab, new_tab_name): def add_and_display_tab(self, new_tab, new_tab_name):
"""just calls the component methods""" """just calls the component methods"""
self.add_tab(new_tab, new_tab_name) self.add_tab(new_tab, new_tab_name)
self.display_tab(new_tab_name) self.display_tab(new_tab_name)
#end def add_and_display_tab #end def add_and_display_tab
def add_tab(self, new_tab, new_tab_name): def add_tab(self, new_tab, new_tab_name):
"""adds a tab, namely creates the button and displays it and appends all the relevant arrays""" """adds a tab, namely creates the button and displays it and appends all the relevant arrays"""
#print "start of add_tab" #print "start of add_tab"
for i in self.tab_names: #todo: check this is valid for i in self.tab_names: #todo: check this is valid
if i==new_tab_name: if i==new_tab_name:
return # we depend on this to not create duplicate tabs, there's no reason to raise an error here? return # we depend on this to not create duplicate tabs, there's no reason to raise an error here?
# raise fpdb_simple.FpdbError("duplicate tab_name not permitted") # raise fpdb_simple.FpdbError("duplicate tab_name not permitted")
self.tabs.append(new_tab) self.tabs.append(new_tab)
self.tab_names.append(new_tab_name) self.tab_names.append(new_tab_name)
new_tab_sel_button=gtk.ToggleButton(new_tab_name) new_tab_sel_button=gtk.ToggleButton(new_tab_name)
new_tab_sel_button.connect("clicked", self.tab_clicked, new_tab_name) new_tab_sel_button.connect("clicked", self.tab_clicked, new_tab_name)
self.tab_box.add(new_tab_sel_button) self.tab_box.add(new_tab_sel_button)
new_tab_sel_button.show() new_tab_sel_button.show()
self.tab_buttons.append(new_tab_sel_button) self.tab_buttons.append(new_tab_sel_button)
#end def add_tab #end def add_tab
def display_tab(self, new_tab_name): def display_tab(self, new_tab_name):
"""displays the indicated tab""" """displays the indicated tab"""
#print "start of display_tab, len(self.tab_names):",len(self.tab_names) #print "start of display_tab, len(self.tab_names):",len(self.tab_names)
tab_no=-1 tab_no=-1
#if len(self.tab_names)>1: #if len(self.tab_names)>1:
for i in range(len(self.tab_names)): for i in range(len(self.tab_names)):
#print "display_tab, new_tab_name:",new_tab_name," self.tab_names[i]:", self.tab_names[i] #print "display_tab, new_tab_name:",new_tab_name," self.tab_names[i]:", self.tab_names[i]
if (new_tab_name==self.tab_names[i]): if (new_tab_name==self.tab_names[i]):
tab_no=i tab_no=i
#self.tab_buttons[i].set_active(False) #self.tab_buttons[i].set_active(False)
#else: #else:
# tab_no=0 # tab_no=0
#current_tab_no=-1 #current_tab_no=-1
for i in range(len(self.tab_names)): for i in range(len(self.tab_names)):
if self.current_tab==self.tabs[i]: if self.current_tab==self.tabs[i]:
#self.tab_buttons[i].set_active(False) #self.tab_buttons[i].set_active(False)
pass pass
if tab_no==-1: if tab_no==-1:
raise fpdb_simple.FpdbError("invalid tab_no") raise fpdb_simple.FpdbError("invalid tab_no")
else: else:
self.main_vbox.remove(self.current_tab) self.main_vbox.remove(self.current_tab)
#self.current_tab.destroy() #self.current_tab.destroy()
self.current_tab=self.tabs[tab_no] self.current_tab=self.tabs[tab_no]
self.main_vbox.add(self.current_tab) self.main_vbox.add(self.current_tab)
self.tab_buttons[tab_no].set_active(True) self.tab_buttons[tab_no].set_active(True)
self.current_tab.show() self.current_tab.show()
#end def display_tab #end def display_tab
def delete_event(self, widget, event, data=None): def delete_event(self, widget, event, data=None):
return False return False
#end def delete_event #end def delete_event
def destroy(self, widget, data=None): def destroy(self, widget, data=None):
self.quit(widget, data) self.quit(widget, data)
#end def destroy #end def destroy
def dia_about(self, widget, data): def dia_about(self, widget, data):
print "todo: implement dia_about", print "todo: implement dia_about",
print " version = %s, requires database version %s" % (VERSION, "118") print " version = %s, requires database version %s" % (VERSION, "118")
#end def dia_about #end def dia_about
def dia_create_del_database(self, widget, data): def dia_create_del_database(self, widget, data):
print "todo: implement dia_create_del_database" print "todo: implement dia_create_del_database"
self.obtain_global_lock() self.obtain_global_lock()
#end def dia_create_del_database #end def dia_create_del_database
def dia_create_del_user(self, widget, data): def dia_create_del_user(self, widget, data):
print "todo: implement dia_create_del_user" print "todo: implement dia_create_del_user"
self.obtain_global_lock() self.obtain_global_lock()
#end def dia_create_del_user #end def dia_create_del_user
def dia_database_stats(self, widget, data): def dia_database_stats(self, widget, data):
print "todo: implement dia_database_stats" print "todo: implement dia_database_stats"
#string=fpdb_db.getDbStats(db, cursor) #string=fpdb_db.getDbStats(db, cursor)
#end def dia_database_stats #end def dia_database_stats
def dia_delete_db_parts(self, widget, data): def dia_delete_db_parts(self, widget, data):
print "todo: implement dia_delete_db_parts" print "todo: implement dia_delete_db_parts"
self.obtain_global_lock() self.obtain_global_lock()
#end def dia_delete_db_parts #end def dia_delete_db_parts
def dia_edit_profile(self, widget=None, data=None, create_default=False, path=None): def dia_edit_profile(self, widget=None, data=None, create_default=False, path=None):
print "todo: implement dia_edit_profile" print "todo: implement dia_edit_profile"
self.obtain_global_lock() self.obtain_global_lock()
#end def dia_edit_profile #end def dia_edit_profile
def dia_export_db(self, widget, data): def dia_export_db(self, widget, data):
print "todo: implement dia_export_db" print "todo: implement dia_export_db"
self.obtain_global_lock() self.obtain_global_lock()
#end def dia_export_db #end def dia_export_db
def dia_get_db_root_credentials(self): def dia_get_db_root_credentials(self):
"""obtains db root credentials from user""" """obtains db root credentials from user"""
print "todo: implement dia_get_db_root_credentials" print "todo: implement dia_get_db_root_credentials"
# user, pw=None, None # user, pw=None, None
# #
# dialog=gtk.Dialog(title="DB Credentials needed", parent=None, flags=0, # dialog=gtk.Dialog(title="DB Credentials needed", parent=None, flags=0,
# buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,"Connect and recreate",gtk.RESPONSE_OK)) # buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,"Connect and recreate",gtk.RESPONSE_OK))
# #
# label_warning1=gtk.Label("Please enter credentials for a database user for "+self.host+" that has permissions to create a database.") # label_warning1=gtk.Label("Please enter credentials for a database user for "+self.host+" that has permissions to create a database.")
# #
# #
# label_user=gtk.Label("Username") # label_user=gtk.Label("Username")
# dialog.vbox.add(label_user) # dialog.vbox.add(label_user)
# label_user.show() # label_user.show()
# #
# response=dialog.run() # response=dialog.run()
# dialog.destroy() # dialog.destroy()
# return (user, pw, response) # return (user, pw, response)
#end def dia_get_db_root_credentials #end def dia_get_db_root_credentials
def dia_import_db(self, widget, data): def dia_import_db(self, widget, data):
print "todo: implement dia_import_db" print "todo: implement dia_import_db"
self.obtain_global_lock() self.obtain_global_lock()
#end def dia_import_db #end def dia_import_db
def dia_licensing(self, widget, data): def dia_licensing(self, widget, data):
print "todo: implement dia_licensing" print "todo: implement dia_licensing"
#end def dia_licensing #end def dia_licensing
def dia_load_profile(self, widget, data): def dia_load_profile(self, widget, data):
"""Dialogue to select a file to load a profile from""" """Dialogue to select a file to load a profile from"""
self.obtain_global_lock() self.obtain_global_lock()
chooser = gtk.FileChooserDialog(title="Please select a profile file to load", chooser = gtk.FileChooserDialog(title="Please select a profile file to load",
action=gtk.FILE_CHOOSER_ACTION_OPEN, action=gtk.FILE_CHOOSER_ACTION_OPEN,
buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
chooser.set_filename(self.profile) chooser.set_filename(self.profile)
response = chooser.run() response = chooser.run()
chooser.destroy() chooser.destroy()
if response == gtk.RESPONSE_OK: if response == gtk.RESPONSE_OK:
self.load_profile(chooser.get_filename()) self.load_profile(chooser.get_filename())
elif response == gtk.RESPONSE_CANCEL: elif response == gtk.RESPONSE_CANCEL:
print 'User cancelled loading profile' print 'User cancelled loading profile'
#end def dia_load_profile #end def dia_load_profile
def dia_recreate_tables(self, widget, data): def dia_recreate_tables(self, widget, data):
"""Dialogue that asks user to confirm that he wants to delete and recreate the tables""" """Dialogue that asks user to confirm that he wants to delete and recreate the tables"""
self.obtain_global_lock() self.obtain_global_lock()
dia_confirm=gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, dia_confirm=gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING,
buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm deleting and recreating tables") buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm deleting and recreating tables")
diastring=("Please confirm that you want to (re-)create the tables. If there already are tables in the database "+self.db.database+" on "+self.db.host+" they will be deleted.") diastring=("Please confirm that you want to (re-)create the tables. If there already are tables in the database "+self.db.database+" on "+self.db.host+" they will be deleted.")
dia_confirm.format_secondary_text(diastring)#todo: make above string with bold for db, host and deleted dia_confirm.format_secondary_text(diastring)#todo: make above string with bold for db, host and deleted
response=dia_confirm.run() response=dia_confirm.run()
dia_confirm.destroy() dia_confirm.destroy()
if response == gtk.RESPONSE_YES: if response == gtk.RESPONSE_YES:
self.db.recreate_tables() self.db.recreate_tables()
elif response == gtk.RESPONSE_NO: elif response == gtk.RESPONSE_NO:
print 'User cancelled recreating tables' print 'User cancelled recreating tables'
#end def dia_recreate_tables #end def dia_recreate_tables
def dia_regression_test(self, widget, data): def dia_regression_test(self, widget, data):
print "todo: implement dia_regression_test" print "todo: implement dia_regression_test"
self.obtain_global_lock() self.obtain_global_lock()
#end def dia_regression_test #end def dia_regression_test
def dia_save_profile(self, widget, data): def dia_save_profile(self, widget, data):
print "todo: implement dia_save_profile" print "todo: implement dia_save_profile"
#end def dia_save_profile #end def dia_save_profile
def diaSetupWizard(self, path): def diaSetupWizard(self, path):
print "todo: implement setup wizard" print "todo: implement setup wizard"
print "setup wizard not implemented - please create the default configuration file:", path print "setup wizard not implemented - please create the default configuration file:", path
diaSetupWizard = gtk.Dialog(title="Fatal Error - Config File Missing", parent=None, flags=0, buttons=(gtk.STOCK_QUIT,gtk.RESPONSE_OK)) diaSetupWizard = gtk.Dialog(title="Fatal Error - Config File Missing", parent=None, flags=0, buttons=(gtk.STOCK_QUIT,gtk.RESPONSE_OK))
label = gtk.Label("Please copy the config file from the docs folder to:") label = gtk.Label("Please copy the config file from the docs folder to:")
diaSetupWizard.vbox.add(label) diaSetupWizard.vbox.add(label)
label.show() label.show()
label = gtk.Label(path) label = gtk.Label(path)
diaSetupWizard.vbox.add(label) diaSetupWizard.vbox.add(label)
label.show() label.show()
label = gtk.Label("and edit it according to the install documentation at http://fpdb.sourceforge.net") label = gtk.Label("and edit it according to the install documentation at http://fpdb.sourceforge.net")
diaSetupWizard.vbox.add(label) diaSetupWizard.vbox.add(label)
label.show() label.show()
response = diaSetupWizard.run() response = diaSetupWizard.run()
sys.exit(1) sys.exit(1)
#end def diaSetupWizard #end def diaSetupWizard
def get_menu(self, window): def get_menu(self, window):
"""returns the menu for this program""" """returns the menu for this program"""
accel_group = gtk.AccelGroup() accel_group = gtk.AccelGroup()
self.item_factory = gtk.ItemFactory(gtk.MenuBar, "<main>", accel_group) self.item_factory = gtk.ItemFactory(gtk.MenuBar, "<main>", accel_group)
self.item_factory.create_items(self.menu_items) self.item_factory.create_items(self.menu_items)
window.add_accel_group(accel_group) window.add_accel_group(accel_group)
return self.item_factory.get_widget("<main>") return self.item_factory.get_widget("<main>")
#end def get_menu #end def get_menu
def load_profile(self): def load_profile(self):
"""Loads profile from the provided path name.""" """Loads profile from the provided path name."""
self.settings = {} self.settings = {}
if (os.sep=="/"): if (os.sep=="/"):
self.settings['os']="linuxmac" self.settings['os']="linuxmac"
else: else:
self.settings['os']="windows" self.settings['os']="windows"
self.settings.update(self.config.get_db_parameters()) self.settings.update(self.config.get_db_parameters())
self.settings.update(self.config.get_tv_parameters()) self.settings.update(self.config.get_tv_parameters())
self.settings.update(self.config.get_import_parameters()) self.settings.update(self.config.get_import_parameters())
self.settings.update(self.config.get_default_paths()) self.settings.update(self.config.get_default_paths())
if self.db!=None: if self.db!=None:
self.db.disconnect() self.db.disconnect()
self.db = fpdb_db.fpdb_db() self.db = fpdb_db.fpdb_db()
#print "end of fpdb.load_profile, databaseName:",self.settings['db-databaseName'] #print "end of fpdb.load_profile, databaseName:",self.settings['db-databaseName']
self.db.connect(self.settings['db-backend'], self.db.connect(self.settings['db-backend'],
self.settings['db-host'], self.settings['db-host'],
self.settings['db-databaseName'], self.settings['db-databaseName'],
self.settings['db-user'], self.settings['db-user'],
self.settings['db-password']) self.settings['db-password'])
if self.db.wrongDbVersion: if self.db.wrongDbVersion:
diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK))
label = gtk.Label("An invalid DB version or missing tables have been detected.") label = gtk.Label("An invalid DB version or missing tables have been detected.")
diaDbVersionWarning.vbox.add(label) diaDbVersionWarning.vbox.add(label)
label.show() label.show()
label = gtk.Label("This error is not necessarily fatal but it is strongly recommended that you recreate the tables by using the Database menu.") label = gtk.Label("This error is not necessarily fatal but it is strongly recommended that you recreate the tables by using the Database menu.")
diaDbVersionWarning.vbox.add(label) diaDbVersionWarning.vbox.add(label)
label.show() label.show()
label = gtk.Label("Not doing this will likely lead to misbehaviour including fpdb crashes, corrupt data etc.") label = gtk.Label("Not doing this will likely lead to misbehaviour including fpdb crashes, corrupt data etc.")
diaDbVersionWarning.vbox.add(label) diaDbVersionWarning.vbox.add(label)
label.show() label.show()
response = diaDbVersionWarning.run() response = diaDbVersionWarning.run()
diaDbVersionWarning.destroy() diaDbVersionWarning.destroy()
# Database connected to successfully, load queries to pass on to other classes # Database connected to successfully, load queries to pass on to other classes
self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name())
#end def load_profile #end def load_profile
def not_implemented(self): def not_implemented(self):
print "todo: called unimplemented menu entry (users: pls ignore this)"#remove this once more entries are implemented print "todo: called unimplemented menu entry (users: pls ignore this)"#remove this once more entries are implemented
#end def not_implemented #end def not_implemented
def obtain_global_lock(self): def obtain_global_lock(self):
print "todo: implement obtain_global_lock (users: pls ignore this)" print "todo: implement obtain_global_lock (users: pls ignore this)"
#end def obtain_global_lock #end def obtain_global_lock
def quit(self, widget, data): def quit(self, widget, data):
print "Quitting normally" print "Quitting normally"
#check if current settings differ from profile, if so offer to save or abort #check if current settings differ from profile, if so offer to save or abort
self.db.disconnect() self.db.disconnect()
gtk.main_quit() gtk.main_quit()
#end def quit_cliecked #end def quit_cliecked
def release_global_lock(self): def release_global_lock(self):
print "todo: implement release_global_lock" print "todo: implement release_global_lock"
#end def release_global_lock #end def release_global_lock
def tab_abbreviations(self, widget, data): def tab_abbreviations(self, widget, data):
print "todo: implement tab_abbreviations" print "todo: implement tab_abbreviations"
#end def tab_abbreviations #end def tab_abbreviations
def tab_auto_import(self, widget, data): def tab_auto_import(self, widget, data):
"""opens the auto import tab""" """opens the auto import tab"""
new_aimp_thread=GuiAutoImport.GuiAutoImport(self.settings, self.config) new_aimp_thread=GuiAutoImport.GuiAutoImport(self.settings, self.config)
self.threads.append(new_aimp_thread) self.threads.append(new_aimp_thread)
aimp_tab=new_aimp_thread.get_vbox() aimp_tab=new_aimp_thread.get_vbox()
self.add_and_display_tab(aimp_tab, "Auto Import") self.add_and_display_tab(aimp_tab, "Auto Import")
#end def tab_auto_import #end def tab_auto_import
def tab_bulk_import(self, widget, data): def tab_bulk_import(self, widget, data):
"""opens a tab for bulk importing""" """opens a tab for bulk importing"""
#print "start of tab_bulk_import" #print "start of tab_bulk_import"
new_import_thread=GuiBulkImport.GuiBulkImport(self.db, self.settings, self.config) new_import_thread=GuiBulkImport.GuiBulkImport(self.db, self.settings, self.config)
self.threads.append(new_import_thread) self.threads.append(new_import_thread)
bulk_tab=new_import_thread.get_vbox() bulk_tab=new_import_thread.get_vbox()
self.add_and_display_tab(bulk_tab, "Bulk Import") self.add_and_display_tab(bulk_tab, "Bulk Import")
#end def tab_bulk_import #end def tab_bulk_import
def tab_player_stats(self, widget, data): def tab_player_stats(self, widget, data):
new_ps_thread=GuiPlayerStats.GuiPlayerStats(self.db, self.config, self.querydict) new_ps_thread=GuiPlayerStats.GuiPlayerStats(self.db, self.config, self.querydict)
self.threads.append(new_ps_thread) self.threads.append(new_ps_thread)
ps_tab=new_ps_thread.get_vbox() ps_tab=new_ps_thread.get_vbox()
self.add_and_display_tab(ps_tab, "Player Stats") self.add_and_display_tab(ps_tab, "Player Stats")
def tab_positional_stats(self, widget, data):
new_ps_thread=GuiPositionalStats.GuiPositionalStats(self.db, self.config, self.querydict)
self.threads.append(new_ps_thread)
ps_tab=new_ps_thread.get_vbox()
self.add_and_display_tab(ps_tab, "Ppositional Stats")
def tab_main_help(self, widget, data): def tab_main_help(self, widget, data):
"""Displays a tab with the main fpdb help screen""" """Displays a tab with the main fpdb help screen"""
#print "start of tab_main_help" #print "start of tab_main_help"
mh_tab=gtk.Label("""Welcome to Fpdb! mh_tab=gtk.Label("""Welcome to Fpdb!
For documentation please visit our website at http://fpdb.sourceforge.net/ or check the docs directory in the fpdb folder. For documentation please visit our website at http://fpdb.sourceforge.net/ or check the docs directory in the fpdb folder.
Please note that default.conf is no longer needed nor used, all configuration now happens in HUD_config.xml Please note that default.conf is no longer needed nor used, all configuration now happens in HUD_config.xml
This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
self.add_and_display_tab(mh_tab, "Help") self.add_and_display_tab(mh_tab, "Help")
#end def tab_main_help #end def tab_main_help
def tab_table_viewer(self, widget, data): def tab_table_viewer(self, widget, data):
"""opens a table viewer tab""" """opens a table viewer tab"""
#print "start of tab_table_viewer" #print "start of tab_table_viewer"
new_tv_thread=GuiTableViewer.GuiTableViewer(self.db, self.settings) new_tv_thread=GuiTableViewer.GuiTableViewer(self.db, self.settings)
self.threads.append(new_tv_thread) self.threads.append(new_tv_thread)
tv_tab=new_tv_thread.get_vbox() tv_tab=new_tv_thread.get_vbox()
self.add_and_display_tab(tv_tab, "Table Viewer") self.add_and_display_tab(tv_tab, "Table Viewer")
#end def tab_table_viewer #end def tab_table_viewer
def tabGraphViewer(self, widget, data): def tabGraphViewer(self, widget, data):
"""opens a graph viewer tab""" """opens a graph viewer tab"""
#print "start of tabGraphViewer" #print "start of tabGraphViewer"
new_gv_thread=GuiGraphViewer.GuiGraphViewer(self.db, self.settings, self.querydict, self.config) new_gv_thread=GuiGraphViewer.GuiGraphViewer(self.db, self.settings, self.querydict, self.config)
self.threads.append(new_gv_thread) self.threads.append(new_gv_thread)
gv_tab=new_gv_thread.get_vbox() gv_tab=new_gv_thread.get_vbox()
self.add_and_display_tab(gv_tab, "Graphs") self.add_and_display_tab(gv_tab, "Graphs")
#end def tabGraphViewer #end def tabGraphViewer
def __init__(self): def __init__(self):
self.threads=[] self.threads=[]
self.db=None self.db=None
self.config = Configuration.Config() self.config = Configuration.Config()
self.load_profile() self.load_profile()
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.connect("delete_event", self.delete_event) self.window.connect("delete_event", self.delete_event)
self.window.connect("destroy", self.destroy) self.window.connect("destroy", self.destroy)
self.window.set_title("Free Poker DB - v%s or higher" % (VERSION, )) self.window.set_title("Free Poker DB - v%s or higher" % (VERSION, ))
self.window.set_border_width(1) self.window.set_border_width(1)
self.window.set_size_request(1020,400) self.window.set_size_request(1020,400)
self.window.set_resizable(True) self.window.set_resizable(True)
self.menu_items = ( self.menu_items = (
( "/_Main", None, None, 0, "<Branch>" ), ( "/_Main", None, None, 0, "<Branch>" ),
( "/Main/_Load Profile (broken)", "<control>L", self.dia_load_profile, 0, None ), ( "/Main/_Load Profile (broken)", "<control>L", self.dia_load_profile, 0, None ),
( "/Main/_Edit Profile (todo)", "<control>E", self.dia_edit_profile, 0, None ), ( "/Main/_Edit Profile (todo)", "<control>E", self.dia_edit_profile, 0, None ),
( "/Main/_Save Profile (todo)", None, self.dia_save_profile, 0, None ), ( "/Main/_Save Profile (todo)", None, self.dia_save_profile, 0, None ),
("/Main/sep1", None, None, 0, "<Separator>" ), ("/Main/sep1", None, None, 0, "<Separator>" ),
("/Main/_Quit", "<control>Q", self.quit, 0, None ), ("/Main/_Quit", "<control>Q", self.quit, 0, None ),
("/_Import", None, None, 0, "<Branch>" ), ("/_Import", None, None, 0, "<Branch>" ),
("/Import/_Bulk Import", "<control>B", self.tab_bulk_import, 0, None ), ("/Import/_Bulk Import", "<control>B", self.tab_bulk_import, 0, None ),
("/Import/_Auto Import and HUD", "<control>A", self.tab_auto_import, 0, None ), ("/Import/_Auto Import and HUD", "<control>A", self.tab_auto_import, 0, None ),
("/Import/Auto _Rating (todo)", "<control>R", self.not_implemented, 0, None ), ("/Import/Auto _Rating (todo)", "<control>R", self.not_implemented, 0, None ),
("/_Viewers", None, None, 0, "<Branch>" ), ("/_Viewers", None, None, 0, "<Branch>" ),
("/_Viewers/_Auto Import and HUD", "<control>A", self.tab_auto_import, 0, None ), ("/_Viewers/_Auto Import and HUD", "<control>A", self.tab_auto_import, 0, None ),
("/Viewers/_Graphs", "<control>G", self.tabGraphViewer, 0, None ), ("/Viewers/_Graphs", "<control>G", self.tabGraphViewer, 0, None ),
("/Viewers/Hand _Replayer (todo)", None, self.not_implemented, 0, None ), ("/Viewers/Hand _Replayer (todo)", None, self.not_implemented, 0, None ),
("/Viewers/Player _Details (todo)", None, self.not_implemented, 0, None ), ("/Viewers/Player _Details (todo)", None, self.not_implemented, 0, None ),
("/Viewers/_Player Stats (tabulated view)", None, self.tab_player_stats, 0, None ), ("/Viewers/_Player Stats (tabulated view)", None, self.tab_player_stats, 0, None ),
("/Viewers/Starting _Hands (todo)", None, self.not_implemented, 0, None ), ("/Viewers/Positional Stats (tabulated view)", None, self.tab_positional_stats, 0, None ),
("/Viewers/_Session Replayer (todo)", None, self.not_implemented, 0, None ), ("/Viewers/Starting _Hands (todo)", None, self.not_implemented, 0, None ),
("/Viewers/Poker_table Viewer (mostly obselete)", "<control>T", self.tab_table_viewer, 0, None ), ("/Viewers/_Session Replayer (todo)", None, self.not_implemented, 0, None ),
#( "/Viewers/Tourney Replayer ("/Viewers/Poker_table Viewer (mostly obselete)", "<control>T", self.tab_table_viewer, 0, None ),
( "/_Database", None, None, 0, "<Branch>" ), #( "/Viewers/Tourney Replayer
( "/Database/Create or Delete _Database (todo)", None, self.dia_create_del_database, 0, None ), ( "/_Database", None, None, 0, "<Branch>" ),
( "/Database/Create or Delete _User (todo)", None, self.dia_create_del_user, 0, None ), ( "/Database/Create or Delete _Database (todo)", None, self.dia_create_del_database, 0, None ),
( "/Database/Create or Recreate _Tables", None, self.dia_recreate_tables, 0, None ), ( "/Database/Create or Delete _User (todo)", None, self.dia_create_del_user, 0, None ),
( "/Database/_Statistics (todo)", None, self.dia_database_stats, 0, None ), ( "/Database/Create or Recreate _Tables", None, self.dia_recreate_tables, 0, None ),
( "/D_ebugging", None, None, 0, "<Branch>" ), ( "/Database/_Statistics (todo)", None, self.dia_database_stats, 0, None ),
( "/Debugging/_Delete Parts of Database (todo)", None, self.dia_delete_db_parts, 0, None ), ( "/D_ebugging", None, None, 0, "<Branch>" ),
( "/Debugging/_Export DB (todo)", None, self.dia_export_db, 0, None ), ( "/Debugging/_Delete Parts of Database (todo)", None, self.dia_delete_db_parts, 0, None ),
( "/Debugging/_Import DB (todo)", None, self.dia_import_db, 0, None ), ( "/Debugging/_Export DB (todo)", None, self.dia_export_db, 0, None ),
( "/Debugging/_Regression test (todo)", None, self.dia_regression_test, 0, None ), ( "/Debugging/_Import DB (todo)", None, self.dia_import_db, 0, None ),
( "/_Help", None, None, 0, "<LastBranch>" ), ( "/Debugging/_Regression test (todo)", None, self.dia_regression_test, 0, None ),
( "/Help/_Main Help", "<control>H", self.tab_main_help, 0, None ), ( "/_Help", None, None, 0, "<LastBranch>" ),
( "/Help/_Abbrevations (todo)", None, self.tab_abbreviations, 0, None ), ( "/Help/_Main Help", "<control>H", self.tab_main_help, 0, None ),
( "/Help/sep1", None, None, 0, "<Separator>" ), ( "/Help/_Abbrevations (todo)", None, self.tab_abbreviations, 0, None ),
( "/Help/A_bout (todo)", None, self.dia_about, 0, None ), ( "/Help/sep1", None, None, 0, "<Separator>" ),
( "/Help/_License and Copying (todo)", None, self.dia_licensing, 0, None ) ( "/Help/A_bout (todo)", None, self.dia_about, 0, None ),
) ( "/Help/_License and Copying (todo)", None, self.dia_licensing, 0, None )
)
self.main_vbox = gtk.VBox(False, 1) self.main_vbox = gtk.VBox(False, 1)
self.main_vbox.set_border_width(1) self.main_vbox.set_border_width(1)
self.window.add(self.main_vbox) self.window.add(self.main_vbox)
self.main_vbox.show() self.main_vbox.show()
menubar = self.get_menu(self.window) menubar = self.get_menu(self.window)
self.main_vbox.pack_start(menubar, False, True, 0) self.main_vbox.pack_start(menubar, False, True, 0)
menubar.show() menubar.show()
#done menubar #done menubar
self.tabs=[] self.tabs=[]
self.tab_names=[] self.tab_names=[]
self.tab_buttons=[] self.tab_buttons=[]
self.tab_box = gtk.HBox(False,1) self.tab_box = gtk.HBox(False,1)
self.main_vbox.pack_start(self.tab_box, False, True, 0) self.main_vbox.pack_start(self.tab_box, False, True, 0)
self.tab_box.show() self.tab_box.show()
#done tab bar #done tab bar
self.current_tab = gtk.VBox(False,1) self.current_tab = gtk.VBox(False,1)
self.current_tab.set_border_width(1) self.current_tab.set_border_width(1)
self.main_vbox.add(self.current_tab) self.main_vbox.add(self.current_tab)
self.current_tab.show() self.current_tab.show()
self.tab_main_help(None, None) self.tab_main_help(None, None)
self.status_bar = gtk.Label("Status: Connected to "+self.db.get_backend_name()+" database named "+self.db.database+" on host "+self.db.host) self.status_bar = gtk.Label("Status: Connected to "+self.db.get_backend_name()+" database named "+self.db.database+" on host "+self.db.host)
self.main_vbox.pack_end(self.status_bar, False, True, 0) self.main_vbox.pack_end(self.status_bar, False, True, 0)
self.status_bar.show() self.status_bar.show()
self.window.show() self.window.show()
#end def __init__ #end def __init__
def main(self): def main(self):
gtk.main() gtk.main()
return 0 return 0
#end def main #end def main
if __name__ == "__main__": if __name__ == "__main__":
me = fpdb() me = fpdb()
me.main() me.main()