Merge branch 'master' of git://git.assembla.com/fpdb.git
This commit is contained in:
commit
51b62392e1
|
@ -29,8 +29,8 @@ cp -R regression-test fpdb-$1/
|
||||||
cp -R utils fpdb-$1/
|
cp -R utils fpdb-$1/
|
||||||
|
|
||||||
cd fpdb-$1
|
cd fpdb-$1
|
||||||
zip -r ../../fpdb-1.0_$1.zip *
|
zip -r releases/fpdb-1.0_$1.zip *
|
||||||
tar -cf - * | bzip2 >> ../../fpdb-1.0_$1.tar.bz2
|
tar -cf - * | bzip2 >> releases/fpdb-1.0_$1.tar.bz2
|
||||||
cd ..
|
cd ..
|
||||||
rm -r fpdb-$1
|
rm -r fpdb-$1
|
||||||
|
|
||||||
|
|
|
@ -312,11 +312,10 @@ The program itself is licensed under AGPLv3, see agpl-3.0.txt</p>
|
||||||
</TABLE>
|
</TABLE>
|
||||||
<p><BR></P>
|
<p><BR></P>
|
||||||
<p><B>Table HandsPlayers</B></P>
|
<p><B>Table HandsPlayers</B></P>
|
||||||
<p>cardX: can be 1 through 20, one for each card. In holdem only 1-2 of these are used, in omaha 1-4, in stud/razz 1-7, in single draw games 1-10 is used and in badugi 1-16 (4*4) is used.</P>
|
<p>cardX: can be 1 through 20, one for each card. In holdem only 1-2 of these are used, in omaha 1-4, in stud/razz 1-7, in single draw 1-10, in tripple draw all 20 and in badugi 1-16 (4*4).</P>
|
||||||
<p>For the draw games: the first 5 (badugi: 4) cards are the initial cards, the next 5 (badugi: 4) are after the first draw. If a player keeps some cards then those cards' spaces are filled with "k", short for "kept".<br>
|
<p>For the draw games: the first 5 (badugi: 4) cards are the initial cards, the next 5 (badugi: 4) are after the first draw, etc.<br>
|
||||||
Example 1: If a player gets 2-6 spades for his first five cards and decides to throw away the 4 and then gets a 7 of spades then the first 10 fields of cardXValue would be as follows: 2, 3, 4, 5, 6, k, k, 7, k, k<br>
|
Example 1: If a player gets 2-6 spades for his first five cards and decides to throw away the 4 and then gets a 7 of spades then the first 10 fields of cardXValue would be as follows: 2, 3, 4, 5, 6, 2, 3, 5, 6, 7<br>
|
||||||
Example 2: If a player gets 2, 3, 5, 8, J of spades for his first five cards and decides to throw away the 2 and the 3 and then gets a Q and K of spades then the first 10 fields of cardXValue would be as follows: 2, 3, 5, 8, J, Q, K, k, k, k<br>
|
Example 2: If a player gets 2, 3, 5, 8, J of spades for his first five cards and decides to throw away the 2 and the 3 and then gets a Q and K of spades then the first 10 fields of cardXValue would be as follows: 2, 3, 5, 8, J, 5, 8, J, Q, K.</p>
|
||||||
Note that it will k in the space of which card was there previously, so in example 2 where the player kept the last 3 cards, the last 3 fields of the first draw (ie. card8-10Value) are replaced with k.</p>
|
|
||||||
<p>I did not separate this into an extra table because I felt the lost space is not sufficiently large. Also the benefit for searching is far less relevant.</P>
|
<p>I did not separate this into an extra table because I felt the lost space is not sufficiently large. Also the benefit for searching is far less relevant.</P>
|
||||||
<TABLE BORDER=1 CELLPADDING=2 CELLSPACING=0>
|
<TABLE BORDER=1 CELLPADDING=2 CELLSPACING=0>
|
||||||
<TR VALIGN=TOP>
|
<TR VALIGN=TOP>
|
||||||
|
@ -370,6 +369,17 @@ Note that it will k in the space of which card was there previously, so in examp
|
||||||
<TD><P>char(1)</P></TD>
|
<TD><P>char(1)</P></TD>
|
||||||
<TD><P>h=hearts, s=spades, d=diamonds, c=clubs, unknown/no card=x</P></TD>
|
<TD><P>h=hearts, s=spades, d=diamonds, c=clubs, unknown/no card=x</P></TD>
|
||||||
</TR>
|
</TR>
|
||||||
|
<TR VALIGN=TOP>
|
||||||
|
<TD><P>cardXDiscarded</P></TD>
|
||||||
|
<TD><P>boolean</P></TD>
|
||||||
|
<TD><P>Whether the card was discarded (this only applies to draw games, X can be 1 through 15 since the final cards can obviously not be discarded).</P></TD>
|
||||||
|
</TR>
|
||||||
|
<TR VALIGN=TOP>
|
||||||
|
<TD><P>DrawnX</P></TD>
|
||||||
|
<TD><P>smallint</P></TD>
|
||||||
|
<TD><p>X can be 1 through 3.<br>
|
||||||
|
This field denotes how many cards the player has drawn on each draw.</P></TD>
|
||||||
|
</TR>
|
||||||
<TR VALIGN=TOP>
|
<TR VALIGN=TOP>
|
||||||
<TD><P>winnings</P></TD>
|
<TD><P>winnings</P></TD>
|
||||||
<TD><P>int</P></TD>
|
<TD><P>int</P></TD>
|
||||||
|
|
|
@ -444,9 +444,9 @@ class Config:
|
||||||
def get_import_parameters(self):
|
def get_import_parameters(self):
|
||||||
imp = {}
|
imp = {}
|
||||||
try:
|
try:
|
||||||
imp['callFpdbHud'] = self.callFpdbHud
|
imp['callFpdbHud'] = self.imp.callFpdbHud
|
||||||
imp['interval'] = self.interval
|
imp['interval'] = self.imp.interval
|
||||||
imp['hhArchiveBase'] = self.hhArchiveBase
|
imp['hhArchiveBase'] = self.imp.hhArchiveBase
|
||||||
except: # Default params
|
except: # Default params
|
||||||
imp['callFpdbHud'] = True
|
imp['callFpdbHud'] = True
|
||||||
imp['interval'] = 10
|
imp['interval'] = 10
|
||||||
|
@ -613,9 +613,7 @@ if __name__== "__main__":
|
||||||
print "----------- END POPUP WINDOW FORMATS -----------"
|
print "----------- END POPUP WINDOW FORMATS -----------"
|
||||||
|
|
||||||
print "\n----------- IMPORT -----------"
|
print "\n----------- IMPORT -----------"
|
||||||
tmp = c.get_import_parameters()
|
print c.imp
|
||||||
for param in tmp:
|
|
||||||
print " " + str(param) + ": " + str(tmp[param])
|
|
||||||
print "----------- END IMPORT -----------"
|
print "----------- END IMPORT -----------"
|
||||||
|
|
||||||
print "\n----------- TABLE VIEW -----------"
|
print "\n----------- TABLE VIEW -----------"
|
||||||
|
|
187
pyfpdb/EverleafToFpdb.py
Normal file → Executable file
187
pyfpdb/EverleafToFpdb.py
Normal file → Executable file
|
@ -58,42 +58,46 @@ from HandHistoryConverter import *
|
||||||
# smaragdar calls [$ 34.50 USD]
|
# smaragdar calls [$ 34.50 USD]
|
||||||
# ** Dealing Turn ** [ 2d ]
|
# ** Dealing Turn ** [ 2d ]
|
||||||
# ** Dealing River ** [ 6c ]
|
# ** Dealing River ** [ 6c ]
|
||||||
|
# dogge shows [ 9h, 9c ]a pair of nines
|
||||||
|
# spicybum shows [ 5d, 6d ]a straight, eight high
|
||||||
|
# harrydebeng does not show cards
|
||||||
# smaragdar wins $ 102 USD from main pot with a pair of aces [ ad, ah, qs, 8h, 6c ]
|
# smaragdar wins $ 102 USD from main pot with a pair of aces [ ad, ah, qs, 8h, 6c ]
|
||||||
|
|
||||||
|
|
||||||
class Everleaf(HandHistoryConverter):
|
class Everleaf(HandHistoryConverter):
|
||||||
def __init__(self, config, file):
|
def __init__(self, config, file):
|
||||||
print "Initialising Everleaf converter class"
|
print "Initialising Everleaf converter class"
|
||||||
HandHistoryConverter.__init__(self, config, file, "Everleaf") # Call super class init.
|
HandHistoryConverter.__init__(self, config, file, sitename="Everleaf") # Call super class init.
|
||||||
self.sitename = "Everleaf"
|
self.sitename = "Everleaf"
|
||||||
self.setFileType("text")
|
self.setFileType("text")
|
||||||
self.rexx.setGameInfoRegex('.*Blinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)')
|
self.rexx.setGameInfoRegex('.*Blinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)')
|
||||||
self.rexx.setSplitHandRegex('\n\n\n\n')
|
self.rexx.setSplitHandRegex('\n\n\n\n')
|
||||||
self.rexx.setHandInfoRegex('.*#(?P<HID>[0-9]+)\n.*\nBlinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<YEAR>[0-9]+)/(?P<MON>[0-9]+)/(?P<DAY>[0-9]+) - (?P<HR>[0-9]+):(?P<MIN>[0-9]+):(?P<SEC>[0-9]+)\nTable (?P<TABLE>[ a-zA-Z]+)\nSeat (?P<BUTTON>[0-9]+)')
|
self.rexx.setHandInfoRegex('.*#(?P<HID>[0-9]+)\n.*\nBlinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<YEAR>[0-9]+)/(?P<MON>[0-9]+)/(?P<DAY>[0-9]+) - (?P<HR>[0-9]+):(?P<MIN>[0-9]+):(?P<SEC>[0-9]+)\nTable (?P<TABLE>[ a-zA-Z]+)\nSeat (?P<BUTTON>[0-9]+)')
|
||||||
self.rexx.setPlayerInfoRegex('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \( \$ (?P<CASH>[.0-9]+) USD \)')
|
self.rexx.setPlayerInfoRegex('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \( \$ (?P<CASH>[.0-9]+) USD \)')
|
||||||
self.rexx.setPostSbRegex('.*\n(?P<PNAME>.*): posts small blind \[')
|
self.rexx.setPostSbRegex('.*\n(?P<PNAME>.*): posts small blind \[\$? (?P<SB>[.0-9]+)')
|
||||||
self.rexx.setPostBbRegex('.*\n(?P<PNAME>.*): posts big blind \[')
|
self.rexx.setPostBbRegex('.*\n(?P<PNAME>.*): posts big blind \[\$? (?P<BB>[.0-9]+)')
|
||||||
self.rexx.setHeroCardsRegex('.*\nDealt\sto\s(?P<PNAME>.*)\s\[ (?P<HOLECARDS>.*) \]')
|
# mct : what about posting small & big blinds simultaneously?
|
||||||
self.rexx.setActionStepRegex('.*\n(?P<PNAME>.*) (?P<ATYPE>bets|checks|raises|calls|folds)(\s\[\$ (?P<BET>[.\d]+) USD\])?')
|
self.rexx.setHeroCardsRegex('.*\nDealt\sto\s(?P<PNAME>.*)\s\[ (?P<HOLE1>\S\S), (?P<HOLE2>\S\S) \]')
|
||||||
self.rexx.compileRegexes()
|
self.rexx.setActionStepRegex('.*\n(?P<PNAME>.*) (?P<ATYPE>bets|checks|raises|calls|folds)(\s\[\$ (?P<BET>[.\d]+) USD\])?')
|
||||||
|
self.rexx.setShowdownActionRegex('.*\n(?P<PNAME>.*) shows \[ (?P<CARDS>.*) \]')
|
||||||
|
self.rexx.compileRegexes()
|
||||||
|
|
||||||
def readSupportedGames(self):
|
def readSupportedGames(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def determineGameType(self):
|
def determineGameType(self):
|
||||||
# Cheating with this regex, only support nlhe at the moment
|
# Cheating with this regex, only support nlhe at the moment
|
||||||
gametype = ["ring", "hold", "nl"]
|
gametype = ["ring", "hold", "nl"]
|
||||||
|
|
||||||
m = self.rexx.game_info_re.search(self.obs)
|
m = self.rexx.game_info_re.search(self.obs)
|
||||||
gametype = gametype + [m.group('SB')]
|
gametype = gametype + [m.group('SB')]
|
||||||
gametype = gametype + [m.group('BB')]
|
gametype = gametype + [m.group('BB')]
|
||||||
|
|
||||||
return gametype
|
return gametype
|
||||||
|
|
||||||
def readHandInfo(self, hand):
|
def readHandInfo(self, hand):
|
||||||
m = self.rexx.hand_info_re.search(hand.string)
|
m = self.rexx.hand_info_re.search(hand.string)
|
||||||
hand.handid = m.group('HID')
|
hand.handid = m.group('HID')
|
||||||
hand.tablename = m.group('TABLE')
|
hand.tablename = m.group('TABLE')
|
||||||
# These work, but the info is already in the Hand class - should be used for tourneys though.
|
# These work, but the info is already in the Hand class - should be used for tourneys though.
|
||||||
# m.group('SB')
|
# m.group('SB')
|
||||||
# m.group('BB')
|
# m.group('BB')
|
||||||
|
@ -106,66 +110,87 @@ class Everleaf(HandHistoryConverter):
|
||||||
# 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 = "%d/%02d/%02d %d:%02d:%02d ET" %(int(m.group('YEAR')), int(m.group('MON')), int(m.group('DAY')),
|
hand.starttime = "%d/%02d/%02d %d:%02d:%02d ET" %(int(m.group('YEAR')), int(m.group('MON')), int(m.group('DAY')),
|
||||||
int(m.group('HR')), int(m.group('MIN')), int(m.group('SEC')))
|
int(m.group('HR')), int(m.group('MIN')), int(m.group('SEC')))
|
||||||
hand.buttonpos = int(m.group('BUTTON'))
|
hand.buttonpos = int(m.group('BUTTON'))
|
||||||
|
|
||||||
def readPlayerStacks(self, hand):
|
def readPlayerStacks(self, hand):
|
||||||
m = self.rexx.player_info_re.finditer(hand.string)
|
m = self.rexx.player_info_re.finditer(hand.string)
|
||||||
players = []
|
players = []
|
||||||
|
|
||||||
for a in m:
|
for a in m:
|
||||||
players = players + [[a.group('SEAT'), a.group('PNAME'), a.group('CASH')]]
|
hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH'))
|
||||||
|
|
||||||
hand.players = players
|
def markStreets(self, hand):
|
||||||
|
# PREFLOP = ** Dealing down cards **
|
||||||
def markStreets(self, hand):
|
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)
|
||||||
# PREFLOP = ** Dealing down cards **
|
|
||||||
m = re.search('(\*\* Dealing down cards \*\*\n)(?P<PREFLOP>.*?\n\*\*)?( Dealing Flop \*\*)?(?P<FLOP>.*?\*\*)?( Dealing Turn \*\*)?(?P<TURN>.*?\*\*)?( Dealing River \*\*)?(?P<RIVER>.*)', hand.string,re.DOTALL)
|
|
||||||
# for street in m.groupdict():
|
# for street in m.groupdict():
|
||||||
# print "DEBUG: Street: %s\tspan: %s" %(street, str(m.span(street)))
|
# print "DEBUG: Street: %s\tspan: %s" %(street, str(m.span(street)))
|
||||||
hand.streets = m
|
hand.streets = m
|
||||||
|
|
||||||
def readBlinds(self, hand):
|
def readCommunityCards(self, hand):
|
||||||
try:
|
# currently regex in wrong place pls fix my brain's fried
|
||||||
m = self.rexx.small_blind_re.search(hand.string)
|
# what a mess!
|
||||||
hand.posted = [m.group('PNAME')]
|
re_board = re.compile('\*\* Dealing (?P<STREET>.*) \*\* \[ (?P<CARDS>.*) \]')
|
||||||
except:
|
m = re_board.finditer(hand.string)
|
||||||
hand.posted = ["FpdbNBP"]
|
for street in m:
|
||||||
m = self.rexx.big_blind_re.finditer(hand.string)
|
#print street.groups()
|
||||||
for a in m:
|
re_card = re.compile('(?P<CARD>[0-9tjqka][schd])') # look that's weird, hole cards have a capital rank but board cards are lower case?
|
||||||
hand.posted = hand.posted + [a.group('PNAME')]
|
cardsmatch = re_card.finditer(street.group('CARDS'))
|
||||||
|
hand.setCommunityCards(street.group('STREET'), [card.group('CARD') for card in cardsmatch])
|
||||||
|
|
||||||
def readHeroCards(self, hand):
|
def readBlinds(self, hand):
|
||||||
m = self.rexx.hero_cards_re.search(hand.string)
|
try:
|
||||||
if(m == None):
|
m = self.rexx.small_blind_re.search(hand.string)
|
||||||
#Not involved in hand
|
hand.addBlind(m.group('PNAME'), m.group('SB'))
|
||||||
hand.involved = False
|
#hand.posted = [m.group('PNAME')]
|
||||||
else:
|
except:
|
||||||
hand.hero = m.group('PNAME')
|
hand.addBlind(None, 0)
|
||||||
hand.holecards = m.group('HOLECARDS')
|
#hand.posted = ["FpdbNBP"]
|
||||||
hand.holecards = hand.holecards.replace(',','')
|
m = self.rexx.big_blind_re.finditer(hand.string)
|
||||||
#Must be a better way to do the following tr akqjt AKQJT
|
for a in m:
|
||||||
hand.holecards = hand.holecards.replace('a','A')
|
hand.addBlind(a.group('PNAME'), a.group('BB'))
|
||||||
hand.holecards = hand.holecards.replace('k','K')
|
#hand.posted = hand.posted + [a.group('PNAME')]
|
||||||
hand.holecards = hand.holecards.replace('q','Q')
|
|
||||||
hand.holecards = hand.holecards.replace('j','J')
|
|
||||||
hand.holecards = hand.holecards.replace('t','T')
|
|
||||||
|
|
||||||
def readAction(self, hand, street):
|
def readHeroCards(self, hand):
|
||||||
m = self.rexx.action_re.finditer(hand.streets.group(street))
|
m = self.rexx.hero_cards_re.search(hand.string)
|
||||||
hand.actions[street] = []
|
if(m == None):
|
||||||
for action in m:
|
#Not involved in hand
|
||||||
if action.group('ATYPE') == 'raises' or action.group('ATYPE') == 'calls':
|
hand.involved = False
|
||||||
hand.actions[street] += [[action.group('PNAME'), action.group('ATYPE'), action.group('BET')]]
|
else:
|
||||||
else:
|
hand.hero = m.group('PNAME')
|
||||||
hand.actions[street] += [[action.group('PNAME'), action.group('ATYPE')]]
|
hand.addHoleCards([m.group('HOLE1'), m.group('HOLE2')], m.group('PNAME'))
|
||||||
print "DEBUG: readAction: %s " %(hand.actions)
|
|
||||||
|
|
||||||
|
def readAction(self, hand, street):
|
||||||
|
m = self.rexx.action_re.finditer(hand.streets.group(street))
|
||||||
|
hand.actions[street] = []
|
||||||
|
for action in m:
|
||||||
|
if action.group('ATYPE') == 'raises':
|
||||||
|
hand.addRaiseTo( street, action.group('PNAME'), action.group('BET') )
|
||||||
|
elif action.group('ATYPE') == 'calls':
|
||||||
|
hand.addCall( street, action.group('PNAME'), action.group('BET') )
|
||||||
|
elif action.group('ATYPE') == 'bets':
|
||||||
|
hand.addBet( street, action.group('PNAME'), action.group('BET') )
|
||||||
|
else:
|
||||||
|
#print "DEBUG: unimplemented readAction: %s %s" %(action.group('PNAME'),action.group('ATYPE'),)
|
||||||
|
hand.actions[street] += [[action.group('PNAME'), action.group('ATYPE')]]
|
||||||
|
|
||||||
|
|
||||||
|
def readShowdownActions(self, hand):
|
||||||
|
for shows in self.rexx.showdown_action_re.finditer(hand.string):
|
||||||
|
print shows.groups()
|
||||||
|
re_card = re.compile('(?P<CARD>[0-9tjqka][schd])') # copied from earlier
|
||||||
|
cards = [card.group('CARD') for card in re_card.finditer(shows.group('CARDS'))]
|
||||||
|
print cards
|
||||||
|
hand.addHoleCards(cards, shows.group('PNAME'))
|
||||||
|
|
||||||
|
|
||||||
|
def getRake(self, hand):
|
||||||
|
hand.rake = hand.totalpot * Decimal('0.05') # probably not quite right
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
c = Configuration.Config()
|
c = Configuration.Config()
|
||||||
e = Everleaf(c, "regression-test-files/everleaf/Speed_Kuala.txt")
|
e = Everleaf(c, "Speed_Kuala.txt")
|
||||||
e.processFile()
|
e.processFile()
|
||||||
print str(e)
|
print str(e)
|
||||||
|
|
||||||
|
|
|
@ -573,6 +573,27 @@ class FpdbSQLQueries:
|
||||||
elif(self.dbname == 'SQLite'):
|
elif(self.dbname == 'SQLite'):
|
||||||
self.query['createHudCacheTable'] = """ """
|
self.query['createHudCacheTable'] = """ """
|
||||||
|
|
||||||
|
if(self.dbname == 'MySQL InnoDB'):
|
||||||
|
self.query['addTourneyIndex'] = """ALTER TABLE Tourneys ADD INDEX siteTourneyNo(siteTourneyNo)"""
|
||||||
|
elif(self.dbname == 'PostgreSQL'):
|
||||||
|
self.query['addTourneyIndex'] = """CREATE INDEX siteTourneyNo ON Tourneys (siteTourneyNo)"""
|
||||||
|
elif(self.dbname == 'SQLite'):
|
||||||
|
self.query['addHandsIndex'] = """ """
|
||||||
|
|
||||||
|
if(self.dbname == 'MySQL InnoDB'):
|
||||||
|
self.query['addHandsIndex'] = """ALTER TABLE Hands ADD INDEX siteHandNo(siteHandNo)"""
|
||||||
|
elif(self.dbname == 'PostgreSQL'):
|
||||||
|
self.query['addHandsIndex'] = """CREATE INDEX siteHandNo ON Hands (siteHandNo)"""
|
||||||
|
elif(self.dbname == 'SQLite'):
|
||||||
|
self.query['addHandsIndex'] = """ """
|
||||||
|
|
||||||
|
if(self.dbname == 'MySQL InnoDB'):
|
||||||
|
self.query['addPlayersIndex'] = """ALTER TABLE Players ADD INDEX name(name)"""
|
||||||
|
elif(self.dbname == 'PostgreSQL'):
|
||||||
|
self.query['addPlayersIndex'] = """CREATE INDEX name ON Players (name)"""
|
||||||
|
elif(self.dbname == 'SQLite'):
|
||||||
|
self.query['addPlayersIndex'] = """ """
|
||||||
|
|
||||||
################################
|
################################
|
||||||
# Queries used in GuiGraphViewer
|
# Queries used in GuiGraphViewer
|
||||||
################################
|
################################
|
||||||
|
@ -609,6 +630,11 @@ class FpdbSQLQueries:
|
||||||
WHERE Players.name = %s AND HandsPlayers.handId = %s
|
WHERE Players.name = %s AND HandsPlayers.handId = %s
|
||||||
AND Players.siteId = %s AND (tourneysPlayersId IS NULL)"""
|
AND Players.siteId = %s AND (tourneysPlayersId IS NULL)"""
|
||||||
|
|
||||||
|
if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'):
|
||||||
|
self.query['getPlayerId'] = """SELECT id from Players where name = %s"""
|
||||||
|
elif(self.dbname == 'SQLite'):
|
||||||
|
self.query['getPlayerId'] = """SELECT id from Players where name = %s"""
|
||||||
|
|
||||||
if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'):
|
if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'):
|
||||||
self.query['getRingProfitAllHandsPlayerIdSite'] = """
|
self.query['getRingProfitAllHandsPlayerIdSite'] = """
|
||||||
SELECT hp.handId, hp.winnings, SUM(ha.amount), hp.winnings - SUM(ha.amount)
|
SELECT hp.handId, hp.winnings, SUM(ha.amount), hp.winnings - SUM(ha.amount)
|
||||||
|
@ -673,13 +699,11 @@ class FpdbSQLQueries:
|
||||||
,round(100*sum(street2Aggr)/sum(street2Seen)) AS TuAFq
|
,round(100*sum(street2Aggr)/sum(street2Seen)) AS TuAFq
|
||||||
,round(100*sum(street3Aggr)/sum(street3Seen)) AS RvAFq
|
,round(100*sum(street3Aggr)/sum(street3Seen)) AS RvAFq
|
||||||
,round(100*(sum(street1Aggr)+sum(street2Aggr)+sum(street3Aggr))
|
,round(100*(sum(street1Aggr)+sum(street2Aggr)+sum(street3Aggr))
|
||||||
|
|
||||||
/(sum(street1Seen)+sum(street2Seen)+sum(street3Seen))) AS PFAFq
|
/(sum(street1Seen)+sum(street2Seen)+sum(street3Seen))) AS PFAFq
|
||||||
from Gametypes gt
|
from Gametypes gt
|
||||||
inner join Sites s on s.Id = gt.siteId
|
inner join Sites s on s.Id = gt.siteId
|
||||||
inner join HudCache hc on hc.gameTypeId = gt.Id
|
inner join HudCache hc on hc.gameTypeId = gt.Id
|
||||||
where gt.limittype = 'nl'
|
where hc.playerId in <player_test>
|
||||||
and hc.playerId in (3) # use <player_test> here?
|
|
||||||
# use <gametype_test> here ?
|
# use <gametype_test> here ?
|
||||||
group by hc.gametypeId
|
group by hc.gametypeId
|
||||||
) stats
|
) stats
|
||||||
|
@ -692,7 +716,7 @@ class FpdbSQLQueries:
|
||||||
from HandsPlayers hp
|
from HandsPlayers hp
|
||||||
inner join Hands h ON h.id = hp.handId
|
inner join Hands h ON h.id = hp.handId
|
||||||
inner join HandsActions ha ON ha.handPlayerId = hp.id
|
inner join HandsActions ha ON ha.handPlayerId = hp.id
|
||||||
where hp.playerId in (3) # use <player_test> here?
|
where hp.playerId in <player_test>
|
||||||
# use <gametype_test> here ?
|
# use <gametype_test> here ?
|
||||||
and hp.tourneysPlayersId IS NULL
|
and hp.tourneysPlayersId IS NULL
|
||||||
group by hp.handId, h.gameTypeId, hp.position, hp.winnings
|
group by hp.handId, h.gameTypeId, hp.position, hp.winnings
|
||||||
|
|
|
@ -24,289 +24,300 @@ from time import time
|
||||||
#import pokereval
|
#import pokereval
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import matplotlib
|
import matplotlib
|
||||||
matplotlib.use('GTK')
|
matplotlib.use('GTK')
|
||||||
from matplotlib.figure import Figure
|
from matplotlib.figure import Figure
|
||||||
from matplotlib.backends.backend_gtk import FigureCanvasGTK as FigureCanvas
|
from matplotlib.backends.backend_gtk import FigureCanvasGTK as FigureCanvas
|
||||||
from matplotlib.backends.backend_gtkagg import NavigationToolbar2GTKAgg as NavigationToolbar
|
from matplotlib.backends.backend_gtkagg import NavigationToolbar2GTKAgg as NavigationToolbar
|
||||||
from numpy import arange, cumsum
|
from numpy import arange, cumsum
|
||||||
from pylab import *
|
from pylab import *
|
||||||
except:
|
except:
|
||||||
print """Failed to load libs for graphing, graphing will not function. Please in
|
print """Failed to load libs for graphing, graphing will not function. Please in
|
||||||
stall numpy and matplotlib if you want to use graphs."""
|
stall numpy and matplotlib if you want to use graphs."""
|
||||||
print """This is of no consequence for other parts of the program, e.g. import
|
print """This is of no consequence for other parts of the program, e.g. import
|
||||||
and HUD are NOT affected by this problem."""
|
and HUD are NOT affected by this problem."""
|
||||||
|
|
||||||
import fpdb_import
|
import fpdb_import
|
||||||
import fpdb_db
|
import fpdb_db
|
||||||
|
|
||||||
class GuiGraphViewer (threading.Thread):
|
class GuiGraphViewer (threading.Thread):
|
||||||
def get_vbox(self):
|
def get_vbox(self):
|
||||||
"""returns the vbox of this thread"""
|
"""returns the vbox of this thread"""
|
||||||
return self.mainHBox
|
return self.mainHBox
|
||||||
#end def get_vbox
|
#end def get_vbox
|
||||||
|
|
||||||
def generateGraph(self, widget, data):
|
|
||||||
try: self.canvas.destroy()
|
|
||||||
except AttributeError: pass
|
|
||||||
|
|
||||||
# Whaich sites are selected?
|
def generateGraph(self, widget, data):
|
||||||
# TODO:
|
try: self.canvas.destroy()
|
||||||
# What hero names for the selected site?
|
except AttributeError: pass
|
||||||
# TODO:
|
|
||||||
|
|
||||||
name = self.heroes[self.sites]
|
# Whaich sites are selected?
|
||||||
|
# TODO:
|
||||||
if self.sites == "PokerStars":
|
# What hero names for the selected site?
|
||||||
site=2
|
# TODO:
|
||||||
sitename="PokerStars: "
|
|
||||||
elif self.sites=="Full Tilt":
|
|
||||||
site=1
|
|
||||||
sitename="Full Tilt: "
|
|
||||||
else:
|
|
||||||
print "invalid text in site selection in graph, defaulting to PS"
|
|
||||||
site=2
|
|
||||||
|
|
||||||
self.fig = Figure(figsize=(5,4), dpi=100)
|
|
||||||
|
|
||||||
#Set graph properties
|
name = self.heroes[self.sites]
|
||||||
self.ax = self.fig.add_subplot(111)
|
|
||||||
|
|
||||||
#Get graph data from DB
|
if self.sites == "PokerStars":
|
||||||
starttime = time()
|
site=2
|
||||||
line = self.getRingProfitGraph(name, site)
|
sitename="PokerStars: "
|
||||||
print "Graph generated in: %s" %(time() - starttime)
|
elif self.sites=="Full Tilt":
|
||||||
|
site=1
|
||||||
|
sitename="Full Tilt: "
|
||||||
|
else:
|
||||||
|
print "invalid text in site selection in graph, defaulting to PS"
|
||||||
|
site=2
|
||||||
|
|
||||||
self.ax.set_title("Profit graph for ring games")
|
self.fig = Figure(figsize=(5,4), dpi=100)
|
||||||
|
|
||||||
#Set axis labels and grid overlay properites
|
#Set graph properties
|
||||||
self.ax.set_xlabel("Hands", fontsize = 12)
|
self.ax = self.fig.add_subplot(111)
|
||||||
self.ax.set_ylabel("$", fontsize = 12)
|
|
||||||
self.ax.grid(color='g', linestyle=':', linewidth=0.2)
|
|
||||||
text = "All Hands, " + sitename + str(name) + "\nProfit: $" + str(line[-1]) + "\nTotal Hands: " + str(len(line))
|
|
||||||
|
|
||||||
self.ax.annotate(text, xy=(10, -10),
|
#Get graph data from DB
|
||||||
xycoords='axes points',
|
starttime = time()
|
||||||
horizontalalignment='left', verticalalignment='top',
|
line = self.getRingProfitGraph(name, site)
|
||||||
fontsize=10)
|
print "Graph generated in: %s" %(time() - starttime)
|
||||||
|
|
||||||
|
self.ax.set_title("Profit graph for ring games")
|
||||||
|
|
||||||
|
#Set axis labels and grid overlay properites
|
||||||
|
self.ax.set_xlabel("Hands", fontsize = 12)
|
||||||
|
self.ax.set_ylabel("$", fontsize = 12)
|
||||||
|
self.ax.grid(color='g', linestyle=':', linewidth=0.2)
|
||||||
|
#This line will crash if no hands exist in the query.
|
||||||
|
text = "All Hands, " + sitename + str(name) + "\nProfit: $" + str(line[-1]) + "\nTotal Hands: " + str(len(line))
|
||||||
|
|
||||||
|
self.ax.annotate(text,
|
||||||
|
xy=(10, -10),
|
||||||
|
xycoords='axes points',
|
||||||
|
horizontalalignment='left', verticalalignment='top',
|
||||||
|
fontsize=10)
|
||||||
|
|
||||||
|
|
||||||
#Draw plot
|
#Draw plot
|
||||||
self.ax.plot(line,)
|
self.ax.plot(line,)
|
||||||
|
|
||||||
self.canvas = FigureCanvas(self.fig) # a gtk.DrawingArea
|
self.canvas = FigureCanvas(self.fig) # a gtk.DrawingArea
|
||||||
self.graphBox.add(self.canvas)
|
self.graphBox.add(self.canvas)
|
||||||
self.canvas.show()
|
self.canvas.show()
|
||||||
#end of def showClicked
|
#end of def showClicked
|
||||||
|
|
||||||
def getRingProfitGraph(self, name, site):
|
def getRingProfitGraph(self, name, site):
|
||||||
self.cursor.execute(self.sql.query['getRingProfitAllHandsPlayerIdSite'], (name, site))
|
self.cursor.execute(self.sql.query['getRingProfitAllHandsPlayerIdSite'], (name, site))
|
||||||
# returns (HandId,Winnings,Costs,Profit)
|
#returns (HandId,Winnings,Costs,Profit)
|
||||||
winnings = self.db.cursor.fetchall()
|
winnings = self.db.cursor.fetchall()
|
||||||
|
|
||||||
y=map(lambda x:float(x[3]), winnings)
|
y=map(lambda x:float(x[3]), winnings)
|
||||||
line = cumsum(y)
|
line = cumsum(y)
|
||||||
return line/100
|
return line/100
|
||||||
#end of def getRingProfitGraph
|
#end of def getRingProfitGraph
|
||||||
|
|
||||||
def createPlayerLine(self, hbox, site, player):
|
def createPlayerLine(self, hbox, site, player):
|
||||||
label = gtk.Label(site +" id:")
|
label = gtk.Label(site +" id:")
|
||||||
hbox.pack_start(label, False, False, 0)
|
hbox.pack_start(label, False, False, 0)
|
||||||
label.show()
|
label.show()
|
||||||
|
|
||||||
pname = gtk.Entry()
|
pname = gtk.Entry()
|
||||||
pname.set_text(player)
|
pname.set_text(player)
|
||||||
pname.set_width_chars(20)
|
pname.set_width_chars(20)
|
||||||
hbox.pack_start(pname, False, True, 0)
|
hbox.pack_start(pname, False, True, 0)
|
||||||
#TODO: Need to connect a callback here
|
#TODO: Need to connect a callback here
|
||||||
pname.connect("changed", self.__set_hero_name, site)
|
pname.connect("changed", self.__set_hero_name, site)
|
||||||
#TODO: Look at GtkCompletion - to fill out usernames
|
#TODO: Look at GtkCompletion - to fill out usernames
|
||||||
pname.show()
|
pname.show()
|
||||||
|
|
||||||
self.__set_hero_name(pname, site)
|
self.__set_hero_name(pname, site)
|
||||||
|
|
||||||
def __set_hero_name(self, w, site):
|
def __set_hero_name(self, w, site):
|
||||||
self.heroes[site] = w.get_text()
|
self.heroes[site] = w.get_text()
|
||||||
print "DEBUG: settings heroes[%s]: %s"%(site, self.heroes[site])
|
print "DEBUG: settings heroes[%s]: %s"%(site, self.heroes[site])
|
||||||
|
|
||||||
def createSiteLine(self, hbox, site):
|
def createSiteLine(self, hbox, site):
|
||||||
cb = gtk.CheckButton(site)
|
cb = gtk.CheckButton(site)
|
||||||
cb.connect('clicked', self.__set_site_select, site)
|
cb.connect('clicked', self.__set_site_select, site)
|
||||||
hbox.pack_start(cb, False, False, 0)
|
hbox.pack_start(cb, False, False, 0)
|
||||||
cb.show()
|
cb.show()
|
||||||
|
|
||||||
def __set_site_select(self, w, site):
|
def __set_site_select(self, w, site):
|
||||||
# This doesn't behave as intended - self.site only allows 1 site for the moment.
|
# This doesn't behave as intended - self.site only allows 1 site for the moment.
|
||||||
self.sites = site
|
self.sites = site
|
||||||
print "self.sites set to %s" %(self.sites)
|
print "self.sites set to %s" %(self.sites)
|
||||||
|
|
||||||
def fillPlayerFrame(self, vbox):
|
def fillPlayerFrame(self, vbox):
|
||||||
for site in self.conf.supported_sites.keys():
|
for site in self.conf.supported_sites.keys():
|
||||||
pathHBox = gtk.HBox(False, 0)
|
pathHBox = gtk.HBox(False, 0)
|
||||||
vbox.pack_start(pathHBox, False, True, 0)
|
vbox.pack_start(pathHBox, False, True, 0)
|
||||||
pathHBox.show()
|
pathHBox.show()
|
||||||
|
|
||||||
player = self.conf.supported_sites[site].screen_name
|
player = self.conf.supported_sites[site].screen_name
|
||||||
self.createPlayerLine(pathHBox, site, player)
|
self.createPlayerLine(pathHBox, site, player)
|
||||||
|
|
||||||
def fillSitesFrame(self, vbox):
|
def fillSitesFrame(self, vbox):
|
||||||
for site in self.conf.supported_sites.keys():
|
for site in self.conf.supported_sites.keys():
|
||||||
hbox = gtk.HBox(False, 0)
|
hbox = gtk.HBox(False, 0)
|
||||||
vbox.pack_start(hbox, False, True, 0)
|
vbox.pack_start(hbox, False, True, 0)
|
||||||
hbox.show()
|
hbox.show()
|
||||||
self.createSiteLine(hbox, site)
|
self.createSiteLine(hbox, site)
|
||||||
|
|
||||||
def fillDateFrame(self, vbox):
|
def fillDateFrame(self, vbox):
|
||||||
# Hat tip to Mika Bostrom - calendar code comes from PokerStats
|
# Hat tip to Mika Bostrom - calendar code comes from PokerStats
|
||||||
hbox = gtk.HBox()
|
hbox = gtk.HBox()
|
||||||
vbox.pack_start(hbox, False, True, 0)
|
vbox.pack_start(hbox, False, True, 0)
|
||||||
hbox.show()
|
hbox.show()
|
||||||
|
|
||||||
lbl_start = gtk.Label('From:')
|
lbl_start = gtk.Label('From:')
|
||||||
lbl_start.show()
|
lbl_start.show()
|
||||||
|
|
||||||
btn_start = gtk.Button()
|
btn_start = gtk.Button()
|
||||||
btn_start.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON))
|
btn_start.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON))
|
||||||
btn_start.connect('clicked', self.__calendar_dialog, self.start_date)
|
btn_start.connect('clicked', self.__calendar_dialog, self.start_date)
|
||||||
btn_start.show()
|
btn_start.show()
|
||||||
|
|
||||||
hbox.pack_start(lbl_start, expand=False, padding=3)
|
hbox.pack_start(lbl_start, expand=False, padding=3)
|
||||||
hbox.pack_start(btn_start, expand=False, padding=3)
|
hbox.pack_start(btn_start, expand=False, padding=3)
|
||||||
hbox.pack_start(self.start_date, expand=False, padding=2)
|
hbox.pack_start(self.start_date, expand=False, padding=2)
|
||||||
self.start_date.show()
|
self.start_date.show()
|
||||||
|
|
||||||
#New row for end date
|
#New row for end date
|
||||||
hbox = gtk.HBox()
|
hbox = gtk.HBox()
|
||||||
vbox.pack_start(hbox, False, True, 0)
|
vbox.pack_start(hbox, False, True, 0)
|
||||||
hbox.show()
|
hbox.show()
|
||||||
|
|
||||||
lbl_end = gtk.Label(' To:')
|
lbl_end = gtk.Label(' To:')
|
||||||
lbl_end.show()
|
lbl_end.show()
|
||||||
btn_end = gtk.Button()
|
btn_end = gtk.Button()
|
||||||
btn_end.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON))
|
btn_end.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON))
|
||||||
btn_end.connect('clicked', self.__calendar_dialog, self.end_date)
|
btn_end.connect('clicked', self.__calendar_dialog, self.end_date)
|
||||||
btn_end.show()
|
btn_end.show()
|
||||||
|
|
||||||
btn_clear = gtk.Button(label=' Clear Dates ')
|
btn_clear = gtk.Button(label=' Clear Dates ')
|
||||||
btn_clear.connect('clicked', self.__clear_dates)
|
btn_clear.connect('clicked', self.__clear_dates)
|
||||||
btn_clear.show()
|
btn_clear.show()
|
||||||
|
|
||||||
hbox.pack_start(lbl_end, expand=False, padding=3)
|
hbox.pack_start(lbl_end, expand=False, padding=3)
|
||||||
hbox.pack_start(btn_end, expand=False, padding=3)
|
hbox.pack_start(btn_end, expand=False, padding=3)
|
||||||
hbox.pack_start(self.end_date, expand=False, padding=2)
|
hbox.pack_start(self.end_date, expand=False, padding=2)
|
||||||
self.end_date.show()
|
self.end_date.show()
|
||||||
|
|
||||||
hbox.pack_start(btn_clear, expand=False, padding=15)
|
hbox.pack_start(btn_clear, expand=False, padding=15)
|
||||||
|
|
||||||
def __calendar_dialog(self, widget, entry):
|
def __calendar_dialog(self, widget, entry):
|
||||||
d = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
d = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
||||||
d.set_title('Pick a date')
|
d.set_title('Pick a date')
|
||||||
|
|
||||||
vb = gtk.VBox()
|
vb = gtk.VBox()
|
||||||
cal = gtk.Calendar()
|
cal = gtk.Calendar()
|
||||||
vb.pack_start(cal, expand=False, padding=0)
|
vb.pack_start(cal, expand=False, padding=0)
|
||||||
|
|
||||||
btn = gtk.Button('Done')
|
btn = gtk.Button('Done')
|
||||||
btn.connect('clicked', self.__get_date, cal, entry, d)
|
btn.connect('clicked', self.__get_date, cal, entry, d)
|
||||||
|
|
||||||
vb.pack_start(btn, expand=False, padding=4)
|
vb.pack_start(btn, expand=False, padding=4)
|
||||||
|
|
||||||
d.add(vb)
|
d.add(vb)
|
||||||
d.set_position(gtk.WIN_POS_MOUSE)
|
d.set_position(gtk.WIN_POS_MOUSE)
|
||||||
d.show_all()
|
d.show_all()
|
||||||
|
|
||||||
def __clear_dates(self, w):
|
def __clear_dates(self, w):
|
||||||
self.start_date.set_text('')
|
self.start_date.set_text('')
|
||||||
self.end_date.set_text('')
|
self.end_date.set_text('')
|
||||||
|
|
||||||
def __get_dates(self):
|
def __get_dates(self):
|
||||||
t1 = self.start_date.get_text()
|
t1 = self.start_date.get_text()
|
||||||
t2 = self.end_date.get_text()
|
t2 = self.end_date.get_text()
|
||||||
return (t1, t2)
|
return (t1, t2)
|
||||||
|
|
||||||
def __get_date(self, widget, calendar, entry, win):
|
def __get_date(self, widget, calendar, entry, win):
|
||||||
# year and day are correct, month is 0..11
|
# year and day are correct, month is 0..11
|
||||||
(year, month, day) = calendar.get_date()
|
(year, month, day) = calendar.get_date()
|
||||||
month += 1
|
month += 1
|
||||||
ds = '%04d-%02d-%02d' % (year, month, day)
|
ds = '%04d-%02d-%02d' % (year, month, day)
|
||||||
entry.set_text(ds)
|
entry.set_text(ds)
|
||||||
win.destroy()
|
win.destroy()
|
||||||
|
|
||||||
def __init__(self, db, settings, querylist, config, debug=True):
|
def exportGraph (self, widget, data):
|
||||||
"""Constructor for GraphViewer"""
|
dia_chooser = gtk.FileChooserDialog(title="Please choose the directory you wish to export to:",
|
||||||
self.debug=debug
|
action=gtk.FILE_CHOOSER_ACTION_OPEN,
|
||||||
#print "start of GraphViewer constructor"
|
buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
|
||||||
self.db=db
|
|
||||||
self.cursor=db.cursor
|
|
||||||
self.settings=settings
|
|
||||||
self.sql=querylist
|
|
||||||
self.conf = config
|
|
||||||
|
|
||||||
self.sites = "PokerStars"
|
response = dia_chooser.run()
|
||||||
self.heroes = {}
|
if response == gtk.RESPONSE_OK:
|
||||||
|
self.exportDir = dia_chooser.get_filename()
|
||||||
|
elif response == gtk.RESPONSE_CANCEL:
|
||||||
|
print 'Closed, no graph exported'
|
||||||
|
dia_chooser.destroy()
|
||||||
|
|
||||||
# For use in date ranges.
|
def __init__(self, db, settings, querylist, config, debug=True):
|
||||||
self.start_date = gtk.Entry(max=12)
|
"""Constructor for GraphViewer"""
|
||||||
self.end_date = gtk.Entry(max=12)
|
self.debug=debug
|
||||||
self.start_date.set_property('editable', False)
|
#print "start of GraphViewer constructor"
|
||||||
self.end_date.set_property('editable', False)
|
self.db=db
|
||||||
|
self.cursor=db.cursor
|
||||||
|
self.settings=settings
|
||||||
|
self.sql=querylist
|
||||||
|
self.conf = config
|
||||||
|
|
||||||
|
self.sites = "PokerStars"
|
||||||
|
self.heroes = {}
|
||||||
|
|
||||||
|
# For use in date ranges.
|
||||||
|
self.start_date = gtk.Entry(max=12)
|
||||||
|
self.end_date = gtk.Entry(max=12)
|
||||||
|
self.start_date.set_property('editable', False)
|
||||||
|
self.end_date.set_property('editable', False)
|
||||||
|
|
||||||
self.mainHBox = gtk.HBox(False, 0)
|
self.mainHBox = gtk.HBox(False, 0)
|
||||||
self.mainHBox.show()
|
self.mainHBox.show()
|
||||||
|
|
||||||
self.leftPanelBox = gtk.VBox(False, 0)
|
self.leftPanelBox = gtk.VBox(False, 0)
|
||||||
self.graphBox = gtk.VBox(False, 0)
|
self.graphBox = gtk.VBox(False, 0)
|
||||||
|
|
||||||
self.hpane = gtk.HPaned()
|
self.hpane = gtk.HPaned()
|
||||||
self.hpane.pack1(self.leftPanelBox)
|
self.hpane.pack1(self.leftPanelBox)
|
||||||
self.hpane.pack2(self.graphBox)
|
self.hpane.pack2(self.graphBox)
|
||||||
self.hpane.show()
|
self.hpane.show()
|
||||||
|
|
||||||
self.mainHBox.add(self.hpane)
|
self.mainHBox.add(self.hpane)
|
||||||
|
|
||||||
playerFrame = gtk.Frame("Hero:")
|
playerFrame = gtk.Frame("Hero:")
|
||||||
playerFrame.set_label_align(0.0, 0.0)
|
playerFrame.set_label_align(0.0, 0.0)
|
||||||
playerFrame.show()
|
playerFrame.show()
|
||||||
vbox = gtk.VBox(False, 0)
|
vbox = gtk.VBox(False, 0)
|
||||||
vbox.show()
|
vbox.show()
|
||||||
|
|
||||||
self.fillPlayerFrame(vbox)
|
self.fillPlayerFrame(vbox)
|
||||||
playerFrame.add(vbox)
|
playerFrame.add(vbox)
|
||||||
|
|
||||||
sitesFrame = gtk.Frame("Sites:")
|
sitesFrame = gtk.Frame("Sites:")
|
||||||
sitesFrame.set_label_align(0.0, 0.0)
|
sitesFrame.set_label_align(0.0, 0.0)
|
||||||
sitesFrame.show()
|
sitesFrame.show()
|
||||||
vbox = gtk.VBox(False, 0)
|
vbox = gtk.VBox(False, 0)
|
||||||
vbox.show()
|
vbox.show()
|
||||||
|
|
||||||
self.fillSitesFrame(vbox)
|
self.fillSitesFrame(vbox)
|
||||||
sitesFrame.add(vbox)
|
sitesFrame.add(vbox)
|
||||||
|
|
||||||
dateFrame = gtk.Frame("Date:")
|
dateFrame = gtk.Frame("Date:")
|
||||||
dateFrame.set_label_align(0.0, 0.0)
|
dateFrame.set_label_align(0.0, 0.0)
|
||||||
dateFrame.show()
|
dateFrame.show()
|
||||||
vbox = gtk.VBox(False, 0)
|
vbox = gtk.VBox(False, 0)
|
||||||
vbox.show()
|
vbox.show()
|
||||||
|
|
||||||
self.fillDateFrame(vbox)
|
self.fillDateFrame(vbox)
|
||||||
dateFrame.add(vbox)
|
dateFrame.add(vbox)
|
||||||
|
|
||||||
graphButton=gtk.Button("Generate Graph")
|
graphButton=gtk.Button("Generate Graph")
|
||||||
graphButton.connect("clicked", self.generateGraph, "cliced data")
|
graphButton.connect("clicked", self.generateGraph, "cliced data")
|
||||||
graphButton.show()
|
graphButton.show()
|
||||||
|
|
||||||
self.exportButton=gtk.Button("Export to File")
|
self.exportButton=gtk.Button("Export to File")
|
||||||
#@ self.exportButton.connect("clicked", self.exportGraph, "show clicked")
|
self.exportButton.connect("clicked", self.exportGraph, "show clicked")
|
||||||
self.exportButton.show()
|
self.exportButton.show()
|
||||||
|
|
||||||
self.leftPanelBox.add(playerFrame)
|
self.leftPanelBox.add(playerFrame)
|
||||||
self.leftPanelBox.add(sitesFrame)
|
self.leftPanelBox.add(sitesFrame)
|
||||||
self.leftPanelBox.add(dateFrame)
|
self.leftPanelBox.add(dateFrame)
|
||||||
self.leftPanelBox.add(graphButton)
|
self.leftPanelBox.add(graphButton)
|
||||||
self.leftPanelBox.add(self.exportButton)
|
self.leftPanelBox.add(self.exportButton)
|
||||||
|
|
||||||
self.leftPanelBox.show()
|
self.leftPanelBox.show()
|
||||||
self.graphBox.show()
|
self.graphBox.show()
|
||||||
|
|
||||||
#Note: Assumes PokerStars is in the config
|
|
||||||
# self.nameEntry.set_text(self.conf.supported_sites["PokerStars"].screen_name)
|
|
||||||
|
|
165
pyfpdb/GuiPlayerStats.py
Normal file
165
pyfpdb/GuiPlayerStats.py
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
#Copyright 2008 Steffen Jobbagy-Felso
|
||||||
|
#This program is free software: you can redistribute it and/or modify
|
||||||
|
#it under the terms of the GNU Affero General Public License as published by
|
||||||
|
#the Free Software Foundation, version 3 of the License.
|
||||||
|
#
|
||||||
|
#This program is distributed in the hope that it will be useful,
|
||||||
|
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
#GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
#You should have received a copy of the GNU Affero General Public License
|
||||||
|
#along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#In the "official" distribution you can find the license in
|
||||||
|
#agpl-3.0.txt in the docs folder of the package.
|
||||||
|
|
||||||
|
import threading
|
||||||
|
import pygtk
|
||||||
|
pygtk.require('2.0')
|
||||||
|
import gtk
|
||||||
|
import os
|
||||||
|
|
||||||
|
import fpdb_import
|
||||||
|
import fpdb_db
|
||||||
|
import FpdbSQLQueries
|
||||||
|
|
||||||
|
class GuiPlayerStats (threading.Thread):
|
||||||
|
def get_vbox(self):
|
||||||
|
"""returns the vbox of this thread"""
|
||||||
|
return self.main_hbox
|
||||||
|
|
||||||
|
def toggleCallback(self, widget, data=None):
|
||||||
|
# print "%s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()])
|
||||||
|
self.activesite = data
|
||||||
|
print "DEBUG: activesite set to %s" %(self.activesite)
|
||||||
|
|
||||||
|
def refreshStats(self, widget, data):
|
||||||
|
try: self.stats_table.destroy()
|
||||||
|
except AttributeError: pass
|
||||||
|
self.fillStatsFrame(self.stats_frame)
|
||||||
|
|
||||||
|
def fillStatsFrame(self, vbox):
|
||||||
|
# Get currently active site and grab playerid
|
||||||
|
tmp = self.sql.query['playerStats']
|
||||||
|
|
||||||
|
result = self.cursor.execute(self.sql.query['getPlayerId'], self.heroes[self.activesite])
|
||||||
|
result = self.db.cursor.fetchall()
|
||||||
|
pid = result[0][0]
|
||||||
|
tmp = tmp.replace("<player_test>", "(" + str(pid) + ")")
|
||||||
|
self.cursor.execute(tmp)
|
||||||
|
result = self.db.cursor.fetchall()
|
||||||
|
cols = 18
|
||||||
|
rows = len(result)+1 # +1 for title row
|
||||||
|
self.stats_table = gtk.Table(rows, cols, False)
|
||||||
|
self.stats_table.set_col_spacings(4)
|
||||||
|
self.stats_table.show()
|
||||||
|
vbox.add(self.stats_table)
|
||||||
|
|
||||||
|
# Create header row
|
||||||
|
titles = ("GID", "base", "Style", "Site", "$BB", "Hands", "VPIP", "PFR", "saw_f", "sawsd", "wtsdwsf", "wmsd", "FlAFq", "TuAFq", "RvAFq", "PFAFq", "Net($)", "BB/100")
|
||||||
|
|
||||||
|
col = 0
|
||||||
|
row = 0
|
||||||
|
for t in titles:
|
||||||
|
l = gtk.Label(titles[col])
|
||||||
|
l.show()
|
||||||
|
self.stats_table.attach(l, col, col+1, row, row+1)
|
||||||
|
col +=1
|
||||||
|
|
||||||
|
for row in range(rows-1):
|
||||||
|
for col in range(cols):
|
||||||
|
if(row%2 == 0):
|
||||||
|
bgcolor = "white"
|
||||||
|
else:
|
||||||
|
bgcolor = "lightgrey"
|
||||||
|
eb = gtk.EventBox()
|
||||||
|
eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor))
|
||||||
|
l = gtk.Label(result[row-1][col])
|
||||||
|
eb.add(l)
|
||||||
|
self.stats_table.attach(eb, col, col+1, row+1, row+2)
|
||||||
|
l.show()
|
||||||
|
eb.show()
|
||||||
|
|
||||||
|
|
||||||
|
def fillPlayerFrame(self, vbox):
|
||||||
|
for site in self.conf.supported_sites.keys():
|
||||||
|
hbox = gtk.HBox(False, 0)
|
||||||
|
vbox.pack_start(hbox, False, True, 0)
|
||||||
|
hbox.show()
|
||||||
|
|
||||||
|
player = self.conf.supported_sites[site].screen_name
|
||||||
|
self.createPlayerLine(hbox, site, player)
|
||||||
|
hbox = gtk.HBox(False, 0)
|
||||||
|
button = gtk.Button("Refresh")
|
||||||
|
button.connect("clicked", self.refreshStats, False)
|
||||||
|
button.show()
|
||||||
|
hbox.add(button)
|
||||||
|
vbox.pack_start(hbox, False, True, 0)
|
||||||
|
hbox.show()
|
||||||
|
|
||||||
|
def createPlayerLine(self, hbox, site, player):
|
||||||
|
if(self.buttongroup == None):
|
||||||
|
button = gtk.RadioButton(None, site + " id:")
|
||||||
|
button.set_active(True)
|
||||||
|
self.buttongroup = button
|
||||||
|
self.activesite = site
|
||||||
|
else:
|
||||||
|
button = gtk.RadioButton(self.buttongroup, site + " id:")
|
||||||
|
hbox.pack_start(button, True, True, 0)
|
||||||
|
button.connect("toggled", self.toggleCallback, site)
|
||||||
|
button.show()
|
||||||
|
|
||||||
|
pname = gtk.Entry()
|
||||||
|
pname.set_text(player)
|
||||||
|
pname.set_width_chars(20)
|
||||||
|
hbox.pack_start(pname, False, True, 0)
|
||||||
|
pname.connect("changed", self.__set_hero_name, site)
|
||||||
|
#TODO: Look at GtkCompletion - to fill out usernames
|
||||||
|
pname.show()
|
||||||
|
self.__set_hero_name(pname, site)
|
||||||
|
|
||||||
|
def __set_hero_name(self, w, site):
|
||||||
|
self.heroes[site] = w.get_text()
|
||||||
|
print "DEBUG: settings heroes[%s]: %s"%(site, self.heroes[site])
|
||||||
|
|
||||||
|
def __init__(self, db, config, querylist, debug=True):
|
||||||
|
self.debug=debug
|
||||||
|
self.db=db
|
||||||
|
self.cursor=db.cursor
|
||||||
|
self.conf=config
|
||||||
|
|
||||||
|
self.sql = querylist
|
||||||
|
|
||||||
|
self.activesite = None
|
||||||
|
self.buttongroup = None
|
||||||
|
|
||||||
|
self.heroes = {}
|
||||||
|
self.stat_table = None
|
||||||
|
self.stats_frame = None
|
||||||
|
|
||||||
|
self.main_hbox = gtk.HBox(False, 0)
|
||||||
|
self.main_hbox.show()
|
||||||
|
|
||||||
|
playerFrame = gtk.Frame("Hero:")
|
||||||
|
playerFrame.set_label_align(0.0, 0.0)
|
||||||
|
playerFrame.show()
|
||||||
|
vbox = gtk.VBox(False, 0)
|
||||||
|
vbox.show()
|
||||||
|
|
||||||
|
self.fillPlayerFrame(vbox)
|
||||||
|
playerFrame.add(vbox)
|
||||||
|
|
||||||
|
statsFrame = gtk.Frame("Stats:")
|
||||||
|
statsFrame.set_label_align(0.0, 0.0)
|
||||||
|
statsFrame.show()
|
||||||
|
self.stats_frame = gtk.VBox(False, 0)
|
||||||
|
self.stats_frame.show()
|
||||||
|
|
||||||
|
self.fillStatsFrame(self.stats_frame)
|
||||||
|
statsFrame.add(self.stats_frame)
|
||||||
|
|
||||||
|
self.main_hbox.pack_start(playerFrame)
|
||||||
|
self.main_hbox.pack_start(statsFrame)
|
||||||
|
|
|
@ -169,4 +169,3 @@ if __name__== "__main__":
|
||||||
main_window.show_all()
|
main_window.show_all()
|
||||||
|
|
||||||
gtk.main()
|
gtk.main()
|
||||||
|
|
||||||
|
|
|
@ -23,254 +23,492 @@ import traceback
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import xml.dom.minidom
|
import xml.dom.minidom
|
||||||
|
from decimal import Decimal
|
||||||
|
import operator
|
||||||
from xml.dom.minidom import Node
|
from xml.dom.minidom import Node
|
||||||
|
from pokereval import PokerEval
|
||||||
|
|
||||||
class HandHistoryConverter:
|
class HandHistoryConverter:
|
||||||
def __init__(self, config, file, sitename):
|
eval = PokerEval()
|
||||||
print "HandHistory init called"
|
def __init__(self, config, file, sitename):
|
||||||
self.c = config
|
print "HandHistory init called"
|
||||||
self.sitename = sitename
|
|
||||||
self.obs = "" # One big string
|
|
||||||
self.filetype = "text"
|
|
||||||
self.doc = None # For XML based HH files
|
|
||||||
self.file = file
|
|
||||||
self.hhbase = self.c.get_import_parameters().get("hhArchiveBase")
|
|
||||||
self.hhbase = os.path.expanduser(self.hhbase)
|
|
||||||
self.hhdir = os.path.join(self.hhbase,sitename)
|
|
||||||
self.gametype = []
|
|
||||||
# self.ofile = os.path.join(self.hhdir,file)
|
|
||||||
self.rexx = FpdbRegex.FpdbRegex()
|
|
||||||
|
|
||||||
def __str__(self):
|
self.c = config
|
||||||
tmp = "HandHistoryConverter: '%s'\n" % (self.sitename)
|
self.sitename = sitename
|
||||||
tmp = tmp + "\thhbase: '%s'\n" % (self.hhbase)
|
self.obs = "" # One big string
|
||||||
tmp = tmp + "\thhdir: '%s'\n" % (self.hhdir)
|
self.filetype = "text"
|
||||||
tmp = tmp + "\tfiletype: '%s'\n" % (self.filetype)
|
self.doc = None # For XML based HH files
|
||||||
tmp = tmp + "\tinfile: '%s'\n" % (self.file)
|
self.file = file
|
||||||
|
self.hhbase = self.c.get_import_parameters().get("hhArchiveBase")
|
||||||
|
self.hhbase = os.path.expanduser(self.hhbase)
|
||||||
|
self.hhdir = os.path.join(self.hhbase,sitename)
|
||||||
|
self.gametype = []
|
||||||
|
# self.ofile = os.path.join(self.hhdir,file)
|
||||||
|
self.rexx = FpdbRegex.FpdbRegex()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
tmp = "HandHistoryConverter: '%s'\n" % (self.sitename)
|
||||||
|
tmp = tmp + "\thhbase: '%s'\n" % (self.hhbase)
|
||||||
|
tmp = tmp + "\thhdir: '%s'\n" % (self.hhdir)
|
||||||
|
tmp = tmp + "\tfiletype: '%s'\n" % (self.filetype)
|
||||||
|
tmp = tmp + "\tinfile: '%s'\n" % (self.file)
|
||||||
# tmp = tmp + "\toutfile: '%s'\n" % (self.ofile)
|
# tmp = tmp + "\toutfile: '%s'\n" % (self.ofile)
|
||||||
# tmp = tmp + "\tgametype: '%s'\n" % (self.gametype[0])
|
# tmp = tmp + "\tgametype: '%s'\n" % (self.gametype[0])
|
||||||
# tmp = tmp + "\tgamebase: '%s'\n" % (self.gametype[1])
|
# tmp = tmp + "\tgamebase: '%s'\n" % (self.gametype[1])
|
||||||
# tmp = tmp + "\tlimit: '%s'\n" % (self.gametype[2])
|
# tmp = tmp + "\tlimit: '%s'\n" % (self.gametype[2])
|
||||||
# tmp = tmp + "\tsb/bb: '%s/%s'\n" % (self.gametype[3], self.gametype[4])
|
# tmp = tmp + "\tsb/bb: '%s/%s'\n" % (self.gametype[3], self.gametype[4])
|
||||||
return tmp
|
return tmp
|
||||||
|
|
||||||
def processFile(self):
|
def processFile(self):
|
||||||
if not self.sanityCheck():
|
if not self.sanityCheck():
|
||||||
print "Cowardly refusing to continue after failed sanity check"
|
print "Cowardly refusing to continue after failed sanity check"
|
||||||
return
|
return
|
||||||
self.readFile(self.file)
|
self.readFile(self.file)
|
||||||
self.gametype = self.determineGameType()
|
self.gametype = self.determineGameType()
|
||||||
self.hands = self.splitFileIntoHands()
|
self.hands = self.splitFileIntoHands()
|
||||||
for hand in self.hands:
|
for hand in self.hands:
|
||||||
self.readHandInfo(hand)
|
self.readHandInfo(hand)
|
||||||
self.readPlayerStacks(hand)
|
self.readPlayerStacks(hand)
|
||||||
self.markStreets(hand)
|
self.markStreets(hand)
|
||||||
self.readBlinds(hand)
|
self.readBlinds(hand)
|
||||||
self.readHeroCards(hand)
|
self.readHeroCards(hand) # want to generalise to draw games
|
||||||
|
self.readCommunityCards(hand) # read community cards
|
||||||
|
self.readShowdownActions(hand)
|
||||||
|
# Read action (Note: no guarantee this is in hand order.
|
||||||
|
for street in hand.streets.groupdict():
|
||||||
|
self.readAction(hand, street)
|
||||||
|
|
||||||
# Read action (Note: no guarantee this is in hand order.
|
# finalise it (total the pot)
|
||||||
for street in hand.streets.groupdict():
|
hand.totalPot()
|
||||||
self.readAction(hand, street)
|
self.getRake(hand)
|
||||||
|
|
||||||
|
if(hand.involved == True):
|
||||||
|
#self.writeHand("output file", hand)
|
||||||
|
hand.printHand()
|
||||||
|
else:
|
||||||
|
pass #Don't write out observed hands
|
||||||
|
|
||||||
if(hand.involved == True):
|
#####
|
||||||
self.writeHand("output file", hand)
|
# These functions are parse actions that may be overridden by the inheriting class
|
||||||
else:
|
#
|
||||||
pass #Don't write out observed hands
|
|
||||||
|
def readSupportedGames(self): abstract
|
||||||
|
|
||||||
# Functions to be implemented in the inheriting class
|
# should return a list
|
||||||
def readSupportedGames(self): abstract
|
# type base limit
|
||||||
|
# [ ring, hold, nl , sb, bb ]
|
||||||
|
# Valid types specified in docs/tabledesign.html in Gametypes
|
||||||
|
def determineGameType(self): abstract
|
||||||
|
|
||||||
# should return a list
|
# Read any of:
|
||||||
# type base limit
|
# HID HandID
|
||||||
# [ ring, hold, nl , sb, bb ]
|
# TABLE Table name
|
||||||
# Valid types specified in docs/tabledesign.html in Gametypes
|
# SB small blind
|
||||||
def determineGameType(self): abstract
|
# BB big blind
|
||||||
|
# GAMETYPE gametype
|
||||||
|
# YEAR MON DAY HR MIN SEC datetime
|
||||||
|
# BUTTON button seat number
|
||||||
|
def readHandInfo(self, hand): abstract
|
||||||
|
|
||||||
#TODO: Comment
|
# Needs to return a list of lists in the format
|
||||||
def readHandInfo(self, hand): abstract
|
# [['seat#', 'player1name', 'stacksize'] ['seat#', 'player2name', 'stacksize'] [...]]
|
||||||
|
def readPlayerStacks(self, hand): abstract
|
||||||
|
|
||||||
# Needs to return a list of lists in the format
|
# Needs to return a MatchObject with group names identifying the streets into the Hand object
|
||||||
# [['seat#', 'player1name', 'stacksize'] ['seat#', 'player2name', 'stacksize'] [...]]
|
# that is, pulls the chunks of preflop, flop, turn and river text into hand.streets MatchObject.
|
||||||
def readPlayerStacks(self, hand): abstract
|
def markStreets(self, hand): abstract
|
||||||
|
|
||||||
# Needs to return a MatchObject with group names identifying the streets into the Hand object
|
#Needs to return a list in the format
|
||||||
def markStreets(self, hand): abstract
|
# ['player1name', 'player2name', ...] where player1name is the sb and player2name is bb,
|
||||||
|
# addtional players are assumed to post a bb oop
|
||||||
|
def readBlinds(self, hand): abstract
|
||||||
|
def readHeroCards(self, hand): abstract
|
||||||
|
def readAction(self, hand, street): abstract
|
||||||
|
|
||||||
|
# Some sites don't report the rake. This will be called at the end of the hand after the pot total has been calculated
|
||||||
|
# so that an inheriting class can calculate it for the specific site if need be.
|
||||||
|
def getRake(self, hand): abstract
|
||||||
|
|
||||||
|
def sanityCheck(self):
|
||||||
|
sane = True
|
||||||
|
base_w = False
|
||||||
|
#Check if hhbase exists and is writable
|
||||||
|
#Note: Will not try to create the base HH directory
|
||||||
|
if not (os.access(self.hhbase, os.W_OK) and os.path.isdir(self.hhbase)):
|
||||||
|
print "HH Sanity Check: Directory hhbase '" + self.hhbase + "' doesn't exist or is not writable"
|
||||||
|
else:
|
||||||
|
#Check if hhdir exists and is writable
|
||||||
|
if not os.path.isdir(self.hhdir):
|
||||||
|
# In first pass, dir may not exist. Attempt to create dir
|
||||||
|
print "Creating directory: '%s'" % (self.hhdir)
|
||||||
|
os.mkdir(self.hhdir)
|
||||||
|
sane = True
|
||||||
|
elif os.access(self.hhdir, os.W_OK):
|
||||||
|
sane = True
|
||||||
|
else:
|
||||||
|
print "HH Sanity Check: Directory hhdir '" + self.hhdir + "' or its parent directory are not writable"
|
||||||
|
|
||||||
#Needs to return a list in the format
|
return sane
|
||||||
# ['player1name', 'player2name', ...] where player1name is the sb and player2name is bb,
|
|
||||||
# addtional players are assumed to post a bb oop
|
|
||||||
def readBlinds(self, hand): abstract
|
|
||||||
def readHeroCards(self, hand): abstract
|
|
||||||
def readAction(self, hand, street): abstract
|
|
||||||
|
|
||||||
def sanityCheck(self):
|
# Functions not necessary to implement in sub class
|
||||||
sane = False
|
def setFileType(self, filetype = "text"):
|
||||||
base_w = False
|
self.filetype = filetype
|
||||||
#Check if hhbase exists and is writable
|
|
||||||
#Note: Will not try to create the base HH directory
|
|
||||||
if not (os.access(self.hhbase, os.W_OK) and os.path.isdir(self.hhbase)):
|
|
||||||
print "HH Sanity Check: Directory hhbase '" + self.hhbase + "' doesn't exist or is not writable"
|
|
||||||
else:
|
|
||||||
#Check if hhdir exists and is writable
|
|
||||||
if not os.path.isdir(self.hhdir):
|
|
||||||
# In first pass, dir may not exist. Attempt to create dir
|
|
||||||
print "Creating directory: '%s'" % (self.hhdir)
|
|
||||||
os.mkdir(self.hhdir)
|
|
||||||
sane = True
|
|
||||||
elif os.access(self.hhdir, os.W_OK):
|
|
||||||
sane = True
|
|
||||||
else:
|
|
||||||
print "HH Sanity Check: Directory hhdir '" + self.hhdir + "' or its parent directory are not writable"
|
|
||||||
|
|
||||||
return sane
|
def splitFileIntoHands(self):
|
||||||
|
hands = []
|
||||||
# Functions not necessary to implement in sub class
|
list = self.rexx.split_hand_re.split(self.obs)
|
||||||
def setFileType(self, filetype = "text"):
|
list.pop() #Last entry is empty
|
||||||
self.filetype = filetype
|
for l in list:
|
||||||
|
|
||||||
def splitFileIntoHands(self):
|
|
||||||
hands = []
|
|
||||||
list = self.rexx.split_hand_re.split(self.obs)
|
|
||||||
list.pop() #Last entry is empty
|
|
||||||
for l in list:
|
|
||||||
# print "'" + l + "'"
|
# print "'" + l + "'"
|
||||||
hands = hands + [Hand(self.sitename, self.gametype, l)]
|
hands = hands + [Hand(self.sitename, self.gametype, l)]
|
||||||
return hands
|
return hands
|
||||||
|
|
||||||
def readFile(self, filename):
|
def readFile(self, filename):
|
||||||
"""Read file"""
|
"""Read file"""
|
||||||
print "Reading file: '%s'" %(filename)
|
print "Reading file: '%s'" %(filename)
|
||||||
if(self.filetype == "text"):
|
if(self.filetype == "text"):
|
||||||
infile=open(filename, "rU")
|
infile=open(filename, "rU")
|
||||||
self.obs = infile.read()
|
self.obs = infile.read()
|
||||||
infile.close()
|
infile.close()
|
||||||
elif(self.filetype == "xml"):
|
elif(self.filetype == "xml"):
|
||||||
try:
|
try:
|
||||||
doc = xml.dom.minidom.parse(filename)
|
doc = xml.dom.minidom.parse(filename)
|
||||||
self.doc = doc
|
self.doc = doc
|
||||||
except:
|
except:
|
||||||
traceback.print_exc(file=sys.stderr)
|
traceback.print_exc(file=sys.stderr)
|
||||||
|
|
||||||
def writeHand(self, file, hand):
|
def writeHand(self, file, hand):
|
||||||
"""Write out parsed data"""
|
"""Write out parsed data"""
|
||||||
print "DEBUG: *************************"
|
print "DEBUG: *************************"
|
||||||
print "DEBUG: Start of print hand"
|
print "DEBUG: Start of print hand"
|
||||||
print "DEBUG: *************************"
|
print "DEBUG: *************************"
|
||||||
|
|
||||||
print "%s Game #%s: %s ($%s/$%s) - %s" %(hand.sitename, hand.handid, "XXXXhand.gametype", hand.sb, hand.bb, hand.starttime)
|
print "%s Game #%s: %s ($%s/$%s) - %s" %(hand.sitename, hand.handid, "XXXXhand.gametype", hand.sb, hand.bb, hand.starttime)
|
||||||
print "Table '%s' %d-max Seat #%s is the button" %(hand.tablename, hand.maxseats, hand.buttonpos)
|
print "Table '%s' %d-max Seat #%s is the button" %(hand.tablename, hand.maxseats, hand.buttonpos)
|
||||||
|
|
||||||
for player in hand.players:
|
for player in hand.players:
|
||||||
print "Seat %s: %s ($%s)" %(player[0], player[1], player[2])
|
print "Seat %s: %s ($%s)" %(player[0], player[1], player[2])
|
||||||
|
|
||||||
if(hand.posted[0] == "FpdbNBP"):
|
if(hand.posted[0] == "FpdbNBP"):
|
||||||
print "No small blind posted"
|
print "No small blind posted"
|
||||||
else:
|
else:
|
||||||
print "%s: posts small blind $%s" %(hand.posted[0], hand.sb)
|
print "%s: posts small blind $%s" %(hand.posted[0], hand.sb)
|
||||||
|
|
||||||
#May be more than 1 bb posting
|
#May be more than 1 bb posting
|
||||||
print "%s: posts big blind $%s" %(hand.posted[1], hand.bb)
|
print "%s: posts big blind $%s" %(hand.posted[1], hand.bb)
|
||||||
if(len(hand.posted) > 2):
|
if(len(hand.posted) > 2):
|
||||||
# Need to loop on all remaining big blinds - lazy
|
# Need to loop on all remaining big blinds - lazy
|
||||||
print "XXXXXXXXX FIXME XXXXXXXX"
|
print "XXXXXXXXX FIXME XXXXXXXX"
|
||||||
|
|
||||||
print "*** HOLE CARDS ***"
|
print "*** HOLE CARDS ***"
|
||||||
print "Dealt to %s [%s]" %(hand.hero ,hand.holecards)
|
print "Dealt to %s [%s %s]" %(hand.hero , hand.holecards[0], hand.holecards[1])
|
||||||
#
|
|
||||||
## ACTION STUFF
|
|
||||||
# This is no limit only at the moment
|
|
||||||
|
|
||||||
for act in hand.actions['PREFLOP']:
|
|
||||||
self.printActionLine(act, 0)
|
|
||||||
|
|
||||||
if 'FLOP' in hand.actions:
|
for act in hand.actions['PREFLOP']:
|
||||||
print "*** FLOP *** [%s]" %("XXXXX Flop cards XXXXXX")
|
self.printActionLine(act, 0)
|
||||||
for act in hand.actions['FLOP']:
|
|
||||||
self.printActionLine(act, 0)
|
|
||||||
|
|
||||||
if 'TURN' in hand.actions:
|
if 'PREFLOP' in hand.actions:
|
||||||
print "*** TURN *** [%s] [%s]" %("XXXXX Flop cards XXXXXX", "XXXXX Turn Card XXXXX")
|
for act in hand.actions['PREFLOP']:
|
||||||
for act in hand.actions['TURN']:
|
print "PF action"
|
||||||
self.printActionLine(act, 0)
|
|
||||||
|
|
||||||
if 'RIVER' in hand.actions:
|
if 'FLOP' in hand.actions:
|
||||||
print "*** RIVER *** [%s %s] [%s]" %("XXXXX Flop cards XXXXXX", "XXXXX Turn Card XXXXX", "XXXXX River Card XXXXX")
|
print "*** FLOP *** [%s %s %s]" %(hand.streets.group("FLOP1"), hand.streets.group("FLOP2"), hand.streets.group("FLOP3"))
|
||||||
for act in hand.actions['RIVER']:
|
for act in hand.actions['FLOP']:
|
||||||
self.printActionLine(act, 0)
|
self.printActionLine(act, 0)
|
||||||
|
|
||||||
print "*** SUMMARY ***"
|
if 'TURN' in hand.actions:
|
||||||
print "XXXXXXXXXXXX Need sumary info XXXXXXXXXXX"
|
print "*** TURN *** [%s %s %s] [%s]" %(hand.streets.group("FLOP1"), hand.streets.group("FLOP2"), hand.streets.group("FLOP3"), hand.streets.group("TURN1"))
|
||||||
# print "Total pot $%s | Rake $%s)" %(hand.totalpot $" + hand.rake)
|
for act in hand.actions['TURN']:
|
||||||
# print "Board [" + boardcards + "]"
|
self.printActionLine(act, 0)
|
||||||
#
|
|
||||||
# SUMMARY STUFF
|
if 'RIVER' in hand.actions:
|
||||||
|
print "*** RIVER *** [%s %s %s %s] [%s]" %(hand.streets.group("FLOP1"), hand.streets.group("FLOP2"), hand.streets.group("FLOP3"), hand.streets.group("TURN1"), hand.streets.group("RIVER1"))
|
||||||
|
for act in hand.actions['RIVER']:
|
||||||
|
self.printActionLine(act, 0)
|
||||||
|
|
||||||
|
print "*** SUMMARY ***"
|
||||||
|
print "XXXXXXXXXXXX Need sumary info XXXXXXXXXXX"
|
||||||
|
|
||||||
|
|
||||||
def printActionLine(self, act, pot):
|
def printActionLine(self, act, pot):
|
||||||
if act[1] == 'folds' or act[1] == 'checks':
|
if act[1] == 'folds' or act[1] == 'checks':
|
||||||
print "%s: %s" %(act[0], act[1])
|
print "%s: %s " %(act[0], act[1])
|
||||||
if act[1] == 'calls':
|
if act[1] == 'calls':
|
||||||
print "%s: %s $%s" %(act[0], act[1], act[2])
|
print "%s: %s $%s" %(act[0], act[1], act[2])
|
||||||
if act[1] == 'raises':
|
if act[1] == 'raises':
|
||||||
print "%s: %s $%s to XXXpottotalXXX" %(act[0], act[1], act[2])
|
print "%s: %s $%s to XXXpottotalXXX" %(act[0], act[1], act[2])
|
||||||
|
|
||||||
|
|
||||||
#takes a poker float (including , for thousand seperator and converts it to an int
|
#takes a poker float (including , for thousand seperator and converts it to an int
|
||||||
def float2int (self, string):
|
def float2int (self, string):
|
||||||
pos=string.find(",")
|
pos=string.find(",")
|
||||||
if (pos!=-1): #remove , the thousand seperator
|
if (pos!=-1): #remove , the thousand seperator
|
||||||
string=string[0:pos]+string[pos+1:]
|
string=string[0:pos]+string[pos+1:]
|
||||||
|
|
||||||
pos=string.find(".")
|
pos=string.find(".")
|
||||||
if (pos!=-1): #remove decimal point
|
if (pos!=-1): #remove decimal point
|
||||||
string=string[0:pos]+string[pos+1:]
|
string=string[0:pos]+string[pos+1:]
|
||||||
|
|
||||||
result = int(string)
|
result = int(string)
|
||||||
if pos==-1: #no decimal point - was in full dollars - need to multiply with 100
|
if pos==-1: #no decimal point - was in full dollars - need to multiply with 100
|
||||||
result*=100
|
result*=100
|
||||||
return result
|
return result
|
||||||
#end def float2int
|
#end def float2int
|
||||||
|
|
||||||
class Hand:
|
class Hand:
|
||||||
# def __init__(self, sitename, gametype, sb, bb, string):
|
# def __init__(self, sitename, gametype, sb, bb, string):
|
||||||
|
|
||||||
|
UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K'}
|
||||||
def __init__(self, sitename, gametype, string):
|
def __init__(self, sitename, gametype, string):
|
||||||
self.sitename = sitename
|
self.sitename = sitename
|
||||||
self.gametype = gametype
|
self.gametype = gametype
|
||||||
self.string = string
|
self.string = string
|
||||||
|
|
||||||
|
self.streets = None # A MatchObject using a groupnames to identify streets.
|
||||||
|
self.streetList = ['BLINDS','PREFLOP','FLOP','TURN','RIVER'] # a list of the observed street names in order
|
||||||
|
self.actions = {}
|
||||||
|
|
||||||
|
self.handid = 0
|
||||||
|
self.sb = gametype[3]
|
||||||
|
self.bb = gametype[4]
|
||||||
|
self.tablename = "Slartibartfast"
|
||||||
|
self.maxseats = 10
|
||||||
|
self.counted_seats = 0
|
||||||
|
self.buttonpos = 0
|
||||||
|
self.seating = []
|
||||||
|
self.players = []
|
||||||
|
self.posted = []
|
||||||
|
self.involved = True
|
||||||
|
|
||||||
|
self.hero = "Hiro"
|
||||||
|
self.holecards = {} # dict from player names to lists of hole cards
|
||||||
|
self.board = {} # dict from street names to community cards
|
||||||
|
|
||||||
|
self.action = []
|
||||||
|
self.totalpot = 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):
|
||||||
|
"""seat, an int indicating the seat
|
||||||
|
name, the player name
|
||||||
|
chips, the chips the player has at the start of the hand"""
|
||||||
|
#self.players.append(name)
|
||||||
|
self.players.append([seat, name, chips])
|
||||||
|
self.holecards[name] = []
|
||||||
|
#self.startChips[name] = chips
|
||||||
|
#self.endChips[name] = chips
|
||||||
|
#self.winners[name] = 0
|
||||||
|
for street in self.streetList:
|
||||||
|
self.bets[street][name] = []
|
||||||
|
|
||||||
self.streets = None # A MatchObject using a groupnames to identify streets.
|
|
||||||
self.actions = {}
|
|
||||||
|
|
||||||
self.handid = 0
|
def addHoleCards(self, cards, player=None): # generalise to add hole cards for a specific seat or player
|
||||||
self.sb = gametype[3]
|
for c in cards:
|
||||||
self.bb = gametype[4]
|
self.holecards[player].append(self.card(c))
|
||||||
self.tablename = "Slartibartfast"
|
|
||||||
self.maxseats = 10
|
|
||||||
self.counted_seats = 0
|
def discardHoleCards(self, cards, player=None):
|
||||||
self.buttonpos = 0
|
if seat is None:
|
||||||
self.seating = []
|
#raise something
|
||||||
self.players = []
|
pass
|
||||||
self.posted = []
|
for card in cards:
|
||||||
self.involved = True
|
try:
|
||||||
self.hero = "Hiro"
|
self.holecards[player].remove(card)
|
||||||
self.holecards = "Xx Xx"
|
except ValueError:
|
||||||
self.action = []
|
print "tried to discard a card player apparently didn't have"
|
||||||
self.totalpot = 0
|
|
||||||
self.rake = 0
|
def setCommunityCards(self, street, cards):
|
||||||
|
self.board[street] = [self.card(c) for c in cards]
|
||||||
|
print self.board[street]
|
||||||
|
|
||||||
|
def card(self,c):
|
||||||
|
"""upper case the ranks but not suits, 'atjqk' => 'ATJQK'"""
|
||||||
|
# don't know how to make this 'static'
|
||||||
|
for k,v in self.UPS.items():
|
||||||
|
c = c.replace(k,v)
|
||||||
|
return c
|
||||||
|
|
||||||
|
def addBlind(self, player, amount):
|
||||||
|
# if player is None, it's a missing small blind.
|
||||||
|
if player is not None:
|
||||||
|
self.bets['PREFLOP'][player].append(Decimal(amount))
|
||||||
|
self.lastBet['PREFLOP'] = Decimal(amount)
|
||||||
|
self.posted += [player]
|
||||||
|
|
||||||
|
|
||||||
|
#def addFold(self, street, player=None):
|
||||||
|
## Called when a player folds.
|
||||||
|
#self.bets[street][player].append(None)
|
||||||
|
|
||||||
|
#def addCheck(self, street, player=None):
|
||||||
|
#self.bets[street][player].append(0)
|
||||||
|
|
||||||
|
def addCall(self, street, player=None, amount=None):
|
||||||
|
# Potentially calculate the amount of the call if not supplied
|
||||||
|
# corner cases include if player would be all in
|
||||||
|
if amount is not None:
|
||||||
|
self.bets[street][player].append(Decimal(amount))
|
||||||
|
#self.lastBet[street] = Decimal(amount)
|
||||||
|
self.actions[street] += [[player, 'calls', amount]]
|
||||||
|
|
||||||
|
def addRaiseTo(self, street, player, amountTo):
|
||||||
|
# Given only the amount raised to, the amount of the raise can be calculated by
|
||||||
|
# working out how much this player has already in the pot
|
||||||
|
# (which is the sum of self.bets[street][player])
|
||||||
|
# and how much he needs to call to match the previous player
|
||||||
|
# (which is tracked by self.lastBet)
|
||||||
|
committedThisStreet = reduce(operator.add, self.bets[street][player], 0)
|
||||||
|
amountToCall = self.lastBet[street] - committedThisStreet
|
||||||
|
self.lastBet[street] = Decimal(amountTo)
|
||||||
|
amountBy = Decimal(amountTo) - amountToCall
|
||||||
|
self.bets[street][player].append(amountBy+amountToCall)
|
||||||
|
self.actions[street] += [[player, 'raises', amountBy, amountTo]]
|
||||||
|
|
||||||
|
def addBet(self, street, player=None, amount=0):
|
||||||
|
self.bets[street][name].append(Decimal(amount))
|
||||||
|
self.orderedBets[street].append(Decimal(amount))
|
||||||
|
self.actions[street] += [[player, 'bets', amount]]
|
||||||
|
|
||||||
|
def totalPot(self):
|
||||||
|
"""If all bets and blinds have been added, totals up the total pot size
|
||||||
|
Known bug: doesn't take into account side pots"""
|
||||||
|
if self.totalpot is None:
|
||||||
|
self.totalpot = 0
|
||||||
|
|
||||||
|
# player names:
|
||||||
|
# print [x[1] for x in self.players]
|
||||||
|
for player in [x[1] for x in self.players]:
|
||||||
|
for street in self.streetList:
|
||||||
|
#print street, self.bets[street][player]
|
||||||
|
self.totalpot += reduce(operator.add, self.bets[street][player], 0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def printHand(self):
|
def printHand(self):
|
||||||
print self.sitename
|
# PokerStars format.
|
||||||
print self.gametype
|
print "### DEBUG ###"
|
||||||
print self.string
|
print "%s Game #%s: %s ($%s/$%s) - %s" %(self.sitename, self.handid, "XXXXhand.gametype", self.sb, self.bb, self.starttime)
|
||||||
print self.handid
|
print "Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)
|
||||||
print self.sb
|
for player in self.players:
|
||||||
print self.bb
|
print "Seat %s: %s ($%s)" %(player[0], player[1], player[2])
|
||||||
print self.tablename
|
|
||||||
print self.maxseats
|
if(self.posted[0] is None):
|
||||||
print self.counted_seats
|
print "No small blind posted"
|
||||||
print self.buttonpos
|
else:
|
||||||
print self.seating
|
print "%s: posts small blind $%s" %(self.posted[0], self.sb)
|
||||||
print self.players
|
|
||||||
print self.posted
|
#May be more than 1 bb posting
|
||||||
print self.action
|
for a in self.posted[1:]:
|
||||||
print self.involved
|
print "%s: posts big blind $%s" %(self.posted[1], self.bb)
|
||||||
print self.hero
|
|
||||||
|
# What about big & small blinds?
|
||||||
|
|
||||||
|
print "*** HOLE CARDS ***"
|
||||||
|
print "Dealt to %s [%s %s]" %(self.hero , self.holecards[self.hero][0], self.holecards[self.hero][1])
|
||||||
|
|
||||||
|
if 'PREFLOP' in self.actions:
|
||||||
|
for act in self.actions['PREFLOP']:
|
||||||
|
self.printActionLine(act)
|
||||||
|
|
||||||
|
if 'FLOP' in self.actions:
|
||||||
|
print "*** FLOP *** [%s %s %s]" %(self.streets.group("FLOP1"), self.streets.group("FLOP2"), self.streets.group("FLOP3"))
|
||||||
|
for act in self.actions['FLOP']:
|
||||||
|
self.printActionLine(act)
|
||||||
|
|
||||||
|
if 'TURN' in self.actions:
|
||||||
|
print "*** TURN *** [%s %s %s] [%s]" %(self.streets.group("FLOP1"), self.streets.group("FLOP2"), self.streets.group("FLOP3"), self.streets.group("TURN1"))
|
||||||
|
for act in self.actions['TURN']:
|
||||||
|
self.printActionLine(act)
|
||||||
|
|
||||||
|
if 'RIVER' in self.actions:
|
||||||
|
print "*** RIVER *** [%s %s %s %s] [%s]" %(self.streets.group("FLOP1"), self.streets.group("FLOP2"), self.streets.group("FLOP3"), self.streets.group("TURN1"), self.streets.group("RIVER1"))
|
||||||
|
for act in self.actions['RIVER']:
|
||||||
|
self.printActionLine(act)
|
||||||
|
|
||||||
|
|
||||||
|
#Some sites don't have a showdown section so we have to figure out if there should be one
|
||||||
|
# The logic for a showdown is: at the end of river action there are at least two players in the hand
|
||||||
|
if 'SHOWDOWN' in self.actions:
|
||||||
|
print "*** SHOW DOWN ***"
|
||||||
|
print "what do they show"
|
||||||
|
|
||||||
|
print "*** SUMMARY ***"
|
||||||
|
print "Total pot $%s | Rake $%s)" % (self.totalpot, self.rake)
|
||||||
|
print "Board [%s %s %s %s %s]" % (self.streets.group("FLOP1"), self.streets.group("FLOP2"), self.streets.group("FLOP3"), self.streets.group("TURN1"), self.streets.group("RIVER1"))
|
||||||
|
|
||||||
|
#print self.board
|
||||||
|
for player in self.players:
|
||||||
|
if self.holecards[player[1]]: # empty list default is false
|
||||||
|
hole = self.holecards[player[1]]
|
||||||
|
#print self.board.values()
|
||||||
|
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)
|
||||||
|
else:
|
||||||
|
print "Seat %d: %s mucked or folded" % (player[0], player[1])
|
||||||
|
|
||||||
|
|
||||||
|
def printActionLine(self, act):
|
||||||
|
if act[1] == 'folds' or act[1] == 'checks':
|
||||||
|
print "%s: %s " %(act[0], act[1])
|
||||||
|
if act[1] == 'calls':
|
||||||
|
print "%s: %s $%s" %(act[0], act[1], act[2])
|
||||||
|
if act[1] == 'raises':
|
||||||
|
print "%s: %s $%s to $%s" %(act[0], act[1], act[2], act[3])
|
||||||
|
|
||||||
|
# going to use pokereval to figure out hands
|
||||||
|
# these functions are copied from pokergame.py
|
||||||
|
# im thinking perhaps its best to use all the functionality of pokergame instead
|
||||||
|
# of reinventing the wheel
|
||||||
|
def bestHand(self, side, cards):
|
||||||
|
#if self.variant == "omaha" or self.variant == "omaha8":
|
||||||
|
#hand = self.serial2player[serial].hand.tolist(True)
|
||||||
|
#board = self.board.tolist(True)
|
||||||
|
#else:
|
||||||
|
#hand = hand.tolist(True) + board.tolist(True)
|
||||||
|
#board = []
|
||||||
|
print cards
|
||||||
|
return HandHistoryConverter.eval.best('hi', cards, [])
|
||||||
|
|
||||||
|
def bestHandValue(self, side, serial):
|
||||||
|
(value, cards) = self.bestHand(side, serial)
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def readableHandValueLong(self, side, value, cards):
|
||||||
|
cards = self.eval.card2string(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
|
3
pyfpdb/Mucked.py
Normal file → Executable file
3
pyfpdb/Mucked.py
Normal file → Executable file
|
@ -170,6 +170,7 @@ class Stud_cards:
|
||||||
for r in range(0, self.rows):
|
for r in range(0, self.rows):
|
||||||
self.grid_contents[( 0, r)] = gtk.Label("%d" % (r + 1))
|
self.grid_contents[( 0, r)] = gtk.Label("%d" % (r + 1))
|
||||||
self.grid_contents[( 1, r)] = gtk.Label("player %d" % (r + 1))
|
self.grid_contents[( 1, r)] = gtk.Label("player %d" % (r + 1))
|
||||||
|
self.grid_contents[( 1, r)].set_property("width-chars", 12)
|
||||||
self.grid_contents[( 4, r)] = gtk.Label("-")
|
self.grid_contents[( 4, r)] = gtk.Label("-")
|
||||||
self.grid_contents[( 9, r)] = gtk.Label("-")
|
self.grid_contents[( 9, r)] = gtk.Label("-")
|
||||||
self.grid_contents[( 2, r)] = self.eb[( 0, r)]
|
self.grid_contents[( 2, r)] = self.eb[( 0, r)]
|
||||||
|
@ -289,7 +290,7 @@ class Stud_cards:
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
for r in range(0, self.rows):
|
for r in range(0, self.rows):
|
||||||
self.grid_contents[(1, r)].set_text(" ")
|
self.grid_contents[(1, r)].set_text(" ")
|
||||||
for c in range(0, 7):
|
for c in range(0, 7):
|
||||||
self.seen_cards[(c, r)].set_from_pixbuf(self.card_images[('B', 'S')])
|
self.seen_cards[(c, r)].set_from_pixbuf(self.card_images[('B', 'S')])
|
||||||
self.eb[(c, r)].set_tooltip_text('')
|
self.eb[(c, r)].set_tooltip_text('')
|
||||||
|
|
|
@ -35,72 +35,72 @@ import unittest
|
||||||
|
|
||||||
class TestSequenceFunctions(unittest.TestCase):
|
class TestSequenceFunctions(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Configure MySQL settings/database and establish connection"""
|
"""Configure MySQL settings/database and establish connection"""
|
||||||
self.c = Configuration.Config()
|
self.c = Configuration.Config()
|
||||||
self.mysql_settings={ 'db-host':"localhost",
|
self.mysql_settings={ 'db-host':"localhost",
|
||||||
'db-backend':2,
|
'db-backend':2,
|
||||||
'db-databaseName':"fpdbtest",
|
'db-databaseName':"fpdbtest",
|
||||||
'db-user':"fpdb",
|
'db-user':"fpdb",
|
||||||
'db-password':"fpdb"}
|
'db-password':"fpdb"}
|
||||||
self.mysql_db = fpdb_db.fpdb_db()
|
self.mysql_db = fpdb_db.fpdb_db()
|
||||||
self.mysql_db.connect(self.mysql_settings['db-backend'], self.mysql_settings['db-host'],
|
self.mysql_db.connect(self.mysql_settings['db-backend'], self.mysql_settings['db-host'],
|
||||||
self.mysql_settings['db-databaseName'], self.mysql_settings['db-user'],
|
self.mysql_settings['db-databaseName'], self.mysql_settings['db-user'],
|
||||||
self.mysql_settings['db-password'])
|
self.mysql_settings['db-password'])
|
||||||
self.mysqldict = FpdbSQLQueries.FpdbSQLQueries('MySQL InnoDB')
|
self.mysqldict = FpdbSQLQueries.FpdbSQLQueries('MySQL InnoDB')
|
||||||
self.mysqlimporter = fpdb_import.Importer(self, self.mysql_settings, self.c)
|
self.mysqlimporter = fpdb_import.Importer(self, self.mysql_settings, self.c)
|
||||||
self.mysqlimporter.setCallHud(False)
|
self.mysqlimporter.setCallHud(False)
|
||||||
|
|
||||||
# """Configure Postgres settings/database and establish connection"""
|
# """Configure Postgres settings/database and establish connection"""
|
||||||
# self.pg_settings={ 'db-host':"localhost", 'db-backend':3, 'db-databaseName':"fpdbtest", 'db-user':"fpdb", 'db-password':"fpdb"}
|
# self.pg_settings={ 'db-host':"localhost", 'db-backend':3, 'db-databaseName':"fpdbtest", 'db-user':"fpdb", 'db-password':"fpdb"}
|
||||||
# self.pg_db = fpdb_db.fpdb_db()
|
# self.pg_db = fpdb_db.fpdb_db()
|
||||||
# self.pg_db.connect(self.pg_settings['db-backend'], self.pg_settings['db-host'],
|
# self.pg_db.connect(self.pg_settings['db-backend'], self.pg_settings['db-host'],
|
||||||
# self.pg_settings['db-databaseName'], self.pg_settings['db-user'],
|
# self.pg_settings['db-databaseName'], self.pg_settings['db-user'],
|
||||||
# self.pg_settings['db-password'])
|
# self.pg_settings['db-password'])
|
||||||
# self.pgdict = FpdbSQLQueries.FpdbSQLQueries('PostgreSQL')
|
# self.pgdict = FpdbSQLQueries.FpdbSQLQueries('PostgreSQL')
|
||||||
|
|
||||||
|
|
||||||
def testDatabaseConnection(self):
|
def testDatabaseConnection(self):
|
||||||
"""Test all supported DBs"""
|
"""Test all supported DBs"""
|
||||||
self.result = self.mysql_db.cursor.execute(self.mysqldict.query['list_tables'])
|
self.result = self.mysql_db.cursor.execute(self.mysqldict.query['list_tables'])
|
||||||
self.failUnless(self.result==13, "Number of tables in database incorrect. Expected 13 got " + str(self.result))
|
self.failUnless(self.result==13, "Number of tables in database incorrect. Expected 13 got " + str(self.result))
|
||||||
|
|
||||||
# self.result = self.pg_db.cursor.execute(self.pgdict.query['list_tables'])
|
# self.result = self.pg_db.cursor.execute(self.pgdict.query['list_tables'])
|
||||||
# self.failUnless(self.result==13, "Number of tables in database incorrect. Expected 13 got " + str(self.result))
|
# self.failUnless(self.result==13, "Number of tables in database incorrect. Expected 13 got " + str(self.result))
|
||||||
|
|
||||||
def testMySQLRecreateTables(self):
|
def testMySQLRecreateTables(self):
|
||||||
"""Test droping then recreating fpdb table schema"""
|
"""Test droping then recreating fpdb table schema"""
|
||||||
self.mysql_db.recreate_tables()
|
self.mysql_db.recreate_tables()
|
||||||
self.result = self.mysql_db.cursor.execute("SHOW TABLES")
|
self.result = self.mysql_db.cursor.execute("SHOW TABLES")
|
||||||
self.failUnless(self.result==13, "Number of tables in database incorrect. Expected 13 got " + str(self.result))
|
self.failUnless(self.result==13, "Number of tables in database incorrect. Expected 13 got " + str(self.result))
|
||||||
|
|
||||||
def testPokerStarsHHDate(self):
|
def testPokerStarsHHDate(self):
|
||||||
latest = "PokerStars Game #21969660557: Hold'em No Limit ($0.50/$1.00) - 2008/11/12 10:00:48 CET [2008/11/12 4:00:48 ET]"
|
latest = "PokerStars Game #21969660557: Hold'em No Limit ($0.50/$1.00) - 2008/11/12 10:00:48 CET [2008/11/12 4:00:48 ET]"
|
||||||
previous = "PokerStars Game #21969660557: Hold'em No Limit ($0.50/$1.00) - 2008/08/17 - 01:14:43 (ET)"
|
previous = "PokerStars Game #21969660557: Hold'em No Limit ($0.50/$1.00) - 2008/08/17 - 01:14:43 (ET)"
|
||||||
older1 = "PokerStars Game #21969660557: Hold'em No Limit ($0.50/$1.00) - 2008/09/07 06:23:14 ET"
|
older1 = "PokerStars Game #21969660557: Hold'em No Limit ($0.50/$1.00) - 2008/09/07 06:23:14 ET"
|
||||||
|
|
||||||
result = fpdb_simple.parseHandStartTime(older1, "ps")
|
result = fpdb_simple.parseHandStartTime(older1, "ps")
|
||||||
self.failUnless(result==datetime.datetime(2008,9,7,11,23,14),
|
self.failUnless(result==datetime.datetime(2008,9,7,11,23,14),
|
||||||
"Date incorrect, expected: 2008-09-07 11:23:14 got: " + str(result))
|
"Date incorrect, expected: 2008-09-07 11:23:14 got: " + str(result))
|
||||||
result = fpdb_simple.parseHandStartTime(latest, "ps")
|
result = fpdb_simple.parseHandStartTime(latest, "ps")
|
||||||
self.failUnless(result==datetime.datetime(2008,11,12,15,00,48),
|
self.failUnless(result==datetime.datetime(2008,11,12,15,00,48),
|
||||||
"Date incorrect, expected: 2008-11-12 15:00:48 got: " + str(result))
|
"Date incorrect, expected: 2008-11-12 15:00:48 got: " + str(result))
|
||||||
result = fpdb_simple.parseHandStartTime(previous, "ps")
|
result = fpdb_simple.parseHandStartTime(previous, "ps")
|
||||||
self.failUnless(result==datetime.datetime(2008,8,17,6,14,43),
|
self.failUnless(result==datetime.datetime(2008,8,17,6,14,43),
|
||||||
"Date incorrect, expected: 2008-08-17 01:14:43 got: " + str(result))
|
"Date incorrect, expected: 2008-08-17 01:14:43 got: " + str(result))
|
||||||
|
|
||||||
def testImportHandHistoryFiles(self):
|
def testImportHandHistoryFiles(self):
|
||||||
"""Test import of single HH file"""
|
"""Test import of single HH file"""
|
||||||
self.mysqlimporter.addImportFile("regression-test-files/hand-histories/ps-lhe-ring-3hands.txt")
|
self.mysqlimporter.addImportFile("regression-test-files/hand-histories/ps-lhe-ring-3hands.txt")
|
||||||
self.mysqlimporter.runImport()
|
self.mysqlimporter.runImport()
|
||||||
self.mysqlimporter.addImportDirectory("regression-test-files/hand-histories")
|
self.mysqlimporter.addImportDirectory("regression-test-files/hand-histories")
|
||||||
self.mysqlimporter.runImport()
|
self.mysqlimporter.runImport()
|
||||||
|
|
||||||
# def testPostgresSQLRecreateTables(self):
|
# def testPostgresSQLRecreateTables(self):
|
||||||
# """Test droping then recreating fpdb table schema"""
|
# """Test droping then recreating fpdb table schema"""
|
||||||
# self.pg_db.recreate_tables()
|
# self.pg_db.recreate_tables()
|
||||||
# self.result = self.pg_db.cursor.execute(self.pgdict.query['list_tables'])
|
# self.result = self.pg_db.cursor.execute(self.pgdict.query['list_tables'])
|
||||||
# self.failUnless(self.result==13, "Number of tables in database incorrect. Expected 13 got " + str(self.result))
|
# self.failUnless(self.result==13, "Number of tables in database incorrect. Expected 13 got " + str(self.result))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -229,12 +229,11 @@ class Sql:
|
||||||
sum(street3CheckCallRaiseDone) AS ccr_3,
|
sum(street3CheckCallRaiseDone) AS ccr_3,
|
||||||
sum(street4CheckCallRaiseChance) AS ccr_opp_4,
|
sum(street4CheckCallRaiseChance) AS ccr_opp_4,
|
||||||
sum(street4CheckCallRaiseDone) AS ccr_4
|
sum(street4CheckCallRaiseDone) AS ccr_4
|
||||||
FROM HudCache, Hands
|
FROM Hands
|
||||||
WHERE HudCache.PlayerId in
|
INNER JOIN HandsPlayers ON (HandsPlayers.handId = %s)
|
||||||
(SELECT PlayerId FROM HandsPlayers
|
INNER JOIN HudCache ON ( HudCache.PlayerId = HandsPlayers.PlayerId+0
|
||||||
WHERE handId = %s)
|
AND HudCache.gametypeId+0 = Hands.gametypeId+0)
|
||||||
AND Hands.id = %s
|
WHERE Hands.id = %s
|
||||||
AND Hands.gametypeId = HudCache.gametypeId
|
|
||||||
GROUP BY HudCache.PlayerId
|
GROUP BY HudCache.PlayerId
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
110
pyfpdb/Stats.py
110
pyfpdb/Stats.py
|
@ -71,6 +71,7 @@ def do_stat(stat_dict, player = 24, stat = 'vpip'):
|
||||||
# functions that return individual stats
|
# functions that return individual stats
|
||||||
|
|
||||||
def playername(stat_dict, player):
|
def playername(stat_dict, player):
|
||||||
|
""" Player Name."""
|
||||||
return (stat_dict[player]['screen_name'],
|
return (stat_dict[player]['screen_name'],
|
||||||
stat_dict[player]['screen_name'],
|
stat_dict[player]['screen_name'],
|
||||||
stat_dict[player]['screen_name'],
|
stat_dict[player]['screen_name'],
|
||||||
|
@ -98,6 +99,26 @@ def vpip(stat_dict, player):
|
||||||
'Voluntarily Put In Pot %'
|
'Voluntarily Put In Pot %'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def vpip_0(stat_dict, player):
|
||||||
|
""" Voluntarily put $ in the pot (no decimals)."""
|
||||||
|
stat = 0.0
|
||||||
|
try:
|
||||||
|
stat = float(stat_dict[player]['vpip'])/float(stat_dict[player]['n'])
|
||||||
|
return (stat,
|
||||||
|
'%2.0f' % (100*stat) + '%',
|
||||||
|
'v=%2.0f' % (100*stat) + '%',
|
||||||
|
'vpip=%2.0f' % (100*stat) + '%',
|
||||||
|
'(%d/%d)' % (stat_dict[player]['vpip'], stat_dict[player]['n']),
|
||||||
|
'vpip'
|
||||||
|
)
|
||||||
|
except: return (stat,
|
||||||
|
'%2.0f' % (0) + '%',
|
||||||
|
'w=%2.0f' % (0) + '%',
|
||||||
|
'wtsd=%2.0f' % (0) + '%',
|
||||||
|
'(%d/%d)' % (0, 0),
|
||||||
|
'wtsd'
|
||||||
|
)
|
||||||
|
|
||||||
def pfr(stat_dict, player):
|
def pfr(stat_dict, player):
|
||||||
""" Preflop (3rd street) raise."""
|
""" Preflop (3rd street) raise."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
|
@ -119,6 +140,27 @@ def pfr(stat_dict, player):
|
||||||
'Pre-Flop Raise %'
|
'Pre-Flop Raise %'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def pfr_0(stat_dict, player):
|
||||||
|
""" Preflop (3rd street) raise (no decimals)."""
|
||||||
|
stat = 0.0
|
||||||
|
try:
|
||||||
|
stat = float(stat_dict[player]['pfr'])/float(stat_dict[player]['n'])
|
||||||
|
return (stat,
|
||||||
|
'%2.0f' % (100*stat) + '%',
|
||||||
|
'p=%2.0f' % (100*stat) + '%',
|
||||||
|
'pfr=%2.0f' % (100*stat) + '%',
|
||||||
|
'(%d/%d)' % (stat_dict[player]['pfr'], stat_dict[player]['n']),
|
||||||
|
'pfr'
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
return (stat,
|
||||||
|
'%2.0f' % (0) + '%',
|
||||||
|
'p=%2.0f' % (0) + '%',
|
||||||
|
'pfr=%2.0f' % (0) + '%',
|
||||||
|
'(%d/%d)' % (0, 0),
|
||||||
|
'pfr'
|
||||||
|
)
|
||||||
|
|
||||||
def wtsd(stat_dict, player):
|
def wtsd(stat_dict, player):
|
||||||
""" Went to SD when saw flop/4th."""
|
""" Went to SD when saw flop/4th."""
|
||||||
stat = 0.0
|
stat = 0.0
|
||||||
|
@ -149,7 +191,7 @@ def wmsd(stat_dict, player):
|
||||||
'%3.1f' % (100*stat) + '%',
|
'%3.1f' % (100*stat) + '%',
|
||||||
'w=%3.1f' % (100*stat) + '%',
|
'w=%3.1f' % (100*stat) + '%',
|
||||||
'wmsd=%3.1f' % (100*stat) + '%',
|
'wmsd=%3.1f' % (100*stat) + '%',
|
||||||
'(%f5.0/%d)' % (stat_dict[player]['wmsd'], stat_dict[player]['sd']),
|
'(%5.1f/%d)' % (float(stat_dict[player]['wmsd']), stat_dict[player]['sd']),
|
||||||
'% won money at showdown'
|
'% won money at showdown'
|
||||||
)
|
)
|
||||||
except:
|
except:
|
||||||
|
@ -412,6 +454,61 @@ def a_freq_4(stat_dict, player):
|
||||||
'(%d/%d)' % (0, 0),
|
'(%d/%d)' % (0, 0),
|
||||||
'Aggression Freq 7th'
|
'Aggression Freq 7th'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def a_freq_123(stat_dict, player):
|
||||||
|
""" Post-Flop aggression frequency."""
|
||||||
|
stat = 0.0
|
||||||
|
try:
|
||||||
|
stat = float( stat_dict[player]['aggr_1'] + stat_dict[player]['aggr_2'] + stat_dict[player]['aggr_3']
|
||||||
|
) / float( stat_dict[player]['saw_1'] + stat_dict[player]['saw_2'] + stat_dict[player]['saw_3']);
|
||||||
|
return (stat,
|
||||||
|
'%3.1f' % (100*stat) + '%',
|
||||||
|
'afq=%3.1f' % (100*stat) + '%',
|
||||||
|
'postf_aggfq=%3.1f' % (100*stat) + '%',
|
||||||
|
'(%d/%d)' % ( stat_dict[player]['aggr_1']
|
||||||
|
+ stat_dict[player]['aggr_2']
|
||||||
|
+ stat_dict[player]['aggr_3']
|
||||||
|
, stat_dict[player]['saw_1']
|
||||||
|
+ stat_dict[player]['saw_2']
|
||||||
|
+ stat_dict[player]['saw_3']
|
||||||
|
),
|
||||||
|
'Post-Flop Aggression Freq'
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
return (stat,
|
||||||
|
'%2.0f' % (0) + '%',
|
||||||
|
'a3=%2.0f' % (0) + '%',
|
||||||
|
'a_fq_3=%2.0f' % (0) + '%',
|
||||||
|
'(%d/%d)' % (0, 0),
|
||||||
|
'Post-Flop Aggression Freq'
|
||||||
|
)
|
||||||
|
|
||||||
|
def a_freq_123_0(stat_dict, player):
|
||||||
|
""" Post-Flop aggression frequency (no decimals)."""
|
||||||
|
stat = 0.0
|
||||||
|
try:
|
||||||
|
stat = float( stat_dict[player]['aggr_1'] + stat_dict[player]['aggr_2'] + stat_dict[player]['aggr_3']) / float( stat_dict[player]['saw_1'] + stat_dict[player]['saw_2'] + stat_dict[player]['saw_3']);
|
||||||
|
return (stat,
|
||||||
|
'%2.0f' % (100*stat) + '%',
|
||||||
|
'afq=%2.0f' % (100*stat) + '%',
|
||||||
|
'postf_aggfq=%2.0f' % (100*stat) + '%',
|
||||||
|
'(%d/%d)' % ( stat_dict[player]['aggr_1']
|
||||||
|
+ stat_dict[player]['aggr_2']
|
||||||
|
+ stat_dict[player]['aggr_3']
|
||||||
|
, stat_dict[player]['saw_1']
|
||||||
|
+ stat_dict[player]['saw_2']
|
||||||
|
+ stat_dict[player]['saw_3']
|
||||||
|
),
|
||||||
|
'Post-Flop Aggression Freq'
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
return (stat,
|
||||||
|
'%2.0f' % (0) + '%',
|
||||||
|
'a3=%2.0f' % (0) + '%',
|
||||||
|
'a_fq_3=%2.0f' % (0) + '%',
|
||||||
|
'(%d/%d)' % (0, 0),
|
||||||
|
'Post-Flop Aggression Freq'
|
||||||
|
)
|
||||||
|
|
||||||
def cb_1(stat_dict, player):
|
def cb_1(stat_dict, player):
|
||||||
""" Flop continuation bet."""
|
""" Flop continuation bet."""
|
||||||
|
@ -589,7 +686,9 @@ if __name__== "__main__":
|
||||||
|
|
||||||
for player in stat_dict.keys():
|
for player in stat_dict.keys():
|
||||||
print "player = ", player, do_stat(stat_dict, player = player, stat = 'vpip')
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'vpip')
|
||||||
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'vpip_0')
|
||||||
print "player = ", player, do_stat(stat_dict, player = player, stat = 'pfr')
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'pfr')
|
||||||
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'pfr_0')
|
||||||
print "player = ", player, do_stat(stat_dict, player = player, stat = 'wtsd')
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'wtsd')
|
||||||
print "player = ", player, do_stat(stat_dict, player = player, stat = 'saw_f')
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'saw_f')
|
||||||
print "player = ", player, do_stat(stat_dict, player = player, stat = 'n')
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'n')
|
||||||
|
@ -604,6 +703,8 @@ if __name__== "__main__":
|
||||||
print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_2')
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_2')
|
||||||
print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_3')
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_3')
|
||||||
print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_4')
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_4')
|
||||||
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_123')
|
||||||
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_123_0')
|
||||||
print "player = ", player, do_stat(stat_dict, player = player, stat = 'cb_1')
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'cb_1')
|
||||||
print "player = ", player, do_stat(stat_dict, player = player, stat = 'cb_2')
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'cb_2')
|
||||||
print "player = ", player, do_stat(stat_dict, player = player, stat = 'cb_3')
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'cb_3')
|
||||||
|
@ -611,7 +712,8 @@ if __name__== "__main__":
|
||||||
print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_1')
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_1')
|
||||||
print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_2')
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_2')
|
||||||
print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_3')
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_3')
|
||||||
print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_4')
|
print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_4')
|
||||||
|
print "\n"
|
||||||
|
|
||||||
print "\n\nLegal stats:"
|
print "\n\nLegal stats:"
|
||||||
for attr in dir():
|
for attr in dir():
|
||||||
|
@ -619,8 +721,8 @@ if __name__== "__main__":
|
||||||
if attr in ("Configuration", "Database", "GInitiallyUnowned", "gtk", "pygtk",
|
if attr in ("Configuration", "Database", "GInitiallyUnowned", "gtk", "pygtk",
|
||||||
"player", "c", "db_connection", "do_stat", "do_tip", "stat_dict",
|
"player", "c", "db_connection", "do_stat", "do_tip", "stat_dict",
|
||||||
"h"): continue
|
"h"): continue
|
||||||
print attr, eval("%s.__doc__" % (attr))
|
print "%-14s %s" % (attr, eval("%s.__doc__" % (attr)))
|
||||||
# print " <pu_stat pu_stat_name = \"%s\"> </pu_stat>" % (attr)
|
# print " <pu_stat pu_stat_name = \"%s\"> </pu_stat>" % (attr)
|
||||||
|
|
||||||
db_connection.close
|
db_connection.close_connection
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ import gtk
|
||||||
import fpdb_db
|
import fpdb_db
|
||||||
import fpdb_simple
|
import fpdb_simple
|
||||||
import GuiBulkImport
|
import GuiBulkImport
|
||||||
|
import GuiPlayerStats
|
||||||
import GuiTableViewer
|
import GuiTableViewer
|
||||||
import GuiAutoImport
|
import GuiAutoImport
|
||||||
import GuiGraphViewer
|
import GuiGraphViewer
|
||||||
|
@ -117,12 +118,12 @@ class fpdb:
|
||||||
|
|
||||||
def dia_create_del_database(self, widget, data):
|
def dia_create_del_database(self, widget, data):
|
||||||
print "todo: implement dia_create_del_database"
|
print "todo: implement dia_create_del_database"
|
||||||
obtain_global_lock()
|
self.obtain_global_lock()
|
||||||
#end def dia_create_del_database
|
#end def dia_create_del_database
|
||||||
|
|
||||||
def dia_create_del_user(self, widget, data):
|
def dia_create_del_user(self, widget, data):
|
||||||
print "todo: implement dia_create_del_user"
|
print "todo: implement dia_create_del_user"
|
||||||
obtain_global_lock()
|
self.obtain_global_lock()
|
||||||
#end def dia_create_del_user
|
#end def dia_create_del_user
|
||||||
|
|
||||||
def dia_database_stats(self, widget, data):
|
def dia_database_stats(self, widget, data):
|
||||||
|
@ -132,17 +133,17 @@ class fpdb:
|
||||||
|
|
||||||
def dia_delete_db_parts(self, widget, data):
|
def dia_delete_db_parts(self, widget, data):
|
||||||
print "todo: implement dia_delete_db_parts"
|
print "todo: implement dia_delete_db_parts"
|
||||||
obtain_global_lock()
|
self.obtain_global_lock()
|
||||||
#end def dia_delete_db_parts
|
#end def dia_delete_db_parts
|
||||||
|
|
||||||
def dia_edit_profile(self, widget=None, data=None, create_default=False, path=None):
|
def dia_edit_profile(self, widget=None, data=None, create_default=False, path=None):
|
||||||
print "todo: implement dia_edit_profile"
|
print "todo: implement dia_edit_profile"
|
||||||
obtain_global_lock()
|
self.obtain_global_lock()
|
||||||
#end def dia_edit_profile
|
#end def dia_edit_profile
|
||||||
|
|
||||||
def dia_export_db(self, widget, data):
|
def dia_export_db(self, widget, data):
|
||||||
print "todo: implement dia_export_db"
|
print "todo: implement dia_export_db"
|
||||||
obtain_global_lock()
|
self.obtain_global_lock()
|
||||||
#end def dia_export_db
|
#end def dia_export_db
|
||||||
|
|
||||||
def dia_get_db_root_credentials(self):
|
def dia_get_db_root_credentials(self):
|
||||||
|
@ -167,7 +168,7 @@ class fpdb:
|
||||||
|
|
||||||
def dia_import_db(self, widget, data):
|
def dia_import_db(self, widget, data):
|
||||||
print "todo: implement dia_import_db"
|
print "todo: implement dia_import_db"
|
||||||
obtain_global_lock()
|
self.obtain_global_lock()
|
||||||
#end def dia_import_db
|
#end def dia_import_db
|
||||||
|
|
||||||
def dia_licensing(self, widget, data):
|
def dia_licensing(self, widget, data):
|
||||||
|
@ -263,7 +264,11 @@ class fpdb:
|
||||||
|
|
||||||
self.db = fpdb_db.fpdb_db()
|
self.db = fpdb_db.fpdb_db()
|
||||||
#print "end of fpdb.load_profile, databaseName:",self.settings['db-databaseName']
|
#print "end of fpdb.load_profile, databaseName:",self.settings['db-databaseName']
|
||||||
self.db.connect(self.settings['db-backend'], self.settings['db-host'], self.settings['db-databaseName'], self.settings['db-user'], self.settings['db-password'])
|
self.db.connect(self.settings['db-backend'],
|
||||||
|
self.settings['db-host'],
|
||||||
|
self.settings['db-databaseName'],
|
||||||
|
self.settings['db-user'],
|
||||||
|
self.settings['db-password'])
|
||||||
if self.db.wrongDbVersion:
|
if self.db.wrongDbVersion:
|
||||||
diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK))
|
diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK))
|
||||||
|
|
||||||
|
@ -283,7 +288,7 @@ class fpdb:
|
||||||
diaDbVersionWarning.destroy()
|
diaDbVersionWarning.destroy()
|
||||||
|
|
||||||
# Database connected to successfully, load queries to pass on to other classes
|
# Database connected to successfully, load queries to pass on to other classes
|
||||||
self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name())
|
self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name())
|
||||||
#end def load_profile
|
#end def load_profile
|
||||||
|
|
||||||
def not_implemented(self):
|
def not_implemented(self):
|
||||||
|
@ -326,6 +331,13 @@ class fpdb:
|
||||||
self.add_and_display_tab(bulk_tab, "Bulk Import")
|
self.add_and_display_tab(bulk_tab, "Bulk Import")
|
||||||
#end def tab_bulk_import
|
#end def tab_bulk_import
|
||||||
|
|
||||||
|
def tab_player_stats(self, widget, data):
|
||||||
|
new_ps_thread=GuiPlayerStats.GuiPlayerStats(self.db, self.config, self.querydict)
|
||||||
|
self.threads.append(new_ps_thread)
|
||||||
|
ps_tab=new_ps_thread.get_vbox()
|
||||||
|
self.add_and_display_tab(ps_tab, "Player Stats")
|
||||||
|
|
||||||
|
|
||||||
def tab_main_help(self, widget, data):
|
def tab_main_help(self, widget, data):
|
||||||
"""Displays a tab with the main fpdb help screen"""
|
"""Displays a tab with the main fpdb help screen"""
|
||||||
#print "start of tab_main_help"
|
#print "start of tab_main_help"
|
||||||
|
@ -384,7 +396,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
|
||||||
("/Viewers/_Graphs", "<control>G", self.tabGraphViewer, 0, None ),
|
("/Viewers/_Graphs", "<control>G", self.tabGraphViewer, 0, None ),
|
||||||
("/Viewers/Hand _Replayer (todo)", None, self.not_implemented, 0, None ),
|
("/Viewers/Hand _Replayer (todo)", None, self.not_implemented, 0, None ),
|
||||||
("/Viewers/Player _Details (todo)", None, self.not_implemented, 0, None ),
|
("/Viewers/Player _Details (todo)", None, self.not_implemented, 0, None ),
|
||||||
("/Viewers/_Player Stats (tabulated view) (todo)", None, self.not_implemented, 0, None ),
|
("/Viewers/_Player Stats (tabulated view)", None, self.tab_player_stats, 0, None ),
|
||||||
("/Viewers/Starting _Hands (todo)", None, self.not_implemented, 0, None ),
|
("/Viewers/Starting _Hands (todo)", None, self.not_implemented, 0, None ),
|
||||||
("/Viewers/_Session Replayer (todo)", None, self.not_implemented, 0, None ),
|
("/Viewers/_Session Replayer (todo)", None, self.not_implemented, 0, None ),
|
||||||
("/Viewers/Poker_table Viewer (mostly obselete)", "<control>T", self.tab_table_viewer, 0, None ),
|
("/Viewers/Poker_table Viewer (mostly obselete)", "<control>T", self.tab_table_viewer, 0, None ),
|
||||||
|
|
292
pyfpdb/fpdb_db.py
Executable file → Normal file
292
pyfpdb/fpdb_db.py
Executable file → Normal file
|
@ -21,153 +21,171 @@ import fpdb_simple
|
||||||
import FpdbSQLQueries
|
import FpdbSQLQueries
|
||||||
|
|
||||||
class fpdb_db:
|
class fpdb_db:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Simple constructor, doesnt really do anything"""
|
"""Simple constructor, doesnt really do anything"""
|
||||||
self.db=None
|
self.db=None
|
||||||
self.cursor=None
|
self.cursor=None
|
||||||
self.sql = {}
|
self.sql = {}
|
||||||
self.MYSQL_INNODB=2
|
self.MYSQL_INNODB=2
|
||||||
self.PGSQL=3
|
self.PGSQL=3
|
||||||
self.SQLITE=4
|
self.SQLITE=4
|
||||||
#end def __init__
|
#end def __init__
|
||||||
|
|
||||||
def connect(self, backend, host, database, user, password):
|
def connect(self, backend=None, host=None, database=None,
|
||||||
"""Connects a database with the given parameters"""
|
user=None, password=None):
|
||||||
self.backend=backend
|
"""Connects a database with the given parameters"""
|
||||||
self.host=host
|
if backend is None:
|
||||||
self.database=database
|
raise FpdbError('Database backend not defined')
|
||||||
self.user=user
|
self.backend=backend
|
||||||
self.password=password
|
self.host=host
|
||||||
if backend==self.MYSQL_INNODB:
|
self.user=user
|
||||||
import MySQLdb
|
self.password=password
|
||||||
self.db=MySQLdb.connect(host = host, user = user, passwd = password, db = database)
|
self.database=database
|
||||||
elif backend==self.PGSQL:
|
if backend==self.MYSQL_INNODB:
|
||||||
import psycopg2
|
import MySQLdb
|
||||||
self.db = psycopg2.connect(host = host, user = user, password = password, database = database)
|
self.db=MySQLdb.connect(host = host, user = user, passwd = password, db = database)
|
||||||
else:
|
elif backend==self.PGSQL:
|
||||||
raise fpdb_simple.FpdbError("unrecognised database backend:"+backend)
|
import psycopg2
|
||||||
self.cursor=self.db.cursor()
|
# If DB connection is made over TCP, then the variables
|
||||||
self.cursor.execute('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED')
|
# host, user and password are required
|
||||||
# Set up query dictionary as early in the connection process as we can.
|
print "host=%s user=%s pass=%s." % (host, user, password)
|
||||||
self.sql = FpdbSQLQueries.FpdbSQLQueries(self.get_backend_name())
|
if self.host and self.user and self.password:
|
||||||
self.wrongDbVersion=False
|
self.db = psycopg2.connect(host = host,
|
||||||
try:
|
user = user,
|
||||||
self.cursor.execute("SELECT * FROM Settings")
|
password = password,
|
||||||
settings=self.cursor.fetchone()
|
database = database)
|
||||||
if settings[0]!=118:
|
# For local domain-socket connections, only DB name is
|
||||||
print "outdated or too new database version - please recreate tables"
|
# needed, and everything else is in fact undefined and/or
|
||||||
self.wrongDbVersion=True
|
# flat out wrong
|
||||||
except:# _mysql_exceptions.ProgrammingError:
|
else:
|
||||||
print "failed to read settings table - please recreate tables"
|
self.db = psycopg2.connect(database = database)
|
||||||
self.wrongDbVersion=True
|
else:
|
||||||
#end def connect
|
raise fpdb_simple.FpdbError("unrecognised database backend:"+backend)
|
||||||
|
self.cursor=self.db.cursor()
|
||||||
|
self.cursor.execute('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED')
|
||||||
|
# Set up query dictionary as early in the connection process as we can.
|
||||||
|
self.sql = FpdbSQLQueries.FpdbSQLQueries(self.get_backend_name())
|
||||||
|
self.wrongDbVersion=False
|
||||||
|
try:
|
||||||
|
self.cursor.execute("SELECT * FROM Settings")
|
||||||
|
settings=self.cursor.fetchone()
|
||||||
|
if settings[0]!=118:
|
||||||
|
print "outdated or too new database version - please recreate tables"
|
||||||
|
self.wrongDbVersion=True
|
||||||
|
except:# _mysql_exceptions.ProgrammingError:
|
||||||
|
print "failed to read settings table - please recreate tables"
|
||||||
|
self.wrongDbVersion=True
|
||||||
|
#end def connect
|
||||||
|
|
||||||
def disconnect(self, due_to_error=False):
|
def disconnect(self, due_to_error=False):
|
||||||
"""Disconnects the DB"""
|
"""Disconnects the DB"""
|
||||||
if due_to_error:
|
if due_to_error:
|
||||||
self.db.rollback()
|
self.db.rollback()
|
||||||
else:
|
else:
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
self.cursor.close()
|
self.cursor.close()
|
||||||
self.db.close()
|
self.db.close()
|
||||||
#end def disconnect
|
#end def disconnect
|
||||||
|
|
||||||
def reconnect(self, due_to_error=False):
|
def reconnect(self, due_to_error=False):
|
||||||
"""Reconnects the DB"""
|
"""Reconnects the DB"""
|
||||||
#print "started fpdb_db.reconnect"
|
#print "started fpdb_db.reconnect"
|
||||||
self.disconnect(due_to_error)
|
self.disconnect(due_to_error)
|
||||||
self.connect(self.backend, self.host, self.database, self.user, self.password)
|
self.connect(self.backend, self.host, self.database, self.user, self.password)
|
||||||
|
|
||||||
def create_tables(self):
|
def create_tables(self):
|
||||||
#todo: should detect and fail gracefully if tables already exist.
|
#todo: should detect and fail gracefully if tables already exist.
|
||||||
self.cursor.execute(self.sql.query['createSettingsTable'])
|
self.cursor.execute(self.sql.query['createSettingsTable'])
|
||||||
self.cursor.execute(self.sql.query['createSitesTable'])
|
self.cursor.execute(self.sql.query['createSitesTable'])
|
||||||
self.cursor.execute(self.sql.query['createGametypesTable'])
|
self.cursor.execute(self.sql.query['createGametypesTable'])
|
||||||
self.cursor.execute(self.sql.query['createPlayersTable'])
|
self.cursor.execute(self.sql.query['createPlayersTable'])
|
||||||
self.cursor.execute(self.sql.query['createAutoratesTable'])
|
self.cursor.execute(self.sql.query['createAutoratesTable'])
|
||||||
self.cursor.execute(self.sql.query['createHandsTable'])
|
self.cursor.execute(self.sql.query['createHandsTable'])
|
||||||
self.cursor.execute(self.sql.query['createBoardCardsTable'])
|
self.cursor.execute(self.sql.query['createBoardCardsTable'])
|
||||||
self.cursor.execute(self.sql.query['createTourneyTypesTable'])
|
self.cursor.execute(self.sql.query['createTourneyTypesTable'])
|
||||||
self.cursor.execute(self.sql.query['createTourneysTable'])
|
self.cursor.execute(self.sql.query['createTourneysTable'])
|
||||||
self.cursor.execute(self.sql.query['createTourneysPlayersTable'])
|
self.cursor.execute(self.sql.query['createTourneysPlayersTable'])
|
||||||
self.cursor.execute(self.sql.query['createHandsPlayersTable'])
|
self.cursor.execute(self.sql.query['createHandsPlayersTable'])
|
||||||
self.cursor.execute(self.sql.query['createHandsActionsTable'])
|
self.cursor.execute(self.sql.query['createHandsActionsTable'])
|
||||||
self.cursor.execute(self.sql.query['createHudCacheTable'])
|
self.cursor.execute(self.sql.query['createHudCacheTable'])
|
||||||
self.fillDefaultData()
|
self.cursor.execute(self.sql.query['addTourneyIndex'])
|
||||||
self.db.commit()
|
self.cursor.execute(self.sql.query['addHandsIndex'])
|
||||||
|
self.cursor.execute(self.sql.query['addPlayersIndex'])
|
||||||
|
self.fillDefaultData()
|
||||||
|
self.db.commit()
|
||||||
#end def disconnect
|
#end def disconnect
|
||||||
|
|
||||||
def drop_tables(self):
|
def drop_tables(self):
|
||||||
"""Drops the fpdb tables from the current db"""
|
"""Drops the fpdb tables from the current db"""
|
||||||
|
|
||||||
if(self.get_backend_name() == 'MySQL InnoDB'):
|
if(self.get_backend_name() == 'MySQL InnoDB'):
|
||||||
#Databases with FOREIGN KEY support need this switched of before you can drop tables
|
#Databases with FOREIGN KEY support need this switched of before you can drop tables
|
||||||
self.drop_referencial_integrity()
|
self.drop_referencial_integrity()
|
||||||
|
|
||||||
# Query the DB to see what tables exist
|
# Query the DB to see what tables exist
|
||||||
self.cursor.execute(self.sql.query['list_tables'])
|
self.cursor.execute(self.sql.query['list_tables'])
|
||||||
for table in self.cursor:
|
for table in self.cursor:
|
||||||
self.cursor.execute(self.sql.query['drop_table'] + table[0])
|
self.cursor.execute(self.sql.query['drop_table'] + table[0])
|
||||||
elif(self.get_backend_name() == 'PostgreSQL'):
|
elif(self.get_backend_name() == 'PostgreSQL'):
|
||||||
self.db.commit()# I have no idea why this makes the query work--REB 07OCT2008
|
self.db.commit()# I have no idea why this makes the query work--REB 07OCT2008
|
||||||
self.cursor.execute(self.sql.query['list_tables'])
|
self.cursor.execute(self.sql.query['list_tables'])
|
||||||
tables = self.cursor.fetchall()
|
tables = self.cursor.fetchall()
|
||||||
for table in tables:
|
for table in tables:
|
||||||
self.cursor.execute(self.sql.query['drop_table'] + table[0] + ' cascade')
|
self.cursor.execute(self.sql.query['drop_table'] + table[0] + ' cascade')
|
||||||
elif(self.get_backend_name() == 'SQLite'):
|
elif(self.get_backend_name() == 'SQLite'):
|
||||||
#todo: sqlite version here
|
#todo: sqlite version here
|
||||||
print "Empty function here"
|
print "Empty function here"
|
||||||
|
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
#end def drop_tables
|
#end def drop_tables
|
||||||
|
|
||||||
def drop_referencial_integrity(self):
|
def drop_referencial_integrity(self):
|
||||||
"""Update all tables to remove foreign keys"""
|
"""Update all tables to remove foreign keys"""
|
||||||
|
|
||||||
self.cursor.execute(self.sql.query['list_tables'])
|
self.cursor.execute(self.sql.query['list_tables'])
|
||||||
result = self.cursor.fetchall()
|
result = self.cursor.fetchall()
|
||||||
|
|
||||||
for i in range(len(result)):
|
for i in range(len(result)):
|
||||||
self.cursor.execute("SHOW CREATE TABLE " + result[i][0])
|
self.cursor.execute("SHOW CREATE TABLE " + result[i][0])
|
||||||
inner = self.cursor.fetchall()
|
inner = self.cursor.fetchall()
|
||||||
|
|
||||||
for j in range(len(inner)):
|
for j in range(len(inner)):
|
||||||
# result[i][0] - Table name
|
# result[i][0] - Table name
|
||||||
# result[i][1] - CREATE TABLE parameters
|
# result[i][1] - CREATE TABLE parameters
|
||||||
#Searching for CONSTRAINT `tablename_ibfk_1`
|
#Searching for CONSTRAINT `tablename_ibfk_1`
|
||||||
for m in re.finditer('(ibfk_[0-9]+)', inner[j][1]):
|
for m in re.finditer('(ibfk_[0-9]+)', inner[j][1]):
|
||||||
key = "`" + inner[j][0] + "_" + m.group() + "`"
|
key = "`" + inner[j][0] + "_" + m.group() + "`"
|
||||||
self.cursor.execute("ALTER TABLE " + inner[j][0] + " DROP FOREIGN KEY " + key)
|
self.cursor.execute("ALTER TABLE " + inner[j][0] + " DROP FOREIGN KEY " + key)
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
#end drop_referencial_inegrity
|
#end drop_referencial_inegrity
|
||||||
|
|
||||||
def get_backend_name(self):
|
def get_backend_name(self):
|
||||||
"""Returns the name of the currently used backend"""
|
"""Returns the name of the currently used backend"""
|
||||||
if self.backend==2:
|
if self.backend==2:
|
||||||
return "MySQL InnoDB"
|
return "MySQL InnoDB"
|
||||||
elif self.backend==3:
|
elif self.backend==3:
|
||||||
return "PostgreSQL"
|
return "PostgreSQL"
|
||||||
else:
|
else:
|
||||||
raise fpdb_simple.FpdbError("invalid backend")
|
raise fpdb_simple.FpdbError("invalid backend")
|
||||||
#end def get_backend_name
|
#end def get_backend_name
|
||||||
|
|
||||||
def get_db_info(self):
|
def get_db_info(self):
|
||||||
return (self.host, self.database, self.user, self.password)
|
return (self.host, self.database, self.user, self.password)
|
||||||
#end def get_db_info
|
#end def get_db_info
|
||||||
|
|
||||||
def fillDefaultData(self):
|
def fillDefaultData(self):
|
||||||
self.cursor.execute("INSERT INTO Settings VALUES (118);")
|
self.cursor.execute("INSERT INTO Settings VALUES (118);")
|
||||||
self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'Full Tilt Poker', 'USD');")
|
self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'Full Tilt Poker', 'USD');")
|
||||||
self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'PokerStars', 'USD');")
|
self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'PokerStars', 'USD');")
|
||||||
self.cursor.execute("INSERT INTO TourneyTypes VALUES (DEFAULT, 1, 0, 0, 0, False);")
|
self.cursor.execute("INSERT INTO TourneyTypes VALUES (DEFAULT, 1, 0, 0, 0, False);")
|
||||||
#end def fillDefaultData
|
#end def fillDefaultData
|
||||||
|
|
||||||
def recreate_tables(self):
|
def recreate_tables(self):
|
||||||
"""(Re-)creates the tables of the current DB"""
|
"""(Re-)creates the tables of the current DB"""
|
||||||
|
|
||||||
self.drop_tables()
|
self.drop_tables()
|
||||||
self.create_tables()
|
self.create_tables()
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
print "Finished recreating tables"
|
print "Finished recreating tables"
|
||||||
#end def recreate_tables
|
#end def recreate_tables
|
||||||
#end class fpdb_db
|
#end class fpdb_db
|
||||||
|
|
508
pyfpdb/fpdb_import.py
Executable file → Normal file
508
pyfpdb/fpdb_import.py
Executable file → Normal file
|
@ -20,16 +20,16 @@
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import MySQLdb
|
import MySQLdb
|
||||||
mysqlLibFound=True
|
mysqlLibFound=True
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import psycopg2
|
import psycopg2
|
||||||
pgsqlLibFound=True
|
pgsqlLibFound=True
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
import traceback
|
import traceback
|
||||||
import math
|
import math
|
||||||
|
@ -42,274 +42,282 @@ from time import time
|
||||||
|
|
||||||
class Importer:
|
class Importer:
|
||||||
|
|
||||||
def __init__(self, caller, settings, config):
|
def __init__(self, caller, settings, config):
|
||||||
"""Constructor"""
|
"""Constructor"""
|
||||||
self.settings=settings
|
self.settings=settings
|
||||||
self.caller=caller
|
self.caller=caller
|
||||||
self.config = config
|
self.config = config
|
||||||
self.db = None
|
self.db = None
|
||||||
self.cursor = None
|
self.cursor = None
|
||||||
self.filelist = {}
|
self.filelist = {}
|
||||||
self.dirlist = {}
|
self.dirlist = {}
|
||||||
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
|
||||||
self.faobs = None #File as one big string
|
self.faobs = None #File as one big string
|
||||||
self.pos_in_file = {} # dict to remember how far we have read in the file
|
self.pos_in_file = {} # dict to remember how far we have read in the file
|
||||||
#Set defaults
|
#Set defaults
|
||||||
self.callHud = self.config.get_import_parameters().get("callFpdbHud")
|
self.callHud = self.config.get_import_parameters().get("callFpdbHud")
|
||||||
if not self.settings.has_key('minPrint'):
|
if not self.settings.has_key('minPrint'):
|
||||||
self.settings['minPrint'] = 30
|
self.settings['minPrint'] = 30
|
||||||
self.dbConnect()
|
self.dbConnect()
|
||||||
|
|
||||||
def dbConnect(self):
|
# XXX: Why is this here, when fpdb_db.connect() already does the
|
||||||
#connect to DB
|
# same?
|
||||||
if self.settings['db-backend'] == 2:
|
def dbConnect(self):
|
||||||
if not mysqlLibFound:
|
#connect to DB
|
||||||
raise fpdb_simple.FpdbError("interface library MySQLdb not found but MySQL selected as backend - please install the library or change the config file")
|
if self.settings['db-backend'] == 2:
|
||||||
self.db = MySQLdb.connect(self.settings['db-host'], self.settings['db-user'],
|
if not mysqlLibFound:
|
||||||
self.settings['db-password'], self.settings['db-databaseName'])
|
raise fpdb_simple.FpdbError("interface library MySQLdb not found but MySQL selected as backend - please install the library or change the config file")
|
||||||
elif self.settings['db-backend'] == 3:
|
self.db = MySQLdb.connect(self.settings['db-host'], self.settings['db-user'],
|
||||||
if not pgsqlLibFound:
|
self.settings['db-password'], self.settings['db-databaseName'])
|
||||||
raise fpdb_simple.FpdbError("interface library psycopg2 not found but PostgreSQL selected as backend - please install the library or change the config file")
|
elif self.settings['db-backend'] == 3:
|
||||||
print self.settings
|
if not pgsqlLibFound:
|
||||||
self.db = psycopg2.connect(host = self.settings['db-host'],
|
raise fpdb_simple.FpdbError("interface library psycopg2 not found but PostgreSQL selected as backend - please install the library or change the config file")
|
||||||
user = self.settings['db-user'],
|
print self.settings
|
||||||
password = self.settings['db-password'],
|
if self.settings.has_key('db-host') and \
|
||||||
database = self.settings['db-databaseName'])
|
self.settings.has_key('db-user'):
|
||||||
elif self.settings['db-backend'] == 4:
|
self.db = psycopg2.connect(host = self.settings['db-host'],
|
||||||
pass
|
user = self.settings['db-user'],
|
||||||
else:
|
password = self.settings['db-password'],
|
||||||
pass
|
database = self.settings['db-databaseName'])
|
||||||
self.cursor = self.db.cursor()
|
else:
|
||||||
|
dbname = self.settings['db-databaseName']
|
||||||
|
self.db = psycopg2.connect(database = dbname)
|
||||||
|
elif self.settings['db-backend'] == 4:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
self.cursor = self.db.cursor()
|
||||||
|
|
||||||
#Set functions
|
#Set functions
|
||||||
def setCallHud(self, value):
|
def setCallHud(self, value):
|
||||||
self.callHud = value
|
self.callHud = value
|
||||||
|
|
||||||
def setMinPrint(self, value):
|
def setMinPrint(self, value):
|
||||||
self.settings['minPrint'] = int(value)
|
self.settings['minPrint'] = int(value)
|
||||||
|
|
||||||
def setHandCount(self, value):
|
def setHandCount(self, value):
|
||||||
self.settings['handCount'] = int(value)
|
self.settings['handCount'] = int(value)
|
||||||
|
|
||||||
def setQuiet(self, value):
|
def setQuiet(self, value):
|
||||||
self.settings['quiet'] = value
|
self.settings['quiet'] = value
|
||||||
|
|
||||||
def setFailOnError(self, value):
|
def setFailOnError(self, value):
|
||||||
self.settings['failOnError'] = value
|
self.settings['failOnError'] = value
|
||||||
|
|
||||||
# def setWatchTime(self):
|
# def setWatchTime(self):
|
||||||
# self.updated = time()
|
# self.updated = time()
|
||||||
|
|
||||||
def clearFileList(self):
|
def clearFileList(self):
|
||||||
self.filelist = {}
|
self.filelist = {}
|
||||||
|
|
||||||
#Add an individual file to filelist
|
#Add an individual file to filelist
|
||||||
def addImportFile(self, filename, site = "default", filter = "passthrough"):
|
def addImportFile(self, filename, site = "default", filter = "passthrough"):
|
||||||
#TODO: test it is a valid file
|
#TODO: test it is a valid file
|
||||||
self.filelist[filename] = [site] + [filter]
|
self.filelist[filename] = [site] + [filter]
|
||||||
|
|
||||||
#Add a directory of files to filelist
|
#Add a directory of files to filelist
|
||||||
#Only one import directory per site supported.
|
#Only one import directory per site supported.
|
||||||
#dirlist is a hash of lists:
|
#dirlist is a hash of lists:
|
||||||
#dirlist{ 'PokerStars' => ["/path/to/import/", "filtername"] }
|
#dirlist{ 'PokerStars' => ["/path/to/import/", "filtername"] }
|
||||||
def addImportDirectory(self,dir,monitor = False, site = "default", filter = "passthrough"):
|
def addImportDirectory(self,dir,monitor = False, site = "default", filter = "passthrough"):
|
||||||
if os.path.isdir(dir):
|
if os.path.isdir(dir):
|
||||||
if monitor == True:
|
if monitor == True:
|
||||||
self.monitor = True
|
self.monitor = True
|
||||||
self.dirlist[site] = [dir] + [filter]
|
self.dirlist[site] = [dir] + [filter]
|
||||||
|
|
||||||
for file in os.listdir(dir):
|
for file in os.listdir(dir):
|
||||||
self.addImportFile(os.path.join(dir, file), site, filter)
|
self.addImportFile(os.path.join(dir, file), site, filter)
|
||||||
else:
|
else:
|
||||||
print "Warning: Attempted to add: '" + str(dir) + "' as an import directory"
|
print "Warning: Attempted to add: '" + str(dir) + "' as an import directory"
|
||||||
|
|
||||||
#Run full import on filelist
|
#Run full import on filelist
|
||||||
def runImport(self):
|
def runImport(self):
|
||||||
for file in self.filelist:
|
for file in self.filelist:
|
||||||
self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1])
|
self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1])
|
||||||
|
|
||||||
#Run import on updated files, then store latest update time.
|
#Run import on updated files, then store latest update time.
|
||||||
def runUpdated(self):
|
def runUpdated(self):
|
||||||
#Check for new files in directory
|
#Check for new files in directory
|
||||||
#todo: make efficient - always checks for new file, should be able to use mtime of directory
|
#todo: make efficient - always checks for new file, should be able to use mtime of directory
|
||||||
# ^^ May not work on windows
|
# ^^ May not work on windows
|
||||||
for site in self.dirlist:
|
for site in self.dirlist:
|
||||||
self.addImportDirectory(self.dirlist[site][0], False, site, self.dirlist[site][1])
|
self.addImportDirectory(self.dirlist[site][0], False, site, self.dirlist[site][1])
|
||||||
|
|
||||||
for file in self.filelist:
|
for file in self.filelist:
|
||||||
stat_info = os.stat(file)
|
stat_info = os.stat(file)
|
||||||
try:
|
try:
|
||||||
lastupdate = self.updated[file]
|
lastupdate = self.updated[file]
|
||||||
if stat_info.st_mtime > lastupdate:
|
if stat_info.st_mtime > lastupdate:
|
||||||
self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1])
|
self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1])
|
||||||
self.updated[file] = time()
|
self.updated[file] = time()
|
||||||
except:
|
except:
|
||||||
self.updated[file] = time()
|
self.updated[file] = time()
|
||||||
# This codepath only runs first time the file is found, if modified in the last
|
# This codepath only runs first time the file is found, if modified in the last
|
||||||
# minute run an immediate import.
|
# minute run an immediate import.
|
||||||
if (time() - stat_info.st_mtime) < 60:
|
if (time() - stat_info.st_mtime) < 60:
|
||||||
self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1])
|
self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1])
|
||||||
|
|
||||||
# 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):
|
||||||
if(filter == "passthrough"):
|
if(filter == "passthrough"):
|
||||||
self.import_fpdb_file(file, site)
|
self.import_fpdb_file(file, site)
|
||||||
else:
|
else:
|
||||||
#Load filter, and run filtered file though main importer
|
#Load filter, and run filtered file though main importer
|
||||||
self.import_fpdb_file(file, site)
|
self.import_fpdb_file(file, site)
|
||||||
|
|
||||||
|
|
||||||
def import_fpdb_file(self, file, site):
|
def import_fpdb_file(self, file, site):
|
||||||
starttime = time()
|
starttime = time()
|
||||||
last_read_hand=0
|
last_read_hand=0
|
||||||
loc = 0
|
loc = 0
|
||||||
if (file=="stdin"):
|
if (file=="stdin"):
|
||||||
inputFile=sys.stdin
|
inputFile=sys.stdin
|
||||||
else:
|
else:
|
||||||
inputFile=open(file, "rU")
|
inputFile=open(file, "rU")
|
||||||
try: loc = self.pos_in_file[file]
|
try: loc = self.pos_in_file[file]
|
||||||
except: pass
|
except: pass
|
||||||
|
|
||||||
# Read input file into class and close file
|
# Read input file into class and close file
|
||||||
inputFile.seek(loc)
|
inputFile.seek(loc)
|
||||||
self.lines=fpdb_simple.removeTrailingEOL(inputFile.readlines())
|
self.lines=fpdb_simple.removeTrailingEOL(inputFile.readlines())
|
||||||
self.pos_in_file[file] = inputFile.tell()
|
self.pos_in_file[file] = inputFile.tell()
|
||||||
inputFile.close()
|
inputFile.close()
|
||||||
|
|
||||||
try: # sometimes we seem to be getting an empty self.lines, in which case, we just want to return.
|
try: # sometimes we seem to be getting an empty self.lines, in which case, we just want to return.
|
||||||
firstline = self.lines[0]
|
firstline = self.lines[0]
|
||||||
except:
|
except:
|
||||||
# print "import_fpdb_file", file, site, self.lines, "\n"
|
# print "import_fpdb_file", file, site, self.lines, "\n"
|
||||||
return
|
return
|
||||||
|
|
||||||
if firstline.find("Tournament Summary")!=-1:
|
if firstline.find("Tournament Summary")!=-1:
|
||||||
print "TODO: implement importing tournament summaries"
|
print "TODO: implement importing tournament summaries"
|
||||||
#self.faobs = readfile(inputFile)
|
#self.faobs = readfile(inputFile)
|
||||||
#self.parseTourneyHistory()
|
#self.parseTourneyHistory()
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
site=fpdb_simple.recogniseSite(firstline)
|
site=fpdb_simple.recogniseSite(firstline)
|
||||||
category=fpdb_simple.recogniseCategory(firstline)
|
category=fpdb_simple.recogniseCategory(firstline)
|
||||||
|
|
||||||
startpos=0
|
startpos=0
|
||||||
stored=0 #counter
|
stored=0 #counter
|
||||||
duplicates=0 #counter
|
duplicates=0 #counter
|
||||||
partial=0 #counter
|
partial=0 #counter
|
||||||
errors=0 #counter
|
errors=0 #counter
|
||||||
|
|
||||||
for i in range (len(self.lines)): #main loop, iterates through the lines of a file and calls the appropriate parser method
|
for i in range (len(self.lines)): #main loop, iterates through the lines of a file and calls the appropriate parser method
|
||||||
if (len(self.lines[i])<2):
|
if (len(self.lines[i])<2):
|
||||||
endpos=i
|
endpos=i
|
||||||
hand=self.lines[startpos:endpos]
|
hand=self.lines[startpos:endpos]
|
||||||
|
|
||||||
if (len(hand[0])<2):
|
if (len(hand[0])<2):
|
||||||
hand=hand[1:]
|
hand=hand[1:]
|
||||||
|
|
||||||
cancelled=False
|
cancelled=False
|
||||||
damaged=False
|
damaged=False
|
||||||
if (site=="ftp"):
|
if (site=="ftp"):
|
||||||
for i in range (len(hand)):
|
for i in range (len(hand)):
|
||||||
if (hand[i].endswith(" has been canceled")): #this is their typo. this is a typo, right?
|
if (hand[i].endswith(" has been canceled")): #this is their typo. this is a typo, right?
|
||||||
cancelled=True
|
cancelled=True
|
||||||
|
|
||||||
seat1=hand[i].find("Seat ") #todo: make this recover by skipping this line
|
seat1=hand[i].find("Seat ") #todo: make this recover by skipping this line
|
||||||
if (seat1!=-1):
|
if (seat1!=-1):
|
||||||
if (hand[i].find("Seat ", seat1+3)!=-1):
|
if (hand[i].find("Seat ", seat1+3)!=-1):
|
||||||
damaged=True
|
damaged=True
|
||||||
|
|
||||||
if (len(hand)<3):
|
if (len(hand)<3):
|
||||||
pass
|
pass
|
||||||
#todo: the above 2 lines are kind of a dirty hack, the mentioned circumstances should be handled elsewhere but that doesnt work with DOS/Win EOL. actually this doesnt work.
|
#todo: the above 2 lines are kind of a dirty hack, the mentioned circumstances should be handled elsewhere but that doesnt work with DOS/Win EOL. actually this doesnt work.
|
||||||
elif (hand[0].endswith(" (partial)")): #partial hand - do nothing
|
elif (hand[0].endswith(" (partial)")): #partial hand - do nothing
|
||||||
partial+=1
|
partial+=1
|
||||||
elif (hand[1].find("Seat")==-1 and hand[2].find("Seat")==-1 and hand[3].find("Seat")==-1):#todo: should this be or instead of and?
|
elif (hand[1].find("Seat")==-1 and hand[2].find("Seat")==-1 and hand[3].find("Seat")==-1):#todo: should this be or instead of and?
|
||||||
partial+=1
|
partial+=1
|
||||||
elif (cancelled or damaged):
|
elif (cancelled or damaged):
|
||||||
partial+=1
|
partial+=1
|
||||||
else: #normal processing
|
else: #normal processing
|
||||||
isTourney=fpdb_simple.isTourney(hand[0])
|
isTourney=fpdb_simple.isTourney(hand[0])
|
||||||
if not isTourney:
|
if not isTourney:
|
||||||
fpdb_simple.filterAnteBlindFold(site,hand)
|
fpdb_simple.filterAnteBlindFold(site,hand)
|
||||||
hand=fpdb_simple.filterCrap(site, hand, isTourney)
|
hand=fpdb_simple.filterCrap(site, hand, isTourney)
|
||||||
self.hand=hand
|
self.hand=hand
|
||||||
|
|
||||||
try:
|
try:
|
||||||
handsId=fpdb_parse_logic.mainParser(self.db, self.cursor, site, category, hand)
|
handsId=fpdb_parse_logic.mainParser(self.settings['db-backend'], self.db
|
||||||
self.db.commit()
|
,self.cursor, site, category, hand)
|
||||||
|
self.db.commit()
|
||||||
stored+=1
|
|
||||||
self.db.commit()
|
stored+=1
|
||||||
if self.callHud:
|
self.db.commit()
|
||||||
#print "call to HUD here. handsId:",handsId
|
if self.callHud:
|
||||||
#pipe the Hands.id out to the HUD
|
#print "call to HUD here. handsId:",handsId
|
||||||
self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep)
|
#pipe the Hands.id out to the HUD
|
||||||
except fpdb_simple.DuplicateError:
|
self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep)
|
||||||
duplicates+=1
|
except fpdb_simple.DuplicateError:
|
||||||
except (ValueError), fe:
|
duplicates+=1
|
||||||
errors+=1
|
except (ValueError), fe:
|
||||||
self.printEmailErrorMessage(errors, file, hand)
|
errors+=1
|
||||||
|
self.printEmailErrorMessage(errors, file, hand)
|
||||||
if (self.settings['failOnError']):
|
|
||||||
self.db.commit() #dont remove this, in case hand processing was cancelled.
|
if (self.settings['failOnError']):
|
||||||
raise
|
self.db.commit() #dont remove this, in case hand processing was cancelled.
|
||||||
except (fpdb_simple.FpdbError), fe:
|
raise
|
||||||
errors+=1
|
except (fpdb_simple.FpdbError), fe:
|
||||||
self.printEmailErrorMessage(errors, file, hand)
|
errors+=1
|
||||||
|
self.printEmailErrorMessage(errors, file, hand)
|
||||||
|
|
||||||
#fe.printStackTrace() #todo: get stacktrace
|
#fe.printStackTrace() #todo: get stacktrace
|
||||||
self.db.rollback()
|
self.db.rollback()
|
||||||
|
|
||||||
if (self.settings['failOnError']):
|
if (self.settings['failOnError']):
|
||||||
self.db.commit() #dont remove this, in case hand processing was cancelled.
|
self.db.commit() #dont remove this, in case hand processing was cancelled.
|
||||||
raise
|
raise
|
||||||
if (self.settings['minPrint']!=0):
|
if (self.settings['minPrint']!=0):
|
||||||
if ((stored+duplicates+partial+errors)%self.settings['minPrint']==0):
|
if ((stored+duplicates+partial+errors)%self.settings['minPrint']==0):
|
||||||
print "stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors
|
print "stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors
|
||||||
|
|
||||||
if (self.settings['handCount']!=0):
|
if (self.settings['handCount']!=0):
|
||||||
if ((stored+duplicates+partial+errors)>=self.settings['handCount']):
|
if ((stored+duplicates+partial+errors)>=self.settings['handCount']):
|
||||||
if (not self.settings['quiet']):
|
if (not self.settings['quiet']):
|
||||||
print "quitting due to reaching the amount of hands to be imported"
|
print "quitting due to reaching the amount of hands to be imported"
|
||||||
print "Total stored:", stored, "duplicates:", duplicates, "partial/damaged:", partial, "errors:", errors, " time:", (time() - starttime)
|
print "Total stored:", stored, "duplicates:", duplicates, "partial/damaged:", partial, "errors:", errors, " time:", (time() - starttime)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
startpos=endpos
|
startpos=endpos
|
||||||
print "Total stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors, " time:", (time() - starttime)
|
print "Total stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors, " time:", (time() - starttime)
|
||||||
|
|
||||||
if stored==0:
|
if stored==0:
|
||||||
if duplicates>0:
|
if duplicates>0:
|
||||||
for line_no in range(len(self.lines)):
|
for line_no in range(len(self.lines)):
|
||||||
if self.lines[line_no].find("Game #")!=-1:
|
if self.lines[line_no].find("Game #")!=-1:
|
||||||
final_game_line=self.lines[line_no]
|
final_game_line=self.lines[line_no]
|
||||||
handsId=fpdb_simple.parseSiteHandNo(final_game_line)
|
handsId=fpdb_simple.parseSiteHandNo(final_game_line)
|
||||||
else:
|
else:
|
||||||
print "failed to read a single hand from file:", inputFile
|
print "failed to read a single hand from file:", inputFile
|
||||||
handsId=0
|
handsId=0
|
||||||
#todo: this will cause return of an unstored hand number if the last hand was error or partial
|
#todo: this will cause return of an unstored hand number if the last hand was error or partial
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
self.handsId=handsId
|
self.handsId=handsId
|
||||||
return handsId
|
return handsId
|
||||||
#end def import_file_dict
|
#end def import_file_dict
|
||||||
|
|
||||||
def parseTourneyHistory(self):
|
def parseTourneyHistory(self):
|
||||||
print "Tourney history parser stub"
|
print "Tourney history parser stub"
|
||||||
#Find tournament boundaries.
|
#Find tournament boundaries.
|
||||||
#print self.foabs
|
#print self.foabs
|
||||||
|
|
||||||
|
|
||||||
def printEmailErrorMessage(self, errors, filename, line):
|
def printEmailErrorMessage(self, errors, filename, line):
|
||||||
traceback.print_exc(file=sys.stderr)
|
traceback.print_exc(file=sys.stderr)
|
||||||
print "Error No.",errors,", please send the hand causing this to steffen@sycamoretest.info so I can fix it."
|
print "Error No.",errors,", please send the hand causing this to steffen@sycamoretest.info so I can fix it."
|
||||||
print "Filename:", filename
|
print "Filename:", filename
|
||||||
print "Here is the first line so you can identify it. Please mention that the error was a ValueError:"
|
print "Here is the first line so you can identify it. Please mention that the error was a ValueError:"
|
||||||
print self.hand[0]
|
print self.hand[0]
|
||||||
print "Hand logged to hand-errors.txt"
|
print "Hand logged to hand-errors.txt"
|
||||||
logfile = open('hand-errors.txt', 'a')
|
logfile = open('hand-errors.txt', 'a')
|
||||||
for s in self.hand:
|
for s in self.hand:
|
||||||
logfile.write(str(s) + "\n")
|
logfile.write(str(s) + "\n")
|
||||||
logfile.write("\n")
|
logfile.write("\n")
|
||||||
logfile.close()
|
logfile.close()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
print "CLI for fpdb_import is now available as CliFpdb.py"
|
print "CLI for fpdb_import is now available as CliFpdb.py"
|
||||||
|
|
|
@ -21,146 +21,171 @@ import fpdb_simple
|
||||||
import fpdb_save_to_db
|
import fpdb_save_to_db
|
||||||
|
|
||||||
#parses a holdem hand
|
#parses a holdem hand
|
||||||
def mainParser(db, cursor, site, category, hand):
|
def mainParser(backend, db, cursor, site, category, hand):
|
||||||
if (category=="holdem" or category=="omahahi" or category=="omahahilo"):
|
if (category=="holdem" or category=="omahahi" or category=="omahahilo"):
|
||||||
base="hold"
|
base="hold"
|
||||||
else:
|
else:
|
||||||
base="stud"
|
base="stud"
|
||||||
#part 0: create the empty arrays
|
#part 0: create the empty arrays
|
||||||
lineTypes=[] #char, valid values: header, name, cards, action, win, rake, ignore
|
lineTypes=[] #char, valid values: header, name, cards, action, win, rake, ignore
|
||||||
lineStreets=[] #char, valid values: (predeal, preflop, flop, turn, river)
|
lineStreets=[] #char, valid values: (predeal, preflop, flop, turn, river)
|
||||||
|
|
||||||
cardValues, cardSuits, boardValues, boardSuits, antes, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo, seatLines, winnings, rakes=[],[],[],[],[],[],[],[],[],[],[],[],[]
|
cardValues, cardSuits, boardValues, boardSuits, antes, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo, seatLines, winnings, rakes=[],[],[],[],[],[],[],[],[],[],[],[],[]
|
||||||
|
|
||||||
#part 1: read hand no and check for duplicate
|
#part 1: read hand no and check for duplicate
|
||||||
siteHandNo=fpdb_simple.parseSiteHandNo(hand[0])
|
siteHandNo=fpdb_simple.parseSiteHandNo(hand[0])
|
||||||
handStartTime=fpdb_simple.parseHandStartTime(hand[0], site)
|
handStartTime=fpdb_simple.parseHandStartTime(hand[0], site)
|
||||||
siteID=fpdb_simple.recogniseSiteID(cursor, site)
|
siteID=fpdb_simple.recogniseSiteID(cursor, site)
|
||||||
#print "parse logic, siteID:",siteID,"site:",site
|
#print "parse logic, siteID:",siteID,"site:",site
|
||||||
|
|
||||||
isTourney=fpdb_simple.isTourney(hand[0])
|
isTourney=fpdb_simple.isTourney(hand[0])
|
||||||
smallBlindLine=0
|
smallBlindLine=0
|
||||||
for i in range(len(hand)):
|
for i in range(len(hand)):
|
||||||
if hand[i].find("posts small blind")!=-1 or hand[i].find("posts the small blind")!=-1:
|
if hand[i].find("posts small blind")!=-1 or hand[i].find("posts the small blind")!=-1:
|
||||||
if hand[i][-2:] == "$0":
|
if hand[i][-2:] == "$0":
|
||||||
continue
|
continue
|
||||||
smallBlindLine=i
|
smallBlindLine=i
|
||||||
#print "found small blind line:",smallBlindLine
|
#print "found small blind line:",smallBlindLine
|
||||||
break
|
break
|
||||||
#print "small blind line:",smallBlindLine
|
#print "small blind line:",smallBlindLine
|
||||||
gametypeID=fpdb_simple.recogniseGametypeID(cursor, hand[0], hand[smallBlindLine], siteID, category, isTourney)
|
gametypeID=fpdb_simple.recogniseGametypeID(backend, db, cursor, hand[0], hand[smallBlindLine], siteID, category, isTourney)
|
||||||
if isTourney:
|
if isTourney:
|
||||||
if site!="ps":
|
if site!="ps":
|
||||||
raise fpdb_simple.FpdbError("tourneys are only supported on PS right now")
|
raise fpdb_simple.FpdbError("tourneys are only supported on PS right now")
|
||||||
siteTourneyNo=fpdb_simple.parseTourneyNo(hand[0])
|
siteTourneyNo=fpdb_simple.parseTourneyNo(hand[0])
|
||||||
buyin=fpdb_simple.parseBuyin(hand[0])
|
buyin=fpdb_simple.parseBuyin(hand[0])
|
||||||
fee=fpdb_simple.parseFee(hand[0])
|
fee=fpdb_simple.parseFee(hand[0])
|
||||||
entries=-1 #todo: parse this
|
entries=-1 #todo: parse this
|
||||||
prizepool=-1 #todo: parse this
|
prizepool=-1 #todo: parse this
|
||||||
knockout=0
|
knockout=0
|
||||||
tourneyStartTime=handStartTime #todo: read tourney start time
|
tourneyStartTime=handStartTime #todo: read tourney start time
|
||||||
rebuyOrAddon=fpdb_simple.isRebuyOrAddon(hand[0])
|
rebuyOrAddon=fpdb_simple.isRebuyOrAddon(hand[0])
|
||||||
|
|
||||||
tourneyTypeId=fpdb_simple.recogniseTourneyTypeId(cursor, siteID, buyin, fee, knockout, rebuyOrAddon)
|
tourneyTypeId=fpdb_simple.recogniseTourneyTypeId(cursor, siteID, buyin, fee, knockout, rebuyOrAddon)
|
||||||
fpdb_simple.isAlreadyInDB(cursor, gametypeID, siteHandNo)
|
fpdb_simple.isAlreadyInDB(cursor, gametypeID, siteHandNo)
|
||||||
|
|
||||||
#part 2: classify lines by type (e.g. cards, action, win, sectionchange) and street
|
#part 2: classify lines by type (e.g. cards, action, win, sectionchange) and street
|
||||||
fpdb_simple.classifyLines(hand, category, lineTypes, lineStreets)
|
fpdb_simple.classifyLines(hand, category, lineTypes, lineStreets)
|
||||||
|
|
||||||
#part 3: read basic player info
|
#part 3: read basic player info
|
||||||
#3a read player names, startcashes
|
#3a read player names, startcashes
|
||||||
for i in range (len(hand)): #todo: use maxseats+1 here.
|
for i in range (len(hand)): #todo: use maxseats+1 here.
|
||||||
if (lineTypes[i]=="name"):
|
if (lineTypes[i]=="name"):
|
||||||
seatLines.append(hand[i])
|
seatLines.append(hand[i])
|
||||||
names=fpdb_simple.parseNames(seatLines)
|
names=fpdb_simple.parseNames(seatLines)
|
||||||
playerIDs = fpdb_simple.recognisePlayerIDs(cursor, names, siteID)
|
playerIDs = fpdb_simple.recognisePlayerIDs(cursor, names, siteID)
|
||||||
tmp=fpdb_simple.parseCashesAndSeatNos(seatLines, site)
|
tmp=fpdb_simple.parseCashesAndSeatNos(seatLines, site)
|
||||||
startCashes=tmp['startCashes']
|
startCashes=tmp['startCashes']
|
||||||
seatNos=tmp['seatNos']
|
seatNos=tmp['seatNos']
|
||||||
|
|
||||||
fpdb_simple.createArrays(category, len(names), cardValues, cardSuits, antes, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo)
|
fpdb_simple.createArrays(category, len(names), cardValues, cardSuits, antes, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo)
|
||||||
|
|
||||||
#3b read positions
|
#3b read positions
|
||||||
if base=="hold":
|
if base=="hold":
|
||||||
positions = fpdb_simple.parsePositions (hand, names)
|
positions = fpdb_simple.parsePositions (hand, names)
|
||||||
|
|
||||||
#part 4: take appropriate action for each line based on linetype
|
#part 4: take appropriate action for each line based on linetype
|
||||||
for i in range(len(hand)):
|
for i in range(len(hand)):
|
||||||
if (lineTypes[i]=="cards"):
|
if (lineTypes[i]=="cards"):
|
||||||
fpdb_simple.parseCardLine (site, category, lineStreets[i], hand[i], names, cardValues, cardSuits, boardValues, boardSuits)
|
fpdb_simple.parseCardLine (site, category, lineStreets[i], hand[i], names, cardValues, cardSuits, boardValues, boardSuits)
|
||||||
#if category=="studhilo":
|
#if category=="studhilo":
|
||||||
# print "hand[i]:", hand[i]
|
# print "hand[i]:", hand[i]
|
||||||
# print "cardValues:", cardValues
|
# print "cardValues:", cardValues
|
||||||
# print "cardSuits:", cardSuits
|
# print "cardSuits:", cardSuits
|
||||||
elif (lineTypes[i]=="action"):
|
elif (lineTypes[i]=="action"):
|
||||||
fpdb_simple.parseActionLine (site, base, isTourney, hand[i], lineStreets[i], playerIDs, names, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo)
|
fpdb_simple.parseActionLine (site, base, isTourney, hand[i], lineStreets[i], playerIDs, names, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo)
|
||||||
elif (lineTypes[i]=="win"):
|
elif (lineTypes[i]=="win"):
|
||||||
fpdb_simple.parseWinLine (hand[i], site, names, winnings, isTourney)
|
fpdb_simple.parseWinLine (hand[i], site, names, winnings, isTourney)
|
||||||
elif (lineTypes[i]=="rake"):
|
elif (lineTypes[i]=="rake"):
|
||||||
if isTourney:
|
if isTourney:
|
||||||
totalRake=0
|
totalRake=0
|
||||||
else:
|
else:
|
||||||
totalRake=fpdb_simple.parseRake(hand[i])
|
totalRake=fpdb_simple.parseRake(hand[i])
|
||||||
fpdb_simple.splitRake(winnings, rakes, totalRake)
|
fpdb_simple.splitRake(winnings, rakes, totalRake)
|
||||||
elif (lineTypes[i]=="header" or lineTypes[i]=="rake" or lineTypes[i]=="name" or lineTypes[i]=="ignore"):
|
elif (lineTypes[i]=="header" or lineTypes[i]=="rake" or lineTypes[i]=="name" or lineTypes[i]=="ignore"):
|
||||||
pass
|
pass
|
||||||
elif (lineTypes[i]=="ante"):
|
elif (lineTypes[i]=="ante"):
|
||||||
fpdb_simple.parseAnteLine(hand[i], site, isTourney, names, antes)
|
fpdb_simple.parseAnteLine(hand[i], site, isTourney, names, antes)
|
||||||
elif (lineTypes[i]=="table"):
|
elif (lineTypes[i]=="table"):
|
||||||
tableResult=fpdb_simple.parseTableLine(site, base, hand[i])
|
tableResult=fpdb_simple.parseTableLine(site, base, hand[i])
|
||||||
else:
|
else:
|
||||||
raise fpdb_simple.FpdbError("unrecognised lineType:"+lineTypes[i])
|
raise fpdb_simple.FpdbError("unrecognised lineType:"+lineTypes[i])
|
||||||
if site=="ftp":
|
if site=="ftp":
|
||||||
tableResult=fpdb_simple.parseTableLine(site, base, hand[0])
|
tableResult=fpdb_simple.parseTableLine(site, base, hand[0])
|
||||||
maxSeats=tableResult['maxSeats']
|
maxSeats=tableResult['maxSeats']
|
||||||
tableName=tableResult['tableName']
|
tableName=tableResult['tableName']
|
||||||
#print "before part5, antes:", antes
|
#print "before part5, antes:", antes
|
||||||
|
|
||||||
#part 5: final preparations, then call fpdb_save_to_db.* with
|
#part 5: final preparations, then call fpdb_save_to_db.* with
|
||||||
# the arrays as they are - that file will fill them.
|
# the arrays as they are - that file will fill them.
|
||||||
fpdb_simple.convertCardValues(cardValues)
|
fpdb_simple.convertCardValues(cardValues)
|
||||||
if base=="hold":
|
if base=="hold":
|
||||||
fpdb_simple.convertCardValuesBoard(boardValues)
|
fpdb_simple.convertCardValuesBoard(boardValues)
|
||||||
fpdb_simple.convertBlindBet(actionTypes, actionAmounts)
|
fpdb_simple.convertBlindBet(actionTypes, actionAmounts)
|
||||||
fpdb_simple.checkPositions(positions)
|
fpdb_simple.checkPositions(positions)
|
||||||
|
|
||||||
cursor.execute("SELECT limitType FROM Gametypes WHERE id=%s",(gametypeID, ))
|
cursor.execute("SELECT limitType FROM Gametypes WHERE id=%s",(gametypeID, ))
|
||||||
limit_type=cursor.fetchone()[0]
|
limit_type=cursor.fetchone()[0]
|
||||||
fpdb_simple.convert3B4B(site, category, limit_type, actionTypes, actionAmounts)
|
fpdb_simple.convert3B4B(site, category, limit_type, actionTypes, actionAmounts)
|
||||||
|
|
||||||
totalWinnings=0
|
totalWinnings=0
|
||||||
for i in range(len(winnings)):
|
for i in range(len(winnings)):
|
||||||
totalWinnings+=winnings[i]
|
totalWinnings+=winnings[i]
|
||||||
|
|
||||||
if base=="hold":
|
if base=="hold":
|
||||||
hudImportData=fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes, allIns, actionTypeByNo, winnings, totalWinnings, positions)
|
hudImportData=fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes
|
||||||
else:
|
, allIns, actionTypeByNo, winnings, totalWinnings, positions
|
||||||
hudImportData=fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes, allIns, actionTypeByNo, winnings, totalWinnings, None)
|
, actionTypes, actionAmounts)
|
||||||
|
else:
|
||||||
if isTourney:
|
hudImportData=fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes
|
||||||
ranks=[]
|
, allIns, actionTypeByNo, winnings, totalWinnings, None
|
||||||
for i in range (len(names)):
|
, actionTypes, actionAmounts)
|
||||||
ranks.append(0)
|
|
||||||
payin_amounts=fpdb_simple.calcPayin(len(names), buyin, fee)
|
if isTourney:
|
||||||
|
ranks=[]
|
||||||
if base=="hold":
|
for i in range (len(names)):
|
||||||
result = fpdb_save_to_db.tourney_holdem_omaha(cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteID,
|
ranks.append(0)
|
||||||
siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, positions, cardValues, cardSuits, boardValues, boardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos)
|
payin_amounts=fpdb_simple.calcPayin(len(names), buyin, fee)
|
||||||
elif base=="stud":
|
|
||||||
result = fpdb_save_to_db.tourney_stud(cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteID,
|
if base=="hold":
|
||||||
siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, antes, cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos)
|
result = fpdb_save_to_db.tourney_holdem_omaha(
|
||||||
else:
|
backend, db, cursor, base, category, siteTourneyNo, buyin
|
||||||
raise fpdb_simple.FpdbError ("unrecognised category")
|
, fee, knockout, entries, prizepool, tourneyStartTime
|
||||||
else:
|
, payin_amounts, ranks, tourneyTypeId, siteID, siteHandNo
|
||||||
if base=="hold":
|
, gametypeID, handStartTime, names, playerIDs, startCashes
|
||||||
result = fpdb_save_to_db.ring_holdem_omaha(cursor, base, category, siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, positions, cardValues, cardSuits, boardValues, boardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos)
|
, positions, cardValues, cardSuits, boardValues, boardSuits
|
||||||
elif base=="stud":
|
, winnings, rakes, actionTypes, allIns, actionAmounts
|
||||||
result = fpdb_save_to_db.ring_stud(cursor, base, category, siteHandNo, gametypeID,
|
, actionNos, hudImportData, maxSeats, tableName, seatNos)
|
||||||
handStartTime, names, playerIDs, startCashes, antes, cardValues,
|
elif base=="stud":
|
||||||
cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos)
|
result = fpdb_save_to_db.tourney_stud(
|
||||||
else:
|
backend, db, cursor, base, category, siteTourneyNo
|
||||||
raise fpdb_simple.FpdbError ("unrecognised category")
|
, buyin, fee, knockout, entries, prizepool, tourneyStartTime
|
||||||
db.commit()
|
, payin_amounts, ranks, tourneyTypeId, siteID, siteHandNo
|
||||||
return result
|
, gametypeID, handStartTime, names, playerIDs, startCashes
|
||||||
|
, antes, cardValues, cardSuits, winnings, rakes, actionTypes
|
||||||
|
, allIns, actionAmounts, actionNos, hudImportData, maxSeats
|
||||||
|
, tableName, seatNos)
|
||||||
|
else:
|
||||||
|
raise fpdb_simple.FpdbError ("unrecognised category")
|
||||||
|
else:
|
||||||
|
if base=="hold":
|
||||||
|
result = fpdb_save_to_db.ring_holdem_omaha(
|
||||||
|
backend, db, cursor, base, category, siteHandNo
|
||||||
|
, gametypeID, handStartTime, names, playerIDs
|
||||||
|
, startCashes, positions, cardValues, cardSuits
|
||||||
|
, boardValues, boardSuits, winnings, rakes
|
||||||
|
, actionTypes, allIns, actionAmounts, actionNos
|
||||||
|
, hudImportData, maxSeats, tableName, seatNos)
|
||||||
|
elif base=="stud":
|
||||||
|
result = fpdb_save_to_db.ring_stud(
|
||||||
|
backend, db, cursor, base, category, siteHandNo, gametypeID
|
||||||
|
, handStartTime, names, playerIDs, startCashes, antes
|
||||||
|
, cardValues, cardSuits, winnings, rakes, actionTypes, allIns
|
||||||
|
, actionAmounts, actionNos, hudImportData, maxSeats, tableName
|
||||||
|
, seatNos)
|
||||||
|
else:
|
||||||
|
raise fpdb_simple.FpdbError ("unrecognised category")
|
||||||
|
db.commit()
|
||||||
|
return result
|
||||||
#end def mainParser
|
#end def mainParser
|
||||||
|
|
||||||
|
|
|
@ -18,77 +18,110 @@
|
||||||
#This file contains methods to store hands into the db. decides to move this
|
#This file contains methods to store hands into the db. decides to move this
|
||||||
#into a seperate file since its ugly, fairly long and just generally in the way.
|
#into a seperate file since its ugly, fairly long and just generally in the way.
|
||||||
|
|
||||||
|
from time import time
|
||||||
|
|
||||||
import fpdb_simple
|
import fpdb_simple
|
||||||
|
|
||||||
#stores a stud/razz hand into the database
|
#stores a stud/razz hand into the database
|
||||||
def ring_stud(cursor, base, category, site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes, action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos):
|
def ring_stud(backend, db, cursor, base, category, site_hand_no, gametype_id, hand_start_time
|
||||||
fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits)
|
,names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes
|
||||||
|
,action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName
|
||||||
hands_id=fpdb_simple.storeHands(cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats)
|
,seatNos):
|
||||||
|
fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits)
|
||||||
#print "before calling store_hands_players_stud, antes:", antes
|
|
||||||
hands_players_ids=fpdb_simple.store_hands_players_stud(cursor, hands_id, player_ids,
|
hands_id=fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id
|
||||||
start_cashes, antes, card_values, card_suits, winnings, rakes, seatNos)
|
,hand_start_time, names, tableName, maxSeats)
|
||||||
|
|
||||||
fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData)
|
#print "before calling store_hands_players_stud, antes:", antes
|
||||||
|
hands_players_ids=fpdb_simple.store_hands_players_stud(backend, db, cursor, hands_id, player_ids
|
||||||
fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos)
|
,start_cashes, antes, card_values
|
||||||
return hands_id
|
,card_suits, winnings, rakes, seatNos)
|
||||||
|
|
||||||
|
fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData)
|
||||||
|
|
||||||
|
fpdb_simple.storeActions(cursor, hands_players_ids, action_types
|
||||||
|
,allIns, action_amounts, actionNos)
|
||||||
|
return hands_id
|
||||||
#end def ring_stud
|
#end def ring_stud
|
||||||
|
|
||||||
def ring_holdem_omaha(cursor, base, category, site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, positions, card_values, card_suits, board_values, board_suits, winnings, rakes, action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos):
|
def ring_holdem_omaha(backend, db, cursor, base, category, site_hand_no, gametype_id
|
||||||
"""stores a holdem/omaha hand into the database"""
|
,hand_start_time, names, player_ids, start_cashes, positions, card_values
|
||||||
fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits)
|
,card_suits, board_values, board_suits, winnings, rakes, action_types, allIns
|
||||||
fpdb_simple.fill_board_cards(board_values, board_suits)
|
,action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos):
|
||||||
|
"""stores a holdem/omaha hand into the database"""
|
||||||
|
t0 = time()
|
||||||
|
fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits)
|
||||||
|
t1 = time()
|
||||||
|
fpdb_simple.fill_board_cards(board_values, board_suits)
|
||||||
|
t2 = time()
|
||||||
|
|
||||||
hands_id=fpdb_simple.storeHands(cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats)
|
hands_id=fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id
|
||||||
|
,hand_start_time, names, tableName, maxSeats)
|
||||||
hands_players_ids=fpdb_simple.store_hands_players_holdem_omaha(cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos)
|
t3 = time()
|
||||||
|
hands_players_ids=fpdb_simple.store_hands_players_holdem_omaha(
|
||||||
fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData)
|
backend, db, cursor, category, hands_id, player_ids, start_cashes
|
||||||
|
, positions, card_values, card_suits, winnings, rakes, seatNos)
|
||||||
fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits)
|
t4 = time()
|
||||||
|
fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData)
|
||||||
fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos)
|
t5 = time()
|
||||||
return hands_id
|
fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits)
|
||||||
|
t6 = time()
|
||||||
|
fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos)
|
||||||
|
t7 = time()
|
||||||
|
print "cards=%4.3f board=%4.3f hands=%4.3f plyrs=%4.3f hudcache=%4.3f board=%4.3f actions=%4.3f" \
|
||||||
|
% (t1-t0, t2-t1, t3-t2, t4-t3, t5-t4, t6-t5, t7-t6)
|
||||||
|
return hands_id
|
||||||
#end def ring_holdem_omaha
|
#end def ring_holdem_omaha
|
||||||
|
|
||||||
def tourney_holdem_omaha(cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourney_start, payin_amounts, ranks, tourneyTypeId, siteId, #end of tourney specific params
|
def tourney_holdem_omaha(backend, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout
|
||||||
site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, positions, card_values, card_suits, board_values, board_suits, winnings, rakes, action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos):
|
,entries, prizepool, tourney_start, payin_amounts, ranks, tourneyTypeId
|
||||||
"""stores a tourney holdem/omaha hand into the database"""
|
,siteId #end of tourney specific params
|
||||||
fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits)
|
,site_hand_no, gametype_id, hand_start_time, names, player_ids
|
||||||
fpdb_simple.fill_board_cards(board_values, board_suits)
|
,start_cashes, positions, card_values, card_suits, board_values
|
||||||
|
,board_suits, winnings, rakes, action_types, allIns, action_amounts
|
||||||
tourney_id=fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourney_start)
|
,actionNos, hudImportData, maxSeats, tableName, seatNos):
|
||||||
tourneys_players_ids=fpdb_simple.store_tourneys_players(cursor, tourney_id, player_ids, payin_amounts, ranks, winnings)
|
"""stores a tourney holdem/omaha hand into the database"""
|
||||||
|
fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits)
|
||||||
hands_id=fpdb_simple.storeHands(cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats)
|
fpdb_simple.fill_board_cards(board_values, board_suits)
|
||||||
|
|
||||||
hands_players_ids=fpdb_simple.store_hands_players_holdem_omaha_tourney(cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids)
|
tourney_id=fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourney_start)
|
||||||
|
tourneys_players_ids=fpdb_simple.store_tourneys_players(cursor, tourney_id, player_ids, payin_amounts, ranks, winnings)
|
||||||
fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData)
|
|
||||||
|
hands_id=fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id
|
||||||
fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits)
|
,hand_start_time, names, tableName, maxSeats)
|
||||||
|
|
||||||
fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos)
|
hands_players_ids=fpdb_simple.store_hands_players_holdem_omaha_tourney(
|
||||||
return hands_id
|
backend, db, cursor, category, hands_id, player_ids, start_cashes, positions
|
||||||
|
, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids)
|
||||||
|
|
||||||
|
fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData)
|
||||||
|
|
||||||
|
fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits)
|
||||||
|
|
||||||
|
fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos)
|
||||||
|
return hands_id
|
||||||
#end def tourney_holdem_omaha
|
#end def tourney_holdem_omaha
|
||||||
|
|
||||||
def tourney_stud(cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteId,
|
def tourney_stud(backend, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries
|
||||||
siteHandNo, gametypeId, handStartTime, names, playerIds, startCashes, antes, cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos):
|
,prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteId
|
||||||
|
,siteHandNo, gametypeId, handStartTime, names, playerIds, startCashes, antes
|
||||||
|
,cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts
|
||||||
|
,actionNos, hudImportData, maxSeats, tableName, seatNos):
|
||||||
#stores a tourney stud/razz hand into the database
|
#stores a tourney stud/razz hand into the database
|
||||||
fpdb_simple.fillCardArrays(len(names), base, category, cardValues, cardSuits)
|
fpdb_simple.fillCardArrays(len(names), base, category, cardValues, cardSuits)
|
||||||
|
|
||||||
tourney_id=fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourneyStartTime)
|
tourney_id=fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourneyStartTime)
|
||||||
|
|
||||||
tourneys_players_ids=fpdb_simple.store_tourneys_players(cursor, tourney_id, playerIds, payin_amounts, ranks, winnings)
|
tourneys_players_ids=fpdb_simple.store_tourneys_players(cursor, tourney_id, playerIds, payin_amounts, ranks, winnings)
|
||||||
|
|
||||||
hands_id=fpdb_simple.storeHands(cursor, siteHandNo, gametypeId, handStartTime, names, tableName, maxSeats)
|
hands_id=fpdb_simple.storeHands(backend, db, cursor, siteHandNo, gametypeId, handStartTime, names, tableName, maxSeats)
|
||||||
|
|
||||||
hands_players_ids=fpdb_simple.store_hands_players_stud_tourney(cursor, hands_id, playerIds, startCashes, antes, cardValues, cardSuits, winnings, rakes, seatNos, tourneys_players_ids)
|
hands_players_ids=fpdb_simple.store_hands_players_stud_tourney(backend, db, cursor, hands_id
|
||||||
|
, playerIds, startCashes, antes, cardValues, cardSuits
|
||||||
fpdb_simple.storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData)
|
, winnings, rakes, seatNos, tourneys_players_ids)
|
||||||
|
|
||||||
fpdb_simple.storeActions(cursor, hands_players_ids, actionTypes, allIns, actionAmounts, actionNos)
|
fpdb_simple.storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData)
|
||||||
return hands_id
|
|
||||||
|
fpdb_simple.storeActions(cursor, hands_players_ids, actionTypes, allIns, actionAmounts, actionNos)
|
||||||
|
return hands_id
|
||||||
#end def tourney_stud
|
#end def tourney_stud
|
||||||
|
|
4377
pyfpdb/fpdb_simple.py
Normal file → Executable file
4377
pyfpdb/fpdb_simple.py
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
27
pyfpdb/upd_indexes.sql
Executable file
27
pyfpdb/upd_indexes.sql
Executable file
|
@ -0,0 +1,27 @@
|
||||||
|
|
||||||
|
# script to update indexes on mysql (+other?) database
|
||||||
|
|
||||||
|
select '1. Dropping indexes' as ' ';
|
||||||
|
select 'Can''t drop messages indicate index already gone' as ' ';
|
||||||
|
|
||||||
|
ALTER TABLE `fpdb`.`Settings` DROP INDEX `id`;
|
||||||
|
ALTER TABLE `fpdb`.`Sites` DROP INDEX `id`;
|
||||||
|
ALTER TABLE `fpdb`.`Gametypes` DROP INDEX `id`;
|
||||||
|
ALTER TABLE `fpdb`.`Players` DROP INDEX `id`;
|
||||||
|
ALTER TABLE `fpdb`.`Autorates` DROP INDEX `id`;
|
||||||
|
ALTER TABLE `fpdb`.`Hands` DROP INDEX `id`;
|
||||||
|
ALTER TABLE `fpdb`.`BoardCards` DROP INDEX `id`;
|
||||||
|
ALTER TABLE `fpdb`.`TourneyTypes` DROP INDEX `id`;
|
||||||
|
ALTER TABLE `fpdb`.`Tourneys` DROP INDEX `id`;
|
||||||
|
ALTER TABLE `fpdb`.`TourneysPlayers` DROP INDEX `id`;
|
||||||
|
ALTER TABLE `fpdb`.`HandsPlayers` DROP INDEX `id`;
|
||||||
|
ALTER TABLE `fpdb`.`HandsActions` DROP INDEX `id`;
|
||||||
|
ALTER TABLE `fpdb`.`HudCache` DROP INDEX `id`;
|
||||||
|
|
||||||
|
select '2. Adding extra indexes on useful fields' as ' ';
|
||||||
|
select 'Duplicate key name messages indicate new indexes already there' as ' ';
|
||||||
|
|
||||||
|
ALTER TABLE `fpdb`.`tourneys` ADD INDEX `siteTourneyNo`(`siteTourneyNo`);
|
||||||
|
ALTER TABLE `fpdb`.`hands` ADD INDEX `siteHandNo`(`siteHandNo`);
|
||||||
|
ALTER TABLE `fpdb`.`players` ADD INDEX `name`(`name`);
|
||||||
|
|
0
readme.txt
Normal file
0
readme.txt
Normal file
Loading…
Reference in New Issue
Block a user