Merge pull request #40 from nprasad2077/games

Games
This commit is contained in:
2025-08-06 03:21:06 -05:00
committed by GitHub
6 changed files with 840 additions and 395 deletions
+1 -2
View File
@@ -30,9 +30,8 @@ swag init -g main.go -o docs
go run loadtest.go -n 100 -c 10 -url "http://127.0.0.1:8080/api/playeradvancedstats?page=1&pageSize=20" -log results.log -key "xxx"
```
### Local Environment
```bash
docker-compose -f docker-compose.local.yml up --build -d
```
```
+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 ---
}
}
+127 -61
View File
@@ -1,15 +1,3 @@
// FetchPlayerTotalStats godoc
// @Summary Fetch player total stats from external API
// @Description Imports totals data and stores or updates in DB
// @Tags PlayerTotals
// @Accept json
// @Produce json
// @Param season query int false "Season (e.g. 2000)"
// @Param isPlayoff query bool false "Whether the stats are for playoffs"
// @Success 200 {object} map[string]string
// @Failure 500 {object} map[string]string
// @Router /api/playertotals/fetch [get]
package controllers
import (
@@ -19,6 +7,57 @@ import (
"gorm.io/gorm"
)
// --- MODIFICATION START ---
// A DTO is created to control the JSON output.
// It omits fields like ID, ExternalID, CreatedAt, UpdatedAt, and DeletedAt.
type PlayerTotalStatDTO struct {
PlayerID string `json:"playerId"`
PlayerName string `json:"playerName"`
Position string `json:"position"`
Age int `json:"age"`
Games int `json:"games"`
GamesStarted int `json:"gamesStarted"`
MinutesPG float64 `json:"minutesPg"`
FieldGoals int `json:"fieldGoals"`
FieldAttempts int `json:"fieldAttempts"`
FieldPercent float64 `json:"fieldPercent"`
ThreeFG int `json:"threeFg"`
ThreeAttempts int `json:"threeAttempts"`
ThreePercent float64 `json:"threePercent"`
TwoFG int `json:"twoFg"`
TwoAttempts int `json:"twoAttempts"`
TwoPercent float64 `json:"twoPercent"`
EffectFGPercent float64 `json:"effectFgPercent"`
FT int `json:"ft"`
FTAttempts int `json:"ftAttempts"`
FTPercent float64 `json:"ftPercent"`
OffensiveRB int `json:"offensiveRb"`
DefensiveRB int `json:"defensiveRb"`
TotalRB int `json:"totalRb"`
Assists int `json:"assists"`
Steals int `json:"steals"`
Blocks int `json:"blocks"`
Turnovers int `json:"turnovers"`
PersonalFouls int `json:"personalFouls"`
Points int `json:"points"`
Team string `json:"team"`
Season int `json:"season"`
IsPlayoff bool `json:"isPlayoff"`
}
// A dedicated response struct is created for cleaner, type-safe code.
type PlayerTotalsResponse struct {
Data []PlayerTotalStatDTO `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 totalSortMap = map[string]string{
"playerId": "player_id",
"playerName": "player_name",
@@ -53,29 +92,15 @@ var totalSortMap = map[string]string{
"season": "season",
}
// func FetchPlayerTotalStats(db *gorm.DB) fiber.Handler {
// return func(c *fiber.Ctx) error {
// season := c.QueryInt("season", 2025)
// isPlayoff := c.QueryBool("isPlayoff", false)
// err := services.FetchAndStorePlayerTotalStats(db, season, isPlayoff)
// if err != nil {
// return c.Status(500).JSON(fiber.Map{"error": err.Error()})
// }
// return c.JSON(fiber.Map{"message": "Player total stats fetched and saved."})
// }
// }
// ScrapePlayerTotalStats godoc
// @ignore
// @Summary Scrape player total stats from BR website
// @Tags PlayerTotals
// @Param season query int true "Season (e.g. 2025)"
// @Param isPlayoff query bool false "Whether playoffs?"
// @Success 200 {object} map[string]string
// @Failure 400,500 {object} map[string]string
// //@Router /api/playertotals/scrape [get]
// @Summary Scrape player total stats from BR website
// @Tags PlayerTotals
// @Param season query int true "Season (e.g. 2025)"
// @Param isPlayoff query bool false "Whether playoffs?"
// @Success 200 {object} map[string]string
// @Failure 400,500 {object} map[string]string
// //@Router /api/playertotals/scrape [get]
func ScrapePlayerTotalStats(db *gorm.DB) fiber.Handler {
return func(c *fiber.Ctx) error {
season := c.QueryInt("season", 0)
@@ -98,7 +123,7 @@ func ScrapePlayerTotalStats(db *gorm.DB) fiber.Handler {
// @Tags PlayerTotals
// @x-order 1
// @Group Player Stats
// @Accept json
// @Accept json
// @Produce json
// @Param season query int false "Season (e.g. 2000)"
// @Param team query string false "Team abbreviation (e.g. LAL)"
@@ -108,7 +133,7 @@ func ScrapePlayerTotalStats(db *gorm.DB) fiber.Handler {
// @Param sortBy query string false "Field to sort by (e.g. points, assists)"
// @Param ascending query bool false "Sort ascending (default false)"
// @Param isPlayoff query bool false "Whether the stats are for playoffs"
// @Success 200 {object} map[string]interface{}
// @Success 200 {object} controllers.PlayerTotalsResponse
// @Failure 500 {object} map[string]string
// @Router /api/playertotals [get]
func GetPlayerTotalStats(db *gorm.DB) fiber.Handler {
@@ -116,32 +141,31 @@ func GetPlayerTotalStats(db *gorm.DB) fiber.Handler {
var stats []models.PlayerTotalStat
// --- FILTERS ---
playerId := c.Query("playerId")
if playerId == "" {
playerId = c.Query("player_id")
}
playerId := c.Query("playerId")
if playerId == "" {
playerId = c.Query("player_id")
}
season := c.QueryInt("season", 0)
team := c.Query("team")
// playerId := c.Query("playerId")
page := c.QueryInt("page", 1)
pageSize := c.QueryInt("pageSize", 20)
// --- MODIFICATION FOR SORTING ---
sortByParam := c.Query("sortBy", "points")
ascending := c.QueryBool("ascending", false)
// --- SORTING ---
sortByParam := c.Query("sortBy", "points")
ascending := c.QueryBool("ascending", false)
// Translate sortBy param to a valid DB column, defaulting if not found.
sortBy, ok := totalSortMap[sortByParam]
if !ok {
sortBy = "points" // Safe default
}
sortBy, ok := totalSortMap[sortByParam]
if !ok {
sortBy = "points" // Safe default
}
offset := (page - 1) * pageSize
order := sortBy + " DESC"
if ascending {
order = sortBy + " ASC"
}
offset := (page - 1) * pageSize
order := sortBy + " DESC"
if ascending {
order = sortBy + " ASC"
}
query := db.Model(&models.PlayerTotalStat{})
@@ -169,14 +193,56 @@ func GetPlayerTotalStats(db *gorm.DB) fiber.Handler {
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
}
return c.JSON(fiber.Map{
"data": stats,
"pagination": fiber.Map{
"total": total,
"page": page,
"pageSize": pageSize,
"pages": (total + int64(pageSize) - 1) / int64(pageSize),
},
})
// --- MODIFICATION START ---
// Transform the database models into DTOs.
playerTotalDTOs := make([]PlayerTotalStatDTO, len(stats))
for i, s := range stats {
playerTotalDTOs[i] = PlayerTotalStatDTO{
PlayerID: s.PlayerID,
PlayerName: s.PlayerName,
Position: s.Position,
Age: s.Age,
Games: s.Games,
GamesStarted: s.GamesStarted,
MinutesPG: s.MinutesPG,
FieldGoals: s.FieldGoals,
FieldAttempts: s.FieldAttempts,
FieldPercent: s.FieldPercent,
ThreeFG: s.ThreeFG,
ThreeAttempts: s.ThreeAttempts,
ThreePercent: s.ThreePercent,
TwoFG: s.TwoFG,
TwoAttempts: s.TwoAttempts,
TwoPercent: s.TwoPercent,
EffectFGPercent: s.EffectFGPercent,
FT: s.FT,
FTAttempts: s.FTAttempts,
FTPercent: s.FTPercent,
OffensiveRB: s.OffensiveRB,
DefensiveRB: s.DefensiveRB,
TotalRB: s.TotalRB,
Assists: s.Assists,
Steals: s.Steals,
Blocks: s.Blocks,
Turnovers: s.Turnovers,
PersonalFouls: s.PersonalFouls,
Points: s.Points,
Team: s.Team,
Season: s.Season,
IsPlayoff: s.IsPlayoff,
}
}
// Build the final response using the new DTOs and response struct.
resp := PlayerTotalsResponse{
Data: playerTotalDTOs,
}
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 ---
}
}
+225 -104
View File
@@ -355,8 +355,7 @@ const docTemplate = `{
"200": {
"description": "OK",
"schema": {
"type": "object",
"additionalProperties": true
"$ref": "#/definitions/controllers.PlayerTotalsResponse"
}
},
"500": {
@@ -380,7 +379,7 @@ const docTemplate = `{
"data": {
"type": "array",
"items": {
"$ref": "#/definitions/models.PlayerAdvancedStat"
"$ref": "#/definitions/controllers.PlayerAdvancedStatDTO"
}
},
"pagination": {
@@ -408,9 +407,6 @@ const docTemplate = `{
"arena": {
"type": "string"
},
"boxScoreUrl": {
"type": "string"
},
"date": {
"type": "string"
},
@@ -418,6 +414,7 @@ const docTemplate = `{
"type": "string"
},
"gameId": {
"description": "ID uint ` + "`" + `json:\"id\"` + "`" + `",
"type": "string"
},
"homePts": {
@@ -426,13 +423,11 @@ const docTemplate = `{
"homeTeam": {
"type": "string"
},
"id": {
"type": "integer"
},
"isPlayoff": {
"type": "boolean"
},
"lineScores": {
"description": "BoxScoreURL string ` + "`" + `json:\"boxScoreUrl\"` + "`" + `",
"type": "array",
"items": {
"$ref": "#/definitions/controllers.LineScoreDTO"
@@ -534,6 +529,98 @@ const docTemplate = `{
}
}
},
"controllers.PlayerAdvancedStatDTO": {
"type": "object",
"properties": {
"age": {
"type": "integer"
},
"assistPercent": {
"type": "number"
},
"blockPercent": {
"type": "number"
},
"box": {
"type": "number"
},
"defensiveBox": {
"type": "number"
},
"defensiveRBPercent": {
"type": "number"
},
"defensiveWS": {
"type": "number"
},
"ftr": {
"type": "number"
},
"games": {
"type": "integer"
},
"isPlayoff": {
"type": "boolean"
},
"minutesPlayed": {
"type": "integer"
},
"offensiveBox": {
"type": "number"
},
"offensiveRBPercent": {
"type": "number"
},
"offensiveWS": {
"type": "number"
},
"per": {
"type": "number"
},
"playerId": {
"type": "string"
},
"playerName": {
"type": "string"
},
"position": {
"type": "string"
},
"season": {
"type": "integer"
},
"stealPercent": {
"type": "number"
},
"team": {
"type": "string"
},
"threePAR": {
"type": "number"
},
"totalRBPercent": {
"type": "number"
},
"tsPercent": {
"type": "number"
},
"turnoverPercent": {
"type": "number"
},
"usagePercent": {
"type": "number"
},
"vorp": {
"type": "number"
},
"winShares": {
"type": "number"
},
"winSharesPer": {
"type": "number"
}
}
},
"controllers.PlayerGameAdvStatDTO": {
"type": "object",
"properties": {
@@ -678,6 +765,135 @@ const docTemplate = `{
}
}
},
"controllers.PlayerTotalStatDTO": {
"type": "object",
"properties": {
"age": {
"type": "integer"
},
"assists": {
"type": "integer"
},
"blocks": {
"type": "integer"
},
"defensiveRb": {
"type": "integer"
},
"effectFgPercent": {
"type": "number"
},
"fieldAttempts": {
"type": "integer"
},
"fieldGoals": {
"type": "integer"
},
"fieldPercent": {
"type": "number"
},
"ft": {
"type": "integer"
},
"ftAttempts": {
"type": "integer"
},
"ftPercent": {
"type": "number"
},
"games": {
"type": "integer"
},
"gamesStarted": {
"type": "integer"
},
"isPlayoff": {
"type": "boolean"
},
"minutesPg": {
"type": "number"
},
"offensiveRb": {
"type": "integer"
},
"personalFouls": {
"type": "integer"
},
"playerId": {
"type": "string"
},
"playerName": {
"type": "string"
},
"points": {
"type": "integer"
},
"position": {
"type": "string"
},
"season": {
"type": "integer"
},
"steals": {
"type": "integer"
},
"team": {
"type": "string"
},
"threeAttempts": {
"type": "integer"
},
"threeFg": {
"type": "integer"
},
"threePercent": {
"type": "number"
},
"totalRb": {
"type": "integer"
},
"turnovers": {
"type": "integer"
},
"twoAttempts": {
"type": "integer"
},
"twoFg": {
"type": "integer"
},
"twoPercent": {
"type": "number"
}
}
},
"controllers.PlayerTotalsResponse": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/definitions/controllers.PlayerTotalStatDTO"
}
},
"pagination": {
"type": "object",
"properties": {
"page": {
"type": "integer"
},
"pageSize": {
"type": "integer"
},
"pages": {
"type": "integer"
},
"total": {
"type": "integer"
}
}
}
}
},
"controllers.TeamGameAdvStatDTO": {
"type": "object",
"properties": {
@@ -789,101 +1005,6 @@ const docTemplate = `{
}
}
},
"models.PlayerAdvancedStat": {
"type": "object",
"properties": {
"age": {
"type": "integer"
},
"assistPercent": {
"type": "number"
},
"blockPercent": {
"type": "number"
},
"box": {
"type": "number"
},
"defensiveBox": {
"type": "number"
},
"defensiveRBPercent": {
"type": "number"
},
"defensiveWS": {
"type": "number"
},
"ftr": {
"type": "number"
},
"games": {
"type": "integer"
},
"id": {
"type": "integer"
},
"isPlayoff": {
"type": "boolean"
},
"minutesPlayed": {
"type": "integer"
},
"offensiveBox": {
"type": "number"
},
"offensiveRBPercent": {
"type": "number"
},
"offensiveWS": {
"type": "number"
},
"per": {
"type": "number"
},
"playerId": {
"type": "string"
},
"playerName": {
"type": "string"
},
"position": {
"type": "string"
},
"season": {
"type": "integer"
},
"stealPercent": {
"type": "number"
},
"team": {
"type": "string"
},
"threePAR": {
"type": "number"
},
"totalRBPercent": {
"type": "number"
},
"tsPercent": {
"type": "number"
},
"turnoverPercent": {
"type": "number"
},
"usagePercent": {
"type": "number"
},
"vorp": {
"type": "number"
},
"winShares": {
"type": "number"
},
"winSharesPer": {
"type": "number"
}
}
},
"models.PlayerShotChart": {
"type": "object",
"properties": {
+225 -104
View File
@@ -352,8 +352,7 @@
"200": {
"description": "OK",
"schema": {
"type": "object",
"additionalProperties": true
"$ref": "#/definitions/controllers.PlayerTotalsResponse"
}
},
"500": {
@@ -377,7 +376,7 @@
"data": {
"type": "array",
"items": {
"$ref": "#/definitions/models.PlayerAdvancedStat"
"$ref": "#/definitions/controllers.PlayerAdvancedStatDTO"
}
},
"pagination": {
@@ -405,9 +404,6 @@
"arena": {
"type": "string"
},
"boxScoreUrl": {
"type": "string"
},
"date": {
"type": "string"
},
@@ -415,6 +411,7 @@
"type": "string"
},
"gameId": {
"description": "ID uint `json:\"id\"`",
"type": "string"
},
"homePts": {
@@ -423,13 +420,11 @@
"homeTeam": {
"type": "string"
},
"id": {
"type": "integer"
},
"isPlayoff": {
"type": "boolean"
},
"lineScores": {
"description": "BoxScoreURL string `json:\"boxScoreUrl\"`",
"type": "array",
"items": {
"$ref": "#/definitions/controllers.LineScoreDTO"
@@ -531,6 +526,98 @@
}
}
},
"controllers.PlayerAdvancedStatDTO": {
"type": "object",
"properties": {
"age": {
"type": "integer"
},
"assistPercent": {
"type": "number"
},
"blockPercent": {
"type": "number"
},
"box": {
"type": "number"
},
"defensiveBox": {
"type": "number"
},
"defensiveRBPercent": {
"type": "number"
},
"defensiveWS": {
"type": "number"
},
"ftr": {
"type": "number"
},
"games": {
"type": "integer"
},
"isPlayoff": {
"type": "boolean"
},
"minutesPlayed": {
"type": "integer"
},
"offensiveBox": {
"type": "number"
},
"offensiveRBPercent": {
"type": "number"
},
"offensiveWS": {
"type": "number"
},
"per": {
"type": "number"
},
"playerId": {
"type": "string"
},
"playerName": {
"type": "string"
},
"position": {
"type": "string"
},
"season": {
"type": "integer"
},
"stealPercent": {
"type": "number"
},
"team": {
"type": "string"
},
"threePAR": {
"type": "number"
},
"totalRBPercent": {
"type": "number"
},
"tsPercent": {
"type": "number"
},
"turnoverPercent": {
"type": "number"
},
"usagePercent": {
"type": "number"
},
"vorp": {
"type": "number"
},
"winShares": {
"type": "number"
},
"winSharesPer": {
"type": "number"
}
}
},
"controllers.PlayerGameAdvStatDTO": {
"type": "object",
"properties": {
@@ -675,6 +762,135 @@
}
}
},
"controllers.PlayerTotalStatDTO": {
"type": "object",
"properties": {
"age": {
"type": "integer"
},
"assists": {
"type": "integer"
},
"blocks": {
"type": "integer"
},
"defensiveRb": {
"type": "integer"
},
"effectFgPercent": {
"type": "number"
},
"fieldAttempts": {
"type": "integer"
},
"fieldGoals": {
"type": "integer"
},
"fieldPercent": {
"type": "number"
},
"ft": {
"type": "integer"
},
"ftAttempts": {
"type": "integer"
},
"ftPercent": {
"type": "number"
},
"games": {
"type": "integer"
},
"gamesStarted": {
"type": "integer"
},
"isPlayoff": {
"type": "boolean"
},
"minutesPg": {
"type": "number"
},
"offensiveRb": {
"type": "integer"
},
"personalFouls": {
"type": "integer"
},
"playerId": {
"type": "string"
},
"playerName": {
"type": "string"
},
"points": {
"type": "integer"
},
"position": {
"type": "string"
},
"season": {
"type": "integer"
},
"steals": {
"type": "integer"
},
"team": {
"type": "string"
},
"threeAttempts": {
"type": "integer"
},
"threeFg": {
"type": "integer"
},
"threePercent": {
"type": "number"
},
"totalRb": {
"type": "integer"
},
"turnovers": {
"type": "integer"
},
"twoAttempts": {
"type": "integer"
},
"twoFg": {
"type": "integer"
},
"twoPercent": {
"type": "number"
}
}
},
"controllers.PlayerTotalsResponse": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/definitions/controllers.PlayerTotalStatDTO"
}
},
"pagination": {
"type": "object",
"properties": {
"page": {
"type": "integer"
},
"pageSize": {
"type": "integer"
},
"pages": {
"type": "integer"
},
"total": {
"type": "integer"
}
}
}
}
},
"controllers.TeamGameAdvStatDTO": {
"type": "object",
"properties": {
@@ -786,101 +1002,6 @@
}
}
},
"models.PlayerAdvancedStat": {
"type": "object",
"properties": {
"age": {
"type": "integer"
},
"assistPercent": {
"type": "number"
},
"blockPercent": {
"type": "number"
},
"box": {
"type": "number"
},
"defensiveBox": {
"type": "number"
},
"defensiveRBPercent": {
"type": "number"
},
"defensiveWS": {
"type": "number"
},
"ftr": {
"type": "number"
},
"games": {
"type": "integer"
},
"id": {
"type": "integer"
},
"isPlayoff": {
"type": "boolean"
},
"minutesPlayed": {
"type": "integer"
},
"offensiveBox": {
"type": "number"
},
"offensiveRBPercent": {
"type": "number"
},
"offensiveWS": {
"type": "number"
},
"per": {
"type": "number"
},
"playerId": {
"type": "string"
},
"playerName": {
"type": "string"
},
"position": {
"type": "string"
},
"season": {
"type": "integer"
},
"stealPercent": {
"type": "number"
},
"team": {
"type": "string"
},
"threePAR": {
"type": "number"
},
"totalRBPercent": {
"type": "number"
},
"tsPercent": {
"type": "number"
},
"turnoverPercent": {
"type": "number"
},
"usagePercent": {
"type": "number"
},
"vorp": {
"type": "number"
},
"winShares": {
"type": "number"
},
"winSharesPer": {
"type": "number"
}
}
},
"models.PlayerShotChart": {
"type": "object",
"properties": {
+150 -70
View File
@@ -4,7 +4,7 @@ definitions:
properties:
data:
items:
$ref: '#/definitions/models.PlayerAdvancedStat'
$ref: '#/definitions/controllers.PlayerAdvancedStatDTO'
type: array
pagination:
properties:
@@ -22,23 +22,21 @@ definitions:
properties:
arena:
type: string
boxScoreUrl:
type: string
date:
type: string
gameDuration:
type: string
gameId:
description: ID uint `json:"id"`
type: string
homePts:
type: integer
homeTeam:
type: string
id:
type: integer
isPlayoff:
type: boolean
lineScores:
description: BoxScoreURL string `json:"boxScoreUrl"`
items:
$ref: '#/definitions/controllers.LineScoreDTO'
type: array
@@ -105,6 +103,67 @@ definitions:
total:
type: integer
type: object
controllers.PlayerAdvancedStatDTO:
properties:
age:
type: integer
assistPercent:
type: number
blockPercent:
type: number
box:
type: number
defensiveBox:
type: number
defensiveRBPercent:
type: number
defensiveWS:
type: number
ftr:
type: number
games:
type: integer
isPlayoff:
type: boolean
minutesPlayed:
type: integer
offensiveBox:
type: number
offensiveRBPercent:
type: number
offensiveWS:
type: number
per:
type: number
playerId:
type: string
playerName:
type: string
position:
type: string
season:
type: integer
stealPercent:
type: number
team:
type: string
threePAR:
type: number
totalRBPercent:
type: number
tsPercent:
type: number
turnoverPercent:
type: number
usagePercent:
type: number
vorp:
type: number
winShares:
type: number
winSharesPer:
type: number
type: object
controllers.PlayerGameAdvStatDTO:
properties:
astPercent:
@@ -201,6 +260,91 @@ definitions:
trb:
type: integer
type: object
controllers.PlayerTotalStatDTO:
properties:
age:
type: integer
assists:
type: integer
blocks:
type: integer
defensiveRb:
type: integer
effectFgPercent:
type: number
fieldAttempts:
type: integer
fieldGoals:
type: integer
fieldPercent:
type: number
ft:
type: integer
ftAttempts:
type: integer
ftPercent:
type: number
games:
type: integer
gamesStarted:
type: integer
isPlayoff:
type: boolean
minutesPg:
type: number
offensiveRb:
type: integer
personalFouls:
type: integer
playerId:
type: string
playerName:
type: string
points:
type: integer
position:
type: string
season:
type: integer
steals:
type: integer
team:
type: string
threeAttempts:
type: integer
threeFg:
type: integer
threePercent:
type: number
totalRb:
type: integer
turnovers:
type: integer
twoAttempts:
type: integer
twoFg:
type: integer
twoPercent:
type: number
type: object
controllers.PlayerTotalsResponse:
properties:
data:
items:
$ref: '#/definitions/controllers.PlayerTotalStatDTO'
type: array
pagination:
properties:
page:
type: integer
pageSize:
type: integer
pages:
type: integer
total:
type: integer
type: object
type: object
controllers.TeamGameAdvStatDTO:
properties:
astPercent:
@@ -275,69 +419,6 @@ definitions:
trb:
type: integer
type: object
models.PlayerAdvancedStat:
properties:
age:
type: integer
assistPercent:
type: number
blockPercent:
type: number
box:
type: number
defensiveBox:
type: number
defensiveRBPercent:
type: number
defensiveWS:
type: number
ftr:
type: number
games:
type: integer
id:
type: integer
isPlayoff:
type: boolean
minutesPlayed:
type: integer
offensiveBox:
type: number
offensiveRBPercent:
type: number
offensiveWS:
type: number
per:
type: number
playerId:
type: string
playerName:
type: string
position:
type: string
season:
type: integer
stealPercent:
type: number
team:
type: string
threePAR:
type: number
totalRBPercent:
type: number
tsPercent:
type: number
turnoverPercent:
type: number
usagePercent:
type: number
vorp:
type: number
winShares:
type: number
winSharesPer:
type: number
type: object
models.PlayerShotChart:
properties:
date:
@@ -614,8 +695,7 @@ paths:
"200":
description: OK
schema:
additionalProperties: true
type: object
$ref: '#/definitions/controllers.PlayerTotalsResponse'
"500":
description: Internal Server Error
schema: