Merge branch 'master' into monkeyfutz

Everleaf converts hands
Moved process hand logic into the hand subclass that knows what it
wants, it calls back to the hhc (which knows about the format) to populate itself

Conflicts:

	pyfpdb/EverleafToFpdb.py
	pyfpdb/Hand.py
	pyfpdb/HandHistoryConverter.py
This commit is contained in:
Matt Turnbull 2009-03-01 23:22:47 +00:00
commit 5c26bb028d
13 changed files with 396 additions and 374 deletions

View File

@ -62,6 +62,7 @@ class Site:
self.aux_window = node.getAttribute("aux_window") self.aux_window = node.getAttribute("aux_window")
self.font = node.getAttribute("font") self.font = node.getAttribute("font")
self.font_size = node.getAttribute("font_size") self.font_size = node.getAttribute("font_size")
self.use_frames = node.getAttribute("use_frames")
self.layout = {} self.layout = {}
for layout_node in node.getElementsByTagName('layout'): for layout_node in node.getElementsByTagName('layout'):
@ -466,6 +467,9 @@ class Config:
paths['bulkImport-defaultPath'] = "default" paths['bulkImport-defaultPath'] = "default"
return paths return paths
def get_frames(self, site = "PokerStars"):
return self.supported_sites[site].use_frames == "True"
def get_default_colors(self, site = "PokerStars"): def get_default_colors(self, site = "PokerStars"):
colors = {} colors = {}
if self.supported_sites[site].hudopacity == "": if self.supported_sites[site].hudopacity == "":

View File

@ -116,31 +116,30 @@ class Database:
row = c.fetchone() row = c.fetchone()
return row[0] return row[0]
# def get_cards(self, hand):
# this version is for the PTrackSv2 db
# c = self.connection.cursor()
# c.execute(self.sql.query['get_cards'], hand)
# colnames = [desc[0] for desc in c.description]
# cards = {}
# for row in c.fetchall():
# s_dict = {}
# for name, val in zip(colnames, row):
# s_dict[name] = val
# cards[s_dict['seat_number']] = s_dict
# return (cards)
def get_cards(self, hand): def get_cards(self, hand):
# this version is for the fpdb db """Get and return the cards for each player in the hand."""
cards = {} # dict of cards, the key is the seat number example: {1: 'AcQd9hTs5d'}
c = self.connection.cursor() c = self.connection.cursor()
c.execute(self.sql.query['get_cards'], hand) c.execute(self.sql.query['get_cards'], hand)
colnames = [desc[0] for desc in c.description] colnames = [desc[0] for desc in c.description]
cards = {}
for row in c.fetchall(): for row in c.fetchall():
s_dict = {} s_dict = {}
for name, val in zip(colnames, row): for name, val in zip(colnames, row):
s_dict[name] = val s_dict[name] = val
cards[s_dict['seat_number']] = s_dict cards[s_dict['seat_number']] = (self.convert_cards(s_dict))
return (cards) return cards
def convert_cards(self, d):
ranks = ('', '', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A')
cards = ""
for i in range(1, 8):
if d['card' + str(i) + 'Value'] == None:
break
elif d['card' + str(i) + 'Value'] == 0:
cards += "xx"
else:
cards += ranks[d['card' + str(i) + 'Value']] + d['card' +str(i) + 'Suit']
return cards
def get_action_from_hand(self, hand_no): def get_action_from_hand(self, hand_no):
action = [ [], [], [], [], [] ] action = [ [], [], [], [], [] ]
@ -214,6 +213,7 @@ if __name__=="__main__":
for p in stat_dict.keys(): for p in stat_dict.keys():
print p, " ", stat_dict[p] print p, " ", stat_dict[p]
print "cards =", db_connection.get_cards(73525)
db_connection.close_connection db_connection.close_connection
print "press enter to continue" print "press enter to continue"

View File

@ -40,23 +40,26 @@ class Everleaf(HandHistoryConverter):
in_path (default '-' = sys.stdin) in_path (default '-' = sys.stdin)
out_path (default '-' = sys.stdout) out_path (default '-' = sys.stdout)
follow : whether to tail -f the input""" follow : whether to tail -f the input"""
super(Everleaf, self).__init__(in_path, out_path, sitename="Everleaf", follow=follow) # Call super class init. HandHistoryConverter.__init__(self, in_path, out_path, sitename="Everleaf", follow=follow)
logging.info("Initialising Everleaf converter class") logging.info("Initialising Everleaf converter class")
self.filetype = "text" self.filetype = "text"
self.codepage = "cp1252" self.codepage = "cp1252"
self.start() self.start()
def compilePlayerRegexs(self): def compilePlayerRegexs(self, players):
player_re = "(?P<PNAME>" + "|".join(map(re.escape, self.players)) + ")" if not players <= self.compiledPlayers: # x <= y means 'x is subset of y'
logging.debug("player_re: "+ player_re) # we need to recompile the player regexs.
self.re_PostSB = re.compile(r"^%s: posts small blind \[\$? (?P<SB>[.0-9]+)" % player_re, re.MULTILINE) self.compiledPlayers = players
self.re_PostBB = re.compile(r"^%s: posts big blind \[\$? (?P<BB>[.0-9]+)" % player_re, re.MULTILINE) player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")"
self.re_PostBoth = re.compile(r"^%s: posts both blinds \[\$? (?P<SBBB>[.0-9]+)" % player_re, re.MULTILINE) logging.debug("player_re: "+ player_re)
self.re_HeroCards = re.compile(r"^Dealt to %s \[ (?P<CARDS>.*) \]" % player_re, re.MULTILINE) self.re_PostSB = re.compile(r"^%s: posts small blind \[\$? (?P<SB>[.0-9]+)" % player_re, re.MULTILINE)
self.re_Action = re.compile(r"^%s(?P<ATYPE>: bets| checks| raises| calls| folds)(\s\[\$ (?P<BET>[.\d]+) (USD|EUR)\])?" % player_re, re.MULTILINE) self.re_PostBB = re.compile(r"^%s: posts big blind \[\$? (?P<BB>[.0-9]+)" % player_re, re.MULTILINE)
self.re_ShowdownAction = re.compile(r"^%s shows \[ (?P<CARDS>.*) \]" % player_re, re.MULTILINE) self.re_PostBoth = re.compile(r"^%s: posts both blinds \[\$? (?P<SBBB>[.0-9]+)" % player_re, re.MULTILINE)
self.re_CollectPot = re.compile(r"^%s wins \$ (?P<POT>[.\d]+) (USD|EUR)(.*?\[ (?P<CARDS>.*?) \])?" % player_re, re.MULTILINE) self.re_HeroCards = re.compile(r"^Dealt to %s \[ (?P<CARDS>.*) \]" % player_re, re.MULTILINE)
self.re_SitsOut = re.compile(r"^%s sits out" % player_re, re.MULTILINE) self.re_Action = re.compile(r"^%s(?P<ATYPE>: bets| checks| raises| calls| folds)(\s\[\$ (?P<BET>[.\d]+) (USD|EUR)\])?" % player_re, re.MULTILINE)
self.re_ShowdownAction = re.compile(r"^%s shows \[ (?P<CARDS>.*) \]" % player_re, re.MULTILINE)
self.re_CollectPot = re.compile(r"^%s wins \$ (?P<POT>[.\d]+) (USD|EUR)(.*?\[ (?P<CARDS>.*?) \])?" % player_re, re.MULTILINE)
self.re_SitsOut = re.compile(r"^%s sits out" % player_re, re.MULTILINE)
def readSupportedGames(self): def readSupportedGames(self):
return [["ring", "hold", "nl"], return [["ring", "hold", "nl"],
@ -69,6 +72,13 @@ follow : whether to tail -f the input"""
# 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
# $0.25/$0.50 7 Card Stud - 2008/12/05 - 21:43:59 # $0.25/$0.50 7 Card Stud - 2008/12/05 - 21:43:59
# Tourney:
# Everleaf Gaming Game #75065769
# ***** Hand history for game #75065769 *****
# Blinds 10/20 NL Hold'em - 2009/02/25 - 17:30:32
# Table 2
structure = "" # nl, pl, cn, cp, fl structure = "" # nl, pl, cn, cp, fl
game = "" game = ""
@ -95,84 +105,89 @@ follow : whether to tail -f the input"""
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):
logging.info("Didn't match re_HandInfo") logging.info("Didn't match re_HandInfo")
logging.info(hand.handtext) logging.info(hand.handtext)
return None return None
logging.debug("HID %s" % m.group('HID')) logging.debug("HID %s, Table %s" % (m.group('HID'), m.group('TABLE')))
hand.handid = m.group('HID') hand.handid = m.group('HID')
hand.tablename = m.group('TABLE')
hand.maxseats = 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
# 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 return
#return({'HID': m.group('HID'), 'table':m.group('TABLE'), 'max_seats':6})
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)
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
if street in ('FLOP','TURN','RIVER'): # a list of streets which get dealt community cards (i.e. all but PREFLOP) # If this has been called, street is a street which gets dealt community cards by type hand
m = self.re_Board.search(hand.streets.group(street)) # but it might be worth checking somehow.
hand.setCommunityCards(street, m.group('CARDS').split(', ')) # if street in ('FLOP','TURN','RIVER'): # a list of streets which get dealt community cards (i.e. all but PREFLOP)
m = self.re_Board.search(hand.streets[street])
cards = m.group('CARDS')
cards = [card.strip() for card in cards.split(',')]
hand.setCommunityCards(street, cards)
def readBlinds(self, hand): def readBlinds(self, hand):
m = self.re_PostSB.search(hand.string) m = self.re_PostSB.search(hand.handText)
if m is not None: 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'))
else: else:
logging.debug("No small blind") 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 = set(cards.split(', ')) cards = [card.strip() for card in 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):
m = self.re_Action.finditer(hand.streets.group(street)) m = self.re_Action.finditer(hand.streets[street])
for action in m: for action in m:
if action.group('ATYPE') == ' raises': if action.group('ATYPE') == ' raises':
hand.addCallandRaise( street, action.group('PNAME'), action.group('BET') ) hand.addCallandRaise( street, action.group('PNAME'), action.group('BET') )
@ -189,20 +204,22 @@ follow : whether to tail -f the input"""
def readShowdownActions(self, hand): def readShowdownActions(self, hand):
for shows in self.re_ShowdownAction.finditer(hand.string): """Reads lines where holecards are reported in a showdown"""
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_CollectPot.finditer(hand.string): """Reads lines where hole & board cards are mixed to form a hand (summary lines)"""
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 = set(cards.split(', ')) cards = cards.split(', ')
hand.addShownCards(cards=None, player=m.group('PNAME'), holeandboard=cards) hand.addShownCards(cards=None, player=m.group('PNAME'), holeandboard=cards)

View File

@ -28,7 +28,7 @@ class FullTilt(HandHistoryConverter):
re_GameInfo = re.compile('- \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (Ante \$(?P<ANTE>[.0-9]+) )?- (?P<LTYPE>(No|Pot)? )?Limit (?P<GAME>(Hold\'em|Omaha|Razz))') re_GameInfo = re.compile('- \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (Ante \$(?P<ANTE>[.0-9]+) )?- (?P<LTYPE>(No|Pot)? )?Limit (?P<GAME>(Hold\'em|Omaha|Razz))')
re_SplitHands = re.compile(r"\n\n+") re_SplitHands = re.compile(r"\n\n+")
re_HandInfo = re.compile('.*#(?P<HID>[0-9]+): Table (?P<TABLE>[- a-zA-Z]+) (\((?P<TABLEATTRIBUTES>.+)\) )?- \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (Ante \$(?P<ANTE>[.0-9]+) )?- (?P<GAMETYPE>[a-zA-Z\' ]+) - (?P<DATETIME>.*)') re_HandInfo = re.compile('.*#(?P<HID>[0-9]+): Table (?P<TABLE>[- a-zA-Z]+) (\((?P<TABLEATTRIBUTES>.+)\) )?- \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (Ante \$(?P<ANTE>[.0-9]+) )?- (?P<GAMETYPE>[a-zA-Z\' ]+) - (?P<DATETIME>.*)')
re_Button = re.compile('^The button is in seat #(?P<BUTTON>\d+)') re_Button = re.compile('^The button is in seat #(?P<BUTTON>\d+)', re.MULTILINE)
re_PlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$(?P<CASH>[.0-9]+)\)\n') re_PlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$(?P<CASH>[.0-9]+)\)\n')
re_Board = re.compile(r"\[(?P<CARDS>.+)\]") re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
@ -43,9 +43,10 @@ class FullTilt(HandHistoryConverter):
print "DEBUG player_re: " + player_re print "DEBUG player_re: " + player_re
self.re_PostSB = re.compile(r"^%s posts the small blind of \$?(?P<SB>[.0-9]+)" % player_re, re.MULTILINE) self.re_PostSB = re.compile(r"^%s posts the small blind of \$?(?P<SB>[.0-9]+)" % player_re, re.MULTILINE)
self.re_PostBB = re.compile(r"^%s posts (the big blind of )?\$?(?P<BB>[.0-9]+)" % player_re, re.MULTILINE) self.re_PostBB = re.compile(r"^%s posts (the big blind of )?\$?(?P<BB>[.0-9]+)" % player_re, re.MULTILINE)
self.re_Antes = re.compile(r"^%s antes \$?(?P<ANTE>[.0-9]+)" % player_re, re.MULTILINE)
self.re_BringIn = re.compile(r"^%s brings in for \$?(?P<BRINGIN>[.0-9]+)" % player_re, re.MULTILINE) self.re_BringIn = re.compile(r"^%s brings in for \$?(?P<BRINGIN>[.0-9]+)" % player_re, re.MULTILINE)
self.re_PostBoth = re.compile(r"^%s posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)" % player_re, re.MULTILINE) self.re_PostBoth = re.compile(r"^%s posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)" % player_re, re.MULTILINE)
self.re_HeroCards = re.compile(r"^Dealt to %s \[(?P<CARDS>.*)\]( \[(?P<NEWCARD>.*)\])?" % player_re, re.MULTILINE) self.re_HeroCards = re.compile(r"^Dealt to %s \[(?P<CARDS>[AKQJT0-9hcsd ]+)\]( \[(?P<NEWCARD>[AKQJT0-9hcsd ]+)\])?" % player_re, re.MULTILINE)
self.re_Action = re.compile(r"^%s(?P<ATYPE> bets| checks| raises to| calls| folds)(\s\$(?P<BET>[.\d]+))?" % player_re, re.MULTILINE) self.re_Action = re.compile(r"^%s(?P<ATYPE> bets| checks| raises to| calls| folds)(\s\$(?P<BET>[.\d]+))?" % player_re, re.MULTILINE)
self.re_ShowdownAction = re.compile(r"^%s shows \[(?P<CARDS>.*)\]" % player_re, re.MULTILINE) self.re_ShowdownAction = re.compile(r"^%s shows \[(?P<CARDS>.*)\]" % player_re, re.MULTILINE)
self.re_CollectPot = re.compile(r"^Seat (?P<SEAT>[0-9]+): %s (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(\$(?P<POT>[.\d]+)\)(, mucked| with.*)" % player_re, re.MULTILINE) self.re_CollectPot = re.compile(r"^Seat (?P<SEAT>[0-9]+): %s (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(\$(?P<POT>[.\d]+)\)(, mucked| with.*)" % player_re, re.MULTILINE)
@ -155,13 +156,17 @@ class FullTilt(HandHistoryConverter):
def readAntes(self, hand): def readAntes(self, hand):
print "DEBUG: reading antes" print "DEBUG: reading antes"
print "DEBUG: FIXME reading antes" m = self.re_Antes.finditer(hand.string)
for player in m:
print "DEBUG: hand.addAnte(%s,%s)" %(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" print "DEBUG: reading bring in"
# print hand.string # print hand.string
m = self.re_BringIn.search(hand.string,re.DOTALL) m = self.re_BringIn.search(hand.string,re.DOTALL)
print "DEBUG: Player bringing in: %s for %s" %(m.group('PNAME'), m.group('BRINGIN')) print "DEBUG: Player bringing in: %s for %s" %(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.string).group('BUTTON'))
@ -183,16 +188,15 @@ class FullTilt(HandHistoryConverter):
#Used for stud hands - borrows the HeroCards regex for now. #Used for stud hands - borrows the HeroCards regex for now.
m = self.re_HeroCards.finditer(hand.streets.group(street)) m = self.re_HeroCards.finditer(hand.streets.group(street))
print "DEBUG: razz/stud readPlayerCards" print "DEBUG: razz/stud readPlayerCards"
print "DEBUG: STREET: %s", street print hand.streets.group(street)
for player in m: for player in m:
print player.groups() print player.groups()
#hand.hero = m.group('PNAME')
# "2c, qh" -> set(["2c","qc"])
# Also works with Omaha hands.
cards = player.group('CARDS') cards = player.group('CARDS')
print "DEBUG: PNAME: %s CARDS: %s" %(player.group('PNAME'), player.group('CARDS')) if player.group('NEWCARD') != None:
print cards
cards = cards + " " + player.group('NEWCARD')
cards = set(cards.split(' ')) cards = set(cards.split(' '))
# hand.addHoleCards(cards, m.group('PNAME')) hand.addPlayerCards(cards, player.group('PNAME'))
def readAction(self, hand, street): def readAction(self, hand, street):
m = self.re_Action.finditer(hand.streets.group(street)) m = self.re_Action.finditer(hand.streets.group(street))

View File

@ -35,6 +35,20 @@ import Configuration
class GuiBulkImport(): class GuiBulkImport():
def import_dir(self):
"""imports a directory, non-recursive. todo: move this to fpdb_import so CLI can use it"""
self.path = self.inputFile
self.importer.addImportDirectory(self.path)
self.importer.setCallHud(False)
starttime = time()
if not self.importer.settings['threads'] > 1:
(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'\
% (stored, dups, partial, errs, ttime, stored / ttime)
else:
self.importer.RunImportThreaded()
def load_clicked(self, widget, data=None): def load_clicked(self, widget, data=None):
# get the dir to import from the chooser # get the dir to import from the chooser
self.inputFile = self.chooser.get_filename() self.inputFile = self.chooser.get_filename()
@ -66,6 +80,7 @@ class GuiBulkImport():
self.lab_info.set_text("Import finished") self.lab_info.set_text("Import finished")
def get_vbox(self): def get_vbox(self):
"""returns the vbox of this thread"""
return self.vbox return self.vbox
def __init__(self, db, settings, config): def __init__(self, db, settings, config):

View File

@ -29,6 +29,11 @@ Main for FreePokerTools HUD.
# Standard Library modules # Standard Library modules
import sys import sys
# redirect the stderr
errorfile = open('HUD-error.txt', 'w', 0)
sys.stderr = errorfile
import os import os
import thread import thread
import time import time
@ -72,7 +77,7 @@ class HUD_main(object):
def destroy(*args): # call back for terminating the main eventloop def destroy(*args): # call back for terminating the main eventloop
gtk.main_quit() gtk.main_quit()
def create_HUD(self, new_hand_id, table, table_name, max, poker_game, is_tournament, stat_dict): def create_HUD(self, new_hand_id, table, table_name, max, poker_game, is_tournament, stat_dict, cards):
def idle_func(): def idle_func():
@ -82,20 +87,21 @@ class HUD_main(object):
self.vb.add(newlabel) self.vb.add(newlabel)
newlabel.show() newlabel.show()
self.hud_dict[table_name] = Hud.Hud(self, table, max, poker_game, self.config, self.db_connection)
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) self.hud_dict[table_name].create(new_hand_id, self.config, stat_dict, cards)
for m in self.hud_dict[table_name].aux_windows: for m in self.hud_dict[table_name].aux_windows:
m.update_data(new_hand_id, self.db_connection) m.update_data(new_hand_id, self.db_connection)
m.update_gui(new_hand_id) m.update_gui(new_hand_id)
self.hud_dict[table_name].update(new_hand_id, self.config, stat_dict) self.hud_dict[table_name].update(new_hand_id, self.config)
self.hud_dict[table_name].reposition_windows() self.hud_dict[table_name].reposition_windows()
return False return False
finally: finally:
gtk.gdk.threads_leave() gtk.gdk.threads_leave()
self.hud_dict[table_name] = Hud.Hud(self, table, max, poker_game, self.config, self.db_connection)
gobject.idle_add(idle_func) gobject.idle_add(idle_func)
def update_HUD(self, new_hand_id, table_name, config, stat_dict): def update_HUD(self, new_hand_id, table_name, config):
"""Update a HUD gui from inside the non-gui read_stdin thread.""" """Update a HUD gui from inside the non-gui read_stdin thread."""
# This is written so that only 1 thread can touch the gui--mainly # This is written so that only 1 thread can touch the gui--mainly
# for compatibility with Windows. This method dispatches the # for compatibility with Windows. This method dispatches the
@ -103,7 +109,7 @@ class HUD_main(object):
def idle_func(): def idle_func():
gtk.gdk.threads_enter() gtk.gdk.threads_enter()
try: try:
self.hud_dict[table_name].update(new_hand_id, config, stat_dict) self.hud_dict[table_name].update(new_hand_id, config)
for m in self.hud_dict[table_name].aux_windows: for m in self.hud_dict[table_name].aux_windows:
m.update_gui(new_hand_id) m.update_gui(new_hand_id)
return False return False
@ -145,6 +151,7 @@ class HUD_main(object):
try: try:
(table_name, max, poker_game) = self.db_connection.get_table_name(new_hand_id) (table_name, max, poker_game) = self.db_connection.get_table_name(new_hand_id)
stat_dict = self.db_connection.get_stats_from_hand(new_hand_id) stat_dict = self.db_connection.get_stats_from_hand(new_hand_id)
cards = self.db_connection.get_cards(new_hand_id)
except: except:
print "skipping ", new_hand_id print "skipping ", new_hand_id
sys.stderr.write("Database error in hand %d. Skipping.\n" % int(new_hand_id)) sys.stderr.write("Database error in hand %d. Skipping.\n" % int(new_hand_id))
@ -163,9 +170,11 @@ class HUD_main(object):
# Update an existing HUD # Update an existing HUD
if temp_key in self.hud_dict: if temp_key in self.hud_dict:
self.hud_dict[temp_key].stat_dict = stat_dict
self.hud_dict[temp_key].cards = cards
for aw in self.hud_dict[temp_key].aux_windows: for aw in self.hud_dict[temp_key].aux_windows:
aw.update_data(new_hand_id, self.db_connection) aw.update_data(new_hand_id, self.db_connection)
self.update_HUD(new_hand_id, temp_key, self.config, stat_dict) self.update_HUD(new_hand_id, temp_key, self.config)
# Or create a new HUD # Or create a new HUD
else: else:
@ -175,11 +184,12 @@ class HUD_main(object):
tablewindow = Tables.discover_table_by_name(self.config, table_name) tablewindow = Tables.discover_table_by_name(self.config, table_name)
if tablewindow == None: if tablewindow == None:
# If no client window is found on the screen, complain and continue
if is_tournament: if is_tournament:
table_name = tour_number + " " + tab_number table_name = tour_number + " " + tab_number
sys.stderr.write("table name "+table_name+" not found, skipping.\n") sys.stderr.write("table name "+table_name+" not found, skipping.\n")
else: else:
self.create_HUD(new_hand_id, tablewindow, temp_key, max, poker_game, is_tournament, stat_dict) self.create_HUD(new_hand_id, tablewindow, temp_key, max, poker_game, is_tournament, stat_dict, cards)
if __name__== "__main__": if __name__== "__main__":
sys.stderr.write("HUD_main starting\n") sys.stderr.write("HUD_main starting\n")

View File

@ -15,38 +15,25 @@
#In the "official" distribution you can find the license in #In the "official" distribution you can find the license in
#agpl-3.0.txt in the docs folder of the package. #agpl-3.0.txt in the docs folder of the package.
import Hand
import re import re
import sys import sys
import traceback import traceback
import logging import logging
import os import os
import os.path import os.path
import xml.dom.minidom
import codecs
from decimal import Decimal from decimal import Decimal
import operator import operator
import time import time
from copy import deepcopy from copy import deepcopy
from Exceptions import *
class Hand: class Hand:
# 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, handtext): def __init__(self, sitename, gametype, handText):
self.sitename = sitename self.sitename = sitename
self.gametype = gametype self.gametype = gametype
self.string = handtext self.handText = handText
if gametype[1] == "hold" or self.gametype[1] == "omaha":
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":
self.streetList = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] # a list of the observed street names in order
self.handid = 0 self.handid = 0
self.sb = gametype[3]
self.bb = gametype[4]
self.tablename = "Slartibartfast" self.tablename = "Slartibartfast"
self.hero = "Hiro" self.hero = "Hiro"
self.maxseats = 10 self.maxseats = 10
@ -56,38 +43,26 @@ class Hand:
self.players = [] self.players = []
self.posted = [] self.posted = []
self.involved = True self.involved = True
self.pot = Pot() self.pot = Pot()
#
# Collections indexed by street names # Collections indexed by street names
# self.bets = {}
self.lastBet = {}
self.streets = {}
self.actions = {} # [['mct','bets','$10'],['mika','folds'],['carlg','raises','$20']]
for street in self.streetList:
self.streets[street] = "" # portions of the handText, filled by markStreets()
self.bets[street] = {}
self.lastBet[street] = 0
self.actions[street] = []
# A MatchObject using a groupnames to identify streets. self.board = {} # dict from street names to community cards
# filled by markStreets()
self.streets = None
# dict from street names to lists of tuples, such as
# [['mct','bets','$10'],['mika','folds'],['carlg','raises','$20']]
# actually they're clearly lists but they probably should be tuples.
self.actions = {}
# dict from street names to community cards
self.board = {}
#
# Collections indexed by player names # Collections indexed by player names
# self.holecards = {} # dict from player names to lists of hole cards
# dict from player names to lists of hole cards
self.holecards = {}
self.stacks = {} self.stacks = {}
self.collected = [] #list of ?
# dict from player names to amounts collected self.collectees = {} # dict from player names to amounts collected (?)
self.collected = []
self.collectees = {}
# Sets of players # Sets of players
self.shown = set() self.shown = set()
@ -99,11 +74,7 @@ class Hand:
self.rake = None self.rake = None
self.bets = {}
self.lastBet = {}
for street in self.streetList:
self.bets[street] = {}
self.lastBet[street] = 0
def addPlayer(self, seat, name, chips): def addPlayer(self, seat, name, chips):
"""\ """\
@ -115,7 +86,7 @@ If a player has None chips he won't be added."""
if chips is not None: if chips is not None:
self.players.append([seat, name, chips]) self.players.append([seat, name, chips])
self.stacks[name] = Decimal(chips) self.stacks[name] = Decimal(chips)
self.holecards[name] = set() self.holecards[name] = []
self.pot.addPlayer(name) self.pot.addPlayer(name)
for street in self.streetList: for street in self.streetList:
self.bets[street][name] = [] self.bets[street][name] = []
@ -124,21 +95,34 @@ 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 is not None:
self.streets = match self.streets.update(match.groupdict())
for street in match.groupdict(): logging.debug(self.streets)
if match.group(street) is not None:
self.actions[street] = []
else: else:
logging.error("markstreets didn't match") logging.error("markstreets didn't match")
def addHoleCards(self, cards, player): def addHoleCards(self, cards, player):
"""\ """\
Assigns observed holecards to a player. Assigns observed holecards to a player.
cards set of card bigrams e.g. set(['2h','Jc']) cards list of card bigrams e.g. ['2h','Jc']
player (string) name of player player (string) name of player
""" """
#print "DEBUG: addHoleCards", cards,player #print "DEBUG: addHoleCards", cards,player
try:
self.checkPlayerExists(player)
cards = set([self.card(c) for c in cards])
self.holecards[player].extend(cards)
except FpdbParseError, e:
print "[ERROR] Tried to add holecards for unknown player: %s" % (player,)
def addPlayerCards(self, cards, player):
"""\
Assigns observed cards to a player.
cards list of card bigrams e.g. ['2h','Jc']
player (string) name of player
Should probably be merged with addHoleCards
"""
logging.debug("addPlayerCards %s, %s" % ( cards,player))
try: try:
self.checkPlayerExists(player) self.checkPlayerExists(player)
cards = set([self.card(c) for c in cards]) cards = set([self.card(c) for c in cards])
@ -185,25 +169,31 @@ Card ranks will be uppercased
c = c.replace(k,v) c = c.replace(k,v)
return c return c
def addAnte(self, player, ante):
if player is not None:
self.bets['ANTES'][player].append(Decimal(ante))
self.stacks[player] -= Decimal(ante)
act = (player, 'posts', "ante", ante, self.stacks[player]==0)
self.actions['ANTES'].append(act)
self.pot.addMoney(player, Decimal(ante))
def addBlind(self, player, blindtype, amount): def addBlind(self, player, blindtype, amount):
# if player is None, it's a missing small blind. # if player is None, it's a missing small blind.
# TODO:
# The situation we need to cover are: # The situation we need to cover are:
# 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 sb and a raise to 1 bb
# #
# If a player posts a big & small blind
# - 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)
#print "DEBUG %s posts, stack %s" % (player, self.stacks[player]) #print "DEBUG %s posts, stack %s" % (player, self.stacks[player])
act = (player, 'posts', blindtype, amount, self.stacks[player]==0) act = (player, 'posts', blindtype, amount, self.stacks[player]==0)
self.actions['PREFLOP'].append(act) self.actions['BLINDSANTES'].append(act)
self.pot.addMoney(player, Decimal(amount)) self.pot.addMoney(player, Decimal(amount))
if blindtype == 'big blind': if blindtype == 'big blind':
self.lastBet['PREFLOP'] = Decimal(amount) self.lastBet['PREFLOP'] = Decimal(amount)
@ -214,6 +204,8 @@ Card ranks will be uppercased
#print "DEBUG: self.posted: %s" %(self.posted) #print "DEBUG: self.posted: %s" %(self.posted)
def addCall(self, street, player=None, amount=None): def addCall(self, street, player=None, amount=None):
# Potentially calculate the amount of the call if not supplied # Potentially calculate the amount of the call if not supplied
# corner cases include if player would be all in # corner cases include if player would be all in
@ -365,22 +357,69 @@ Map the tuple self.gametype onto the pokerstars string describing it
"cp" : "Cap Pot Limit" "cp" : "Cap Pot Limit"
} }
logging.debug("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 string return retstring
def writeHand(self, fh=sys.__stdout__): def writeHand(self, fh=sys.__stdout__):
if self.gametype[1] == "hold" or self.gametype[1] == "omaha": print >>fh, "Override me"
self.writeHoldemHand(fh)
else:
self.writeStudHand(fh)
def printHand(self):
self.writeHand(sys.stdout)
def writeHoldemHand(self, fh=sys.__stdout__): def printActionLine(self, act, fh):
if act[1] == 'folds':
print >>fh, _("%s: folds " %(act[0]))
elif act[1] == 'checks':
print >>fh, _("%s: checks " %(act[0]))
elif act[1] == 'calls':
print >>fh, _("%s: calls $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else ''))
elif act[1] == 'bets':
print >>fh, _("%s: bets $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else ''))
elif act[1] == 'raises':
print >>fh, _("%s: raises $%s to $%s%s" %(act[0], act[2], act[3], ' and is all-in' if act[5] else ''))
elif act[1] == 'posts':
if(act[2] == "small blind"):
print >>fh, _("%s: posts small blind $%s" %(act[0], act[3]))
elif(act[2] == "big blind"):
print >>fh, _("%s: posts big blind $%s" %(act[0], act[3]))
elif(act[2] == "both"):
print >>fh, _("%s: posts small & big blinds $%s" %(act[0], act[3]))
class HoldemOmahaHand(Hand):
def __init__(self, hhc, sitename, gametype, handText):
if gametype[1] not in ["hold","omaha"]:
pass # or indeed don't pass and complain instead
self.streetList = ['BLINDSANTES', 'PREFLOP','FLOP','TURN','RIVER'] # a list of the observed street names in order
self.communityStreets = ['FLOP', 'TURN', 'RIVER']
self.actionStreets = ['PREFLOP','FLOP','TURN','RIVER']
Hand.__init__(self, sitename, gametype, handText)
self.sb = gametype[3]
self.bb = gametype[4]
hhc.readHandInfo(self)
hhc.readPlayerStacks(self)
hhc.compilePlayerRegexs(players = set([player[1] for player in self.players]))
hhc.markStreets(self)
hhc.readBlinds(self)
hhc.readButton(self)
hhc.readHeroCards(self)
hhc.readShowdownActions(self)
# Read actions in street order
for street in self.communityStreets:
if self.streets[street]:
hhc.readCommunityCards(self, street)
for street in self.actionStreets:
if self.streets[street]:
hhc.readAction(self, street)
hhc.readCollectPot(self)
hhc.readShownCards(self)
self.totalPot() # finalise it (total the pot)
hhc.getRake(self)
def writeHand(self, fh=sys.__stdout__):
# PokerStars format. # PokerStars format.
#print "\n### Pseudo stars format ###"
#print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %(self.sitename, self.handid, self.getGameTypeAsString(), self.sb, self.bb, self.starttime))
print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d - %H:%M:%S (ET)', self.starttime))) print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d - %H:%M:%S (ET)', self.starttime)))
print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos))
@ -390,35 +429,29 @@ Map the tuple self.gametype onto the pokerstars string describing it
#Only print stacks of players who do something preflop #Only print stacks of players who do something preflop
print >>fh, _("Seat %s: %s ($%s)" %(player[0], player[1], player[2])) print >>fh, _("Seat %s: %s ($%s)" %(player[0], player[1], player[2]))
if self.actions['BLINDSANTES']:
#May be more than 1 bb posting for act in self.actions['BLINDSANTES']:
for a in self.posted: self.printActionLine(act, fh)
if(a[1] == "small blind"):
print >>fh, _("%s: posts small blind $%s" %(a[0], self.sb))
if(a[1] == "big blind"):
print >>fh, _("%s: posts big blind $%s" %(a[0], self.bb))
if(a[1] == "both"):
print >>fh, _("%s: posts small & big blinds $%.2f" %(a[0], (Decimal(self.sb) + Decimal(self.bb))))
print >>fh, _("*** HOLE CARDS ***") print >>fh, _("*** HOLE CARDS ***")
if self.involved: if self.involved:
print >>fh, _("Dealt to %s [%s]" %(self.hero , " ".join(self.holecards[self.hero]))) print >>fh, _("Dealt to %s [%s]" %(self.hero , " ".join(self.holecards[self.hero])))
if 'PREFLOP' in self.actions: if self.actions['PREFLOP']:
for act in self.actions['PREFLOP']: for act in self.actions['PREFLOP']:
self.printActionLine(act, fh) self.printActionLine(act, fh)
if 'FLOP' in self.actions: if self.actions['FLOP']:
print >>fh, _("*** FLOP *** [%s]" %( " ".join(self.board['FLOP']))) print >>fh, _("*** FLOP *** [%s]" %( " ".join(self.board['FLOP'])))
for act in self.actions['FLOP']: for act in self.actions['FLOP']:
self.printActionLine(act, fh) self.printActionLine(act, fh)
if 'TURN' in self.actions: if self.actions['TURN']:
print >>fh, _("*** TURN *** [%s] [%s]" %( " ".join(self.board['FLOP']), " ".join(self.board['TURN']))) print >>fh, _("*** TURN *** [%s] [%s]" %( " ".join(self.board['FLOP']), " ".join(self.board['TURN'])))
for act in self.actions['TURN']: for act in self.actions['TURN']:
self.printActionLine(act, fh) self.printActionLine(act, fh)
if 'RIVER' in self.actions: if self.actions['RIVER']:
print >>fh, _("*** RIVER *** [%s] [%s]" %(" ".join(self.board['FLOP']+self.board['TURN']), " ".join(self.board['RIVER']) )) print >>fh, _("*** RIVER *** [%s] [%s]" %(" ".join(self.board['FLOP']+self.board['TURN']), " ".join(self.board['RIVER']) ))
for act in self.actions['RIVER']: for act in self.actions['RIVER']:
self.printActionLine(act, fh) self.printActionLine(act, fh)
@ -429,7 +462,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
@ -467,26 +500,45 @@ Map the tuple self.gametype onto the pokerstars string describing it
print >>fh, _("Seat %d: %s mucked" % (seatnum, name)) print >>fh, _("Seat %d: %s mucked" % (seatnum, name))
print >>fh, "\n\n" print >>fh, "\n\n"
# TODO:
# logic for side pots
# logic for which players get to showdown
# I'm just not sure we need to do this so heavily.. and if we do, it's probably better to use pokerlib
#if self.holecards[player[1]]: # empty list default is false
#hole = self.holecards[player[1]]
##board = []
##for s in self.board.values():
##board += s
##playerhand = self.bestHand('hi', board+hole)
##print "Seat %d: %s showed %s and won/lost with %s" % (player[0], player[1], hole, playerhand)
#print "Seat %d: %s showed %s" % (player[0], player[1], hole)
#else:
#print "Seat %d: %s mucked or folded" % (player[0], player[1])
class StudHand(Hand):
def __init__(self, hhc, sitename, gametype, handText):
if gametype[1] not in ["razz","stud","stud8"]:
pass # or indeed don't pass and complain instead
self.streetList = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] # a list of the observed street names in order
Hand.__init__(self, sitename, gametype, handText)
hhc.readHandInfo(self)
hhc.readPlayerStacks(self)
hhc.compilePlayerRegexs(players = set([player[1] for player in self.players]))
hhc.markStreets(self)
hhc.readAntes(self)
hhc.readBringIn(self)
hhc.readShowdownActions(self)
# Read actions in street order
for street in self.streetList:
if self.streets[street]:
logging.debug(street)
logging.debug(hand.streets[street])
hhc.readPlayerCards(self, street)
hhc.readAction(self, street)
hhc.readCollectPot(self)
hhc.readShownCards(self)
self.totalPot() # finalise it (total the pot)
hhc.getRake(self)
def addBringIn(self, player, ante):
if player is not None:
self.bets['THIRD'][player].append(Decimal(ante))
self.stacks[player] -= Decimal(ante)
act = (player, 'bringin', "bringin", ante, self.stacks[player]==0)
self.actions['THIRD'].append(act)
self.pot.addMoney(player, Decimal(ante))
def writeStudHand(self, fh=sys.__stdout__): def writeStudHand(self, fh=sys.__stdout__):
# PokerStars format. # PokerStars format.
#print "\n### Pseudo stars format ###"
#print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %(self.sitename, self.handid, self.getGameTypeAsString(), self.sb, self.bb, self.starttime))
print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d - %H:%M:%S (ET)', self.starttime))) print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d - %H:%M:%S (ET)', self.starttime)))
print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos))
@ -496,10 +548,16 @@ Map the tuple self.gametype onto the pokerstars string describing it
#Only print stacks of players who do something preflop #Only print stacks of players who do something preflop
print >>fh, _("Seat %s: %s ($%s)" %(player[0], player[1], player[2])) print >>fh, _("Seat %s: %s ($%s)" %(player[0], player[1], player[2]))
if 'ANTES' in self.actions:
for act in self.actions['ANTES']:
print >>fh, _("%s: posts the ante $%s" %(act[0], act[3]))
if 'THIRD' in self.actions: if 'THIRD' in self.actions:
print >>fh, _("*** 3RD STREET ***") print >>fh, _("*** 3RD STREET ***")
for player in [x for x in self.players if x[1] in players_who_post_antes]:
print >>fh, _("Dealt to ")
for act in self.actions['THIRD']: for act in self.actions['THIRD']:
#FIXME: Need some logic here for bringin vs completes
self.printActionLine(act, fh) self.printActionLine(act, fh)
if 'FOURTH' in self.actions: if 'FOURTH' in self.actions:
@ -527,7 +585,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
@ -566,77 +624,10 @@ Map the tuple self.gametype onto the pokerstars string describing it
print >>fh, _("Seat %d: %s mucked" % (seatnum, name)) print >>fh, _("Seat %d: %s mucked" % (seatnum, name))
print >>fh, "\n\n" print >>fh, "\n\n"
# TODO:
# logic for side pots
# logic for which players get to showdown
# I'm just not sure we need to do this so heavily.. and if we do, it's probably better to use pokerlib
#if self.holecards[player[1]]: # empty list default is false
#hole = self.holecards[player[1]]
##board = []
##for s in self.board.values():
##board += s
##playerhand = self.bestHand('hi', board+hole)
##print "Seat %d: %s showed %s and won/lost with %s" % (player[0], player[1], hole, playerhand)
#print "Seat %d: %s showed %s" % (player[0], player[1], hole)
#else:
#print "Seat %d: %s mucked or folded" % (player[0], player[1])
def printHand(self):
self.writeHand(sys.stdout)
def printActionLine(self, act, fh):
if act[1] == 'folds':
print >>fh, _("%s: folds " %(act[0]))
elif act[1] == 'checks':
print >>fh, _("%s: checks " %(act[0]))
if act[1] == 'calls':
print >>fh, _("%s: calls $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else ''))
if act[1] == 'bets':
print >>fh, _("%s: bets $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else ''))
if act[1] == 'raises':
print >>fh, _("%s: raises $%s to $%s%s" %(act[0], act[2], act[3], ' and is all-in' if act[5] else ''))
# going to use pokereval to figure out hands at some point.
# these functions are copied from pokergame.py
def bestHand(self, side, cards):
return HandHistoryConverter.eval.best('hi', cards, [])
# from pokergame.py
# got rid of the _ for internationalisation
def readableHandValueLong(self, side, value, cards):
if value == "NoPair":
if side == "low":
if cards[0][0] == '5':
return ("The wheel")
else:
return join(map(lambda card: card[0], cards), ", ")
else:
return ("High card %(card)s") % { 'card' : (letter2name[cards[0][0]]) }
elif value == "OnePair":
return ("A pair of %(card)s") % { 'card' : (letter2names[cards[0][0]]) } + (", %(card)s kicker") % { 'card' : (letter2name[cards[2][0]]) }
elif value == "TwoPair":
return ("Two pairs %(card1)s and %(card2)s") % { 'card1' : (letter2names[cards[0][0]]), 'card2' : _(letter2names[cards[2][0]]) } + (", %(card)s kicker") % { 'card' : (letter2name[cards[4][0]]) }
elif value == "Trips":
return ("Three of a kind %(card)s") % { 'card' : (letter2names[cards[0][0]]) } + (", %(card)s kicker") % { 'card' : (letter2name[cards[3][0]]) }
elif value == "Straight":
return ("Straight %(card1)s to %(card2)s") % { 'card1' : (letter2name[cards[0][0]]), 'card2' : (letter2name[cards[4][0]]) }
elif value == "Flush":
return ("Flush %(card)s high") % { 'card' : (letter2name[cards[0][0]]) }
elif value == "FlHouse":
return ("%(card1)ss full of %(card2)ss") % { 'card1' : (letter2name[cards[0][0]]), 'card2' : (letter2name[cards[3][0]]) }
elif value == "Quads":
return _("Four of a kind %(card)s") % { 'card' : (letter2names[cards[0][0]]) } + (", %(card)s kicker") % { 'card' : (letter2name[cards[4][0]]) }
elif value == "StFlush":
if letter2name[cards[0][0]] == 'Ace':
return ("Royal flush")
else:
return ("Straight flush %(card)s high") % { 'card' : (letter2name[cards[0][0]]) }
return value
class FpdbParseError(Exception): pass
class Pot(object): class Pot(object):
@ -711,4 +702,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

@ -72,13 +72,10 @@ letter2names = {
import gettext import gettext
gettext.install('myapplication') gettext.install('myapplication')
class HandHistoryConverter(threading.Thread): class HandHistoryConverter(threading.Thread):
# eval = PokerEval()
def __init__(self, in_path = '-', out_path = '-', sitename = None, follow=False): def __init__(self, in_path = '-', out_path = '-', sitename = None, follow=False):
super(HandHistoryConverter, self).__init__() threading.Thread.__init__(self)
logging.info("HandHistory init called") logging.info("HandHistory init called")
# default filetype and codepage. Subclasses should set these properly. # default filetype and codepage. Subclasses should set these properly.
@ -94,7 +91,7 @@ class HandHistoryConverter(threading.Thread):
self.out_fh = open(self.out_path, 'a') self.out_fh = open(self.out_path, 'a')
self.sitename = sitename self.sitename = sitename
self.follow = follow self.follow = follow
self.players = set() self.compiledPlayers = set()
self.maxseats = 10 self.maxseats = 10
def __str__(self): def __str__(self):
@ -145,45 +142,11 @@ class HandHistoryConverter(threading.Thread):
gametype = self.determineGameType(handtext) gametype = self.determineGameType(handtext)
if gametype is None: if gametype is None:
return return
hand = Hand.Hand(self.sitename, gametype, handtext)
self.readHandInfo(hand)
self.readPlayerStacks(hand)
playersThisHand = set([player[1] for player in hand.players])
if playersThisHand <= self.players: # x <= y means 'x is subset of y'
# we're ok; the regex should already cover them all.
pass
else:
# we need to recompile the player regexs.
self.players = playersThisHand
self.compilePlayerRegexs()
self.markStreets(hand) if gametype[1] in ("hold", "omaha"):
# Different calls if stud or holdem like hand = Hand.HoldemOmahaHand(self, self.sitename, gametype, handtext)
if gametype[1] == "hold" or gametype[1] == "omaha": elif gametype[1] in ("razz","stud","stud8"):
self.readBlinds(hand) hand = Hand.StudHand(self, self.sitename, gametype, handtext)
self.readButton(hand)
self.readHeroCards(hand) # want to generalise to draw games
elif gametype[1] == "razz" or gametype[1] == "stud" or gametype[1] == "stud8":
self.readAntes(hand)
self.readBringIn(hand)
self.readShowdownActions(hand)
# Read actions in street order
for street in hand.streetList: # go through them in order
#logging.debug(street)
if hand.streets.group(street) is not None:
if gametype[1] == "hold" or gametype[1] == "omaha":
self.readCommunityCards(hand, street) # read community cards
elif gametype[1] == "razz" or gametype[1] == "stud" or gametype[1] == "stud8":
self.readPlayerCards(hand, street)
self.readAction(hand, street)
self.readCollectPot(hand)
self.readShownCards(hand)
hand.totalPot() # finalise it (total the pot)
self.getRake(hand)
hand.writeHand(self.out_fh) hand.writeHand(self.out_fh)
@ -207,7 +170,7 @@ class HandHistoryConverter(threading.Thread):
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)
@ -264,7 +227,6 @@ class HandHistoryConverter(threading.Thread):
endtime = time.time() endtime = time.time()
print "Processed %d hands in %.3f seconds" % (len(self.hands), endtime - starttime) print "Processed %d hands in %.3f seconds" % (len(self.hands), endtime - starttime)
#####
# These functions are parse actions that may be overridden by the inheriting class # These functions are parse actions that may be overridden by the inheriting class
# This function should return a list of lists looking like: # This function should return a list of lists looking like:
# return [["ring", "hold", "nl"], ["tour", "hold", "nl"]] # return [["ring", "hold", "nl"], ["tour", "hold", "nl"]]
@ -279,13 +241,13 @@ class HandHistoryConverter(threading.Thread):
def determineGameType(self): abstract def determineGameType(self): abstract
# Read any of: # Read any of:
# HID HandID # HID HandID
# TABLE Table name # TABLE Table name
# SB small blind # SB small blind
# BB big blind # BB big blind
# GAMETYPE gametype # GAMETYPE gametype
# YEAR MON DAY HR MIN SEC datetime # YEAR MON DAY HR MIN SEC datetime
# BUTTON button seat number # BUTTON button seat number
def readHandInfo(self, hand): abstract def readHandInfo(self, hand): abstract
# Needs to return a list of lists in the format # Needs to return a list of lists in the format
@ -355,7 +317,7 @@ class HandHistoryConverter(threading.Thread):
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

@ -48,6 +48,8 @@ import HUD_main
class Hud: class Hud:
def __init__(self, parent, table, max, poker_game, config, db_connection): def __init__(self, parent, table, max, poker_game, config, db_connection):
# __init__ is (now) intended to be called from the stdin thread, so it
# cannot touch the gui
self.parent = parent self.parent = parent
self.table = table self.table = table
self.config = config self.config = config
@ -57,26 +59,28 @@ class Hud:
self.deleted = False self.deleted = False
self.stacked = True self.stacked = True
self.site = table.site self.site = table.site
self.colors = config.get_default_colors(self.table.site) self.mw_created = False
self.stat_windows = {} self.stat_windows = {}
self.popup_windows = {} self.popup_windows = {}
self.aux_windows = [] self.aux_windows = []
(font, font_size) = config.get_default_font(self.table.site) (font, font_size) = config.get_default_font(self.table.site)
self.colors = config.get_default_colors(self.table.site)
if font == None: if font == None:
font = "Sans" font = "Sans"
if font_size == None: if font_size == None:
font_size = "8" font_size = "8"
self.font = pango.FontDescription(font + " " + font_size) self.font = pango.FontDescription(font + " " + font_size)
# do we need to add some sort of condition here for dealing with a request for a font that doesn't exist? # do we need to add some sort of condition here for dealing with a request for a font that doesn't exist?
def create_mw(self):
# Set up a main window for this this instance of the HUD # Set up a main window for this this instance of the HUD
self.main_window = gtk.Window() self.main_window = gtk.Window()
self.main_window.set_gravity(gtk.gdk.GRAVITY_STATIC) self.main_window.set_gravity(gtk.gdk.GRAVITY_STATIC)
self.main_window.set_title(table.name + " FPDBHUD") self.main_window.set_title(self.table.name + " FPDBHUD")
self.main_window.destroyhandler = self.main_window.connect("destroy", self.kill_hud) self.main_window.destroyhandler = self.main_window.connect("destroy", self.kill_hud)
self.main_window.set_decorated(False) self.main_window.set_decorated(False)
self.main_window.set_opacity(self.colors["hudopacity"]) self.main_window.set_opacity(self.colors["hudopacity"])
@ -123,6 +127,7 @@ class Hud:
self.ebox.connect_object("button-press-event", self.on_button_press, self.menu) self.ebox.connect_object("button-press-event", self.on_button_press, self.menu)
self.main_window.show_all() self.main_window.show_all()
self.mw_created = True
# TODO: fold all uses of this type of 'topify' code into a single function, if the differences between the versions don't # TODO: fold all uses of this type of 'topify' code into a single function, if the differences between the versions don't
# create adverse effects? # create adverse effects?
@ -228,13 +233,17 @@ class Hud:
return self.stat_dict[key]['seat'] return self.stat_dict[key]['seat']
sys.stderr.write("Error finding actual seat.\n") sys.stderr.write("Error finding actual seat.\n")
def create(self, hand, config, stat_dict): def create(self, hand, config, stat_dict, cards):
# update this hud, to the stats and players as of "hand" # update this hud, to the stats and players as of "hand"
# hand is the hand id of the most recent hand played at this table # hand is the hand id of the most recent hand played at this table
# #
# this method also manages the creating and destruction of stat # this method also manages the creating and destruction of stat
# windows via calls to the Stat_Window class # windows via calls to the Stat_Window class
if not self.mw_created:
self.create_mw()
self.stat_dict = stat_dict self.stat_dict = stat_dict
self.cards = cards
sys.stderr.write("------------------------------------------------------------\nCreating hud from hand %s\n" % hand) sys.stderr.write("------------------------------------------------------------\nCreating hud from hand %s\n" % hand)
adj = self.adj_seats(hand, config) adj = self.adj_seats(hand, config)
sys.stderr.write("adj = %s\n" % adj) sys.stderr.write("adj = %s\n" % adj)
@ -274,37 +283,35 @@ class Hud:
if os.name == "nt": if os.name == "nt":
gobject.timeout_add(500, self.update_table_position) gobject.timeout_add(500, self.update_table_position)
def update(self, hand, config, stat_dict): def update(self, hand, config):
self.hand = hand # this is the last hand, so it is available later self.hand = hand # this is the last hand, so it is available later
self.stat_dict = stat_dict # so this is available for popups, etc
self.update_table_position() self.update_table_position()
self.stat_dict = stat_dict
for s in stat_dict: for s in self.stat_dict:
try: try:
self.stat_windows[stat_dict[s]['seat']].player_id = stat_dict[s]['player_id'] self.stat_windows[self.stat_dict[s]['seat']].player_id = self.stat_dict[s]['player_id']
except: # omg, we have more seats than stat windows .. damn poker sites with incorrect max seating info .. let's force 10 here except: # omg, we have more seats than stat windows .. damn poker sites with incorrect max seating info .. let's force 10 here
self.max = 10 self.max = 10
self.create(hand, config) self.create(hand, config, self.stat_dict, self.cards)
self.stat_windows[stat_dict[s]['seat']].player_id = stat_dict[s]['player_id'] self.stat_windows[self.stat_dict[s]['seat']].player_id = self.stat_dict[s]['player_id']
for r in range(0, config.supported_games[self.poker_game].rows): for r in range(0, config.supported_games[self.poker_game].rows):
for c in range(0, config.supported_games[self.poker_game].cols): for c in range(0, config.supported_games[self.poker_game].cols):
this_stat = config.supported_games[self.poker_game].stats[self.stats[r][c]] this_stat = config.supported_games[self.poker_game].stats[self.stats[r][c]]
number = Stats.do_stat(stat_dict, player = stat_dict[s]['player_id'], stat = self.stats[r][c]) number = Stats.do_stat(self.stat_dict, player = self.stat_dict[s]['player_id'], stat = self.stats[r][c])
statstring = this_stat.hudprefix + str(number[1]) + this_stat.hudsuffix statstring = this_stat.hudprefix + str(number[1]) + this_stat.hudsuffix
if this_stat.hudcolor != "": if this_stat.hudcolor != "":
self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor']))
self.stat_windows[stat_dict[s]['seat']].label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.hudcolor)) self.stat_windows[stat_dict[s]['seat']].label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.hudcolor))
self.stat_windows[stat_dict[s]['seat']].label[r][c].set_text(statstring) self.stat_windows[self.stat_dict[s]['seat']].label[r][c].set_text(statstring)
if statstring != "xxx": # is there a way to tell if this particular stat window is visible already, or no? if statstring != "xxx": # is there a way to tell if this particular stat window is visible already, or no?
self.stat_windows[stat_dict[s]['seat']].window.show_all() self.stat_windows[self.stat_dict[s]['seat']].window.show_all()
# self.reposition_windows() # self.reposition_windows()
tip = stat_dict[s]['screen_name'] + "\n" + number[5] + "\n" + \ tip = self.stat_dict[s]['screen_name'] + "\n" + number[5] + "\n" + \
number[3] + ", " + number[4] number[3] + ", " + number[4]
Stats.do_tip(self.stat_windows[stat_dict[s]['seat']].e_box[r][c], tip) Stats.do_tip(self.stat_windows[self.stat_dict[s]['seat']].e_box[r][c], tip)
def topify_window(self, window): def topify_window(self, window):
"""Set the specified gtk window to stayontop in MS Windows.""" """Set the specified gtk window to stayontop in MS Windows."""
@ -365,6 +372,7 @@ class Stat_Window:
self.y = y + table.y # x and y are the location relative to table.x & y self.y = y + table.y # x and y are the location relative to table.x & y
self.player_id = player_id # looks like this isn't used ;) self.player_id = player_id # looks like this isn't used ;)
self.sb_click = 0 # used to figure out button clicks self.sb_click = 0 # used to figure out button clicks
self.useframes = parent.config.get_frames(parent.site)
self.window = gtk.Window() self.window = gtk.Window()
self.window.set_decorated(0) self.window.set_decorated(0)
@ -382,23 +390,28 @@ class Stat_Window:
self.frame = [] self.frame = []
self.label = [] self.label = []
for r in range(self.game.rows): for r in range(self.game.rows):
self.frame.append([]) if self.useframes:
self.frame.append([])
self.e_box.append([]) self.e_box.append([])
self.label.append([]) self.label.append([])
for c in range(self.game.cols): for c in range(self.game.cols):
self.frame[r].append( gtk.Frame() ) if self.useframes:
self.frame[r].append( gtk.Frame() )
self.e_box[r].append( gtk.EventBox() ) self.e_box[r].append( gtk.EventBox() )
self.e_box[r][c].modify_bg(gtk.STATE_NORMAL, parent.backgroundcolor) self.e_box[r][c].modify_bg(gtk.STATE_NORMAL, parent.backgroundcolor)
self.e_box[r][c].modify_fg(gtk.STATE_NORMAL, parent.foregroundcolor) self.e_box[r][c].modify_fg(gtk.STATE_NORMAL, parent.foregroundcolor)
Stats.do_tip(self.e_box[r][c], 'stuff') Stats.do_tip(self.e_box[r][c], 'stuff')
# self.grid.attach(self.e_box[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0) if self.useframes:
self.grid.attach(self.frame[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0) self.grid.attach(self.frame[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0)
self.frame[r][c].add(self.e_box[r][c]) self.frame[r][c].add(self.e_box[r][c])
else:
self.grid.attach(self.e_box[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0)
self.label[r].append( gtk.Label('xxx') ) self.label[r].append( gtk.Label('xxx') )
self.frame[r][c].modify_bg(gtk.STATE_NORMAL, parent.backgroundcolor) if self.useframes:
self.frame[r][c].modify_bg(gtk.STATE_NORMAL, parent.backgroundcolor)
self.label[r][c].modify_bg(gtk.STATE_NORMAL, parent.backgroundcolor) self.label[r][c].modify_bg(gtk.STATE_NORMAL, parent.backgroundcolor)
self.label[r][c].modify_fg(gtk.STATE_NORMAL, parent.foregroundcolor) self.label[r][c].modify_fg(gtk.STATE_NORMAL, parent.foregroundcolor)

View File

@ -154,7 +154,7 @@ class Stud_list:
winners = winners + player winners = winners + player
pot_dec = "%.2f" % (float(pot)/100) pot_dec = "%.2f" % (float(pot)/100)
hero_cards = self.get_hero_cards(self.parent.hero, self.parent.mucked_cards.cards) hero_cards = self.get_hero_cards(self.parent.hero, self.parent.hud.cards)
self.info_row = ((new_hand_id, hero_cards, pot_dec, winners), ) self.info_row = ((new_hand_id, hero_cards, pot_dec, winners), )
def get_hero_cards(self, hero, cards): def get_hero_cards(self, hero, cards):
@ -163,11 +163,10 @@ class Stud_list:
if hero == '': if hero == '':
return "xxxxxx" return "xxxxxx"
else: else:
for k in cards.keys(): # find the hero's seat from the stat_dict
if cards[k]['screen_name'] == hero: for stat in self.parent.hud.stat_dict.itervalues():
return trans[cards[k]['card1Value']] + cards[k]['card1Suit'] \ if stat['screen_name'] == hero:
+ trans[cards[k]['card2Value']] + cards[k]['card2Suit'] \ return self.parent.hud.cards[stat['seat']][0:6]
+ trans[cards[k]['card3Value']] + cards[k]['card3Suit']
return "xxxxxx" return "xxxxxx"
def update_gui(self, new_hand_id): def update_gui(self, new_hand_id):
@ -225,25 +224,7 @@ class Stud_cards:
self.container.add(self.grid) self.container.add(self.grid)
def translate_cards(self, old_cards):
ranks = ('', '', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A')
for c in old_cards.keys():
for i in range(1, 8):
rank = 'card' + str(i) + 'Value'
suit = 'card' + str(i) + 'Suit'
key = 'hole_card_' + str(i)
if old_cards[c][rank] == 0:
old_cards[c][key] = 'xx'
else:
old_cards[c][key] = ranks[old_cards[c][rank]] + old_cards[c][suit]
return old_cards
def update_data(self, new_hand_id, db_connection): def update_data(self, new_hand_id, db_connection):
# db_connection = Database.Database(self.config, 'fpdb', '')
cards = db_connection.get_cards(new_hand_id)
self.cards = self.translate_cards(cards)
self.tips = [] self.tips = []
action = db_connection.get_action_from_hand(new_hand_id) action = db_connection.get_action_from_hand(new_hand_id)
for street in action: for street in action:
@ -261,13 +242,13 @@ class Stud_cards:
def update_gui(self, new_hand_id): def update_gui(self, new_hand_id):
self.clear() self.clear()
for c in self.cards.keys(): for c, cards in self.parent.hud.cards.iteritems():
self.grid_contents[(1, self.cards[c]['seat_number'] - 1)].set_text(self.cards[c]['screen_name']) self.grid_contents[(1, c - 1)].set_text(self.get_screen_name(c))
for i in ((0, 'hole_card_1'), (1, 'hole_card_2'), (2, 'hole_card_3'), (3, 'hole_card_4'), for i in ((0, cards[0:2]), (1, cards[2:4]), (2, cards[4:6]), (3, cards[6:8]),
(4, 'hole_card_5'), (5, 'hole_card_6'), (6, 'hole_card_7')): (4, cards[8:10]), (5, cards[10:12]), (6, cards[12:14])):
if not self.cards[c][i[1]] == "xx": if not i[1] == "xx":
self.seen_cards[(i[0], self.cards[c]['seat_number'] - 1)]. \ self.seen_cards[(i[0], c - 1)]. \
set_from_pixbuf(self.card_images[self.split_cards(self.cards[c][i[1]])]) set_from_pixbuf(self.card_images[self.split_cards(i[1])])
## action in tool tips for 3rd street cards ## action in tool tips for 3rd street cards
for c in (0, 1, 2): for c in (0, 1, 2):
for r in range(0, self.rows): for r in range(0, self.rows):
@ -279,6 +260,13 @@ class Stud_cards:
for r in range(0, self.rows): for r in range(0, self.rows):
self.eb[(round_to_col[round], r)].set_tooltip_text(self.tips[round]) self.eb[(round_to_col[round], r)].set_tooltip_text(self.tips[round])
def get_screen_name(self, seat_no):
"""Gets and returns the screen name from stat_dict, given seat number."""
for k in self.parent.hud.stat_dict.keys():
if self.parent.hud.stat_dict[k]['seat'] == seat_no:
return self.parent.hud.stat_dict[k]['screen_name']
return "No Name"
def split_cards(self, card): def split_cards(self, card):
return (card[0], card[1].upper()) return (card[0], card[1].upper())

View File

@ -70,6 +70,13 @@ def do_stat(stat_dict, player = 24, stat = 'vpip'):
########################################### ###########################################
# functions that return individual stats # functions that return individual stats
def totalprofit(stat_dict, player):
""" Total Profit."""
if stat_dict[player]['net'] != 0:
stat = float(stat_dict[player]['net']) / 100
return (stat, '$%.2f' % stat, 'tp=$%.2f' % stat, 'totalprofit=$%.2f' % stat, str(stat), '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."""
return (stat_dict[player]['screen_name'], return (stat_dict[player]['screen_name'],

View File

@ -390,9 +390,9 @@ if __name__=="__main__":
print discover_table_by_name(c, "Ringe") print discover_table_by_name(c, "Ringe")
# print discover_tournament_table(c, "118942908", "3") # print discover_tournament_table(c, "118942908", "3")
# tables = discover(c) tables = discover(c)
# for t in tables.keys(): for t in tables.keys():
# print tables[t] print tables[t]
print "press enter to continue" print "press enter to continue"
sys.stdin.readline() sys.stdin.readline()

View File

@ -61,6 +61,7 @@ class Importer:
self.filelist = {} self.filelist = {}
self.dirlist = {} self.dirlist = {}
self.addToDirList = {} self.addToDirList = {}
self.removeFromFileList = {} # to remove deleted files
self.monitor = False self.monitor = False
self.updated = {} #Time last import was run {file:mtime} self.updated = {} #Time last import was run {file:mtime}
self.lines = None self.lines = None
@ -210,7 +211,12 @@ class Importer:
for dir in self.addToDirList: for dir in self.addToDirList:
self.addImportDirectory(dir, True, self.addToDirList[dir][0], self.addToDirList[dir][1]) self.addImportDirectory(dir, True, self.addToDirList[dir][0], self.addToDirList[dir][1])
for file in self.removeFromFileList:
if file in self.filelist:
del self.filelist[file]
self.addToDirList = {} self.addToDirList = {}
self.removeFromFileList = {}
# This is now an internal function that should not be called directly. # This is now an internal function that should not be called directly.
def import_file_dict(self, file, site, filter): def import_file_dict(self, file, site, filter):
@ -266,9 +272,15 @@ class Importer:
if (file=="stdin"): if (file=="stdin"):
inputFile=sys.stdin inputFile=sys.stdin
else: else:
inputFile=open(file, "rU") if os.path.exists(file):
try: loc = self.pos_in_file[file] inputFile = open(file, "rU")
except: pass else:
self.removeFromFileList[file] = True
return (0, 0, 0, 1, 0)
try:
loc = self.pos_in_file[file]
except:
pass
# Read input file into class and close file # Read input file into class and close file
inputFile.seek(loc) inputFile.seek(loc)