Clinical #1: Subject ID 자유입력 → Phantom/Human/ETC 카테고리 (회의 결정)

회의 결정: 자유 텍스트 ID 입력 대신 측정 대상을 PHANTOM/HUMAN/ETC 세
카테고리로 명확히 구분. JSON/labdb 저장 방식도 함께 변경.

데이터 모델 (ClinicalSession.kt):
  - SubjectType enum 추가: PHANTOM / HUMAN / ETC
  - val subjectId: String 제거 → val subjectType: SubjectType
  - 폴더명: "{subjectId}_{...}" → "{SUBJECT_TYPE}_{...}"
    예: PHANTOM_VBT26050202_SUPINE_ALIGN_0CM_2026-06-08_15-30-00

JSON 변경 (meta.json + measurement.json):
  - "subject_id": "S001" → "subject_type": "PHANTOM"

labdb payload (LabdbUploader):
  - params.subject_id → params.subject_type (서버는 free JSON이라 코드 변경 불필요)

UI (ClinicalHomeView):
  - Subject ID OutlinedTextField 제거
  - LabeledSegmented "Subject Type" 3개 버튼 (Phantom/Human/ETC)
  - 마지막 선택 기억 (ClinicalSessionStore.lastSubjectType)

ClinicalLive 상단 sub line: "S=S001 · TV=300mL · Ab=22mm"
                          → "Phantom · TV=300mL · Ab=22mm"

호환성: 기존 측정 폴더는 그대로. 새 폴더부터 새 형식 적용.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-09 09:03:22 +09:00
parent f00aef50e7
commit f3cca9a4c7
5 changed files with 28 additions and 26 deletions
@@ -24,6 +24,11 @@ enum class ClinicalPosture(val label: String) {
SUPINE("Supine"), SITTING("Sitting"), STANDING("Standing")
}
/** 측정 대상 분류 — 회의 결정 (subject ID 자유 입력 대체). */
enum class SubjectType(val label: String) {
PHANTOM("Phantom"), HUMAN("Human"), ETC("ETC")
}
/**
* 측정 단계.
* - ALIGN_0CM ~ ALIGN_4CM: 정렬모드 알고리즘 개발용 (기기 아래 끝 기준 치골 위 0~4cm)
@@ -44,8 +49,8 @@ data class ClinicalSession(
val step: ClinicalStep,
val examiner: String = "",
val notes: String = "",
// 임상 시험 정보 (vesiscan_test Section 2-1 프로토콜과 매칭)
val subjectId: String = "", // 피험자 ID (예: "S001")
// 측정 대상 분류 (회의 결정: Phantom/Human/ETC 버튼 — subject ID 자유 입력 대체)
val subjectType: SubjectType = SubjectType.PHANTOM,
val trueVolumeMl: Double? = null, // 외부 초음파 측정기 참값 (mL)
val abdomenThicknessMm: Double? = null, // 복부 두께 측정기 참값 (mm)
val startedAt: Long = System.currentTimeMillis(),
@@ -53,13 +58,9 @@ data class ClinicalSession(
) {
private val folderFmt = SimpleDateFormat("yyyy-MM-dd_HHmmss", Locale.US)
/** "S001_VBT26050202_SUPINE_ALIGN_0CM_2026-05-28_14-30-15"
* subjectId 비어있으면 기존 형식 유지 (deviceName_posture_step_timestamp). */
/** "PHANTOM_VBT26050202_SUPINE_ALIGN_0CM_2026-05-28_14-30-15" */
val folderName: String
get() = buildString {
if (subjectId.isNotBlank()) { append(subjectId); append('_') }
append("${deviceName}_${posture.name}_${step.name}_${folderFmt.format(Date(startedAt))}")
}
get() = "${subjectType.name}_${deviceName}_${posture.name}_${step.name}_${folderFmt.format(Date(startedAt))}"
/** clinical_label 컬럼/필드 값 (라벨링 자동) */
val label: String