player adv controller update

This commit is contained in:
Ravi Prasad
2025-08-06 03:15:41 -05:00
parent 3cfdcdbc4d
commit 90c57c340a
4 changed files with 360 additions and 310 deletions
+112 -54
View File
@@ -8,6 +8,56 @@ import (
"github.com/nprasad2077/NBA_Go/services"
)
// --- MODIFICATION START ---
// A DTO is created to control the JSON output for advanced stats.
// It omits fields like ID, ExternalID, CreatedAt, UpdatedAt, and DeletedAt.
type PlayerAdvancedStatDTO struct {
PlayerID string `json:"playerId"`
PlayerName string `json:"playerName"`
Position string `json:"position"`
Age int `json:"age"`
Team string `json:"team"`
Games int `json:"games"`
MinutesPlayed int `json:"minutesPlayed"`
PER float64 `json:"per"`
TSPercent float64 `json:"tsPercent"`
ThreePAR float64 `json:"threePAR"`
FTr float64 `json:"ftr"`
OffensiveRBPercent float64 `json:"offensiveRBPercent"`
DefensiveRBPercent float64 `json:"defensiveRBPercent"`
TotalRBPercent float64 `json:"totalRBPercent"`
AssistPercent float64 `json:"assistPercent"`
StealPercent float64 `json:"stealPercent"`
BlockPercent float64 `json:"blockPercent"`
TurnoverPercent float64 `json:"turnoverPercent"`
UsagePercent float64 `json:"usagePercent"`
OffensiveWS float64 `json:"offensiveWS"`
DefensiveWS float64 `json:"defensiveWS"`
WinShares float64 `json:"winShares"`
WinSharesPer float64 `json:"winSharesPer"`
OffensiveBox float64 `json:"offensiveBox"`
DefensiveBox float64 `json:"defensiveBox"`
Box float64 `json:"box"`
VORP float64 `json:"vorp"`
Season int `json:"season"`
IsPlayoff bool `json:"isPlayoff"`
}
// AdvancedStatsResponse is the swagger response model for GetAllAdvancedPlayerStats
// It wraps the returned player advanced stats and pagination metadata.
// The Data field is updated to use the DTO.
type AdvancedStatsResponse struct {
Data []PlayerAdvancedStatDTO `json:"data"`
Pagination struct {
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"pageSize"`
Pages int64 `json:"pages"`
} `json:"pagination"`
}
// --- MODIFICATION END ---
var advancedSortMap = map[string]string{
"playerId": "player_id",
"playerName": "player_name",
@@ -39,32 +89,6 @@ var advancedSortMap = map[string]string{
"season": "season",
}
// AdvancedStatsResponse is the swagger response model for GetAllAdvancedPlayerStats
// It wraps the returned player advanced stats and pagination metadata.
type AdvancedStatsResponse struct {
Data []models.PlayerAdvancedStat `json:"data"`
Pagination struct {
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"pageSize"`
Pages int64 `json:"pages"`
} `json:"pagination"`
}
// FetchPlayerAdvancedStats returns a handler that imports advanced stats for a season
// Note: not exposed in Swagger docs, only internal use.
// func FetchPlayerAdvancedStats(db *gorm.DB) fiber.Handler {
// return func(c *fiber.Ctx) error {
// season := c.QueryInt("season", 2025)
// isPlayoff := c.QueryBool("isPlayoff", false)
// if err := services.FetchAndStorePlayerAdvancedStats(db, season, isPlayoff); err != nil {
// return c.Status(500).JSON(fiber.Map{"error": err.Error()})
// }
// return c.JSON(fiber.Map{"message": "Player stats fetched and saved."})
// }
// }
// ScrapePlayerAdvancedStats godoc
// @ignore
@@ -114,40 +138,35 @@ func GetAllAdvancedPlayerStats(db *gorm.DB) fiber.Handler {
return func(c *fiber.Ctx) error {
var stats []models.PlayerAdvancedStat
// --- MODIFICATION FOR FILTERS ---
// Allow both "playerId" and "player_id"
playerId := c.Query("playerId")
if playerId == "" {
playerId = c.Query("player_id")
}
// --- FILTERS ---
playerId := c.Query("playerId")
if playerId == "" {
playerId = c.Query("player_id")
}
// Filters
season := c.QueryInt("season", 0)
team := c.Query("team")
// playerId := c.Query("playerId")
// Pagination
// --- PAGINATION ---
page := c.QueryInt("page", 1)
pageSize := c.QueryInt("pageSize", 20)
offset := (page - 1) * pageSize
// --- MODIFICATION FOR SORTING ---
// Sorting
sortByParam := c.Query("sortBy", "winShares") // Default to a common field
ascending := c.QueryBool("ascending", false)
// --- SORTING ---
sortByParam := c.Query("sortBy", "winShares")
ascending := c.QueryBool("ascending", false)
// Translate sortBy param to a valid DB column, defaulting if not found.
sortBy, ok := advancedSortMap[sortByParam]
if !ok {
sortBy = "win_shares" // Safe default
}
sortBy, ok := advancedSortMap[sortByParam]
if !ok {
sortBy = "win_shares" // Safe default
}
order := sortBy + " DESC"
if ascending {
order = sortBy + " ASC"
}
order := sortBy + " DESC"
if ascending {
order = sortBy + " ASC"
}
// Build query
// --- QUERY BUILDING ---
query := db.Model(&models.PlayerAdvancedStat{})
if season != 0 {
@@ -160,29 +179,68 @@ func GetAllAdvancedPlayerStats(db *gorm.DB) fiber.Handler {
query = query.Where("player_id = ?", playerId)
}
// Only apply the isPlayoff filter if the parameter is actually present in the query string
if c.Query("isPlayoff") != "" {
isPlayoff := c.QueryBool("isPlayoff", false)
query = query.Where("is_playoff = ?", isPlayoff)
}
// Count total
// Count total records for pagination
var total int64
query.Count(&total)
// Fetch page
// Fetch the data page
err := query.Order(order).Limit(pageSize).Offset(offset).Find(&stats).Error
if err != nil {
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
}
// Build response
resp := AdvancedStatsResponse{Data: stats}
// --- MODIFICATION START ---
// Transform the database models into DTOs.
advancedStatDTOs := make([]PlayerAdvancedStatDTO, len(stats))
for i, s := range stats {
advancedStatDTOs[i] = PlayerAdvancedStatDTO{
PlayerID: s.PlayerID,
PlayerName: s.PlayerName,
Position: s.Position,
Age: s.Age,
Team: s.Team,
Games: s.Games,
MinutesPlayed: s.MinutesPlayed,
PER: s.PER,
TSPercent: s.TSPercent,
ThreePAR: s.ThreePAR,
FTr: s.FTR, // FIX: Changed s.FTr to s.FTR to match the model
OffensiveRBPercent: s.OffensiveRBPercent,
DefensiveRBPercent: s.DefensiveRBPercent,
TotalRBPercent: s.TotalRBPercent,
AssistPercent: s.AssistPercent,
StealPercent: s.StealPercent,
BlockPercent: s.BlockPercent,
TurnoverPercent: s.TurnoverPercent,
UsagePercent: s.UsagePercent,
OffensiveWS: s.OffensiveWS,
DefensiveWS: s.DefensiveWS,
WinShares: s.WinShares,
WinSharesPer: s.WinSharesPer,
OffensiveBox: s.OffensiveBox,
DefensiveBox: s.DefensiveBox,
Box: s.Box,
VORP: s.VORP,
Season: s.Season,
IsPlayoff: s.IsPlayoff,
}
}
// Build the final response using the new DTOs and response struct.
resp := AdvancedStatsResponse{
Data: advancedStatDTOs,
}
resp.Pagination.Total = total
resp.Pagination.Page = page
resp.Pagination.PageSize = pageSize
resp.Pagination.Pages = (total + int64(pageSize) - 1) / int64(pageSize)
return c.JSON(resp)
// --- MODIFICATION END ---
}
}