Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python | |
| # coding: utf-8 | |
| # 建立環境 | |
| # In[50]: | |
| # get_ipython().system('pip install gradio') | |
| # In[51]: | |
| # get_ipython().system('pip install gspread google-auth') | |
| # In[52]: | |
| import pandas as pd | |
| import matplotlib.pyplot as plt | |
| import numpy as np | |
| import gradio as gr | |
| import sklearn | |
| import pickle | |
| import joblib | |
| import time | |
| import os | |
| import json | |
| import gspread | |
| from sklearn.model_selection import train_test_split, RandomizedSearchCV | |
| from sklearn.compose import ColumnTransformer | |
| from sklearn.preprocessing import OneHotEncoder, StandardScaler | |
| from sklearn.pipeline import Pipeline | |
| from sklearn.linear_model import LogisticRegression | |
| from sklearn.metrics import classification_report, confusion_matrix, f1_score, accuracy_score, precision_score, balanced_accuracy_score | |
| from sklearn.ensemble import RandomForestClassifier | |
| from lightgbm import LGBMClassifier | |
| from AutoPreprocess import AutoPreprocess | |
| from google.oauth2.service_account import Credentials | |
| from datetime import datetime, timezone, timedelta | |
| # Gradio 使用者介面 | |
| # In[53]: | |
| # 載入模型 | |
| import pickle | |
| model_path = os.path.abspath("DASS_model.bin") | |
| with open(model_path, "rb") as f: | |
| model = pickle.load(f) | |
| model | |
| # 定義儲存測試資料的功能 | |
| # In[54]: | |
| import os | |
| import json | |
| from datetime import datetime, timezone, timedelta | |
| import gspread | |
| from google.oauth2.service_account import Credentials | |
| # 設定台灣時區 | |
| tw_timezone = timezone(timedelta(hours=8)) | |
| def save_to_google_sheets(inputs, a_score, d_score, s_score, t_score, score): | |
| # 1. 設定 Google Sheets 存取權限 | |
| scope = ['https://www.googleapis.com/auth/spreadsheets', | |
| 'https://www.googleapis.com/auth/drive'] | |
| # 設定Secret Variables(藏金鑰) | |
| google_json = os.environ.get("DASS_JSON") | |
| info = json.loads(google_json) | |
| creds = Credentials.from_service_account_info(info, scopes=scope) | |
| client = gspread.authorize(creds) | |
| # 2. 開啟指定名稱的試算表 (確保已分享權限給 service account) | |
| sheet = client.open("DASS使用者測試資料_個人").sheet1 # 存於檔案的第一張工作表 | |
| # 1. 拆分資料:前 3 個是基本資料,後面剩下的 (*rest) 是 12 題答案 | |
| user_info = inputs[:3] # 取得前三個:姓名, 年齡, 性別 | |
| q_answers = inputs[3:] # 取得剩下的 12 題 | |
| now = datetime.now(tw_timezone).strftime("%Y-%m-%d %H:%M:%S") | |
| # 2. 準備要儲存的資料字典 | |
| row_to_add = [ | |
| now, # 欄位 A: 測試時間 | |
| user_info[0], # 欄位 B: 性別 | |
| user_info[1], # 欄位 C: 年齡 | |
| user_info[2], # 欄位 D: 家庭人數 | |
| a_score, # 欄位 E: 焦慮分數 | |
| d_score, # 欄位 F: 憂鬱分數 | |
| s_score, # 欄位 G: 壓力分數 | |
| t_score, # 欄位 H: 總體分數 | |
| score # 欄位 I: 整體程度 (標籤) | |
| ] | |
| row_to_add.extend(q_answers) # 加入 Q1-Q12 (J欄以後) | |
| # 4. 追加到試算表最後一行 | |
| def to_py(v): | |
| return v.item() if hasattr(v, "item") else v | |
| row_to_add = [to_py(x) for x in row_to_add] | |
| sheet.append_row(row_to_add) | |
| def save_to_google_sheets_full42(inputs, dep_score, anx_score, str_score, overall, answers42): | |
| scope = ['https://www.googleapis.com/auth/spreadsheets', | |
| 'https://www.googleapis.com/auth/drive'] | |
| google_json = os.environ.get("DASS_JSON") | |
| info = json.loads(google_json) | |
| creds = Credentials.from_service_account_info(info, scopes=scope) | |
| client = gspread.authorize(creds) | |
| sh = client.open("DASS使用者測試資料_個人") | |
| ws_title = "DASS42_完整版" | |
| try: | |
| sheet = sh.worksheet(ws_title) | |
| except gspread.exceptions.WorksheetNotFound: | |
| sheet = sh.add_worksheet(title=ws_title, rows=2000, cols=60) | |
| header = ( | |
| ["測試時間", "性別", "年齡", "家庭人數", | |
| "焦慮分數", "憂鬱分數", "壓力分數", "總體分數", "整體程度"] | |
| + [f"Q{i}" for i in range(1, 43)] | |
| ) | |
| if sheet.acell("A1").value in (None, ""): | |
| sheet.update("A1", [header]) | |
| # ===== 整理資料 ===== | |
| now = datetime.now(tw_timezone).strftime("%Y-%m-%d %H:%M:%S") | |
| # inputs = [name, gen, age, family] + answers | |
| _, gen, age, family = inputs[0], inputs[1], inputs[2], inputs[3] | |
| # 若 family 是 15人以上 → 存成 16 | |
| if family == "15人以上": | |
| family = 16 | |
| t_score = dep_score + anx_score + str_score | |
| row_to_add = [ | |
| now, | |
| gen, | |
| age, | |
| family, | |
| anx_score, | |
| dep_score, | |
| str_score, | |
| t_score, | |
| overall | |
| ] | |
| row_to_add.extend(list(answers42)) | |
| def to_py(v): | |
| return v.item() if hasattr(v, "item") else v | |
| row_to_add = [to_py(x) for x in row_to_add] | |
| sheet.append_row(row_to_add) | |
| # 定義歷史紀錄功能 | |
| # In[56]: | |
| def update_history(current_result_1, current_result_2, history_list): | |
| """ | |
| current_result_1 & 2: 來自 predict_risk 的兩個回傳值 (HTML 字串) | |
| history_list: 來自 gr.State 的現有紀錄列表 | |
| """ | |
| # 獲取當前時間,格式為:2023-10-27 14:30:05 | |
| now = datetime.now(tw_timezone).strftime("%Y-%m-%d %H:%M:%S") | |
| # 組合這次的結果 (假設你想存這兩個 outputs 的組合) | |
| new_entry = f""" | |
| <div style="border-bottom: 2px solid #eee; padding-bottom: 20px; margin-bottom: 20px;"> | |
| <div style="font-size: 18px; color: #666; margin-bottom: 10px; font-weight: bold;"> | |
| 🕒 測驗時間:{now} | |
| </div> | |
| <div style=" | |
| display: flex; | |
| flex-direction: row; | |
| justify-content: space-between; | |
| align-items: flex-start; | |
| gap: 20px; | |
| border-bottom: 1px dashed #ccc; | |
| padding-bottom: 15px; | |
| margin-bottom: 15px; | |
| width: 100%;"> | |
| <div style="flex: 1;">{current_result_1}</div> | |
| <div style="flex: 1;">{current_result_2}</div> | |
| </div> | |
| </div> | |
| """ | |
| # 將新紀錄放在最前面 (置頂) | |
| history_list.insert(0, new_entry) | |
| # 組合所有歷史紀錄,並整體縮小 80% | |
| # 使用 zoom: 0.8 或 transform 達到字體與版面同時縮小的效果 | |
| combined_html = f""" | |
| <div style="zoom: 0.8; -moz-transform: scale(0.8); -moz-transform-origin: 0 0;"> | |
| {"".join(history_list)} | |
| </div> | |
| """ | |
| return combined_html, history_list | |
| # 定義重新測驗功能 | |
| # In[57]: | |
| # 清空函數:回傳與輸入組件數量相同的 None (15個:gen, age, family + 12個問題) | |
| def clear_all(): | |
| # 15個輸入(gen, age, family, q1~q12) + 2個即時結果 + 1個歷史面板 | |
| return [None] * 15 + ["", ""] | |
| # 排名設定 | |
| def make_rank_list(a_score, d_score, s_score): | |
| items = [ | |
| ("焦慮 (Anxiety)", a_score), | |
| ("憂鬱 (Depression)", d_score), | |
| ("壓力 (Stress)", s_score), | |
| ] | |
| items_sorted = sorted(items, key=lambda x: x[1], reverse=True) | |
| medal = ["🥇", "🥈", "🥉"] | |
| rows = "" | |
| for i, (name, _) in enumerate(items_sorted): | |
| rows += f""" | |
| <div style="display:flex; justify-content:space-between; padding:10px 0; border-bottom:1px solid #eee;"> | |
| <div style="font-size:18px;">{medal[i]} {name}</div> | |
| <div style="font-size:18px; color:#666;">第 {i+1} 名</div> | |
| </div> | |
| """ | |
| return f""" | |
| <div style="padding: 20px; background: white; border-radius: 10px; border: 1px solid #ddd;"> | |
| <h2 style="color:#313230; margin-top:0; margin-bottom:10px;">各面向排名</h2> | |
| {rows} | |
| </div> | |
| """ | |
| # 定義主要測試功能 | |
| # In[58]: | |
| # DASS-42 官方計分 | |
| dep_nums = [3,5,10,13,16,17,21,24,26,31,34,37,38,42] | |
| anx_nums = [2,4,7,9,15,19,20,23,25,28,30,36,40,41] | |
| str_nums = [1,6,8,11,12,14,18,22,27,29,32,33,35,39] | |
| def qcols(nums): | |
| return [f"Q{n}A" for n in nums] | |
| def level_dep(score): | |
| # DASS-42 Depression | |
| if score <= 9: return 0 | |
| if score <= 13: return 1 | |
| if score <= 20: return 2 | |
| if score <= 27: return 3 | |
| return 4 | |
| def level_anx(score): | |
| # DASS-42 Anxiety | |
| if score <= 7: return 0 | |
| if score <= 9: return 1 | |
| if score <= 14: return 2 | |
| if score <= 19: return 3 | |
| return 4 | |
| def level_str(score): | |
| # DASS-42 Stress | |
| if score <= 14: return 0 | |
| if score <= 18: return 1 | |
| if score <= 25: return 2 | |
| if score <= 33: return 3 | |
| return 4 | |
| LEVEL_NAME = {0:"正常", 1:"輕度", 2:"中度", 3:"重度", 4:"極重度"} | |
| def overall_severity_v2(d_level, a_level, s_level): | |
| total = d_level + a_level + s_level | |
| if (d_level == 4) or (a_level == 4) or (s_level == 4): | |
| return 2 | |
| if total >= 9: | |
| return 2 | |
| if (d_level == 3) or (a_level == 3) or (s_level == 3): | |
| return 1 | |
| if total <= 5: | |
| return 0 | |
| else: | |
| return 1 | |
| OVERALL_NAME = { | |
| 0:"低度風險", | |
| 1:"中度風險", | |
| 2:"高度風險"} | |
| OVERALL_COLOR = { | |
| 0: "#91cd92", # 綠 | |
| 1: "#f59e0b", # 橘 | |
| 2: "#ef4444", # 紅 | |
| } | |
| def predict_dass42_full(name, gen, age, family, *answers): | |
| """ | |
| 完整版:42題官方計分(0-3) | |
| 回傳:只顯示 Overall(v2)(大字置中)+ 右側排名卡(保留) | |
| 並寫入 Google Sheet(DASS42_完整版) | |
| """ | |
| inputs = [name, gen, age, family] + list(answers) | |
| if any(v is None or v == "" for v in inputs): | |
| raise gr.Error("⚠️請確保基本資料與 42 題都已填答。") | |
| # 建立 Q1A~Q42A | |
| row = {f"Q{i+1}A": int(answers[i]) for i in range(42)} | |
| # 官方三向度分數 | |
| dep_score = sum(row[c] for c in qcols(dep_nums)) | |
| anx_score = sum(row[c] for c in qcols(anx_nums)) | |
| str_score = sum(row[c] for c in qcols(str_nums)) | |
| # 分級 | |
| dep_level = level_dep(dep_score) | |
| anx_level = level_anx(anx_score) | |
| str_level = level_str(str_score) | |
| # Overall v2 | |
| overall = overall_severity_v2(dep_level, anx_level, str_level) | |
| # 寫入 Google Sheet(42 題) | |
| # answers42 就是 42 題答案本身 | |
| save_to_google_sheets_full42( | |
| inputs=[name, gen, age, family], | |
| dep_score=dep_score, | |
| anx_score=anx_score, | |
| str_score=str_score, | |
| overall=overall, | |
| answers42=answers | |
| ) | |
| # 顏色 + 顯示文字 | |
| color = OVERALL_COLOR.get(overall, "#999999") | |
| text = OVERALL_NAME.get(overall, str(overall)) | |
| # 左側大字結果(不含下方說明) | |
| result_html = f""" | |
| <div style="text-align:center; font-family:sans-serif; padding: 40px 0;"> | |
| <div style="font-size: 44px; font-weight: 900; color:#313230; margin-bottom: 26px;"> | |
| 您的預測結果為 | |
| </div> | |
| <div style="font-size: 96px; font-weight: 900; color:{color}; line-height: 1;"> | |
| {text} | |
| </div> | |
| </div> | |
| """ | |
| # 右邊排名卡 | |
| rank_html = make_rank_list(anx_score, dep_score, str_score) | |
| return result_html, rank_html | |
| # 定義預測功能 | |
| def predict_risk(gen, age, family, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12): | |
| inputs = [gen, age, family, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12] | |
| if any(v is None or v == "" for v in inputs): | |
| raise gr.Error("⚠️測驗載入有誤:請確保每一題都已填答或查看填答格式是否正確。") | |
| progress = gr.Progress() | |
| progress(0, desc="模型計算中...") | |
| # age 可能是 int / str,都統一轉 int | |
| age = int(age) | |
| # family 可能是 int / str / "15人以上" | |
| if family == "15人以上": | |
| family = 16 | |
| else: | |
| family = int(family) | |
| cols = ["gender", "age", "familysize", "Q2A", "Q4A", "Q19A", "Q20A", "Q28A", "Q21A", "Q26A", "Q37A", "Q42A", "Q11A", "Q12A", "Q27A"] | |
| input_df = pd.DataFrame([[gen, age, family, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12]], columns=cols) | |
| progress(0.5, desc="正在分析數據...") | |
| time.sleep(0.5) | |
| score = model.predict(input_df)[0] | |
| if score == 0: | |
| label = "低度風險" | |
| color = "#91cd92" | |
| elif score == 1: | |
| label = "中度風險" | |
| color = "#f59e0b" | |
| elif score == 2: | |
| label = "高度風險" | |
| color = "#ef4444" | |
| else: | |
| label = "計算結果有誤,請重新測試。" | |
| color = "#999999" | |
| a_score = (q1 + q2 + q3 + q4 + q5) | |
| d_score = (q6 + q7 + q8 + q9) | |
| s_score = (q10 + q11 + q12) | |
| t_score = a_score + d_score + s_score | |
| result_score = f""" | |
| <div style="text-align: center; font-family: sans-serif;"> | |
| <h2 style="color: #313230;">您的預測結果為</h2> | |
| <h1 style="font-size: 60px; color: {color}; margin: 0;"> | |
| {label} | |
| </h1> | |
| </div> | |
| """ | |
| label_html = make_rank_list(a_score, d_score, s_score) | |
| save_to_google_sheets(inputs, a_score, d_score, s_score, t_score, score) | |
| progress(1.0, desc="完成") | |
| return result_score, label_html | |
| # In[59]: | |
| # 設定主題色 | |
| theme = gr.themes.Default( | |
| primary_hue="amber", | |
| secondary_hue="amber", | |
| ).set( | |
| body_background_fill="#fffbeb" | |
| ) | |
| # In[60]: | |
| # 線上主題調色器 | |
| # gr.themes.builder() | |
| # In[61]: | |
| # 介面編排 | |
| #按鈕及面板格式設定 | |
| custom_css = """ | |
| #my_green_btn { | |
| background-color: #91cd92 !important; | |
| color: white !important; | |
| border: none; | |
| } | |
| #my_green_btn:hover { | |
| background-color: #72a473 !important; /* 滑鼠懸停時變深 */ | |
| } | |
| #my_white_btn { | |
| background-color: #ffffff !important; | |
| color: black !important; | |
| border: 1px solid #e4e4e7; | |
| } | |
| #my_white_btn:hover { | |
| background-color: #e4e4e7 !important; | |
| color: black !important; /* 滑鼠懸停時變深 */ | |
| } | |
| .my-custom-panel { | |
| background-color: #fffef8 !important; | |
| border: 2px solid #e4e4e7 !important; | |
| padding: 20px; | |
| border-radius: 15px; | |
| } | |
| #history_panel .label-wrap span { | |
| font-weight: bold !important; | |
| } | |
| """ | |
| # UI | |
| age_choices = list(range(1, 100)) # 1~99歲 | |
| family_choices = list(range(1, 16)) + ["15人以上"] | |
| with gr.Blocks() as demo: | |
| # Tab1 歷史 | |
| history_state = gr.State([]) | |
| gr.Markdown("") | |
| gr.HTML(""" | |
| <div style="text-align: center; font-family: sans-serif;"> | |
| <h2 style="font-size: 32px; color: #313230; margin: 0;">🌿心理健康風險程度測試📝</h2> | |
| </div> | |
| """) | |
| with gr.Tabs(): | |
| # ========================================================= | |
| # TAB 1:簡易版(12題|模型) | |
| # ========================================================= | |
| with gr.TabItem("簡易版 12題"): | |
| gr.HTML(""" | |
| <div style="text-align: center; font-family: sans-serif;"> | |
| <h2 style="font-size: 18px; color: #313230; margin: 0;">歡迎來到心理健康風險程度測試環境!<br> | |
| 本測驗將透過12題問答,替您在5分鐘內簡單計算出潛在的心理健康風險程度。<br> | |
| 請輕鬆填答,無須思慮過度,測驗愉快!</h2> | |
| </div> | |
| """) | |
| with gr.Column(variant="panel", elem_classes="my-custom-panel"): | |
| gr.Markdown("## Step 1. 請輸入基本資訊") | |
| with gr.Row(): | |
| with gr.Column(): | |
| name = gr.Textbox(label="暱稱") | |
| gen = gr.Dropdown(choices=["男", "女", "其他"], label="性別") | |
| with gr.Column(): | |
| age = gr.Dropdown( | |
| choices=age_choices, | |
| label="年齡", | |
| value=None | |
| ) | |
| family = gr.Dropdown( | |
| choices=family_choices, | |
| label="家庭人數", | |
| value=None | |
| ) | |
| gr.Markdown("## Step 2. 請依自身狀態選擇符合的答案") | |
| q1 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)], label="Q1.我感覺到口乾舌燥。") | |
| q2 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)], label="Q2.我感到呼吸困難(例如:在沒有體力勞動的情況下,呼吸過度急促或喘不過氣)。") | |
| q3 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)], label="Q3.在氣溫不高或沒有體力勞動的情況下,我明顯地流汗(例如:手汗)。") | |
| q4 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)], label="Q4.我無緣無故地感到害怕。") | |
| q5 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)], label="Q5.我覺得自己接近恐慌發作的邊緣。") | |
| q6 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)], label="Q6.我覺得生命沒什麼意義/價值。") | |
| q7 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)], label="Q7.我感到垂頭喪氣、情緒低落。") | |
| q8 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)], label="Q8.我覺得未來毫無希望。") | |
| q9 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)], label="Q9.我發現自己很難打起精神主動去做事。") | |
| q10 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)], label="Q10.我發現自己很容易變得心煩意亂。") | |
| q11 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)], label="Q11.我覺得自己消耗了大量的神經能量(處於高度緊繃狀態)。") | |
| q12 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)], label="Q12.我發現自己非常易怒(容易焦躁)。") | |
| sub_button = gr.Button("確認送出", elem_id="my_green_btn") | |
| btn_reset = gr.Button("重新測驗", elem_id="my_white_btn") | |
| with gr.Row(): | |
| out_html = gr.HTML() | |
| out_label = gr.HTML() | |
| with gr.Accordion("查看歷史紀錄", open=False, elem_id="history_panel"): | |
| history_display = gr.HTML(value="目前尚無測驗紀錄") | |
| sub_button.click( | |
| fn=predict_risk, | |
| inputs=[gen, age, family, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12], | |
| outputs=[out_html, out_label], | |
| ).then( | |
| fn=update_history, | |
| inputs=[out_html, out_label, history_state], | |
| outputs=[history_display, history_state], | |
| ) | |
| btn_reset.click( | |
| fn=lambda: [None]*15 + ["", ""], | |
| inputs=None, | |
| outputs=[gen, age, family, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, out_html, out_label], | |
| ) | |
| gr.Markdown("## 免責聲明") | |
| gr.Markdown("""本測驗結果僅供參考,非屬正規醫療檢驗範疇。 | |
| 若對於自身狀況有任何疑慮,敬請尋求正規專業醫療協助!♡第四組關心您♡""") | |
| # ========================================================= | |
| # TAB 2:完整版(42題|官方計分) | |
| # ========================================================= | |
| with gr.TabItem("完整版 42題"): | |
| # Tab2 歷史 | |
| full_history_state = gr.State([]) | |
| gr.HTML(""" | |
| <div style="text-align: center; font-family: sans-serif; margin-bottom: 6px;"> | |
| <h2 style="font-size: 18px; color: #313230; margin: 0;"> | |
| 歡迎來到 DASS-42 完整版心理測驗!<br> | |
| 本測驗將依 42 題官方計分規則,計算您的心理狀態並輸出風險程度。<br> | |
| 請依過去一週的感受作答,測驗愉快! | |
| </h2> | |
| </div> | |
| """) | |
| gr.Markdown("## Step 1. 請輸入基本資訊") | |
| with gr.Row(): | |
| with gr.Column(): | |
| full_name = gr.Textbox(label="暱稱") | |
| full_gen = gr.Dropdown(choices=["男", "女", "其他"], label="性別") | |
| with gr.Column(): | |
| full_age = gr.Dropdown( | |
| choices=age_choices, | |
| label="年齡", | |
| value=None | |
| ) | |
| full_family = gr.Dropdown( | |
| choices=family_choices, | |
| label="家庭人數", | |
| value=None | |
| ) | |
| gr.Markdown("## Step 2. DASS-42(0~3)") | |
| dass42_questions = [ | |
| "1. 我發覺自己會因為瑣事而沮喪", | |
| "2. 我察覺到自己口乾舌燥", | |
| "3. 我似乎無法經驗任何正向的感受", | |
| "4. 我經歷過呼吸困難(例如:在沒有耗費體力的情況下仍呼吸過快、呼吸困難)", | |
| "5. 我似乎就是提不起勁", | |
| "6. 我傾向對情境過度反應", | |
| "7. 我有顫抖的感覺(例如:雙腿無力)", | |
| "8. 我發覺難以放鬆", | |
| "9. 我發覺我處於讓自己頗焦慮的情況,而當它們結束時我感到紓解", | |
| "10. 我覺得我沒有什麼可以期待的", | |
| "11. 我發覺自己頗容易變得沮喪", | |
| "12. 我覺得我相當費心勞神", | |
| "13. 我感到傷心且憂鬱", | |
| "14. 我發覺自己在任何被延誤的情況中(例如:等電梯、等紅綠燈、一直等待)會變得不耐煩", | |
| "15. 我有頭暈無力的感覺", | |
| "16. 我覺得我幾乎對任何事情已失去興趣", | |
| "17. 我覺得我作為一個人沒有多少價值", | |
| "18. 我覺得我頗敏感", | |
| "19. 在沒有高溫或耗費體力的情況下,我仍明顯出汗(例如:冒手汗)", | |
| "20. 我會無緣無故地感到害怕", | |
| "21. 我覺得人生沒有價值", | |
| "22. 我發覺難以平靜下來", | |
| "23. 我有吞嚥的困難", | |
| "24. 我似乎無法從所做的事情中獲得任何樂趣", | |
| "25. 在沒有耗費體力的情況下,我仍覺察到我心臟的活動(例如:感覺心率增加、心跳漏拍)", | |
| "26. 我感到沮喪而消沉", | |
| "27. 我發覺自己煩躁易怒", | |
| "28. 我覺得自己快要陷入恐慌", | |
| "29. 我發覺當某些事物讓我沮喪後,我難以平靜下來", | |
| "30. 我怕自己會被某些瑣碎但不熟悉的任務給難倒", | |
| "31. 我無法對任何事物變得熱衷", | |
| "32. 我發覺難以容忍自己正在做的事情被打擾", | |
| "33. 我處於神經緊繃的狀態", | |
| "34. 我覺得我頗沒有價值", | |
| "35. 我不能容忍任何阻礙我繼續做事的事物", | |
| "36. 我感到懼怕", | |
| "37. 我看不到未來可以期盼的事物", | |
| "38. 我覺得人生是沒有意義的", | |
| "39. 我發覺自己變得激動不安", | |
| "40. 我對於可能會讓我恐慌或是出糗的情境感到擔憂", | |
| "41. 我有過顫抖的經驗(例如:手部)", | |
| "42. 我發覺難以產生動力去做事", | |
| ] | |
| full_q_widgets = [] | |
| for q_text in dass42_questions: | |
| full_q_widgets.append( | |
| gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)], label=q_text) | |
| ) | |
| full_submit = gr.Button("確認送出(計算完整版分數)", elem_id="my_green_btn") | |
| with gr.Row(): | |
| full_out_html = gr.HTML() | |
| full_out_rank = gr.HTML() | |
| with gr.Accordion("查看歷史紀錄(完整版)", open=False, elem_id="history_panel"): | |
| full_history_display = gr.HTML(value="目前尚無測驗紀錄") | |
| full_submit.click( | |
| fn=predict_dass42_full, | |
| inputs=[full_name, full_gen, full_age, full_family] + full_q_widgets, | |
| outputs=[full_out_html, full_out_rank], | |
| ).then( | |
| fn=update_history, | |
| inputs=[full_out_html, full_out_rank, full_history_state], | |
| outputs=[full_history_display, full_history_state], | |
| ) | |
| gr.Markdown("## 免責聲明") | |
| gr.Markdown("""本測驗結果僅供參考,非屬正規醫療檢驗範疇。 | |
| 若對於自身狀況有任何疑慮,敬請尋求正規專業醫療協助!♡第四組關心您♡""") | |
| demo.launch(theme=theme, css=custom_css) |