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
|
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)
|
||||||
|
|||||||
Reference in New Issue
Block a user