def mainParser(settings, siteID, category, hand, config, db = None, writeq = None): """ mainParser for Holdem Hands """ t0 = time() backend = settings['db-backend'] # Ideally db connection is passed in, if not use sql list if passed in, # otherwise start from scratch if db is None: db = Database.Database(c = config, sql = None) category = fpdb_simple.recogniseCategory(hand[0]) base = "hold" if (category == "holdem" or category == "omahahi" or category == "omahahilo") else "stud" #part 0: create the empty arrays # lineTypes valid values: header, name, cards, action, win, rake, ignore # lineStreets valid values: predeal, preflop, flop, turn, river lineTypes = [] lineStreets = [] cardValues = [] cardSuits = [] boardValues = [] boardSuits = [] antes = [] allIns = [] actionAmounts = [] actionNos = [] actionTypes = [] actionTypeByNo = [] seatLines = [] winnings = [] rakes = [] #part 1: read hand no and check for duplicate siteHandNo = fpdb_simple.parseSiteHandNo(hand[0]) handStartTime = fpdb_simple.parseHandStartTime(hand[0]) isTourney = fpdb_simple.isTourney(hand[0]) smallBlindLine = None for i, line in enumerate(hand): if 'posts small blind' in line or 'posts the small blind' in line: if line[-2:] == "$0": continue smallBlindLine = i break else: smallBlindLine = 0 # If we did not find a small blind line, what happens? # if we leave it at None, it errors two lines down. gametypeID = fpdb_simple.recogniseGametypeID(backend, db, db.get_cursor(), hand[0], hand[smallBlindLine], siteID, category, isTourney) if isTourney: siteTourneyNo = fpdb_simple.parseTourneyNo(hand[0]) buyin = fpdb_simple.parseBuyin(hand[0]) fee = fpdb_simple.parseFee(hand[0]) entries = -1 #todo: parse this prizepool = -1 #todo: parse this knockout = False tourneyStartTime= handStartTime #todo: read tourney start time rebuyOrAddon = fpdb_simple.isRebuyOrAddon(hand[0]) # The tourney site id has to be searched because it may already be in # db with a TourneyTypeId which is different from the one automatically # calculated (Summary import first) tourneyTypeId = fpdb_simple.recogniseTourneyTypeId(db, siteID, siteTourneyNo, buyin, fee, knockout, rebuyOrAddon) else: siteTourneyNo = -1 buyin = -1 fee = -1 entries = -1 prizepool = -1 knockout = 0 tourneyStartTime= None rebuyOrAddon = -1 tourneyTypeId = 1 fpdb_simple.isAlreadyInDB(db, gametypeID, siteHandNo) 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) #part 3: read basic player info #3a read player names, startcashes for i, line in enumerate(hand): if lineTypes[i] == "name": seatLines.append(line) names = fpdb_simple.parseNames(seatLines) playerIDs = db.recognisePlayerIDs(names, siteID) # inserts players as needed tmp = fpdb_simple.parseCashesAndSeatNos(seatLines) startCashes = tmp['startCashes'] seatNos = tmp['seatNos'] fpdb_simple.createArrays(category, len(names), cardValues, cardSuits, antes, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo) #3b read positions if base == "hold": positions = fpdb_simple.parsePositions(hand, names) #part 4: take appropriate action for each line based on linetype for i, line in enumerate(hand): if lineTypes[i] == "cards": fpdb_simple.parseCardLine(category, lineStreets[i], line, 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(base, isTourney, line, lineStreets[i], playerIDs, names, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo) elif lineTypes[i] == "win": fpdb_simple.parseWinLine(line, names, winnings, isTourney) elif lineTypes[i] == "rake": totalRake = 0 if isTourney else fpdb_simple.parseRake(line) fpdb_simple.splitRake(winnings, rakes, totalRake) elif (lineTypes[i] == "header" or lineTypes[i] == "rake" or lineTypes[i] == "name" or lineTypes[i] == "ignore"): pass elif lineTypes[i] == "ante": fpdb_simple.parseAnteLine(line, isTourney, names, antes) elif lineTypes[i] == "table": tableResult=fpdb_simple.parseTableLine(base, line) else: raise FpdbError("unrecognised lineType:" + lineTypes[i]) maxSeats = tableResult['maxSeats'] tableName = tableResult['tableName'] #print "before part5, antes:", antes #part 5: final preparations, then call Database.* with # the arrays as they are - that file will fill them. fpdb_simple.convertCardValues(cardValues) if base == "hold": fpdb_simple.convertCardValuesBoard(boardValues) fpdb_simple.convertBlindBet(actionTypes, actionAmounts) fpdb_simple.checkPositions(positions) c = db.get_cursor() c.execute("SELECT limitType FROM Gametypes WHERE id=%s" % (db.sql.query['placeholder'],), (gametypeID, )) limit_type = c.fetchone()[0] fpdb_simple.convert3B4B(category, limit_type, actionTypes, actionAmounts) totalWinnings = sum(winnings) # if hold'em, use positions and not antes, if stud do not use positions, use antes # this is used for handsplayers inserts, so still needed even if hudcache update is being skipped if base == "hold": hudImportData = fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes, allIns, actionTypeByNo, winnings, totalWinnings, positions, actionTypes, actionAmounts, None) else: hudImportData = fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes, allIns, actionTypeByNo, winnings, totalWinnings, None, actionTypes, actionAmounts, antes) try: db.commit() # need to commit new players as different db connection used # for other writes. maybe this will change maybe not ... except: # TODO: this really needs to be narrowed down print "parse: error during commit: " + str(sys.exc_value) # HERE's an ugly kludge to keep from failing when positions is undef # We'll fix this by getting rid of the legacy importer. REB try: if positions: pass except NameError: positions = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] # save data structures in a HandToWrite instance and then insert into database: htw = Database.HandToWrite() htw.set_all( config, settings, base, category, siteTourneyNo, buyin , fee, knockout, entries, prizepool, tourneyStartTime , isTourney, tourneyTypeId, siteID, siteHandNo , gametypeID, handStartTime, names, playerIDs, startCashes , positions, antes, cardValues, cardSuits, boardValues, boardSuits , winnings, rakes, actionTypes, allIns, actionAmounts , actionNos, hudImportData, maxSeats, tableName, seatNos) # save hand in db via direct call or via q if in a thread if writeq is None: result = db.store_the_hand(htw) else: writeq.put(htw) result = -999 # meaning unknown t9 = time() #print "parse and save=(%4.3f)" % (t9-t0) return result
def import_fpdb_lines(self, db, lines, starttime, file, site, q = None): """Import an fpdb hand history held in the list lines, could be one hand or many""" #db.lock_for_insert() # should be ok when using one thread, but doesn't help?? while gtk.events_pending(): gtk.main_iteration(False) try: # sometimes we seem to be getting an empty self.lines, in which case, we just want to return. firstline = lines[0] except: # just skip the debug message and return silently: #print "DEBUG: import_fpdb_file: failed on lines[0]: '%s' '%s' '%s' '%s' " %( file, site, lines, loc) return (0,0,0,1,0,0) if "Tournament Summary" in firstline: print "TODO: implement importing tournament summaries" #self.faobs = readfile(inputFile) #self.parseTourneyHistory() return (0,0,0,1,0,0) category = fpdb_simple.recogniseCategory(firstline) startpos = 0 stored = 0 #counter duplicates = 0 #counter partial = 0 #counter errors = 0 #counter ttime = 0 handsId = 0 for i in xrange(len(lines)): if len(lines[i]) < 2: #Wierd way to detect for '\r\n' or '\n' endpos = i hand = lines[startpos:endpos] if len(hand[0]) < 2: hand=hand[1:] 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: hand = fpdb_simple.filterAnteBlindFold(hand) self.hand = hand try: handsId = fpdb_parse_logic.mainParser( self.settings, self.siteIds[site] , category, hand, self.config , db, q ) db.commit() stored += 1 if self.callHud: #print "call to HUD here. handsId:",handsId #pipe the Hands.id out to the HUD # print "fpdb_import: sending hand to hud", handsId, "pipe =", self.caller.pipe_to_hud try: self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep) except IOError: # hud closed self.callHud = False pass # continue import without hud except Exceptions.DuplicateError: duplicates += 1 db.rollback() except (ValueError), fe: errors += 1 self.printEmailErrorMessage(errors, file, hand) if (self.settings['failOnError']): db.commit() #dont remove this, in case hand processing was cancelled. raise else: db.rollback() except (fpdb_simple.FpdbError), fe: errors += 1 self.printEmailErrorMessage(errors, file, hand) db.rollback() if self.settings['failOnError']: db.commit() #dont remove this, in case hand processing was cancelled. raise if self.settings['minPrint']: if not ((stored+duplicates+errors) % self.settings['minPrint']): print "stored:", stored, " duplicates:", duplicates, "errors:", errors if self.settings['handCount']: 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