From 28ee291228ffb9f16c57305e0296bd0dec1bee3f Mon Sep 17 00:00:00 2001 From: Thomas Pitzel Date: Sat, 11 Jul 2026 19:03:41 -0600 Subject: [PATCH] Fix play-by-play special teams and LCB output --- managers/ExportManager.go | 2 +- managers/StatsManager.go | 48 +++++++++++++-------------------------- structs/PlayByPlay.go | 13 ++++++++--- util/PlayByPlayUtil.go | 2 +- 4 files changed, 28 insertions(+), 37 deletions(-) diff --git a/managers/ExportManager.go b/managers/ExportManager.go index 2ba3247..5e91ff2 100644 --- a/managers/ExportManager.go +++ b/managers/ExportManager.go @@ -536,7 +536,7 @@ func ExportNFLPlayByPlayToCSV(gameID string, w http.ResponseWriter) { strconv.Itoa(int(play.Rolb)), strconv.Itoa(int(play.Rilb)), strconv.Itoa(int(play.Mlb)), strconv.Itoa(int(play.Lilb)), strconv.Itoa(int(play.Lolb)), strconv.Itoa(int(play.Rcb)), strconv.Itoa(int(play.Extradb1)), strconv.Itoa(int(play.Extradb2)), strconv.Itoa(int(play.Extradb3)), - strconv.Itoa(int(play.Fs)), strconv.Itoa(int(play.Ss)), strconv.Itoa(int(play.Fcb)), + strconv.Itoa(int(play.Fs)), strconv.Itoa(int(play.Ss)), strconv.Itoa(int(play.Lcb)), strconv.Itoa(int(play.Blitzer1)), strconv.Itoa(int(play.Blitzer2)), strconv.Itoa(int(play.Blitzer3)), } diff --git a/managers/StatsManager.go b/managers/StatsManager.go index 02e8ddc..e5a5ac3 100644 --- a/managers/StatsManager.go +++ b/managers/StatsManager.go @@ -1335,7 +1335,7 @@ func GenerateCFBPlayByPlayResponse(playByPlays []structs.CollegePlayByPlay, part CBCoverage: cb, SCoverage: s, PresureID: p.PressureID, - PlayersInvoledInPlay: p.PlayersInvoledInPlay, + PlayersInvoledInPlay: p.PlayersInvoledInPlay.NormalizeCornerbacks(), } var result []string if isStream { @@ -1417,7 +1417,7 @@ func GenerateNFLPlayByPlayResponse(playByPlays []structs.NFLPlayByPlay, particip CBCoverage: cb, SCoverage: s, PresureID: p.PressureID, - PlayersInvoledInPlay: p.PlayersInvoledInPlay, + PlayersInvoledInPlay: p.PlayersInvoledInPlay.NormalizeCornerbacks(), } var result []string if isStream { @@ -1516,8 +1516,9 @@ func generateResultsString(play structs.PlayByPlay, playType string, participant if play.IsTouchback { firstSegment += " Touchback. " } else { - resultYdsStr := strconv.Itoa(int(100 - play.ResultYards)) - resultYards := util.GetYardsString(play.ResultYards) + returnYards := play.ResultYards + resultYdsStr := strconv.Itoa(int(returnYards)) + resultYards := util.GetYardsString(returnYards) firstSegment += recLabel + " returns the ball " + resultYdsStr + resultYards } case "Punt": @@ -1528,17 +1529,9 @@ func generateResultsString(play structs.PlayByPlay, playType string, participant distanceStr := util.GetYardsString(play.KickDistance) verb := " punts for " firstSegment = kickerLabel + verb + strconv.Itoa(int(play.KickDistance)) + distanceStr - los := play.LineOfScrimmage - if los > 50 { - los = 100 - los - } - outside := los + play.KickDistance - netReturnYards := outside - play.ResultYards - resultYdsStr := strconv.Itoa(int(netReturnYards)) - resultYards := util.GetYardsString(netReturnYards) - if !play.IsTouchback { - resultYdsStr = strconv.Itoa(int(netReturnYards)) - } + returnYards := play.ResultYards + resultYdsStr := strconv.Itoa(int(returnYards)) + resultYards := util.GetYardsString(returnYards) if play.IsBlocked { blockerLabel := getPlayerLabel(participantMap[turnID]) @@ -1729,10 +1722,10 @@ func generateStreamString(play structs.PlayByPlay, playType, playName, poa strin if play.IsTouchback { firstSegment += util.GetTouchbackStatement() } else { - netReturnYards := int(play.ResultYards) - outside - resultYdsStr := strconv.Itoa(int(netReturnYards)) - resultYards := util.GetYardsString(int8(netReturnYards)) - verb := util.GetReturnVerb(netReturnYards, play.IsTouchdown, play.IsOutOfBounds) + returnYards := play.ResultYards + resultYdsStr := strconv.Itoa(int(returnYards)) + resultYards := util.GetYardsString(returnYards) + verb := util.GetReturnVerb(int(returnYards), play.IsTouchdown, play.IsOutOfBounds) firstSegment += recLabel + verb + resultYdsStr + resultYards } case "Punt": @@ -1743,18 +1736,9 @@ func generateStreamString(play structs.PlayByPlay, playType, playName, poa strin distanceStr := util.GetYardsString(play.KickDistance) verb := util.GetPuntVerb() firstSegment = kickerLabel + verb + strconv.Itoa(int(play.KickDistance)) + distanceStr - los := play.LineOfScrimmage - if los > 50 { - los = 100 - los - } - outside := los + play.KickDistance - // Line of Scrimmage + kick distance = ball spot // Result yards - ball spot = actual yards ran // Ball spot - yards ran = next line of scrimmage - netReturnYards := outside - play.ResultYards - resultYards := util.GetYardsString(netReturnYards) - resultYdsStr := strconv.Itoa(int(netReturnYards)) - if !play.IsTouchback { - resultYdsStr = strconv.Itoa(int(netReturnYards)) - } + returnYards := play.ResultYards + resultYards := util.GetYardsString(returnYards) + resultYdsStr := strconv.Itoa(int(returnYards)) if play.IsBlocked { blockerLabel := getPlayerLabel(participantMap[turnID]) verb := util.GetBlockedStatement(false) @@ -1766,7 +1750,7 @@ func generateStreamString(play structs.PlayByPlay, playType, playName, poa strin tb := util.GetTouchbackStatement() firstSegment += tb } else { - verb := util.GetReturnVerb(int(netReturnYards), play.IsTouchdown, play.IsOutOfBounds) + verb := util.GetReturnVerb(int(returnYards), play.IsTouchdown, play.IsOutOfBounds) firstSegment += recLabel + verb + resultYdsStr + resultYards } case "XP": diff --git a/structs/PlayByPlay.go b/structs/PlayByPlay.go index 5508295..4ecbae1 100644 --- a/structs/PlayByPlay.go +++ b/structs/PlayByPlay.go @@ -38,13 +38,20 @@ type PlayersInvoledInPlay struct { Extradb3 uint Fs uint Ss uint - Fcb uint + Fcb uint `json:"-"` Lcb uint Blitzer1 uint Blitzer2 uint Blitzer3 uint } +func (p PlayersInvoledInPlay) NormalizeCornerbacks() PlayersInvoledInPlay { + if p.Lcb == 0 && p.Fcb != 0 { + p.Lcb = p.Fcb + } + return p +} + type PlayByPlay struct { ID uint GameID uint @@ -158,14 +165,14 @@ func (p *PlayByPlay) Map(play PlayByPlayDTO) { p.IsComplete = play.IsComplete p.IsGood = play.IsGood p.IsLeft = play.IsLeft - p.IsLeft = play.IsRight + p.IsRight = play.IsRight p.IsOffUpright = play.IsOffUpright p.IsShort = play.IsShort p.KickDistance = int8(play.KickDistance) p.OnOffense = play.OnOffense p.HomeHasBall = play.HomeHasBall p.PressureID = uint(play.PressureID) - p.PlayersInvoledInPlay = play.PlayersInvoledInPlay + p.PlayersInvoledInPlay = play.PlayersInvoledInPlay.NormalizeCornerbacks() } type PlayByPlayDTO struct { diff --git a/util/PlayByPlayUtil.go b/util/PlayByPlayUtil.go index 5a06013..041fae7 100644 --- a/util/PlayByPlayUtil.go +++ b/util/PlayByPlayUtil.go @@ -494,7 +494,7 @@ func GetFGEndStatement(isGood bool, isLeft, isOffUpright, isRight bool) string { " and its just slightly misses from the right. No good. ", " and it looks like it's just too far right. No good. ", " and it's too wide right. No good. ", - " and it just misses from the left. The kicker looks frustrated. ", + " and it just misses from the right. The kicker looks frustrated. ", " and it veers right, no good! ", " and it hooks to the right! No good! ", " and the kick is right of the mark! No good. ",