From 713debaf9be0f843ad1d411c51d44fed44819745 Mon Sep 17 00:00:00 2001 From: Codex Date: Fri, 28 Aug 2026 18:59:18 +0900 Subject: [PATCH] fix: clarify snapshot and calibration controls --- apps/acoustic-camera/main.js | 9 ++++++--- tests/integration/camera-ui.test.js | 9 +++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/apps/acoustic-camera/main.js b/apps/acoustic-camera/main.js index fe5b91f..fff81ed 100644 --- a/apps/acoustic-camera/main.js +++ b/apps/acoustic-camera/main.js @@ -1,4 +1,5 @@ import { evaluateDasBand, exportBandEvaluation } from "/packages/acoustics-core/evaluation.js"; +import { DEFAULT_MAX_COMPENSATION_DB } from "/packages/acoustics-core/frequency-response.js"; import { downloadJson, readJsonFile } from "/packages/contracts/io.js"; import { validateArrayDefinition, @@ -405,10 +406,12 @@ function renderAcousticSummary() { const responseCurveCount = state.arrayDefinition.microphones.filter( (microphone) => microphone.frequencyResponse?.length >= 2, ).length; + const maxCompensationDb = + state.experiment.beamforming.maxCompensationDb ?? DEFAULT_MAX_COMPENSATION_DB; const responseMode = state.experiment.beamforming.compensateFrequencyResponse === false ? "응답 역보정 꺼짐" - : "알려진 응답 역보정"; + : "알려진 응답 역보정 ≤ " + formatNumber(maxCompensationDb, 0) + " dB"; elements.acousticEnvironmentSummary.textContent = profileLabels[profile] + " · 수신점당 최대 " + maximumSparsePathsPerReceiver(state.scene) + "개 sparse path · 응답 curve " + @@ -894,7 +897,7 @@ function applyValidation(validation) { if (!state.active) { elements.runButton.disabled = !validation.valid; if (validation.valid) { - elements.runButton.textContent = state.lastRun ? "▶ 다시 실행" : "▶ 기본 예제 실행"; + elements.runButton.textContent = state.lastRun ? "▶ 다시 실행" : "▶ Snapshot 실행"; if (!state.lastRun && document.documentElement.dataset.runState === "idle") { setRunStatus( `${state.arrayDefinition.microphones.length} ch · ` + @@ -1143,7 +1146,7 @@ async function runSimulation() { activity.worker?.terminate(); if (state.active === activity) state.active = null; setConfigurationLocked(false); - elements.runButton.textContent = state.lastRun ? "▶ 다시 실행" : "▶ 기본 예제 실행"; + elements.runButton.textContent = state.lastRun ? "▶ 다시 실행" : "▶ Snapshot 실행"; renderBandEditors(); await validateCurrent(); } diff --git a/tests/integration/camera-ui.test.js b/tests/integration/camera-ui.test.js index 84bffc4..392250c 100644 --- a/tests/integration/camera-ui.test.js +++ b/tests/integration/camera-ui.test.js @@ -86,6 +86,10 @@ test("Acoustic Camera가 8×8 CPU 실행·결과 저장·stale·재실행 흐름 documentObject.querySelector("#acoustic-environment-summary").textContent.includes("sparse path"), "bounded acoustic cost is visible", ); + assert( + documentObject.querySelector("#acoustic-environment-summary").textContent.includes("≤ 24 dB"), + "safe inverse-response boost limit is visible", + ); const canvas = documentObject.querySelector("#scene-canvas"); await waitFor(() => canvas.width > 0 && canvas.height > 0, "scene canvas 초기 렌더"); @@ -103,6 +107,11 @@ test("Acoustic Camera가 8×8 CPU 실행·결과 저장·stale·재실행 흐름 !documentObject.querySelector("#run-button").disabled, "8×8 CPU 입력 검증", ); + assertEqual( + documentObject.querySelector("#run-button").textContent.trim(), + "▶ Snapshot 실행", + "snapshot label survives runtime validation", + ); assertEqual(documentObject.querySelector("#grid-preset").value, "custom", "custom grid preset"); assert( documentObject.documentElement.dataset.unsavedWork.includes("Experiment"),