v4.1.1: weather_map_screenshot 연결 + 언어앱 카드생성 버그 수정 + 상담앱 심리검사 5종 추가

- weather_map_screenshot 툴이 코드(weather.ts)·레지스트리엔 있었지만 buildTools()
  스키마가 없어 모델이 호출 자체를 못 하던 걸 연결. 날씨앱(wt_ 세션) 전용으로 게이팅
- 언어앱 "AI 카드 생성"이 실제로는 0장을 반환하던 버그 수정 — config.json 모델이
  kimi-k2.6:cloud(추론모델)로 바뀌면서 num_predict가 너무 작아 생각(thinking)만 하다
  토큰을 다 쓰고 실제 답변을 못 내놓고 있었음. think:false + num_predict 상향으로 해결
  (generate-flashcards/generate-lesson/check-answer 3개 API 모두 동일 수정)
- 언어앱 플래시카드에 타일 그리드 뷰 추가 — 카테고리 카드 전체를 한번에 펼쳐보고
  개별 탭으로 뒤집어볼 수 있음
- 상담앱 심리검사를 7종 → 12종으로 확장: PCL-5(PTSD), MDQ(양극성), OCI-R(강박),
  ASRS-6(성인ADHD), SPIN(사회불안) 추가. PHQ-9 9번 문항(자살/자해 생각) 안전장치를
  안내문 한 줄에서 결과화면 상단 위기상담 배너로 강화

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
kim
2026-07-13 21:46:18 +09:00
co-authored by Claude Sonnet 5
parent b969c672b0
commit c1d72a2a2d
5 changed files with 275 additions and 9 deletions
+195 -1
View File
@@ -106,6 +106,10 @@ body{background:var(--bg);color:var(--text);font-family:system-ui,sans-serif;dis
.q-disclaimer{font-size:10px;color:var(--muted);line-height:1.6;margin-top:12px;padding:10px 12px;border:1px dashed var(--line);border-radius:7px;}
.q-disclaimer strong{display:block;color:var(--text);margin-bottom:3px;font-size:10px;}
.q-refs{font-size:10px;color:var(--muted);margin-top:6px;font-style:italic;opacity:.85;}
.crisis-banner{background:rgba(239,68,68,.1);border:2px solid rgba(239,68,68,.5);border-radius:12px;padding:16px;margin-bottom:16px;}
.crisis-banner strong{display:block;color:#f87171;font-size:14px;margin-bottom:8px;}
.crisis-banner p{font-size:12px;color:var(--text);line-height:1.6;margin-bottom:8px;}
.crisis-banner .crisis-lines{display:flex;flex-direction:column;gap:4px;font-size:13px;font-weight:700;color:var(--text);}
/* ── Breathing widget ── */
.breath-container{display:flex;flex-direction:column;align-items:center;gap:24px;padding:20px 0;}
@@ -314,6 +318,26 @@ body{background:var(--bg);color:var(--text);font-family:system-ui,sans-serif;dis
<span>📋</span>
<span class="t-lbl">AUDIT<span class="t-sub">알코올 선별</span></span>
</button>
<button class="mn-tool" id="tool-pcl5" onclick="showTool('pcl5')">
<span>📋</span>
<span class="t-lbl">PCL-5<span class="t-sub">PTSD(외상후스트레스) 선별</span></span>
</button>
<button class="mn-tool" id="tool-mdq" onclick="showTool('mdq')">
<span>📋</span>
<span class="t-lbl">MDQ<span class="t-sub">양극성장애 선별</span></span>
</button>
<button class="mn-tool" id="tool-ocir" onclick="showTool('ocir')">
<span>📋</span>
<span class="t-lbl">OCI-R<span class="t-sub">강박장애 선별</span></span>
</button>
<button class="mn-tool" id="tool-asrs" onclick="showTool('asrs')">
<span>📋</span>
<span class="t-lbl">ASRS-6<span class="t-sub">성인 ADHD 선별</span></span>
</button>
<button class="mn-tool" id="tool-spin" onclick="showTool('spin')">
<span>📋</span>
<span class="t-lbl">SPIN<span class="t-sub">사회불안 척도</span></span>
</button>
<button class="mn-tool" id="tool-cbt" onclick="showTool('cbt')">
<span>✍️</span>
<span class="t-lbl">생각 기록지<span class="t-sub">CBT 인지 재구성</span></span>
@@ -519,6 +543,11 @@ const toolTitles={
who5:'📋 WHO-5 웰빙 지수',
rosenberg:'📋 Rosenberg 자존감 척도',
audit:'📋 AUDIT 알코올 사용장애 선별검사',
pcl5:'📋 PCL-5 PTSD(외상후스트레스장애) 선별 검사',
mdq:'📋 MDQ 기분장애 선별 질문지',
ocir:'📋 OCI-R 강박장애 선별 검사',
asrs:'📋 ASRS-6 성인 ADHD 자가보고 척도',
spin:'📋 SPIN 사회공포증 척도',
cbt:'✍️ 생각 기록지 (CBT)',
breath:'🌬️ 호흡 명상',
};
@@ -539,7 +568,7 @@ function showTool(name){
const widget=document.getElementById('center-widget');
widget.style.display='';
// render
const renders={emotion:renderEmotion,phq9:()=>renderQuestionnaire('phq9'),gad7:()=>renderQuestionnaire('gad7'),pss10:()=>renderQuestionnaire('pss10'),isi:()=>renderQuestionnaire('isi'),who5:()=>renderQuestionnaire('who5'),rosenberg:()=>renderQuestionnaire('rosenberg'),audit:()=>renderQuestionnaire('audit'),cbt:renderCBT,breath:renderBreath};
const renders={emotion:renderEmotion,phq9:()=>renderQuestionnaire('phq9'),gad7:()=>renderQuestionnaire('gad7'),pss10:()=>renderQuestionnaire('pss10'),isi:()=>renderQuestionnaire('isi'),who5:()=>renderQuestionnaire('who5'),rosenberg:()=>renderQuestionnaire('rosenberg'),audit:()=>renderQuestionnaire('audit'),pcl5:()=>renderQuestionnaire('pcl5'),mdq:()=>renderQuestionnaire('mdq'),ocir:()=>renderQuestionnaire('ocir'),asrs:()=>renderQuestionnaire('asrs'),spin:()=>renderQuestionnaire('spin'),cbt:renderCBT,breath:renderBreath};
(renders[name]||function(){widget.innerHTML='<div class="widget"><p>준비 중입니다.</p></div>';})();
}
@@ -602,6 +631,7 @@ const TESTS={
'남들이 눈치 챌 정도로 너무 느리게 움직이거나 말을 함, 또는 반대로 너무 안절부절 못하거나 들떠 있음',
'스스로를 해치거나 자살하는 것이 낫겠다는 생각',
],
crisisItem:8,
levels:[
{max:4,cls:'minimal',label:'정상 범위',desc:'우울 증상이 거의 없습니다.'},
{max:9,cls:'mild',label:'경미한 우울',desc:'가벼운 우울 증상이 있습니다. 생활 습관 개선이 도움될 수 있습니다.'},
@@ -762,6 +792,156 @@ const TESTS={
],
refs:'Saunders et al.(1993); 한국어판 Lee et al.(2000). AUDIT-C 절단점 ≥4(남)/≥3(여).',
},
pcl5:{
title:'PCL-5 외상후스트레스장애(PTSD) 선별 검사',
intro:'지난 한 달 동안, 스트레스가 매우 심했던 사건 경험 때문에 다음 문제들로 얼마나 자주 힘들었습니까? 특정 사건을 구체적으로 지목하지 않아도 괜찮습니다.',
scale:['전혀 아님(0)','조금(1)','보통(2)','많이(3)','매우 많이(4)'],
questions:[
'그 사건에 대한 반복적이고 원치 않는 괴로운 기억',
'그 사건에 대한 반복적이고 괴로운 꿈',
'갑자기 그 사건이 다시 일어나고 있는 것처럼 느끼거나 행동함 (플래시백)',
'그 사건을 떠올리게 하는 것에 노출됐을 때 강한 심리적 고통을 느낌',
'그 사건을 떠올리게 하는 것에 노출됐을 때 강한 신체 반응(심장 두근거림, 호흡곤란, 식은땀 등)이 나타남',
'그 사건에 대한 기억·생각·감정을 애써 피하려 함',
'그 사건을 떠올리게 하는 사람·장소·대화·활동·사물·상황을 피하려 함',
'그 사건의 중요한 부분을 기억하기 어려움',
'자신·타인·세상에 대한 강한 부정적 신념 (예: "나는 나쁘다", "아무도 믿을 수 없다", "세상은 완전히 위험하다")',
'그 사건이나 그로 인해 벌어진 일에 대해 자신 또는 타인을 탓함',
'두려움·공포·분노·죄책감·수치심 같은 강한 부정적 감정',
'예전에 즐기던 활동에 대한 흥미 상실',
'다른 사람들로부터 거리감이나 단절감을 느낌',
'긍정적인 감정(행복, 사랑 등)을 경험하기 어려움',
'과민한 행동, 분노 폭발, 공격적인 행동',
'지나치게 위험하거나 스스로를 해칠 수 있는 행동을 함',
'지나치게 경계하거나 주위를 살핌',
'쉽게 놀라거나 소스라침',
'집중하는 데 어려움을 겪음',
'잠들기 어렵거나 잠을 유지하기 어려움',
],
levels:[
{max:9,cls:'minimal',label:'정상 범위',desc:'외상 관련 증상이 거의 없습니다.'},
{max:32,cls:'mild',label:'경미~중등도 증상',desc:'일부 외상 관련 증상이 있습니다. 경과를 지켜보며 필요시 상담을 고려하세요.'},
{max:80,cls:'severe',label:'PTSD 가능성 높음',desc:'외상후스트레스장애(PTSD) 가능성을 시사하는 점수입니다. 전문가 평가를 권장합니다.'},
],
refs:'Weathers et al.(2013), National Center for PTSD 개발. 절단점 ≥31~33 (연구별로 상이).',
note:'특정 외상 사건을 염두에 두고 응답하는 검사입니다. 사건 자체를 이야기하고 싶지 않다면 하지 않아도 괜찮습니다.',
},
mdq:{
title:'MDQ 기분장애 선별 질문지 (양극성 스펙트럼)',
intro:'지금까지 살아오면서, 평소의 나와는 다르게 아래와 같았던 시기가 있었는지 "예/아니오"로 답해주세요.',
scale:['아니오(0)','예(1)'],
questions:[
'평소와 달리 기분이 너무 좋거나 들떠서, 남들이 평소의 당신 같지 않다고 하거나 그것 때문에 문제가 생긴 적이 있나요?',
'너무 짜증이 나서 사람들에게 소리치거나 싸움·논쟁을 시작한 적이 있나요?',
'평소보다 훨씬 자신감이 넘쳤던 적이 있나요?',
'평소보다 잠을 훨씬 적게 잤는데도 피곤하지 않았던 적이 있나요?',
'평소보다 말이 훨씬 많아지거나 말이 빨라진 적이 있나요?',
'생각이 머릿속에서 너무 빠르게 흘러가서 멈출 수 없었던 적이 있나요?',
'주변 것들에 너무 쉽게 정신이 팔려서 집중하기 어려웠던 적이 있나요?',
'평소보다 훨씬 에너지가 넘쳤던 적이 있나요?',
'평소보다 훨씬 활동적이거나 많은 일을 벌였던 적이 있나요?',
'평소보다 훨씬 사교적이거나 외향적이 되었던 적이 있나요? (예: 한밤중에 친구에게 전화)',
'평소보다 성(性)에 대한 관심이 훨씬 커진 적이 있나요?',
'평소와 다르게 무리하거나 위험할 수 있는 행동(과소비, 난폭 운전 등)을 한 적이 있나요?',
'돈을 너무 많이 써서 본인이나 가족이 곤란해진 적이 있나요?',
],
levels:[
{max:6,cls:'minimal',label:'낮음',desc:'조증·경조증 관련 증상이 뚜렷하지 않습니다.'},
{max:13,cls:'moderate',label:'양극성 스펙트럼 증상 가능성',desc:'조증·경조증과 관련된 증상이 여러 개 확인됩니다. 전문가 평가를 통해 정확히 확인해보는 것이 좋습니다.'},
],
refs:'Hirschfeld et al.(2000) 개발. 원본 절단점은 "예" 7개 이상.',
note:'원본 MDQ는 "예" 개수 외에도 "여러 증상이 같은 시기에 함께 나타났는지"와 "일상에 얼마나 지장을 주었는지"를 함께 확인해야 양성으로 판정합니다. 이 검사는 문항 수를 단순화한 선별용이며, 이 결과만으로 양극성장애 여부를 판단할 수 없습니다.',
},
ocir:{
title:'OCI-R 강박장애 선별 검사',
intro:'지난 한 달 동안, 다음 경험들이 얼마나 괴로움이나 불편함을 주었습니까?',
scale:['전혀 아님(0)','약간(1)','보통(2)','많이(3)','매우 많이(4)'],
questions:[
'물건을 너무 많이 모아둬서 방해가 될 정도이다 (저장)',
'필요 이상으로 자주 물건을 확인한다 (확인)',
'물건이 제대로 정리되어 있지 않으면 속상하다 (정리정돈)',
'어떤 일을 할 때 숫자를 세야만 할 것 같은 충동을 느낀다 (중화행동)',
'낯선 사람이나 특정 사람이 만진 물건을 만지기가 꺼려진다 (씻기)',
'내 생각을 스스로 통제하기 어렵다고 느낀다 (침투사고)',
'필요 없는 물건들을 모은다 (저장)',
'문·창문·서랍 등을 반복해서 확인한다 (확인)',
'누군가 내가 정리해 둔 것을 바꿔놓으면 속상하다 (정리정돈)',
'특정 숫자를 반복해야 할 것 같은 느낌이 든다 (중화행동)',
'오염된 느낌 때문에 씻거나 청소를 해야 할 때가 있다 (씻기)',
'원치 않는 불쾌한 생각이 떠올라 괴롭다 (침투사고)',
'나중에 필요할까봐 물건을 버리지 못한다 (저장)',
'가스·수도꼭지·전등 스위치를 끈 후에도 반복해서 확인한다 (확인)',
'물건이 특정한 순서로 정리되어 있어야 한다 (정리정돈)',
'좋은 숫자와 나쁜 숫자가 있다고 느낀다 (중화행동)',
'필요 이상으로 손을 자주, 오래 씻는다 (씻기)',
'불쾌한 생각이 자꾸 떠올라 떨쳐내기 어렵다 (침투사고)',
],
levels:[
{max:13,cls:'minimal',label:'정상 범위',desc:'강박 관련 증상이 거의 없습니다.'},
{max:20,cls:'mild',label:'경미한 증상',desc:'가벼운 강박 관련 증상이 있습니다.'},
{max:72,cls:'moderate',label:'강박장애 가능성',desc:'강박장애(OCD) 가능성을 시사하는 점수입니다. 전문가 평가를 권장합니다.'},
],
subscores:[
{name:'저장(Hoarding)',items:[0,6,12]},
{name:'확인(Checking)',items:[1,7,13]},
{name:'정리정돈(Ordering)',items:[2,8,14]},
{name:'중화행동(Neutralizing)',items:[3,9,15]},
{name:'씻기(Washing)',items:[4,10,16]},
{name:'침투사고(Obsessing)',items:[5,11,17]},
],
refs:'Foa et al.(2002) 개발. 절단점 ≥21 (연구별로 18~21 범위).',
note:'각 문항 뒤 괄호는 이해를 돕기 위한 하위척도 표시로, 실제 검사에는 표시되지 않습니다.',
},
asrs:{
title:'ASRS-6 성인 ADHD 자가보고 척도',
intro:'지난 6개월 동안 다음 문제들이 얼마나 자주 있었습니까? (세계보건기구 WHO 개발 성인 ADHD 선별 도구)',
scale:['전혀 없음(0)','드물게(1)','가끔(2)','자주(3)','매우 자주(4)'],
questions:[
'어려운 부분을 끝낸 후, 프로젝트의 마무리 세부 작업을 처리하는 데 어려움을 겪은 적이 얼마나 자주 있었나요?',
'체계적으로 처리해야 하는 일을 할 때, 순서를 정리하는 데 어려움을 겪은 적이 얼마나 자주 있었나요?',
'약속이나 해야 할 일을 잊어버린 적이 얼마나 자주 있었나요?',
'많은 생각이 필요한 일을 시작하는 것을 미루거나 피한 적이 얼마나 자주 있었나요?',
'오래 앉아 있어야 할 때 손이나 발을 꼼지락거리거나 몸을 움직인 적이 얼마나 자주 있었나요?',
'마치 모터가 달린 것처럼 지나치게 활동적이거나 무언가를 해야만 할 것 같은 느낌이 든 적이 얼마나 자주 있었나요?',
],
levels:[
{max:13,cls:'minimal',label:'낮음',desc:'ADHD 관련 증상이 뚜렷하지 않습니다.'},
{max:24,cls:'moderate',label:'성인 ADHD 증상과 일치',desc:'성인 ADHD와 관련된 증상 패턴이 확인됩니다. 전문가 평가를 권장합니다.'},
],
refs:'Kessler et al.(2005), WHO/Harvard 개발 ASRS v1.1 Part A(6문항 스크리너).',
note:'원본 ASRS-6는 문항별로 다른 절단 기준(문항에 따라 "가끔" 이상 또는 "자주" 이상)을 적용해 4개 이상 해당되면 양성으로 판정하는 방식입니다. 이 검사는 단순 합산 점수로 근사한 것이며, 정확한 채점은 원본 방식과 다를 수 있습니다.',
},
spin:{
title:'SPIN 사회공포증 척도',
intro:'지난 한 주 동안, 다음 상황들이 얼마나 불편하거나 두려웠습니까?',
scale:['전혀 아님(0)','약간(1)','보통(2)','많이(3)','매우 많이(4)'],
questions:[
'권위 있는 사람들이 두렵다',
'사람들 앞에서 얼굴이 빨개지는 것이 신경 쓰인다',
'파티나 사교 모임이 두렵다',
'모르는 사람과 대화하는 것을 피한다',
'비판받는 것이 매우 두렵다',
'창피할까봐 어떤 일을 하거나 사람들에게 말하는 것을 피한다',
'사람들 앞에서 땀을 흘리는 것이 괴롭다',
'파티에 가는 것을 피한다',
'내가 주목받는 활동을 피한다',
'낯선 사람에게 말을 거는 것이 두렵다',
'연설이나 발표를 해야 하는 상황을 피한다',
'비판받지 않기 위해서라면 무엇이든 하겠다',
'사람들 곁에 있을 때 심장이 두근거려 괴롭다',
'사람들이 지켜볼 수도 있는 상황에서 무언가를 하는 것이 두렵다',
'창피당하거나 바보처럼 보이는 것이 가장 두려운 일 중 하나이다',
'권위 있는 사람에게 말을 거는 것을 피한다',
'사람들 앞에서 떨리거나 흔들리는 것이 괴롭다',
],
levels:[
{max:20,cls:'minimal',label:'정상 범위',desc:'사회불안 관련 증상이 거의 없습니다.'},
{max:30,cls:'mild',label:'경미한 사회불안',desc:'가벼운 사회불안 증상이 있습니다.'},
{max:40,cls:'moderate',label:'중등도 사회불안',desc:'중간 정도의 사회불안 증상입니다. 전문가 상담을 고려해보세요.'},
{max:68,cls:'severe',label:'심각한 사회불안',desc:'심각한 사회불안 증상입니다. 전문가 상담을 권장합니다.'},
],
refs:'Connor et al.(2000) 개발. 절단점 ≥19(경도 이상 시사).',
},
};
let testAnswers={};
@@ -858,6 +1038,19 @@ function submitQuestionnaire(testId){
</div>`).join('')}</div>`:'';
const itemTable=`<div class="q-result-detail"><table><thead><tr><th>#</th><th>문항</th><th>응답</th><th>점수</th></tr></thead><tbody>${items.map(it=>`<tr><td class="q-num">${it.n}</td><td>${escHtml(it.q)}</td><td>${escHtml(it.label)}</td><td class="q-sc">${it.score}</td></tr>`).join('')}</tbody></table></div>`;
const disclaimer=`<div class="q-disclaimer"><strong>안내</strong>본 검사는 자기보고식 선별도구로 임상 진단을 대체하지 않습니다. 결과는 참고용이며, 정확한 평가는 임상심리사 또는 정신건강의학과 전문의를 통해 받으세요.${test.note?'<br>'+escHtml(test.note):''}${test.refs?`<div class="q-refs">참고: ${escHtml(test.refs)}</div>`:''}</div>`;
// Standard clinical practice for PHQ-9: item 9 (suicidal/self-harm ideation) warrants
// a direct safety check regardless of total score — previously buried as one line in
// the disclaimer, now a prominent banner if the respondent scored above 0 on it.
const crisisBanner=(test.crisisItem!==undefined&&items[test.crisisItem].score>0)?`<div class="crisis-banner">
<strong>⚠️ 확인이 필요합니다</strong>
<p>"${escHtml(test.questions[test.crisisItem])}" 문항에 응답하신 내용이 있습니다. 지금 힘든 마음이시라면 아래 연락처로 바로 도움을 받으실 수 있습니다.</p>
<div class="crisis-lines">
<span>☎ 자살예방상담전화 1393 (24시간, 무료)</span>
<span>☎ 정신건강위기상담전화 1577-0199 (24시간)</span>
<span>☎ 생명의전화 1588-9191</span>
<span>☎ 청소년전화 1388</span>
</div>
</div>`:'';
lastResult={title:test.title,score,level,subscores,items,refs:test.refs,minScore:range.min,maxScore:range.max};
@@ -865,6 +1058,7 @@ function submitQuestionnaire(testId){
w.innerHTML=`
<div class="widget">
<h2>${test.title} 결과</h2>
${crisisBanner}
<div class="result-card ${level.cls}">
<div class="r-score">${scoreDisplay}</div>
<div class="r-label">${level.label}</div>