diff --git a/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt b/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt index 0a8923e..8987557 100644 --- a/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt +++ b/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt @@ -151,7 +151,8 @@ fun PiezoMonitoringView(appState: AppState) { var totalWallCount = 0 val validChannels = channels.filter { it.isValid } - if (validChannels.isNotEmpty()) { + val allChannelsReceived = channels.filter { it.buffer.size >= 20 }.size >= 6 + if (validChannels.isNotEmpty() && allChannelsReceived) { val method = com.example.medilightv2android.managers.GreenZoneConstants.detectionMethod val analyzerA = com.example.medilightv2android.managers.PiezoEchoAnalyzerA.shared @@ -287,18 +288,20 @@ fun PiezoMonitoringView(appState: AppState) { handler.post { if (finalRawVol != null && finalRawVol > 0) { if (isAutoMeasuring) { - if (finalTotalWalls >= 4) { + if (allChannelsReceived) { autoVolumeWindow.add(finalRawVol) - Log.d("PiezoMonitor", "AUTO window[${autoVolumeWindow.size}/$autoWindowSize] +${"%.1f".format(finalRawVol)}ml (valid=$finalTotalWalls)") + // 슬라이딩 윈도우: 오래된 값 제거 + while (autoVolumeWindow.size > autoWindowSize) autoVolumeWindow.removeAt(0) + Log.d("PiezoMonitor", "AUTO window[${autoVolumeWindow.size}/$autoWindowSize] +${"%.1f".format(finalRawVol)}ml") } else { - Log.d("PiezoMonitor", "AUTO skip ${"%.1f".format(finalRawVol)}ml (valid=$finalTotalWalls < 4)") + Log.d("PiezoMonitor", "AUTO skip ${"%.1f".format(finalRawVol)}ml (channels incomplete)") } - if (autoVolumeWindow.size >= autoWindowSize) { + // 윈도우에 5개 이상이면 매번 trimmed mean 업데이트 + if (autoVolumeWindow.size >= 5) { val displayVol = trimmedMean(autoVolumeWindow.toList()) lastVolumeMl = displayVol maxVolumeMl = maxOf(maxVolumeMl, displayVol) Log.d("PiezoMonitor", "AUTO trimmedMean=${"%.1f".format(displayVol)}ml from ${autoVolumeWindow.map { "%.0f".format(it) }}") - autoVolumeWindow.clear() } } else { lastVolumeMl = finalRawVol @@ -753,20 +756,20 @@ fun PiezoMonitoringView(appState: AppState) { ) // Donut chart with Bladdy - val donutSize = if (isCompact) 180.dp else 240.dp + val donutSize = if (isCompact) 220.dp else 280.dp Box(contentAlignment = Alignment.Center) { DonutChartView( progress = appState.bladderLevel.progress, urgency = urgency, - lineWidth = if (isCompact) 20.dp else 28.dp, + lineWidth = if (isCompact) 22.dp else 30.dp, size = donutSize ) Column(horizontalAlignment = Alignment.CenterHorizontally) { - BladdyRiveView(urgency = urgency, size = if (isCompact) 70.dp else 100.dp) + BladdyRiveView(urgency = urgency, size = if (isCompact) 80.dp else 110.dp) Spacer(modifier = Modifier.height(4.dp)) Text( - if (maxVolumeMl > 0) "${"%.0f".format(maxVolumeMl)} ml" else "${appState.estimatedVolume} ml", - fontSize = 16.sp, + if (lastVolumeMl > 0) "${"%.0f".format(lastVolumeMl)} ml" else "${appState.estimatedVolume} ml", + fontSize = 18.sp, fontWeight = FontWeight.Bold, color = urgency.accentColor, modifier = Modifier @@ -778,12 +781,15 @@ fun PiezoMonitoringView(appState: AppState) { } } - // Info cards + // Info cards (Fill/Level은 maxVolume 기준) + val maxVol = appState.piezoSettings.maxVolume.toDouble() + val fillPct = if (maxVol > 0 && lastVolumeMl > 0) (lastVolumeMl / maxVol * 100).coerceAtMost(100.0) else 0.0 + val levelVal = if (maxVol > 0 && lastVolumeMl > 0) ((lastVolumeMl / maxVol) * BladderLevel.MAX_LEVEL).toInt().coerceIn(0, BladderLevel.MAX_LEVEL) else 0 Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) { - val displayVol = if (lastVolumeMl > 0) "%.0f".format(lastVolumeMl) else "${appState.estimatedVolume}" + val displayVol = if (lastVolumeMl > 0) "%.0f".format(lastVolumeMl) else "—" InfoCard("Volume", displayVol, "ml", urgency.accentColor, Modifier.weight(1f)) - InfoCard("Fill", String.format("%.0f", appState.fillPercentage), "%", urgency.accentColor, Modifier.weight(1f)) - InfoCard("Level", "${appState.bladderLevel.currentLevel}/${BladderLevel.MAX_LEVEL}", "", urgency.accentColor, Modifier.weight(1f)) + InfoCard("Fill", if (fillPct > 0) "%.0f".format(fillPct) else "—", "%", urgency.accentColor, Modifier.weight(1f)) + InfoCard("Level", if (levelVal > 0) "$levelVal/${BladderLevel.MAX_LEVEL}" else "—", "", urgency.accentColor, Modifier.weight(1f)) } // Control buttons: Void/Catheterize / Auto / Spot