Claude commited on
Commit
05eaacf
·
unverified ·
1 Parent(s): 5aad439

fix: 공감 동점 시 같은 등수 뱃지 + 3초 쿨다운 추가

Browse files

- 같은 공감 수 = 같은 뱃지 (dense rank, 예: 동점 1위 둘 다 🥇)
- 공감 클릭 후 3초간 모든 공감 버튼 비활성화

https://claude.ai/code/session_016DE3uHLsVmA5Uv7gZGGaKT

Files changed (1) hide show
  1. components/chat_board.py +15 -4
components/chat_board.py CHANGED
@@ -1,3 +1,4 @@
 
1
  import streamlit as st
2
  import plotly.express as px
3
  from collections import Counter
@@ -9,6 +10,7 @@ from config import DASHBOARD_FETCH_LIMIT, LIVE_BOARD_FETCH_LIMIT, LIVE_REFRESH_I
9
 
10
 
11
  _RANK_BADGES = {1: "🥇", 2: "🥈", 3: "🥉"}
 
12
 
13
 
14
  def _anon_ip(raw_ip: str) -> str:
@@ -62,6 +64,7 @@ def _live_chat_board_core(supabase, room_name, user_role, teacher_auth, student_
62
  my_likes = set()
63
  badge_map = {}
64
  my_anon_ip = ""
 
65
  if use_likes:
66
  likes_data = fetch_room_likes(supabase, room_name)
67
  likes_count = Counter(item['opinion_id'] for item in likes_data)
@@ -69,9 +72,16 @@ def _live_chat_board_core(supabase, room_name, user_role, teacher_auth, student_
69
  raw_client_ip = get_client_ip()
70
  if raw_client_ip:
71
  my_anon_ip = _anon_ip(raw_client_ip)
72
- # 상위 3개 뱃지
73
- top3 = [oid for oid, _ in likes_count.most_common(3) if likes_count[oid] > 0]
74
- badge_map = {oid: _RANK_BADGES[rank] for rank, oid in enumerate(top3, 1)}
 
 
 
 
 
 
 
75
 
76
  def delete_chat_msg(msg_id):
77
  try:
@@ -86,6 +96,7 @@ def _live_chat_board_core(supabase, room_name, user_role, teacher_auth, student_
86
  def do_toggle_like(msg_id):
87
  toggle_like(supabase, msg_id, room_name, student_name)
88
  fetch_room_likes.clear()
 
89
 
90
  def render_msg(row):
91
  formatted_timestamp = format_kst_datetime(row.get("timestamp", ""))
@@ -97,7 +108,7 @@ def _live_chat_board_core(supabase, room_name, user_role, teacher_auth, student_
97
  # 셀프 공감 차단: 의견 작성자 IP와 현재 사용자 IP 비교
98
  row_ip = str(row.get("ip_address", "")).strip() if hasattr(row, "get") else ""
99
  is_self = bool(my_anon_ip and row_ip and my_anon_ip == row_ip)
100
- like_disabled = is_self or not use_likes
101
  like_label = f"👍 {count}" if count > 0 else "👍"
102
  like_type = "primary" if is_liked else "secondary"
103
 
 
1
+ import time
2
  import streamlit as st
3
  import plotly.express as px
4
  from collections import Counter
 
10
 
11
 
12
  _RANK_BADGES = {1: "🥇", 2: "🥈", 3: "🥉"}
13
+ _LIKE_COOLDOWN = 3
14
 
15
 
16
  def _anon_ip(raw_ip: str) -> str:
 
64
  my_likes = set()
65
  badge_map = {}
66
  my_anon_ip = ""
67
+ on_like_cooldown = False
68
  if use_likes:
69
  likes_data = fetch_room_likes(supabase, room_name)
70
  likes_count = Counter(item['opinion_id'] for item in likes_data)
 
72
  raw_client_ip = get_client_ip()
73
  if raw_client_ip:
74
  my_anon_ip = _anon_ip(raw_client_ip)
75
+ # 동점 처리: 같은 공감 수 = 같은 등수 (dense rank)
76
+ distinct_counts = sorted({c for c in likes_count.values() if c > 0}, reverse=True)[:3]
77
+ count_to_rank = {c: rank for rank, c in enumerate(distinct_counts, 1)}
78
+ badge_map = {
79
+ oid: _RANK_BADGES[count_to_rank[cnt]]
80
+ for oid, cnt in likes_count.items()
81
+ if cnt > 0 and cnt in count_to_rank
82
+ }
83
+ # 쿨다운 확인
84
+ on_like_cooldown = (time.time() - st.session_state.get('_last_like_ts', 0)) < _LIKE_COOLDOWN
85
 
86
  def delete_chat_msg(msg_id):
87
  try:
 
96
  def do_toggle_like(msg_id):
97
  toggle_like(supabase, msg_id, room_name, student_name)
98
  fetch_room_likes.clear()
99
+ st.session_state['_last_like_ts'] = time.time()
100
 
101
  def render_msg(row):
102
  formatted_timestamp = format_kst_datetime(row.get("timestamp", ""))
 
108
  # 셀프 공감 차단: 의견 작성자 IP와 현재 사용자 IP 비교
109
  row_ip = str(row.get("ip_address", "")).strip() if hasattr(row, "get") else ""
110
  is_self = bool(my_anon_ip and row_ip and my_anon_ip == row_ip)
111
+ like_disabled = is_self or not use_likes or on_like_cooldown
112
  like_label = f"👍 {count}" if count > 0 else "👍"
113
  like_type = "primary" if is_liked else "secondary"
114