diff --git a/nba_data/migrations/0012_playersalarydata.py b/nba_data/migrations/0012_playersalarydata.py
new file mode 100644
index 0000000..e5b188f
--- /dev/null
+++ b/nba_data/migrations/0012_playersalarydata.py
@@ -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)),
+ ],
+ ),
+ ]
diff --git a/nba_data/migrations/0013_playersalarydata_season_playersalarydata_team.py b/nba_data/migrations/0013_playersalarydata_season_playersalarydata_team.py
new file mode 100644
index 0000000..0f600b2
--- /dev/null
+++ b/nba_data/migrations/0013_playersalarydata_season_playersalarydata_team.py
@@ -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),
+ ),
+ ]
diff --git a/nba_data/migrations/0014_playershotchartdata.py b/nba_data/migrations/0014_playershotchartdata.py
new file mode 100644
index 0000000..81b0220
--- /dev/null
+++ b/nba_data/migrations/0014_playershotchartdata.py
@@ -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)),
+ ],
+ ),
+ ]
diff --git a/nba_data/migrations/0015_alter_playershotchartdata_time_remaining.py b/nba_data/migrations/0015_alter_playershotchartdata_time_remaining.py
new file mode 100644
index 0000000..9c0f2bf
--- /dev/null
+++ b/nba_data/migrations/0015_alter_playershotchartdata_time_remaining.py
@@ -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),
+ ),
+ ]
diff --git a/nba_data/migrations/0016_alter_playershotchartdata_qtr.py b/nba_data/migrations/0016_alter_playershotchartdata_qtr.py
new file mode 100644
index 0000000..337ed34
--- /dev/null
+++ b/nba_data/migrations/0016_alter_playershotchartdata_qtr.py
@@ -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),
+ ),
+ ]
diff --git a/nba_data/migrations/0017_alter_playershotchartdata_result.py b/nba_data/migrations/0017_alter_playershotchartdata_result.py
new file mode 100644
index 0000000..400f4ee
--- /dev/null
+++ b/nba_data/migrations/0017_alter_playershotchartdata_result.py
@@ -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),
+ ),
+ ]
diff --git a/nba_data/models.py b/nba_data/models.py
index f7c39ca..810a7b1 100644
--- a/nba_data/models.py
+++ b/nba_data/models.py
@@ -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
+
+
+
+
diff --git a/nba_data/nba_scraper_advanced.py b/nba_data/nba_scraper_advanced.py
index e8e4808..2e7ed4b 100644
--- a/nba_data/nba_scraper_advanced.py
+++ b/nba_data/nba_scraper_advanced.py
@@ -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:
diff --git a/nba_data/nba_scraper_playoffs_totals.py b/nba_data/nba_scraper_playoffs_totals.py
index 202fe41..47853ff 100644
--- a/nba_data/nba_scraper_playoffs_totals.py
+++ b/nba_data/nba_scraper_playoffs_totals.py
@@ -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? ')
diff --git a/nba_data/nba_scraper_salary.py b/nba_data/nba_scraper_salary.py
new file mode 100644
index 0000000..ad2e1dc
--- /dev/null
+++ b/nba_data/nba_scraper_salary.py
@@ -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')
+
+
+
\ No newline at end of file
diff --git a/nba_data/nba_scraper_shot_chart.py b/nba_data/nba_scraper_shot_chart.py
new file mode 100644
index 0000000..1bb7462
--- /dev/null
+++ b/nba_data/nba_scraper_shot_chart.py
@@ -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('
')
+
+ # 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')
diff --git a/nba_data/nba_scraper_totals.py b/nba_data/nba_scraper_totals.py
index 8ca132f..600e30a 100644
--- a/nba_data/nba_scraper_totals.py
+++ b/nba_data/nba_scraper_totals.py
@@ -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.
diff --git a/nba_data/serializers.py b/nba_data/serializers.py
index 9f03285..fd0147c 100644
--- a/nba_data/serializers.py
+++ b/nba_data/serializers.py
@@ -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'
+
diff --git a/nba_data/templates/landing.html b/nba_data/templates/landing.html
new file mode 100644
index 0000000..47de3e7
--- /dev/null
+++ b/nba_data/templates/landing.html
@@ -0,0 +1,14 @@
+
+
+