diff --git a/dashboard/pages/03_auction.py b/dashboard/pages/03_auction.py index 04f9078..d11c554 100644 --- a/dashboard/pages/03_auction.py +++ b/dashboard/pages/03_auction.py @@ -15,7 +15,7 @@ from dashboard.viz.components import inject_css, section, insight, role_chip, kp from dashboard.viz.charts import budget_waterfall, value_scatter from dashboard.viz.template import ( PITCH_GREEN, GOLD, RED, SKY, VIOLET, BG, CARD_BG, BORDER, TEXT_SECONDARY, - WHITE, FANTABETO_TEMPLATE, HEATMAP_COLORS, ROLE_COLORS, ROLE_ICONS, + WHITE, FANTABETO_TEMPLATE, HEATMAP_COLORS, ROLE_COLORS, ROLE_ICONS, GRIDLINE, ) AUCTION_PLAN = Path(__file__).resolve().parent.parent.parent / "data" / "auction_plan_al_cihred.xlsx" @@ -214,6 +214,30 @@ def run(): fig = value_scatter(players) st.plotly_chart(fig, width="stretch") + # ── Contingency Plan ──── + st.divider() + section("🔄 Contingency — If You Miss a Target", "Backup players ranked by projected FV per role.") + + if proj is not None: + role_names = {"P": ("🧤 Goalkeepers", 3), "D": ("🛡 Defenders", 8), + "C": ("⚙ Midfielders", 8), "A": ("⚡ Forwards", 6)} + for role, (label, quota) in role_names.items(): + already = {s["player"] for s in squad if s["role"] == role} + backups = proj[(proj["role"] == role) & ~proj["player"].isin(already)].nlargest(quota * 2, "fv_proj") + if backups.empty: + continue + st.markdown(f"**{label}** — backup targets:", unsafe_allow_html=False) + cols = st.columns(min(4, len(backups))) + for j, (_, b) in enumerate(backups.head(12).iterrows()): + with cols[j % 4]: + price = b.get("price", b.get("qi", 10) * 3) if "price" in b.index else b.get("qi", 10) * 2 + st.markdown( + f'{role_chip(b["role"])} **{b["player"]}** ({b["team"]})
' + f'FV: {b["fv_proj"]:.2f} · ~{price:.0f} cr · ' + f'{int(b.get("games",0))}gms', + unsafe_allow_html=True, + ) + # ── Methodology ── st.divider() with st.expander("⚙️ Methodology — How this squad was computed"):