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

Conflicts:

	pyfpdb/fpdb.py
This commit is contained in:
Worros 2009-06-08 19:20:01 +08:00
commit d8dffb193f
4 changed files with 197 additions and 42 deletions

View File

@ -23,11 +23,11 @@ import os
import os.path
from decimal import Decimal
import operator
import time
import time,datetime
from copy import deepcopy
from Exceptions import *
import DerivedStats
import Card
class Hand:
UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K', 'S':'s', 'C':'c', 'H':'h', 'D':'d'}
@ -148,7 +148,8 @@ db: a connected fpdb_db object"""
def select(self, handId):
""" Function to create Hand object from database """
pass
def addPlayer(self, seat, name, chips):
@ -408,34 +409,34 @@ Map the tuple self.gametype onto the pokerstars string describing it
def printActionLine(self, act, fh):
if act[1] == 'folds':
print >>fh, _("%s: folds " %(act[0]))
print >>fh, ("%s: folds " %(act[0]))
elif act[1] == 'checks':
print >>fh, _("%s: checks " %(act[0]))
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 ''))
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 ''))
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 ''))
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] == 'completea':
print >>fh, _("%s: completes to $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else ''))
print >>fh, ("%s: completes to $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else ''))
elif act[1] == 'posts':
if(act[2] == "small blind"):
print >>fh, _("%s: posts small blind $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else ''))
print >>fh, ("%s: posts small blind $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else ''))
elif(act[2] == "big blind"):
print >>fh, _("%s: posts big blind $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else ''))
print >>fh, ("%s: posts big blind $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else ''))
elif(act[2] == "both"):
print >>fh, _("%s: posts small & big blinds $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else ''))
print >>fh, ("%s: posts small & big blinds $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else ''))
elif act[1] == 'bringin':
print >>fh, _("%s: brings in for $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else ''))
print >>fh, ("%s: brings in for $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else ''))
elif act[1] == 'discards':
print >>fh, _("%s: discards %s %s%s" %(act[0], act[2], 'card' if act[2] == 1 else 'cards' , " [" + " ".join(self.discards[act[0]]['DRAWONE']) + "]" if self.hero == act[0] else ''))
print >>fh, ("%s: discards %s %s%s" %(act[0], act[2], 'card' if act[2] == 1 else 'cards' , " [" + " ".join(self.discards[act[0]]['DRAWONE']) + "]" if self.hero == act[0] else ''))
elif act[1] == 'stands pat':
print >>fh, _("%s: stands pat" %(act[0]))
print >>fh, ("%s: stands pat" %(act[0]))
class HoldemOmahaHand(Hand):
def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC"):
def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC", handid=None):
if gametype['base'] != 'hold':
pass # or indeed don't pass and complain instead
logging.debug("HoldemOmahaHand")
@ -470,7 +471,14 @@ class HoldemOmahaHand(Hand):
self.totalPot() # finalise it (total the pot)
hhc.getRake(self)
elif builtFrom == "DB":
self.select("dummy") # Will need a handId
if handid is not None:
self.select(handid) # Will need a handId
else:
logging.warning("HoldemOmahaHand.__init__:Can't assemble hand from db without a handid")
else:
logging.warning("HoldemOmahaHand.__init__:Neither HHC nor DB+handid provided")
pass
def addHoleCards(self, cards, player, shown=False):
"""\
@ -508,41 +516,41 @@ Card ranks will be uppercased
def writeHand(self, fh=sys.__stdout__):
# PokerStars format.
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, ("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET')))
print >>fh, ("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos))
players_who_act_preflop = set(([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']]))
logging.debug(self.actions['PREFLOP'])
for player in [x for x in self.players if x[1] in players_who_act_preflop]:
#Only print stacks of players who do something preflop
print >>fh, _("Seat %s: %s ($%s in chips) " %(player[0], player[1], player[2]))
print >>fh, ("Seat %s: %s ($%s in chips) " %(player[0], player[1], player[2]))
if self.actions['BLINDSANTES']:
for act in self.actions['BLINDSANTES']:
self.printActionLine(act, fh)
print >>fh, _("*** HOLE CARDS ***")
print >>fh, ("*** HOLE CARDS ***")
if self.involved:
print >>fh, _("Dealt to %s [%s]" %(self.hero , " ".join(self.holecards[self.hero]['PREFLOP'])))
print >>fh, ("Dealt to %s [%s]" %(self.hero , " ".join(self.holecards[self.hero]['PREFLOP'])))
if self.actions['PREFLOP']:
for act in self.actions['PREFLOP']:
self.printActionLine(act, fh)
if self.board['FLOP']:
print >>fh, _("*** FLOP *** [%s]" %( " ".join(self.board['FLOP'])))
print >>fh, ("*** FLOP *** [%s]" %( " ".join(self.board['FLOP'])))
if self.actions['FLOP']:
for act in self.actions['FLOP']:
self.printActionLine(act, fh)
if self.board['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'])))
if self.actions['TURN']:
for act in self.actions['TURN']:
self.printActionLine(act, fh)
if self.board['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']) ))
if self.actions['RIVER']:
for act in self.actions['RIVER']:
self.printActionLine(act, fh)
@ -552,7 +560,7 @@ Card ranks will be uppercased
# The logic for a showdown is: at the end of river action there are at least two players in the hand
# we probably don't need a showdown section in pseudo stars format for our filtering purposes
if self.shown:
print >>fh, _("*** SHOW DOWN ***")
print >>fh, ("*** SHOW DOWN ***")
for name in self.shown:
# TODO: legacy importer can't handle only one holecard here, make sure there are 2 for holdem, 4 for omaha
# TOOD: If HoldHand subclass supports more than omahahi, omahahilo, holdem, add them here
@ -562,7 +570,7 @@ Card ranks will be uppercased
elif self.gametype['category'] in ('holdem'):
numOfHoleCardsNeeded = 2
if len(self.holecards[name]['PREFLOP']) == numOfHoleCardsNeeded:
print >>fh, _("%s shows [%s] (a hand...)" % (name, " ".join(self.holecards[name]['PREFLOP'])))
print >>fh, ("%s shows [%s] (a hand...)" % (name, " ".join(self.holecards[name]['PREFLOP'])))
# Current PS format has the lines:
# Uncalled bet ($111.25) returned to s0rrow
@ -572,35 +580,35 @@ Card ranks will be uppercased
# Immediately before the summary.
# The current importer uses those lines for importing winning rather than the summary
for name in self.pot.returned:
print >>fh, _("Uncalled bet ($%s) returned to %s" %(self.pot.returned[name],name))
print >>fh, ("Uncalled bet ($%s) returned to %s" %(self.pot.returned[name],name))
for entry in self.collected:
print >>fh, _("%s collected $%s from x pot" %(entry[0], entry[1]))
print >>fh, ("%s collected $%s from x pot" %(entry[0], entry[1]))
print >>fh, _("*** SUMMARY ***")
print >>fh, ("*** SUMMARY ***")
print >>fh, "%s | Rake $%.2f" % (self.pot, self.rake)
board = []
for s in self.board.values():
board += s
if board: # sometimes hand ends preflop without a board
print >>fh, _("Board [%s]" % (" ".join(board)))
print >>fh, ("Board [%s]" % (" ".join(board)))
for player in [x for x in self.players if x[1] in players_who_act_preflop]:
seatnum = player[0]
name = player[1]
if name in self.collectees and name in self.shown:
print >>fh, _("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards[name]['PREFLOP']), self.collectees[name]))
print >>fh, ("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards[name]['PREFLOP']), self.collectees[name]))
elif name in self.collectees:
print >>fh, _("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name]))
print >>fh, ("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name]))
#~ elif name in self.shown:
#~ print >>fh, _("Seat %d: %s showed [%s]" % (seatnum, name, " ".join(self.holecards[name]['PREFLOP'])))
elif name in self.folded:
print >>fh, _("Seat %d: %s folded" % (seatnum, name))
print >>fh, ("Seat %d: %s folded" % (seatnum, name))
else:
if name in self.shown:
print >>fh, _("Seat %d: %s showed [%s] and lost with..." % (seatnum, name, " ".join(self.holecards[name]['PREFLOP'])))
print >>fh, ("Seat %d: %s showed [%s] and lost with..." % (seatnum, name, " ".join(self.holecards[name]['PREFLOP'])))
else:
print >>fh, _("Seat %d: %s mucked" % (seatnum, name))
print >>fh, ("Seat %d: %s mucked" % (seatnum, name))
print >>fh, "\n\n"
@ -1086,6 +1094,154 @@ class Pot(object):
# no small blind and walk in bb (hopefully)
return "Total pot $%.2f" % (self.total,)
else:
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.
# The thing to do here is raise a Hand error like fpdb import does and file it into errors.txt
def assemble(cnxn, handid):
c = cnxn.cursor()
# We need the following for the Hand.__init__
c.execute("""
select
s.name,
g.category,
g.base,
g.type,
g.limitType,
g.hilo,
g.smallBlind / 100.0,
g.bigBlind / 100.0 ,
g.smallBet / 100.0,
g.bigBet / 100.0,
s.currency,
bc.card1value,
bc.card1suit,
bc.card2value,bc.card2suit,
bc.card3value,bc.card3suit,
bc.card4value,bc.card4suit,
bc.card5value,bc.card5suit
from
hands as h,
boardcards as bc,
sites as s,
gametypes as g,
handsplayers as hp,
players as p
where
h.id = %(handid)s
and bc.handid = h.id
and g.id = h.gametypeid
and hp.handid = h.id
and p.id = hp.playerid
and s.id = p.siteid
limit 1""", {'handid':handid})
#TODO: siteid should be in hands table - we took the scenic route through players here.
res = c.fetchone()
gametype = {'category':res[1],'base':res[2],'type':res[3],'limitType':res[4],'hilo':res[5],'sb':res[6],'bb':res[7], 'currency':res[10]}
h = HoldemOmahaHand(hhc = None, sitename=res[0], gametype = gametype, handText=None, builtFrom = "DB", handid=handid)
cards = map("".join, zip(map(str,res[11:21:2]), res[12:21:2]))
if cards[0] != "0x":
h.setCommunityCards('FLOP', cards[0:3])
if cards[3] != "0x":
h.setCommunityCards('TURN', cards[3])
if cards[4] != "0x":
h.setCommunityCards('RIVER', cards[4])
#[Card.valueSuitFromCard(x) for x in cards]
#TODO : doesn't look like this is in the database; don't like the way Hand requires it
h.hero = 'mcturnbull'
# HandInfo : HID, TABLE
# BUTTON - why is this treated specially in Hand?
# answer: it is written out in hand histories
# still, I think we should record all the active seat positions in a seat_order array
c.execute("""
SELECT
h.sitehandno as hid,
h.tablename as table,
h.handstart as starttime
FROM
hands as h
WHERE h.id = %(handid)s
""", {'handid':handid})
res = c.fetchone()
h.handid = res[0]
h.tablename = res[1]
h.starttime = res[2] # automatically a datetime
# PlayerStacks
c.execute("""
SELECT
hp.seatno,
p.name,
round(hp.startcash / 100.0,2) as chips,
(hp.card1,hp.card2) as hole
FROM
handsplayers as hp,
players as p
WHERE
hp.handid = %(handid)s
and p.id = hp.playerid
""", {'handid':handid})
for (seat, name, chips, cards) in c.fetchall():
h.addPlayer(seat,name,chips)
h.addHoleCards([Card.valueSuitFromCard(x) for x in cards],name)
# actions
c.execute("""
SELECT
(ha.street,ha.actionno) as actnum,
p.name,
ha.street,
ha.action,
ha.allin,
ha.amount / 100.0
FROM
handsplayers as hp,
handsactions as ha,
players as p
WHERE
hp.handid = %(handid)s
and ha.handsplayerid = hp.id
and p.id = hp.playerid
ORDER BY
ha.street,ha.actionno
""", {'handid':handid})
res = c.fetchall()
for (actnum,player, streetnum, act, allin, amount) in res:
act=act.strip()
street = h.streetList[streetnum+2]
if act==u'blind':
h.addBlind(player, 'big blind', amount)
# TODO: The type of blind is not recorded in the DB.
# TODO: preflop street name anomalies in Hand
elif act==u'fold':
h.addFold(street,player)
elif act==u'call':
h.addCall(street,player,amount)
elif act==u'bet':
h.addBet(street,player,amount)
elif act==u'check':
h.addCheck(street,player)
elif act==u'unbet':
pass
else:
print act, player, streetnum, allin, amount
# TODO : other actions
#hhc.readCollectPot(self)
#hhc.readShowdownActions(self)
#hc.readShownCards(self)
h.totalPot()
h.rake = h.totalpot - h.totalcollected
return h

View File

@ -134,8 +134,8 @@ follow : whether to tail -f the input"""
#2008/08/17 - 01:14:43 (ET)
#2008/09/07 06:23:14 ET
m2 = re.search("(?P<Y>[0-9]{4})\/(?P<M>[0-9]{2})\/(?P<D>[0-9]{2})[\- ]+(?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)", info[key])
datetime = "%s/%s/%s %s:%s:%s" % (m2.group('Y'), m2.group('M'),m2.group('D'),m2.group('H'),m2.group('MIN'),m2.group('S'))
hand.starttime = time.strptime(datetime, "%Y/%m/%d %H:%M:%S")
datetimestr = "%s/%s/%s %s:%s:%s" % (m2.group('Y'), m2.group('M'),m2.group('D'),m2.group('H'),m2.group('MIN'),m2.group('S'))
hand.starttime = datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S")
if key == 'HID':
hand.handid = info[key]
if key == 'TABLE':

View File

@ -409,7 +409,7 @@ class fpdb:
return self.fdb_lock.get_global_lock()
#end def obtain_global_lock
def quit(self, widget):
def quit(self, widget, data):
print "Quitting normally"
#check if current settings differ from profile, if so offer to save or abort
self.db.disconnect()

View File

@ -1138,7 +1138,6 @@ def storeActions(cursor, handsPlayersIds, actionTypes, allIns, actionAmounts, ac
def store_board_cards(cursor, hands_id, board_values, board_suits):
#stores into table board_cards
return
cursor.execute ("""INSERT INTO BoardCards (handId, card1Value, card1Suit,
card2Value, card2Suit, card3Value, card3Suit, card4Value, card4Suit,
card5Value, card5Suit) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""",
@ -2382,7 +2381,7 @@ def storeHudCache2(backend, cursor, base, category, gametypeId, hand_start_time,
# Try to do the update first:
num = cursor.execute("""UPDATE HudCache
SET HDs=HDs+%s, street0VPI=street0VPI+%s, street0Aggr=street0Aggr+%s,
street0_3BChance=street0_3BChance+%s, street0_3BDone=street0_3BDone+%s,
street0_3B4BChance=street0_3B4BChance+%s, street0_3B4BDone=street0_3B4BDone+%s,
street1Seen=street1Seen+%s, street2Seen=street2Seen+%s, street3Seen=street3Seen+%s,
street4Seen=street4Seen+%s, sawShowdown=sawShowdown+%s,
street1Aggr=street1Aggr+%s, street2Aggr=street2Aggr+%s, street3Aggr=street3Aggr+%s,