Example #1
0
    def addPlay(self,
                gameID,
                driveNo,
                prevPlayNo,
                prevPlay,
                possData,
                debug=False):
        debug = True
        text = None
        if gameID == "401012282":
            if driveNo == 8 and prevPlayNo == 11:
                text = "Tyrel Dodson 78 Yd Return of Blocked Field Goal (Seth Small Kick)"
                print(prevPlay)

        if text is not None:
            ptype = playtype(text)
            play = ptype.getPlay()
            play.analyze(debug=debug)
            playPossession = possData.determinePossession(play, debug=debug)
            playStart = prevPlay.start
            playResult = playsummary(possession=playPossession,
                                     start=playStart,
                                     play=play,
                                     valid=True)
            if debug:
                print(
                    "Adding play [{0}] for team [{1}] with text [{2}]".format(
                        play.name, playPossession.start, text))
            return playResult

        return None
Example #2
0
    def splitKickoff(self, gameData):
        fname = sys._getframe().f_code.co_name
        self.logger.debug("\n{0}{1}()".format(self.ind, fname))

        changes = []

        for idr in range(len(gameData)):
            drivePlays = gameData[idr].plays
            for dp in range(len(drivePlays)):
                playData = drivePlays[dp]
                if playData.valid is not True:
                    continue
                if isinstance(playData.play, kickoffplay):
                    self.logger.debug("{0}  Kickoff Play: {1}".format(
                        self.ind, playData.play.text))
                    newReturnPlay = returnplay(text=playData.play.text)
                    newReturnPlay.pa.kickoffplay = False
                    newReturnPlay.pa.touchdown = playData.play.pa.touchdown
                    newReturnPlay.pa.fumble = playData.play.pa.fumble
                    newReturnPlay.pa.runback = playData.play.pa.runback
                    playData.play.pa.touchdown = False
                    playData.play.pa.fumble = False
                    playData.play.pa.runback = False

                    newPossession = playpossession(start=None,
                                                   end=None,
                                                   text=playData.play.text)
                    if playData.play.pa.getKey(
                            "forced"
                    ) is not None and not playData.possession.isKnownStart():
                        self.logger.debug(
                            "{0}  Using previous kickoff data to set possession to {1}"
                            .format(playData.play.pa.forced))
                        newPossession.start = playData.play.pa.forced
                        playData.play.pa.forced = False
                        playData.possession.start = self.flipPossession(
                            newPossession.start)
                    else:
                        newPossession.start = self.flipPossession(
                            playData.possession)
                    newPlayData = playsummary(possession=newPossession,
                                              start=playData.start.copy(),
                                              play=newReturnPlay,
                                              valid=playData.valid)
                    drivePlays.insert(dp + 1, newPlayData)

                    newReturnPlay.connectedPlays.append(playData)
                    playData.play.connectedPlays.append(newReturnPlay)

                    changes.append(idr)
                    break

        self.logger.debug("{0}Found {1} Drives With Splits in {2}()".format(
            self.ind, len(changes), fname))
        for idr in set(changes):
            self.dc.showDrive(gameData[idr], idr, "Drive {0}".format(idr))

        return gameData
Example #3
0
    def splitInterception(self, gameData):
        fname = sys._getframe().f_code.co_name
        self.logger.debug("\n{0}{1}()".format(self.ind, fname))

        changes = []

        mixposs = mixedpossession()
        for idr in range(len(gameData)):
            drivePlays = gameData[idr].plays
            for dp in range(len(drivePlays)):
                playData = drivePlays[dp]
                if playData.valid is not True:
                    continue
                if isinstance(playData.play, passingplay
                              ) and playData.play.pa.getKey("interception"):
                    self.logger.debug("{0}  Interception Play: {1}".format(
                        self.ind, playData.play.text))

                    newReturnPlay = returnplay(text=playData.play.text)
                    newReturnPlay.pa.passingplay = False
                    newReturnPlay.pa.touchdown = playData.play.pa.touchdown
                    newReturnPlay.pa.fumble = playData.play.pa.fumble
                    newReturnPlay.pa.runback = playData.play.pa.runback
                    newReturnPlay.pa.interception = False
                    playData.play.pa.touchdown = False
                    playData.play.pa.fumble = False
                    playData.play.pa.runback = False

                    playData = mixposs.determineInterception(
                        playData, drivePlays, dp)
                    newPossession = playpossession(start=None,
                                                   end=None,
                                                   text=playData.play.text)
                    try:
                        newPossession.start = self.copMap[
                            playData.possession.start]
                    except:
                        newPossession.start = playData.possession.setUnknownStart(
                        )
                    newPlayData = playsummary(possession=newPossession,
                                              start=playData.start.copy(),
                                              play=newReturnPlay,
                                              valid=playData.valid)
                    drivePlays.insert(dp + 1, newPlayData)

                    newReturnPlay.connectedPlays.append(playData)
                    playData.play.connectedPlays.append(newReturnPlay)

                    changes.append(idr)
                    break

        self.logger.debug("{0}Found {1} Drives With Splits in {2}()".format(
            self.ind, len(changes), fname))
        for idr in set(changes):
            self.dc.showDrive(gameData[idr], idr, "Drive {0}".format(idr))

        return gameData
Example #4
0
    def returns(self, gameData):
        self.logger.debug("\n{0}".format(2*self.sep))
        self.logger.debug("{0}Analyzing Kickoff Returns".format(self.ind))
        
        for idr,driveData in enumerate(gameData):
            drivePlays = driveData.plays
            
            retval = self.getKickoffPlays(drivePlays)
            if retval is None:
                continue
            try:
                kickplay, retplay, genplay = retval
            except:
                raise ValueError("Could not parse return value: {0}".format(retval))
                
            self.dc.showDrive(driveData, idr)
                
            ### Get starting place
            startingLine = kickplay.start.distToEndZone
            kickingYards = kickplay.play.yds.yards
            
            self.logger.debug("{0}  Starting/Kicking -> {1} {2}".format(self.ind, startingLine, kickingYards))
            
            ### Set starting line
            returnStart = startingLine - kickingYards
            if returnStart < 65:
                retplay.start.side   = retplay.possession.start
                retplay.start.startY = returnStart
            else:
                raise ValueError("Not sure what to do about this kickoff!!!")
            
            if kickplay.play.pa.getKey("outofbounds") is True:
                retplay.play.yds.yards = None
                oobplay = self.pt.getPlay("No Play")
                oobplay.text = "Penalty: Kickoff Out of Bounds"
                oobplay.penalty = penalty(oobplay.text)
                oobposs = playpossession(start=kickplay.possession.start, end=None, text=oobplay.text)
                oobstart = kickplay.start.copy()
                oobstart.startY = 35
                playResult = playsummary(possession=oobposs, start=oobstart, play=oobplay, valid=True)
                playResult.start.setYards(playResult.possession.start)                
                drivePlays.insert(1, playResult)
                
                                
                noretplay = self.pt.getPlay("")
                noretplay.text = "Post Penalty: Starting at 35 yard line"
                noretplay.yds.yards = 0
                noretposs = playpossession(start=retplay.possession.start, end=None, text=noretplay.text)
                noretstart = retplay.start.copy()
                noretstart.startY = 35
                playResult = playsummary(possession=noretposs, start=noretstart, play=noretplay, valid=True)
                playResult.start.setYards(playResult.possession.start)

                drivePlays.pop(2) ## get rid of old return play
                drivePlays.insert(2, playResult) ## insert new return play of zero yards

                        
            self.dc.showDrive(driveData, idr)
            
        self.logger.debug("{0}Analyzing Kickoff Returns -> Done".format(self.ind))
        return gameData
Example #5
0
    def splitTouchdown(self, gameData):
        fname = sys._getframe().f_code.co_name
        self.logger.debug("\n{0}{1}()".format(self.ind, fname))

        changes = []

        mixposs = mixedpossession()
        for idr in range(len(gameData)):
            drivePlays = gameData[idr].plays
            for dp in range(len(drivePlays)):
                playData = drivePlays[dp]
                if playData.valid is not True:
                    continue
                if playData.play.pa.getKey("touchdown") is True:

                    playData = mixposs.determineTouchdown(playData,
                                                          drivePlays,
                                                          dp,
                                                          debug=False)
                    if sum([isinstance(x.play, patplay)
                            for x in drivePlays]) > 0:
                        break
                    playData.play.pa.addPAT()
                    if playData.play.pa.getKey("addpat") is True:
                        self.logger.debug("{0}  Touchdown Play: {1}".format(
                            self.ind, playData.play.text))
                        playData.play.pa.addpat = False

                        ## Split Depends on Offense vs Defense PAT
                        if playData.play.pa.getKey("defpat"):
                            newPATPlay = patplay(text=playData.play.text)
                            newPATPlay.pa.touchdown = False
                            newPATPlay.pa.runback = playData.play.pa.runback
                            playData.play.pa.runback = False

                            newPossession = playpossession(
                                start=None, end=None, text=playData.play.text)
                            try:
                                newPossession.start = self.copMap[
                                    playData.possession.start]
                            except:
                                newPossession.start = playData.possession.setUnknownStart(
                                )

                            self.logger.debug(
                                "{0}This is a DEF PAT with POSS = {1}".format(
                                    self.ind, newPossession.start))
                            newPlayData = playsummary(
                                possession=newPossession,
                                start=playData.start.copy(),
                                play=newPATPlay,
                                valid=playData.valid)

                            newPATPlay.connectedPlays.append(playData)
                            playData.play.connectedPlays.append(newPATPlay)

                            drivePlays.insert(dp + 1, newPlayData)
                            changes.append(idr)
                        else:
                            newPATPlay = patplay(text=playData.play.text)
                            newPATPlay.pa.touchdown = False
                            newPATPlay.pa.runback = playData.play.pa.runback
                            playData.play.pa.runback = False

                            newPossession = playpossession(
                                start=None, end=None, text=playData.play.text)
                            newPossession.start = playData.possession.start

                            self.logger.debug(
                                "{0}This is a REGULAR PAT with POSS = {1}".
                                format(self.ind, newPossession.start))
                            newPlayData = playsummary(
                                possession=playData.possession,
                                start=playData.start.copy(),
                                play=newPATPlay,
                                valid=playData.valid)
                            drivePlays.insert(dp + 1, newPlayData)

                            newPATPlay.connectedPlays.append(playData)
                            playData.play.connectedPlays.append(newPATPlay)

                            changes.append(idr)
                        break

        self.logger.debug("{0}Found {1} Drives With Splits in {2}()".format(
            self.ind, len(changes), fname))
        for idr in set(changes):
            self.dc.showDrive(gameData[idr], idr, "Drive {0}".format(idr))

        return gameData
Example #6
0
    def splitFumble(self, gameData):
        fname = sys._getframe().f_code.co_name
        self.logger.debug("\n{0}{1}()".format(self.ind, fname))

        changes = []

        mixposs = mixedpossession()
        for idr in range(len(gameData)):
            drivePlays = gameData[idr].plays
            for dp in range(len(drivePlays)):
                playData = drivePlays[dp]
                if playData.valid is not True:
                    continue
                if playData.play.pa.getKey("fumble") is True:
                    self.logger.debug("{0}  Fumble Play: {1}".format(
                        self.ind, playData.play.text))

                    lostFumble = True
                    try:
                        if playData.possession.start == drivePlays[
                                dp + 1].possession.start and drivePlays[
                                    dp + 1].valid is True:
                            lostFumble = False
                    except:
                        lostFumble = True

                    newReturnPlay = returnplay(text=playData.play.text)
                    newReturnPlay.pa.touchdown = playData.play.pa.touchdown
                    newReturnPlay.pa.fumble = False
                    newReturnPlay.pa.runback = playData.play.pa.runback
                    playData.play.pa.touchdown = False
                    playData.play.pa.runback = False
                    playData.play.pa.fumblereturn = False

                    playData = mixposs.determineFumble(playData,
                                                       drivePlays,
                                                       dp,
                                                       debug=False)
                    newPossession = playpossession(start=None,
                                                   end=None,
                                                   text=playData.play.text)

                    if playData.play.pa.getKey("forced") is not None:
                        self.logger.debug(
                            "{0}Using previous fumble data to set possession to {1}"
                            .format(self.ind, playData.play.pa.forced))
                        newPossession.start = playData.play.pa.forced
                        try:
                            playData.possession.start = self.copMap[
                                playData.possession.start]
                        except:
                            playData.possession.setPreviousStart()

                        playData.play.pa.forced = False
                    else:
                        self.logger.debug(
                            "{0}Result of a lost fumble is {1}".format(
                                self.ind, lostFumble))

                        if lostFumble:
                            try:
                                newPossession.start = self.copMap[
                                    playData.possession.start]
                            except:
                                newPossession.setPreviousStart()
                        else:
                            newPossession.start = playData.possession.start

                    self.logger.debug("{0}Fumble Old possession is {1}".format(
                        self.ind, playData.possession.start))
                    self.logger.debug("{0}Fumble New possession is {1}".format(
                        self.ind, newPossession.start))

                    changes.append(idr)
                    gameData[idr].plays[dp] = playData
                    if lostFumble:
                        newPlayData = playsummary(possession=newPossession,
                                                  start=playData.start.copy(),
                                                  play=newReturnPlay,
                                                  valid=playData.valid)

                        newReturnPlay.connectedPlays.append(playData)
                        playData.play.connectedPlays.append(newReturnPlay)

                        drivePlays.insert(dp + 1, newPlayData)
                        break

        self.logger.debug("{0}Found {1} Drives With Splits in {2}()".format(
            self.ind, len(changes), fname))
        for idr in set(changes):
            self.dc.showDrive(gameData[idr], idr, "Drive {0}".format(idr))

        return gameData
Example #7
0
    def splitPunt(self, gameData):
        fname = sys._getframe().f_code.co_name
        self.logger.debug("\n{0}{1}()".format(self.ind, fname))

        changes = []

        mixposs = mixedpossession()
        for idr in range(len(gameData)):
            drivePlays = gameData[idr].plays
            for dp in range(len(drivePlays)):
                playData = drivePlays[dp]
                if playData.valid is not True:
                    continue
                if isinstance(playData.play, puntplay):
                    ## Ignore if there is a safety
                    if playData.play.pa.getKey("safety") is True:
                        continue

                    self.logger.debug("{0}  Punt Play: {1}".format(
                        self.ind, playData.play.text))
                    newReturnPlay = returnplay(text=playData.play.text)
                    newReturnPlay.pa.puntplay = False
                    newReturnPlay.pa.touchdown = playData.play.pa.touchdown
                    newReturnPlay.pa.fumble = playData.play.pa.fumble
                    newReturnPlay.pa.runback = playData.play.pa.runback
                    playData.play.pa.touchdown = False
                    playData.play.pa.fumble = False
                    playData.play.pa.runback = False

                    playData = mixposs.determinePunt(playData,
                                                     drivePlays,
                                                     dp,
                                                     debug=False)
                    newPossession = playpossession(start=None,
                                                   end=None,
                                                   text=playData.play.text)
                    newPossession.start = self.flipPossession(
                        playData.possession)
                    try:
                        newPossession.start = self.copMap[
                            playData.possession.start]
                    except:
                        newPossession.start = playData.possession.setUnknownStart(
                        )
                    newPlayData = playsummary(possession=newPossession,
                                              start=playData.start.copy(),
                                              play=newReturnPlay,
                                              valid=playData.valid)
                    drivePlays.insert(dp + 1, newPlayData)

                    newReturnPlay.connectedPlays.append(playData)
                    playData.play.connectedPlays.append(newReturnPlay)

                    changes.append(idr)

                    ## Check if the first play of the next drive is unknown
                    try:
                        if not gameData[idr +
                                        1].plays[0].possession.isKnownStart():
                            gameData[idr + 1].plays[
                                0].possession.start = newPossession.start
                    except:
                        pass
                    break

        self.logger.debug("{0}Found {1} Drives With Splits in {2}()".format(
            self.ind, len(changes), fname))
        for idr in set(changes):
            self.dc.showDrive(gameData[idr], idr, "Drive {0}".format(idr))

        return gameData
Example #8
0
    def parseGames(self,
                   gameID=None,
                   test=False,
                   debug=False,
                   verydebug=False):
        self.logger.info("Parsing Games")

        if self.hist is None:
            raise ValueError("Must set historical class!")

        sep = "======================================================"

        if verydebug:
            debug = True

        self.unknownPlays = []

        self.toughParsing = ['400547724']
        self.poorlyParsed = [
            '401012731', '400547781', '400547808', '400548070', '400548428',
            '400610207', '400547822'
        ]
        self.poorlyParsed += [
            '400547970', '400547835', '400548026', '400548167', '400547827',
            '400548458'
        ]
        self.poorlyParsed += [
            '400547901', '400547976', '400548246', '400548278', '400548292',
            '400548448'
        ]

        self.statsToGet = {}
        self.badGames = {}
        self.goodGames = {}

        dc = debugclass()

        files = self.hist.getGamesResultsFiles()
        for ifile in files:
            try:
                year = int(getBaseFilename(ifile).split("-")[0])
            except:
                raise ValueError("Could not get year from {0}".format(ifile))

            if year != 2018:
                continue

            self.logger.info(" Parsing Games from {0}".format(year))

            yearData = getFile(ifile)
            seasonData = self.hist.getSeasonResultsData(year)
            statsData = self.hist.getStatisticsResultsData(year)
            augmentedStatsData = self.hist.getStatisticsAugmentedData(year)

            totalGames = 0
            for gameIdent, gameData in yearData.items():
                if gameID is not None:
                    if gameID != gameIdent:
                        continue

                if gameIdent in self.hist.noGameData or gameIdent in self.poorlyParsed or gameIdent in self.toughParsing:
                    continue

                self.logger.info("  Parsing Game ID {0}".format(gameIdent))

                teamsMetaData = gameData["Teams"]
                homeTeamMetaData = teamsMetaData["Home"]
                awayTeamMetaData = teamsMetaData["Away"]
                driveData = gameData["Plays"]

                ################################################################################
                ### Get maps
                ################################################################################
                fieldMap = self.makeFieldMap(awayTeamMetaData,
                                             homeTeamMetaData)
                copmap = self.makeCopMap(awayTeamMetaData, homeTeamMetaData)

                ################################################################################
                ### Get team data
                ################################################################################
                homeTeamGameData = self.getTeamGameData(
                    gameIdent, seasonData, homeTeamMetaData)
                if homeTeamGameData is None:
                    continue
                awayTeamGameData = self.getTeamGameData(
                    gameIdent, seasonData, awayTeamMetaData)
                if awayTeamGameData is None:
                    continue

                ################################################################################
                ### Learn key plays for use in determining possession
                ################################################################################
                players = gameplayers(teamsMap=fieldMap, statsData=statsData)
                players.augmentData(augmentedStatsData)

                pfp = possessionfromplayer(players)
                ps = playstart()
                pc = playclock()
                pt = playtype()
                ap = analyzepossession(copmap, players)
                ay = analyzeyards()
                ak = analyzekicking()
                apen = analyzepenalties()
                pcc = possessionchangeclass(copmap)

                gameResult = []
                totalPlays = 0

                ################################################################################
                ### Collect Post Drive Scores
                ################################################################################
                postDriveScores = {"Drives": [], "Final": []}
                postDriveScores["Final"] = [
                    awayTeamGameData.teamAScore, homeTeamGameData.teamAScore
                ]

                ################################################################################
                ### Iterate over drives
                ################################################################################
                for idr, drive in enumerate(driveData):
                    self.logger.debug("\n\n{0}".format(2 * sep))
                    self.logger.debug("{0}Parsing Plays for Drive {1}".format(
                        self.ind, idr))

                    ds = drivesummary(drive, fieldMap)
                    drivePlays = ds.getDrivePlays()

                    postDriveScores["Drives"].append(ds.getPostDriveScore())

                    ################################################################################
                    ### Iterate over plays in drive
                    ################################################################################
                    driveResults = []
                    for ipl, drivePlay in enumerate(drivePlays):
                        #playNo        = drivePlay['Play']
                        playStartText = drivePlay['Start']
                        playData = drivePlay['Data']
                        self.logger.debug("\n  {0}".format(sep))
                        self.logger.debug("{0}  Play {1}/{2}: {3}".format(
                            self.ind, ipl, len(drivePlays), playData))

                        ### Determine play starting position
                        startVals = ps.getStart(playStartText)

                        ### Determine play clock and quarter
                        pc.parsePlay(playData)
                        startVals.setClock(pc)
                        playText = pc.getPlayText()

                        ### Determine play type
                        play = pt.getPlay(playText)

                        #
                        ### Determine possession
                        playPossession = pfp.determinePossession(play)
                        if playPossession.isForced() is not None:
                            play.pa.forced = playPossession.isForced()

                        ### Result of play
                        playResult = playsummary(possession=playPossession,
                                                 start=startVals,
                                                 play=play,
                                                 valid=play.valid)

                        ### Save and move on
                        totalPlays += 1
                        driveResults.append(playResult)
                        continue

                        ### Check if we need to insert a play
                        #newPlay = self.addPlay(gameIdent, idr, ipl, playResult, possData, verydebug)
                        #if newPlay is not None:
                        #    totalPlays += 1
                        #    driveResults.append(newPlay)

                    fullDriveData = ds.getFullDrive()
                    fullDriveData.setPlays(driveResults)
                    #fullDriveData = self.insertMissingData(gameIdent, idr, fullDriveData, debug)
                    #fullDriveData = self.augmentPlayWithScore(fullDriveData, fieldMap, debug)
                    gameResult.append(fullDriveData)

                ################################################################################
                ### Show State Before Alterations
                ################################################################################
                self.logger.debug("\n{0}".format(2 * sep))
                self.logger.debug("{0}Found {1} Drives For This Game".format(
                    self.ind, len(gameResult)))
                self.logger.debug("\n{0}\n".format(2 * sep))

                ################################################################################
                ### Analyze Possession
                ################################################################################
                dc.showGame(gameResult)

                gameResult = ap.continuity(gameResult)
                gameResult = pcc.splitChangeOfPossession(gameResult)

                gameResult = ap.continuity(gameResult)
                gameResult = ap.returns(gameResult)
                gameResult = ap.pats(gameResult)
                gameResult = ap.endofgame(gameResult, postDriveScores)
                gameResult = ap.noplays(gameResult)
                gameResult = ap.nextplay(gameResult)
                gameResult = ap.endofdrive(gameResult)

                dc.showGame(gameResult, "Game")
                gameResult = ay.analyze(gameResult)

                gameResult = ak.kickoffs(gameResult)
                gameResult = ak.returns(gameResult)

                #gameResult = apen.penalties(gameResult)
                #gameResult = apen.isPenaltyAdditive(gameResult)

                scoreResult = ap.gamescore(gameResult, postDriveScores)

                if scoreResult is False:
                    if gameID is None:
                        self.badGames[gameIdent] = True
                        continue
                    dc.showGame(gameResult, "Score Is Not Corrent")
                dc.showGame(gameResult, "Good Game")

                totalGames += 1
                if debug:
                    self.logger.info("Found {0} plays in this game {1}".format(
                        totalPlays, gameID))

            self.logger.info("Found {0} total games for {1}".format(
                totalGames, ifile))