From e63862c943aef2508ed3ff58abeda190f8086d5c Mon Sep 17 00:00:00 2001 From: Ravi Prasad Date: Tue, 13 May 2025 17:43:08 -0500 Subject: [PATCH] totals data service update --- Dockerfile | 2 +- controllers/player_total_controller.go | 23 +++ go.mod | 10 +- go.sum | 57 ++++++ isolated_scrape.go | 103 +++++++++++ routes/player_total_routes.go | 1 + scrape_shotchart.go | 226 ++++++++++++++++++++++++ scrape_totals.go | 128 ++++++++++++++ services/player_total_scrape_service.go | 171 ++++++++++++++++++ totals_2025.csv | 215 ++++++++++++++++++++++ 10 files changed, 931 insertions(+), 5 deletions(-) create mode 100644 isolated_scrape.go create mode 100644 scrape_shotchart.go create mode 100644 scrape_totals.go create mode 100644 services/player_total_scrape_service.go create mode 100644 totals_2025.csv diff --git a/Dockerfile b/Dockerfile index 2aeeeca..9a592d0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # STEP 1 - build with CGO enabled -FROM golang:1.22-bullseye AS builder +FROM golang:1.24-bullseye AS builder ENV CGO_ENABLED=1 ENV GOOS=linux diff --git a/controllers/player_total_controller.go b/controllers/player_total_controller.go index bb137a8..71a0858 100644 --- a/controllers/player_total_controller.go +++ b/controllers/player_total_controller.go @@ -33,6 +33,29 @@ func FetchPlayerTotalStats(db *gorm.DB) fiber.Handler { } } +// ScrapePlayerTotalStats godoc +// @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) + if season == 0 { + return c.Status(400).JSON(fiber.Map{"error":"season is required"}) + } + isPlayoff := c.QueryBool("isPlayoff", false) + + if err := services.FetchAndStorePlayerTotalScrapedStats(db, season, isPlayoff); err != nil { + return c.Status(500).JSON(fiber.Map{"error": err.Error()}) + } + return c.JSON(fiber.Map{"message":"scrapestore complete"}) + } +} + // GetPlayerTotalStats godoc // @Security ApiKeyAuth diff --git a/go.mod b/go.mod index 0c01d8e..b823e78 100644 --- a/go.mod +++ b/go.mod @@ -1,14 +1,16 @@ module github.com/nprasad2077/NBA_Go -go 1.22 +go 1.23.0 toolchain go1.24.2 require ( github.com/KyleBanks/depth v1.2.1 // indirect + github.com/PuerkitoBio/goquery v1.10.3 // indirect github.com/PuerkitoBio/purell v1.1.1 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/andybalholm/brotli v1.1.0 // indirect + github.com/andybalholm/cascadia v1.3.3 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -41,9 +43,9 @@ require ( 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/net v0.33.0 // indirect - golang.org/x/sys v0.30.0 // indirect - golang.org/x/text v0.21.0 // indirect + golang.org/x/net v0.39.0 // indirect + golang.org/x/sys v0.32.0 // indirect + golang.org/x/text v0.24.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/protobuf v1.36.5 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index c450334..20f8b43 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= +github.com/PuerkitoBio/goquery v1.10.3 h1:pFYcNSqHxBD06Fpj/KsbStFRsgRATgnf3LeXiUkhzPo= +github.com/PuerkitoBio/goquery v1.10.3/go.mod h1:tMUX0zDMHXYlAQk6p35XxQMqMweEKB7iK7iLNd4RH4Y= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= @@ -9,6 +11,8 @@ github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaW github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM= +github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= @@ -32,6 +36,7 @@ github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/ github.com/gofiber/fiber/v2 v2.32.0/go.mod h1:CMy5ZLiXkn6qwthrl03YMyW1NLfj0rhxz2LKl4t7ZTY= 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/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -112,23 +117,48 @@ github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdI github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= +golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -138,25 +168,52 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 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= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= +golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/isolated_scrape.go b/isolated_scrape.go new file mode 100644 index 0000000..b0de76c --- /dev/null +++ b/isolated_scrape.go @@ -0,0 +1,103 @@ +//go:build ignore +// +build ignore + +package main + +import ( + "encoding/csv" + "flag" + "fmt" + "net/http" + "os" + // "strconv" + "strings" + + "github.com/PuerkitoBio/goquery" +) + +func main() { + season := flag.Int("season", 0, "NBA season year (e.g. 2024)") + outPath := flag.String("out", "", "output CSV file path (default: stdout)") + flag.Parse() + + if *season == 0 { + fmt.Fprintln(os.Stderr, "❌ must provide -season, e.g. -season=2024") + os.Exit(1) + } + + url := fmt.Sprintf("https://www.basketball-reference.com/leagues/NBA_%d_advanced.html", *season) + fmt.Println("Fetching:", url) + resp, err := http.Get(url) + if err != nil { + fmt.Fprintln(os.Stderr, "HTTP error:", err) + os.Exit(1) + } + defer resp.Body.Close() + + doc, err := goquery.NewDocumentFromReader(resp.Body) + if err != nil { + fmt.Fprintln(os.Stderr, "Parse error:", err) + os.Exit(1) + } + + // --- Extract headers --- + var headers []string + doc.Find("#div_advanced table#advanced thead tr th").EachWithBreak(func(i int, s *goquery.Selection) bool { + // grab first 29 columns, then we'll append our own PlayerID + text := strings.TrimSpace(s.Text()) + if i < 29 { + headers = append(headers, text) + return true + } + return false + }) + headers = append(headers, "Player-additional") + + // --- Extract data rows --- + var rows [][]string + doc.Find("#div_advanced table#advanced tbody tr").Each(func(_ int, row *goquery.Selection) { + if row.HasClass("thead") { // skip repeated headers + return + } + // rank in + vals := []string{strings.TrimSpace(row.Find("th").Text())} + row.Find("td").Each(func(__ int, cell *goquery.Selection) { + vals = append(vals, strings.TrimSpace(cell.Text())) + }) + if id, ok := row.Find("td[data-append-csv]").Attr("data-append-csv"); ok { + vals = append(vals, id) + rows = append(rows, vals) + } + }) + + // open writer + var w *csv.Writer + if *outPath != "" { + f, err := os.Create(*outPath) + if err != nil { + fmt.Fprintln(os.Stderr, "Could not create file:", err) + os.Exit(1) + } + defer f.Close() + w = csv.NewWriter(f) + } else { + w = csv.NewWriter(os.Stdout) + } + // write header + rows + w.Write(headers) + for _, r := range rows { + w.Write(r) + } + w.Flush() + if err := w.Error(); err != nil { + fmt.Fprintln(os.Stderr, "CSV write error:", err) + os.Exit(1) + } + + // also print first 5 records to console + fmt.Println("\nFirst 5 rows:") + for i := 0; i < len(rows) && i < 5; i++ { + fmt.Println(rows[i]) + } + fmt.Printf("\n✅ Wrote %d rows\n", len(rows)) +} \ No newline at end of file diff --git a/routes/player_total_routes.go b/routes/player_total_routes.go index 49d2ea9..30a4559 100644 --- a/routes/player_total_routes.go +++ b/routes/player_total_routes.go @@ -10,5 +10,6 @@ func RegisterPlayerTotalRoutes(app *fiber.App, db *gorm.DB) { api := app.Group("/api/playertotals") api.Get("/fetch", controllers.FetchPlayerTotalStats(db)) + api.Get("/scrape", controllers.ScrapePlayerTotalStats(db)) api.Get("/", controllers.GetPlayerTotalStats(db)) } \ No newline at end of file diff --git a/scrape_shotchart.go b/scrape_shotchart.go new file mode 100644 index 0000000..49a4e85 --- /dev/null +++ b/scrape_shotchart.go @@ -0,0 +1,226 @@ +//go:build ignore +// +build ignore + +package main + +import ( + "bytes" + "encoding/csv" + "flag" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "strconv" + "strings" + + "github.com/PuerkitoBio/goquery" + "golang.org/x/net/html" +) + +func main() { + playerID := flag.String("playerid", "", "Basketball-Reference player ID (e.g. derozde01)") + playerName := flag.String("playername", "", "Player name for file naming (e.g. \"DeMar DeRozan\")") + startSeason := flag.Int("start", 0, "Recent start season (e.g. 2024)") + endSeason := flag.Int("end", 0, "Rookie/end season (e.g. 2021)") + outDir := flag.String("outdir", "", "If set, write CSV files into this directory; otherwise stdout") + flag.Parse() + + if *playerID == "" || *playerName == "" || *startSeason == 0 || *endSeason == 0 { + fmt.Fprintln(os.Stderr, "❌ must provide -playerid, -playername, -start and -end") + os.Exit(1) + } + if *startSeason < *endSeason { + fmt.Fprintln(os.Stderr, "❌ start must be >= end") + os.Exit(1) + } + + for season := *startSeason; season >= *endSeason; season-- { + url := fmt.Sprintf( + "https://www.basketball-reference.com/players/%s/%s/shooting/%d", + (*playerID)[:1], *playerID, season, + ) + fmt.Println("Fetching:", url) + + // Build a real-browser request + client := &http.Client{} + req, err := http.NewRequest("GET", url, nil) + if err != nil { + fmt.Fprintf(os.Stderr, "Request creation error for season %d: %v\n", season, err) + continue + } + req.Header.Set("User-Agent", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "+ + "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36", + ) + + resp, err := client.Do(req) + if err != nil { + fmt.Fprintf(os.Stderr, "HTTP error for %d: %v\n", season, err) + continue + } + bodyBytes, err := io.ReadAll(resp.Body) + resp.Body.Close() + if err != nil { + fmt.Fprintf(os.Stderr, "Read error for %d: %v\n", season, err) + continue + } + + // Parse the full HTML to find the commented-out shot-chart block + shotHTML := extractCommentedShotChart(bodyBytes) + if shotHTML == "" { + fmt.Fprintf(os.Stderr, "❌ no shot‐chart comment found for %d\n", season) + continue + } + + // Now parse that snippet + doc, err := goquery.NewDocumentFromReader(strings.NewReader(shotHTML)) + if err != nil { + fmt.Fprintf(os.Stderr, "Parse error for %d: %v\n", season, err) + continue + } + + // grab the shot-wrapper inside the commented HTML + wrapper := doc.Find("div#div_shot-chart div#shot-wrapper") + if wrapper.Length() == 0 { + fmt.Fprintf(os.Stderr, "❌ no shot‐wrapper found in comment for %d\n", season) + continue + } + + shots := wrapper.Find("div.tooltip.make, div.tooltip.miss") + var rows [][]string + shots.Each(func(_ int, s *goquery.Selection) { + style, _ := s.Attr("style") + tip, _ := s.Attr("tip") + + // parse top/left + parts := strings.Split(style, ";") + topVal := parsePx(parts[0]) + leftVal:= parsePx(parts[1]) + + tipParts := strings.Split(tip, "
") + // date, team code, opponent + dateSegs := strings.SplitN(tipParts[0], ", ", 3) + date := dateSegs[0] + "," + dateSegs[1] + team := "" + if len(dateSegs) == 3 { + team = dateSegs[2] + } + opponent := "" + if parts := strings.SplitN(tipParts[0], " at ", 2); len(parts) == 2 { + opponent = parts[1] + } else if parts := strings.SplitN(tipParts[0], " vs ", 2); len(parts) == 2 { + opponent = parts[1] + } + + // quarter & time + qt := strings.SplitN(tipParts[1], ",", 2) + quarter := qt[0] + timeRem := strings.Fields(qt[1])[0] + + // result, shot type, distance + rt := strings.Fields(tipParts[2]) + result := (rt[0] == "Made") + shotType := rt[1] + distance := parseInt(rt[len(rt)-2]) + + // scores + last := strings.Fields(tipParts[3]) + sc := strings.Split(last[len(last)-1], "-") + teamScore := parseInt(sc[0]) + opponentScore := parseInt(sc[1]) + lead := teamScore > opponentScore + + rows = append(rows, []string{ + *playerName, + fmt.Sprint(topVal), + fmt.Sprint(leftVal), + date, + quarter, + timeRem, + fmt.Sprint(result), + shotType, + fmt.Sprint(distance), + fmt.Sprint(lead), + fmt.Sprint(teamScore), + fmt.Sprint(opponentScore), + opponent, + team, + fmt.Sprint(season), + *playerID, + }) + }) + + headers := []string{ + "playerName","top","left","date","qtr","timeRemaining", + "result","shotType","distanceFt","lead", + "teamScore","opponentTeamScore","opponent","team","season","playerId", + } + + var w *csv.Writer + if *outDir != "" { + os.MkdirAll(*outDir, 0755) + fname := filepath.Join(*outDir, + fmt.Sprintf("%s_%d_shotchart.csv", *playerID, season), + ) + f, err := os.Create(fname) + if err != nil { + fmt.Fprintf(os.Stderr, "Could not create %s: %v\n", fname, err) + continue + } + defer f.Close() + w = csv.NewWriter(f) + fmt.Printf("→ Writing %d rows to %s\n", len(rows), fname) + } else { + w = csv.NewWriter(os.Stdout) + } + + w.Write(headers) + for _, r := range rows { + w.Write(r) + } + w.Flush() + if err := w.Error(); err != nil { + fmt.Fprintf(os.Stderr, "CSV error: %v\n", err) + } + + fmt.Printf("\nFirst 5 rows for %d:\n", season) + for i := 0; i < len(rows) && i < 5; i++ { + fmt.Println(rows[i]) + } + fmt.Printf("✅ Season %d: %d total shots\n\n", season, len(rows)) + } +} + +// extractCommentedShotChart scans the HTML for a comment node containing +// the div#div_shot-chart block, and returns its inner HTML. +func extractCommentedShotChart(htmlBytes []byte) string { + root, err := html.Parse(bytes.NewReader(htmlBytes)) + if err != nil { + return "" + } + var found string + var f func(*html.Node) + f = func(n *html.Node) { + if n.Type == html.CommentNode && strings.Contains(n.Data, `id="div_shot-chart"`) { + found = n.Data + return + } + for c := n.FirstChild; c != nil && found == ""; c = c.NextSibling { + f(c) + } + } + f(root) + return found +} + +func parsePx(s string) int { + parts := strings.Split(s, ":") + return parseInt(strings.TrimSuffix(parts[1], "px")) +} + +func parseInt(s string) int { + v, _ := strconv.Atoi(strings.TrimSpace(s)) + return v +} \ No newline at end of file diff --git a/scrape_totals.go b/scrape_totals.go new file mode 100644 index 0000000..000abb5 --- /dev/null +++ b/scrape_totals.go @@ -0,0 +1,128 @@ +//go:build ignore +// +build ignore + + +package main + +import ( + "bytes" + "encoding/csv" + "flag" + "fmt" + "io" + "net/http" + "os" + "strings" + + "github.com/PuerkitoBio/goquery" +) + +func main() { + season := flag.Int("season", 0, "NBA season year (e.g. 2024)") + outPath := flag.String("out", "", "output CSV file path (default stdout)") + flag.Parse() + + if *season == 0 { + fmt.Fprintln(os.Stderr, "❌ must provide -season") + os.Exit(1) + } + + url := fmt.Sprintf("https://www.basketball-reference.com/playoffs/NBA_%d_totals.html", *season) + fmt.Println("Fetching:", url) + + // pretend to be a real browser + client := &http.Client{} + req, err := http.NewRequest("GET", url, nil) + if err != nil { + fmt.Fprintln(os.Stderr, "Request error:", err) + os.Exit(1) + } + req.Header.Set("User-Agent", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "+ + "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36", + ) + resp, err := client.Do(req) + if err != nil { + fmt.Fprintln(os.Stderr, "HTTP error:", err) + os.Exit(1) + } + body, err := io.ReadAll(resp.Body) + resp.Body.Close() + if err != nil { + fmt.Fprintln(os.Stderr, "Read error:", err) + os.Exit(1) + } + + doc, err := goquery.NewDocumentFromReader(bytes.NewReader(body)) + if err != nil { + fmt.Fprintln(os.Stderr, "Parse error:", err) + os.Exit(1) + } + + table := doc.Find("table#totals_stats") + if table.Length() == 0 { + fmt.Fprintln(os.Stderr, "❌ could not find table with id 'totals_stats'") + os.Exit(1) + } + + // Extract headers + var headers []string + table.Find("thead tr th").Each(func(_ int, th *goquery.Selection) { + if stat, exists := th.Attr("data-stat"); exists && stat != "" { + headers = append(headers, stat) + } + }) + // ensure player-additional + headers = append(headers, "player-additional") + + // Extract rows + var rows [][]string + table.Find("tbody tr").Each(func(_ int, tr *goquery.Selection) { + if cl, _ := tr.Attr("class"); strings.Contains(cl, "thead") { + return + } + var row []string + var playerID string + tr.Find("th, td").Each(func(_ int, cell *goquery.Selection) { + row = append(row, strings.TrimSpace(cell.Text())) + if id, ok := cell.Attr("data-append-csv"); ok { + playerID = id + } + }) + if playerID != "" { + row = append(row, playerID) + rows = append(rows, row) + } + }) + + // open writer + var w *csv.Writer + if *outPath != "" { + f, err := os.Create(*outPath) + if err != nil { + fmt.Fprintln(os.Stderr, "Could not create file:", err) + os.Exit(1) + } + defer f.Close() + w = csv.NewWriter(f) + fmt.Printf("→ Writing %d rows to %s\n", len(rows), *outPath) + } else { + w = csv.NewWriter(os.Stdout) + } + + // write CSV + w.Write(headers) + for _, r := range rows { + w.Write(r) + } + w.Flush() + if err := w.Error(); err != nil { + fmt.Fprintln(os.Stderr, "CSV write error:", err) + os.Exit(1) + } + fmt.Println("First 5 rows:") + for i := 0; i < len(rows) && i < 5; i++ { + fmt.Println(rows[i]) + } + fmt.Printf("✅ Wrote %d rows for season %d\n", len(rows), *season) +} \ No newline at end of file diff --git a/services/player_total_scrape_service.go b/services/player_total_scrape_service.go new file mode 100644 index 0000000..6c33990 --- /dev/null +++ b/services/player_total_scrape_service.go @@ -0,0 +1,171 @@ +// File: NBA_Go/services/player_total_scrape_service.go + +package services + +import ( + "bytes" + "fmt" + "io" + "log" + "net/http" + "strconv" + "strings" + + "github.com/PuerkitoBio/goquery" + "github.com/nprasad2077/NBA_Go/models" + "gorm.io/gorm" + "gorm.io/gorm/clause" +) + +const ( + regularURLFmt = "https://www.basketball-reference.com/leagues/NBA_%d_totals.html" + playoffURLFmt = "https://www.basketball-reference.com/playoffs/NBA_%d_totals.html" +) + +// urlForSeason chooses regular vs. playoff URL. +func urlForSeason(season int, isPlayoff bool) string { + if isPlayoff { + return fmt.Sprintf(playoffURLFmt, season) + } + return fmt.Sprintf(regularURLFmt, season) +} + +// FetchAndStorePlayerTotalScrapedStats scrapes BR totals (regular or playoffs) +// and upserts into PlayerTotalStat. +func FetchAndStorePlayerTotalScrapedStats(db *gorm.DB, season int, isPlayoff bool) error { + url := urlForSeason(season, isPlayoff) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return err + } + req.Header.Set("User-Agent", "Mozilla/5.0 (compatible)") + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + doc, err := goquery.NewDocumentFromReader(bytes.NewReader(body)) + if err != nil { + return err + } + + table := doc.Find("table#totals_stats") + if table.Length() == 0 { + return fmt.Errorf("could not find table#totals_stats") + } + + // 1) collect the data-stat keys in header order + var headers []string + table.Find("thead tr th").Each(func(i int, th *goquery.Selection) { + if stat, ok := th.Attr("data-stat"); ok && stat != "" { + headers = append(headers, stat) + } + }) + // add the appended-player column + headers = append(headers, "player-additional") + + // 2) iterate rows + table.Find("tbody tr").Each(func(_ int, tr *goquery.Selection) { + if cl, _ := tr.Attr("class"); strings.Contains(cl, "thead") { + return // skip header rows + } + + cells := tr.Find("th, td") + data := make(map[string]string, len(headers)) + var playerID string + + cells.Each(func(i int, cell *goquery.Selection) { + text := strings.TrimSpace(cell.Text()) + key := headers[i] + data[key] = text + if id, ok := cell.Attr("data-append-csv"); ok { + playerID = id + } + }) + if playerID == "" { + return + } + data["player-additional"] = playerID + + // 3) map into GORM model + stat := models.PlayerTotalStat{ + ExternalID: mustAtoi(data["rk"]), + PlayerID: playerID, + PlayerName: data["player"], + Position: data["pos"], + Age: mustAtoi(data["age"]), + Games: mustAtoi(data["g"]), + GamesStarted: mustAtoi(data["gs"]), + MinutesPG: mustParseFloat(data["mp"]), // TOTAL minutes as float + FieldGoals: mustAtoi(data["fg"]), + FieldAttempts: mustAtoi(data["fga"]), + FieldPercent: mustParseFloat(data["fg_pct"]), + ThreeFG: mustAtoi(data["fg3"]), + ThreeAttempts: mustAtoi(data["fg3a"]), + ThreePercent: mustParseFloat(data["fg3_pct"]), + TwoFG: mustAtoi(data["fg2"]), + TwoAttempts: mustAtoi(data["fg2a"]), + TwoPercent: mustParseFloat(data["fg2_pct"]), + EffectFGPercent: mustParseFloat(data["efg_pct"]), + FT: mustAtoi(data["ft"]), + FTAttempts: mustAtoi(data["fta"]), + FTPercent: mustParseFloat(data["ft_pct"]), + OffensiveRB: mustAtoi(data["orb"]), + DefensiveRB: mustAtoi(data["drb"]), + TotalRB: mustAtoi(data["trb"]), + Assists: mustAtoi(data["ast"]), + Steals: mustAtoi(data["stl"]), + Blocks: mustAtoi(data["blk"]), + Turnovers: mustAtoi(data["tov"]), + PersonalFouls: mustAtoi(data["pf"]), + Points: mustAtoi(data["pts"]), + Team: data["team_id"], + Season: season, + IsPlayoff: isPlayoff, + } + + // 4) upsert on (player_id, season, team, is_playoff) + if err := db.Clauses(clause.OnConflict{ + Columns: []clause.Column{ + {Name: "player_id"}, + {Name: "season"}, + {Name: "team"}, + {Name: "is_playoff"}, + }, + DoUpdates: clause.AssignmentColumns([]string{ + "external_id", "player_name", "position", "age", + "games", "games_started", "minutes_pg", + "field_goals", "field_attempts", "field_percent", + "three_fg", "three_attempts", "three_percent", + "two_fg", "two_attempts", "two_percent", + "effect_fg_percent", + "ft", "ft_attempts", "ft_percent", + "offensive_rb", "defensive_rb", "total_rb", + "assists", "steals", "blocks", "turnovers", + "personal_fouls", "points", + }), + }).Create(&stat).Error; err != nil { + log.Printf("Failed upsert for %s: %v", stat.PlayerID, err) + } + }) + + return nil +} + +// mustAtoi parses integer or returns 0 +func mustAtoi(s string) int { + i, _ := strconv.Atoi(s) + return i +} + +// mustParseFloat parses float or returns 0.0 +func mustParseFloat(s string) float64 { + f, _ := strconv.ParseFloat(s, 64) + return f +} \ No newline at end of file diff --git a/totals_2025.csv b/totals_2025.csv new file mode 100644 index 0000000..a3bae3b --- /dev/null +++ b/totals_2025.csv @@ -0,0 +1,215 @@ +ranker,player,pos,age,team_id,g,gs,mp,fg,fga,fg_pct,fg3,fg3a,fg3_pct,fg2,fg2a,fg2_pct,efg_pct,ft,fta,ft_pct,orb,drb,trb,ast,stl,blk,tov,pf,pts,player-additional +1,Precious Achiuwa,C,25,NYK,3,0,12,3,6,.500,0,0,,3,6,.500,.500,0,1,.000,1,2,3,0,0,0,0,1,6,achiupr01 +2,Steven Adams,C,31,HOU,7,0,155,12,20,.600,0,0,,12,20,.600,.600,16,30,.533,23,23,46,4,3,8,5,7,40,adamsst01 +3,Bam Adebayo,C,27,MIA,4,4,153,28,64,.438,7,21,.333,21,43,.488,.492,7,11,.636,16,28,44,17,4,1,12,9,70,adebaba01 +4,Santi Aldama,PF,24,MEM,4,1,122,21,44,.477,10,24,.417,11,20,.550,.591,0,0,,2,22,24,7,0,1,5,7,52,aldamsa01 +5,Nickeil Alexander-Walker,SG,26,MIN,9,0,175,21,59,.356,10,33,.303,11,26,.423,.441,11,12,.917,2,12,14,20,4,3,14,14,63,alexani01 +6,Jarrett Allen,C,26,CLE,8,8,231,40,55,.727,0,0,,40,55,.727,.727,32,33,.970,20,52,72,12,12,8,15,14,112,allenja01 +7,Kyle Anderson,SF,31,MIA,2,0,14,0,2,.000,0,0,,0,2,.000,.000,0,0,,0,1,1,1,0,0,1,1,0,anderky01 +8,Giannis Antetokounmpo,PF,30,MIL,5,5,188,60,99,.606,1,5,.200,59,94,.628,.611,44,63,.698,19,58,77,33,5,5,23,12,165,antetgi01 +9,Cole Anthony,PG,24,ORL,5,0,51,4,14,.286,0,6,.000,4,8,.500,.286,3,4,.750,3,4,7,6,0,1,9,12,11,anthoco01 +10,OG Anunoby,PF,27,NYK,10,10,407,57,134,.425,24,62,.387,33,72,.458,.515,22,25,.880,13,30,43,11,20,9,17,26,160,anunoog01 +11,Marvin Bagley III,PF,25,MEM,2,0,28,8,9,.889,1,1,1.000,7,8,.875,.944,0,0,,2,4,6,0,2,1,3,3,17,baglema01 +12,Paolo Banchero,PF,22,ORL,5,5,197,54,124,.435,12,27,.444,42,97,.433,.484,27,41,.659,12,30,42,21,3,4,15,18,147,banchpa01 +13,Desmond Bane,SG,26,MEM,4,4,139,20,63,.317,7,32,.219,13,31,.419,.373,14,15,.933,5,22,27,13,3,2,15,9,61,banede01 +14,Nicolas Batum,PF,36,LAC,7,0,172,13,33,.394,13,33,.394,0,0,,.591,0,0,,4,23,27,14,6,12,3,13,39,batumni01 +15,Malik Beasley,SG,28,DET,6,0,163,28,75,.373,20,59,.339,8,16,.500,.507,8,8,1.000,1,14,15,7,3,1,7,10,84,beaslma01 +16,Goga Bitadze,C,25,ORL,3,0,11,1,1,1.000,0,0,,1,1,1.000,1.000,0,0,,0,3,3,1,0,1,0,6,2,bitadgo01 +17,Anthony Black,PG,21,ORL,5,0,89,15,37,.405,2,13,.154,13,24,.542,.432,9,13,.692,10,12,22,0,4,1,2,8,41,blackan01 +18,Bogdan Bogdanović,SG,32,LAC,7,0,117,16,44,.364,7,24,.292,9,20,.450,.443,6,7,.857,5,15,20,15,3,0,11,25,45,bogdabo01 +19,Tony Bradley,C,27,IND,4,0,16,0,1,.000,0,0,,0,1,.000,.000,0,0,,2,4,6,2,0,0,0,0,0,bradlto01 +20,Christian Braun,SG,23,DEN,11,11,429,49,108,.454,14,48,.292,35,60,.583,.519,15,23,.652,20,48,68,23,12,7,9,37,127,braunch01 +21,Mikal Bridges,SF,28,NYK,10,10,408,66,146,.452,16,55,.291,50,91,.549,.507,6,7,.857,9,44,53,28,21,10,19,20,154,bridgmi01 +22,Dillon Brooks,SF,29,HOU,7,7,206,28,63,.444,10,29,.345,18,34,.529,.524,20,24,.833,9,13,22,9,5,2,9,27,86,brookdi01 +23,Jaylen Brown,SF,28,BOS,9,9,333,69,158,.437,15,49,.306,54,109,.495,.484,44,56,.786,11,53,64,25,9,2,30,27,197,brownja02 +24,Kobe Brown,PF,25,LAC,3,0,15,7,8,.875,1,1,1.000,6,7,.857,.938,1,1,1.000,0,1,1,4,0,0,0,0,16,brownko01 +25,Jalen Brunson,PG,28,NYK,10,10,401,103,237,.435,29,79,.367,74,158,.468,.496,66,81,.815,10,30,40,80,5,3,27,32,301,brunsja01 +26,Thomas Bryant,C,27,IND,9,0,89,5,11,.455,3,6,.500,2,5,.400,.591,5,6,.833,5,11,16,3,3,4,6,11,18,bryanth01 +27,Alec Burks,SG,33,MIA,1,1,15,2,3,.667,2,3,.667,0,0,,1.000,0,0,,0,2,2,2,0,0,0,0,6,burksal01 +28,Jimmy Butler,SF,35,GSW,10,10,355,64,141,.454,11,33,.333,53,108,.491,.493,55,69,.797,23,44,67,51,11,3,12,17,194,butleji01 +29,Kentavious Caldwell-Pope,SG,31,ORL,5,5,163,8,30,.267,6,23,.261,2,7,.286,.367,3,4,.750,1,14,15,9,7,3,2,11,25,caldwke01 +30,Vlatko Čančar,PF,27,DEN,3,0,11,0,0,,0,0,,0,0,,,0,0,,0,2,2,0,0,0,2,0,0,cancavl01 +31,Wendell Carter Jr.,C,25,ORL,5,5,162,21,40,.525,3,11,.273,18,29,.621,.563,6,10,.600,19,35,54,6,2,2,8,12,51,cartewe01 +32,Alex Caruso,SG,30,OKC,8,0,170,23,53,.434,14,34,.412,9,19,.474,.566,8,13,.615,5,18,23,25,15,6,5,15,68,carusal01 +33,Cam Christie,SG,19,LAC,3,0,13,2,3,.667,1,2,.500,1,1,1.000,.833,0,0,,0,2,2,0,1,0,1,0,5,chrisca02 +34,Jaylen Clark,SG,23,MIN,2,0,6,0,0,,0,0,,0,0,,,2,2,1.000,0,1,1,0,1,0,1,2,2,clarkja02 +35,Mike Conley,PG,37,MIN,9,9,217,17,56,.304,10,33,.303,7,23,.304,.393,8,9,.889,11,16,27,30,5,1,6,13,52,conlemi01 +36,Pat Connaughton,SG,32,MIL,3,0,14,2,8,.250,1,4,.250,1,4,.250,.313,1,2,.500,0,2,2,1,0,0,1,1,6,connapa01 +37,Torrey Craig,SF,34,BOS,3,0,8,1,1,1.000,1,1,1.000,0,0,,1.500,0,0,,0,0,0,0,1,0,1,0,3,craigto01 +38,Cade Cunningham,PG,23,DET,6,6,248,55,129,.426,5,28,.179,50,101,.495,.446,35,42,.833,6,44,50,52,11,8,32,20,150,cunnica01 +39,Stephen Curry,PG,36,GSW,8,8,281,62,130,.477,32,80,.400,30,50,.600,.600,25,28,.893,2,40,42,41,8,6,27,13,181,curryst01 +40,Tristan Da Silva,SF,23,ORL,2,0,5,0,1,.000,0,1,.000,0,0,,.000,0,0,,0,4,4,1,0,0,2,0,0,dasiltr01 +41,JD Davison,PG,22,BOS,2,0,5,0,4,.000,0,1,.000,0,3,.000,.000,0,0,,1,2,3,2,0,0,0,0,0,davisjd01 +42,Ousmane Dieng,C,21,OKC,1,0,8,0,3,.000,0,1,.000,0,2,.000,.000,2,2,1.000,0,2,2,1,0,0,0,0,2,diengou01 +43,Donte DiVincenzo,SG,28,MIN,9,0,232,24,80,.300,12,52,.231,12,28,.429,.375,7,9,.778,9,21,30,29,13,3,18,31,67,divindo01 +44,Luka Dončić,PG,25,LAL,5,5,208,47,104,.452,16,46,.348,31,58,.534,.529,41,46,.891,2,33,35,29,5,3,20,16,151,doncilu01 +45,Luguentz Dort,SF,25,OKC,8,8,227,19,64,.297,14,55,.255,5,9,.556,.406,9,12,.750,11,18,29,6,6,5,5,26,61,dortlu01 +46,Kris Dunn,PG,30,LAC,7,6,153,17,44,.386,10,28,.357,7,16,.438,.500,0,0,,10,14,24,9,8,4,1,18,44,dunnkr01 +47,Jalen Duren,C,21,DET,6,6,203,26,40,.650,0,0,,26,40,.650,.650,19,23,.826,26,38,64,21,2,10,10,26,71,durenja01 +48,Tari Eason,PF,23,HOU,7,0,132,21,44,.477,7,19,.368,14,25,.560,.557,4,8,.500,7,23,30,5,8,7,10,13,53,easonta01 +49,Zach Edey,C,22,MEM,4,4,108,10,15,.667,0,0,,10,15,.667,.667,5,7,.714,11,20,31,7,0,10,6,12,25,edeyza01 +50,Anthony Edwards,SG,23,MIN,9,9,358,86,196,.439,30,82,.366,56,114,.491,.515,41,55,.745,13,60,73,47,14,5,16,17,243,edwaran01 +51,Drew Eubanks,C,27,LAC,3,0,13,0,2,.000,0,0,,0,2,.000,.000,4,6,.667,0,1,1,0,0,0,0,2,4,eubandr01 +52,Dorian Finney-Smith,PF,31,LAL,5,1,170,12,29,.414,7,19,.368,5,10,.500,.534,0,0,,10,11,21,13,1,2,5,17,31,finnedo01 +53,Johnny Furphy,SG,20,IND,5,0,21,0,3,.000,0,2,.000,0,1,.000,.000,0,0,,1,3,4,1,0,1,0,5,0,furphjo01 +54,Darius Garland,PG,25,CLE,4,4,115,25,53,.472,10,29,.345,15,24,.625,.566,19,20,.950,1,6,7,23,2,0,10,13,79,garlada01 +55,Luka Garza,C,26,MIN,2,0,5,1,1,1.000,0,0,,1,1,1.000,1.000,0,0,,1,0,1,0,0,0,0,1,2,garzalu01 +56,Shai Gilgeous-Alexander,PG,26,OKC,8,8,293,75,172,.436,11,47,.234,64,125,.512,.468,60,70,.857,14,39,53,53,11,5,15,22,221,gilgesh01 +57,Rudy Gobert,C,32,MIN,9,9,253,26,47,.553,0,0,,26,47,.553,.553,20,34,.588,32,56,88,3,5,12,9,26,72,goberru01 +58,Jordan Goodwin,PG,26,LAL,4,0,31,1,5,.200,0,2,.000,1,3,.333,.200,1,2,.500,2,3,5,2,1,1,1,7,3,goodwjo01 +59,Aaron Gordon,PF,29,DEN,11,11,422,71,143,.497,19,46,.413,52,97,.536,.563,40,46,.870,42,41,83,28,6,5,18,31,201,gordoaa01 +60,A.J. Green,SG,25,MIL,5,1,135,18,39,.462,18,35,.514,0,4,.000,.692,1,2,.500,2,12,14,10,0,1,0,13,55,greenaj01 +61,Draymond Green,PF,34,GSW,11,11,353,38,97,.392,15,54,.278,23,43,.535,.469,8,11,.727,7,53,60,40,16,11,33,40,99,greendr01 +62,Jalen Green,SG,22,HOU,7,7,219,32,86,.372,13,44,.295,19,42,.452,.448,16,24,.667,3,35,38,20,4,2,10,6,93,greenja05 +63,Javonte Green,SG,31,CLE,6,0,39,4,10,.400,1,5,.200,3,5,.600,.450,6,6,1.000,1,8,9,2,4,0,2,2,15,greenja02 +64,Jeff Green,PF,38,HOU,3,0,5,1,3,.333,1,1,1.000,0,2,.000,.500,0,0,,1,0,1,0,0,0,0,0,3,greenje02 +65,Rui Hachimura,PF,26,LAL,5,5,182,28,57,.491,15,31,.484,13,26,.500,.623,3,3,1.000,4,19,23,5,3,3,7,12,74,hachiru01 +66,Tyrese Haliburton,PG,24,IND,9,9,305,53,118,.449,16,55,.291,37,63,.587,.517,22,28,.786,3,46,49,85,6,8,17,13,144,halibty01 +67,Tim Hardaway Jr.,SG,32,DET,6,6,188,24,71,.338,16,52,.308,8,19,.421,.451,8,10,.800,2,15,17,7,2,0,9,10,72,hardati02 +68,James Harden,PG,35,LAC,7,7,276,44,101,.436,16,44,.364,28,57,.491,.515,27,33,.818,4,34,38,64,9,7,21,16,131,hardeja01 +69,Gary Harris,SG,30,ORL,5,0,83,3,8,.375,1,6,.167,2,2,1.000,.438,0,0,,1,4,5,3,3,1,0,7,7,harriga01 +70,Tobias Harris,PF,32,DET,6,6,233,34,71,.479,10,23,.435,24,48,.500,.549,16,16,1.000,8,38,46,3,6,7,6,16,94,harrito02 +71,Josh Hart,SG,29,NYK,10,10,375,44,90,.489,12,31,.387,32,59,.542,.556,24,32,.750,24,60,84,49,12,9,19,33,124,hartjo01 +72,Isaiah Hartenstein,C,26,OKC,8,8,209,36,65,.554,0,0,,36,65,.554,.554,8,12,.667,28,48,76,28,8,5,12,25,80,harteis01 +73,Sam Hauser,PF,27,BOS,6,0,78,6,13,.462,4,11,.364,2,2,1.000,.615,0,0,,0,8,8,2,1,1,3,7,16,hausesa01 +74,Jaxson Hayes,C,24,LAL,4,4,31,3,8,.375,0,0,,3,8,.375,.375,1,2,.500,5,3,8,1,0,1,1,8,7,hayesja02 +75,Tyler Herro,SG,25,MIA,4,4,144,27,65,.415,9,29,.310,18,36,.500,.485,8,10,.800,0,14,14,11,2,0,9,12,71,herroty01 +76,Buddy Hield,SG,32,GSW,11,8,298,50,116,.431,33,73,.452,17,43,.395,.573,9,10,.900,16,22,38,20,12,5,9,19,142,hieldbu01 +77,Haywood Highsmith,SF,28,MIA,4,0,84,11,19,.579,7,15,.467,4,4,1.000,.763,0,0,,4,9,13,4,3,2,4,11,29,highsha01 +78,Aaron Holiday,PG,28,HOU,3,0,27,4,10,.400,2,5,.400,2,5,.400,.500,2,4,.500,1,1,2,3,0,0,1,3,12,holidaa01 +79,Jrue Holiday,PG,34,BOS,6,6,202,23,44,.523,7,21,.333,16,23,.696,.602,5,6,.833,9,13,22,26,6,1,13,18,58,holidjr01 +80,Ron Holland,SF,19,DET,5,0,34,0,5,.000,0,3,.000,0,2,.000,.000,9,10,.900,3,3,6,0,0,1,6,5,9,hollaro01 +81,Chet Holmgren,C,22,OKC,8,8,239,41,98,.418,14,41,.341,27,57,.474,.490,31,37,.838,14,63,77,7,7,20,10,16,127,holmgch01 +82,Al Horford,C,38,BOS,9,7,297,25,58,.431,10,28,.357,15,30,.500,.517,6,7,.857,16,43,59,18,7,13,5,23,66,horfoal01 +83,Caleb Houstan,SF,22,ORL,5,0,47,2,14,.143,2,10,.200,0,4,.000,.214,0,0,,2,2,4,1,0,1,2,3,6,houstca01 +84,Jett Howard,SF,21,ORL,1,0,4,2,2,1.000,2,2,1.000,0,0,,1.500,0,0,,0,0,0,0,0,0,0,1,6,howarje01 +85,Jay Huff,C,26,MEM,2,0,18,2,4,.500,0,1,.000,2,3,.667,.500,4,4,1.000,1,2,3,1,0,3,1,1,8,huffja01 +86,Ariel Hukporti,C,22,NYK,1,0,2,1,1,1.000,0,0,,1,1,1.000,1.000,0,0,,0,2,2,0,0,0,0,0,2,hukpoar01 +87,De'Andre Hunter,SF,27,CLE,7,0,155,22,51,.431,10,22,.455,12,29,.414,.529,22,25,.880,4,20,24,7,3,1,7,13,76,huntede01 +88,Jonathan Isaac,PF,27,ORL,5,0,69,7,12,.583,1,4,.250,6,8,.750,.625,3,5,.600,5,5,10,2,2,1,2,3,18,isaacjo01 +89,Andre Jackson Jr.,SG,23,MIL,2,0,5,0,1,.000,0,1,.000,0,0,,.000,0,0,,0,0,0,0,0,0,0,0,0,jacksan01 +90,Jaren Jackson Jr.,C,25,MEM,4,4,137,22,58,.379,3,11,.273,19,47,.404,.405,17,20,.850,9,11,20,6,4,2,11,14,64,jacksja02 +91,Trayce Jackson-Davis,C,24,GSW,8,2,73,15,17,.882,0,0,,15,17,.882,.882,5,13,.385,7,12,19,2,2,2,1,15,35,jackstr02 +92,Bronny James,SG,20,LAL,2,0,4,0,2,.000,0,2,.000,0,0,,.000,0,0,,0,0,0,0,0,0,0,0,0,jamesbr02 +93,LeBron James,SF,40,LAL,5,5,204,43,88,.489,10,28,.357,33,60,.550,.545,31,40,.775,12,33,45,28,10,9,13,8,127,jamesle01 +94,Jaime Jaquez Jr.,SF,23,MIA,3,0,19,1,6,.167,0,2,.000,1,4,.250,.167,2,2,1.000,3,1,4,1,0,0,1,1,4,jaqueja01 +95,Ty Jerome,SG,27,CLE,8,1,180,34,87,.391,12,33,.364,22,54,.407,.460,17,20,.850,5,17,22,30,4,1,11,13,97,jeromty01 +96,Isaiah Joe,SG,25,OKC,8,0,105,18,38,.474,12,31,.387,6,7,.857,.632,3,4,.750,6,5,11,10,4,0,4,5,51,joeis01 +97,James Johnson,PF,37,IND,2,0,13,2,3,.667,0,1,.000,2,2,1.000,.667,1,2,.500,0,1,1,2,2,2,1,1,5,johnsja01 +98,Keshad Johnson,SF,23,MIA,2,0,8,1,1,1.000,0,0,,1,1,1.000,1.000,0,0,,1,0,1,0,0,0,1,1,2,johnske10 +99,Nikola Jokić,C,29,DEN,11,11,441,100,220,.455,20,59,.339,80,161,.497,.500,54,73,.740,21,119,140,92,24,11,47,37,274,jokicni01 +100,Derrick Jones Jr.,SF,27,LAC,7,1,129,21,48,.438,6,20,.300,15,28,.536,.500,3,8,.375,5,8,13,2,4,9,3,3,51,jonesde02 +101,Dillon Jones,SF,23,OKC,2,0,16,2,3,.667,0,1,.000,2,2,1.000,.667,2,2,1.000,0,2,2,1,0,1,2,1,6,jonesdi01 +102,DeAndre Jordan,C,36,DEN,7,0,36,3,3,1.000,0,0,,3,3,1.000,1.000,0,4,.000,1,8,9,2,0,1,2,9,6,jordade01 +103,Cory Joseph,PG,33,ORL,5,5,124,10,24,.417,5,16,.313,5,8,.625,.521,0,0,,1,8,9,15,5,2,2,10,25,josepco01 +104,Nikola Jović,PF,21,MIA,4,0,75,13,35,.371,6,24,.250,7,11,.636,.457,6,6,1.000,4,12,16,6,3,1,5,2,38,jovicni01 +105,Luke Kennard,SG,28,MEM,4,0,80,8,18,.444,2,9,.222,6,9,.667,.500,0,0,,2,12,14,8,4,1,6,3,18,kennalu01 +106,Braxton Key,SF,27,GSW,5,0,23,1,8,.125,0,1,.000,1,7,.143,.125,0,0,,5,4,9,1,2,2,3,4,2,keybr01 +107,Maxi Kleber,PF,33,LAL,1,0,5,0,1,.000,0,1,.000,0,0,,.000,2,2,1.000,0,0,0,0,0,0,1,1,2,klebima01 +108,Dalton Knecht,SF,23,LAL,2,0,4,2,5,.400,1,4,.250,1,1,1.000,.500,0,0,,2,1,3,0,0,0,0,0,5,knechda01 +109,Kevin Knox,SF,25,GSW,5,0,38,8,20,.400,1,6,.167,7,14,.500,.425,4,5,.800,3,4,7,4,0,1,2,2,21,knoxke01 +110,John Konchar,SG,28,MEM,4,0,69,3,9,.333,1,6,.167,2,3,.667,.389,4,4,1.000,3,10,13,6,2,2,2,8,11,konchjo01 +111,Luke Kornet,C,29,BOS,9,0,134,14,21,.667,0,0,,14,21,.667,.667,7,7,1.000,12,17,29,3,5,5,3,14,35,kornelu01 +112,Jonathan Kuminga,PF,22,GSW,7,1,155,34,70,.486,7,16,.438,27,54,.500,.536,21,28,.750,6,11,17,10,2,4,11,11,96,kuminjo01 +113,Kyle Kuzma,PF,29,MIL,5,4,102,12,35,.343,2,10,.200,10,25,.400,.371,3,6,.500,3,8,11,4,0,1,3,12,29,kuzmaky01 +114,Jock Landale,C,29,HOU,1,0,5,1,2,.500,0,0,,1,2,.500,.500,0,0,,0,0,0,0,0,0,0,0,2,landajo01 +115,Pelle Larsson,SG,23,MIA,4,0,52,8,15,.533,3,8,.375,5,7,.714,.633,1,3,.333,2,7,9,4,1,0,2,6,20,larsspe01 +116,Alex Len,C,31,LAL,2,0,4,0,1,.000,0,0,,0,1,.000,.000,0,0,,3,1,4,0,0,0,0,0,0,lenal01 +117,Kawhi Leonard,SF,33,LAC,7,7,265,66,123,.537,15,37,.405,51,86,.593,.598,28,36,.778,11,42,53,33,8,5,15,12,175,leonaka01 +118,Damian Lillard,PG,34,MIL,3,3,75,6,27,.222,3,16,.188,3,11,.273,.278,6,7,.857,1,7,8,14,2,2,3,8,21,lillada01 +119,Chris Livingston,SF,21,MIL,2,0,5,0,1,.000,0,1,.000,0,0,,.000,0,0,,0,1,1,0,0,0,0,0,0,livinch01 +120,Kevon Looney,C,28,GSW,11,0,114,10,23,.435,0,0,,10,23,.435,.435,6,8,.750,16,24,40,3,5,4,2,27,26,looneke01 +121,Brook Lopez,C,36,MIL,5,4,74,8,22,.364,4,15,.267,4,7,.571,.455,5,5,1.000,3,5,8,4,1,5,4,11,25,lopezbr01 +122,Bennedict Mathurin,SF,22,IND,8,0,144,28,59,.475,9,31,.290,19,28,.679,.551,29,33,.879,4,16,20,5,5,1,10,19,94,mathube01 +123,Miles McBride,PG,24,NYK,10,0,171,18,48,.375,12,32,.375,6,16,.375,.500,2,4,.500,0,10,10,8,4,0,5,10,50,mcbrimi01 +124,T.J. McConnell,PG,32,IND,9,0,156,36,68,.529,3,6,.500,33,62,.532,.551,11,12,.917,5,24,29,42,4,0,12,8,86,mccontj01 +125,Jaden McDaniels,PF,24,MIN,9,9,319,56,98,.571,10,26,.385,46,72,.639,.622,18,21,.857,17,40,57,11,10,8,8,30,140,mcdanja02 +126,Sam Merrill,SG,28,CLE,8,3,159,15,40,.375,14,39,.359,1,1,1.000,.550,2,3,.667,7,13,20,14,4,2,2,18,46,merrisa01 +127,Jordan Miller,SF,25,LAC,3,0,13,3,7,.429,0,1,.000,3,6,.500,.429,1,2,.500,0,2,2,4,3,0,0,0,7,millejo02 +128,Leonard Miller,SF,21,MIN,2,0,5,1,2,.500,0,0,,1,2,.500,.500,0,0,,1,1,2,0,0,0,0,0,2,millele01 +129,Patty Mills,PG,36,LAC,1,0,4,1,2,.500,1,1,1.000,0,1,.000,.750,0,0,,0,0,0,0,0,0,1,1,3,millspa02 +130,Shake Milton,SG,28,LAL,2,0,4,0,1,.000,0,0,,0,1,.000,.000,0,0,,0,0,0,0,0,0,0,1,0,miltosh01 +131,Josh Minott,SF,22,MIN,2,0,6,1,3,.333,0,2,.000,1,1,1.000,.333,0,0,,0,0,0,1,0,0,0,0,2,minotjo01 +132,Ajay Mitchell,SG,22,OKC,3,0,30,6,13,.462,3,6,.500,3,7,.429,.577,1,2,.500,0,2,2,2,1,0,1,4,16,mitchaj01 +133,Davion Mitchell,PG,26,MIA,4,3,142,25,41,.610,7,14,.500,18,27,.667,.695,3,7,.429,2,7,9,25,3,1,8,11,60,mitchda01 +134,Donovan Mitchell,SG,28,CLE,8,8,251,78,169,.462,24,71,.338,54,98,.551,.533,51,68,.750,9,24,33,34,13,2,15,16,231,mitchdo01 +135,Evan Mobley,PF,23,CLE,7,7,220,43,75,.573,13,29,.448,30,46,.652,.660,14,16,.875,16,38,54,12,9,6,11,10,113,mobleev01 +136,Moses Moody,SG,22,GSW,11,2,181,25,74,.338,13,42,.310,12,32,.375,.426,10,12,.833,8,17,25,12,4,3,3,13,73,moodymo01 +137,Ja Morant,PG,25,MEM,3,3,82,22,53,.415,4,16,.250,18,37,.486,.453,7,11,.636,1,5,6,15,2,2,6,3,55,moranja01 +138,Jamal Murray,PG,27,DEN,11,11,459,86,188,.457,28,69,.406,58,119,.487,.532,39,45,.867,6,49,55,61,14,8,33,23,239,murraja01 +139,Andrew Nembhard,SG,25,IND,9,9,291,48,98,.490,19,38,.500,29,60,.483,.587,13,15,.867,5,26,31,54,13,2,15,20,128,nembhan01 +140,Aaron Nesmith,SF,25,IND,9,9,259,48,88,.545,26,49,.531,22,39,.564,.693,11,12,.917,14,38,52,14,5,8,7,35,133,nesmiaa01 +141,Zeke Nnaji,PF,24,DEN,5,0,25,1,6,.167,1,4,.250,0,2,.000,.250,4,7,.571,3,2,5,2,1,2,2,5,7,nnajize01 +142,Chuma Okeke,PF,26,CLE,3,0,13,1,4,.250,1,4,.250,0,0,,.375,0,0,,0,0,0,1,1,0,0,0,3,okekech01 +143,Isaac Okoro,SG,24,CLE,8,0,111,14,28,.500,6,16,.375,8,12,.667,.607,5,8,.625,4,7,11,5,5,1,3,12,39,okorois01 +144,Cameron Payne,PG,30,NYK,10,0,74,10,26,.385,3,13,.231,7,13,.538,.442,1,3,.333,0,5,5,6,4,0,5,15,24,payneca01 +145,Gary Payton II,SG,32,GSW,10,1,174,21,47,.447,9,23,.391,12,24,.500,.543,0,0,,10,14,24,16,9,0,6,21,51,paytoga02 +146,Jalen Pickett,SG,25,DEN,7,0,48,3,10,.300,1,4,.250,2,6,.333,.350,0,0,,0,5,5,3,0,1,6,3,7,pickeja02 +147,Scotty Pippen Jr.,PG,24,MEM,4,4,129,22,58,.379,10,28,.357,12,30,.400,.466,19,19,1.000,4,18,22,14,4,1,14,19,73,pippesc02 +148,Brandin Podziemski,SG,21,GSW,11,10,346,37,113,.327,18,61,.295,19,52,.365,.407,15,19,.789,14,40,54,33,13,2,16,15,107,podzibr01 +149,Craig Porter Jr.,PG,24,CLE,6,0,35,6,12,.500,0,3,.000,6,9,.667,.500,0,0,,3,3,6,9,3,2,2,2,12,portecr01 +150,Kevin Porter Jr.,SG,24,MIL,5,1,151,19,48,.396,7,15,.467,12,33,.364,.469,11,13,.846,3,15,18,27,4,0,9,12,56,porteke02 +151,Michael Porter Jr.,SF,26,DEN,11,11,354,39,96,.406,22,56,.393,17,40,.425,.521,10,14,.714,11,55,66,6,5,5,11,19,110,portemi01 +152,Bobby Portis,PF,29,MIL,5,1,158,30,68,.441,10,28,.357,20,40,.500,.515,0,1,.000,8,33,41,7,2,2,6,8,70,portibo01 +153,Kristaps Porziņģis,C,29,BOS,9,6,207,24,72,.333,3,22,.136,21,50,.420,.354,29,41,.707,20,25,45,8,10,7,8,23,80,porzikr01 +154,Quinten Post,PF,24,GSW,11,2,136,15,44,.341,9,28,.321,6,16,.375,.443,3,4,.750,6,19,25,12,3,3,4,19,42,postqu01 +155,Norman Powell,SG,31,LAC,7,7,238,42,89,.472,14,40,.350,28,49,.571,.551,14,18,.778,1,16,17,17,8,2,12,15,112,powelno01 +156,Taurean Prince,SF,30,MIL,5,2,61,2,10,.200,2,9,.222,0,1,.000,.300,0,0,,0,5,5,8,2,1,5,3,6,princta02 +157,Payton Pritchard,PG,27,BOS,9,0,235,34,72,.472,21,49,.429,13,23,.565,.618,14,17,.824,6,12,18,10,5,0,9,17,103,pritcpa01 +158,Neemias Queta,C,25,BOS,2,0,6,2,2,1.000,0,0,,2,2,1.000,1.000,0,0,,0,0,0,1,0,0,0,0,4,quetane01 +159,Julius Randle,PF,30,MIN,9,9,334,73,151,.483,17,49,.347,56,102,.549,.540,47,53,.887,14,37,51,54,8,2,26,31,210,randlju01 +160,Austin Reaves,SG,26,LAL,5,5,196,30,73,.411,15,47,.319,15,26,.577,.514,6,7,.857,4,23,27,18,1,3,14,18,81,reaveau01 +161,Paul Reed,C,25,DET,5,0,53,5,8,.625,0,0,,5,8,.625,.625,4,6,.667,7,8,15,1,5,3,5,8,14,reedpa01 +162,Naz Reid,C,25,MIN,9,0,232,37,70,.529,21,43,.488,16,27,.593,.679,7,11,.636,6,26,32,16,8,7,16,26,102,reidna01 +163,Duncan Robinson,SF,30,MIA,4,0,59,5,14,.357,4,12,.333,1,2,.500,.500,3,4,.750,0,4,4,1,0,0,6,6,17,robindu01 +164,Mitchell Robinson,C,26,NYK,10,0,186,15,29,.517,0,0,,15,29,.517,.517,11,38,.289,37,28,65,4,8,4,8,20,41,robinmi01 +165,Ryan Rollins,PG,22,MIL,3,1,30,4,13,.308,2,7,.286,2,6,.333,.385,0,0,,1,1,2,4,1,0,0,4,10,rolliry01 +166,Gui Santos,PF,22,GSW,9,0,56,8,13,.615,4,7,.571,4,6,.667,.769,4,6,.667,0,7,7,8,3,0,6,9,24,santogu01 +167,Baylor Scheierman,SG,24,BOS,2,0,6,1,3,.333,1,1,1.000,0,2,.000,.500,0,0,,0,2,2,0,0,0,0,1,3,scheiba01 +168,Dennis Schröder,PG,31,DET,6,0,164,26,53,.491,10,21,.476,16,32,.500,.585,13,16,.813,4,10,14,22,7,1,7,12,75,schrode01 +169,Alperen Şengün,C,22,HOU,7,7,256,59,131,.450,3,8,.375,56,123,.455,.462,25,40,.625,21,62,83,37,13,3,15,26,146,sengual01 +170,Landry Shamet,SG,27,NYK,5,0,22,1,3,.333,0,1,.000,1,2,.500,.333,0,0,,0,0,0,0,0,0,2,0,2,shamela01 +171,Terrence Shannon Jr.,SG,24,MIN,5,0,18,2,6,.333,0,0,,2,6,.333,.333,0,0,,1,4,5,2,2,0,0,2,4,shannte01 +172,Ben Sheppard,SG,23,IND,7,0,92,9,21,.429,5,16,.313,4,5,.800,.548,2,2,1.000,3,9,12,1,0,0,3,10,25,sheppbe01 +173,Reed Sheppard,PG,20,HOU,3,0,10,0,2,.000,0,2,.000,0,0,,.000,0,0,,0,1,1,1,2,1,1,1,0,sheppre01 +174,Pascal Siakam,PF,30,IND,9,9,281,68,119,.571,13,29,.448,55,90,.611,.626,18,27,.667,6,48,54,26,8,2,12,29,167,siakapa01 +175,Ben Simmons,PG,28,LAC,5,0,42,2,6,.333,0,0,,2,6,.333,.333,0,0,,3,4,7,4,1,4,2,11,4,simmobe01 +176,Jericho Sims,C,26,MIL,5,0,58,6,6,1.000,0,0,,6,6,1.000,1.000,2,3,.667,11,9,20,1,0,1,5,5,14,simsje01 +177,Jabari Smith Jr.,PF,21,HOU,7,0,143,17,34,.500,10,22,.455,7,12,.583,.647,8,10,.800,7,20,27,4,1,5,10,6,52,smithja05 +178,Pat Spencer,PG,28,GSW,7,0,57,15,23,.652,1,2,.500,14,21,.667,.674,3,3,1.000,4,6,10,5,3,0,4,8,34,spencpa01 +179,Lamar Stevens,PF,27,MEM,2,0,12,2,9,.222,0,3,.000,2,6,.333,.222,0,0,,0,4,4,1,0,0,1,1,4,stevela01 +180,Isaiah Stewart,C,23,DET,1,0,19,1,2,.500,0,0,,1,2,.500,.500,0,0,,1,4,5,1,0,2,0,5,2,stewais01 +181,Julian Strawther,SG,22,DEN,6,0,41,5,12,.417,2,4,.500,3,8,.375,.500,2,3,.667,2,0,2,1,0,1,2,7,14,strawju01 +182,Max Strus,SF,28,CLE,8,8,227,37,80,.463,26,61,.426,11,19,.579,.625,5,6,.833,13,31,44,33,6,2,7,19,105,strusma01 +183,Jayson Tatum,PF,26,BOS,8,8,322,74,175,.423,29,78,.372,45,97,.464,.506,48,54,.889,9,83,92,43,17,6,26,21,225,tatumja01 +184,Amen Thompson,SF,22,HOU,7,7,231,42,85,.494,1,4,.250,41,81,.506,.500,25,36,.694,19,29,48,23,12,6,12,18,110,thompam01 +185,Ausar Thompson,SF,22,DET,6,6,135,24,42,.571,0,2,.000,24,40,.600,.571,21,36,.583,8,23,31,6,7,5,11,25,69,thompau01 +186,Tristan Thompson,C,33,CLE,3,0,29,3,6,.500,0,0,,3,6,.500,.500,1,3,.333,2,13,15,1,1,2,2,2,7,thomptr01 +187,Obi Toppin,PF,26,IND,9,0,148,31,59,.525,9,25,.360,22,34,.647,.602,9,14,.643,4,18,22,15,6,2,7,16,80,toppiob01 +188,Karl-Anthony Towns,C,29,NYK,10,10,365,75,152,.493,13,35,.371,62,117,.530,.536,34,37,.919,22,94,116,12,8,10,19,45,197,townska01 +189,Gary Trent Jr.,SG,26,MIL,5,3,171,32,62,.516,22,44,.500,10,18,.556,.694,8,10,.800,1,10,11,6,13,0,3,9,94,trentga02 +190,Myles Turner,C,28,IND,9,9,276,52,101,.515,17,38,.447,35,63,.556,.599,34,42,.810,11,42,53,13,7,21,11,23,155,turnemy01 +191,Hunter Tyson,PF,24,DEN,4,0,21,3,7,.429,0,3,.000,3,4,.750,.429,4,4,1.000,2,3,5,1,1,0,1,1,10,tysonhu01 +192,Jaylon Tyson,SG,22,CLE,4,0,31,7,15,.467,5,9,.556,2,6,.333,.633,5,6,.833,3,4,7,7,2,1,2,4,24,tysonja01 +193,Jarred Vanderbilt,PF,25,LAL,5,0,60,2,6,.333,0,1,.000,2,5,.400,.333,3,4,.750,4,15,19,5,3,1,3,9,7,vandeja01 +194,Fred VanVleet,PG,30,HOU,7,7,280,40,93,.430,27,62,.435,13,31,.419,.575,24,24,1.000,3,26,29,31,7,2,13,16,131,vanvlfr01 +195,Gabe Vincent,PG,28,LAL,5,0,99,5,14,.357,4,13,.308,1,1,1.000,.500,0,0,,0,5,5,5,1,2,1,8,14,vincega01 +196,Dean Wade,PF,28,CLE,8,1,123,4,15,.267,3,13,.231,1,2,.500,.367,0,0,,8,24,32,6,3,1,2,6,11,wadede01 +197,Franz Wagner,SF,23,ORL,5,5,195,51,115,.443,7,37,.189,44,78,.564,.474,20,26,.769,3,21,24,28,6,2,10,16,129,wagnefr01 +198,Jarace Walker,PF,21,IND,9,0,96,10,29,.345,6,16,.375,4,13,.308,.448,2,4,.500,0,19,19,8,1,1,5,8,28,walkeja02 +199,Cason Wallace,SG,21,OKC,8,0,158,16,35,.457,7,17,.412,9,18,.500,.557,1,2,.500,8,14,22,18,9,2,5,21,40,wallaca01 +200,Jordan Walsh,PF,20,BOS,3,0,7,0,0,,0,0,,0,0,,,0,0,,0,0,0,1,0,0,0,0,0,walshjo01 +201,Kel'el Ware,C,20,MIA,4,4,73,8,18,.444,3,11,.273,5,7,.714,.528,0,0,,4,15,19,4,1,2,2,3,19,wareke01 +202,Peyton Watson,SF,22,DEN,11,0,150,21,40,.525,6,11,.545,15,29,.517,.600,4,10,.400,8,18,26,2,8,7,4,15,52,watsope01 +203,Russell Westbrook,PG,36,DEN,10,0,254,46,111,.414,18,53,.340,28,58,.483,.495,24,34,.706,14,22,36,29,11,0,20,35,134,westbru01 +204,Derrick White,SG,30,BOS,9,9,345,56,120,.467,31,83,.373,25,37,.676,.596,22,25,.880,14,38,52,35,6,9,10,17,165,whitede01 +205,Cam Whitmore,SF,20,HOU,3,0,5,0,2,.000,0,1,.000,0,1,.000,.000,0,0,,0,1,1,0,0,0,0,0,0,whitmca01 +206,Aaron Wiggins,SG,26,OKC,8,0,112,27,54,.500,11,27,.407,16,27,.593,.602,6,7,.857,8,15,23,4,4,1,6,7,71,wiggiaa01 +207,Andrew Wiggins,SF,29,MIA,4,4,122,16,43,.372,7,20,.350,9,23,.391,.453,7,10,.700,4,9,13,9,1,5,11,6,46,wiggian01 +208,Jalen Williams,SG,23,OKC,8,8,277,63,137,.460,11,45,.244,52,92,.565,.500,31,41,.756,9,29,38,42,11,7,12,13,168,willija06 +209,Jaylin Williams,PF,22,OKC,8,0,71,8,14,.571,5,10,.500,3,4,.750,.750,2,5,.400,1,10,11,6,3,2,5,16,23,willija07 +210,Jeenathan Williams,SG,25,HOU,3,0,5,0,1,.000,0,1,.000,0,0,,.000,0,0,,0,0,0,0,0,0,1,1,0,willije02 +211,Kenrich Williams,PF,30,OKC,3,0,29,4,14,.286,0,6,.000,4,8,.500,.286,2,2,1.000,2,10,12,2,4,0,2,2,10,willike04 +212,Vince Williams Jr.,SG,24,MEM,3,0,38,4,7,.571,4,7,.571,0,0,,.857,2,2,1.000,1,6,7,4,2,1,3,3,14,willivi01 +213,Delon Wright,PG,32,NYK,1,0,3,0,0,,0,0,,0,0,,,0,0,,0,0,0,0,0,0,0,0,0,wrighde01 +214,Ivica Zubac,C,27,LAC,7,7,256,54,82,.659,0,0,,54,82,.659,.659,14,26,.538,27,44,71,16,5,7,11,19,122,zubaciv01