Merge pull request #11 from nprasad2077/deploy

Deploy
This commit is contained in:
Nikhil Prasad authored and GitHub committed 2023-05-10 15:33:09 -05:00
commit eb588061fa
16 files changed
+488 -11

No files matched your search

@@ -0,0 +1,21 @@
# Generated by Django 4.2 on 2023-05-08 23:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('nba_data', '0011_alter_playerplayoffadvanceddata_bpm_and_more'),
]
operations = [
migrations.CreateModel(
name='PlayerSalaryData',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('player_name', models.CharField(max_length=255, null=True)),
('salary', models.IntegerField(null=True)),
],
),
]
@@ -0,0 +1,23 @@
# Generated by Django 4.2 on 2023-05-09 00:16
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('nba_data', '0012_playersalarydata'),
]
operations = [
migrations.AddField(
model_name='playersalarydata',
name='season',
field=models.IntegerField(null=True),
),
migrations.AddField(
model_name='playersalarydata',
name='team',
field=models.CharField(default='', max_length=30),
),
]
@@ -0,0 +1,34 @@
# Generated by Django 4.2 on 2023-05-10 02:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('nba_data', '0013_playersalarydata_season_playersalarydata_team'),
]
operations = [
migrations.CreateModel(
name='PlayerShotChartData',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('player_name', models.CharField(default='', max_length=255)),
('top', models.IntegerField(null=True)),
('left', models.IntegerField(null=True)),
('date', models.CharField(default='', max_length=255)),
('qtr', models.CharField(default='', max_length=6)),
('time_remaining', models.IntegerField(null=True)),
('result', models.BooleanField(null=True)),
('shot_type', models.CharField(default='', max_length=6)),
('distance_ft', models.IntegerField(null=True)),
('lead', models.BooleanField(null=True)),
('lebron_team_score', models.IntegerField(null=True)),
('opponent_team_score', models.IntegerField(null=True)),
('opponent', models.CharField(default='', max_length=30)),
('team', models.CharField(default='', max_length=30)),
('season', models.IntegerField(null=True)),
],
),
]
@@ -0,0 +1,18 @@
# Generated by Django 4.2 on 2023-05-10 02:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('nba_data', '0014_playershotchartdata'),
]
operations = [
migrations.AlterField(
model_name='playershotchartdata',
name='time_remaining',
field=models.CharField(default='', max_length=12),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 4.2 on 2023-05-10 05:32
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('nba_data', '0015_alter_playershotchartdata_time_remaining'),
]
operations = [
migrations.AlterField(
model_name='playershotchartdata',
name='qtr',
field=models.CharField(default='', max_length=255),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 4.2 on 2023-05-10 05:33
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('nba_data', '0016_alter_playershotchartdata_qtr'),
]
operations = [
migrations.AlterField(
model_name='playershotchartdata',
name='result',
field=models.BooleanField(default='', null=True),
),
]
+34
View File
@@ -199,6 +199,40 @@ class PlayerPlayoffAdvancedData(models.Model):
def __str__(self):
return self.player_name
class PlayerSalaryData(models.Model):
player_name = models.CharField(max_length=255, null=True)
salary = models.IntegerField(null=True)
team = models.CharField(max_length=30, default='')
season = models.IntegerField(null=True)
def __str__(self):
return self.player_name
class PlayerShotChartData(models.Model):
player_name = models.CharField(max_length=255, default='')
top = models.IntegerField(null=True)
left = models.IntegerField(null=True)
date = models.CharField(max_length=255, default='')
qtr = models.CharField(max_length=255, default='')
time_remaining = models.CharField(max_length=12, default='')
result = models.BooleanField(null=True, default='')
shot_type = models.CharField(max_length=6, default='')
distance_ft = models.IntegerField(null=True)
lead = models.BooleanField(null=True)
lebron_team_score = models.IntegerField(null=True)
opponent_team_score = models.IntegerField(null=True)
opponent = models.CharField(max_length=30, default='')
team = models.CharField(max_length=30, default='')
season = models.IntegerField(null=True)
def __str__(self):
return self.player_name
+12 -3
View File
@@ -15,10 +15,19 @@ django.setup()
from nba_data.models import PlayerAdvancedData
# If season is 2014, then change CHO to CHA
teams = ['HOU' ,'PHI', 'BOS', 'NYK', 'BRK', 'TOR', 'MEM', 'NOP', 'DAL', 'SAS', 'DEN', 'MIN', 'OKC', 'UTA', 'POR', 'MIL', 'CLE', 'CHI', 'IND', 'DET', 'SAC', 'PHO', 'GSW', 'LAC', 'LAL', 'MIA', 'ATL', 'WAS', 'ORL', 'CHO']
team_abbreviations = ['ATL', 'BOS', 'BRK', 'CHI', 'CHO', 'CLE', 'DAL', 'DEN', 'DET', 'GSW', 'HOU', 'IND', 'LAC', 'LAL', 'MEM', 'MIA', 'MIL', 'MIN', 'NOP', 'NYK', 'OKC', 'ORL', 'PHI', 'PHO', 'POR', 'SAC', 'SAS', 'TOR', 'UTA', 'WAS']
# Change CHO to CHA 2014 and prior.
# Change NOP to NOH for 2013 and prior.
# Change BRK to NJN for 2012 and prior.
# Change OKC to SEA for 2008 and prior.
# Change NOH to NOK for 2007 and 2006
# Change NOK to NOH for 2005 and prior.
# Change NOH to CHH for 2002 and prior. NOLA did not have a team before 2003.
# Change WAS to WSB for 1997 and prior.
# Change MEM to VAN for 2001 and prior.
# Change LAC to SDC for 1984 and prior.
teams = ['HOU' ,'PHI', 'BOS', 'NYK', 'NJN', 'TOR', 'MEM', 'NOH', 'DAL', 'SAS', 'DEN', 'MIN', 'OKC', 'UTA', 'POR', 'MIL', 'CLE', 'CHI', 'IND', 'DET', 'SAC', 'PHO', 'GSW', 'LAC', 'LAL', 'MIA', 'ATL', 'WAS', 'ORL', 'CHA']
season = input('What season? ')
for team in teams:
+1
View File
@@ -29,6 +29,7 @@ from nba_data.models import PlayerPlayoffTotalsData
teams = ['HOU' ,'PHI', 'BOS', 'NYK', 'NJN', 'TOR', 'MEM', 'NOH', 'DAL', 'SAS', 'DEN', 'MIN', 'OKC', 'UTA', 'POR', 'MIL', 'CLE', 'CHI', 'IND', 'DET', 'SAC', 'PHO', 'GSW', 'LAC', 'LAL', 'MIA', 'ATL', 'WAS', 'ORL', 'CHA']
team_abbreviations = ['ATL', 'BOS', 'BRK', 'CHI', 'CHO', 'CLE', 'DAL', 'DEN', 'DET', 'GSW', 'HOU', 'IND', 'LAC', 'LAL', 'MEM', 'MIA', 'MIL', 'MIN', 'NOP', 'NYK', 'OKC', 'ORL', 'PHI', 'PHO', 'POR', 'SAC', 'SAS', 'TOR', 'UTA', 'WAS']
season = input('What season? ')
+104
View File
@@ -0,0 +1,104 @@
import os
import sys
import django
import requests
from bs4 import BeautifulSoup, Comment
import csv
import json
import time
import re
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'nba_stats.settings')
django.setup()
from nba_data.models import PlayerSalaryData
# Change CHO to CHA 2014 and prior.
# Change NOP to NOH for 2013 and prior.
# Change OKC to SEA for 2008 and prior.
# Change NOH to NOK for 2007 and 2006
# Change NOK to NOH for 2005 and prior.
# Change NOH to CHH for 2002 and prior. NOLA did not have a team before 2003.
# Change WAS to WSB for 1997 and prior.
# Change BRK to NJN for 2012 and prior.
# Change MEM to VAN for 2001 and prior.
# Change LAC to SDC for 1984 and prior.
teams = ['HOU' ,'PHI', 'BOS', 'NYK', 'BRK', 'TOR', 'MEM', 'NOP', 'DAL', 'SAS', 'DEN', 'MIN', 'OKC', 'UTA', 'POR', 'MIL', 'CLE', 'CHI', 'IND', 'DET', 'SAC', 'PHO', 'GSW', 'LAC', 'LAL', 'MIA', 'ATL', 'WAS', 'ORL', 'CHO']
teams_test = ['HOU', 'PHI', 'BOS']
season = input('What season? ')
for team in teams:
url_make = 'https://www.basketball-reference.com/teams/' + team + '/' + season + '.html'
response = requests.get(url_make)
soup = BeautifulSoup(response.text, "html.parser")
comment = soup.find(string=lambda text: isinstance(text, Comment) and "salaries2" in text)
table_soup = BeautifulSoup(comment, "html.parser")
table = table_soup.find("table", {'class': 'suppress_all stats_table', 'id': 'salaries2'})
if table is None:
print(f"Table not found for team {team} and season {season}.")
# sys.exit(1)
continue
header_row = table.find("thead").find("tr")
rows = table.find("tbody").find_all("tr")
# Extract coloumn headers
headers = ['player_name']
headers.extend([col.text.strip() for col in header_row.find_all("th")][2:])
headers.extend(['team', 'season']) # Add 'team' and 'season' fields to headers
# Extract rows as dictionaries
data = []
for row in rows:
cols = row.find_all("td")
cols = [col.text.strip() for col in cols]
row_dict = {header: (None if col == "" else col) for header, col in zip(headers, cols)}
row_dict['team'] = team
row_dict['season'] = season
data.append(row_dict)
# locate current directory
script_dir = os.path.dirname(os.path.abspath(__file__))
# save as CSV file
csv_output_path = os.path.join(script_dir, '..', 'data', f'{team}_{season}_player_salary_output.csv')
with open(csv_output_path, "w", newline="") as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=headers)
writer.writeheader()
for row in data:
writer.writerow(row)
# Save as JSON
json_output_path = os.path.join(script_dir, '..', 'data', f'{team}_{season}_player_salary_output.json')
with open(json_output_path, 'w') as jsonfile:
json.dump(data, jsonfile)
# save data to database
for row in data:
row['Salary'] = int(row['Salary'].replace(',', '').replace('$', '')) if row['Salary'] else None
player_data = PlayerSalaryData(
player_name = row['player_name'],
salary = row['Salary'],
team = row['team'],
season = row['season'],
)
player_data.save()
print('success')
+113
View File
@@ -0,0 +1,113 @@
import os
import sys
import django
import requests
from bs4 import BeautifulSoup, Comment
import csv
import re
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'nba_stats.settings')
django.setup()
from nba_data.models import PlayerShotChartData
player_name = 'LeBron James'
season = 2014
# team = 'LAL' # You might want to find a way to get this from the webpage
url = 'https://www.basketball-reference.com/players/j/jamesle01/shooting/' + \
str(season)
response = requests.get(url)
soup = BeautifulSoup(response.text, "html.parser")
# Find the comment containing the shot chart
comment = soup.find(string=lambda text: isinstance(
text, Comment) and "div_shot-chart" in text)
shot_chart_soup = BeautifulSoup(comment, "html.parser")
# Now you can find the shot chart in the parsed comment
shot_chart = shot_chart_soup.find("div", {"id": "shot-wrapper"})
shots = shot_chart.find_all("div", {"class": ["tooltip make", "tooltip miss"]})
# save data to database and CSV
shot_chart_data = []
for shot_div in shots:
try:
# Parse shot data
style_values = shot_div['style'].split(';')
top_value = int(style_values[0].split(
':')[1].replace('px', '').strip())
left_value = int(style_values[1].split(
':')[1].replace('px', '').strip())
# Parse tip attribute
tip_parts = shot_div['tip'].split('<br>')
# Within your loop:
date_and_opponent = re.split(' at | vs ', tip_parts[0])
date = date_and_opponent[0].strip().split(
',')[0] + ',' + date_and_opponent[0].strip().split(',')[1]
team = date_and_opponent[0].strip().split(',')[2].strip()
opponent = date_and_opponent[1].strip()
quarter_and_time = tip_parts[1].split(',')
quarter = quarter_and_time[0].strip()
time_remaining = quarter_and_time[1].strip().split(' ')[0]
result_and_type_and_distance = tip_parts[2].split(' ')
result = result_and_type_and_distance[0].strip() == 'Made'
shot_type = int(result_and_type_and_distance[1][0])
distance_ft = int(result_and_type_and_distance[-2].strip())
team_score_and_opponent_score = tip_parts[3].split(' ')[-1].split('-')
team_score = int(team_score_and_opponent_score[0].strip())
opponent_score = int(team_score_and_opponent_score[1].strip())
lead = team_score > opponent_score
shot_chart_row = {
'player_name': player_name,
'top': top_value,
'left': left_value,
'date': date,
'qtr': quarter,
'time_remaining': time_remaining,
'result': result,
'shot_type': shot_type,
'distance_ft': distance_ft,
'lead': lead,
'lebron_team_score': team_score,
'opponent_team_score': opponent_score,
'opponent': opponent,
'team': team,
'season': season
}
shot_chart_data.append(shot_chart_row)
except Exception as e:
print(f"Error processing shot_div: {shot_div}")
print(f"Exception: {e}")
# save as CSV file
script_dir = os.path.dirname(os.path.abspath(__file__))
csv_output_path = os.path.join(
script_dir, '..', 'data', f'{player_name}_{season}_shot_chart_output.csv')
with open(csv_output_path, "w", newline="") as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=shot_chart_data[0].keys())
writer.writeheader()
for row in shot_chart_data:
writer.writerow(row)
# Save the records in the database
try:
PlayerShotChartData.objects.bulk_create(
PlayerShotChartData(**row) for row in shot_chart_data
)
except Exception as e:
print(f"Error inserting data into database: {e}")
print('success')
+13 -2
View File
@@ -15,8 +15,19 @@ django.setup()
from nba_data.models import PlayerTotalsData
teams = ['HOU' ,'PHI', 'BOS', 'NYK', 'BRK', 'TOR', 'MEM', 'NOP', 'DAL', 'SAS', 'DEN', 'MIN', 'OKC', 'UTA', 'POR', 'MIL', 'CLE', 'CHI', 'IND', 'DET', 'SAC', 'PHO', 'GSW', 'LAC', 'LAL', 'MIA', 'ATL', 'WAS', 'ORL', 'CHO']
team_abbreviations = ['ATL', 'BOS', 'BRK', 'CHI', 'CHO', 'CLE', 'DAL', 'DEN', 'DET', 'GSW', 'HOU', 'IND', 'LAC', 'LAL', 'MEM', 'MIA', 'MIL', 'MIN', 'NOP', 'NYK', 'OKC', 'ORL', 'PHI', 'PHO', 'POR', 'SAC', 'SAS', 'TOR', 'UTA', 'WAS']
# Change CHO to CHA 2014 and prior.
# Change NOP to NOH for 2013 and prior.
# Change OKC to SEA for 2008 and prior.
# Change NOH to NOK for 2007 and 2006
# Change NOK to NOH for 2005 and prior.
# Change NOH to CHH for 2002 and prior. NOLA did not have a team before 2003.
# Change WAS to WSB for 1997 and prior.
# Change BRK to NJN for 2012 and prior.
# Change MEM to VAN for 2001 and prior.
# Change LAC to SDC for 1984 and prior.
teams = ['HOU' ,'PHI', 'BOS', 'NYK', 'NJN', 'TOR', 'MEM', 'NOH', 'DAL', 'SAS', 'DEN', 'MIN', 'OKC', 'UTA', 'POR', 'MIL', 'CLE', 'CHI', 'IND', 'DET', 'SAC', 'PHO', 'GSW', 'LAC', 'LAL', 'MIA', 'ATL', 'WAS', 'ORL', 'CHA']
# team = input('What team? ')
# OMIT above. Will now only ask for season and iterate thru teams list.
+16 -1
View File
@@ -1,6 +1,6 @@
# Serializers are defined that will convert model instances to JSON
from rest_framework import serializers
from .models import PlayerData, PlayerTotalsData, PlayerAdvancedData, PlayerPlayoffTotalsData, PlayerPlayoffAdvancedData
from .models import PlayerData, PlayerTotalsData, PlayerAdvancedData, PlayerPlayoffTotalsData, PlayerPlayoffAdvancedData, PlayerSalaryData, PlayerShotChartData
class PlayerDataSerializer(serializers.ModelSerializer):
class Meta:
@@ -30,5 +30,20 @@ class PlayerPlayoffAdvancedDataSerializer(serializers.ModelSerializer):
class Meta:
model = PlayerPlayoffAdvancedData
fields = '__all__'
class PlayerSalaryDataSerializer(serializers.ModelSerializer):
class Meta:
model = PlayerSalaryData
fields = '__all__'
class PlayerShotChartDataSerializer(serializers.ModelSerializer):
color = serializers.SerializerMethodField()
class Meta:
model = PlayerShotChartData
fields = ['top', 'left', 'date', 'qtr', 'time_remaining', 'result', 'shot_type', 'distance_ft', 'lead', 'lebron_team_score', 'opponent_team_score', 'opponent', 'team', 'season', 'color']
def get_color(self, obj):
return 'green' if obj.result else 'red'
+14
View File
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NBA Data API</title>
</head>
<body>
<h1>Welcome to NBA Data API!</h1>
</body>
</html>
+4 -1
View File
@@ -1,7 +1,8 @@
from django.urls import path
from .views import PlayerDataList, PlayerDataByTeamList, PlayerDataBySeasonList, PlayerDataByNameList, TopScorersbySeasonList, TopScorersbySeasonListPlayoffs, ThreeTwoTopPointTrends, TopAssistsBySeasonList, TopReboundsBySeasonList, TopBlocksBySeasonList, TopStealsBySeasonList, TopOffensiveReboundsBySeasonList, TopDefensiveReboundsBySeasonList, PointsPerGameHistogramBySeasonList, TopPtsScatterPlotData, TopPtsScatterPlotDataFast, TopPtsScatterPlotDataFast2018, Top20ScorersPost2009WS, Top20ScorersPost2014WS, Top20ScorersPost2018WS, TopAssistsBySeasonListPlayoffs, Top25ScorersPostSeasonPlayoffs, TopPtsScatterPlotDataFastSelect, OverallDBStats, TopScorersbySeasonTotalsList, TopAssistsBySeasonTotalsList, TopReboundsbySeasonTotalsList, TopStealsbySeasonTotalsList, TopBlocksbySeasonTotalsList, TopDefensiveReboundsBySeasonTotalsList, TopOffensiveReboundsbySeasonTotalsList
from .views import PlayerDataList, PlayerDataByTeamList, PlayerDataBySeasonList, PlayerDataByNameList, TopScorersbySeasonList, TopScorersbySeasonListPlayoffs, ThreeTwoTopPointTrends, TopAssistsBySeasonList, TopReboundsBySeasonList, TopBlocksBySeasonList, TopStealsBySeasonList, TopOffensiveReboundsBySeasonList, TopDefensiveReboundsBySeasonList, PointsPerGameHistogramBySeasonList, TopPtsScatterPlotData, TopPtsScatterPlotDataFast, TopPtsScatterPlotDataFast2018, Top20ScorersPost2009WS, Top20ScorersPost2014WS, Top20ScorersPost2018WS, TopAssistsBySeasonListPlayoffs, Top25ScorersPostSeasonPlayoffs, TopPtsScatterPlotDataFastSelect, OverallDBStats, TopScorersbySeasonTotalsList, TopAssistsBySeasonTotalsList, TopReboundsbySeasonTotalsList, TopStealsbySeasonTotalsList, TopBlocksbySeasonTotalsList, TopDefensiveReboundsBySeasonTotalsList, TopOffensiveReboundsbySeasonTotalsList, UsageRateHistogramView, PlayerShotChartDataList, landing_page
urlpatterns = [
path('', landing_page, name='landing'),
path('api/playerdata/', PlayerDataList.as_view(), name='playerdata_list'),
path('api/playerdata/team/<str:team>/', PlayerDataByTeamList.as_view(), name='playerdata_by_team'),
path('api/playerdata/season/<str:season>/', PlayerDataBySeasonList.as_view(), name='playerdata_by_season'),
@@ -24,6 +25,7 @@ urlpatterns = [
path('api/top_rebounds_defensive/<int:season>/', TopDefensiveReboundsBySeasonList.as_view(), name='top_rebounds_DRB'),
path('api/top_rebounds_defensive/totals/<int:season>/', TopDefensiveReboundsBySeasonTotalsList.as_view(), name='top_rebounds_DRB_totals'),
path('api/points_per_game_histogram/<int:season>/', PointsPerGameHistogramBySeasonList.as_view(), name='points_per_game_histogram'),
path('api/usage_histogram/<int:season>/', UsageRateHistogramView.as_view(), name='usage_histogram'),
path('api/top_pts_scatter_plot/', TopPtsScatterPlotData.as_view(), name='top_pts_scatter_plot'),
path('api/top_pts_scatter_plot_fast/', TopPtsScatterPlotDataFast.as_view(), name='top_pts_scatter_plot_fast'),
path('api/top_pts_scatter_plot_fast_2018/', TopPtsScatterPlotDataFast2018.as_view(), name='top_pts_scatter_plot_fast_2018'),
@@ -33,4 +35,5 @@ urlpatterns = [
path('api/top_25_PTS_ws/playoffs/<int:season>/', Top25ScorersPostSeasonPlayoffs.as_view(), name='top_25_PTS_ws_playoffs'),
path('api/top_25_PTS_ws/season/<int:season>/', TopPtsScatterPlotDataFastSelect.as_view(), name='top_25_PTS_ws_season'),
path('api/stats/', OverallDBStats.as_view(), name='overall_db_stats'),
path('api/shot_chart_data/<str:player_name>/<str:season>/', PlayerShotChartDataList.as_view(), name='player_shot_chart'),
]
+45 -4
View File
@@ -1,12 +1,12 @@
from django.shortcuts import render
from django.http import JsonResponse, Http404
from django.core import serializers
from .models import PlayerData, PlayerTotalsData, PlayerAdvancedData, PlayerPlayoffTotalsData, PlayerPlayoffAdvancedData
from .models import PlayerData, PlayerTotalsData, PlayerAdvancedData, PlayerPlayoffTotalsData, PlayerPlayoffAdvancedData, PlayerShotChartData
from rest_framework import generics
from .serializers import PlayerDataSerializer, HistogramDataSerializer, PlayerPlayoffTotalsDataSerializer, PlayerTotalsDataSerializer
from .serializers import PlayerDataSerializer, HistogramDataSerializer, PlayerPlayoffTotalsDataSerializer, PlayerTotalsDataSerializer, PlayerShotChartDataSerializer
from rest_framework.views import APIView
from rest_framework.response import Response
from django.db.models import Avg, Sum, F, FloatField, Min, Max
from django.db.models import Avg, Sum, F, Min, Max
from collections import Counter
import math
from django.db import connection
@@ -245,8 +245,40 @@ class PointsPerGameHistogramBySeasonList(generics.ListAPIView):
return histogram_list
# USG Percent Histogram
# Scatter Plot - Top 30 players by total PTS across all seasons in DB. Then map those 30 players on a scatter plot against total PTS/WS for each season.
class UsageRateHistogramView(generics.ListAPIView):
serializer_class = HistogramDataSerializer
def get_queryset(self):
season = self.kwargs['season']
queryset = PlayerAdvancedData.objects.filter(season=season)
# Get the usage rates for each player, ignoring null values
usage_rate_list = [player.usg_percent for player in queryset if player.usg_percent is not None]
# Define histogram bins for usage rate ranges
bin_ranges = [i * 5 for i in range(21)] # 0, 5, 10, ..., 100
histogram_data = Counter()
# Fill the histogram with data
for usage_rate in usage_rate_list:
bin_index = next(
(i for i, r in enumerate(bin_ranges) if r >= usage_rate), -1)
if bin_index >= 1:
bin_label = f"{bin_ranges[bin_index - 1]}-{bin_ranges[bin_index]}"
histogram_data[bin_label] += 1
# Convert histogram_data to list of dicts for serialization
histogram_list = [{"range": k, "count": v}
for k, v in histogram_data.items()]
return histogram_list
# Scatter Plot - Top 25 players by total PTS across all seasons in DB. Then map those 25 players on a scatter plot against total PTS/WS for each season.
class TopPtsScatterPlotData(APIView):
def get(self, request, *args, **kwargs):
@@ -627,5 +659,14 @@ class OverallDBStats(APIView):
return Response(response_data)
class PlayerShotChartDataList(generics.ListAPIView):
serializer_class = PlayerShotChartDataSerializer
def get_queryset(self):
player_name = self.kwargs['player_name']
season = self.kwargs['season']
return PlayerShotChartData.objects.filter(player_name__icontains=player_name, season=season).order_by('id')
def landing_page(request):
return render(request, 'landing.html')