From 7828bc1fe941c1fc2a57fa95c48de13c90a87ecc Mon Sep 17 00:00:00 2001 From: ykcheungab Date: Sun, 11 Oct 2026 16:44:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=98=8E=E7=A1=AE=20Autocal=20=E5=BD=95?= =?UTF-8?q?=E5=88=B6=E6=8C=89=E9=92=AE=E5=8F=8A=E4=B8=AD=E6=AD=A2=E7=BB=93?= =?UTF-8?q?=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 区分连续录制和到档标记,并验证中止重试的目录数量。相关测试与代码检查通过。 --- apps/autocal/config/locales/en_US.json | 22 ++++++++----- apps/autocal/config/locales/zh_CN.json | 24 ++++++++------ .../orisys_autocal/ui/calibration_panel.py | 12 ++++++- apps/autocal/tests/test_manual_trial.py | 32 ++++++++++++++++++- 4 files changed, 71 insertions(+), 19 deletions(-) diff --git a/apps/autocal/config/locales/en_US.json b/apps/autocal/config/locales/en_US.json index 641de98..0250ad5 100644 --- a/apps/autocal/config/locales/en_US.json +++ b/apps/autocal/config/locales/en_US.json @@ -271,17 +271,22 @@ "uv": "U / V (px)", "position": "Mesh position", "levels": "Load levels (N)", - "hold": "Suggested hold", - "reference": "Actual reference (N)", - "start": "Start trial recording", - "confirm": "Confirm current level", - "finish": "Finish and save", - "abort": "Abort and keep data", + "hold": "Planned hold", + "hold_tip": "The planned hold time is saved; levels and recording do not advance automatically.", + "reference": "Manual reference force (N)", + "start": "Record this site", + "start_tip": "Create one trial folder for this site and continuously record images and sensor output. This does not move the platform. One load-unload cycle uses this folder.", + "confirm": "Mark load reached", + "confirm_tip": "After reaching the target and entering the manual reference force, mark this level's start and begin its hold timer. Images are already recording.", + "finish": "Stop and complete", + "finish_tip": "After all levels are marked, stop recording, flush the files, and check this trial.", + "abort": "Abort this recording", + "abort_tip": "Stop recording, keep this folder, and mark it incomplete. Starting again creates a new folder; it does not resume this one.", "load": "Load", "unload": "Unload", "next_step": "Next: {branch} to {load:g} N", - "before_start": "Start trial recording first", - "ready_to_finish": "All levels confirmed; finish and save", + "before_start": "Select a site and start the input, then begin recording", + "ready_to_finish": "All levels marked; recording can be stopped", "no_step": "No step pending", "progress": "Progress {done}/{total} · {status}", "held": " · Current level held {seconds:.1f} s", @@ -293,6 +298,7 @@ "complete": "Complete", "incomplete": "Incomplete", "result": "{status}: {path}", + "incomplete_result": "This recording is incomplete; data written so far is at: {path}", "error": "Action failed: {detail}", "invalid_site": "Select a valid UV site first", "start_input": "Start camera or video input first", diff --git a/apps/autocal/config/locales/zh_CN.json b/apps/autocal/config/locales/zh_CN.json index aa5e01f..f99e92b 100644 --- a/apps/autocal/config/locales/zh_CN.json +++ b/apps/autocal/config/locales/zh_CN.json @@ -271,28 +271,34 @@ "uv": "U / V (px)", "position": "网格坐标", "levels": "加载档位 (N)", - "hold": "建议保持", - "reference": "实际参考力 (N)", - "start": "开始试验并录制", - "confirm": "确认当前档位", - "finish": "完成并保存", - "abort": "中止并保留", + "hold": "计划保持", + "hold_tip": "仅保存计划保持时间;不会自动切换档位或结束录制。", + "reference": "人工参考力 (N)", + "start": "开始本测点录制", + "start_tip": "为当前测点新建试验目录,持续录制图像与传感器输出;不会移动平台。一次加载—卸载循环共用此目录。", + "confirm": "标记到档时刻", + "confirm_tip": "达到目标载荷并填写人工参考力后点击;记录本档起点并开始保持计时。图像此前已开始持续录制。", + "finish": "结束录制并完成", + "finish_tip": "全部档位标记后停止录制、完成写盘并检查本次试验。", + "abort": "中止本次录制", + "abort_tip": "停止录制并保留当前目录,标记为未完成;再次开始会创建新目录,不会续录。", "load": "加载", "unload": "卸载", "next_step": "下一档:{branch}至 {load:g} N", - "before_start": "请先开始试验并录制", - "ready_to_finish": "全部档位已确认,请完成并保存", + "before_start": "先选测点并启动输入,再开始录制", + "ready_to_finish": "全部档位已标记,可结束录制", "no_step": "无待确认档位", "progress": "进度 {done}/{total} · {status}", "held": " · 当前档已保持 {seconds:.1f} s", "source_state": "输入:{status} · 帧 {frame} · 采集丢帧 {dropped}", "replay_note": "视频重放仅用于调试;本次人工参考力不能与原实验时间同步。", "idle": "未开始", - "recording": "记录中", + "recording": "录制中", "closing": "正在写盘", "complete": "已完成", "incomplete": "未完成", "result": "{status}:{path}", + "incomplete_result": "本次录制未完成;已写入的数据在:{path}", "error": "操作失败:{detail}", "invalid_site": "请先选择有效的 UV 测点", "start_input": "请先启动相机或视频输入", diff --git a/apps/autocal/src/orisys_autocal/ui/calibration_panel.py b/apps/autocal/src/orisys_autocal/ui/calibration_panel.py index 989d0c9..526a859 100644 --- a/apps/autocal/src/orisys_autocal/ui/calibration_panel.py +++ b/apps/autocal/src/orisys_autocal/ui/calibration_panel.py @@ -267,8 +267,13 @@ class CalibrationPanel(QWidget): previous = self.trial.status current = self.trial.poll() if current != previous and current in {"complete", "incomplete"}: + result_key = ( + "calibration.incomplete_result" + if current == "incomplete" + else "calibration.result" + ) self.result_label.setText( - t("calibration.result").format( + t(result_key).format( status=t(f"calibration.{current}"), path=self.trial.directory ) + ( @@ -355,9 +360,14 @@ class CalibrationPanel(QWidget): self.position_label.setText(t("calibration.position")) self.levels_label.setText(t("calibration.levels")) self.hold_label.setText(t("calibration.hold")) + self.hold.setToolTip(t("calibration.hold_tip")) self.reference_label.setText(t("calibration.reference")) self.start_button.setText(t("calibration.start")) + self.start_button.setToolTip(t("calibration.start_tip")) self.confirm_button.setText(t("calibration.confirm")) + self.confirm_button.setToolTip(t("calibration.confirm_tip")) self.finish_button.setText(t("calibration.finish")) + self.finish_button.setToolTip(t("calibration.finish_tip")) self.abort_button.setText(t("calibration.abort")) + self.abort_button.setToolTip(t("calibration.abort_tip")) self._sync() diff --git a/apps/autocal/tests/test_manual_trial.py b/apps/autocal/tests/test_manual_trial.py index 0978918..2b5da96 100644 --- a/apps/autocal/tests/test_manual_trial.py +++ b/apps/autocal/tests/test_manual_trial.py @@ -163,6 +163,29 @@ def test_manual_trial_records_video_stamps_and_load_unload_events(tmp_dir): assert session["sensor_model"] == "Finger D40" assert session["reference_file"] == "reference.csv" assert session["site"]["mesh_sha256"] + assert len(list(tmp_dir.glob("*/session.json"))) == 1 + + second_directory = trial.start( + root=tmp_dir, + site=site, + levels=[5, 10], + hold_s=20, + sensor_model="Finger D40", + sensor_sn="F-001", + bundle_path=str(bundle), + source={"kind": "camera", "value": 0}, + config_ref=str(config), + fps=30, + ) + worker.emit() + trial.confirm(5) + trial.finish(aborted=True, reason="operator aborted") + trial.recorder.stop(wait=True) + assert trial.poll() == "incomplete" + assert len(list(tmp_dir.glob("*/session.json"))) == 2 + assert second_directory != directory + with (second_directory / "reference.csv").open(encoding="utf-8", newline="") as handle: + assert [row["F_ref_normal_N"] for row in csv.DictReader(handle)] == ["5.0"] def test_calibration_page_keeps_precise_uv_site_when_switching_to_live_view( @@ -186,7 +209,14 @@ def test_calibration_page_keeps_precise_uv_site_when_switching_to_live_view( uv_max=(1, 1), ) panel = window.calibration_panel - assert panel.start_button.text() == t("calibration.start") + for key, button in ( + ("start", panel.start_button), + ("confirm", panel.confirm_button), + ("finish", panel.finish_button), + ("abort", panel.abort_button), + ): + assert button.text() == t(f"calibration.{key}") + assert button.toolTip() == t(f"calibration.{key}_tip") assert panel.target_label.text() == t("calibration.before_start") panel.set_flat(flat, "bundle") panel._picked(2, 1)