From 4db6a51e5c320a195de02c242269aa3c03972e34 Mon Sep 17 00:00:00 2001 From: R Brook Date: Sun, 21 Dec 2025 19:38:34 +0100 Subject: [PATCH 1/8] [5] Add NextGen stats fetching. --- .github/workflows/nextjs.yml | 7 +++-- .gitignore | 7 ++++- pages/_app.tsx | 10 +++++-- pages/qb/index.tsx | 50 ++++++++++++++++++++++++++++++++++ scripts/ngs_passing.py | 7 +++++ scripts/ngs_receiving.py | 7 +++++ scripts/ngs_rushing.py | 7 +++++ scripts/qb_season.py | 7 ++++- scripts/qb_weekly.py | 7 ++++- scripts/utils/fetch_ngs.py | 32 ++++++++++++++++++++++ scripts/utils/fetch_qb_data.py | 5 +++- 11 files changed, 137 insertions(+), 9 deletions(-) create mode 100644 pages/qb/index.tsx create mode 100644 scripts/ngs_passing.py create mode 100644 scripts/ngs_receiving.py create mode 100644 scripts/ngs_rushing.py create mode 100644 scripts/utils/fetch_ngs.py diff --git a/.github/workflows/nextjs.yml b/.github/workflows/nextjs.yml index 238cd63..6834d16 100644 --- a/.github/workflows/nextjs.yml +++ b/.github/workflows/nextjs.yml @@ -43,9 +43,12 @@ jobs: - name: Run Python script run: | set -e - python scripts/team_data.py - python scripts/qb_weekly.py + python scripts/ngs_passing.py + python scripts/ngs_receiving.py + python scripts/ngs_rushing.py python scripts/qb_season.py + python scripts/qb_weekly.py + python scripts/team_data.py # Upload the file the script produced - name: Upload Python output diff --git a/.gitignore b/.gitignore index f593a5f..cf8f61f 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,9 @@ npm-debug.log* next-env.d.ts # script outputs -/scripts/generated-files/*.ts \ No newline at end of file +/scripts/generated-files/*.ts + +# temporary +/public/qb_test/* +/public/images/players/* +/public/qb_headshots 22.31.32/* \ No newline at end of file diff --git a/pages/_app.tsx b/pages/_app.tsx index a7a790f..7459efa 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -1,6 +1,10 @@ -import "@/styles/globals.css"; -import type { AppProps } from "next/app"; +import "@/styles/globals.css" +import type { AppProps } from "next/app" export default function App({ Component, pageProps }: AppProps) { - return ; + return ( +
+ +
+ ) } diff --git a/pages/qb/index.tsx b/pages/qb/index.tsx new file mode 100644 index 0000000..577af4f --- /dev/null +++ b/pages/qb/index.tsx @@ -0,0 +1,50 @@ +import { qbDataSeason } from "@/scripts/generated-files/qb-data-season" +import Head from "next/head" +import Image from "next/image" + +export default function Home() { + const qbsSortedTDs = qbDataSeason.sort((a, b) => + a.passing_tds + a.rushing_tds > b.passing_tds + b.rushing_tds ? -1 : 1 + ) + + return ( +
+ + NFL Stats + +
+

Quarterback Stats

+
+ {qbsSortedTDs.map((qb, key) => ( +
+
+ {qb.player_display_name} +
+ +
+
+ Name: {qb.player_name} + TDs: {qb.passing_tds + qb.rushing_tds} +
+ Passing: {qb.passing_tds} Rushing: {qb.rushing_tds} +
+
+ ))} +
+
+
+ ) +} diff --git a/scripts/ngs_passing.py b/scripts/ngs_passing.py new file mode 100644 index 0000000..2ac9e50 --- /dev/null +++ b/scripts/ngs_passing.py @@ -0,0 +1,7 @@ +from utils.fetch_ngs import parse_ngs + +StatType = "passing" +OutputFile = "ngs-data-" + StatType +VariableName = "nGSStats" + StatType.capitalize() + +parse_ngs(StatType, OutputFile, VariableName) \ No newline at end of file diff --git a/scripts/ngs_receiving.py b/scripts/ngs_receiving.py new file mode 100644 index 0000000..45f39d4 --- /dev/null +++ b/scripts/ngs_receiving.py @@ -0,0 +1,7 @@ +from utils.fetch_ngs import parse_ngs + +StatType = "receiving" +OutputFile = "ngs-data-" + StatType +VariableName = "nGSStats" + StatType.capitalize() + +parse_ngs(StatType, OutputFile, VariableName) \ No newline at end of file diff --git a/scripts/ngs_rushing.py b/scripts/ngs_rushing.py new file mode 100644 index 0000000..1625de2 --- /dev/null +++ b/scripts/ngs_rushing.py @@ -0,0 +1,7 @@ +from utils.fetch_ngs import parse_ngs + +StatType = "rushing" +OutputFile = "ngs-data-" + StatType +VariableName = "nGSStats" + StatType.capitalize() + +parse_ngs(StatType, OutputFile, VariableName) \ No newline at end of file diff --git a/scripts/qb_season.py b/scripts/qb_season.py index a195640..56a36e0 100644 --- a/scripts/qb_season.py +++ b/scripts/qb_season.py @@ -1,3 +1,8 @@ from utils.fetch_qb_data import parse_qbs -parse_qbs("reg", "qb_season", "qb-data-season", "qbDataSeason") \ No newline at end of file +SummaryLevel = "season" +TriggerFileName = "qb_" + SummaryLevel +OutputFileName = "qb-data-" + SummaryLevel +OutputConstName = "qbData" + SummaryLevel.capitalize() + +parse_qbs("reg", TriggerFileName, OutputFileName, OutputConstName) \ No newline at end of file diff --git a/scripts/qb_weekly.py b/scripts/qb_weekly.py index 9f2ac4e..600289e 100644 --- a/scripts/qb_weekly.py +++ b/scripts/qb_weekly.py @@ -1,3 +1,8 @@ from utils.fetch_qb_data import parse_qbs -parse_qbs("week", "qb_weekly", "qb-data-weekly", "qbDataWeekly") \ No newline at end of file +SummaryLevel = "weekly" +TriggerFileName = "qb_" + SummaryLevel +OutputFileName = "qb-data-" + SummaryLevel +OutputConstName = "qbData" + SummaryLevel.capitalize() + +parse_qbs("week", TriggerFileName, OutputFileName, OutputConstName) \ No newline at end of file diff --git a/scripts/utils/fetch_ngs.py b/scripts/utils/fetch_ngs.py new file mode 100644 index 0000000..20e3071 --- /dev/null +++ b/scripts/utils/fetch_ngs.py @@ -0,0 +1,32 @@ +import json +import polars as pl +import nflreadpy as nfl +from pathlib import Path +from typing import Literal + +IStatType = Literal["passing", "receiving", "rushing"] + + +def parse_ngs(statType: IStatType, outputFileName: str, variableName: str): + """ + Fetch current-season next-gen stats and write them to a .ts file + """ + try: + # Fetch next-gen stats (current season by default) + player_stats = nfl.load_nextgen_stats(stat_type=statType).to_dicts() + + # Write the data to a TypeScript file + output_path = Path("scripts/generated-files") / f"{outputFileName}.ts" + output_path.parent.mkdir(parents=True, exist_ok=True) + + with open(output_path, "w", encoding="utf-8") as f: + f.write("// file generated by fetch_ngs.py\n\n") + f.write("export const " + variableName + " = ") + json.dump(player_stats, f, indent=2) + f.write(";\n") + + print(f"Created file {output_path} with {len(player_stats)} " + statType) + + except Exception as e: + print(f"ERROR: {e}") + raise \ No newline at end of file diff --git a/scripts/utils/fetch_qb_data.py b/scripts/utils/fetch_qb_data.py index 2152c92..da5dd81 100644 --- a/scripts/utils/fetch_qb_data.py +++ b/scripts/utils/fetch_qb_data.py @@ -2,8 +2,11 @@ import polars as pl import nflreadpy as nfl from pathlib import Path +from typing import Literal -def parse_qbs(summaryLevel, triggerFileName, outputFileName, outputConstName): +ISummaryLevel = Literal["week", "reg", "post", "reg+post"] + +def parse_qbs(summaryLevel: ISummaryLevel, triggerFileName: str, outputFileName: str, outputConstName: str): """ Fetch current-season QB stats and write them to scripts/qb-data.ts """ From 5bd44c46e6d9954dee724537f15a0e3d4ad6e1f6 Mon Sep 17 00:00:00 2001 From: R Brook Date: Sun, 21 Dec 2025 19:39:17 +0100 Subject: [PATCH 2/8] [5] Temporary change of branch to trigger GitHub Actions. --- .github/workflows/nextjs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nextjs.yml b/.github/workflows/nextjs.yml index 6834d16..1b90b2b 100644 --- a/.github/workflows/nextjs.yml +++ b/.github/workflows/nextjs.yml @@ -4,7 +4,7 @@ name: Deploy Next.js site to Pages on: # Runs on pushes targeting the default branch push: - branches: ["main"] + # branches: ["main"] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: From 1a9d41ccc602caa6166128ea2f4e026d917725c1 Mon Sep 17 00:00:00 2001 From: R Brook Date: Sun, 21 Dec 2025 19:45:20 +0100 Subject: [PATCH 3/8] [5] Add NGS stats generated files to uploaded Python files during GitHub Action. --- .github/workflows/nextjs.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/nextjs.yml b/.github/workflows/nextjs.yml index 1b90b2b..85975cf 100644 --- a/.github/workflows/nextjs.yml +++ b/.github/workflows/nextjs.yml @@ -60,6 +60,9 @@ jobs: scripts/generated-files/team-data.ts scripts/generated-files/qb-data-weekly.ts scripts/generated-files/qb-data-season.ts + scripts/generated-files/ngs-data-passing.ts + scripts/generated-files/ngs-data-receiving.ts + scripts/generated-files/ngs-data-rushing.ts # Build job build: From 03eaacb0ecc12e1c1946deb65d3fdcb518983cd9 Mon Sep 17 00:00:00 2001 From: R Brook Date: Sun, 21 Dec 2025 21:35:18 +0100 Subject: [PATCH 4/8] [5] Switch GitHub Action to run only on main branch. --- .github/workflows/nextjs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nextjs.yml b/.github/workflows/nextjs.yml index 85975cf..e89f744 100644 --- a/.github/workflows/nextjs.yml +++ b/.github/workflows/nextjs.yml @@ -4,7 +4,7 @@ name: Deploy Next.js site to Pages on: # Runs on pushes targeting the default branch push: - # branches: ["main"] + branches: ["main"] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: From 415c795d911ef21cc5789ca5c2de3f10aa2f9ecd Mon Sep 17 00:00:00 2001 From: R Brook Date: Sun, 21 Dec 2025 21:43:23 +0100 Subject: [PATCH 5/8] [5] Tidy up homepage. --- pages/index.tsx | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/pages/index.tsx b/pages/index.tsx index cfa13a3..4e11657 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,3 +1,6 @@ +import { nGSStatsPassing } from "@/scripts/generated-files/ngs-data-passing" +import { nGSStatsReceiving } from "@/scripts/generated-files/ngs-data-receiving" +import { nGSStatsRushing } from "@/scripts/generated-files/ngs-data-rushing" import { qbDataSeason } from "@/scripts/generated-files/qb-data-season" import { qbDataWeekly } from "@/scripts/generated-files/qb-data-weekly" import { teamData } from "@/scripts/generated-files/team-data" @@ -12,19 +15,14 @@ export default function Home() {

NFL Stats

- - {teamData ? "has fetched team data" : "has not fetched team data"} - - - {qbDataSeason - ? "has fetched QB season data" - : "has not fetched QB data"} - - - {qbDataWeekly - ? "has fetched QB weekly data" - : "has not fetched QB data"} - +
    +
  • {teamData && "has fetched team data"}
  • +
  • {qbDataSeason && "has fetched QB season data"}
  • +
  • {qbDataWeekly && "has fetched QB weekly data"}
  • +
  • {nGSStatsPassing && "has fetched NGS passing"}
  • +
  • {nGSStatsReceiving && "has fetched NGS passing"}
  • +
  • {nGSStatsRushing && "has fetched NGS passing"}
  • +
From 59a10dcb79b77764843622e586cee2bc3117c8f6 Mon Sep 17 00:00:00 2001 From: R Brook Date: Sun, 21 Dec 2025 21:48:38 +0100 Subject: [PATCH 6/8] [5] Make Python script runner. --- .github/workflows/nextjs.yml | 15 ++++++++------- scripts/run_scripts.py | 5 +++++ scripts/utils/fetch_ngs.py | 1 - 3 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 scripts/run_scripts.py diff --git a/.github/workflows/nextjs.yml b/.github/workflows/nextjs.yml index e89f744..345d53f 100644 --- a/.github/workflows/nextjs.yml +++ b/.github/workflows/nextjs.yml @@ -4,7 +4,7 @@ name: Deploy Next.js site to Pages on: # Runs on pushes targeting the default branch push: - branches: ["main"] + # branches: ["main"] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -43,12 +43,13 @@ jobs: - name: Run Python script run: | set -e - python scripts/ngs_passing.py - python scripts/ngs_receiving.py - python scripts/ngs_rushing.py - python scripts/qb_season.py - python scripts/qb_weekly.py - python scripts/team_data.py + python scripts/run_scripts.py + # python scripts/ngs_passing.py + # python scripts/ngs_receiving.py + # python scripts/ngs_rushing.py + # python scripts/qb_season.py + # python scripts/qb_weekly.py + # python scripts/team_data.py # Upload the file the script produced - name: Upload Python output diff --git a/scripts/run_scripts.py b/scripts/run_scripts.py new file mode 100644 index 0000000..6236752 --- /dev/null +++ b/scripts/run_scripts.py @@ -0,0 +1,5 @@ +from pathlib import Path +import subprocess + +for script in sorted(Path("scripts").glob("*.py")): + subprocess.run(["python", script], check=True) diff --git a/scripts/utils/fetch_ngs.py b/scripts/utils/fetch_ngs.py index 20e3071..b968b55 100644 --- a/scripts/utils/fetch_ngs.py +++ b/scripts/utils/fetch_ngs.py @@ -6,7 +6,6 @@ IStatType = Literal["passing", "receiving", "rushing"] - def parse_ngs(statType: IStatType, outputFileName: str, variableName: str): """ Fetch current-season next-gen stats and write them to a .ts file From 03a2de9c05cd96f23929946a8958f7bb38ce64f1 Mon Sep 17 00:00:00 2001 From: R Brook Date: Sun, 21 Dec 2025 21:52:55 +0100 Subject: [PATCH 7/8] [5] Move script runner outside of folder it runs. --- scripts/run_scripts.py => run_scripts.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/run_scripts.py => run_scripts.py (100%) diff --git a/scripts/run_scripts.py b/run_scripts.py similarity index 100% rename from scripts/run_scripts.py rename to run_scripts.py From 97cd2c33032011994706dc5deed9deb8e27ca5c5 Mon Sep 17 00:00:00 2001 From: R Brook Date: Sun, 21 Dec 2025 21:54:21 +0100 Subject: [PATCH 8/8] [5] Fix broken GitHub Actions file. --- .github/workflows/nextjs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nextjs.yml b/.github/workflows/nextjs.yml index 345d53f..83ed445 100644 --- a/.github/workflows/nextjs.yml +++ b/.github/workflows/nextjs.yml @@ -43,7 +43,7 @@ jobs: - name: Run Python script run: | set -e - python scripts/run_scripts.py + python run_scripts.py # python scripts/ngs_passing.py # python scripts/ngs_receiving.py # python scripts/ngs_rushing.py