Files
reducers/backend/src/physical_validators/fasteners.py
T

68 lines
2.5 KiB
Python

from __future__ import annotations
from ..models import PhysicalRelation, ValidationCheck
from .base import (
BasePhysicalRelationValidator,
PhysicalValidationContext,
add_check,
add_common_relation_checks,
relation_code,
)
class BoltedValidator(BasePhysicalRelationValidator):
relation_type = "bolted"
def validate(
self,
context: PhysicalValidationContext,
relation: PhysicalRelation,
checks: list[ValidationCheck],
) -> None:
mount_id = relation.details.get("mount")
extra = [mount_id] if isinstance(mount_id, str) else []
add_common_relation_checks(context, relation, checks, extra_components=extra)
params = context.instance.industrial_parameters
if params is None:
add_check(
checks,
section="geometry",
code=relation_code(relation, "geometry_clearance_or_fit"),
passed=False,
message="industrial parameters are required for bolted joint validation",
)
return
bolt_ids = [
component_id
for component_id in context.snapshot.manifest.components
if component_id.startswith("housing_bolt_")
]
enough_bolts = len(bolt_ids) >= params.bolt_count
bolt_circle_valid = (
params.bolt_circle_diameter_mm < params.housing_outer_diameter_mm
and params.bolt_diameter_mm < params.housing_wall_thickness_mm
)
add_check(
checks,
section="assembly",
code=relation_code(relation, "fastener_count"),
passed=enough_bolts,
message="bolted industrial joint has the rule-computed housing fastener count",
actual=len(bolt_ids),
expected=params.bolt_count,
)
add_check(
checks,
section="geometry",
code=relation_code(relation, "geometry_clearance_or_fit"),
passed=bolt_circle_valid,
message="bolt circle and bolt diameter fit within housing wall",
actual={
"bolt_circle_diameter_mm": params.bolt_circle_diameter_mm,
"housing_outer_diameter_mm": params.housing_outer_diameter_mm,
"bolt_diameter_mm": params.bolt_diameter_mm,
"housing_wall_thickness_mm": params.housing_wall_thickness_mm,
},
expected="bolt circle inside housing OD and bolt diameter < wall thickness",
)