# 输入输出说明

## 输入 JSON

复制 examples/workshop.json 即可修改。字段严格校验，未知字段报错。上限、状态和错误码的权威表见[接口契约](接口契约.md)，该表由 MoonBit 生成并由 CI 核对。

| 字段 | 含义 |
| --- | --- |
| action | analyze 或 search |
| units | 固定为 mm |
| base_radius_mm | 分析时必填，基圆半径 |
| roller_radius_mm | 正滚轮半径 |
| offset_mm | 有符号偏置 |
| rpm | 正的恒定转速 |
| resolution | 整数；分析、搜索的不同上限见[接口契约](接口契约.md) |
| pressure_limit_deg | 大于 0°且小于 90° |
| segments | 非空分段数组，每段 angle_deg、lift_mm、law；段数上限见接口契约 |
| search | 搜索时必填，lower_mm、upper_mm、intervals |
| outputs | 可选数组，points / csv / svg / dxf；默认 ["points"]，[] 仅摘要 |
| include_input | 可选布尔值，默认 false；true 时回显原始请求 |

law 为 cycloidal、345 或 4567。停歇段也保留 law 字段；lift_mm=0。单段最小角度见接口契约的 segment_angle_min，总角度一圈且总升程为零。

搜索至少一个区间，上限由 search_intervals_max 定义。包含上下界，访问位置数为区间数加一。偏置导致几何不合法的小基圆会跳过，tested 包括这些已访问位置。

## 返回结果

schema_version=2。成功为 {"ok":true,"result":{...}}，失败包含 error_code、error 和 field（可定位的字段路径，例如 segments[0].law、search.intervals；其余为 null）。invalid_input / invalid_json / input_too_large 表示输入问题，calculation_failed / internal_error 表示计算失败，check_indeterminate 表示搜索遇到无法可靠判定的几何，no_candidate 表示网格搜索结束但没有候选。输入按 UTF-8 字节限制，数值见接口契约的 input_bytes_max；CLI 从 MoonBit 导出接口读取同一限制。

ok=true 只表示成功生成报告，不保证 sampled_feasible。sampled_local_feasible 表示局部条件。crossing_check 的 status 为 complete / indeterminate / failed / not_checked；仅 complete 提供整数 count，其他状态 count 为 null，并可附错误；indeterminate 同时给出 confirmed_crossings 和 uncertain_pairs，但不承诺完整交叉计数。sampled_feasible 仅在局部通过、交叉检查完成、交叉数为零时为 true。state 为 accepted_sampled / rejected / incomplete。不再返回 -1 哨兵值。incomplete 时 false 表示未获接受，不能直接作为物理不可行结论；未知状态也必须保守处理。

sampling.nominal_resolution 是目标采样密度；actual_intervals 是实际区间数；sample_count 含重复闭合点。逐段向上取整是保留段界的有意设计，不能把目标分辨率理解为精确点数。

最小偏置因子出现的角度命名为 min_offset_factor_angle（类型化接口），JSON 为 min_offset_factor_angle_rad。它是最小裕量位置，因子为正时不应称为根切角。

points 包含角度、升程、时间导数、中心轨迹、实际轮廓、压力角、曲率和偏置因子。边界点取右侧段值；最大跃度额外检查段端点两侧，所以存在跳变时应参考汇总报告。

csv、svg、dxf 已由 MoonBit 生成。宿主保存字符串，不调用外部软件生成轮廓。

## 单位与格式

- 核心库：弧度、rad/s、统一长度单位。
- JSON 与网页：毫米、角度、rpm；时间导数单位 mm/s、mm/s²、mm/s³。
- CSV：角度为弧度，ds_dtheta 等列为角度导数；坐标为毫米，曲率为 1/mm。
- DXF：ASCII R2000，INSUNITS=4，闭合 LWPOLYLINE；省略重复末点，通过闭合标志连接首尾。
- SVG：翻转 y 显示方向；轮廓不依赖字体。

## CLI 与网页

```sh
node bin/mooncam.mjs INPUT.json [--out DIRECTORY]
```

不指定目录时输出摘要；指定目录后保存固定文件名，同名文件会覆盖，应为不同设计选择不同目录。report.json 只含检查摘要和 files 文件引用，不内嵌三个导出文件，也不重复保存点数组；应用参数覆盖后的实际输入单独写入 input.json。API 仅在 outputs 请求相应格式时生成其内容。

网页需先构建，再运行 npm run serve。服务只监听本机 127.0.0.1。直接双击 HTML 无法正常加载模块和 Worker。

网页优先由 Worker 本地计算，20 秒超时会终止并重建引擎。没有模块 Worker 时会提示进入主线程兼容模式，此模式不能强制中断计算。参数修改时提示现有结果仍对应上次计算；开始新计算时清除旧输出。目前没有启用公开网页托管。

退出码：0 采样通过；2 采样拒绝；3 搜索无候选；4 检查未完成；1 输入或运行错误。搜索无候选不证明连续参数空间无解。

浏览器初次计算只请求点数据和 SVG；CSV、DXF 在点击下载时由 MoonBit Session 从已保存的点数组生成，不再重新运行分析或搜索。可通过 include_input=true 获取输入副本，默认响应不会回显。

## 库层上限与兼容字段

MoonBit 的 `sample`、`measure`、`analyze` 与 JSON、搜索采用不同的名义分辨率上限，统一数值表见[接口契约](接口契约.md)。JSON 的较低上限控制响应和宿主成本，搜索还需要更细网格复核。`sample_count` 顶层字段暂时保留用于兼容，新增调用方建议读取 `sampling.sample_count`。

## CLI 批量和参数覆盖

```sh
node bin/mooncam.mjs --version
node bin/mooncam.mjs - --rpm 120 --resolution 1440
node bin/mooncam.mjs examples/workshop.json examples/pressure-limit.json --out artifacts/batch
```

`-` 从标准输入读取一个 JSON，按同一 UTF-8 字节上限流式限制。多个输入顺序处理，标准输出为逐行 JSON；导出分别放入带序号的独立子目录。支持 `--rpm`、`--resolution`、`--base-radius`、`--pressure-limit`，数值业务规则仍由 MoonBit 校验。单个文件失败不阻止后续文件。批量退出码按输入/运行错误、检查未完成、搜索无候选、采样拒绝、通过的顺序取最高严重度。

## 会话导出

类型化 `Session::run` 与无状态 `run_json` 返回相同计算结果。会话保存最近请求的点数据，`Session::export_profile` 按需导出。请求失败后旧缓存失效，不能误下载先前结果。宿主必须为独立用户或任务创建独立 Session；网页桥接实例仅服务当前页面的单一顺序请求。

## 稳定分类与字段定位

基础 MoonBit 函数仍保留 Result[T, String]；其消息供人阅读，宿主不得靠字符串解析分类。JSON 的 error_code 由 ErrorCode 定义，CLI 的错误和结果退出码均使用 MoonBit 映射。参数类型、范围、单字段关系尽量返回 field；程序整体角度/升程闭合错误定位为 segments。

输入通过校验后发生导数溢出等数值失败，返回 calculation_failed。分析时拓扑本身失败保留在 result.crossing_check，整体是 incomplete；搜索中检查失败中止搜索，返回 calculation_failed，几何不确定则返回 check_indeterminate。完整区别见[错误码表](接口契约.md)。

## 可选诊断与采样比较

成功分析报告默认包含 `diagnostics`、`segments`、`crossing_evidence`；点表在保留原字段的同时增加 `sample_index` 与 `segment_index`。`compare_sampling` 为可选布尔请求字段，默认 false；设为 true 后结果增加 `sampling_comparison`。相关字段、单位、段界及闭合点规则见[接口契约](接口契约.md)，操作示例见[位置、诊断与采样比较](位置诊断与采样比较.md)。已有综合状态和退出码不变。
