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

This commit is contained in:
Eric Blade 2009-11-29 12:28:14 -05:00
commit bab3ad6ca9
13 changed files with 419 additions and 94 deletions

View File

@ -672,38 +672,50 @@ class Config:
except:
hui['label'] = default_text
try: hui['hud_style'] = self.ui.hud_style
except: hui['hud_style'] = 'A' # default is show stats for All-time, also S(session) and T(ime)
try: hui['hud_days'] = int(self.ui.hud_days)
except: hui['hud_days'] = 90
try: hui['aggregate_ring'] = self.ui.aggregate_ring
except: hui['aggregate_ring'] = False
try: hui['aggregate_tour'] = self.ui.aggregate_tour
except: hui['aggregate_tour'] = True
try: hui['hud_style'] = self.ui.hud_style
except: hui['hud_style'] = 'A'
try: hui['hud_days'] = int(self.ui.hud_days)
except: hui['hud_days'] = 90
try: hui['agg_bb_mult'] = self.ui.agg_bb_mult
except: hui['agg_bb_mult'] = 1
try: hui['seats_style'] = self.ui.seats_style
except: hui['seats_style'] = 'C' # A / C / E, use A(ll) / C(ustom) / E(xact) seat numbers
try: hui['seats_cust_nums'] = self.ui.seats_cust_nums
except: hui['seats_cust_nums'] = ['n/a', 'n/a', (2,2), (3,4), (3,5), (4,6), (5,7), (6,8), (7,9), (8,10), (8,10)]
# Hero specific
try: hui['h_aggregate_ring'] = self.ui.h_aggregate_ring
except: hui['h_aggregate_ring'] = False
try: hui['h_aggregate_tour'] = self.ui.h_aggregate_tour
except: hui['h_aggregate_tour'] = True
try: hui['h_hud_style'] = self.ui.h_hud_style
except: hui['h_hud_style'] = 'S'
try: hui['h_hud_days'] = int(self.ui.h_hud_days)
except: hui['h_hud_days'] = 30
try: hui['h_aggregate_ring'] = self.ui.h_aggregate_ring
except: hui['h_aggregate_ring'] = False
try: hui['h_aggregate_tour'] = self.ui.h_aggregate_tour
except: hui['h_aggregate_tour'] = True
try: hui['h_agg_bb_mult'] = self.ui.h_agg_bb_mult
except: hui['h_agg_bb_mult'] = 1
try: hui['h_seats_style'] = self.ui.h_seats_style
except: hui['h_seats_style'] = 'E' # A / C / E, use A(ll) / C(ustom) / E(xact) seat numbers
try: hui['h_seats_cust_nums'] = self.ui.h_seats_cust_nums
except: hui['h_seats_cust_nums'] = ['n/a', 'n/a', (2,2), (3,4), (3,5), (4,6), (5,7), (6,8), (7,9), (8,10), (8,10)]
return hui
@ -948,8 +960,14 @@ if __name__== "__main__":
for game in c.get_supported_games():
print c.get_game_parameters(game)
for hud_param, value in c.get_hud_ui_parameters().iteritems():
print "hud param %s = %s" % (hud_param, value)
print "start up path = ", c.execution_path("")
from xml.dom.ext import PrettyPrint
for site_node in c.doc.getElementsByTagName("site"):
PrettyPrint(site_node, stream=sys.stdout, encoding="utf-8")
try:
from xml.dom.ext import PrettyPrint
for site_node in c.doc.getElementsByTagName("site"):
PrettyPrint(site_node, stream=sys.stdout, encoding="utf-8")
except:
print "xml.dom.ext needs PyXML to be installed!"

View File

@ -433,17 +433,50 @@ class Database:
def get_stats_from_hand( self, hand, type # type is "ring" or "tour"
, hud_params = {'hud_style':'A', 'agg_bb_mult':1000
,'h_hud_style':'S', 'h_agg_bb_mult':1000}
,'seats_style':'A', 'seats_cust_nums':['n/a', 'n/a', (2,2), (3,4), (3,5), (4,6), (5,7), (6,8), (7,9), (8,10), (8,10)]
,'h_hud_style':'S', 'h_agg_bb_mult':1000
,'h_seats_style':'A', 'h_seats_cust_nums':['n/a', 'n/a', (2,2), (3,4), (3,5), (4,6), (5,7), (6,8), (7,9), (8,10), (8,10)]
}
, hero_id = -1
, num_seats = 6
):
hud_style = hud_params['hud_style']
agg_bb_mult = hud_params['agg_bb_mult']
seats_style = hud_params['seats_style']
seats_cust_nums = hud_params['seats_cust_nums']
h_hud_style = hud_params['h_hud_style']
h_agg_bb_mult = hud_params['h_agg_bb_mult']
h_seats_style = hud_params['h_seats_style']
h_seats_cust_nums = hud_params['h_seats_cust_nums']
stat_dict = {}
if seats_style == 'A':
seats_min, seats_max = 0, 10
elif seats_style == 'C':
seats_min, seats_max = seats_cust_nums[num_seats][0], seats_cust_nums[num_seats][1]
elif seats_style == 'E':
seats_min, seats_max = num_seats, num_seats
else:
seats_min, seats_max = 0, 10
print "bad seats_style value:", seats_style
if h_seats_style == 'A':
h_seats_min, h_seats_max = 0, 10
elif h_seats_style == 'C':
h_seats_min, h_seats_max = h_seats_cust_nums[num_seats][0], h_seats_cust_nums[num_seats][1]
elif h_seats_style == 'E':
h_seats_min, h_seats_max = num_seats, num_seats
else:
h_seats_min, h_seats_max = 0, 10
print "bad h_seats_style value:", h_seats_style
print "opp seats style", seats_style, "hero seats style", h_seats_style
print "opp seats:", seats_min, seats_max, " hero seats:", h_seats_min, h_seats_max
if hud_style == 'S' or h_hud_style == 'S':
self.get_stats_from_hand_session(hand, stat_dict, hero_id, hud_style, h_hud_style)
self.get_stats_from_hand_session(hand, stat_dict, hero_id
,hud_style, seats_min, seats_max
,h_hud_style, h_seats_min, h_seats_max)
if hud_style == 'S' and h_hud_style == 'S':
return stat_dict
@ -475,7 +508,9 @@ class Database:
# h_stylekey = date_nhands_ago needs array by player here ...
query = 'get_stats_from_hand_aggregated'
subs = (hand, hero_id, stylekey, agg_bb_mult, agg_bb_mult, hero_id, h_stylekey, h_agg_bb_mult, h_agg_bb_mult)
subs = (hand
,hero_id, stylekey, agg_bb_mult, agg_bb_mult, seats_min, seats_max # hero params
,hero_id, h_stylekey, h_agg_bb_mult, h_agg_bb_mult, h_seats_min, h_seats_max) # villain params
#print "get stats: hud style =", hud_style, "query =", query, "subs =", subs
c = self.connection.cursor()
@ -495,12 +530,15 @@ class Database:
return stat_dict
# uses query on handsplayers instead of hudcache to get stats on just this session
def get_stats_from_hand_session(self, hand, stat_dict, hero_id, hud_style, h_hud_style):
def get_stats_from_hand_session(self, hand, stat_dict, hero_id
,hud_style, seats_min, seats_max
,h_hud_style, h_seats_min, h_seats_max):
"""Get stats for just this session (currently defined as any play in the last 24 hours - to
be improved at some point ...)
h_hud_style and hud_style params indicate whether to get stats for hero and/or others
- only fetch heros stats if h_hud_style == 'S',
and only fetch others stats if hud_style == 'S'
seats_min/max params give seats limits, only include stats if between these values
"""
query = self.sql.query['get_stats_from_hand_session']
@ -509,7 +547,8 @@ class Database:
else:
query = query.replace("<signed>", '')
subs = (self.hand_1day_ago, hand)
subs = (self.hand_1day_ago, hand, hero_id, seats_min, seats_max
, hero_id, h_seats_min, h_seats_max)
c = self.get_cursor()
# now get the stats
@ -524,6 +563,7 @@ class Database:
# Loop through stats adding them to appropriate stat_dict:
while row:
playerid = row[0]
seats = row[1]
if (playerid == hero_id and h_hud_style == 'S') or (playerid != hero_id and hud_style == 'S'):
for name, val in zip(colnames, row):
if not playerid in stat_dict:
@ -535,7 +575,7 @@ class Database:
stat_dict[playerid][name.lower()] += val
n += 1
if n >= 10000: break # todo: don't think this is needed so set nice and high
# for now - comment out or remove?
# prevents infinite loop so leave for now - comment out or remove?
row = c.fetchone()
else:
log.error("ERROR: query %s result does not have player_id as first column" % (query,))
@ -2746,7 +2786,9 @@ if __name__=="__main__":
# db_connection = Database(c, 'PTrackSv2', 'razz') # mysql razz
# db_connection = Database(c, 'ptracks', 'razz') # postgres
print "database connection object = ", db_connection.connection
db_connection.recreate_tables()
# db_connection.recreate_tables()
db_connection.dropAllIndexes()
db_connection.createAllIndexes()
h = db_connection.get_last_hand()
print "last hand = ", h

View File

@ -27,5 +27,12 @@ class FpdbMySQLAccessDenied(FpdbDatabaseError):
def __str__(self):
return repr(self.value +" " + self.errmsg)
class FpdbMySQLNoDatabase(FpdbDatabaseError):
def __init__(self, value='', errmsg=''):
self.value = value
self.errmsg = errmsg
def __str__(self):
return repr(self.value +" " + self.errmsg)
class DuplicateError(FpdbError):
pass

View File

@ -200,7 +200,7 @@ class HUD_main(object):
# get basic info about the new hand from the db
# if there is a db error, complain, skip hand, and proceed
try:
(table_name, max, poker_game, type, site_id, site_name, tour_number, tab_number) = \
(table_name, max, poker_game, type, site_id, site_name, num_seats, tour_number, tab_number) = \
self.db_connection.get_table_info(new_hand_id)
except Exception, err: # TODO: we need to make this a much less generic Exception lulz
print "db error: skipping %s" % new_hand_id
@ -217,7 +217,8 @@ class HUD_main(object):
# get stats using hud's specific params and get cards
self.db_connection.init_hud_stat_vars( self.hud_dict[temp_key].hud_params['hud_days']
, self.hud_dict[temp_key].hud_params['h_hud_days'])
stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_dict[temp_key].hud_params, self.hero_ids[site_id])
stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_dict[temp_key].hud_params
,self.hero_ids[site_id], num_seats)
try:
self.hud_dict[temp_key].stat_dict = stat_dict
except KeyError: # HUD instance has been killed off, key is stale
@ -238,7 +239,8 @@ class HUD_main(object):
else:
# get stats using default params--also get cards
self.db_connection.init_hud_stat_vars( self.hud_params['hud_days'], self.hud_params['h_hud_days'] )
stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_params, self.hero_ids[site_id])
stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_params
,self.hero_ids[site_id], num_seats)
cards = self.db_connection.get_cards(new_hand_id)
comm_cards = self.db_connection.get_common_cards(new_hand_id)
if comm_cards != {}: # stud!

View File

@ -510,7 +510,7 @@ Map the tuple self.gametype onto the pokerstars string describing it
def printHand(self):
self.writeHand(sys.stdout)
def actionString(self, act):
def actionString(self, act, street=None):
if act[1] == 'folds':
return ("%s: folds " %(act[0]))
elif act[1] == 'checks':
@ -535,7 +535,7 @@ Map the tuple self.gametype onto the pokerstars string describing it
elif act[1] == 'bringin':
return ("%s: brings in for %s%s%s" %(act[0], self.sym, act[2], ' and is all-in' if act[3] else ''))
elif act[1] == 'discards':
return ("%s: discards %s %s%s" %(act[0], act[2], 'card' if act[2] == 1 else 'cards' , " [" + " ".join(self.discards[act[0]]['DRAWONE']) + "]" if self.hero == act[0] else ''))
return ("%s: discards %s %s%s" %(act[0], act[2], 'card' if act[2] == 1 else 'cards' , " [" + " ".join(self.discards[street][act[0]]) + "]" if self.hero == act[0] else ''))
elif act[1] == 'stands pat':
return ("%s: stands pat" %(act[0]))
@ -872,7 +872,7 @@ class DrawHand(Hand):
self.streetList = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE']
self.allStreets = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE']
self.holeStreets = ['DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE']
self.actionStreets = ['PREDEAL', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE']
self.actionStreets = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE']
self.communityStreets = []
Hand.__init__(self, sitename, gametype, handText)
self.sb = gametype['sb']
@ -953,6 +953,13 @@ class DrawHand(Hand):
act = (player, 'discards', num)
self.actions[street].append(act)
def holecardsAsSet(self, street, player):
"""Return holdcards: (oc, nc) as set()"""
(nc,oc) = self.holecards[street][player]
nc = set(nc)
oc = set(oc)
return (nc, oc)
def getStreetTotals(self):
# street1Pot INT, /* pot size at flop/street4 */
# street2Pot INT, /* pot size at turn/street5 */
@ -979,18 +986,19 @@ class DrawHand(Hand):
if 'DEAL' in self.actions:
print >>fh, _("*** DEALING HANDS ***")
for player in [x[1] for x in self.players if x[1] in players_who_act_ondeal]:
if 'DEAL' in self.holecards[player]:
(nc,oc) = self.holecards[player]['DEAL']
print >>fh, _("Dealt to %s: [%s]") % (player, " ".join(nc))
if 'DEAL' in self.holecards:
if self.holecards['DEAL'].has_key(player):
(nc,oc) = self.holecards['DEAL'][player]
print >>fh, _("Dealt to %s: [%s]") % (player, " ".join(nc))
for act in self.actions['DEAL']:
print >>fh, self.actionString(act)
print >>fh, self.actionString(act, 'DEAL')
if 'DRAWONE' in self.actions:
print >>fh, _("*** FIRST DRAW ***")
for act in self.actions['DRAWONE']:
print >>fh, self.actionString(act)
print >>fh, self.actionString(act, 'DRAWONE')
if act[0] == self.hero and act[1] == 'discards':
(nc,oc) = self.holecards['DRAWONE'][act[0]]
(nc,oc) = self.holecardsAsSet('DRAWONE', act[0])
dc = self.discards['DRAWONE'][act[0]]
kc = oc - dc
print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc)))
@ -998,9 +1006,9 @@ class DrawHand(Hand):
if 'DRAWTWO' in self.actions:
print >>fh, _("*** SECOND DRAW ***")
for act in self.actions['DRAWTWO']:
print >>fh, self.actionString(act)
print >>fh, self.actionString(act, 'DRAWTWO')
if act[0] == self.hero and act[1] == 'discards':
(nc,oc) = self.holecards['DRAWTWO'][act[0]]
(nc,oc) = self.holecardsAsSet('DRAWONE', act[0])
dc = self.discards['DRAWTWO'][act[0]]
kc = oc - dc
print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc)))
@ -1008,9 +1016,9 @@ class DrawHand(Hand):
if 'DRAWTHREE' in self.actions:
print >>fh, _("*** THIRD DRAW ***")
for act in self.actions['DRAWTHREE']:
print >>fh, self.actionString(act)
print >>fh, self.actionString(act, 'DRAWTHREE')
if act[0] == self.hero and act[1] == 'discards':
(nc,oc) = self.holecards['DRAWTHREE'][act[0]]
(nc,oc) = self.holecardsAsSet('DRAWONE', act[0])
dc = self.discards['DRAWTHREE'][act[0]]
kc = oc - dc
print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc)))

View File

@ -261,8 +261,8 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py.
gametype = self.determineGameType(handText)
log.debug("gametype %s" % gametype)
hand = None
l = None
if gametype is None:
l = None
gametype = "unmatched"
# TODO: not ideal, just trying to not error.
# TODO: Need to count failed hands.

View File

@ -173,8 +173,26 @@ class Hud:
item = gtk.CheckMenuItem(' All Levels')
self.aggMenu.append(item)
item.connect("activate", self.set_aggregation, ('P',10000))
setattr(self, 'h_aggBBmultItem10000', item)
#
setattr(self, 'h_aggBBmultItem10000', item)
#
item = gtk.MenuItem('For #Seats:')
self.aggMenu.append(item)
#
item = gtk.CheckMenuItem(' Any Number')
self.aggMenu.append(item)
item.connect("activate", self.set_seats_style, ('P','A'))
setattr(self, 'h_seatsStyleOptionA', item)
#
item = gtk.CheckMenuItem(' Custom')
self.aggMenu.append(item)
item.connect("activate", self.set_seats_style, ('P','C'))
setattr(self, 'h_seatsStyleOptionC', item)
#
item = gtk.CheckMenuItem(' Exact')
self.aggMenu.append(item)
item.connect("activate", self.set_seats_style, ('P','E'))
setattr(self, 'h_seatsStyleOptionE', item)
#
item = gtk.MenuItem('Since:')
self.aggMenu.append(item)
#
@ -224,8 +242,26 @@ class Hud:
item = gtk.CheckMenuItem(' All Levels')
self.aggMenu.append(item)
item.connect("activate", self.set_aggregation, ('O',10000))
setattr(self, 'aggBBmultItem10000', item)
#
setattr(self, 'aggBBmultItem10000', item)
#
item = gtk.MenuItem('For #Seats:')
self.aggMenu.append(item)
#
item = gtk.CheckMenuItem(' Any Number')
self.aggMenu.append(item)
item.connect("activate", self.set_seats_style, ('O','A'))
setattr(self, 'seatsStyleOptionA', item)
#
item = gtk.CheckMenuItem(' Custom')
self.aggMenu.append(item)
item.connect("activate", self.set_seats_style, ('O','C'))
setattr(self, 'seatsStyleOptionC', item)
#
item = gtk.CheckMenuItem(' Exact')
self.aggMenu.append(item)
item.connect("activate", self.set_seats_style, ('O','E'))
setattr(self, 'seatsStyleOptionE', item)
#
item = gtk.MenuItem('Since:')
self.aggMenu.append(item)
#
@ -267,6 +303,20 @@ class Hud:
elif self.hud_params['agg_bb_mult'] > 9000:
getattr(self, 'aggBBmultItem10000').set_active(True)
#
if self.hud_params['h_seats_style'] == 'A':
getattr(self, 'h_seatsStyleOptionA').set_active(True)
elif self.hud_params['h_seats_style'] == 'C':
getattr(self, 'h_seatsStyleOptionC').set_active(True)
elif self.hud_params['h_seats_style'] == 'E':
getattr(self, 'h_seatsStyleOptionE').set_active(True)
#
if self.hud_params['seats_style'] == 'A':
getattr(self, 'seatsStyleOptionA').set_active(True)
elif self.hud_params['seats_style'] == 'C':
getattr(self, 'seatsStyleOptionC').set_active(True)
elif self.hud_params['seats_style'] == 'E':
getattr(self, 'seatsStyleOptionE').set_active(True)
#
if self.hud_params['h_hud_style'] == 'A':
getattr(self, 'h_hudStyleOptionA').set_active(True)
elif self.hud_params['h_hud_style'] == 'S':
@ -344,6 +394,29 @@ class Hud:
if mult != str(num):
getattr(self, 'aggBBmultItem'+mult).set_active(False)
def set_seats_style(self, widget, val):
(player_opp, style) = val
if player_opp == 'P':
param = 'h_seats_style'
prefix = 'h_'
else:
param = 'seats_style'
prefix = ''
if style == 'A' and getattr(self, prefix+'seatsStyleOptionA').get_active():
self.hud_params[param] = 'A'
getattr(self, prefix+'seatsStyleOptionC').set_active(False)
getattr(self, prefix+'seatsStyleOptionE').set_active(False)
elif style == 'C' and getattr(self, prefix+'seatsStyleOptionC').get_active():
self.hud_params[param] = 'C'
getattr(self, prefix+'seatsStyleOptionA').set_active(False)
getattr(self, prefix+'seatsStyleOptionE').set_active(False)
elif style == 'E' and getattr(self, prefix+'seatsStyleOptionE').get_active():
self.hud_params[param] = 'E'
getattr(self, prefix+'seatsStyleOptionA').set_active(False)
getattr(self, prefix+'seatsStyleOptionC').set_active(False)
print "setting self.hud_params[%s] = %s" % (param, style)
def set_hud_style(self, widget, val):
(player_opp, style) = val
if player_opp == 'P':

View File

@ -50,7 +50,7 @@ class PokerStars(HandHistoryConverter):
\s?(?P<TOUR_ISO>%(LEGAL_ISO)s)?
)\s)? # close paren of tournament info
(?P<MIXED>HORSE|8\-Game|HOSE)?\s?\(?
(?P<GAME>Hold\'em|Razz|7\sCard\sStud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball)\s
(?P<GAME>Hold\'em|Razz|7\sCard\sStud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball|5\sCard\sDraw)\s
(?P<LIMIT>No\sLimit|Limit|Pot\sLimit)\)?,?\s
(-\sLevel\s(?P<LEVEL>[IVXLC]+)\s)?
\(? # open paren of the stakes
@ -101,7 +101,7 @@ class PokerStars(HandHistoryConverter):
self.re_HeroCards = re.compile(r"^Dealt to %(PLYR)s(?: \[(?P<OLDCARDS>.+?)\])?( \[(?P<NEWCARDS>.+?)\])" % subst, re.MULTILINE)
self.re_Action = re.compile(r"""
^%(PLYR)s:(?P<ATYPE>\sbets|\schecks|\sraises|\scalls|\sfolds|\sdiscards|\sstands\spat)
(\s%(CUR)s(?P<BET>[.\d]+))?(\sto\s%(CUR)s(?P<BETTO>[.\d]+))? # the number discarded goes in <BET>
(\s(%(CUR)s)?(?P<BET>[.\d]+))?(\sto\s%(CUR)s(?P<BETTO>[.\d]+))? # the number discarded goes in <BET>
(\scards?(\s\[(?P<DISCARDED>.+?)\])?)?"""
% subst, re.MULTILINE|re.VERBOSE)
self.re_ShowdownAction = re.compile(r"^%s: shows \[(?P<CARDS>.*)\]" % player_re, re.MULTILINE)
@ -133,6 +133,7 @@ class PokerStars(HandHistoryConverter):
info = {}
m = self.re_GameInfo.search(handText)
if not m:
print "DEBUG: determineGameType(): did not match"
return None
mg = m.groupdict()
@ -147,6 +148,7 @@ class PokerStars(HandHistoryConverter):
'7 Card Stud Hi/Lo' : ('stud','studhilo'),
'Badugi' : ('draw','badugi'),
'Triple Draw 2-7 Lowball' : ('draw','27_3draw'),
'5 Card Draw' : ('draw','fivedraw')
}
currencies = { u'':'EUR', '$':'USD', '':'T$' }
# I don't think this is doing what we think. mg will always have all

View File

@ -1402,6 +1402,7 @@ class Sql:
AND gt1.bigblind <= gt2.bigblind * %s /* bigblind similar size */
AND gt1.bigblind >= gt2.bigblind / %s
AND gt2.id = h.gametypeId)
AND hc.activeSeats between %s and %s
)
OR
( hp.playerId = %s
@ -1415,6 +1416,7 @@ class Sql:
AND gt1.bigblind <= gt2.bigblind * %s /* bigblind similar size */
AND gt1.bigblind >= gt2.bigblind / %s
AND gt2.id = h.gametypeId)
AND hc.activeSeats between %s and %s
)
)
GROUP BY hc.PlayerId, p.name
@ -1432,11 +1434,11 @@ class Sql:
if db_server == 'mysql':
self.query['get_stats_from_hand_session'] = """
SELECT hp.playerId AS player_id,
SELECT hp.playerId AS player_id, /* playerId and seats must */
h.seats AS seats, /* be first and second field */
hp.handId AS hand_id,
hp.seatNo AS seat,
p.name AS screen_name,
h.seats AS seats,
1 AS n,
cast(hp2.street0VPI as <signed>integer) AS vpip,
cast(hp2.street0Aggr as <signed>integer) AS pfr,
@ -1494,21 +1496,30 @@ class Sql:
cast(hp2.street4CheckCallRaiseChance as <signed>integer) AS ccr_opp_4,
cast(hp2.street4CheckCallRaiseDone as <signed>integer) AS ccr_4
FROM
Hands h /* players in this hand */
Hands h
INNER JOIN Hands h2 ON (h2.id > %s AND h2.tableName = h.tableName)
INNER JOIN HandsPlayers hp ON (h.id = hp.handId)
INNER JOIN HandsPlayers hp ON (h.id = hp.handId) /* players in this hand */
INNER JOIN HandsPlayers hp2 ON (hp2.playerId+0 = hp.playerId+0 AND (hp2.handId = h2.id+0)) /* other hands by these players */
INNER JOIN Players p ON (p.id = hp2.PlayerId+0)
WHERE hp.handId = %s
/* check activeseats once this data returned (don't want to do that here as it might
assume a session ended just because the number of seats dipped for a few hands)
*/
AND ( /* 2 separate parts for hero and opponents */
( hp2.playerId != %s
AND h2.seats between %s and %s
)
OR
( hp2.playerId = %s
AND h2.seats between %s and %s
)
)
ORDER BY h.handStart desc, hp2.PlayerId
/* order rows by handstart descending so that we can stop reading rows when
there's a gap over X minutes between hands (ie. when we get back to start of
the session */
"""
else: # assume postgresql
elif db_server == 'postgresql':
self.query['get_stats_from_hand_session'] = """
SELECT hp.playerId AS player_id,
hp.handId AS hand_id,
@ -1582,6 +1593,103 @@ class Sql:
/* check activeseats once this data returned (don't want to do that here as it might
assume a session ended just because the number of seats dipped for a few hands)
*/
AND ( /* 2 separate parts for hero and opponents */
( hp2.playerId != %s
AND h2.seats between %s and %s
)
OR
( hp2.playerId = %s
AND h2.seats between %s and %s
)
)
ORDER BY h.handStart desc, hp2.PlayerId
/* order rows by handstart descending so that we can stop reading rows when
there's a gap over X minutes between hands (ie. when we get back to start of
the session */
"""
elif db_server == 'sqlite':
self.query['get_stats_from_hand_session'] = """
SELECT hp.playerId AS player_id,
hp.handId AS hand_id,
hp.seatNo AS seat,
p.name AS screen_name,
h.seats AS seats,
1 AS n,
cast(hp2.street0VPI as <signed>integer) AS vpip,
cast(hp2.street0Aggr as <signed>integer) AS pfr,
cast(hp2.street0_3BChance as <signed>integer) AS TB_opp_0,
cast(hp2.street0_3BDone as <signed>integer) AS TB_0,
cast(hp2.street1Seen as <signed>integer) AS saw_f,
cast(hp2.street1Seen as <signed>integer) AS saw_1,
cast(hp2.street2Seen as <signed>integer) AS saw_2,
cast(hp2.street3Seen as <signed>integer) AS saw_3,
cast(hp2.street4Seen as <signed>integer) AS saw_4,
cast(hp2.sawShowdown as <signed>integer) AS sd,
cast(hp2.street1Aggr as <signed>integer) AS aggr_1,
cast(hp2.street2Aggr as <signed>integer) AS aggr_2,
cast(hp2.street3Aggr as <signed>integer) AS aggr_3,
cast(hp2.street4Aggr as <signed>integer) AS aggr_4,
cast(hp2.otherRaisedStreet1 as <signed>integer) AS was_raised_1,
cast(hp2.otherRaisedStreet2 as <signed>integer) AS was_raised_2,
cast(hp2.otherRaisedStreet3 as <signed>integer) AS was_raised_3,
cast(hp2.otherRaisedStreet4 as <signed>integer) AS was_raised_4,
cast(hp2.foldToOtherRaisedStreet1 as <signed>integer) AS f_freq_1,
cast(hp2.foldToOtherRaisedStreet2 as <signed>integer) AS f_freq_2,
cast(hp2.foldToOtherRaisedStreet3 as <signed>integer) AS f_freq_3,
cast(hp2.foldToOtherRaisedStreet4 as <signed>integer) AS f_freq_4,
cast(hp2.wonWhenSeenStreet1 as <signed>integer) AS w_w_s_1,
cast(hp2.wonAtSD as <signed>integer) AS wmsd,
cast(hp2.stealAttemptChance as <signed>integer) AS steal_opp,
cast(hp2.stealAttempted as <signed>integer) AS steal,
cast(hp2.foldSbToStealChance as <signed>integer) AS SBstolen,
cast(hp2.foldedSbToSteal as <signed>integer) AS SBnotDef,
cast(hp2.foldBbToStealChance as <signed>integer) AS BBstolen,
cast(hp2.foldedBbToSteal as <signed>integer) AS BBnotDef,
cast(hp2.street1CBChance as <signed>integer) AS CB_opp_1,
cast(hp2.street1CBDone as <signed>integer) AS CB_1,
cast(hp2.street2CBChance as <signed>integer) AS CB_opp_2,
cast(hp2.street2CBDone as <signed>integer) AS CB_2,
cast(hp2.street3CBChance as <signed>integer) AS CB_opp_3,
cast(hp2.street3CBDone as <signed>integer) AS CB_3,
cast(hp2.street4CBChance as <signed>integer) AS CB_opp_4,
cast(hp2.street4CBDone as <signed>integer) AS CB_4,
cast(hp2.foldToStreet1CBChance as <signed>integer) AS f_cb_opp_1,
cast(hp2.foldToStreet1CBDone as <signed>integer) AS f_cb_1,
cast(hp2.foldToStreet2CBChance as <signed>integer) AS f_cb_opp_2,
cast(hp2.foldToStreet2CBDone as <signed>integer) AS f_cb_2,
cast(hp2.foldToStreet3CBChance as <signed>integer) AS f_cb_opp_3,
cast(hp2.foldToStreet3CBDone as <signed>integer) AS f_cb_3,
cast(hp2.foldToStreet4CBChance as <signed>integer) AS f_cb_opp_4,
cast(hp2.foldToStreet4CBDone as <signed>integer) AS f_cb_4,
cast(hp2.totalProfit as <signed>integer) AS net,
cast(hp2.street1CheckCallRaiseChance as <signed>integer) AS ccr_opp_1,
cast(hp2.street1CheckCallRaiseDone as <signed>integer) AS ccr_1,
cast(hp2.street2CheckCallRaiseChance as <signed>integer) AS ccr_opp_2,
cast(hp2.street2CheckCallRaiseDone as <signed>integer) AS ccr_2,
cast(hp2.street3CheckCallRaiseChance as <signed>integer) AS ccr_opp_3,
cast(hp2.street3CheckCallRaiseDone as <signed>integer) AS ccr_3,
cast(hp2.street4CheckCallRaiseChance as <signed>integer) AS ccr_opp_4,
cast(hp2.street4CheckCallRaiseDone as <signed>integer) AS ccr_4
FROM Hands h /* this hand */
INNER JOIN Hands h2 ON ( h2.id > %s /* other hands */
AND h2.tableName = h.tableName)
INNER JOIN HandsPlayers hp ON (h.id = hp.handId) /* players in this hand */
INNER JOIN HandsPlayers hp2 ON ( hp2.playerId+0 = hp.playerId+0
AND hp2.handId = h2.id) /* other hands by these players */
INNER JOIN Players p ON (p.id = hp2.PlayerId+0)
WHERE h.id = %s
/* check activeseats once this data returned (don't want to do that here as it might
assume a session ended just because the number of seats dipped for a few hands)
*/
AND ( /* 2 separate parts for hero and opponents */
( hp2.playerId != %s
AND h2.seats between %s and %s
)
OR
( hp2.playerId = %s
AND h2.seats between %s and %s
)
)
ORDER BY h.handStart desc, hp2.PlayerId
/* order rows by handstart descending so that we can stop reading rows when
there's a gap over X minutes between hands (ie. when we get back to start of
@ -1605,10 +1713,13 @@ class Sql:
self.query['get_table_name'] = """
SELECT h.tableName, h.maxSeats, gt.category, gt.type, s.id, s.name
FROM Hands h, Gametypes gt, Sites s
, count(1) as numseats
FROM Hands h, Gametypes gt, Sites s, HandsPlayers hp
WHERE h.id = %s
AND gt.id = h.gametypeId
AND s.id = gt.siteID
AND hp.handId = h.id
GROUP BY h.tableName, h.maxSeats, gt.category, gt.type, s.id, s.name
"""
self.query['get_actual_seat'] = """

View File

@ -248,7 +248,7 @@ class ttracker_main(object):
# get basic info about the new hand from the db
# if there is a db error, complain, skip hand, and proceed
try:
(table_name, max, poker_game, type, site_id) = self.db_connection.get_table_name(new_hand_id)
(table_name, max, poker_game, type, site_id, numseats) = self.db_connection.get_table_name(new_hand_id)
stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, aggregate_stats[type]
,hud_style, agg_bb_mult)

View File

@ -95,37 +95,97 @@ class fpdb:
self.add_tab(new_tab, new_tab_name)
self.display_tab(new_tab_name)
def add_tab(self, new_tab, new_tab_name):
def add_tab(self, new_page, new_tab_name):
"""adds a tab, namely creates the button and displays it and appends all the relevant arrays"""
for i in self.tab_names: #todo: check this is valid
if i == new_tab_name:
for name in self.nb_tabs: #todo: check this is valid
if name == new_tab_name:
return # if tab already exists, just go to it
self.tabs.append(new_tab)
self.tab_names.append(new_tab_name)
used_before = False
for i, name in enumerate(self.tab_names): #todo: check this is valid
if name == new_tab_name:
used_before = True
event_box = self.tabs[i]
page = self.pages[i]
break
new_tab_sel_button = gtk.ToggleButton(new_tab_name)
new_tab_sel_button.connect("clicked", self.tab_clicked, new_tab_name)
self.tab_box.add(new_tab_sel_button)
new_tab_sel_button.show()
self.tab_buttons.append(new_tab_sel_button)
if not used_before:
event_box = self.create_custom_tab(new_tab_name, self.nb)
page = new_page
self.pages.append(new_page)
self.tabs.append(event_box)
self.tab_names.append(new_tab_name)
#self.nb.append_page(new_page, gtk.Label(new_tab_name))
self.nb.append_page(page, event_box)
self.nb_tabs.append(new_tab_name)
page.show()
def display_tab(self, new_tab_name):
"""displays the indicated tab"""
tab_no = -1
for i, name in enumerate(self.tab_names):
if name == new_tab_name:
for i, name in enumerate(self.nb_tabs):
if new_tab_name == name:
tab_no = i
break
if tab_no == -1:
raise FpdbError("invalid tab_no")
if tab_no < 0 or tab_no >= self.nb.get_n_pages():
raise FpdbError("invalid tab_no " + str(tab_no))
else:
self.main_vbox.remove(self.current_tab)
self.current_tab=self.tabs[tab_no]
self.main_vbox.add(self.current_tab)
self.tab_buttons[tab_no].set_active(True)
self.current_tab.show()
self.nb.set_current_page(tab_no)
def create_custom_tab(self, text, nb):
#create a custom tab for notebook containing a
#label and a button with STOCK_ICON
eventBox = gtk.EventBox()
tabBox = gtk.HBox(False, 2)
tabLabel = gtk.Label(text)
tabBox.pack_start(tabLabel, False)
eventBox.add(tabBox)
if nb.get_n_pages() > 0:
tabButton = gtk.Button()
tabButton.connect('clicked', self.remove_tab, (nb, text))
#Add a picture on a button
self.add_icon_to_button(tabButton)
tabBox.pack_start(tabButton, False)
# needed, otherwise even calling show_all on the notebook won't
# make the hbox contents appear.
tabBox.show_all()
return eventBox
def add_icon_to_button(self, button):
iconBox = gtk.HBox(False, 0)
image = gtk.Image()
image.set_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_MENU)
gtk.Button.set_relief(button, gtk.RELIEF_NONE)
settings = gtk.Widget.get_settings(button);
(w,h) = gtk.icon_size_lookup_for_settings(settings, gtk.ICON_SIZE_MENU);
gtk.Widget.set_size_request (button, w + 4, h + 4);
image.show()
iconBox.pack_start(image, True, False, 0)
button.add(iconBox)
iconBox.show()
return
# Remove a page from the notebook
def remove_tab(self, button, data):
(nb, text) = data
page = -1
#print "\n remove_tab: start", text
for i, tab in enumerate(self.nb_tabs):
if text == tab:
page = i
#print " page =", page
if page >= 0 and page < self.nb.get_n_pages():
#print " removing page", page
del self.nb_tabs[page]
nb.remove_page(page)
# Need to refresh the widget --
# This forces the widget to redraw itself.
#nb.queue_draw_area(0,0,-1,-1) needed or not??
def delete_event(self, widget, event, data=None):
return False
@ -473,6 +533,10 @@ class fpdb:
except Exceptions.FpdbMySQLAccessDenied:
self.warning_box("MySQL Server reports: Access denied. Are your permissions set correctly?")
exit()
except Exceptions.FpdbMySQLNoDatabase:
msg = "MySQL client reports: 2002 error. Unable to connect - Please check that the MySQL service has been started"
self.warning_box(msg)
exit
# except FpdbMySQLFailedError:
# self.warning_box("Unable to connect to MySQL! Is the MySQL server running?!", "FPDB ERROR")
@ -628,18 +692,14 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
menubar.show()
#done menubar
self.nb = gtk.Notebook()
self.nb.set_show_tabs(True)
self.nb.show()
self.main_vbox.pack_start(self.nb, True, True, 0)
self.pages=[]
self.tabs=[]
self.tab_names=[]
self.tab_buttons=[]
self.tab_box = gtk.HBox(True,1)
self.main_vbox.pack_start(self.tab_box, False, True, 0)
self.tab_box.show()
#done tab bar
self.current_tab = gtk.VBox(False,1)
self.current_tab.set_border_width(1)
self.main_vbox.add(self.current_tab)
self.current_tab.show()
self.nb_tabs=[]
self.tab_main_help(None, None)

View File

@ -106,6 +106,8 @@ class fpdb_db:
except MySQLdb.Error, ex:
if ex.args[0] == 1045:
raise FpdbMySQLAccessDenied(ex.args[0], ex.args[1])
elif ex.args[0] == 2002:
raise FpdbMySQLNoDatabase(ex.args[0], ex.args[1])
else:
print "*** WARNING UNKNOWN MYSQL ERROR", ex
elif backend == fpdb_db.PGSQL:

View File

@ -95,16 +95,16 @@ def testStudImport():
(stored, dups, partial, errs, ttime) = importer.runImport()
importer.clearFileList()
#def testDrawImport():
# db.recreate_tables()
# importer = fpdb_import.Importer(False, settings, config)
# importer.setDropIndexes("don't drop")
# importer.setFailOnError(True)
# importer.setThreads(-1)
# importer.addBulkImportImportFileOrDir(
# """regression-test-files/cash/Stars/Draw/3-Draw-Limit-USD-0.10-0.20-200911.txt""", site="PokerStars")
# importer.addBulkImportImportFileOrDir(
# """regression-test-files/cash/Stars/Draw/5-Carddraw-USD-0.10-0.20-200911.txt""", site="PokerStars")
# importer.setCallHud(False)
# (stored, dups, partial, errs, ttime) = importer.runImport()
# importer.clearFileList()
def testDrawImport():
db.recreate_tables()
importer = fpdb_import.Importer(False, settings, config)
importer.setDropIndexes("don't drop")
importer.setFailOnError(True)
importer.setThreads(-1)
importer.addBulkImportImportFileOrDir(
"""regression-test-files/cash/Stars/Draw/3-Draw-Limit-USD-0.10-0.20-200911.txt""", site="PokerStars")
importer.addBulkImportImportFileOrDir(
"""regression-test-files/cash/Stars/Draw/5-Carddraw-USD-0.10-0.20-200911.txt""", site="PokerStars")
importer.setCallHud(False)
(stored, dups, partial, errs, ttime) = importer.runImport()
importer.clearFileList()