diff --git a/app.py b/app.py index f284aed..458a8e4 100644 --- a/app.py +++ b/app.py @@ -37,6 +37,10 @@ CATEGORIES = [ ("utility_team", "πŸ›  μ‹€μš©μ„±μƒ", "팜레슀트 5개"), ] +# μˆ˜μƒ κ²°μ • μš°μ„ μˆœμœ„ (λ†’μ„μˆ˜λ‘ λ¨Όμ € κ²°μ •, ν›„μˆœμœ„ μƒμ—μ„œ κ·Έ νŒ€ μ œμ™Έ) +# 팜레슀트(μ‹€μš©μ„±) > μ–‘μš°μ‚°(완성도) > 손선풍기(재미) +PRIZE_PRIORITY = ["utility_team", "polish_team", "fun_team"] + def get_conn(): conn = sqlite3.connect(DB_PATH) @@ -90,6 +94,36 @@ def fmt_team(team, titles): return f"{team} β€” {t}" if t else team +def compute_winners(): + """ + μš°μ„ μˆœμœ„ 기반 1νŒ€ 1상 보μž₯. + PRIZE_PRIORITY 순으둜 κ²°μ •, 이미 μˆ˜μƒν•œ νŒ€μ€ ν›„μˆœμœ„ μƒμ—μ„œ μ œμ™Έ. + return: dict[col] = (winner_team, winner_votes, diff_with_2nd, all_rows_excluded) + """ + conn = get_conn() + rankings = {} + for col, _, _ in CATEGORIES: + rankings[col] = conn.execute( + f"SELECT {col} AS team, COUNT(*) AS c FROM votes " + f"GROUP BY {col} ORDER BY c DESC, team ASC" + ).fetchall() + conn.close() + + winners = {} + excluded = set() + for col in PRIZE_PRIORITY: + rows = rankings[col] + filtered = [(t, c) for t, c in rows if t not in excluded] + if not filtered: + winners[col] = None + continue + winner, votes = filtered[0] + runner = filtered[1][1] if len(filtered) > 1 else 0 + winners[col] = (winner, votes, votes - runner, filtered) + excluded.add(winner) + return winners, rankings + + def render_voter(): st.title("πŸ—³ 해컀톀 νˆ¬ν‘œ") st.caption("이름 선택 β†’ 본인 νŒ€ μžλ™ λ§€ν•‘ β†’ 본인 νŒ€ μ œμ™Έ 3λΆ„μ•Ό νˆ¬ν‘œ. ν•œ 번만 제좜 κ°€λŠ₯.") @@ -204,24 +238,29 @@ def render_admin(): st.rerun() st.divider() - st.subheader("πŸ“Š 뢄야별 집계") + st.subheader("πŸ“Š 뢄야별 집계 (μš°μ„ μˆœμœ„ 적용 β€” 1νŒ€ 1상)") + st.caption( + "μˆ˜μƒ κ²°μ • μˆœμ„œ: 팜레슀트(μ‹€μš©μ„±) β†’ μ–‘μš°μ‚°(완성도) β†’ 손선풍기(재미). " + "이미 받은 νŒ€μ€ ν›„μˆœμœ„ μƒμ—μ„œ μ œμ™Έ." + ) - public_lines = [] # μ‹œμƒμ‹ λ°œν‘œμš© (ν•˜μœ„ λΉ„κ³΅κ°œ) + winners, rankings = compute_winners() + awarded_teams = {w[0] for w in winners.values() if w} + public_lines = [] - 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() - - st.markdown(f"### {label}") + for col, label, prize in CATEGORIES: + rows = rankings[col] + st.markdown(f"### {label} ({prize})") if not rows: st.caption("ν‘œ μ—†μŒ") continue - winner_team, winner_votes = rows[0] - runner_votes = rows[1][1] if len(rows) > 1 else 0 - diff = winner_votes - runner_votes + result = winners.get(col) + if not result: + st.warning("후보 μ—†μŒ (λͺ¨λ‘ μš°μ„ μˆœμœ„ 상 μˆ˜μƒ)") + continue + winner_team, winner_votes, diff, _ = result winner_label = fmt_team(winner_team, titles) st.success( f"**우승: {winner_label}** β€” {winner_votes}ν‘œ (2μœ„μ™€ {diff}ν‘œ 차이)" @@ -230,9 +269,12 @@ def render_admin(): f"- {label} 우승: **{winner_label}** ({winner_votes}ν‘œ, 2μœ„μ™€ {diff}ν‘œ 차이)" ) - with st.expander("전체 뢄포 (μ§„ν–‰μžλ§Œ)"): + with st.expander("전체 뢄포 β€” raw (μ œμ™Έ 적용 μ „)"): for team, c in rows: - st.write(f"- {fmt_team(team, titles)}: {c}ν‘œ") + marker = "" + if team in awarded_teams and team != winner_team: + marker = " πŸš«μƒμœ„μƒμˆ˜μƒμœΌλ‘œ μ œμ™Έ" + st.write(f"- {fmt_team(team, titles)}: {c}ν‘œ{marker}") st.divider() st.subheader("🎀 μ‹œμƒμ‹ λ°œν‘œμš© (λ³΅μ‚¬ν•΄μ„œ ν™”λ©΄ 곡유)") @@ -256,19 +298,15 @@ def render_ceremony(): return titles = get_titles() - conn = get_conn() + winners, _ = compute_winners() + # CATEGORIES μˆœμ„œλ‘œ reveal (손선풍기 β†’ μ–‘μš°μ‚° β†’ 팜레슀트) 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() + result = winners.get(col) + if result: + winner, votes, diff, _ = result + results.append((label, prize, winner, votes, diff)) if "ceremony_step" not in st.session_state: st.session_state.ceremony_step = 0