Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| def _init_state(): | |
| if "sk_players" not in st.session_state: | |
| st.session_state.sk_players = [] | |
| if "sk_game_started" not in st.session_state: | |
| st.session_state.sk_game_started = False | |
| if "sk_scores" not in st.session_state: | |
| st.session_state.sk_scores = {} | |
| def _setup_phase(): | |
| st.subheader("Player Setup") | |
| def _sk_add_player(): | |
| name = st.session_state.sk_new_player.strip() | |
| if name and name not in st.session_state.sk_players: | |
| st.session_state.sk_players.append(name) | |
| st.session_state.sk_new_player = "" | |
| col1, col2 = st.columns([3, 1]) | |
| with col1: | |
| st.text_input("Player name", key="sk_new_player") | |
| with col2: | |
| st.write("") | |
| st.write("") | |
| st.button("Add Player", key="sk_add_btn", on_click=_sk_add_player) | |
| if st.session_state.sk_players: | |
| st.markdown("**Players:**") | |
| for i, p in enumerate(st.session_state.sk_players): | |
| col_name, col_del = st.columns([4, 1]) | |
| col_name.write(f"{i + 1}. {p}") | |
| if col_del.button("Remove", key=f"sk_rm_{i}"): | |
| st.session_state.sk_players.pop(i) | |
| st.rerun() | |
| if len(st.session_state.sk_players) >= 2: | |
| if st.button("Start Game", type="primary"): | |
| st.session_state.sk_game_started = True | |
| st.session_state.sk_scores = {} | |
| st.rerun() | |
| else: | |
| st.info("Add at least 2 players to start.") | |
| def _game_phase(): | |
| players = st.session_state.sk_players | |
| scores = st.session_state.sk_scores | |
| completed_rounds = sorted(scores.keys()) | |
| next_round = (completed_rounds[-1] + 1) if completed_rounds else 1 | |
| if st.button("Reset Game"): | |
| st.session_state.sk_game_started = False | |
| st.session_state.sk_players = [] | |
| st.session_state.sk_scores = {} | |
| st.rerun() | |
| if completed_rounds: | |
| st.subheader("Scoreboard") | |
| _render_scoreboard(players, scores, completed_rounds) | |
| if next_round <= 10: | |
| st.subheader(f"Round {next_round}") | |
| st.caption(f"Each player is dealt {next_round} card{'s' if next_round > 1 else ''}.") | |
| round_scores = {} | |
| cols = st.columns(len(players)) | |
| for i, player in enumerate(players): | |
| with cols[i]: | |
| round_scores[player] = st.number_input( | |
| player, | |
| value=0, | |
| step=10, | |
| key=f"sk_input_r{next_round}_{player}", | |
| ) | |
| if st.button("Save Round", type="primary", key=f"sk_save_r{next_round}"): | |
| st.session_state.sk_scores[next_round] = round_scores | |
| st.rerun() | |
| else: | |
| st.success("Game complete! All 10 rounds played.") | |
| _render_final_standings(players, scores, completed_rounds) | |
| def _render_scoreboard(players, scores, completed_rounds): | |
| header_cols = ["Round"] + players | |
| rows_html = [] | |
| cumsum = {p: 0 for p in players} | |
| prev_cumsum = {p: 0 for p in players} | |
| for r in completed_rounds: | |
| row = [f"**{r}**"] | |
| for p in players: | |
| pts = scores[r].get(p, 0) | |
| prev_cumsum[p] = cumsum[p] | |
| cumsum[p] += pts | |
| change = cumsum[p] - prev_cumsum[p] | |
| if change > 0: | |
| indicator = f' <span style="color:green">▲ +{change}</span>' | |
| elif change < 0: | |
| indicator = f' <span style="color:red">▼ {change}</span>' | |
| else: | |
| indicator = "" | |
| row.append(f"**{cumsum[p]}**{indicator}") | |
| rows_html.append(row) | |
| md = "| " + " | ".join(header_cols) + " |\n" | |
| md += "| " + " | ".join(["---"] * len(header_cols)) + " |\n" | |
| for row in rows_html: | |
| md += "| " + " | ".join(str(c) for c in row) + " |\n" | |
| st.markdown(md, unsafe_allow_html=True) | |
| def _render_final_standings(players, scores, completed_rounds): | |
| st.subheader("Final Standings") | |
| totals = {p: sum(scores[r].get(p, 0) for r in completed_rounds) for p in players} | |
| ranked = sorted(totals.items(), key=lambda x: x[1], reverse=True) | |
| for i, (player, total) in enumerate(ranked): | |
| medal = ["1st", "2nd", "3rd"][i] if i < 3 else f"{i+1}th" | |
| st.write(f"**{medal}** - {player}: **{total}** points") | |
| # Page entry point | |
| st.title("Skull King") | |
| _init_state() | |
| if not st.session_state.sk_game_started: | |
| _setup_phase() | |
| else: | |
| _game_phase() | |