ui(align): 지시문을 "치골 위 N cm 에 붙이고 측정" 하나로 — 상대 이동(올리고/내리고)을 뺀다
현장 의견(2026-09-29): 판정 뒤 "최적 N cm" 옆에 "아래로 2cm 내리세요" 가 붙어 나와
어디에 붙이라는 건지 헷갈린다. 2026-09-09 에 "최적 위치/부착 위치" 두 숫자가 헷갈려
상대 이동으로 바꿨는데, 상대 이동도 판정 숫자와 나란히 보이면 다시 숫자가 둘이 된다.
치골은 손으로 짚는 기준점이라 **치골 위 절대 위치 하나**만 말한다. 버튼의 숫자
("N cm 측정하기")와 같아 서로를 확인해 주고, 셀 것도 비교할 것도 없다.
수집 치골 위 N cm 에 붙이고 측정
확인 측정 치골 위 N cm 에 다시 붙이고 측정 (이미 그 자리면 "에서 한 번 더 측정")
확정 치골 위 N+1 cm 에 붙이세요 — 재지 말고 좌우로
재부착 더 아래에 다시 붙이세요 (갈 자리가 없어 이것만 상대적)
화살표(↑↓●)는 남긴다 — 글에는 방향을 쓰지 않고 눈으로만 거든다. 좌우 단계 안내도
"1cm 올린 자리" 대신 "치골 위 N cm 에 붙인 그대로" 로.
시험: AlignInstructionTest 문구 갱신 + "재부착 말고는 상대 이동을 말하지 않는다" 추가.
docs/CLINICAL_ALGORITHM.md §3.6 흐름을 새 문구로.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -13,21 +13,23 @@
|
||||
* cycle 수가 곧 trace 수를 정하는데(20 → 11 trace), trace 가 줄면 CH3 검출률의 해상도가
|
||||
* 거칠어져 0.8 임계가 불안정해진다.
|
||||
*
|
||||
* ## 화면은 지시문 하나만 보여준다
|
||||
* ## 화면은 지시문 하나만 보여준다 — 숫자는 "치골 위 N cm" 하나뿐
|
||||
* 위치 이름(최적·부착)을 쓰지 않는다. 시험하는 사람이 두 숫자를 계속 헷갈렸다
|
||||
* (2026-09-09 현장) — 둘 다 "위치"라는 이름의 숫자이고 단계마다 다른 쪽이 커졌기
|
||||
* 때문이다. 프로브를 잡은 사람에게 필요한 것은 **지금 할 동작 하나**다([instructionOf]).
|
||||
* 때문이다. 그래서 한때 상대 이동("2cm 내리고 측정")으로 바꿨는데, 그것도 헷갈렸다
|
||||
* (2026-09-29 현장: "최적 N cm" 옆에 "아래로 2cm" 가 붙어 다시 숫자가 둘이 됐다).
|
||||
* 지금은 **치골 위 절대 위치 하나**만 말한다([instructionOf]). 치골이 기준점이라
|
||||
* 간호사가 세지 않아도 되고, 버튼의 숫자와 같아 서로를 확인해 준다.
|
||||
*
|
||||
* 카드(동작) 버튼(자리)
|
||||
* 치골 바로 위에 붙이고 측정 [0cm 측정하기]
|
||||
* 1cm 올리고 측정 [1cm 측정하기]
|
||||
* 카드(자리) 버튼(자리)
|
||||
* 치골 위 0cm 에 붙이고 측정 [0cm 측정하기]
|
||||
* 치골 위 1cm 에 붙이고 측정 [1cm 측정하기]
|
||||
* ...
|
||||
* 2cm 내리고 측정 [1cm 측정하기]
|
||||
* 여기서 한 번 더 측정 [1cm 측정하기]
|
||||
* **1cm 올리세요 (재지 말고 좌우로)** — 버튼 없음
|
||||
* 치골 위 1cm 에 다시 붙이고 측정 [1cm 측정하기] (확인 측정)
|
||||
* 치골 위 1cm 에서 한 번 더 측정 [1cm 측정하기] (이미 그 자리)
|
||||
* **치골 위 2cm 에 붙이세요 (재지 말고 좌우로)** — 버튼 없음
|
||||
*
|
||||
* 카드는 **어떻게 움직일지**, 버튼은 **움직인 뒤 어디를 재는지**다. 둘 다 숫자를 쓰면
|
||||
* 서로를 확인해 준다 — 카드대로 움직였으면 버튼의 숫자가 지금 자리와 맞는다.
|
||||
* 화살표(↑↓●)는 지금 자리에서 어느 쪽인지 눈으로만 거든다 — 글에는 방향을 쓰지 않는다.
|
||||
*
|
||||
* 마지막 +1cm 자리는 **측정하지 않는다**. 설계상 그 자리는 지표가 나쁘므로, 재확인하면
|
||||
* 반드시 "미달"이 떠서 도달 전에 멈추게 된다.
|
||||
@@ -685,13 +687,12 @@ fun AnchorAlignView(appState: AppState) {
|
||||
}
|
||||
Spacer(Modifier.height(16.dp))
|
||||
|
||||
// 지금 무엇을 할지 — 크게. **위치 이름을 쓰지 않는다.**
|
||||
// 지금 어디에 붙일지 — 크게. **숫자는 "치골 위 N cm" 하나.**
|
||||
//
|
||||
// 종전에는 "지금 측정할 위치 2cm" 과 "부착 위치 3cm" 을 번갈아 보여 줬다.
|
||||
// 두 숫자가 다 "위치"라는 이름을 달고 나오니, 시험하는 사람이 어느 자리에
|
||||
// 붙여야 하는지 매번 헷갈렸다(2026-09-09 현장 피드백). 실제로 필요한 것은
|
||||
// **지금 할 동작 하나**다 — 1cm 올려서 재라, 2cm 내려서 재라, 1cm 올리고
|
||||
// 좌우로 넘어가라. 절대 위치는 기록의 몫이고 사람이 셀 일이 아니다.
|
||||
// 종전에는 "지금 측정할 위치 2cm" 과 "부착 위치 3cm" 을 번갈아 보여 줬고
|
||||
// (2026-09-09: 둘 다 "위치"라 헷갈림), 그 다음엔 "2cm 내리고 측정" 같은 상대
|
||||
// 이동으로 바꿨다(2026-09-29: "최적 N cm" 과 나란히 보여 다시 헷갈림). 치골을
|
||||
// 기준으로 한 절대 위치 하나만 말하면 셀 것도 비교할 것도 없다([instructionOf]).
|
||||
// ── 단일 pass 와 비교 (감사용) ──────────────────────────────────
|
||||
// 앱이 쓰는 값은 전수 판정이다. 단일 pass 가 냈을 답을 같이 보여 주면
|
||||
// "단봉 가정이 얼마나 깨지는가"를 현장에서도 세어 볼 수 있다.
|
||||
@@ -800,14 +801,10 @@ fun AnchorAlignView(appState: AppState) {
|
||||
enabled = isConnected && !measuring,
|
||||
modifier = Modifier.fillMaxWidth().height(52.dp),
|
||||
shape = RoundedCornerShape(14.dp),
|
||||
// 카드와 버튼이 역할을 나눈다: **카드는 동작(상대), 버튼은 자리(절대).**
|
||||
//
|
||||
// 카드 "1cm 올리고 측정" ← 프로브를 어떻게 움직일지
|
||||
// 버튼 "1cm 측정하기" ← 움직인 뒤 어디를 재는지
|
||||
//
|
||||
// 한때 버튼을 "여기서 측정"으로 두었는데 "여기"가 어디인지 알 수
|
||||
// 없다는 피드백이 왔다(2026-09-10). 둘 다 숫자를 쓰면 서로를 확인해
|
||||
// 준다 — 카드대로 움직였으면 버튼의 숫자가 지금 자리와 맞는다.
|
||||
// 카드와 버튼이 같은 숫자를 말한다: 카드 "치골 위 1cm 에 붙이고 측정",
|
||||
// 버튼 "1cm 측정하기". 한때 버튼을 "여기서 측정"으로 두었는데 "여기"가
|
||||
// 어디인지 알 수 없다는 피드백이 왔다(2026-09-10). 둘 다 숫자를 쓰면
|
||||
// 서로를 확인해 준다 — 카드대로 붙였으면 버튼의 숫자가 지금 자리와 맞는다.
|
||||
) { Text("${cm}cm 측정하기", fontSize = 16.sp, fontWeight = FontWeight.Bold) }
|
||||
|
||||
// 수집을 중단하는 문. 두 경우를 한 버튼으로 덮는다:
|
||||
@@ -1105,7 +1102,8 @@ private fun LateralSection(
|
||||
.padding(10.dp)
|
||||
) {
|
||||
Text(
|
||||
"앞에서 1cm 올린 자리 그대로 둡니다. 아직 안 올렸으면 지금 올리세요.",
|
||||
anchorCm?.let { "치골 위 ${it}cm 에 붙인 그대로 둡니다. 아직이면 지금 치골 위 ${it}cm 에 붙이세요." }
|
||||
?: "앞에서 정한 자리 그대로 둡니다.",
|
||||
fontSize = 13.sp, fontWeight = FontWeight.SemiBold, color = MlPrimary,
|
||||
)
|
||||
}
|
||||
@@ -1244,21 +1242,23 @@ private fun RecordRow(
|
||||
}
|
||||
|
||||
/**
|
||||
* 화면에 띄울 **지시문 하나**. 위치 이름을 쓰지 않는다.
|
||||
* 화면에 띄울 **지시문 하나**. 숫자는 "치골 위 N cm" 하나뿐이고 방향은 글에 쓰지 않는다.
|
||||
*
|
||||
* 시험하는 사람이 "최적 위치"와 "부착 위치"를 계속 헷갈렸다(2026-09-09 현장). 당연하다 —
|
||||
* 둘 다 "위치"라는 이름의 숫자이고, 화면이 단계마다 다른 쪽을 크게 보여 줬다. 그런데
|
||||
* 프로브를 잡은 사람에게 필요한 것은 **지금 할 동작 하나**다. 절대 cm 은 기록의 몫이다.
|
||||
* 시험하는 사람이 "최적 위치"와 "부착 위치"를 계속 헷갈렸다(2026-09-09 현장) — 둘 다
|
||||
* "위치"라는 이름의 숫자였다. 그래서 상대 이동("2cm 내리고 측정")으로 바꿨는데 그것도
|
||||
* 헷갈렸다(2026-09-29 현장) — 판정 결과 "N cm" 옆에 "아래로 2cm" 가 붙어 다시 숫자가
|
||||
* 둘이 됐다. 치골은 손으로 짚는 기준점이라 **치골 위 절대 위치** 하나면 셀 것이 없다.
|
||||
* 화살표는 지금 자리에서 어느 쪽인지 눈으로만 거든다.
|
||||
*
|
||||
* | 상태 | 지시 |
|
||||
* |---|---|
|
||||
* | 첫 측정 전 | 치골 바로 위에 붙이고 측정 |
|
||||
* | 탐색 중 | N cm 올리고 측정 |
|
||||
* | best 를 지나침 | N cm 내리고 측정 |
|
||||
* | 확정 | 1cm 올리고 **재지 말고** 좌우로 |
|
||||
* | 재부착 | 더 아래(치골 쪽)에 다시 붙이기 |
|
||||
* | 첫 측정 전 | 치골 위 0cm 에 붙이고 측정 |
|
||||
* | 탐색 중 | 치골 위 N cm 에 붙이고 측정 |
|
||||
* | 판정된 자리로 | 치골 위 N cm 에 다시 붙이고 측정 (이미 그 자리면 "에서 한 번 더 측정") |
|
||||
* | 확정 | 치골 위 N+오프셋 cm 에 붙이세요 — **재지 말고** 좌우로 |
|
||||
* | 재부착 | 더 아래(치골 쪽)에 다시 붙이기 — 갈 자리가 없어 이것만 상대적이다 |
|
||||
*
|
||||
* @param nextCm 화면이 다음에 재려는 위치. 호출부가 판정 뒤 이미 갱신해 둔다.
|
||||
* @param nextCm 화면이 다음에 재려는 위치(치골 위 cm). 호출부가 판정 뒤 이미 갱신해 둔다.
|
||||
*/
|
||||
internal data class AlignInstruction(
|
||||
val arrow: String,
|
||||
@@ -1284,22 +1284,25 @@ internal fun instructionOf(
|
||||
needReattach: Boolean = false,
|
||||
): AlignInstruction = when {
|
||||
step == null -> AlignInstruction(
|
||||
"●", "치골 바로 위에 붙이고 측정",
|
||||
"●", "치골 위 0cm 에 붙이고 측정",
|
||||
"젤을 바르고, 프로브를 치골 바로 위에 밀착시킵니다.")
|
||||
|
||||
// 확인 측정까지 끝났다 — 올리고 좌우로. 이 자리는 재지 않는다.
|
||||
confirmDone -> AlignInstruction(
|
||||
"↑", "${offsetCm}cm 올리세요",
|
||||
"여기서는 측정하지 않습니다. 올린 뒤 좌우 맞추기로 넘어갑니다.",
|
||||
done = true)
|
||||
// 확인 측정까지 끝났다 — 오프셋 자리에 붙이고 좌우로. 그 자리는 재지 않는다.
|
||||
confirmDone -> {
|
||||
val attach = (confirmTarget ?: step.record?.cm ?: nextCm) + offsetCm
|
||||
AlignInstruction(
|
||||
"↑", "치골 위 ${attach}cm 에 붙이세요",
|
||||
"여기서는 측정하지 않습니다. 붙인 뒤 좌우 맞추기로 넘어갑니다.",
|
||||
done = true)
|
||||
}
|
||||
|
||||
// 수집 중에는 판정이 뭐라 하든 계속 올린다. 판정은 다 재고 나서 한다.
|
||||
// 수집 중에는 판정이 뭐라 하든 다음 자리로 간다. 판정은 다 재고 나서 한다.
|
||||
sweeping -> AlignInstruction(
|
||||
"↑", "1cm 올리고 측정",
|
||||
"↑", "치골 위 ${nextCm}cm 에 붙이고 측정",
|
||||
decidedAtCm?.let {
|
||||
"${AnchorConfig.SEARCH_MAX_CM}cm 까지 전부 잽니다. " +
|
||||
"0~${AnchorConfig.SEARCH_MAX_CM}cm 를 전부 잽니다. " +
|
||||
"(옛 방식이면 ${it}cm 에서 멈췄을 자리입니다 — 지금은 다 재고 판정합니다.)"
|
||||
} ?: "${AnchorConfig.SEARCH_MAX_CM}cm 까지 전부 잽니다.")
|
||||
} ?: "0~${AnchorConfig.SEARCH_MAX_CM}cm 를 전부 잽니다.")
|
||||
|
||||
// 다 쟀는데 후보가 하나도 없다.
|
||||
needReattach -> AlignInstruction(
|
||||
@@ -1307,22 +1310,22 @@ internal fun instructionOf(
|
||||
"잰 위치 중 CH3 이 제대로 잡힌 곳이 없습니다. 치골 쪽으로 내려 다시 부착한 뒤 " +
|
||||
"[처음부터 다시 정렬] 을 눌러 주세요.")
|
||||
|
||||
// 판정된 자리로 이동 → 확인 측정.
|
||||
// 판정된 자리로 이동 → 확인 측정. 화살표만 방향을 거든다.
|
||||
confirmTarget != null -> {
|
||||
val from = step.record?.cm ?: confirmTarget
|
||||
val delta = confirmTarget - from
|
||||
when {
|
||||
delta > 0 -> AlignInstruction("↑", "${delta}cm 올리고 측정",
|
||||
delta > 0 -> AlignInstruction("↑", "치골 위 ${confirmTarget}cm 에 다시 붙이고 측정",
|
||||
"잰 위치 전부로 고른 자리입니다. 여기서 확인 측정 한 번 합니다.")
|
||||
delta < 0 -> AlignInstruction("↓", "${-delta}cm 내리고 측정",
|
||||
delta < 0 -> AlignInstruction("↓", "치골 위 ${confirmTarget}cm 에 다시 붙이고 측정",
|
||||
"잰 위치 전부로 고른 자리입니다. 여기서 확인 측정 한 번 합니다.")
|
||||
else -> AlignInstruction("●", "여기서 한 번 더 측정",
|
||||
else -> AlignInstruction("●", "치골 위 ${confirmTarget}cm 에서 한 번 더 측정",
|
||||
"옮겨 온 자리의 상태를 확인하는 마지막 측정입니다.")
|
||||
}
|
||||
}
|
||||
|
||||
// 여기까지 오면 아직 한 위치도 못 쟀거나 상태가 어긋난 것이다.
|
||||
else -> AlignInstruction("↑", "1cm 올리고 측정", null)
|
||||
else -> AlignInstruction("↑", "치골 위 ${nextCm}cm 에 붙이고 측정", null)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user