#!/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. #This file contains simple functions for fpdb #Aiming to eventually remove this module, functions will move to, eg: #fpdb_db db create/re-create/management/etc #Hands or related files for saving hands to db, etc import datetime import time import re import sys import Card PS = 1 FTP = 2 # TODO: these constants are also used in fpdb_save_to_db and others, is there a way to do like C #define, and #include ? # answer - yes. These are defined in fpdb_db so are accessible through that class. MYSQL_INNODB = 2 PGSQL = 3 SQLITE = 4 class DuplicateError(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) class FpdbError(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) #returns an array of the total money paid. intending to add rebuys/addons here def calcPayin(count, buyin, fee): return [buyin + fee for i in xrange(count)] #end def calcPayin def checkPositions(positions): """ verify positions are valid """ if any(not (p == "B" or p == "S" or (p >= 0 and p <= 9)) for p in positions): raise FpdbError("invalid position '"+p+"' found in checkPositions") ### RHH modified to allow for "position 9" here (pos==9 is when you're a dead hand before the BB ### eric - position 8 could be valid - if only one blind is posted, but there's still 10 people, ie a sitout is present, and the small is dead... #classifies each line for further processing in later code. Manipulates the passed arrays. def classifyLines(hand, category, lineTypes, lineStreets): currentStreet = "predeal" done = False #set this to true once we reach the last relevant line (the summary, except rake, is all repeats) for i, line in enumerate(hand): if done: if "[" not in line or "mucked [" not in line: lineTypes.append("ignore") else: lineTypes.append("cards") elif line.startswith("Dealt to"): lineTypes.append("cards") elif i == 0: lineTypes.append("header") elif line.startswith("Table '"): lineTypes.append("table") elif line.startswith("Seat ") and ( ("in chips" in line) or "($" in line): lineTypes.append("name") elif isActionLine(line): lineTypes.append("action") if " posts " in line or " posts the " in line: currentStreet="preflop" elif " antes " in line or " posts the ante " in line: lineTypes.append("ante") elif line.startswith("*** FLOP *** ["): lineTypes.append("cards") currentStreet="flop" elif line.startswith("*** TURN *** ["): lineTypes.append("cards") currentStreet="turn" elif line.startswith("*** RIVER *** ["): lineTypes.append("cards") currentStreet="river" elif line.startswith("*** 3"): lineTypes.append("ignore") currentStreet=0 elif line.startswith("*** 4"): lineTypes.append("ignore") currentStreet=1 elif line.startswith("*** 5"): lineTypes.append("ignore") currentStreet=2 elif line.startswith("*** 6"): lineTypes.append("ignore") currentStreet=3 elif line.startswith("*** 7") or line == "*** RIVER ***": lineTypes.append("ignore") currentStreet=4 elif isWinLine(line): lineTypes.append("win") elif line.startswith("Total pot ") and "Rake" in line: lineTypes.append("rake") done=True elif "*** SHOW DOWN ***" in line or "*** SUMMARY ***" in line: lineTypes.append("ignore") #print "in classifyLine, showdown or summary" elif " shows [" in line: lineTypes.append("cards") else: raise FpdbError("unrecognised linetype in:"+hand[i]) lineStreets.append(currentStreet) #end def classifyLines def convert3B4B(category, limit_type, actionTypes, actionAmounts): """calculates the actual bet amounts in the given amount array and changes it accordingly.""" for i in xrange(len(actionTypes)): for j in xrange(len(actionTypes[i])): bets=[] for k in xrange(len(actionTypes[i][j])): if (actionTypes[i][j][k]=="bet"): bets.append((i,j,k)) if (len(bets)>=2): #print "len(bets) 2 or higher, need to correct it. bets:",bets,"len:",len(bets) for betNo in reversed(xrange (1,len(bets))): amount2=actionAmounts[bets[betNo][0]][bets[betNo][1]][bets[betNo][2]] amount1=actionAmounts[bets[betNo-1][0]][bets[betNo-1][1]][bets[betNo-1][2]] actionAmounts[bets[betNo][0]][bets[betNo][1]][bets[betNo][2]]=amount2-amount1 #print "actionAmounts postConvert",actionAmounts #end def convert3B4B(actionTypes, actionAmounts) #Corrects the bet amount if the player had to pay blinds def convertBlindBet(actionTypes, actionAmounts): i=0#setting street to pre-flop for j in xrange(len(actionTypes[i])):#playerloop blinds=[] bets=[] for k in xrange(len(actionTypes[i][j])): if actionTypes[i][j][k] == "blind": blinds.append((i,j,k)) if blinds and actionTypes[i][j][k] == "bet": # if (len(blinds)>0 and actionTypes[i][j][k]=="bet"): bets.append((i,j,k)) if len(bets) == 1: blind_amount=actionAmounts[blinds[0][0]][blinds[0][1]][blinds[0][2]] bet_amount=actionAmounts[bets[0][0]][bets[0][1]][bets[0][2]] actionAmounts[bets[0][0]][bets[0][1]][bets[0][2]]=bet_amount-blind_amount #end def convertBlindBet #converts the strings in the given array to ints (changes the passed array, no returning). see table design for conversion details #todo: make this use convertCardValuesBoard def convertCardValues(arr): map(convertCardValuesBoard, arr) #end def convertCardValues # a 0-card is one in a stud game that we did not see or was not shown card_map = { 0: 0, "2": 2, "3" : 3, "4" : 4, "5" : 5, "6" : 6, "7" : 7, "8" : 8, "9" : 9, "T" : 10, "J" : 11, "Q" : 12, "K" : 13, "A" : 14} #converts the strings in the given array to ints (changes the passed array, no returning). see table design for conversion details def convertCardValuesBoard(arr): for i in xrange(len(arr)): arr[i] = card_map[arr[i]] #end def convertCardValuesBoard #this creates the 2D/3D arrays. manipulates the passed arrays instead of returning. def createArrays(category, seats, card_values, card_suits, antes, winnings, rakes, action_types, allIns, action_amounts, actionNos, actionTypeByNo): for i in xrange(seats):#create second dimension arrays card_values.append( [] ) card_suits.append( [] ) antes.append(0) winnings.append(0) rakes.append(0) streetCount = 4 if category == "holdem" or category == "omahahi" or category == "omahahilo" else 5 for i in xrange(streetCount): #build the first dimension array, for streets action_types.append([]) allIns.append([]) action_amounts.append([]) actionNos.append([]) actionTypeByNo.append([]) for j in xrange (seats): #second dimension arrays: players action_types[i].append([]) allIns[i].append([]) action_amounts[i].append([]) actionNos[i].append([]) # if (category=="holdem" or category=="omahahi" or category=="omahahilo"): # pass if category=="razz" or category=="studhi" or category=="studhilo":#need to fill card arrays. for i in xrange(seats): for j in xrange(7): card_values[i].append(0) card_suits[i].append("x") # else: # raise FpdbError("invalid category") #end def createArrays def fill_board_cards(board_values, board_suits): #fill up the two board card arrays while (len(board_values)<5): board_values.append(0) board_suits.append("x") #end def fill_board_cards def fillCardArrays(player_count, base, category, card_values, card_suits): """fills up the two card arrays""" if (category=="holdem"): cardCount = 2 elif (category=="omahahi" or category=="omahahilo"): cardCount = 4 elif base=="stud": cardCount = 7 else: raise fpdb_simple.FpdbError("invalid category:", category) for i in xrange(player_count): while (len(card_values[i]) < cardCount): card_values[i].append(0) card_suits[i].append("x") #end def fillCardArrays #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(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" pre3rd=[] for i, line in enumerate(hand): if line.startswith("*** 3") or line.startswith("*** HOLE"): pre3rd = hand[0:i] foldeeName=None for line in pre3rd: if line.endswith("folds") or line.endswith("is sitting out") or line.endswith(" stands up"): #found ante fold or timeout pos = line.find(" folds") foldeeName = line[0:pos] if pos == -1 and " in chips)" not in line: pos = line.find(" is sitting out") foldeeName = line[0:pos] if pos == -1: pos = line.find(" stands up") foldeeName = line[0:pos] if pos == -1: pos1 = line.find(": ") + 2 pos2 = line.find(" (") foldeeName = line[pos1:pos2] if foldeeName!=None: #print "filterAnteBlindFold, foldeeName:",foldeeName for i, line in enumerate(hand): if foldeeName in line: hand[i] = None return [line for line in hand if line] #end def filterAnteFold def stripEOLspaces(str): return str.rstrip() #removes useless lines as well as trailing spaces def filterCrap(hand, isTourney): #remove two trailing spaces at end of line hand = [line.rstrip() for line in hand] #print "hand after trailing space removal in filterCrap:",hand #general variable position word filter/string filter for i in xrange (len(hand)): if hand[i].startswith("Board ["): hand[i] = False elif hand[i].find(" out of hand ")!=-1: hand[i]=hand[i][:-56] elif "($0 in chips)" in hand[i]: hand[i] = False elif hand[i]=="*** HOLE CARDS ***": hand[i] = False elif hand[i].endswith("has been disconnected"): hand[i] = False elif hand[i].endswith("has requested TIME"): hand[i] = False elif hand[i].endswith("has returned"): hand[i] = False elif hand[i].endswith("will be allowed to play after the button"): hand[i] = False elif hand[i].endswith("has timed out"): hand[i] = False elif hand[i].endswith("has timed out while disconnected"): hand[i] = False elif hand[i].endswith("has timed out while being disconnected"): hand[i] = False elif hand[i].endswith("is connected"): hand[i] = False elif hand[i].endswith("is disconnected"): hand[i] = False elif hand[i].find(" is low with [")!=-1: hand[i] = False elif hand[i].endswith(" mucks"): hand[i] = False elif hand[i].endswith(": mucks hand"): hand[i] = False elif hand[i] == "No low hand qualified": hand[i] = False elif hand[i] == "Pair on board - a double bet is allowed": hand[i] = False elif " shows " in hand[i] and "[" not in hand[i]: hand[i] = False elif hand[i].startswith("The button is in seat #"): hand[i] = False #above is alphabetic, reorder below if bored elif hand[i].startswith("Time has expired"): hand[i] = False elif hand[i].endswith("has reconnected"): hand[i] = False elif hand[i].endswith("seconds left to act"): hand[i] = False elif hand[i].endswith("seconds to reconnect"): hand[i] = False elif hand[i].endswith("was removed from the table for failing to post"): hand[i] = False elif "joins the table at seat " in hand[i]: hand[i] = False elif (hand[i].endswith("leaves the table")): hand[i] = False elif "is high with " in hand[i]: hand[i] = False elif hand[i].endswith("doesn't show hand"): hand[i] = False elif hand[i].endswith("is being treated as all-in"): hand[i] = False elif " adds $" in hand[i]: hand[i] = False elif hand[i] == "Betting is capped": hand[i] = False elif (hand[i].find(" said, \"")!=-1): hand[i] = False if isTourney and not hand[i] == False: if (hand[i].endswith(" is sitting out") and (not hand[i].startswith("Seat "))): hand[i] = False elif hand[i]: if (hand[i].endswith(": sits out")): hand[i] = False elif (hand[i].endswith(" is sitting out")): hand[i] = False hand = [line for line in hand if line] # python docs say this is identical to filter(None, list) #print "done with filterCrap, hand:", hand return hand #end filterCrap #takes a poker float (including , for thousand seperator and converts it to an int def float2int(string): pos = string.find(",") if pos != -1: #remove , the thousand seperator string = "%s%s" % (string[0:pos], string[pos+1:]) pos = string.find(".") if pos != -1: #remove decimal point string = "%s%s" % (string[0:pos], string[pos+1:]) result = int(string) if pos == -1: #no decimal point - was in full dollars - need to multiply with 100 result *= 100 return result #end def float2int ActionLines = ( "calls $", ": calls ", "brings in for", "completes it to", "posts small blind", "posts the small blind", "posts big blind", "posts the big blind", "posts small & big blinds", "posts $", "posts a dead", "bets $", ": bets ", " raises") #returns boolean whether the passed line is an action line def isActionLine(line): if (line.endswith("folds")): return True elif (line.endswith("checks")): return True elif (line.startswith("Uncalled bet")): return True return any(x for x in ActionLines if x in line) # return bool([ x for x in ActionLines if x in line]) # ret = any(True for searchstr in ActionLines if searchstr in line) # ret = len( [ x for x in ActionLines if line.find(x) > -1] ) > 0 # ret = any(searchstr in line for searchstr in ActionLines) #end def isActionLine #returns whether this is a duplicate def isAlreadyInDB(cursor, gametypeID, siteHandNo): #print "isAlreadyInDB gtid,shand:",gametypeID, siteHandNo cursor.execute ("SELECT id FROM Hands WHERE gametypeId=%s AND siteHandNo=%s", (gametypeID, siteHandNo)) result=cursor.fetchall() if (len(result)>=1): raise DuplicateError ("dupl") #end isAlreadyInDB def isRebuyOrAddon(topline): """isRebuyOrAddon not implemented yet""" return False #end def isRebuyOrAddon #returns whether the passed topline indicates a tournament or not def isTourney(topline): return "Tournament" in topline #end def isTourney WinLines = ( "wins the pot", "ties for the ", "wins side pot", "wins the low main pot", "wins the high main pot", "wins the low", "wins the high pot", "wins the high side pot", "wins the main pot", "wins the side pot", "collected" ) #returns boolean whether the passed line is a win line def isWinLine(line): return any(x for x in WinLines if x in line) #end def isWinLine #returns the amount of cash/chips put into the put in the given action line def parseActionAmount(line, atype, isTourney): #if (line.endswith(" and is all-in")): # line=line[:-14] #elif (line.endswith(", and is all in")): # line=line[:-15] if line.endswith(", and is capped"):#ideally we should recognise this as an all-in if category is capXl line=line[:-15] if line.endswith(" and is capped"): line=line[:-14] if atype == "fold" or atype == "check": amount = 0 elif atype == "unbet": pos1 = line.find("$") + 1 if pos1 == 0: pos1 = line.find("(") + 1 pos2 = line.find(")") amount = float2int(line[pos1:pos2]) elif atype == "bet" and line.find(": raises $")!=-1 and line.find("to $")!=-1: pos=line.find("to $")+4 amount=float2int(line[pos:]) else: if not isTourney: pos = line.rfind("$")+1 #print "parseActionAmount, line:", line, "line[pos:]:", line[pos:] amount = float2int(line[pos:]) else: #print "line:"+line+"EOL" pos = line.rfind(" ")+1 #print "pos:",pos #print "pos of 20:", line.find("20") amount = int(line[pos:]) if atype == "unbet": amount *= -1 return amount #end def parseActionAmount #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(base, isTourney, line, street, playerIDs, names, action_types, allIns, action_amounts, actionNos, actionTypeByNo): if street == "predeal" or street == "preflop": street = 0 elif street == "flop": street = 1 elif street == "turn": street = 2 elif street == "river": street = 3 nextActionNo = 0 for player in xrange(len(actionNos[street])): for count in xrange(len(actionNos[street][player])): if actionNos[street][player][count]>=nextActionNo: nextActionNo=actionNos[street][player][count]+1 (line, allIn) = goesAllInOnThisLine(line) atype = parseActionType(line) playerno = recognisePlayerNo(line, names, atype) amount = parseActionAmount(line, atype, isTourney) action_types[street][playerno].append(atype) allIns[street][playerno].append(allIn) action_amounts[street][playerno].append(amount) actionNos[street][playerno].append(nextActionNo) tmp=(playerIDs[playerno], atype) actionTypeByNo[street].append(tmp) #end def parseActionLine def goesAllInOnThisLine(line): """returns whether the player went all-in on this line and removes the all-in text from the line.""" isAllIn = False if (line.endswith(" and is all-in")): line = line[:-14] isAllIn = True elif (line.endswith(", and is all in")): line = line[:-15] isAllIn = True return (line, isAllIn) #end def goesAllInOnThisLine #returns the action type code (see table design) of the given action line 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")): return "unbet" elif (line.endswith(" folds")): return "fold" elif (line.endswith(" checks")): return "check" else: for x in ActionTypes: if x in line: return ActionTypes[x] raise FpdbError ("failed to recognise actiontype in parseActionLine in: "+line) #end def parseActionType #parses the ante out of the given line and checks which player paid it, updates antes accordingly. def parseAnteLine(line, isTourney, names, antes): for i, name in enumerate(names): if line.startswith(name.encode("latin-1")): pos = line.rfind("$") + 1 if not isTourney: antes[i] += float2int(line[pos:]) else: if "all-in" not in line: pos = line.rfind(" ") + 1 antes[i] += int(line[pos:]) else: pos1 = line.rfind("ante") + 5 pos2 = line.find(" ", pos1) antes[i] += int(line[pos1:pos2]) #print "parseAnteLine line: ", line, "antes[i]", antes[i], "antes", antes #end def parseAntes #returns the buyin of a tourney in cents def parseBuyin(topline): pos1 = topline.find("$")+1 pos2 = topline.find("+") return float2int(topline[pos1:pos2]) #end def parseBuyin #parses a card line and changes the passed arrays accordingly #todo: reorganise this messy method def parseCardLine(category, street, line, names, cardValues, cardSuits, boardValues, boardSuits): if line.startswith("Dealt to") or " shows [" in line or "mucked [" in line: playerNo = recognisePlayerNo(line, names, "card") #anything but unbet will be ok for that string pos = line.rfind("[")+1 if category == "holdem": for i in (pos, pos+3): cardValues[playerNo].append(line[i:i+1]) cardSuits[playerNo].append(line[i+1:i+2]) if len(cardValues[playerNo]) !=2: if cardValues[playerNo][0]==cardValues[playerNo][2] and cardSuits[playerNo][1]==cardSuits[playerNo][3]: #two tests will do cardValues[playerNo]=cardValues[playerNo][0:2] cardSuits[playerNo]=cardSuits[playerNo][0:2] else: print "line:",line,"cardValues[playerNo]:",cardValues[playerNo] raise FpdbError("read too many/too few holecards in parseCardLine") elif category == "omahahi" or category == "omahahilo": for i in (pos, pos+3, pos+6, pos+9): cardValues[playerNo].append(line[i:i+1]) cardSuits[playerNo].append(line[i+1:i+2]) if (len(cardValues[playerNo])!=4): if cardValues[playerNo][0]==cardValues[playerNo][4] and cardSuits[playerNo][3]==cardSuits[playerNo][7]: #two tests will do cardValues[playerNo]=cardValues[playerNo][0:4] cardSuits[playerNo]=cardSuits[playerNo][0:4] else: print "line:",line,"cardValues[playerNo]:",cardValues[playerNo] raise FpdbError("read too many/too few holecards in parseCardLine") elif category=="razz" or category=="studhi" or category=="studhilo": if "shows" not in line and "mucked" not in line: #print "parseCardLine(in stud if), street:", street if line[pos+2]=="]": #-> not (hero and 3rd street) cardValues[playerNo][street+2]=line[pos:pos+1] cardSuits[playerNo][street+2]=line[pos+1:pos+2] else: #print "hero card1:", line[pos:pos+2], "hero card2:", line[pos+3:pos+5], "hero card3:", line[pos+6:pos+8], cardValues[playerNo][street]=line[pos:pos+1] cardSuits[playerNo][street]=line[pos+1:pos+2] cardValues[playerNo][street+1]=line[pos+3:pos+4] cardSuits[playerNo][street+1]=line[pos+4:pos+5] cardValues[playerNo][street+2]=line[pos+6:pos+7] cardSuits[playerNo][street+2]=line[pos+7:pos+8] else: #print "parseCardLine(in stud else), street:", street cardValues[playerNo][0]=line[pos:pos+1] cardSuits[playerNo][0]=line[pos+1:pos+2] pos+=3 cardValues[playerNo][1]=line[pos:pos+1] cardSuits[playerNo][1]=line[pos+1:pos+2] if street==4: pos=pos=line.rfind("]")-2 cardValues[playerNo][6]=line[pos:pos+1] cardSuits[playerNo][6]=line[pos+1:pos+2] #print "cardValues:", cardValues #print "cardSuits:", cardSuits else: print "line:",line,"street:",street raise FpdbError("invalid category") #print "end of parseCardLine/playercards, cardValues:",cardValues elif (line.startswith("*** FLOP ***")): pos=line.find("[")+1 for i in (pos, pos+3, pos+6): boardValues.append(line[i:i+1]) boardSuits.append(line[i+1:i+2]) #print boardValues elif (line.startswith("*** TURN ***") or line.startswith("*** RIVER ***")): pos=line.find("[")+1 pos=line.find("[", pos+1)+1 boardValues.append(line[pos:pos+1]) boardSuits.append(line[pos+1:pos+2]) #print boardValues else: raise FpdbError ("unrecognised line:"+line) #end def parseCardLine 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 = [] for i in xrange (len(lines)): pos2=lines[i].find(":") seatNos.append(int(lines[i][5:pos2])) 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 pos2=lines[i].find(" in chips") cashes.append(float2int(lines[i][pos1:pos2])) return {'startCashes':cashes, 'seatNos':seatNos} #end def parseCashesAndSeatNos #returns the buyin of a tourney in cents def parseFee(topline): pos1=topline.find("$")+1 pos1=topline.find("$",pos1)+1 pos2=topline.find(" ", pos1) return float2int(topline[pos1:pos2]) #end def parsefee #returns a datetime object with the starttime indicated in the given topline def parseHandStartTime(topline): #convert x:13:35 to 0x:13:35 counter=0 while counter < 10: pos = topline.find(" %d:" % counter) if pos != -1: topline = "%s0%s" % (topline[0:pos+1], topline[pos+1:]) break counter += 1 isUTC=False 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) 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 not isUTC: #these use US ET result+=datetime.timedelta(hours=5) return result #end def parseHandStartTime #parses the names out of the given lines and returns them as an array def findName(line): pos1 = line.find(":") + 2 pos2 = line.rfind("(") - 1 return unicode(line[pos1:pos2], "latin-1") def parseNames(lines): return [findName(line) for line in lines] #end def parseNames def parsePositions(hand, names): positions = [-1 for i in names] sb, bb = -1, -1 #find blinds for line in hand: if sb == -1 and "small blind" in line and "dead small blind" not in line: sb = line if bb == -1 and "big blind" in line and "dead big blind" not in line: bb = line #identify blinds #print "parsePositions before recognising sb/bb. names:",names sbExists = True if sb != -1: sb = recognisePlayerNo(sb, names, "bet") else: sbExists = False if bb != -1: bb = recognisePlayerNo(bb, names, "bet") # print "sb = ", sb, "bb = ", bb if bb == sb: # if big and small are same, then don't duplicate the small sbExists = False sb = -1 #write blinds into array if sbExists: positions[sb]="S" positions[bb]="B" #fill up rest of array if sbExists: arraypos = sb-1 else: arraypos = bb-1 distFromBtn=0 while arraypos >= 0 and arraypos != bb: #print "parsePositions first while, arraypos:",arraypos,"positions:",positions positions[arraypos] = distFromBtn arraypos -= 1 distFromBtn += 1 # eric - this takes into account dead seats between blinds if sbExists: i = bb - 1 while positions[i] < 0 and i != sb: positions[i] = 9 i -= 1 ### RHH - Changed to set the null seats before BB to "9" if sbExists: i = sb-1 else: i = bb-1 while positions[i] < 0: positions[i]=9 i-=1 arraypos=len(names)-1 if (bb!=0 or (bb==0 and sbExists==False) or (bb == 1 and sb != arraypos) ): while (arraypos>bb and arraypos > sb): positions[arraypos]=distFromBtn arraypos-=1 distFromBtn+=1 if any(p == -1 for p in positions): print "parsePositions names:",names print "result:",positions raise FpdbError ("failed to read positions") # print str(positions), "\n" return positions #end def parsePositions #simply parses the rake amount and returns it as an int def parseRake(line): pos=line.find("Rake")+6 rake=float2int(line[pos:]) return rake #end def parseRake def parseSiteHandNo(topline): """returns the hand no assigned by the poker site""" pos1=topline.find("#")+1 pos2=topline.find(":") return topline[pos1:pos2] #end def parseSiteHandNo def parseTableLine(base, line): """returns a dictionary with maxSeats and tableName""" 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 def parseTourneyNo(topline): pos1=topline.find("Tournament #")+12 pos2=topline.find(",", pos1) #print "parseTourneyNo pos1:",pos1," pos2:",pos2, " result:",topline[pos1:pos2] return topline[pos1:pos2] #end def parseTourneyNo #parses a win/collect line. manipulates the passed array winnings, no explicit return def parseWinLine(line, names, winnings, isTourney): #print "parseWinLine: line:",line for i,n in enumerate(names): n = n.encode("latin-1") if line.startswith(n): if isTourney: pos1 = line.rfind("collected ") + 10 pos2 = line.find(" ", pos1) winnings[i]+=int(line[pos1:pos2]) else: pos1 = line.rfind("$") + 1 pos2 = line.find(" ", pos1) winnings[i] += float2int(line[pos1:pos2]) #end def parseWinLine #returns the category (as per database) string for the given line def recogniseCategory(line): if "Razz" in line: return "razz" elif "Hold'em" in line: return "holdem" elif "Omaha" in line: if "Hi/Lo" not in line and "H/L" not in line: return "omahahi" else: return "omahahilo" elif "Stud" in line: if "Hi/Lo" not in line and "H/L" not in line: return "studhi" else: return "studhilo" else: raise FpdbError("failed to recognise category, line:"+line) #end def recogniseCategory #returns the int for the gametype_id for the given line def recogniseGametypeID(backend, db, cursor, topline, smallBlindLine, site_id, category, isTourney):#todo: this method is messy #if (topline.find("HORSE")!=-1): # raise FpdbError("recogniseGametypeID: HORSE is not yet supported.") #note: the below variable names small_bet and big_bet are misleading, in NL/PL they mean small/big blind if isTourney: type="tour" pos1=topline.find("(")+1 if (topline[pos1]=="H" or topline[pos1]=="O" or topline[pos1]=="R" or topline[pos1]=="S" or topline[pos1+2]=="C"): pos1=topline.find("(", pos1)+1 pos2=topline.find("/", pos1) small_bet=int(topline[pos1:pos2]) else: type="ring" pos1=topline.find("$")+1 pos2=topline.find("/$") small_bet=float2int(topline[pos1:pos2]) pos1=pos2+2 if isTourney: pos1-=1 pos2=topline.find(")") if pos2<=pos1: pos2=topline.find(")", pos1) if isTourney: big_bet=int(topline[pos1:pos2]) else: big_bet=float2int(topline[pos1:pos2]) if (topline.find("No Limit")!=-1): limit_type="nl" if (topline.find("Cap No")!=-1): limit_type="cn" elif (topline.find("Pot Limit")!=-1): limit_type="pl" if (topline.find("Cap Pot")!=-1): limit_type="cp" else: limit_type="fl" #print "recogniseGametypeID small_bet/blind:",small_bet,"big bet/blind:", big_bet,"limit type:",limit_type if (limit_type=="fl"): cursor.execute ("SELECT id FROM Gametypes WHERE siteId=%s AND type=%s AND category=%s AND limitType=%s AND smallBet=%s AND bigBet=%s", (site_id, type, category, limit_type, small_bet, big_bet)) else: cursor.execute ("SELECT id FROM Gametypes WHERE siteId=%s AND type=%s AND category=%s AND limitType=%s AND smallBlind=%s AND bigBlind=%s", (site_id, type, category, limit_type, small_bet, big_bet)) result=cursor.fetchone() #print "recgt1 result=",result #ret=result[0] #print "recgt1 ret=",ret #print "tried SELECTing gametypes.id, result:",result try: len(result) except TypeError: if category=="holdem" or category=="omahahi" or category=="omahahilo": base="hold" else: base="stud" if category=="holdem" or category=="omahahi" or category=="studhi": hiLo='h' elif category=="razz": hiLo='l' else: hiLo='s' if (limit_type=="fl"): big_blind=small_bet if base=="hold": if smallBlindLine==topline: raise FpdbError("invalid small blind line") elif isTourney: pos=smallBlindLine.rfind(" ")+1 small_blind=int(smallBlindLine[pos:]) else: pos=smallBlindLine.rfind("$")+1 small_blind=float2int(smallBlindLine[pos:]) else: small_blind=0 cursor.execute( """INSERT INTO Gametypes(siteId, type, base, category, limitType ,hiLo, smallBlind, bigBlind, smallBet, bigBet) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""" , (site_id, type, base, category, limit_type, hiLo ,small_blind, big_blind, small_bet, big_bet) ) #cursor.execute ("SELECT id FROM Gametypes WHERE siteId=%s AND type=%s AND category=%s #AND limitType=%s AND smallBet=%s AND bigBet=%s", (site_id, type, category, limit_type, small_bet, big_bet)) else: cursor.execute( """INSERT INTO Gametypes(siteId, type, base, category, limitType ,hiLo, smallBlind, bigBlind, smallBet, bigBet) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""" , (site_id, type, base, category, limit_type ,hiLo, small_bet, big_bet, 0, 0))#remember, for these bet means blind #cursor.execute ("SELECT id FROM Gametypes WHERE siteId=%s AND type=%s AND category=%s #AND limitType=%s AND smallBlind=%s AND bigBlind=%s", (site_id, type, category, limit_type, small_bet, big_bet)) #result=(db.insert_id(),) result=(db.get_last_insert_id(),) return result[0] #end def recogniseGametypeID def recogniseTourneyTypeId(cursor, siteId, buyin, fee, knockout, rebuyOrAddon): cursor.execute ("SELECT id FROM TourneyTypes WHERE siteId=%s AND buyin=%s AND fee=%s AND knockout=%s AND rebuyOrAddon=%s", (siteId, buyin, fee, knockout, rebuyOrAddon)) result=cursor.fetchone() #print "tried SELECTing gametypes.id, result:",result try: len(result) except TypeError:#this means we need to create a new entry cursor.execute("""INSERT INTO TourneyTypes (siteId, buyin, fee, knockout, rebuyOrAddon) VALUES (%s, %s, %s, %s, %s)""", (siteId, buyin, fee, knockout, rebuyOrAddon)) cursor.execute("SELECT id FROM TourneyTypes WHERE siteId=%s AND buyin=%s AND fee=%s AND knockout=%s AND rebuyOrAddon=%s", (siteId, buyin, fee, knockout, rebuyOrAddon)) result=cursor.fetchone() return result[0] #end def recogniseTourneyTypeId #returns the SQL ids of the names given in an array # TODO: if someone gets industrious, they should make the parts that use the output of this function deal with a dict # { 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 = 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 # Here's a version that would work if it wasn't for the fact that it needs to have the output in the same order as input # this version could also be improved upon using list comprehensions, etc #def recognisePlayerIDs(cursor, names, site_id): # result = [] # notfound = [] # cursor.execute("SELECT name,id FROM Players WHERE name='%s'" % "' OR name='".join(names)) # tmp = dict(cursor.fetchall()) # for n in names: # if n not in tmp: # notfound.append(n) # else: # result.append(tmp[n]) # if notfound: # cursor.executemany("INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")", (notfound)) # cursor.execute("SELECT id FROM Players WHERE name='%s'" % "' OR name='".join(notfound)) # tmp = cursor.fetchall() # for n in tmp: # result.append(n[0]) # # return result #recognises the name in the given line and returns its array position in the given array def recognisePlayerNo(line, names, atype): #print "recogniseplayerno, names:",names for i in xrange(len(names)): if (atype=="unbet"): if (line.endswith(names[i].encode("latin-1"))): return (i) elif (line.startswith("Dealt to ")): #print "recognisePlayerNo, card precut, line:",line tmp=line[9:] #print "recognisePlayerNo, card postcut, tmp:",tmp if (tmp.startswith(names[i].encode("latin-1"))): return (i) elif (line.startswith("Seat ")): if (line.startswith("Seat 10")): tmp=line[9:] else: tmp=line[8:] if (tmp.startswith(names[i].encode("latin-1"))): return (i) else: if (line.startswith(names[i].encode("latin-1"))): return (i) #if we're here we mustve failed raise FpdbError ("failed to recognise player in: "+line+" atype:"+atype) #end def recognisePlayerNo #removes trailing \n from the given array def removeTrailingEOL(arr): for i in xrange(len(arr)): if (arr[i].endswith("\n")): #print "arr[i] before removetrailingEOL:", arr[i] arr[i]=arr[i][:-1] #print "arr[i] after removetrailingEOL:", arr[i] return arr #end def removeTrailingEOL #splits the rake according to the proportion of pot won. manipulates the second passed array. def splitRake(winnings, rakes, totalRake): winnercnt=0 totalWin=0 for i in xrange(len(winnings)): if winnings[i]!=0: winnercnt+=1 totalWin+=winnings[i] firstWinner=i if winnercnt==1: rakes[firstWinner]=totalRake else: totalWin=float(totalWin) for i in xrange(len(winnings)): if winnings[i]!=0: winPortion=winnings[i]/totalWin rakes[i]=totalRake*winPortion #end def splitRake def generateHudCacheData(player_ids, base, category, action_types, allIns, actionTypeByNo ,winnings, totalWinnings, positions, actionTypes, actionAmounts, antes): """calculates data for the HUD during import. IMPORTANT: if you change this method make sure to also change the following storage method and table_viewer.prepare_data if necessary """ #print "generateHudCacheData, len(player_ids)=", len(player_ids) #setup subarrays of the result dictionary. 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=[] 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 firstPfCallByNo=-1 firstPfCallerId=-1 for i, action in enumerate(actionTypeByNo[0]): if action[1] == "bet": firstPfRaiseByNo = i firstPfRaiserId = action[0] for j, pid in enumerate(player_ids): if pid == firstPfRaiserId: firstPfRaiserNo = j break break for i, action in enumerate(actionTypeByNo[0]): if action[1] == "call": firstPfCallByNo = i firstPfCallerId = action[0] break firstPlayId = firstPfCallerId if firstPfRaiseByNo <> -1: if firstPfRaiseByNo < firstPfCallByNo or firstPfCallByNo == -1: firstPlayId = firstPfRaiserId cutoffId=-1 buttonId=-1 sbId=-1 bbId=-1 if base=="hold": for player, pos in enumerate(positions): if pos == 1: cutoffId = player_ids[player] if pos == 0: buttonId = player_ids[player] if pos == 'S': sbId = player_ids[player] if pos == 'B': bbId = player_ids[player] someoneStole=False #run a loop for each player preparing the actual values that will be commited to SQL for player in xrange(len(player_ids)): #set default values myStreet0VPI=False myStreet0Aggr=False myStreet0_3BChance=False myStreet0_3BDone=False myStreet1Seen=False myStreet2Seen=False myStreet3Seen=False myStreet4Seen=False mySawShowdown=False myStreet1Aggr=False myStreet2Aggr=False myStreet3Aggr=False myStreet4Aggr=False myOtherRaisedStreet1=False myOtherRaisedStreet2=False myOtherRaisedStreet3=False myOtherRaisedStreet4=False myFoldToOtherRaisedStreet1=False myFoldToOtherRaisedStreet2=False myFoldToOtherRaisedStreet3=False myFoldToOtherRaisedStreet4=False myWonWhenSeenStreet1=0.0 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 heroPfRaiseCount=0 for currentAction in action_types[street][player]: # finally individual actions if currentAction == "bet": 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 pfRaise=-1 if firstPfRaiseByNo != -1: for i, actionType in enumerate(actionTypeByNo[0]): if actionType[0] == player_ids[player]: if actionType[1] == "bet" and pfRaise == -1 and i > firstPfRaiseByNo: pfRaise = i if actionType[1] == "fold" and pfFold == -1: pfFold = i if pfFold == -1 or pfFold > firstPfRaiseByNo: myStreet0_3BChance = True if pfRaise > firstPfRaiseByNo: myStreet0_3BDone = True #steal calculations 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] \ and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo): myStealAttempted=True 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] \ and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo): myStealAttempted=True 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] \ and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo): myStealAttempted=True myStealAttemptChance=True if firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1: myStealAttemptChance=True if positions[player]=='B': pass if myStealAttempted: someoneStole=True #calculate saw* values isAllIn = False if any(i for i in allIns[0][player]): isAllIn = True if (len(action_types[1][player])>0 or isAllIn): myStreet1Seen = True if any(i for i in allIns[1][player]): isAllIn = True if (len(action_types[2][player])>0 or isAllIn): myStreet2Seen = True if any(i for i in allIns[2][player]): isAllIn = True if (len(action_types[3][player])>0 or isAllIn): myStreet3Seen = True #print "base:", base if base=="hold": mySawShowdown = True if any(actiontype == "fold" for actiontype in action_types[3][player]): mySawShowdown = False else: #print "in else" if any(i for i in allIns[3][player]): isAllIn = True if (len(action_types[4][player])>0 or isAllIn): #print "in if" myStreet4Seen = True 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 if myStreet1Seen: 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 else: for countOther in xrange(len(action_types[street][otherPlayer])): if action_types[street][otherPlayer][countOther]=="bet": myOtherRaisedStreet1=True for countOtherFold in xrange(len(action_types[street][player])): if action_types[street][player][countOtherFold]=="fold": myFoldToOtherRaisedStreet1=True #turn stuff - copy of flop with different vars street=2 if myStreet2Seen: 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 else: for countOther in xrange(len(action_types[street][otherPlayer])): if action_types[street][otherPlayer][countOther]=="bet": myOtherRaisedStreet2=True for countOtherFold in xrange(len(action_types[street][player])): if action_types[street][player][countOtherFold]=="fold": myFoldToOtherRaisedStreet2=True #river stuff - copy of flop with different vars street=3 if myStreet3Seen: 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 else: for countOther in xrange(len(action_types[street][otherPlayer])): if action_types[street][otherPlayer][countOther]=="bet": myOtherRaisedStreet3=True for countOtherFold in xrange(len(action_types[street][player])): if action_types[street][player][countOtherFold]=="fold": myFoldToOtherRaisedStreet3=True #stud river stuff - copy of flop with different vars street=4 if myStreet4Seen: 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 else: for countOther in xrange(len(action_types[street][otherPlayer])): if action_types[street][otherPlayer][countOther]=="bet": myOtherRaisedStreet4=True for countOtherFold in xrange(len(action_types[street][player])): if action_types[street][player][countOtherFold]=="fold": myFoldToOtherRaisedStreet4=True if winnings[player] != 0: if myStreet1Seen: myWonWhenSeenStreet1 = winnings[player] / float(totalWinnings) if mySawShowdown: myWonAtSD=myWonWhenSeenStreet1 #add each value to the appropriate array street0VPI.append(myStreet0VPI) street0Aggr.append(myStreet0Aggr) street0_3BChance.append(myStreet0_3BChance) street0_3BDone.append(myStreet0_3BDone) street1Seen.append(myStreet1Seen) street2Seen.append(myStreet2Seen) street3Seen.append(myStreet3Seen) street4Seen.append(myStreet4Seen) sawShowdown.append(mySawShowdown) street1Aggr.append(myStreet1Aggr) street2Aggr.append(myStreet2Aggr) street3Aggr.append(myStreet3Aggr) street4Aggr.append(myStreet4Aggr) otherRaisedStreet1.append(myOtherRaisedStreet1) otherRaisedStreet2.append(myOtherRaisedStreet2) otherRaisedStreet3.append(myOtherRaisedStreet3) otherRaisedStreet4.append(myOtherRaisedStreet4) foldToOtherRaisedStreet1.append(myFoldToOtherRaisedStreet1) foldToOtherRaisedStreet2.append(myFoldToOtherRaisedStreet2) foldToOtherRaisedStreet3.append(myFoldToOtherRaisedStreet3) foldToOtherRaisedStreet4.append(myFoldToOtherRaisedStreet4) wonWhenSeenStreet1.append(myWonWhenSeenStreet1) wonAtSD.append(myWonAtSD) stealAttemptChance.append(myStealAttemptChance) stealAttempted.append(myStealAttempted) if base=="hold": pos=positions[player] if pos=='B': hudDataPositions.append('B') elif pos=='S': hudDataPositions.append('S') elif pos==0: hudDataPositions.append('D') elif pos==1: hudDataPositions.append('C') elif pos>=2 and pos<=4: hudDataPositions.append('M') elif pos>=5 and pos<=8: hudDataPositions.append('E') ### RHH Added this elif to handle being a dead hand before the BB (pos==9) elif pos==9: hudDataPositions.append('X') else: raise FpdbError("invalid position") 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['street0Aggr']=street0Aggr result['street0_3BChance']=street0_3BChance result['street0_3BDone']=street0_3BDone result['street1Seen']=street1Seen result['street2Seen']=street2Seen result['street3Seen']=street3Seen result['street4Seen']=street4Seen result['sawShowdown']=sawShowdown result['street1Aggr']=street1Aggr result['otherRaisedStreet1']=otherRaisedStreet1 result['foldToOtherRaisedStreet1']=foldToOtherRaisedStreet1 result['street2Aggr']=street2Aggr result['otherRaisedStreet2']=otherRaisedStreet2 result['foldToOtherRaisedStreet2']=foldToOtherRaisedStreet2 result['street3Aggr']=street3Aggr result['otherRaisedStreet3']=otherRaisedStreet3 result['foldToOtherRaisedStreet3']=foldToOtherRaisedStreet3 result['street4Aggr']=street4Aggr result['otherRaisedStreet4']=otherRaisedStreet4 result['foldToOtherRaisedStreet4']=foldToOtherRaisedStreet4 result['wonWhenSeenStreet1']=wonWhenSeenStreet1 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=[] foldedBbToSteal=[] foldSbToStealChance=[] foldedSbToSteal=[] for player in xrange(len(player_ids)): myFoldBbToStealChance=False myFoldedBbToSteal=False myFoldSbToStealChance=False myFoldedSbToSteal=False if base=="hold": if someoneStole and (positions[player]=='B' or positions[player]=='S') and firstPfRaiserId!=player_ids[player]: street=0 for count in xrange(len(action_types[street][player])):#individual actions if positions[player]=='B': myFoldBbToStealChance=True if action_types[street][player][count]=="fold": myFoldedBbToSteal=True if positions[player]=='S': myFoldSbToStealChance=True if action_types[street][player][count]=="fold": myFoldedSbToSteal=True foldBbToStealChance.append(myFoldBbToStealChance) foldedBbToSteal.append(myFoldedBbToSteal) foldSbToStealChance.append(myFoldSbToStealChance) foldedSbToSteal.append(myFoldedSbToSteal) result['foldBbToStealChance']=foldBbToStealChance result['foldedBbToSteal']=foldedBbToSteal result['foldSbToStealChance']=foldSbToStealChance result['foldedSbToSteal']=foldedSbToSteal #now CB street1CBChance=[] street1CBDone=[] didStreet1CB=[] for player in xrange(len(player_ids)): myStreet1CBChance=False myStreet1CBDone=False if street0VPI[player]: myStreet1CBChance=True if street1Aggr[player]: myStreet1CBDone=True didStreet1CB.append(player_ids[player]) street1CBChance.append(myStreet1CBChance) street1CBDone.append(myStreet1CBDone) result['street1CBChance']=street1CBChance result['street1CBDone']=street1CBDone #now 2B street2CBChance=[] street2CBDone=[] didStreet2CB=[] for player in xrange(len(player_ids)): myStreet2CBChance=False myStreet2CBDone=False if street1CBDone[player]: myStreet2CBChance=True if street2Aggr[player]: myStreet2CBDone=True didStreet2CB.append(player_ids[player]) street2CBChance.append(myStreet2CBChance) street2CBDone.append(myStreet2CBDone) result['street2CBChance']=street2CBChance result['street2CBDone']=street2CBDone #now 3B street3CBChance=[] street3CBDone=[] didStreet3CB=[] for player in xrange(len(player_ids)): myStreet3CBChance=False myStreet3CBDone=False if street2CBDone[player]: myStreet3CBChance=True if street3Aggr[player]: myStreet3CBDone=True didStreet3CB.append(player_ids[player]) street3CBChance.append(myStreet3CBChance) street3CBDone.append(myStreet3CBDone) result['street3CBChance']=street3CBChance result['street3CBDone']=street3CBDone #and 4B street4CBChance=[] street4CBDone=[] didStreet4CB=[] for player in xrange(len(player_ids)): myStreet4CBChance=False myStreet4CBDone=False if street3CBDone[player]: myStreet4CBChance=True if street4Aggr[player]: myStreet4CBDone=True didStreet4CB.append(player_ids[player]) street4CBChance.append(myStreet4CBChance) street4CBDone.append(myStreet4CBDone) result['street4CBChance']=street4CBChance result['street4CBDone']=street4CBDone result['position']=hudDataPositions foldToStreet1CBChance=[] foldToStreet1CBDone=[] foldToStreet2CBChance=[] foldToStreet2CBDone=[] foldToStreet3CBChance=[] foldToStreet3CBDone=[] foldToStreet4CBChance=[] foldToStreet4CBDone=[] for player in xrange(len(player_ids)): myFoldToStreet1CBChance=False myFoldToStreet1CBDone=False foldToStreet1CBChance.append(myFoldToStreet1CBChance) foldToStreet1CBDone.append(myFoldToStreet1CBDone) myFoldToStreet2CBChance=False myFoldToStreet2CBDone=False foldToStreet2CBChance.append(myFoldToStreet2CBChance) foldToStreet2CBDone.append(myFoldToStreet2CBDone) myFoldToStreet3CBChance=False myFoldToStreet3CBDone=False foldToStreet3CBChance.append(myFoldToStreet3CBChance) foldToStreet3CBDone.append(myFoldToStreet3CBDone) myFoldToStreet4CBChance=False myFoldToStreet4CBDone=False foldToStreet4CBChance.append(myFoldToStreet4CBChance) foldToStreet4CBDone.append(myFoldToStreet4CBDone) if len(didStreet1CB)>=1: generateFoldToCB(1, player_ids, didStreet1CB, street1CBDone, foldToStreet1CBChance, foldToStreet1CBDone, actionTypeByNo) if len(didStreet2CB)>=1: generateFoldToCB(2, player_ids, didStreet2CB, street2CBDone, foldToStreet2CBChance, foldToStreet2CBDone, actionTypeByNo) if len(didStreet3CB)>=1: generateFoldToCB(3, player_ids, didStreet3CB, street3CBDone, foldToStreet3CBChance, foldToStreet3CBDone, actionTypeByNo) if len(didStreet4CB)>=1: generateFoldToCB(4, player_ids, didStreet4CB, street4CBDone, foldToStreet4CBChance, foldToStreet4CBDone, actionTypeByNo) result['foldToStreet1CBChance']=foldToStreet1CBChance result['foldToStreet1CBDone']=foldToStreet1CBDone result['foldToStreet2CBChance']=foldToStreet2CBChance result['foldToStreet2CBDone']=foldToStreet2CBDone result['foldToStreet3CBChance']=foldToStreet3CBChance result['foldToStreet3CBDone']=foldToStreet3CBDone result['foldToStreet4CBChance']=foldToStreet4CBChance result['foldToStreet4CBDone']=foldToStreet4CBDone totalProfit=[] street1CheckCallRaiseChance=[] street1CheckCallRaiseDone=[] street2CheckCallRaiseChance=[] street2CheckCallRaiseDone=[] street3CheckCallRaiseChance=[] street3CheckCallRaiseDone=[] street4CheckCallRaiseChance=[] street4CheckCallRaiseDone=[] #print "b4 totprof calc, len(playerIds)=", len(player_ids) for pl in xrange(len(player_ids)): #print "pl=", pl myTotalProfit=winnings[pl] # still need to deduct other costs if antes: myTotalProfit=winnings[pl] - antes[pl] for i in xrange(len(actionTypes)): #iterate through streets #for j in xrange(len(actionTypes[i])): #iterate through names (using pl loop above) for k in xrange(len(actionTypes[i][pl])): #iterate through individual actions of that player on that street myTotalProfit -= actionAmounts[i][pl][k] myStreet1CheckCallRaiseChance=False myStreet1CheckCallRaiseDone=False myStreet2CheckCallRaiseChance=False myStreet2CheckCallRaiseDone=False myStreet3CheckCallRaiseChance=False myStreet3CheckCallRaiseDone=False myStreet4CheckCallRaiseChance=False myStreet4CheckCallRaiseDone=False #print "myTotalProfit=", myTotalProfit totalProfit.append(myTotalProfit) #print "totalProfit[]=", totalProfit street1CheckCallRaiseChance.append(myStreet1CheckCallRaiseChance) street1CheckCallRaiseDone.append(myStreet1CheckCallRaiseDone) street2CheckCallRaiseChance.append(myStreet2CheckCallRaiseChance) street2CheckCallRaiseDone.append(myStreet2CheckCallRaiseDone) street3CheckCallRaiseChance.append(myStreet3CheckCallRaiseChance) street3CheckCallRaiseDone.append(myStreet3CheckCallRaiseDone) street4CheckCallRaiseChance.append(myStreet4CheckCallRaiseChance) street4CheckCallRaiseDone.append(myStreet4CheckCallRaiseDone) result['totalProfit']=totalProfit #print "res[totalProfit]=", result['totalProfit'] result['street1CheckCallRaiseChance']=street1CheckCallRaiseChance result['street1CheckCallRaiseDone']=street1CheckCallRaiseDone result['street2CheckCallRaiseChance']=street2CheckCallRaiseChance result['street2CheckCallRaiseDone']=street2CheckCallRaiseDone result['street3CheckCallRaiseChance']=street3CheckCallRaiseChance result['street3CheckCallRaiseDone']=street3CheckCallRaiseDone result['street4CheckCallRaiseChance']=street4CheckCallRaiseChance result['street4CheckCallRaiseDone']=street4CheckCallRaiseDone return result #end def generateHudCacheData def generateFoldToCB(street, playerIDs, didStreetCB, streetCBDone, foldToStreetCBChance, foldToStreetCBDone, actionTypeByNo): """fills the passed foldToStreetCB* arrays appropriately depending on the given street""" #print "beginning of generateFoldToCB, street:", street, "len(actionTypeByNo):", len(actionTypeByNo) #print "len(actionTypeByNo[street]):",len(actionTypeByNo[street]) firstCBReaction=0 for action in xrange(len(actionTypeByNo[street])): if actionTypeByNo[street][action][1]=="bet": for player in didStreetCB: if player==actionTypeByNo[street][action][0] and firstCBReaction==0: firstCBReaction=action+1 break for action in actionTypeByNo[street][firstCBReaction:]: for player in xrange(len(playerIDs)): if playerIDs[player]==action[0]: foldToStreetCBChance[player]=True if action[1]=="fold": foldToStreetCBDone[player]=True #end def generateFoldToCB