mirror of
https://github.com/nprasad2077/NBA_Go.git
synced 2026-09-22 14:05:13 +00:00
backend functioning. Player models init
This commit is contained in:
@@ -23,3 +23,9 @@ go.work.sum
|
|||||||
|
|
||||||
# env file
|
# env file
|
||||||
.env
|
.env
|
||||||
|
|
||||||
|
|
||||||
|
data/nba.db
|
||||||
|
/data/
|
||||||
|
/data
|
||||||
|
/data/*
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"gorm.io/driver/sqlite" // Or Postgres
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"github.com/nprasad2077/NBA_Go/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitDB() *gorm.DB {
|
||||||
|
db, err := gorm.Open(sqlite.Open("/Users/ravi/code/projects/NBA_Go/data/nba.db"), &gorm.Config{})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Failed to connect database")
|
||||||
|
}
|
||||||
|
|
||||||
|
db.AutoMigrate(&models.PlayerStat{})
|
||||||
|
|
||||||
|
return db
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"github.com/nprasad2077/NBA_Go/services"
|
||||||
|
"github.com/nprasad2077/NBA_Go/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
func FetchPlayerStats(db *gorm.DB) fiber.Handler {
|
||||||
|
return func(c *fiber.Ctx) error {
|
||||||
|
season := c.QueryInt("season", 2025)
|
||||||
|
|
||||||
|
// Call service and assign err here
|
||||||
|
err := services.FetchAndStorePlayerStats(db, season)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(fiber.Map{"message": "Player stats fetched and saved."})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func GetAllPlayerStats(db *gorm.DB) fiber.Handler {
|
||||||
|
return func(c *fiber.Ctx) error {
|
||||||
|
var stats []models.PlayerStat
|
||||||
|
|
||||||
|
if err := db.Find(&stats).Error; err != nil {
|
||||||
|
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(stats)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
module github.com/nprasad2077/NBA_Go
|
||||||
|
|
||||||
|
go 1.24.2
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/andybalholm/brotli v1.1.0 // indirect
|
||||||
|
github.com/gofiber/fiber/v2 v2.52.6 // indirect
|
||||||
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
|
github.com/klauspost/compress v1.17.9 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.22 // indirect
|
||||||
|
github.com/rivo/uniseg v0.2.0 // indirect
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
|
github.com/valyala/fasthttp v1.51.0 // indirect
|
||||||
|
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||||
|
golang.org/x/sys v0.28.0 // indirect
|
||||||
|
golang.org/x/text v0.20.0 // indirect
|
||||||
|
gorm.io/driver/sqlite v1.5.7 // indirect
|
||||||
|
gorm.io/gorm v1.26.0 // indirect
|
||||||
|
)
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||||
|
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||||
|
github.com/gofiber/fiber/v2 v2.52.6 h1:Rfp+ILPiYSvvVuIPvxrBns+HJp8qGLDnLJawAu27XVI=
|
||||||
|
github.com/gofiber/fiber/v2 v2.52.6/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||||
|
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
|
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||||
|
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
|
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||||
|
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||||
|
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
|
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||||
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
|
github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA=
|
||||||
|
github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g=
|
||||||
|
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||||
|
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||||
|
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
||||||
|
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
||||||
|
gorm.io/driver/sqlite v1.5.7 h1:8NvsrhP0ifM7LX9G4zPB97NwovUakUxc+2V2uuf3Z1I=
|
||||||
|
gorm.io/driver/sqlite v1.5.7/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4=
|
||||||
|
gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde h1:9DShaph9qhkIYw7QF91I/ynrr4cOO2PZra2PFD7Mfeg=
|
||||||
|
gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||||
|
gorm.io/gorm v1.26.0 h1:9lqQVPG5aNNS6AyHdRiwScAVnXHg/L/Srzx55G5fOgs=
|
||||||
|
gorm.io/gorm v1.26.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"github.com/nprasad2077/NBA_Go/config"
|
||||||
|
"github.com/nprasad2077/NBA_Go/routes"
|
||||||
|
"github.com/nprasad2077/NBA_Go/services"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := fiber.New()
|
||||||
|
db := config.InitDB()
|
||||||
|
|
||||||
|
// Automatically fetch player stats on startup
|
||||||
|
go func() {
|
||||||
|
if err := services.FetchAndStorePlayerStats(db, 2025); err != nil {
|
||||||
|
log.Println("Initial fetch failed:", err)
|
||||||
|
} else {
|
||||||
|
log.Println("Initial player stats fetch successful.")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
routes.RegisterPlayerRoutes(app, db)
|
||||||
|
app.Listen(":3001")
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import "gorm.io/gorm"
|
||||||
|
|
||||||
|
type PlayerStat struct {
|
||||||
|
gorm.Model
|
||||||
|
ExternalID int `json:"id"`
|
||||||
|
PlayerID string `gorm:"not null;uniqueIndex:idx_player_season_team" json:"playerId"`
|
||||||
|
PlayerName string `json:"playerName"`
|
||||||
|
Position string `json:"position"`
|
||||||
|
Age int `json:"age"`
|
||||||
|
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"`
|
||||||
|
Team string `gorm:"not null;uniqueIndex:idx_player_season_team" json:"team"`
|
||||||
|
Season int `gorm:"not null;uniqueIndex:idx_player_season_team" json:"season"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package routes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"github.com/nprasad2077/NBA_Go/controllers"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RegisterPlayerRoutes(app *fiber.App, db *gorm.DB) {
|
||||||
|
api := app.Group("/api/playerstats")
|
||||||
|
|
||||||
|
api.Get("/fetch", controllers.FetchPlayerStats(db))
|
||||||
|
api.Get("/", controllers.GetAllPlayerStats(db)) // ✅ Add this line
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"github.com/nprasad2077/NBA_Go/models"
|
||||||
|
"github.com/nprasad2077/NBA_Go/utils"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"gorm.io/gorm/clause"
|
||||||
|
)
|
||||||
|
|
||||||
|
func FetchAndStorePlayerStats(db *gorm.DB, season int) error {
|
||||||
|
url := fmt.Sprintf("http://rest.nbaapi.com/api/PlayerDataAdvanced/query?season=%d&sortBy=Points&ascending=false&pageNumber=1&pageSize=20", season)
|
||||||
|
|
||||||
|
body, err := utils.GetJSON(url)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var stats []models.PlayerStat
|
||||||
|
if err := json.Unmarshal(body, &stats); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, stat := range stats {
|
||||||
|
// Ensure the season is included from the query param
|
||||||
|
stat.Season = season
|
||||||
|
|
||||||
|
err := db.Clauses(clause.OnConflict{
|
||||||
|
Columns: []clause.Column{{Name: "player_id"}, {Name: "season"}, {Name: "team"}},
|
||||||
|
DoUpdates: clause.AssignmentColumns([]string{
|
||||||
|
"external_id", "player_name", "position", "age", "games",
|
||||||
|
"minutes_played", "per", "ts_percent", "three_par", "ftr",
|
||||||
|
"offensive_rb_percent", "defensive_rb_percent", "total_rb_percent",
|
||||||
|
"assist_percent", "steal_percent", "block_percent", "turnover_percent",
|
||||||
|
"usage_percent", "offensive_ws", "defensive_ws", "win_shares",
|
||||||
|
"win_shares_per", "offensive_box", "defensive_box", "box", "vorp",
|
||||||
|
}),
|
||||||
|
}).Create(&stat).Error
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed to upsert stat for playerId %s (%s): %v", stat.PlayerID, stat.Team, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetJSON(url string) ([]byte, error) {
|
||||||
|
client := &http.Client{Timeout: 10 * time.Second}
|
||||||
|
|
||||||
|
resp, err := client.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return nil, errors.New("received non-200 response: " + resp.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return body, nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user