""" 실패 기록 표시 컴포넌트 시도 기록을 HTML로 렌더링 👨‍💻 담당: 개발자 B """ import random import gradio as gr from frontend.renderers.radar_chart import render_radar_chart class HistoryDisplayComponent: """실패 기록 표시 컴포넌트""" def __init__(self): self.history_html = None self.give_up_trigger_btn = None def render(self): """ 실패 기록 UI 렌더링 기록이 없으면 아무것도 표시하지 않음 Returns: gr.HTML: history_html 컴포넌트 """ self.history_html = gr.HTML(value="") # visible=False면 DOM에 생성되지 않아 JS로 클릭 불가할 수 있음 # visible=True로 하고 CSS로 숨김 self.give_up_trigger_btn = gr.Button( value="Give Up Trigger", visible=True, elem_id="hidden-give-up-btn", elem_classes=["hidden-trigger"] ) return self.history_html, self.give_up_trigger_btn @staticmethod def render_empty_history() -> str: """ 빈 기록 화면 렌더링 - 빈 상태 UI 표시 Returns: str: HTML 문자열 """ widget_id = f"hist{random.randint(1000, 9999)}" return f"""
History
0
No attempts yet. Record your voice to start!
""" @staticmethod def render_failure_history(history: list) -> str: """ 실패 기록 리스트 렌더링 - 좌우 분할 레이아웃 (좌: 기록 목록, 우: 오각 그래프) CSS 기반 토글 (radio button hidden) Args: history (list): 실패 기록 리스트 [{"timestamp": str, "text": str, "audio": str, "metrics": dict}, ...] Returns: str: HTML 문자열 """ if not history: return HistoryDisplayComponent.render_empty_history() # 고유 ID 생성 widget_id = f"hist{random.randint(1000, 9999)}" # 역순 (최신이 위로) reversed_history = list(reversed(history)) # CSS 스타일 html = f"""
History
{len(history)}
""" # 라디오 버튼 생성 (첫 번째가 기본 선택) for idx in range(len(reversed_history)): checked = "checked" if idx == 0 else "" html += f'' html += f"""
""" # 기록 리스트 for idx, entry in enumerate(reversed_history): # overall 점수 사용 metrics = entry.get('metrics', {}) overall_score = metrics.get('overall', 0) score = f"{overall_score:.1f}" if isinstance(overall_score, float) else str(overall_score) # user_text (STT 결과) 가져오기 user_text = entry.get('user_text', '') display_text = f'{user_text}' if user_text else '-' html += f""" """ html += f"""
""" # 점수 색상 결정 함수 def get_score_color(val): return "#e8a054" if val < 85 else "#4db8ff" # 각 기록에 대한 그래프 패널 생성 for idx, entry in enumerate(reversed_history): metrics = entry.get('metrics', {}) radar_svg = render_radar_chart(metrics, size=280) if metrics else "" html += f"""
{radar_svg}
Pronunciation
{metrics.get('pronunciation', '-')}
Pitch
{metrics.get('pitch', '-')}
Line Accuracy
{metrics.get('tone', '-')}
Rhythm
{metrics.get('rhythm', '-')}
Energy
{metrics.get('energy', '-')}
{entry.get('advice', '')}
""" html += """
""" return html