diff --git a/app.py b/app.py index b087dff..bd4a0c1 100644 --- a/app.py +++ b/app.py @@ -32,9 +32,9 @@ TEAMS = sorted(set(PARTICIPANTS.values())) if PARTICIPANTS else [ ] CATEGORIES = [ - ("fun_team", "πŸŽ‰ μž¬λ―Έμƒ"), - ("polish_team", "πŸ† 완성도상"), - ("utility_team", "πŸ›  μ‹€μš©μ„±μƒ"), + ("fun_team", "πŸŽ‰ μž¬λ―Έμƒ", "손선풍기 5개"), + ("polish_team", "πŸ† 완성도상", "팜레슀트 5개"), + ("utility_team", "πŸ›  μ‹€μš©μ„±μƒ", "μ–‘μš°μ‚° 5개"), ] @@ -117,7 +117,7 @@ def render_voter(): with st.form("vote", clear_on_submit=False): st.divider() picks = {} - for col, label in CATEGORIES: + for col, label, _ in CATEGORIES: picks[col] = st.radio( label, candidates, @@ -128,7 +128,7 @@ def render_voter(): submitted = st.form_submit_button("제좜") if submitted: - if any(picks.get(col) is None for col, _ in CATEGORIES): + if any(picks.get(col) is None for col, _, _ in CATEGORIES): st.error("3λΆ„μ•Ό λͺ¨λ‘ μ„ νƒν•˜μ„Έμš”.") return @@ -208,7 +208,7 @@ def render_admin(): public_lines = [] # μ‹œμƒμ‹ λ°œν‘œμš© (ν•˜μœ„ λΉ„κ³΅κ°œ) - for col, label in CATEGORIES: + for col, label, _ in CATEGORIES: rows = conn.execute( f"SELECT {col} AS team, COUNT(*) AS c FROM votes GROUP BY {col} ORDER BY c DESC, team ASC" ).fetchall() @@ -248,11 +248,111 @@ def render_admin(): conn.close() +def render_ceremony(): + """μ‹œμƒμ‹ reveal νŽ˜μ΄μ§€. μ§„ν–‰μžκ°€ 클릭으둜 단계별 곡개.""" + token = st.query_params.get("token", "") + if token != ADMIN_TOKEN: + st.error("κΆŒν•œ μ—†μŒ. ?mode=ceremony&token=... ν˜•μ‹ ν•„μš”.") + return + + titles = get_titles() + conn = get_conn() + + results = [] + for col, label, prize in CATEGORIES: + rows = conn.execute( + f"SELECT {col} AS team, COUNT(*) AS c FROM votes " + f"GROUP BY {col} ORDER BY c DESC, team ASC" + ).fetchall() + if rows: + winner, votes = rows[0] + runner = rows[1][1] if len(rows) > 1 else 0 + results.append((label, prize, winner, votes, votes - runner)) + conn.close() + + if "ceremony_step" not in st.session_state: + st.session_state.ceremony_step = 0 + if "ceremony_revealed" not in st.session_state: + st.session_state.ceremony_revealed = False + + st.markdown( + """ + + """, + unsafe_allow_html=True, + ) + + step = st.session_state.ceremony_step + + if step == 0: + st.markdown('
πŸŽ‰ 해컀톀 μ‹œμƒμ‹ πŸŽ‰
', unsafe_allow_html=True) + st.markdown('
μ€€λΉ„λμŠ΅λ‹ˆλ‹€
', unsafe_allow_html=True) + if st.button("μ‹œμž‘ β†’", use_container_width=True, type="primary"): + st.session_state.ceremony_step = 1 + st.session_state.ceremony_revealed = False + st.rerun() + + elif step > len(results): + st.markdown('
🎊 λͺ¨λ“  μ‹œμƒ μ™„λ£Œ 🎊
', unsafe_allow_html=True) + st.balloons() + st.snow() + if st.button("처음으둜", use_container_width=True): + st.session_state.ceremony_step = 0 + st.session_state.ceremony_revealed = False + st.rerun() + + else: + label, prize, winner, votes, diff = results[step - 1] + st.markdown(f'
{label}
', unsafe_allow_html=True) + st.markdown(f'
🎁 μƒν’ˆ: {prize}
', unsafe_allow_html=True) + + if not st.session_state.ceremony_revealed: + st.markdown('
πŸ₯πŸ₯πŸ₯
', unsafe_allow_html=True) + if st.button("μš°μŠΉνŒ€ 곡개 β†’", use_container_width=True, type="primary"): + st.session_state.ceremony_revealed = True + st.rerun() + else: + st.balloons() + winner_label = fmt_team(winner, titles) + st.markdown( + f'
πŸ†
{winner_label}
', + unsafe_allow_html=True, + ) + st.markdown( + f'
{votes}ν‘œ (2μœ„μ™€ {diff}ν‘œ 차이)
', + unsafe_allow_html=True, + ) + next_label = "λ‹€μŒ λΆ€λ¬Έ β†’" if step < len(results) else "마무리 β†’" + if st.button(next_label, use_container_width=True, type="primary"): + st.session_state.ceremony_step = step + 1 + st.session_state.ceremony_revealed = False + st.rerun() + + def main(): - st.set_page_config(page_title="해컀톀 νˆ¬ν‘œ", page_icon="πŸ—³") + st.set_page_config(page_title="해컀톀 νˆ¬ν‘œ", page_icon="πŸ—³", layout="wide") mode = st.query_params.get("mode", "vote") if mode == "admin": render_admin() + elif mode == "ceremony": + render_ceremony() else: render_voter()