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
Example #2
0
    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