use env for data.csv

This commit is contained in:
John Gatward
2026-03-20 12:36:59 +00:00
parent 71450d20cb
commit 80ef59af5e

View File

@@ -1,3 +1,4 @@
import os
from flask import Flask, render_template from flask import Flask, render_template
import pandas as pd import pandas as pd
import plotly.express as px import plotly.express as px
@@ -17,6 +18,7 @@ app = Flask(__name__)
# Data loading # Data loading
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
def get_data_frame(filename): def get_data_frame(filename):
df = pd.read_csv(filename) df = pd.read_csv(filename)
df["Date"] = pd.to_datetime(df["Date"], dayfirst=True) df["Date"] = pd.to_datetime(df["Date"], dayfirst=True)
@@ -27,7 +29,8 @@ def get_data_frame(filename):
def build_hovertext(df, attendance_columns): def build_hovertext(df, attendance_columns):
present = [c for c in attendance_columns if c in df.columns] present = [c for c in attendance_columns if c in df.columns]
return df[present].apply( return df[present].apply(
lambda row: ", ".join(p for p in present if row[p] == 1) or "No attendance", lambda row: ", ".join(
p for p in present if row[p] == 1) or "No attendance",
axis=1, axis=1,
) )
@@ -45,7 +48,8 @@ def generate_position_trend(df):
df = df.copy() df = df.copy()
df["Date_ordinal"] = df["Date"].map(pd.Timestamp.toordinal) df["Date_ordinal"] = df["Date"].map(pd.Timestamp.toordinal)
df["Relative Percentile"] = df["Relative Position"] * 100 df["Relative Percentile"] = df["Relative Position"] * 100
df["Rolling Avg (5)"] = df["Relative Percentile"].rolling(5, min_periods=1).mean() df["Rolling Avg (5)"] = df["Relative Percentile"].rolling(
5, min_periods=1).mean()
df["Attendees"] = build_hovertext(df, constants.PLAYER_NAME_COLUMNS) df["Attendees"] = build_hovertext(df, constants.PLAYER_NAME_COLUMNS)
X = sm.add_constant(df["Date_ordinal"]) X = sm.add_constant(df["Date_ordinal"])
@@ -61,7 +65,8 @@ def generate_position_trend(df):
if slope < 0: if slope < 0:
predicted_ordinal = (target_percentile - intercept) / slope predicted_ordinal = (target_percentile - intercept) / slope
end_ord = max(max_ord, predicted_ordinal) if predicted_ordinal and predicted_ordinal > max_ord else max_ord end_ord = max(
max_ord, predicted_ordinal) if predicted_ordinal and predicted_ordinal > max_ord else max_ord
extended_ords = np.linspace(min_ord, end_ord, 200) extended_ords = np.linspace(min_ord, end_ord, 200)
extended_percentile = intercept + slope * extended_ords extended_percentile = intercept + slope * extended_ords
@@ -120,9 +125,11 @@ def generate_position_trend(df):
fig.update_layout( fig.update_layout(
title="Relative Position Over Time", title="Relative Position Over Time",
xaxis_title="Date", xaxis_title="Date",
yaxis=dict(title="Relative Position Percentile (lower is better)", range=[0, 100], ticksuffix="th"), yaxis=dict(title="Relative Position Percentile (lower is better)", range=[
0, 100], ticksuffix="th"),
template="plotly_white", template="plotly_white",
legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1), legend=dict(orientation="h", yanchor="bottom",
y=1.02, xanchor="right", x=1),
hovermode="x unified", hovermode="x unified",
margin=dict(t=60, b=40), margin=dict(t=60, b=40),
) )
@@ -146,12 +153,14 @@ def generate_player_impact(df):
n = len(attended) n = len(attended)
if n >= MIN_APPEARANCES: if n >= MIN_APPEARANCES:
percentile = attended["Relative Position"].mean() * 100 percentile = attended["Relative Position"].mean() * 100
rows.append({"Player": name, "Relative Percentile": round(percentile, 1), "Games": n}) rows.append(
{"Player": name, "Relative Percentile": round(percentile, 1), "Games": n})
if not rows: if not rows:
return go.Figure() return go.Figure()
impact_df = pd.DataFrame(rows).sort_values("Relative Percentile", ascending=True) impact_df = pd.DataFrame(rows).sort_values(
"Relative Percentile", ascending=True)
colors = [ colors = [
"#16a34a" if p <= overall_percentile else "#dc2626" "#16a34a" if p <= overall_percentile else "#dc2626"
for p in impact_df["Relative Percentile"] for p in impact_df["Relative Percentile"]
@@ -176,7 +185,8 @@ def generate_player_impact(df):
x=overall_percentile, x=overall_percentile,
line_dash="dot", line_dash="dot",
line_color="#6b7280", line_color="#6b7280",
annotation_text=f"Overall avg ({constants.ordinal(round(overall_percentile))})", annotation_text=f"Overall avg ({constants.ordinal(
round(overall_percentile))})",
annotation_position="top right", annotation_position="top right",
) )
@@ -330,7 +340,8 @@ def generate_weekly_attendance_calendar(df):
y_labels.append(f"{year} · W{start}-{end}") y_labels.append(f"{year} · W{start}-{end}")
calendar["RowLabel"] = calendar.apply( calendar["RowLabel"] = calendar.apply(
lambda r: f"{int(r['Year'])} · W{(int(r['Block']) - 1) * 13 + 1}-{min(int(r['Block']) * 13, 53)}", lambda r: f"{int(r['Year'])} · W{(int(r['Block']) - 1)
* 13 + 1}-{min(int(r['Block']) * 13, 53)}",
axis=1, axis=1,
) )
@@ -389,7 +400,7 @@ def generate_visualisations(df):
@app.route("/") @app.route("/")
def index(): def index():
df = get_data_frame("data.csv") df = get_data_frame(os.environ.get("DATA_CSV_PATH", "data.csv"))
stats, highlights = generate_stats(df) stats, highlights = generate_stats(df)
player_table = generate_player_table(df) player_table = generate_player_table(df)
plots = generate_visualisations(df) plots = generate_visualisations(df)