mirror of
https://github.com/nprasad2077/NBA_Go.git
synced 2026-09-22 05:55:13 +00:00
go lint
This commit is contained in:
+26
-26
@@ -1,35 +1,35 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"github.com/nprasad2077/NBA_Go/models"
|
||||||
"gorm.io/driver/sqlite"
|
"github.com/nprasad2077/NBA_Go/utils/metrics"
|
||||||
"gorm.io/gorm"
|
"gorm.io/driver/sqlite"
|
||||||
"github.com/nprasad2077/NBA_Go/models"
|
"gorm.io/gorm"
|
||||||
"github.com/nprasad2077/NBA_Go/utils/metrics"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func InitDB(shouldMigrate bool) *gorm.DB {
|
func InitDB(shouldMigrate bool) *gorm.DB {
|
||||||
db, err := gorm.Open(sqlite.Open("/app/data/nba.db"), &gorm.Config{})
|
db, err := gorm.Open(sqlite.Open("/app/data/nba.db"), &gorm.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to connect database: %v", err)
|
log.Fatalf("failed to connect database: %v", err)
|
||||||
}
|
}
|
||||||
metrics.DBOperationsTotal.WithLabelValues("connect", "database").Inc()
|
metrics.DBOperationsTotal.WithLabelValues("connect", "database").Inc()
|
||||||
|
|
||||||
if shouldMigrate {
|
if shouldMigrate {
|
||||||
if err := db.AutoMigrate(&models.PlayerAdvancedStat{}); err != nil {
|
if err := db.AutoMigrate(&models.PlayerAdvancedStat{}); err != nil {
|
||||||
log.Fatalf("migrate PlayerAdvancedStat: %v", err)
|
log.Fatalf("migrate PlayerAdvancedStat: %v", err)
|
||||||
}
|
}
|
||||||
if err := db.AutoMigrate(&models.PlayerTotalStat{}); err != nil {
|
if err := db.AutoMigrate(&models.PlayerTotalStat{}); err != nil {
|
||||||
log.Fatalf("migrate PlayerTotalStat: %v", err)
|
log.Fatalf("migrate PlayerTotalStat: %v", err)
|
||||||
}
|
}
|
||||||
if err := db.AutoMigrate(&models.PlayerShotChart{}); err != nil {
|
if err := db.AutoMigrate(&models.PlayerShotChart{}); err != nil {
|
||||||
log.Fatalf("migrate PlayerShotChart: %v", err)
|
log.Fatalf("migrate PlayerShotChart: %v", err)
|
||||||
}
|
}
|
||||||
if err := db.AutoMigrate(&models.APIKey{}); err != nil {
|
if err := db.AutoMigrate(&models.APIKey{}); err != nil {
|
||||||
log.Fatalf("migrate APIKey: %v", err)
|
log.Fatalf("migrate APIKey: %v", err)
|
||||||
}
|
}
|
||||||
metrics.DBOperationsTotal.WithLabelValues("migrate", "database").Inc()
|
metrics.DBOperationsTotal.WithLabelValues("migrate", "database").Inc()
|
||||||
}
|
}
|
||||||
|
|
||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
@@ -44,18 +44,18 @@ type AdvancedStatsResponse struct {
|
|||||||
// @Failure 400,500 {object} map[string]string
|
// @Failure 400,500 {object} map[string]string
|
||||||
// @Router /api/playeradvancedstats/scrape [get]
|
// @Router /api/playeradvancedstats/scrape [get]
|
||||||
func ScrapePlayerAdvancedStats(db *gorm.DB) fiber.Handler {
|
func ScrapePlayerAdvancedStats(db *gorm.DB) fiber.Handler {
|
||||||
return func(c *fiber.Ctx) error {
|
return func(c *fiber.Ctx) error {
|
||||||
season := c.QueryInt("season", 0)
|
season := c.QueryInt("season", 0)
|
||||||
if season == 0 {
|
if season == 0 {
|
||||||
return c.Status(400).JSON(fiber.Map{"error":"season is required"})
|
return c.Status(400).JSON(fiber.Map{"error": "season is required"})
|
||||||
}
|
}
|
||||||
isPlayoff := c.QueryBool("isPlayoff", false)
|
isPlayoff := c.QueryBool("isPlayoff", false)
|
||||||
|
|
||||||
if err := services.FetchAndStorePlayerAdvancedScrapedStats(db, season, isPlayoff); err != nil {
|
if err := services.FetchAndStorePlayerAdvancedScrapedStats(db, season, isPlayoff); err != nil {
|
||||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||||
}
|
}
|
||||||
return c.JSON(fiber.Map{"message":"scrape+store complete"})
|
return c.JSON(fiber.Map{"message": "scrape+store complete"})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllAdvancedPlayerStats godoc
|
// GetAllAdvancedPlayerStats godoc
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"github.com/nprasad2077/NBA_Go/models"
|
"github.com/nprasad2077/NBA_Go/models"
|
||||||
"github.com/nprasad2077/NBA_Go/services"
|
"github.com/nprasad2077/NBA_Go/services"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FetchPlayerShotChartAPI godoc
|
// FetchPlayerShotChartAPI godoc
|
||||||
@@ -32,7 +32,9 @@ import (
|
|||||||
// ScrapePlayerShotChart godoc
|
// ScrapePlayerShotChart godoc
|
||||||
// @Summary Scrape a player's shot-chart from BR website
|
// @Summary Scrape a player's shot-chart from BR website
|
||||||
// @Description Scrapes seasons [startSeason…endSeason] for the given playerId
|
// @Description Scrapes seasons [startSeason…endSeason] for the given playerId
|
||||||
// (playerName is auto-detected).
|
//
|
||||||
|
// (playerName is auto-detected).
|
||||||
|
//
|
||||||
// @Tags PlayerShotChart
|
// @Tags PlayerShotChart
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
@@ -43,25 +45,25 @@ import (
|
|||||||
// @Failure 400,500 {object} map[string]string
|
// @Failure 400,500 {object} map[string]string
|
||||||
// @Router /api/playershotchart/scrape [get]
|
// @Router /api/playershotchart/scrape [get]
|
||||||
func ScrapePlayerShotChart(db *gorm.DB) fiber.Handler {
|
func ScrapePlayerShotChart(db *gorm.DB) fiber.Handler {
|
||||||
return func(c *fiber.Ctx) error {
|
return func(c *fiber.Ctx) error {
|
||||||
pid := c.Query("playerId")
|
pid := c.Query("playerId")
|
||||||
start := c.QueryInt("startSeason", 0)
|
start := c.QueryInt("startSeason", 0)
|
||||||
end := c.QueryInt("endSeason", 0)
|
end := c.QueryInt("endSeason", 0)
|
||||||
if pid == "" || start == 0 || end == 0 {
|
if pid == "" || start == 0 || end == 0 {
|
||||||
return c.Status(400).JSON(fiber.Map{
|
return c.Status(400).JSON(fiber.Map{
|
||||||
"error": "playerId, startSeason and endSeason are required",
|
"error": "playerId, startSeason and endSeason are required",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if start < end {
|
if start < end {
|
||||||
return c.Status(400).JSON(fiber.Map{
|
return c.Status(400).JSON(fiber.Map{
|
||||||
"error": "startSeason must be >= endSeason",
|
"error": "startSeason must be >= endSeason",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if err := services.FetchAndStoreShotChartScrapedForPlayer(db, pid, start, end); err != nil {
|
if err := services.FetchAndStoreShotChartScrapedForPlayer(db, pid, start, end); err != nil {
|
||||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||||
}
|
}
|
||||||
return c.JSON(fiber.Map{"message": "Shot chart scraped and saved for " + pid})
|
return c.JSON(fiber.Map{"message": "Shot chart scraped and saved for " + pid})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPlayerShotChart godoc
|
// GetPlayerShotChart godoc
|
||||||
@@ -77,21 +79,21 @@ func ScrapePlayerShotChart(db *gorm.DB) fiber.Handler {
|
|||||||
// @Failure 500 {object} map[string]string
|
// @Failure 500 {object} map[string]string
|
||||||
// @Router /api/playershotchart [get]
|
// @Router /api/playershotchart [get]
|
||||||
func GetPlayerShotChart(db *gorm.DB) fiber.Handler {
|
func GetPlayerShotChart(db *gorm.DB) fiber.Handler {
|
||||||
return func(c *fiber.Ctx) error {
|
return func(c *fiber.Ctx) error {
|
||||||
var shots []models.PlayerShotChart
|
var shots []models.PlayerShotChart
|
||||||
|
|
||||||
query := db.Model(&models.PlayerShotChart{})
|
query := db.Model(&models.PlayerShotChart{})
|
||||||
|
|
||||||
if pid := c.Query("playerId"); pid != "" {
|
if pid := c.Query("playerId"); pid != "" {
|
||||||
query = query.Where("player_id = ?", pid)
|
query = query.Where("player_id = ?", pid)
|
||||||
}
|
}
|
||||||
if s := c.QueryInt("season", 0); s != 0 {
|
if s := c.QueryInt("season", 0); s != 0 {
|
||||||
query = query.Where("season = ?", s)
|
query = query.Where("season = ?", s)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := query.Find(&shots).Error; err != nil {
|
if err := query.Find(&shots).Error; err != nil {
|
||||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||||
}
|
}
|
||||||
return c.JSON(shots)
|
return c.JSON(shots)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14,9 +14,9 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"github.com/nprasad2077/NBA_Go/models"
|
||||||
"github.com/nprasad2077/NBA_Go/services"
|
"github.com/nprasad2077/NBA_Go/services"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"github.com/nprasad2077/NBA_Go/models"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// func FetchPlayerTotalStats(db *gorm.DB) fiber.Handler {
|
// func FetchPlayerTotalStats(db *gorm.DB) fiber.Handler {
|
||||||
@@ -42,21 +42,20 @@ import (
|
|||||||
// @Failure 400,500 {object} map[string]string
|
// @Failure 400,500 {object} map[string]string
|
||||||
// @Router /api/playertotals/scrape [get]
|
// @Router /api/playertotals/scrape [get]
|
||||||
func ScrapePlayerTotalStats(db *gorm.DB) fiber.Handler {
|
func ScrapePlayerTotalStats(db *gorm.DB) fiber.Handler {
|
||||||
return func(c *fiber.Ctx) error {
|
return func(c *fiber.Ctx) error {
|
||||||
season := c.QueryInt("season", 0)
|
season := c.QueryInt("season", 0)
|
||||||
if season == 0 {
|
if season == 0 {
|
||||||
return c.Status(400).JSON(fiber.Map{"error":"season is required"})
|
return c.Status(400).JSON(fiber.Map{"error": "season is required"})
|
||||||
}
|
}
|
||||||
isPlayoff := c.QueryBool("isPlayoff", false)
|
isPlayoff := c.QueryBool("isPlayoff", false)
|
||||||
|
|
||||||
if err := services.FetchAndStorePlayerTotalScrapedStats(db, season, isPlayoff); err != nil {
|
if err := services.FetchAndStorePlayerTotalScrapedStats(db, season, isPlayoff); err != nil {
|
||||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||||
}
|
}
|
||||||
return c.JSON(fiber.Map{"message":"scrapestore complete"})
|
return c.JSON(fiber.Map{"message": "scrapestore complete"})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// GetPlayerTotalStats godoc
|
// GetPlayerTotalStats godoc
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Summary Get player total stats
|
// @Summary Get player total stats
|
||||||
|
|||||||
+13
-13
@@ -2,25 +2,25 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// Seed the RNG once when the package is initialized
|
// Seed the RNG once when the package is initialized
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
}
|
}
|
||||||
|
|
||||||
// SleepWithJitter sleeps for the given base duration plus or minus 25% random jitter.
|
// SleepWithJitter sleeps for the given base duration plus or minus 25% random jitter.
|
||||||
// It also logs the actual sleep duration so you can verify it fired correctly.
|
// It also logs the actual sleep duration so you can verify it fired correctly.
|
||||||
func SleepWithJitter(base time.Duration) {
|
func SleepWithJitter(base time.Duration) {
|
||||||
half := base / 2
|
half := base / 2
|
||||||
// Random value in [0, half)
|
// Random value in [0, half)
|
||||||
randOffset := time.Duration(rand.Int63n(int64(half)))
|
randOffset := time.Duration(rand.Int63n(int64(half)))
|
||||||
// Shift to center jitter around zero: [-half/2, +half/2)
|
// Shift to center jitter around zero: [-half/2, +half/2)
|
||||||
delta := randOffset - half/2
|
delta := randOffset - half/2
|
||||||
actual := base + delta
|
actual := base + delta
|
||||||
log.Printf("⏱️ Sleeping for %v (base=%v, jitter=%v)", actual, base, delta)
|
log.Printf("⏱️ Sleeping for %v (base=%v, jitter=%v)", actual, base, delta)
|
||||||
time.Sleep(actual)
|
time.Sleep(actual)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user