Clinical: dataType "001" (내부 임상) + measurement.json/meta.json에 data_type 필드 노출
labdb 자료 구분 코드를 "000"(외부 일반 VesiScan) → "001"(내부 임상 R&D)로 변경. ClinicalSessionStore에 const DATA_TYPE을 두고, meta.json과 measurement.json의 meta 블록에 "data_type": "001"을 함께 기록 — 폴더만 보고도 내부 임상 데이터임을 즉시 식별 가능. LabdbUploader는 measurement.json의 meta.data_type을 우선 사용하고 없으면 "001" fallback. 향후 dataType이 늘어나도 단일 진실 출처(meta)에서 파생되도록 분리. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -32,6 +32,9 @@ data class MeasurementCycle(
|
|||||||
*/
|
*/
|
||||||
object ClinicalSessionStore {
|
object ClinicalSessionStore {
|
||||||
|
|
||||||
|
/** labdb 자료 구분 코드 — "001" = 내부 임상 R&D (외부 일반 VesiScan "000"과 구분). */
|
||||||
|
const val DATA_TYPE: String = "001"
|
||||||
|
|
||||||
/** ClinicalHome 화면에 진입한 상태인지. BLE 연결을 위한 DeviceScan 우회/Back 라우팅에 사용. */
|
/** ClinicalHome 화면에 진입한 상태인지. BLE 연결을 위한 DeviceScan 우회/Back 라우팅에 사용. */
|
||||||
@Volatile
|
@Volatile
|
||||||
var inClinicalFlow: Boolean = false
|
var inClinicalFlow: Boolean = false
|
||||||
@@ -96,6 +99,7 @@ object ClinicalSessionStore {
|
|||||||
val dir = currentLogDir() ?: return
|
val dir = currentLogDir() ?: return
|
||||||
dir.mkdirs()
|
dir.mkdirs()
|
||||||
val meta = JSONObject().apply {
|
val meta = JSONObject().apply {
|
||||||
|
put("data_type", DATA_TYPE)
|
||||||
put("device_name", s.deviceName)
|
put("device_name", s.deviceName)
|
||||||
put("posture", s.posture.name)
|
put("posture", s.posture.name)
|
||||||
put("step", s.step.name)
|
put("step", s.step.name)
|
||||||
@@ -174,6 +178,7 @@ object ClinicalSessionStore {
|
|||||||
|
|
||||||
// meta: writeMeta()와 동일 내용 포함 (단독 파일로 자족 가능)
|
// meta: writeMeta()와 동일 내용 포함 (단독 파일로 자족 가능)
|
||||||
val meta = JSONObject().apply {
|
val meta = JSONObject().apply {
|
||||||
|
put("data_type", DATA_TYPE)
|
||||||
put("subject_id", s.subjectId)
|
put("subject_id", s.subjectId)
|
||||||
put("device_name", s.deviceName)
|
put("device_name", s.deviceName)
|
||||||
put("posture", s.posture.name)
|
put("posture", s.posture.name)
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ import java.util.Locale
|
|||||||
* - 성공: folder/labdb_upload.json (응답 본문)
|
* - 성공: folder/labdb_upload.json (응답 본문)
|
||||||
* - 실패: folder/labdb_upload_error.json (에러 본문) — 폴더는 그대로 유지되어 수동 재시도 가능
|
* - 실패: folder/labdb_upload_error.json (에러 본문) — 폴더는 그대로 유지되어 수동 재시도 가능
|
||||||
*
|
*
|
||||||
* dataType = "000" (VesiScan 6채널). vesiscan_test 프로토콜과 동일.
|
* dataType = "001" (내부 임상 R&D — 외부 일반 VesiScan "000"과 구분).
|
||||||
|
* measurement.json의 meta.data_type을 우선 사용, 없으면 DEFAULT_DATA_TYPE fallback.
|
||||||
*
|
*
|
||||||
* testId:
|
* testId:
|
||||||
* - 폴더명 그대로 사용 (사용자 결정). 단 ^[A-Za-z0-9_-]{1,40}$ 제한 때문에
|
* - 폴더명 그대로 사용 (사용자 결정). 단 ^[A-Za-z0-9_-]{1,40}$ 제한 때문에
|
||||||
@@ -30,7 +31,7 @@ import java.util.Locale
|
|||||||
*/
|
*/
|
||||||
object LabdbUploader {
|
object LabdbUploader {
|
||||||
private const val TAG = "LabdbUploader"
|
private const val TAG = "LabdbUploader"
|
||||||
private const val DATA_TYPE = "000"
|
private const val DEFAULT_DATA_TYPE = "001"
|
||||||
|
|
||||||
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
||||||
private val isoFmt: SimpleDateFormat
|
private val isoFmt: SimpleDateFormat
|
||||||
@@ -74,6 +75,7 @@ object LabdbUploader {
|
|||||||
val meta = measurement.optJSONObject("meta") ?: JSONObject()
|
val meta = measurement.optJSONObject("meta") ?: JSONObject()
|
||||||
val cycles = measurement.optJSONArray("cycles") ?: JSONArray()
|
val cycles = measurement.optJSONArray("cycles") ?: JSONArray()
|
||||||
val testId = sanitizeTestId(folderName)
|
val testId = sanitizeTestId(folderName)
|
||||||
|
val dataType = meta.optString("data_type").ifBlank { DEFAULT_DATA_TYPE }
|
||||||
|
|
||||||
val records = JSONArray()
|
val records = JSONArray()
|
||||||
for (i in 0 until cycles.length()) {
|
for (i in 0 until cycles.length()) {
|
||||||
@@ -99,7 +101,7 @@ object LabdbUploader {
|
|||||||
|
|
||||||
return JSONObject().apply {
|
return JSONObject().apply {
|
||||||
put("testId", testId)
|
put("testId", testId)
|
||||||
put("dataType", DATA_TYPE)
|
put("dataType", dataType)
|
||||||
put("sessionName", meta.optString("label").ifBlank { folderName })
|
put("sessionName", meta.optString("label").ifBlank { folderName })
|
||||||
put("memo", meta.optString("notes"))
|
put("memo", meta.optString("notes"))
|
||||||
meta.optLong("ended_at", 0L).takeIf { it > 0 }?.let {
|
meta.optLong("ended_at", 0L).takeIf { it > 0 }?.let {
|
||||||
|
|||||||
Reference in New Issue
Block a user