feat: bootstrap HoopScout scouting app

This commit is contained in:
bisco
2026-06-03 21:37:15 +02:00
parent c4b1b6ee15
commit cc188468bc
52 changed files with 14505 additions and 126 deletions
@@ -0,0 +1 @@
@@ -0,0 +1,156 @@
from django.core.management.base import BaseCommand
from scouting.models import League, Player, PlayerGameLog, PlayerSeasonStat, Season, Team
class Command(BaseCommand):
help = "Seed synthetic European scouting data for local development."
def handle(self, *args, **options):
season, _ = Season.objects.update_or_create(label="2025-26", defaults={"is_active": True})
leagues = {
"LBA": League.objects.update_or_create(
code="LBA",
defaults={"name": "Lega Basket Serie A", "region": "Europe", "country": "Italy"},
)[0],
"ACB": League.objects.update_or_create(
code="ACB",
defaults={"name": "Liga Endesa", "region": "Europe", "country": "Spain"},
)[0],
"ABA": League.objects.update_or_create(
code="ABA",
defaults={"name": "ABA League", "region": "Europe", "country": "Adriatic"},
)[0],
"BBL": League.objects.update_or_create(
code="BBL",
defaults={"name": "Basketball Bundesliga", "region": "Europe", "country": "Germany"},
)[0],
"BSL": League.objects.update_or_create(
code="BSL",
defaults={"name": "Basketbol Super Ligi", "region": "Europe", "country": "Turkey"},
)[0],
"LNB": League.objects.update_or_create(
code="LNB",
defaults={"name": "LNB Elite", "region": "Europe", "country": "France"},
)[0],
}
demo_rows = [
{
"first_name": "Luca",
"last_name": "Marini",
"position": "PG",
"role": "Primary ball handler",
"birth_year": 2001,
"height_cm": 190,
"weight_kg": 86,
"nationality": "Italy",
"team": "Milano",
"league": "LBA",
"points": 16.8,
"assists": 6.2,
"rebounds": 3.8,
"efficiency": 20.5,
"ts": 59.2,
"usage": 25.0,
},
{
"first_name": "Mateo",
"last_name": "Santos",
"position": "SF",
"role": "3 and D wing",
"birth_year": 1999,
"height_cm": 201,
"weight_kg": 96,
"nationality": "Spain",
"team": "Madrid",
"league": "ACB",
"points": 11.2,
"assists": 2.1,
"rebounds": 5.5,
"efficiency": 13.7,
"ts": 55.8,
"usage": 17.5,
},
{
"first_name": "Jonas",
"last_name": "Keller",
"position": "C",
"role": "Roll man",
"birth_year": 2000,
"height_cm": 211,
"weight_kg": 109,
"nationality": "Germany",
"team": "Berlin",
"league": "BBL",
"points": 13.1,
"assists": 1.4,
"rebounds": 8.6,
"efficiency": 18.9,
"ts": 63.1,
"usage": 19.0,
},
]
for row in demo_rows:
league = leagues[row["league"]]
team, _ = Team.objects.update_or_create(
name=row["team"],
league=league,
defaults={"country": league.country},
)
player, _ = Player.objects.update_or_create(
first_name=row["first_name"],
last_name=row["last_name"],
birth_year=row["birth_year"],
nationality=row["nationality"],
defaults={
"position": row["position"],
"role": row["role"],
"height_cm": row["height_cm"],
"weight_kg": row["weight_kg"],
"current_team": team,
"external_source": "synthetic",
},
)
PlayerSeasonStat.objects.update_or_create(
player=player,
team=team,
league=league,
season=season,
defaults={
"games_played": 28,
"minutes_per_game": 27.5,
"points_per_game": row["points"],
"assists_per_game": row["assists"],
"rebounds_per_game": row["rebounds"],
"steals_per_game": 1.0,
"blocks_per_game": 0.4,
"turnovers_per_game": 1.8,
"field_goal_percentage": 48.0,
"three_point_percentage": 37.5,
"free_throw_percentage": 81.0,
"efficiency_rating": row["efficiency"],
"true_shooting_percentage": row["ts"],
"usage_percentage": row["usage"],
"total_points": int(row["points"] * 28),
"total_assists": int(row["assists"] * 28),
"total_rebounds": int(row["rebounds"] * 28),
},
)
PlayerGameLog.objects.update_or_create(
player=player,
team=team,
league=league,
season=season,
game_date="2026-01-10",
opponent="Top domestic opponent",
defaults={
"points": int(row["points"] + 10),
"assists": int(row["assists"] + 3),
"rebounds": int(row["rebounds"] + 2),
"efficiency_rating": row["efficiency"] + 10,
},
)
self.stdout.write(self.style.SUCCESS("Seeded synthetic HoopScout demo data."))