From 72dff55f6f38eb984181c7b55e122ad437f73b29 Mon Sep 17 00:00:00 2001 From: Worros Date: Mon, 9 Mar 2009 18:07:04 +0900 Subject: [PATCH 001/104] [KILLFTP 1/x] Tear out FTP specific hand import code --- pyfpdb/fpdb_import.py | 131 +++++++++++++----------------------------- 1 file changed, 41 insertions(+), 90 deletions(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index d86c4214..fde69125 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -293,12 +293,6 @@ class Importer: # print "import_fpdb_file", file, site, self.lines, "\n" return (0,0,0,1,0) - if firstline.find("Tournament Summary")!=-1: - print "TODO: implement importing tournament summaries" - #self.faobs = readfile(inputFile) - #self.parseTourneyHistory() - return 0 - site=fpdb_simple.recogniseSite(firstline) category=fpdb_simple.recogniseCategory(firstline) @@ -316,91 +310,53 @@ class Importer: if (len(hand[0])<2): hand=hand[1:] - cancelled=False - damaged=False - if (site=="ftp"): - for i in range (len(hand)): - if (hand[i].endswith(" has been canceled")): #this is their typo. this is a typo, right? - cancelled=True - - #FTP generates lines looking like: - #Seat 1: IOS Seat 2: kashman59 (big blind) showed [8c 9d] and won ($3.25) with a pair of Eights - #ie. Seat X multiple times on the same line in the summary section, when a new player sits down in the - #middle of the hand. - #TODO: Deal with this properly, either fix the file or make the parsing code work with this line. - if "Seat" in hand[i]: - mo = re.search(" Seat [0-9]+: ", hand[i]) - if mo: - print "mo=", mo, "\nmo.start=", mo.start(),"\nhand[i]=",hand[i] - hand.insert(i+1, hand[i][mo.start()+1:]) - hand[i] = hand[i][0:mo.start()] - - if (len(hand)<3): - pass - #todo: the above 2 lines are kind of a dirty hack, the mentioned circumstances should be handled elsewhere but that doesnt work with DOS/Win EOL. actually this doesnt work. - elif (hand[0].endswith(" (partial)")): #partial hand - do nothing - partial+=1 - elif (hand[1].find("Seat")==-1 and hand[2].find("Seat")==-1 and hand[3].find("Seat")==-1):#todo: should this be or instead of and? - partial+=1 - elif (cancelled or damaged): - partial+=1 - if damaged: - print """ - DEBUG: Partial hand triggered by a line containing 'Seat X:' twice. This is a - bug in the FTP software when a player sits down in the middle of a hand. - Adding a newline after the player name will fix the issue - """ - print "File: %s" %(file) - print "Line: %s" %(startpos) - else: #normal processing - isTourney=fpdb_simple.isTourney(hand[0]) - if not isTourney: - fpdb_simple.filterAnteBlindFold(site,hand) - hand=fpdb_simple.filterCrap(site, hand, isTourney) - self.hand=hand + isTourney=fpdb_simple.isTourney(hand[0]) + if not isTourney: + fpdb_simple.filterAnteBlindFold(site,hand) + hand=fpdb_simple.filterCrap(site, hand, isTourney) + self.hand=hand - try: - handsId=fpdb_parse_logic.mainParser(self.settings['db-backend'], self.fdb.db + try: + handsId=fpdb_parse_logic.mainParser(self.settings['db-backend'], self.fdb.db ,self.fdb.cursor, site, category, hand) - self.fdb.db.commit() + self.fdb.db.commit() - stored+=1 - if self.callHud: - #print "call to HUD here. handsId:",handsId - #pipe the Hands.id out to the HUD - self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep) - except fpdb_simple.DuplicateError: - duplicates+=1 - except (ValueError), fe: - errors+=1 - self.printEmailErrorMessage(errors, file, hand) - - if (self.settings['failOnError']): - self.fdb.db.commit() #dont remove this, in case hand processing was cancelled. - raise - except (fpdb_simple.FpdbError), fe: - errors+=1 - self.printEmailErrorMessage(errors, file, hand) + stored+=1 + if self.callHud: + #print "call to HUD here. handsId:",handsId + #pipe the Hands.id out to the HUD + self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep) + except fpdb_simple.DuplicateError: + duplicates+=1 + except (ValueError), fe: + errors+=1 + self.printEmailErrorMessage(errors, file, hand) - #fe.printStackTrace() #todo: get stacktrace - self.fdb.db.rollback() + if (self.settings['failOnError']): + self.fdb.db.commit() #dont remove this, in case hand processing was cancelled. + raise + except (fpdb_simple.FpdbError), fe: + errors+=1 + self.printEmailErrorMessage(errors, file, hand) + + self.fdb.db.rollback() - if (self.settings['failOnError']): - self.fdb.db.commit() #dont remove this, in case hand processing was cancelled. - raise - if (self.settings['minPrint']!=0): - if ((stored+duplicates+partial+errors)%self.settings['minPrint']==0): - print "stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors + if (self.settings['failOnError']): + self.fdb.db.commit() #dont remove this, in case hand processing was cancelled. + raise + if (self.settings['minPrint']!=0): + if ((stored+duplicates+errors)%self.settings['minPrint']==0): + print "stored:", stored, "duplicates:", duplicates, "errors:", errors - if (self.settings['handCount']!=0): - if ((stored+duplicates+partial+errors)>=self.settings['handCount']): - if (not self.settings['quiet']): - print "quitting due to reaching the amount of hands to be imported" - print "Total stored:", stored, "duplicates:", duplicates, "partial/damaged:", partial, "errors:", errors, " time:", (time() - starttime) - sys.exit(0) - startpos=endpos + if (self.settings['handCount']!=0): + if ((stored+duplicates+errors)>=self.settings['handCount']): + if (not self.settings['quiet']): + print "quitting due to reaching the amount of hands to be imported" + print "Total stored:", stored, "duplicates:", duplicates, "errors:", errors, " time:", (time() - starttime) + sys.exit(0) + startpos=endpos ttime = time() - starttime - print "\rTotal stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors, " time:", ttime + print "\rTotal stored:", stored, "duplicates:", duplicates, "errors:", errors, " time:", ttime if stored==0: if duplicates>0: @@ -411,16 +367,11 @@ class Importer: else: print "failed to read a single hand from file:", inputFile handsId=0 - #todo: this will cause return of an unstored hand number if the last hand was error or partial + #todo: this will cause return of an unstored hand number if the last hand was error self.fdb.db.commit() self.handsId=handsId return (stored, duplicates, partial, errors, ttime) - def parseTourneyHistory(self): - print "Tourney history parser stub" - #Find tournament boundaries. - #print self.foabs - def printEmailErrorMessage(self, errors, filename, line): traceback.print_exc(file=sys.stderr) print "Error No.",errors,", please send the hand causing this to steffen@sycamoretest.info so I can fix it." From 58445c0a1b72fb16f3db97bb13a798db1d896feb Mon Sep 17 00:00:00 2001 From: Worros Date: Mon, 9 Mar 2009 18:21:22 +0900 Subject: [PATCH 002/104] [KILLFTP 2/x] More ftp specific code removal --- pyfpdb/fpdb_parse_logic.py | 2 - pyfpdb/fpdb_simple.py | 140 ++++++++----------------------------- 2 files changed, 29 insertions(+), 113 deletions(-) diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py index dab3bcc4..c5076283 100644 --- a/pyfpdb/fpdb_parse_logic.py +++ b/pyfpdb/fpdb_parse_logic.py @@ -111,8 +111,6 @@ def mainParser(backend, db, cursor, site, category, hand): tableResult=fpdb_simple.parseTableLine(site, base, hand[i]) else: raise fpdb_simple.FpdbError("unrecognised lineType:"+lineTypes[i]) - if site=="ftp": - tableResult=fpdb_simple.parseTableLine(site, base, hand[0]) maxSeats=tableResult['maxSeats'] tableName=tableResult['tableName'] #print "before part5, antes:", antes diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index dbf53e93..d3bb4097 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -476,8 +476,6 @@ def convert3B4B(site, category, limit_type, actionTypes, actionAmounts): #todo: run correction for below if (site=="ps" and category=="holdem" and limit_type=="nl" and len(bets)==3): fail=False - if (site=="ftp" and category=="omahahi" and limit_type=="pl" and len(bets)==3): - fail=False if fail: print "len(bets)>2 in convert3B4B, i didnt think this is possible. i:",i,"j:",j,"k:",k @@ -689,18 +687,8 @@ def filterCrap(site, hand, isTourney): toRemove.append(hand[i]) elif (hand[i].endswith("is disconnected")): toRemove.append(hand[i]) - elif (hand[i].endswith(" is feeling angry")): - toRemove.append(hand[i]) - elif (hand[i].endswith(" is feeling confused")): - toRemove.append(hand[i]) - elif (hand[i].endswith(" is feeling happy")): - toRemove.append(hand[i]) - elif (hand[i].endswith(" is feeling normal")): - toRemove.append(hand[i]) elif (hand[i].find(" is low with [")!=-1): toRemove.append(hand[i]) - #elif (hand[i].find("-max Seat #")!=-1 and hand[i].find(" is the button")!=-1): - # toRemove.append(hand[i]) elif (hand[i].endswith(" mucks")): toRemove.append(hand[i]) elif (hand[i].endswith(": mucks hand")): @@ -711,8 +699,6 @@ def filterCrap(site, hand, isTourney): toRemove.append(hand[i]) elif (hand[i].find(" shows ")!=-1 and hand[i].find("[")==-1): toRemove.append(hand[i]) - #elif (hand[i].startswith("Table '") and hand[i].endswith("-max")): - # toRemove.append(hand[i]) elif (hand[i].startswith("The button is in seat #")): toRemove.append(hand[i]) #above is alphabetic, reorder below if bored @@ -747,8 +733,6 @@ def filterCrap(site, hand, isTourney): #site specific variable position filter elif (hand[i].find(" said, \"")!=-1): toRemove.append(hand[i]) - elif (hand[i].find(": ")!=-1 and site=="ftp" and hand[i].find("Seat ")==-1 and hand[i].find(": Table")==-1): #filter ftp chat - toRemove.append(hand[i]) if isTourney: if (hand[i].endswith(" is sitting out") and (not hand[i].startswith("Seat "))): toRemove.append(hand[i]) @@ -857,14 +841,6 @@ def isWinLine(line): return True elif (line.find("ties for the low side pot")!=-1): return True - elif (line.find("ties for the main pot")!=-1): #for ftp tied main pot of split pot - return True - elif (line.find("ties for the pot")!=-1): #for ftp tie - return True - elif (line.find("ties for the side pot")!=-1): #for ftp tied split pots - return True - elif (line.find("wins side pot #")!=-1): #for ftp multi split pots - return True elif (line.find("wins the low main pot")!=-1): return True elif (line.find("wins the low pot")!=-1): @@ -879,8 +855,6 @@ def isWinLine(line): return True elif (line.find("wins the main pot")!=-1): return True - elif (line.find("wins the side pot")!=-1): #for ftp split pots - return True elif (line.find("collected")!=-1): return True else: @@ -904,10 +878,6 @@ def parseActionAmount(line, atype, site, isTourney): amount=0 elif (atype=="check"): amount=0 - elif (atype=="unbet" and site=="ftp"): - pos1=line.find("$")+1 - pos2=line.find(" returned to") - amount=float2int(line[pos1:pos2]) elif (atype=="unbet" and site=="ps"): #print "ps unbet, line:",line pos1=line.find("$")+1 @@ -1129,8 +1099,6 @@ def parseCashesAndSeatNos(lines, site): pos1=lines[i].rfind("($")+2 if pos1==1: #for tourneys - it's 1 instead of -1 due to adding 2 above pos1=lines[i].rfind("(")+1 - if (site=="ftp"): - pos2=lines[i].rfind(")") elif (site=="ps"): pos2=lines[i].find(" in chips") cashes.append(float2int(lines[i][pos1:pos2])) @@ -1157,41 +1125,25 @@ def parseHandStartTime(topline, site): if counter==10: break isUTC=False - if site=="ftp": - # Full Tilt Sit'n'Go - # Full Tilt Poker Game #10311865543: $1 + $0.25 Sit & Go (78057629), Table 1 - 25/50 - No Limit Hold'em - 0:07:45 ET - 2009/01/29 - # Cash Game: - # Full Tilt Poker Game #9403951181: Table CR - tay - $0.05/$0.10 - No Limit Hold'em - 9:40:20 ET - 2008/12/09 - # Full Tilt Poker Game #9468383505: Table Bike (deep 6) - $0.05/$0.10 - No Limit Hold'em - 5:09:36 ET - 2008/12/13 - pos = topline.find(" ", len(topline)-26)+1 - tmp = topline[pos:] - - rexx = '(?P
[0-9]+):(?P[0-9]+):(?P[0-9]+) ET [\- ]+(?P[0-9]{4})\/(?P[0-9]{2})\/(?P[0-9]{2})' - m = re.search(rexx,tmp) - result = datetime.datetime(int(m.group('YEAR')), int(m.group('MON')), int(m.group('DAY')), int(m.group('HR')), int(m.group('MIN')), int(m.group('SEC'))) - elif site=="ps": - if topline.find("UTC")!=-1: - pos1 = topline.find("-")+2 - pos2 = topline.find("UTC") - tmp=topline[pos1:pos2] - isUTC=True - else: - tmp=topline - #print "parsehandStartTime, tmp:", tmp - pos = tmp.find("-")+2 - tmp = tmp[pos:] - #Need to match either - # 2008/09/07 06:23:14 ET or - # 2008/08/17 - 01:14:43 (ET) or - # 2008/11/12 9:33:31 CET [2008/11/12 3:33:31 ET] - rexx = '(?P[0-9]{4})\/(?P[0-9]{2})\/(?P[0-9]{2})[\- ]+(?P
[0-9]+):(?P[0-9]+):(?P[0-9]+)' - m = re.search(rexx,tmp) - #print "year:", int(m.group('YEAR')), "month", int(m.group('MON')), "day", int(m.group('DAY')), "hour", int(m.group('HR')), "minute", int(m.group('MIN')), "second", int(m.group('SEC')) - result = datetime.datetime(int(m.group('YEAR')), int(m.group('MON')), int(m.group('DAY')), int(m.group('HR')), int(m.group('MIN')), int(m.group('SEC'))) + if topline.find("UTC")!=-1: + pos1 = topline.find("-")+2 + pos2 = topline.find("UTC") + tmp=topline[pos1:pos2] + isUTC=True else: - raise FpdbError("invalid site in parseHandStartTime") + tmp=topline + #print "parsehandStartTime, tmp:", tmp + pos = tmp.find("-")+2 + tmp = tmp[pos:] + #Need to match either + # 2008/09/07 06:23:14 ET or + # 2008/08/17 - 01:14:43 (ET) or + # 2008/11/12 9:33:31 CET [2008/11/12 3:33:31 ET] + rexx = '(?P[0-9]{4})\/(?P[0-9]{2})\/(?P[0-9]{2})[\- ]+(?P
[0-9]+):(?P[0-9]+):(?P[0-9]+)' + m = re.search(rexx,tmp) + result = datetime.datetime(int(m.group('YEAR')), int(m.group('MON')), int(m.group('DAY')), int(m.group('HR')), int(m.group('MIN')), int(m.group('SEC'))) - if (site=="ftp" or site=="ps") and not isUTC: #these use US ET + if not isUTC: #these use US ET result+=datetime.timedelta(hours=5) return result @@ -1308,40 +1260,13 @@ def parseSiteHandNo(topline): def parseTableLine(site, base, line): """returns a dictionary with maxSeats and tableName""" - if site=="ps": - pos1=line.find('\'')+1 - pos2=line.find('\'', pos1) - #print "table:",line[pos1:pos2] - pos3=pos2+2 - pos4=line.find("-max") - #print "seats:",line[pos3:pos4] - return {'maxSeats':int(line[pos3:pos4]), 'tableName':line[pos1:pos2]} - elif site=="ftp": - pos1=line.find("Table ")+6 - pos2=line.find("-")-1 - if base=="hold": - maxSeats=9 - elif base=="stud": - maxSeats=8 - - if line.find("6 max")!=-1: - maxSeats=6 - elif line.find("4 max")!=-1: - maxSeats=4 - elif line.find("heads up")!=-1: - maxSeats=2 - - tableName = line[pos1:pos2] - for pattern in [' \(6 max\)', ' \(heads up\)', ' \(deep\)', - ' \(deep hu\)', ' \(deep 6\)', ' \(2\)', - ' \(edu\)', ' \(edu, 6 max\)', ' \(6\)', - ' \(speed\)', - ' no all-in', ' fast', ',', ' 50BB min', '\s+$']: - tableName = re.sub(pattern, '', tableName) - tableName = tableName.rstrip() - return {'maxSeats':maxSeats, 'tableName':tableName} - else: - raise FpdbError("invalid site ID") + pos1=line.find('\'')+1 + pos2=line.find('\'', pos1) + #print "table:",line[pos1:pos2] + pos3=pos2+2 + pos4=line.find("-max") + #print "seats:",line[pos3:pos4] + return {'maxSeats':int(line[pos3:pos4]), 'tableName':line[pos1:pos2]} #end def parseTableLine #returns the hand no assigned by the poker site @@ -1359,17 +1284,11 @@ def parseWinLine(line, site, names, winnings, isTourney): if (line.startswith(names[i].encode("latin-1"))): #found a winner if isTourney: pos1=line.rfind("collected ")+10 - if (site=="ftp"): - pos2=line.find(")", pos1) - elif (site=="ps"): - pos2=line.find(" ", pos1) + pos2=line.find(" ", pos1) winnings[i]+=int(line[pos1:pos2]) else: pos1=line.rfind("$")+1 - if (site=="ftp"): - pos2=line.find(")", pos1) - elif (site=="ps"): - pos2=line.find(" ", pos1) + pos2=line.find(" ", pos1) winnings[i]+=float2int(line[pos1:pos2]) #end def parseWinLine @@ -1413,10 +1332,8 @@ def recogniseGametypeID(backend, db, cursor, topline, smallBlindLine, site_id, c pos1=pos2+2 if isTourney: pos1-=1 - if (site_id==1): #ftp - pos2=topline.find(" ", pos1) - elif (site_id==2): #ps - pos2=topline.find(")") + #ps + pos2=topline.find(")") if pos2<=pos1: pos2=topline.find(")", pos1) @@ -1558,6 +1475,7 @@ def recognisePlayerNo(line, names, atype): #returns the site abbreviation for the given site def recogniseSite(line): + # TODO: Make site agnostic if (line.startswith("Full Tilt Poker")): return "ftp" elif (line.startswith("PokerStars")): From 14b58d6ad538dfb7e930e07b84176d12b1cb8d47 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 10 Mar 2009 21:36:52 +0900 Subject: [PATCH 003/104] [KILLFTP 3/x] Fix screwup from patch 1 --- pyfpdb/fpdb_import.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index fde69125..03de8554 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -354,7 +354,7 @@ class Importer: print "quitting due to reaching the amount of hands to be imported" print "Total stored:", stored, "duplicates:", duplicates, "errors:", errors, " time:", (time() - starttime) sys.exit(0) - startpos=endpos + startpos=endpos ttime = time() - starttime print "\rTotal stored:", stored, "duplicates:", duplicates, "errors:", errors, " time:", ttime From 161485e44e5886d21d5ea3e67ee673e4ce6f7bb6 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 10 Mar 2009 22:00:37 +0900 Subject: [PATCH 004/104] [KILLFTP 4/x] paper bag fix caused iun patch 1. This code needs replacing --- pyfpdb/fpdb_import.py | 98 +++++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 46 deletions(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 03de8554..c4c4e261 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -208,7 +208,7 @@ class Importer: #if os.path.isdir(file): #self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1]) - self.addToDirList = filter(lambda x: self.addImportDirectory(x, True, self.addToDirList[x][0], self.addToDirList[x][1]), self.addToDirList) + self.addToDirList = filter(lambda x: self.addImportDirectory(x, True, self.addToDirList[x][0], self.addToDirList[x][1]), self.addToDirList) for file in self.removeFromFileList: if file in self.filelist: @@ -302,58 +302,64 @@ class Importer: partial=0 #counter errors=0 #counter - for i in xrange (len(self.lines)): #main loop, iterates through the lines of a file and calls the appropriate parser method - if (len(self.lines[i])<2): + for i in xrange (len(self.lines)): + if (len(self.lines[i])<2): #Wierd way to detect for '\r\n' or '\n' endpos=i hand=self.lines[startpos:endpos] if (len(hand[0])<2): hand=hand[1:] + - isTourney=fpdb_simple.isTourney(hand[0]) - if not isTourney: - fpdb_simple.filterAnteBlindFold(site,hand) - hand=fpdb_simple.filterCrap(site, hand, isTourney) - self.hand=hand + if (len(hand)<3): + pass + #TODO: This is ugly - we didn't actually find the start of the + # hand with the outer loop so we test again... + else: + isTourney=fpdb_simple.isTourney(hand[0]) + if not isTourney: + fpdb_simple.filterAnteBlindFold(site,hand) + hand=fpdb_simple.filterCrap(site, hand, isTourney) + self.hand=hand + + try: + handsId=fpdb_parse_logic.mainParser(self.settings['db-backend'], self.fdb.db + ,self.fdb.cursor, site, category, hand) + self.fdb.db.commit() + + stored+=1 + if self.callHud: + #print "call to HUD here. handsId:",handsId + #pipe the Hands.id out to the HUD + self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep) + except fpdb_simple.DuplicateError: + duplicates+=1 + except (ValueError), fe: + errors+=1 + self.printEmailErrorMessage(errors, file, hand) + + if (self.settings['failOnError']): + self.fdb.db.commit() #dont remove this, in case hand processing was cancelled. + raise + except (fpdb_simple.FpdbError), fe: + errors+=1 + self.printEmailErrorMessage(errors, file, hand) + + self.fdb.db.rollback() + + if (self.settings['failOnError']): + self.fdb.db.commit() #dont remove this, in case hand processing was cancelled. + raise + if (self.settings['minPrint']!=0): + if ((stored+duplicates+errors)%self.settings['minPrint']==0): + print "stored:", stored, "duplicates:", duplicates, "errors:", errors - try: - handsId=fpdb_parse_logic.mainParser(self.settings['db-backend'], self.fdb.db - ,self.fdb.cursor, site, category, hand) - self.fdb.db.commit() - - stored+=1 - if self.callHud: - #print "call to HUD here. handsId:",handsId - #pipe the Hands.id out to the HUD - self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep) - except fpdb_simple.DuplicateError: - duplicates+=1 - except (ValueError), fe: - errors+=1 - self.printEmailErrorMessage(errors, file, hand) - - if (self.settings['failOnError']): - self.fdb.db.commit() #dont remove this, in case hand processing was cancelled. - raise - except (fpdb_simple.FpdbError), fe: - errors+=1 - self.printEmailErrorMessage(errors, file, hand) - - self.fdb.db.rollback() - - if (self.settings['failOnError']): - self.fdb.db.commit() #dont remove this, in case hand processing was cancelled. - raise - if (self.settings['minPrint']!=0): - if ((stored+duplicates+errors)%self.settings['minPrint']==0): - print "stored:", stored, "duplicates:", duplicates, "errors:", errors - - if (self.settings['handCount']!=0): - if ((stored+duplicates+errors)>=self.settings['handCount']): - if (not self.settings['quiet']): - print "quitting due to reaching the amount of hands to be imported" - print "Total stored:", stored, "duplicates:", duplicates, "errors:", errors, " time:", (time() - starttime) - sys.exit(0) + if (self.settings['handCount']!=0): + if ((stored+duplicates+errors)>=self.settings['handCount']): + if (not self.settings['quiet']): + print "quitting due to reaching the amount of hands to be imported" + print "Total stored:", stored, "duplicates:", duplicates, "errors:", errors, " time:", (time() - starttime) + sys.exit(0) startpos=endpos ttime = time() - starttime print "\rTotal stored:", stored, "duplicates:", duplicates, "errors:", errors, " time:", ttime From 264b18863339013ee65956a58c490650b05e7496 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 10 Mar 2009 23:03:02 +0900 Subject: [PATCH 005/104] [KILLFTP 5/x] Remove references to the named site "PokerStars" or "Full Tilt Poker" --- pyfpdb/fpdb_import.py | 8 ++--- pyfpdb/fpdb_parse_logic.py | 22 +++++++------- pyfpdb/fpdb_simple.py | 61 +++++++++++--------------------------- 3 files changed, 32 insertions(+), 59 deletions(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index c4c4e261..dde5ec6f 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -293,7 +293,7 @@ class Importer: # print "import_fpdb_file", file, site, self.lines, "\n" return (0,0,0,1,0) - site=fpdb_simple.recogniseSite(firstline) + # site=fpdb_simple.recogniseSite(firstline) category=fpdb_simple.recogniseCategory(firstline) startpos=0 @@ -318,13 +318,13 @@ class Importer: else: isTourney=fpdb_simple.isTourney(hand[0]) if not isTourney: - fpdb_simple.filterAnteBlindFold(site,hand) - hand=fpdb_simple.filterCrap(site, hand, isTourney) + fpdb_simple.filterAnteBlindFold(hand) + hand=fpdb_simple.filterCrap(hand, isTourney) self.hand=hand try: handsId=fpdb_parse_logic.mainParser(self.settings['db-backend'], self.fdb.db - ,self.fdb.cursor, site, category, hand) + ,self.fdb.cursor, category, hand) self.fdb.db.commit() stored+=1 diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py index c5076283..a1f2540f 100644 --- a/pyfpdb/fpdb_parse_logic.py +++ b/pyfpdb/fpdb_parse_logic.py @@ -21,7 +21,7 @@ import fpdb_simple import fpdb_save_to_db #parses a holdem hand -def mainParser(backend, db, cursor, site, category, hand): +def mainParser(backend, db, cursor, category, hand): category=fpdb_simple.recogniseCategory(hand[0]) if (category=="holdem" or category=="omahahi" or category=="omahahilo"): base="hold" @@ -35,8 +35,8 @@ def mainParser(backend, db, cursor, site, category, hand): #part 1: read hand no and check for duplicate siteHandNo=fpdb_simple.parseSiteHandNo(hand[0]) - handStartTime=fpdb_simple.parseHandStartTime(hand[0], site) - siteID=fpdb_simple.recogniseSiteID(cursor, site) + handStartTime=fpdb_simple.parseHandStartTime(hand[0]) + siteID=fpdb_simple.recogniseSiteID() #print "parse logic, siteID:",siteID,"site:",site isTourney=fpdb_simple.isTourney(hand[0]) @@ -51,8 +51,6 @@ def mainParser(backend, db, cursor, site, category, hand): #print "small blind line:",smallBlindLine gametypeID=fpdb_simple.recogniseGametypeID(backend, db, cursor, hand[0], hand[smallBlindLine], siteID, category, isTourney) if isTourney: - if site!="ps": - raise fpdb_simple.FpdbError("tourneys are only supported on PS right now") siteTourneyNo=fpdb_simple.parseTourneyNo(hand[0]) buyin=fpdb_simple.parseBuyin(hand[0]) fee=fpdb_simple.parseFee(hand[0]) @@ -75,7 +73,7 @@ def mainParser(backend, db, cursor, site, category, hand): seatLines.append(hand[i]) names=fpdb_simple.parseNames(seatLines) playerIDs = fpdb_simple.recognisePlayerIDs(cursor, names, siteID) - tmp=fpdb_simple.parseCashesAndSeatNos(seatLines, site) + tmp=fpdb_simple.parseCashesAndSeatNos(seatLines) startCashes=tmp['startCashes'] seatNos=tmp['seatNos'] @@ -88,15 +86,15 @@ def mainParser(backend, db, cursor, site, category, hand): #part 4: take appropriate action for each line based on linetype for i in range(len(hand)): if (lineTypes[i]=="cards"): - fpdb_simple.parseCardLine (site, category, lineStreets[i], hand[i], names, cardValues, cardSuits, boardValues, boardSuits) + fpdb_simple.parseCardLine (category, lineStreets[i], hand[i], names, cardValues, cardSuits, boardValues, boardSuits) #if category=="studhilo": # print "hand[i]:", hand[i] # print "cardValues:", cardValues # print "cardSuits:", cardSuits elif (lineTypes[i]=="action"): - fpdb_simple.parseActionLine (site, base, isTourney, hand[i], lineStreets[i], playerIDs, names, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo) + fpdb_simple.parseActionLine (base, isTourney, hand[i], lineStreets[i], playerIDs, names, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo) elif (lineTypes[i]=="win"): - fpdb_simple.parseWinLine (hand[i], site, names, winnings, isTourney) + fpdb_simple.parseWinLine (hand[i], names, winnings, isTourney) elif (lineTypes[i]=="rake"): if isTourney: totalRake=0 @@ -106,9 +104,9 @@ def mainParser(backend, db, cursor, site, category, hand): elif (lineTypes[i]=="header" or lineTypes[i]=="rake" or lineTypes[i]=="name" or lineTypes[i]=="ignore"): pass elif (lineTypes[i]=="ante"): - fpdb_simple.parseAnteLine(hand[i], site, isTourney, names, antes) + fpdb_simple.parseAnteLine(hand[i], isTourney, names, antes) elif (lineTypes[i]=="table"): - tableResult=fpdb_simple.parseTableLine(site, base, hand[i]) + tableResult=fpdb_simple.parseTableLine(base, hand[i]) else: raise fpdb_simple.FpdbError("unrecognised lineType:"+lineTypes[i]) maxSeats=tableResult['maxSeats'] @@ -125,7 +123,7 @@ def mainParser(backend, db, cursor, site, category, hand): cursor.execute("SELECT limitType FROM Gametypes WHERE id=%s",(gametypeID, )) limit_type=cursor.fetchone()[0] - fpdb_simple.convert3B4B(site, category, limit_type, actionTypes, actionAmounts) + fpdb_simple.convert3B4B(category, limit_type, actionTypes, actionAmounts) totalWinnings=0 for i in range(len(winnings)): diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index d3bb4097..cad7e046 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -458,7 +458,7 @@ def classifyLines(hand, category, lineTypes, lineStreets): lineStreets.append(currentStreet) #end def classifyLines -def convert3B4B(site, category, limit_type, actionTypes, actionAmounts): +def convert3B4B(category, limit_type, actionTypes, actionAmounts): """calculates the actual bet amounts in the given amount array and changes it accordingly.""" for i in range (len(actionTypes)): for j in range (len(actionTypes[i])): @@ -474,7 +474,7 @@ def convert3B4B(site, category, limit_type, actionTypes, actionAmounts): elif (len(bets)>2): fail=True #todo: run correction for below - if (site=="ps" and category=="holdem" and limit_type=="nl" and len(bets)==3): + if (limit_type=="nl" or limit_type == "pl"): fail=False if fail: @@ -611,7 +611,7 @@ def fillCardArrays(player_count, base, category, card_values, card_suits): #filters out a player that folded before paying ante or blinds. This should be called #before calling the actual hand parser. manipulates hand, no return. -def filterAnteBlindFold(site,hand): +def filterAnteBlindFold(hand): #todo: this'll only get rid of one ante folder, not multiple ones #todo: in tourneys this should not be removed but #print "start of filterAnteBlindFold" @@ -649,7 +649,7 @@ def filterAnteBlindFold(site,hand): #end def filterAnteFold #removes useless lines as well as trailing spaces -def filterCrap(site, hand, isTourney): +def filterCrap(hand, isTourney): #remove two trailing spaces at end of line for i in range (len(hand)): if (hand[i][-1]==' '): @@ -714,12 +714,8 @@ def filterCrap(site, hand, isTourney): toRemove.append(hand[i]) elif (hand[i].find("joins the table at seat ")!=-1): toRemove.append(hand[i]) - elif (hand[i].endswith(" sits down")): - toRemove.append(hand[i]) elif (hand[i].endswith("leaves the table")): toRemove.append(hand[i]) - elif (hand[i].endswith(" stands up")): - toRemove.append(hand[i]) elif (hand[i].find("is high with ")!=-1): toRemove.append(hand[i]) elif (hand[i].endswith("doesn't show hand")): @@ -862,7 +858,7 @@ def isWinLine(line): #end def isWinLine #returns the amount of cash/chips put into the put in the given action line -def parseActionAmount(line, atype, site, isTourney): +def parseActionAmount(line, atype, isTourney): #if (line.endswith(" and is all-in")): # line=line[:-14] #elif (line.endswith(", and is all in")): @@ -878,14 +874,14 @@ def parseActionAmount(line, atype, site, isTourney): amount=0 elif (atype=="check"): amount=0 - elif (atype=="unbet" and site=="ps"): + elif (atype=="unbet"): #print "ps unbet, line:",line pos1=line.find("$")+1 if pos1==0: pos1=line.find("(")+1 pos2=line.find(")") amount=float2int(line[pos1:pos2]) - elif (atype=="bet" and site=="ps" and line.find(": raises $")!=-1 and line.find("to $")!=-1): + elif (atype=="bet" and line.find(": raises $")!=-1 and line.find("to $")!=-1): pos=line.find("to $")+4 amount=float2int(line[pos:]) else: @@ -908,7 +904,7 @@ def parseActionAmount(line, atype, site, isTourney): #doesnt return anything, simply changes the passed arrays action_types and # action_amounts. For stud this expects numeric streets (3-7), for # holdem/omaha it expects predeal, preflop, flop, turn or river -def parseActionLine(site, base, isTourney, line, street, playerIDs, names, action_types, allIns, action_amounts, actionNos, actionTypeByNo): +def parseActionLine(base, isTourney, line, street, playerIDs, names, action_types, allIns, action_amounts, actionNos, actionTypeByNo): if (street=="predeal" or street=="preflop"): street=0 elif (street=="flop"): @@ -927,7 +923,7 @@ def parseActionLine(site, base, isTourney, line, street, playerIDs, names, actio line, allIn=goesAllInOnThisLine(line) atype=parseActionType(line) playerno=recognisePlayerNo(line, names, atype) - amount=parseActionAmount(line, atype, site, isTourney) + amount=parseActionAmount(line, atype, isTourney) action_types[street][playerno].append(atype) allIns[street][playerno].append(allIn) @@ -988,7 +984,7 @@ def parseActionType(line): #end def parseActionType #parses the ante out of the given line and checks which player paid it, updates antes accordingly. -def parseAnteLine(line, site, isTourney, names, antes): +def parseAnteLine(line, isTourney, names, antes): for i in range(len(names)): if (line.startswith(names[i].encode("latin-1"))): #found the ante'er pos=line.rfind("$")+1 @@ -1014,7 +1010,7 @@ def parseBuyin(topline): #parses a card line and changes the passed arrays accordingly #todo: reorganise this messy method -def parseCardLine(site, category, street, line, names, cardValues, cardSuits, boardValues, boardSuits): +def parseCardLine(category, street, line, names, cardValues, cardSuits, boardValues, boardSuits): if (line.startswith("Dealt to ") or line.find(" shows [")!=-1 or line.find("mucked [")!=-1): playerNo=recognisePlayerNo(line, names, "card") #anything but unbet will be ok for that string @@ -1088,7 +1084,7 @@ def parseCardLine(site, category, street, line, names, cardValues, cardSuits, bo raise FpdbError ("unrecognised line:"+line) #end def parseCardLine -def parseCashesAndSeatNos(lines, site): +def parseCashesAndSeatNos(lines): """parses the startCashes and seatNos of each player out of the given lines and returns them as a dictionary of two arrays""" cashes = [] seatNos = [] @@ -1099,8 +1095,7 @@ def parseCashesAndSeatNos(lines, site): pos1=lines[i].rfind("($")+2 if pos1==1: #for tourneys - it's 1 instead of -1 due to adding 2 above pos1=lines[i].rfind("(")+1 - elif (site=="ps"): - pos2=lines[i].find(" in chips") + pos2=lines[i].find(" in chips") cashes.append(float2int(lines[i][pos1:pos2])) return {'startCashes':cashes, 'seatNos':seatNos} #end def parseCashesAndSeatNos @@ -1114,7 +1109,7 @@ def parseFee(topline): #end def parsefee #returns a datetime object with the starttime indicated in the given topline -def parseHandStartTime(topline, site): +def parseHandStartTime(topline): #convert x:13:35 to 0x:13:35 counter=0 while (True): @@ -1258,7 +1253,7 @@ def parseSiteHandNo(topline): return topline[pos1:pos2] #end def parseSiteHandNo -def parseTableLine(site, base, line): +def parseTableLine(base, line): """returns a dictionary with maxSeats and tableName""" pos1=line.find('\'')+1 pos2=line.find('\'', pos1) @@ -1278,7 +1273,7 @@ def parseTourneyNo(topline): #end def parseTourneyNo #parses a win/collect line. manipulates the passed array winnings, no explicit return -def parseWinLine(line, site, names, winnings, isTourney): +def parseWinLine(line, names, winnings, isTourney): #print "parseWinLine: line:",line for i in range(len(names)): if (line.startswith(names[i].encode("latin-1"))): #found a winner @@ -1473,28 +1468,8 @@ def recognisePlayerNo(line, names, atype): raise FpdbError ("failed to recognise player in: "+line+" atype:"+atype) #end def recognisePlayerNo -#returns the site abbreviation for the given site -def recogniseSite(line): - # TODO: Make site agnostic - if (line.startswith("Full Tilt Poker")): - return "ftp" - elif (line.startswith("PokerStars")): - return "ps" - else: - raise FpdbError("failed to recognise site, line:"+line) -#end def recogniseSite - -#returns the ID of the given site -def recogniseSiteID(cursor, site): - if (site=="ftp"): - return 1 - #cursor.execute("SELECT id FROM Sites WHERE name = ('Full Tilt Poker')") - elif (site=="ps"): - return 2 - #cursor.execute("SELECT id FROM Sites WHERE name = ('PokerStars')") - else: - raise FpdbError("invalid site in recogniseSiteID: "+site) - return cursor.fetchall()[0][0] +def recogniseSiteID(): + return 2 #end def recogniseSiteID #removes trailing \n from the given array From ae4704b8dc003a035ab38c44e6bbec6a480c9b58 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 21 Mar 2009 21:23:51 +0900 Subject: [PATCH 006/104] First working(?) version of siteneutral import --- pyfpdb/FpdbSQLQueries.py | 4 ++-- pyfpdb/fpdb_import.py | 24 ++++++++++++++++++------ pyfpdb/fpdb_parse_logic.py | 4 +--- pyfpdb/fpdb_save_to_db.py | 11 +++++++---- pyfpdb/fpdb_simple.py | 8 ++------ 5 files changed, 30 insertions(+), 21 deletions(-) diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index c3260466..55bf8c2e 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 """ diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index e6baea29..fc878746 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -58,13 +58,14 @@ class Importer: self.cursor = None self.filelist = {} self.dirlist = {} + self.siteIds = {} self.addToDirList = {} self.removeFromFileList = {} # to remove deleted files self.monitor = False - self.updated = {} #Time last import was run {file:mtime} + self.updated = {} #Time last import was run {file:mtime} self.lines = None - self.faobs = None #File as one big string - self.pos_in_file = {} # dict to remember how far we have read in the file + self.faobs = None # File as one big string + self.pos_in_file = {} # dict to remember how far we have read in the file #Set defaults self.callHud = self.config.get_import_parameters().get("callFpdbHud") if 'minPrint' not in self.settings: @@ -111,6 +112,18 @@ class Importer: def addImportFile(self, filename, site = "default", filter = "passthrough"): #TODO: test it is a valid file -> put that in config!! self.filelist[filename] = [site] + [filter] + if site not in self.siteIds: + # Get id from Sites table in DB + self.fdb.cursor.execute(self.fdb.sql.query['getSiteId'], (site,)) + result = self.fdb.cursor.fetchall() + if len(result) == 1: + self.siteIds[site] = result[0][0] + else: + if len(result) == 0: + print "[ERROR] Database ID for %s not found" % site + else: + print "[ERROR] More than 1 Database ID found for %s - Multiple currencies not implemented yet" % site + # Called from GuiBulkImport to add a file or directory. def addBulkImportImportFileOrDir(self, inputPath,filter = "passthrough"): @@ -289,9 +302,8 @@ class Importer: print "TODO: implement importing tournament summaries" #self.faobs = readfile(inputFile) #self.parseTourneyHistory() - return 0 + return (0,0,0,1,0) - site=fpdb_simple.recogniseSite(firstline) category=fpdb_simple.recogniseCategory(firstline) startpos=0 @@ -322,7 +334,7 @@ class Importer: try: handsId=fpdb_parse_logic.mainParser(self.settings['db-backend'], self.fdb.db - ,self.fdb.cursor, site, category, hand, self.config) + ,self.fdb.cursor, self.siteIds[site], category, hand, self.config) self.fdb.db.commit() stored+=1 diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py index dd5d84ea..58cc94df 100644 --- a/pyfpdb/fpdb_parse_logic.py +++ b/pyfpdb/fpdb_parse_logic.py @@ -21,7 +21,7 @@ import fpdb_simple import fpdb_save_to_db #parses a holdem hand -def mainParser(backend, db, cursor, category, hand, config): +def mainParser(backend, db, cursor, siteID, category, hand, config): category = fpdb_simple.recogniseCategory(hand[0]) base = "hold" if category == "holdem" or category == "omahahi" or category == "omahahilo" else "stud" @@ -35,8 +35,6 @@ def mainParser(backend, db, cursor, category, hand, config): #part 1: read hand no and check for duplicate siteHandNo = fpdb_simple.parseSiteHandNo(hand[0]) handStartTime = fpdb_simple.parseHandStartTime(hand[0]) - siteID = fpdb_simple.recogniseSiteID() - #print "parse logic, siteID:",siteID,"site:",site isTourney = fpdb_simple.isTourney(hand[0]) smallBlindLine = 0 diff --git a/pyfpdb/fpdb_save_to_db.py b/pyfpdb/fpdb_save_to_db.py index f13c8032..85468c2b 100644 --- a/pyfpdb/fpdb_save_to_db.py +++ b/pyfpdb/fpdb_save_to_db.py @@ -28,11 +28,12 @@ SQLITE = 4 fastStoreHudCache = True # set this to True to test the new storeHudCache routine -saveActions = False # set this to False to avoid storing action data +saveActions = True # set this to False to avoid storing action data # Pros: speeds up imports # Cons: no action data is saved, so you need to keep the hand histories # variance not available on stats page - + # : No graphs + #stores a stud/razz hand into the database def ring_stud(config, backend, db, cursor, base, category, site_hand_no, gametype_id, hand_start_time ,names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes @@ -41,7 +42,7 @@ def ring_stud(config, backend, db, cursor, base, category, site_hand_no, gametyp import_options = config.get_import_parameters() - saveActions = True if import_options['saveActions'] == 'True' else False + saveActions = False if import_options['saveActions'] == 'False' else True fastStoreHudCache = True if import_options['fastStoreHudCache'] == 'True' else False fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) @@ -69,9 +70,11 @@ def ring_holdem_omaha(config, backend, db, cursor, base, category, site_hand_no, """stores a holdem/omaha hand into the database""" import_options = config.get_import_parameters() - saveActions = True if import_options['saveActions'] == 'True' else False + saveActions = False if import_options['saveActions'] == 'False' else True fastStoreHudCache = True if import_options['fastStoreHudCache'] == 'True' else False + #print "DEBUG: saveActions: %s fastStoreHudCache: %s" %(saveActions, fastStoreHudCache) + t0 = time() fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) t1 = time() diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index b6e7e237..5a75af45 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -691,14 +691,13 @@ def filterCrap(hand, isTourney): hand[i] = False elif (hand[i]=="Betting is capped"): hand[i] = False - #site specific variable position filter elif (hand[i].find(" said, \"")!=-1): hand[i] = False + if isTourney: if (hand[i].endswith(" is sitting out") and (not hand[i].startswith("Seat "))): hand[i] = False - elif: - if (hand[i].endswith(": sits out")): + elif (hand[i].endswith(": sits out")): hand[i] = False elif (hand[i].endswith(" is sitting out")): hand[i] = False @@ -1375,9 +1374,6 @@ def recognisePlayerNo(line, names, atype): raise FpdbError ("failed to recognise player in: "+line+" atype:"+atype) #end def recognisePlayerNo -def recogniseSiteID(): - return 2 -#end def recogniseSiteID #removes trailing \n from the given array def removeTrailingEOL(arr): From 497354d4f46becc19a861d8559f7e7ced735c293 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 24 Mar 2009 22:58:45 +0900 Subject: [PATCH 007/104] Make BulkImport work only with HHCs Added new section to config for converters for ease of creating the gui. Removed the section in the site line for filter and supported games --- pyfpdb/Configuration.py | 20 ++++++++++++++++++++ pyfpdb/GuiBulkImport.py | 16 +++++++--------- pyfpdb/HUD_config.xml.example | 11 ++++++++--- pyfpdb/fpdb_import.py | 8 ++++---- pyfpdb/fpdb_parse_logic.py | 2 +- 5 files changed, 40 insertions(+), 17 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 19e62038..3e0ca3dd 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -194,6 +194,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") @@ -273,6 +282,7 @@ class Config: self.supported_games = {} self.supported_databases = {} self.aux_windows = {} + self.hhcs = {} self.popup_windows = {} # s_sites = doc.getElementsByTagName("supported_sites") @@ -295,6 +305,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) @@ -696,6 +711,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/GuiBulkImport.py b/pyfpdb/GuiBulkImport.py index 1a62a37d..35563fe3 100755 --- a/pyfpdb/GuiBulkImport.py +++ b/pyfpdb/GuiBulkImport.py @@ -66,10 +66,10 @@ class GuiBulkImport(): self.importer.setDropIndexes(cb_model[cb_index][0]) else: self.importer.setDropIndexes("auto") - hhc=self.cbfilter.get_model()[self.cbfilter.get_active()][0] + sitename = self.cbfilter.get_model()[self.cbfilter.get_active()][0] self.lab_info.set_text("Importing") - self.importer.addBulkImportImportFileOrDir(self.inputFile,filter=hhc) + self.importer.addBulkImportImportFileOrDir(self.inputFile, site = sitename) self.importer.setCallHud(False) starttime = time() (stored, dups, partial, errs, ttime) = self.importer.runImport() @@ -175,11 +175,9 @@ class GuiBulkImport(): # ComboBox - filter self.cbfilter = gtk.combo_box_new_text() - self.cbfilter.append_text("passthrough") - self.cbfilter.append_text("BetfairToFpdb") - self.cbfilter.append_text("EverleafToFpdb") - self.cbfilter.append_text("FulltiltToFpdb") - self.cbfilter.append_text("PokerStarsToFpdb") + for w in self.config.hhcs: + print w + self.cbfilter.append_text(w) self.cbfilter.set_active(0) self.table.attach(self.cbfilter, 3, 4, 2, 3, xpadding = 10, ypadding = 0, yoptions=gtk.SHRINK) self.cbfilter.show() @@ -223,7 +221,7 @@ def main(argv=None): parser.add_option("-q", "--quiet", action="store_false", dest="gui", default=True, help="don't start gui; deprecated (just give a filename with -f).") parser.add_option("-c", "--convert", dest="filtername", default="passthrough", metavar="FILTER", - help="Conversion filter (*passthrough, FullTiltToFpdb, PokerStarsToFpdb, EverleafToFpdb)") + help="Conversion filter (*Full Tilt Poker, PokerStars, Everleaf)") parser.add_option("-x", "--failOnError", action="store_true", default=False, help="If this option is passed it quits when it encounters any error") parser.add_option("-m", "--minPrint", "--status", dest="minPrint", default="0", type="int", @@ -258,7 +256,7 @@ def main(argv=None): importer = fpdb_import.Importer(False,settings, config) importer.setDropIndexes("auto") importer.setFailOnError(options.failOnError) - importer.addBulkImportImportFileOrDir(os.path.expanduser(options.filename), filter=options.filtername) + importer.addBulkImportImportFileOrDir(os.path.expanduser(options.filename), site=options.filtername) importer.setCallHud(False) importer.runImport() importer.clearFileList() diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index f7351526..ad7d440b 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -2,7 +2,7 @@ - + @@ -49,7 +49,7 @@ - + @@ -84,7 +84,7 @@ - + @@ -198,6 +198,11 @@ + + + + + diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 5ce23928..68373fb0 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -126,18 +126,18 @@ class Importer: # Called from GuiBulkImport to add a file or directory. - def addBulkImportImportFileOrDir(self, inputPath,filter = "passthrough"): + def addBulkImportImportFileOrDir(self, inputPath, site = "PokerStars"): """Add a file or directory for bulk import""" - + filter = self.config.hhcs[site].converter # Bulk import never monitors # if directory, add all files in it. Otherwise add single file. # TODO: only add sane files? if os.path.isdir(inputPath): for subdir in os.walk(inputPath): for file in subdir[2]: - self.addImportFile(os.path.join(inputPath, subdir[0], file), site="default", filter=filter) + self.addImportFile(os.path.join(inputPath, subdir[0], file), site=site, filter=filter) else: - self.addImportFile(inputPath, site="default", filter=filter) + self.addImportFile(inputPath, site=site, filter=filter) #Add a directory of files to filelist #Only one import directory per site supported. #dirlist is a hash of lists: diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py index 0badbb82..750b1512 100644 --- a/pyfpdb/fpdb_parse_logic.py +++ b/pyfpdb/fpdb_parse_logic.py @@ -60,7 +60,7 @@ def mainParser(backend, db, cursor, siteID, category, hand, config): fpdb_simple.isAlreadyInDB(cursor, gametypeID, siteHandNo) - hand=fpdb_simple.filterCrap(site, hand, isTourney) + hand=fpdb_simple.filterCrap(hand, isTourney) #part 2: classify lines by type (e.g. cards, action, win, sectionchange) and street fpdb_simple.classifyLines(hand, category, lineTypes, lineStreets) From 20dd3e1aec8295369f4f2af671807b9608a1f6d7 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 25 Mar 2009 18:35:19 +0900 Subject: [PATCH 008/104] Make CET timezones work with Stars hands --- pyfpdb/PokerStarsToFpdb.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 8b905005..f521bbd0 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -128,9 +128,11 @@ follow : whether to tail -f the input""" logging.debug("readHandInfo: %s" % info) for key in info: if key == 'DATETIME': - datetime = info[key].replace(" - "," ") # some are like "2009/02/26 - 15:22:55 ET" - datetime = datetime.replace(" (ET)","") # kludge for now. - datetime = datetime.replace(" ET","") # kludge for now. + #2008/11/12 10:00:48 CET [2008/11/12 4:00:48 ET] + #2008/08/17 - 01:14:43 (ET) + #2008/09/07 06:23:14 ET + m2 = re.search("(?P[0-9]{4})\/(?P[0-9]{2})\/(?P[0-9]{2})[\- ]+(?P[0-9]+):(?P[0-9]+):(?P[0-9]+)", info[key]) + datetime = "%s/%s/%s %s:%s:%s" % (m2.group('Y'), m2.group('M'),m2.group('D'),m2.group('H'),m2.group('MIN'),m2.group('S')) hand.starttime = time.strptime(datetime, "%Y/%m/%d %H:%M:%S") if key == 'HID': hand.handid = info[key] From 710893b186edf4fba36ea1c3749daa38ed37eb48 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 28 Mar 2009 00:54:30 +0900 Subject: [PATCH 009/104] Fix merge breakage --- pyfpdb/fpdb_import.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 17bf04f1..1e5049d0 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -338,7 +338,7 @@ class Importer: try: handsId = fpdb_parse_logic.mainParser(self.settings['db-backend'], self.fdb.db - ,self.fdb.cursor, site, category, hand, self.config) + ,self.fdb.cursor, self.siteIds[site], category, hand, self.config) self.fdb.db.commit() stored += 1 From f6ca8c1bc10fce6eb61206ecbbb708eee278f910 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 28 Mar 2009 19:38:37 +0900 Subject: [PATCH 010/104] GuiBulkImport cli breakage fix --- pyfpdb/GuiBulkImport.py | 2 +- pyfpdb/fpdb_import.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/GuiBulkImport.py b/pyfpdb/GuiBulkImport.py index 35563fe3..e90be69a 100755 --- a/pyfpdb/GuiBulkImport.py +++ b/pyfpdb/GuiBulkImport.py @@ -236,7 +236,7 @@ def main(argv=None): if os.name == 'nt': settings['os'] = 'windows' else: settings['os'] = 'linuxmac' - settings.update(config.get_db_parameters('fpdb')) + settings.update(config.get_db_parameters()) settings.update(config.get_tv_parameters()) settings.update(config.get_import_parameters()) settings.update(config.get_default_paths()) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 1e5049d0..2b421e19 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -21,7 +21,7 @@ import os # todo: remove this once import_dir is in fpdb_import import sys -from time import time +from time import time, strftime import traceback import math import datetime From 95add137311ac0f173fb90d64fe62b4a43ed91ce Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 28 Mar 2009 19:39:13 +0900 Subject: [PATCH 011/104] No passthough converter in siteneutral --- pyfpdb/GuiBulkImport.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/GuiBulkImport.py b/pyfpdb/GuiBulkImport.py index e90be69a..7dbb9858 100755 --- a/pyfpdb/GuiBulkImport.py +++ b/pyfpdb/GuiBulkImport.py @@ -220,7 +220,7 @@ def main(argv=None): help="Input file in quiet mode") parser.add_option("-q", "--quiet", action="store_false", dest="gui", default=True, help="don't start gui; deprecated (just give a filename with -f).") - parser.add_option("-c", "--convert", dest="filtername", default="passthrough", metavar="FILTER", + parser.add_option("-c", "--convert", dest="filtername", default="PokerStars", metavar="FILTER", help="Conversion filter (*Full Tilt Poker, PokerStars, Everleaf)") parser.add_option("-x", "--failOnError", action="store_true", default=False, help="If this option is passed it quits when it encounters any error") From bdd615ede9ec20a6ccac58eb48ed806e0b305f2f Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 28 Mar 2009 20:32:30 +0900 Subject: [PATCH 012/104] utf8 fix to db connection Change mysql connection type to use_unicode. --- pyfpdb/fpdb_db.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 771b79fa..eba87f52 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -59,7 +59,7 @@ class fpdb_db: self.database=database if backend==self.MYSQL_INNODB: import MySQLdb - self.db=MySQLdb.connect(host = host, user = user, passwd = password, db = database) + self.db=MySQLdb.connect(host = host, user = user, passwd = password, db = database, use_unicode=True) elif backend==self.PGSQL: import psycopg2 # If DB connection is made over TCP, then the variables From 683190a2616942877eae94c03c62c908bf43d39d Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 6 Apr 2009 10:34:14 -0400 Subject: [PATCH 013/104] Updated example config to work with recent code changes. --- pyfpdb/HUD_config.xml.example | 117 +++++++++++++++++++++++++++++----- 1 file changed, 102 insertions(+), 15 deletions(-) diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index e300e67b..96a1931d 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -1,8 +1,25 @@ + + + - + + @@ -49,7 +66,21 @@ - + + @@ -84,7 +115,16 @@ - + + @@ -120,8 +160,10 @@ + - + + @@ -129,7 +171,8 @@ - + + @@ -137,7 +180,8 @@ - + + @@ -145,7 +189,8 @@ - + + @@ -153,7 +198,8 @@ - + + @@ -161,7 +207,8 @@ - + + @@ -170,6 +217,7 @@ + @@ -196,15 +244,54 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + From cd2b2aaf42057bfba781568d95b636d10cd9df45 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 6 Apr 2009 11:03:51 -0400 Subject: [PATCH 014/104] Comment out some intermediate print. --- pyfpdb/Hud.py | 6 +++--- pyfpdb/Mucked.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 15145095..3646c6c9 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -204,14 +204,14 @@ class Hud: def reposition_windows(self, *args): for w in self.stat_windows.itervalues(): if type(w) == int: - print "in reposition, w =", w +# print "in reposition, w =", w continue - print "in reposition, w =", w, w.x, w.y +# print "in reposition, w =", w, w.x, w.y w.window.move(w.x, w.y) return True def debug_stat_windows(self, *args): - print self.table, "\n", self.main_window.window.get_transient_for() +# print self.table, "\n", self.main_window.window.get_transient_for() for w in self.stat_windows: print self.stat_windows[w].window.window.get_transient_for() diff --git a/pyfpdb/Mucked.py b/pyfpdb/Mucked.py index 9d70f8e3..93f6d102 100755 --- a/pyfpdb/Mucked.py +++ b/pyfpdb/Mucked.py @@ -451,7 +451,7 @@ class Flop_Mucked(Aux_Window): def save_layout(self, *args): """Save new layout back to the aux element in the config file.""" new_locs = {} - print "adj =", self.adj +# print "adj =", self.adj for (i, pos) in self.positions.iteritems(): if i != 'common': new_locs[self.adj[int(i)]] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y) From 87efd2cc8d57d89074b6f4d6e9cc42e8dcf430b6 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 6 Apr 2009 23:40:06 -0400 Subject: [PATCH 015/104] Minor edits in HUD_config.xml.example. --- pyfpdb/HUD_config.xml.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index 96a1931d..e21f342a 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -69,10 +69,10 @@ Date: Mon, 6 Apr 2009 23:42:36 -0400 Subject: [PATCH 016/104] Fix regression in naming HUDs that caused inconsistent killing. --- pyfpdb/HUD_main.py | 3 +-- pyfpdb/Hud.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index 332e33c8..39d190a8 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -108,9 +108,9 @@ class HUD_main(object): gtk.gdk.threads_leave() self.hud_dict[table_name] = Hud.Hud(self, table, max, poker_game, self.config, self.db_connection) + self.hud_dict[table_name].table_name = table_name self.hud_dict[table_name].stat_dict = stat_dict self.hud_dict[table_name].cards = cards - [aw.update_data(new_hand_id, self.db_connection) for aw in self.hud_dict[table_name].aux_windows] gobject.idle_add(idle_func) @@ -184,7 +184,6 @@ class HUD_main(object): tablewindow = Tables.discover_tournament_table(self.config, tour_number, tab_number) else: tablewindow = Tables.discover_table_by_name(self.config, table_name) - if tablewindow == None: # If no client window is found on the screen, complain and continue if is_tournament: diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 3646c6c9..363175a1 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -125,7 +125,7 @@ class Hud: self.menu = gtk.Menu() self.item1 = gtk.MenuItem('Kill this HUD') self.menu.append(self.item1) - self.item1.connect("activate", self.parent.kill_hud, self.table.name) + self.item1.connect("activate", self.parent.kill_hud, self.table_name) self.item1.show() self.item2 = gtk.MenuItem('Save Layout') From a2862c9712ddbd1d84b4541608841952790e4950 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 6 Apr 2009 23:45:56 -0400 Subject: [PATCH 017/104] Minor change to allow proper detection of FTP tables. --- pyfpdb/Tables.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Tables.py b/pyfpdb/Tables.py index ffc50b01..58da2690 100755 --- a/pyfpdb/Tables.py +++ b/pyfpdb/Tables.py @@ -135,7 +135,7 @@ def discover_posix(c): if re.search(params['table_finder'], listing): if 'Lobby' in listing: continue if 'Instant Hand History' in listing: continue - if '\"Full Tilt Poker\"' in listing: continue +# if '\"Full Tilt Poker\"' in listing: continue if 'History for table:' in listing: continue if 'has no name' in listing: continue info = decode_xwininfo(c, listing) @@ -387,7 +387,7 @@ def discover_mac_by_name(c, tablename): if __name__=="__main__": c = Configuration.Config() - print discover_table_by_name(c, "Ringe") + print discover_table_by_name(c, "Torino") # print discover_tournament_table(c, "118942908", "3") tables = discover(c) From 460102c3f512259db3c81eee412ca5f451147b33 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 7 Apr 2009 10:44:06 -0400 Subject: [PATCH 018/104] Version 0.11 --- pyfpdb/fpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 0f0f3bf3..49b3ad82 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -47,7 +47,7 @@ import GuiGraphViewer import FpdbSQLQueries import Configuration -VERSION = "0.10" +VERSION = "0.11" class fpdb: def tab_clicked(self, widget, tab_name): From fdabe29ea23659258f7ad091478e6b92eeb3ceb9 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 8 Apr 2009 16:43:40 -0400 Subject: [PATCH 019/104] Fix stats aggregation and simplify HUD_main.py. --- pyfpdb/HUD_main.py | 32 ++++++++++++++++++-------------- pyfpdb/SQL.py | 2 +- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index 39d190a8..4501821a 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -51,6 +51,8 @@ import Database import Tables import Hud +aggregate_stats = {"ring": False, "tour": False} # config file! + class HUD_main(object): """A main() object to own both the read_stdin thread and the gui.""" # This class mainly provides state for controlling the multiple HUDs. @@ -85,7 +87,7 @@ class HUD_main(object): del(self.hud_dict[table]) self.main_window.resize(1,1) - def create_HUD(self, new_hand_id, table, table_name, max, poker_game, is_tournament, stat_dict, cards): + def create_HUD(self, new_hand_id, table, table_name, max, poker_game, stat_dict, cards): def idle_func(): @@ -149,8 +151,8 @@ 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) = self.db_connection.get_table_name(new_hand_id) - stat_dict = self.db_connection.get_stats_from_hand(new_hand_id) + (table_name, max, poker_game, type) = self.db_connection.get_table_name(new_hand_id) + stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, aggregate = aggregate_stats[type]) cards = self.db_connection.get_cards(new_hand_id) comm_cards = self.db_connection.get_common_cards(new_hand_id) if comm_cards != {}: # stud! @@ -160,15 +162,17 @@ class HUD_main(object): sys.stderr.write("Database error %s in hand %d. Skipping.\n" % (err, int(new_hand_id))) continue -# find out if this hand is from a tournament - mat_obj = tourny_finder.search(table_name) - if mat_obj: - is_tournament = True - (tour_number, tab_number) = mat_obj.group(1, 2) - temp_key = tour_number + if type == "tour": # hand is from a tournament + mat_obj = tourny_finder.search(table_name) + if mat_obj: + (tour_number, tab_number) = mat_obj.group(1, 2) + temp_key = tour_number + else: # tourney, but can't get number and table + print "could not find tournamtne: skipping " + sys.stderr.write("Could not find tournament %d in hand %d. Skipping.\n" % (int(tour_number), int(new_hand_id))) + continue + else: - is_tournament = False - (tour_number, tab_number) = (0, 0) temp_key = table_name # Update an existing HUD @@ -180,17 +184,17 @@ class HUD_main(object): # Or create a new HUD else: - if is_tournament: + if type == "tour": tablewindow = Tables.discover_tournament_table(self.config, tour_number, tab_number) else: tablewindow = Tables.discover_table_by_name(self.config, table_name) if tablewindow == None: # If no client window is found on the screen, complain and continue - if is_tournament: + if type == "tour": table_name = "%s %s" % (tour_number, tab_number) sys.stderr.write("table name "+table_name+" not found, skipping.\n") else: - self.create_HUD(new_hand_id, tablewindow, temp_key, max, poker_game, is_tournament, stat_dict, cards) + self.create_HUD(new_hand_id, tablewindow, temp_key, max, poker_game, stat_dict, cards) if __name__== "__main__": sys.stderr.write("HUD_main starting\n") diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 2c67cb0a..c9314305 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -331,7 +331,7 @@ class Sql: """ self.query['get_table_name'] = """ - select tableName, maxSeats, category + select tableName, maxSeats, category, type from Hands,Gametypes where Hands.id = %s and Gametypes.id = Hands.gametypeId From 6866f409ce4f6afa331730bb223e0a28eaf5f191 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 9 Apr 2009 09:21:52 -0400 Subject: [PATCH 020/104] Fix regression importing some Stars tournaments. --- pyfpdb/fpdb_simple.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index 609e3b4c..b2ef9d59 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -869,11 +869,19 @@ def goesAllInOnThisLine(line): #end def goesAllInOnThisLine #returns the action type code (see table design) of the given action line -ActionTypes = { 'calls':"call", 'brings in for':"blind", 'completes it to':"bet", ' posts $':"blind", - ' posts a dead ' : "blind", ' posts the small blind of $':"blind", ': posts big blind ':"blind", - ' posts the big blind of $':"blind", ': posts small & big blinds $':"blind", - ': posts small blind $':"blind", - ' bets' : "bet", ' raises' : "bet" +ActionTypes = { 'brings in for' :"blind", + ' posts $' :"blind", + ' posts a dead ' :"blind", + ' posts the small blind of $' :"blind", + ': posts big blind ' :"blind", + ': posts small blind ' :"blind", + ' posts the big blind of $' :"blind", + ': posts small & big blinds $' :"blind", + ': posts small blind $' :"blind", + 'calls' :"call", + 'completes it to' :"bet", + ' bets' :"bet", + ' raises' :"bet" } def parseActionType(line): if (line.startswith("Uncalled bet")): From 584c658590e6c78d8ed42e635133a96160aa42b3 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 11 Apr 2009 03:51:45 +0800 Subject: [PATCH 021/104] Forgot the converter line in merge --- pyfpdb/HUD_config.xml.example | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index 32017934..ce397e42 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -13,6 +13,7 @@ site_path="C:/Program Files/PokerStars/" HH_path="C:/Program Files/PokerStars/HandHistory/YOUR SCREEN NAME HERE/" decoder="pokerstars_decode_table" + converter="PokerStarsToFpdb" bgcolor="#000000" fgcolor="#FFFFFF" hudopacity="1.0" @@ -73,6 +74,7 @@ site_path="C:/Program Files/Full Tilt Poker/" HH_path="C:/Program Files/Full Tilt Poker/HandHistory/YOUR SCREEN NAME HERE/" decoder="fulltilt_decode_table" + converter="FullTiltToFpdb" bgcolor="#000000" fgcolor="#FFFFFF" hudopacity="1.0" @@ -121,6 +123,7 @@ site_path="" HH_path="" decoder="everleaf_decode_table" + converter="EverleafToFpdb" supported_games="holdem"> From 5a842c52fa0e6d3eea0b3db140c5f200344b18a8 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 11 Apr 2009 04:16:36 +0800 Subject: [PATCH 022/104] Add section to example config and remove converter from Change to make building GUI easier from config. --- pyfpdb/HUD_config.xml.example | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index ce397e42..20f38235 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -13,7 +13,6 @@ site_path="C:/Program Files/PokerStars/" HH_path="C:/Program Files/PokerStars/HandHistory/YOUR SCREEN NAME HERE/" decoder="pokerstars_decode_table" - converter="PokerStarsToFpdb" bgcolor="#000000" fgcolor="#FFFFFF" hudopacity="1.0" @@ -74,7 +73,6 @@ site_path="C:/Program Files/Full Tilt Poker/" HH_path="C:/Program Files/Full Tilt Poker/HandHistory/YOUR SCREEN NAME HERE/" decoder="fulltilt_decode_table" - converter="FullTiltToFpdb" bgcolor="#000000" fgcolor="#FFFFFF" hudopacity="1.0" @@ -123,7 +121,6 @@ site_path="" HH_path="" decoder="everleaf_decode_table" - converter="EverleafToFpdb" supported_games="holdem"> @@ -288,6 +285,12 @@ + + + + + + From 2bc564e29255e4364e0c277e490b81510bd49b4c Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 11 Apr 2009 04:18:10 +0800 Subject: [PATCH 023/104] Remove draw from supported list. Olld import code doesn't support draw yet, this patch prevents the bulk importer from crashing if you have a draw hh file in the list accidentally. --- pyfpdb/PokerStarsToFpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index f81d4dc7..300c6071 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -73,7 +73,7 @@ follow : whether to tail -f the input""" ["ring", "hold", "pl"], ["ring", "hold", "fl"], ["ring", "stud", "fl"], - ["ring", "draw", "fl"], + #["ring", "draw", "fl"], ["ring", "omaha", "pl"] ] From b1aade624f182c61fef906753fee348588e118c9 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 11 Apr 2009 04:28:54 +0800 Subject: [PATCH 024/104] Change default window size because it bugged me --- pyfpdb/fpdb.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 49b3ad82..80fcedae 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -381,7 +381,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") self.window.connect("destroy", self.destroy) self.window.set_title("Free Poker DB - v%s or higher" % (VERSION, )) self.window.set_border_width(1) - self.window.set_size_request(1020,400) + self.window.set_default_size(900,720) self.window.set_resizable(True) self.menu_items = ( @@ -449,7 +449,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") self.tab_main_help(None, None) - self.status_bar = gtk.Label("Status: Connected to "+self.db.get_backend_name()+" database named "+self.db.database+" on host "+self.db.host) + self.status_bar = gtk.Label("Status: Connected to %s database named %s on host %s"%(self.db.get_backend_name(),self.db.database, self.db.host)) self.main_vbox.pack_end(self.status_bar, False, True, 0) self.status_bar.show() From 702cb5851a30f234b735f883584fb7a1f15c54ae Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 11 Apr 2009 11:14:01 +0800 Subject: [PATCH 025/104] Oops - revert converter removal --- pyfpdb/HUD_config.xml.example | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index 20f38235..ef30fb9b 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -12,7 +12,8 @@ screen_name="YOUR SCREEN NAME HERE" site_path="C:/Program Files/PokerStars/" HH_path="C:/Program Files/PokerStars/HandHistory/YOUR SCREEN NAME HERE/" - decoder="pokerstars_decode_table" + decoder="pokerstars_decode_table" + converter="PokerStarsToFpdb" bgcolor="#000000" fgcolor="#FFFFFF" hudopacity="1.0" @@ -73,6 +74,7 @@ site_path="C:/Program Files/Full Tilt Poker/" HH_path="C:/Program Files/Full Tilt Poker/HandHistory/YOUR SCREEN NAME HERE/" decoder="fulltilt_decode_table" + converter="FulltiltToFpdb" bgcolor="#000000" fgcolor="#FFFFFF" hudopacity="1.0" @@ -121,6 +123,7 @@ site_path="" HH_path="" decoder="everleaf_decode_table" + converter="EverleafToFpdb" supported_games="holdem"> From 76d7b63b817e7a3afec054a5818f0d88af8b6dc3 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 11 Apr 2009 14:38:46 +0800 Subject: [PATCH 026/104] Make Grapher use get_supported_sites() properly --- pyfpdb/GuiGraphViewer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index 5afc4a92..8899c576 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -185,7 +185,7 @@ class GuiGraphViewer (threading.Thread): print "self.sites[%s] set to %s" %(site, self.sites[site]) def fillPlayerFrame(self, vbox): - for site in self.conf.supported_sites.keys(): + for site in self.conf.get_supported_sites(): pathHBox = gtk.HBox(False, 0) vbox.pack_start(pathHBox, False, True, 0) pathHBox.show() @@ -194,7 +194,7 @@ class GuiGraphViewer (threading.Thread): self.createPlayerLine(pathHBox, site, player) def fillSitesFrame(self, vbox): - for site in self.conf.supported_sites.keys(): + for site in self.conf.get_supported_sites(): hbox = gtk.HBox(False, 0) vbox.pack_start(hbox, False, True, 0) hbox.show() From cf637a4ce6bd9315df244ee4e41391641913bc82 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 11 Apr 2009 14:38:46 +0800 Subject: [PATCH 027/104] Make Grapher use get_supported_sites() properly --- pyfpdb/GuiGraphViewer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index 5afc4a92..8899c576 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -185,7 +185,7 @@ class GuiGraphViewer (threading.Thread): print "self.sites[%s] set to %s" %(site, self.sites[site]) def fillPlayerFrame(self, vbox): - for site in self.conf.supported_sites.keys(): + for site in self.conf.get_supported_sites(): pathHBox = gtk.HBox(False, 0) vbox.pack_start(pathHBox, False, True, 0) pathHBox.show() @@ -194,7 +194,7 @@ class GuiGraphViewer (threading.Thread): self.createPlayerLine(pathHBox, site, player) def fillSitesFrame(self, vbox): - for site in self.conf.supported_sites.keys(): + for site in self.conf.get_supported_sites(): hbox = gtk.HBox(False, 0) vbox.pack_start(hbox, False, True, 0) hbox.show() From 15d7e1fab50bddee5620f6ce60bef01ad2be4211 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 11 Apr 2009 17:10:00 +0800 Subject: [PATCH 028/104] Add a couple of queries for GUI building --- pyfpdb/FpdbSQLQueries.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index f1981d71..fe04aec6 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -1153,6 +1153,12 @@ 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""" + if __name__== "__main__": from optparse import OptionParser From ead50c5ff892548ce35de495aecf36def8b5f743 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 11 Apr 2009 17:10:00 +0800 Subject: [PATCH 029/104] Add a couple of queries for GUI building --- pyfpdb/FpdbSQLQueries.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index 24948986..ee6330c3 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -1153,6 +1153,12 @@ 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""" + if __name__== "__main__": from optparse import OptionParser From 2550a0b0e0f273078df5622998503b5cbd6b67d7 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 11 Apr 2009 17:11:13 +0800 Subject: [PATCH 030/104] Add preliminary filters file --- pyfpdb/Filters.py | 319 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 319 insertions(+) create mode 100644 pyfpdb/Filters.py diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py new file mode 100644 index 00000000..1626d784 --- /dev/null +++ b/pyfpdb/Filters.py @@ -0,0 +1,319 @@ +#!/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, 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.sites = {} + self.games = {} + self.limits = {} + self.siteid = {} + self.heroes = {} + + # For use in date ranges. + self.start_date = gtk.Entry(max=12) + self.end_date = gtk.Entry(max=12) + self.start_date.set_property('editable', False) + self.end_date.set_property('editable', False) + + # Outer Packing box + self.mainVBox = gtk.VBox(False, 0) + + playerFrame = gtk.Frame("Hero:") + playerFrame.set_label_align(0.0, 0.0) + playerFrame.show() + vbox = gtk.VBox(False, 0) + + self.fillPlayerFrame(vbox) + playerFrame.add(vbox) + + sitesFrame = gtk.Frame("Sites:") + sitesFrame.set_label_align(0.0, 0.0) + sitesFrame.show() + vbox = gtk.VBox(False, 0) + + self.fillSitesFrame(vbox) + sitesFrame.add(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) + + # Limits + limitsFrame = gtk.Frame("Games:") + limitsFrame.set_label_align(0.0, 0.0) + limitsFrame.show() + vbox = gtk.VBox(False, 0) + + self.fillLimitsFrame(vbox) + limitsFrame.add(vbox) + + 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) + + graphButton=gtk.Button("Generate Graph") + #graphButton.connect("clicked", self.generateGraph, "cliced data") + + self.fig = None + self.exportButton=gtk.Button("Export to File") + #self.exportButton.connect("clicked", self.exportGraph, "show clicked") + self.exportButton.set_sensitive(False) + + self.mainVBox.add(playerFrame) + self.mainVBox.add(sitesFrame) + self.mainVBox.add(gamesFrame) + self.mainVBox.add(limitsFrame) + self.mainVBox.add(dateFrame) + self.mainVBox.add(graphButton) + self.mainVBox.add(self.exportButton) + + self.mainVBox.show_all() + + def get_vbox(self): + """returns the vbox of this thread""" + return self.mainVBox + #end def get_vbox + + 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) + 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): + cb = gtk.CheckButton(str(limit)) + cb.connect('clicked', self.__set_limit_select, limit) + hbox.pack_start(cb, False, False, 0) + + 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]) + + 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): + self.cursor.execute(self.sql.query['getLimits']) + 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.createLimitLine(hbox, line[0]) + else: + print "INFO: No games returned from database" + + 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 __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() + 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()) + + From d16bb0ac8bcbeaabb7c8b6f50364915bd31333d6 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 11 Apr 2009 19:14:32 +0800 Subject: [PATCH 031/104] Make Grapher use new Filters object --- pyfpdb/Filters.py | 26 +++- pyfpdb/GuiGraphViewer.py | 321 +++++++++------------------------------ 2 files changed, 96 insertions(+), 251 deletions(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index 1626d784..6e075973 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -96,8 +96,7 @@ class Filters(threading.Thread): self.fillDateFrame(vbox) dateFrame.add(vbox) - graphButton=gtk.Button("Generate Graph") - #graphButton.connect("clicked", self.generateGraph, "cliced data") + self.graphButton=gtk.Button("Generate Graph") self.fig = None self.exportButton=gtk.Button("Export to File") @@ -109,7 +108,7 @@ class Filters(threading.Thread): self.mainVBox.add(gamesFrame) self.mainVBox.add(limitsFrame) self.mainVBox.add(dateFrame) - self.mainVBox.add(graphButton) + self.mainVBox.add(self.graphButton) self.mainVBox.add(self.exportButton) self.mainVBox.show_all() @@ -119,6 +118,21 @@ class Filters(threading.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 getDates(self): + return self.__get_dates() + + def registerGraphCallback(self, callback): + self.graphButton.connect("clicked", callback, "clicked") + def createPlayerLine(self, hbox, site, player): label = gtk.Label(site +" id:") hbox.pack_start(label, False, False, 0) @@ -266,6 +280,12 @@ class Filters(threading.Thread): 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): diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index 8899c576..359161cf 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -39,8 +39,73 @@ except: import fpdb_import import fpdb_db +import Filters class GuiGraphViewer (threading.Thread): + + def __init__(self, db, settings, querylist, config, debug=True): + """Constructor for GraphViewer""" + self.debug=debug + #print "start of GraphViewer constructor" + self.db=db + self.cursor=db.cursor + self.settings=settings + self.sql=querylist + self.conf = config + + self.filters = Filters.Filters(db, settings, config, querylist) + self.filters.registerGraphCallback(self.generateGraph) + + self.mainHBox = gtk.HBox(False, 0) + self.mainHBox.show() + + self.leftPanelBox = self.filters.get_vbox() + self.graphBox = gtk.VBox(False, 0) + + self.hpane = gtk.HPaned() + self.hpane.pack1(self.leftPanelBox) + self.hpane.pack2(self.graphBox) + + self.mainHBox.add(self.hpane) + + self.fig = None + self.exportButton=gtk.Button("Export to File") + self.exportButton.connect("clicked", self.exportGraph, "show clicked") + self.exportButton.set_sensitive(False) + + self.fig = Figure(figsize=(5,4), dpi=100) + self.canvas = None + + self.mainHBox.show_all() + +################################# +# +# self.db.cursor.execute("""select UNIX_TIMESTAMP(handStart) as time, id from Hands ORDER BY time""") +# THRESHOLD = 1800 +# hands = self.db.cursor.fetchall() +# +# times = map(lambda x:long(x[0]), hands) +# handids = map(lambda x:int(x[1]), hands) +# print "DEBUG: len(times) %s" %(len(times)) +# diffs = diff(times) +# print "DEBUG: len(diffs) %s" %(len(diffs)) +# index = nonzero(diff(times) > THRESHOLD) +# print "DEBUG: len(index[0]) %s" %(len(index[0])) +# print "DEBUG: index %s" %(index) +# print "DEBUG: index[0][0] %s" %(index[0][0]) +# +# total = 0 +# +# last_idx = 0 +# for i in range(len(index[0])): +# print "Hands in session %4s: %4s Start: %s End: %s Total: %s" %(i, index[0][i] - last_idx, strftime("%d/%m/%Y %H:%M", localtime(times[last_idx])), strftime("%d/%m/%Y %H:%M", localtime(times[index[0][i]])), times[index[0][i]] - times[last_idx]) +# total = total + (index[0][i] - last_idx) +# last_idx = index[0][i] + 1 +# +# print "Total: ", total +################################# + + def get_vbox(self): """returns the vbox of this thread""" return self.mainHBox @@ -59,11 +124,14 @@ class GuiGraphViewer (threading.Thread): sitenos = [] playerids = [] + sites = self.filters.getSites() + heroes = self.filters.getHeroes() + siteids = self.filters.getSiteIds() # Which sites are selected? - for site in self.sites: - if self.sites[site] == True: - sitenos.append(self.siteid[site]) - self.cursor.execute(self.sql.query['getPlayerId'], (self.heroes[site],)) + for site in sites: + if sites[site] == True: + sitenos.append(siteids[site]) + self.cursor.execute(self.sql.query['getPlayerId'], (heroes[site],)) result = self.db.cursor.fetchall() if len(result) == 1: playerids.append(result[0][0]) @@ -117,12 +185,7 @@ class GuiGraphViewer (threading.Thread): def getRingProfitGraph(self, names, sites): tmp = self.sql.query['getRingProfitAllHandsPlayerIdSite'] # print "DEBUG: getRingProfitGraph" - start_date, end_date = self.__get_dates() - - if start_date == '': - start_date = '1970-01-01' - if end_date == '': - end_date = '2020-12-12' + start_date, end_date = self.filters.getDates() #Buggered if I can find a way to do this 'nicely' take a list of intergers and longs # and turn it into a tuple readale by sql. @@ -153,136 +216,6 @@ class GuiGraphViewer (threading.Thread): return line/100 #end of def getRingProfitGraph - def createPlayerLine(self, hbox, site, player): - label = gtk.Label(site +" id:") - hbox.pack_start(label, False, False, 0) - label.show() - - pname = gtk.Entry() - pname.set_text(player) - pname.set_width_chars(20) - hbox.pack_start(pname, False, True, 0) - pname.connect("changed", self.__set_hero_name, site) - #TODO: Look at GtkCompletion - to fill out usernames - pname.show() - - self.__set_hero_name(pname, site) - - def __set_hero_name(self, w, site): - self.heroes[site] = w.get_text() -# print "DEBUG: settings heroes[%s]: %s"%(site, self.heroes[site]) - - def createSiteLine(self, hbox, site): - cb = gtk.CheckButton(site) - cb.connect('clicked', self.__set_site_select, site) - hbox.pack_start(cb, False, False, 0) - cb.show() - - def __set_site_select(self, w, site): - # This doesn't behave as intended - self.site only allows 1 site for the moment. - print w.get_active() - self.sites[site] = w.get_active() - print "self.sites[%s] set to %s" %(site, self.sites[site]) - - def fillPlayerFrame(self, vbox): - for site in self.conf.get_supported_sites(): - pathHBox = gtk.HBox(False, 0) - vbox.pack_start(pathHBox, False, True, 0) - pathHBox.show() - - 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) - hbox.show() - 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 fillDateFrame(self, vbox): - # Hat tip to Mika Bostrom - calendar code comes from PokerStats - hbox = gtk.HBox() - vbox.pack_start(hbox, False, True, 0) - hbox.show() - - lbl_start = gtk.Label('From:') - lbl_start.show() - - 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) - btn_start.show() - - 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) - self.start_date.show() - - #New row for end date - hbox = gtk.HBox() - vbox.pack_start(hbox, False, True, 0) - hbox.show() - - lbl_end = gtk.Label(' To:') - lbl_end.show() - 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_end.show() - - btn_clear = gtk.Button(label=' Clear Dates ') - btn_clear.connect('clicked', self.__clear_dates) - btn_clear.show() - - 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) - self.end_date.show() - - hbox.pack_start(btn_clear, expand=False, padding=15) - - 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() - 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 exportGraph (self, widget, data): if self.fig is None: return # Might want to disable export button until something has been generated. @@ -303,112 +236,4 @@ class GuiGraphViewer (threading.Thread): #TODO: This asks for a directory but will take a filename and overwrite it. self.fig.savefig(self.exportDir, format="png") - def __init__(self, db, settings, querylist, config, debug=True): - """Constructor for GraphViewer""" - self.debug=debug - #print "start of GraphViewer constructor" - self.db=db - self.cursor=db.cursor - self.settings=settings - self.sql=querylist - self.conf = config - - self.sites = {} - self.siteid = {} - self.heroes = {} - - # For use in date ranges. - self.start_date = gtk.Entry(max=12) - self.end_date = gtk.Entry(max=12) - self.start_date.set_property('editable', False) - self.end_date.set_property('editable', False) - - self.mainHBox = gtk.HBox(False, 0) - self.mainHBox.show() - - self.leftPanelBox = gtk.VBox(False, 0) - self.graphBox = gtk.VBox(False, 0) - - self.hpane = gtk.HPaned() - self.hpane.pack1(self.leftPanelBox) - self.hpane.pack2(self.graphBox) - self.hpane.show() - - self.mainHBox.add(self.hpane) - - playerFrame = gtk.Frame("Hero:") - playerFrame.set_label_align(0.0, 0.0) - playerFrame.show() - vbox = gtk.VBox(False, 0) - vbox.show() - - self.fillPlayerFrame(vbox) - playerFrame.add(vbox) - - sitesFrame = gtk.Frame("Sites:") - sitesFrame.set_label_align(0.0, 0.0) - sitesFrame.show() - vbox = gtk.VBox(False, 0) - vbox.show() - - self.fillSitesFrame(vbox) - sitesFrame.add(vbox) - - dateFrame = gtk.Frame("Date:") - dateFrame.set_label_align(0.0, 0.0) - dateFrame.show() - vbox = gtk.VBox(False, 0) - vbox.show() - - self.fillDateFrame(vbox) - dateFrame.add(vbox) - - graphButton=gtk.Button("Generate Graph") - graphButton.connect("clicked", self.generateGraph, "cliced data") - graphButton.show() - - self.fig = None - self.exportButton=gtk.Button("Export to File") - self.exportButton.connect("clicked", self.exportGraph, "show clicked") - self.exportButton.set_sensitive(False) - self.exportButton.show() - - self.leftPanelBox.add(playerFrame) - self.leftPanelBox.add(sitesFrame) - self.leftPanelBox.add(dateFrame) - self.leftPanelBox.add(graphButton) - self.leftPanelBox.add(self.exportButton) - - self.leftPanelBox.show() - self.graphBox.show() - - self.fig = Figure(figsize=(5,4), dpi=100) - self.canvas = None - -################################# -# -# self.db.cursor.execute("""select UNIX_TIMESTAMP(handStart) as time, id from Hands ORDER BY time""") -# THRESHOLD = 1800 -# hands = self.db.cursor.fetchall() -# -# times = map(lambda x:long(x[0]), hands) -# handids = map(lambda x:int(x[1]), hands) -# print "DEBUG: len(times) %s" %(len(times)) -# diffs = diff(times) -# print "DEBUG: len(diffs) %s" %(len(diffs)) -# index = nonzero(diff(times) > THRESHOLD) -# print "DEBUG: len(index[0]) %s" %(len(index[0])) -# print "DEBUG: index %s" %(index) -# print "DEBUG: index[0][0] %s" %(index[0][0]) -# -# total = 0 -# -# last_idx = 0 -# for i in range(len(index[0])): -# print "Hands in session %4s: %4s Start: %s End: %s Total: %s" %(i, index[0][i] - last_idx, strftime("%d/%m/%Y %H:%M", localtime(times[last_idx])), strftime("%d/%m/%Y %H:%M", localtime(times[index[0][i]])), times[index[0][i]] - times[last_idx]) -# total = total + (index[0][i] - last_idx) -# last_idx = index[0][i] + 1 -# -# print "Total: ", total -################################# From 15e31eccb28656cf61c4cecf1cceae75a2dc5430 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 11 Apr 2009 20:07:50 +0800 Subject: [PATCH 032/104] Make player and positional stats use Filters --- pyfpdb/Filters.py | 27 +++- pyfpdb/GuiPlayerStats.py | 222 +++++++++++++---------------- pyfpdb/GuiPositionalStats.py | 261 ++++++++++++++--------------------- 3 files changed, 226 insertions(+), 284 deletions(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index 6e075973..1e93127b 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -56,7 +56,6 @@ class Filters(threading.Thread): playerFrame = gtk.Frame("Hero:") playerFrame.set_label_align(0.0, 0.0) - playerFrame.show() vbox = gtk.VBox(False, 0) self.fillPlayerFrame(vbox) @@ -64,7 +63,6 @@ class Filters(threading.Thread): sitesFrame = gtk.Frame("Sites:") sitesFrame.set_label_align(0.0, 0.0) - sitesFrame.show() vbox = gtk.VBox(False, 0) self.fillSitesFrame(vbox) @@ -133,6 +131,9 @@ class Filters(threading.Thread): def registerGraphCallback(self, callback): self.graphButton.connect("clicked", callback, "clicked") + 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) @@ -153,6 +154,7 @@ class Filters(threading.Thread): 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): @@ -223,6 +225,27 @@ class Filters(threading.Thread): else: print "INFO: No games returned from database" + 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() diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index b2eb0108..76aa06dd 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -23,146 +23,34 @@ import os import fpdb_import import fpdb_db +import Filters import FpdbSQLQueries class GuiPlayerStats (threading.Thread): - def get_vbox(self): - """returns the vbox of this thread""" - return self.main_hbox - - def toggleCallback(self, widget, data=None): -# print "%s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()]) - self.activesite = data - print "DEBUG: activesite set to %s" %(self.activesite) - - def refreshStats(self, widget, data): - try: self.stats_table.destroy() - except AttributeError: pass - self.fillStatsFrame(self.stats_frame) - - def fillStatsFrame(self, vbox): - # Get currently active site and grab playerid - tmp = self.sql.query['playerStats'] - - result = self.cursor.execute(self.sql.query['getPlayerId'], (self.heroes[self.activesite],)) - result = self.cursor.fetchall() - if not result == (): - pid = result[0][0] - pid = result[0][0] - tmp = tmp.replace("", "(" + str(pid) + ")") - self.cursor.execute(tmp) - result = self.cursor.fetchall() - cols = 16 - rows = len(result)+1 # +1 for title row - self.stats_table = gtk.Table(rows, cols, False) - self.stats_table.set_col_spacings(4) - self.stats_table.show() - vbox.add(self.stats_table) - - # Create header row - titles = ("Game", "Hands", "VPIP", "PFR", "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq", "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance") - - col = 0 - row = 0 - for t in titles: - l = gtk.Label(titles[col]) - l.show() - self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK) - col +=1 - - for row in range(rows-1): - if(row%2 == 0): - bgcolor = "white" - else: - bgcolor = "lightgrey" - for col in range(cols): - eb = gtk.EventBox() - eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) - if result[row][col]: - l = gtk.Label(result[row][col]) - else: - l = gtk.Label(' ') - if col == 0: - l.set_alignment(xalign=0.0, yalign=0.5) - else: - l.set_alignment(xalign=1.0, yalign=0.5) - eb.add(l) - self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) - l.show() - eb.show() - self.fdb.db.commit() - #end def fillStatsFrame(self, vbox): - - def fillPlayerFrame(self, vbox): - for site in self.conf.supported_sites.keys(): - hbox = gtk.HBox(False, 0) - vbox.pack_start(hbox, False, True, 0) - hbox.show() - - player = self.conf.supported_sites[site].screen_name - self.createPlayerLine(hbox, site, player) - hbox = gtk.HBox(False, 0) - button = gtk.Button("Refresh") - button.connect("clicked", self.refreshStats, False) - button.show() - hbox.add(button) - vbox.pack_start(hbox, False, True, 0) - hbox.show() - - def createPlayerLine(self, hbox, site, player): - if(self.buttongroup == None): - button = gtk.RadioButton(None, site + " id:") - button.set_active(True) - self.buttongroup = button - self.activesite = site - else: - button = gtk.RadioButton(self.buttongroup, site + " id:") - hbox.pack_start(button, True, True, 0) - button.connect("toggled", self.toggleCallback, site) - button.show() - - pname = gtk.Entry() - pname.set_text(player) - pname.set_width_chars(20) - hbox.pack_start(pname, False, True, 0) - pname.connect("changed", self.__set_hero_name, site) - #TODO: Look at GtkCompletion - to fill out usernames - pname.show() - self.__set_hero_name(pname, site) - - def __set_hero_name(self, w, site): - self.heroes[site] = w.get_text() - def __init__(self, db, config, querylist, debug=True): self.debug=debug self.conf=config # create new db connection to avoid conflicts with other threads - self.fdb = fpdb_db.fpdb_db() - self.fdb.do_connect(self.conf) - self.cursor=self.fdb.cursor - + self.db = fpdb_db.fpdb_db() + self.db.do_connect(self.conf) + self.cursor=self.db.cursor self.sql = querylist - self.activesite = None - self.buttongroup = 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()) + + self.filters = Filters.Filters(db, settings, config, querylist) - self.heroes = {} self.stat_table = None self.stats_frame = None self.main_hbox = gtk.HBox(False, 0) self.main_hbox.show() - playerFrame = gtk.Frame("Hero:") - playerFrame.set_label_align(0.0, 0.0) - playerFrame.show() - vbox = gtk.VBox(False, 0) - vbox.show() - - self.fillPlayerFrame(vbox) - playerFrame.add(vbox) - statsFrame = gtk.Frame("Stats:") statsFrame.set_label_align(0.0, 0.0) statsFrame.show() @@ -172,6 +60,92 @@ class GuiPlayerStats (threading.Thread): self.fillStatsFrame(self.stats_frame) statsFrame.add(self.stats_frame) - self.main_hbox.pack_start(playerFrame) + self.main_hbox.pack_start(self.filters.get_vbox()) self.main_hbox.pack_start(statsFrame) + def get_vbox(self): + """returns the vbox of this thread""" + return self.main_hbox + + def refreshStats(self, widget, data): + try: self.stats_table.destroy() + except AttributeError: pass + self.fillStatsFrame(self.stats_frame) + + def fillStatsFrame(self, vbox): + sites = self.filters.getSites() + heroes = self.filters.getHeroes() + siteids = self.filters.getSiteIds() + sitenos = [] + playerids = [] + + # Which sites are selected? + for site in sites: + if sites[site] == True: + sitenos.append(siteids[site]) + self.cursor.execute(self.sql.query['getPlayerId'], (heroes[site],)) + result = self.db.cursor.fetchall() + if len(result) == 1: + playerids.append(result[0][0]) + + if not sitenos: + #Should probably pop up here. + print "No sites selected - defaulting to PokerStars" + sitenos = [2] + if not playerids: + print "No player ids found" + return + + self.createStatsTable(vbox, playerids, sitenos) + + def createStatsTable(self, vbox, playerids, sitenos): + tmp = self.sql.query['playerStats'] + + nametest = str(tuple(playerids)) + nametest = nametest.replace("L", "") + nametest = nametest.replace(",)",")") + + tmp = tmp.replace("", nametest) + + self.cursor.execute(tmp) + result = self.cursor.fetchall() + cols = 16 + rows = len(result)+1 # +1 for title row + self.stats_table = gtk.Table(rows, cols, False) + self.stats_table.set_col_spacings(4) + self.stats_table.show() + vbox.add(self.stats_table) + + # Create header row + titles = ("Game", "Hands", "VPIP", "PFR", "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq", "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance") + + col = 0 + row = 0 + for t in titles: + l = gtk.Label(titles[col]) + l.show() + self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK) + col +=1 + + for row in range(rows-1): + if(row%2 == 0): + bgcolor = "white" + else: + bgcolor = "lightgrey" + for col in range(cols): + eb = gtk.EventBox() + eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) + if result[row][col]: + l = gtk.Label(result[row][col]) + else: + l = gtk.Label(' ') + if col == 0: + l.set_alignment(xalign=0.0, yalign=0.5) + else: + l.set_alignment(xalign=1.0, yalign=0.5) + eb.add(l) + self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) + l.show() + eb.show() + self.db.db.commit() + #end def fillStatsFrame(self, vbox): diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index 64828573..41b51829 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -23,180 +23,34 @@ import os import fpdb_import import fpdb_db +import Filters import FpdbSQLQueries class GuiPositionalStats (threading.Thread): - def get_vbox(self): - """returns the vbox of this thread""" - return self.main_hbox - - def toggleCallback(self, widget, data=None): -# print "%s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()]) - self.activesite = data - print "DEBUG: activesite set to %s" %(self.activesite) - - def cardCallback(self, widget, data=None): - print "DEBUG: %s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()]) - - def refreshStats(self, widget, data): - try: self.stats_table.destroy() - except AttributeError: pass - self.fillStatsFrame(self.stats_frame) - - def fillStatsFrame(self, vbox): - # Get currently active site and grab playerid - print "DEBUG: attempting to fill stats frame" - tmp = self.sql.query['playerStatsByPosition'] - - result = self.cursor.execute(self.sql.query['getPlayerId'], (self.heroes[self.activesite],)) - result = self.cursor.fetchall() - if not result == (): - pid = result[0][0] - pid = result[0][0] - tmp = tmp.replace("", "(" + str(pid) + ")") - self.cursor.execute(tmp) - result = self.cursor.fetchall() - cols = 16 - rows = len(result)+1 # +1 for title row - self.stats_table = gtk.Table(rows, cols, False) - self.stats_table.set_col_spacings(4) - self.stats_table.show() - vbox.add(self.stats_table) - - # Create header row - titles = ("Game", "Position", "#", "VPIP", "PFR", "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq", "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance") - - col = 0 - row = 0 - for t in titles: - l = gtk.Label(titles[col]) - l.show() - self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK) - col +=1 - - for row in range(rows-1): - if(row%2 == 0): - bgcolor = "white" - else: - bgcolor = "lightgrey" - for col in range(cols): - eb = gtk.EventBox() - eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) - if result[row][col]: - l = gtk.Label(result[row][col]) - else: - l = gtk.Label(' ') - if col == 0: - l.set_alignment(xalign=0.0, yalign=0.5) - else: - l.set_alignment(xalign=1.0, yalign=0.5) - eb.add(l) - self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) - l.show() - eb.show() - self.fdb.db.commit() - #end def fillStatsFrame(self, vbox): - - def fillPlayerFrame(self, vbox): - for site in self.conf.supported_sites.keys(): - hbox = gtk.HBox(False, 0) - vbox.pack_start(hbox, False, True, 0) - hbox.show() - - player = self.conf.supported_sites[site].screen_name - self.createPlayerLine(hbox, site, player) - hbox = gtk.HBox(False, 0) - button = gtk.Button("Refresh") - button.connect("clicked", self.refreshStats, False) - button.show() - hbox.add(button) - vbox.pack_start(hbox, False, True, 0) - hbox.show() - - def 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 createPlayerLine(self, hbox, site, player): - if(self.buttongroup == None): - button = gtk.RadioButton(None, site + " id:") - button.set_active(True) - self.buttongroup = button - self.activesite = site - else: - button = gtk.RadioButton(self.buttongroup, site + " id:") - hbox.pack_start(button, True, True, 0) - button.connect("toggled", self.toggleCallback, site) - button.show() - - pname = gtk.Entry() - pname.set_text(player) - pname.set_width_chars(20) - hbox.pack_start(pname, False, True, 0) - pname.connect("changed", self.__set_hero_name, site) - #TODO: Look at GtkCompletion - to fill out usernames - pname.show() - self.__set_hero_name(pname, site) - - def __set_hero_name(self, w, site): - self.heroes[site] = w.get_text() - def __init__(self, db, config, querylist, debug=True): self.debug=debug self.conf=config # create new db connection to avoid conflicts with other threads - self.fdb = fpdb_db.fpdb_db() - self.fdb.do_connect(self.conf) - self.cursor=self.fdb.cursor - + self.db = fpdb_db.fpdb_db() + self.db.do_connect(self.conf) + self.cursor=self.db.cursor self.sql = querylist - self.activesite = None - self.buttongroup = 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()) + + self.filters = Filters.Filters(db, settings, config, querylist) - self.heroes = {} self.stat_table = None self.stats_frame = None self.main_hbox = gtk.HBox(False, 0) self.main_hbox.show() - playerFrame = gtk.Frame("Hero:") - playerFrame.set_label_align(0.0, 0.0) - playerFrame.show() - vbox = gtk.VBox(False, 0) - vbox.show() - - self.fillPlayerFrame(vbox) - playerFrame.add(vbox) - - cardsFrame = gtk.Frame("Cards:") - cardsFrame.set_label_align(0.0, 0.0) - cardsFrame.show() - vbox = gtk.VBox(False, 0) - vbox.show() - - self.fillCardsFrame(vbox) - cardsFrame.add(vbox) - statsFrame = gtk.Frame("Stats:") statsFrame.set_label_align(0.0, 0.0) statsFrame.show() @@ -206,6 +60,97 @@ class GuiPositionalStats (threading.Thread): self.fillStatsFrame(self.stats_frame) statsFrame.add(self.stats_frame) - self.main_hbox.pack_start(playerFrame) + self.main_hbox.pack_start(self.filters.get_vbox()) self.main_hbox.pack_start(statsFrame) + def get_vbox(self): + """returns the vbox of this thread""" + return self.main_hbox + + def toggleCallback(self, widget, data=None): +# print "%s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()]) + self.activesite = data + print "DEBUG: activesite set to %s" %(self.activesite) + + def refreshStats(self, widget, data): + try: self.stats_table.destroy() + except AttributeError: pass + self.fillStatsFrame(self.stats_frame) + + def fillStatsFrame(self, vbox): + sites = self.filters.getSites() + heroes = self.filters.getHeroes() + siteids = self.filters.getSiteIds() + sitenos = [] + playerids = [] + + # Which sites are selected? + for site in sites: + if sites[site] == True: + sitenos.append(siteids[site]) + self.cursor.execute(self.sql.query['getPlayerId'], (heroes[site],)) + result = self.db.cursor.fetchall() + if len(result) == 1: + playerids.append(result[0][0]) + + if not sitenos: + #Should probably pop up here. + print "No sites selected - defaulting to PokerStars" + sitenos = [2] + if not playerids: + print "No player ids found" + return + + self.createStatsTable(vbox, playerids, sitenos) + + def createStatsTable(self, vbox, playerids, sitenos): + tmp = self.sql.query['playerStatsByPosition'] + + nametest = str(tuple(playerids)) + nametest = nametest.replace("L", "") + nametest = nametest.replace(",)",")") + + tmp = tmp.replace("", nametest) + + self.cursor.execute(tmp) + result = self.cursor.fetchall() + cols = 16 + rows = len(result)+1 # +1 for title row + self.stats_table = gtk.Table(rows, cols, False) + self.stats_table.set_col_spacings(4) + self.stats_table.show() + vbox.add(self.stats_table) + + # Create header row + titles = ("Game", "Position", "#", "VPIP", "PFR", "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq", "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance") + + col = 0 + row = 0 + for t in titles: + l = gtk.Label(titles[col]) + l.show() + self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK) + col +=1 + + for row in range(rows-1): + if(row%2 == 0): + bgcolor = "white" + else: + bgcolor = "lightgrey" + for col in range(cols): + eb = gtk.EventBox() + eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) + if result[row][col]: + l = gtk.Label(result[row][col]) + else: + l = gtk.Label(' ') + if col == 0: + l.set_alignment(xalign=0.0, yalign=0.5) + else: + l.set_alignment(xalign=1.0, yalign=0.5) + eb.add(l) + self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) + l.show() + eb.show() + self.db.db.commit() + #end def fillStatsFrame(self, vbox): From 1939979e3c64e931e6a1be2fb6916d7e9ca4947e Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 14 Apr 2009 21:31:29 +0800 Subject: [PATCH 033/104] Make Grapher work with limits --- pyfpdb/Filters.py | 7 +++++++ pyfpdb/FpdbSQLQueries.py | 19 +++---------------- pyfpdb/GuiGraphViewer.py | 21 ++++++++++++++------- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index 1e93127b..67e26443 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -125,6 +125,13 @@ class Filters(threading.Thread): 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 getDates(self): return self.__get_dates() diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index fe04aec6..fca17a5f 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -609,7 +609,7 @@ 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)) @@ -617,28 +617,15 @@ class FpdbSQLQueries: 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 ORDER BY h.handStart""" - 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""" if(self.dbname == 'MySQL InnoDB'): self.query['playerStats'] = """ diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index 359161cf..9aaa4506 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -124,9 +124,10 @@ class GuiGraphViewer (threading.Thread): sitenos = [] playerids = [] - sites = self.filters.getSites() - heroes = self.filters.getHeroes() + sites = self.filters.getSites() + heroes = self.filters.getHeroes() siteids = self.filters.getSiteIds() + limits = self.filters.getLimits() # Which sites are selected? for site in sites: if sites[site] == True: @@ -141,18 +142,20 @@ class GuiGraphViewer (threading.Thread): print "No sites selected - defaulting to PokerStars" sitenos = [2] - if not playerids: print "No player ids found" return + if not limits: + print "No limits found" + return #Set graph properties self.ax = self.fig.add_subplot(111) #Get graph data from DB starttime = time() - line = self.getRingProfitGraph(playerids, sitenos) + line = self.getRingProfitGraph(playerids, sitenos, limits) print "Graph generated in: %s" %(time() - starttime) self.ax.set_title("Profit graph for ring games") @@ -182,7 +185,7 @@ class GuiGraphViewer (threading.Thread): self.exportButton.set_sensitive(True) #end of def showClicked - def getRingProfitGraph(self, names, sites): + def getRingProfitGraph(self, names, sites, limits): tmp = self.sql.query['getRingProfitAllHandsPlayerIdSite'] # print "DEBUG: getRingProfitGraph" start_date, end_date = self.filters.getDates() @@ -192,18 +195,22 @@ class GuiGraphViewer (threading.Thread): # [5L] into (5) not (5,) and [5L, 2829L] into (5, 2829) nametest = str(tuple(names)) sitetest = str(tuple(sites)) + limittest = str(tuple(limits)) nametest = nametest.replace("L", "") nametest = nametest.replace(",)",")") sitetest = sitetest.replace(",)",")") + limittest = limittest.replace("L", "") + limittest = limittest.replace(",)",")") #Must be a nicer way to deal with tuples of size 1 ie. (2,) - which makes sql barf tmp = tmp.replace("", nametest) tmp = tmp.replace("", sitetest) tmp = tmp.replace("", start_date) tmp = tmp.replace("", end_date) + tmp = tmp.replace("", limittest) -# print "DEBUG: sql query:" -# print tmp + #print "DEBUG: sql query:" + #print tmp self.cursor.execute(tmp) #returns (HandId,Winnings,Costs,Profit) winnings = self.db.cursor.fetchall() From ee1186bd573c24db7bf392e7a6d082dcc113658a Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 17 Apr 2009 12:44:43 +0800 Subject: [PATCH 034/104] Add ability for Filters to hide() panes Also add ability to register a callback and name 2 buttons on hte left panel --- pyfpdb/Filters.py | 44 ++++++++++++++++++++++++++++-------- pyfpdb/GuiGraphViewer.py | 20 ++++++++++++---- pyfpdb/GuiPlayerStats.py | 11 ++++++++- pyfpdb/GuiPositionalStats.py | 11 ++++++++- 4 files changed, 69 insertions(+), 17 deletions(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index 67e26443..df6262a3 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -30,7 +30,7 @@ import fpdb_db import FpdbSQLQueries class Filters(threading.Thread): - def __init__(self, db, settings, config, qdict, debug=True): + def __init__(self, db, settings, config, qdict, display = {},debug=True): self.debug=debug #print "start of GraphViewer constructor" self.db=db @@ -78,7 +78,7 @@ class Filters(threading.Thread): gamesFrame.add(vbox) # Limits - limitsFrame = gtk.Frame("Games:") + limitsFrame = gtk.Frame("Limits:") limitsFrame.set_label_align(0.0, 0.0) limitsFrame.show() vbox = gtk.VBox(False, 0) @@ -94,23 +94,38 @@ class Filters(threading.Thread): self.fillDateFrame(vbox) dateFrame.add(vbox) - self.graphButton=gtk.Button("Generate Graph") + self.Button1=gtk.Button("Unamed 1") - self.fig = None - self.exportButton=gtk.Button("Export to File") + self.Button2=gtk.Button("Unamed 2") #self.exportButton.connect("clicked", self.exportGraph, "show clicked") - self.exportButton.set_sensitive(False) + self.Button2.set_sensitive(False) self.mainVBox.add(playerFrame) self.mainVBox.add(sitesFrame) self.mainVBox.add(gamesFrame) self.mainVBox.add(limitsFrame) self.mainVBox.add(dateFrame) - self.mainVBox.add(self.graphButton) - self.mainVBox.add(self.exportButton) + self.mainVBox.add(self.Button1) + self.mainVBox.add(self.Button2) self.mainVBox.show_all() + # Should do this cleaner + if display["Heroes"] == False: + playerFrame.hide() + if display["Sites"] == False: + sitesFrame.hide() + if display["Games"] == False: + gamesFrame.hide() + if display["Limits"] == False: + limitsFrame.hide() + if display["Dates"] == False: + dateFrame.hide() + if display["Button1"] == False: + self.Button1.hide() + if display["Button2"] == False: + self.Button2.hide() + def get_vbox(self): """returns the vbox of this thread""" return self.mainVBox @@ -135,8 +150,17 @@ class Filters(threading.Thread): def getDates(self): return self.__get_dates() - def registerGraphCallback(self, callback): - self.graphButton.connect("clicked", callback, "clicked") + def registerButton1Name(self, title): + self.Button1.set_label(title) + + def registerButton1Callback(self, callback): + self.Button1.connect("clicked", callback, "clicked") + + def registerButton2Name(self, title): + self.Button2.set_label(title) + + def registerButton2Callback(self, callback): + self.Button2.connect("clicked", callback, "clicked") def cardCallback(self, widget, data=None): print "DEBUG: %s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()]) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index 9aaa4506..b1f87989 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -53,8 +53,20 @@ class GuiGraphViewer (threading.Thread): self.sql=querylist self.conf = config - self.filters = Filters.Filters(db, settings, config, querylist) - self.filters.registerGraphCallback(self.generateGraph) + filters_display = { "Heroes" : True, + "Sites" : True, + "Games" : True, + "Limits" : True, + "Dates" : True, + "Button1" : True, + "Button2" : True + } + + self.filters = Filters.Filters(db, settings, config, querylist, display = filters_display) + self.filters.registerButton1Name("Refresh Graph") + self.filters.registerButton1Callback(self.generateGraph) + self.filters.registerButton2Name("Export to File") + self.filters.registerButton2Callback(self.exportGraph) self.mainHBox = gtk.HBox(False, 0) self.mainHBox.show() @@ -69,9 +81,7 @@ class GuiGraphViewer (threading.Thread): self.mainHBox.add(self.hpane) self.fig = None - self.exportButton=gtk.Button("Export to File") - self.exportButton.connect("clicked", self.exportGraph, "show clicked") - self.exportButton.set_sensitive(False) + #self.exportButton.set_sensitive(False) self.fig = Figure(figsize=(5,4), dpi=100) self.canvas = None diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 76aa06dd..213d7535 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -43,7 +43,16 @@ class GuiPlayerStats (threading.Thread): settings.update(config.get_import_parameters()) settings.update(config.get_default_paths()) - self.filters = Filters.Filters(db, settings, config, querylist) + filters_display = { "Heroes" : True, + "Sites" : True, + "Games" : False, + "Limits" : False, + "Dates" : False, + "Button1" : False, + "Button2" : False + } + + self.filters = Filters.Filters(db, settings, config, querylist, display = filters_display) self.stat_table = None self.stats_frame = None diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index 41b51829..587742a3 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -43,7 +43,16 @@ class GuiPositionalStats (threading.Thread): settings.update(config.get_import_parameters()) settings.update(config.get_default_paths()) - self.filters = Filters.Filters(db, settings, config, querylist) + filters_display = { "Heroes" : True, + "Sites" : True, + "Games" : False, + "Limits" : False, + "Dates" : False, + "Button1" : False, + "Button2" : False + } + + self.filters = Filters.Filters(db, settings, config, querylist, display = filters_display) self.stat_table = None self.stats_frame = None From 85b03ef720cc5b6e11357e3cddf55755e1af6f79 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 26 Apr 2009 21:31:05 +0100 Subject: [PATCH 035/104] fix 3bet stat bug in storeHudCache2 --- pyfpdb/fpdb_simple.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index 384b2eac..fc5b00a9 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -2892,7 +2892,7 @@ def storeHudCache2(backend, cursor, base, category, gametypeId, playerIds, hudIm # Try to do the update first: num = cursor.execute("""UPDATE HudCache SET HDs=HDs+%s, street0VPI=street0VPI+%s, street0Aggr=street0Aggr+%s, - street0_3B4BChance=%s, street0_3B4BDone=%s, + street0_3B4BChance=street0_3B4BChance+%s, street0_3B4BDone=street0_3B4BDone+%s, street1Seen=street1Seen+%s, street2Seen=street2Seen+%s, street3Seen=street3Seen+%s, street4Seen=street4Seen+%s, sawShowdown=sawShowdown+%s, street1Aggr=street1Aggr+%s, street2Aggr=street2Aggr+%s, street3Aggr=street3Aggr+%s, From b266b48c3337664652bc75b41edc68d59f5b2d61 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 26 Apr 2009 21:38:04 +0100 Subject: [PATCH 036/104] add rollback to release locks when db reads are finished --- pyfpdb/fpdb.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 6e203889..ac18caac 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -290,6 +290,7 @@ class fpdb: # Database connected to successfully, load queries to pass on to other classes self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) + self.db.db.rollback() #end def load_profile def not_implemented(self): From 6cee8b7a97f1fe81fe7a2b22f264ae8cbed1025d Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 26 Apr 2009 21:47:28 +0100 Subject: [PATCH 037/104] always release locks when db work finished --- pyfpdb/fpdb_import.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 8b567032..4a210d35 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -67,6 +67,7 @@ class Importer: self.settings['handCount'] = 0 self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql self.fdb.do_connect(self.config) + self.fdb.db.rollback() #Set functions def setCallHud(self, value): @@ -235,6 +236,7 @@ class Importer: self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep) except fpdb_simple.DuplicateError: duplicates+=1 + self.fdb.db.rollback() except (ValueError), fe: errors+=1 self.printEmailErrorMessage(errors, file, hand) @@ -242,6 +244,8 @@ class Importer: if (self.settings['failOnError']): self.fdb.db.commit() #dont remove this, in case hand processing was cancelled. raise + else: + self.fdb.db.rollback() except (fpdb_simple.FpdbError), fe: errors+=1 self.printEmailErrorMessage(errors, file, hand) From 3c815ed0e8bf9e58edb5ea2545e6cb1dace24042 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 26 Apr 2009 22:20:24 +0100 Subject: [PATCH 038/104] steal stat fixes to match pokertracker --- pyfpdb/fpdb_simple.py | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index fc5b00a9..6bc2ac6c 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -2109,6 +2109,11 @@ sure to also change the following storage method and table_viewer.prepare_data i firstPfCallByNo=i firstPfCallerId=actionTypeByNo[0][i][0] break + firstPlayId = firstPfCallerId + if firstPfRaiseByNo <> -1: + if firstPfRaiseByNo < firstPfCallByNo or firstPfCallByNo == -1: + firstPlayId = firstPfRaiserId + cutoffId=-1 buttonId=-1 @@ -2116,13 +2121,13 @@ sure to also change the following storage method and table_viewer.prepare_data i bbId=-1 if base=="hold": for player in range(len(positions)): - if positions==1: + if positions[player]==1: cutoffId=player_ids[player] - if positions==0: + if positions[player]==0: buttonId=player_ids[player] - if positions=='S': + if positions[player]=='S': sbId=player_ids[player] - if positions=='B': + if positions[player]=='B': bbId=player_ids[player] someoneStole=False @@ -2183,24 +2188,27 @@ sure to also change the following storage method and table_viewer.prepare_data i #steal calculations if base=="hold": - if len(player_ids)>=5: #no point otherwise + if len(player_ids)>=3: # no point otherwise # was 5, use 3 to match pokertracker definition if positions[player]==1: - if firstPfRaiserId==player_ids[player]: - myStealAttemptChance=True + if firstPfRaiserId==player_ids[player] \ + and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo): myStealAttempted=True - elif firstPfRaiserId==buttonId or firstPfRaiserId==sbId or firstPfRaiserId==bbId or firstPfRaiserId==-1: + myStealAttemptChance=True + if firstPlayId==cutoffId or firstPlayId==buttonId or firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1: myStealAttemptChance=True if positions[player]==0: - if firstPfRaiserId==player_ids[player]: - myStealAttemptChance=True + if firstPfRaiserId==player_ids[player] \ + and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo): myStealAttempted=True - elif firstPfRaiserId==sbId or firstPfRaiserId==bbId or firstPfRaiserId==-1: + myStealAttemptChance=True + if firstPlayId==buttonId or firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1: myStealAttemptChance=True if positions[player]=='S': - if firstPfRaiserId==player_ids[player]: - myStealAttemptChance=True + if firstPfRaiserId==player_ids[player] \ + and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo): myStealAttempted=True - elif firstPfRaiserId==bbId or firstPfRaiserId==-1: + myStealAttemptChance=True + if firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1: myStealAttemptChance=True if positions[player]=='B': pass From 064a7a6de665374bb56cddff8eed4e149b6e9d51 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 26 Apr 2009 21:31:05 +0100 Subject: [PATCH 039/104] fix 3bet stat bug in storeHudCache2 --- pyfpdb/fpdb_simple.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index e9c074bd..941fb4fc 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -2404,7 +2404,7 @@ def storeHudCache2(backend, cursor, base, category, gametypeId, playerIds, hudIm # Try to do the update first: num = cursor.execute("""UPDATE HudCache SET HDs=HDs+%s, street0VPI=street0VPI+%s, street0Aggr=street0Aggr+%s, - street0_3B4BChance=%s, street0_3B4BDone=%s, + street0_3B4BChance=street0_3B4BChance+%s, street0_3B4BDone=street0_3B4BDone+%s, street1Seen=street1Seen+%s, street2Seen=street2Seen+%s, street3Seen=street3Seen+%s, street4Seen=street4Seen+%s, sawShowdown=sawShowdown+%s, street1Aggr=street1Aggr+%s, street2Aggr=street2Aggr+%s, street3Aggr=street3Aggr+%s, From d9d8043888023944c091db0b96c9bb7e210a557a Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 26 Apr 2009 21:38:04 +0100 Subject: [PATCH 040/104] add rollback to release locks when db reads are finished --- pyfpdb/fpdb.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 80fcedae..3e0b4337 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -267,6 +267,7 @@ class fpdb: self.settings['db-databaseName'], self.settings['db-user'], self.settings['db-password']) +<<<<<<< HEAD:pyfpdb/fpdb.py if self.db.wrongDbVersion: diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) @@ -287,6 +288,7 @@ class fpdb: # Database connected to successfully, load queries to pass on to other classes self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) + self.db.db.rollback() #end def load_profile def not_implemented(self): From 326f29b5b607e253368359a548f98f3c8edc2abd Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 26 Apr 2009 21:47:28 +0100 Subject: [PATCH 041/104] always release locks when db work finished --- pyfpdb/fpdb_import.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 2b421e19..a3bdb3cc 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -74,6 +74,7 @@ class Importer: self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql self.fdb.do_connect(self.config) + self.fdb.db.rollback() #Set functions def setCallHud(self, value): @@ -348,6 +349,7 @@ class Importer: self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep) except fpdb_simple.DuplicateError: duplicates += 1 + self.fdb.db.rollback() except (ValueError), fe: errors += 1 self.printEmailErrorMessage(errors, file, hand) @@ -355,6 +357,8 @@ class Importer: if (self.settings['failOnError']): self.fdb.db.commit() #dont remove this, in case hand processing was cancelled. raise + else: + self.fdb.db.rollback() except (fpdb_simple.FpdbError), fe: errors += 1 self.printEmailErrorMessage(errors, file, hand) From d2c978d7f59338199265e41475922df44499adc2 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 26 Apr 2009 22:20:24 +0100 Subject: [PATCH 042/104] steal stat fixes to match pokertracker --- pyfpdb/fpdb_simple.py | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index 941fb4fc..60e1f2a9 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -1630,6 +1630,11 @@ sure to also change the following storage method and table_viewer.prepare_data i firstPfCallByNo = i firstPfCallerId = action[0] break + firstPlayId = firstPfCallerId + if firstPfRaiseByNo <> -1: + if firstPfRaiseByNo < firstPfCallByNo or firstPfCallByNo == -1: + firstPlayId = firstPfRaiserId + cutoffId=-1 buttonId=-1 @@ -1702,25 +1707,28 @@ sure to also change the following storage method and table_viewer.prepare_data i myStreet0_3B4BDone = True #steal calculations - if base == "hold": - if len(player_ids)>=5: #no point otherwise + if base=="hold": + if len(player_ids)>=3: # no point otherwise # was 5, use 3 to match pokertracker definition if positions[player]==1: - if firstPfRaiserId==player_ids[player]: - myStealAttemptChance=True + if firstPfRaiserId==player_ids[player] \ + and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo): myStealAttempted=True - elif firstPfRaiserId==buttonId or firstPfRaiserId==sbId or firstPfRaiserId==bbId or firstPfRaiserId==-1: + myStealAttemptChance=True + if firstPlayId==cutoffId or firstPlayId==buttonId or firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1: myStealAttemptChance=True if positions[player]==0: - if firstPfRaiserId==player_ids[player]: - myStealAttemptChance=True + if firstPfRaiserId==player_ids[player] \ + and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo): myStealAttempted=True - elif firstPfRaiserId==sbId or firstPfRaiserId==bbId or firstPfRaiserId==-1: + myStealAttemptChance=True + if firstPlayId==buttonId or firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1: myStealAttemptChance=True if positions[player]=='S': - if firstPfRaiserId==player_ids[player]: - myStealAttemptChance=True + if firstPfRaiserId==player_ids[player] \ + and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo): myStealAttempted=True - elif firstPfRaiserId==bbId or firstPfRaiserId==-1: + myStealAttemptChance=True + if firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1: myStealAttemptChance=True if positions[player]=='B': pass From 2efc6f1c8e8b79d2d8d8e666819e7ad18e504833 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 27 Apr 2009 21:29:02 +0100 Subject: [PATCH 043/104] use lower case for keys into stat_dict as postgres returns column names in lower case --- pyfpdb/Database.py | 2 +- pyfpdb/Stats.py | 38 ++++++++++++++++++++------------------ 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 154edec5..f575266a 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -186,7 +186,7 @@ class Database: 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 t_dict['screen_name'] = names[t_dict['player_id']] t_dict['seat'] = seats[t_dict['player_id']] diff --git a/pyfpdb/Stats.py b/pyfpdb/Stats.py index 0870c73e..368552bc 100644 --- a/pyfpdb/Stats.py +++ b/pyfpdb/Stats.py @@ -32,6 +32,8 @@ # float(stat_dict[player]['vpip'])/float(stat_dict[player]['n']). You can see how the # keys of stat_dict relate to the column names in HudCache by inspecting # the proper section of the SQL.py module. +# The stat_dict keys should be in lower case, i.e. vpip not VPIP, since +# postgres returns the column names in lower case. # 3 You have to write a small function for each stat you want to add. See # the vpip() function for example. This function has to be protected from # exceptions, using something like the try:/except: paragraphs in vpip. @@ -309,12 +311,12 @@ def f_SB_steal(stat_dict, player): """ Folded SB to steal.""" stat = 0.0 try: - stat = float(stat_dict[player]['SBnotDef'])/float(stat_dict[player]['SBstolen']) + stat = float(stat_dict[player]['sbnotdef'])/float(stat_dict[player]['sbstolen']) return (stat, '%3.1f' % (100*stat) + '%', 'fSB=%3.1f' % (100*stat) + '%', 'fSB_s=%3.1f' % (100*stat) + '%', - '(%d/%d)' % (stat_dict[player]['SBnotDef'], stat_dict[player]['SBstolen']), + '(%d/%d)' % (stat_dict[player]['sbnotdef'], stat_dict[player]['sbstolen']), '% folded SB to steal' ) except: @@ -329,12 +331,12 @@ def f_BB_steal(stat_dict, player): """ Folded BB to steal.""" stat = 0.0 try: - stat = float(stat_dict[player]['BBnotDef'])/float(stat_dict[player]['BBstolen']) + stat = float(stat_dict[player]['bbnotdef'])/float(stat_dict[player]['bbstolen']) return (stat, '%3.1f' % (100*stat) + '%', 'fBB=%3.1f' % (100*stat) + '%', 'fBB_s=%3.1f' % (100*stat) + '%', - '(%d/%d)' % (stat_dict[player]['BBnotDef'], stat_dict[player]['BBstolen']), + '(%d/%d)' % (stat_dict[player]['bbnotdef'], stat_dict[player]['bbstolen']), '% folded BB to steal' ) except: @@ -349,12 +351,12 @@ def three_B_0(stat_dict, player): """ Three bet preflop/3rd.""" stat = 0.0 try: - stat = float(stat_dict[player]['TB_0'])/float(stat_dict[player]['TB_opp_0']) + stat = float(stat_dict[player]['tb_0'])/float(stat_dict[player]['tb_opp_0']) return (stat, '%3.1f' % (100*stat) + '%', '3B=%3.1f' % (100*stat) + '%', '3B_pf=%3.1f' % (100*stat) + '%', - '(%d/%d)' % (stat_dict[player]['TB_0'], stat_dict[player]['TB_opp_0']), + '(%d/%d)' % (stat_dict[player]['tb_0'], stat_dict[player]['tb_opp_0']), '% 3/4 Bet preflop/3rd' ) except: @@ -530,12 +532,12 @@ def cb_1(stat_dict, player): """ Flop continuation bet.""" stat = 0.0 try: - stat = float(stat_dict[player]['CB_1'])/float(stat_dict[player]['CB_opp_1']) + stat = float(stat_dict[player]['cb_1'])/float(stat_dict[player]['cb_opp_1']) return (stat, '%3.1f' % (100*stat) + '%', 'cb1=%3.1f' % (100*stat) + '%', 'cb_1=%3.1f' % (100*stat) + '%', - '(%d/%d)' % (stat_dict[player]['CB_1'], stat_dict[player]['CB_opp_1']), + '(%d/%d)' % (stat_dict[player]['cb_1'], stat_dict[player]['cb_opp_1']), '% continuation bet flop/4th' ) except: @@ -551,12 +553,12 @@ def cb_2(stat_dict, player): """ Turn continuation bet.""" stat = 0.0 try: - stat = float(stat_dict[player]['CB_2'])/float(stat_dict[player]['CB_opp_2']) + stat = float(stat_dict[player]['cb_2'])/float(stat_dict[player]['cb_opp_2']) return (stat, '%3.1f' % (100*stat) + '%', 'cb2=%3.1f' % (100*stat) + '%', 'cb_2=%3.1f' % (100*stat) + '%', - '(%d/%d)' % (stat_dict[player]['CB_2'], stat_dict[player]['CB_opp_2']), + '(%d/%d)' % (stat_dict[player]['cb_2'], stat_dict[player]['cb_opp_2']), '% continuation bet turn/5th' ) except: @@ -572,12 +574,12 @@ def cb_3(stat_dict, player): """ River continuation bet.""" stat = 0.0 try: - stat = float(stat_dict[player]['CB_3'])/float(stat_dict[player]['CB_opp_3']) + stat = float(stat_dict[player]['cb_3'])/float(stat_dict[player]['cb_opp_3']) return (stat, '%3.1f' % (100*stat) + '%', 'cb3=%3.1f' % (100*stat) + '%', 'cb_3=%3.1f' % (100*stat) + '%', - '(%d/%d)' % (stat_dict[player]['CB_3'], stat_dict[player]['CB_opp_3']), + '(%d/%d)' % (stat_dict[player]['cb_3'], stat_dict[player]['cb_opp_3']), '% continuation bet river/6th' ) except: @@ -593,12 +595,12 @@ def cb_4(stat_dict, player): """ 7th street continuation bet.""" stat = 0.0 try: - stat = float(stat_dict[player]['CB_4'])/float(stat_dict[player]['CB_opp_4']) + stat = float(stat_dict[player]['cb_4'])/float(stat_dict[player]['cb_opp_4']) return (stat, '%3.1f' % (100*stat) + '%', 'cb4=%3.1f' % (100*stat) + '%', 'cb_4=%3.1f' % (100*stat) + '%', - '(%d/%d)' % (stat_dict[player]['CB_4'], stat_dict[player]['CB_opp_4']), + '(%d/%d)' % (stat_dict[player]['cb_4'], stat_dict[player]['cb_opp_4']), '% continuation bet 7th' ) except: @@ -712,10 +714,10 @@ if __name__== "__main__": print "player = ", player, do_stat(stat_dict, player = player, stat = 'fold_f') print "player = ", player, do_stat(stat_dict, player = player, stat = 'wmsd') print "player = ", player, do_stat(stat_dict, player = player, stat = 'steal') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'f_SB_steal') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'f_BB_steal') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'three_B_0') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'WMsF') + print "player = ", player, do_stat(stat_dict, player = player, stat = 'f_sb_steal') + print "player = ", player, do_stat(stat_dict, player = player, stat = 'f_bb_steal') + print "player = ", player, do_stat(stat_dict, player = player, stat = 'three_b_0') + print "player = ", player, do_stat(stat_dict, player = player, stat = 'wmsf') print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_1') print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_2') print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_3') From f6311276a77a64c3742d803c043ac8291b3923b6 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 28 Apr 2009 14:50:50 +0800 Subject: [PATCH 044/104] Remove some merge noise --- pyfpdb/fpdb.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 3e0b4337..36ff556f 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -267,7 +267,6 @@ class fpdb: self.settings['db-databaseName'], self.settings['db-user'], self.settings['db-password']) -<<<<<<< HEAD:pyfpdb/fpdb.py if self.db.wrongDbVersion: diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) From d28bdf7c6005d6cf59109ef0efd150a60efd5b38 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 28 Apr 2009 22:47:05 +0100 Subject: [PATCH 045/104] added a few more stats with no decimal places --- pyfpdb/Stats.py | 83 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/pyfpdb/Stats.py b/pyfpdb/Stats.py index 368552bc..42cd503e 100644 --- a/pyfpdb/Stats.py +++ b/pyfpdb/Stats.py @@ -184,6 +184,27 @@ def wtsd(stat_dict, player): '% went to showdown' ) +def wtsd_0(stat_dict, player): + """ Went to SD when saw flop/4th.""" + stat = 0.0 + try: + stat = float(stat_dict[player]['sd'])/float(stat_dict[player]['saw_f']) + return (stat, + '%2.0f' % (100*stat) + '%', + 'w=%2.0f' % (100*stat) + '%', + 'wtsd=%2.0f' % (100*stat) + '%', + '(%d/%d)' % (stat_dict[player]['sd'], stat_dict[player]['saw_f']), + '% went to showdown' + ) + except: + return (stat, + '%2.0f' % (0) + '%', + 'w=%2.0f' % (0) + '%', + 'wtsd=%2.0f' % (0) + '%', + '(%d/%d)' % (0, 0), + '% went to showdown' + ) + def wmsd(stat_dict, player): """ Won $ at showdown.""" stat = 0.0 @@ -205,6 +226,27 @@ def wmsd(stat_dict, player): '% won money at showdown' ) +def wmsd_0(stat_dict, player): + """ Won $ at showdown.""" + stat = 0.0 + try: + stat = float(stat_dict[player]['wmsd'])/float(stat_dict[player]['sd']) + return (stat, + '%2.0f' % (100*stat) + '%', + 'w=%2.0f' % (100*stat) + '%', + 'wmsd=%2.0f' % (100*stat) + '%', + '(%5.1f/%d)' % (float(stat_dict[player]['wmsd']), stat_dict[player]['sd']), + '% won money at showdown' + ) + except: + return (stat, + '%2.0f' % (0) + '%', + 'w=%2.0f' % (0) + '%', + 'wmsd=%2.0f' % (0) + '%', + '(%d/%d)' % (0, 0), + '% won money at showdown' + ) + def profit100_0(stat_dict, player): """ Profit won per 100 hands (no decimal places).""" stat = 0.0 @@ -306,6 +348,27 @@ def steal(stat_dict, player): ) except: return (stat, 'NA', 'st=NA', 'steal=NA', '(0/0)', '% steal attempted') + +def steal_0(stat_dict, player): + """ Steal %.""" + stat = 0.0 + try: + stat = float(stat_dict[player]['steal'])/float(stat_dict[player]['steal_opp']) + return (stat, + '%2.0f' % (100*stat) + '%', + 'st=%2.0f' % (100*stat) + '%', + 'steal=%2.0f' % (100*stat) + '%', + '(%d/%d)' % (stat_dict[player]['steal'], stat_dict[player]['steal_opp']), + '% steal attempted' + ) + except: + return (stat, + '%2.0f' % (0) + '%', + 'st=%2.0f' % (0) + '%', + 'steal=%2.0f' % (0) + '%', + '(%d/%d)' % (0, 0), + '% steal attempted' + ) def f_SB_steal(stat_dict, player): """ Folded SB to steal.""" @@ -347,6 +410,26 @@ def f_BB_steal(stat_dict, player): '(0/0)', '% folded BB to steal') +def f_BB_steal_0(stat_dict, player): + """ Folded BB to steal.""" + stat = 0.0 + try: + stat = float(stat_dict[player]['bbnotdef'])/float(stat_dict[player]['bbstolen']) + return (stat, + '%2.0f' % (100*stat) + '%', + 'fBB=%2.0f' % (100*stat) + '%', + 'fBB_s=%2.0f' % (100*stat) + '%', + '(%d/%d)' % (stat_dict[player]['bbnotdef'], stat_dict[player]['bbstolen']), + '% folded BB to steal' + ) + except: + return (stat, + 'NA', + 'fBB=NA', + 'fBB_s=NA', + '(0/0)', + '% folded BB to steal') + def three_B_0(stat_dict, player): """ Three bet preflop/3rd.""" stat = 0.0 From 6504cd38a622f637138211ae56f7bc8086350d16 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 30 Apr 2009 00:16:39 +0800 Subject: [PATCH 046/104] use lower case for keys into stat_dict as postgres returns column names in lower case Conflicts: pyfpdb/Database.py --- pyfpdb/Database.py | 5 ++++- pyfpdb/Stats.py | 38 ++++++++++++++++++++------------------ 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 3fba5c5e..94489525 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -200,7 +200,10 @@ class Database: 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 + t_dict['screen_name'] = names[t_dict['player_id']] + t_dict['seat'] = seats[t_dict['player_id']] stat_dict[t_dict['player_id']] = t_dict return stat_dict diff --git a/pyfpdb/Stats.py b/pyfpdb/Stats.py index 8c33f3a1..16fdc845 100644 --- a/pyfpdb/Stats.py +++ b/pyfpdb/Stats.py @@ -32,6 +32,8 @@ # float(stat_dict[player]['vpip'])/float(stat_dict[player]['n']). You can see how the # keys of stat_dict relate to the column names in HudCache by inspecting # the proper section of the SQL.py module. +# The stat_dict keys should be in lower case, i.e. vpip not VPIP, since +# postgres returns the column names in lower case. # 3 You have to write a small function for each stat you want to add. See # the vpip() function for example. This function has to be protected from # exceptions, using something like the try:/except: paragraphs in vpip. @@ -316,12 +318,12 @@ def f_SB_steal(stat_dict, player): """ Folded SB to steal.""" stat = 0.0 try: - stat = float(stat_dict[player]['SBnotDef'])/float(stat_dict[player]['SBstolen']) + stat = float(stat_dict[player]['sbnotdef'])/float(stat_dict[player]['sbstolen']) return (stat, '%3.1f' % (100*stat) + '%', 'fSB=%3.1f' % (100*stat) + '%', 'fSB_s=%3.1f' % (100*stat) + '%', - '(%d/%d)' % (stat_dict[player]['SBnotDef'], stat_dict[player]['SBstolen']), + '(%d/%d)' % (stat_dict[player]['sbnotdef'], stat_dict[player]['sbstolen']), '% folded SB to steal' ) except: @@ -336,12 +338,12 @@ def f_BB_steal(stat_dict, player): """ Folded BB to steal.""" stat = 0.0 try: - stat = float(stat_dict[player]['BBnotDef'])/float(stat_dict[player]['BBstolen']) + stat = float(stat_dict[player]['bbnotdef'])/float(stat_dict[player]['bbstolen']) return (stat, '%3.1f' % (100*stat) + '%', 'fBB=%3.1f' % (100*stat) + '%', 'fBB_s=%3.1f' % (100*stat) + '%', - '(%d/%d)' % (stat_dict[player]['BBnotDef'], stat_dict[player]['BBstolen']), + '(%d/%d)' % (stat_dict[player]['bbnotdef'], stat_dict[player]['bbstolen']), '% folded BB to steal' ) except: @@ -356,12 +358,12 @@ def three_B_0(stat_dict, player): """ Three bet preflop/3rd.""" stat = 0.0 try: - stat = float(stat_dict[player]['TB_0'])/float(stat_dict[player]['TB_opp_0']) + stat = float(stat_dict[player]['tb_0'])/float(stat_dict[player]['tb_opp_0']) return (stat, '%3.1f' % (100*stat) + '%', '3B=%3.1f' % (100*stat) + '%', '3B_pf=%3.1f' % (100*stat) + '%', - '(%d/%d)' % (stat_dict[player]['TB_0'], stat_dict[player]['TB_opp_0']), + '(%d/%d)' % (stat_dict[player]['tb_0'], stat_dict[player]['tb_opp_0']), '% 3/4 Bet preflop/3rd' ) except: @@ -537,12 +539,12 @@ def cb_1(stat_dict, player): """ Flop continuation bet.""" stat = 0.0 try: - stat = float(stat_dict[player]['CB_1'])/float(stat_dict[player]['CB_opp_1']) + stat = float(stat_dict[player]['cb_1'])/float(stat_dict[player]['cb_opp_1']) return (stat, '%3.1f' % (100*stat) + '%', 'cb1=%3.1f' % (100*stat) + '%', 'cb_1=%3.1f' % (100*stat) + '%', - '(%d/%d)' % (stat_dict[player]['CB_1'], stat_dict[player]['CB_opp_1']), + '(%d/%d)' % (stat_dict[player]['cb_1'], stat_dict[player]['cb_opp_1']), '% continuation bet flop/4th' ) except: @@ -558,12 +560,12 @@ def cb_2(stat_dict, player): """ Turn continuation bet.""" stat = 0.0 try: - stat = float(stat_dict[player]['CB_2'])/float(stat_dict[player]['CB_opp_2']) + stat = float(stat_dict[player]['cb_2'])/float(stat_dict[player]['cb_opp_2']) return (stat, '%3.1f' % (100*stat) + '%', 'cb2=%3.1f' % (100*stat) + '%', 'cb_2=%3.1f' % (100*stat) + '%', - '(%d/%d)' % (stat_dict[player]['CB_2'], stat_dict[player]['CB_opp_2']), + '(%d/%d)' % (stat_dict[player]['cb_2'], stat_dict[player]['cb_opp_2']), '% continuation bet turn/5th' ) except: @@ -579,12 +581,12 @@ def cb_3(stat_dict, player): """ River continuation bet.""" stat = 0.0 try: - stat = float(stat_dict[player]['CB_3'])/float(stat_dict[player]['CB_opp_3']) + stat = float(stat_dict[player]['cb_3'])/float(stat_dict[player]['cb_opp_3']) return (stat, '%3.1f' % (100*stat) + '%', 'cb3=%3.1f' % (100*stat) + '%', 'cb_3=%3.1f' % (100*stat) + '%', - '(%d/%d)' % (stat_dict[player]['CB_3'], stat_dict[player]['CB_opp_3']), + '(%d/%d)' % (stat_dict[player]['cb_3'], stat_dict[player]['cb_opp_3']), '% continuation bet river/6th' ) except: @@ -600,12 +602,12 @@ def cb_4(stat_dict, player): """ 7th street continuation bet.""" stat = 0.0 try: - stat = float(stat_dict[player]['CB_4'])/float(stat_dict[player]['CB_opp_4']) + stat = float(stat_dict[player]['cb_4'])/float(stat_dict[player]['cb_opp_4']) return (stat, '%3.1f' % (100*stat) + '%', 'cb4=%3.1f' % (100*stat) + '%', 'cb_4=%3.1f' % (100*stat) + '%', - '(%d/%d)' % (stat_dict[player]['CB_4'], stat_dict[player]['CB_opp_4']), + '(%d/%d)' % (stat_dict[player]['cb_4'], stat_dict[player]['cb_opp_4']), '% continuation bet 7th' ) except: @@ -719,10 +721,10 @@ if __name__== "__main__": print "player = ", player, do_stat(stat_dict, player = player, stat = 'fold_f') print "player = ", player, do_stat(stat_dict, player = player, stat = 'wmsd') print "player = ", player, do_stat(stat_dict, player = player, stat = 'steal') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'f_SB_steal') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'f_BB_steal') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'three_B_0') - print "player = ", player, do_stat(stat_dict, player = player, stat = 'WMsF') + print "player = ", player, do_stat(stat_dict, player = player, stat = 'f_sb_steal') + print "player = ", player, do_stat(stat_dict, player = player, stat = 'f_bb_steal') + print "player = ", player, do_stat(stat_dict, player = player, stat = 'three_b_0') + print "player = ", player, do_stat(stat_dict, player = player, stat = 'wmsf') print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_1') print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_2') print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_3') From fd804f443147c5a824a525ff47ab9834f719ea16 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 28 Apr 2009 22:47:05 +0100 Subject: [PATCH 047/104] added a few more stats with no decimal places --- pyfpdb/Stats.py | 83 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/pyfpdb/Stats.py b/pyfpdb/Stats.py index 16fdc845..eddb0e25 100644 --- a/pyfpdb/Stats.py +++ b/pyfpdb/Stats.py @@ -191,6 +191,27 @@ def wtsd(stat_dict, player): '% went to showdown' ) +def wtsd_0(stat_dict, player): + """ Went to SD when saw flop/4th.""" + stat = 0.0 + try: + stat = float(stat_dict[player]['sd'])/float(stat_dict[player]['saw_f']) + return (stat, + '%2.0f' % (100*stat) + '%', + 'w=%2.0f' % (100*stat) + '%', + 'wtsd=%2.0f' % (100*stat) + '%', + '(%d/%d)' % (stat_dict[player]['sd'], stat_dict[player]['saw_f']), + '% went to showdown' + ) + except: + return (stat, + '%2.0f' % (0) + '%', + 'w=%2.0f' % (0) + '%', + 'wtsd=%2.0f' % (0) + '%', + '(%d/%d)' % (0, 0), + '% went to showdown' + ) + def wmsd(stat_dict, player): """ Won $ at showdown.""" stat = 0.0 @@ -212,6 +233,27 @@ def wmsd(stat_dict, player): '% won money at showdown' ) +def wmsd_0(stat_dict, player): + """ Won $ at showdown.""" + stat = 0.0 + try: + stat = float(stat_dict[player]['wmsd'])/float(stat_dict[player]['sd']) + return (stat, + '%2.0f' % (100*stat) + '%', + 'w=%2.0f' % (100*stat) + '%', + 'wmsd=%2.0f' % (100*stat) + '%', + '(%5.1f/%d)' % (float(stat_dict[player]['wmsd']), stat_dict[player]['sd']), + '% won money at showdown' + ) + except: + return (stat, + '%2.0f' % (0) + '%', + 'w=%2.0f' % (0) + '%', + 'wmsd=%2.0f' % (0) + '%', + '(%d/%d)' % (0, 0), + '% won money at showdown' + ) + def profit100_0(stat_dict, player): """ Profit won per 100 hands (no decimal places).""" stat = 0.0 @@ -313,6 +355,27 @@ def steal(stat_dict, player): ) except: return (stat, 'NA', 'st=NA', 'steal=NA', '(0/0)', '% steal attempted') + +def steal_0(stat_dict, player): + """ Steal %.""" + stat = 0.0 + try: + stat = float(stat_dict[player]['steal'])/float(stat_dict[player]['steal_opp']) + return (stat, + '%2.0f' % (100*stat) + '%', + 'st=%2.0f' % (100*stat) + '%', + 'steal=%2.0f' % (100*stat) + '%', + '(%d/%d)' % (stat_dict[player]['steal'], stat_dict[player]['steal_opp']), + '% steal attempted' + ) + except: + return (stat, + '%2.0f' % (0) + '%', + 'st=%2.0f' % (0) + '%', + 'steal=%2.0f' % (0) + '%', + '(%d/%d)' % (0, 0), + '% steal attempted' + ) def f_SB_steal(stat_dict, player): """ Folded SB to steal.""" @@ -354,6 +417,26 @@ def f_BB_steal(stat_dict, player): '(0/0)', '% folded BB to steal') +def f_BB_steal_0(stat_dict, player): + """ Folded BB to steal.""" + stat = 0.0 + try: + stat = float(stat_dict[player]['bbnotdef'])/float(stat_dict[player]['bbstolen']) + return (stat, + '%2.0f' % (100*stat) + '%', + 'fBB=%2.0f' % (100*stat) + '%', + 'fBB_s=%2.0f' % (100*stat) + '%', + '(%d/%d)' % (stat_dict[player]['bbnotdef'], stat_dict[player]['bbstolen']), + '% folded BB to steal' + ) + except: + return (stat, + 'NA', + 'fBB=NA', + 'fBB_s=NA', + '(0/0)', + '% folded BB to steal') + def three_B_0(stat_dict, player): """ Three bet preflop/3rd.""" stat = 0.0 From a4662012857497764a84a77ddc2ae5ec5a0c6942 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 29 Apr 2009 23:27:53 +0100 Subject: [PATCH 048/104] fix tab error on inserted line - change to spaces --- pyfpdb/fpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index a7d7b444..20e0ff11 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -287,7 +287,7 @@ class fpdb: # Database connected to successfully, load queries to pass on to other classes self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) - self.db.db.rollback() + self.db.db.rollback() #end def load_profile def not_implemented(self): From 2c991ad2d060943291e41721c0c2a3bb89026bac Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sat, 2 May 2009 00:28:53 +0100 Subject: [PATCH 049/104] sql and cursor execute bugfixes to make it work with postgres --- pyfpdb/Database.py | 4 ++-- pyfpdb/SQL.py | 4 +++- pyfpdb/fpdb_simple.py | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index a0b08992..932a08dd 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -120,7 +120,7 @@ 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] for row in c.fetchall(): s_dict = {} @@ -133,7 +133,7 @@ class Database: """Get and return the community cards for the specified hand.""" cards = {} c = self.connection.cursor() - c.execute(self.sql.query['get_common_cards'], hand) + c.execute(self.sql.query['get_common_cards'], [hand]) colnames = [desc[0] for desc in c.description] for row in c.fetchall(): s_dict = {} diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index c9314305..d9904225 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -173,6 +173,8 @@ class Sql: self.query['get_stats_from_hand'] = """ SELECT HudCache.playerId AS player_id, + HandsPlayers.seatNo AS seat, + Players.name AS screen_name, seatNo AS seat, name AS screen_name, sum(HDs) AS n, @@ -237,7 +239,7 @@ class Sql: AND HudCache.gametypeId+0 = Hands.gametypeId+0) INNER JOIN Players ON (Players.id = HandsPlayers.PlayerId+0) WHERE Hands.id = %s - GROUP BY HudCache.PlayerId + GROUP BY HudCache.PlayerId, HandsPlayers.seatNo, Players.name """ # same as above except stats are aggregated for all blind/limit levels diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index 73fe06c9..e9093fbc 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -1411,7 +1411,7 @@ def recognisePlayerIDs(cursor, names, site_id): if len(ids) != len(names): notfound = [n for n in names if n not in ids] # make list of names not in database if notfound: # insert them into database - cursor.executemany("INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")", (notfound)) + cursor.executemany("INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")", [[n] for n in notfound]) q2 = "SELECT name,id FROM Players WHERE name=%s" % " OR name=".join(["%s" for n in notfound]) cursor.execute(q2, notfound) # get their new ids tmp = dict(cursor.fetchall()) From 882f19a34d4d7a9daea6402720fc474fc40b8a5b Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sat, 2 May 2009 21:07:52 +0100 Subject: [PATCH 050/104] removed redundant db variable --- pyfpdb/GuiBulkImport.py | 7 ++----- pyfpdb/fpdb.py | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/pyfpdb/GuiBulkImport.py b/pyfpdb/GuiBulkImport.py index dbf56152..8a047769 100755 --- a/pyfpdb/GuiBulkImport.py +++ b/pyfpdb/GuiBulkImport.py @@ -30,7 +30,6 @@ import gtk # fpdb/FreePokerTools modules import fpdb_simple import fpdb_import -import fpdb_db import Configuration class GuiBulkImport(): @@ -83,8 +82,7 @@ class GuiBulkImport(): """returns the vbox of this thread""" return self.vbox - def __init__(self, db, settings, config): - self.db = db # this is an instance of fpdb_db + def __init__(self, settings, config): self.settings = settings self.config = config self.importer = fpdb_import.Importer(self, self.settings, @@ -227,7 +225,6 @@ def main(argv=None): (options, sys.argv) = parser.parse_args(args = argv) config = Configuration.Config() - db = None settings = {} settings['minPrint'] = options.minPrint @@ -243,7 +240,7 @@ def main(argv=None): print '-q is deprecated. Just use "-f filename" instead' # This is because -q on its own causes an error, so -f is necessary and sufficient for cmd line use if not options.filename: - i = GuiBulkImport(db, settings, config) + i = GuiBulkImport(settings, config) main_window = gtk.Window() main_window.connect('destroy', destroy) main_window.add(i.vbox) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 36ff556f..42c9c6bc 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -324,7 +324,7 @@ class fpdb: def tab_bulk_import(self, widget, data): """opens a tab for bulk importing""" #print "start of tab_bulk_import" - new_import_thread=GuiBulkImport.GuiBulkImport(self.db, self.settings, self.config) + new_import_thread=GuiBulkImport.GuiBulkImport(self.settings, self.config) self.threads.append(new_import_thread) bulk_tab=new_import_thread.get_vbox() self.add_and_display_tab(bulk_tab, "Bulk Import") From 79b3dba2dd1f66ac3d626848492e62cc2892e067 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sat, 2 May 2009 21:32:47 +0100 Subject: [PATCH 051/104] add steal stat to playerstats --- pyfpdb/FpdbSQLQueries.py | 8 ++++++++ pyfpdb/GuiPlayerStats.py | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index fca17a5f..55d56650 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -641,6 +641,7 @@ class FpdbSQLQueries: ,stats.n ,stats.vpip ,stats.pfr + ,stats.steals ,stats.saw_f ,stats.sawsd ,stats.wtsdwsf @@ -671,6 +672,9 @@ class FpdbSQLQueries: ,sum(HDs) AS n ,format(100.0*sum(street0VPI)/sum(HDs),1) AS vpip ,format(100.0*sum(street0Aggr)/sum(HDs),1) AS pfr + ,case when sum(stealattemptchance) = 0 then '0' + 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 'oo' @@ -740,6 +744,7 @@ class FpdbSQLQueries: ,stats.n ,stats.vpip ,stats.pfr + ,stats.steals ,stats.saw_f ,stats.sawsd ,stats.wtsdwsf @@ -769,6 +774,9 @@ class FpdbSQLQueries: ,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 + ,case when sum(stealattemptchance) = 0 then '0' + 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 'oo' diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 213d7535..1a6fbadb 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -118,7 +118,7 @@ class GuiPlayerStats (threading.Thread): self.cursor.execute(tmp) result = self.cursor.fetchall() - cols = 16 + cols = 17 rows = len(result)+1 # +1 for title row self.stats_table = gtk.Table(rows, cols, False) self.stats_table.set_col_spacings(4) @@ -126,7 +126,7 @@ class GuiPlayerStats (threading.Thread): vbox.add(self.stats_table) # Create header row - titles = ("Game", "Hands", "VPIP", "PFR", "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq", "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance") + titles = ("Game", "Hands", "VPIP", "PFR", "Steals", "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq", "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance") col = 0 row = 0 From 5111eb1a8f88f18bb29b7ad65a85b72b2f30e110 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sat, 2 May 2009 21:39:48 +0100 Subject: [PATCH 052/104] remove redundant db variable --- pyfpdb/GuiPlayerStats.py | 4 ++-- pyfpdb/fpdb.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 1a6fbadb..0c7729dc 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -27,7 +27,7 @@ import Filters import FpdbSQLQueries class GuiPlayerStats (threading.Thread): - def __init__(self, db, config, querylist, debug=True): + def __init__(self, config, querylist, debug=True): self.debug=debug self.conf=config @@ -52,7 +52,7 @@ class GuiPlayerStats (threading.Thread): "Button2" : False } - self.filters = Filters.Filters(db, settings, config, querylist, display = filters_display) + self.filters = Filters.Filters(self.db, settings, config, querylist, display = filters_display) self.stat_table = None self.stats_frame = None diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 42c9c6bc..3ed004ef 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -331,7 +331,7 @@ class fpdb: #end def tab_bulk_import def tab_player_stats(self, widget, data): - new_ps_thread=GuiPlayerStats.GuiPlayerStats(self.db, self.config, self.querydict) + new_ps_thread=GuiPlayerStats.GuiPlayerStats(self.config, self.querydict) self.threads.append(new_ps_thread) ps_tab=new_ps_thread.get_vbox() self.add_and_display_tab(ps_tab, "Player Stats") From 1b82ad7f65095318790192943d02c9ac33ea210f Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 3 May 2009 01:24:10 +0100 Subject: [PATCH 053/104] re-fix a couple of errors from previous merges --- pyfpdb/Database.py | 2 -- pyfpdb/SQL.py | 2 -- 2 files changed, 4 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index f2575f5f..0e5c1547 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -202,8 +202,6 @@ class Database: for name, val in zip(colnames, row): t_dict[name.lower()] = val # print t_dict - t_dict['screen_name'] = names[t_dict['player_id']] - t_dict['seat'] = seats[t_dict['player_id']] stat_dict[t_dict['player_id']] = t_dict return stat_dict diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index d9904225..322b7fa0 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -175,8 +175,6 @@ class Sql: SELECT HudCache.playerId AS player_id, HandsPlayers.seatNo AS seat, Players.name AS screen_name, - seatNo AS seat, - name AS screen_name, sum(HDs) AS n, sum(street0VPI) AS vpip, sum(street0Aggr) AS pfr, From fddb29b3b80d2cc95486d50c8859f7f04efaf8cb Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 3 May 2009 01:31:15 +0100 Subject: [PATCH 054/104] add steal stat to positional stats and fix for postgres --- pyfpdb/FpdbSQLQueries.py | 210 +++++++++++++++++++++++++---------- pyfpdb/GuiPositionalStats.py | 7 +- 2 files changed, 155 insertions(+), 62 deletions(-) diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index 55d56650..c905170e 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -670,13 +670,13 @@ class FpdbSQLQueries: ,gt.bigBlind ,hc.gametypeId ,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(street0VPI)/sum(HDs),1) AS vpip + ,format(100.0*sum(street0Aggr)/sum(HDs),1) AS pfr ,case when sum(stealattemptchance) = 0 then '0' 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 + ,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' else format(100.0*sum(sawShowdown)/sum(street1Seen),1) end AS wtsdwsf @@ -718,8 +718,8 @@ class FpdbSQLQueries: avg(hprof.profit/100.0) profitperhand, variance(hprof.profit/100.0) variance from - (select hp.handId, h.gameTypeId, hp.winnings, SUM(ha.amount) - costs, hp.winnings - SUM(ha.amount) profit + (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 @@ -860,6 +860,7 @@ class FpdbSQLQueries: ,stats.n ,stats.vpip ,stats.pfr + ,stats.steals ,stats.saw_f ,stats.sawsd ,stats.wtsdwsf @@ -896,10 +897,13 @@ 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 + ,format(100.0*sum(street0VPI)/sum(HDs),1) AS vpip + ,format(100.0*sum(street0Aggr)/sum(HDs),1) AS pfr + ,case when sum(stealattemptchance) = 0 then '0' + 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 'oo' else format(100.0*sum(sawShowdown)/sum(street1Seen),1) end AS wtsdwsf @@ -949,8 +953,8 @@ class FpdbSQLQueries: avg(hprof.profit/100.0) as profitperhand, variance(hprof.profit/100.0) as variance 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 @@ -968,52 +972,138 @@ class FpdbSQLQueries: 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 || ' $' + || trim(leading ' ' from + case when stats.bigBlind < 100 + then to_char(stats.bigBlind/100.0,'90D00') + else to_char(stats.bigBlind/100.0,'999990') + end ) 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.steals + ,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 + /*,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 + */ + ,to_char(hprof2.variance, '0D00') AS Variance + FROM + (select /* stats from hudcache */ + gt.base + ,gt.category + ,upper(gt.limitType) as limitType + ,s.name + ,gt.bigBlind + ,hc.gametypeId + ,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)),'90D0') AS vpip + ,to_char(round(100.0*sum(street0Aggr)/sum(HDs)),'90D0') AS pfr + ,case when sum(stealattemptchance) = 0 then '0' + 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 'NA' + else to_char(round(100.0*sum(sawShowdown)/sum(street1Seen)),'90D0') + end AS wtsdwsf + ,case when sum(sawShowdown) = 0 then 'NA' + else to_char(round(100.0*sum(wonAtSD)/sum(sawShowdown)),'90D0') + end AS wmsd + ,case when sum(street1Seen) = 0 then 'NA' + else to_char(round(100.0*sum(street1Aggr)/sum(street1Seen)),'90D0') + end AS FlAFq + ,case when sum(street2Seen) = 0 then 'NA' + else to_char(round(100.0*sum(street2Aggr)/sum(street2Seen)),'90D0') + end AS TuAFq + ,case when sum(street3Seen) = 0 then 'NA' + else to_char(round(100.0*sum(street3Aggr)/sum(street3Seen)),'90D0') + end AS RvAFq + ,case when sum(street1Seen)+sum(street2Seen)+sum(street3Seen) = 0 then 'NA' + 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 + + 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 ? */ + group by gt.base + ,gt.category + ,upper(gt.limitType) + ,s.name + ,gt.bigBlind + ,hc.gametypeId + ,PlPosition + ) stats + inner join + ( select /* profit from handsplayers/handsactions */ + hprof.gameTypeId, + 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, + variance(hprof.profit/100.0) as variance + from + (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 + 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 + ) hprof2 + on ( hprof2.gameTypeId = stats.gameTypeId + and hprof2.PlPosition = stats.PlPosition) + order by stats.category, stats.limittype, stats.bigBlind, cast(stats.PlPosition as smallint) """ elif(self.dbname == 'SQLite'): self.query['playerStatsByPosition'] = """ """ @@ -1131,8 +1221,8 @@ 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 diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index 587742a3..5e9d1d71 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -120,10 +120,11 @@ class GuiPositionalStats (threading.Thread): nametest = nametest.replace(",)",")") tmp = tmp.replace("", nametest) + #tmp = tmp.replace("", "gt.id") self.cursor.execute(tmp) result = self.cursor.fetchall() - cols = 16 + cols = 18 rows = len(result)+1 # +1 for title row self.stats_table = gtk.Table(rows, cols, False) self.stats_table.set_col_spacings(4) @@ -131,7 +132,7 @@ class GuiPositionalStats (threading.Thread): vbox.add(self.stats_table) # Create header row - titles = ("Game", "Position", "#", "VPIP", "PFR", "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq", "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance") + titles = ("Game", "Position", "#", "VPIP", "PFR", "Steals", "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq", "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance") col = 0 row = 0 @@ -155,6 +156,8 @@ class GuiPositionalStats (threading.Thread): l = gtk.Label(' ') if col == 0: l.set_alignment(xalign=0.0, yalign=0.5) + elif col == 1: + l.set_alignment(xalign=0.5, yalign=0.5) else: l.set_alignment(xalign=1.0, yalign=0.5) eb.add(l) From e60c2542045a0b74bdd6e1d9b2feadfbfc0aee78 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 3 May 2009 01:46:18 +0100 Subject: [PATCH 055/104] add rollback() to make sure db locks are released --- pyfpdb/GuiGraphViewer.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index b1f87989..91de84e1 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -87,6 +87,7 @@ class GuiGraphViewer (threading.Thread): self.canvas = None self.mainHBox.show_all() + self.db.db.rollback() ################################# # @@ -224,6 +225,7 @@ class GuiGraphViewer (threading.Thread): self.cursor.execute(tmp) #returns (HandId,Winnings,Costs,Profit) winnings = self.db.cursor.fetchall() + self.db.db.rollback() if(winnings == ()): return None From f0a77755919e05499835d8e5083f920c7c3a6f5e Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 3 May 2009 10:49:00 +0100 Subject: [PATCH 056/104] add totals lines, enable refresh button to view other players --- pyfpdb/GuiPositionalStats.py | 92 +++++++++++++++++++++++++++++++++--- 1 file changed, 85 insertions(+), 7 deletions(-) diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index 5e9d1d71..837ec28e 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -48,11 +48,13 @@ class GuiPositionalStats (threading.Thread): "Games" : False, "Limits" : False, "Dates" : False, - "Button1" : False, + "Button1" : True, "Button2" : False } self.filters = Filters.Filters(db, settings, config, querylist, display = filters_display) + self.filters.registerButton1Name("Refresh") + self.filters.registerButton1Callback(self.refreshStats) self.stat_table = None self.stats_frame = None @@ -125,8 +127,8 @@ class GuiPositionalStats (threading.Thread): self.cursor.execute(tmp) result = self.cursor.fetchall() cols = 18 - rows = len(result)+1 # +1 for title row - self.stats_table = gtk.Table(rows, cols, False) + rows = len(result) # gtk table expands as required + self.stats_table = gtk.Table(1, cols, False) self.stats_table.set_col_spacings(4) self.stats_table.show() vbox.add(self.stats_table) @@ -142,16 +144,21 @@ class GuiPositionalStats (threading.Thread): self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK) col +=1 - for row in range(rows-1): + last_game = "" + sqlrow = 0 + while sqlrow < rows: if(row%2 == 0): bgcolor = "white" else: bgcolor = "lightgrey" + rowprinted=0 for col in range(cols): eb = gtk.EventBox() eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) - if result[row][col]: - l = gtk.Label(result[row][col]) + # print blank row between levels: + if result[sqlrow][col] and (sqlrow == 0 or result[sqlrow][0] == last_game): + l = gtk.Label(result[sqlrow][col]) + rowprinted=1 else: l = gtk.Label(' ') if col == 0: @@ -164,5 +171,76 @@ class GuiPositionalStats (threading.Thread): self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) l.show() eb.show() - self.db.db.commit() + last_game = result[sqlrow][0] + if rowprinted: + sqlrow = sqlrow+1 + row = row + 1 + + # show totals at bottom + tmp = self.sql.query['playerStats'] + tmp = tmp.replace("", nametest) + self.cursor.execute(tmp) + result = self.cursor.fetchall() + rows = len(result) + + # blank row + col = 0 + if(row%2 == 0): + bgcolor = "white" + else: + bgcolor = "lightgrey" + eb = gtk.EventBox() + eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) + l = gtk.Label(' ') + eb.add(l) + self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) + l.show() + eb.show() + row = row + 1 + + for sqlrow in range(rows): + if(row%2 == 0): + bgcolor = "white" + else: + bgcolor = "lightgrey" + inc = 0 + for col in range(cols): + eb = gtk.EventBox() + eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) + if col == 1: + l = gtk.Label('Totals') + inc = 1 + elif result[sqlrow][col-inc]: + l = gtk.Label(result[sqlrow][col-inc]) + else: + l = gtk.Label(' ') + if col == 0: + l.set_alignment(xalign=0.0, yalign=0.5) + elif col == 1: + l.set_alignment(xalign=0.5, yalign=0.5) + else: + l.set_alignment(xalign=1.0, yalign=0.5) + eb.add(l) + self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) + l.show() + eb.show() + row = row + 1 + + self.db.db.rollback() #end def fillStatsFrame(self, vbox): + + + + + + + + + + + + + + + + From 885f0a023277470a91326b5a6deaed7b9fdb2711 Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 3 May 2009 19:21:21 +0800 Subject: [PATCH 057/104] Fix indentation error from sqlcoder --- pyfpdb/fpdb_simple.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index 0224209a..4413d461 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -190,7 +190,7 @@ def prepareBulkImport(fdb): print "drop index %s_%s_idx" % (idx['tab'],idx['col']) #print "dropped pg index ", idx['tab'], idx['col'] except: - print "! failed drop index %s_%s_idx" % (idx['tab'],idx['col']) + print "! failed drop index %s_%s_idx" % (idx['tab'],idx['col']) else: print "Only MySQL and Postgres supported so far" return -1 From 87f2dde961502130a735912eebe74dc70954e363 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 4 May 2009 02:10:05 +0100 Subject: [PATCH 058/104] add 3bet to stats pages and make column and heading choices configurable by editing lists in the init code --- pyfpdb/FpdbSQLQueries.py | 27 +++++++++++++++---- pyfpdb/GuiPlayerStats.py | 4 +-- pyfpdb/GuiPositionalStats.py | 52 +++++++++++++++++++++++++----------- 3 files changed, 60 insertions(+), 23 deletions(-) diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index c905170e..d5dc7412 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -641,6 +641,7 @@ class FpdbSQLQueries: ,stats.n ,stats.vpip ,stats.pfr + ,stats.pf3 ,stats.steals ,stats.saw_f ,stats.sawsd @@ -672,7 +673,11 @@ class FpdbSQLQueries: ,sum(HDs) AS n ,format(100.0*sum(street0VPI)/sum(HDs),1) AS vpip ,format(100.0*sum(street0Aggr)/sum(HDs),1) AS pfr - ,case when sum(stealattemptchance) = 0 then '0' + ,case when sum(street0_3b4bchance) = 0 then '0' + else format(100.0*sum(street0_3b4bdone)/sum(street0_3b4bchance),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 @@ -744,6 +749,7 @@ class FpdbSQLQueries: ,stats.n ,stats.vpip ,stats.pfr + ,stats.pf3 ,stats.steals ,stats.saw_f ,stats.sawsd @@ -772,13 +778,16 @@ class FpdbSQLQueries: ,gt.bigBlind ,hc.gametypeId ,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(street0VPI)/sum(HDs),'90D0') AS vpip + ,to_char(100.0*sum(street0Aggr)/sum(HDs),'90D0') AS pfr + ,case when sum(street0_3b4bchance) = 0 then '0' + else to_char(100.0*sum(street0_3b4bdone)/sum(street0_3b4bchance),'90D0') + end AS pf3 ,case when sum(stealattemptchance) = 0 then '0' 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 + ,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' else to_char(100.0*sum(sawShowdown)/sum(street1Seen),'90D0') end AS wtsdwsf @@ -860,6 +869,7 @@ class FpdbSQLQueries: ,stats.n ,stats.vpip ,stats.pfr + ,stats.pf3 ,stats.steals ,stats.saw_f ,stats.sawsd @@ -899,6 +909,9 @@ class FpdbSQLQueries: ,sum(HDs) AS n ,format(100.0*sum(street0VPI)/sum(HDs),1) AS vpip ,format(100.0*sum(street0Aggr)/sum(HDs),1) AS pfr + ,case when sum(street0_3b4bchance) = 0 then '0' + else format(100.0*sum(street0_3b4bdone)/sum(street0_3b4bchance),1) + end AS pf3 ,case when sum(stealattemptchance) = 0 then '0' else format(100.0*sum(stealattempted)/sum(stealattemptchance),1) end AS steals @@ -991,6 +1004,7 @@ class FpdbSQLQueries: ,stats.n ,stats.vpip ,stats.pfr + ,stats.pf3 ,stats.steals ,stats.saw_f ,stats.sawsd @@ -1031,6 +1045,9 @@ class FpdbSQLQueries: ,to_char(round(100.0*sum(street0VPI)/sum(HDs)),'90D0') AS vpip ,to_char(round(100.0*sum(street0Aggr)/sum(HDs)),'90D0') AS pfr + ,case when sum(street0_3b4bchance) = 0 then '0' + else to_char(100.0*sum(street0_3b4bdone)/sum(street0_3b4bchance),'90D0') + end AS pf3 ,case when sum(stealattemptchance) = 0 then '0' else to_char(100.0*sum(stealattempted)/sum(stealattemptchance),'90D0') end AS steals diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 0c7729dc..e3ab446c 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -118,7 +118,7 @@ class GuiPlayerStats (threading.Thread): self.cursor.execute(tmp) result = self.cursor.fetchall() - cols = 17 + cols = 18 rows = len(result)+1 # +1 for title row self.stats_table = gtk.Table(rows, cols, False) self.stats_table.set_col_spacings(4) @@ -126,7 +126,7 @@ class GuiPlayerStats (threading.Thread): vbox.add(self.stats_table) # Create header row - titles = ("Game", "Hands", "VPIP", "PFR", "Steals", "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq", "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance") + titles = ("Game", "Hands", "VPIP", "PFR", "PF3", "Steals", "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq", "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance") col = 0 row = 0 diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index 837ec28e..70a877f0 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -68,12 +68,27 @@ class GuiPositionalStats (threading.Thread): self.stats_frame = gtk.VBox(False, 0) self.stats_frame.show() + # This could be stored in config eventually, or maybe configured in this window somehow. + # Each posncols element is the name of a column returned by the sql + # query (in lower case) and each posnheads element is the text to use as + # the heading in the GUI. Both sequences should be the same length. + # To miss columns out remove them from both tuples (the 1st 2 elements should always be included). + # To change the heading just edit the second list element as required + # If the first list element does not match a query column that pair is ignored + self.posncols = ( "game", "plposition", "vpip", "pfr", "pf3", "steals" + , "saw_f", "sawsd", "wtsdwsf", "wmsd", "flafq", "tuafq", "rvafq" + , "pofafq", "net", "bbper100", "profitperhand", "variance", "n" ) + self.posnheads = ( "Game", "Posn", "VPIP", "PFR", "PF3", "Steals" + , "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq" + , "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance", "Hds" ) + self.fillStatsFrame(self.stats_frame) statsFrame.add(self.stats_frame) self.main_hbox.pack_start(self.filters.get_vbox()) self.main_hbox.pack_start(statsFrame) + def get_vbox(self): """returns the vbox of this thread""" return self.main_hbox @@ -126,20 +141,18 @@ class GuiPositionalStats (threading.Thread): self.cursor.execute(tmp) result = self.cursor.fetchall() - cols = 18 - rows = len(result) # gtk table expands as required - self.stats_table = gtk.Table(1, cols, False) + self.stats_table = gtk.Table(1, 1, False) # gtk table expands as required self.stats_table.set_col_spacings(4) self.stats_table.show() vbox.add(self.stats_table) - # Create header row - titles = ("Game", "Position", "#", "VPIP", "PFR", "Steals", "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq", "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance") + colnames = [desc[0].lower() for desc in self.cursor.description] + rows = len(result) col = 0 row = 0 - for t in titles: - l = gtk.Label(titles[col]) + for t in self.posnheads: + l = gtk.Label(self.posnheads[col]) l.show() self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK) col +=1 @@ -152,12 +165,16 @@ class GuiPositionalStats (threading.Thread): else: bgcolor = "lightgrey" rowprinted=0 - for col in range(cols): + for col,colname in enumerate(self.posncols): + if colname in colnames: + sqlcol = colnames.index(colname) + else: + continue eb = gtk.EventBox() eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) # print blank row between levels: - if result[sqlrow][col] and (sqlrow == 0 or result[sqlrow][0] == last_game): - l = gtk.Label(result[sqlrow][col]) + if result[sqlrow][sqlcol] and (sqlrow == 0 or result[sqlrow][0] == last_game): + l = gtk.Label(result[sqlrow][sqlcol]) rowprinted=1 else: l = gtk.Label(' ') @@ -182,6 +199,7 @@ class GuiPositionalStats (threading.Thread): self.cursor.execute(tmp) result = self.cursor.fetchall() rows = len(result) + colnames = [desc[0].lower() for desc in self.cursor.description] # blank row col = 0 @@ -203,15 +221,17 @@ class GuiPositionalStats (threading.Thread): bgcolor = "white" else: bgcolor = "lightgrey" - inc = 0 - for col in range(cols): + for col,colname in enumerate(self.posncols): + if colname in colnames: + sqlcol = colnames.index(colname) + elif colname != "plposition": + continue eb = gtk.EventBox() eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) - if col == 1: + if colname == 'plposition': l = gtk.Label('Totals') - inc = 1 - elif result[sqlrow][col-inc]: - l = gtk.Label(result[sqlrow][col-inc]) + elif result[sqlrow][sqlcol]: + l = gtk.Label(result[sqlrow][sqlcol]) else: l = gtk.Label(' ') if col == 0: From f9a769ebd36d4909fcc97deddf93d202283fc13c Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 4 May 2009 20:12:41 +0100 Subject: [PATCH 059/104] add summaries to position stats and allow choice of levels --- pyfpdb/Filters.py | 9 ++- pyfpdb/FpdbSQLQueries.py | 128 +++++++++++++++-------------------- pyfpdb/GuiPlayerStats.py | 1 + pyfpdb/GuiPositionalStats.py | 115 ++++++++++++++++++++++--------- 4 files changed, 146 insertions(+), 107 deletions(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index df6262a3..e319c5fd 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -83,7 +83,7 @@ class Filters(threading.Thread): limitsFrame.show() vbox = gtk.VBox(False, 0) - self.fillLimitsFrame(vbox) + self.fillLimitsFrame(vbox, display) limitsFrame.add(vbox) dateFrame = gtk.Frame("Date:") @@ -197,6 +197,7 @@ class Filters(threading.Thread): cb = gtk.CheckButton(str(limit)) cb.connect('clicked', self.__set_limit_select, limit) hbox.pack_start(cb, False, False, 0) + cb.set_active(True) def __set_site_select(self, w, site): print w.get_active() @@ -245,7 +246,7 @@ class Filters(threading.Thread): else: print "INFO: No games returned from database" - def fillLimitsFrame(self, vbox): + def fillLimitsFrame(self, vbox, display): self.cursor.execute(self.sql.query['getLimits']) result = self.db.cursor.fetchall() if len(result) >= 1: @@ -253,6 +254,10 @@ class Filters(threading.Thread): hbox = gtk.HBox(False, 0) vbox.pack_start(hbox, False, True, 0) self.createLimitLine(hbox, line[0]) + if "LimitSep" in display and display["LimitSep"] == True and len(result) >= 2: + hbox = gtk.HBox(False, 0) + vbox.pack_start(hbox, False, True, 0) + self.createLimitLine(hbox, "Separate levels") else: print "INFO: No games returned from database" diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index d5dc7412..1525b7e4 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -677,7 +677,6 @@ class FpdbSQLQueries: else format(100.0*sum(street0_3b4bdone)/sum(street0_3b4bchance),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 @@ -709,7 +708,7 @@ class FpdbSQLQueries: 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 group by gt.base ,gt.category ,upper(gt.limitType) @@ -729,7 +728,6 @@ class FpdbSQLQueries: 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 @@ -815,6 +813,7 @@ class FpdbSQLQueries: inner join Sites s on s.Id = gt.siteId inner join HudCache hc on hc.gameTypeId = gt.Id where hc.playerId in + and group by gt.base ,gt.category ,upper(gt.limitType) @@ -853,10 +852,7 @@ class FpdbSQLQueries: 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) + ,cast(stats.bigBlindDesc as char) ) AS Game ,case when stats.PlPosition = -2 then 'BB' when stats.PlPosition = -1 then 'SB' @@ -879,25 +875,20 @@ 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 'NA' + else format(hprof2.variance, 2) + end AS Variance 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 @@ -944,18 +935,18 @@ class FpdbSQLQueries: 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 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 @@ -964,23 +955,24 @@ 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) 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 - # 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.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, gtId, hp.position, hp.winnings + ) 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, cast(stats.PlPosition as signed) """ elif(self.dbname == 'PostgreSQL'): self.query['playerStatsByPosition'] = """ @@ -988,11 +980,7 @@ class FpdbSQLQueries: upper(stats.limitType) || ' ' || upper(substr(stats.category,1,1)) || substr(stats.category,2) || ' ' || stats.name || ' $' - || trim(leading ' ' from - case when stats.bigBlind < 100 - then to_char(stats.bigBlind/100.0,'90D00') - else to_char(stats.bigBlind/100.0,'999990') - end ) AS Game + || stats.bigBlindDesc AS Game ,case when stats.PlPosition = -2 then 'BB' when stats.PlPosition = -1 then 'SB' when stats.PlPosition = 0 then 'Btn' @@ -1014,25 +1002,20 @@ 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 - */ - ,to_char(hprof2.variance, '0D00') AS Variance + ,case when hprof2.variance = -999 then 'NA' + else to_char(hprof2.variance, '0D00') + end AS Variance 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 @@ -1040,9 +1023,8 @@ class FpdbSQLQueries: when hc.position = 'M' then 2 when hc.position = 'E' then 5 else 9 - end as PlPosition + end AS PlPosition ,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 ,case when sum(street0_3b4bchance) = 0 then '0' @@ -1074,23 +1056,22 @@ class FpdbSQLQueries: 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') + 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 - 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 group by gt.base ,gt.category ,upper(gt.limitType) ,s.name - ,gt.bigBlind - ,hc.gametypeId + + ,gtId ,PlPosition ) stats inner join @@ -1104,23 +1085,24 @@ 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.gameTypeId = 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) 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 - /* use here ? */ - and hp.tourneysPlayersId IS NULL - group by hp.handId, h.gameTypeId, hp.position, hp.winnings - ) hprof + (select hp.handId, as 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 + where hp.playerId in + and hp.tourneysPlayersId IS NULL + group by hp.handId, gameTypeId, hp.position, hp.winnings + ) hprof group by hprof.gameTypeId, PlPosition - ) hprof2 - on ( hprof2.gameTypeId = stats.gameTypeId + ) hprof2 + on ( hprof2.gameTypeId = stats.gtId and hprof2.PlPosition = stats.PlPosition) - order by stats.category, stats.limittype, stats.bigBlind, cast(stats.PlPosition as smallint) + order by stats.category, stats.limitType, stats.bigBlindDesc, cast(stats.PlPosition as smallint) """ elif(self.dbname == 'SQLite'): self.query['playerStatsByPosition'] = """ """ diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index e3ab446c..aef2ba38 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -115,6 +115,7 @@ class GuiPlayerStats (threading.Thread): nametest = nametest.replace(",)",")") tmp = tmp.replace("", nametest) + tmp = tmp.replace("", "1 = 1") self.cursor.execute(tmp) result = self.cursor.fetchall() diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index 70a877f0..9346bff2 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -36,6 +36,9 @@ class GuiPositionalStats (threading.Thread): self.db.do_connect(self.conf) self.cursor=self.db.cursor self.sql = querylist + self.MYSQL_INNODB = 2 + self.PGSQL = 3 + self.SQLITE = 4 settings = {} settings.update(config.get_db_parameters()) @@ -43,13 +46,14 @@ class GuiPositionalStats (threading.Thread): settings.update(config.get_import_parameters()) settings.update(config.get_default_paths()) - filters_display = { "Heroes" : True, - "Sites" : True, - "Games" : False, - "Limits" : False, - "Dates" : False, - "Button1" : True, - "Button2" : False + filters_display = { "Heroes" : True, + "Sites" : True, + "Games" : False, + "Limits" : True, + "LimitSep" : True, + "Dates" : False, + "Button1" : True, + "Button2" : False } self.filters = Filters.Filters(db, settings, config, querylist, display = filters_display) @@ -107,6 +111,7 @@ class GuiPositionalStats (threading.Thread): sites = self.filters.getSites() heroes = self.filters.getHeroes() siteids = self.filters.getSiteIds() + limits = self.filters.getLimits() sitenos = [] playerids = [] @@ -126,19 +131,15 @@ class GuiPositionalStats (threading.Thread): if not playerids: print "No player ids found" return + if not limits: + print "No limits found" + return - self.createStatsTable(vbox, playerids, sitenos) + self.createStatsTable(vbox, playerids, sitenos, limits) - def createStatsTable(self, vbox, playerids, sitenos): + def createStatsTable(self, vbox, playerids, sitenos, limits): tmp = self.sql.query['playerStatsByPosition'] - - nametest = str(tuple(playerids)) - nametest = nametest.replace("L", "") - nametest = nametest.replace(",)",")") - - tmp = tmp.replace("", nametest) - #tmp = tmp.replace("", "gt.id") - + tmp = self.refineQuery(tmp, playerids, sitenos, limits) self.cursor.execute(tmp) result = self.cursor.fetchall() self.stats_table = gtk.Table(1, 1, False) # gtk table expands as required @@ -195,13 +196,14 @@ class GuiPositionalStats (threading.Thread): # show totals at bottom tmp = self.sql.query['playerStats'] - tmp = tmp.replace("", nametest) + tmp = self.refineQuery(tmp, playerids, sitenos, limits) + self.cursor.execute(tmp) result = self.cursor.fetchall() rows = len(result) colnames = [desc[0].lower() for desc in self.cursor.description] - # blank row + # blank row between main stats and totals: col = 0 if(row%2 == 0): bgcolor = "white" @@ -249,18 +251,67 @@ class GuiPositionalStats (threading.Thread): self.db.db.rollback() #end def fillStatsFrame(self, vbox): + def refineQuery(self, query, playerids, sitenos, limits): + nametest = str(tuple(playerids)) + nametest = nametest.replace("L", "") + nametest = nametest.replace(",)",")") + query = query.replace("", nametest) + blindtest = str(tuple([x for x in limits if str(x).isdigit()])) + blindtest = blindtest.replace("L", "") + blindtest = blindtest.replace(",)",")") + query = query.replace("", "gt.bigBlind in " + blindtest) - - - - - - - - - - - - - + groupLevels = "Separate" not in str(limits) + if groupLevels: + if self.db.backend == self.MYSQL_INNODB: + bigblindselect = """concat(trim(leading ' ' from + case when min(gt.bigBlind) < 100 + then format(min(gt.bigBlind)/100.0, 2) + else format(min(gt.bigBlind)/100.0, 0) + end) + ,' - ' + trim(leading ' ' from + case when max(gt.bigBlind) < 100 + then format(max(gt.bigBlind)/100.0, 2) + else format(max(gt.bigBlind)/100.0, 0) + end) + ) """ + else: + bigblindselect = """trim(leading ' ' from + case when min(gt.bigBlind) < 100 + then to_char(min(gt.bigBlind)/100.0,'90D00') + else to_char(min(gt.bigBlind)/100.0,'999990') + end) + || ' - ' || + trim(leading ' ' from + case when max(gt.bigBlind) < 100 + then to_char(max(gt.bigBlind)/100.0,'90D00') + else to_char(max(gt.bigBlind)/100.0,'999990') + end) """ + query = query.replace("", bigblindselect) + query = query.replace("", "") + query = query.replace("", "-1") + query = query.replace("", "-1") + else: + if self.db.backend == self.MYSQL_INNODB: + bigblindselect = """trim(leading ' ' from + case when gt.bigBlind < 100 + then format(gt.bigBlind/100.0, 2) + else format(gt.bigBlind/100.0, 0) + end + ) """ + else: + bigblindselect = """trim(leading ' ' from + case when gt.bigBlind < 100 + then to_char(gt.bigBlind/100.0,'90D00') + else to_char(gt.bigBlind/100.0,'999990') + end + ) """ + query = query.replace("", bigblindselect) + query = query.replace("", ",gt.bigBlind") + query = query.replace("", "hc.gametypeId") + query = query.replace("", "h.gameTypeId") + #print "query =\n", query + return(query) + #end def refineQuery(self, query, playerids, sitenos, limits): From de98d5dd15496186329da08430bf4fbbbba04540 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 4 May 2009 20:36:11 +0100 Subject: [PATCH 060/104] remove surplus db variable and debug mysql problem in previous commit --- pyfpdb/GuiPositionalStats.py | 28 +++++++++++++++++----------- pyfpdb/fpdb.py | 2 +- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index 9346bff2..4ffffd6c 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -27,7 +27,7 @@ import Filters import FpdbSQLQueries class GuiPositionalStats (threading.Thread): - def __init__(self, db, config, querylist, debug=True): + def __init__(self, config, querylist, debug=True): self.debug=debug self.conf=config @@ -56,7 +56,7 @@ class GuiPositionalStats (threading.Thread): "Button2" : False } - self.filters = Filters.Filters(db, settings, config, querylist, display = filters_display) + self.filters = Filters.Filters(self.db, settings, config, querylist, display = filters_display) self.filters.registerButton1Name("Refresh") self.filters.registerButton1Callback(self.refreshStats) @@ -252,15 +252,21 @@ class GuiPositionalStats (threading.Thread): #end def fillStatsFrame(self, vbox): def refineQuery(self, query, playerids, sitenos, limits): - nametest = str(tuple(playerids)) - nametest = nametest.replace("L", "") - nametest = nametest.replace(",)",")") - query = query.replace("", nametest) + if playerids: + nametest = str(tuple(playerids)) + nametest = nametest.replace("L", "") + nametest = nametest.replace(",)",")") + query = query.replace("", nametest) + else: + query = query.replace("", "1 = 2") - blindtest = str(tuple([x for x in limits if str(x).isdigit()])) - blindtest = blindtest.replace("L", "") - blindtest = blindtest.replace(",)",")") - query = query.replace("", "gt.bigBlind in " + blindtest) + if [x for x in limits if str(x).isdigit()]: + blindtest = str(tuple([x for x in limits if str(x).isdigit()])) + blindtest = blindtest.replace("L", "") + blindtest = blindtest.replace(",)",")") + query = query.replace("", "gt.bigBlind in " + blindtest) + else: + query = query.replace("", "gt.bigBlind = -1 ") groupLevels = "Separate" not in str(limits) if groupLevels: @@ -271,7 +277,7 @@ class GuiPositionalStats (threading.Thread): else format(min(gt.bigBlind)/100.0, 0) end) ,' - ' - trim(leading ' ' from + ,trim(leading ' ' from case when max(gt.bigBlind) < 100 then format(max(gt.bigBlind)/100.0, 2) else format(max(gt.bigBlind)/100.0, 0) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 3ed004ef..7fcf75ee 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -337,7 +337,7 @@ class fpdb: self.add_and_display_tab(ps_tab, "Player Stats") def tab_positional_stats(self, widget, data): - new_ps_thread=GuiPositionalStats.GuiPositionalStats(self.db, self.config, self.querydict) + new_ps_thread=GuiPositionalStats.GuiPositionalStats(self.config, self.querydict) self.threads.append(new_ps_thread) ps_tab=new_ps_thread.get_vbox() self.add_and_display_tab(ps_tab, "Positional Stats") From 0ad2b06e97903e7c49da3398b6f063eacd6853d5 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 4 May 2009 23:14:33 +0100 Subject: [PATCH 061/104] Add all/none checkboxes for limits, tidy up stats tables some more --- pyfpdb/Filters.py | 51 ++++++-- pyfpdb/FpdbSQLQueries.py | 233 ++++++++++++++++------------------- pyfpdb/GuiPlayerStats.py | 108 +++++++++++++--- pyfpdb/GuiPositionalStats.py | 6 +- 4 files changed, 246 insertions(+), 152 deletions(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index e319c5fd..ef7c8d29 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -82,6 +82,9 @@ class Filters(threading.Thread): limitsFrame.set_label_align(0.0, 0.0) limitsFrame.show() vbox = gtk.VBox(False, 0) + self.cbLimits = {} + self.cbNoLimits = None + self.cbAllLimits = None self.fillLimitsFrame(vbox, display) limitsFrame.add(vbox) @@ -197,22 +200,39 @@ class Filters(threading.Thread): cb = gtk.CheckButton(str(limit)) cb.connect('clicked', self.__set_limit_select, limit) hbox.pack_start(cb, False, False, 0) - cb.set_active(True) + if limit != "None": + cb.set_active(True) + return(cb) def __set_site_select(self, w, site): - print w.get_active() + #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() + #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() + #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 fillPlayerFrame(self, vbox): for site in self.conf.get_supported_sites(): @@ -250,14 +270,29 @@ class Filters(threading.Thread): self.cursor.execute(self.sql.query['getLimits']) result = self.db.cursor.fetchall() if len(result) >= 1: - for line in result: + hbox = gtk.HBox(True, 0) + vbox.pack_start(hbox, False, False, 0) + vbox1 = gtk.VBox(False, 0) + hbox.pack_start(vbox1, False, False, 0) + vbox2 = gtk.VBox(False, 0) + hbox.pack_start(vbox2, False, False, 0) + for i, line in enumerate(result): hbox = gtk.HBox(False, 0) - vbox.pack_start(hbox, False, True, 0) - self.createLimitLine(hbox, line[0]) + if i < len(result)/2: + vbox1.pack_start(hbox, False, False, 0) + else: + vbox2.pack_start(hbox, False, False, 0) + self.cbLimits[line[0]] = self.createLimitLine(hbox, line[0]) if "LimitSep" in display and display["LimitSep"] == True and len(result) >= 2: hbox = gtk.HBox(False, 0) vbox.pack_start(hbox, False, True, 0) - self.createLimitLine(hbox, "Separate levels") + self.cbAllLimits = self.createLimitLine(hbox, "All") + hbox = gtk.HBox(False, 0) + vbox.pack_start(hbox, False, True, 0) + self.cbNoLimits = self.createLimitLine(hbox, "None") + hbox = gtk.HBox(False, 0) + vbox.pack_start(hbox, False, True, 0) + cb = self.createLimitLine(hbox, "Separate levels") else: print "INFO: No games returned from database" diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index 1525b7e4..ba2d7230 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -633,10 +633,7 @@ class FpdbSQLQueries: 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) + ,cast(stats.bigBlindDesc as char) ) AS Game ,stats.n ,stats.vpip @@ -651,25 +648,20 @@ 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 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 @@ -681,27 +673,27 @@ class FpdbSQLQueries: 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 '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 '-' 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 from Gametypes gt @@ -713,100 +705,94 @@ class FpdbSQLQueries: ,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) as costs + (select hp.handId, as gtId, 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 + 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, gtId, hp.position, hp.winnings + ) 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""" 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.pf3 - ,stats.steals - ,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.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 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 ,case when sum(street0_3b4bchance) = 0 then '0' else to_char(100.0*sum(street0_3b4bdone)/sum(street0_3b4bchance),'90D0') end AS pf3 - ,case when sum(stealattemptchance) = 0 then '0' + ,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 'oo' + ,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 from Gametypes gt @@ -818,31 +804,30 @@ class FpdbSQLQueries: ,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.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, gtId, hp.position, hp.winnings + ) 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""" elif(self.dbname == 'SQLite'): self.query['playerStats'] = """ """ @@ -878,7 +863,7 @@ class FpdbSQLQueries: ,stats.Net ,stats.BBper100 ,stats.Profitperhand - ,case when hprof2.variance = -999 then 'NA' + ,case when hprof2.variance = -999 then '-' else format(hprof2.variance, 2) end AS Variance FROM @@ -903,32 +888,32 @@ class FpdbSQLQueries: ,case when sum(street0_3b4bchance) = 0 then '0' else format(100.0*sum(street0_3b4bdone)/sum(street0_3b4bchance),1) end AS pf3 - ,case when sum(stealattemptchance) = 0 then '0' + ,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 '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 '-' 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 from Gametypes gt @@ -955,7 +940,7 @@ class FpdbSQLQueries: end as PlPosition, sum(hprof.profit) as sum_profit, avg(hprof.profit/100.0) as profitperhand, - case when hprof.gtId = 1 then -999 + case when hprof.gtId = -1 then -999 else variance(hprof.profit/100.0) end as variance from @@ -1005,7 +990,7 @@ class FpdbSQLQueries: ,stats.Net ,stats.BBper100 ,stats.Profitperhand - ,case when hprof2.variance = -999 then 'NA' + ,case when hprof2.variance = -999 then '-' else to_char(hprof2.variance, '0D00') end AS Variance FROM @@ -1030,27 +1015,27 @@ class FpdbSQLQueries: ,case when sum(street0_3b4bchance) = 0 then '0' else to_char(100.0*sum(street0_3b4bdone)/sum(street0_3b4bchance),'90D0') end AS pf3 - ,case when sum(stealattemptchance) = 0 then '0' + ,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 'NA' + ,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 'NA' + ,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 'NA' + ,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 'NA' + ,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 'NA' + ,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 'NA' + ,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 @@ -1076,7 +1061,7 @@ class FpdbSQLQueries: ) 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 @@ -1085,11 +1070,11 @@ class FpdbSQLQueries: end as PlPosition, sum(hprof.profit) as sum_profit, avg(hprof.profit/100.0) as profitperhand, - case when hprof.gameTypeId = 1 then -999 + case when hprof.gtId = -1 then -999 else variance(hprof.profit/100.0) end as variance from - (select hp.handId, as gameTypeId, hp.position, hp.winnings + (select hp.handId, as gtId, 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 @@ -1098,9 +1083,9 @@ class FpdbSQLQueries: and hp.tourneysPlayersId IS NULL group by hp.handId, gameTypeId, hp.position, hp.winnings ) hprof - group by hprof.gameTypeId, PlPosition + group by hprof.gtId, PlPosition ) hprof2 - on ( hprof2.gameTypeId = stats.gtId + on ( hprof2.gtId = stats.gtId and hprof2.PlPosition = stats.PlPosition) order by stats.category, stats.limitType, stats.bigBlindDesc, cast(stats.PlPosition as smallint) """ @@ -1168,24 +1153,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 diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index aef2ba38..dfc5d1c3 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -30,6 +30,9 @@ class GuiPlayerStats (threading.Thread): def __init__(self, config, querylist, debug=True): self.debug=debug self.conf=config + self.MYSQL_INNODB = 2 + self.PGSQL = 3 + self.SQLITE = 4 # create new db connection to avoid conflicts with other threads self.db = fpdb_db.fpdb_db() @@ -43,16 +46,19 @@ class GuiPlayerStats (threading.Thread): settings.update(config.get_import_parameters()) settings.update(config.get_default_paths()) - filters_display = { "Heroes" : True, - "Sites" : True, - "Games" : False, - "Limits" : False, - "Dates" : False, - "Button1" : False, - "Button2" : False + filters_display = { "Heroes" : True, + "Sites" : True, + "Games" : False, + "Limits" : True, + "LimitSep" : True, + "Dates" : False, + "Button1" : True, + "Button2" : False } self.filters = Filters.Filters(self.db, settings, config, querylist, display = filters_display) + self.filters.registerButton1Name("Refresh") + self.filters.registerButton1Callback(self.refreshStats) self.stat_table = None self.stats_frame = None @@ -85,6 +91,7 @@ class GuiPlayerStats (threading.Thread): sites = self.filters.getSites() heroes = self.filters.getHeroes() siteids = self.filters.getSiteIds() + limits = self.filters.getLimits() sitenos = [] playerids = [] @@ -104,19 +111,15 @@ class GuiPlayerStats (threading.Thread): if not playerids: print "No player ids found" return + if not limits: + print "No limits found" + return - self.createStatsTable(vbox, playerids, sitenos) + self.createStatsTable(vbox, playerids, sitenos, limits) - def createStatsTable(self, vbox, playerids, sitenos): + def createStatsTable(self, vbox, playerids, sitenos, limits): tmp = self.sql.query['playerStats'] - - nametest = str(tuple(playerids)) - nametest = nametest.replace("L", "") - nametest = nametest.replace(",)",")") - - tmp = tmp.replace("", nametest) - tmp = tmp.replace("", "1 = 1") - + tmp = self.refineQuery(tmp, playerids, sitenos, limits) self.cursor.execute(tmp) result = self.cursor.fetchall() cols = 18 @@ -159,3 +162,74 @@ class GuiPlayerStats (threading.Thread): eb.show() self.db.db.commit() #end def fillStatsFrame(self, vbox): + + def refineQuery(self, query, playerids, sitenos, limits): + if playerids: + nametest = str(tuple(playerids)) + nametest = nametest.replace("L", "") + nametest = nametest.replace(",)",")") + query = query.replace("", nametest) + else: + query = query.replace("", "1 = 2") + + if [x for x in limits if str(x).isdigit()]: + blindtest = str(tuple([x for x in limits if str(x).isdigit()])) + blindtest = blindtest.replace("L", "") + blindtest = blindtest.replace(",)",")") + query = query.replace("", "gt.bigBlind in " + blindtest) + else: + query = query.replace("", "gt.bigBlind = -1 ") + + groupLevels = "Separate" not in str(limits) + if groupLevels: + if self.db.backend == self.MYSQL_INNODB: + bigblindselect = """concat(trim(leading ' ' from + case when min(gt.bigBlind) < 100 + then format(min(gt.bigBlind)/100.0, 2) + else format(min(gt.bigBlind)/100.0, 0) + end) + ,' - ' + ,trim(leading ' ' from + case when max(gt.bigBlind) < 100 + then format(max(gt.bigBlind)/100.0, 2) + else format(max(gt.bigBlind)/100.0, 0) + end) + ) """ + else: + bigblindselect = """trim(leading ' ' from + case when min(gt.bigBlind) < 100 + then to_char(min(gt.bigBlind)/100.0,'90D00') + else to_char(min(gt.bigBlind)/100.0,'999990') + end) + || ' - ' || + trim(leading ' ' from + case when max(gt.bigBlind) < 100 + then to_char(max(gt.bigBlind)/100.0,'90D00') + else to_char(max(gt.bigBlind)/100.0,'999990') + end) """ + query = query.replace("", bigblindselect) + query = query.replace("", "") + query = query.replace("", "-1") + query = query.replace("", "-1") + else: + if self.db.backend == self.MYSQL_INNODB: + bigblindselect = """trim(leading ' ' from + case when gt.bigBlind < 100 + then format(gt.bigBlind/100.0, 2) + else format(gt.bigBlind/100.0, 0) + end + ) """ + else: + bigblindselect = """trim(leading ' ' from + case when gt.bigBlind < 100 + then to_char(gt.bigBlind/100.0,'90D00') + else to_char(gt.bigBlind/100.0,'999990') + end + ) """ + query = query.replace("", bigblindselect) + query = query.replace("", ",gt.bigBlind") + query = query.replace("", "hc.gametypeId") + query = query.replace("", "h.gameTypeId") + #print "query =\n", query + return(query) + #end def refineQuery(self, query, playerids, sitenos, limits): diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index 4ffffd6c..8ed12172 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -30,15 +30,15 @@ class GuiPositionalStats (threading.Thread): def __init__(self, config, querylist, debug=True): self.debug=debug self.conf=config + self.MYSQL_INNODB = 2 + self.PGSQL = 3 + self.SQLITE = 4 # create new db connection to avoid conflicts with other threads self.db = fpdb_db.fpdb_db() self.db.do_connect(self.conf) self.cursor=self.db.cursor self.sql = querylist - self.MYSQL_INNODB = 2 - self.PGSQL = 3 - self.SQLITE = 4 settings = {} settings.update(config.get_db_parameters()) From 47dad738dde87a779f2f9399f657d5190a831b8d Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 5 May 2009 23:57:20 +0100 Subject: [PATCH 062/104] work around unicode problem with windows and postgres - use old version of recognisePlayerIDs --- pyfpdb/fpdb_simple.py | 59 +++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index 4413d461..f0d3d633 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -1310,35 +1310,38 @@ def recogniseTourneyTypeId(cursor, siteId, buyin, fee, knockout, rebuyOrAddon): # { playername: id } instead of depending on it's relation to the positions list # then this can be reduced in complexity a bit -#def recognisePlayerIDs(cursor, names, site_id): -# result = [] -# for i in xrange(len(names)): -# cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],)) -# tmp=cursor.fetchall() -# if (len(tmp)==0): #new player -# cursor.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)", (names[i], site_id)) -# #print "Number of players rows inserted: %d" % cursor.rowcount -# cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],)) -# tmp=cursor.fetchall() -# #print "recognisePlayerIDs, names[i]:",names[i],"tmp:",tmp -# result.append(tmp[0][0]) -# return result - def recognisePlayerIDs(cursor, names, site_id): - q = "SELECT name,id FROM Players WHERE name=%s" % " OR name=".join(["%s" for n in names]) - cursor.execute(q, names) # get all playerids by the names passed in - ids = dict(cursor.fetchall()) # convert to dict - if len(ids) != len(names): - notfound = [n for n in names if n not in ids] # make list of names not in database - if notfound: # insert them into database - cursor.executemany("INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")", [[n] for n in notfound]) - q2 = "SELECT name,id FROM Players WHERE name=%s" % " OR name=".join(["%s" for n in notfound]) - cursor.execute(q2, notfound) # get their new ids - tmp = dict(cursor.fetchall()) - for n in tmp: # put them all into the same dict - ids[n] = tmp[n] - # return them in the SAME ORDER that they came in in the names argument, rather than the order they came out of the DB - return [ids[n] for n in names] + result = [] + for i in xrange(len(names)): + cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],)) + tmp=cursor.fetchall() + if (len(tmp)==0): #new player + cursor.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)", (names[i], site_id)) + #print "Number of players rows inserted: %d" % cursor.rowcount + cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],)) + tmp=cursor.fetchall() + #print "recognisePlayerIDs, names[i]:",names[i],"tmp:",tmp + result.append(tmp[0][0]) + return result + +# This version breaks for me using postgres on windows with a unicode problem. The names don't come out in unicode +# for some reason so the id isn't found even though it's just been created. Currently investigating the unicode issue but +# not really understanding it yet .... - sqlcoder +#def recognisePlayerIDs(cursor, names, site_id): +# q = "SELECT name,id FROM Players WHERE name=%s" % " OR name=".join(["%s" for n in names]) +# cursor.execute(q, names) # get all playerids by the names passed in +# ids = dict(cursor.fetchall()) # convert to dict +# if len(ids) != len(names): +# notfound = [n for n in names if n not in ids] # make list of names not in database +# if notfound: # insert them into database +# cursor.executemany("INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")", [[n] for n in notfound]) +# q2 = "SELECT name,id FROM Players WHERE name=%s" % " OR name=".join(["%s" for n in notfound]) +# cursor.execute(q2, notfound) # get their new ids +# tmp = dict(cursor.fetchall()) +# for n in tmp: # put them all into the same dict +# ids[n] = tmp[n] +# # return them in the SAME ORDER that they came in in the names argument, rather than the order they came out of the DB +# return [ids[n] for n in names] #end def recognisePlayerIDs From 9fe2fc902dd90af057d9c0cbfb285b866ae370a1 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 7 May 2009 21:17:14 +0100 Subject: [PATCH 063/104] make psycopg2 return unicode strings and go back to new recognisePlayerIDs() very similar to @885f0a023 --- pyfpdb/fpdb_simple.py | 59 ++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index f0d3d633..988b5dbb 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -1310,38 +1310,35 @@ def recogniseTourneyTypeId(cursor, siteId, buyin, fee, knockout, rebuyOrAddon): # { playername: id } instead of depending on it's relation to the positions list # then this can be reduced in complexity a bit -def recognisePlayerIDs(cursor, names, site_id): - result = [] - for i in xrange(len(names)): - cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],)) - tmp=cursor.fetchall() - if (len(tmp)==0): #new player - cursor.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)", (names[i], site_id)) - #print "Number of players rows inserted: %d" % cursor.rowcount - cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],)) - tmp=cursor.fetchall() - #print "recognisePlayerIDs, names[i]:",names[i],"tmp:",tmp - result.append(tmp[0][0]) - return result - -# This version breaks for me using postgres on windows with a unicode problem. The names don't come out in unicode -# for some reason so the id isn't found even though it's just been created. Currently investigating the unicode issue but -# not really understanding it yet .... - sqlcoder #def recognisePlayerIDs(cursor, names, site_id): -# q = "SELECT name,id FROM Players WHERE name=%s" % " OR name=".join(["%s" for n in names]) -# cursor.execute(q, names) # get all playerids by the names passed in -# ids = dict(cursor.fetchall()) # convert to dict -# if len(ids) != len(names): -# notfound = [n for n in names if n not in ids] # make list of names not in database -# if notfound: # insert them into database -# cursor.executemany("INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")", [[n] for n in notfound]) -# q2 = "SELECT name,id FROM Players WHERE name=%s" % " OR name=".join(["%s" for n in notfound]) -# cursor.execute(q2, notfound) # get their new ids -# tmp = dict(cursor.fetchall()) -# for n in tmp: # put them all into the same dict -# ids[n] = tmp[n] -# # return them in the SAME ORDER that they came in in the names argument, rather than the order they came out of the DB -# return [ids[n] for n in names] +# result = [] +# for i in xrange(len(names)): +# cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],)) +# tmp=cursor.fetchall() +# if (len(tmp)==0): #new player +# cursor.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)", (names[i], site_id)) +# #print "Number of players rows inserted: %d" % cursor.rowcount +# cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],)) +# tmp=cursor.fetchall() +# #print "recognisePlayerIDs, names[i]:",names[i],"tmp:",tmp +# result.append(tmp[0][0]) +# return result + +def recognisePlayerIDs(cursor, names, site_id): + q = "SELECT name,id FROM Players WHERE name=%s" % " OR name=".join(["%s" for n in names]) + cursor.execute(q, names) # get all playerids by the names passed in + ids = dict(cursor.fetchall()) # convert to dict + if len(ids) != len(names): + notfound = [n for n in names if n not in ids] # make list of names not in database + if notfound: # insert them into database + cursor.executemany("INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")", [(n,) for n in notfound]) + q2 = "SELECT name,id FROM Players WHERE name=%s" % " OR name=".join(["%s" for n in notfound]) + cursor.execute(q2, notfound) # get their new ids + tmp = cursor.fetchall() + for n,id in tmp: # put them all into the same dict + ids[n] = id + # return them in the SAME ORDER that they came in in the names argument, rather than the order they came out of the DB + return [ids[n] for n in names] #end def recognisePlayerIDs From 4ffc028bbce3206610a81c41a0437a46d67feef4 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 7 May 2009 21:24:06 +0100 Subject: [PATCH 064/104] oops, missed out the key change in previous commit --- pyfpdb/fpdb_db.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index eba87f52..fda04e19 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -62,6 +62,8 @@ class fpdb_db: self.db=MySQLdb.connect(host = host, user = user, passwd = password, db = database, use_unicode=True) elif backend==self.PGSQL: import psycopg2 + import psycopg2.extensions + psycopg2.extensions.register_type(psycopg2.extensions.UNICODE) # If DB connection is made over TCP, then the variables # host, user and password are required print "host=%s user=%s pass=%s." % (host, user, password) From 527232595bd044ddd09c56ee78d7dcc66ddcbcd9 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 7 May 2009 21:24:53 +0100 Subject: [PATCH 065/104] change import time calc --- pyfpdb/GuiBulkImport.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyfpdb/GuiBulkImport.py b/pyfpdb/GuiBulkImport.py index 8a047769..77dee9b7 100755 --- a/pyfpdb/GuiBulkImport.py +++ b/pyfpdb/GuiBulkImport.py @@ -72,6 +72,9 @@ class GuiBulkImport(): self.importer.setCallHud(False) starttime = time() (stored, dups, partial, errs, ttime) = self.importer.runImport() + ttime = time() - starttime + if ttime == 0: + ttime = 1 print 'GuiBulkImport.import_dir done: Stored: %d \tDuplicates: %d \tPartial: %d \tErrors: %d in %s seconds - %d/sec'\ % (stored, dups, partial, errs, ttime, stored / ttime) self.importer.clearFileList() From b7ee4255587c84d997deacce36a57d7d26a35cb2 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Fri, 8 May 2009 22:41:09 +0100 Subject: [PATCH 066/104] add seats to filters and stats queries --- pyfpdb/Filters.py | 86 +++++++++++++++++++++++++++------ pyfpdb/FpdbSQLQueries.py | 36 ++++++++++---- pyfpdb/GuiPlayerStats.py | 51 +++++++++++++------- pyfpdb/GuiPositionalStats.py | 93 ++++++++++++++++++++++++------------ 4 files changed, 193 insertions(+), 73 deletions(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index ef7c8d29..9a8e788f 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -42,9 +42,15 @@ class Filters(threading.Thread): self.sites = {} self.games = {} self.limits = {} + self.seats = {} self.siteid = {} self.heroes = {} + # 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:', 'seatsand':'Show Seats' + } + # For use in date ranges. self.start_date = gtk.Entry(max=12) self.end_date = gtk.Entry(max=12) @@ -89,6 +95,16 @@ class Filters(threading.Thread): self.fillLimitsFrame(vbox, display) limitsFrame.add(vbox) + # Seats + seatsFrame = gtk.Frame("Seats:") + seatsFrame.set_label_align(0.0, 0.0) + seatsFrame.show() + vbox = gtk.VBox(False, 0) + self.sbSeats = {} + + self.fillSeatsFrame(vbox) + seatsFrame.add(vbox) + dateFrame = gtk.Frame("Date:") dateFrame.set_label_align(0.0, 0.0) dateFrame.show() @@ -97,9 +113,9 @@ class Filters(threading.Thread): self.fillDateFrame(vbox) dateFrame.add(vbox) - self.Button1=gtk.Button("Unamed 1") + self.Button1=gtk.Button("Unnamed 1") - self.Button2=gtk.Button("Unamed 2") + self.Button2=gtk.Button("Unnamed 2") #self.exportButton.connect("clicked", self.exportGraph, "show clicked") self.Button2.set_sensitive(False) @@ -107,6 +123,7 @@ class Filters(threading.Thread): 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) @@ -114,19 +131,21 @@ class Filters(threading.Thread): self.mainVBox.show_all() # Should do this cleaner - if display["Heroes"] == False: + if "Heroes" not in display or display["Heroes"] == False: playerFrame.hide() - if display["Sites"] == False: + if "Sites" not in display or display["Sites"] == False: sitesFrame.hide() - if display["Games"] == False: + if "Games" not in display or display["Games"] == False: gamesFrame.hide() - if display["Limits"] == False: + if "Limits" not in display or display["Limits"] == False: limitsFrame.hide() - if display["Dates"] == False: + if "Seats" not in display or display["Seats"] == False: + seatsFrame.hide() + if "Dates" not in display or display["Dates"] == False: dateFrame.hide() - if display["Button1"] == False: + if "Button1" not in display or display["Button1"] == False: self.Button1.hide() - if display["Button2"] == False: + if "Button2" not in display or display["Button2"] == False: self.Button2.hide() def get_vbox(self): @@ -150,6 +169,11 @@ class Filters(threading.Thread): ltuple.append(l) return ltuple + def getSeats(self): + self.seats['from'] = self.sbSeats['from'].get_value_as_int() + self.seats['to'] = self.sbSeats['to'].get_value_as_int() + return self.seats + def getDates(self): return self.__get_dates() @@ -196,8 +220,8 @@ class Filters(threading.Thread): cb.connect('clicked', self.__set_game_select, game) hbox.pack_start(cb, False, False, 0) - def createLimitLine(self, hbox, limit): - cb = gtk.CheckButton(str(limit)) + 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": @@ -234,6 +258,11 @@ class Filters(threading.Thread): 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) @@ -282,20 +311,47 @@ class Filters(threading.Thread): vbox1.pack_start(hbox, False, False, 0) else: vbox2.pack_start(hbox, False, False, 0) - self.cbLimits[line[0]] = self.createLimitLine(hbox, line[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) vbox.pack_start(hbox, False, True, 0) - self.cbAllLimits = self.createLimitLine(hbox, "All") + self.cbAllLimits = self.createLimitLine(hbox, 'all', self.filterText['limitsall']) hbox = gtk.HBox(False, 0) vbox.pack_start(hbox, False, True, 0) - self.cbNoLimits = self.createLimitLine(hbox, "None") + self.cbNoLimits = self.createLimitLine(hbox, 'none', self.filterText['limitsnone']) hbox = gtk.HBox(False, 0) vbox.pack_start(hbox, False, True, 0) - cb = self.createLimitLine(hbox, "Separate levels") + cb = self.createLimitLine(hbox, 'show', self.filterText['limitsshow']) else: print "INFO: No games returned from database" + def fillSeatsFrame(self, vbox): + hbox = gtk.HBox(False, 0) + vbox.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) + cb = gtk.CheckButton(self.filterText['seatsand']) + cb.connect('clicked', self.__set_seat_select, 'show') + + 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) + + hbox = gtk.HBox(False, 0) + vbox.pack_start(hbox, False, True, 0) + hbox.pack_start(cb, False, False, 0) + + self.sbSeats['from'] = sb1 + self.sbSeats['to'] = sb2 + self.sbSeats['show'] = cb + self.seats['show'] = False + def fillCardsFrame(self, vbox): hbox1 = gtk.HBox(True,0) hbox1.show() diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index ba2d7230..5bb3f7c4 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -632,7 +632,7 @@ class FpdbSQLQueries: SELECT concat(upper(stats.limitType), ' ' ,concat(upper(substring(stats.category,1,1)),substring(stats.category,2) ), ' ' - ,stats.name, ' $' + ,stats.name, ' ' ,cast(stats.bigBlindDesc as char) ) AS Game ,stats.n @@ -654,6 +654,7 @@ class FpdbSQLQueries: ,case when hprof2.variance = -999 then '-' else format(hprof2.variance, 2) end AS Variance + ,stats.AvgSeats FROM (select /* stats from hudcache */ gt.base @@ -696,11 +697,13 @@ class FpdbSQLQueries: ,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( avg(activeSeats), 1) 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 group by gt.base ,gt.category ,upper(gt.limitType) @@ -728,12 +731,12 @@ class FpdbSQLQueries: group by hprof.gtId ) hprof2 on hprof2.gtId = stats.gtId - order by stats.category, stats.limittype, stats.bigBlindDesc""" + order by stats.category, stats.limittype, stats.bigBlindDesc """ elif(self.dbname == 'PostgreSQL'): self.query['playerStats'] = """ SELECT upper(stats.limitType) || ' ' || initcap(stats.category) || ' ' - || stats.name || ' $' + || stats.name || ' ' || stats.bigBlindDesc AS Game ,stats.n ,stats.vpip @@ -754,6 +757,7 @@ class FpdbSQLQueries: ,case when hprof2.variance = -999 then '-' else to_char(hprof2.variance, '0D00') end AS Variance + ,AvgSeats FROM (select gt.base ,gt.category @@ -762,7 +766,7 @@ class FpdbSQLQueries: , AS bigBlindDesc , AS gtId ,sum(HDs) as n - ,to_char(100.0*sum(street0VPI)/sum(HDs),'90D0') AS vpip + ,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_3b4bchance) = 0 then '0' else to_char(100.0*sum(street0_3b4bdone)/sum(street0_3b4bchance),'90D0') @@ -795,11 +799,13 @@ class FpdbSQLQueries: ,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(avg(activeSeats),'90D0') 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 group by gt.base ,gt.category ,upper(gt.limitType) @@ -827,7 +833,7 @@ class FpdbSQLQueries: group by hprof.gtId ) hprof2 on hprof2.gtId = stats.gtId - order by stats.base, stats.limittype, stats.bigBlindDesc""" + order by stats.base, stats.limittype, stats.bigBlindDesc """ elif(self.dbname == 'SQLite'): self.query['playerStats'] = """ """ @@ -836,7 +842,7 @@ class FpdbSQLQueries: SELECT concat(upper(stats.limitType), ' ' ,concat(upper(substring(stats.category,1,1)),substring(stats.category,2) ), ' ' - ,stats.name, ' $' + ,stats.name, ' ' ,cast(stats.bigBlindDesc as char) ) AS Game ,case when stats.PlPosition = -2 then 'BB' @@ -866,6 +872,7 @@ class FpdbSQLQueries: ,case when hprof2.variance = -999 then '-' else format(hprof2.variance, 2) end AS Variance + ,stats.AvgSeats FROM (select /* stats from hudcache */ gt.base @@ -916,17 +923,20 @@ class FpdbSQLQueries: ,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( avg(activeSeats), 1) 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 group by gt.base ,gt.category ,upper(gt.limitType) ,s.name ,gtId + ,PlPosition ) stats inner join @@ -957,14 +967,15 @@ class FpdbSQLQueries: ) hprof2 on ( hprof2.gtId = stats.gtId and hprof2.PlPosition = stats.PlPosition) - order by stats.category, stats.limitType, stats.bigBlindDesc, cast(stats.PlPosition as signed) + order by stats.category, stats.limitType, stats.bigBlindDesc + , cast(stats.PlPosition as signed) """ elif(self.dbname == 'PostgreSQL'): self.query['playerStatsByPosition'] = """ select /* stats from hudcache */ upper(stats.limitType) || ' ' || upper(substr(stats.category,1,1)) || substr(stats.category,2) || ' ' - || stats.name || ' $' + || stats.name || ' ' || stats.bigBlindDesc AS Game ,case when stats.PlPosition = -2 then 'BB' when stats.PlPosition = -1 then 'SB' @@ -993,6 +1004,7 @@ class FpdbSQLQueries: ,case when hprof2.variance = -999 then '-' else to_char(hprof2.variance, '0D00') end AS Variance + ,stats.AvgSeats FROM (select /* stats from hudcache */ gt.base @@ -1010,7 +1022,7 @@ class FpdbSQLQueries: else 9 end AS PlPosition ,sum(HDs) AS n - ,to_char(round(100.0*sum(street0VPI)/sum(HDs)),'90D0') AS vpip + ,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_3b4bchance) = 0 then '0' else to_char(100.0*sum(street0_3b4bdone)/sum(street0_3b4bchance),'90D0') @@ -1046,17 +1058,20 @@ class FpdbSQLQueries: ,case when sum(HDs) = 0 then '0' else to_char( (sum(totalProfit)/100.0) / sum(HDs), '90D0000') end AS Profitperhand + ,to_char(avg(activeSeats),'90D0') 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 group by gt.base ,gt.category ,upper(gt.limitType) ,s.name ,gtId + ,PlPosition ) stats inner join @@ -1087,7 +1102,8 @@ class FpdbSQLQueries: ) hprof2 on ( hprof2.gtId = stats.gtId and hprof2.PlPosition = stats.PlPosition) - order by stats.category, stats.limitType, stats.bigBlindDesc, cast(stats.PlPosition as smallint) + order by stats.category, stats.limitType, stats.bigBlindDesc + , cast(stats.PlPosition as smallint) """ elif(self.dbname == 'SQLite'): self.query['playerStatsByPosition'] = """ """ diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index dfc5d1c3..432cd283 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -92,6 +92,7 @@ class GuiPlayerStats (threading.Thread): heroes = self.filters.getHeroes() siteids = self.filters.getSiteIds() limits = self.filters.getLimits() + seats = self.filters.getSeats() sitenos = [] playerids = [] @@ -115,11 +116,11 @@ class GuiPlayerStats (threading.Thread): print "No limits found" return - self.createStatsTable(vbox, playerids, sitenos, limits) + self.createStatsTable(vbox, playerids, sitenos, limits, seats) - def createStatsTable(self, vbox, playerids, sitenos, limits): + def createStatsTable(self, vbox, playerids, sitenos, limits, seats): tmp = self.sql.query['playerStats'] - tmp = self.refineQuery(tmp, playerids, sitenos, limits) + tmp = self.refineQuery(tmp, playerids, sitenos, limits, seats) self.cursor.execute(tmp) result = self.cursor.fetchall() cols = 18 @@ -163,7 +164,7 @@ class GuiPlayerStats (threading.Thread): self.db.db.commit() #end def fillStatsFrame(self, vbox): - def refineQuery(self, query, playerids, sitenos, limits): + def refineQuery(self, query, playerids, sitenos, limits, seats): if playerids: nametest = str(tuple(playerids)) nametest = nametest.replace("L", "") @@ -172,6 +173,19 @@ class GuiPlayerStats (threading.Thread): else: query = query.replace("", "1 = 2") + if seats: + query = query.replace('', 'between ' + str(seats['from']) + ' and ' + str(seats['to'])) + if 'show' in seats and seats['show']: + query = query.replace('', ',hc.activeSeats') + query = query.replace('', ',stats.AvgSeats') + else: + query = query.replace('', '') + query = query.replace('', '') + else: + query = query.replace('', 'between 0 and 100') + query = query.replace('', '') + query = query.replace('', '') + if [x for x in limits if str(x).isdigit()]: blindtest = str(tuple([x for x in limits if str(x).isdigit()])) blindtest = blindtest.replace("L", "") @@ -180,7 +194,7 @@ class GuiPlayerStats (threading.Thread): else: query = query.replace("", "gt.bigBlind = -1 ") - groupLevels = "Separate" not in str(limits) + groupLevels = "show" not in str(limits) if groupLevels: if self.db.backend == self.MYSQL_INNODB: bigblindselect = """concat(trim(leading ' ' from @@ -207,25 +221,28 @@ class GuiPlayerStats (threading.Thread): then to_char(max(gt.bigBlind)/100.0,'90D00') else to_char(max(gt.bigBlind)/100.0,'999990') end) """ + bigblindselect = "cast('' as char)" # avoid odd effects when some posns and/or seats + # are missing from some limits (dunno why cast is + # needed but it says "unknown type" otherwise?! query = query.replace("", bigblindselect) query = query.replace("", "") query = query.replace("", "-1") query = query.replace("", "-1") else: if self.db.backend == self.MYSQL_INNODB: - bigblindselect = """trim(leading ' ' from - case when gt.bigBlind < 100 - then format(gt.bigBlind/100.0, 2) - else format(gt.bigBlind/100.0, 0) - end - ) """ + bigblindselect = """concat('$', trim(leading ' ' from + case when gt.bigBlind < 100 + then format(gt.bigBlind/100.0, 2) + else format(gt.bigBlind/100.0, 0) + end + ) ) """ else: - bigblindselect = """trim(leading ' ' from - case when gt.bigBlind < 100 - then to_char(gt.bigBlind/100.0,'90D00') - else to_char(gt.bigBlind/100.0,'999990') - end - ) """ + bigblindselect = """'$' || trim(leading ' ' from + case when gt.bigBlind < 100 + then to_char(gt.bigBlind/100.0,'90D00') + else to_char(gt.bigBlind/100.0,'999990') + end + ) """ query = query.replace("", bigblindselect) query = query.replace("", ",gt.bigBlind") query = query.replace("", "hc.gametypeId") diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index 8ed12172..4498b214 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -51,6 +51,7 @@ class GuiPositionalStats (threading.Thread): "Games" : False, "Limits" : True, "LimitSep" : True, + "Seats" : True, "Dates" : False, "Button1" : True, "Button2" : False @@ -79,12 +80,14 @@ class GuiPositionalStats (threading.Thread): # To miss columns out remove them from both tuples (the 1st 2 elements should always be included). # To change the heading just edit the second list element as required # If the first list element does not match a query column that pair is ignored - self.posncols = ( "game", "plposition", "vpip", "pfr", "pf3", "steals" + self.posncols = ( "game", "avgseats", "plposition", "vpip", "pfr", "pf3", "steals" , "saw_f", "sawsd", "wtsdwsf", "wmsd", "flafq", "tuafq", "rvafq" - , "pofafq", "net", "bbper100", "profitperhand", "variance", "n" ) - self.posnheads = ( "Game", "Posn", "VPIP", "PFR", "PF3", "Steals" + , "pofafq", "net", "bbper100", "profitperhand", "variance", "n" + ) + self.posnheads = ( "Game", "Seats", "Posn", "VPIP", "PFR", "PF3", "Steals" , "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq" - , "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance", "Hds" ) + , "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance", "Hds" + ) self.fillStatsFrame(self.stats_frame) statsFrame.add(self.stats_frame) @@ -112,6 +115,7 @@ class GuiPositionalStats (threading.Thread): heroes = self.filters.getHeroes() siteids = self.filters.getSiteIds() limits = self.filters.getLimits() + seats = self.filters.getSeats() sitenos = [] playerids = [] @@ -135,11 +139,11 @@ class GuiPositionalStats (threading.Thread): print "No limits found" return - self.createStatsTable(vbox, playerids, sitenos, limits) + self.createStatsTable(vbox, playerids, sitenos, limits, seats) - def createStatsTable(self, vbox, playerids, sitenos, limits): + def createStatsTable(self, vbox, playerids, sitenos, limits, seats): tmp = self.sql.query['playerStatsByPosition'] - tmp = self.refineQuery(tmp, playerids, sitenos, limits) + tmp = self.refineQuery(tmp, playerids, sitenos, limits, seats) self.cursor.execute(tmp) result = self.cursor.fetchall() self.stats_table = gtk.Table(1, 1, False) # gtk table expands as required @@ -158,14 +162,14 @@ class GuiPositionalStats (threading.Thread): self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK) col +=1 - last_game = "" - sqlrow = 0 + last_game,last_seats,sqlrow = "","",0 while sqlrow < rows: if(row%2 == 0): bgcolor = "white" else: bgcolor = "lightgrey" rowprinted=0 + avgcol = colnames.index('avgseats') for col,colname in enumerate(self.posncols): if colname in colnames: sqlcol = colnames.index(colname) @@ -174,9 +178,17 @@ class GuiPositionalStats (threading.Thread): eb = gtk.EventBox() eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) # print blank row between levels: - if result[sqlrow][sqlcol] and (sqlrow == 0 or result[sqlrow][0] == last_game): - l = gtk.Label(result[sqlrow][sqlcol]) - rowprinted=1 + if result[sqlrow][sqlcol]: + if sqlrow == 0: + l = gtk.Label(result[sqlrow][sqlcol]) + rowprinted=1 + elif result[sqlrow][0] != last_game: + l = gtk.Label(' ') + elif 'show' in seats and seats['show'] and result[sqlrow][avgcol] != last_seats: + l = gtk.Label(' ') + else: + l = gtk.Label(result[sqlrow][sqlcol]) + rowprinted=1 else: l = gtk.Label(' ') if col == 0: @@ -190,13 +202,14 @@ class GuiPositionalStats (threading.Thread): l.show() eb.show() last_game = result[sqlrow][0] + last_seats = result[sqlrow][avgcol] if rowprinted: sqlrow = sqlrow+1 row = row + 1 # show totals at bottom tmp = self.sql.query['playerStats'] - tmp = self.refineQuery(tmp, playerids, sitenos, limits) + tmp = self.refineQuery(tmp, playerids, sitenos, limits, seats) self.cursor.execute(tmp) result = self.cursor.fetchall() @@ -251,7 +264,7 @@ class GuiPositionalStats (threading.Thread): self.db.db.rollback() #end def fillStatsFrame(self, vbox): - def refineQuery(self, query, playerids, sitenos, limits): + def refineQuery(self, query, playerids, sitenos, limits, seats): if playerids: nametest = str(tuple(playerids)) nametest = nametest.replace("L", "") @@ -260,6 +273,19 @@ class GuiPositionalStats (threading.Thread): else: query = query.replace("", "1 = 2") + if seats: + query = query.replace('', 'between ' + str(seats['from']) + ' and ' + str(seats['to'])) + if 'show' in seats and seats['show']: + query = query.replace('', ',hc.activeSeats') + query = query.replace('', ',stats.AvgSeats') + else: + query = query.replace('', '') + query = query.replace('', '') + else: + query = query.replace('', 'between 0 and 100') + query = query.replace('', '') + query = query.replace('', '') + if [x for x in limits if str(x).isdigit()]: blindtest = str(tuple([x for x in limits if str(x).isdigit()])) blindtest = blindtest.replace("L", "") @@ -268,15 +294,16 @@ class GuiPositionalStats (threading.Thread): else: query = query.replace("", "gt.bigBlind = -1 ") - groupLevels = "Separate" not in str(limits) + groupLevels = "show" not in str(limits) if groupLevels: if self.db.backend == self.MYSQL_INNODB: - bigblindselect = """concat(trim(leading ' ' from + bigblindselect = """concat('$' + ,trim(leading ' ' from case when min(gt.bigBlind) < 100 then format(min(gt.bigBlind)/100.0, 2) else format(min(gt.bigBlind)/100.0, 0) end) - ,' - ' + ,' - $' ,trim(leading ' ' from case when max(gt.bigBlind) < 100 then format(max(gt.bigBlind)/100.0, 2) @@ -284,36 +311,40 @@ class GuiPositionalStats (threading.Thread): end) ) """ else: - bigblindselect = """trim(leading ' ' from + bigblindselect = """'$' || + trim(leading ' ' from case when min(gt.bigBlind) < 100 then to_char(min(gt.bigBlind)/100.0,'90D00') else to_char(min(gt.bigBlind)/100.0,'999990') end) - || ' - ' || + || ' - $' || trim(leading ' ' from case when max(gt.bigBlind) < 100 then to_char(max(gt.bigBlind)/100.0,'90D00') else to_char(max(gt.bigBlind)/100.0,'999990') end) """ + bigblindselect = "cast('' as char)" # avoid odd effects when some posns and/or seats + # are missing from some limits (dunno why cast is + # needed but it says "unknown type" otherwise?! query = query.replace("", bigblindselect) query = query.replace("", "") query = query.replace("", "-1") query = query.replace("", "-1") else: if self.db.backend == self.MYSQL_INNODB: - bigblindselect = """trim(leading ' ' from - case when gt.bigBlind < 100 - then format(gt.bigBlind/100.0, 2) - else format(gt.bigBlind/100.0, 0) - end - ) """ + bigblindselect = """concat('$', trim(leading ' ' from + case when gt.bigBlind < 100 + then format(gt.bigBlind/100.0, 2) + else format(gt.bigBlind/100.0, 0) + end + ) )""" else: - bigblindselect = """trim(leading ' ' from - case when gt.bigBlind < 100 - then to_char(gt.bigBlind/100.0,'90D00') - else to_char(gt.bigBlind/100.0,'999990') - end - ) """ + bigblindselect = """'$' || trim(leading ' ' from + case when gt.bigBlind < 100 + then to_char(gt.bigBlind/100.0,'90D00') + else to_char(gt.bigBlind/100.0,'999990') + end + ) """ query = query.replace("", bigblindselect) query = query.replace("", ",gt.bigBlind") query = query.replace("", "hc.gametypeId") From 199a91ea99346376aba632ee9634a7efa3f6010e Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sat, 9 May 2009 23:18:58 +0100 Subject: [PATCH 067/104] add rollback to release locks taken in postgres --- pyfpdb/HUD_main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index 4501821a..17e133ff 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -195,6 +195,7 @@ class HUD_main(object): sys.stderr.write("table name "+table_name+" not found, skipping.\n") else: self.create_HUD(new_hand_id, tablewindow, temp_key, max, poker_game, stat_dict, cards) + self.db_connection.connection.rollback() if __name__== "__main__": sys.stderr.write("HUD_main starting\n") From a4302b61a9f1a5cae81cf8fa9e3a699e540c9757 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 10 May 2009 22:30:26 +0100 Subject: [PATCH 068/104] make gui hide new seats part of filter, refine empty query test --- pyfpdb/GuiGraphViewer.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index 91de84e1..cec91e61 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -57,6 +57,7 @@ class GuiGraphViewer (threading.Thread): "Sites" : True, "Games" : True, "Limits" : True, + "Seats" : False, "Dates" : True, "Button1" : True, "Button2" : True @@ -73,10 +74,12 @@ class GuiGraphViewer (threading.Thread): self.leftPanelBox = self.filters.get_vbox() self.graphBox = gtk.VBox(False, 0) + self.graphBox.show() self.hpane = gtk.HPaned() self.hpane.pack1(self.leftPanelBox) self.hpane.pack2(self.graphBox) + self.hpane.show() self.mainHBox.add(self.hpane) @@ -86,7 +89,7 @@ class GuiGraphViewer (threading.Thread): self.fig = Figure(figsize=(5,4), dpi=100) self.canvas = None - self.mainHBox.show_all() + self.db.db.rollback() ################################# @@ -175,7 +178,8 @@ class GuiGraphViewer (threading.Thread): self.ax.set_xlabel("Hands", fontsize = 12) self.ax.set_ylabel("$", fontsize = 12) self.ax.grid(color='g', linestyle=':', linewidth=0.2) - if(line == None): + if line == None or line == []: + #TODO: Do something useful like alert user print "No hands returned by graph query" else: @@ -193,7 +197,7 @@ class GuiGraphViewer (threading.Thread): self.graphBox.add(self.canvas) self.canvas.show() - self.exportButton.set_sensitive(True) + #self.exportButton.set_sensitive(True) #end of def showClicked def getRingProfitGraph(self, names, sites, limits): From 3e805f03b1a33b219606664215471cab9b1709e1 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 10 May 2009 22:37:02 +0100 Subject: [PATCH 069/104] correct avg seats calculation, select limits in reverse order, i.e. highest first --- pyfpdb/FpdbSQLQueries.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index 5bb3f7c4..023e530e 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -697,7 +697,7 @@ class FpdbSQLQueries: ,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( avg(activeSeats), 1) AS AvgSeats + ,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 @@ -731,7 +731,7 @@ class FpdbSQLQueries: group by hprof.gtId ) hprof2 on hprof2.gtId = stats.gtId - order by stats.category, stats.limittype, stats.bigBlindDesc """ + order by stats.category, stats.limittype, stats.bigBlindDesc desc """ elif(self.dbname == 'PostgreSQL'): self.query['playerStats'] = """ SELECT upper(stats.limitType) || ' ' @@ -799,7 +799,7 @@ class FpdbSQLQueries: ,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(avg(activeSeats),'90D0') AS AvgSeats + ,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 @@ -833,7 +833,7 @@ class FpdbSQLQueries: group by hprof.gtId ) hprof2 on hprof2.gtId = stats.gtId - order by stats.base, stats.limittype, stats.bigBlindDesc """ + order by stats.base, stats.limittype, stats.bigBlindDesc desc """ elif(self.dbname == 'SQLite'): self.query['playerStats'] = """ """ @@ -923,7 +923,7 @@ class FpdbSQLQueries: ,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( avg(activeSeats), 1) AS AvgSeats + ,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 @@ -967,7 +967,7 @@ class FpdbSQLQueries: ) hprof2 on ( hprof2.gtId = stats.gtId and hprof2.PlPosition = stats.PlPosition) - order by stats.category, stats.limitType, stats.bigBlindDesc + order by stats.category, stats.limitType, stats.bigBlindDesc desc , cast(stats.PlPosition as signed) """ elif(self.dbname == 'PostgreSQL'): @@ -1058,7 +1058,7 @@ class FpdbSQLQueries: ,case when sum(HDs) = 0 then '0' else to_char( (sum(totalProfit)/100.0) / sum(HDs), '90D0000') end AS Profitperhand - ,to_char(avg(activeSeats),'90D0') AS AvgSeats + ,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) @@ -1102,7 +1102,7 @@ class FpdbSQLQueries: ) hprof2 on ( hprof2.gtId = stats.gtId and hprof2.PlPosition = stats.PlPosition) - order by stats.category, stats.limitType, stats.bigBlindDesc + order by stats.category, stats.limitType, stats.bigBlindDesc desc , cast(stats.PlPosition as smallint) """ elif(self.dbname == 'SQLite'): From fe806ccea16815a22e266dae6ecf70ba62072af9 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 10 May 2009 22:59:35 +0100 Subject: [PATCH 070/104] update playerstats for new avgseats column and seats filter (is this window redundant now?) --- pyfpdb/GuiPlayerStats.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 432cd283..66b312ce 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -51,6 +51,7 @@ class GuiPlayerStats (threading.Thread): "Games" : False, "Limits" : True, "LimitSep" : True, + "Seats" : True, "Dates" : False, "Button1" : True, "Button2" : False @@ -123,7 +124,8 @@ class GuiPlayerStats (threading.Thread): tmp = self.refineQuery(tmp, playerids, sitenos, limits, seats) self.cursor.execute(tmp) result = self.cursor.fetchall() - cols = 18 + cols = 19 + rows = len(result)+1 # +1 for title row self.stats_table = gtk.Table(rows, cols, False) self.stats_table.set_col_spacings(4) @@ -131,7 +133,7 @@ class GuiPlayerStats (threading.Thread): vbox.add(self.stats_table) # Create header row - titles = ("Game", "Hands", "VPIP", "PFR", "PF3", "Steals", "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq", "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance") + titles = ("Game", "Hands", "VPIP", "PFR", "PF3", "Steals", "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq", "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance", "AvgSeats") col = 0 row = 0 From aba5b9484717a9fc6a6fc98335ad620c4b71db49 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 10 May 2009 23:06:35 +0100 Subject: [PATCH 071/104] add new SeatSep display flag for filter, re-order some code with possible aim of using one function instead of 2 similar blocks of code for breakdown and totals --- pyfpdb/GuiPositionalStats.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index 4498b214..753fe874 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -52,6 +52,7 @@ class GuiPositionalStats (threading.Thread): "Limits" : True, "LimitSep" : True, "Seats" : True, + "SeatSep" : True, "Dates" : False, "Button1" : True, "Button2" : False @@ -142,26 +143,35 @@ class GuiPositionalStats (threading.Thread): self.createStatsTable(vbox, playerids, sitenos, limits, seats) def createStatsTable(self, vbox, playerids, sitenos, limits, seats): - tmp = self.sql.query['playerStatsByPosition'] - tmp = self.refineQuery(tmp, playerids, sitenos, limits, seats) - self.cursor.execute(tmp) - result = self.cursor.fetchall() + + + + self.stats_table = gtk.Table(1, 1, False) # gtk table expands as required self.stats_table.set_col_spacings(4) self.stats_table.show() vbox.add(self.stats_table) - colnames = [desc[0].lower() for desc in self.cursor.description] - rows = len(result) + row = 0 + + col = 0 - row = 0 + for t in self.posnheads: l = gtk.Label(self.posnheads[col]) l.show() self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK) col +=1 + tmp = self.sql.query['playerStatsByPosition'] + tmp = self.refineQuery(tmp, playerids, sitenos, limits, seats) + self.cursor.execute(tmp) + result = self.cursor.fetchall() + + rows = len(result) + colnames = [desc[0].lower() for desc in self.cursor.description] + last_game,last_seats,sqlrow = "","",0 while sqlrow < rows: if(row%2 == 0): From 6495346874f5c2aba1b22ce56ac9bf24f5570254 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 10 May 2009 23:11:30 +0100 Subject: [PATCH 072/104] Add new seatsep display flag --- pyfpdb/Filters.py | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index 9a8e788f..d35d0817 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -48,7 +48,7 @@ class Filters(threading.Thread): # 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:', 'seatsand':'Show Seats' + ,'seatsbetween':'Between:', 'seatsand':'And:', 'seatsshow':'Show Seats' } # For use in date ranges. @@ -102,7 +102,7 @@ class Filters(threading.Thread): vbox = gtk.VBox(False, 0) self.sbSeats = {} - self.fillSeatsFrame(vbox) + self.fillSeatsFrame(vbox, display) seatsFrame.add(vbox) dateFrame = gtk.Frame("Date:") @@ -170,8 +170,10 @@ class Filters(threading.Thread): return ltuple def getSeats(self): - self.seats['from'] = self.sbSeats['from'].get_value_as_int() - self.seats['to'] = self.sbSeats['to'].get_value_as_int() + 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): @@ -307,7 +309,7 @@ class Filters(threading.Thread): hbox.pack_start(vbox2, False, False, 0) for i, line in enumerate(result): hbox = gtk.HBox(False, 0) - if i < len(result)/2: + if i <= len(result)/2: vbox1.pack_start(hbox, False, False, 0) else: vbox2.pack_start(hbox, False, False, 0) @@ -325,7 +327,7 @@ class Filters(threading.Thread): else: print "INFO: No games returned from database" - def fillSeatsFrame(self, vbox): + def fillSeatsFrame(self, vbox, display): hbox = gtk.HBox(False, 0) vbox.pack_start(hbox, False, True, 0) @@ -335,22 +337,28 @@ class Filters(threading.Thread): 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) - cb = gtk.CheckButton(self.filterText['seatsand']) - cb.connect('clicked', self.__set_seat_select, 'show') + + 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) - hbox = gtk.HBox(False, 0) - vbox.pack_start(hbox, False, True, 0) - hbox.pack_start(cb, False, False, 0) + if "SeatSep" in display and display["SeatSep"] == True: + hbox = gtk.HBox(False, 0) + vbox.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 - self.sbSeats['show'] = cb - self.seats['show'] = False + + def fillCardsFrame(self, vbox): hbox1 = gtk.HBox(True,0) From 339f48582c71a4f96949c921a7596c44abee218a Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 17 May 2009 00:06:53 +0100 Subject: [PATCH 073/104] add more stat fields to db --- pyfpdb/FpdbSQLQueries.py | 458 +++++++++++++++++++++++++++++++++++---- pyfpdb/fpdb_simple.py | 144 +++++++++--- 2 files changed, 537 insertions(+), 65 deletions(-) diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index 023e530e..b9613e18 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -185,6 +185,13 @@ class FpdbSQLQueries: importTime DATETIME NOT NULL, seats SMALLINT NOT NULL, maxSeats SMALLINT NOT NULL, + vpi SMALLINT NOT NULL, + street0Seen SMALLINT NOT NULL, + street1Seen SMALLINT NOT NULL, + street2Seen SMALLINT NOT NULL, + street3Seen SMALLINT NOT NULL, + street4Seen SMALLINT NOT NULL, + sdSeen SMALLINT NOT NULL, comment TEXT, commentTs DATETIME) ENGINE=INNODB""" @@ -198,6 +205,13 @@ class FpdbSQLQueries: importTime timestamp without time zone, seats SMALLINT, maxSeats SMALLINT, + vpi SMALLINT NOT NULL, + street0Seen SMALLINT NOT NULL, + street1Seen SMALLINT NOT NULL, + street2Seen SMALLINT NOT NULL, + street3Seen SMALLINT NOT NULL, + street4Seen SMALLINT NOT NULL, + sdSeen SMALLINT NOT NULL, comment TEXT, commentTs timestamp without time zone)""" elif(self.dbname == 'SQLite'): @@ -306,7 +320,7 @@ class FpdbSQLQueries: startCash INT NOT NULL, position CHAR(1), seatNo SMALLINT NOT NULL, - ante INT, + activeSeats SMALLINT NOT NULL, card1Value smallint NOT NULL, card1Suit char(1) NOT NULL, @@ -322,28 +336,104 @@ class FpdbSQLQueries: card6Suit char(1), card7Value smallint, card7Suit char(1), + startCards smallint, + ante INT, 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 NOT NULL, + wonWhenSeenStreet3 FLOAT NOT NULL, + wonWhenSeenStreet4 FLOAT NOT NULL, + 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 NOT NULL, + street0_4BDone BOOLEAN NOT NULL, + other3BStreet0 BOOLEAN NOT NULL, + other4BStreet0 BOOLEAN NOT NULL, + + 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 NOT NULL, + otherRaisedStreet1 BOOLEAN NOT NULL, + otherRaisedStreet2 BOOLEAN NOT NULL, + otherRaisedStreet3 BOOLEAN NOT NULL, + otherRaisedStreet4 BOOLEAN NOT NULL, + foldToOtherRaisedStreet0 BOOLEAN NOT NULL, + 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, + + 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, - ante INT, + seatNo SMALLINT NOT NULL, + activeSeats SMALLINT NOT NULL, - card1Value smallint, - card1Suit char(1), - card2Value smallint, - card2Suit char(1), + 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, @@ -354,12 +444,89 @@ class FpdbSQLQueries: card6Suit char(1), card7Value smallint, card7Suit char(1), + startCards smallint, - winnings int, - rake int, + ante 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 NOT NULL, + wonWhenSeenStreet3 FLOAT NOT NULL, + wonWhenSeenStreet4 FLOAT NOT NULL, + 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 NOT NULL, + street0_4BDone BOOLEAN NOT NULL, + other3BStreet0 BOOLEAN NOT NULL, + other4BStreet0 BOOLEAN NOT NULL, + + 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 NOT NULL, + otherRaisedStreet1 BOOLEAN NOT NULL, + otherRaisedStreet2 BOOLEAN NOT NULL, + otherRaisedStreet3 BOOLEAN NOT NULL, + otherRaisedStreet4 BOOLEAN NOT NULL, + foldToOtherRaisedStreet0 BOOLEAN NOT NULL, + 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, + + FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id))""" elif(self.dbname == 'SQLite'): self.query['createHandsPlayersTable'] = """ """ @@ -400,7 +567,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 (handPlayerId) REFERENCES HandsPlayers(id), street SMALLINT NOT NULL, actionNo SMALLINT NOT NULL, action CHAR(5) NOT NULL, @@ -412,7 +579,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 (handPlayerId) REFERENCES HandsPlayers(id), street SMALLINT, actionNo SMALLINT, action CHAR(5), @@ -611,12 +778,10 @@ class FpdbSQLQueries: 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 @@ -624,9 +789,74 @@ class FpdbSQLQueries: 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', 'PostgreSQL']: + self.query['playerDetailedStats'] = """ + select + h.gametypeId + ,sum(hp.totalProfit) AS sum_profit + ,avg(hp.totalProfit/100.0) AS profitperhand + /*,case when h.gametypeId = -1 then -999 + else variance(hp.totalProfit/100.0) + end AS variance*/ + ,gt.base + ,gt.category + ,upper(gt.limitType) AS limitType + ,s.name + /*, AS bigBlindDesc + , AS gtId*/ + ,count(1) AS n + ,100.0*sum(cast(street0VPI as integer))/count(1) AS vpip + ,100.0*sum(cast(street0Aggr as integer))/count(1) AS pfr + ,case when sum(cast(street0_3b4bchance as integer)) = 0 then '0' + else 100.0*sum(cast(street0_3b4bdone as integer))/sum(cast(street0_3b4bchance as integer)) + end AS pf3 + ,case when sum(cast(stealattemptchance as integer)) = 0 then -999 + else 100.0*sum(cast(stealattempted as integer))/sum(cast(stealattemptchance as integer)) + end AS steals + ,100.0*sum(cast(street1Seen as integer))/count(1) AS saw_f + ,100.0*sum(cast(sawShowdown as integer))/count(1) AS sawsd + ,case when sum(cast(street1Seen as integer)) = 0 then -999 + else 100.0*sum(cast(sawShowdown as integer))/sum(cast(street1Seen as integer)) + end AS wtsdwsf + ,case when sum(cast(sawShowdown as integer)) = 0 then -999 + else 100.0*sum(cast(wonAtSD as integer))/sum(cast(sawShowdown as integer)) + end AS wmsd + ,case when sum(cast(street1Seen as integer)) = 0 then -999 + else 100.0*sum(cast(street1Aggr as integer))/sum(cast(street1Seen as integer)) + end AS FlAFq + ,case when sum(cast(street2Seen as integer)) = 0 then -999 + else 100.0*sum(cast(street2Aggr as integer))/sum(cast(street2Seen as integer)) + end AS TuAFq + ,case when sum(cast(street3Seen as integer)) = 0 then -999 + else 100.0*sum(cast(street3Aggr as integer))/sum(cast(street3Seen as integer)) + end AS RvAFq + ,case when sum(cast(street1Seen as integer))+sum(cast(street2Seen as integer))+sum(cast(street3Seen as integer)) = 0 then -999 + else 100.0*(sum(cast(street1Aggr as integer))+sum(cast(street2Aggr as integer))+sum(cast(street3Aggr as integer))) + /(sum(cast(street1Seen as integer))+sum(cast(street2Seen as integer))+sum(cast(street3Seen as integer))) + end AS PoFAFq + ,sum(totalProfit)/100.0 AS Net + ,(sum(totalProfit/(gt.bigBlind+0.0))) / (count(1)/100.0) + AS BBper100 + ,(sum(totalProfit)/100.0) / count(1) AS Profitperhand + ,sum(activeSeats)/(count(1)+0.0) AS AvgSeats + 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 (1) /* */ + and hp.tourneysPlayersId IS NULL + group by h.gametypeId + ,hp.playerId + ,gt.base + ,gt.category + ,upper(gt.limitType) + ,s.name""" + elif(self.dbname == 'SQLite'): + self.query['playerDetailedStats'] = """ """ + if(self.dbname == 'MySQL InnoDB'): self.query['playerStats'] = """ SELECT @@ -719,14 +949,12 @@ class FpdbSQLQueries: else variance(hprof.profit/100.0) end as variance from - (select hp.handId, as gtId, hp.winnings, SUM(ha.amount) as costs - , hp.winnings - SUM(ha.amount) as profit + (select hp.handId, as gtId, hp.totalProfit 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, gtId, hp.position, hp.winnings + group by hp.handId, gtId, hp.totalProfit ) hprof group by hprof.gtId ) hprof2 @@ -821,14 +1049,12 @@ class FpdbSQLQueries: else variance(hprof.profit/100.0) end as variance from - (select hp.handId, as gtId, hp.winnings, - SUM(ha.amount) as costs, hp.winnings - SUM(ha.amount) as profit + (select hp.handId, as gtId, hp.totalProfit 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) where hp.playerId in and hp.tourneysPlayersId IS NULL - group by hp.handId, gtId, hp.position, hp.winnings + group by hp.handId, gtId, hp.totalProfit ) hprof group by hprof.gtId ) hprof2 @@ -954,14 +1180,13 @@ class FpdbSQLQueries: else variance(hprof.profit/100.0) end as variance from - (select hp.handId, as gtId, hp.position, hp.winnings - , SUM(ha.amount) as costs, hp.winnings - SUM(ha.amount) as profit + (select hp.handId, as gtId, hp.position + , hp.totalProfit 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) where hp.playerId in and hp.tourneysPlayersId IS NULL - group by hp.handId, gtId, hp.position, hp.winnings + group by hp.handId, gtId, hp.position, hp.totalProfit ) hprof group by hprof.gtId, PlPosition ) hprof2 @@ -1089,14 +1314,13 @@ class FpdbSQLQueries: else variance(hprof.profit/100.0) end as variance from - (select hp.handId, as gtId, hp.position, hp.winnings - , SUM(ha.amount) as costs, hp.winnings - SUM(ha.amount) as profit + (select hp.handId, as gtId, hp.position + , hp.totalProfit 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) where hp.playerId in and hp.tourneysPlayersId IS NULL - group by hp.handId, gameTypeId, hp.position, hp.winnings + group by hp.handId, gameTypeId, hp.position, hp.totalProfit ) hprof group by hprof.gtId, PlPosition ) hprof2 @@ -1245,6 +1469,160 @@ class FpdbSQLQueries: 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 + ,HDs + ,wonWhenSeenStreet1 + ,wonAtSD + ,street0VPI + ,street0Aggr + ,street0_3B4BChance + ,street0_3B4BDone + ,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 + ,hp.activeSeats + ,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 + ,count(1) + ,sum(wonWhenSeenStreet1) + ,sum(wonAtSD) + ,sum(CAST(street0VPI as integer)) + ,sum(CAST(street0Aggr as integer)) + ,sum(CAST(street0_3B4BChance as integer)) + ,sum(CAST(street0_3B4BDone 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 + ,hp.activeSeats + ,hc_position + ,hp.tourneyTypeId +""" + + if __name__== "__main__": from optparse import OptionParser diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index 988b5dbb..e8103ffa 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -187,10 +187,10 @@ def prepareBulkImport(fdb): # mod to use tab_col for index name? try: fdb.cursor.execute( "drop index %s_%s_idx" % (idx['tab'],idx['col']) ) - print "drop index %s_%s_idx" % (idx['tab'],idx['col']) + print "drop index %s_%s_idx" % (idx['tab'],idx['col']) #print "dropped pg index ", idx['tab'], idx['col'] except: - print "! failed drop index %s_%s_idx" % (idx['tab'],idx['col']) + print "! failed drop index %s_%s_idx" % (idx['tab'],idx['col']) else: print "Only MySQL and Postgres supported so far" return -1 @@ -1065,7 +1065,7 @@ def parsePositions(hand, names): if bb != -1: bb = recognisePlayerNo(bb, names, "bet") -# print "sb = ", sb, "bb = ", bb +# print "sb = ", sb, "bb = ", bb if bb == sb: # if big and small are same, then don't duplicate the small sbExists = False sb = -1 @@ -1094,7 +1094,7 @@ def parsePositions(hand, names): while positions[i] < 0 and i != sb: positions[i] = 9 i -= 1 - ### RHH - Changed to set the null seats before BB to "9" + ### RHH - Changed to set the null seats before BB to "9" if sbExists: i = sb-1 else: @@ -1114,7 +1114,7 @@ def parsePositions(hand, names): print "parsePositions names:",names print "result:",positions raise FpdbError ("failed to read positions") -# print str(positions), "\n" +# print str(positions), "\n" return positions #end def parsePositions @@ -1438,6 +1438,7 @@ def storeActions(cursor, handsPlayersIds, actionTypes, allIns, actionAmounts, ac def store_board_cards(cursor, hands_id, board_values, board_suits): #stores into table board_cards + return cursor.execute ("""INSERT INTO BoardCards (handId, card1Value, card1Suit, card2Value, card2Suit, card3Value, card3Suit, card4Value, card4Suit, card5Value, card5Suit) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", @@ -1458,35 +1459,128 @@ def storeHands(backend, conn, cursor, site_hand_no, gametype_id #end def storeHands def store_hands_players_holdem_omaha(backend, conn, cursor, category, hands_id, player_ids, start_cashes - ,positions, card_values, card_suits, winnings, rakes, seatNos): + ,positions, card_values, card_suits, winnings, rakes, seatNos, hudCache): result=[] + + # postgres (and others?) needs the booleans converted to ints before saving: + # (or we could just save them as boolean ... but then we can't sum them so easily in sql ???) + # NO - storing booleans for now so don't need this + #hudCacheInt = {} + #for k,v in hudCache.iteritems(): + # if k in ('wonWhenSeenStreet1', 'wonAtSD', 'totalProfit'): + # hudCacheInt[k] = v + # else: + # hudCacheInt[k] = map(lambda x: 1 if x else 0, v) + if (category=="holdem"): for i in xrange(len(player_ids)): + x,y = card_values[i][0],card_values[i][1] + if (card_suits[i][0] == card_suits[i][1] and x < y) or (card_suits[i][0] != card_suits[i][1] and x > y): + x,y = y,x + startCards = 13 * (x-2) + (y-2) cursor.execute (""" INSERT INTO HandsPlayers -(handId, playerId, startCash, position, -card1Value, card1Suit, card2Value, card2Suit, winnings, rake, seatNo) -VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", - (hands_id, player_ids[i], start_cashes[i], positions[i], - card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], - winnings[i], rakes[i], seatNos[i])) +(handId, playerId, startCash, position, activeSeats, tourneyTypeId, + card1Value, card1Suit, card2Value, card2Suit, winnings, rake, seatNo, totalProfit, + street0VPI, street0Aggr, street0_3B4BChance, street0_3B4BDone, + street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown, + street1Aggr, street2Aggr, street3Aggr, street4Aggr, + otherRaisedStreet1, otherRaisedStreet2, otherRaisedStreet3, otherRaisedStreet4, + foldToOtherRaisedStreet1, foldToOtherRaisedStreet2, foldToOtherRaisedStreet3, foldToOtherRaisedStreet4, + wonWhenSeenStreet1, wonAtSD, + stealAttemptChance, stealAttempted, foldBbToStealChance, foldedBbToSteal, foldSbToStealChance, foldedSbToSteal, + street1CBChance, street1CBDone, street2CBChance, street2CBDone, + street3CBChance, street3CBDone, street4CBChance, street4CBDone, + foldToStreet1CBChance, foldToStreet1CBDone, foldToStreet2CBChance, foldToStreet2CBDone, + foldToStreet3CBChance, foldToStreet3CBDone, foldToStreet4CBChance, foldToStreet4CBDone, + street1CheckCallRaiseChance, street1CheckCallRaiseDone, street2CheckCallRaiseChance, street2CheckCallRaiseDone, + street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone +) +VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", + (hands_id, player_ids[i], start_cashes[i], positions[i], len(player_ids), 1, # tourneytypeid + card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], + winnings[i], rakes[i], seatNos[i], hudCache['totalProfit'][i], + hudCache['street0VPI'][i], hudCache['street0Aggr'][i], + hudCache['street0_3B4BChance'][i], hudCache['street0_3B4BDone'][i], + hudCache['street1Seen'][i], hudCache['street2Seen'][i], hudCache['street3Seen'][i], + hudCache['street4Seen'][i], hudCache['sawShowdown'][i], + hudCache['street1Aggr'][i], hudCache['street2Aggr'][i], hudCache['street3Aggr'][i], hudCache['street4Aggr'][i], + hudCache['otherRaisedStreet1'][i], hudCache['otherRaisedStreet2'][i], + hudCache['otherRaisedStreet3'][i], hudCache['otherRaisedStreet4'][i], + hudCache['foldToOtherRaisedStreet1'][i], hudCache['foldToOtherRaisedStreet2'][i], + hudCache['foldToOtherRaisedStreet3'][i], hudCache['foldToOtherRaisedStreet4'][i], + hudCache['wonWhenSeenStreet1'][i], hudCache['wonAtSD'][i], + hudCache['stealAttemptChance'][i], hudCache['stealAttempted'][i], hudCache['foldBbToStealChance'][i], + hudCache['foldedBbToSteal'][i], hudCache['foldSbToStealChance'][i], hudCache['foldedSbToSteal'][i], + hudCache['street1CBChance'][i], hudCache['street1CBDone'][i], hudCache['street2CBChance'][i], hudCache['street2CBDone'][i], + hudCache['street3CBChance'][i], hudCache['street3CBDone'][i], hudCache['street4CBChance'][i], hudCache['street4CBDone'][i], + hudCache['foldToStreet1CBChance'][i], hudCache['foldToStreet1CBDone'][i], + hudCache['foldToStreet2CBChance'][i], hudCache['foldToStreet2CBDone'][i], + hudCache['foldToStreet3CBChance'][i], hudCache['foldToStreet3CBDone'][i], + hudCache['foldToStreet4CBChance'][i], hudCache['foldToStreet4CBDone'][i], + hudCache['street1CheckCallRaiseChance'][i], hudCache['street1CheckCallRaiseDone'][i], + hudCache['street2CheckCallRaiseChance'][i], hudCache['street2CheckCallRaiseDone'][i], + hudCache['street3CheckCallRaiseChance'][i], hudCache['street3CheckCallRaiseDone'][i], + hudCache['street4CheckCallRaiseChance'][i], hudCache['street4CheckCallRaiseDone'][i] + ) ) #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId=%s", (hands_id, player_ids[i])) #result.append(cursor.fetchall()[0][0]) - result.append( getLastInsertId(backend, conn, cursor) ) # mysql only + result.append( getLastInsertId(backend, conn, cursor) ) elif (category=="omahahi" or category=="omahahilo"): for i in xrange(len(player_ids)): cursor.execute ("""INSERT INTO HandsPlayers -(handId, playerId, startCash, position, -card1Value, card1Suit, card2Value, card2Suit, -card3Value, card3Suit, card4Value, card4Suit, winnings, rake, seatNo) -VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", - (hands_id, player_ids[i], start_cashes[i], positions[i], - card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], - card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3], - winnings[i], rakes[i], seatNos[i])) +(handId, playerId, startCash, position, activeSeats, tourneyTypeId, + card1Value, card1Suit, card2Value, card2Suit, + card3Value, card3Suit, card4Value, card4Suit, winnings, rake, seatNo, totalProfit, + street0VPI, street0Aggr, street0_3B4BChance, street0_3B4BDone, + street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown, + street1Aggr, street2Aggr, street3Aggr, street4Aggr, + otherRaisedStreet1, otherRaisedStreet2, otherRaisedStreet3, otherRaisedStreet4, + foldToOtherRaisedStreet1, foldToOtherRaisedStreet2, foldToOtherRaisedStreet3, foldToOtherRaisedStreet4, + wonWhenSeenStreet1, wonAtSD, + stealAttemptChance, stealAttempted, foldBbToStealChance, foldedBbToSteal, foldSbToStealChance, foldedSbToSteal, + street1CBChance, street1CBDone, street2CBChance, street2CBDone, + street3CBChance, street3CBDone, street4CBChance, street4CBDone, + foldToStreet1CBChance, foldToStreet1CBDone, foldToStreet2CBChance, foldToStreet2CBDone, + foldToStreet3CBChance, foldToStreet3CBDone, foldToStreet4CBChance, foldToStreet4CBDone, + street1CheckCallRaiseChance, street1CheckCallRaiseDone, street2CheckCallRaiseChance, street2CheckCallRaiseDone, + street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone +) +VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", + (hands_id, player_ids[i], start_cashes[i], positions[i], len(player_ids), 1, # tourneytypeid + card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], + card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3], + winnings[i], rakes[i], seatNos[i], hudCache['totalProfit'][i], + hudCache['street0VPI'][i], hudCache['street0Aggr'][i], + hudCache['street0_3B4BChance'][i], hudCache['street0_3B4BDone'][i], + hudCache['street1Seen'][i], hudCache['street2Seen'][i], hudCache['street3Seen'][i], + hudCache['street4Seen'][i], hudCache['sawShowdown'][i], + hudCache['street1Aggr'][i], hudCache['street2Aggr'][i], hudCache['street3Aggr'][i], hudCache['street4Aggr'][i], + hudCache['otherRaisedStreet1'][i], hudCache['otherRaisedStreet2'][i], + hudCache['otherRaisedStreet3'][i], hudCache['otherRaisedStreet4'][i], + hudCache['foldToOtherRaisedStreet1'][i], hudCache['foldToOtherRaisedStreet2'][i], + hudCache['foldToOtherRaisedStreet3'][i], hudCache['foldToOtherRaisedStreet4'][i], + hudCache['wonWhenSeenStreet1'][i], hudCache['wonAtSD'][i], + hudCache['stealAttemptChance'][i], hudCache['stealAttempted'][i], hudCache['foldBbToStealChance'][i], + hudCache['foldedBbToSteal'][i], hudCache['foldSbToStealChance'][i], hudCache['foldedSbToSteal'][i], + hudCache['street1CBChance'][i], hudCache['street1CBDone'][i], hudCache['street2CBChance'][i], hudCache['street2CBDone'][i], + hudCache['street3CBChance'][i], hudCache['street3CBDone'][i], hudCache['street4CBChance'][i], hudCache['street4CBDone'][i], + hudCache['foldToStreet1CBChance'][i], hudCache['foldToStreet1CBDone'][i], + hudCache['foldToStreet2CBChance'][i], hudCache['foldToStreet2CBDone'][i], + hudCache['foldToStreet3CBChance'][i], hudCache['foldToStreet3CBDone'][i], + hudCache['foldToStreet4CBChance'][i], hudCache['foldToStreet4CBDone'][i], + hudCache['street1CheckCallRaiseChance'][i], hudCache['street1CheckCallRaiseDone'][i], + hudCache['street2CheckCallRaiseChance'][i], hudCache['street2CheckCallRaiseDone'][i], + hudCache['street3CheckCallRaiseChance'][i], hudCache['street3CheckCallRaiseDone'][i], + hudCache['street4CheckCallRaiseChance'][i], hudCache['street4CheckCallRaiseDone'][i] + ) ) #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i])) #result.append(cursor.fetchall()[0][0]) - result.append( getLastInsertId(backend, conn, cursor) ) # mysql only + result.append( getLastInsertId(backend, conn, cursor) ) else: raise FpdbError("invalid category") return result @@ -1513,7 +1607,7 @@ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, card_values[i][6], card_suits[i][6], winnings[i], rakes[i], seatNos[i])) #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i])) #result.append(cursor.fetchall()[0][0]) - result.append( getLastInsertId(backend, conn, cursor) ) # mysql only + result.append( getLastInsertId(backend, conn, cursor) ) return result #end def store_hands_players_stud @@ -1547,7 +1641,7 @@ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", raise FpdbError ("invalid card_values length:"+str(len(card_values[0]))) #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i])) #result.append(cursor.fetchall()[0][0]) - result.append( getLastInsertId(backend, conn, cursor) ) # mysql only + result.append( getLastInsertId(backend, conn, cursor) ) return result #end def store_hands_players_holdem_omaha_tourney @@ -1572,7 +1666,7 @@ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, card_values[i][6], card_suits[i][6], winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i])) #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i])) #result.append(cursor.fetchall()[0][0]) - result.append( getLastInsertId(backend, conn, cursor) ) # mysql only + result.append( getLastInsertId(backend, conn, cursor) ) return result #end def store_hands_players_stud_tourney From a5884ff7ae21884933c478fd499784863c20463a Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 17 May 2009 12:41:47 +0800 Subject: [PATCH 074/104] Fix createHandsActionTable --- pyfpdb/FpdbSQLQueries.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index b9613e18..32c192f9 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -567,7 +567,7 @@ class FpdbSQLQueries: if(self.dbname == 'MySQL InnoDB'): self.query['createHandsActionsTable'] = """CREATE TABLE HandsActions ( id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), - handsPlayerId 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, @@ -579,7 +579,7 @@ class FpdbSQLQueries: elif(self.dbname == 'PostgreSQL'): self.query['createHandsActionsTable'] = """CREATE TABLE HandsActions ( id BIGSERIAL, PRIMARY KEY (id), - handsPlayerId BIGINT, FOREIGN KEY (handPlayerId) REFERENCES HandsPlayers(id), + handsPlayerId BIGINT, FOREIGN KEY (handsPlayerId) REFERENCES HandsPlayers(id), street SMALLINT, actionNo SMALLINT, action CHAR(5), From e2137a596ae4bdaac8122d93278a0d01c560e878 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 17 May 2009 17:26:05 +0100 Subject: [PATCH 075/104] screwed up previous release using branches, this should work now (added hc fields as well as hp, made new fields NULLable, use 3b not 3b4b fields), next job calculate some of these fields ... --- pyfpdb/DerivedStats.py | 6 +- pyfpdb/FpdbSQLQueries.py | 146 ++++++++++++++++++++++----------------- pyfpdb/GuiTableViewer.py | 4 +- pyfpdb/SQL.py | 138 ++++++++++++++++++------------------ pyfpdb/fpdb_simple.py | 54 +++++++-------- 5 files changed, 186 insertions(+), 162 deletions(-) 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/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index 32c192f9..e234df51 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -185,13 +185,13 @@ class FpdbSQLQueries: importTime DATETIME NOT NULL, seats SMALLINT NOT NULL, maxSeats SMALLINT NOT NULL, - vpi SMALLINT NOT NULL, - street0Seen SMALLINT NOT NULL, - street1Seen SMALLINT NOT NULL, - street2Seen SMALLINT NOT NULL, - street3Seen SMALLINT NOT NULL, - street4Seen SMALLINT NOT NULL, - sdSeen SMALLINT NOT NULL, + vpi SMALLINT, + street0Seen SMALLINT, + street1Seen SMALLINT, + street2Seen SMALLINT, + street3Seen SMALLINT, + street4Seen SMALLINT, + sdSeen SMALLINT, comment TEXT, commentTs DATETIME) ENGINE=INNODB""" @@ -205,13 +205,13 @@ class FpdbSQLQueries: importTime timestamp without time zone, seats SMALLINT, maxSeats SMALLINT, - vpi SMALLINT NOT NULL, - street0Seen SMALLINT NOT NULL, - street1Seen SMALLINT NOT NULL, - street2Seen SMALLINT NOT NULL, - street3Seen SMALLINT NOT NULL, - street4Seen SMALLINT NOT NULL, - sdSeen SMALLINT NOT NULL, + vpi SMALLINT, + street0Seen SMALLINT, + street1Seen SMALLINT, + street2Seen SMALLINT, + street3Seen SMALLINT, + street4Seen SMALLINT, + sdSeen SMALLINT, comment TEXT, commentTs timestamp without time zone)""" elif(self.dbname == 'SQLite'): @@ -348,19 +348,19 @@ class FpdbSQLQueries: tourneyTypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), wonWhenSeenStreet1 FLOAT NOT NULL, - wonWhenSeenStreet2 FLOAT NOT NULL, - wonWhenSeenStreet3 FLOAT NOT NULL, - wonWhenSeenStreet4 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 NOT NULL, - street0_4BDone BOOLEAN NOT NULL, - other3BStreet0 BOOLEAN NOT NULL, - other4BStreet0 BOOLEAN NOT NULL, + street0_4BChance BOOLEAN, + street0_4BDone BOOLEAN, + other3BStreet0 BOOLEAN, + other4BStreet0 BOOLEAN, street1Seen BOOLEAN NOT NULL, street2Seen BOOLEAN NOT NULL, @@ -373,12 +373,12 @@ class FpdbSQLQueries: street3Aggr BOOLEAN NOT NULL, street4Aggr BOOLEAN NOT NULL, - otherRaisedStreet0 BOOLEAN NOT NULL, + otherRaisedStreet0 BOOLEAN, otherRaisedStreet1 BOOLEAN NOT NULL, otherRaisedStreet2 BOOLEAN NOT NULL, otherRaisedStreet3 BOOLEAN NOT NULL, otherRaisedStreet4 BOOLEAN NOT NULL, - foldToOtherRaisedStreet0 BOOLEAN NOT NULL, + foldToOtherRaisedStreet0 BOOLEAN, foldToOtherRaisedStreet1 BOOLEAN NOT NULL, foldToOtherRaisedStreet2 BOOLEAN NOT NULL, foldToOtherRaisedStreet3 BOOLEAN NOT NULL, @@ -456,19 +456,19 @@ class FpdbSQLQueries: tourneyTypeId INT NOT NULL, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), wonWhenSeenStreet1 FLOAT NOT NULL, - wonWhenSeenStreet2 FLOAT NOT NULL, - wonWhenSeenStreet3 FLOAT NOT NULL, - wonWhenSeenStreet4 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 NOT NULL, - street0_4BDone BOOLEAN NOT NULL, - other3BStreet0 BOOLEAN NOT NULL, - other4BStreet0 BOOLEAN NOT NULL, + street0_4BChance BOOLEAN, + street0_4BDone BOOLEAN, + other3BStreet0 BOOLEAN, + other4BStreet0 BOOLEAN, street1Seen BOOLEAN NOT NULL, street2Seen BOOLEAN NOT NULL, @@ -481,12 +481,12 @@ class FpdbSQLQueries: street3Aggr BOOLEAN NOT NULL, street4Aggr BOOLEAN NOT NULL, - otherRaisedStreet0 BOOLEAN NOT NULL, + otherRaisedStreet0 BOOLEAN, otherRaisedStreet1 BOOLEAN NOT NULL, otherRaisedStreet2 BOOLEAN NOT NULL, otherRaisedStreet3 BOOLEAN NOT NULL, otherRaisedStreet4 BOOLEAN NOT NULL, - foldToOtherRaisedStreet0 BOOLEAN NOT NULL, + foldToOtherRaisedStreet0 BOOLEAN, foldToOtherRaisedStreet1 BOOLEAN NOT NULL, foldToOtherRaisedStreet2 BOOLEAN NOT NULL, foldToOtherRaisedStreet3 BOOLEAN NOT NULL, @@ -603,13 +603,23 @@ class FpdbSQLQueries: activeSeats SMALLINT NOT NULL, position CHAR(1), tourneyTypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), - 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, @@ -620,17 +630,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, @@ -638,7 +648,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, @@ -676,12 +686,23 @@ class FpdbSQLQueries: activeSeats SMALLINT, position CHAR(1), tourneyTypeId INT, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), - 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, @@ -691,16 +712,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, @@ -810,8 +832,8 @@ class FpdbSQLQueries: ,count(1) AS n ,100.0*sum(cast(street0VPI as integer))/count(1) AS vpip ,100.0*sum(cast(street0Aggr as integer))/count(1) AS pfr - ,case when sum(cast(street0_3b4bchance as integer)) = 0 then '0' - else 100.0*sum(cast(street0_3b4bdone as integer))/sum(cast(street0_3b4bchance as integer)) + ,case when sum(cast(street0_3Bchance as integer)) = 0 then '0' + else 100.0*sum(cast(street0_3Bdone as integer))/sum(cast(street0_3Bchance as integer)) end AS pf3 ,case when sum(cast(stealattemptchance as integer)) = 0 then -999 else 100.0*sum(cast(stealattempted as integer))/sum(cast(stealattemptchance as integer)) @@ -896,8 +918,8 @@ class FpdbSQLQueries: ,sum(HDs) AS n ,format(100.0*sum(street0VPI)/sum(HDs),1) AS vpip ,format(100.0*sum(street0Aggr)/sum(HDs),1) AS pfr - ,case when sum(street0_3b4bchance) = 0 then '0' - else format(100.0*sum(street0_3b4bdone)/sum(street0_3b4bchance),1) + ,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) @@ -996,8 +1018,8 @@ class FpdbSQLQueries: ,sum(HDs) as n ,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_3b4bchance) = 0 then '0' - else to_char(100.0*sum(street0_3b4bdone)/sum(street0_3b4bchance),'90D0') + ,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') @@ -1118,8 +1140,8 @@ class FpdbSQLQueries: ,sum(HDs) AS n ,format(100.0*sum(street0VPI)/sum(HDs),1) AS vpip ,format(100.0*sum(street0Aggr)/sum(HDs),1) AS pfr - ,case when sum(street0_3b4bchance) = 0 then '0' - else format(100.0*sum(street0_3b4bdone)/sum(street0_3b4bchance),1) + ,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) @@ -1249,8 +1271,8 @@ class FpdbSQLQueries: ,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_3b4bchance) = 0 then '0' - else to_char(100.0*sum(street0_3b4bdone)/sum(street0_3b4bchance),'90D0') + ,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') @@ -1448,8 +1470,8 @@ class FpdbSQLQueries: (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 @@ -1489,8 +1511,8 @@ class FpdbSQLQueries: ,wonAtSD ,street0VPI ,street0Aggr - ,street0_3B4BChance - ,street0_3B4BDone + ,street0_3BChance + ,street0_3BDone ,street1Seen ,street2Seen ,street3Seen @@ -1563,8 +1585,8 @@ class FpdbSQLQueries: ,sum(wonAtSD) ,sum(CAST(street0VPI as integer)) ,sum(CAST(street0Aggr as integer)) - ,sum(CAST(street0_3B4BChance as integer)) - ,sum(CAST(street0_3B4BDone 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)) diff --git a/pyfpdb/GuiTableViewer.py b/pyfpdb/GuiTableViewer.py index f024a193..35dbb797 100644 --- a/pyfpdb/GuiTableViewer.py +++ b/pyfpdb/GuiTableViewer.py @@ -76,7 +76,7 @@ class GuiTableViewer (threading.Thread): arr=[] #first prepare the header row if (self.category=="holdem" or self.category=="omahahi" or self.category=="omahahilo"): - tmp=("Name", "HDs", "VPIP", "PFR", "PF3B4B", "ST") + tmp=("Name", "HDs", "VPIP", "PFR", "PF3B", "ST") tmp+=("FS", "FB") @@ -131,7 +131,7 @@ class GuiTableViewer (threading.Thread): tmp.append(str(row[6]))#Hands tmp.append(self.hudDivide(row[7],row[6])) #VPIP tmp.append(self.hudDivide(row[8],row[6])) #PFR - tmp.append(self.hudDivide(row[10],row[9])+" ("+str(row[9])+")") #PF3B4B + tmp.append(self.hudDivide(row[10],row[9])+" ("+str(row[9])+")") #PF3B tmp.append(self.hudDivide(row[31],row[30])+" ("+str(row[30])+")") #ST diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 322b7fa0..9eb42d0f 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -172,72 +172,72 @@ class Sql: """ self.query['get_stats_from_hand'] = """ - SELECT HudCache.playerId AS player_id, - HandsPlayers.seatNo AS seat, - Players.name AS screen_name, - sum(HDs) AS n, - sum(street0VPI) AS vpip, - sum(street0Aggr) AS pfr, - sum(street0_3B4BChance) AS TB_opp_0, - sum(street0_3B4BDone) AS TB_0, - sum(street1Seen) AS saw_f, - sum(street1Seen) AS saw_1, - sum(street2Seen) AS saw_2, - sum(street3Seen) AS saw_3, - sum(street4Seen) AS saw_4, - sum(sawShowdown) AS sd, - sum(street1Aggr) AS aggr_1, - sum(street2Aggr) AS aggr_2, - sum(street3Aggr) AS aggr_3, - sum(street4Aggr) AS aggr_4, - sum(otherRaisedStreet1) AS was_raised_1, - sum(otherRaisedStreet2) AS was_raised_2, - sum(otherRaisedStreet3) AS was_raised_3, - sum(otherRaisedStreet4) AS was_raised_4, - sum(foldToOtherRaisedStreet1) AS f_freq_1, - sum(foldToOtherRaisedStreet2) AS f_freq_2, - sum(foldToOtherRaisedStreet3) AS f_freq_3, - sum(foldToOtherRaisedStreet4) AS f_freq_4, - sum(wonWhenSeenStreet1) AS w_w_s_1, - sum(wonAtSD) AS wmsd, - sum(stealAttemptChance) AS steal_opp, - sum(stealAttempted) AS steal, - sum(foldSbToStealChance) AS SBstolen, - sum(foldedSbToSteal) AS SBnotDef, - sum(foldBbToStealChance) AS BBstolen, - sum(foldedBbToSteal) AS BBnotDef, - sum(street1CBChance) AS CB_opp_1, - sum(street1CBDone) AS CB_1, - sum(street2CBChance) AS CB_opp_2, - sum(street2CBDone) AS CB_2, - sum(street3CBChance) AS CB_opp_3, - sum(street3CBDone) AS CB_3, - sum(street4CBChance) AS CB_opp_4, - sum(street4CBDone) AS CB_4, - sum(foldToStreet1CBChance) AS f_cb_opp_1, - sum(foldToStreet1CBDone) AS f_cb_1, - sum(foldToStreet2CBChance) AS f_cb_opp_2, - sum(foldToStreet2CBDone) AS f_cb_2, - sum(foldToStreet3CBChance) AS f_cb_opp_3, - sum(foldToStreet3CBDone) AS f_cb_3, - sum(foldToStreet4CBChance) AS f_cb_opp_4, - sum(foldToStreet4CBDone) AS f_cb_4, - sum(totalProfit) AS net, - sum(street1CheckCallRaiseChance) AS ccr_opp_1, - sum(street1CheckCallRaiseDone) AS ccr_1, - sum(street2CheckCallRaiseChance) AS ccr_opp_2, - sum(street2CheckCallRaiseDone) AS ccr_2, - sum(street3CheckCallRaiseChance) AS ccr_opp_3, - sum(street3CheckCallRaiseDone) AS ccr_3, - sum(street4CheckCallRaiseChance) AS ccr_opp_4, - sum(street4CheckCallRaiseDone) AS ccr_4 - FROM Hands - INNER JOIN HandsPlayers ON (HandsPlayers.handId = %s) - INNER JOIN HudCache ON ( HudCache.PlayerId = HandsPlayers.PlayerId+0 - AND HudCache.gametypeId+0 = Hands.gametypeId+0) - INNER JOIN Players ON (Players.id = HandsPlayers.PlayerId+0) - WHERE Hands.id = %s - GROUP BY HudCache.PlayerId, HandsPlayers.seatNo, Players.name + SELECT hc.playerId AS player_id, + hp.seatNo AS seat, + p.name AS screen_name, + sum(hc.HDs) AS n, + sum(hc.street0VPI) AS vpip, + sum(hc.street0Aggr) AS pfr, + sum(hc.street0_3BChance) AS TB_opp_0, + sum(hc.street0_3BDone) AS TB_0, + sum(hc.street1Seen) AS saw_f, + sum(hc.street1Seen) AS saw_1, + sum(hc.street2Seen) AS saw_2, + sum(hc.street3Seen) AS saw_3, + sum(hc.street4Seen) AS saw_4, + sum(hc.sawShowdown) AS sd, + sum(hc.street1Aggr) AS aggr_1, + sum(hc.street2Aggr) AS aggr_2, + sum(hc.street3Aggr) AS aggr_3, + sum(hc.street4Aggr) AS aggr_4, + sum(hc.otherRaisedStreet1) AS was_raised_1, + sum(hc.otherRaisedStreet2) AS was_raised_2, + sum(hc.otherRaisedStreet3) AS was_raised_3, + sum(hc.otherRaisedStreet4) AS was_raised_4, + sum(hc.foldToOtherRaisedStreet1) AS f_freq_1, + sum(hc.foldToOtherRaisedStreet2) AS f_freq_2, + sum(hc.foldToOtherRaisedStreet3) AS f_freq_3, + sum(hc.foldToOtherRaisedStreet4) AS f_freq_4, + sum(hc.wonWhenSeenStreet1) AS w_w_s_1, + sum(hc.wonAtSD) AS wmsd, + sum(hc.stealAttemptChance) AS steal_opp, + sum(hc.stealAttempted) AS steal, + sum(hc.foldSbToStealChance) AS SBstolen, + sum(hc.foldedSbToSteal) AS SBnotDef, + sum(hc.foldBbToStealChance) AS BBstolen, + sum(hc.foldedBbToSteal) AS BBnotDef, + sum(hc.street1CBChance) AS CB_opp_1, + sum(hc.street1CBDone) AS CB_1, + sum(hc.street2CBChance) AS CB_opp_2, + sum(hc.street2CBDone) AS CB_2, + sum(hc.street3CBChance) AS CB_opp_3, + sum(hc.street3CBDone) AS CB_3, + sum(hc.street4CBChance) AS CB_opp_4, + sum(hc.street4CBDone) AS CB_4, + sum(hc.foldToStreet1CBChance) AS f_cb_opp_1, + sum(hc.foldToStreet1CBDone) AS f_cb_1, + sum(hc.foldToStreet2CBChance) AS f_cb_opp_2, + sum(hc.foldToStreet2CBDone) AS f_cb_2, + sum(hc.foldToStreet3CBChance) AS f_cb_opp_3, + sum(hc.foldToStreet3CBDone) AS f_cb_3, + sum(hc.foldToStreet4CBChance) AS f_cb_opp_4, + sum(hc.foldToStreet4CBDone) AS f_cb_4, + sum(hc.totalProfit) AS net, + sum(hc.street1CheckCallRaiseChance) AS ccr_opp_1, + sum(hc.street1CheckCallRaiseDone) AS ccr_1, + sum(hc.street2CheckCallRaiseChance) AS ccr_opp_2, + sum(hc.street2CheckCallRaiseDone) AS ccr_2, + sum(hc.street3CheckCallRaiseChance) AS ccr_opp_3, + sum(hc.street3CheckCallRaiseDone) AS ccr_3, + sum(hc.street4CheckCallRaiseChance) AS ccr_opp_4, + sum(hc.street4CheckCallRaiseDone) AS ccr_4 + FROM Hands h + INNER JOIN HandsPlayers hp ON (hp.handId = %s) + INNER JOIN HudCache hc ON ( hc.PlayerId = hp.PlayerId+0 + AND hc.gametypeId+0 = h.gametypeId+0) + INNER JOIN Players p ON (p.id = hp.PlayerId+0) + WHERE h.id = %s + GROUP BY hc.PlayerId, hp.seatNo, p.name """ # same as above except stats are aggregated for all blind/limit levels @@ -246,8 +246,8 @@ class Sql: sum(HDs) AS n, sum(street0VPI) AS vpip, sum(street0Aggr) AS pfr, - sum(street0_3B4BChance) AS TB_opp_0, - sum(street0_3B4BDone) AS TB_0, + sum(street0_3BChance) AS TB_opp_0, + sum(street0_3BDone) AS TB_0, sum(street1Seen) AS saw_f, sum(street1Seen) AS saw_1, sum(street2Seen) AS saw_2, @@ -377,7 +377,7 @@ class Sql: FROM Players, HandsActions, HandsPlayers WHERE HandsPlayers.handid = %s AND HandsPlayers.playerid = Players.id - AND HandsActions.handPlayerId = HandsPlayers.id + AND HandsActions.handsPlayerId = HandsPlayers.id ORDER BY street, actionno """ if __name__== "__main__": diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index e8103ffa..cd8a9e76 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -54,7 +54,7 @@ indexes = [ , {'tab':'Gametypes', 'col':'siteId', 'drop':0} , {'tab':'Hands', 'col':'gametypeId', 'drop':0} # mct 22/3/09 , {'tab':'Hands', 'col':'siteHandNo', 'drop':0} - , {'tab':'HandsActions', 'col':'handplayerId', 'drop':0} + , {'tab':'HandsActions', 'col':'handsPlayerId', 'drop':0} , {'tab':'HandsPlayers', 'col':'handId', 'drop':1} , {'tab':'HandsPlayers', 'col':'playerId', 'drop':1} , {'tab':'HandsPlayers', 'col':'tourneysPlayersId', 'drop':0} @@ -78,7 +78,7 @@ foreignKeys = [ {'fktab':'Hands', 'fkcol':'gametypeId', 'rtab':'Gametypes', 'rcol':'id', 'drop':1} , {'fktab':'HandsPlayers', 'fkcol':'handId', 'rtab':'Hands', 'rcol':'id', 'drop':1} , {'fktab':'HandsPlayers', 'fkcol':'playerId', 'rtab':'Players', 'rcol':'id', 'drop':1} - , {'fktab':'HandsActions', 'fkcol':'handPlayerId', 'rtab':'HandsPlayers', 'rcol':'id', 'drop':1} + , {'fktab':'HandsActions', 'fkcol':'handsPlayerId', 'rtab':'HandsPlayers', 'rcol':'id', 'drop':1} , {'fktab':'HudCache', 'fkcol':'gametypeId', 'rtab':'Gametypes', 'rcol':'id', 'drop':1} , {'fktab':'HudCache', 'fkcol':'playerId', 'rtab':'Players', 'rcol':'id', 'drop':0} , {'fktab':'HudCache', 'fkcol':'tourneyTypeId', 'rtab':'TourneyTypes', 'rcol':'id', 'drop':1} @@ -87,7 +87,7 @@ foreignKeys = [ {'fktab':'Hands', 'fkcol':'gametypeId', 'rtab':'Gametypes', 'rcol':'id', 'drop':1} , {'fktab':'HandsPlayers', 'fkcol':'handId', 'rtab':'Hands', 'rcol':'id', 'drop':1} , {'fktab':'HandsPlayers', 'fkcol':'playerId', 'rtab':'Players', 'rcol':'id', 'drop':1} - , {'fktab':'HandsActions', 'fkcol':'handPlayerId', 'rtab':'HandsPlayers', 'rcol':'id', 'drop':1} + , {'fktab':'HandsActions', 'fkcol':'handsPlayerId', 'rtab':'HandsPlayers', 'rcol':'id', 'drop':1} , {'fktab':'HudCache', 'fkcol':'gametypeId', 'rtab':'Gametypes', 'rcol':'id', 'drop':1} , {'fktab':'HudCache', 'fkcol':'playerId', 'rtab':'Players', 'rcol':'id', 'drop':0} , {'fktab':'HudCache', 'fkcol':'tourneyTypeId', 'rtab':'TourneyTypes', 'rcol':'id', 'drop':1} @@ -1433,7 +1433,7 @@ def storeActions(cursor, handsPlayersIds, actionTypes, allIns, actionAmounts, ac # Add inserts into a list and let inserts = inserts + [(handsPlayersIds[j], i, actionNos[i][j][k], actionTypes[i][j][k], allIns[i][j][k], actionAmounts[i][j][k])] - cursor.executemany("INSERT INTO HandsActions (handPlayerId, street, actionNo, action, allIn, amount) VALUES (%s, %s, %s, %s, %s, %s)", inserts) + cursor.executemany("INSERT INTO HandsActions (handsPlayerId, street, actionNo, action, allIn, amount) VALUES (%s, %s, %s, %s, %s, %s)", inserts) #end def storeActions def store_board_cards(cursor, hands_id, board_values, board_suits): @@ -1482,7 +1482,7 @@ def store_hands_players_holdem_omaha(backend, conn, cursor, category, hands_id, INSERT INTO HandsPlayers (handId, playerId, startCash, position, activeSeats, tourneyTypeId, card1Value, card1Suit, card2Value, card2Suit, winnings, rake, seatNo, totalProfit, - street0VPI, street0Aggr, street0_3B4BChance, street0_3B4BDone, + street0VPI, street0Aggr, street0_3BChance, street0_3BDone, street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown, street1Aggr, street2Aggr, street3Aggr, street4Aggr, otherRaisedStreet1, otherRaisedStreet2, otherRaisedStreet3, otherRaisedStreet4, @@ -1503,7 +1503,7 @@ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], winnings[i], rakes[i], seatNos[i], hudCache['totalProfit'][i], hudCache['street0VPI'][i], hudCache['street0Aggr'][i], - hudCache['street0_3B4BChance'][i], hudCache['street0_3B4BDone'][i], + hudCache['street0_3BChance'][i], hudCache['street0_3BDone'][i], hudCache['street1Seen'][i], hudCache['street2Seen'][i], hudCache['street3Seen'][i], hudCache['street4Seen'][i], hudCache['sawShowdown'][i], hudCache['street1Aggr'][i], hudCache['street2Aggr'][i], hudCache['street3Aggr'][i], hudCache['street4Aggr'][i], @@ -1534,7 +1534,7 @@ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, (handId, playerId, startCash, position, activeSeats, tourneyTypeId, card1Value, card1Suit, card2Value, card2Suit, card3Value, card3Suit, card4Value, card4Suit, winnings, rake, seatNo, totalProfit, - street0VPI, street0Aggr, street0_3B4BChance, street0_3B4BDone, + street0VPI, street0Aggr, street0_3BChance, street0_3BDone, street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown, street1Aggr, street2Aggr, street3Aggr, street4Aggr, otherRaisedStreet1, otherRaisedStreet2, otherRaisedStreet3, otherRaisedStreet4, @@ -1556,7 +1556,7 @@ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3], winnings[i], rakes[i], seatNos[i], hudCache['totalProfit'][i], hudCache['street0VPI'][i], hudCache['street0Aggr'][i], - hudCache['street0_3B4BChance'][i], hudCache['street0_3B4BDone'][i], + hudCache['street0_3BChance'][i], hudCache['street0_3BDone'][i], hudCache['street1Seen'][i], hudCache['street2Seen'][i], hudCache['street3Seen'][i], hudCache['street4Seen'][i], hudCache['sawShowdown'][i], hudCache['street1Aggr'][i], hudCache['street2Aggr'][i], hudCache['street3Aggr'][i], hudCache['street4Aggr'][i], @@ -1679,8 +1679,8 @@ sure to also change the following storage method and table_viewer.prepare_data i #setup subarrays of the result dictionary. street0VPI=[] street0Aggr=[] - street0_3B4BChance=[] - street0_3B4BDone=[] + street0_3BChance=[] + street0_3BDone=[] street1Seen=[] street2Seen=[] street3Seen=[] @@ -1753,8 +1753,8 @@ sure to also change the following storage method and table_viewer.prepare_data i #set default values myStreet0VPI=False myStreet0Aggr=False - myStreet0_3B4BChance=False - myStreet0_3B4BDone=False + myStreet0_3BChance=False + myStreet0_3BDone=False myStreet1Seen=False myStreet2Seen=False myStreet3Seen=False @@ -1786,7 +1786,7 @@ sure to also change the following storage method and table_viewer.prepare_data i if currentAction == "bet" or currentAction == "call": myStreet0VPI = True - #PF3B4BChance and PF3B4B + #PF3BChance and PF3B pfFold=-1 pfRaise=-1 if firstPfRaiseByNo != -1: @@ -1797,9 +1797,9 @@ sure to also change the following storage method and table_viewer.prepare_data i if actionType[1] == "fold" and pfFold == -1: pfFold = i if pfFold == -1 or pfFold > firstPfRaiseByNo: - myStreet0_3B4BChance = True + myStreet0_3BChance = True if pfRaise > firstPfRaiseByNo: - myStreet0_3B4BDone = True + myStreet0_3BDone = True #steal calculations if base=="hold": @@ -1944,8 +1944,8 @@ sure to also change the following storage method and table_viewer.prepare_data i #add each value to the appropriate array street0VPI.append(myStreet0VPI) street0Aggr.append(myStreet0Aggr) - street0_3B4BChance.append(myStreet0_3B4BChance) - street0_3B4BDone.append(myStreet0_3B4BDone) + street0_3BChance.append(myStreet0_3BChance) + street0_3BDone.append(myStreet0_3BDone) street1Seen.append(myStreet1Seen) street2Seen.append(myStreet2Seen) street3Seen.append(myStreet3Seen) @@ -1993,8 +1993,8 @@ sure to also change the following storage method and table_viewer.prepare_data i #add each array to the to-be-returned dictionary result={'street0VPI':street0VPI} result['street0Aggr']=street0Aggr - result['street0_3B4BChance']=street0_3B4BChance - result['street0_3B4BDone']=street0_3B4BDone + result['street0_3BChance']=street0_3BChance + result['street0_3BDone']=street0_3BDone result['street1Seen']=street1Seen result['street2Seen']=street2Seen result['street3Seen']=street3Seen @@ -2305,8 +2305,8 @@ def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData): row[6]+=1 #HDs if hudImportData['street0VPI'][player]: row[7]+=1 if hudImportData['street0Aggr'][player]: row[8]+=1 - if hudImportData['street0_3B4BChance'][player]: row[9]+=1 - if hudImportData['street0_3B4BDone'][player]: row[10]+=1 + if hudImportData['street0_3BChance'][player]: row[9]+=1 + if hudImportData['street0_3BDone'][player]: row[10]+=1 if hudImportData['street1Seen'][player]: row[11]+=1 if hudImportData['street2Seen'][player]: row[12]+=1 if hudImportData['street3Seen'][player]: row[13]+=1 @@ -2369,7 +2369,7 @@ def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData): #print "playerid before insert:",row[2] cursor.execute("""INSERT INTO HudCache (gametypeId, playerId, activeSeats, position, tourneyTypeId, -HDs, street0VPI, street0Aggr, street0_3B4BChance, street0_3B4BDone, +HDs, street0VPI, street0Aggr, street0_3BChance, street0_3BDone, street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown, street1Aggr, street2Aggr, street3Aggr, street4Aggr, otherRaisedStreet1, otherRaisedStreet2, otherRaisedStreet3, otherRaisedStreet4, foldToOtherRaisedStreet1, foldToOtherRaisedStreet2, @@ -2395,7 +2395,7 @@ VALUES (%s, %s, %s, %s, %s, else: #print "storing updated hud data line" cursor.execute("""UPDATE HudCache -SET HDs=%s, street0VPI=%s, street0Aggr=%s, street0_3B4BChance=%s, street0_3B4BDone=%s, +SET HDs=%s, street0VPI=%s, street0Aggr=%s, street0_3BChance=%s, street0_3BDone=%s, street1Seen=%s, street2Seen=%s, street3Seen=%s, street4Seen=%s, sawShowdown=%s, street1Aggr=%s, street2Aggr=%s, street3Aggr=%s, street4Aggr=%s, otherRaisedStreet1=%s, otherRaisedStreet2=%s, otherRaisedStreet3=%s, otherRaisedStreet4=%s, foldToOtherRaisedStreet1=%s, foldToOtherRaisedStreet2=%s, @@ -2444,8 +2444,8 @@ def storeHudCache2(backend, cursor, base, category, gametypeId, playerIds, hudIm row[6]+=1 #HDs if hudImportData['street0VPI'][player]: row[7]+=1 if hudImportData['street0Aggr'][player]: row[8]+=1 - if hudImportData['street0_3B4BChance'][player]: row[9]+=1 - if hudImportData['street0_3B4BDone'][player]: row[10]+=1 + if hudImportData['street0_3BChance'][player]: row[9]+=1 + if hudImportData['street0_3BDone'][player]: row[10]+=1 if hudImportData['street1Seen'][player]: row[11]+=1 if hudImportData['street2Seen'][player]: row[12]+=1 if hudImportData['street3Seen'][player]: row[13]+=1 @@ -2507,7 +2507,7 @@ def storeHudCache2(backend, cursor, base, category, gametypeId, playerIds, hudIm # Try to do the update first: num = cursor.execute("""UPDATE HudCache SET HDs=HDs+%s, street0VPI=street0VPI+%s, street0Aggr=street0Aggr+%s, - street0_3B4BChance=street0_3B4BChance+%s, street0_3B4BDone=street0_3B4BDone+%s, + street0_3BChance=street0_3BChance+%s, street0_3BDone=street0_3BDone+%s, street1Seen=street1Seen+%s, street2Seen=street2Seen+%s, street3Seen=street3Seen+%s, street4Seen=street4Seen+%s, sawShowdown=sawShowdown+%s, street1Aggr=street1Aggr+%s, street2Aggr=street2Aggr+%s, street3Aggr=street3Aggr+%s, @@ -2556,7 +2556,7 @@ AND tourneyTypeId+0=%s""", (row[6], row[7], row[8], row[9], row[10], #print "playerid before insert:",row[2]," num = ", num cursor.execute("""INSERT INTO HudCache (gametypeId, playerId, activeSeats, position, tourneyTypeId, -HDs, street0VPI, street0Aggr, street0_3B4BChance, street0_3B4BDone, +HDs, street0VPI, street0Aggr, street0_3BChance, street0_3BDone, street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown, street1Aggr, street2Aggr, street3Aggr, street4Aggr, otherRaisedStreet1, otherRaisedStreet2, otherRaisedStreet3, otherRaisedStreet4, foldToOtherRaisedStreet1, foldToOtherRaisedStreet2, From b3b99778c9ce30d2abe430ad7334ac05b43d1a78 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 17 May 2009 22:59:09 +0100 Subject: [PATCH 076/104] make player stats use new single detailed query and format the output in python ready for more detailed stats --- pyfpdb/FpdbSQLQueries.py | 95 +++++++++++++------------- pyfpdb/GuiPlayerStats.py | 141 ++++++++++++++++++++------------------- 2 files changed, 124 insertions(+), 112 deletions(-) diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index e234df51..dd770106 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -320,7 +320,6 @@ class FpdbSQLQueries: startCash INT NOT NULL, position CHAR(1), seatNo SMALLINT NOT NULL, - activeSeats SMALLINT NOT NULL, card1Value smallint NOT NULL, card1Suit char(1) NOT NULL, @@ -428,7 +427,6 @@ class FpdbSQLQueries: startCash INT NOT NULL, position CHAR(1), seatNo SMALLINT NOT NULL, - activeSeats SMALLINT NOT NULL, card1Value smallint NOT NULL, card1Suit char(1) NOT NULL, @@ -816,66 +814,73 @@ class FpdbSQLQueries: if self.dbname in ['MySQL InnoDB', 'PostgreSQL']: self.query['playerDetailedStats'] = """ - select - h.gametypeId - ,sum(hp.totalProfit) AS sum_profit - ,avg(hp.totalProfit/100.0) AS profitperhand - /*,case when h.gametypeId = -1 then -999 - else variance(hp.totalProfit/100.0) - end AS variance*/ + select AS hgametypeid ,gt.base ,gt.category - ,upper(gt.limitType) AS limitType + ,upper(gt.limitType) AS limittype ,s.name - /*, AS bigBlindDesc - , AS gtId*/ + ,min(gt.bigBlind) AS minbigblind + ,max(gt.bigBlind) AS maxbigblind + /*, AS gtid*/ ,count(1) AS n - ,100.0*sum(cast(street0VPI as integer))/count(1) AS vpip - ,100.0*sum(cast(street0Aggr as integer))/count(1) AS pfr - ,case when sum(cast(street0_3Bchance as integer)) = 0 then '0' - else 100.0*sum(cast(street0_3Bdone as integer))/sum(cast(street0_3Bchance as integer)) + ,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(stealattemptchance as integer)) = 0 then -999 - else 100.0*sum(cast(stealattempted as integer))/sum(cast(stealattemptchance as integer)) + ,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(street1Seen as integer))/count(1) AS saw_f - ,100.0*sum(cast(sawShowdown as integer))/count(1) AS sawsd - ,case when sum(cast(street1Seen as integer)) = 0 then -999 - else 100.0*sum(cast(sawShowdown as integer))/sum(cast(street1Seen as integer)) + ,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(sawShowdown as integer)) = 0 then -999 - else 100.0*sum(cast(wonAtSD as integer))/sum(cast(sawShowdown as integer)) + ,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(street1Seen as integer)) = 0 then -999 - else 100.0*sum(cast(street1Aggr as integer))/sum(cast(street1Seen as integer)) - end AS FlAFq - ,case when sum(cast(street2Seen as integer)) = 0 then -999 - else 100.0*sum(cast(street2Aggr as integer))/sum(cast(street2Seen as integer)) - end AS TuAFq - ,case when sum(cast(street3Seen as integer)) = 0 then -999 - else 100.0*sum(cast(street3Aggr as integer))/sum(cast(street3Seen as integer)) - end AS RvAFq - ,case when sum(cast(street1Seen as integer))+sum(cast(street2Seen as integer))+sum(cast(street3Seen as integer)) = 0 then -999 - else 100.0*(sum(cast(street1Aggr as integer))+sum(cast(street2Aggr as integer))+sum(cast(street3Aggr as integer))) - /(sum(cast(street1Seen as integer))+sum(cast(street2Seen as integer))+sum(cast(street3Seen as integer))) - end AS PoFAFq - ,sum(totalProfit)/100.0 AS Net - ,(sum(totalProfit/(gt.bigBlind+0.0))) / (count(1)/100.0) - AS BBper100 - ,(sum(totalProfit)/100.0) / count(1) AS Profitperhand - ,sum(activeSeats)/(count(1)+0.0) AS AvgSeats + ,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 (1) /* */ + where hp.playerId in and hp.tourneysPlayersId IS NULL - group by h.gametypeId + and h.seats + group by hgameTypeId ,hp.playerId ,gt.base ,gt.category + ,upper(gt.limitType) - ,s.name""" + ,s.name + order by hp.playerId + ,gt.base + ,gt.category + + ,upper(gt.limitType) + ,s.name + """ elif(self.dbname == 'SQLite'): self.query['playerDetailedStats'] = """ """ diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 66b312ce..08207454 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -52,6 +52,7 @@ class GuiPlayerStats (threading.Thread): "Limits" : True, "LimitSep" : True, "Seats" : True, + "SeatSep" : True, "Dates" : False, "Button1" : True, "Button2" : False @@ -61,6 +62,31 @@ class GuiPlayerStats (threading.Thread): self.filters.registerButton1Name("Refresh") self.filters.registerButton1Callback(self.refreshStats) + # TODO: these probably be a dict keyed on colAlias and the headings loop should use colAlias ... + # This could be stored in config eventually, or maybe configured in this window somehow. + # Each colAlias element is the name of a column returned by the sql + # query (in lower case) and each colHeads element is the text to use as + # the heading in the GUI. Both sequences should be the same length. + # To miss columns out remove them from both tuples (the 1st 2 elements should always be included). + # To change the heading just edit the second list element as required + # If the first list element does not match a query column that pair is ignored + self.colAlias = ( "game", "n", "avgseats", "vpip", "pfr", "pf3", "steals" + , "saw_f", "sawsd", "wtsdwsf", "wmsd", "flafq", "tuafq", "rvafq" + , "pofafq", "net", "bbper100", "rake", "variance" + ) + self.colHeads = ( "Game", "Hds", "Seats", "VPIP", "PFR", "PF3", "Steals" + , "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq" + , "PoFAFq", "Net($)", "BB/100", "Rake($)", "Variance" + ) + self.colXAligns = ( 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 + , 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 + , 1.0, 1.0, 1.0, 1.0, 1.0 + ) + self.colFormats = ( "%s", "%d", "%3.1f", "%3.1f", "%3.1f", "%3.1f", "%3.1f" + , "%3.1f", "%3.1f", "%3.1f", "%3.1f", "%3.1f", "%3.1f", "%3.1f" + , "%3.1f", "%6.2f", "%4.2f", "%6.2f", "%5.2f" + ) + self.stat_table = None self.stats_frame = None @@ -120,45 +146,64 @@ class GuiPlayerStats (threading.Thread): self.createStatsTable(vbox, playerids, sitenos, limits, seats) def createStatsTable(self, vbox, playerids, sitenos, limits, seats): - tmp = self.sql.query['playerStats'] - tmp = self.refineQuery(tmp, playerids, sitenos, limits, seats) - self.cursor.execute(tmp) - result = self.cursor.fetchall() - cols = 19 - - rows = len(result)+1 # +1 for title row - self.stats_table = gtk.Table(rows, cols, False) + self.stats_table = gtk.Table(1, 1, False) self.stats_table.set_col_spacings(4) self.stats_table.show() vbox.add(self.stats_table) # Create header row - titles = ("Game", "Hands", "VPIP", "PFR", "PF3", "Steals", "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq", "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance", "AvgSeats") - - col = 0 row = 0 - for t in titles: - l = gtk.Label(titles[col]) + col = 0 + for t in self.colHeads: + l = gtk.Label(self.colHeads[col]) + l.set_alignment(xalign=self.colXAligns[col], yalign=0.5) l.show() self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK) col +=1 - for row in range(rows-1): + tmp = self.sql.query['playerDetailedStats'] + tmp = self.refineQuery(tmp, playerids, sitenos, limits, seats) + self.cursor.execute(tmp) + result = self.cursor.fetchall() + + #cols = 19 + rows = len(result) # +1 for title row + colnames = [desc[0].lower() for desc in self.cursor.description] + + col = 0 + for row in range(rows): if(row%2 == 0): bgcolor = "white" else: bgcolor = "lightgrey" - for col in range(cols): + for col,colname in enumerate(self.colAlias): + if colname in colnames: + value = result[row][colnames.index(colname)] + else: + if colname == 'game': + minbb = result[row][colnames.index('minbigblind')] + maxbb = result[row][colnames.index('maxbigblind')] + value = result[row][colnames.index('limittype')] + ' ' \ + + result[row][colnames.index('category')].title() + ' ' \ + + result[row][colnames.index('name')] + ' $' + if 100 * int(minbb/100.0) != minbb: + value += '%.2f' % (minbb/100.0) + else: + value += '%.0f' % (minbb/100.0) + if minbb != maxbb: + if 100 * int(maxbb/100.0) != maxbb: + value += ' - $' + '%.2f' % (maxbb/100.0) + else: + value += ' - $' + '%.0f' % (maxbb/100.0) + else: + continue eb = gtk.EventBox() eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) - if result[row][col]: - l = gtk.Label(result[row][col]) + if value and value != -999: + l = gtk.Label(self.colFormats[col] % value) else: l = gtk.Label(' ') - if col == 0: - l.set_alignment(xalign=0.0, yalign=0.5) - else: - l.set_alignment(xalign=1.0, yalign=0.5) + l.set_alignment(xalign=self.colXAligns[col], yalign=0.5) eb.add(l) self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) l.show() @@ -178,8 +223,8 @@ class GuiPlayerStats (threading.Thread): if seats: query = query.replace('', 'between ' + str(seats['from']) + ' and ' + str(seats['to'])) if 'show' in seats and seats['show']: - query = query.replace('', ',hc.activeSeats') - query = query.replace('', ',stats.AvgSeats') + query = query.replace('', ',h.seats') + query = query.replace('', ',h.seats') else: query = query.replace('', '') query = query.replace('', '') @@ -198,57 +243,19 @@ class GuiPlayerStats (threading.Thread): groupLevels = "show" not in str(limits) if groupLevels: - if self.db.backend == self.MYSQL_INNODB: - bigblindselect = """concat(trim(leading ' ' from - case when min(gt.bigBlind) < 100 - then format(min(gt.bigBlind)/100.0, 2) - else format(min(gt.bigBlind)/100.0, 0) - end) - ,' - ' - ,trim(leading ' ' from - case when max(gt.bigBlind) < 100 - then format(max(gt.bigBlind)/100.0, 2) - else format(max(gt.bigBlind)/100.0, 0) - end) - ) """ - else: - bigblindselect = """trim(leading ' ' from - case when min(gt.bigBlind) < 100 - then to_char(min(gt.bigBlind)/100.0,'90D00') - else to_char(min(gt.bigBlind)/100.0,'999990') - end) - || ' - ' || - trim(leading ' ' from - case when max(gt.bigBlind) < 100 - then to_char(max(gt.bigBlind)/100.0,'90D00') - else to_char(max(gt.bigBlind)/100.0,'999990') - end) """ - bigblindselect = "cast('' as char)" # avoid odd effects when some posns and/or seats - # are missing from some limits (dunno why cast is - # needed but it says "unknown type" otherwise?! - query = query.replace("", bigblindselect) query = query.replace("", "") query = query.replace("", "-1") query = query.replace("", "-1") else: - if self.db.backend == self.MYSQL_INNODB: - bigblindselect = """concat('$', trim(leading ' ' from - case when gt.bigBlind < 100 - then format(gt.bigBlind/100.0, 2) - else format(gt.bigBlind/100.0, 0) - end - ) ) """ - else: - bigblindselect = """'$' || trim(leading ' ' from - case when gt.bigBlind < 100 - then to_char(gt.bigBlind/100.0,'90D00') - else to_char(gt.bigBlind/100.0,'999990') - end - ) """ - query = query.replace("", bigblindselect) query = query.replace("", ",gt.bigBlind") query = query.replace("", "hc.gametypeId") query = query.replace("", "h.gameTypeId") + + if self.db.backend == self.MYSQL_INNODB: + query = query.replace("", 'signed ') + else: + query = query.replace("", '') + #print "query =\n", query return(query) #end def refineQuery(self, query, playerids, sitenos, limits): From cee4cade3e08b8da7c7818d8a12a6890ed4652c7 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 20 May 2009 09:58:38 +0100 Subject: [PATCH 077/104] Add hotkeys for stats windows and pass main window into guiplayerstats --- pyfpdb/GuiPlayerStats.py | 3 ++- pyfpdb/fpdb.py | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 08207454..73cb981f 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -27,9 +27,10 @@ import Filters import FpdbSQLQueries class GuiPlayerStats (threading.Thread): - def __init__(self, config, querylist, debug=True): + def __init__(self, config, querylist, mainwin, debug=True): self.debug=debug self.conf=config + self.main_window=mainwin self.MYSQL_INNODB = 2 self.PGSQL = 3 self.SQLITE = 4 diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 7fcf75ee..f310e255 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -331,7 +331,7 @@ class fpdb: #end def tab_bulk_import def tab_player_stats(self, widget, data): - new_ps_thread=GuiPlayerStats.GuiPlayerStats(self.config, self.querydict) + new_ps_thread=GuiPlayerStats.GuiPlayerStats(self.config, self.querydict, self.window) self.threads.append(new_ps_thread) ps_tab=new_ps_thread.get_vbox() self.add_and_display_tab(ps_tab, "Player Stats") @@ -401,8 +401,8 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") ("/Viewers/_Graphs", "G", self.tabGraphViewer, 0, None ), ("/Viewers/Hand _Replayer (todo)", None, self.not_implemented, 0, None ), ("/Viewers/Player _Details (todo)", None, self.not_implemented, 0, None ), - ("/Viewers/_Player Stats (tabulated view)", None, self.tab_player_stats, 0, None ), - ("/Viewers/Positional Stats (tabulated view)", None, self.tab_positional_stats, 0, None ), + ("/Viewers/_Player Stats (tabulated view)", "P", self.tab_player_stats, 0, None ), + ("/Viewers/P_ositional Stats (tabulated view)", "O", self.tab_positional_stats, 0, None ), ("/Viewers/Starting _Hands (todo)", None, self.not_implemented, 0, None ), ("/Viewers/_Session Replayer (todo)", None, self.not_implemented, 0, None ), ("/Viewers/Poker_table Viewer (mostly obselete)", "T", self.tab_table_viewer, 0, None ), From 93f643a9585d48befc00e8e37b6fdf05325c17e9 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 20 May 2009 23:21:50 +0100 Subject: [PATCH 078/104] fix error when choosing unimplemented menu option --- pyfpdb/fpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index f310e255..06b5d1f9 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -290,7 +290,7 @@ class fpdb: self.db.db.rollback() #end def load_profile - def not_implemented(self): + def not_implemented(self, widget, data): print "todo: called unimplemented menu entry (users: pls ignore this)"#remove this once more entries are implemented #end def not_implemented From cf8b6c7e923ef4e97eab0866817924e5e15c0c9e Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 21 May 2009 04:26:00 +0100 Subject: [PATCH 079/104] several db changes and a fancy playerstats window, now to tidy the code up a bit .... --- pyfpdb/Card.py | 68 +++++++ pyfpdb/Database.py | 16 +- pyfpdb/Filters.py | 111 ++++++++---- pyfpdb/FpdbSQLQueries.py | 204 +++++++++++++++------ pyfpdb/GuiPlayerStats.py | 368 ++++++++++++++++++++++++++++---------- pyfpdb/SQL.py | 14 +- pyfpdb/fpdb_save_to_db.py | 4 +- pyfpdb/fpdb_simple.py | 200 ++++++++++++++++++--- 8 files changed, 758 insertions(+), 227 deletions(-) create mode 100755 pyfpdb/Card.py diff --git a/pyfpdb/Card.py b/pyfpdb/Card.py new file mode 100755 index 00000000..4ecd69b0 --- /dev/null +++ b/pyfpdb/Card.py @@ -0,0 +1,68 @@ +#!/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 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/Database.py b/pyfpdb/Database.py index 0e5c1547..0483da96 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -32,6 +32,7 @@ import traceback # FreePokerTools modules import Configuration import SQL +import Card class Database: def __init__(self, c, db_name, game): @@ -78,6 +79,7 @@ class Database: self.type = c.supported_databases[db_name].db_type self.sql = SQL.Sql(game = game, type = self.type) + self.connection.rollback() def close_connection(self): self.connection.close() @@ -122,11 +124,17 @@ class Database: c = self.connection.cursor() 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): diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index d35d0817..3a5f0365 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -38,6 +38,7 @@ class Filters(threading.Thread): self.settings=settings self.sql=qdict self.conf = config + self.display = display self.sites = {} self.games = {} @@ -45,10 +46,12 @@ class Filters(threading.Thread): 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 Seats' + 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. @@ -66,6 +69,7 @@ class Filters(threading.Thread): self.fillPlayerFrame(vbox) playerFrame.add(vbox) + self.boxes['player'] = vbox sitesFrame = gtk.Frame("Sites:") sitesFrame.set_label_align(0.0, 0.0) @@ -73,6 +77,7 @@ class Filters(threading.Thread): self.fillSitesFrame(vbox) sitesFrame.add(vbox) + self.boxes['sites'] = vbox # Game types gamesFrame = gtk.Frame("Games:") @@ -82,29 +87,29 @@ class Filters(threading.Thread): self.fillGamesFrame(vbox) gamesFrame.add(vbox) + self.boxes['games'] = vbox # Limits - limitsFrame = gtk.Frame("Limits:") - limitsFrame.set_label_align(0.0, 0.0) + limitsFrame = gtk.Frame() limitsFrame.show() vbox = gtk.VBox(False, 0) self.cbLimits = {} self.cbNoLimits = None self.cbAllLimits = None - self.fillLimitsFrame(vbox, display) + self.fillLimitsFrame(vbox, self.display) limitsFrame.add(vbox) # Seats - seatsFrame = gtk.Frame("Seats:") - seatsFrame.set_label_align(0.0, 0.0) + seatsFrame = gtk.Frame() seatsFrame.show() vbox = gtk.VBox(False, 0) self.sbSeats = {} - self.fillSeatsFrame(vbox, display) + self.fillSeatsFrame(vbox, self.display) seatsFrame.add(vbox) + # Date dateFrame = gtk.Frame("Date:") dateFrame.set_label_align(0.0, 0.0) dateFrame.show() @@ -112,11 +117,13 @@ class Filters(threading.Thread): 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.exportButton.connect("clicked", self.exportGraph, "show clicked") self.Button2.set_sensitive(False) self.mainVBox.add(playerFrame) @@ -131,21 +138,21 @@ class Filters(threading.Thread): self.mainVBox.show_all() # Should do this cleaner - if "Heroes" not in display or display["Heroes"] == False: + if "Heroes" not in self.display or self.display["Heroes"] == False: playerFrame.hide() - if "Sites" not in display or display["Sites"] == False: + if "Sites" not in self.display or self.display["Sites"] == False: sitesFrame.hide() - if "Games" not in display or display["Games"] == False: + if "Games" not in self.display or self.display["Games"] == False: gamesFrame.hide() - if "Limits" not in display or display["Limits"] == False: + if "Limits" not in self.display or self.display["Limits"] == False: limitsFrame.hide() - if "Seats" not in display or display["Seats"] == False: + if "Seats" not in self.display or self.display["Seats"] == False: seatsFrame.hide() - if "Dates" not in display or display["Dates"] == False: + if "Dates" not in self.display or self.display["Dates"] == False: dateFrame.hide() - if "Button1" not in display or display["Button1"] == False: + if "Button1" not in self.display or self.display["Button1"] == False: self.Button1.hide() - if "Button2" not in display or display["Button2"] == False: + if "Button2" not in self.display or self.display["Button2"] == False: self.Button2.hide() def get_vbox(self): @@ -184,12 +191,14 @@ class Filters(threading.Thread): 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()]) @@ -226,7 +235,7 @@ class Filters(threading.Thread): cb = gtk.CheckButton(str(ltext)) cb.connect('clicked', self.__set_limit_select, limit) hbox.pack_start(cb, False, False, 0) - if limit != "None": + if limit != "none": cb.set_active(True) return(cb) @@ -251,11 +260,11 @@ class Filters(threading.Thread): else: if self.cbAllLimits != None: self.cbAllLimits.set_active(False) - elif limit == "All": + elif limit == "all": if self.limits[limit]: for cb in self.cbLimits.values(): cb.set_active(True) - elif limit == "None": + elif limit == "none": if self.limits[limit]: for cb in self.cbLimits.values(): cb.set_active(False) @@ -298,38 +307,66 @@ class Filters(threading.Thread): 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) - vbox.pack_start(hbox, False, False, 0) - vbox1 = gtk.VBox(False, 0) - hbox.pack_start(vbox1, False, False, 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: - vbox1.pack_start(hbox, False, False, 0) - else: 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) - vbox.pack_start(hbox, False, True, 0) + vbox1.pack_start(hbox, False, True, 0) self.cbAllLimits = self.createLimitLine(hbox, 'all', self.filterText['limitsall']) hbox = gtk.HBox(False, 0) - vbox.pack_start(hbox, False, True, 0) + vbox1.pack_start(hbox, False, True, 0) self.cbNoLimits = self.createLimitLine(hbox, 'none', self.filterText['limitsnone']) hbox = gtk.HBox(False, 0) - vbox.pack_start(hbox, False, True, 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, True, 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']) @@ -338,8 +375,6 @@ class Filters(threading.Thread): 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) @@ -347,7 +382,7 @@ class Filters(threading.Thread): if "SeatSep" in display and display["SeatSep"] == True: hbox = gtk.HBox(False, 0) - vbox.pack_start(hbox, False, True, 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) @@ -358,8 +393,6 @@ class Filters(threading.Thread): self.sbSeats['from'] = sb1 self.sbSeats['to'] = sb2 - - def fillCardsFrame(self, vbox): hbox1 = gtk.HBox(True,0) hbox1.show() @@ -414,6 +447,16 @@ class Filters(threading.Thread): 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') diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index dd770106..422da934 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -183,37 +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, - vpi SMALLINT, - street0Seen SMALLINT, - street1Seen SMALLINT, - street2Seen SMALLINT, - street3Seen SMALLINT, - street4Seen SMALLINT, - sdSeen SMALLINT, + 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, - vpi SMALLINT, - street0Seen SMALLINT, - street1Seen SMALLINT, - street2Seen SMALLINT, - street3Seen SMALLINT, - street4Seen SMALLINT, - sdSeen 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'] = """ """ @@ -321,20 +351,13 @@ class FpdbSQLQueries: position CHAR(1), seatNo SMALLINT NOT NULL, - 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), + 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, @@ -416,7 +439,25 @@ class FpdbSQLQueries: 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'): @@ -428,20 +469,13 @@ class FpdbSQLQueries: position CHAR(1), seatNo SMALLINT NOT NULL, - 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), + 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, @@ -524,6 +558,24 @@ class FpdbSQLQueries: 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'] = """ """ @@ -674,7 +726,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 ( @@ -756,7 +825,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'] = """ """ @@ -867,6 +953,8 @@ class FpdbSQLQueries: where hp.playerId in and hp.tourneysPlayersId IS NULL and h.seats + + group by hgameTypeId ,hp.playerId ,gt.base @@ -878,6 +966,8 @@ class FpdbSQLQueries: ,gt.base ,gt.category + + ,maxbigblind desc ,upper(gt.limitType) ,s.name """ diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 73cb981f..a7f3abf1 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -20,7 +20,9 @@ import pygtk pygtk.require('2.0') import gtk import os - +from time import time, strftime + +import Card import fpdb_import import fpdb_db import Filters @@ -47,6 +49,10 @@ class GuiPlayerStats (threading.Thread): settings.update(config.get_import_parameters()) settings.update(config.get_default_paths()) + # text used on screen stored here so that it can be configured + self.filterText = {'handhead':'Hand Breakdown for all levels listed above' + } + filters_display = { "Heroes" : True, "Sites" : True, "Games" : False, @@ -55,65 +61,93 @@ class GuiPlayerStats (threading.Thread): "Seats" : True, "SeatSep" : True, "Dates" : False, + "Groups" : True, "Button1" : True, - "Button2" : False + "Button2" : True } self.filters = Filters.Filters(self.db, settings, config, querylist, display = filters_display) - self.filters.registerButton1Name("Refresh") - self.filters.registerButton1Callback(self.refreshStats) + self.filters.registerButton1Name("_Filters") + self.filters.registerButton1Callback(self.showDetailFilter) + self.filters.registerButton2Name("_Refresh") + self.filters.registerButton2Callback(self.refreshStats) - # TODO: these probably be a dict keyed on colAlias and the headings loop should use colAlias ... - # This could be stored in config eventually, or maybe configured in this window somehow. - # Each colAlias element is the name of a column returned by the sql - # query (in lower case) and each colHeads element is the text to use as - # the heading in the GUI. Both sequences should be the same length. - # To miss columns out remove them from both tuples (the 1st 2 elements should always be included). - # To change the heading just edit the second list element as required - # If the first list element does not match a query column that pair is ignored - self.colAlias = ( "game", "n", "avgseats", "vpip", "pfr", "pf3", "steals" - , "saw_f", "sawsd", "wtsdwsf", "wmsd", "flafq", "tuafq", "rvafq" - , "pofafq", "net", "bbper100", "rake", "variance" - ) - self.colHeads = ( "Game", "Hds", "Seats", "VPIP", "PFR", "PF3", "Steals" - , "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq" - , "PoFAFq", "Net($)", "BB/100", "Rake($)", "Variance" - ) - self.colXAligns = ( 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 - , 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 - , 1.0, 1.0, 1.0, 1.0, 1.0 - ) - self.colFormats = ( "%s", "%d", "%3.1f", "%3.1f", "%3.1f", "%3.1f", "%3.1f" - , "%3.1f", "%3.1f", "%3.1f", "%3.1f", "%3.1f", "%3.1f", "%3.1f" - , "%3.1f", "%6.2f", "%4.2f", "%6.2f", "%5.2f" - ) + # ToDo: store in config + # ToDo: create popup to adjust column config + # columns to display, keys match column name returned by sql, values in tuple are: + # is column displayed, column heading, xalignment, formatting + self.columns = [ ("game", True, "Game", 0.0, "%s") + , ("hand", False, "Hand", 0.0, "%s") # true not allowed for this line + , ("n", True, "Hds", 1.0, "%d") + , ("avgseats", True, "Seats", 1.0, "%3.1f") + , ("vpip", True, "VPIP", 1.0, "%3.1f") + , ("pfr", True, "PFR", 1.0, "%3.1f") + , ("pf3", True, "PF3", 1.0, "%3.1f") + , ("steals", True, "Steals", 1.0, "%3.1f") + , ("saw_f", True, "Saw_F", 1.0, "%3.1f") + , ("sawsd", True, "SawSD", 1.0, "%3.1f") + , ("wtsdwsf", True, "WtSDwsF", 1.0, "%3.1f") + , ("wmsd", True, "W$SD", 1.0, "%3.1f") + , ("flafq", True, "FlAFq", 1.0, "%3.1f") + , ("tuafq", True, "TuAFq", 1.0, "%3.1f") + , ("rvafq", True, "RvAFq", 1.0, "%3.1f") + , ("pofafq", False, "PoFAFq", 1.0, "%3.1f") + , ("net", True, "Net($)", 1.0, "%6.2f") + , ("bbper100", True, "BB/100", 1.0, "%4.2f") + , ("rake", True, "Rake($)", 1.0, "%6.2f") + , ("variance", True, "Variance", 1.0, "%5.2f") + ] + + # Detail filters: This holds the data used in the popup window, extra values are + # added at the end of these lists during processing + # sql test, screen description, min, max + self.handtests = [ # already in filter class : ['h.seats', 'Number of Players', 2, 10] + ['h.maxSeats', 'Size of Table', 2, 10] + ,['h.playersVpi', 'Players who VPI', 0, 10] + ,['h.playersAtStreet1', 'Players at Flop', 0, 10] + ,['h.playersAtStreet2', 'Players at Turn', 0, 10] + ,['h.playersAtStreet3', 'Players at River', 0, 10] + ,['h.playersAtStreet4', 'Players at Street7', 0, 10] + ,['h.playersAtShowdown', 'Players at Showdown', 0, 10] + ,['h.street0Raises', 'Bets to See Flop', 0, 5] + ,['h.street1Raises', 'Bets to See Turn', 0, 5] + ,['h.street2Raises', 'Bets to See River', 0, 5] + ,['h.street3Raises', 'Bets to See Street7', 0, 5] + ,['h.street4Raises', 'Bets to See Showdown', 0, 5] + ] - self.stat_table = None self.stats_frame = None + self.stats_vbox = None + self.detailFilters = [] # the data used to enhance the sql select self.main_hbox = gtk.HBox(False, 0) self.main_hbox.show() - statsFrame = gtk.Frame("Stats:") - statsFrame.set_label_align(0.0, 0.0) - statsFrame.show() - self.stats_frame = gtk.VBox(False, 0) + self.stats_frame = gtk.Frame() self.stats_frame.show() - self.fillStatsFrame(self.stats_frame) - statsFrame.add(self.stats_frame) + self.stats_vbox = gtk.VBox(False, 0) + self.stats_vbox.show() + self.stats_frame.add(self.stats_vbox) + self.fillStatsFrame(self.stats_vbox) self.main_hbox.pack_start(self.filters.get_vbox()) - self.main_hbox.pack_start(statsFrame) + self.main_hbox.pack_start(self.stats_frame, expand=True, fill=True) + + # make sure Hand column is not displayed + [x for x in self.columns if x[0] == 'hand'][0][1] == False def get_vbox(self): """returns the vbox of this thread""" return self.main_hbox def refreshStats(self, widget, data): - try: self.stats_table.destroy() + try: self.stats_vbox.destroy() except AttributeError: pass - self.fillStatsFrame(self.stats_frame) + self.stats_vbox = gtk.VBox(False, 0) + self.stats_vbox.show() + self.stats_frame.add(self.stats_vbox) + self.fillStatsFrame(self.stats_vbox) def fillStatsFrame(self, vbox): sites = self.filters.getSites() @@ -147,72 +181,137 @@ class GuiPlayerStats (threading.Thread): self.createStatsTable(vbox, playerids, sitenos, limits, seats) def createStatsTable(self, vbox, playerids, sitenos, limits, seats): + starttime = time() + + # Display summary table at top of page + # 3rd parameter passes extra flags, currently includes: + # holecards - whether to display card breakdown (True/False) + flags = [False] + self.addTable(vbox, 'playerDetailedStats', flags, playerids, sitenos, limits, seats) + + # Separator + sep = gtk.HSeparator() + vbox.pack_start(sep, expand=False, padding=3) + sep.show_now() + vbox.show_now() + heading = gtk.Label(self.filterText['handhead']) + heading.show() + vbox.pack_start(heading, expand=False, padding=3) + + # Scrolled window for detailed table (display by hand) + swin = gtk.ScrolledWindow(hadjustment=None, vadjustment=None) + swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + swin.show() + vbox.pack_start(swin, expand=True, padding=3) + + vbox1 = gtk.VBox(False, 0) + vbox1.show() + swin.add_with_viewport(vbox1) + + # Detailed table + flags = [True] + self.addTable(vbox1, 'playerDetailedStats', flags, playerids, sitenos, limits, seats) + + self.db.db.commit() + print "Stats page displayed in %4.2f seconds" % (time() - starttime) + #end def fillStatsFrame(self, vbox): + + def addTable(self, vbox, query, flags, playerids, sitenos, limits, seats): + row = 0 + sqlrow = 0 + colalias,colshow,colheading,colxalign,colformat = 0,1,2,3,4 + if not flags: holecards = False + else: holecards = flags[0] + + self.stats_table = gtk.Table(1, 1, False) self.stats_table.set_col_spacings(4) self.stats_table.show() - vbox.add(self.stats_table) - - # Create header row - row = 0 - col = 0 - for t in self.colHeads: - l = gtk.Label(self.colHeads[col]) - l.set_alignment(xalign=self.colXAligns[col], yalign=0.5) - l.show() - self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK) - col +=1 - - tmp = self.sql.query['playerDetailedStats'] - tmp = self.refineQuery(tmp, playerids, sitenos, limits, seats) + + tmp = self.sql.query[query] + tmp = self.refineQuery(tmp, flags, playerids, sitenos, limits, seats) self.cursor.execute(tmp) result = self.cursor.fetchall() - - #cols = 19 - rows = len(result) # +1 for title row colnames = [desc[0].lower() for desc in self.cursor.description] - col = 0 - for row in range(rows): + # pre-fetch some constant values: + cols_to_show = [x for x in self.columns if x[colshow]] + hgametypeid_idx = colnames.index('hgametypeid') + + liststore = gtk.ListStore(*([str] * len(cols_to_show))) + view = gtk.TreeView(model=liststore) + view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH) + vbox.pack_start(view, expand=False, padding=3) + textcell = gtk.CellRendererText() + numcell = gtk.CellRendererText() + numcell.set_property('xalign', 1.0) + listcols = [] + + # Create header row eg column: ("game", True, "Game", 0.0, "%s") + for col, column in enumerate(cols_to_show): + if column[colalias] == 'game' and holecards: + s = [x for x in self.columns if x[colalias] == 'hand'][0][colheading] + else: + s = column[colheading] + listcols.append(gtk.TreeViewColumn(s)) + view.append_column(listcols[col]) + if column[colformat] == '%s': + if col == 1 and holecards: + listcols[col].pack_start(textcell, expand=True) + else: + listcols[col].pack_start(textcell, expand=False) + listcols[col].add_attribute(textcell, 'text', col) + else: + listcols[col].pack_start(numcell, expand=False) + listcols[col].add_attribute(numcell, 'text', col) + + rows = len(result) # +1 for title row + + while sqlrow < rows: + treerow = [] if(row%2 == 0): bgcolor = "white" else: bgcolor = "lightgrey" - for col,colname in enumerate(self.colAlias): - if colname in colnames: - value = result[row][colnames.index(colname)] + for col,column in enumerate(cols_to_show): + if column[colalias] in colnames: + value = result[sqlrow][colnames.index(column[colalias])] else: - if colname == 'game': - minbb = result[row][colnames.index('minbigblind')] - maxbb = result[row][colnames.index('maxbigblind')] - value = result[row][colnames.index('limittype')] + ' ' \ - + result[row][colnames.index('category')].title() + ' ' \ - + result[row][colnames.index('name')] + ' $' - if 100 * int(minbb/100.0) != minbb: - value += '%.2f' % (minbb/100.0) + if column[colalias] == 'game': + if holecards: + value = Card.twoStartCardString( result[sqlrow][hgametypeid_idx] ) else: - value += '%.0f' % (minbb/100.0) - if minbb != maxbb: - if 100 * int(maxbb/100.0) != maxbb: - value += ' - $' + '%.2f' % (maxbb/100.0) + minbb = result[sqlrow][colnames.index('minbigblind')] + maxbb = result[sqlrow][colnames.index('maxbigblind')] + value = result[sqlrow][colnames.index('limittype')] + ' ' \ + + result[sqlrow][colnames.index('category')].title() + ' ' \ + + result[sqlrow][colnames.index('name')] + ' $' + if 100 * int(minbb/100.0) != minbb: + value += '%.2f' % (minbb/100.0) else: - value += ' - $' + '%.0f' % (maxbb/100.0) + value += '%.0f' % (minbb/100.0) + if minbb != maxbb: + if 100 * int(maxbb/100.0) != maxbb: + value += ' - $' + '%.2f' % (maxbb/100.0) + else: + value += ' - $' + '%.0f' % (maxbb/100.0) else: continue - eb = gtk.EventBox() - eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) if value and value != -999: - l = gtk.Label(self.colFormats[col] % value) + treerow.append(column[colformat] % value) else: - l = gtk.Label(' ') - l.set_alignment(xalign=self.colXAligns[col], yalign=0.5) - eb.add(l) - self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) - l.show() - eb.show() - self.db.db.commit() - #end def fillStatsFrame(self, vbox): + treerow.append(' ') + iter = liststore.append(treerow) + sqlrow += 1 + row += 1 + vbox.show_all() + + #end def addTable(self, query, vars, playerids, sitenos, limits, seats): + + def refineQuery(self, query, flags, playerids, sitenos, limits, seats): + if not flags: holecards = False + else: holecards = flags[0] - def refineQuery(self, query, playerids, sitenos, limits, seats): if playerids: nametest = str(tuple(playerids)) nametest = nametest.replace("L", "") @@ -238,20 +337,32 @@ class GuiPlayerStats (threading.Thread): blindtest = str(tuple([x for x in limits if str(x).isdigit()])) blindtest = blindtest.replace("L", "") blindtest = blindtest.replace(",)",")") - query = query.replace("", "gt.bigBlind in " + blindtest) + query = query.replace("", " and gt.bigBlind in " + blindtest + " ") else: - query = query.replace("", "gt.bigBlind = -1 ") + query = query.replace("", "") - groupLevels = "show" not in str(limits) - if groupLevels: - query = query.replace("", "") - query = query.replace("", "-1") - query = query.replace("", "-1") + if holecards: # pinch level variables for hole card query + query = query.replace("", "hp.startcards") + query = query.replace("", ",hgameTypeId desc") else: - query = query.replace("", ",gt.bigBlind") - query = query.replace("", "hc.gametypeId") - query = query.replace("", "h.gameTypeId") + query = query.replace("", "") + groupLevels = "show" not in str(limits) + if groupLevels: + query = query.replace("", "-1") + else: + query = query.replace("", "h.gameTypeId") + # process self.detailFilters (a list of tuples) + flagtest = '' + #self.detailFilters = [('h.seats', 5, 6)] # for debug + if self.detailFilters: + for f in self.detailFilters: + if len(f) == 3: + # X between Y and Z + flagtest += ' and %s between %s and %s ' % (f[0], str(f[1]), str(f[2])) + query = query.replace("", flagtest) + + # allow for differences in sql cast() function: if self.db.backend == self.MYSQL_INNODB: query = query.replace("", 'signed ') else: @@ -260,3 +371,70 @@ class GuiPlayerStats (threading.Thread): #print "query =\n", query return(query) #end def refineQuery(self, query, playerids, sitenos, limits): + + def showDetailFilter(self, widget, data): + detailDialog = gtk.Dialog(title="Detailed Filters", parent=self.main_window + ,flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT + ,buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, + gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)) + + handbox = gtk.VBox(True, 0) + detailDialog.vbox.pack_start(handbox, False, False, 0) + handbox.show() + + label = gtk.Label("Hand Filters:") + handbox.add(label) + label.show() + + betweenFilters = [] + for htest in self.handtests: + hbox = gtk.HBox(False, 0) + handbox.pack_start(hbox, False, False, 0) + hbox.show() + + cb = gtk.CheckButton() + lbl_from = gtk.Label(htest[1]) + lbl_from.set_alignment(xalign=0.0, yalign=0.5) + lbl_tween = gtk.Label('between') + lbl_to = gtk.Label('and') + adj1 = gtk.Adjustment(value=htest[2], lower=0, 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=htest[3], lower=2, upper=10, step_incr=1, page_incr=1, page_size=0) + sb2 = gtk.SpinButton(adjustment=adj2, climb_rate=0.0, digits=0) + + for df in [x for x in self.detailFilters if x[0] == htest[0]]: + cb.set_active(True) + + hbox.pack_start(cb, expand=False, padding=3) + hbox.pack_start(lbl_from, expand=True, padding=3) + hbox.pack_start(lbl_tween, 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) + + cb.show() + lbl_from.show() + lbl_tween.show() + sb1.show() + lbl_to.show() + sb2.show() + + htest[4:7] = [cb,sb1,sb2] + + response = detailDialog.run() + + if response == gtk.RESPONSE_ACCEPT: + self.detailFilters = [] + for ht in self.handtests: + if ht[4].get_active(): + self.detailFilters.append( (ht[0], ht[5].get_value_as_int(), ht[6].get_value_as_int()) ) + ht[2],ht[3] = ht[5].get_value_as_int(), ht[6].get_value_as_int() + print "detailFilters =", self.detailFilters + self.refreshStats(None, None) + + detailDialog.destroy() + + + + + diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 9eb42d0f..6d4c3241 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -349,13 +349,13 @@ class Sql: select seatNo AS seat_number, name AS screen_name, - card1Value, card1Suit, - card2Value, card2Suit, - card3Value, card3Suit, - card4Value, card4Suit, - card5Value, card5Suit, - card6Value, card6Suit, - card7Value, card7Suit + card1, /*card1Value, card1Suit, */ + card2, /*card2Value, card2Suit, */ + card3, /*card3Value, card3Suit, */ + card4, /*card4Value, card4Suit, */ + card5, /*card5Value, card5Suit, */ + card6, /*card6Value, card6Suit, */ + card7 /*card7Value, card7Suit */ from HandsPlayers, Players where handID = %s and HandsPlayers.playerId = Players.id order by seatNo diff --git a/pyfpdb/fpdb_save_to_db.py b/pyfpdb/fpdb_save_to_db.py index f983b910..18344030 100644 --- a/pyfpdb/fpdb_save_to_db.py +++ b/pyfpdb/fpdb_save_to_db.py @@ -82,11 +82,11 @@ def ring_holdem_omaha(config, backend, db, cursor, base, category, site_hand_no, t2 = time() hands_id = fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats) + ,hand_start_time, names, tableName, maxSeats, hudImportData) t3 = time() hands_players_ids = fpdb_simple.store_hands_players_holdem_omaha( backend, db, cursor, category, hands_id, player_ids, start_cashes - , positions, card_values, card_suits, winnings, rakes, seatNos) + , positions, card_values, card_suits, winnings, rakes, seatNos, hudImportData) t4 = time() #print "ring holdem, backend=%d" % backend if fastStoreHudCache: diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index cd8a9e76..2b36cf01 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -20,6 +20,8 @@ import datetime import time import re + +import Card PS = 1 FTP = 2 @@ -1448,14 +1450,29 @@ card5Value, card5Suit) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", #end def store_board_cards def storeHands(backend, conn, cursor, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats): -#stores into table hands - cursor.execute ("INSERT INTO Hands (siteHandNo, gametypeId, handStart, seats, tableName, importTime, maxSeats) VALUES (%s, %s, %s, %s, %s, %s, %s)", (site_hand_no, gametype_id, hand_start_time, len(names), tableName, datetime.datetime.today(), maxSeats)) - #todo: find a better way of doing this... - #cursor.execute("SELECT id FROM Hands WHERE siteHandNo=%s AND gametypeId=%s", (site_hand_no, gametype_id)) - #return cursor.fetchall()[0][0] + ,hand_start_time, names, tableName, maxSeats, hudCache): +#stores into table hands: + cursor.execute ("""INSERT INTO Hands + (siteHandNo, gametypeId, handStart, seats, tableName, importTime, maxSeats + ,playersVpi, playersAtStreet1, playersAtStreet2 + ,playersAtStreet3, playersAtStreet4, playersAtShowdown + ,street0Raises, street1Raises, street2Raises + ,street3Raises, street4Raises, street1Pot + ,street2Pot, street3Pot, street4Pot + ,showdownPot + ) + VALUES + (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) + """ + , (site_hand_no, gametype_id, hand_start_time, len(names), tableName, datetime.datetime.today(), maxSeats + ,hudCache['playersVpi'], hudCache['playersAtStreet1'], hudCache['playersAtStreet2'] + ,hudCache['playersAtStreet3'], hudCache['playersAtStreet4'], hudCache['playersAtShowdown'] + ,hudCache['street0Raises'], hudCache['street1Raises'], hudCache['street2Raises'] + ,hudCache['street3Raises'], hudCache['street4Raises'], hudCache['street1Pot'] + ,hudCache['street2Pot'], hudCache['street3Pot'], hudCache['street4Pot'] + ,hudCache['showdownPot'] + )) return getLastInsertId(backend, conn, cursor) - #return db.insert_id() # mysql only #end def storeHands def store_hands_players_holdem_omaha(backend, conn, cursor, category, hands_id, player_ids, start_cashes @@ -1474,14 +1491,13 @@ def store_hands_players_holdem_omaha(backend, conn, cursor, category, hands_id, if (category=="holdem"): for i in xrange(len(player_ids)): - x,y = card_values[i][0],card_values[i][1] - if (card_suits[i][0] == card_suits[i][1] and x < y) or (card_suits[i][0] != card_suits[i][1] and x > y): - x,y = y,x - startCards = 13 * (x-2) + (y-2) + startCards = Card.twoStartCards(card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1]) + card1 = Card.cardFromValueSuit(card_values[i][0], card_suits[i][0]) + card2 = Card.cardFromValueSuit(card_values[i][1], card_suits[i][1]) cursor.execute (""" INSERT INTO HandsPlayers -(handId, playerId, startCash, position, activeSeats, tourneyTypeId, - card1Value, card1Suit, card2Value, card2Suit, winnings, rake, seatNo, totalProfit, +(handId, playerId, startCash, position, tourneyTypeId, + card1, card2, startCards, winnings, rake, seatNo, totalProfit, street0VPI, street0Aggr, street0_3BChance, street0_3BDone, street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown, street1Aggr, street2Aggr, street3Aggr, street4Aggr, @@ -1494,13 +1510,16 @@ INSERT INTO HandsPlayers foldToStreet1CBChance, foldToStreet1CBDone, foldToStreet2CBChance, foldToStreet2CBDone, foldToStreet3CBChance, foldToStreet3CBDone, foldToStreet4CBChance, foldToStreet4CBDone, street1CheckCallRaiseChance, street1CheckCallRaiseDone, street2CheckCallRaiseChance, street2CheckCallRaiseDone, - street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone + street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone, + street0Calls, street1Calls, street2Calls, street3Calls, street4Calls, + street0Bets, street1Bets, street2Bets, street3Bets, street4Bets ) -VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, +VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", - (hands_id, player_ids[i], start_cashes[i], positions[i], len(player_ids), 1, # tourneytypeid - card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, %s, %s, %s)""", + (hands_id, player_ids[i], start_cashes[i], positions[i], 1, # tourneytypeid + card1, card2, startCards, winnings[i], rakes[i], seatNos[i], hudCache['totalProfit'][i], hudCache['street0VPI'][i], hudCache['street0Aggr'][i], hudCache['street0_3BChance'][i], hudCache['street0_3BDone'][i], @@ -1523,7 +1542,9 @@ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, hudCache['street1CheckCallRaiseChance'][i], hudCache['street1CheckCallRaiseDone'][i], hudCache['street2CheckCallRaiseChance'][i], hudCache['street2CheckCallRaiseDone'][i], hudCache['street3CheckCallRaiseChance'][i], hudCache['street3CheckCallRaiseDone'][i], - hudCache['street4CheckCallRaiseChance'][i], hudCache['street4CheckCallRaiseDone'][i] + hudCache['street4CheckCallRaiseChance'][i], hudCache['street4CheckCallRaiseDone'][i], + hudCache['street0Calls'][i], hudCache['street1Calls'][i], hudCache['street2Calls'][i], hudCache['street3Calls'][i], hudCache['street4Calls'][i], + hudCache['street0Bets'][i], hudCache['street1Bets'][i], hudCache['street2Bets'][i], hudCache['street3Bets'][i], hudCache['street4Bets'][i] ) ) #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId=%s", (hands_id, player_ids[i])) #result.append(cursor.fetchall()[0][0]) @@ -1531,8 +1552,8 @@ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, elif (category=="omahahi" or category=="omahahilo"): for i in xrange(len(player_ids)): cursor.execute ("""INSERT INTO HandsPlayers -(handId, playerId, startCash, position, activeSeats, tourneyTypeId, - card1Value, card1Suit, card2Value, card2Suit, +(handId, playerId, startCash, position, tourneyTypeId, + card1Value, card1Suit, card2Value, card2Suit, card3Value, card3Suit, card4Value, card4Suit, winnings, rake, seatNo, totalProfit, street0VPI, street0Aggr, street0_3BChance, street0_3BDone, street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown, @@ -1546,12 +1567,15 @@ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, foldToStreet1CBChance, foldToStreet1CBDone, foldToStreet2CBChance, foldToStreet2CBDone, foldToStreet3CBChance, foldToStreet3CBDone, foldToStreet4CBChance, foldToStreet4CBDone, street1CheckCallRaiseChance, street1CheckCallRaiseDone, street2CheckCallRaiseChance, street2CheckCallRaiseDone, - street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone + street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone, + street0Calls, street1Calls, street2Calls, street3Calls, street4Calls, + street0Bets, street1Bets, street2Bets, street3Bets, street4Bets ) -VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, +VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", - (hands_id, player_ids[i], start_cashes[i], positions[i], len(player_ids), 1, # tourneytypeid + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, %s, %s, %s)""", + (hands_id, player_ids[i], start_cashes[i], positions[i], 1, # tourneytypeid card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3], winnings[i], rakes[i], seatNos[i], hudCache['totalProfit'][i], @@ -1576,7 +1600,9 @@ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, hudCache['street1CheckCallRaiseChance'][i], hudCache['street1CheckCallRaiseDone'][i], hudCache['street2CheckCallRaiseChance'][i], hudCache['street2CheckCallRaiseDone'][i], hudCache['street3CheckCallRaiseChance'][i], hudCache['street3CheckCallRaiseDone'][i], - hudCache['street4CheckCallRaiseChance'][i], hudCache['street4CheckCallRaiseDone'][i] + hudCache['street4CheckCallRaiseChance'][i], hudCache['street4CheckCallRaiseDone'][i], + hudCache['street0Calls'][i], hudCache['street1Calls'][i], hudCache['street2Calls'][i], hudCache['street3Calls'][i], hudCache['street4Calls'][i], + hudCache['street0Bets'][i], hudCache['street1Bets'][i], hudCache['street2Bets'][i], hudCache['street3Bets'][i], hudCache['street4Bets'][i] ) ) #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i])) #result.append(cursor.fetchall()[0][0]) @@ -1705,6 +1731,41 @@ sure to also change the following storage method and table_viewer.prepare_data i stealAttempted=[] hudDataPositions=[] + street0Calls=[] + street1Calls=[] + street2Calls=[] + street3Calls=[] + street4Calls=[] + street0Bets=[] + street1Bets=[] + street2Bets=[] + street3Bets=[] + street4Bets=[] + #street0Raises=[] + #street1Raises=[] + #street2Raises=[] + #street3Raises=[] + #street4Raises=[] + + # Summary figures for hand table: + result={} + result['playersVpi']=0 + result['playersAtStreet1']=0 + result['playersAtStreet2']=0 + result['playersAtStreet3']=0 + result['playersAtStreet4']=0 + result['playersAtShowdown']=0 + result['street0Raises']=0 + result['street1Raises']=0 + result['street2Raises']=0 + result['street3Raises']=0 + result['street4Raises']=0 + result['street1Pot']=0 + result['street2Pot']=0 + result['street3Pot']=0 + result['street4Pot']=0 + result['showdownPot']=0 + firstPfRaiseByNo=-1 firstPfRaiserId=-1 firstPfRaiserNo=-1 @@ -1776,6 +1837,21 @@ sure to also change the following storage method and table_viewer.prepare_data i myWonAtSD=0.0 myStealAttemptChance=False myStealAttempted=False + myStreet0Calls=0 + myStreet1Calls=0 + myStreet2Calls=0 + myStreet3Calls=0 + myStreet4Calls=0 + myStreet0Bets=0 + myStreet1Bets=0 + myStreet2Bets=0 + myStreet3Bets=0 + myStreet4Bets=0 + #myStreet0Raises=0 + #myStreet1Raises=0 + #myStreet2Raises=0 + #myStreet3Raises=0 + #myStreet4Raises=0 #calculate VPIP and PFR street=0 @@ -1785,6 +1861,13 @@ sure to also change the following storage method and table_viewer.prepare_data i myStreet0Aggr = True if currentAction == "bet" or currentAction == "call": myStreet0VPI = True + + if myStreet0VPI: + result['playersVpi'] += 1 + myStreet0Calls = action_types[street][player].count('call') + myStreet0Bets = action_types[street][player].count('bet') + # street0Raises = action_types[street][player].count('raise') bet count includes raises for now + result['street0Raises'] += myStreet0Bets #PF3BChance and PF3B pfFold=-1 @@ -1865,7 +1948,17 @@ sure to also change the following storage method and table_viewer.prepare_data i mySawShowdown = True if any(actiontype == "fold" for actiontype in action_types[4][player]): mySawShowdown = False - + + if myStreet1Seen: + result['playersAtStreet1'] += 1 + if myStreet2Seen: + result['playersAtStreet2'] += 1 + if myStreet3Seen: + result['playersAtStreet3'] += 1 + if myStreet4Seen: + result['playersAtStreet4'] += 1 + if mySawShowdown: + result['playersAtShowdown'] += 1 #flop stuff street=1 @@ -1873,6 +1966,11 @@ sure to also change the following storage method and table_viewer.prepare_data i if any(actiontype == "bet" for actiontype in action_types[street][player]): myStreet1Aggr = True + myStreet1Calls = action_types[street][player].count('call') + myStreet1Bets = action_types[street][player].count('bet') + # street1Raises = action_types[street][player].count('raise') bet count includes raises for now + result['street1Raises'] += myStreet1Bets + for otherPlayer in xrange(len(player_ids)): if player==otherPlayer: pass @@ -1890,6 +1988,11 @@ sure to also change the following storage method and table_viewer.prepare_data i if any(actiontype == "bet" for actiontype in action_types[street][player]): myStreet2Aggr = True + myStreet2Calls = action_types[street][player].count('call') + myStreet2Bets = action_types[street][player].count('bet') + # street2Raises = action_types[street][player].count('raise') bet count includes raises for now + result['street2Raises'] += myStreet2Bets + for otherPlayer in xrange(len(player_ids)): if player==otherPlayer: pass @@ -1907,6 +2010,11 @@ sure to also change the following storage method and table_viewer.prepare_data i if any(actiontype == "bet" for actiontype in action_types[street][player]): myStreet3Aggr = True + myStreet3Calls = action_types[street][player].count('call') + myStreet3Bets = action_types[street][player].count('bet') + # street3Raises = action_types[street][player].count('raise') bet count includes raises for now + result['street3Raises'] += myStreet3Bets + for otherPlayer in xrange(len(player_ids)): if player==otherPlayer: pass @@ -1924,6 +2032,11 @@ sure to also change the following storage method and table_viewer.prepare_data i if any(actiontype == "bet" for actiontype in action_types[street][player]): myStreet4Aggr=True + myStreet4Calls = action_types[street][player].count('call') + myStreet4Bets = action_types[street][player].count('bet') + # street4Raises = action_types[street][player].count('raise') bet count includes raises for now + result['street4Raises'] += myStreet4Bets + for otherPlayer in xrange(len(player_ids)): if player==otherPlayer: pass @@ -1989,9 +2102,25 @@ sure to also change the following storage method and table_viewer.prepare_data i elif base=="stud": #todo: stud positions and steals pass + + street0Calls.append(myStreet0Calls) + street1Calls.append(myStreet1Calls) + street2Calls.append(myStreet2Calls) + street3Calls.append(myStreet3Calls) + street4Calls.append(myStreet4Calls) + street0Bets.append(myStreet0Bets) + street1Bets.append(myStreet1Bets) + street2Bets.append(myStreet2Bets) + street3Bets.append(myStreet3Bets) + street4Bets.append(myStreet4Bets) + #street0Raises.append(myStreet0Raises) + #street1Raises.append(myStreet1Raises) + #street2Raises.append(myStreet2Raises) + #street3Raises.append(myStreet3Raises) + #street4Raises.append(myStreet4Raises) #add each array to the to-be-returned dictionary - result={'street0VPI':street0VPI} + result['street0VPI']=street0VPI result['street0Aggr']=street0Aggr result['street0_3BChance']=street0_3BChance result['street0_3BDone']=street0_3BDone @@ -2017,6 +2146,21 @@ sure to also change the following storage method and table_viewer.prepare_data i result['wonAtSD']=wonAtSD result['stealAttemptChance']=stealAttemptChance result['stealAttempted']=stealAttempted + result['street0Calls']=street0Calls + result['street1Calls']=street1Calls + result['street2Calls']=street2Calls + result['street3Calls']=street3Calls + result['street4Calls']=street4Calls + result['street0Bets']=street0Bets + result['street1Bets']=street1Bets + result['street2Bets']=street2Bets + result['street3Bets']=street3Bets + result['street4Bets']=street4Bets + #result['street0Raises']=street0Raises + #result['street1Raises']=street1Raises + #result['street2Raises']=street2Raises + #result['street3Raises']=street3Raises + #result['street4Raises']=street4Raises #now the various steal values foldBbToStealChance=[] From 399bfd98c66980aed6ca2cb0f04ec6e658b38c9a Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 21 May 2009 11:14:47 +0100 Subject: [PATCH 080/104] fix unimportant typo in print --- pyfpdb/HUD_main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index 17e133ff..b58d09d3 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -168,7 +168,7 @@ class HUD_main(object): (tour_number, tab_number) = mat_obj.group(1, 2) temp_key = tour_number else: # tourney, but can't get number and table - print "could not find tournamtne: skipping " + print "could not find tournament: skipping " sys.stderr.write("Could not find tournament %d in hand %d. Skipping.\n" % (int(tour_number), int(new_hand_id))) continue From 828b23510f5cc1ded5642c161e46e575ec303616 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 21 May 2009 11:23:50 +0100 Subject: [PATCH 081/104] add rollback to release locks (we should create a set transaction read_only method in fpdb_db) --- pyfpdb/fpdb_import.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index a3bdb3cc..33ab49be 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -235,6 +235,8 @@ class Importer: self.addToDirList = {} self.removeFromFileList = {} + self.fdb.db.rollback() + # This is now an internal function that should not be called directly. def import_file_dict(self, file, site, filter): From eda23de609e9a62ca6fd6f4a8129a5308b16032c Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 21 May 2009 12:19:52 +0100 Subject: [PATCH 082/104] stop storehudcache from breaking with hudcache changes (storehudcache2 is better) --- pyfpdb/fpdb_simple.py | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index 2b36cf01..52b09a39 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -2411,9 +2411,43 @@ def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData): #, len(hudImportData['street0VPI']), " len(totprof)=", len(hudImportData['totalProfit']) for player in xrange(len(playerIds)): if base=="hold": - cursor.execute("SELECT * FROM HudCache WHERE gametypeId+0=%s AND playerId=%s AND activeSeats=%s AND position=%s", (gametypeId, playerIds[player], len(playerIds), hudImportData['position'][player])) + cursor.execute("""SELECT id, gametypeId, playerId, activeSeats, position, tourneyTypeId, HDs, + street0VPI, street0Aggr, street0_3BChance, street0_3BDone, + street1Seen, street2Seen, street3Seen, street4Seen, + sawShowdown, street1Aggr, street2Aggr, street3Aggr, street4Aggr, + otherRaisedStreet1, otherRaisedStreet2, otherRaisedStreet3, otherRaisedStreet4, + foldToOtherRaisedStreet1, foldToOtherRaisedStreet2, foldToOtherRaisedStreet3, foldToOtherRaisedStreet4, + wonWhenSeenStreet1, wonAtSD, 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 + FROM HudCache + WHERE gametypeId+0=%s AND playerId=%s AND activeSeats=%s AND position=%s + """ + , (gametypeId, playerIds[player], len(playerIds), hudImportData['position'][player])) else: - cursor.execute("SELECT * FROM HudCache WHERE gametypeId+0=%s AND playerId=%s AND activeSeats=%s", (gametypeId, playerIds[player], len(playerIds))) + cursor.execute("""SELECT id, gametypeId, playerId, activeSeats, position, tourneyTypeId, HDs, + street0VPI, street0Aggr, street0_3BChance, street0_3BDone, + street1Seen, street2Seen, street3Seen, street4Seen, + sawShowdown, street1Aggr, street2Aggr, street3Aggr, street4Aggr, + otherRaisedStreet1, otherRaisedStreet2, otherRaisedStreet3, otherRaisedStreet4, + foldToOtherRaisedStreet1, foldToOtherRaisedStreet2, foldToOtherRaisedStreet3, foldToOtherRaisedStreet4, + wonWhenSeenStreet1, wonAtSD, 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 + FROM HudCache + WHERE gametypeId+0=%s AND playerId=%s AND activeSeats=%s + """ + , (gametypeId, playerIds[player], len(playerIds))) row=cursor.fetchone() #print "gametypeId:", gametypeId, "playerIds[player]",playerIds[player], "len(playerIds):",len(playerIds), "row:",row From 4819fc28e5bfabf1f2e21142d3962f475050a63a Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 21 May 2009 22:14:49 +0800 Subject: [PATCH 083/104] Fix omaha hudCache update --- pyfpdb/Card.py | 8 ++++++++ pyfpdb/fpdb_simple.py | 11 +++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/pyfpdb/Card.py b/pyfpdb/Card.py index 4ecd69b0..0d7f9d34 100755 --- a/pyfpdb/Card.py +++ b/pyfpdb/Card.py @@ -44,6 +44,14 @@ def twoStartCardString(card): 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 e.g. AAds + 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""" + # This doesn't actually do anything yet - CG + 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) diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index 52b09a39..f4615013 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -1551,10 +1551,14 @@ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, result.append( getLastInsertId(backend, conn, cursor) ) elif (category=="omahahi" or category=="omahahilo"): for i in xrange(len(player_ids)): + startCards = Card.fourStartCards(card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3]) + card1 = Card.cardFromValueSuit(card_values[i][0], card_suits[i][0]) + card2 = Card.cardFromValueSuit(card_values[i][1], card_suits[i][1]) + card3 = Card.cardFromValueSuit(card_values[i][2], card_suits[i][2]) + card4 = Card.cardFromValueSuit(card_values[i][3], card_suits[i][3]) cursor.execute ("""INSERT INTO HandsPlayers (handId, playerId, startCash, position, tourneyTypeId, - card1Value, card1Suit, card2Value, card2Suit, - card3Value, card3Suit, card4Value, card4Suit, winnings, rake, seatNo, totalProfit, + card1, card2, card3, card4, winnings, rake, seatNo, totalProfit, street0VPI, street0Aggr, street0_3BChance, street0_3BDone, street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown, street1Aggr, street2Aggr, street3Aggr, street4Aggr, @@ -1576,8 +1580,7 @@ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", (hands_id, player_ids[i], start_cashes[i], positions[i], 1, # tourneytypeid - card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], - card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3], + card1, card2, card3, card4, winnings[i], rakes[i], seatNos[i], hudCache['totalProfit'][i], hudCache['street0VPI'][i], hudCache['street0Aggr'][i], hudCache['street0_3BChance'][i], hudCache['street0_3BDone'][i], From dc8affb8c3969f7152b4d60d00d2a2eaa76521c2 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 21 May 2009 23:02:50 +0800 Subject: [PATCH 084/104] Quick comment add before checking out 0.11 --- pyfpdb/Card.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyfpdb/Card.py b/pyfpdb/Card.py index 0d7f9d34..5b1d9310 100755 --- a/pyfpdb/Card.py +++ b/pyfpdb/Card.py @@ -50,6 +50,10 @@ def fourStartCards(value1, suit1, value2, suit2, value3, suit3, value4, suit4): (y+2) represents rank of second card (2=2 .. 14=Ace) If x > y then pair is suited, if x < y then unsuited""" # This doesn't actually do anything yet - CG + #AAKKds + #AAKKs + #AAKKr + # Is probably what we are looking for return(0) def cardFromValueSuit(value, suit): From fcc6cf5d4f18af5efb0c7f7e8475bf835581ea8e Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 21 May 2009 18:02:11 +0100 Subject: [PATCH 085/104] updated comment --- pyfpdb/Card.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pyfpdb/Card.py b/pyfpdb/Card.py index 0d7f9d34..1aa18733 100755 --- a/pyfpdb/Card.py +++ b/pyfpdb/Card.py @@ -45,11 +45,12 @@ def twoStartCardString(card): 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 e.g. AAds - 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""" + """ 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 return(0) def cardFromValueSuit(value, suit): From 0651e89e2ef5760973618e425feb4da0d5d262e7 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 21 May 2009 18:02:42 +0100 Subject: [PATCH 086/104] add try-except blocks and correct spelling --- pyfpdb/fpdb_db.py | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index fda04e19..6e48fcf4 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -59,7 +59,10 @@ class fpdb_db: self.database=database if backend==self.MYSQL_INNODB: import MySQLdb - self.db=MySQLdb.connect(host = host, user = user, passwd = password, db = database, use_unicode=True) + try: + self.db = MySQLdb.connect(host = host, user = user, passwd = password, db = database, use_unicode=True) + except: + raise fpdb_simple.FpdbError("MySQL connection failed") elif backend==self.PGSQL: import psycopg2 import psycopg2.extensions @@ -68,15 +71,21 @@ class fpdb_db: # host, user and password are required print "host=%s user=%s pass=%s." % (host, user, password) if self.host and self.user and self.password: - self.db = psycopg2.connect(host = host, - user = user, - password = password, - database = database) + try: + self.db = psycopg2.connect(host = host, + user = user, + password = password, + database = database) + except: + raise fpdb_simple.FpdbError("PostgreSQL connection failed") # For local domain-socket connections, only DB name is # needed, and everything else is in fact undefined and/or # flat out wrong else: - self.db = psycopg2.connect(database = database) + try: + self.db = psycopg2.connect(database = database) + except: + raise fpdb_simple.FpdbError("PostgreSQL connection failed") else: raise fpdb_simple.FpdbError("unrecognised database backend:"+backend) self.cursor=self.db.cursor() @@ -138,7 +147,7 @@ class fpdb_db: if(self.get_backend_name() == 'MySQL InnoDB'): #Databases with FOREIGN KEY support need this switched of before you can drop tables - self.drop_referencial_integrity() + self.drop_referential_integrity() # Query the DB to see what tables exist self.cursor.execute(self.sql.query['list_tables']) @@ -157,7 +166,7 @@ class fpdb_db: self.db.commit() #end def drop_tables - def drop_referencial_integrity(self): + def drop_referential_integrity(self): """Update all tables to remove foreign keys""" self.cursor.execute(self.sql.query['list_tables']) @@ -175,7 +184,7 @@ class fpdb_db: key = "`" + inner[j][0] + "_" + m.group() + "`" self.cursor.execute("ALTER TABLE " + inner[j][0] + " DROP FOREIGN KEY " + key) self.db.commit() - #end drop_referencial_inegrity + #end drop_referential_inegrity def get_backend_name(self): """Returns the name of the currently used backend""" From 985d2c28d4ee57005b7296ce21c9deee3a1d1734 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 21 May 2009 18:43:32 +0100 Subject: [PATCH 087/104] add styleKey to hudcache --- pyfpdb/FpdbSQLQueries.py | 4 ++++ pyfpdb/fpdb_simple.py | 26 ++++++++++++++++++++------ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index 422da934..0e81c4fb 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -653,6 +653,7 @@ 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, @@ -753,6 +754,7 @@ 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, wonWhenSeenStreet1 FLOAT NOT NULL, @@ -1601,6 +1603,7 @@ class FpdbSQLQueries: ,activeSeats ,position ,tourneyTypeId + ,styleKey ,HDs ,wonWhenSeenStreet1 ,wonAtSD @@ -1675,6 +1678,7 @@ class FpdbSQLQueries: else 'E' end AS hc_position ,hp.tourneyTypeId + ,'A000000' /* All-time cache, no key required */ ,count(1) ,sum(wonWhenSeenStreet1) ,sum(wonAtSD) diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index f4615013..be88ef17 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -2549,7 +2549,7 @@ def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData): if doInsert: #print "playerid before insert:",row[2] cursor.execute("""INSERT INTO HudCache -(gametypeId, playerId, activeSeats, position, tourneyTypeId, +(gametypeId, playerId, activeSeats, position, tourneyTypeId, styleKey, HDs, street0VPI, street0Aggr, street0_3BChance, street0_3BDone, street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown, street1Aggr, street2Aggr, street3Aggr, street4Aggr, otherRaisedStreet1, @@ -2561,7 +2561,7 @@ street3CBDone, street4CBChance, street4CBDone, foldToStreet1CBChance, foldToStre foldToStreet2CBChance, foldToStreet2CBDone, foldToStreet3CBChance, foldToStreet3CBDone, foldToStreet4CBChance, foldToStreet4CBDone, totalProfit, street1CheckCallRaiseChance, street1CheckCallRaiseDone, street2CheckCallRaiseChance, street2CheckCallRaiseDone, street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone) -VALUES (%s, %s, %s, %s, %s, +VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, @@ -2572,7 +2572,14 @@ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, -%s, %s, %s, %s, %s)""", (row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8], row[9], row[10], row[11], row[12], row[13], row[14], row[15], row[16], row[17], row[18], row[19], row[20], row[21], row[22], row[23], row[24], row[25], row[26], row[27], row[28], row[29], row[30], row[31], row[32], row[33], row[34], row[35], row[36], row[37], row[38], row[39], row[40], row[41], row[42], row[43], row[44], row[45], row[46], row[47], row[48], row[49], row[50], row[51], row[52], row[53], row[54], row[55], row[56], row[57], row[58], row[59], row[60])) +%s, %s, %s, %s, %s)""" + # hard-code styleKey as 'A000000' (all-time cache, no key) for now + , (row[1], row[2], row[3], row[4], row[5], 'A000000', row[6], row[7], row[8], row[9], row[10] + ,row[11], row[12], row[13], row[14], row[15], row[16], row[17], row[18], row[19], row[20] + ,row[21], row[22], row[23], row[24], row[25], row[26], row[27], row[28], row[29], row[30] + ,row[31], row[32], row[33], row[34], row[35], row[36], row[37], row[38], row[39], row[40] + ,row[41], row[42], row[43], row[44], row[45], row[46], row[47], row[48], row[49], row[50] + ,row[51], row[52], row[53], row[54], row[55], row[56], row[57], row[58], row[59], row[60])) else: #print "storing updated hud data line" cursor.execute("""UPDATE HudCache @@ -2736,7 +2743,7 @@ AND tourneyTypeId+0=%s""", (row[6], row[7], row[8], row[9], row[10], or (backend == MYSQL_INNODB and num == 0) ): #print "playerid before insert:",row[2]," num = ", num cursor.execute("""INSERT INTO HudCache -(gametypeId, playerId, activeSeats, position, tourneyTypeId, +(gametypeId, playerId, activeSeats, position, tourneyTypeId, styleKey, HDs, street0VPI, street0Aggr, street0_3BChance, street0_3BDone, street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown, street1Aggr, street2Aggr, street3Aggr, street4Aggr, otherRaisedStreet1, @@ -2748,7 +2755,7 @@ street3CBDone, street4CBChance, street4CBDone, foldToStreet1CBChance, foldToStre foldToStreet2CBChance, foldToStreet2CBDone, foldToStreet3CBChance, foldToStreet3CBDone, foldToStreet4CBChance, foldToStreet4CBDone, totalProfit, street1CheckCallRaiseChance, street1CheckCallRaiseDone, street2CheckCallRaiseChance, street2CheckCallRaiseDone, street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone) -VALUES (%s, %s, %s, %s, %s, +VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, @@ -2759,7 +2766,14 @@ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, -%s, %s, %s, %s, %s)""", (row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8], row[9], row[10], row[11], row[12], row[13], row[14], row[15], row[16], row[17], row[18], row[19], row[20], row[21], row[22], row[23], row[24], row[25], row[26], row[27], row[28], row[29], row[30], row[31], row[32], row[33], row[34], row[35], row[36], row[37], row[38], row[39], row[40], row[41], row[42], row[43], row[44], row[45], row[46], row[47], row[48], row[49], row[50], row[51], row[52], row[53], row[54], row[55], row[56], row[57], row[58], row[59], row[60])) +%s, %s, %s, %s, %s)""" + # hard-code styleKey as 'A000000' (all-time cache, no key) for now + , (row[1], row[2], row[3], row[4], row[5], 'A000000', row[6], row[7], row[8], row[9], row[10] + ,row[11], row[12], row[13], row[14], row[15], row[16], row[17], row[18], row[19], row[20] + ,row[21], row[22], row[23], row[24], row[25], row[26], row[27], row[28], row[29], row[30] + ,row[31], row[32], row[33], row[34], row[35], row[36], row[37], row[38], row[39], row[40] + ,row[41], row[42], row[43], row[44], row[45], row[46], row[47], row[48], row[49], row[50] + ,row[51], row[52], row[53], row[54], row[55], row[56], row[57], row[58], row[59], row[60]) ) #print "hopefully inserted hud data line: ", cursor.statusmessage # message seems to be "INSERT 0 1" else: From d986966332336ace8b068c4054ecbafcd3778c16 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 21 May 2009 20:30:18 +0100 Subject: [PATCH 088/104] prevent error when trying to close HUD that has already gone --- pyfpdb/HUD_main.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index b58d09d3..5d34e409 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -81,10 +81,11 @@ class HUD_main(object): def kill_hud(self, event, table): # called by an event in the HUD, to kill this specific HUD - self.hud_dict[table].kill() - self.hud_dict[table].main_window.destroy() - self.vb.remove(self.hud_dict[table].tablehudlabel) - del(self.hud_dict[table]) + if table in self.hud_dict: + self.hud_dict[table].kill() + self.hud_dict[table].main_window.destroy() + self.vb.remove(self.hud_dict[table].tablehudlabel) + del(self.hud_dict[table]) self.main_window.resize(1,1) def create_HUD(self, new_hand_id, table, table_name, max, poker_game, stat_dict, cards): From 07247de03088c4e50221d4e011704e62f2fbf2e3 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 21 May 2009 21:27:44 +0100 Subject: [PATCH 089/104] changes to allow hud to use stylekey and aggregate stats query --- pyfpdb/Database.py | 21 +++--- pyfpdb/SQL.py | 156 ++++++++++++++++++++++++--------------------- 2 files changed, 96 insertions(+), 81 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 0483da96..88f7edd5 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -191,15 +191,14 @@ class Database: winners[row[0]] = row[1] return winners - def get_stats_from_hand(self, hand, aggregate = False): + def get_stats_from_hand(self, hand, aggregate = False, stylekey = 'A000000'): 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) + subs = (hand, hand, stylekey, stylekey) # now get the stats c.execute(self.sql.query[query], subs) @@ -218,7 +217,10 @@ class Database: 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() @@ -234,16 +236,17 @@ if __name__=="__main__": print "last hand = ", h hero = db_connection.get_player_id(c, 'PokerStars', 'nutOmatic') - print "nutOmatic is id_player = %d" % hero + if hero: + print "nutOmatic is id_player = %d" % hero stat_dict = db_connection.get_stats_from_hand(h) for p in stat_dict.keys(): print p, " ", stat_dict[p] - print "nutOmatics stats:" - stat_dict = db_connection.get_stats_from_hand(h, hero) - for p in stat_dict.keys(): - print p, " ", stat_dict[p] + #print "nutOmatics stats:" + #stat_dict = db_connection.get_stats_from_hand(h, hero) + #for p in stat_dict.keys(): + # print p, " ", stat_dict[p] print "cards =", db_connection.get_cards(73525) db_connection.close_connection diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 6d4c3241..33ea3590 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -175,6 +175,7 @@ class Sql: SELECT hc.playerId AS player_id, hp.seatNo AS seat, p.name AS screen_name, + hc.styleKey AS stylekey, sum(hc.HDs) AS n, sum(hc.street0VPI) AS vpip, sum(hc.street0Aggr) AS pfr, @@ -237,82 +238,93 @@ class Sql: AND hc.gametypeId+0 = h.gametypeId+0) INNER JOIN Players p ON (p.id = hp.PlayerId+0) WHERE h.id = %s - GROUP BY hc.PlayerId, hp.seatNo, p.name + AND (hc.styleKey = %s or %s = 'ALL') /* styleKey should be passed in twice */ + /* This allows the caller to query only a particular stylekey or all, + e.g. may want to use different values for Hero and others */ + GROUP BY hc.PlayerId, hp.seatNo, p.name, hc.styleKey """ # same as above except stats are aggregated for all blind/limit levels self.query['get_stats_from_hand_aggregated'] = """ - SELECT HudCache.playerId AS player_id, - sum(HDs) AS n, - sum(street0VPI) AS vpip, - sum(street0Aggr) AS pfr, - sum(street0_3BChance) AS TB_opp_0, - sum(street0_3BDone) AS TB_0, - sum(street1Seen) AS saw_f, - sum(street1Seen) AS saw_1, - sum(street2Seen) AS saw_2, - sum(street3Seen) AS saw_3, - sum(street4Seen) AS saw_4, - sum(sawShowdown) AS sd, - sum(street1Aggr) AS aggr_1, - sum(street2Aggr) AS aggr_2, - sum(street3Aggr) AS aggr_3, - sum(street4Aggr) AS aggr_4, - sum(otherRaisedStreet1) AS was_raised_1, - sum(otherRaisedStreet2) AS was_raised_2, - sum(otherRaisedStreet3) AS was_raised_3, - sum(otherRaisedStreet4) AS was_raised_4, - sum(foldToOtherRaisedStreet1) AS f_freq_1, - sum(foldToOtherRaisedStreet2) AS f_freq_2, - sum(foldToOtherRaisedStreet3) AS f_freq_3, - sum(foldToOtherRaisedStreet4) AS f_freq_4, - sum(wonWhenSeenStreet1) AS w_w_s_1, - sum(wonAtSD) AS wmsd, - sum(stealAttemptChance) AS steal_opp, - sum(stealAttempted) AS steal, - sum(foldSbToStealChance) AS SBstolen, - sum(foldedSbToSteal) AS SBnotDef, - sum(foldBbToStealChance) AS BBstolen, - sum(foldedBbToSteal) AS BBnotDef, - sum(street1CBChance) AS CB_opp_1, - sum(street1CBDone) AS CB_1, - sum(street2CBChance) AS CB_opp_2, - sum(street2CBDone) AS CB_2, - sum(street3CBChance) AS CB_opp_3, - sum(street3CBDone) AS CB_3, - sum(street4CBChance) AS CB_opp_4, - sum(street4CBDone) AS CB_4, - sum(foldToStreet1CBChance) AS f_cb_opp_1, - sum(foldToStreet1CBDone) AS f_cb_1, - sum(foldToStreet2CBChance) AS f_cb_opp_2, - sum(foldToStreet2CBDone) AS f_cb_2, - sum(foldToStreet3CBChance) AS f_cb_opp_3, - sum(foldToStreet3CBDone) AS f_cb_3, - sum(foldToStreet4CBChance) AS f_cb_opp_4, - sum(foldToStreet4CBDone) AS f_cb_4, - sum(totalProfit) AS net, - sum(street1CheckCallRaiseChance) AS ccr_opp_1, - sum(street1CheckCallRaiseDone) AS ccr_1, - sum(street2CheckCallRaiseChance) AS ccr_opp_2, - sum(street2CheckCallRaiseDone) AS ccr_2, - sum(street3CheckCallRaiseChance) AS ccr_opp_3, - sum(street3CheckCallRaiseDone) AS ccr_3, - sum(street4CheckCallRaiseChance) AS ccr_opp_4, - sum(street4CheckCallRaiseDone) AS ccr_4 - FROM HudCache, Hands - WHERE HudCache.PlayerId in - (SELECT PlayerId FROM HandsPlayers - WHERE handId = %s) - AND Hands.id = %s - AND HudCache.gametypeId in - (SELECT gt1.id from Gametypes gt1, Gametypes gt2, Hands - WHERE gt1.siteid = gt2.siteid - AND gt1.type = gt2.type - AND gt1.category = gt2.category - AND gt1.limittype = gt2.limittype - AND gt2.id = Hands.gametypeId - AND Hands.id = %s) - GROUP BY HudCache.PlayerId + SELECT hc.playerId AS player_id, + max(case when hc.gametypeId = h.gametypeId + then hp.seatNo + else -1 + end) AS seat, + p.name AS screen_name, + hc.styleKey AS stylekey, + sum(hc.HDs) AS n, + sum(hc.street0VPI) AS vpip, + sum(hc.street0Aggr) AS pfr, + sum(hc.street0_3BChance) AS TB_opp_0, + sum(hc.street0_3BDone) AS TB_0, + sum(hc.street1Seen) AS saw_f, + sum(hc.street1Seen) AS saw_1, + sum(hc.street2Seen) AS saw_2, + sum(hc.street3Seen) AS saw_3, + sum(hc.street4Seen) AS saw_4, + sum(hc.sawShowdown) AS sd, + sum(hc.street1Aggr) AS aggr_1, + sum(hc.street2Aggr) AS aggr_2, + sum(hc.street3Aggr) AS aggr_3, + sum(hc.street4Aggr) AS aggr_4, + sum(hc.otherRaisedStreet1) AS was_raised_1, + sum(hc.otherRaisedStreet2) AS was_raised_2, + sum(hc.otherRaisedStreet3) AS was_raised_3, + sum(hc.otherRaisedStreet4) AS was_raised_4, + sum(hc.foldToOtherRaisedStreet1) AS f_freq_1, + sum(hc.foldToOtherRaisedStreet2) AS f_freq_2, + sum(hc.foldToOtherRaisedStreet3) AS f_freq_3, + sum(hc.foldToOtherRaisedStreet4) AS f_freq_4, + sum(hc.wonWhenSeenStreet1) AS w_w_s_1, + sum(hc.wonAtSD) AS wmsd, + sum(hc.stealAttemptChance) AS steal_opp, + sum(hc.stealAttempted) AS steal, + sum(hc.foldSbToStealChance) AS SBstolen, + sum(hc.foldedSbToSteal) AS SBnotDef, + sum(hc.foldBbToStealChance) AS BBstolen, + sum(hc.foldedBbToSteal) AS BBnotDef, + sum(hc.street1CBChance) AS CB_opp_1, + sum(hc.street1CBDone) AS CB_1, + sum(hc.street2CBChance) AS CB_opp_2, + sum(hc.street2CBDone) AS CB_2, + sum(hc.street3CBChance) AS CB_opp_3, + sum(hc.street3CBDone) AS CB_3, + sum(hc.street4CBChance) AS CB_opp_4, + sum(hc.street4CBDone) AS CB_4, + sum(hc.foldToStreet1CBChance) AS f_cb_opp_1, + sum(hc.foldToStreet1CBDone) AS f_cb_1, + sum(hc.foldToStreet2CBChance) AS f_cb_opp_2, + sum(hc.foldToStreet2CBDone) AS f_cb_2, + sum(hc.foldToStreet3CBChance) AS f_cb_opp_3, + sum(hc.foldToStreet3CBDone) AS f_cb_3, + sum(hc.foldToStreet4CBChance) AS f_cb_opp_4, + sum(hc.foldToStreet4CBDone) AS f_cb_4, + sum(hc.totalProfit) AS net, + sum(hc.street1CheckCallRaiseChance) AS ccr_opp_1, + sum(hc.street1CheckCallRaiseDone) AS ccr_1, + sum(hc.street2CheckCallRaiseChance) AS ccr_opp_2, + sum(hc.street2CheckCallRaiseDone) AS ccr_2, + sum(hc.street3CheckCallRaiseChance) AS ccr_opp_3, + sum(hc.street3CheckCallRaiseDone) AS ccr_3, + sum(hc.street4CheckCallRaiseChance) AS ccr_opp_4, + sum(hc.street4CheckCallRaiseDone) AS ccr_4 + FROM Hands h + INNER JOIN HandsPlayers hp ON (hp.handId = %s) + INNER JOIN HudCache hc ON (hc.playerId = hp.playerId) + INNER JOIN Players p ON (p.id = hc.playerId) + WHERE h.id = %s + AND (hc.styleKey = %s or %s = 'ALL') /* styleKey should be passed in twice */ + /* This allows the caller to query only a particular stylekey or all, + e.g. may want to use different values for Hero and others */ + AND hc.gametypeId+0 in + (SELECT gt1.id from Gametypes gt1, Gametypes gt2 + WHERE gt1.siteid = gt2.siteid + AND gt1.type = gt2.type + AND gt1.category = gt2.category + AND gt1.limittype = gt2.limittype + AND gt2.id = h.gametypeId) + GROUP BY hc.PlayerId, hc.styleKey """ self.query['get_players_from_hand'] = """ From a9963a6a47fe5fac4da11d65d783d6ddec57cddf Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 21 May 2009 23:00:46 +0100 Subject: [PATCH 090/104] try to improve look of autoimport tab --- pyfpdb/GuiAutoImport.py | 78 ++++++++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 25 deletions(-) diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py index 872c5c67..ebd3b636 100755 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -57,28 +57,55 @@ class GuiAutoImport (threading.Thread): self.database=settings['db-databaseName'] self.mainVBox=gtk.VBox(False,1) - self.mainVBox.show() - self.settingsHBox = gtk.HBox(False, 0) - self.mainVBox.pack_start(self.settingsHBox, False, True, 0) - self.settingsHBox.show() + hbox = gtk.HBox(True, 0) # contains 2 equal vboxes + self.mainVBox.pack_start(hbox, False, False, 0) + + vbox1 = gtk.VBox(True, 0) + hbox.pack_start(vbox1, True, True, 0) + vbox2 = gtk.VBox(True, 0) + hbox.pack_start(vbox2, True, True, 0) self.intervalLabel = gtk.Label("Interval (ie. break) between imports in seconds:") - self.settingsHBox.pack_start(self.intervalLabel) - self.intervalLabel.show() + self.intervalLabel.set_alignment(xalign=1.0, yalign=0.5) + vbox1.pack_start(self.intervalLabel, True, True, 0) - self.intervalEntry=gtk.Entry() + hbox = gtk.HBox(False, 0) + vbox2.pack_start(hbox, True, True, 0) + self.intervalEntry = gtk.Entry() self.intervalEntry.set_text(str(self.config.get_import_parameters().get("interval"))) - self.settingsHBox.pack_start(self.intervalEntry) - self.intervalEntry.show() + hbox.pack_start(self.intervalEntry, False, False, 0) + lbl1 = gtk.Label() + hbox.pack_start(lbl1, expand=True, fill=True) - self.addSites(self.mainVBox) + lbl = gtk.Label('') + vbox1.pack_start(lbl, expand=True, fill=True) + lbl = gtk.Label('') + vbox2.pack_start(lbl, expand=True, fill=True) + + self.addSites(vbox1, vbox2) + + hbox = gtk.HBox(False, 0) + self.mainVBox.pack_start(hbox, expand=True, padding=3) + + hbox = gtk.HBox(False, 0) + self.mainVBox.pack_start(hbox, expand=False, padding=3) + + lbl1 = gtk.Label() + hbox.pack_start(lbl1, expand=True, fill=False) self.doAutoImportBool = False - self.startButton=gtk.ToggleButton("Start Autoimport") + self.startButton = gtk.ToggleButton(" _Start Autoimport ") self.startButton.connect("clicked", self.startClicked, "start clicked") - self.mainVBox.add(self.startButton) - self.startButton.show() + hbox.pack_start(self.startButton, expand=False, fill=False) + + lbl2 = gtk.Label() + hbox.pack_start(lbl2, expand=True, fill=False) + + hbox = gtk.HBox(False, 0) + hbox.show() + self.mainVBox.pack_start(hbox, expand=True, padding=3) + self.mainVBox.show_all() #end of GuiAutoImport.__init__ @@ -177,40 +204,41 @@ class GuiAutoImport (threading.Thread): #Create the site line given required info and setup callbacks #enabling and disabling sites from this interface not possible #expects a box to layout the line horizontally - def createSiteLine(self, hbox, site, iconpath, hhpath, filter_name, active = True): + def createSiteLine(self, hbox1, hbox2, site, iconpath, hhpath, filter_name, active = True): label = gtk.Label(site + " auto-import:") - hbox.pack_start(label, False, False, 0) + hbox1.pack_start(label, False, False, 3) label.show() dirPath=gtk.Entry() dirPath.set_text(hhpath) - hbox.pack_start(dirPath, False, True, 0) + hbox1.pack_start(dirPath, True, True, 3) dirPath.show() browseButton=gtk.Button("Browse...") browseButton.connect("clicked", self.browseClicked, [site] + [dirPath]) - hbox.pack_start(browseButton, False, False, 0) + hbox2.pack_start(browseButton, False, False, 3) browseButton.show() - label = gtk.Label(site + " filter:") - hbox.pack_start(label, False, False, 0) + label = gtk.Label(' ' + site + " filter:") + hbox2.pack_start(label, False, False, 3) label.show() filter=gtk.Entry() filter.set_text(filter_name) - hbox.pack_start(filter, False, True, 0) + hbox2.pack_start(filter, True, True, 3) filter.show() - def addSites(self, vbox): + def addSites(self, vbox1, vbox2): the_sites = self.config.get_supported_sites() for site in the_sites: - pathHBox = gtk.HBox(False, 0) - vbox.pack_start(pathHBox, False, True, 0) - pathHBox.show() + pathHBox1 = gtk.HBox(False, 0) + vbox1.pack_start(pathHBox1, False, True, 0) + pathHBox2 = gtk.HBox(False, 0) + vbox2.pack_start(pathHBox2, False, True, 0) params = self.config.get_site_parameters(site) paths = self.config.get_default_paths(site) - self.createSiteLine(pathHBox, site, False, paths['hud-defaultPath'], params['converter'], params['enabled']) + self.createSiteLine(pathHBox1, pathHBox2, site, False, paths['hud-defaultPath'], params['converter'], params['enabled']) self.input_settings[site] = [paths['hud-defaultPath']] + [params['converter']] if __name__== "__main__": From ee9d69ae5e0d86d916637f96cd1426da99374988 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 21 May 2009 23:09:11 +0100 Subject: [PATCH 091/104] more minor cosmetic changes --- pyfpdb/GuiAutoImport.py | 2 +- pyfpdb/fpdb.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py index ebd3b636..06f4a96c 100755 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -66,7 +66,7 @@ class GuiAutoImport (threading.Thread): vbox2 = gtk.VBox(True, 0) hbox.pack_start(vbox2, True, True, 0) - self.intervalLabel = gtk.Label("Interval (ie. break) between imports in seconds:") + self.intervalLabel = gtk.Label("Time between imports in seconds:") self.intervalLabel.set_alignment(xalign=1.0, yalign=0.5) vbox1.pack_start(self.intervalLabel, True, True, 0) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 06b5d1f9..80b1ed4e 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -438,7 +438,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") self.tabs=[] self.tab_names=[] self.tab_buttons=[] - self.tab_box = gtk.HBox(False,1) + 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 From 203dcb44aee6daeb5ac9af20db6c3a75a2a4a9b3 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 21 May 2009 23:29:34 +0100 Subject: [PATCH 092/104] copy storehudcache2 into storehudcache, keeping the extra copy for more changes ... --- pyfpdb/fpdb_simple.py | 154 ++++++++++++++++++------------------------ 1 file changed, 65 insertions(+), 89 deletions(-) diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index be88ef17..d3a1712c 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -2407,77 +2407,23 @@ def generateFoldToCB(street, playerIDs, didStreetCB, streetCBDone, foldToStreetC foldToStreetCBDone[player]=True #end def generateFoldToCB -def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData): +def storeHudCache(backend, cursor, base, category, gametypeId, playerIds, hudImportData): + """Modified version aiming for more speed ...""" # if (category=="holdem" or category=="omahahi" or category=="omahahilo"): #print "storeHudCache, len(playerIds)=", len(playerIds), " len(vpip)=" \ #, len(hudImportData['street0VPI']), " len(totprof)=", len(hudImportData['totalProfit']) for player in xrange(len(playerIds)): - if base=="hold": - cursor.execute("""SELECT id, gametypeId, playerId, activeSeats, position, tourneyTypeId, HDs, - street0VPI, street0Aggr, street0_3BChance, street0_3BDone, - street1Seen, street2Seen, street3Seen, street4Seen, - sawShowdown, street1Aggr, street2Aggr, street3Aggr, street4Aggr, - otherRaisedStreet1, otherRaisedStreet2, otherRaisedStreet3, otherRaisedStreet4, - foldToOtherRaisedStreet1, foldToOtherRaisedStreet2, foldToOtherRaisedStreet3, foldToOtherRaisedStreet4, - wonWhenSeenStreet1, wonAtSD, 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 - FROM HudCache - WHERE gametypeId+0=%s AND playerId=%s AND activeSeats=%s AND position=%s - """ - , (gametypeId, playerIds[player], len(playerIds), hudImportData['position'][player])) - else: - cursor.execute("""SELECT id, gametypeId, playerId, activeSeats, position, tourneyTypeId, HDs, - street0VPI, street0Aggr, street0_3BChance, street0_3BDone, - street1Seen, street2Seen, street3Seen, street4Seen, - sawShowdown, street1Aggr, street2Aggr, street3Aggr, street4Aggr, - otherRaisedStreet1, otherRaisedStreet2, otherRaisedStreet3, otherRaisedStreet4, - foldToOtherRaisedStreet1, foldToOtherRaisedStreet2, foldToOtherRaisedStreet3, foldToOtherRaisedStreet4, - wonWhenSeenStreet1, wonAtSD, 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 - FROM HudCache - WHERE gametypeId+0=%s AND playerId=%s AND activeSeats=%s - """ - , (gametypeId, playerIds[player], len(playerIds))) - row=cursor.fetchone() - #print "gametypeId:", gametypeId, "playerIds[player]",playerIds[player], "len(playerIds):",len(playerIds), "row:",row - try: len(row) - except TypeError: - row=[] - - if not row: - #print "new huddata row" - doInsert=True - row=[] - row.append(0)#blank for id - row.append(gametypeId) - row.append(playerIds[player]) - row.append(len(playerIds))#seats - for i in xrange(len(hudImportData)+2): - row.append(0) + # Set up a clean row + row=[] + row.append(0)#blank for id + row.append(gametypeId) + row.append(playerIds[player]) + row.append(len(playerIds))#seats + for i in xrange(len(hudImportData)+2): + row.append(0) - else: - doInsert=False - # This is making a copy of the original list, although i really don't see any reason it's being done? - newrow=[] - newrow.extend(row) -# for i in xrange(len(row)): -# newrow.append(row[i]) - row=newrow - if base=="hold": row[4]=hudImportData['position'][player] else: @@ -2546,8 +2492,56 @@ def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData): if hudImportData['street4CheckCallRaiseChance'][player]: row[59]+=1 if hudImportData['street4CheckCallRaiseDone'][player]: row[60]+=1 - if doInsert: - #print "playerid before insert:",row[2] + # Try to do the update first: + num = cursor.execute("""UPDATE HudCache +SET HDs=HDs+%s, street0VPI=street0VPI+%s, street0Aggr=street0Aggr+%s, + street0_3BChance=street0_3BChance+%s, street0_3BDone=street0_3BDone+%s, + street1Seen=street1Seen+%s, street2Seen=street2Seen+%s, street3Seen=street3Seen+%s, + street4Seen=street4Seen+%s, sawShowdown=sawShowdown+%s, + street1Aggr=street1Aggr+%s, street2Aggr=street2Aggr+%s, street3Aggr=street3Aggr+%s, + street4Aggr=street4Aggr+%s, otherRaisedStreet1=otherRaisedStreet1+%s, + otherRaisedStreet2=otherRaisedStreet2+%s, otherRaisedStreet3=otherRaisedStreet3+%s, + otherRaisedStreet4=otherRaisedStreet4+%s, + foldToOtherRaisedStreet1=foldToOtherRaisedStreet1+%s, foldToOtherRaisedStreet2=foldToOtherRaisedStreet2+%s, + foldToOtherRaisedStreet3=foldToOtherRaisedStreet3+%s, foldToOtherRaisedStreet4=foldToOtherRaisedStreet4+%s, + wonWhenSeenStreet1=wonWhenSeenStreet1+%s, wonAtSD=wonAtSD+%s, stealAttemptChance=stealAttemptChance+%s, + stealAttempted=stealAttempted+%s, foldBbToStealChance=foldBbToStealChance+%s, + foldedBbToSteal=foldedBbToSteal+%s, + foldSbToStealChance=foldSbToStealChance+%s, foldedSbToSteal=foldedSbToSteal+%s, + street1CBChance=street1CBChance+%s, street1CBDone=street1CBDone+%s, street2CBChance=street2CBChance+%s, + street2CBDone=street2CBDone+%s, street3CBChance=street3CBChance+%s, + street3CBDone=street3CBDone+%s, street4CBChance=street4CBChance+%s, street4CBDone=street4CBDone+%s, + foldToStreet1CBChance=foldToStreet1CBChance+%s, foldToStreet1CBDone=foldToStreet1CBDone+%s, + foldToStreet2CBChance=foldToStreet2CBChance+%s, foldToStreet2CBDone=foldToStreet2CBDone+%s, + foldToStreet3CBChance=foldToStreet3CBChance+%s, + foldToStreet3CBDone=foldToStreet3CBDone+%s, foldToStreet4CBChance=foldToStreet4CBChance+%s, + foldToStreet4CBDone=foldToStreet4CBDone+%s, totalProfit=totalProfit+%s, + street1CheckCallRaiseChance=street1CheckCallRaiseChance+%s, + street1CheckCallRaiseDone=street1CheckCallRaiseDone+%s, street2CheckCallRaiseChance=street2CheckCallRaiseChance+%s, + street2CheckCallRaiseDone=street2CheckCallRaiseDone+%s, street3CheckCallRaiseChance=street3CheckCallRaiseChance+%s, + street3CheckCallRaiseDone=street3CheckCallRaiseDone+%s, street4CheckCallRaiseChance=street4CheckCallRaiseChance+%s, + street4CheckCallRaiseDone=street4CheckCallRaiseDone+%s +WHERE gametypeId+0=%s +AND playerId=%s +AND activeSeats=%s +AND position=%s +AND tourneyTypeId+0=%s""", (row[6], row[7], row[8], row[9], row[10], + row[11], row[12], row[13], row[14], row[15], + row[16], row[17], row[18], row[19], row[20], + row[21], row[22], row[23], row[24], row[25], + row[26], row[27], row[28], row[29], row[30], + row[31], row[32], row[33], row[34], row[35], + row[36], row[37], row[38], row[39], row[40], + row[41], row[42], row[43], row[44], row[45], + row[46], row[47], row[48], row[49], row[50], + row[51], row[52], row[53], row[54], row[55], + row[56], row[57], row[58], row[59], row[60], + row[1], row[2], row[3], str(row[4]), row[5])) + # Test statusmessage to see if update worked, do insert if not + #print "storehud2, upd num =", num + if ( (backend == PGSQL and cursor.statusmessage != "UPDATE 1") + or (backend == MYSQL_INNODB and num == 0) ): + #print "playerid before insert:",row[2]," num = ", num cursor.execute("""INSERT INTO HudCache (gametypeId, playerId, activeSeats, position, tourneyTypeId, styleKey, HDs, street0VPI, street0Aggr, street0_3BChance, street0_3BDone, @@ -2579,30 +2573,12 @@ VALUES (%s, %s, %s, %s, %s, %s, ,row[21], row[22], row[23], row[24], row[25], row[26], row[27], row[28], row[29], row[30] ,row[31], row[32], row[33], row[34], row[35], row[36], row[37], row[38], row[39], row[40] ,row[41], row[42], row[43], row[44], row[45], row[46], row[47], row[48], row[49], row[50] - ,row[51], row[52], row[53], row[54], row[55], row[56], row[57], row[58], row[59], row[60])) + ,row[51], row[52], row[53], row[54], row[55], row[56], row[57], row[58], row[59], row[60]) ) + #print "hopefully inserted hud data line: ", cursor.statusmessage + # message seems to be "INSERT 0 1" else: - #print "storing updated hud data line" - cursor.execute("""UPDATE HudCache -SET HDs=%s, street0VPI=%s, street0Aggr=%s, street0_3BChance=%s, street0_3BDone=%s, -street1Seen=%s, street2Seen=%s, street3Seen=%s, street4Seen=%s, sawShowdown=%s, -street1Aggr=%s, street2Aggr=%s, street3Aggr=%s, street4Aggr=%s, otherRaisedStreet1=%s, -otherRaisedStreet2=%s, otherRaisedStreet3=%s, otherRaisedStreet4=%s, foldToOtherRaisedStreet1=%s, foldToOtherRaisedStreet2=%s, -foldToOtherRaisedStreet3=%s, foldToOtherRaisedStreet4=%s, wonWhenSeenStreet1=%s, wonAtSD=%s, stealAttemptChance=%s, -stealAttempted=%s, foldBbToStealChance=%s, foldedBbToSteal=%s, foldSbToStealChance=%s, foldedSbToSteal=%s, -street1CBChance=%s, street1CBDone=%s, street2CBChance=%s, street2CBDone=%s, street3CBChance=%s, -street3CBDone=%s, street4CBChance=%s, street4CBDone=%s, foldToStreet1CBChance=%s, foldToStreet1CBDone=%s, -foldToStreet2CBChance=%s, foldToStreet2CBDone=%s, foldToStreet3CBChance=%s, foldToStreet3CBDone=%s, foldToStreet4CBChance=%s, -foldToStreet4CBDone=%s, totalProfit=%s, street1CheckCallRaiseChance=%s, street1CheckCallRaiseDone=%s, street2CheckCallRaiseChance=%s, -street2CheckCallRaiseDone=%s, street3CheckCallRaiseChance=%s, street3CheckCallRaiseDone=%s, street4CheckCallRaiseChance=%s, street4CheckCallRaiseDone=%s -WHERE gametypeId=%s AND playerId=%s AND activeSeats=%s AND position=%s AND tourneyTypeId=%s""", (row[6], row[7], row[8], row[9], row[10], - row[11], row[12], row[13], row[14], row[15], - row[16], row[17], row[18], row[19], row[20], - row[21], row[22], row[23], row[24], row[25], - row[26], row[27], row[28], row[29], row[30], - row[31], row[32], row[33], row[34], row[35], row[36], row[37], row[38], row[39], row[40], - row[41], row[42], row[43], row[44], row[45], row[46], row[47], row[48], row[49], row[50], - row[51], row[52], row[53], row[54], row[55], row[56], row[57], row[58], row[59], row[60], - row[1], row[2], row[3], str(row[4]), row[5])) + #print "updated(2) hud data line" + pass # else: # print "todo: implement storeHudCache for stud base" #end def storeHudCache From 06b1ce002f237c94f4168137ac9c0063cf8986ac Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sat, 23 May 2009 09:47:50 +0100 Subject: [PATCH 093/104] fix sql to work in postgres --- pyfpdb/SQL.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 33ea3590..02193287 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -324,7 +324,7 @@ class Sql: AND gt1.category = gt2.category AND gt1.limittype = gt2.limittype AND gt2.id = h.gametypeId) - GROUP BY hc.PlayerId, hc.styleKey + GROUP BY hc.PlayerId, p.name, hc.styleKey """ self.query['get_players_from_hand'] = """ From 061ff083a6f80c06b4e6c875c9190e488abe1985 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sat, 23 May 2009 21:42:26 +0100 Subject: [PATCH 094/104] get rid of warning message when starting fpdb --- pyfpdb/fpdb.py | 169 ++++++++++++++++++++++++++++++------------------- 1 file changed, 103 insertions(+), 66 deletions(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 80b1ed4e..3529dfe9 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -105,30 +105,30 @@ class fpdb: #end def delete_event def destroy(self, widget, data=None): - self.quit(widget, data) + self.quit(widget) #end def destroy - def dia_about(self, widget, data): + def dia_about(self, widget, data=None): print "todo: implement dia_about", print " version = %s, requires database version %s" % (VERSION, "118") #end def dia_about - def dia_create_del_database(self, widget, data): + def dia_create_del_database(self, widget, data=None): print "todo: implement dia_create_del_database" self.obtain_global_lock() #end def dia_create_del_database - def dia_create_del_user(self, widget, data): + def dia_create_del_user(self, widget, data=None): print "todo: implement dia_create_del_user" self.obtain_global_lock() #end def dia_create_del_user - def dia_database_stats(self, widget, data): + def dia_database_stats(self, widget, data=None): print "todo: implement dia_database_stats" #string=fpdb_db.getDbStats(db, cursor) #end def dia_database_stats - def dia_delete_db_parts(self, widget, data): + def dia_delete_db_parts(self, widget, data=None): print "todo: implement dia_delete_db_parts" self.obtain_global_lock() #end def dia_delete_db_parts @@ -138,7 +138,7 @@ class fpdb: self.obtain_global_lock() #end def dia_edit_profile - def dia_export_db(self, widget, data): + def dia_export_db(self, widget, data=None): print "todo: implement dia_export_db" self.obtain_global_lock() #end def dia_export_db @@ -163,16 +163,16 @@ class fpdb: # return (user, pw, response) #end def dia_get_db_root_credentials - def dia_import_db(self, widget, data): + def dia_import_db(self, widget, data=None): print "todo: implement dia_import_db" self.obtain_global_lock() #end def dia_import_db - def dia_licensing(self, widget, data): + def dia_licensing(self, widget, data=None): print "todo: implement dia_licensing" #end def dia_licensing - def dia_load_profile(self, widget, data): + def dia_load_profile(self, widget, data=None): """Dialogue to select a file to load a profile from""" self.obtain_global_lock() chooser = gtk.FileChooserDialog(title="Please select a profile file to load", @@ -188,7 +188,7 @@ class fpdb: print 'User cancelled loading profile' #end def dia_load_profile - def dia_recreate_tables(self, widget, data): + def dia_recreate_tables(self, widget, data=None): """Dialogue that asks user to confirm that he wants to delete and recreate the tables""" self.obtain_global_lock() @@ -205,12 +205,12 @@ class fpdb: print 'User cancelled recreating tables' #end def dia_recreate_tables - def dia_regression_test(self, widget, data): + def dia_regression_test(self, widget, data=None): print "todo: implement dia_regression_test" self.obtain_global_lock() #end def dia_regression_test - def dia_save_profile(self, widget, data): + def dia_save_profile(self, widget, data=None): print "todo: implement dia_save_profile" #end def dia_save_profile @@ -237,11 +237,87 @@ class fpdb: def get_menu(self, window): """returns the menu for this program""" - accel_group = gtk.AccelGroup() - self.item_factory = gtk.ItemFactory(gtk.MenuBar, "
", accel_group) - self.item_factory.create_items(self.menu_items) + fpdbmenu = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + uimanager = gtk.UIManager() + accel_group = uimanager.get_accel_group() + actiongroup = gtk.ActionGroup('UIManagerExample') + + # Create actions + actiongroup.add_actions([('main', None, '_Main'), + ('Quit', gtk.STOCK_QUIT, '_Quit me!', None, 'Quit the Program', self.quit), + ('LoadProf', None, '_Load Profile (broken)', 'L', 'Load your profile', self.dia_load_profile), + ('EditProf', None, '_Edit Profile (todo)', 'E', 'Edit your profile', self.dia_edit_profile), + ('SaveProf', None, '_Save Profile (todo)', 'S', 'Save your profile', self.dia_save_profile), + ('import', None, '_Import'), + ('bulkimp', None, '_Bulk Import', 'B', 'Bulk Import', self.tab_bulk_import), + ('autorate', None, 'Auto _Rating (todo)', 'R', 'Auto Rating (todo)', self.not_implemented), + ('viewers', None, '_Viewers'), + ('autoimp', None, '_Auto Import and HUD', 'A', 'Auto Import and HUD', self.tab_auto_import), + ('graphs', None, '_Graphs', 'G', 'Graphs', self.tabGraphViewer), + ('handreplay', None, 'Hand _Replayer (todo)', None, 'Hand Replayer (todo)', self.not_implemented), + ('playerdetails', None, 'Player _Details (todo)', None, 'Player Details (todo)', self.not_implemented), + ('playerstats', None, '_Player Stats (tabulated view)', 'control>P', 'Player Stats (tabulated view)', self.tab_player_stats), + ('posnstats', None, 'P_ositional Stats (tabulated view)', 'control>O', 'Positional Stats (tabulated view)', self.tab_positional_stats), + ('sessionreplay', None, '_Session Replayer (todo)', None, 'Session Replayer (todo)', self.not_implemented), + ('tableviewer', None, 'Poker_table Viewer (mostly obselete)', None, 'Poker_table Viewer (mostly obselete)', self.tab_table_viewer), + ('database', None, '_Database'), + ('createdb', None, 'Create or Delete _Database (todo)', None, 'Create or Delete Database', self.dia_create_del_database), + ('createuser', None, 'Create or Delete _User (todo)', None, 'Create or Delete User', self.dia_create_del_user), + ('createtabs', None, 'Create or Recreate _Tables', None, 'Create or Recreate Tables ', self.dia_recreate_tables), + ('stats', None, '_Statistics (todo)', None, 'View Database Statistics', self.dia_database_stats), + ('help', None, '_Help'), + ('Abbrev', None, '_Abbrevations (todo)', None, 'List of Abbrevations', self.tab_abbreviations), + ('About', None, 'A_bout', None, 'About the program', self.dia_about), + ('License', None, '_License and Copying (todo)', None, 'License and Copying', self.dia_licensing), + ]) + actiongroup.get_action('Quit').set_property('short-label', '_Quit') + + uimanager.insert_action_group(actiongroup, 0) + merge_id = uimanager.add_ui_from_string(fpdbmenu) + + # Create a MenuBar + menubar = uimanager.get_widget('/MenuBar') window.add_accel_group(accel_group) - return self.item_factory.get_widget("
") + return menubar #end def get_menu def load_profile(self): @@ -298,7 +374,7 @@ class fpdb: print "todo: implement obtain_global_lock (users: pls ignore this)" #end def obtain_global_lock - def quit(self, widget, data): + def quit(self, widget): print "Quitting normally" #check if current settings differ from profile, if so offer to save or abort self.db.disconnect() @@ -309,11 +385,11 @@ class fpdb: print "todo: implement release_global_lock" #end def release_global_lock - def tab_abbreviations(self, widget, data): + def tab_abbreviations(self, widget, data=None): print "todo: implement tab_abbreviations" #end def tab_abbreviations - def tab_auto_import(self, widget, data): + def tab_auto_import(self, widget, data=None): """opens the auto import tab""" new_aimp_thread=GuiAutoImport.GuiAutoImport(self.settings, self.config) self.threads.append(new_aimp_thread) @@ -321,7 +397,7 @@ class fpdb: self.add_and_display_tab(aimp_tab, "Auto Import") #end def tab_auto_import - def tab_bulk_import(self, widget, data): + def tab_bulk_import(self, widget, data=None): """opens a tab for bulk importing""" #print "start of tab_bulk_import" new_import_thread=GuiBulkImport.GuiBulkImport(self.settings, self.config) @@ -330,20 +406,20 @@ class fpdb: self.add_and_display_tab(bulk_tab, "Bulk Import") #end def tab_bulk_import - def tab_player_stats(self, widget, data): + def tab_player_stats(self, widget, data=None): new_ps_thread=GuiPlayerStats.GuiPlayerStats(self.config, self.querydict, self.window) self.threads.append(new_ps_thread) ps_tab=new_ps_thread.get_vbox() self.add_and_display_tab(ps_tab, "Player Stats") - def tab_positional_stats(self, widget, data): + def tab_positional_stats(self, widget, data=None): new_ps_thread=GuiPositionalStats.GuiPositionalStats(self.config, self.querydict) self.threads.append(new_ps_thread) ps_tab=new_ps_thread.get_vbox() self.add_and_display_tab(ps_tab, "Positional Stats") - def tab_main_help(self, widget, data): + def tab_main_help(self, widget, data=None): """Displays a tab with the main fpdb help screen""" #print "start of tab_main_help" mh_tab=gtk.Label("""Welcome to Fpdb! @@ -353,7 +429,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") self.add_and_display_tab(mh_tab, "Help") #end def tab_main_help - def tab_table_viewer(self, widget, data): + def tab_table_viewer(self, widget, data=None): """opens a table viewer tab""" #print "start of tab_table_viewer" new_tv_thread=GuiTableViewer.GuiTableViewer(self.db, self.settings) @@ -362,7 +438,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") self.add_and_display_tab(tv_tab, "Table Viewer") #end def tab_table_viewer - def tabGraphViewer(self, widget, data): + def tabGraphViewer(self, widget, data=None): """opens a graph viewer tab""" #print "start of tabGraphViewer" new_gv_thread=GuiGraphViewer.GuiGraphViewer(self.db, self.settings, self.querydict, self.config) @@ -385,46 +461,6 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") self.window.set_default_size(900,720) self.window.set_resizable(True) - self.menu_items = ( - ( "/_Main", None, None, 0, "" ), - ( "/Main/_Load Profile (broken)", "L", self.dia_load_profile, 0, None ), - ( "/Main/_Edit Profile (todo)", "E", self.dia_edit_profile, 0, None ), - ( "/Main/_Save Profile (todo)", None, self.dia_save_profile, 0, None ), - ("/Main/sep1", None, None, 0, "" ), - ("/Main/_Quit", "Q", self.quit, 0, None ), - ("/_Import", None, None, 0, "" ), - ("/Import/_Bulk Import", "B", self.tab_bulk_import, 0, None ), - ("/Import/_Auto Import and HUD", "A", self.tab_auto_import, 0, None ), - ("/Import/Auto _Rating (todo)", "R", self.not_implemented, 0, None ), - ("/_Viewers", None, None, 0, "" ), - ("/_Viewers/_Auto Import and HUD", "A", self.tab_auto_import, 0, None ), - ("/Viewers/_Graphs", "G", self.tabGraphViewer, 0, None ), - ("/Viewers/Hand _Replayer (todo)", None, self.not_implemented, 0, None ), - ("/Viewers/Player _Details (todo)", None, self.not_implemented, 0, None ), - ("/Viewers/_Player Stats (tabulated view)", "P", self.tab_player_stats, 0, None ), - ("/Viewers/P_ositional Stats (tabulated view)", "O", self.tab_positional_stats, 0, None ), - ("/Viewers/Starting _Hands (todo)", None, self.not_implemented, 0, None ), - ("/Viewers/_Session Replayer (todo)", None, self.not_implemented, 0, None ), - ("/Viewers/Poker_table Viewer (mostly obselete)", "T", self.tab_table_viewer, 0, None ), - #( "/Viewers/Tourney Replayer - ( "/_Database", None, None, 0, "" ), - ( "/Database/Create or Delete _Database (todo)", None, self.dia_create_del_database, 0, None ), - ( "/Database/Create or Delete _User (todo)", None, self.dia_create_del_user, 0, None ), - ( "/Database/Create or Recreate _Tables", None, self.dia_recreate_tables, 0, None ), - ( "/Database/_Statistics (todo)", None, self.dia_database_stats, 0, None ), - ( "/D_ebugging", None, None, 0, "" ), - ( "/Debugging/_Delete Parts of Database (todo)", None, self.dia_delete_db_parts, 0, None ), - ( "/Debugging/_Export DB (todo)", None, self.dia_export_db, 0, None ), - ( "/Debugging/_Import DB (todo)", None, self.dia_import_db, 0, None ), - ( "/Debugging/_Regression test (todo)", None, self.dia_regression_test, 0, None ), - ( "/_Help", None, None, 0, "" ), - ( "/Help/_Main Help", "H", self.tab_main_help, 0, None ), - ( "/Help/_Abbrevations (todo)", None, self.tab_abbreviations, 0, None ), - ( "/Help/sep1", None, None, 0, "" ), - ( "/Help/A_bout (todo)", None, self.dia_about, 0, None ), - ( "/Help/_License and Copying (todo)", None, self.dia_licensing, 0, None ) - ) - self.main_vbox = gtk.VBox(False, 1) self.main_vbox.set_border_width(1) self.window.add(self.main_vbox) @@ -455,6 +491,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") self.status_bar.show() self.window.show() + sys.stderr.write("fpdb starting ...") #end def __init__ def main(self): From e7532ea49727ba52822651cacd052d4a60a39136 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sat, 23 May 2009 22:06:41 +0100 Subject: [PATCH 095/104] fix typos in control keys in last release --- pyfpdb/fpdb.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 3529dfe9..66ed87cf 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -295,8 +295,8 @@ class fpdb: ('graphs', None, '_Graphs', 'G', 'Graphs', self.tabGraphViewer), ('handreplay', None, 'Hand _Replayer (todo)', None, 'Hand Replayer (todo)', self.not_implemented), ('playerdetails', None, 'Player _Details (todo)', None, 'Player Details (todo)', self.not_implemented), - ('playerstats', None, '_Player Stats (tabulated view)', 'control>P', 'Player Stats (tabulated view)', self.tab_player_stats), - ('posnstats', None, 'P_ositional Stats (tabulated view)', 'control>O', 'Positional Stats (tabulated view)', self.tab_positional_stats), + ('playerstats', None, '_Player Stats (tabulated view)', 'P', 'Player Stats (tabulated view)', self.tab_player_stats), + ('posnstats', None, 'P_ositional Stats (tabulated view)', 'O', 'Positional Stats (tabulated view)', self.tab_positional_stats), ('sessionreplay', None, '_Session Replayer (todo)', None, 'Session Replayer (todo)', self.not_implemented), ('tableviewer', None, 'Poker_table Viewer (mostly obselete)', None, 'Poker_table Viewer (mostly obselete)', self.tab_table_viewer), ('database', None, '_Database'), From 962ce03feacbc2c6d8752ac150e93c139d221b2a Mon Sep 17 00:00:00 2001 From: Worros Date: Mon, 25 May 2009 09:31:36 +0800 Subject: [PATCH 096/104] Fix storeHudCache callers --- pyfpdb/fpdb_save_to_db.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pyfpdb/fpdb_save_to_db.py b/pyfpdb/fpdb_save_to_db.py index 18344030..cfc820c6 100644 --- a/pyfpdb/fpdb_save_to_db.py +++ b/pyfpdb/fpdb_save_to_db.py @@ -54,7 +54,7 @@ def ring_stud(config, backend, db, cursor, base, category, site_hand_no, gametyp ,start_cashes, antes, card_values ,card_suits, winnings, rakes, seatNos) - fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData) + fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, player_ids, hudImportData) if saveActions: fpdb_simple.storeActions(cursor, hands_players_ids, action_types @@ -92,7 +92,7 @@ def ring_holdem_omaha(config, backend, db, cursor, base, category, site_hand_no, if fastStoreHudCache: fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, player_ids, hudImportData) else: - fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData) + fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, player_ids, hudImportData) t5 = time() fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) t6 = time() @@ -133,7 +133,7 @@ def tourney_holdem_omaha(config, backend, db, cursor, base, category, siteTourne if fastStoreHudCache: fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, player_ids, hudImportData) else: - fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData) + fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, player_ids, hudImportData) fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) @@ -165,7 +165,7 @@ def tourney_stud(config, backend, db, cursor, base, category, siteTourneyNo, buy , playerIds, startCashes, antes, cardValues, cardSuits , winnings, rakes, seatNos, tourneys_players_ids) - fpdb_simple.storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData) + fpdb_simple.storeHudCache(backend, cursor, base, category, gametypeId, playerIds, hudImportData) if saveActions: fpdb_simple.storeActions(cursor, hands_players_ids, actionTypes, allIns, actionAmounts, actionNos) From 90b886e77f06105639a2b35bb9391b9254c722de Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 25 May 2009 21:30:37 +0100 Subject: [PATCH 097/104] another parameter fix to the fpdb.py gui update --- pyfpdb/fpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 66ed87cf..70ece5e4 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -366,7 +366,7 @@ class fpdb: self.db.db.rollback() #end def load_profile - def not_implemented(self, widget, data): + def not_implemented(self, widget, data=None): print "todo: called unimplemented menu entry (users: pls ignore this)"#remove this once more entries are implemented #end def not_implemented From 3892b3789d3b28f51b9f4f4f493fd8188a005138 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 26 May 2009 16:10:27 +0800 Subject: [PATCH 098/104] Session breakdown Proof of Concept Only prints some of the session breakdown to stdout at the moment, otherwise is a copy of PlayerStats with a bunch of stuff commented out. Looks like: DEBUG: len(times) 337 DEBUG: len(diffs) 336 DEBUG: len(index[0]) 2 DEBUG: index [54 88] DEBUG: index[0][0] 54 Hands in session 0: 54 Start: 22/03/2009 07:04 End: 22/03/2009 07:49 Total: 2669 Hands in session 1: 33 Start: 24/03/2009 17:10 End: 24/03/2009 17:35 Total: 1482 I think the Total number has an index incorrect at the moment. --- pyfpdb/GuiSessionViewer.py | 310 +++++++++++++++++++++++++++++++++++++ pyfpdb/fpdb.py | 9 ++ 2 files changed, 319 insertions(+) create mode 100644 pyfpdb/GuiSessionViewer.py diff --git a/pyfpdb/GuiSessionViewer.py b/pyfpdb/GuiSessionViewer.py new file mode 100644 index 00000000..51398b0f --- /dev/null +++ b/pyfpdb/GuiSessionViewer.py @@ -0,0 +1,310 @@ +#!/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 +from time import time, strftime, localtime +from numpy import diff, nonzero + +import Card +import fpdb_import +import fpdb_db +import Filters +import FpdbSQLQueries + +class GuiSessionViewer (threading.Thread): + def __init__(self, config, querylist, debug=True): + self.debug=debug + self.conf=config + self.MYSQL_INNODB = 2 + self.PGSQL = 3 + self.SQLITE = 4 + + # create new db connection to avoid conflicts with other threads + self.db = fpdb_db.fpdb_db() + self.db.do_connect(self.conf) + self.cursor=self.db.cursor + self.sql = querylist + + 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()) + + # text used on screen stored here so that it can be configured + self.filterText = {'handhead':'Hand Breakdown for all levels listed above' + } + + filters_display = { "Heroes" : True, + "Sites" : True, + "Games" : False, + "Limits" : True, + "LimitSep" : True, + "Seats" : True, + "SeatSep" : True, + "Dates" : False, + "Groups" : True, + "Button1" : True, + "Button2" : True + } + + self.filters = Filters.Filters(self.db, settings, config, querylist, display = filters_display) + self.filters.registerButton2Name("_Refresh") + self.filters.registerButton2Callback(self.refreshStats) + + # ToDo: store in config + # ToDo: create popup to adjust column config + # columns to display, keys match column name returned by sql, values in tuple are: + # is column displayed, column heading, xalignment, formatting + self.columns = [ ("game", True, "Game", 0.0, "%s") + , ("hand", False, "Hand", 0.0, "%s") # true not allowed for this line + , ("n", True, "Hds", 1.0, "%d") + , ("avgseats", True, "Seats", 1.0, "%3.1f") + , ("vpip", True, "VPIP", 1.0, "%3.1f") + , ("pfr", True, "PFR", 1.0, "%3.1f") + , ("pf3", True, "PF3", 1.0, "%3.1f") + , ("steals", True, "Steals", 1.0, "%3.1f") + , ("saw_f", True, "Saw_F", 1.0, "%3.1f") + , ("sawsd", True, "SawSD", 1.0, "%3.1f") + , ("wtsdwsf", True, "WtSDwsF", 1.0, "%3.1f") + , ("wmsd", True, "W$SD", 1.0, "%3.1f") + , ("flafq", True, "FlAFq", 1.0, "%3.1f") + , ("tuafq", True, "TuAFq", 1.0, "%3.1f") + , ("rvafq", True, "RvAFq", 1.0, "%3.1f") + , ("pofafq", False, "PoFAFq", 1.0, "%3.1f") + , ("net", True, "Net($)", 1.0, "%6.2f") + , ("bbper100", True, "BB/100", 1.0, "%4.2f") + , ("rake", True, "Rake($)", 1.0, "%6.2f") + , ("variance", True, "Variance", 1.0, "%5.2f") + ] + + self.stats_frame = None + self.stats_vbox = None + self.detailFilters = [] # the data used to enhance the sql select + + self.main_hbox = gtk.HBox(False, 0) + self.main_hbox.show() + + self.stats_frame = gtk.Frame() + self.stats_frame.show() + + self.stats_vbox = gtk.VBox(False, 0) + self.stats_vbox.show() + self.stats_frame.add(self.stats_vbox) + self.fillStatsFrame(self.stats_vbox) + + self.main_hbox.pack_start(self.filters.get_vbox()) + self.main_hbox.pack_start(self.stats_frame, expand=True, fill=True) + +################################ + + + # make sure Hand column is not displayed + [x for x in self.columns if x[0] == 'hand'][0][1] == False + + def get_vbox(self): + """returns the vbox of this thread""" + return self.main_hbox + + def refreshStats(self, widget, data): + try: self.stats_vbox.destroy() + except AttributeError: pass + self.stats_vbox = gtk.VBox(False, 0) + self.stats_vbox.show() + self.stats_frame.add(self.stats_vbox) + self.fillStatsFrame(self.stats_vbox) + + def fillStatsFrame(self, vbox): + sites = self.filters.getSites() + heroes = self.filters.getHeroes() + siteids = self.filters.getSiteIds() + limits = self.filters.getLimits() + seats = self.filters.getSeats() + sitenos = [] + playerids = [] + + # Which sites are selected? + for site in sites: + if sites[site] == True: + sitenos.append(siteids[site]) + self.cursor.execute(self.sql.query['getPlayerId'], (heroes[site],)) + result = self.db.cursor.fetchall() + if len(result) == 1: + playerids.append(result[0][0]) + + if not sitenos: + #Should probably pop up here. + print "No sites selected - defaulting to PokerStars" + sitenos = [2] + if not playerids: + print "No player ids found" + return + if not limits: + print "No limits found" + return + + self.createStatsTable(vbox, playerids, sitenos, limits, seats) + + def createStatsTable(self, vbox, playerids, sitenos, limits, seats): + starttime = time() + + # Display summary table at top of page + # 3rd parameter passes extra flags, currently includes: + # holecards - whether to display card breakdown (True/False) + flags = [False] + self.addTable(vbox, 'playerDetailedStats', flags, playerids, sitenos, limits, seats) + + # Separator + sep = gtk.HSeparator() + vbox.pack_start(sep, expand=False, padding=3) + sep.show_now() + vbox.show_now() + heading = gtk.Label(self.filterText['handhead']) + heading.show() + vbox.pack_start(heading, expand=False, padding=3) + + # Scrolled window for detailed table (display by hand) + swin = gtk.ScrolledWindow(hadjustment=None, vadjustment=None) + swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + swin.show() + vbox.pack_start(swin, expand=True, padding=3) + + vbox1 = gtk.VBox(False, 0) + vbox1.show() + swin.add_with_viewport(vbox1) + + # Detailed table + flags = [True] + self.addTable(vbox1, 'playerDetailedStats', flags, playerids, sitenos, limits, seats) + + self.db.db.commit() + print "Stats page displayed in %4.2f seconds" % (time() - starttime) + #end def fillStatsFrame(self, vbox): + + def addTable(self, vbox, query, flags, playerids, sitenos, limits, seats): + row = 0 + sqlrow = 0 + colalias,colshow,colheading,colxalign,colformat = 0,1,2,3,4 + if not flags: holecards = False + else: holecards = flags[0] + + + self.stats_table = gtk.Table(1, 1, False) + self.stats_table.set_col_spacings(4) + self.stats_table.show() + + self.db.cursor.execute("""select UNIX_TIMESTAMP(handStart) as time, id from Hands ORDER BY time""") + THRESHOLD = 1800 + hands = self.db.cursor.fetchall() + + times = map(lambda x:long(x[0]), hands) + handids = map(lambda x:int(x[1]), hands) + print "DEBUG: len(times) %s" %(len(times)) + diffs = diff(times) + print "DEBUG: len(diffs) %s" %(len(diffs)) + index = nonzero(diff(times) > THRESHOLD) + print "DEBUG: len(index[0]) %s" %(len(index[0])) + print "DEBUG: index %s" %(index) + print "DEBUG: index[0][0] %s" %(index[0][0]) + + total = 0 + + last_idx = 0 + for i in range(len(index[0])): + print "Hands in session %4s: %4s Start: %s End: %s Total: %s" %(i, index[0][i] - last_idx, strftime("%d/%m/%Y %H:%M", localtime(times[last_idx])), strftime("%d/%m/%Y %H:%M", localtime(times[index[0][i]])), times[index[0][i]] - times[last_idx]) + total = total + (index[0][i] - last_idx) + last_idx = index[0][i] + 1 + + print "Total: ", total +# +# colnames = [desc[0].lower() for desc in self.cursor.description] +# +# # pre-fetch some constant values: +# cols_to_show = [x for x in self.columns if x[colshow]] +# hgametypeid_idx = colnames.index('hgametypeid') +# +# liststore = gtk.ListStore(*([str] * len(cols_to_show))) +# view = gtk.TreeView(model=liststore) +# view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH) +# vbox.pack_start(view, expand=False, padding=3) +# textcell = gtk.CellRendererText() +# numcell = gtk.CellRendererText() +# numcell.set_property('xalign', 1.0) +# listcols = [] +# +# # Create header row eg column: ("game", True, "Game", 0.0, "%s") +# for col, column in enumerate(cols_to_show): +# if column[colalias] == 'game' and holecards: +# s = [x for x in self.columns if x[colalias] == 'hand'][0][colheading] +# else: +# s = column[colheading] +# listcols.append(gtk.TreeViewColumn(s)) +# view.append_column(listcols[col]) +# if column[colformat] == '%s': +# if col == 1 and holecards: +# listcols[col].pack_start(textcell, expand=True) +# else: +# listcols[col].pack_start(textcell, expand=False) +# listcols[col].add_attribute(textcell, 'text', col) +# else: +# listcols[col].pack_start(numcell, expand=False) +# listcols[col].add_attribute(numcell, 'text', col) +# +# rows = len(result) # +1 for title row +# +# while sqlrow < rows: +# treerow = [] +# if(row%2 == 0): +# bgcolor = "white" +# else: +# bgcolor = "lightgrey" +# for col,column in enumerate(cols_to_show): +# if column[colalias] in colnames: +# value = result[sqlrow][colnames.index(column[colalias])] +# else: +# if column[colalias] == 'game': +# if holecards: +# value = Card.twoStartCardString( result[sqlrow][hgametypeid_idx] ) +# else: +# minbb = result[sqlrow][colnames.index('minbigblind')] +# maxbb = result[sqlrow][colnames.index('maxbigblind')] +# value = result[sqlrow][colnames.index('limittype')] + ' ' \ +# + result[sqlrow][colnames.index('category')].title() + ' ' \ +# + result[sqlrow][colnames.index('name')] + ' $' +# if 100 * int(minbb/100.0) != minbb: +# value += '%.2f' % (minbb/100.0) +# else: +# value += '%.0f' % (minbb/100.0) +# if minbb != maxbb: +# if 100 * int(maxbb/100.0) != maxbb: +# value += ' - $' + '%.2f' % (maxbb/100.0) +# else: +# value += ' - $' + '%.0f' % (maxbb/100.0) +# else: +# continue +# if value and value != -999: +# treerow.append(column[colformat] % value) +# else: +# treerow.append(' ') +# iter = liststore.append(treerow) +# sqlrow += 1 +# row += 1 + vbox.show_all() diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 66ed87cf..2bd413a4 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -44,6 +44,7 @@ import GuiPositionalStats import GuiTableViewer import GuiAutoImport import GuiGraphViewer +import GuiSessionViewer import FpdbSQLQueries import Configuration @@ -128,6 +129,12 @@ class fpdb: #string=fpdb_db.getDbStats(db, cursor) #end def dia_database_stats + def dia_database_sessions(self, widget, data=None): + new_sessions_thread=GuiSessionViewer.GuiSessionViewer(self.config, self.querydict) + self.threads.append(new_sessions_thread) + sessions_tab=new_sessions_thread.get_vbox() + self.add_and_display_tab(sessions_tab, "Sessions") + def dia_delete_db_parts(self, widget, data=None): print "todo: implement dia_delete_db_parts" self.obtain_global_lock() @@ -267,6 +274,7 @@ class fpdb: + @@ -304,6 +312,7 @@ class fpdb: ('createuser', None, 'Create or Delete _User (todo)', None, 'Create or Delete User', self.dia_create_del_user), ('createtabs', None, 'Create or Recreate _Tables', None, 'Create or Recreate Tables ', self.dia_recreate_tables), ('stats', None, '_Statistics (todo)', None, 'View Database Statistics', self.dia_database_stats), + ('sessions', None, 'Sessions', None, 'View Sessions', self.dia_database_sessions), ('help', None, '_Help'), ('Abbrev', None, '_Abbrevations (todo)', None, 'List of Abbrevations', self.tab_abbreviations), ('About', None, 'A_bout', None, 'About the program', self.dia_about), From d41a8beacd5d12f955315b8795c8b3cfb8907644 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 27 May 2009 22:21:22 +0100 Subject: [PATCH 099/104] add self. to variable reference and comment out debug message --- pyfpdb/fpdb_import.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 33ab49be..fbb74cec 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -226,7 +226,7 @@ class Importer: #if os.path.isdir(file): #self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1]) else: - removeFromFileList[file] = True + self.removeFromFileList[file] = True self.addToDirList = filter(lambda x: self.addImportDirectory(x, True, self.addToDirList[x][0], self.addToDirList[x][1]), self.addToDirList) for file in self.removeFromFileList: @@ -303,7 +303,8 @@ class Importer: try: # sometimes we seem to be getting an empty self.lines, in which case, we just want to return. firstline = self.lines[0] except: - print "DEBUG: import_fpdb_file: failed on self.lines[0]: '%s' '%s' '%s' '%s' " %( file, site, self.lines, loc) + # just skip the debug message and return silently: + #print "DEBUG: import_fpdb_file: failed on self.lines[0]: '%s' '%s' '%s' '%s' " %( file, site, self.lines, loc) return (0,0,0,1,0) if firstline.find("Tournament Summary")!=-1: From afee4ddb8c6f5cdc315d256c014686fc42d06ef6 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 27 May 2009 22:25:29 +0100 Subject: [PATCH 100/104] minor cosmetic change to autoimport button --- pyfpdb/GuiAutoImport.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py index 06f4a96c..2b4c8b76 100755 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -154,7 +154,7 @@ class GuiAutoImport (threading.Thread): # to watch. if widget.get_active(): # toggled on self.doAutoImportBool = True - widget.set_label(u'Stop Autoimport') + widget.set_label(u' _Stop Autoimport ') if self.pipe_to_hud is None: if os.name == 'nt': command = "python HUD_main.py" + " %s" % (self.database) @@ -190,7 +190,7 @@ class GuiAutoImport (threading.Thread): #print >>self.pipe_to_hud.stdin, "\n" self.pipe_to_hud.communicate('\n') # waits for process to terminate self.pipe_to_hud = None - self.startButton.set_label(u'Start Autoimport') + self.startButton.set_label(u' _Start Autoimport ') From 060c102843b5baeef2b76cda06eb04f43e3562f7 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 27 May 2009 23:34:10 +0100 Subject: [PATCH 101/104] changes to store date in hudcache.stylekey and display all-time / session / n days stats in hud --- pyfpdb/Database.py | 104 ++++++++++++++++++-- pyfpdb/SQL.py | 200 ++++++++++++++++++++++++++++++++++++-- pyfpdb/fpdb_save_to_db.py | 12 +-- pyfpdb/fpdb_simple.py | 38 +++++--- 4 files changed, 318 insertions(+), 36 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 88f7edd5..ca4e5996 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -26,6 +26,7 @@ Create and manage the database objects. # Standard Library modules import sys import traceback +from datetime import datetime, date, time, timedelta # pyGTK modules @@ -77,10 +78,40 @@ class Database: print "press enter to continue" sys.exit() + self.db_server = c.supported_databases[db_name].db_server self.type = c.supported_databases[db_name].db_type - self.sql = SQL.Sql(game = game, type = self.type) + 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() @@ -191,16 +222,25 @@ class Database: winners[row[0]] = row[1] return winners - def get_stats_from_hand(self, hand, aggregate = False, stylekey = 'A000000'): + 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' - else: - query = 'get_stats_from_hand' - subs = (hand, hand, stylekey, stylekey) - -# 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 = {} @@ -210,6 +250,52 @@ class Database: 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): diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 02193287..18d7d116 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -29,7 +29,7 @@ Set up all of the SQL statements for a given game and database type. class Sql: - def __init__(self, game = 'holdem', type = 'PT3'): + def __init__(self, game = 'holdem', type = 'PT3', db_server = 'mysql'): self.query = {} ############################################################################ @@ -175,7 +175,6 @@ class Sql: SELECT hc.playerId AS player_id, hp.seatNo AS seat, p.name AS screen_name, - hc.styleKey AS stylekey, sum(hc.HDs) AS n, sum(hc.street0VPI) AS vpip, sum(hc.street0Aggr) AS pfr, @@ -238,10 +237,16 @@ class Sql: AND hc.gametypeId+0 = h.gametypeId+0) INNER JOIN Players p ON (p.id = hp.PlayerId+0) WHERE h.id = %s - AND (hc.styleKey = %s or %s = 'ALL') /* styleKey should be passed in twice */ - /* This allows the caller to query only a particular stylekey or all, - e.g. may want to use different values for Hero and others */ - GROUP BY hc.PlayerId, hp.seatNo, p.name, hc.styleKey + AND hc.styleKey > %s + /* styleKey is currently 'd' (for date) followed by a yyyymmdd + date key. Set it to 0000000 or similar to get all records */ + /* also check activeseats here? even if only 3 groups eg 2-3/4-6/7+ ?? + e.g. could use a multiplier: + AND h.seats > X / 1.25 and hp.seats < X * 1.25 + where X is the number of active players at the current table (and + 1.25 would be a config value so user could change it) + */ + GROUP BY hc.PlayerId, hp.seatNo, p.name """ # same as above except stats are aggregated for all blind/limit levels @@ -252,7 +257,6 @@ class Sql: else -1 end) AS seat, p.name AS screen_name, - hc.styleKey AS stylekey, sum(hc.HDs) AS n, sum(hc.street0VPI) AS vpip, sum(hc.street0Aggr) AS pfr, @@ -314,9 +318,15 @@ class Sql: INNER JOIN HudCache hc ON (hc.playerId = hp.playerId) INNER JOIN Players p ON (p.id = hc.playerId) WHERE h.id = %s - AND (hc.styleKey = %s or %s = 'ALL') /* styleKey should be passed in twice */ - /* This allows the caller to query only a particular stylekey or all, - e.g. may want to use different values for Hero and others */ + AND hc.styleKey > %s + /* styleKey is currently 'd' (for date) followed by a yyyymmdd + date key. Set it to 0000000 or similar to get all records */ + /* also check activeseats here? even if only 3 groups eg 2-3/4-6/7+ ?? + e.g. could use a multiplier: + AND h.seats > %s / 1.25 and hp.seats < %s * 1.25 + where %s is the number of active players at the current table (and + 1.25 would be a config value so user could change it) + */ AND hc.gametypeId+0 in (SELECT gt1.id from Gametypes gt1, Gametypes gt2 WHERE gt1.siteid = gt2.siteid @@ -326,6 +336,164 @@ class Sql: AND gt2.id = h.gametypeId) GROUP BY hc.PlayerId, p.name, hc.styleKey """ + + if db_server == 'mysql': + 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 integer) AS vpip, + cast(hp2.street0Aggr as integer) AS pfr, + cast(hp2.street0_3BChance as integer) AS TB_opp_0, + cast(hp2.street0_3BDone as integer) AS TB_0, + cast(hp2.street1Seen as integer) AS saw_f, + cast(hp2.street1Seen as integer) AS saw_1, + cast(hp2.street2Seen as integer) AS saw_2, + cast(hp2.street3Seen as integer) AS saw_3, + cast(hp2.street4Seen as integer) AS saw_4, + cast(hp2.sawShowdown as integer) AS sd, + cast(hp2.street1Aggr as integer) AS aggr_1, + cast(hp2.street2Aggr as integer) AS aggr_2, + cast(hp2.street3Aggr as integer) AS aggr_3, + cast(hp2.street4Aggr as integer) AS aggr_4, + cast(hp2.otherRaisedStreet1 as integer) AS was_raised_1, + cast(hp2.otherRaisedStreet2 as integer) AS was_raised_2, + cast(hp2.otherRaisedStreet3 as integer) AS was_raised_3, + cast(hp2.otherRaisedStreet4 as integer) AS was_raised_4, + cast(hp2.foldToOtherRaisedStreet1 as integer) AS f_freq_1, + cast(hp2.foldToOtherRaisedStreet2 as integer) AS f_freq_2, + cast(hp2.foldToOtherRaisedStreet3 as integer) AS f_freq_3, + cast(hp2.foldToOtherRaisedStreet4 as integer) AS f_freq_4, + cast(hp2.wonWhenSeenStreet1 as integer) AS w_w_s_1, + cast(hp2.wonAtSD as integer) AS wmsd, + cast(hp2.stealAttemptChance as integer) AS steal_opp, + cast(hp2.stealAttempted as integer) AS steal, + cast(hp2.foldSbToStealChance as integer) AS SBstolen, + cast(hp2.foldedSbToSteal as integer) AS SBnotDef, + cast(hp2.foldBbToStealChance as integer) AS BBstolen, + cast(hp2.foldedBbToSteal as integer) AS BBnotDef, + cast(hp2.street1CBChance as integer) AS CB_opp_1, + cast(hp2.street1CBDone as integer) AS CB_1, + cast(hp2.street2CBChance as integer) AS CB_opp_2, + cast(hp2.street2CBDone as integer) AS CB_2, + cast(hp2.street3CBChance as integer) AS CB_opp_3, + cast(hp2.street3CBDone as integer) AS CB_3, + cast(hp2.street4CBChance as integer) AS CB_opp_4, + cast(hp2.street4CBDone as integer) AS CB_4, + cast(hp2.foldToStreet1CBChance as integer) AS f_cb_opp_1, + cast(hp2.foldToStreet1CBDone as integer) AS f_cb_1, + cast(hp2.foldToStreet2CBChance as integer) AS f_cb_opp_2, + cast(hp2.foldToStreet2CBDone as integer) AS f_cb_2, + cast(hp2.foldToStreet3CBChance as integer) AS f_cb_opp_3, + cast(hp2.foldToStreet3CBDone as integer) AS f_cb_3, + cast(hp2.foldToStreet4CBChance as integer) AS f_cb_opp_4, + cast(hp2.foldToStreet4CBDone as integer) AS f_cb_4, + cast(hp2.totalProfit as integer) AS net, + cast(hp2.street1CheckCallRaiseChance as integer) AS ccr_opp_1, + cast(hp2.street1CheckCallRaiseDone as integer) AS ccr_1, + cast(hp2.street2CheckCallRaiseChance as integer) AS ccr_opp_2, + cast(hp2.street2CheckCallRaiseDone as integer) AS ccr_2, + cast(hp2.street3CheckCallRaiseChance as integer) AS ccr_opp_3, + cast(hp2.street3CheckCallRaiseDone as integer) AS ccr_3, + cast(hp2.street4CheckCallRaiseChance as integer) AS ccr_opp_4, + cast(hp2.street4CheckCallRaiseDone as integer) AS ccr_4 + FROM + Hands h /* players in this hand */ + 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 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) + */ + 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 + 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 integer) AS vpip, + cast(hp2.street0Aggr as integer) AS pfr, + cast(hp2.street0_3BChance as integer) AS TB_opp_0, + cast(hp2.street0_3BDone as integer) AS TB_0, + cast(hp2.street1Seen as integer) AS saw_f, + cast(hp2.street1Seen as integer) AS saw_1, + cast(hp2.street2Seen as integer) AS saw_2, + cast(hp2.street3Seen as integer) AS saw_3, + cast(hp2.street4Seen as integer) AS saw_4, + cast(hp2.sawShowdown as integer) AS sd, + cast(hp2.street1Aggr as integer) AS aggr_1, + cast(hp2.street2Aggr as integer) AS aggr_2, + cast(hp2.street3Aggr as integer) AS aggr_3, + cast(hp2.street4Aggr as integer) AS aggr_4, + cast(hp2.otherRaisedStreet1 as integer) AS was_raised_1, + cast(hp2.otherRaisedStreet2 as integer) AS was_raised_2, + cast(hp2.otherRaisedStreet3 as integer) AS was_raised_3, + cast(hp2.otherRaisedStreet4 as integer) AS was_raised_4, + cast(hp2.foldToOtherRaisedStreet1 as integer) AS f_freq_1, + cast(hp2.foldToOtherRaisedStreet2 as integer) AS f_freq_2, + cast(hp2.foldToOtherRaisedStreet3 as integer) AS f_freq_3, + cast(hp2.foldToOtherRaisedStreet4 as integer) AS f_freq_4, + cast(hp2.wonWhenSeenStreet1 as integer) AS w_w_s_1, + cast(hp2.wonAtSD as integer) AS wmsd, + cast(hp2.stealAttemptChance as integer) AS steal_opp, + cast(hp2.stealAttempted as integer) AS steal, + cast(hp2.foldSbToStealChance as integer) AS SBstolen, + cast(hp2.foldedSbToSteal as integer) AS SBnotDef, + cast(hp2.foldBbToStealChance as integer) AS BBstolen, + cast(hp2.foldedBbToSteal as integer) AS BBnotDef, + cast(hp2.street1CBChance as integer) AS CB_opp_1, + cast(hp2.street1CBDone as integer) AS CB_1, + cast(hp2.street2CBChance as integer) AS CB_opp_2, + cast(hp2.street2CBDone as integer) AS CB_2, + cast(hp2.street3CBChance as integer) AS CB_opp_3, + cast(hp2.street3CBDone as integer) AS CB_3, + cast(hp2.street4CBChance as integer) AS CB_opp_4, + cast(hp2.street4CBDone as integer) AS CB_4, + cast(hp2.foldToStreet1CBChance as integer) AS f_cb_opp_1, + cast(hp2.foldToStreet1CBDone as integer) AS f_cb_1, + cast(hp2.foldToStreet2CBChance as integer) AS f_cb_opp_2, + cast(hp2.foldToStreet2CBDone as integer) AS f_cb_2, + cast(hp2.foldToStreet3CBChance as integer) AS f_cb_opp_3, + cast(hp2.foldToStreet3CBDone as integer) AS f_cb_3, + cast(hp2.foldToStreet4CBChance as integer) AS f_cb_opp_4, + cast(hp2.foldToStreet4CBDone as integer) AS f_cb_4, + cast(hp2.totalProfit as integer) AS net, + cast(hp2.street1CheckCallRaiseChance as integer) AS ccr_opp_1, + cast(hp2.street1CheckCallRaiseDone as integer) AS ccr_1, + cast(hp2.street2CheckCallRaiseChance as integer) AS ccr_opp_2, + cast(hp2.street2CheckCallRaiseDone as integer) AS ccr_2, + cast(hp2.street3CheckCallRaiseChance as integer) AS ccr_opp_3, + cast(hp2.street3CheckCallRaiseDone as integer) AS ccr_3, + cast(hp2.street4CheckCallRaiseChance as integer) AS ccr_opp_4, + cast(hp2.street4CheckCallRaiseDone as 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) + */ + 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 */ + """ self.query['get_players_from_hand'] = """ SELECT HandsPlayers.playerId, seatNo, name @@ -392,6 +560,18 @@ class Sql: AND HandsActions.handsPlayerId = HandsPlayers.id ORDER BY street, actionno """ + + if db_server == 'mysql': + self.query['get_hand_1day_ago'] = """ + select coalesce(max(id),0) + from hands + where handstart < date_sub(utc_timestamp(), interval '1' day)""" + else: # assume postgresql + self.query['get_hand_1day_ago'] = """ + select coalesce(max(id),0) + from hands + where handstart < now() at time zone 'UTC' - interval '1 day'""" + if __name__== "__main__": # just print the default queries and exit s = Sql(game = 'razz', type = 'ptracks') diff --git a/pyfpdb/fpdb_save_to_db.py b/pyfpdb/fpdb_save_to_db.py index cfc820c6..0dbcbf61 100644 --- a/pyfpdb/fpdb_save_to_db.py +++ b/pyfpdb/fpdb_save_to_db.py @@ -54,7 +54,7 @@ def ring_stud(config, backend, db, cursor, base, category, site_hand_no, gametyp ,start_cashes, antes, card_values ,card_suits, winnings, rakes, seatNos) - fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, player_ids, hudImportData) + fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) if saveActions: fpdb_simple.storeActions(cursor, hands_players_ids, action_types @@ -90,9 +90,9 @@ def ring_holdem_omaha(config, backend, db, cursor, base, category, site_hand_no, t4 = time() #print "ring holdem, backend=%d" % backend if fastStoreHudCache: - fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, player_ids, hudImportData) + fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) else: - fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, player_ids, hudImportData) + fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) t5 = time() fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) t6 = time() @@ -131,9 +131,9 @@ def tourney_holdem_omaha(config, backend, db, cursor, base, category, siteTourne #print "tourney holdem, backend=%d" % backend if fastStoreHudCache: - fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, player_ids, hudImportData) + fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) else: - fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, player_ids, hudImportData) + fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) @@ -165,7 +165,7 @@ def tourney_stud(config, backend, db, cursor, base, category, siteTourneyNo, buy , playerIds, startCashes, antes, cardValues, cardSuits , winnings, rakes, seatNos, tourneys_players_ids) - fpdb_simple.storeHudCache(backend, cursor, base, category, gametypeId, playerIds, hudImportData) + fpdb_simple.storeHudCache(backend, cursor, base, category, gametypeId, hand_start_time, playerIds, hudImportData) if saveActions: fpdb_simple.storeActions(cursor, hands_players_ids, actionTypes, allIns, actionAmounts, actionNos) diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index d3a1712c..e4471e24 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -31,6 +31,8 @@ MYSQL_INNODB = 2 PGSQL = 3 SQLITE = 4 +# config while trying out new hudcache mechanism +use_date_in_hudcache = True # Data Structures for index and foreign key creation # drop_code is an int with possible values: 0 - don't drop for bulk import @@ -2407,9 +2409,15 @@ def generateFoldToCB(street, playerIDs, didStreetCB, streetCBDone, foldToStreetC foldToStreetCBDone[player]=True #end def generateFoldToCB -def storeHudCache(backend, cursor, base, category, gametypeId, playerIds, hudImportData): +def storeHudCache(backend, cursor, base, category, gametypeId, hand_start_time, playerIds, hudImportData): """Modified version aiming for more speed ...""" # if (category=="holdem" or category=="omahahi" or category=="omahahilo"): + if use_date_in_hudcache: + #print "key =", "d%02d%02d%02d " % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day) + styleKey = "d%02d%02d%02d" % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day) + else: + # hard-code styleKey as 'A000000' (all-time cache, no key) for now + styleKey = 'A000000' #print "storeHudCache, len(playerIds)=", len(playerIds), " len(vpip)=" \ #, len(hudImportData['street0VPI']), " len(totprof)=", len(hudImportData['totalProfit']) @@ -2525,7 +2533,9 @@ WHERE gametypeId+0=%s AND playerId=%s AND activeSeats=%s AND position=%s -AND tourneyTypeId+0=%s""", (row[6], row[7], row[8], row[9], row[10], +AND tourneyTypeId+0=%s +AND styleKey=%s + """, (row[6], row[7], row[8], row[9], row[10], row[11], row[12], row[13], row[14], row[15], row[16], row[17], row[18], row[19], row[20], row[21], row[22], row[23], row[24], row[25], @@ -2536,7 +2546,7 @@ AND tourneyTypeId+0=%s""", (row[6], row[7], row[8], row[9], row[10], row[46], row[47], row[48], row[49], row[50], row[51], row[52], row[53], row[54], row[55], row[56], row[57], row[58], row[59], row[60], - row[1], row[2], row[3], str(row[4]), row[5])) + row[1], row[2], row[3], str(row[4]), row[5], styleKey)) # Test statusmessage to see if update worked, do insert if not #print "storehud2, upd num =", num if ( (backend == PGSQL and cursor.statusmessage != "UPDATE 1") @@ -2567,8 +2577,7 @@ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""" - # hard-code styleKey as 'A000000' (all-time cache, no key) for now - , (row[1], row[2], row[3], row[4], row[5], 'A000000', row[6], row[7], row[8], row[9], row[10] + , (row[1], row[2], row[3], row[4], row[5], styleKey, row[6], row[7], row[8], row[9], row[10] ,row[11], row[12], row[13], row[14], row[15], row[16], row[17], row[18], row[19], row[20] ,row[21], row[22], row[23], row[24], row[25], row[26], row[27], row[28], row[29], row[30] ,row[31], row[32], row[33], row[34], row[35], row[36], row[37], row[38], row[39], row[40] @@ -2583,11 +2592,17 @@ VALUES (%s, %s, %s, %s, %s, %s, # print "todo: implement storeHudCache for stud base" #end def storeHudCache -def storeHudCache2(backend, cursor, base, category, gametypeId, playerIds, hudImportData): +def storeHudCache2(backend, cursor, base, category, gametypeId, hand_start_time, playerIds, hudImportData): """Modified version aiming for more speed ...""" # if (category=="holdem" or category=="omahahi" or category=="omahahilo"): + if use_date_in_hudcache: + #print "key =", "d%02d%02d%02d " % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day) + styleKey = "d%02d%02d%02d" % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day) + else: + # hard-code styleKey as 'A000000' (all-time cache, no key) for now + styleKey = 'A000000' - #print "storeHudCache, len(playerIds)=", len(playerIds), " len(vpip)=" \ + #print "storeHudCache2, len(playerIds)=", len(playerIds), " len(vpip)=" \ #, len(hudImportData['street0VPI']), " len(totprof)=", len(hudImportData['totalProfit']) for player in xrange(len(playerIds)): @@ -2701,7 +2716,9 @@ WHERE gametypeId+0=%s AND playerId=%s AND activeSeats=%s AND position=%s -AND tourneyTypeId+0=%s""", (row[6], row[7], row[8], row[9], row[10], +AND tourneyTypeId+0=%s +AND styleKey=%s + """, (row[6], row[7], row[8], row[9], row[10], row[11], row[12], row[13], row[14], row[15], row[16], row[17], row[18], row[19], row[20], row[21], row[22], row[23], row[24], row[25], @@ -2712,7 +2729,7 @@ AND tourneyTypeId+0=%s""", (row[6], row[7], row[8], row[9], row[10], row[46], row[47], row[48], row[49], row[50], row[51], row[52], row[53], row[54], row[55], row[56], row[57], row[58], row[59], row[60], - row[1], row[2], row[3], str(row[4]), row[5])) + row[1], row[2], row[3], str(row[4]), row[5], styleKey)) # Test statusmessage to see if update worked, do insert if not #print "storehud2, upd num =", num if ( (backend == PGSQL and cursor.statusmessage != "UPDATE 1") @@ -2743,8 +2760,7 @@ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""" - # hard-code styleKey as 'A000000' (all-time cache, no key) for now - , (row[1], row[2], row[3], row[4], row[5], 'A000000', row[6], row[7], row[8], row[9], row[10] + , (row[1], row[2], row[3], row[4], row[5], styleKey, row[6], row[7], row[8], row[9], row[10] ,row[11], row[12], row[13], row[14], row[15], row[16], row[17], row[18], row[19], row[20] ,row[21], row[22], row[23], row[24], row[25], row[26], row[27], row[28], row[29], row[30] ,row[31], row[32], row[33], row[34], row[35], row[36], row[37], row[38], row[39], row[40] From e0e4eb4c3cf438e1b0fb139ab0dfc7a399e37125 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 28 May 2009 19:54:32 +0100 Subject: [PATCH 102/104] add date filter to positional stats --- pyfpdb/FpdbSQLQueries.py | 167 ++++++++++++++++++++++++++++++++++- pyfpdb/GuiPositionalStats.py | 26 +++--- 2 files changed, 175 insertions(+), 18 deletions(-) diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index 0e81c4fb..a85c2491 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -1053,6 +1053,8 @@ class FpdbSQLQueries: where hc.playerId in 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) @@ -1073,6 +1075,7 @@ class FpdbSQLQueries: 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 @@ -1153,6 +1156,8 @@ class FpdbSQLQueries: 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) @@ -1173,6 +1178,7 @@ class FpdbSQLQueries: 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 @@ -1275,6 +1281,8 @@ class FpdbSQLQueries: where hc.playerId in 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) @@ -1305,6 +1313,7 @@ class FpdbSQLQueries: 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 @@ -1409,6 +1418,8 @@ class FpdbSQLQueries: 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) @@ -1439,6 +1450,7 @@ class FpdbSQLQueries: 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 @@ -1662,7 +1674,7 @@ class FpdbSQLQueries: ) SELECT h.gametypeId ,hp.playerId - ,hp.activeSeats + ,h.seats ,case when hp.position = 'B' then 'B' when hp.position = 'S' then 'S' when hp.position = '0' then 'D' @@ -1678,7 +1690,7 @@ class FpdbSQLQueries: else 'E' end AS hc_position ,hp.tourneyTypeId - ,'A000000' /* All-time cache, no key required */ + ,date_format(h.handStart, 'd%y%m%d') ,count(1) ,sum(wonWhenSeenStreet1) ,sum(wonAtSD) @@ -1738,9 +1750,158 @@ class FpdbSQLQueries: INNER JOIN Hands h ON (h.id = hp.handId) GROUP BY h.gametypeId ,hp.playerId - ,hp.activeSeats + ,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') """ diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index 753fe874..042f7779 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -53,7 +53,7 @@ class GuiPositionalStats (threading.Thread): "LimitSep" : True, "Seats" : True, "SeatSep" : True, - "Dates" : False, + "Dates" : True, "Button1" : True, "Button2" : False } @@ -117,6 +117,7 @@ class GuiPositionalStats (threading.Thread): siteids = self.filters.getSiteIds() limits = self.filters.getLimits() seats = self.filters.getSeats() + dates = self.filters.getDates() sitenos = [] playerids = [] @@ -140,24 +141,16 @@ class GuiPositionalStats (threading.Thread): print "No limits found" return - self.createStatsTable(vbox, playerids, sitenos, limits, seats) - - def createStatsTable(self, vbox, playerids, sitenos, limits, seats): - - - + self.createStatsTable(vbox, playerids, sitenos, limits, seats, dates) + def createStatsTable(self, vbox, playerids, sitenos, limits, seats, dates): self.stats_table = gtk.Table(1, 1, False) # gtk table expands as required self.stats_table.set_col_spacings(4) self.stats_table.show() vbox.add(self.stats_table) row = 0 - - - col = 0 - for t in self.posnheads: l = gtk.Label(self.posnheads[col]) l.show() @@ -165,7 +158,7 @@ class GuiPositionalStats (threading.Thread): col +=1 tmp = self.sql.query['playerStatsByPosition'] - tmp = self.refineQuery(tmp, playerids, sitenos, limits, seats) + tmp = self.refineQuery(tmp, playerids, sitenos, limits, seats, dates) self.cursor.execute(tmp) result = self.cursor.fetchall() @@ -219,8 +212,7 @@ class GuiPositionalStats (threading.Thread): # show totals at bottom tmp = self.sql.query['playerStats'] - tmp = self.refineQuery(tmp, playerids, sitenos, limits, seats) - + tmp = self.refineQuery(tmp, playerids, sitenos, limits, seats, dates) self.cursor.execute(tmp) result = self.cursor.fetchall() rows = len(result) @@ -274,7 +266,7 @@ class GuiPositionalStats (threading.Thread): self.db.db.rollback() #end def fillStatsFrame(self, vbox): - def refineQuery(self, query, playerids, sitenos, limits, seats): + def refineQuery(self, query, playerids, sitenos, limits, seats, dates): if playerids: nametest = str(tuple(playerids)) nametest = nametest.replace("L", "") @@ -359,6 +351,10 @@ class GuiPositionalStats (threading.Thread): query = query.replace("", ",gt.bigBlind") query = query.replace("", "hc.gametypeId") query = query.replace("", "h.gameTypeId") + + # Filter on dates + query = query.replace("", " between '" + dates[0] + "' and '" + dates[1] + "'") + #print "query =\n", query return(query) #end def refineQuery(self, query, playerids, sitenos, limits): From 91bb9fc65f6a9b057a28e092fe51419b4918a863 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 28 May 2009 20:45:25 +0100 Subject: [PATCH 103/104] Tidy up alignment and expanding of cells in Player Stats window --- pyfpdb/GuiPlayerStats.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index a7f3abf1..311d9a10 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -259,11 +259,14 @@ class GuiPlayerStats (threading.Thread): if col == 1 and holecards: listcols[col].pack_start(textcell, expand=True) else: - listcols[col].pack_start(textcell, expand=False) + listcols[col].pack_start(textcell, expand=True) listcols[col].add_attribute(textcell, 'text', col) + listcols[col].set_expand(True) else: - listcols[col].pack_start(numcell, expand=False) + listcols[col].pack_start(numcell, expand=True) listcols[col].add_attribute(numcell, 'text', col) + listcols[col].set_alignment(1.0) + listcols[col].set_expand(True) rows = len(result) # +1 for title row @@ -435,6 +438,3 @@ class GuiPlayerStats (threading.Thread): detailDialog.destroy() - - - From d44b093144246afc236e09f13a482f8c83c82081 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 28 May 2009 22:40:58 +0100 Subject: [PATCH 104/104] put debug message back in, this point should not be reached --- pyfpdb/fpdb_import.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index fbb74cec..2dbb4807 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -303,8 +303,7 @@ class Importer: try: # sometimes we seem to be getting an empty self.lines, in which case, we just want to return. firstline = self.lines[0] except: - # just skip the debug message and return silently: - #print "DEBUG: import_fpdb_file: failed on self.lines[0]: '%s' '%s' '%s' '%s' " %( file, site, self.lines, loc) + print "DEBUG: import_fpdb_file: failed on self.lines[0]: '%s' '%s' '%s' '%s' " %( file, site, self.lines, loc) return (0,0,0,1,0) if firstline.find("Tournament Summary")!=-1: