Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/black-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ on:
branches: [main]
paths:
- '**/*.py'
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches: [main, dev]
pull_request:
branches: [main]
workflow_dispatch:

jobs:
test:
Expand Down
4 changes: 2 additions & 2 deletions database/db_ingestion.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Reads `front_7_pass_rush/{season}.xlsx` and
`ol_pass_block/{season}.xlsx` files that
`preprocessing/front_7.py` and `preprocessing/offensive_line.py` already
produce, and upserts them into `pass_rush_stats` / `pass_block_stats` tables.
produce, and bulk-inserts them into `pass_rush_stats` / `pass_block_stats` tables.

Idempotent: rerunning for same season/position first deletes existing
rows for that slice, then bulk-inserts fresh ones — cleaner than
Expand Down Expand Up @@ -107,7 +107,7 @@ def ingest_pass_rush(sess: Session, data_dir: Path, seasons: list[int]) -> int:

position_df.dropna(subset=["PR Opp"], inplace=True)

# Wipe slice before reinserting: simplest cross-dialect upsert.
# Wipe slice before re-insertion.
sess.execute(
delete(PassRushStat).where(
PassRushStat.season == season,
Expand Down
11 changes: 9 additions & 2 deletions database/db_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class PassRushStat(Base):

id = Column(Integer, primary_key=True, autoincrement=True)
season = Column(Integer, nullable=False)

position = Column(String(4), nullable=False) # DI / ED.
team_code = Column(String(4), ForeignKey("teams.code"), nullable=False)
player = Column(String, nullable=False)
Expand All @@ -46,10 +47,13 @@ class PassRushStat(Base):
games = Column(Integer)
pr_opp = Column(Integer) # PR Opp.
tps_pr_opp = Column(Integer) # TPS PR Opp.

win_rate = Column(Float) # Win Rate.
tps_win_rate = Column(Float) # TPS Win Rate.

pressure_rate = Column(Float) # Pressure Rate.
tps_pressure_rate = Column(Float) # TPS Pressure Rate.

havoc_rate = Column(Float) # Havoc Rate.
tps_havoc_rate = Column(Float) # TPS Havoc Rate.

Expand All @@ -72,16 +76,19 @@ class PassBlockStat(Base):

id = Column(Integer, primary_key=True, autoincrement=True)
season = Column(Integer, nullable=False)
position = Column(String(4), nullable=False) # T / G / C

position = Column(String(4), nullable=False) # T / G / C.
team_code = Column(String(4), ForeignKey("teams.code"), nullable=False)
player = Column(String, nullable=False)
abbr_name = Column(String, nullable=False)

games = Column(Integer)
non_spike_pb_snaps = Column(Integer) # Non Spike PB Snaps.
tps_non_spike_pb_snaps = Column(Integer) # TPS Non Spike PB Snaps.

allowed_pressure_pct = Column(Float) # Allowed Pressure %.
tps_allowed_pressure_pct = Column(Float) # TPS Allowed Pressure %.

allowed_havoc_pct = Column(Float) # Allowed Havoc %.
tps_allowed_havoc_pct = Column(Float) # TPS Allowed Havoc %.

Expand All @@ -101,7 +108,7 @@ class PassBlockStat(Base):

# Serialization helpers used by main.py to keep API payload shape
# identical to what frontend already expects (space-and-mixed-case keys
# preserved so no client-side renaming is needed). ---
# preserved so no client-side renaming is needed).


def pass_rush_row_to_dict(row: PassRushStat) -> dict:
Expand Down
Loading
Loading