diff --git a/THANKS.txt b/THANKS.txt new file mode 100644 index 00000000..7adf9825 --- /dev/null +++ b/THANKS.txt @@ -0,0 +1,35 @@ +=**Thanks - Contributors to FPDB**= + +This page is to acknowledge the people developing and contributing to FPDB, be it with code, documentation, testing, forum support and everything else that is required to make an open source project work. + +Most people have found the project though the software forum at [[http://forumserver.twoplustwo.com/45/software/|2+2]] so most references to 2+2 aliases + +Sincere apologies to those not listed. FPDB started life in August 2008, but we only got around to putting together a proper contributers list in April 2009. Private messages and emails have been deleted so we dont have a full history of non-code based contributions + +==**Developers**== +Active: +Steffen123 - The initial code drop and project lead. +Eratosthenes - Initial HUD code drop, release manager +Ekdikeo - Contributor - contributed Everleaf support and much HUD work +Sorrow - Contributor - Graphing, import framework +mcturnbull (2+2?) - Contributor - import framework + +Inactive: +Sqlcoder - SQL query guru - Graphing filters, Player Stats, Positional Stats queries + general sql optimisation work +Bostik - Author of [[http://bostik.iki.fi/pokerstats/|PokerStats]] - Postgres linux work. PokerStats import code was the inspiration for the new framework. I'm sure well use more of his ideas in future. +FIXME - Original windows installer/packager + +==Documentation== +FIXME - Original web site guy +FIXME - Guy who wrote the Mac install page +FIXME - Any other wiki editors. + +==Other== +Eleatic Stranger - Super tester and contributor - Our #1 tester. Tracks the git repo and works the code harder than anyone and gives great feedback and bug reports. Thankyou. +Xaviax - Tester and honorary helpdesk - Another excellent tester tracking git, has responded to many queries in the fpdb thread on his own time. +KayosD - Hand History donation - Carbon Poker +freerollerjb - Hand History donation - Carbon Poker +puru - Hand History donation - Carbon Poker +freestailo - Hand History donation - Carbon Poker +MoDDe (Sourceforge) - Hand History Donation - Betfair +Jay10826 - Hand History donation - Ultimate Bet diff --git a/pyfpdb/CarbonToFpdb.py b/pyfpdb/CarbonToFpdb.py index cf9fc8d3..fa1ad6fd 100644 --- a/pyfpdb/CarbonToFpdb.py +++ b/pyfpdb/CarbonToFpdb.py @@ -54,6 +54,7 @@ class CarbonPoker(HandHistoryConverter): print "Initialising Carbon Poker converter class" HandHistoryConverter.__init__(self, config, filename, "Carbon") # Call super class init self.setFileType("xml") + self.siteId = 4 # Needs to match id entry in Sites database def readSupportedGames(self): pass diff --git a/pyfpdb/Card.py b/pyfpdb/Card.py new file mode 100755 index 00000000..75c742f9 --- /dev/null +++ b/pyfpdb/Card.py @@ -0,0 +1,83 @@ +#!/usr/bin/python + +#Copyright 2008 Carl Gherardi +#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 . +#In the "official" distribution you can find the license in +#agpl-3.0.txt in the docs folder of the package. + + + + +def twoStartCards(value1, suit1, value2, suit2): + """ Function to convert 2 value,suit pairs into a Holdem style starting hand e.g. AQo + Hand is stored as an int 13 * x + y where (x+2) represents rank of 1st card and + (y+2) represents rank of second card (2=2 .. 14=Ace) + If x > y then pair is suited, if x < y then unsuited""" + if value1 < 2 or value2 < 2: + return(0) + if (suit1 == suit2 and value1 < value2) or (suit1 != suit2 and value2 > value1): + return(13 * (value2-2) + (value1-1)) + else: + return(13 * (value1-2) + (value2-1)) + +def twoStartCardString(card): + """ Function to convert an int representing 2 holdem hole cards (as created by twoStartCards) + into a string like AQo """ + if card <= 0: + return 'xx' + else: + card -= 1 + s = ('2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A') + x = card/13 + y = card - 13*x + if x == y: return(s[x] + s[y]) + elif x > y: return(s[x] + s[y] + 's') + else: return(s[y] + s[x] + 'o') + +def fourStartCards(value1, suit1, value2, suit2, value3, suit3, value4, suit4): + """ Function to convert 4 value,suit pairs into a Omaha style starting hand, + haven't decided how to encode this yet """ + # This doesn't actually do anything yet - CG + + # What combinations do we need to store? just cards: AA23? some suits as well e.g. when + # double suited ATcKTd? Lots more possible combos than holdem :-( 270K vs 1326? not sure + # Probably need to use this field as a key into some other table - sc + + #AAKKds + #AAKKs + #AAKKr + # Is probably what we are looking for + return(0) + +def cardFromValueSuit(value, suit): + """ 0=none, 1-13=2-Ah 14-26=2-Ad 27-39=2-Ac 40-52=2-As """ + if suit == 'h': return(value-1) + elif suit == 'd': return(value+12) + elif suit == 'c': return(value+25) + elif suit == 's': return(value+38) + else: return(0) + +def valueSuitFromCard(card): + """ Function to convert a card stored in the database (int 0-52) into value + and suit like 9s, 4c etc """ + if card < 0 or card > 52: + return('') + else: + return( ['', '2h', '3h', '4h', '5h', '6h', '7h', '8h', '9h', 'Th', 'Jh', 'Qh', 'Kh', 'Ah' + , '2d', '3d', '4d', '5d', '6d', '7d', '8d', '9d', 'Td', 'Jd', 'Qd', 'Kd', 'Ad' + , '2c', '3c', '4c', '5c', '6c', '7c', '8c', '9c', 'Tc', 'Jc', 'Qc', 'Kc', 'Ac' + , '2s', '3s', '4s', '5s', '6s', '7s', '8s', '9s', 'Ts', 'Js', 'Qs', 'Ks', 'As' + ][card] ) + + + diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index e6395301..1d93f3f1 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -197,6 +197,15 @@ class Aux_window: temp = temp + "%s" % self.layout[layout] return temp +class HHC: + def __init__(self, node): + self.site = node.getAttribute("site") + self.converter = node.getAttribute("converter") + + def __str__(self): + return "%s:\t%s" % (self.site, self.converter) + + class Popup: def __init__(self, node): self.name = node.getAttribute("pu_name") @@ -277,6 +286,7 @@ class Config: self.supported_games = {} self.supported_databases = {} self.aux_windows = {} + self.hhcs = {} self.popup_windows = {} # s_sites = doc.getElementsByTagName("supported_sites") @@ -299,6 +309,11 @@ class Config: aw = Aux_window(node = aw_node) self.aux_windows[aw.name] = aw +# s_dbs = doc.getElementsByTagName("mucked_windows") + for hhc_node in doc.getElementsByTagName("hhc"): + hhc = HHC(node = hhc_node) + self.hhcs[hhc.site] = hhc + # s_dbs = doc.getElementsByTagName("popup_windows") for pu_node in doc.getElementsByTagName("pu"): pu = Popup(node = pu_node) @@ -706,6 +721,11 @@ if __name__== "__main__": for w in c.aux_windows.keys(): print c.aux_windows[w] print "----------- END AUX WINDOW FORMATS -----------" + + print "\n----------- HAND HISTORY CONVERTERS -----------" + for w in c.hhcs.keys(): + print c.hhcs[w] + print "----------- END HAND HISTORY CONVERTERS -----------" print "\n----------- POPUP WINDOW FORMATS -----------" for w in c.popup_windows.keys(): diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py old mode 100644 new mode 100755 index 236a8dc2..0eabcdda --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -27,12 +27,14 @@ Create and manage the database objects. import sys import traceback import string +from datetime import datetime, date, time, timedelta # pyGTK modules # FreePokerTools modules import Configuration import SQL +import Card class Database: def __init__(self, c, db_name, game): @@ -83,8 +85,38 @@ class Database: sys.exit() self.type = db_params['db-type'] - self.sql = SQL.Sql(game = game, type = self.type) - + self.db_server = c.supported_databases[db_name].db_server + self.sql = SQL.Sql(game = game, type = self.type, db_server = self.db_server) + self.connection.rollback() + # To add to config: + self.hud_style = 'T' # A=All-time + # S=Session + # T=timed (last n days) + # Future values may also include: + # H=Hands (last n hands) + self.hud_hands = 1000 # Max number of hands from each player to use for hud stats + self.hud_days = 90 # Max number of days from each player to use for hud stats + self.hud_session_gap = 30 # Gap (minutes) between hands that indicates a change of session + # (hands every 2 mins for 1 hour = one session, if followed + # by a 40 minute gap and then more hands on same table that is + # a new session) + cur = self.connection.cursor() + + self.hand_1day_ago = 0 + cur.execute(self.sql.query['get_hand_1day_ago']) + row = cur.fetchone() + if row and row[0]: + self.hand_1day_ago = row[0] + #print "hand 1day ago =", self.hand_1day_ago + + d = timedelta(days=self.hud_days) + now = datetime.utcnow() - d + self.date_ndays_ago = "d%02d%02d%02d" % (now.year-2000, now.month, now.day) + + self.hand_nhands_ago = 0 # todo + #cur.execute(self.sql.query['get_table_name'], (hand_id, )) + #row = cur.fetchone() + def close_connection(self): self.connection.close() @@ -126,13 +158,19 @@ class Database: """Get and return the cards for each player in the hand.""" cards = {} # dict of cards, the key is the seat number example: {1: 'AcQd9hTs5d'} c = self.connection.cursor() - c.execute(self.sql.query['get_cards'], (hand, )) + c.execute(self.sql.query['get_cards'], [hand]) colnames = [desc[0] for desc in c.description] + cardnames = ['card1', 'card2', 'card3', 'card4', 'card5', 'card6', 'card7'] for row in c.fetchall(): - s_dict = {} - for name, val in zip(colnames, row): - s_dict[name] = val - cards[s_dict['seat_number']] = (self.convert_cards(s_dict)) + cs = ['', '', '', '', '', '', ''] + seat = -1 + for col,name in enumerate(colnames): + if name in cardnames: + cs[cardnames.index(name)] = Card.valueSuitFromCard(row[col]) + elif name == 'seat_number': + seat = row[col] + if seat != -1: + cards[seat] = ''.join(cs) return cards def get_common_cards(self, hand): @@ -190,31 +228,89 @@ class Database: return winners def get_stats_from_hand(self, hand, aggregate = False): + if self.hud_style == 'S': + return( self.get_stats_from_hand_session(hand) ) + else: # self.hud_style == A + if aggregate: + query = 'get_stats_from_hand_aggregated' + else: + query = 'get_stats_from_hand' + + if self.hud_style == 'T': + stylekey = self.date_ndays_ago + else: # assume A (all-time) + stylekey = '0000000' # all stylekey values should be higher than this + + subs = (hand, hand, stylekey) + #print "get stats: hud style =", self.hud_style, "subs =", subs c = self.connection.cursor() - if aggregate: - query = 'get_stats_from_hand_aggregated' - subs = (hand, hand, hand) - else: - query = 'get_stats_from_hand' - subs = (hand, hand) - -# now get the stats +# now get the stats c.execute(self.sql.query[query], subs) colnames = [desc[0] for desc in c.description] stat_dict = {} for row in c.fetchall(): t_dict = {} for name, val in zip(colnames, row): - t_dict[name] = val + t_dict[name.lower()] = val +# print t_dict stat_dict[t_dict['player_id']] = t_dict + + 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): + + if self.hud_style == 'S': + query = self.sql.query['get_stats_from_hand_session'] + if self.db_server == 'mysql': + query = query.replace("", 'signed ') + else: + query = query.replace("", '') + else: # self.hud_style == A + return None + + subs = (self.hand_1day_ago, hand) + c = self.connection.cursor() + + # now get the stats + #print "sess_stats: subs =", subs, "subs[0] =", subs[0] + c.execute(query, subs) + colnames = [desc[0] for desc in c.description] + n,stat_dict = 0,{} + row = c.fetchone() + while row: + if colnames[0].lower() == 'player_id': + playerid = row[0] + else: + print "ERROR: query %s result does not have player_id as first column" % (query,) + break + + for name, val in zip(colnames, row): + if not playerid in stat_dict: + stat_dict[playerid] = {} + stat_dict[playerid][name.lower()] = val + elif not name.lower() in stat_dict[playerid]: + stat_dict[playerid][name.lower()] = val + elif name.lower() not in ('hand_id', 'player_id', 'seat', 'screen_name', 'seats'): + stat_dict[playerid][name.lower()] += val + n += 1 + if n >= 4000: break # todo: don't think this is needed so set nice and high + # for now - comment out or remove? + row = c.fetchone() + #print " %d rows fetched, len(stat_dict) = %d" % (n, len(stat_dict)) + + #print "session stat_dict =", stat_dict return stat_dict def get_player_id(self, config, site, player_name): c = self.connection.cursor() c.execute(self.sql.query['get_player_id'], {'player': player_name, 'site': site}) row = c.fetchone() - return row[0] + if row: + return row[0] + else: + return None if __name__=="__main__": c = Configuration.Config() diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index b526632a..68bc8d8f 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -26,8 +26,10 @@ class DerivedStats(): self.HDs = 0 self.street0VPI = 0 self.street0Aggr = 0 - self.street0_3B4BChance = 0 - self.street0_3B4BDone = 0 + self.street0_3BChance = 0 + self.street0_3BDone = 0 + self.street0_4BChance = 0 + self.street0_4BDone = 0 self.street1Seen = 0 self.street2Seen = 0 diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index 29808295..6ed2b6ba 100755 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -27,7 +27,8 @@ from HandHistoryConverter import * class Everleaf(HandHistoryConverter): # Static regexes - re_SplitHands = re.compile(r"(\n\n\n+)") + re_SplitHands = re.compile(r"\n\n\n+") + re_TailSplitHands = re.compile(r"(\n\n\n+)") re_GameInfo = re.compile(ur"^(Blinds )?(?P\$| €|)(?P[.0-9]+)/(?:\$| €)?(?P[.0-9]+) (?PNL|PL|) ?(?P(Hold\'em|Omaha|7 Card Stud))", re.MULTILINE) #re.compile(ur"^(Blinds )?(?P\$| €|)(?P[.0-9]+)/(?:\$| €)?(?P[.0-9]+) (?PNL|PL|) (?P(Hold\'em|Omaha|7 Card Stud))", re.MULTILINE) re_HandInfo = re.compile(ur".*#(?P[0-9]+)\n.*\n(Blinds )?(?:\$| €|)(?P[.0-9]+)/(?:\$| €|)(?P[.0-9]+) (?P.*) - (?P\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P.+$)", re.MULTILINE) @@ -48,6 +49,7 @@ debugging: if False, pass on partially supported game types. If true, have a go logging.info("Initialising Everleaf converter class") self.filetype = "text" self.codepage = "cp1252" + self.siteId = 3 # Needs to match id entry in Sites database self.debugging = debugging if autostart: self.start() diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py new file mode 100644 index 00000000..3a5f0365 --- /dev/null +++ b/pyfpdb/Filters.py @@ -0,0 +1,540 @@ +#!/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 . +#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 sys +from optparse import OptionParser +from time import * +#import pokereval + +import Configuration +import fpdb_db +import FpdbSQLQueries + +class Filters(threading.Thread): + def __init__(self, db, settings, config, qdict, display = {},debug=True): + self.debug=debug + #print "start of GraphViewer constructor" + self.db=db + self.cursor=db.cursor + self.settings=settings + self.sql=qdict + self.conf = config + self.display = display + + self.sites = {} + self.games = {} + self.limits = {} + self.seats = {} + self.siteid = {} + self.heroes = {} + self.boxes = {} + + # text used on screen stored here so that it can be configured + self.filterText = {'limitsall':'All', 'limitsnone':'None', 'limitsshow':'Show _Limits' + ,'seatsbetween':'Between:', 'seatsand':'And:', 'seatsshow':'Show Number of _Players' + ,'limitstitle':'Limits:', 'seatstitle':'Number of Players:' + } + + # 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) + + # Outer Packing box + self.mainVBox = gtk.VBox(False, 0) + + playerFrame = gtk.Frame("Hero:") + playerFrame.set_label_align(0.0, 0.0) + vbox = gtk.VBox(False, 0) + + self.fillPlayerFrame(vbox) + playerFrame.add(vbox) + self.boxes['player'] = vbox + + sitesFrame = gtk.Frame("Sites:") + sitesFrame.set_label_align(0.0, 0.0) + vbox = gtk.VBox(False, 0) + + self.fillSitesFrame(vbox) + sitesFrame.add(vbox) + self.boxes['sites'] = vbox + + # Game types + gamesFrame = gtk.Frame("Games:") + gamesFrame.set_label_align(0.0, 0.0) + gamesFrame.show() + vbox = gtk.VBox(False, 0) + + self.fillGamesFrame(vbox) + gamesFrame.add(vbox) + self.boxes['games'] = vbox + + # Limits + limitsFrame = gtk.Frame() + limitsFrame.show() + vbox = gtk.VBox(False, 0) + self.cbLimits = {} + self.cbNoLimits = None + self.cbAllLimits = None + + self.fillLimitsFrame(vbox, self.display) + limitsFrame.add(vbox) + + # Seats + seatsFrame = gtk.Frame() + seatsFrame.show() + vbox = gtk.VBox(False, 0) + self.sbSeats = {} + + self.fillSeatsFrame(vbox, self.display) + seatsFrame.add(vbox) + + # Date + dateFrame = gtk.Frame("Date:") + dateFrame.set_label_align(0.0, 0.0) + dateFrame.show() + vbox = gtk.VBox(False, 0) + + self.fillDateFrame(vbox) + dateFrame.add(vbox) + self.boxes['date'] = vbox + + # Buttons + self.Button1=gtk.Button("Unnamed 1") + self.Button1.set_sensitive(False) + + self.Button2=gtk.Button("Unnamed 2") + self.Button2.set_sensitive(False) + + self.mainVBox.add(playerFrame) + self.mainVBox.add(sitesFrame) + self.mainVBox.add(gamesFrame) + self.mainVBox.add(limitsFrame) + self.mainVBox.add(seatsFrame) + self.mainVBox.add(dateFrame) + self.mainVBox.add(self.Button1) + self.mainVBox.add(self.Button2) + + self.mainVBox.show_all() + + # Should do this cleaner + if "Heroes" not in self.display or self.display["Heroes"] == False: + playerFrame.hide() + if "Sites" not in self.display or self.display["Sites"] == False: + sitesFrame.hide() + if "Games" not in self.display or self.display["Games"] == False: + gamesFrame.hide() + if "Limits" not in self.display or self.display["Limits"] == False: + limitsFrame.hide() + if "Seats" not in self.display or self.display["Seats"] == False: + seatsFrame.hide() + if "Dates" not in self.display or self.display["Dates"] == False: + dateFrame.hide() + if "Button1" not in self.display or self.display["Button1"] == False: + self.Button1.hide() + if "Button2" not in self.display or self.display["Button2"] == False: + self.Button2.hide() + + def get_vbox(self): + """returns the vbox of this thread""" + return self.mainVBox + #end def get_vbox + + def getSites(self): + return self.sites + + def getSiteIds(self): + return self.siteid + + def getHeroes(self): + return self.heroes + + def getLimits(self): + ltuple = [] + for l in self.limits: + if self.limits[l] == True: + ltuple.append(l) + return ltuple + + def getSeats(self): + if 'from' in self.sbSeats: + self.seats['from'] = self.sbSeats['from'].get_value_as_int() + if 'to' in self.sbSeats: + self.seats['to'] = self.sbSeats['to'].get_value_as_int() + return self.seats + + def getDates(self): + return self.__get_dates() + + def registerButton1Name(self, title): + self.Button1.set_label(title) + + def registerButton1Callback(self, callback): + self.Button1.connect("clicked", callback, "clicked") + self.Button1.set_sensitive(True) + + def registerButton2Name(self, title): + self.Button2.set_label(title) + + def registerButton2Callback(self, callback): + self.Button2.connect("clicked", callback, "clicked") + self.Button2.set_sensitive(True) + + def cardCallback(self, widget, data=None): + print "DEBUG: %s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()]) + + def createPlayerLine(self, hbox, site, player): + label = gtk.Label(site +" id:") + hbox.pack_start(label, False, False, 0) + + 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 + + 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 createSiteLine(self, hbox, site): + cb = gtk.CheckButton(site) + cb.connect('clicked', self.__set_site_select, site) + cb.set_active(True) + hbox.pack_start(cb, False, False, 0) + + def createGameLine(self, hbox, game): + cb = gtk.CheckButton(game) + cb.connect('clicked', self.__set_game_select, game) + hbox.pack_start(cb, False, False, 0) + + def createLimitLine(self, hbox, limit, ltext): + cb = gtk.CheckButton(str(ltext)) + cb.connect('clicked', self.__set_limit_select, limit) + hbox.pack_start(cb, False, False, 0) + if limit != "none": + cb.set_active(True) + return(cb) + + def __set_site_select(self, w, site): + #print w.get_active() + self.sites[site] = w.get_active() + print "self.sites[%s] set to %s" %(site, self.sites[site]) + + def __set_game_select(self, w, game): + #print w.get_active() + self.games[game] = w.get_active() + print "self.games[%s] set to %s" %(game, self.games[game]) + + def __set_limit_select(self, w, limit): + #print w.get_active() + self.limits[limit] = w.get_active() + print "self.limit[%s] set to %s" %(limit, self.limits[limit]) + if str(limit).isdigit(): + if self.limits[limit]: + if self.cbNoLimits != None: + self.cbNoLimits.set_active(False) + else: + if self.cbAllLimits != None: + self.cbAllLimits.set_active(False) + elif limit == "all": + if self.limits[limit]: + for cb in self.cbLimits.values(): + cb.set_active(True) + elif limit == "none": + if self.limits[limit]: + for cb in self.cbLimits.values(): + cb.set_active(False) + + def __set_seat_select(self, w, seat): + #print "__set_seat_select: seat =", seat, "active =", w.get_active() + self.seats[seat] = w.get_active() + print "self.seats[%s] set to %s" %(seat, self.seats[seat]) + + def fillPlayerFrame(self, vbox): + for site in self.conf.get_supported_sites(): + pathHBox = gtk.HBox(False, 0) + vbox.pack_start(pathHBox, False, True, 0) + + player = self.conf.supported_sites[site].screen_name + self.createPlayerLine(pathHBox, site, player) + + def fillSitesFrame(self, vbox): + for site in self.conf.get_supported_sites(): + hbox = gtk.HBox(False, 0) + vbox.pack_start(hbox, False, True, 0) + self.createSiteLine(hbox, site) + #Get db site id for filtering later + self.cursor.execute(self.sql.query['getSiteId'], (site,)) + result = self.db.cursor.fetchall() + if len(result) == 1: + self.siteid[site] = result[0][0] + else: + print "Either 0 or more than one site matched - EEK" + + def fillGamesFrame(self, vbox): + self.cursor.execute(self.sql.query['getGames']) + result = self.db.cursor.fetchall() + if len(result) >= 1: + for line in result: + hbox = gtk.HBox(False, 0) + vbox.pack_start(hbox, False, True, 0) + self.createGameLine(hbox, line[0]) + else: + print "INFO: No games returned from database" + + def fillLimitsFrame(self, vbox, display): + hbox = gtk.HBox(False, 0) + vbox.pack_start(hbox, False, False, 0) + lbl_title = gtk.Label(self.filterText['limitstitle']) + lbl_title.set_alignment(xalign=0.0, yalign=0.5) + hbox.pack_start(lbl_title, expand=True, padding=3) + showb = gtk.Button(label="hide", stock=None, use_underline=True) + showb.set_alignment(xalign=1.0, yalign=0.5) + showb.connect('clicked', self.__toggle_box, 'limits') + hbox.pack_start(showb, expand=False, padding=1) + + vbox1 = gtk.VBox(False, 0) + vbox.pack_start(vbox1, False, False, 0) + self.boxes['limits'] = vbox1 + + self.cursor.execute(self.sql.query['getLimits']) + result = self.db.cursor.fetchall() + if len(result) >= 1: + hbox = gtk.HBox(True, 0) + vbox1.pack_start(hbox, False, False, 0) + vbox2 = gtk.VBox(False, 0) + hbox.pack_start(vbox2, False, False, 0) + vbox3 = gtk.VBox(False, 0) + hbox.pack_start(vbox3, False, False, 0) + for i, line in enumerate(result): + hbox = gtk.HBox(False, 0) + if i <= len(result)/2: + vbox2.pack_start(hbox, False, False, 0) + else: + vbox3.pack_start(hbox, False, False, 0) + self.cbLimits[line[0]] = self.createLimitLine(hbox, line[0], line[0]) + if "LimitSep" in display and display["LimitSep"] == True and len(result) >= 2: + hbox = gtk.HBox(False, 0) + vbox1.pack_start(hbox, False, True, 0) + self.cbAllLimits = self.createLimitLine(hbox, 'all', self.filterText['limitsall']) + hbox = gtk.HBox(False, 0) + vbox1.pack_start(hbox, False, True, 0) + self.cbNoLimits = self.createLimitLine(hbox, 'none', self.filterText['limitsnone']) + hbox = gtk.HBox(False, 0) + vbox1.pack_start(hbox, False, True, 0) + cb = self.createLimitLine(hbox, 'show', self.filterText['limitsshow']) + else: + print "INFO: No games returned from database" + + def fillSeatsFrame(self, vbox, display): + hbox = gtk.HBox(False, 0) + vbox.pack_start(hbox, False, False, 0) + lbl_title = gtk.Label(self.filterText['seatstitle']) + lbl_title.set_alignment(xalign=0.0, yalign=0.5) + hbox.pack_start(lbl_title, expand=True, padding=3) + showb = gtk.Button(label="hide", stock=None, use_underline=True) + showb.set_alignment(xalign=1.0, yalign=0.5) + showb.connect('clicked', self.__toggle_box, 'seats') + hbox.pack_start(showb, expand=False, padding=1) + + vbox1 = gtk.VBox(False, 0) + vbox.pack_start(vbox1, False, False, 0) + self.boxes['seats'] = vbox1 + + hbox = gtk.HBox(False, 0) + vbox1.pack_start(hbox, False, True, 0) + + lbl_from = gtk.Label(self.filterText['seatsbetween']) + lbl_to = gtk.Label(self.filterText['seatsand']) + adj1 = gtk.Adjustment(value=2, lower=2, upper=10, step_incr=1, page_incr=1, page_size=0) + sb1 = gtk.SpinButton(adjustment=adj1, climb_rate=0.0, digits=0) + adj2 = gtk.Adjustment(value=10, lower=2, upper=10, step_incr=1, page_incr=1, page_size=0) + sb2 = gtk.SpinButton(adjustment=adj2, climb_rate=0.0, digits=0) + + hbox.pack_start(lbl_from, expand=False, padding=3) + hbox.pack_start(sb1, False, False, 0) + hbox.pack_start(lbl_to, expand=False, padding=3) + hbox.pack_start(sb2, False, False, 0) + + if "SeatSep" in display and display["SeatSep"] == True: + hbox = gtk.HBox(False, 0) + vbox1.pack_start(hbox, False, True, 0) + cb = gtk.CheckButton(self.filterText['seatsshow']) + cb.connect('clicked', self.__set_seat_select, 'show') + hbox.pack_start(cb, False, False, 0) + self.sbSeats['show'] = cb + self.seats['show'] = False + + + self.sbSeats['from'] = sb1 + self.sbSeats['to'] = sb2 + + def fillCardsFrame(self, vbox): + hbox1 = gtk.HBox(True,0) + hbox1.show() + vbox.pack_start(hbox1, True, True, 0) + + cards = [ "A", "K","Q","J","T","9","8","7","6","5","4","3","2" ] + + for j in range(0, len(cards)): + hbox1 = gtk.HBox(True,0) + hbox1.show() + vbox.pack_start(hbox1, True, True, 0) + for i in range(0, len(cards)): + if i < (j + 1): + suit = "o" + else: + suit = "s" + button = gtk.ToggleButton("%s%s%s" %(cards[i], cards[j], suit)) + button.connect("toggled", self.cardCallback, "%s%s%s" %(cards[i], cards[j], suit)) + hbox1.pack_start(button, True, True, 0) + button.show() + + def fillDateFrame(self, vbox): + # Hat tip to Mika Bostrom - calendar code comes from PokerStats + hbox = gtk.HBox() + vbox.pack_start(hbox, False, True, 0) + + lbl_start = gtk.Label('From:') + + btn_start = gtk.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) + + hbox.pack_start(lbl_start, expand=False, padding=3) + hbox.pack_start(btn_start, expand=False, padding=3) + hbox.pack_start(self.start_date, expand=False, padding=2) + + #New row for end date + hbox = gtk.HBox() + vbox.pack_start(hbox, False, True, 0) + + lbl_end = gtk.Label(' To:') + btn_end = gtk.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_clear = gtk.Button(label=' Clear Dates ') + btn_clear.connect('clicked', self.__clear_dates) + + hbox.pack_start(lbl_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(btn_clear, expand=False, padding=15) + + def __toggle_box(self, widget, entry): + if "Limits" not in self.display or self.display["Limits"] == False: + self.boxes[entry].hide() + elif self.boxes[entry].props.visible: + self.boxes[entry].hide() + widget.set_label("show") + else: + self.boxes[entry].show() + widget.set_label("hide") + + def __calendar_dialog(self, widget, entry): + d = gtk.Window(gtk.WINDOW_TOPLEVEL) + d.set_title('Pick a date') + + vb = gtk.VBox() + cal = gtk.Calendar() + vb.pack_start(cal, expand=False, padding=0) + + btn = gtk.Button('Done') + btn.connect('clicked', self.__get_date, cal, entry, d) + + vb.pack_start(btn, expand=False, padding=4) + + d.add(vb) + d.set_position(gtk.WIN_POS_MOUSE) + d.show_all() + + def __clear_dates(self, w): + self.start_date.set_text('') + self.end_date.set_text('') + + def __get_dates(self): + t1 = self.start_date.get_text() + t2 = self.end_date.get_text() + + if t1 == '': + t1 = '1970-01-01' + if t2 == '': + t2 = '2020-12-12' + + return (t1, t2) + + def __get_date(self, widget, calendar, entry, win): +# year and day are correct, month is 0..11 + (year, month, day) = calendar.get_date() + month += 1 + ds = '%04d-%02d-%02d' % (year, month, day) + entry.set_text(ds) + win.destroy() + +def main(argv=None): + """main can also be called in the python interpreter, by supplying the command line as the argument.""" + if argv is None: + argv = sys.argv[1:] + + def destroy(*args): # call back for terminating the main eventloop + gtk.main_quit() + + parser = OptionParser() + (options, sys.argv) = parser.parse_args(args = argv) + + config = Configuration.Config() + db = None + + settings = {} + + settings.update(config.get_db_parameters()) + settings.update(config.get_tv_parameters()) + settings.update(config.get_import_parameters()) + settings.update(config.get_default_paths()) + + db = fpdb_db.fpdb_db() + db.connect(settings['db-backend'], + settings['db-host'], + settings['db-databaseName'], + settings['db-user'], + settings['db-password']) + + qdict = FpdbSQLQueries.FpdbSQLQueries(db.get_backend_name()) + + i = Filters(db, settings, config, qdict) + main_window = gtk.Window() + main_window.connect('destroy', destroy) + main_window.add(i.get_vbox()) + main_window.show() + gtk.main() + +if __name__ == '__main__': + sys.exit(main()) + + diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index 24948986..4445908e 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -41,8 +41,8 @@ class FpdbSQLQueries: self.query['list_tables'] = """ """ ################################################################## - # Drop Tables - MySQL, PostgreSQL and SQLite all share same syntax - ################################################################## + # Drop Tables - MySQL, PostgreSQL and SQLite all share same syntax + ################################################################## if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'): self.query['drop_table'] = """DROP TABLE IF EXISTS """ @@ -183,23 +183,67 @@ class FpdbSQLQueries: gametypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), handStart DATETIME NOT NULL, importTime DATETIME NOT NULL, - seats SMALLINT NOT NULL, - maxSeats SMALLINT NOT NULL, + seats TINYINT NOT NULL, + maxSeats TINYINT NOT NULL, + boardcard1 smallint, /* 0=none, 1-13=2-Ah 14-26=2-Ad 27-39=2-Ac 40-52=2-As */ + boardcard2 smallint, + boardcard3 smallint, + boardcard4 smallint, + boardcard5 smallint, + texture smallint, + playersVpi SMALLINT NOT NULL, /* num of players vpi */ + playersAtStreet1 SMALLINT NOT NULL, /* num of players seeing flop/street4 */ + playersAtStreet2 SMALLINT NOT NULL, + playersAtStreet3 SMALLINT NOT NULL, + playersAtStreet4 SMALLINT NOT NULL, + playersAtShowdown SMALLINT NOT NULL, + street0Raises TINYINT NOT NULL, /* num small bets paid to see flop/street4, including blind */ + street1Raises TINYINT NOT NULL, /* num small bets paid to see turn/street5 */ + street2Raises TINYINT NOT NULL, /* num big bets paid to see river/street6 */ + street3Raises TINYINT NOT NULL, /* num big bets paid to see sd/street7 */ + street4Raises TINYINT NOT NULL, /* num big bets paid to see showdown */ + street1Pot INT, /* pot size at flop/street4 */ + street2Pot INT, /* pot size at turn/street5 */ + street3Pot INT, /* pot size at river/street6 */ + street4Pot INT, /* pot size at sd/street7 */ + showdownPot INT, /* pot size at sd/street7 */ comment TEXT, commentTs DATETIME) ENGINE=INNODB""" elif(self.dbname == 'PostgreSQL'): self.query['createHandsTable'] = """CREATE TABLE Hands ( - id BIGSERIAL, PRIMARY KEY (id), - tableName VARCHAR(20), - siteHandNo BIGINT, - gametypeId INT, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), - handStart timestamp without time zone, - importTime timestamp without time zone, - seats SMALLINT, - maxSeats SMALLINT, - comment TEXT, - commentTs timestamp without time zone)""" + id BIGSERIAL, PRIMARY KEY (id), + tableName VARCHAR(20) NOT NULL, + siteHandNo BIGINT NOT NULL, + gametypeId INT NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), + handStart timestamp without time zone NOT NULL, + importTime timestamp without time zone NOT NULL, + seats SMALLINT NOT NULL, + maxSeats SMALLINT NOT NULL, + boardcard1 smallint, /* 0=none, 1-13=2-Ah 14-26=2-Ad 27-39=2-Ac 40-52=2-As */ + boardcard2 smallint, + boardcard3 smallint, + boardcard4 smallint, + boardcard5 smallint, + texture smallint, + playersVpi SMALLINT NOT NULL, /* num of players vpi */ + playersAtStreet1 SMALLINT NOT NULL, /* num of players seeing flop/street4 */ + playersAtStreet2 SMALLINT NOT NULL, + playersAtStreet3 SMALLINT NOT NULL, + playersAtStreet4 SMALLINT NOT NULL, + playersAtShowdown SMALLINT NOT NULL, + street0Raises SMALLINT NOT NULL, /* num small bets paid to see flop/street4, including blind */ + street1Raises SMALLINT NOT NULL, /* num small bets paid to see turn/street5 */ + street2Raises SMALLINT NOT NULL, /* num big bets paid to see river/street6 */ + street3Raises SMALLINT NOT NULL, /* num big bets paid to see sd/street7 */ + street4Raises SMALLINT NOT NULL, /* num big bets paid to see showdown */ + street1Pot INT, /* pot size at flop/street4 */ + street2Pot INT, /* pot size at turn/street5 */ + street3Pot INT, /* pot size at river/street6 */ + street4Pot INT, /* pot size at sd/street7 */ + showdownPot INT, /* pot size at sd/street7 */ + comment TEXT, + commentTs timestamp without time zone)""" elif(self.dbname == 'SQLite'): self.query['createHandsTable'] = """ """ @@ -306,60 +350,233 @@ class FpdbSQLQueries: startCash INT NOT NULL, position CHAR(1), seatNo SMALLINT NOT NULL, + + card1 smallint NOT NULL, /* 0=none, 1-13=2-Ah 14-26=2-Ad 27-39=2-Ac 40-52=2-As */ + card2 smallint NOT NULL, + card3 smallint, + card4 smallint, + card5 smallint, + card6 smallint, + card7 smallint, + startCards smallint, + ante INT, - - card1Value smallint NOT NULL, - card1Suit char(1) NOT NULL, - card2Value smallint NOT NULL, - card2Suit char(1) NOT NULL, - card3Value smallint, - card3Suit char(1), - card4Value smallint, - card4Suit char(1), - card5Value smallint, - card5Suit char(1), - card6Value smallint, - card6Suit char(1), - card7Value smallint, - card7Suit char(1), - winnings int NOT NULL, rake int NOT NULL, + totalProfit INT NOT NULL, comment text, commentTs DATETIME, - - tourneysPlayersId BIGINT UNSIGNED, FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id)) + tourneysPlayersId BIGINT UNSIGNED, + tourneyTypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), + + wonWhenSeenStreet1 FLOAT NOT NULL, + wonWhenSeenStreet2 FLOAT, + wonWhenSeenStreet3 FLOAT, + wonWhenSeenStreet4 FLOAT, + wonAtSD FLOAT NOT NULL, + + street0VPI BOOLEAN NOT NULL, + street0Aggr BOOLEAN NOT NULL, + street0_3BChance BOOLEAN NOT NULL, + street0_3BDone BOOLEAN NOT NULL, + street0_4BChance BOOLEAN, + street0_4BDone BOOLEAN, + other3BStreet0 BOOLEAN, + other4BStreet0 BOOLEAN, + + street1Seen BOOLEAN NOT NULL, + street2Seen BOOLEAN NOT NULL, + street3Seen BOOLEAN NOT NULL, + street4Seen BOOLEAN NOT NULL, + sawShowdown BOOLEAN NOT NULL, + + street1Aggr BOOLEAN NOT NULL, + street2Aggr BOOLEAN NOT NULL, + street3Aggr BOOLEAN NOT NULL, + street4Aggr BOOLEAN NOT NULL, + + otherRaisedStreet0 BOOLEAN, + otherRaisedStreet1 BOOLEAN NOT NULL, + otherRaisedStreet2 BOOLEAN NOT NULL, + otherRaisedStreet3 BOOLEAN NOT NULL, + otherRaisedStreet4 BOOLEAN NOT NULL, + foldToOtherRaisedStreet0 BOOLEAN, + foldToOtherRaisedStreet1 BOOLEAN NOT NULL, + foldToOtherRaisedStreet2 BOOLEAN NOT NULL, + foldToOtherRaisedStreet3 BOOLEAN NOT NULL, + foldToOtherRaisedStreet4 BOOLEAN NOT NULL, + + stealAttemptChance BOOLEAN NOT NULL, + stealAttempted BOOLEAN NOT NULL, + foldBbToStealChance BOOLEAN NOT NULL, + foldedBbToSteal BOOLEAN NOT NULL, + foldSbToStealChance BOOLEAN NOT NULL, + foldedSbToSteal BOOLEAN NOT NULL, + + street1CBChance BOOLEAN NOT NULL, + street1CBDone BOOLEAN NOT NULL, + street2CBChance BOOLEAN NOT NULL, + street2CBDone BOOLEAN NOT NULL, + street3CBChance BOOLEAN NOT NULL, + street3CBDone BOOLEAN NOT NULL, + street4CBChance BOOLEAN NOT NULL, + street4CBDone BOOLEAN NOT NULL, + + foldToStreet1CBChance BOOLEAN NOT NULL, + foldToStreet1CBDone BOOLEAN NOT NULL, + foldToStreet2CBChance BOOLEAN NOT NULL, + foldToStreet2CBDone BOOLEAN NOT NULL, + foldToStreet3CBChance BOOLEAN NOT NULL, + foldToStreet3CBDone BOOLEAN NOT NULL, + foldToStreet4CBChance BOOLEAN NOT NULL, + foldToStreet4CBDone BOOLEAN NOT NULL, + + street1CheckCallRaiseChance BOOLEAN NOT NULL, + street1CheckCallRaiseDone BOOLEAN NOT NULL, + street2CheckCallRaiseChance BOOLEAN NOT NULL, + street2CheckCallRaiseDone BOOLEAN NOT NULL, + street3CheckCallRaiseChance BOOLEAN NOT NULL, + street3CheckCallRaiseDone BOOLEAN NOT NULL, + street4CheckCallRaiseChance BOOLEAN NOT NULL, + street4CheckCallRaiseDone BOOLEAN NOT NULL, + + street0Calls TINYINT, + street1Calls TINYINT, + street2Calls TINYINT, + street3Calls TINYINT, + street4Calls TINYINT, + street0Bets TINYINT, + street1Bets TINYINT, + street2Bets TINYINT, + street3Bets TINYINT, + street4Bets TINYINT, + street0Raises TINYINT, + street1Raises TINYINT, + street2Raises TINYINT, + street3Raises TINYINT, + street4Raises TINYINT, + + actionString VARCHAR(15), + + FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id)) ENGINE=INNODB""" elif(self.dbname == 'PostgreSQL'): self.query['createHandsPlayersTable'] = """CREATE TABLE HandsPlayers ( id BIGSERIAL, PRIMARY KEY (id), - handId BIGINT, FOREIGN KEY (handId) REFERENCES Hands(id), - playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id), - startCash INT, + handId BIGINT NOT NULL, FOREIGN KEY (handId) REFERENCES Hands(id), + playerId INT NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id), + startCash INT NOT NULL, position CHAR(1), - seatNo SMALLINT, + seatNo SMALLINT NOT NULL, + + card1 smallint NOT NULL, /* 0=none, 1-13=2-Ah 14-26=2-Ad 27-39=2-Ac 40-52=2-As */ + card2 smallint NOT NULL, + card3 smallint, + card4 smallint, + card5 smallint, + card6 smallint, + card7 smallint, + startCards smallint, + ante INT, - - card1Value smallint, - card1Suit char(1), - card2Value smallint, - card2Suit char(1), - card3Value smallint, - card3Suit char(1), - card4Value smallint, - card4Suit char(1), - card5Value smallint, - card5Suit char(1), - card6Value smallint, - card6Suit char(1), - card7Value smallint, - card7Suit char(1), - - winnings int, - rake int, + winnings int NOT NULL, + rake int NOT NULL, + totalProfit INT NOT NULL, comment text, commentTs timestamp without time zone, - tourneysPlayersId BIGINT, FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id))""" + tourneysPlayersId BIGINT, + tourneyTypeId INT NOT NULL, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), + + wonWhenSeenStreet1 FLOAT NOT NULL, + wonWhenSeenStreet2 FLOAT, + wonWhenSeenStreet3 FLOAT, + wonWhenSeenStreet4 FLOAT, + wonAtSD FLOAT NOT NULL, + + street0VPI BOOLEAN NOT NULL, + street0Aggr BOOLEAN NOT NULL, + street0_3BChance BOOLEAN NOT NULL, + street0_3BDone BOOLEAN NOT NULL, + street0_4BChance BOOLEAN, + street0_4BDone BOOLEAN, + other3BStreet0 BOOLEAN, + other4BStreet0 BOOLEAN, + + street1Seen BOOLEAN NOT NULL, + street2Seen BOOLEAN NOT NULL, + street3Seen BOOLEAN NOT NULL, + street4Seen BOOLEAN NOT NULL, + sawShowdown BOOLEAN NOT NULL, + + street1Aggr BOOLEAN NOT NULL, + street2Aggr BOOLEAN NOT NULL, + street3Aggr BOOLEAN NOT NULL, + street4Aggr BOOLEAN NOT NULL, + + otherRaisedStreet0 BOOLEAN, + otherRaisedStreet1 BOOLEAN NOT NULL, + otherRaisedStreet2 BOOLEAN NOT NULL, + otherRaisedStreet3 BOOLEAN NOT NULL, + otherRaisedStreet4 BOOLEAN NOT NULL, + foldToOtherRaisedStreet0 BOOLEAN, + foldToOtherRaisedStreet1 BOOLEAN NOT NULL, + foldToOtherRaisedStreet2 BOOLEAN NOT NULL, + foldToOtherRaisedStreet3 BOOLEAN NOT NULL, + foldToOtherRaisedStreet4 BOOLEAN NOT NULL, + + stealAttemptChance BOOLEAN NOT NULL, + stealAttempted BOOLEAN NOT NULL, + foldBbToStealChance BOOLEAN NOT NULL, + foldedBbToSteal BOOLEAN NOT NULL, + foldSbToStealChance BOOLEAN NOT NULL, + foldedSbToSteal BOOLEAN NOT NULL, + + street1CBChance BOOLEAN NOT NULL, + street1CBDone BOOLEAN NOT NULL, + street2CBChance BOOLEAN NOT NULL, + street2CBDone BOOLEAN NOT NULL, + street3CBChance BOOLEAN NOT NULL, + street3CBDone BOOLEAN NOT NULL, + street4CBChance BOOLEAN NOT NULL, + street4CBDone BOOLEAN NOT NULL, + + foldToStreet1CBChance BOOLEAN NOT NULL, + foldToStreet1CBDone BOOLEAN NOT NULL, + foldToStreet2CBChance BOOLEAN NOT NULL, + foldToStreet2CBDone BOOLEAN NOT NULL, + foldToStreet3CBChance BOOLEAN NOT NULL, + foldToStreet3CBDone BOOLEAN NOT NULL, + foldToStreet4CBChance BOOLEAN NOT NULL, + foldToStreet4CBDone BOOLEAN NOT NULL, + + street1CheckCallRaiseChance BOOLEAN NOT NULL, + street1CheckCallRaiseDone BOOLEAN NOT NULL, + street2CheckCallRaiseChance BOOLEAN NOT NULL, + street2CheckCallRaiseDone BOOLEAN NOT NULL, + street3CheckCallRaiseChance BOOLEAN NOT NULL, + street3CheckCallRaiseDone BOOLEAN NOT NULL, + street4CheckCallRaiseChance BOOLEAN NOT NULL, + street4CheckCallRaiseDone BOOLEAN NOT NULL, + + street0Calls SMALLINT, + street1Calls SMALLINT, + street2Calls SMALLINT, + street3Calls SMALLINT, + street4Calls SMALLINT, + street0Bets SMALLINT, + street1Bets SMALLINT, + street2Bets SMALLINT, + street3Bets SMALLINT, + street4Bets SMALLINT, + street0Raises SMALLINT, + street1Raises SMALLINT, + street2Raises SMALLINT, + street3Raises SMALLINT, + street4Raises SMALLINT, + + actionString VARCHAR(15), + + FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id))""" elif(self.dbname == 'SQLite'): self.query['createHandsPlayersTable'] = """ """ @@ -400,7 +617,7 @@ class FpdbSQLQueries: if(self.dbname == 'MySQL InnoDB'): self.query['createHandsActionsTable'] = """CREATE TABLE HandsActions ( id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), - handPlayerId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handPlayerId) REFERENCES HandsPlayers(id), + handsPlayerId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handsPlayerId) REFERENCES HandsPlayers(id), street SMALLINT NOT NULL, actionNo SMALLINT NOT NULL, action CHAR(5) NOT NULL, @@ -412,7 +629,7 @@ class FpdbSQLQueries: elif(self.dbname == 'PostgreSQL'): self.query['createHandsActionsTable'] = """CREATE TABLE HandsActions ( id BIGSERIAL, PRIMARY KEY (id), - handPlayerId BIGINT, FOREIGN KEY (handPlayerId) REFERENCES HandsPlayers(id), + handsPlayerId BIGINT, FOREIGN KEY (handsPlayerId) REFERENCES HandsPlayers(id), street SMALLINT, actionNo SMALLINT, action CHAR(5), @@ -436,13 +653,24 @@ class FpdbSQLQueries: activeSeats SMALLINT NOT NULL, position CHAR(1), tourneyTypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), - + styleKey CHAR(7) NOT NULL, /* 1st char is style (A/T/H/S), other 6 are the key */ HDs INT NOT NULL, + + wonWhenSeenStreet1 FLOAT NOT NULL, + wonWhenSeenStreet2 FLOAT, + wonWhenSeenStreet3 FLOAT, + wonWhenSeenStreet4 FLOAT, + wonAtSD FLOAT NOT NULL, + street0VPI INT NOT NULL, street0Aggr INT NOT NULL, - street0_3B4BChance INT NOT NULL, - street0_3B4BDone INT NOT NULL, - + street0_3BChance INT NOT NULL, + street0_3BDone INT NOT NULL, + street0_4BChance INT, + street0_4BDone INT, + other3BStreet0 INT, + other4BStreet0 INT, + street1Seen INT NOT NULL, street2Seen INT NOT NULL, street3Seen INT NOT NULL, @@ -453,17 +681,17 @@ class FpdbSQLQueries: street2Aggr INT NOT NULL, street3Aggr INT NOT NULL, street4Aggr INT NOT NULL, - + + otherRaisedStreet0 INT, otherRaisedStreet1 INT NOT NULL, otherRaisedStreet2 INT NOT NULL, otherRaisedStreet3 INT NOT NULL, otherRaisedStreet4 INT NOT NULL, + foldToOtherRaisedStreet0 INT, foldToOtherRaisedStreet1 INT NOT NULL, foldToOtherRaisedStreet2 INT NOT NULL, foldToOtherRaisedStreet3 INT NOT NULL, foldToOtherRaisedStreet4 INT NOT NULL, - wonWhenSeenStreet1 FLOAT NOT NULL, - wonAtSD FLOAT NOT NULL, stealAttemptChance INT NOT NULL, stealAttempted INT NOT NULL, @@ -471,7 +699,7 @@ class FpdbSQLQueries: foldedBbToSteal INT NOT NULL, foldSbToStealChance INT NOT NULL, foldedSbToSteal INT NOT NULL, - + street1CBChance INT NOT NULL, street1CBDone INT NOT NULL, street2CBChance INT NOT NULL, @@ -499,7 +727,24 @@ class FpdbSQLQueries: street3CheckCallRaiseChance INT NOT NULL, street3CheckCallRaiseDone INT NOT NULL, street4CheckCallRaiseChance INT NOT NULL, - street4CheckCallRaiseDone INT NOT NULL) + street4CheckCallRaiseDone INT NOT NULL, + + street0Calls INT, + street1Calls INT, + street2Calls INT, + street3Calls INT, + street4Calls INT, + street0Bets INT, + street1Bets INT, + street2Bets INT, + street3Bets INT, + street4Bets INT, + street0Raises INT, + street1Raises INT, + street2Raises INT, + street3Raises INT, + street4Raises INT) + ENGINE=INNODB""" elif(self.dbname == 'PostgreSQL'): self.query['createHudCacheTable'] = """CREATE TABLE HudCache ( @@ -509,12 +754,24 @@ class FpdbSQLQueries: activeSeats SMALLINT, position CHAR(1), tourneyTypeId INT, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), - + styleKey CHAR(7) NOT NULL, /* 1st char is style (A/T/H/S), other 6 are the key */ HDs INT, - street0VPI INT, + + wonWhenSeenStreet1 FLOAT NOT NULL, + wonWhenSeenStreet2 FLOAT, + wonWhenSeenStreet3 FLOAT, + wonWhenSeenStreet4 FLOAT, + wonAtSD FLOAT NOT NULL, + + street0VPI INT NOT NULL, street0Aggr INT, - street0_3B4BChance INT, - street0_3B4BDone INT, + street0_3BChance INT NOT NULL, + street0_3BDone INT NOT NULL, + street0_4BChance INT, + street0_4BDone INT, + other3BStreet0 INT, + other4BStreet0 INT, + street1Seen INT, street2Seen INT, street3Seen INT, @@ -524,16 +781,17 @@ class FpdbSQLQueries: street2Aggr INT, street3Aggr INT, street4Aggr INT, + + otherRaisedStreet0 INT, otherRaisedStreet1 INT, otherRaisedStreet2 INT, otherRaisedStreet3 INT, otherRaisedStreet4 INT, + foldToOtherRaisedStreet0 INT, foldToOtherRaisedStreet1 INT, foldToOtherRaisedStreet2 INT, foldToOtherRaisedStreet3 INT, foldToOtherRaisedStreet4 INT, - wonWhenSeenStreet1 FLOAT, - wonAtSD FLOAT, stealAttemptChance INT, stealAttempted INT, @@ -569,7 +827,24 @@ class FpdbSQLQueries: street3CheckCallRaiseChance INT, street3CheckCallRaiseDone INT, street4CheckCallRaiseChance INT, - street4CheckCallRaiseDone INT)""" + street4CheckCallRaiseDone INT, + + street0Calls INT, + street1Calls INT, + street2Calls INT, + street3Calls INT, + street4Calls INT, + street0Bets INT, + street1Bets INT, + street2Bets INT, + street3Bets INT, + street4Bets INT, + street0Raises INT, + street1Raises INT, + street2Raises INT, + street3Raises INT, + street4Raises INT) + """ elif(self.dbname == 'SQLite'): self.query['createHudCacheTable'] = """ """ @@ -609,51 +884,186 @@ class FpdbSQLQueries: elif(self.dbname == 'SQLite'): self.query['getSiteId'] = """SELECT id from Sites where name = %s""" - if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'): + if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'): self.query['getRingProfitAllHandsPlayerIdSite'] = """ - SELECT hp.handId, hp.winnings, coalesce(hp.ante,0) + SUM(ha.amount) - , hp.winnings - (coalesce(hp.ante,0) + SUM(ha.amount)) + SELECT hp.handId, hp.totalProfit, hp.totalProfit, hp.totalProfit FROM HandsPlayers hp INNER JOIN Players pl ON hp.playerId = pl.id INNER JOIN Hands h ON h.id = hp.handId - INNER JOIN HandsActions ha ON ha.handPlayerId = hp.id + INNER JOIN Gametypes g ON h.gametypeId = g.id where pl.id in AND pl.siteId in AND h.handStart > '' AND h.handStart < '' + AND g.bigBlind in AND hp.tourneysPlayersId IS NULL - GROUP BY hp.handId, hp.winnings, h.handStart, hp.ante + GROUP BY h.handStart, hp.handId, hp.totalProfit ORDER BY h.handStart""" + + if self.dbname in ['MySQL InnoDB']: + self.query['playerDetailedStats'] = """ + select AS hgametypeid + ,gt.base + ,gt.category + ,upper(gt.limitType) AS limittype + ,s.name + ,min(gt.bigBlind) AS minbigblind + ,max(gt.bigBlind) AS maxbigblind + /*, AS gtid*/ + ,count(1) AS n + ,100.0*sum(cast(hp.street0VPI as integer))/count(1) AS vpip + ,100.0*sum(cast(hp.street0Aggr as integer))/count(1) AS pfr + ,case when sum(cast(hp.street0_3Bchance as integer)) = 0 then -999 + else 100.0*sum(cast(hp.street0_3Bdone as integer))/sum(cast(hp.street0_3Bchance as integer)) + end AS pf3 + ,case when sum(cast(hp.stealattemptchance as integer)) = 0 then -999 + else 100.0*sum(cast(hp.stealattempted as integer))/sum(cast(hp.stealattemptchance as integer)) + end AS steals + ,100.0*sum(cast(hp.street1Seen as integer))/count(1) AS saw_f + ,100.0*sum(cast(hp.sawShowdown as integer))/count(1) AS sawsd + ,case when sum(cast(hp.street1Seen as integer)) = 0 then -999 + else 100.0*sum(cast(hp.sawShowdown as integer))/sum(cast(hp.street1Seen as integer)) + end AS wtsdwsf + ,case when sum(cast(hp.sawShowdown as integer)) = 0 then -999 + else 100.0*sum(cast(hp.wonAtSD as integer))/sum(cast(hp.sawShowdown as integer)) + end AS wmsd + ,case when sum(cast(hp.street1Seen as integer)) = 0 then -999 + else 100.0*sum(cast(hp.street1Aggr as integer))/sum(cast(hp.street1Seen as integer)) + end AS flafq + ,case when sum(cast(hp.street2Seen as integer)) = 0 then -999 + else 100.0*sum(cast(hp.street2Aggr as integer))/sum(cast(hp.street2Seen as integer)) + end AS tuafq + ,case when sum(cast(hp.street3Seen as integer)) = 0 then -999 + else 100.0*sum(cast(hp.street3Aggr as integer))/sum(cast(hp.street3Seen as integer)) + end AS rvafq + ,case when sum(cast(hp.street1Seen as integer))+sum(cast(hp.street2Seen as integer))+sum(cast(hp.street3Seen as integer)) = 0 then -999 + else 100.0*(sum(cast(hp.street1Aggr as integer))+sum(cast(hp.street2Aggr as integer))+sum(cast(hp.street3Aggr as integer))) + /(sum(cast(hp.street1Seen as integer))+sum(cast(hp.street2Seen as integer))+sum(cast(hp.street3Seen as integer))) + end AS pofafq + ,sum(hp.totalProfit)/100.0 AS net + ,sum(hp.rake)/100.0 AS rake + ,100.0*avg(hp.totalProfit/(gt.bigBlind+0.0)) AS bbper100 + ,avg(hp.totalProfit)/100.0 AS profitperhand + ,100.0*avg((hp.totalProfit+hp.rake)/(gt.bigBlind+0.0)) AS bb100xr + ,avg((hp.totalProfit+hp.rake)/100.0) AS profhndxr + ,avg(h.seats+0.0) AS avgseats + ,variance(hp.totalProfit/100.0) AS variance + from HandsPlayers hp + inner join Hands h on (h.id = hp.handId) + inner join Gametypes gt on (gt.Id = h.gameTypeId) + inner join Sites s on (s.Id = gt.siteId) + where hp.playerId in + and hp.tourneysPlayersId IS NULL + and h.seats + + + and date_format(h.handStart, '%Y-%m-%d') + group by hgameTypeId + ,hp.playerId + ,gt.base + ,gt.category + + ,upper(gt.limitType) + ,s.name + order by hp.playerId + ,gt.base + ,gt.category + + + ,maxbigblind desc + ,upper(gt.limitType) + ,s.name + """ + elif self.dbname in ['PostgreSQL']: + self.query['playerDetailedStats'] = """ + select AS hgametypeid + ,gt.base + ,gt.category + ,upper(gt.limitType) AS limittype + ,s.name + ,min(gt.bigBlind) AS minbigblind + ,max(gt.bigBlind) AS maxbigblind + /*, AS gtid*/ + ,count(1) AS n + ,100.0*sum(cast(hp.street0VPI as integer))/count(1) AS vpip + ,100.0*sum(cast(hp.street0Aggr as integer))/count(1) AS pfr + ,case when sum(cast(hp.street0_3Bchance as integer)) = 0 then -999 + else 100.0*sum(cast(hp.street0_3Bdone as integer))/sum(cast(hp.street0_3Bchance as integer)) + end AS pf3 + ,case when sum(cast(hp.stealattemptchance as integer)) = 0 then -999 + else 100.0*sum(cast(hp.stealattempted as integer))/sum(cast(hp.stealattemptchance as integer)) + end AS steals + ,100.0*sum(cast(hp.street1Seen as integer))/count(1) AS saw_f + ,100.0*sum(cast(hp.sawShowdown as integer))/count(1) AS sawsd + ,case when sum(cast(hp.street1Seen as integer)) = 0 then -999 + else 100.0*sum(cast(hp.sawShowdown as integer))/sum(cast(hp.street1Seen as integer)) + end AS wtsdwsf + ,case when sum(cast(hp.sawShowdown as integer)) = 0 then -999 + else 100.0*sum(cast(hp.wonAtSD as integer))/sum(cast(hp.sawShowdown as integer)) + end AS wmsd + ,case when sum(cast(hp.street1Seen as integer)) = 0 then -999 + else 100.0*sum(cast(hp.street1Aggr as integer))/sum(cast(hp.street1Seen as integer)) + end AS flafq + ,case when sum(cast(hp.street2Seen as integer)) = 0 then -999 + else 100.0*sum(cast(hp.street2Aggr as integer))/sum(cast(hp.street2Seen as integer)) + end AS tuafq + ,case when sum(cast(hp.street3Seen as integer)) = 0 then -999 + else 100.0*sum(cast(hp.street3Aggr as integer))/sum(cast(hp.street3Seen as integer)) + end AS rvafq + ,case when sum(cast(hp.street1Seen as integer))+sum(cast(hp.street2Seen as integer))+sum(cast(hp.street3Seen as integer)) = 0 then -999 + else 100.0*(sum(cast(hp.street1Aggr as integer))+sum(cast(hp.street2Aggr as integer))+sum(cast(hp.street3Aggr as integer))) + /(sum(cast(hp.street1Seen as integer))+sum(cast(hp.street2Seen as integer))+sum(cast(hp.street3Seen as integer))) + end AS pofafq + ,sum(hp.totalProfit)/100.0 AS net + ,sum(hp.rake)/100.0 AS rake + ,100.0*avg(hp.totalProfit/(gt.bigBlind+0.0)) AS bbper100 + ,avg(hp.totalProfit)/100.0 AS profitperhand + ,100.0*avg((hp.totalProfit+hp.rake)/(gt.bigBlind+0.0)) AS bb100xr + ,avg((hp.totalProfit+hp.rake)/100.0) AS profhndxr + ,avg(h.seats+0.0) AS avgseats + ,variance(hp.totalProfit/100.0) AS variance + from HandsPlayers hp + inner join Hands h on (h.id = hp.handId) + inner join Gametypes gt on (gt.Id = h.gameTypeId) + inner join Sites s on (s.Id = gt.siteId) + where hp.playerId in + and hp.tourneysPlayersId IS NULL + and h.seats + + + and to_char(h.handStart, 'YYYY-MM-DD') + group by hgameTypeId + ,hp.playerId + ,gt.base + ,gt.category + + ,upper(gt.limitType) + ,s.name + order by hp.playerId + ,gt.base + ,gt.category + + + ,maxbigblind desc + ,upper(gt.limitType) + ,s.name + """ elif(self.dbname == 'SQLite'): - #Probably doesn't work. - self.query['getRingProfitAllHandsPlayerIdSite'] = """ - SELECT hp.handId, hp.winnings, SUM(ha.amount), hp.winnings - SUM(ha.amount) - FROM HandsPlayers hp - INNER JOIN Players pl ON hp.playerId = pl.id - INNER JOIN Hands h ON h.id = hp.handId - INNER JOIN HandsActions ha ON ha.handPlayerId = hp.id - where pl.id in - AND pl.siteId in - AND h.handStart > '' - AND h.handStart < '' - AND hp.tourneysPlayersId IS NULL - GROUP BY hp.handId, hp.winnings, h.handStart - ORDER BY h.handStart""" + self.query['playerDetailedStats'] = """ """ if(self.dbname == 'MySQL InnoDB'): self.query['playerStats'] = """ SELECT concat(upper(stats.limitType), ' ' ,concat(upper(substring(stats.category,1,1)),substring(stats.category,2) ), ' ' - ,stats.name, ' $' - ,cast(trim(leading ' ' from - case when stats.bigBlind < 100 then format(stats.bigBlind/100.0,2) - else format(stats.bigBlind/100.0,0) - end ) as char) + ,stats.name, ' ' + ,cast(stats.bigBlindDesc as char) ) AS Game ,stats.n ,stats.vpip ,stats.pfr + ,stats.pf3 + ,stats.steals ,stats.saw_f ,stats.sawsd ,stats.wtsdwsf @@ -662,184 +1072,194 @@ class FpdbSQLQueries: ,stats.TuAFq ,stats.RvAFq ,stats.PoFAFq - /* if you have handsactions data the next 3 fields should give same answer as - following 3 commented out fields */ ,stats.Net ,stats.BBper100 ,stats.Profitperhand - /*,format(hprof2.sum_profit/100.0,2) AS Net - ,format((hprof2.sum_profit/(stats.bigBlind+0.0)) / (stats.n/100.0),2) - AS BBlPer100 - ,hprof2.profitperhand AS Profitperhand - */ - ,format(hprof2.variance,2) AS Variance + ,case when hprof2.variance = -999 then '-' + else format(hprof2.variance, 2) + end AS Variance + ,stats.AvgSeats FROM (select /* stats from hudcache */ gt.base ,gt.category ,upper(gt.limitType) as limitType ,s.name - ,gt.bigBlind - ,hc.gametypeId + , AS bigBlindDesc + , AS gtId ,sum(HDs) AS n - ,format(100.0*sum(street0VPI)/sum(HDs),1) AS vpip - ,format(100.0*sum(street0Aggr)/sum(HDs),1) AS pfr - ,format(100.0*sum(street1Seen)/sum(HDs),1) AS saw_f - ,format(100.0*sum(sawShowdown)/sum(HDs),1) AS sawsd - ,case when sum(street1Seen) = 0 then 'oo' + ,format(100.0*sum(street0VPI)/sum(HDs),1) AS vpip + ,format(100.0*sum(street0Aggr)/sum(HDs),1) AS pfr + ,case when sum(street0_3Bchance) = 0 then '0' + else format(100.0*sum(street0_3Bdone)/sum(street0_3Bchance),1) + end AS pf3 + ,case when sum(stealattemptchance) = 0 then '-' + else format(100.0*sum(stealattempted)/sum(stealattemptchance),1) + end AS steals + ,format(100.0*sum(street1Seen)/sum(HDs),1) AS saw_f + ,format(100.0*sum(sawShowdown)/sum(HDs),1) AS sawsd + ,case when sum(street1Seen) = 0 then '-' else format(100.0*sum(sawShowdown)/sum(street1Seen),1) end AS wtsdwsf - ,case when sum(sawShowdown) = 0 then 'oo' + ,case when sum(sawShowdown) = 0 then '-' else format(100.0*sum(wonAtSD)/sum(sawShowdown),1) end AS wmsd - ,case when sum(street1Seen) = 0 then 'oo' + ,case when sum(street1Seen) = 0 then '-' else format(100.0*sum(street1Aggr)/sum(street1Seen),1) end AS FlAFq - ,case when sum(street2Seen) = 0 then 'oo' + ,case when sum(street2Seen) = 0 then '-' else format(100.0*sum(street2Aggr)/sum(street2Seen),1) end AS TuAFq - ,case when sum(street3Seen) = 0 then 'oo' + ,case when sum(street3Seen) = 0 then '-' else format(100.0*sum(street3Aggr)/sum(street3Seen),1) end AS RvAFq - ,case when sum(street1Seen)+sum(street2Seen)+sum(street3Seen) = 0 then 'oo' + ,case when sum(street1Seen)+sum(street2Seen)+sum(street3Seen) = 0 then '-' else format(100.0*(sum(street1Aggr)+sum(street2Aggr)+sum(street3Aggr)) /(sum(street1Seen)+sum(street2Seen)+sum(street3Seen)),1) end AS PoFAFq ,format(sum(totalProfit)/100.0,2) AS Net - ,format((sum(totalProfit)/(gt.bigBlind+0.0)) / (sum(HDs)/100.0),2) + ,format((sum(totalProfit/(gt.bigBlind+0.0))) / (sum(HDs)/100.0),2) AS BBper100 ,format( (sum(totalProfit)/100.0) / sum(HDs), 4) AS Profitperhand + ,format( sum(activeSeats*HDs)/(sum(HDs)+0.0), 2) AS AvgSeats from Gametypes gt inner join Sites s on s.Id = gt.siteId inner join HudCache hc on hc.gameTypeId = gt.Id where hc.playerId in - # use here ? + and + and hc.activeSeats + and concat( '20', substring(hc.styleKey,2,2), '-', substring(hc.styleKey,4,2), '-' + , substring(hc.styleKey,6,2) ) group by gt.base ,gt.category ,upper(gt.limitType) ,s.name - ,gt.bigBlind - ,hc.gametypeId + + ,gtId ) stats inner join ( select # profit from handsplayers/handsactions - hprof.gameTypeId, sum(hprof.profit) sum_profit, + hprof.gtId, sum(hprof.profit) sum_profit, avg(hprof.profit/100.0) profitperhand, - variance(hprof.profit/100.0) variance + case when hprof.gtId = -1 then -999 + else variance(hprof.profit/100.0) + end as variance from - (select hp.handId, h.gameTypeId, hp.winnings, SUM(ha.amount) - costs, hp.winnings - SUM(ha.amount) profit - from HandsPlayers hp - inner join Hands h ON h.id = hp.handId - left join HandsActions ha ON ha.handPlayerId = hp.id - where hp.playerId in - # use here ? - and hp.tourneysPlayersId IS NULL - group by hp.handId, h.gameTypeId, hp.position, hp.winnings - ) hprof - group by hprof.gameTypeId + (select hp.handId, as gtId, hp.totalProfit as profit + from HandsPlayers hp + inner join Hands h ON h.id = hp.handId + where hp.playerId in + and hp.tourneysPlayersId IS NULL + and date_format(h.handStart, '%Y-%m-%d') + group by hp.handId, gtId, hp.totalProfit + ) hprof + group by hprof.gtId ) hprof2 - on hprof2.gameTypeId = stats.gameTypeId - order by stats.category, stats.limittype, stats.bigBlind""" + on hprof2.gtId = stats.gtId + order by stats.category, stats.limittype, stats.bigBlindDesc desc """ elif(self.dbname == 'PostgreSQL'): self.query['playerStats'] = """ SELECT upper(stats.limitType) || ' ' || initcap(stats.category) || ' ' - || stats.name || ' $' - || trim(leading ' ' from - case when stats.bigBlind < 100 then to_char(stats.bigBlind/100.0,'0D00') - else to_char(stats.bigBlind/100.0,'99990') - end ) AS Game - ,stats.n - ,stats.vpip - ,stats.pfr - ,stats.saw_f - ,stats.sawsd - ,stats.wtsdwsf - ,stats.wmsd - ,stats.FlAFq - ,stats.TuAFq - ,stats.RvAFq - ,stats.PoFAFq - /* if you have handsactions data the next 3 fields should give same answer as - following 3 commented out fields */ - ,stats.Net - ,stats.BBper100 - ,stats.Profitperhand - /*,to_char(hprof2.sum_profit/100.0,'9G999G990D00') AS Net - ,to_char((hprof2.sum_profit/(stats.bigBlind+0.0)) / (stats.n/100.0), '990D00') - AS BBper100 - ,hprof2.profitperhand AS Profitperhand - */ - ,round(hprof2.variance,2) AS Variance + || stats.name || ' ' + || stats.bigBlindDesc AS Game + ,stats.n + ,stats.vpip + ,stats.pfr + ,stats.pf3 + ,stats.steals + ,stats.saw_f + ,stats.sawsd + ,stats.wtsdwsf + ,stats.wmsd + ,stats.FlAFq + ,stats.TuAFq + ,stats.RvAFq + ,stats.PoFAFq + ,stats.Net + ,stats.BBper100 + ,stats.Profitperhand + ,case when hprof2.variance = -999 then '-' + else to_char(hprof2.variance, '0D00') + end AS Variance + ,AvgSeats FROM (select gt.base ,gt.category - ,upper(gt.limitType) as limitType + ,upper(gt.limitType) AS limitType ,s.name - ,gt.bigBlind - ,hc.gametypeId + , AS bigBlindDesc + , AS gtId ,sum(HDs) as n - ,to_char(100.0*sum(street0VPI)/sum(HDs),'90D0') AS vpip - ,to_char(100.0*sum(street0Aggr)/sum(HDs),'90D0') AS pfr - ,to_char(100.0*sum(street1Seen)/sum(HDs),'90D0') AS saw_f - ,to_char(100.0*sum(sawShowdown)/sum(HDs),'90D0') AS sawsd - ,case when sum(street1Seen) = 0 then 'oo' + ,to_char(100.0*sum(street0VPI)/sum(HDs),'990D0') AS vpip + ,to_char(100.0*sum(street0Aggr)/sum(HDs),'90D0') AS pfr + ,case when sum(street0_3Bchance) = 0 then '0' + else to_char(100.0*sum(street0_3Bdone)/sum(street0_3Bchance),'90D0') + end AS pf3 + ,case when sum(stealattemptchance) = 0 then '-' + else to_char(100.0*sum(stealattempted)/sum(stealattemptchance),'90D0') + end AS steals + ,to_char(100.0*sum(street1Seen)/sum(HDs),'90D0') AS saw_f + ,to_char(100.0*sum(sawShowdown)/sum(HDs),'90D0') AS sawsd + ,case when sum(street1Seen) = 0 then '-' else to_char(100.0*sum(sawShowdown)/sum(street1Seen),'90D0') end AS wtsdwsf - ,case when sum(sawShowdown) = 0 then 'oo' + ,case when sum(sawShowdown) = 0 then '-' else to_char(100.0*sum(wonAtSD)/sum(sawShowdown),'90D0') end AS wmsd - ,case when sum(street1Seen) = 0 then 'oo' + ,case when sum(street1Seen) = 0 then '-' else to_char(100.0*sum(street1Aggr)/sum(street1Seen),'90D0') end AS FlAFq - ,case when sum(street2Seen) = 0 then 'oo' + ,case when sum(street2Seen) = 0 then '-' else to_char(100.0*sum(street2Aggr)/sum(street2Seen),'90D0') end AS TuAFq - ,case when sum(street3Seen) = 0 then 'oo' + ,case when sum(street3Seen) = 0 then '-' else to_char(100.0*sum(street3Aggr)/sum(street3Seen),'90D0') end AS RvAFq - ,case when sum(street1Seen)+sum(street2Seen)+sum(street3Seen) = 0 then 'oo' + ,case when sum(street1Seen)+sum(street2Seen)+sum(street3Seen) = 0 then '-' else to_char(100.0*(sum(street1Aggr)+sum(street2Aggr)+sum(street3Aggr)) /(sum(street1Seen)+sum(street2Seen)+sum(street3Seen)),'90D0') end AS PoFAFq ,round(sum(totalProfit)/100.0,2) AS Net - ,to_char((sum(totalProfit)/(gt.bigBlind+0.0)) / (sum(HDs)/100.0), '990D00') + ,to_char((sum(totalProfit/(gt.bigBlind+0.0))) / (sum(HDs)/100.0), '990D00') AS BBper100 ,to_char(sum(totalProfit/100.0) / (sum(HDs)+0.0), '990D0000') AS Profitperhand + ,to_char(sum(activeSeats*HDs)/(sum(HDs)+0.0),'90D00') AS AvgSeats from Gametypes gt inner join Sites s on s.Id = gt.siteId inner join HudCache hc on hc.gameTypeId = gt.Id where hc.playerId in + and + and hc.activeSeats + and '20' || SUBSTR(hc.styleKey,2,2) || '-' || SUBSTR(hc.styleKey,4,2) || '-' + || SUBSTR(hc.styleKey,6,2) group by gt.base ,gt.category ,upper(gt.limitType) ,s.name - ,gt.bigBlind - ,hc.gametypeId + + ,gtId ) stats inner join ( select - hprof.gameTypeId, sum(hprof.profit) AS sum_profit, + hprof.gtId, sum(hprof.profit) AS sum_profit, avg(hprof.profit/100.0) AS profitperhand, - variance(hprof.profit/100.0) AS variance + case when hprof.gtId = -1 then -999 + else variance(hprof.profit/100.0) + end as variance from - (select hp.handId, - h.gameTypeId, - hp.winnings, - SUM(ha.amount) as costs, - hp.winnings - SUM(ha.amount) as profit - from HandsPlayers hp - inner join Hands h ON (h.id = hp.handId) - left join HandsActions ha ON (ha.handPlayerId = hp.id) - where hp.playerId in - and hp.tourneysPlayersId IS NULL - group by hp.handId, h.gameTypeId, hp.position, hp.winnings - ) hprof - group by hprof.gameTypeId + (select hp.handId, as gtId, hp.totalProfit as profit + from HandsPlayers hp + inner join Hands h ON (h.id = hp.handId) + where hp.playerId in + and hp.tourneysPlayersId IS NULL + and to_char(h.handStart, 'YYYY-MM-DD') + group by hp.handId, gtId, hp.totalProfit + ) hprof + group by hprof.gtId ) hprof2 - on hprof2.gameTypeId = stats.gameTypeId - order by stats.base, stats.limittype, stats.bigBlind""" + on hprof2.gtId = stats.gtId + order by stats.base, stats.limittype, stats.bigBlindDesc desc """ elif(self.dbname == 'SQLite'): self.query['playerStats'] = """ """ @@ -848,11 +1268,8 @@ class FpdbSQLQueries: SELECT concat(upper(stats.limitType), ' ' ,concat(upper(substring(stats.category,1,1)),substring(stats.category,2) ), ' ' - ,stats.name, ' $' - ,cast(trim(leading ' ' from - case when stats.bigBlind < 100 then format(stats.bigBlind/100.0,2) - else format(stats.bigBlind/100.0,0) - end ) as char) + ,stats.name, ' ' + ,cast(stats.bigBlindDesc as char) ) AS Game ,case when stats.PlPosition = -2 then 'BB' when stats.PlPosition = -1 then 'SB' @@ -865,6 +1282,8 @@ class FpdbSQLQueries: ,stats.n ,stats.vpip ,stats.pfr + ,stats.pf3 + ,stats.steals ,stats.saw_f ,stats.sawsd ,stats.wtsdwsf @@ -873,25 +1292,21 @@ class FpdbSQLQueries: ,stats.TuAFq ,stats.RvAFq ,stats.PoFAFq - /* if you have handsactions data the next 3 fields should give same answer as - following 3 commented out fields */ ,stats.Net ,stats.BBper100 ,stats.Profitperhand - /*,format(hprof2.sum_profit/100.0,2) AS Net - ,format((hprof2.sum_profit/(stats.bigBlind+0.0)) / (stats.n/100.0),2) - AS BBlPer100 - ,hprof2.profitperhand AS Profitperhand - */ - ,format(hprof2.variance,2) AS Variance + ,case when hprof2.variance = -999 then '-' + else format(hprof2.variance, 2) + end AS Variance + ,stats.AvgSeats FROM (select /* stats from hudcache */ gt.base ,gt.category - ,upper(gt.limitType) as limitType + ,upper(gt.limitType) AS limitType ,s.name - ,gt.bigBlind - ,hc.gametypeId + , AS bigBlindDesc + , AS gtId ,case when hc.position = 'B' then -2 when hc.position = 'S' then -1 when hc.position = 'D' then 0 @@ -901,49 +1316,60 @@ class FpdbSQLQueries: else 9 end as PlPosition ,sum(HDs) AS n - ,format(100.0*sum(street0VPI)/sum(HDs),1) AS vpip - ,format(100.0*sum(street0Aggr)/sum(HDs),1) AS pfr - ,format(100.0*sum(street1Seen)/sum(HDs),1) AS saw_f - ,format(100.0*sum(sawShowdown)/sum(HDs),1) AS sawsd - ,case when sum(street1Seen) = 0 then 'oo' + ,format(100.0*sum(street0VPI)/sum(HDs),1) AS vpip + ,format(100.0*sum(street0Aggr)/sum(HDs),1) AS pfr + ,case when sum(street0_3Bchance) = 0 then '0' + else format(100.0*sum(street0_3Bdone)/sum(street0_3Bchance),1) + end AS pf3 + ,case when sum(stealattemptchance) = 0 then '-' + else format(100.0*sum(stealattempted)/sum(stealattemptchance),1) + end AS steals + ,format(100.0*sum(street1Seen)/sum(HDs),1) AS saw_f + ,format(100.0*sum(sawShowdown)/sum(HDs),1) AS sawsd + ,case when sum(street1Seen) = 0 then '-' else format(100.0*sum(sawShowdown)/sum(street1Seen),1) end AS wtsdwsf - ,case when sum(sawShowdown) = 0 then 'oo' + ,case when sum(sawShowdown) = 0 then '-' else format(100.0*sum(wonAtSD)/sum(sawShowdown),1) end AS wmsd - ,case when sum(street1Seen) = 0 then 'oo' + ,case when sum(street1Seen) = 0 then '-' else format(100.0*sum(street1Aggr)/sum(street1Seen),1) end AS FlAFq - ,case when sum(street2Seen) = 0 then 'oo' + ,case when sum(street2Seen) = 0 then '-' else format(100.0*sum(street2Aggr)/sum(street2Seen),1) end AS TuAFq - ,case when sum(street3Seen) = 0 then 'oo' + ,case when sum(street3Seen) = 0 then '-' else format(100.0*sum(street3Aggr)/sum(street3Seen),1) end AS RvAFq - ,case when sum(street1Seen)+sum(street2Seen)+sum(street3Seen) = 0 then 'oo' + ,case when sum(street1Seen)+sum(street2Seen)+sum(street3Seen) = 0 then '-' else format(100.0*(sum(street1Aggr)+sum(street2Aggr)+sum(street3Aggr)) /(sum(street1Seen)+sum(street2Seen)+sum(street3Seen)),1) end AS PoFAFq ,format(sum(totalProfit)/100.0,2) AS Net - ,format((sum(totalProfit)/(gt.bigBlind+0.0)) / (sum(HDs)/100.0),2) + ,format((sum(totalProfit/(gt.bigBlind+0.0))) / (sum(HDs)/100.0),2) AS BBper100 ,format( (sum(totalProfit)/100.0) / sum(HDs), 4) AS Profitperhand + ,format( sum(activeSeats*HDs)/(sum(HDs)+0.0), 2) AS AvgSeats from Gametypes gt inner join Sites s on s.Id = gt.siteId inner join HudCache hc on hc.gameTypeId = gt.Id where hc.playerId in - # use here ? + and + and hc.activeSeats + and concat( '20', substring(hc.styleKey,2,2), '-', substring(hc.styleKey,4,2), '-' + , substring(hc.styleKey,6,2) ) group by gt.base ,gt.category ,upper(gt.limitType) ,s.name - ,gt.bigBlind - ,hc.gametypeId + + ,gtId + ,PlPosition ) stats inner join ( select # profit from handsplayers/handsactions - hprof.gameTypeId, + hprof.gtId, case when hprof.position = 'B' then -2 when hprof.position = 'S' then -1 when hprof.position in ('3','4') then 2 @@ -952,73 +1378,162 @@ class FpdbSQLQueries: end as PlPosition, sum(hprof.profit) as sum_profit, avg(hprof.profit/100.0) as profitperhand, - variance(hprof.profit/100.0) as variance + case when hprof.gtId = -1 then -999 + else variance(hprof.profit/100.0) + end as variance from - (select hp.handId, h.gameTypeId, hp.position, hp.winnings, SUM(ha.amount) - costs, hp.winnings - SUM(ha.amount) profit - from HandsPlayers hp - inner join Hands h ON h.id = hp.handId - left join HandsActions ha ON ha.handPlayerId = hp.id - where hp.playerId in - # use here ? - and hp.tourneysPlayersId IS NULL - group by hp.handId, h.gameTypeId, hp.position, hp.winnings - ) hprof - group by hprof.gameTypeId, PlPosition + (select hp.handId, as gtId, hp.position + , hp.totalProfit as profit + from HandsPlayers hp + inner join Hands h ON (h.id = hp.handId) + where hp.playerId in + and hp.tourneysPlayersId IS NULL + and date_format(h.handStart, '%Y-%m-%d') + group by hp.handId, gtId, hp.position, hp.totalProfit + ) hprof + group by hprof.gtId, PlPosition ) hprof2 - on ( hprof2.gameTypeId = stats.gameTypeId + on ( hprof2.gtId = stats.gtId and hprof2.PlPosition = stats.PlPosition) - order by stats.category, stats.limittype, stats.bigBlind, cast(stats.PlPosition as signed) + order by stats.category, stats.limitType, stats.bigBlindDesc desc + , cast(stats.PlPosition as signed) """ elif(self.dbname == 'PostgreSQL'): self.query['playerStatsByPosition'] = """ select /* stats from hudcache */ - hc.position AS pl_position - ,sum(HDs) as n - ,to_char(round(100.0*sum(street0VPI)/sum(HDs)),'90D0') AS vpip - ,to_char(round(100.0*sum(street0Aggr)/sum(HDs)),'90D0') AS pfr - ,to_char(round(100.0*sum(street1Seen)/sum(HDs)),'90D0') AS saw_f - ,to_char(round(100.0*sum(sawShowdown)/sum(HDs)),'90D0') AS sawsd - ,case when sum(street1Seen) = 0 then 'oo' - else to_char(round(100.0*sum(sawShowdown)/sum(street1Seen)),'90D0') - end AS wtsdwsf - ,case when sum(sawShowdown) = 0 then 'oo' - else to_char(round(100.0*sum(wonAtSD)/sum(sawShowdown)),'90D0') - end AS wmsd - ,case when sum(street1Seen) = 0 then 'oo' - else to_char(round(100.0*sum(street1Aggr)/sum(street1Seen)),'90D0') - end AS FlAFq - ,case when sum(street2Seen) = 0 then 'oo' - else to_char(round(100.0*sum(street2Aggr)/sum(street2Seen)),'90D0') - end AS TuAFq - ,case when sum(street3Seen) = 0 then 'oo' - else to_char(round(100.0*sum(street3Aggr)/sum(street3Seen)),'90D0') - end AS RvAFq - ,case when sum(street1Seen)+sum(street2Seen)+sum(street3Seen) = 0 then 'oo' - else to_char(round(100.0*(sum(street1Aggr)+sum(street2Aggr)+sum(street3Aggr)) - /(sum(street1Seen)+sum(street2Seen)+sum(street3Seen))),'90D0') - end AS PoFAFq - ,to_char(sum(totalProfit)/100.0,'9G999G990D00') AS Net - ,case when sum(HDs) = 0 then 'oo' - else to_char((sum(totalProfit)/(gt.bigBlind+0.0)) / (sum(HDs)/100.0), '990D00') - end AS BBper100 - from Gametypes gt - inner join Sites s on (s.Id = gt.siteId) - inner join HudCache hc on (hc.gameTypeId = gt.Id) - inner join Players p on (p.id = hc.playerId) - where hc.playerId in - and gt.type = 'ring' - and gt.id = /* must specify gametypeid */ - /* and stats.n > 100 optional stat-based queries */ - group by pl_position, gt.bigblind - order by case when hc.position = 'B' then -2 - when hc.position = 'S' then -1 - when hc.position = 'D' then 0 - when hc.position = 'C' then 1 - when hc.position = 'M' then 2 - when hc.position = 'E' then 5 - else 9 - end + upper(stats.limitType) || ' ' + || upper(substr(stats.category,1,1)) || substr(stats.category,2) || ' ' + || stats.name || ' ' + || stats.bigBlindDesc AS Game + ,case when stats.PlPosition = -2 then 'BB' + when stats.PlPosition = -1 then 'SB' + when stats.PlPosition = 0 then 'Btn' + when stats.PlPosition = 1 then 'CO' + when stats.PlPosition = 2 then 'MP' + when stats.PlPosition = 5 then 'EP' + else '??' + end AS PlPosition + ,stats.n + ,stats.vpip + ,stats.pfr + ,stats.pf3 + ,stats.steals + ,stats.saw_f + ,stats.sawsd + ,stats.wtsdwsf + ,stats.wmsd + ,stats.FlAFq + ,stats.TuAFq + ,stats.RvAFq + ,stats.PoFAFq + ,stats.Net + ,stats.BBper100 + ,stats.Profitperhand + ,case when hprof2.variance = -999 then '-' + else to_char(hprof2.variance, '0D00') + end AS Variance + ,stats.AvgSeats + FROM + (select /* stats from hudcache */ + gt.base + ,gt.category + ,upper(gt.limitType) AS limitType + ,s.name + , AS bigBlindDesc + , AS gtId + ,case when hc.position = 'B' then -2 + when hc.position = 'S' then -1 + when hc.position = 'D' then 0 + when hc.position = 'C' then 1 + when hc.position = 'M' then 2 + when hc.position = 'E' then 5 + else 9 + end AS PlPosition + ,sum(HDs) AS n + ,to_char(round(100.0*sum(street0VPI)/sum(HDs)),'990D0') AS vpip + ,to_char(round(100.0*sum(street0Aggr)/sum(HDs)),'90D0') AS pfr + ,case when sum(street0_3Bchance) = 0 then '0' + else to_char(100.0*sum(street0_3Bdone)/sum(street0_3Bchance),'90D0') + end AS pf3 + ,case when sum(stealattemptchance) = 0 then '-' + else to_char(100.0*sum(stealattempted)/sum(stealattemptchance),'90D0') + end AS steals + ,to_char(round(100.0*sum(street1Seen)/sum(HDs)),'90D0') AS saw_f + ,to_char(round(100.0*sum(sawShowdown)/sum(HDs)),'90D0') AS sawsd + ,case when sum(street1Seen) = 0 then '-' + else to_char(round(100.0*sum(sawShowdown)/sum(street1Seen)),'90D0') + end AS wtsdwsf + ,case when sum(sawShowdown) = 0 then '-' + else to_char(round(100.0*sum(wonAtSD)/sum(sawShowdown)),'90D0') + end AS wmsd + ,case when sum(street1Seen) = 0 then '-' + else to_char(round(100.0*sum(street1Aggr)/sum(street1Seen)),'90D0') + end AS FlAFq + ,case when sum(street2Seen) = 0 then '-' + else to_char(round(100.0*sum(street2Aggr)/sum(street2Seen)),'90D0') + end AS TuAFq + ,case when sum(street3Seen) = 0 then '-' + else to_char(round(100.0*sum(street3Aggr)/sum(street3Seen)),'90D0') + end AS RvAFq + ,case when sum(street1Seen)+sum(street2Seen)+sum(street3Seen) = 0 then '-' + else to_char(round(100.0*(sum(street1Aggr)+sum(street2Aggr)+sum(street3Aggr)) + /(sum(street1Seen)+sum(street2Seen)+sum(street3Seen))),'90D0') + end AS PoFAFq + ,to_char(sum(totalProfit)/100.0,'9G999G990D00') AS Net + ,case when sum(HDs) = 0 then '0' + else to_char(sum(totalProfit/(gt.bigBlind+0.0)) / (sum(HDs)/100.0), '990D00') + end AS BBper100 + ,case when sum(HDs) = 0 then '0' + else to_char( (sum(totalProfit)/100.0) / sum(HDs), '90D0000') + end AS Profitperhand + ,to_char(sum(activeSeats*HDs)/(sum(HDs)+0.0),'90D00') AS AvgSeats + from Gametypes gt + inner join Sites s on (s.Id = gt.siteId) + inner join HudCache hc on (hc.gameTypeId = gt.Id) + where hc.playerId in + and + and hc.activeSeats + and '20' || SUBSTR(hc.styleKey,2,2) || '-' || SUBSTR(hc.styleKey,4,2) || '-' + || SUBSTR(hc.styleKey,6,2) + group by gt.base + ,gt.category + ,upper(gt.limitType) + ,s.name + + ,gtId + + ,PlPosition + ) stats + inner join + ( select /* profit from handsplayers/handsactions */ + hprof.gtId, + case when hprof.position = 'B' then -2 + when hprof.position = 'S' then -1 + when hprof.position in ('3','4') then 2 + when hprof.position in ('6','7') then 5 + else cast(hprof.position as smallint) + end as PlPosition, + sum(hprof.profit) as sum_profit, + avg(hprof.profit/100.0) as profitperhand, + case when hprof.gtId = -1 then -999 + else variance(hprof.profit/100.0) + end as variance + from + (select hp.handId, as gtId, hp.position + , hp.totalProfit as profit + from HandsPlayers hp + inner join Hands h ON (h.id = hp.handId) + where hp.playerId in + and hp.tourneysPlayersId IS NULL + and to_char(h.handStart, 'YYYY-MM-DD') + group by hp.handId, gameTypeId, hp.position, hp.totalProfit + ) hprof + group by hprof.gtId, PlPosition + ) hprof2 + on ( hprof2.gtId = stats.gtId + and hprof2.PlPosition = stats.PlPosition) + order by stats.category, stats.limitType, stats.bigBlindDesc desc + , cast(stats.PlPosition as smallint) """ elif(self.dbname == 'SQLite'): self.query['playerStatsByPosition'] = """ """ @@ -1084,24 +1599,24 @@ class FpdbSQLQueries: ,format(100.0*sum(street0Aggr)/sum(HDs),1) AS pfr ,format(100.0*sum(street1Seen)/sum(HDs),1) AS saw_f ,format(100.0*sum(sawShowdown)/sum(HDs),1) AS sawsd - ,case when sum(street1Seen) = 0 then 'oo' + ,case when sum(street1Seen) = 0 then '-' else format(100.0*sum(sawShowdown)/sum(street1Seen),1) end AS wtsdwsf - ,case when sum(sawShowdown) = 0 then 'oo' + ,case when sum(sawShowdown) = 0 then '-' end AS wtsdwsf - ,case when sum(sawShowdown) = 0 then 'oo' + ,case when sum(sawShowdown) = 0 then '-' else format(100.0*sum(wonAtSD)/sum(sawShowdown),1) end AS wmsd - ,case when sum(street1Seen) = 0 then 'oo' + ,case when sum(street1Seen) = 0 then '-' else format(100.0*sum(street1Aggr)/sum(street1Seen),1) end AS FlAFq - ,case when sum(street2Seen) = 0 then 'oo' + ,case when sum(street2Seen) = 0 then '-' else format(100.0*sum(street2Aggr)/sum(street2Seen),1) end AS TuAFq - ,case when sum(street3Seen) = 0 then 'oo' + ,case when sum(street3Seen) = 0 then '-' else format(100.0*sum(street3Aggr)/sum(street3Seen),1) end AS RvAFq - ,case when sum(street1Seen)+sum(street2Seen)+sum(street3Seen) = 0 then 'oo' + ,case when sum(street1Seen)+sum(street2Seen)+sum(street3Seen) = 0 then '-' else format(100.0*(sum(street1Aggr)+sum(street2Aggr)+sum(street3Aggr)) /(sum(street1Seen)+sum(street2Seen)+sum(street3Seen)),1) end AS PoFAFq @@ -1136,11 +1651,11 @@ class FpdbSQLQueries: variance(hprof.profit/100.0) as variance, count(*) as n from - (select hp.handId, h.gameTypeId, hp.position, hp.winnings, SUM(ha.amount) - costs, hp.winnings - SUM(ha.amount) profit + (select hp.handId, h.gameTypeId, hp.position, hp.winnings, SUM(ha.amount) as costs + , hp.winnings - SUM(ha.amount) as profit from HandsPlayers hp - inner join Hands h ON h.id = hp.handId - left join HandsActions ha ON ha.handPlayerId = hp.id + inner join Hands h ON h.id = hp.handId + left join HandsActions ha ON ha.handsPlayerId = hp.id where hp.playerId in # use here ? and hp.tourneysPlayersId IS NULL @@ -1153,6 +1668,317 @@ class FpdbSQLQueries: and hprof2.PlPosition = stats.PlPosition) order by stats.category, stats.limittype, stats.bigBlind, cast(stats.PlPosition as signed) """ + if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'): + self.query['getGames'] = """SELECT DISTINCT category from Gametypes""" + + if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'): + self.query['getLimits'] = """SELECT DISTINCT bigBlind from Gametypes ORDER by bigBlind DESC""" + + + #################################### + # Queries to rebuild/modify hudcache + #################################### + + if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'): + self.query['clearHudCache'] = """DELETE FROM HudCache""" + + if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'): + self.query['rebuildHudCache'] = """ + INSERT INTO HudCache + (gametypeId + ,playerId + ,activeSeats + ,position + ,tourneyTypeId + ,styleKey + ,HDs + ,wonWhenSeenStreet1 + ,wonAtSD + ,street0VPI + ,street0Aggr + ,street0_3BChance + ,street0_3BDone + ,street1Seen + ,street2Seen + ,street3Seen + ,street4Seen + ,sawShowdown + ,street1Aggr + ,street2Aggr + ,street3Aggr + ,street4Aggr + ,otherRaisedStreet1 + ,otherRaisedStreet2 + ,otherRaisedStreet3 + ,otherRaisedStreet4 + ,foldToOtherRaisedStreet1 + ,foldToOtherRaisedStreet2 + ,foldToOtherRaisedStreet3 + ,foldToOtherRaisedStreet4 + ,stealAttemptChance + ,stealAttempted + ,foldBbToStealChance + ,foldedBbToSteal + ,foldSbToStealChance + ,foldedSbToSteal + ,street1CBChance + ,street1CBDone + ,street2CBChance + ,street2CBDone + ,street3CBChance + ,street3CBDone + ,street4CBChance + ,street4CBDone + ,foldToStreet1CBChance + ,foldToStreet1CBDone + ,foldToStreet2CBChance + ,foldToStreet2CBDone + ,foldToStreet3CBChance + ,foldToStreet3CBDone + ,foldToStreet4CBChance + ,foldToStreet4CBDone + ,totalProfit + ,street1CheckCallRaiseChance + ,street1CheckCallRaiseDone + ,street2CheckCallRaiseChance + ,street2CheckCallRaiseDone + ,street3CheckCallRaiseChance + ,street3CheckCallRaiseDone + ,street4CheckCallRaiseChance + ,street4CheckCallRaiseDone + ) + SELECT h.gametypeId + ,hp.playerId + ,h.seats + ,case when hp.position = 'B' then 'B' + when hp.position = 'S' then 'S' + when hp.position = '0' then 'D' + when hp.position = '1' then 'C' + when hp.position = '2' then 'M' + when hp.position = '3' then 'M' + when hp.position = '4' then 'M' + when hp.position = '5' then 'E' + when hp.position = '6' then 'E' + when hp.position = '7' then 'E' + when hp.position = '8' then 'E' + when hp.position = '9' then 'E' + else 'E' + end AS hc_position + ,hp.tourneyTypeId + ,date_format(h.handStart, 'd%y%m%d') + ,count(1) + ,sum(wonWhenSeenStreet1) + ,sum(wonAtSD) + ,sum(CAST(street0VPI as integer)) + ,sum(CAST(street0Aggr as integer)) + ,sum(CAST(street0_3BChance as integer)) + ,sum(CAST(street0_3BDone as integer)) + ,sum(CAST(street1Seen as integer)) + ,sum(CAST(street2Seen as integer)) + ,sum(CAST(street3Seen as integer)) + ,sum(CAST(street4Seen as integer)) + ,sum(CAST(sawShowdown as integer)) + ,sum(CAST(street1Aggr as integer)) + ,sum(CAST(street2Aggr as integer)) + ,sum(CAST(street3Aggr as integer)) + ,sum(CAST(street4Aggr as integer)) + ,sum(CAST(otherRaisedStreet1 as integer)) + ,sum(CAST(otherRaisedStreet2 as integer)) + ,sum(CAST(otherRaisedStreet3 as integer)) + ,sum(CAST(otherRaisedStreet4 as integer)) + ,sum(CAST(foldToOtherRaisedStreet1 as integer)) + ,sum(CAST(foldToOtherRaisedStreet2 as integer)) + ,sum(CAST(foldToOtherRaisedStreet3 as integer)) + ,sum(CAST(foldToOtherRaisedStreet4 as integer)) + ,sum(CAST(stealAttemptChance as integer)) + ,sum(CAST(stealAttempted as integer)) + ,sum(CAST(foldBbToStealChance as integer)) + ,sum(CAST(foldedBbToSteal as integer)) + ,sum(CAST(foldSbToStealChance as integer)) + ,sum(CAST(foldedSbToSteal as integer)) + ,sum(CAST(street1CBChance as integer)) + ,sum(CAST(street1CBDone as integer)) + ,sum(CAST(street2CBChance as integer)) + ,sum(CAST(street2CBDone as integer)) + ,sum(CAST(street3CBChance as integer)) + ,sum(CAST(street3CBDone as integer)) + ,sum(CAST(street4CBChance as integer)) + ,sum(CAST(street4CBDone as integer)) + ,sum(CAST(foldToStreet1CBChance as integer)) + ,sum(CAST(foldToStreet1CBDone as integer)) + ,sum(CAST(foldToStreet2CBChance as integer)) + ,sum(CAST(foldToStreet2CBDone as integer)) + ,sum(CAST(foldToStreet3CBChance as integer)) + ,sum(CAST(foldToStreet3CBDone as integer)) + ,sum(CAST(foldToStreet4CBChance as integer)) + ,sum(CAST(foldToStreet4CBDone as integer)) + ,sum(CAST(totalProfit as integer)) + ,sum(CAST(street1CheckCallRaiseChance as integer)) + ,sum(CAST(street1CheckCallRaiseDone as integer)) + ,sum(CAST(street2CheckCallRaiseChance as integer)) + ,sum(CAST(street2CheckCallRaiseDone as integer)) + ,sum(CAST(street3CheckCallRaiseChance as integer)) + ,sum(CAST(street3CheckCallRaiseDone as integer)) + ,sum(CAST(street4CheckCallRaiseChance as integer)) + ,sum(CAST(street4CheckCallRaiseDone as integer)) + FROM HandsPlayers hp + INNER JOIN Hands h ON (h.id = hp.handId) + GROUP BY h.gametypeId + ,hp.playerId + ,h.seats + ,hc_position + ,hp.tourneyTypeId + ,date_format(h.handStart, 'd%y%m%d') +""" + elif (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'): + self.query['rebuildHudCache'] = """ + INSERT INTO HudCache + (gametypeId + ,playerId + ,activeSeats + ,position + ,tourneyTypeId + ,styleKey + ,HDs + ,wonWhenSeenStreet1 + ,wonAtSD + ,street0VPI + ,street0Aggr + ,street0_3BChance + ,street0_3BDone + ,street1Seen + ,street2Seen + ,street3Seen + ,street4Seen + ,sawShowdown + ,street1Aggr + ,street2Aggr + ,street3Aggr + ,street4Aggr + ,otherRaisedStreet1 + ,otherRaisedStreet2 + ,otherRaisedStreet3 + ,otherRaisedStreet4 + ,foldToOtherRaisedStreet1 + ,foldToOtherRaisedStreet2 + ,foldToOtherRaisedStreet3 + ,foldToOtherRaisedStreet4 + ,stealAttemptChance + ,stealAttempted + ,foldBbToStealChance + ,foldedBbToSteal + ,foldSbToStealChance + ,foldedSbToSteal + ,street1CBChance + ,street1CBDone + ,street2CBChance + ,street2CBDone + ,street3CBChance + ,street3CBDone + ,street4CBChance + ,street4CBDone + ,foldToStreet1CBChance + ,foldToStreet1CBDone + ,foldToStreet2CBChance + ,foldToStreet2CBDone + ,foldToStreet3CBChance + ,foldToStreet3CBDone + ,foldToStreet4CBChance + ,foldToStreet4CBDone + ,totalProfit + ,street1CheckCallRaiseChance + ,street1CheckCallRaiseDone + ,street2CheckCallRaiseChance + ,street2CheckCallRaiseDone + ,street3CheckCallRaiseChance + ,street3CheckCallRaiseDone + ,street4CheckCallRaiseChance + ,street4CheckCallRaiseDone + ) + SELECT h.gametypeId + ,hp.playerId + ,h.seats + ,case when hp.position = 'B' then 'B' + when hp.position = 'S' then 'S' + when hp.position = '0' then 'D' + when hp.position = '1' then 'C' + when hp.position = '2' then 'M' + when hp.position = '3' then 'M' + when hp.position = '4' then 'M' + when hp.position = '5' then 'E' + when hp.position = '6' then 'E' + when hp.position = '7' then 'E' + when hp.position = '8' then 'E' + when hp.position = '9' then 'E' + else 'E' + end AS hc_position + ,hp.tourneyTypeId + ,'d' || to_char(h.handStart, 'YYMMDD') + ,count(1) + ,sum(wonWhenSeenStreet1) + ,sum(wonAtSD) + ,sum(CAST(street0VPI as integer)) + ,sum(CAST(street0Aggr as integer)) + ,sum(CAST(street0_3BChance as integer)) + ,sum(CAST(street0_3BDone as integer)) + ,sum(CAST(street1Seen as integer)) + ,sum(CAST(street2Seen as integer)) + ,sum(CAST(street3Seen as integer)) + ,sum(CAST(street4Seen as integer)) + ,sum(CAST(sawShowdown as integer)) + ,sum(CAST(street1Aggr as integer)) + ,sum(CAST(street2Aggr as integer)) + ,sum(CAST(street3Aggr as integer)) + ,sum(CAST(street4Aggr as integer)) + ,sum(CAST(otherRaisedStreet1 as integer)) + ,sum(CAST(otherRaisedStreet2 as integer)) + ,sum(CAST(otherRaisedStreet3 as integer)) + ,sum(CAST(otherRaisedStreet4 as integer)) + ,sum(CAST(foldToOtherRaisedStreet1 as integer)) + ,sum(CAST(foldToOtherRaisedStreet2 as integer)) + ,sum(CAST(foldToOtherRaisedStreet3 as integer)) + ,sum(CAST(foldToOtherRaisedStreet4 as integer)) + ,sum(CAST(stealAttemptChance as integer)) + ,sum(CAST(stealAttempted as integer)) + ,sum(CAST(foldBbToStealChance as integer)) + ,sum(CAST(foldedBbToSteal as integer)) + ,sum(CAST(foldSbToStealChance as integer)) + ,sum(CAST(foldedSbToSteal as integer)) + ,sum(CAST(street1CBChance as integer)) + ,sum(CAST(street1CBDone as integer)) + ,sum(CAST(street2CBChance as integer)) + ,sum(CAST(street2CBDone as integer)) + ,sum(CAST(street3CBChance as integer)) + ,sum(CAST(street3CBDone as integer)) + ,sum(CAST(street4CBChance as integer)) + ,sum(CAST(street4CBDone as integer)) + ,sum(CAST(foldToStreet1CBChance as integer)) + ,sum(CAST(foldToStreet1CBDone as integer)) + ,sum(CAST(foldToStreet2CBChance as integer)) + ,sum(CAST(foldToStreet2CBDone as integer)) + ,sum(CAST(foldToStreet3CBChance as integer)) + ,sum(CAST(foldToStreet3CBDone as integer)) + ,sum(CAST(foldToStreet4CBChance as integer)) + ,sum(CAST(foldToStreet4CBDone as integer)) + ,sum(CAST(totalProfit as integer)) + ,sum(CAST(street1CheckCallRaiseChance as integer)) + ,sum(CAST(street1CheckCallRaiseDone as integer)) + ,sum(CAST(street2CheckCallRaiseChance as integer)) + ,sum(CAST(street2CheckCallRaiseDone as integer)) + ,sum(CAST(street3CheckCallRaiseChance as integer)) + ,sum(CAST(street3CheckCallRaiseDone as integer)) + ,sum(CAST(street4CheckCallRaiseChance as integer)) + ,sum(CAST(street4CheckCallRaiseDone as integer)) + FROM HandsPlayers hp + INNER JOIN Hands h ON (h.id = hp.handId) + GROUP BY h.gametypeId + ,hp.playerId + ,h.seats + ,hc_position + ,hp.tourneyTypeId + ,to_char(h.handStart, 'YYMMDD') +""" + if __name__== "__main__": from optparse import OptionParser diff --git a/pyfpdb/FulltiltToFpdb.py b/pyfpdb/FulltiltToFpdb.py index f3d30229..a84f683c 100755 --- a/pyfpdb/FulltiltToFpdb.py +++ b/pyfpdb/FulltiltToFpdb.py @@ -28,11 +28,13 @@ class Fulltilt(HandHistoryConverter): # Static regexes re_GameInfo = re.compile('- (?P\$|)?(?P[.0-9]+)/\$?(?P[.0-9]+) (Ante \$(?P[.0-9]+) )?- (?P(No Limit|Pot Limit|Limit))? (?P(Hold\'em|Omaha Hi|Razz))') - re_SplitHands = re.compile(r"(\n\n+)") + re_SplitHands = re.compile(r"\n\n+") + re_TailSplitHands = re.compile(r"(\n\n+)") re_HandInfo = re.compile('.*#(?P[0-9]+): Table (?P
[- a-zA-Z]+) (\((?P.+)\) )?- \$?(?P[.0-9]+)/\$?(?P[.0-9]+) (Ante \$(?P[.0-9]+) )?- (?P[a-zA-Z\' ]+) - (?P.*)') re_Button = re.compile('^The button is in seat #(?P
[- a-zA-Z]+)\'(?P.+?$)?", re.MULTILINE) re_Button = re.compile('Seat #(?P
[- a-zA-Z]+)\'(?P.+?$)?", re.MULTILINE) + re_Button = re.compile('Seat #(?P
[ a-zA-Z]+) - \$?(?P[.0-9]+)/\$?(?P[.0-9]+) - (?P.*) - (?P
[0-9]+):(?P[0-9]+) ET - (?P[0-9]+)/(?P[0-9]+)/(?P[0-9]+)Table (?P
[ a-zA-Z]+)\nSeat (?P