diff --git a/controller/CronController.go b/controller/CronController.go index 812d84b..5e7c449 100644 --- a/controller/CronController.go +++ b/controller/CronController.go @@ -131,7 +131,8 @@ func SyncPhaseTuesdayViaCron() { // Calculate Player Minimum Values and Average Annual Value (AAV) for players if ts.Phase == 19 || ts.NFLWeek == 9 { - managers.CalculatePlayerMinimumAndAAVValues() + // w := http.ResponseWriter(nil) + // managers.CalculatePlayerMinimumAndAAVValues(w) } if (ts.CollegeSeasonOver && !ts.ProgressedCollegePlayers) || (ts.Phase == 31 && !ts.ProgressedCollegePlayers) { diff --git a/controller/OffseasonController.go b/controller/OffseasonController.go index 3ac4bc2..bc78e93 100644 --- a/controller/OffseasonController.go +++ b/controller/OffseasonController.go @@ -18,7 +18,7 @@ func UpdateTeamProfileAffinities(w http.ResponseWriter, r *http.Request) { } func CalculateExtensionValues(w http.ResponseWriter, r *http.Request) { - managers.CalculatePlayerMinimumAndAAVValues() + managers.CalculatePlayerMinimumAndAAVValues(w) json.NewEncoder(w).Encode("Done!") } diff --git a/main.go b/main.go index f27181a..3eb931c 100644 --- a/main.go +++ b/main.go @@ -493,6 +493,7 @@ func handleRequests() http.Handler { apiRouter.HandleFunc("/games/plays/bulk/nfl", controller.GetBulkPlayByPlay).Methods("GET") apiRouter.HandleFunc("/games/fb/games/stream/queue/{league}", controller.GetFBGameQueue).Methods("GET") apiRouter.HandleFunc("/games/cfb/live-plays/test/", controller.TestCFBCronJob).Methods("GET") + apiRouter.HandleFunc("/games/nfl/live-plays/test/", controller.TestNFLCronJob).Methods("GET") // Firebase test endpoints apiRouter.HandleFunc("/firebase/test/notification/", controller.TestNotificationToTuscan).Methods("GET") diff --git a/managers/DiscordManager.go b/managers/DiscordManager.go index 2ab823e..5254605 100644 --- a/managers/DiscordManager.go +++ b/managers/DiscordManager.go @@ -379,13 +379,29 @@ func GetCFBTeamDataForDiscord(id string) structs.CollegeTeamResponseData { } func GetCFBPlayByPlayStreamData(timeslot string, isFBS bool) []structs.StreamResponse { + db := dbprovider.GetInstance().GetDB() ts := GetTimestamp() + _, gameType := ts.GetCFBCurrentGameType() collegeWeekID := ts.CollegeWeekID teamMap := GetCollegeTeamMap() games := GetCollegeGamesByTimeslotAndWeekId(strconv.Itoa(collegeWeekID), timeslot, ts.CFBSpringGames) - + collegePlayers := repository.FindAllCollegePlayers(repository.PlayerQuery{}) + collegePlayerMapByTeamID := MakeCollegePlayerMapByTeamID(collegePlayers, true) + seasonID := strconv.Itoa(int(ts.CollegeSeasonID)) + weekID := strconv.Itoa(int(ts.CollegeWeekID)) + collegePlayerStats := repository.FindCollegePlayerGameStatsRecords(seasonID, weekID, gameType, "") + collegePlayerStatsMap := MakeCollegePlayerStatsMapByTeamID(collegePlayerStats) streams := []structs.StreamResponse{} + var allPbPs []structs.CollegePlayByPlay + gameIDs := make([]uint, 0, len(games)) + for _, game := range games { + gameIDs = append(gameIDs, game.ID) + } + db.Where("game_id IN ?", gameIDs).Find(&allPbPs) + + playByPlayMap := MakeCFBPlayByPlayMapByGameID(allPbPs) + for _, game := range games { if !game.GameComplete || game.IsRevealed { continue @@ -406,34 +422,27 @@ func GetCFBPlayByPlayStreamData(timeslot string, isFBS bool) []structs.StreamRes if homeTeam.IsFBS && awayTeam.IsFBS && !isFBS { continue } - gameID := strconv.Itoa(int(game.ID)) var wg sync.WaitGroup var ( - homeGameplan structs.CollegeGameplan - awayGameplan structs.CollegeGameplan - playByPlays []structs.CollegePlayByPlay - homePlayers []structs.GameResultsPlayer - awayPlayers []structs.GameResultsPlayer - homeStats []structs.CollegePlayerStats - awayStats []structs.CollegePlayerStats + homeGameplan structs.CollegeGameplan + awayGameplan structs.CollegeGameplan + gamePlayByPlays []structs.CollegePlayByPlay + homePlayers []structs.GameResultsPlayer + awayPlayers []structs.GameResultsPlayer + homeStats []structs.CollegePlayerStats + awayStats []structs.CollegePlayerStats ) homeTeamID := strconv.Itoa(game.HomeTeamID) awayTeamID := strconv.Itoa(game.AwayTeamID) - wg.Add(2) - - go func() { - defer wg.Done() - homeStats = GetAllCollegePlayerStatsByGame(gameID, homeTeamID) - }() - - go func() { - defer wg.Done() - awayStats = GetAllCollegePlayerStatsByGame(gameID, awayTeamID) - }() - - wg.Wait() - wg.Add(5) + homeStats = collegePlayerStatsMap[uint(game.HomeTeamID)] + awayStats = collegePlayerStatsMap[uint(game.AwayTeamID)] + roster := collegePlayerMapByTeamID[uint(game.HomeTeamID)] + homePlayers = MakeGameResultsPlayerListFromCFB(homeStats, roster) + awayRoster := collegePlayerMapByTeamID[uint(game.AwayTeamID)] + awayPlayers = MakeGameResultsPlayerListFromCFB(awayStats, awayRoster) + gamePlayByPlays = playByPlayMap[game.ID] + wg.Add(2) go func() { defer wg.Done() @@ -445,25 +454,10 @@ func GetCFBPlayByPlayStreamData(timeslot string, isFBS bool) []structs.StreamRes awayGameplan = GetGameplanByTeamID(awayTeamID) }() - go func() { - defer wg.Done() - playByPlays = GetCFBPlayByPlaysByGameID(gameID) - }() - - go func() { - defer wg.Done() - homePlayers = GetAllCollegePlayersWithGameStatsByTeamID(gameID, homeStats) - }() - - go func() { - defer wg.Done() - awayPlayers = GetAllCollegePlayersWithGameStatsByTeamID(gameID, awayStats) - }() - wg.Wait() participantMap := getGameParticipantMap(homePlayers, awayPlayers) - playbyPlayResponse := GenerateCFBPlayByPlayResponse(playByPlays, participantMap, true, game.HomeTeam, game.AwayTeam) + playbyPlayResponse := GenerateCFBPlayByPlayResponse(gamePlayByPlays, participantMap, true, game.HomeTeam, game.AwayTeam) stream := structs.StreamResponse{ GameID: game.ID, @@ -502,17 +496,29 @@ func GetCFBPlayByPlayStreamData(timeslot string, isFBS bool) []structs.StreamRes func GetNFLPlayByPlayStreamData(timeslot string) []structs.StreamResponse { ts := GetTimestamp() + db := dbprovider.GetInstance().GetDB() + _, gameType := ts.GetNFLCurrentGameType() nflWeekID := ts.NFLWeekID + seasonID := strconv.Itoa(ts.NFLSeasonID) games := GetNFLGamesByTimeslotAndWeekId(strconv.Itoa(nflWeekID), timeslot, ts.NFLPreseason) - + nflPlayers := GetAllNFLPlayers() + nflPlayerMapByTeamID := MakeNFLPlayerMapByTeamID(nflPlayers, true) + nflPlayerStats := repository.FindProPlayerGameStatsRecords(seasonID, strconv.Itoa(nflWeekID), gameType, "") + nflPlayerStatsMap := MakeNFLPlayerStatsMapByTeamID(nflPlayerStats) + var allPbPs []structs.NFLPlayByPlay + gameIDs := make([]uint, 0, len(games)) + for _, game := range games { + gameIDs = append(gameIDs, game.ID) + } + db.Where("game_id IN ?", gameIDs).Find(&allPbPs) streams := []structs.StreamResponse{} + playByPlayMap := MakeNFLPlayByPlayMapByGameID(allPbPs) for _, game := range games { if !game.GameComplete { continue } - gameID := strconv.Itoa(int(game.ID)) var wg sync.WaitGroup var ( homeGameplan structs.NFLGameplan @@ -525,21 +531,15 @@ func GetNFLPlayByPlayStreamData(timeslot string) []structs.StreamResponse { ) homeTeamID := strconv.Itoa(game.HomeTeamID) awayTeamID := strconv.Itoa(game.AwayTeamID) - - wg.Add(2) - - go func() { - defer wg.Done() - homeStats = GetAllNFLPlayerStatsByGame(gameID, homeTeamID) - }() - - go func() { - defer wg.Done() - awayStats = GetAllNFLPlayerStatsByGame(gameID, awayTeamID) - }() - + homeStats = nflPlayerStatsMap[uint(game.HomeTeamID)] + awayStats = nflPlayerStatsMap[uint(game.AwayTeamID)] + homeRoster := nflPlayerMapByTeamID[uint(game.HomeTeamID)] + awayRoster := nflPlayerMapByTeamID[uint(game.AwayTeamID)] + homePlayers = MakeGameResultsPlayerListFromNFL(homeStats, homeRoster) + awayPlayers = MakeGameResultsPlayerListFromNFL(awayStats, awayRoster) + playByPlays = playByPlayMap[game.ID] wg.Wait() - wg.Add(5) + wg.Add(2) go func() { defer wg.Done() @@ -551,21 +551,6 @@ func GetNFLPlayByPlayStreamData(timeslot string) []structs.StreamResponse { awayGameplan = GetNFLGameplanByTeamID(awayTeamID) }() - go func() { - defer wg.Done() - playByPlays = GetNFLPlayByPlaysByGameID(gameID) - }() - - go func() { - defer wg.Done() - homePlayers = GetAllNFLPlayersWithGameStatsByTeamID(gameID, homeStats) - }() - - go func() { - defer wg.Done() - awayPlayers = GetAllNFLPlayersWithGameStatsByTeamID(gameID, awayStats) - }() - wg.Wait() participantMap := getGameParticipantMap(homePlayers, awayPlayers) diff --git a/managers/ExportManager.go b/managers/ExportManager.go index 2ba3247..3a1cbe6 100644 --- a/managers/ExportManager.go +++ b/managers/ExportManager.go @@ -1246,3 +1246,33 @@ func ExportNFLPreseasonPlayByPlayToCSV(w http.ResponseWriter) { } } } + +func ExportMinimumValueAndTagUpdatesToCSV(w http.ResponseWriter, csvRows [][]string) { + w.Header().Set("Content-Type", "text/csv") + filename := "minimum_value_and_tag_updates_test.csv" + w.Header().Set("Content-Disposition", "attachment;filename="+filename) + + writer := csv.NewWriter(w) + defer writer.Flush() + HeaderRow := []string{ + "Group", "ID", "First Name", "Last Name", "Position", "Archetype", + "Position Two", "Archetype Two", "Age", + "Overall", "Calculated Value", "Calculated AAV", "Current Value", "Current AAV", + } + err := writer.Write(HeaderRow) + if err != nil { + log.Fatal("Cannot write header row", err) + } + + for _, row := range csvRows { + if err := writer.Write(row); err != nil { + log.Fatal("Cannot write row to CSV", err) + } + + writer.Flush() + err = writer.Error() + if err != nil { + log.Fatal("Error while writing to file ::", err) + } + } +} diff --git a/managers/ListHelper.go b/managers/ListHelper.go index 6be6404..ca4d0d3 100644 --- a/managers/ListHelper.go +++ b/managers/ListHelper.go @@ -1,6 +1,8 @@ package managers -import "github.com/CalebRose/SimFBA/structs" +import ( + "github.com/CalebRose/SimFBA/structs" +) func MakeCollegeInjuryList(players []structs.CollegePlayer) []structs.CollegePlayer { injuryList := []structs.CollegePlayer{} @@ -67,3 +69,183 @@ func MakeUDFAList(players []structs.NFLPlayer) []structs.NFLPlayer { } return playerList } + +func MakeGameResultsPlayerListFromCFB(stats []structs.CollegePlayerStats, players []structs.CollegePlayer) []structs.GameResultsPlayer { + var matchRows []structs.GameResultsPlayer + statMap := make(map[uint]structs.CollegePlayerStats) + for _, s := range stats { + statMap[uint(s.CollegePlayerID)] = s + } + for _, p := range players { + s := statMap[p.ID] + if s.ID == 0 || s.Snaps == 0 { + continue + } + + row := structs.GameResultsPlayer{ + ID: p.ID, + FirstName: p.FirstName, + LastName: p.LastName, + Position: p.Position, + Archetype: p.Archetype, + Year: uint(p.Year), + TeamAbbr: p.TeamAbbr, + League: "CFB", + Snaps: int(s.Snaps), + PassingYards: int(s.PassingYards), + PassAttempts: int(s.PassAttempts), + PassCompletions: int(s.PassCompletions), + PassingTDs: int(s.PassingTDs), + Interceptions: int(s.Interceptions), + LongestPass: int(s.LongestPass), + Sacks: int(s.Sacks), + RushAttempts: int(s.RushAttempts), + RushingYards: int(s.RushingYards), + RushingTDs: int(s.RushingTDs), + Fumbles: int(s.Fumbles), + LongestRush: int(s.LongestRush), + Targets: int(s.Targets), + Catches: int(s.Catches), + ReceivingYards: int(s.ReceivingYards), + ReceivingTDs: int(s.ReceivingTDs), + LongestReception: int(s.LongestReception), + SoloTackles: s.SoloTackles, + AssistedTackles: s.AssistedTackles, + TacklesForLoss: s.TacklesForLoss, + SacksMade: s.SacksMade, + ForcedFumbles: int(s.ForcedFumbles), + RecoveredFumbles: int(s.RecoveredFumbles), + PassDeflections: int(s.PassDeflections), + InterceptionsCaught: int(s.InterceptionsCaught), + Safeties: int(s.Safeties), + DefensiveTDs: int(s.DefensiveTDs), + FGMade: int(s.FGMade), + FGAttempts: int(s.FGAttempts), + LongestFG: int(s.LongestFG), + ExtraPointsMade: int(s.ExtraPointsMade), + ExtraPointsAttempted: int(s.ExtraPointsAttempted), + KickoffTouchbacks: int(s.KickoffTouchbacks), + Punts: int(s.Punts), + PuntTouchbacks: int(s.PuntTouchbacks), + PuntsInside20: int(s.PuntsInside20), + KickReturns: int(s.KickReturns), + KickReturnTDs: int(s.KickReturnTDs), + KickReturnYards: int(s.KickReturnYards), + PuntReturns: int(s.PuntReturns), + PuntReturnTDs: int(s.PuntReturnTDs), + PuntReturnYards: int(s.PuntReturnYards), + STSoloTackles: s.STSoloTackles, + STAssistedTackles: s.STAssistedTackles, + PuntsBlocked: int(s.PuntsBlocked), + FGBlocked: int(s.FGBlocked), + Pancakes: int(s.Pancakes), + SacksAllowed: int(s.SacksAllowed), + DefensivePressures: int(s.DefensivePressures), + Hurries: int(s.Hurries), + PassRushSnaps: int(s.PassRushSnaps), + PassRushWins: int(s.PassRushWins), + PressuresAllowed: int(s.PressuresAllowed), + PassBlockSnaps: int(s.PassBlockSnaps), + PassBlockWins: int(s.PassBlockWins), + PlayedGame: int(s.PlayedGame), + StartedGame: int(s.StartedGame), + WasInjured: s.WasInjured, + WeeksOfRecovery: s.WeeksOfRecovery, + InjuryType: s.InjuryType, + } + + matchRows = append(matchRows, row) + } + + return matchRows +} + +func MakeGameResultsPlayerListFromNFL(stats []structs.NFLPlayerStats, players []structs.NFLPlayer) []structs.GameResultsPlayer { + var matchRows []structs.GameResultsPlayer + statMap := make(map[uint]structs.NFLPlayerStats) + for _, s := range stats { + statMap[uint(s.NFLPlayerID)] = s + } + for _, p := range players { + s := statMap[p.ID] + if s.ID == 0 || s.Snaps == 0 { + continue + } + + row := structs.GameResultsPlayer{ + ID: p.ID, + FirstName: p.FirstName, + LastName: p.LastName, + Position: p.Position, + Archetype: p.Archetype, + Year: uint(p.Experience), + TeamAbbr: p.TeamAbbr, + League: "NFL", + Snaps: int(s.Snaps), + PassingYards: int(s.PassingYards), + PassAttempts: int(s.PassAttempts), + PassCompletions: int(s.PassCompletions), + PassingTDs: int(s.PassingTDs), + Interceptions: int(s.Interceptions), + LongestPass: int(s.LongestPass), + Sacks: int(s.Sacks), + RushAttempts: int(s.RushAttempts), + RushingYards: int(s.RushingYards), + RushingTDs: int(s.RushingTDs), + Fumbles: int(s.Fumbles), + LongestRush: int(s.LongestRush), + Targets: int(s.Targets), + Catches: int(s.Catches), + ReceivingYards: int(s.ReceivingYards), + ReceivingTDs: int(s.ReceivingTDs), + LongestReception: int(s.LongestReception), + SoloTackles: s.SoloTackles, + AssistedTackles: s.AssistedTackles, + TacklesForLoss: s.TacklesForLoss, + SacksMade: s.SacksMade, + ForcedFumbles: int(s.ForcedFumbles), + RecoveredFumbles: int(s.RecoveredFumbles), + PassDeflections: int(s.PassDeflections), + InterceptionsCaught: int(s.InterceptionsCaught), + Safeties: int(s.Safeties), + DefensiveTDs: int(s.DefensiveTDs), + FGMade: int(s.FGMade), + FGAttempts: int(s.FGAttempts), + LongestFG: int(s.LongestFG), + ExtraPointsMade: int(s.ExtraPointsMade), + ExtraPointsAttempted: int(s.ExtraPointsAttempted), + KickoffTouchbacks: int(s.KickoffTouchbacks), + Punts: int(s.Punts), + PuntTouchbacks: int(s.PuntTouchbacks), + PuntsInside20: int(s.PuntsInside20), + KickReturns: int(s.KickReturns), + KickReturnTDs: int(s.KickReturnTDs), + KickReturnYards: int(s.KickReturnYards), + PuntReturns: int(s.PuntReturns), + PuntReturnTDs: int(s.PuntReturnTDs), + PuntReturnYards: int(s.PuntReturnYards), + STSoloTackles: s.STSoloTackles, + STAssistedTackles: s.STAssistedTackles, + PuntsBlocked: int(s.PuntsBlocked), + FGBlocked: int(s.FGBlocked), + Pancakes: int(s.Pancakes), + SacksAllowed: int(s.SacksAllowed), + DefensivePressures: int(s.DefensivePressures), + Hurries: int(s.Hurries), + PassRushSnaps: int(s.PassRushSnaps), + PassRushWins: int(s.PassRushWins), + PressuresAllowed: int(s.PressuresAllowed), + PassBlockSnaps: int(s.PassBlockSnaps), + PassBlockWins: int(s.PassBlockWins), + PlayedGame: int(s.PlayedGame), + StartedGame: int(s.StartedGame), + WasInjured: s.WasInjured, + WeeksOfRecovery: s.WeeksOfRecovery, + InjuryType: s.InjuryType, + } + + matchRows = append(matchRows, row) + } + + return matchRows +} diff --git a/managers/LiveStreamManager.go b/managers/LiveStreamManager.go index 1c04efb..13cb194 100644 --- a/managers/LiveStreamManager.go +++ b/managers/LiveStreamManager.go @@ -74,6 +74,7 @@ func GetBulkPlayByPlayData(isCollege bool, reqSeason string, reqWeek string, req Plays: make(map[uint][]structs.PlayByPlayResponse), Rosters: make(map[uint]GameRosterDTO), } + _, gameType := ts.GetCFBCurrentGameType() db := dbprovider.GetInstance().GetDB() @@ -86,6 +87,9 @@ func GetBulkPlayByPlayData(isCollege bool, reqSeason string, reqWeek string, req games := repository.FindCollegeGamesRecords(clauses) collegePlayers := repository.FindAllCollegePlayers(repository.PlayerQuery{}) collegePlayerMap := MakeCollegePlayerMap(collegePlayers) + collegePlayerMapByTeamID := MakeCollegePlayerMapByTeamID(collegePlayers, true) + collegePlayerStats := repository.FindCollegePlayerGameStatsRecords(seasonID, weekID, gameType, "") + collegePlayerStatsMap := MakeCollegePlayerStatsMapByTeamID(collegePlayerStats) for _, g := range games { // if reqTimeslot != "" && reqTimeslot != "undefined" && g.TimeSlot != reqTimeslot { @@ -105,7 +109,6 @@ func GetBulkPlayByPlayData(isCollege bool, reqSeason string, reqWeek string, req // if reqTimeslot != "" && reqTimeslot != "undefined" && g.TimeSlot != reqTimeslot { // continue // } - gameIDStr := strconv.Itoa(int(g.ID)) response.Plays[g.ID] = []structs.PlayByPlayResponse{} // Build Roster for this game @@ -116,10 +119,12 @@ func GetBulkPlayByPlayData(isCollege bool, reqSeason string, reqWeek string, req htID := strconv.Itoa(g.HomeTeamID) atID := strconv.Itoa(g.AwayTeamID) - homeStats := GetAllCollegePlayerStatsByGame(gameIDStr, htID) - awayStats := GetAllCollegePlayerStatsByGame(gameIDStr, atID) - homePlayers := GetAllCollegePlayersWithGameStatsByTeamID(gameIDStr, homeStats) - awayPlayers := GetAllCollegePlayersWithGameStatsByTeamID(gameIDStr, awayStats) + homeStats := collegePlayerStatsMap[uint(g.HomeTeamID)] + awayStats := collegePlayerStatsMap[uint(g.AwayTeamID)] + homeRoster := collegePlayerMapByTeamID[uint(g.HomeTeamID)] + awayRoster := collegePlayerMapByTeamID[uint(g.AwayTeamID)] + homePlayers := MakeGameResultsPlayerListFromCFB(homeStats, homeRoster) + awayPlayers := MakeGameResultsPlayerListFromCFB(awayStats, awayRoster) playerStats := []structs.CollegePlayerStats{} playerStats = append(playerStats, homeStats...) @@ -171,6 +176,9 @@ func GetBulkPlayByPlayData(isCollege bool, reqSeason string, reqWeek string, req games := repository.FindNFLGamesRecords(clauses) nflPlayers := GetAllNFLPlayers() proPlayerMap := MakeNFLPlayerMap(nflPlayers) + nflPlayerMapByTeamID := MakeNFLPlayerMapByTeamID(nflPlayers, true) + nflPlayerStats := repository.FindProPlayerGameStatsRecords(seasonID, weekID, gameType, "") + nflPlayerStatsMap := MakeNFLPlayerStatsMapByTeamID(nflPlayerStats) for _, g := range games { // if reqTimeslot != "" && reqTimeslot != "undefined" && g.TimeSlot != reqTimeslot { @@ -190,7 +198,6 @@ func GetBulkPlayByPlayData(isCollege bool, reqSeason string, reqWeek string, req // if reqTimeslot != "" && reqTimeslot != "undefined" && g.TimeSlot != reqTimeslot { // continue // } - gameIDStr := strconv.Itoa(int(g.ID)) response.Plays[g.ID] = []structs.PlayByPlayResponse{} roster := GameRosterDTO{ @@ -199,14 +206,16 @@ func GetBulkPlayByPlayData(isCollege bool, reqSeason string, reqWeek string, req } htID := strconv.Itoa(g.HomeTeamID) atID := strconv.Itoa(g.AwayTeamID) - homePlayerStats := GetAllNFLPlayerStatsByGame(gameIDStr, htID) - awayPlayerStats := GetAllNFLPlayerStatsByGame(gameIDStr, atID) - homePlayers := GetAllNFLPlayersWithGameStatsByTeamID(gameIDStr, homePlayerStats) - awayPlayers := GetAllNFLPlayersWithGameStatsByTeamID(gameIDStr, awayPlayerStats) + homeStats := nflPlayerStatsMap[uint(g.HomeTeamID)] + awayStats := nflPlayerStatsMap[uint(g.AwayTeamID)] + homeRoster := nflPlayerMapByTeamID[uint(g.HomeTeamID)] + awayRoster := nflPlayerMapByTeamID[uint(g.AwayTeamID)] + homePlayers := MakeGameResultsPlayerListFromNFL(homeStats, homeRoster) + awayPlayers := MakeGameResultsPlayerListFromNFL(awayStats, awayRoster) playerStats := []structs.NFLPlayerStats{} - playerStats = append(playerStats, homePlayerStats...) - playerStats = append(playerStats, awayPlayerStats...) + playerStats = append(playerStats, homeStats...) + playerStats = append(playerStats, awayStats...) for _, s := range playerStats { if s.Snaps <= 0 { continue diff --git a/managers/MapHelper.go b/managers/MapHelper.go index 080ff6a..0cf1211 100644 --- a/managers/MapHelper.go +++ b/managers/MapHelper.go @@ -156,29 +156,63 @@ func MakeHistoricCollegeSeasonStatsMapByTeamID(stats []structs.CollegePlayerSeas return statsMap } +func MakeCollegePlayerStatsMapByTeamID(stats []structs.CollegePlayerStats) map[uint][]structs.CollegePlayerStats { + statsMap := make(map[uint][]structs.CollegePlayerStats) + + for _, p := range stats { + if p.TeamID == 0 { + continue + } + if len(statsMap[uint(p.TeamID)]) > 0 { + statsMap[uint(p.TeamID)] = append(statsMap[uint(p.TeamID)], p) + } else { + statsMap[uint(p.TeamID)] = []structs.CollegePlayerStats{p} + } + } + + return statsMap +} + +func MakeNFLPlayerStatsMapByTeamID(stats []structs.NFLPlayerStats) map[uint][]structs.NFLPlayerStats { + statsMap := make(map[uint][]structs.NFLPlayerStats) + + for _, p := range stats { + if p.TeamID == 0 { + continue + } + if len(statsMap[uint(p.TeamID)]) > 0 { + statsMap[uint(p.TeamID)] = append(statsMap[uint(p.TeamID)], p) + } else { + statsMap[uint(p.TeamID)] = []structs.NFLPlayerStats{p} + } + } + + return statsMap +} + /* Where("team_one_id = ? OR team_two_id = ?", teamID, teamID) */ func MakeHistoricRivalriesMapByTeamID(rivals []structs.CollegeRival) map[uint][]structs.CollegeRival { - statsMap := make(map[uint][]structs.CollegeRival) + rivalMap := make(map[uint][]structs.CollegeRival) for _, r := range rivals { if r.TeamOneID == 0 || r.TeamTwoID == 0 { continue } - if len(statsMap[uint(r.TeamOneID)]) > 0 { - statsMap[uint(r.TeamOneID)] = append(statsMap[uint(r.TeamOneID)], r) + if len(rivalMap[uint(r.TeamOneID)]) > 0 { + rivalMap[uint(r.TeamOneID)] = append(rivalMap[uint(r.TeamOneID)], r) } else { - statsMap[uint(r.TeamOneID)] = []structs.CollegeRival{r} + rivalMap[uint(r.TeamOneID)] = []structs.CollegeRival{r} } - if len(statsMap[uint(r.TeamTwoID)]) > 0 { - statsMap[uint(r.TeamTwoID)] = append(statsMap[uint(r.TeamTwoID)], r) + if len(rivalMap[uint(r.TeamTwoID)]) > 0 { + rivalMap[uint(r.TeamTwoID)] = append(rivalMap[uint(r.TeamTwoID)], r) } else { - statsMap[uint(r.TeamTwoID)] = []structs.CollegeRival{r} + rivalMap[uint(r.TeamTwoID)] = []structs.CollegeRival{r} } } - return statsMap + return rivalMap } func MakeHistoricGamesMapByTeamID(games []structs.CollegeGame) map[uint][]structs.CollegeGame { @@ -533,3 +567,21 @@ func MakeStadiumMapByID(stadia []structs.Stadium) map[uint]structs.Stadium { } return stadiumMap } + +func MakeCFBPlayByPlayMapByGameID(plays []structs.CollegePlayByPlay) map[uint][]structs.CollegePlayByPlay { + playMap := make(map[uint][]structs.CollegePlayByPlay) + + for _, p := range plays { + playMap[p.GameID] = append(playMap[p.GameID], p) + } + return playMap +} + +func MakeNFLPlayByPlayMapByGameID(plays []structs.NFLPlayByPlay) map[uint][]structs.NFLPlayByPlay { + playMap := make(map[uint][]structs.NFLPlayByPlay) + + for _, p := range plays { + playMap[p.GameID] = append(playMap[p.GameID], p) + } + return playMap +} diff --git a/managers/ValuationManager.go b/managers/ValuationManager.go index 3000471..3f8b471 100644 --- a/managers/ValuationManager.go +++ b/managers/ValuationManager.go @@ -3,6 +3,7 @@ package managers import ( "log" "math" + "net/http" "sort" "strconv" @@ -331,10 +332,12 @@ func computeGroupExtensionValues(group string, entries []playerGroupEntry) []str // contract (extension) value and AAV for every active NFL player. // Run once per offseason. Also updates OriginalMinimumValue / OriginalAAV so // the week-15 reset restores to this freshly computed baseline. -func CalculatePlayerMinimumAndAAVValues() { +func CalculatePlayerMinimumAndAAVValues(w http.ResponseWriter) { db := dbprovider.GetInstance().GetDB() ts := GetTimestamp() seasonID := strconv.Itoa(ts.NFLSeasonID) + isTest := true // TODO: set to false for production + csvRows := [][]string{} nflPlayers := GetAllNFLPlayers() contracts := repository.FindAllActiveNFLContracts() @@ -362,18 +365,41 @@ func CalculatePlayerMinimumAndAAVValues() { for group, entries := range groupEntries { updated := computeGroupExtensionValues(group, entries) for _, p := range updated { - if err := db.Model(&p).Updates(map[string]interface{}{ - "minimum_value": p.MinimumValue, - "original_minimum_value": p.OriginalMinimumValue, - "aav": p.AAV, - "original_aav": p.OriginalAAV, - }).Error; err != nil { - log.Printf("ValuationManager: failed to save player %d (%s): %v", p.ID, group, err) - continue + if !isTest { + if err := db.Model(&p).Updates(map[string]interface{}{ + "minimum_value": p.MinimumValue, + "original_minimum_value": p.OriginalMinimumValue, + "aav": p.AAV, + "original_aav": p.OriginalAAV, + }).Error; err != nil { + log.Printf("ValuationManager: failed to save player %d (%s): %v", p.ID, group, err) + continue + } + } else { + row := []string{ + group, + strconv.Itoa(int(p.ID)), + p.FirstName, + p.LastName, + p.Position, + p.Archetype, + p.PositionTwo, + p.ArchetypeTwo, + strconv.Itoa(int(p.Age)), + strconv.Itoa(int(p.Overall)), + strconv.FormatFloat(p.OriginalMinimumValue, 'f', 2, 64), + strconv.FormatFloat(p.OriginalAAV, 'f', 2, 64), + strconv.FormatFloat(p.MinimumValue, 'f', 2, 64), + strconv.FormatFloat(p.AAV, 'f', 2, 64), + } + csvRows = append(csvRows, row) } saved++ } } + if isTest { + ExportMinimumValueAndTagUpdatesToCSV(w, csvRows) + } log.Printf("CalculatePlayerMinimumAndAAVValues: updated %d players", saved) }