From 08e60d68383ce8bd64a6614bf8fe3e1fe4b6eb65 Mon Sep 17 00:00:00 2001 From: nprasad2077 <114438461+nprasad2077@users.noreply.github.com> Date: Sat, 22 Apr 2023 18:03:20 -0500 Subject: [PATCH 1/7] create view and logic to serve 2P and 3P data --- nba_data/views.py | 55 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/nba_data/views.py b/nba_data/views.py index 921f7a1..20876d7 100644 --- a/nba_data/views.py +++ b/nba_data/views.py @@ -4,6 +4,9 @@ from django.core import serializers from .models import PlayerData from rest_framework import generics from .serializers import PlayerDataSerializer +from rest_framework.views import APIView +from rest_framework.response import Response +from django.db.models import Avg # Create your views here. @@ -13,40 +16,68 @@ class PlayerDataList(generics.ListCreateAPIView): queryset = PlayerData.objects.all().order_by('id') serializer_class = PlayerDataSerializer # pagination_class = None - - + + # Fetch player data by team class PlayerDataByTeamList(generics.ListAPIView): serializer_class = PlayerDataSerializer - + def get_queryset(self): team = self.kwargs['team'] return PlayerData.objects.filter(team=team) - - + + # Fetch player data by season class PlayerDataBySeasonList(generics.ListAPIView): serializer_class = PlayerDataSerializer - + def get_queryset(self): season = self.kwargs['season'] return PlayerData.objects.filter(season=season) - - + + # Fetch player data by player name class PlayerDataByNameList(generics.ListAPIView): serializer_class = PlayerDataSerializer - + def get_queryset(self): name = self.kwargs['name'] return PlayerData.objects.filter(name__icontains=name) - - + + # Fetch Top 20 players by PTS DESC for the season specified. class TopScorersbySeasonList(generics.ListAPIView): serializer_class = PlayerDataSerializer - + def get_queryset(self): season = self.kwargs['season'] return PlayerData.objects.filter(season=season).order_by('-PTS')[:20] + +# Fetch and calculate the average 3P made, 3P attemps, 2P made, 2P attempts for all players in each season. +# Will use APIview here instead of generics.ListAPIView to avoid having to create a serializer to generate the queryset. avg_three_made and avg_two_made are new data points at the time of creation when compared to the per_game model. +class ThreeTopPointTrends(APIView): + def get(self, request, format=None): + seasons = PlayerData.objects.values_list( + 'season', flat=True).distinct().order_by('season') + data = [] + + for season in seasons: + season_data = PlayerData.objects.filter(season=season) + avg_three_made = season_data.aggregate(Avg('three_fg'))[ + 'three_fg_avg'] + avg_three_attempts = season_data.aggregate(Avg('three_attempts'))[ + 'three_attempts_avg'] + avg_two_made = season_data.aggregate(Avg('two_fg'))['two_fg_avg'] + avg_two_attempts = season_data.aggregate(Avg('two_attempts'))[ + 'two_attempts_avg'] + + data.append({ + 'season': season, + 'avg_three_made': avg_three_made, + 'avg_three_attempts': avg_three_attempts, + 'avg_two_made': avg_two_made, + 'avg_two_attempts': avg_two_attempts, + }) + + return Response(data) From c9711ddd197f34c2eb19b75acfcfc595f42631c7 Mon Sep 17 00:00:00 2001 From: nprasad2077 <114438461+nprasad2077@users.noreply.github.com> Date: Sat, 22 Apr 2023 18:05:58 -0500 Subject: [PATCH 2/7] add views for 2p 3p data --- nba_data/urls.py | 3 ++- nba_data/views.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/nba_data/urls.py b/nba_data/urls.py index dbdf7fc..cc5aaa5 100644 --- a/nba_data/urls.py +++ b/nba_data/urls.py @@ -1,5 +1,5 @@ from django.urls import path -from .views import PlayerDataList, PlayerDataByTeamList, PlayerDataBySeasonList, PlayerDataByNameList, TopScorersbySeasonList +from .views import PlayerDataList, PlayerDataByTeamList, PlayerDataBySeasonList, PlayerDataByNameList, TopScorersbySeasonList, ThreeTwoTopPointTrends urlpatterns = [ path('api/playerdata/', PlayerDataList.as_view(), name='playerdata_list'), @@ -7,4 +7,5 @@ urlpatterns = [ path('api/playerdata/season//', PlayerDataBySeasonList.as_view(), name='playerdata_by_season'), path('api/playerdata/name//', PlayerDataByNameList.as_view(), name='playerdata_by_name'), path('api/playerdata/topscorers/season//', TopScorersbySeasonList.as_view(), name='top_scorers_by_season'), + path('api/three_two_point_trends/', ThreeTwoTopPointTrends.as_view(), name='three_two_point_trends'), ] \ No newline at end of file diff --git a/nba_data/views.py b/nba_data/views.py index 20876d7..3bc911c 100644 --- a/nba_data/views.py +++ b/nba_data/views.py @@ -56,7 +56,7 @@ class TopScorersbySeasonList(generics.ListAPIView): # Fetch and calculate the average 3P made, 3P attemps, 2P made, 2P attempts for all players in each season. # Will use APIview here instead of generics.ListAPIView to avoid having to create a serializer to generate the queryset. avg_three_made and avg_two_made are new data points at the time of creation when compared to the per_game model. -class ThreeTopPointTrends(APIView): +class ThreeTwoTopPointTrends(APIView): def get(self, request, format=None): seasons = PlayerData.objects.values_list( 'season', flat=True).distinct().order_by('season') From 0ef688071defbc3548575affa6f388734c0d1ea8 Mon Sep 17 00:00:00 2001 From: nprasad2077 <114438461+nprasad2077@users.noreply.github.com> Date: Sat, 22 Apr 2023 18:17:51 -0500 Subject: [PATCH 3/7] update views to serve data proper --- nba_data/views.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nba_data/views.py b/nba_data/views.py index 3bc911c..1eb531d 100644 --- a/nba_data/views.py +++ b/nba_data/views.py @@ -65,12 +65,12 @@ class ThreeTwoTopPointTrends(APIView): for season in seasons: season_data = PlayerData.objects.filter(season=season) avg_three_made = season_data.aggregate(Avg('three_fg'))[ - 'three_fg_avg'] + 'three_fg__avg'] avg_three_attempts = season_data.aggregate(Avg('three_attempts'))[ - 'three_attempts_avg'] - avg_two_made = season_data.aggregate(Avg('two_fg'))['two_fg_avg'] + 'three_attempts__avg'] + avg_two_made = season_data.aggregate(Avg('two_fg'))['two_fg__avg'] avg_two_attempts = season_data.aggregate(Avg('two_attempts'))[ - 'two_attempts_avg'] + 'two_attempts__avg'] data.append({ 'season': season, From 2241f2d4851ff5b3fc9f13704a4274a741d9dbe6 Mon Sep 17 00:00:00 2001 From: nprasad2077 <114438461+nprasad2077@users.noreply.github.com> Date: Wed, 26 Apr 2023 14:02:55 -0500 Subject: [PATCH 4/7] top assists view --- nba_data/urls.py | 3 ++- nba_data/views.py | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/nba_data/urls.py b/nba_data/urls.py index cc5aaa5..e652bc8 100644 --- a/nba_data/urls.py +++ b/nba_data/urls.py @@ -1,5 +1,5 @@ from django.urls import path -from .views import PlayerDataList, PlayerDataByTeamList, PlayerDataBySeasonList, PlayerDataByNameList, TopScorersbySeasonList, ThreeTwoTopPointTrends +from .views import PlayerDataList, PlayerDataByTeamList, PlayerDataBySeasonList, PlayerDataByNameList, TopScorersbySeasonList, ThreeTwoTopPointTrends, TopAssistsBySeasonList urlpatterns = [ path('api/playerdata/', PlayerDataList.as_view(), name='playerdata_list'), @@ -8,4 +8,5 @@ urlpatterns = [ path('api/playerdata/name//', PlayerDataByNameList.as_view(), name='playerdata_by_name'), path('api/playerdata/topscorers/season//', TopScorersbySeasonList.as_view(), name='top_scorers_by_season'), path('api/three_two_point_trends/', ThreeTwoTopPointTrends.as_view(), name='three_two_point_trends'), + path('api/top_assists//', TopAssistsBySeasonList.as_view(), name='top_assists') ] \ No newline at end of file diff --git a/nba_data/views.py b/nba_data/views.py index 1eb531d..b990336 100644 --- a/nba_data/views.py +++ b/nba_data/views.py @@ -81,3 +81,11 @@ class ThreeTwoTopPointTrends(APIView): }) return Response(data) + +# Fetch Top 20 players by AST DESC for season specified. +class TopAssistsBySeasonList(generics.ListAPIView): + serializer_class = PlayerDataSerializer + + def get_queryset(self): + season = self.kwargs['season'] + return PlayerData.objects.filter(season=season).order_by('-AST')[:20] From 38c37a3df20d7862e42514154040593324ba4bbc Mon Sep 17 00:00:00 2001 From: nprasad2077 <114438461+nprasad2077@users.noreply.github.com> Date: Wed, 26 Apr 2023 14:17:17 -0500 Subject: [PATCH 5/7] add views and urls for TRB, BLK, STL --- nba_data/urls.py | 7 +++++-- nba_data/views.py | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/nba_data/urls.py b/nba_data/urls.py index e652bc8..4b0d6c1 100644 --- a/nba_data/urls.py +++ b/nba_data/urls.py @@ -1,5 +1,5 @@ from django.urls import path -from .views import PlayerDataList, PlayerDataByTeamList, PlayerDataBySeasonList, PlayerDataByNameList, TopScorersbySeasonList, ThreeTwoTopPointTrends, TopAssistsBySeasonList +from .views import PlayerDataList, PlayerDataByTeamList, PlayerDataBySeasonList, PlayerDataByNameList, TopScorersbySeasonList, ThreeTwoTopPointTrends, TopAssistsBySeasonList, TopReboundsBySeasonList, TopBlocksBySeasonList, TopStealsBySeasonList urlpatterns = [ path('api/playerdata/', PlayerDataList.as_view(), name='playerdata_list'), @@ -8,5 +8,8 @@ urlpatterns = [ path('api/playerdata/name//', PlayerDataByNameList.as_view(), name='playerdata_by_name'), path('api/playerdata/topscorers/season//', TopScorersbySeasonList.as_view(), name='top_scorers_by_season'), path('api/three_two_point_trends/', ThreeTwoTopPointTrends.as_view(), name='three_two_point_trends'), - path('api/top_assists//', TopAssistsBySeasonList.as_view(), name='top_assists') + path('api/top_assists//', TopAssistsBySeasonList.as_view(), name='top_assists'), + path('api/top_rebounds//', TopReboundsBySeasonList.as_view(), name='top_rebounds'), + path('api/top_blocks//', TopBlocksBySeasonList.as_view(), name='top_blocks'), + path('api/top_steals//', TopStealsBySeasonList.as_view(), name='top_steals'), ] \ No newline at end of file diff --git a/nba_data/views.py b/nba_data/views.py index b990336..c39eea0 100644 --- a/nba_data/views.py +++ b/nba_data/views.py @@ -81,11 +81,43 @@ class ThreeTwoTopPointTrends(APIView): }) return Response(data) - + # Fetch Top 20 players by AST DESC for season specified. + + class TopAssistsBySeasonList(generics.ListAPIView): serializer_class = PlayerDataSerializer - + def get_queryset(self): season = self.kwargs['season'] return PlayerData.objects.filter(season=season).order_by('-AST')[:20] + +# Fetch Top 20 players by TRB DESC for season specified. + + +class TopReboundsBySeasonList(generics.ListAPIView): + serializer_class = PlayerDataSerializer + + def get_queryset(self): + season = self.kwargs['season'] + return PlayerData.objects.filter(season=season).order_by('-TRB')[:20] + +# Fetch Top 20 players by BLK DESC for specified season. + + +class TopBlocksBySeasonList(generics.ListAPIView): + serializer_class = PlayerDataSerializer + + def get_queryset(self): + season = self.kwargs['season'] + return PlayerData.objects.filter(season=season).order_by('-BLK')[:20] + +# Fetch Top 20 players by STL DESC for season specified. + + +class TopStealsBySeasonList(generics.ListAPIView): + serializer_class = PlayerDataSerializer + + def get_queryset(self): + season = self.kwargs['season'] + return PlayerData.objects.filter(season=season).order_by('-STL')[:20] From 92cfd0af0f98fc1cf2959c761e3b2d802a7ddf80 Mon Sep 17 00:00:00 2001 From: nprasad2077 <114438461+nprasad2077@users.noreply.github.com> Date: Wed, 26 Apr 2023 14:56:07 -0500 Subject: [PATCH 6/7] add top ORB/DRB views and urls --- nba_data/urls.py | 4 +++- nba_data/views.py | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/nba_data/urls.py b/nba_data/urls.py index 4b0d6c1..45098fd 100644 --- a/nba_data/urls.py +++ b/nba_data/urls.py @@ -1,5 +1,5 @@ from django.urls import path -from .views import PlayerDataList, PlayerDataByTeamList, PlayerDataBySeasonList, PlayerDataByNameList, TopScorersbySeasonList, ThreeTwoTopPointTrends, TopAssistsBySeasonList, TopReboundsBySeasonList, TopBlocksBySeasonList, TopStealsBySeasonList +from .views import PlayerDataList, PlayerDataByTeamList, PlayerDataBySeasonList, PlayerDataByNameList, TopScorersbySeasonList, ThreeTwoTopPointTrends, TopAssistsBySeasonList, TopReboundsBySeasonList, TopBlocksBySeasonList, TopStealsBySeasonList, TopOffensiveReboundsBySeasonList, TopDefensiveReboundsBySeasonList urlpatterns = [ path('api/playerdata/', PlayerDataList.as_view(), name='playerdata_list'), @@ -12,4 +12,6 @@ urlpatterns = [ path('api/top_rebounds//', TopReboundsBySeasonList.as_view(), name='top_rebounds'), path('api/top_blocks//', TopBlocksBySeasonList.as_view(), name='top_blocks'), path('api/top_steals//', TopStealsBySeasonList.as_view(), name='top_steals'), + path('api/top_rebounds_offensive//', TopOffensiveReboundsBySeasonList.as_view(), name='top_rebounds_ORB'), + path('api/top_rebounds_defensive//', TopDefensiveReboundsBySeasonList.as_view(), name='top_rebounds_DRB'), ] \ No newline at end of file diff --git a/nba_data/views.py b/nba_data/views.py index c39eea0..30b42c6 100644 --- a/nba_data/views.py +++ b/nba_data/views.py @@ -121,3 +121,23 @@ class TopStealsBySeasonList(generics.ListAPIView): def get_queryset(self): season = self.kwargs['season'] return PlayerData.objects.filter(season=season).order_by('-STL')[:20] + +# Fetch Top 20 players by ORB DESC for season. + + +class TopOffensiveReboundsBySeasonList(generics.ListAPIView): + serializer_class = PlayerDataSerializer + + def get_queryset(self): + season = self.kwargs['season'] + return PlayerData.objects.filter(season=season).order_by('-ORB')[:20] + + +# Fetch Top 20 players by DRB DESC for season. + +class TopDefensiveReboundsBySeasonList(generics.ListAPIView): + serializer_class = PlayerDataSerializer + + def get_queryset(self): + season = self.kwargs['season'] + return PlayerData.objects.filter(season=season).order_by('-DRB')[:20] From 4455505fd7afc35af5825ee5dddd63d6f9fd39ae Mon Sep 17 00:00:00 2001 From: nprasad2077 <114438461+nprasad2077@users.noreply.github.com> Date: Wed, 26 Apr 2023 16:41:40 -0500 Subject: [PATCH 7/7] add calculation,view,url for PTS histogram --- nba_data/serializers.py | 5 +++++ nba_data/urls.py | 3 ++- nba_data/views.py | 35 ++++++++++++++++++++++++++++++++++- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/nba_data/serializers.py b/nba_data/serializers.py index 88634de..b383302 100644 --- a/nba_data/serializers.py +++ b/nba_data/serializers.py @@ -6,3 +6,8 @@ class PlayerDataSerializer(serializers.ModelSerializer): class Meta: model = PlayerData fields = '__all__' + +class HistogramDataSerializer(serializers.Serializer): + range = serializers.CharField() + count = serializers.IntegerField() + diff --git a/nba_data/urls.py b/nba_data/urls.py index 45098fd..14a3e00 100644 --- a/nba_data/urls.py +++ b/nba_data/urls.py @@ -1,5 +1,5 @@ from django.urls import path -from .views import PlayerDataList, PlayerDataByTeamList, PlayerDataBySeasonList, PlayerDataByNameList, TopScorersbySeasonList, ThreeTwoTopPointTrends, TopAssistsBySeasonList, TopReboundsBySeasonList, TopBlocksBySeasonList, TopStealsBySeasonList, TopOffensiveReboundsBySeasonList, TopDefensiveReboundsBySeasonList +from .views import PlayerDataList, PlayerDataByTeamList, PlayerDataBySeasonList, PlayerDataByNameList, TopScorersbySeasonList, ThreeTwoTopPointTrends, TopAssistsBySeasonList, TopReboundsBySeasonList, TopBlocksBySeasonList, TopStealsBySeasonList, TopOffensiveReboundsBySeasonList, TopDefensiveReboundsBySeasonList, PointsPerGameHistogramBySeasonList urlpatterns = [ path('api/playerdata/', PlayerDataList.as_view(), name='playerdata_list'), @@ -14,4 +14,5 @@ urlpatterns = [ path('api/top_steals//', TopStealsBySeasonList.as_view(), name='top_steals'), path('api/top_rebounds_offensive//', TopOffensiveReboundsBySeasonList.as_view(), name='top_rebounds_ORB'), path('api/top_rebounds_defensive//', TopDefensiveReboundsBySeasonList.as_view(), name='top_rebounds_DRB'), + path('api/points_per_game_histogram//', PointsPerGameHistogramBySeasonList.as_view(), name='points_per_game_histogram'), ] \ No newline at end of file diff --git a/nba_data/views.py b/nba_data/views.py index 30b42c6..c1d3874 100644 --- a/nba_data/views.py +++ b/nba_data/views.py @@ -3,10 +3,12 @@ from django.http import JsonResponse from django.core import serializers from .models import PlayerData from rest_framework import generics -from .serializers import PlayerDataSerializer +from .serializers import PlayerDataSerializer, HistogramDataSerializer from rest_framework.views import APIView from rest_framework.response import Response from django.db.models import Avg +from collections import Counter +import math # Create your views here. @@ -141,3 +143,34 @@ class TopDefensiveReboundsBySeasonList(generics.ListAPIView): def get_queryset(self): season = self.kwargs['season'] return PlayerData.objects.filter(season=season).order_by('-DRB')[:20] + +# PTS Histogram + + +class PointsPerGameHistogramBySeasonList(generics.ListAPIView): + serializer_class = HistogramDataSerializer + + def get_queryset(self): + season = self.kwargs['season'] + queryset = PlayerData.objects.filter(season=season) + + # Get the points per game for each player + points_per_game_list = [float(player.PTS) for player in queryset] + + # Define histogram bins (e.g., 0-5, 5-10, 10-15, etc.) + bin_ranges = range(0, int(math.ceil(max(points_per_game_list))) + 1, 5) + histogram_data = Counter() + + # Fill the histogram with data + for ppg in points_per_game_list: + bin_index = next( + (i for i, r in enumerate(bin_ranges) if r >= ppg), -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