///|
const Schema_version : Int32 = 2
///|
const Resolution_min : Int32 = 36
///|
const Library_resolution_max : Int32 = 20000
///|
const Json_resolution_max : Int32 = 4000
///|
const Search_refinement : Int32 = 2
///|
const Search_resolution_max : Int32 = Json_resolution_max / Search_refinement
///|
const Segments_max : Int32 = 128
///|
const Search_intervals_max : Int32 = 256
///|
const Profile_points_min : Int32 = 4
///|
const Profile_points_max : Int32 = 25000
///|
const Crossing_pair_budget : Int32 = 4000000
///|
const Input_bytes_max : Int32 = 200000
///|
const Geometry_length_max : Double = 1.0e6
///|
const Base_radius_min : Double = 1.0e-6
///|
const Segment_angle_min : Double = 1.0e-6
///|
const Coordinate_max : Double = 1.0e150
///|
const Closure_relative_tolerance : Double = 1.0e-10
///|
const Offset_factor_min : Double = 1.0e-6
///|
const Crossing_witnesses_max : Int32 = 32
///|
const Comparison_levels_max : Int32 = 4
///|
/// Stable wire categories. Human-readable error messages are not an API.
pub(all) enum ErrorCode {
InvalidJson
InvalidRequest
InputTooLarge
CalculationFailed
CheckIndeterminate
NoCandidateFound
InternalError
NoResult
}
///|
pub fn ErrorCode::code(self : ErrorCode) -> String {
match self {
InvalidJson => "invalid_json"
InvalidRequest => "invalid_input"
InputTooLarge => "input_too_large"
CalculationFailed => "calculation_failed"
CheckIndeterminate => "check_indeterminate"
NoCandidateFound => "no_candidate"
InternalError => "internal_error"
NoResult => "no_result"
}
}
///|
pub fn ErrorCode::exit_code(self : ErrorCode) -> Int32 {
match self {
CheckIndeterminate => 4
NoCandidateFound => 3
_ => 1
}
}
///|
/// Host fallback: unknown error codes are errors, never successful completion.
pub fn error_exit_code(code : String) -> Int32 {
for item in error_codes() {
if item.code() == code {
return item.exit_code()
}
}
1
}
///|
fn error_codes() -> Array[ErrorCode] {
[
InvalidJson,
InvalidRequest,
InputTooLarge,
CalculationFailed,
CheckIndeterminate,
NoCandidateFound,
InternalError,
NoResult,
]
}
///|
pub fn CrossingCheck::status(self : CrossingCheck) -> String {
match self {
NotChecked => "not_checked"
Checked(_) => "complete"
Indeterminate(_, _) => "indeterminate"
Failed(_) => "failed"
}
}
///|
/// Includes topology completion; an uncertain local pass is still incomplete.
pub fn Analysis::state(self : Analysis) -> String {
result_state(self.sampled_local_feasible, self.crossings)
}
///|
fn result_state(local_ok : Bool, check : CrossingCheck) -> String {
match check {
Checked(_) =>
if sampled_acceptance(local_ok, check) {
"accepted_sampled"
} else {
"rejected"
}
_ => "incomplete"
}
}
///|
pub fn result_exit_code(state : String) -> Int32 {
match state {
"accepted_sampled" => 0
"rejected" => 2
"incomplete" => 4
_ => 1
}
}
///|
/// Machine-readable source for checked-in contract documentation.
pub fn contract_json() -> String {
let value : Json = {
"schema_version": Json(Schema_version),
"generator": generator_json(),
"limits": {
"resolution_min": Json(Resolution_min),
"library_resolution_max": Json(Library_resolution_max),
"json_resolution_max": Json(Json_resolution_max),
"search_resolution_max": Json(Search_resolution_max),
"search_refinement": Json(Search_refinement),
"segments_max": Json(Segments_max),
"search_intervals_max": Json(Search_intervals_max),
"profile_points_min": Json(Profile_points_min),
"profile_points_max": Json(Profile_points_max),
"crossing_pair_budget": Json(Crossing_pair_budget),
"input_bytes_max": Json(Input_bytes_max),
"base_radius_min": Json(Base_radius_min),
"geometry_length_max": Json(Geometry_length_max),
"coordinate_max": Json(Coordinate_max),
"segment_angle_min": Json(Segment_angle_min),
"closure_relative_tolerance": Json(Closure_relative_tolerance),
"offset_factor_min": Json(Offset_factor_min),
"crossing_witnesses_max": Json(Crossing_witnesses_max),
"comparison_levels_max": Json(Comparison_levels_max),
},
"errors": Json(
error_codes().map(fn(item) {
{ "code": Json(item.code()), "exit_code": Json(item.exit_code()) }
}),
),
"result_states": Json(
[
result_state(true, Checked(0)),
result_state(false, Checked(0)),
result_state(true, NotChecked),
].map(fn(state) {
{ "state": Json(state), "exit_code": Json(result_exit_code(state)) }
}),
),
"crossing_states": Json(
[NotChecked, Checked(0), Indeterminate(0, 1), Failed("")].map(fn(check) {
Json(check.status())
}),
),
"position_contract": {
"index_base": 0,
"segment_intervals": "left_closed_right_open",
"periodic_endpoint_segment": 0,
"edge_definition": "edge i joins samples i and i+1; N+1 closed samples have N edges",
"index_scope": "sample and edge indices belong to one sampling result; never compare across levels",
"fields": {
"sample_index": "采样点的零基下标;纯角度查询为 null,不隐含最近采样点。",
"segment_index": "程序段的零基下标;段界归右侧段,网页展示段号时加一。",
"theta_rad": "本圈角度(弧度),闭合点保留 2π。",
"segment_start_rad": "所属程序段的起始角度(弧度)。",
"segment_end_rad": "所属程序段的结束角度(弧度)。",
"law": "所属段的规律:cycloidal、345 或 4567。",
"periodic_endpoint": "是否为 2π 周期端点;运动值和点归首段,最后一条边仍归末段。",
"edge_index": "边的零基下标,连接点 i 与 i+1。",
"start": "边起点的位置,含该采样点下标。",
"end": "边终点的位置;段界终点可属于下一段。",
},
},
"diagnostic_contract": {
"reason_codes": [
"pressure_limit_exceeded", "offset_factor_rejected", "profile_crossings",
"geometry_indeterminate", "geometry_failed", "geometry_not_checked",
],
"witness_kinds": [
"proper_crossing", "uncertain_contact", "adjacent_reversal",
],
"fields": {
"diagnostics": "局部约束的数值、阈值、余量、通过状态、位置及综合原因码。",
"margin": "压力角为 limit-value;偏置因子为 value-limit;正数表示有余量,不是安全认证。",
"comparison": "压力角允许等于上限;偏置因子必须严格大于阈值。",
"crossing_evidence": "最多保留指定数量的边对,数量达到上限后仍继续统计全部交叉与不确定对。",
"witnesses": "含 kind、edge_a、edge_b;每条边附位置和端点坐标,不计算或声称精确交点。",
"truncated": "是否存在未保留的证据;空证据不能单独证明检查完成。",
"compare_sampling": "可选布尔请求字段,默认 false;true 为最终机构尺寸执行三档完整采样检查。",
"sampling_comparison": "每档拥有独立点号和边号;包含最差位置、局部余量、拓扑状态和综合状态。",
"last_pressure_change_deg": "最后两档最大压力角的绝对差(度),不是误差界。",
"last_offset_factor_change": "最后两档最小偏置因子的绝对差,不是误差界。",
"state_consistent": "各档综合状态是否相同;即使全部 incomplete 也可为 true,不代表通过。",
},
},
}
value.stringify()
}
///|
/// Coordinates must already be finite and bounded. No world-origin tolerance.
fn profile_closed(points : Array[CamPoint]) -> Bool {
let first = points[0]
let last = points[points.length() - 1]
let mut min_x = first.x
let mut max_x = first.x
let mut min_y = first.y
let mut max_y = first.y
for p in points {
min_x = min_x.min(p.x)
max_x = max_x.max(p.x)
min_y = min_y.min(p.y)
max_y = max_y.max(p.y)
}
let span = (max_x - min_x).max(max_y - min_y)
if span == 0.0 {
return first.x == last.x && first.y == last.y
}
@math.hypot((first.x - last.x) / span, (first.y - last.y) / span) <=
Closure_relative_tolerance
}