タブレットで描画タスク(時計描画・五角形模写・TMT等)を実施し、ペンの速度・圧力・傾きなど22特徴量を自動抽出して認知機能リスクを判定。MMSE/MoCA-J の認知検査も統合。施設PINでデータを分離管理。

1. 全体アーキテクチャ(上から下に流れる)

検査者(タブレット / PC) 施設PIN入力(4〜6桁、大型キーパッド) PinGuard(全画面ラップ認証ガード) ① PIN入力 → Firebase Anonymous Auth でサインイン ② Firestore facilities/{pin} の存在確認 → 新規作成 or lastAccessedAt 更新 ③ localStorage に PIN 保存(次回自動認証) 認証OK ページ層 HomePage — 患者ID入力 → 検査種別選択 TestPage(描画テスト 5タスク) MMSEPage(30問) HybridPage(川口式統合 20問) ResultPage / ProfilePage / ExercisePage / FeedbackPage データ保存 データ保存(二層構造) localStorage(主軸・オフライン対応) dct_profiles / dct_history / dct_mmse_history dct_moca_history / dct_assessments / dct_exercise_log 上限50〜200件 / オフライン動作可能 Firestore(施設間共有) facilities/{pin}/assessments/{id} → MMSE/MoCA結果 / downloadLogs 同一PINの複数端末でデータ集約可能

2. 描画テストの流れ(TestPage.tsx)

sentence(文章書字) 「今日はいい天気です」を書く → extractFeatures() で特徴量抽出 pentagon(五角形模写) 2つの重なった五角形を模写 → extractFeatures() tmt_a(TMT-A) 1→2→3→...→25 を数字順に結ぶ → extractFeatures() tmt_b(TMT-B) 1→あ→2→い→3→う… 交互に結ぶ → extractFeatures() cdt(時計描画テスト) 破線ガイド円の上に時計を描く → extractFeatures() 全5タスク完了 スコア計算 → リスク判定 → PDF出力 → localStorage保存 タスク別重み (スコアリング重要度) sentence 0.8 pentagon 0.85 tmt_a 0.9 tmt_b 1.0 ★最重要 cdt 0.95

3. 描画エンジンの仕組み(DrawingCanvas.tsx)

HTML5 Canvas onPointerDown → ストローク開始 onPointerMove → 各点データ収集 onPointerUp → ストローク完了 戻す 消去 完了 データ収集 PenPoint x, y ← 座標 pressure ← ペン圧(0〜1) tiltX, tiltY ← 傾き(°) timestamp ← 時刻(ms) 線幅 = strokeWidth × (0.5 + pressure×1.5) Stroke コレクション 複数のストロークを配列で保持 各ストローク = PenPoint の配列 完了後 → extractFeatures() へ

★ showGuide: タスクに応じたSVGガイドを重畳 — CDT→破線円 / TMT-A→数字サークル25個

4. 22特徴量の構造(featureExtractor.ts)

Kobayashi et al. (2022) に基づく実装。

描画データ(ストローク群)入力 速度・加速度(6種) speedMean 描画速度の平均 speedCv 速度の変動係数(ブレ具合) speedExtrema 速度の極値頻度 accelMean 加速度の平均 accelCv 加速度の変動係数 accelExtrema 加速度の極値頻度 ペン圧(5種) pressureMean ペン圧の平均 pressureCv ペン圧の変動係数 pressureExtrema 極値頻度 pressureChange ペン圧変化の平均 (pressureChange SD) ペン圧変化の標準偏差 ペン傾き(6種) tiltXSd X軸傾きの標準偏差(手のブレ) tiltYSd Y軸傾きの標準偏差 tiltXChange X軸傾き変化の中央値 tiltYChange Y軸傾き変化の中央値 tiltXChangeSd X軸傾き変化の標準偏差 tiltYChangeSd Y軸傾き変化の標準偏差 休止(5種) pauseMeanMs 休止時間の平均(ms) pauseTotal 総休止/距離比 pauseDrawing 休止/描画時間比 totalDuration 総時間/距離比 drawingMotions 動作数/距離比 0 要相談(39点以下) 要注意(40〜69点) 正常範囲(70点以上) 100 40 70

5. 施設PIN認証フロー(PinGuard.tsx)

開始 localStorage に PIN あり? YES 自動再認証 NO PinEntryScreen(大型キーパッド) Firebase Anonymous Auth でサインイン Firestore facilities/{pin} 確認 施設ドキュメント 存在する? YES lastAccessedAt を更新 NO 新規施設として ドキュメント作成 認証完了 → アプリ表示
セキュリティ制約: Firestore Rules は Anonymous Auth のみ確認。PINの一致検証はクライアント側のパス構築に依存。認証済みユーザーが任意PINのデータにアクセスできる構造的リスクあり。

6. プライバシー保護の設計

保存するもの chartId(数字のみのID番号) 描画データ(座標・圧力・傾き) スコア・判定結果 検査日時 保存しないもの 氏名 生年月日・年齢 住所 施設名
患者IDの入力: type="password" で画面上から隠す。年齢正規化: ageNormalization.ts にコードはあるが、個人情報(年齢)を使わないため意図的に無効化している。

7. アーキテクチャ上の注意点

二重アーキテクチャの並存
現在使用中: フロントエンド → Firebase Firestore
残存(未使用): src/worker/index.ts → Cloudflare Workers + D1(SQLite)の旧バックエンド。フロントから呼ばれていない。