Merge branch 'master' of git://git.assembla.com/fpdb-eric
This commit is contained in:
commit
3cc5ed8024
|
@ -24,25 +24,37 @@ def twoStartCards(value1, suit1, value2, suit2):
|
|||
(y+2) represents rank of second card (2=2 .. 14=Ace)
|
||||
If x > y then pair is suited, if x < y then unsuited"""
|
||||
if value1 < 2 or value2 < 2:
|
||||
return(0)
|
||||
if (suit1 == suit2 and value1 < value2) or (suit1 != suit2 and value2 > value1):
|
||||
return(13 * (value2-2) + (value1-1))
|
||||
ret = 0
|
||||
if value1 == value2: # pairs
|
||||
ret = (13 * (value2-2) + (value2-1) )
|
||||
elif suit1 == suit2:
|
||||
if value1 > value2:
|
||||
ret = 13 * (value1-2) + (value2-1)
|
||||
else:
|
||||
return(13 * (value1-2) + (value2-1))
|
||||
ret = 13 * (value2-2) + (value1-1)
|
||||
else:
|
||||
if value1 > value2:
|
||||
ret = 13 * (value2-2) + (value2-1)
|
||||
else:
|
||||
ret = 13 * (value1-2) + (value2-1)
|
||||
|
||||
# print "twoStartCards(", value1, suit1, value2, suit2, ")=", ret
|
||||
return ret
|
||||
|
||||
def twoStartCardString(card):
|
||||
""" Function to convert an int representing 2 holdem hole cards (as created by twoStartCards)
|
||||
into a string like AQo """
|
||||
if card <= 0:
|
||||
return 'xx'
|
||||
else:
|
||||
ret = 'xx'
|
||||
if card > 0:
|
||||
card -= 1
|
||||
s = ('2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A')
|
||||
x = card/13
|
||||
y = card - 13*x
|
||||
if x == y: return(s[x] + s[y])
|
||||
elif x > y: return(s[x] + s[y] + 's')
|
||||
else: return(s[y] + s[x] + 'o')
|
||||
x = card / 13
|
||||
y = card - 13 * x
|
||||
if x == y: ret = s[x] + s[y]
|
||||
elif x > y: ret = s[x] + s[y] + 's'
|
||||
else: ret = s[y] + s[x] + 'o'
|
||||
# print "twoStartCardString(", card ,") = " + ret
|
||||
return ret
|
||||
|
||||
def fourStartCards(value1, suit1, value2, suit2, value3, suit3, value4, suit4):
|
||||
""" Function to convert 4 value,suit pairs into a Omaha style starting hand,
|
||||
|
@ -95,4 +107,7 @@ def valueSuitFromCard(card):
|
|||
][card] )
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
for i in xrange(1, 14):
|
||||
print "card %2d = %s card %2d = %s card %2d = %s card %2d = %s" % \
|
||||
(i, valueSuitFromCard(i), i+13, valueSuitFromCard(i+13), i+26, valueSuitFromCard(i+26), i+39, valueSuitFromCard(i+39))
|
||||
|
|
|
@ -237,11 +237,14 @@ or None if we fail to get the info """
|
|||
# Also works with Omaha hands.
|
||||
cards = m.group('CARDS')
|
||||
cards = [card.strip() for card in cards.split(',')]
|
||||
hand.addHoleCards(cards, m.group('PNAME'))
|
||||
# hand.addHoleCards(cards, m.group('PNAME'))
|
||||
hand.addHoleCards('PREFLOP', hand.hero, closed=cards, shown=False, mucked=False, dealt=True)
|
||||
|
||||
else:
|
||||
#Not involved in hand
|
||||
hand.involved = False
|
||||
|
||||
|
||||
def readStudPlayerCards(self, hand, street):
|
||||
# lol. see Plymouth.txt
|
||||
logging.warning("Everleaf readStudPlayerCards is only a stub.")
|
||||
|
@ -292,7 +295,8 @@ or None if we fail to get the info """
|
|||
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)
|
||||
hand.addShownCards(cards=cards, player=m.group('PNAME'))
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -33,25 +33,33 @@ class Fulltilt(HandHistoryConverter):
|
|||
-\s(?P<CURRENCY>\$|)?
|
||||
(?P<SB>[.0-9]+)/
|
||||
\$?(?P<BB>[.0-9]+)\s
|
||||
(Ante\s\$(?P<ANTE>[.0-9]+)\s)?-\s
|
||||
(Ante\s\$?(?P<ANTE>[.0-9]+)\s)?-\s
|
||||
(?P<LIMIT>(No\sLimit|Pot\sLimit|Limit))?\s
|
||||
(?P<GAME>(Hold\'em|Omaha\sHi|Omaha\sH/L|7\sCard\sStud|Stud\sH/L|Razz))
|
||||
(?P<GAME>(Hold\'em|Omaha\sHi|Omaha\sH/L|7\sCard\sStud|Stud\sH/L|Razz|Stud\sHi))
|
||||
''', re.VERBOSE)
|
||||
re_SplitHands = re.compile(r"\n\n+")
|
||||
re_TailSplitHands = re.compile(r"(\n\n+)")
|
||||
re_HandInfo = re.compile('''.*\#(?P<HID>[0-9]+):\s
|
||||
(?:(?P<TOURNAMENT>.+)\s\((?P<TOURNO>\d+)\),\s)?
|
||||
Table\s(?P<TABLE>[-\s\da-zA-Z]+)\s
|
||||
Table\s
|
||||
(?P<PLAY>Play\sChip\s|PC)?
|
||||
(?P<TABLE>[-\s\da-zA-Z]+)\s
|
||||
(\((?P<TABLEATTRIBUTES>.+)\)\s)?-\s
|
||||
\$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)\s(Ante\s\$(?P<ANTE>[.0-9]+)\s)?-\s
|
||||
\$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)\s(Ante\s\$?(?P<ANTE>[.0-9]+)\s)?-\s
|
||||
(?P<GAMETYPE>[a-zA-Z\/\'\s]+)\s-\s
|
||||
(?P<DATETIME>.*)
|
||||
''', re.VERBOSE)
|
||||
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]+)\)$', re.MULTILINE)
|
||||
re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
|
||||
|
||||
# These regexes are for FTP only
|
||||
re_Mixed = re.compile(r'\s\-\s(?P<MIXED>HA|HORSE|HOSE)\s\-\s', re.VERBOSE)
|
||||
re_Max = re.compile("(?P<MAX>\d+)( max)?", re.MULTILINE)
|
||||
# NB: if we ever match "Full Tilt Poker" we should also match "FullTiltPoker", which PT Stud erroneously exports.
|
||||
|
||||
mixes = { 'HORSE': 'horse', '7-Game': '7game', 'HOSE': 'hose', 'HA': 'ha'}
|
||||
|
||||
def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, index=0):
|
||||
"""\
|
||||
in_path (default '-' = sys.stdin)
|
||||
|
@ -109,7 +117,6 @@ follow : whether to tail -f the input"""
|
|||
m = self.re_GameInfo.search(handText)
|
||||
if not m:
|
||||
return None
|
||||
|
||||
mg = m.groupdict()
|
||||
|
||||
# translations from captured groups to our info strings
|
||||
|
@ -119,8 +126,8 @@ follow : whether to tail -f the input"""
|
|||
'Omaha Hi' : ('hold','omahahi'),
|
||||
'Omaha H/L' : ('hold','omahahilo'),
|
||||
'Razz' : ('stud','razz'),
|
||||
'7 Card Stud' : ('stud','studhi'),
|
||||
'Stud H/L' : ('stud', 'studhilo')
|
||||
'Stud Hi' : ('stud','studhi'),
|
||||
'Stud H/L' : ('stud','studhilo')
|
||||
}
|
||||
currencies = { u' €':'EUR', '$':'USD', '':'T$' }
|
||||
info['limitType'] = limits[mg['LIMIT']]
|
||||
|
@ -137,7 +144,6 @@ follow : whether to tail -f the input"""
|
|||
|
||||
def readHandInfo(self, hand):
|
||||
m = self.re_HandInfo.search(hand.handText,re.DOTALL)
|
||||
|
||||
if(m == None):
|
||||
logging.info("Didn't match re_HandInfo")
|
||||
logging.info(hand.handText)
|
||||
|
@ -146,12 +152,12 @@ follow : whether to tail -f the input"""
|
|||
hand.tablename = m.group('TABLE')
|
||||
hand.starttime = datetime.datetime.strptime(m.group('DATETIME'), "%H:%M:%S ET - %Y/%m/%d")
|
||||
if m.group('TABLEATTRIBUTES'):
|
||||
m2 = re.search("(deep )?(\d+)( max)?", m.group('TABLEATTRIBUTES'))
|
||||
hand.maxseats = int(m2.group(2))
|
||||
m2 = self.re_Max.search(m.group('TABLEATTRIBUTES'))
|
||||
if m2: hand.maxseats = int(m2.group('MAX'))
|
||||
|
||||
hand.tourNo = m.group('TOURNO')
|
||||
# if key == 'PLAY' and info['PLAY'] != None:
|
||||
# hand.gametype['currency'] = 'play'
|
||||
if m.group('PLAY') != None:
|
||||
hand.gametype['currency'] = 'play'
|
||||
|
||||
# These work, but the info is already in the Hand class - should be used for tourneys though.
|
||||
# m.group('SB')
|
||||
|
@ -214,6 +220,7 @@ follow : whether to tail -f the input"""
|
|||
m = self.re_Antes.finditer(hand.handText)
|
||||
for player in m:
|
||||
logging.debug("hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE')))
|
||||
# if player.group() !=
|
||||
hand.addAnte(player.group('PNAME'), player.group('ANTE'))
|
||||
|
||||
def readBringIn(self, hand):
|
||||
|
@ -222,7 +229,7 @@ follow : whether to tail -f the input"""
|
|||
logging.debug("Player bringing in: %s for %s" %(m.group('PNAME'), m.group('BRINGIN')))
|
||||
hand.addBringIn(m.group('PNAME'), m.group('BRINGIN'))
|
||||
else:
|
||||
logging.warning("No bringin found")
|
||||
logging.warning("No bringin found, handid =%s" % hand.handid)
|
||||
|
||||
def readButton(self, hand):
|
||||
hand.buttonpos = int(self.re_Button.search(hand.handText).group('BUTTON'))
|
||||
|
@ -255,10 +262,10 @@ follow : whether to tail -f the input"""
|
|||
else:
|
||||
oldcards = found.group('OLDCARDS').split(' ')
|
||||
|
||||
if street == 'THIRD' and len(newcards) == 3: # hero in stud game
|
||||
if street == 'THIRD' and len(oldcards) == 2: # hero in stud game
|
||||
hand.hero = player
|
||||
hand.dealt.add(player) # need this for stud??
|
||||
hand.addHoleCards(street, player, closed=newcards[0:2], open=[newcards[2]], shown=False, mucked=False, dealt=False)
|
||||
hand.addHoleCards(street, player, closed=oldcards, open=newcards, shown=False, mucked=False, dealt=False)
|
||||
else:
|
||||
hand.addHoleCards(street, player, open=newcards, closed=oldcards, shown=False, mucked=False, dealt=False)
|
||||
|
||||
|
@ -317,6 +324,11 @@ follow : whether to tail -f the input"""
|
|||
if mo <= 6: return 6
|
||||
return 9
|
||||
|
||||
def readOther(self, hand):
|
||||
m = self.re_Mixed.search(self.in_path)
|
||||
if m == None: hand.mixed = None
|
||||
else:
|
||||
hand.mixed = self.mixes[m.groupdict()['MIXED']]
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = OptionParser()
|
||||
|
|
|
@ -262,7 +262,8 @@ def main(argv=None):
|
|||
else:
|
||||
#Do something useful
|
||||
importer = fpdb_import.Importer(False,settings, config)
|
||||
importer.setDropIndexes("auto")
|
||||
# importer.setDropIndexes("auto")
|
||||
importer.setDropIndexes("don't drop")
|
||||
importer.setFailOnError(options.failOnError)
|
||||
importer.addBulkImportImportFileOrDir(os.path.expanduser(options.filename), site=options.filtername)
|
||||
importer.setCallHud(False)
|
||||
|
|
|
@ -39,7 +39,7 @@ class Hand(object):
|
|||
UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K', 'S':'s', 'C':'c', 'H':'h', 'D':'d'}
|
||||
LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'}
|
||||
SYMBOL = {'USD': '$', 'EUR': u'$', 'T$': '', 'play': ''}
|
||||
MS = {'horse' : 'HORSE', '8game' : '8-Game', 'hose' : 'HOSE'}
|
||||
MS = {'horse' : 'HORSE', '8game' : '8-Game', 'hose' : 'HOSE', 'ha': 'HA'}
|
||||
|
||||
|
||||
def __init__(self, sitename, gametype, handText, builtFrom = "HHC"):
|
||||
|
@ -583,7 +583,7 @@ Map the tuple self.gametype onto the pokerstars string describing it
|
|||
table_string = "Table \'%s\' %s-max" % (self.tablename, self.maxseats)
|
||||
if self.gametype['currency'] == 'play':
|
||||
table_string = table_string + " (Play Money)"
|
||||
if self.buttonpos != None:
|
||||
if self.buttonpos != None and self.buttonpos != 0:
|
||||
table_string = table_string + " Seat #%s is the button" % self.buttonpos
|
||||
return table_string
|
||||
|
||||
|
@ -632,6 +632,7 @@ class HoldemOmahaHand(Hand):
|
|||
hhc.getRake(self)
|
||||
if self.maxseats == None:
|
||||
self.maxseats = hhc.guessMaxSeats(self)
|
||||
hhc.readOther(self)
|
||||
elif builtFrom == "DB":
|
||||
if handid is not None:
|
||||
self.select(handid) # Will need a handId
|
||||
|
@ -877,6 +878,9 @@ class DrawHand(Hand):
|
|||
hhc.readShownCards(self)
|
||||
self.totalPot() # finalise it (total the pot)
|
||||
hhc.getRake(self)
|
||||
if self.maxseats == None:
|
||||
self.maxseats = hhc.guessMaxSeats(self)
|
||||
hhc.readOther(self)
|
||||
elif builtFrom == "DB":
|
||||
self.select("dummy") # Will need a handId
|
||||
|
||||
|
@ -1032,7 +1036,8 @@ class StudHand(Hand):
|
|||
hhc.readBringIn(self)
|
||||
hhc.readHeroCards(self)
|
||||
# Read actions in street order
|
||||
for street in self.streetList:
|
||||
for street in self.actionStreets:
|
||||
if street == 'ANTES': continue # OMG--sometime someone folds in the ante round
|
||||
if self.streets[street]:
|
||||
logging.debug(street)
|
||||
logging.debug(self.streets[street])
|
||||
|
@ -1041,6 +1046,9 @@ class StudHand(Hand):
|
|||
hhc.readShownCards(self) # not done yet
|
||||
self.totalPot() # finalise it (total the pot)
|
||||
hhc.getRake(self)
|
||||
if self.maxseats == None:
|
||||
self.maxseats = hhc.guessMaxSeats(self)
|
||||
hhc.readOther(self)
|
||||
elif builtFrom == "DB":
|
||||
self.select("dummy") # Will need a handId
|
||||
|
||||
|
@ -1079,6 +1087,7 @@ closed likewise, but known only to player
|
|||
Add a complete on [street] by [player] to [amountTo]
|
||||
"""
|
||||
logging.debug("%s %s completes %s" % (street, player, amountTo))
|
||||
amountTo = re.sub(u',', u'', amountTo) #some sites have commas
|
||||
self.checkPlayerExists(player)
|
||||
Bp = self.lastBet['THIRD']
|
||||
Bc = reduce(operator.add, self.bets[street][player], 0)
|
||||
|
@ -1314,31 +1323,19 @@ class Pot(object):
|
|||
# Total pot $124.30 Main pot $98.90. Side pot $23.40. | Rake $2
|
||||
|
||||
def __str__(self):
|
||||
if self.sym is None:
|
||||
self.sym = "C"
|
||||
if self.total is None:
|
||||
print "call Pot.end() before printing pot total"
|
||||
# NB if I'm sure end() is idempotent, call it here.
|
||||
raise FpdbParseError
|
||||
|
||||
ret = "Total pot %s%.2f" % (self.sym, self.total)
|
||||
if len(self.pots) < 2:
|
||||
return ret;
|
||||
ret += " Main pot %s%.2f" % (self.sym, self.pots[0])
|
||||
|
||||
# TODO: This really neeads to be a loop to handle multiple side pots
|
||||
if len(self.pots) == 1: # (only use Total pot)
|
||||
return "Total pot %s%.2f" % (self.sym, self.total,)
|
||||
elif len(self.pots) == 2:
|
||||
return "Total pot %s%.2f Main pot %s%.2f. Side pot %s%2.f." % (self.sym, self.total, self.sym, self.pots[0], self.sym, self.pots[1])
|
||||
elif len(self.pots) == 3:
|
||||
return "Total pot %s%.2f Main pot %s%.2f. Side pot-1 %s%2.2f. Side pot-2 %s%.2f." % (self.sym, self.total, self.sym, self.pots[0], self.sym, self.pots[1], self.sym, self.pots[2])
|
||||
elif len(self.pots) == 0:
|
||||
# no small blind and walk in bb (hopefully)
|
||||
return "Total pot %s%.2f" % (self.sym, self.total,)
|
||||
else:
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return ret + ''.join([ (" Side pot %s%.2f." % (self.sym, self.pots[x]) ) for x in xrange(1, len(self.pots)) ])
|
||||
|
||||
def assemble(cnxn, handid):
|
||||
c = cnxn.cursor()
|
||||
|
|
|
@ -270,6 +270,11 @@ or None if we fail to get the info """
|
|||
def readCollectPot(self, hand): abstract
|
||||
def readShownCards(self, hand): abstract
|
||||
|
||||
# Some sites do odd stuff that doesn't fall in to the normal HH parsing.
|
||||
# e.g., FTP doesn't put mixed game info in the HH, but puts in in the
|
||||
# file name. Use readOther() to clean up those messes.
|
||||
def readOther(self, hand): pass
|
||||
|
||||
# Some sites don't report the rake. This will be called at the end of the hand after the pot total has been calculated
|
||||
# an inheriting class can calculate it for the specific site if need be.
|
||||
def getRake(self, hand):
|
||||
|
|
|
@ -244,6 +244,24 @@ class fpdb:
|
|||
self.release_global_lock()
|
||||
#end def dia_recreate_tables
|
||||
|
||||
def dia_recreate_hudcache(self, widget, data=None):
|
||||
if self.obtain_global_lock():
|
||||
try:
|
||||
dia_confirm = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm recreating HUD cache")
|
||||
diastring = "Please confirm that you want to re-create the HUD cache."
|
||||
dia_confirm.format_secondary_text(diastring)
|
||||
|
||||
response = dia_confirm.run()
|
||||
dia_confirm.destroy()
|
||||
if response == gtk.RESPONSE_YES:
|
||||
self.db.rebuild_hudcache()
|
||||
elif response == gtk.REPSONSE_NO:
|
||||
print 'User cancelled rebuilding hud cache'
|
||||
except:
|
||||
pass
|
||||
self.release_global_lock()
|
||||
|
||||
|
||||
def dia_regression_test(self, widget, data=None):
|
||||
print "todo: implement dia_regression_test"
|
||||
self.obtain_global_lock()
|
||||
|
@ -306,6 +324,7 @@ class fpdb:
|
|||
<menuitem action="createdb"/>
|
||||
<menuitem action="createuser"/>
|
||||
<menuitem action="createtabs"/>
|
||||
<menuitem action="rebuildhudcache"/>
|
||||
<menuitem action="stats"/>
|
||||
<menuitem action="sessions"/>
|
||||
</menu>
|
||||
|
@ -344,6 +363,7 @@ class fpdb:
|
|||
('createdb', None, 'Create or Delete _Database (todo)', None, 'Create or Delete Database', self.dia_create_del_database),
|
||||
('createuser', None, 'Create or Delete _User (todo)', None, 'Create or Delete User', self.dia_create_del_user),
|
||||
('createtabs', None, 'Create or Recreate _Tables', None, 'Create or Recreate Tables ', self.dia_recreate_tables),
|
||||
('rebuildhudcache', None, 'Rebuild HUD Cache', None, 'Rebuild HUD Cache', self.dia_recreate_hudcache),
|
||||
('stats', None, '_Statistics (todo)', None, 'View Database Statistics', self.dia_database_stats),
|
||||
('sessions', None, 'Sessions', None, 'View Sessions', self.dia_database_sessions),
|
||||
('help', None, '_Help'),
|
||||
|
|
|
@ -361,6 +361,10 @@ class fpdb_db:
|
|||
"""Drop some indexes/foreign keys to prepare for bulk import.
|
||||
Currently keeping the standalone indexes as needed to import quickly"""
|
||||
stime = time()
|
||||
if self.backend == self.MYSQL_INNODB:
|
||||
self.cursor.execute("SET foreign_key_checks=0")
|
||||
self.cursor.execute("SET autocommit=0")
|
||||
return
|
||||
if self.backend == self.PGSQL:
|
||||
self.db.set_isolation_level(0) # allow table/index operations to work
|
||||
for fk in self.foreignKeys[self.backend]:
|
||||
|
@ -450,6 +454,12 @@ class fpdb_db:
|
|||
def afterBulkImport(self):
|
||||
"""Re-create any dropped indexes/foreign keys after bulk import"""
|
||||
stime = time()
|
||||
|
||||
if self.backend == self.MYSQL_INNODB:
|
||||
self.cursor.execute("SET foreign_key_checks=1")
|
||||
self.cursor.execute("SET autocommit=1")
|
||||
return
|
||||
|
||||
if self.backend == self.PGSQL:
|
||||
self.db.set_isolation_level(0) # allow table/index operations to work
|
||||
for fk in self.foreignKeys[self.backend]:
|
||||
|
|
Loading…
Reference in New Issue
Block a user