// jev-affect-v2 trace(§8.1)의 코드값을 관리자 화면 한글 라벨로 옮긴다. // 모르는 코드는 원문 코드를 그대로 보여 주지 않고 "알 수 없는 값"으로 대체한다. const UNKNOWN_LABEL = "알 수 없는 값"; const APPRAISAL_ITEM_LABELS: Record = { a_understood: "이해받았다고 느낌", a_judged: "평가·비난받는 느낌", a_autonomy: "선택을 강요받는 느낌", a_coping: "제안의 감당 가능성", a_directionless: "방향을 잃은 느낌", a_sore_spot: "민감 지점 자극", a_fact_conflict: "고정 사실과의 충돌", a_move: "상담자 발화 유형", }; export function appraisalItemLabel(key: string): string { return APPRAISAL_ITEM_LABELS[key] ?? UNKNOWN_LABEL; } const A_COPING_LABELS: Record = { nothing_asked: "요구 없음", manageable: "감당 가능", stretch: "부담스러움", overwhelming: "벅참", }; const A_COPING_ORDER = ["nothing_asked", "manageable", "stretch", "overwhelming"]; const A_MOVE_LABELS: Record = { reflection: "반영", validation: "타당화", open_question: "열린 질문", closed_question: "닫힌 질문", clarification: "명료화", confrontation: "직면", interpretation: "해석", advice: "조언", information: "정보 제공", self_disclosure: "자기 개방", topic_shift: "화제 전환", other: "기타", }; const A_MOVE_ORDER = Object.keys(A_MOVE_LABELS); function soreSpotLabel(choice: string): string { if (choice === "none") return "해당 없음"; const match = /^spot_(\d+)$/.exec(choice); return match ? `민감 지점 ${match[1]}` : UNKNOWN_LABEL; } function soreSpotRank(choice: string): number { if (choice === "none") return -1; const match = /^spot_(\d+)$/.exec(choice); return match ? Number(match[1]) : Number.POSITIVE_INFINITY; } export function appraisalChoiceLabel(key: string, choice: string): string { if (key === "a_coping") return A_COPING_LABELS[choice] ?? UNKNOWN_LABEL; if (key === "a_move") return A_MOVE_LABELS[choice] ?? UNKNOWN_LABEL; if (key === "a_sore_spot") return soreSpotLabel(choice); return UNKNOWN_LABEL; } function sortByOrder(entries: Array<[string, number]>, order: string[]): Array<[string, number]> { return [...entries].sort((a, b) => { const rankA = order.indexOf(a[0]); const rankB = order.indexOf(b[0]); return (rankA === -1 ? order.length : rankA) - (rankB === -1 ? order.length : rankB); }); } export function orderedAppraisalChoiceEntries(key: string, probabilities: Record): Array<[string, number]> { const entries = Object.entries(probabilities); if (key === "a_coping") return sortByOrder(entries, A_COPING_ORDER); if (key === "a_move") return sortByOrder(entries, A_MOVE_ORDER); if (key === "a_sore_spot") return [...entries].sort((a, b) => soreSpotRank(a[0]) - soreSpotRank(b[0])); return entries; } function noulDecisionLabel(decision: string): string { if (decision === "true") return "예"; if (decision === "false") return "아니오"; if (decision === "uncertain") return "판단 보류"; return UNKNOWN_LABEL; } export function appraisalDecisionLabel(item: { key: string; kind: "noul" | "choice"; decision: string }): string { if (item.kind === "noul") return noulDecisionLabel(item.decision); if (item.decision === "uncertain") return "판단 보류"; return appraisalChoiceLabel(item.key, item.decision); } const C_BEHAVIOR_LABELS: Record = { disclose_more: "더 털어놓음", stay_with_feeling: "감정에 머묾", hold_core: "핵심은 보류", ask_back: "되물음", minimal_response: "최소 반응", shift_topic: "화제 전환", abstract_talk: "추상적으로 말함", appease: "달래며 동의", self_blame: "자기비난", complain: "불만 표현", argue_back: "반박", take_control: "주도권 요구", }; function behaviorLabel(choice: string): string { return C_BEHAVIOR_LABELS[choice] ?? UNKNOWN_LABEL; } export function behaviorOrUncertainLabel(value: string): string { return value === "uncertain" ? "판단 보류" : behaviorLabel(value); } const C_DISPLAY_LABELS: Record = { as_felt: "그대로", softened: "누그러뜨림", covered_by_agreement: "수긍으로 덮음", masked: "웃음·무덤덤함으로 가림", }; function displayLabel(choice: string): string { return C_DISPLAY_LABELS[choice] ?? UNKNOWN_LABEL; } export function expressionDecisionLabel(kind: "behavior" | "display", decision: string): string { if (decision === "uncertain") return "판단 보류"; return kind === "behavior" ? behaviorLabel(decision) : displayLabel(decision); } export function expressionNoulDecisionLabel(decision: string): string { return noulDecisionLabel(decision); } const GATE_REASON_LABELS: Record = { openness_closed: "매우 닫힘으로 조정", openness_guarded: "경계 상태로 조정", }; export function gateReasonLabel(reason: string | null | undefined): string { if (reason === null || reason === undefined) return "조정 없음"; return GATE_REASON_LABELS[reason] ?? UNKNOWN_LABEL; } const STANCE_LABELS: Record = { engage: "대화에 더 들어옴", cautious: "조심스러운 거리", pull_back: "한발 물러남", push_back: "맞섬·반박", }; export function stanceLabel(stance: string | null | undefined): string { if (stance === null || stance === undefined) return "판단 보류"; return STANCE_LABELS[stance] ?? UNKNOWN_LABEL; }