use env for data.csv
This commit is contained in:
31
src/app.py
31
src/app.py
@@ -1,3 +1,4 @@
|
||||
import os
|
||||
from flask import Flask, render_template
|
||||
import pandas as pd
|
||||
import plotly.express as px
|
||||
@@ -17,6 +18,7 @@ app = Flask(__name__)
|
||||
# Data loading
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def get_data_frame(filename):
|
||||
df = pd.read_csv(filename)
|
||||
df["Date"] = pd.to_datetime(df["Date"], dayfirst=True)
|
||||
@@ -27,7 +29,8 @@ def get_data_frame(filename):
|
||||
def build_hovertext(df, attendance_columns):
|
||||
present = [c for c in attendance_columns if c in df.columns]
|
||||
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,
|
||||
)
|
||||
|
||||
@@ -45,7 +48,8 @@ def generate_position_trend(df):
|
||||
df = df.copy()
|
||||
df["Date_ordinal"] = df["Date"].map(pd.Timestamp.toordinal)
|
||||
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)
|
||||
|
||||
X = sm.add_constant(df["Date_ordinal"])
|
||||
@@ -61,7 +65,8 @@ def generate_position_trend(df):
|
||||
if slope < 0:
|
||||
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_percentile = intercept + slope * extended_ords
|
||||
@@ -120,9 +125,11 @@ def generate_position_trend(df):
|
||||
fig.update_layout(
|
||||
title="Relative Position Over Time",
|
||||
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",
|
||||
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",
|
||||
margin=dict(t=60, b=40),
|
||||
)
|
||||
@@ -146,12 +153,14 @@ def generate_player_impact(df):
|
||||
n = len(attended)
|
||||
if n >= MIN_APPEARANCES:
|
||||
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:
|
||||
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 = [
|
||||
"#16a34a" if p <= overall_percentile else "#dc2626"
|
||||
for p in impact_df["Relative Percentile"]
|
||||
@@ -176,7 +185,8 @@ def generate_player_impact(df):
|
||||
x=overall_percentile,
|
||||
line_dash="dot",
|
||||
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",
|
||||
)
|
||||
|
||||
@@ -330,7 +340,8 @@ def generate_weekly_attendance_calendar(df):
|
||||
y_labels.append(f"{year} · W{start}-{end}")
|
||||
|
||||
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,
|
||||
)
|
||||
|
||||
@@ -389,7 +400,7 @@ def generate_visualisations(df):
|
||||
|
||||
@app.route("/")
|
||||
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)
|
||||
player_table = generate_player_table(df)
|
||||
plots = generate_visualisations(df)
|
||||
|
||||
Reference in New Issue
Block a user