# GENERATED FILE -- DO NOT EDIT BY HAND.
# Source:      schema/a7p.schema.json
# Regenerate:  python scripts/compile.py --python
# fastjsonschema version used to generate this file: 2.21.2

VERSION = "2.21.2"
from decimal import Decimal
from fastjsonschema import JsonSchemaValueException


NoneType = type(None)

def validate_https___a7p_cross_schema_a7p_schema_json(data, custom_formats={}, name_prefix=None):
    validate_https___a7p_cross_schema_a7p_schema_json___defs_payload(data, custom_formats, (name_prefix or "data") + "")
    return data

def validate_https___a7p_cross_schema_a7p_schema_json___defs_payload(data, custom_formats={}, name_prefix=None):
    if not isinstance(data, (dict)):
        raise JsonSchemaValueException("" + (name_prefix or "data") + " must be object", value=data, name="" + (name_prefix or "data") + "", definition={'type': 'object', 'additionalProperties': False, 'required': ['profile'], 'properties': {'profile': {'type': 'object', 'additionalProperties': False, 'required': ['profile_name', 'cartridge_name', 'bullet_name', 'short_name_top', 'short_name_bot', 'caliber', 'device_uuid', 'user_note', 'zero_x', 'zero_y', 'sc_height', 'r_twist', 'twist_dir', 'c_muzzle_velocity', 'c_zero_temperature', 'c_t_coeff', 'c_zero_distance_idx', 'c_zero_air_temperature', 'c_zero_air_pressure', 'c_zero_air_humidity', 'c_zero_w_pitch', 'c_zero_p_temperature', 'b_diameter', 'b_weight', 'b_length', 'bc_type', 'switches', 'distances', 'coef_rows'], 'properties': {'profile_name': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'cartridge_name': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'bullet_name': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'short_name_top': {'type': 'string', 'minLength': 1, 'maxLength': 8}, 'short_name_bot': {'type': 'string', 'minLength': 1, 'maxLength': 8}, 'caliber': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'device_uuid': {'type': 'string', 'maxLength': 50}, 'user_note': {'type': 'string', 'maxLength': 1024}, 'zero_x': {'type': 'integer', 'minimum': -200000, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'click'}, 'zero_y': {'type': 'integer', 'minimum': -200000, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'click'}, 'sc_height': {'type': 'integer', 'minimum': -5000, 'maximum': 5000, 'x-fraction-digits': 0, 'x-unit': 'mm'}, 'r_twist': {'type': 'integer', 'minimum': 0, 'maximum': 10000, 'x-fraction-digits': 2, 'x-unit': 'in/turn'}, 'twist_dir': {'$ref': '#/$defs/TwistDir'}, 'c_muzzle_velocity': {'type': 'integer', 'minimum': 100, 'maximum': 30000, 'x-fraction-digits': 1, 'x-ui-fraction-digits': 0, 'x-unit': 'm/s', 'x-fixed': "dart's A7pValidator checked minimum 10 instead of 100 (its own A7pFieldConstraints.muzzleVelocity implies raw min 100: 10.0 * 10^1) -- fixed."}, 'c_zero_temperature': {'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, 'c_t_coeff': {'type': 'integer', 'minimum': 0, 'maximum': 5000, 'x-fraction-digits': 3, 'x-unit': '%/15°C'}, 'c_zero_distance_idx': {'type': 'integer', 'minimum': 0, 'maximum': 255, 'x-fraction-digits': 0, 'description': "Index into 'distances'.", 'x-discrepancy': "dart's A7pValidator instead bounds this dynamically by len(distances)-1 rather than a fixed 255 -- a cross-field constraint plain JSON Schema can't express without a custom keyword/extension. profile.clj / py / js all use the static 0-255 range encoded here."}, 'c_zero_air_temperature': {'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, 'c_zero_air_pressure': {'type': 'integer', 'minimum': 3000, 'maximum': 15000, 'x-fraction-digits': 1, 'x-ui-fraction-digits': 0, 'x-unit': 'hPa'}, 'c_zero_air_humidity': {'type': 'integer', 'minimum': 0, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '%'}, 'c_zero_w_pitch': {'type': 'integer', 'minimum': -90, 'maximum': 90, 'x-fraction-digits': 0, 'x-unit': '°', 'x-fixed': "dart's A7pValidator did not check this field at all (present in A7pFieldConstraints but missing from _validateProfile) -- check added."}, 'c_zero_p_temperature': {'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, 'b_diameter': {'type': 'integer', 'minimum': 1, 'maximum': 50000, 'x-fraction-digits': 3, 'x-unit': 'in'}, 'b_weight': {'type': 'integer', 'minimum': 10, 'maximum': 65535, 'x-fraction-digits': 1, 'x-unit': 'gr', 'x-fixed': "dart's A7pValidator checked minimum 1 instead of 10 (its own A7pFieldConstraints.bulletWeight implies raw min 10: 1.0 * 10^1) -- fixed."}, 'b_length': {'type': 'integer', 'minimum': 10, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'in', 'x-fixed': "dart's A7pValidator used min 0 instead of 10 -- fixed. js validate.ts used min 1 instead of 10 -- fixed."}, 'bc_type': {'$ref': '#/$defs/BcType'}, 'switches': {'type': 'array', 'minItems': 4, 'items': {'$ref': '#/$defs/SwitchProps'}}, 'distances': {'type': 'array', 'minItems': 1, 'maxItems': 200, 'items': {'type': 'integer', 'minimum': 100, 'maximum': 300000, 'x-fraction-digits': 2, 'x-ui-fraction-digits': 0, 'x-unit': 'm'}}, 'coef_rows': {'type': 'array', 'minItems': 1, 'items': {'$ref': '#/$defs/CoefRow'}, 'x-unique-except-zero': 'mv', 'description': "Not expressible in plain JSON Schema: all 'mv' values must be unique except that any number of rows may have mv == 0. Enforce with one small hand-written check per language, run against schema/fixtures/ to keep behavior in sync.", 'if': {'properties': {'bc_type': {'const': 'CUSTOM'}}}, 'then': {'maxItems': 200, 'items': {'properties': {'mv': {'maximum': 100000}}}}, 'else': {'maxItems': 5, 'items': {'properties': {'mv': {'maximum': 30000}}}}}}}}}, rule='type')
    data_is_dict = isinstance(data, dict)
    if data_is_dict:
        data__missing_keys = set(['profile']) - data.keys()
        if data__missing_keys:
            raise JsonSchemaValueException("" + (name_prefix or "data") + " must contain " + (str(sorted(data__missing_keys)) + " properties"), value=data, name="" + (name_prefix or "data") + "", definition={'type': 'object', 'additionalProperties': False, 'required': ['profile'], 'properties': {'profile': {'type': 'object', 'additionalProperties': False, 'required': ['profile_name', 'cartridge_name', 'bullet_name', 'short_name_top', 'short_name_bot', 'caliber', 'device_uuid', 'user_note', 'zero_x', 'zero_y', 'sc_height', 'r_twist', 'twist_dir', 'c_muzzle_velocity', 'c_zero_temperature', 'c_t_coeff', 'c_zero_distance_idx', 'c_zero_air_temperature', 'c_zero_air_pressure', 'c_zero_air_humidity', 'c_zero_w_pitch', 'c_zero_p_temperature', 'b_diameter', 'b_weight', 'b_length', 'bc_type', 'switches', 'distances', 'coef_rows'], 'properties': {'profile_name': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'cartridge_name': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'bullet_name': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'short_name_top': {'type': 'string', 'minLength': 1, 'maxLength': 8}, 'short_name_bot': {'type': 'string', 'minLength': 1, 'maxLength': 8}, 'caliber': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'device_uuid': {'type': 'string', 'maxLength': 50}, 'user_note': {'type': 'string', 'maxLength': 1024}, 'zero_x': {'type': 'integer', 'minimum': -200000, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'click'}, 'zero_y': {'type': 'integer', 'minimum': -200000, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'click'}, 'sc_height': {'type': 'integer', 'minimum': -5000, 'maximum': 5000, 'x-fraction-digits': 0, 'x-unit': 'mm'}, 'r_twist': {'type': 'integer', 'minimum': 0, 'maximum': 10000, 'x-fraction-digits': 2, 'x-unit': 'in/turn'}, 'twist_dir': {'$ref': '#/$defs/TwistDir'}, 'c_muzzle_velocity': {'type': 'integer', 'minimum': 100, 'maximum': 30000, 'x-fraction-digits': 1, 'x-ui-fraction-digits': 0, 'x-unit': 'm/s', 'x-fixed': "dart's A7pValidator checked minimum 10 instead of 100 (its own A7pFieldConstraints.muzzleVelocity implies raw min 100: 10.0 * 10^1) -- fixed."}, 'c_zero_temperature': {'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, 'c_t_coeff': {'type': 'integer', 'minimum': 0, 'maximum': 5000, 'x-fraction-digits': 3, 'x-unit': '%/15°C'}, 'c_zero_distance_idx': {'type': 'integer', 'minimum': 0, 'maximum': 255, 'x-fraction-digits': 0, 'description': "Index into 'distances'.", 'x-discrepancy': "dart's A7pValidator instead bounds this dynamically by len(distances)-1 rather than a fixed 255 -- a cross-field constraint plain JSON Schema can't express without a custom keyword/extension. profile.clj / py / js all use the static 0-255 range encoded here."}, 'c_zero_air_temperature': {'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, 'c_zero_air_pressure': {'type': 'integer', 'minimum': 3000, 'maximum': 15000, 'x-fraction-digits': 1, 'x-ui-fraction-digits': 0, 'x-unit': 'hPa'}, 'c_zero_air_humidity': {'type': 'integer', 'minimum': 0, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '%'}, 'c_zero_w_pitch': {'type': 'integer', 'minimum': -90, 'maximum': 90, 'x-fraction-digits': 0, 'x-unit': '°', 'x-fixed': "dart's A7pValidator did not check this field at all (present in A7pFieldConstraints but missing from _validateProfile) -- check added."}, 'c_zero_p_temperature': {'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, 'b_diameter': {'type': 'integer', 'minimum': 1, 'maximum': 50000, 'x-fraction-digits': 3, 'x-unit': 'in'}, 'b_weight': {'type': 'integer', 'minimum': 10, 'maximum': 65535, 'x-fraction-digits': 1, 'x-unit': 'gr', 'x-fixed': "dart's A7pValidator checked minimum 1 instead of 10 (its own A7pFieldConstraints.bulletWeight implies raw min 10: 1.0 * 10^1) -- fixed."}, 'b_length': {'type': 'integer', 'minimum': 10, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'in', 'x-fixed': "dart's A7pValidator used min 0 instead of 10 -- fixed. js validate.ts used min 1 instead of 10 -- fixed."}, 'bc_type': {'$ref': '#/$defs/BcType'}, 'switches': {'type': 'array', 'minItems': 4, 'items': {'$ref': '#/$defs/SwitchProps'}}, 'distances': {'type': 'array', 'minItems': 1, 'maxItems': 200, 'items': {'type': 'integer', 'minimum': 100, 'maximum': 300000, 'x-fraction-digits': 2, 'x-ui-fraction-digits': 0, 'x-unit': 'm'}}, 'coef_rows': {'type': 'array', 'minItems': 1, 'items': {'$ref': '#/$defs/CoefRow'}, 'x-unique-except-zero': 'mv', 'description': "Not expressible in plain JSON Schema: all 'mv' values must be unique except that any number of rows may have mv == 0. Enforce with one small hand-written check per language, run against schema/fixtures/ to keep behavior in sync.", 'if': {'properties': {'bc_type': {'const': 'CUSTOM'}}}, 'then': {'maxItems': 200, 'items': {'properties': {'mv': {'maximum': 100000}}}}, 'else': {'maxItems': 5, 'items': {'properties': {'mv': {'maximum': 30000}}}}}}}}}, rule='required')
        data_keys = set(data.keys())
        if "profile" in data_keys:
            data_keys.remove("profile")
            data__profile = data["profile"]
            validate_https___a7p_cross_schema_a7p_schema_json___defs_profile(data__profile, custom_formats, (name_prefix or "data") + ".profile")
        if data_keys:
            raise JsonSchemaValueException("" + (name_prefix or "data") + " must not contain "+str(data_keys)+" properties", value=data, name="" + (name_prefix or "data") + "", definition={'type': 'object', 'additionalProperties': False, 'required': ['profile'], 'properties': {'profile': {'type': 'object', 'additionalProperties': False, 'required': ['profile_name', 'cartridge_name', 'bullet_name', 'short_name_top', 'short_name_bot', 'caliber', 'device_uuid', 'user_note', 'zero_x', 'zero_y', 'sc_height', 'r_twist', 'twist_dir', 'c_muzzle_velocity', 'c_zero_temperature', 'c_t_coeff', 'c_zero_distance_idx', 'c_zero_air_temperature', 'c_zero_air_pressure', 'c_zero_air_humidity', 'c_zero_w_pitch', 'c_zero_p_temperature', 'b_diameter', 'b_weight', 'b_length', 'bc_type', 'switches', 'distances', 'coef_rows'], 'properties': {'profile_name': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'cartridge_name': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'bullet_name': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'short_name_top': {'type': 'string', 'minLength': 1, 'maxLength': 8}, 'short_name_bot': {'type': 'string', 'minLength': 1, 'maxLength': 8}, 'caliber': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'device_uuid': {'type': 'string', 'maxLength': 50}, 'user_note': {'type': 'string', 'maxLength': 1024}, 'zero_x': {'type': 'integer', 'minimum': -200000, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'click'}, 'zero_y': {'type': 'integer', 'minimum': -200000, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'click'}, 'sc_height': {'type': 'integer', 'minimum': -5000, 'maximum': 5000, 'x-fraction-digits': 0, 'x-unit': 'mm'}, 'r_twist': {'type': 'integer', 'minimum': 0, 'maximum': 10000, 'x-fraction-digits': 2, 'x-unit': 'in/turn'}, 'twist_dir': {'$ref': '#/$defs/TwistDir'}, 'c_muzzle_velocity': {'type': 'integer', 'minimum': 100, 'maximum': 30000, 'x-fraction-digits': 1, 'x-ui-fraction-digits': 0, 'x-unit': 'm/s', 'x-fixed': "dart's A7pValidator checked minimum 10 instead of 100 (its own A7pFieldConstraints.muzzleVelocity implies raw min 100: 10.0 * 10^1) -- fixed."}, 'c_zero_temperature': {'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, 'c_t_coeff': {'type': 'integer', 'minimum': 0, 'maximum': 5000, 'x-fraction-digits': 3, 'x-unit': '%/15°C'}, 'c_zero_distance_idx': {'type': 'integer', 'minimum': 0, 'maximum': 255, 'x-fraction-digits': 0, 'description': "Index into 'distances'.", 'x-discrepancy': "dart's A7pValidator instead bounds this dynamically by len(distances)-1 rather than a fixed 255 -- a cross-field constraint plain JSON Schema can't express without a custom keyword/extension. profile.clj / py / js all use the static 0-255 range encoded here."}, 'c_zero_air_temperature': {'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, 'c_zero_air_pressure': {'type': 'integer', 'minimum': 3000, 'maximum': 15000, 'x-fraction-digits': 1, 'x-ui-fraction-digits': 0, 'x-unit': 'hPa'}, 'c_zero_air_humidity': {'type': 'integer', 'minimum': 0, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '%'}, 'c_zero_w_pitch': {'type': 'integer', 'minimum': -90, 'maximum': 90, 'x-fraction-digits': 0, 'x-unit': '°', 'x-fixed': "dart's A7pValidator did not check this field at all (present in A7pFieldConstraints but missing from _validateProfile) -- check added."}, 'c_zero_p_temperature': {'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, 'b_diameter': {'type': 'integer', 'minimum': 1, 'maximum': 50000, 'x-fraction-digits': 3, 'x-unit': 'in'}, 'b_weight': {'type': 'integer', 'minimum': 10, 'maximum': 65535, 'x-fraction-digits': 1, 'x-unit': 'gr', 'x-fixed': "dart's A7pValidator checked minimum 1 instead of 10 (its own A7pFieldConstraints.bulletWeight implies raw min 10: 1.0 * 10^1) -- fixed."}, 'b_length': {'type': 'integer', 'minimum': 10, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'in', 'x-fixed': "dart's A7pValidator used min 0 instead of 10 -- fixed. js validate.ts used min 1 instead of 10 -- fixed."}, 'bc_type': {'$ref': '#/$defs/BcType'}, 'switches': {'type': 'array', 'minItems': 4, 'items': {'$ref': '#/$defs/SwitchProps'}}, 'distances': {'type': 'array', 'minItems': 1, 'maxItems': 200, 'items': {'type': 'integer', 'minimum': 100, 'maximum': 300000, 'x-fraction-digits': 2, 'x-ui-fraction-digits': 0, 'x-unit': 'm'}}, 'coef_rows': {'type': 'array', 'minItems': 1, 'items': {'$ref': '#/$defs/CoefRow'}, 'x-unique-except-zero': 'mv', 'description': "Not expressible in plain JSON Schema: all 'mv' values must be unique except that any number of rows may have mv == 0. Enforce with one small hand-written check per language, run against schema/fixtures/ to keep behavior in sync.", 'if': {'properties': {'bc_type': {'const': 'CUSTOM'}}}, 'then': {'maxItems': 200, 'items': {'properties': {'mv': {'maximum': 100000}}}}, 'else': {'maxItems': 5, 'items': {'properties': {'mv': {'maximum': 30000}}}}}}}}}, rule='additionalProperties')
    return data

def validate_https___a7p_cross_schema_a7p_schema_json___defs_profile(data, custom_formats={}, name_prefix=None):
    if not isinstance(data, (dict)):
        raise JsonSchemaValueException("" + (name_prefix or "data") + " must be object", value=data, name="" + (name_prefix or "data") + "", definition={'type': 'object', 'additionalProperties': False, 'required': ['profile_name', 'cartridge_name', 'bullet_name', 'short_name_top', 'short_name_bot', 'caliber', 'device_uuid', 'user_note', 'zero_x', 'zero_y', 'sc_height', 'r_twist', 'twist_dir', 'c_muzzle_velocity', 'c_zero_temperature', 'c_t_coeff', 'c_zero_distance_idx', 'c_zero_air_temperature', 'c_zero_air_pressure', 'c_zero_air_humidity', 'c_zero_w_pitch', 'c_zero_p_temperature', 'b_diameter', 'b_weight', 'b_length', 'bc_type', 'switches', 'distances', 'coef_rows'], 'properties': {'profile_name': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'cartridge_name': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'bullet_name': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'short_name_top': {'type': 'string', 'minLength': 1, 'maxLength': 8}, 'short_name_bot': {'type': 'string', 'minLength': 1, 'maxLength': 8}, 'caliber': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'device_uuid': {'type': 'string', 'maxLength': 50}, 'user_note': {'type': 'string', 'maxLength': 1024}, 'zero_x': {'type': 'integer', 'minimum': -200000, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'click'}, 'zero_y': {'type': 'integer', 'minimum': -200000, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'click'}, 'sc_height': {'type': 'integer', 'minimum': -5000, 'maximum': 5000, 'x-fraction-digits': 0, 'x-unit': 'mm'}, 'r_twist': {'type': 'integer', 'minimum': 0, 'maximum': 10000, 'x-fraction-digits': 2, 'x-unit': 'in/turn'}, 'twist_dir': {'type': 'string', 'enum': ['RIGHT', 'LEFT']}, 'c_muzzle_velocity': {'type': 'integer', 'minimum': 100, 'maximum': 30000, 'x-fraction-digits': 1, 'x-ui-fraction-digits': 0, 'x-unit': 'm/s', 'x-fixed': "dart's A7pValidator checked minimum 10 instead of 100 (its own A7pFieldConstraints.muzzleVelocity implies raw min 100: 10.0 * 10^1) -- fixed."}, 'c_zero_temperature': {'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, 'c_t_coeff': {'type': 'integer', 'minimum': 0, 'maximum': 5000, 'x-fraction-digits': 3, 'x-unit': '%/15°C'}, 'c_zero_distance_idx': {'type': 'integer', 'minimum': 0, 'maximum': 255, 'x-fraction-digits': 0, 'description': "Index into 'distances'.", 'x-discrepancy': "dart's A7pValidator instead bounds this dynamically by len(distances)-1 rather than a fixed 255 -- a cross-field constraint plain JSON Schema can't express without a custom keyword/extension. profile.clj / py / js all use the static 0-255 range encoded here."}, 'c_zero_air_temperature': {'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, 'c_zero_air_pressure': {'type': 'integer', 'minimum': 3000, 'maximum': 15000, 'x-fraction-digits': 1, 'x-ui-fraction-digits': 0, 'x-unit': 'hPa'}, 'c_zero_air_humidity': {'type': 'integer', 'minimum': 0, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '%'}, 'c_zero_w_pitch': {'type': 'integer', 'minimum': -90, 'maximum': 90, 'x-fraction-digits': 0, 'x-unit': '°', 'x-fixed': "dart's A7pValidator did not check this field at all (present in A7pFieldConstraints but missing from _validateProfile) -- check added."}, 'c_zero_p_temperature': {'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, 'b_diameter': {'type': 'integer', 'minimum': 1, 'maximum': 50000, 'x-fraction-digits': 3, 'x-unit': 'in'}, 'b_weight': {'type': 'integer', 'minimum': 10, 'maximum': 65535, 'x-fraction-digits': 1, 'x-unit': 'gr', 'x-fixed': "dart's A7pValidator checked minimum 1 instead of 10 (its own A7pFieldConstraints.bulletWeight implies raw min 10: 1.0 * 10^1) -- fixed."}, 'b_length': {'type': 'integer', 'minimum': 10, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'in', 'x-fixed': "dart's A7pValidator used min 0 instead of 10 -- fixed. js validate.ts used min 1 instead of 10 -- fixed."}, 'bc_type': {'type': 'string', 'enum': ['G1', 'G7', 'CUSTOM']}, 'switches': {'type': 'array', 'minItems': 4, 'items': {'type': 'object', 'additionalProperties': False, 'required': ['c_idx', 'distance_from', 'distance', 'reticle_idx', 'zoom'], 'properties': {'c_idx': {'description': "Index into coef_rows, or 255 meaning 'unused'.", 'oneOf': [{'type': 'integer', 'minimum': 0, 'maximum': 200}, {'const': 255}], 'x-decision': 'Resolved: 201-254 is rejected (matches profile.clj / py). Locked in by tests/test_schema_validator.py::test_switch_c_idx_bounds in py, which now validates through the public a7p.validate() path (schema_validator.py), not just the old yupy_schema.py.', 'x-discrepancy': "js and dart's A7pValidator both still accept the full 0-255 range unconditionally -- not fixed there yet; would require changing validation logic (not just a numeric constant) in both."}, 'distance_from': {'$ref': '#/$defs/DistanceFrom'}, 'distance': {'description': "Either the 'unused' sentinel 0, or a real distance in [100, 300000] raw (1.0-3000.0 m, 2 fraction digits) -- per profile.clj's (s/or :distance ::distance :unused zero?), unconditional on distance_from.", 'oneOf': [{'const': 0}, {'type': 'integer', 'minimum': 100, 'maximum': 300000}], 'x-fraction-digits': 2, 'x-ui-fraction-digits': 0, 'x-unit': 'm', 'x-decision': 'Resolved: distance is 0-or-[100,300000] unconditionally, regardless of distance_from (matches profile.clj / py) -- distance_from is not consulted for this rule. Locked in by tests/test_schema_validator.py::test_switch_distance_bounds_independent_of_distance_from in py, which now validates through the public a7p.validate() path (schema_validator.py), not just the old yupy_schema.py.', 'x-discrepancy': "js and dart instead branch on distance_from: when INDEX, they validate 'distance' as an index in [0,255] into the distances array; when VALUE, as [100,300000]. Not fixed there yet -- this is a semantic fork, not just a range typo, and would require changing validation logic (not just a numeric constant) in both."}, 'reticle_idx': {'type': 'integer', 'minimum': 0, 'maximum': 255, 'x-fraction-digits': 0}, 'zoom': {'type': 'integer', 'minimum': 0, 'maximum': 6, 'x-fraction-digits': 0, 'description': '0 = unset/default (observed in real profiles for switches with distance_from=INDEX acting as a placeholder entry), 1-6 = real zoom levels on the device.', 'x-fixed': "dart's A7pValidator already checked 0-6 (matching this schema); its A7pFieldConstraints.zoom metadata said min 1, contradicting its own validator and the real shipped profiles below -- doc comment updated to 0-6. js validate.ts previously did not restrict this at all (0-255) -- now bounded to 0-6. py's public a7p.validate() uses this schema directly (0-6), confirmed by tests/test_schema_validator.py::test_switch_zoom_bounds.", 'x-discrepancy': "profile.clj says 0-4 (documented bug, not used here). py's yupy_schema.py module still hard-codes 0-4 in its own tests/regression suite (test_yupy_schema.py), but that module is no longer wired into the public a7p.validate() path, so this doesn't affect real validation -- only relevant if someone imports a7p.yupy_schema directly. Confirmed against real shipped profiles: py/tests/data/example2.a7p and js/scripts/example2.a7p both ship a switch with zoom == 0."}}}}, 'distances': {'type': 'array', 'minItems': 1, 'maxItems': 200, 'items': {'type': 'integer', 'minimum': 100, 'maximum': 300000, 'x-fraction-digits': 2, 'x-ui-fraction-digits': 0, 'x-unit': 'm'}}, 'coef_rows': {'type': 'array', 'minItems': 1, 'items': {'type': 'object', 'additionalProperties': False, 'required': ['bc_cd', 'mv'], 'properties': {'bc_cd': {'type': 'integer', 'minimum': 0, 'maximum': 100000, 'x-fraction-digits': 4, 'x-ui-fraction-digits': 3, 'description': "Holds 'bc' (drag model G1/G7) or 'cd' (CUSTOM drag model); both share the same 0.0-10.0 display range.", 'x-fixed': 'js validate.ts capped this at raw 10000 (display max 1.0) instead of 100000 (display max 10.0), matching profile.clj / py / dart -- fixed.'}, 'mv': {'type': 'integer', 'minimum': 0, 'x-unit': 'm/s (G1/G7) or Ma (CUSTOM)', 'description': "Muzzle velocity for G1/G7 rows (0.0-3000.0 m/s, 1 fraction digit -> raw max 30000), or Mach number 'ma' for CUSTOM rows (0.0-10.0, 4 fraction digits -> raw max 100000). Effective maximum is set contextually by the CoefRows if/then below.", 'x-fixed': 'js capped CUSTOM mv at raw 10000 instead of 100000 -- same missing-factor-of-10 issue as bc_cd above -- fixed.'}}}, 'x-unique-except-zero': 'mv', 'description': "Not expressible in plain JSON Schema: all 'mv' values must be unique except that any number of rows may have mv == 0. Enforce with one small hand-written check per language, run against schema/fixtures/ to keep behavior in sync.", 'if': {'properties': {'bc_type': {'const': 'CUSTOM'}}}, 'then': {'maxItems': 200, 'items': {'properties': {'mv': {'maximum': 100000}}}}, 'else': {'maxItems': 5, 'items': {'properties': {'mv': {'maximum': 30000}}}}}}}, rule='type')
    data_is_dict = isinstance(data, dict)
    if data_is_dict:
        data__missing_keys = set(['profile_name', 'cartridge_name', 'bullet_name', 'short_name_top', 'short_name_bot', 'caliber', 'device_uuid', 'user_note', 'zero_x', 'zero_y', 'sc_height', 'r_twist', 'twist_dir', 'c_muzzle_velocity', 'c_zero_temperature', 'c_t_coeff', 'c_zero_distance_idx', 'c_zero_air_temperature', 'c_zero_air_pressure', 'c_zero_air_humidity', 'c_zero_w_pitch', 'c_zero_p_temperature', 'b_diameter', 'b_weight', 'b_length', 'bc_type', 'switches', 'distances', 'coef_rows']) - data.keys()
        if data__missing_keys:
            raise JsonSchemaValueException("" + (name_prefix or "data") + " must contain " + (str(sorted(data__missing_keys)) + " properties"), value=data, name="" + (name_prefix or "data") + "", definition={'type': 'object', 'additionalProperties': False, 'required': ['profile_name', 'cartridge_name', 'bullet_name', 'short_name_top', 'short_name_bot', 'caliber', 'device_uuid', 'user_note', 'zero_x', 'zero_y', 'sc_height', 'r_twist', 'twist_dir', 'c_muzzle_velocity', 'c_zero_temperature', 'c_t_coeff', 'c_zero_distance_idx', 'c_zero_air_temperature', 'c_zero_air_pressure', 'c_zero_air_humidity', 'c_zero_w_pitch', 'c_zero_p_temperature', 'b_diameter', 'b_weight', 'b_length', 'bc_type', 'switches', 'distances', 'coef_rows'], 'properties': {'profile_name': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'cartridge_name': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'bullet_name': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'short_name_top': {'type': 'string', 'minLength': 1, 'maxLength': 8}, 'short_name_bot': {'type': 'string', 'minLength': 1, 'maxLength': 8}, 'caliber': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'device_uuid': {'type': 'string', 'maxLength': 50}, 'user_note': {'type': 'string', 'maxLength': 1024}, 'zero_x': {'type': 'integer', 'minimum': -200000, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'click'}, 'zero_y': {'type': 'integer', 'minimum': -200000, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'click'}, 'sc_height': {'type': 'integer', 'minimum': -5000, 'maximum': 5000, 'x-fraction-digits': 0, 'x-unit': 'mm'}, 'r_twist': {'type': 'integer', 'minimum': 0, 'maximum': 10000, 'x-fraction-digits': 2, 'x-unit': 'in/turn'}, 'twist_dir': {'type': 'string', 'enum': ['RIGHT', 'LEFT']}, 'c_muzzle_velocity': {'type': 'integer', 'minimum': 100, 'maximum': 30000, 'x-fraction-digits': 1, 'x-ui-fraction-digits': 0, 'x-unit': 'm/s', 'x-fixed': "dart's A7pValidator checked minimum 10 instead of 100 (its own A7pFieldConstraints.muzzleVelocity implies raw min 100: 10.0 * 10^1) -- fixed."}, 'c_zero_temperature': {'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, 'c_t_coeff': {'type': 'integer', 'minimum': 0, 'maximum': 5000, 'x-fraction-digits': 3, 'x-unit': '%/15°C'}, 'c_zero_distance_idx': {'type': 'integer', 'minimum': 0, 'maximum': 255, 'x-fraction-digits': 0, 'description': "Index into 'distances'.", 'x-discrepancy': "dart's A7pValidator instead bounds this dynamically by len(distances)-1 rather than a fixed 255 -- a cross-field constraint plain JSON Schema can't express without a custom keyword/extension. profile.clj / py / js all use the static 0-255 range encoded here."}, 'c_zero_air_temperature': {'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, 'c_zero_air_pressure': {'type': 'integer', 'minimum': 3000, 'maximum': 15000, 'x-fraction-digits': 1, 'x-ui-fraction-digits': 0, 'x-unit': 'hPa'}, 'c_zero_air_humidity': {'type': 'integer', 'minimum': 0, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '%'}, 'c_zero_w_pitch': {'type': 'integer', 'minimum': -90, 'maximum': 90, 'x-fraction-digits': 0, 'x-unit': '°', 'x-fixed': "dart's A7pValidator did not check this field at all (present in A7pFieldConstraints but missing from _validateProfile) -- check added."}, 'c_zero_p_temperature': {'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, 'b_diameter': {'type': 'integer', 'minimum': 1, 'maximum': 50000, 'x-fraction-digits': 3, 'x-unit': 'in'}, 'b_weight': {'type': 'integer', 'minimum': 10, 'maximum': 65535, 'x-fraction-digits': 1, 'x-unit': 'gr', 'x-fixed': "dart's A7pValidator checked minimum 1 instead of 10 (its own A7pFieldConstraints.bulletWeight implies raw min 10: 1.0 * 10^1) -- fixed."}, 'b_length': {'type': 'integer', 'minimum': 10, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'in', 'x-fixed': "dart's A7pValidator used min 0 instead of 10 -- fixed. js validate.ts used min 1 instead of 10 -- fixed."}, 'bc_type': {'type': 'string', 'enum': ['G1', 'G7', 'CUSTOM']}, 'switches': {'type': 'array', 'minItems': 4, 'items': {'type': 'object', 'additionalProperties': False, 'required': ['c_idx', 'distance_from', 'distance', 'reticle_idx', 'zoom'], 'properties': {'c_idx': {'description': "Index into coef_rows, or 255 meaning 'unused'.", 'oneOf': [{'type': 'integer', 'minimum': 0, 'maximum': 200}, {'const': 255}], 'x-decision': 'Resolved: 201-254 is rejected (matches profile.clj / py). Locked in by tests/test_schema_validator.py::test_switch_c_idx_bounds in py, which now validates through the public a7p.validate() path (schema_validator.py), not just the old yupy_schema.py.', 'x-discrepancy': "js and dart's A7pValidator both still accept the full 0-255 range unconditionally -- not fixed there yet; would require changing validation logic (not just a numeric constant) in both."}, 'distance_from': {'$ref': '#/$defs/DistanceFrom'}, 'distance': {'description': "Either the 'unused' sentinel 0, or a real distance in [100, 300000] raw (1.0-3000.0 m, 2 fraction digits) -- per profile.clj's (s/or :distance ::distance :unused zero?), unconditional on distance_from.", 'oneOf': [{'const': 0}, {'type': 'integer', 'minimum': 100, 'maximum': 300000}], 'x-fraction-digits': 2, 'x-ui-fraction-digits': 0, 'x-unit': 'm', 'x-decision': 'Resolved: distance is 0-or-[100,300000] unconditionally, regardless of distance_from (matches profile.clj / py) -- distance_from is not consulted for this rule. Locked in by tests/test_schema_validator.py::test_switch_distance_bounds_independent_of_distance_from in py, which now validates through the public a7p.validate() path (schema_validator.py), not just the old yupy_schema.py.', 'x-discrepancy': "js and dart instead branch on distance_from: when INDEX, they validate 'distance' as an index in [0,255] into the distances array; when VALUE, as [100,300000]. Not fixed there yet -- this is a semantic fork, not just a range typo, and would require changing validation logic (not just a numeric constant) in both."}, 'reticle_idx': {'type': 'integer', 'minimum': 0, 'maximum': 255, 'x-fraction-digits': 0}, 'zoom': {'type': 'integer', 'minimum': 0, 'maximum': 6, 'x-fraction-digits': 0, 'description': '0 = unset/default (observed in real profiles for switches with distance_from=INDEX acting as a placeholder entry), 1-6 = real zoom levels on the device.', 'x-fixed': "dart's A7pValidator already checked 0-6 (matching this schema); its A7pFieldConstraints.zoom metadata said min 1, contradicting its own validator and the real shipped profiles below -- doc comment updated to 0-6. js validate.ts previously did not restrict this at all (0-255) -- now bounded to 0-6. py's public a7p.validate() uses this schema directly (0-6), confirmed by tests/test_schema_validator.py::test_switch_zoom_bounds.", 'x-discrepancy': "profile.clj says 0-4 (documented bug, not used here). py's yupy_schema.py module still hard-codes 0-4 in its own tests/regression suite (test_yupy_schema.py), but that module is no longer wired into the public a7p.validate() path, so this doesn't affect real validation -- only relevant if someone imports a7p.yupy_schema directly. Confirmed against real shipped profiles: py/tests/data/example2.a7p and js/scripts/example2.a7p both ship a switch with zoom == 0."}}}}, 'distances': {'type': 'array', 'minItems': 1, 'maxItems': 200, 'items': {'type': 'integer', 'minimum': 100, 'maximum': 300000, 'x-fraction-digits': 2, 'x-ui-fraction-digits': 0, 'x-unit': 'm'}}, 'coef_rows': {'type': 'array', 'minItems': 1, 'items': {'type': 'object', 'additionalProperties': False, 'required': ['bc_cd', 'mv'], 'properties': {'bc_cd': {'type': 'integer', 'minimum': 0, 'maximum': 100000, 'x-fraction-digits': 4, 'x-ui-fraction-digits': 3, 'description': "Holds 'bc' (drag model G1/G7) or 'cd' (CUSTOM drag model); both share the same 0.0-10.0 display range.", 'x-fixed': 'js validate.ts capped this at raw 10000 (display max 1.0) instead of 100000 (display max 10.0), matching profile.clj / py / dart -- fixed.'}, 'mv': {'type': 'integer', 'minimum': 0, 'x-unit': 'm/s (G1/G7) or Ma (CUSTOM)', 'description': "Muzzle velocity for G1/G7 rows (0.0-3000.0 m/s, 1 fraction digit -> raw max 30000), or Mach number 'ma' for CUSTOM rows (0.0-10.0, 4 fraction digits -> raw max 100000). Effective maximum is set contextually by the CoefRows if/then below.", 'x-fixed': 'js capped CUSTOM mv at raw 10000 instead of 100000 -- same missing-factor-of-10 issue as bc_cd above -- fixed.'}}}, 'x-unique-except-zero': 'mv', 'description': "Not expressible in plain JSON Schema: all 'mv' values must be unique except that any number of rows may have mv == 0. Enforce with one small hand-written check per language, run against schema/fixtures/ to keep behavior in sync.", 'if': {'properties': {'bc_type': {'const': 'CUSTOM'}}}, 'then': {'maxItems': 200, 'items': {'properties': {'mv': {'maximum': 100000}}}}, 'else': {'maxItems': 5, 'items': {'properties': {'mv': {'maximum': 30000}}}}}}}, rule='required')
        data_keys = set(data.keys())
        if "profile_name" in data_keys:
            data_keys.remove("profile_name")
            data__profilename = data["profile_name"]
            if not isinstance(data__profilename, (str)):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".profile_name must be string", value=data__profilename, name="" + (name_prefix or "data") + ".profile_name", definition={'type': 'string', 'minLength': 1, 'maxLength': 50}, rule='type')
            if isinstance(data__profilename, str):
                data__profilename_len = len(data__profilename)
                if data__profilename_len < 1:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".profile_name must be longer than or equal to 1 characters", value=data__profilename, name="" + (name_prefix or "data") + ".profile_name", definition={'type': 'string', 'minLength': 1, 'maxLength': 50}, rule='minLength')
                if data__profilename_len > 50:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".profile_name must be shorter than or equal to 50 characters", value=data__profilename, name="" + (name_prefix or "data") + ".profile_name", definition={'type': 'string', 'minLength': 1, 'maxLength': 50}, rule='maxLength')
        if "cartridge_name" in data_keys:
            data_keys.remove("cartridge_name")
            data__cartridgename = data["cartridge_name"]
            if not isinstance(data__cartridgename, (str)):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".cartridge_name must be string", value=data__cartridgename, name="" + (name_prefix or "data") + ".cartridge_name", definition={'type': 'string', 'minLength': 1, 'maxLength': 50}, rule='type')
            if isinstance(data__cartridgename, str):
                data__cartridgename_len = len(data__cartridgename)
                if data__cartridgename_len < 1:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".cartridge_name must be longer than or equal to 1 characters", value=data__cartridgename, name="" + (name_prefix or "data") + ".cartridge_name", definition={'type': 'string', 'minLength': 1, 'maxLength': 50}, rule='minLength')
                if data__cartridgename_len > 50:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".cartridge_name must be shorter than or equal to 50 characters", value=data__cartridgename, name="" + (name_prefix or "data") + ".cartridge_name", definition={'type': 'string', 'minLength': 1, 'maxLength': 50}, rule='maxLength')
        if "bullet_name" in data_keys:
            data_keys.remove("bullet_name")
            data__bulletname = data["bullet_name"]
            if not isinstance(data__bulletname, (str)):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".bullet_name must be string", value=data__bulletname, name="" + (name_prefix or "data") + ".bullet_name", definition={'type': 'string', 'minLength': 1, 'maxLength': 50}, rule='type')
            if isinstance(data__bulletname, str):
                data__bulletname_len = len(data__bulletname)
                if data__bulletname_len < 1:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".bullet_name must be longer than or equal to 1 characters", value=data__bulletname, name="" + (name_prefix or "data") + ".bullet_name", definition={'type': 'string', 'minLength': 1, 'maxLength': 50}, rule='minLength')
                if data__bulletname_len > 50:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".bullet_name must be shorter than or equal to 50 characters", value=data__bulletname, name="" + (name_prefix or "data") + ".bullet_name", definition={'type': 'string', 'minLength': 1, 'maxLength': 50}, rule='maxLength')
        if "short_name_top" in data_keys:
            data_keys.remove("short_name_top")
            data__shortnametop = data["short_name_top"]
            if not isinstance(data__shortnametop, (str)):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".short_name_top must be string", value=data__shortnametop, name="" + (name_prefix or "data") + ".short_name_top", definition={'type': 'string', 'minLength': 1, 'maxLength': 8}, rule='type')
            if isinstance(data__shortnametop, str):
                data__shortnametop_len = len(data__shortnametop)
                if data__shortnametop_len < 1:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".short_name_top must be longer than or equal to 1 characters", value=data__shortnametop, name="" + (name_prefix or "data") + ".short_name_top", definition={'type': 'string', 'minLength': 1, 'maxLength': 8}, rule='minLength')
                if data__shortnametop_len > 8:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".short_name_top must be shorter than or equal to 8 characters", value=data__shortnametop, name="" + (name_prefix or "data") + ".short_name_top", definition={'type': 'string', 'minLength': 1, 'maxLength': 8}, rule='maxLength')
        if "short_name_bot" in data_keys:
            data_keys.remove("short_name_bot")
            data__shortnamebot = data["short_name_bot"]
            if not isinstance(data__shortnamebot, (str)):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".short_name_bot must be string", value=data__shortnamebot, name="" + (name_prefix or "data") + ".short_name_bot", definition={'type': 'string', 'minLength': 1, 'maxLength': 8}, rule='type')
            if isinstance(data__shortnamebot, str):
                data__shortnamebot_len = len(data__shortnamebot)
                if data__shortnamebot_len < 1:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".short_name_bot must be longer than or equal to 1 characters", value=data__shortnamebot, name="" + (name_prefix or "data") + ".short_name_bot", definition={'type': 'string', 'minLength': 1, 'maxLength': 8}, rule='minLength')
                if data__shortnamebot_len > 8:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".short_name_bot must be shorter than or equal to 8 characters", value=data__shortnamebot, name="" + (name_prefix or "data") + ".short_name_bot", definition={'type': 'string', 'minLength': 1, 'maxLength': 8}, rule='maxLength')
        if "caliber" in data_keys:
            data_keys.remove("caliber")
            data__caliber = data["caliber"]
            if not isinstance(data__caliber, (str)):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".caliber must be string", value=data__caliber, name="" + (name_prefix or "data") + ".caliber", definition={'type': 'string', 'minLength': 1, 'maxLength': 50}, rule='type')
            if isinstance(data__caliber, str):
                data__caliber_len = len(data__caliber)
                if data__caliber_len < 1:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".caliber must be longer than or equal to 1 characters", value=data__caliber, name="" + (name_prefix or "data") + ".caliber", definition={'type': 'string', 'minLength': 1, 'maxLength': 50}, rule='minLength')
                if data__caliber_len > 50:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".caliber must be shorter than or equal to 50 characters", value=data__caliber, name="" + (name_prefix or "data") + ".caliber", definition={'type': 'string', 'minLength': 1, 'maxLength': 50}, rule='maxLength')
        if "device_uuid" in data_keys:
            data_keys.remove("device_uuid")
            data__deviceuuid = data["device_uuid"]
            if not isinstance(data__deviceuuid, (str)):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".device_uuid must be string", value=data__deviceuuid, name="" + (name_prefix or "data") + ".device_uuid", definition={'type': 'string', 'maxLength': 50}, rule='type')
            if isinstance(data__deviceuuid, str):
                data__deviceuuid_len = len(data__deviceuuid)
                if data__deviceuuid_len > 50:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".device_uuid must be shorter than or equal to 50 characters", value=data__deviceuuid, name="" + (name_prefix or "data") + ".device_uuid", definition={'type': 'string', 'maxLength': 50}, rule='maxLength')
        if "user_note" in data_keys:
            data_keys.remove("user_note")
            data__usernote = data["user_note"]
            if not isinstance(data__usernote, (str)):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".user_note must be string", value=data__usernote, name="" + (name_prefix or "data") + ".user_note", definition={'type': 'string', 'maxLength': 1024}, rule='type')
            if isinstance(data__usernote, str):
                data__usernote_len = len(data__usernote)
                if data__usernote_len > 1024:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".user_note must be shorter than or equal to 1024 characters", value=data__usernote, name="" + (name_prefix or "data") + ".user_note", definition={'type': 'string', 'maxLength': 1024}, rule='maxLength')
        if "zero_x" in data_keys:
            data_keys.remove("zero_x")
            data__zerox = data["zero_x"]
            if not isinstance(data__zerox, (int)) and not (isinstance(data__zerox, float) and data__zerox.is_integer()) or isinstance(data__zerox, bool):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".zero_x must be integer", value=data__zerox, name="" + (name_prefix or "data") + ".zero_x", definition={'type': 'integer', 'minimum': -200000, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'click'}, rule='type')
            if isinstance(data__zerox, (int, float, Decimal)):
                if data__zerox < -200000:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".zero_x must be bigger than or equal to -200000", value=data__zerox, name="" + (name_prefix or "data") + ".zero_x", definition={'type': 'integer', 'minimum': -200000, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'click'}, rule='minimum')
                if data__zerox > 200000:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".zero_x must be smaller than or equal to 200000", value=data__zerox, name="" + (name_prefix or "data") + ".zero_x", definition={'type': 'integer', 'minimum': -200000, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'click'}, rule='maximum')
        if "zero_y" in data_keys:
            data_keys.remove("zero_y")
            data__zeroy = data["zero_y"]
            if not isinstance(data__zeroy, (int)) and not (isinstance(data__zeroy, float) and data__zeroy.is_integer()) or isinstance(data__zeroy, bool):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".zero_y must be integer", value=data__zeroy, name="" + (name_prefix or "data") + ".zero_y", definition={'type': 'integer', 'minimum': -200000, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'click'}, rule='type')
            if isinstance(data__zeroy, (int, float, Decimal)):
                if data__zeroy < -200000:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".zero_y must be bigger than or equal to -200000", value=data__zeroy, name="" + (name_prefix or "data") + ".zero_y", definition={'type': 'integer', 'minimum': -200000, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'click'}, rule='minimum')
                if data__zeroy > 200000:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".zero_y must be smaller than or equal to 200000", value=data__zeroy, name="" + (name_prefix or "data") + ".zero_y", definition={'type': 'integer', 'minimum': -200000, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'click'}, rule='maximum')
        if "sc_height" in data_keys:
            data_keys.remove("sc_height")
            data__scheight = data["sc_height"]
            if not isinstance(data__scheight, (int)) and not (isinstance(data__scheight, float) and data__scheight.is_integer()) or isinstance(data__scheight, bool):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".sc_height must be integer", value=data__scheight, name="" + (name_prefix or "data") + ".sc_height", definition={'type': 'integer', 'minimum': -5000, 'maximum': 5000, 'x-fraction-digits': 0, 'x-unit': 'mm'}, rule='type')
            if isinstance(data__scheight, (int, float, Decimal)):
                if data__scheight < -5000:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".sc_height must be bigger than or equal to -5000", value=data__scheight, name="" + (name_prefix or "data") + ".sc_height", definition={'type': 'integer', 'minimum': -5000, 'maximum': 5000, 'x-fraction-digits': 0, 'x-unit': 'mm'}, rule='minimum')
                if data__scheight > 5000:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".sc_height must be smaller than or equal to 5000", value=data__scheight, name="" + (name_prefix or "data") + ".sc_height", definition={'type': 'integer', 'minimum': -5000, 'maximum': 5000, 'x-fraction-digits': 0, 'x-unit': 'mm'}, rule='maximum')
        if "r_twist" in data_keys:
            data_keys.remove("r_twist")
            data__rtwist = data["r_twist"]
            if not isinstance(data__rtwist, (int)) and not (isinstance(data__rtwist, float) and data__rtwist.is_integer()) or isinstance(data__rtwist, bool):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".r_twist must be integer", value=data__rtwist, name="" + (name_prefix or "data") + ".r_twist", definition={'type': 'integer', 'minimum': 0, 'maximum': 10000, 'x-fraction-digits': 2, 'x-unit': 'in/turn'}, rule='type')
            if isinstance(data__rtwist, (int, float, Decimal)):
                if data__rtwist < 0:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".r_twist must be bigger than or equal to 0", value=data__rtwist, name="" + (name_prefix or "data") + ".r_twist", definition={'type': 'integer', 'minimum': 0, 'maximum': 10000, 'x-fraction-digits': 2, 'x-unit': 'in/turn'}, rule='minimum')
                if data__rtwist > 10000:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".r_twist must be smaller than or equal to 10000", value=data__rtwist, name="" + (name_prefix or "data") + ".r_twist", definition={'type': 'integer', 'minimum': 0, 'maximum': 10000, 'x-fraction-digits': 2, 'x-unit': 'in/turn'}, rule='maximum')
        if "twist_dir" in data_keys:
            data_keys.remove("twist_dir")
            data__twistdir = data["twist_dir"]
            validate_https___a7p_cross_schema_a7p_schema_json___defs_twistdir(data__twistdir, custom_formats, (name_prefix or "data") + ".twist_dir")
        if "c_muzzle_velocity" in data_keys:
            data_keys.remove("c_muzzle_velocity")
            data__cmuzzlevelocity = data["c_muzzle_velocity"]
            if not isinstance(data__cmuzzlevelocity, (int)) and not (isinstance(data__cmuzzlevelocity, float) and data__cmuzzlevelocity.is_integer()) or isinstance(data__cmuzzlevelocity, bool):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_muzzle_velocity must be integer", value=data__cmuzzlevelocity, name="" + (name_prefix or "data") + ".c_muzzle_velocity", definition={'type': 'integer', 'minimum': 100, 'maximum': 30000, 'x-fraction-digits': 1, 'x-ui-fraction-digits': 0, 'x-unit': 'm/s', 'x-fixed': "dart's A7pValidator checked minimum 10 instead of 100 (its own A7pFieldConstraints.muzzleVelocity implies raw min 100: 10.0 * 10^1) -- fixed."}, rule='type')
            if isinstance(data__cmuzzlevelocity, (int, float, Decimal)):
                if data__cmuzzlevelocity < 100:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_muzzle_velocity must be bigger than or equal to 100", value=data__cmuzzlevelocity, name="" + (name_prefix or "data") + ".c_muzzle_velocity", definition={'type': 'integer', 'minimum': 100, 'maximum': 30000, 'x-fraction-digits': 1, 'x-ui-fraction-digits': 0, 'x-unit': 'm/s', 'x-fixed': "dart's A7pValidator checked minimum 10 instead of 100 (its own A7pFieldConstraints.muzzleVelocity implies raw min 100: 10.0 * 10^1) -- fixed."}, rule='minimum')
                if data__cmuzzlevelocity > 30000:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_muzzle_velocity must be smaller than or equal to 30000", value=data__cmuzzlevelocity, name="" + (name_prefix or "data") + ".c_muzzle_velocity", definition={'type': 'integer', 'minimum': 100, 'maximum': 30000, 'x-fraction-digits': 1, 'x-ui-fraction-digits': 0, 'x-unit': 'm/s', 'x-fixed': "dart's A7pValidator checked minimum 10 instead of 100 (its own A7pFieldConstraints.muzzleVelocity implies raw min 100: 10.0 * 10^1) -- fixed."}, rule='maximum')
        if "c_zero_temperature" in data_keys:
            data_keys.remove("c_zero_temperature")
            data__czerotemperature = data["c_zero_temperature"]
            if not isinstance(data__czerotemperature, (int)) and not (isinstance(data__czerotemperature, float) and data__czerotemperature.is_integer()) or isinstance(data__czerotemperature, bool):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_zero_temperature must be integer", value=data__czerotemperature, name="" + (name_prefix or "data") + ".c_zero_temperature", definition={'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, rule='type')
            if isinstance(data__czerotemperature, (int, float, Decimal)):
                if data__czerotemperature < -100:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_zero_temperature must be bigger than or equal to -100", value=data__czerotemperature, name="" + (name_prefix or "data") + ".c_zero_temperature", definition={'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, rule='minimum')
                if data__czerotemperature > 100:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_zero_temperature must be smaller than or equal to 100", value=data__czerotemperature, name="" + (name_prefix or "data") + ".c_zero_temperature", definition={'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, rule='maximum')
        if "c_t_coeff" in data_keys:
            data_keys.remove("c_t_coeff")
            data__ctcoeff = data["c_t_coeff"]
            if not isinstance(data__ctcoeff, (int)) and not (isinstance(data__ctcoeff, float) and data__ctcoeff.is_integer()) or isinstance(data__ctcoeff, bool):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_t_coeff must be integer", value=data__ctcoeff, name="" + (name_prefix or "data") + ".c_t_coeff", definition={'type': 'integer', 'minimum': 0, 'maximum': 5000, 'x-fraction-digits': 3, 'x-unit': '%/15°C'}, rule='type')
            if isinstance(data__ctcoeff, (int, float, Decimal)):
                if data__ctcoeff < 0:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_t_coeff must be bigger than or equal to 0", value=data__ctcoeff, name="" + (name_prefix or "data") + ".c_t_coeff", definition={'type': 'integer', 'minimum': 0, 'maximum': 5000, 'x-fraction-digits': 3, 'x-unit': '%/15°C'}, rule='minimum')
                if data__ctcoeff > 5000:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_t_coeff must be smaller than or equal to 5000", value=data__ctcoeff, name="" + (name_prefix or "data") + ".c_t_coeff", definition={'type': 'integer', 'minimum': 0, 'maximum': 5000, 'x-fraction-digits': 3, 'x-unit': '%/15°C'}, rule='maximum')
        if "c_zero_distance_idx" in data_keys:
            data_keys.remove("c_zero_distance_idx")
            data__czerodistanceidx = data["c_zero_distance_idx"]
            if not isinstance(data__czerodistanceidx, (int)) and not (isinstance(data__czerodistanceidx, float) and data__czerodistanceidx.is_integer()) or isinstance(data__czerodistanceidx, bool):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_zero_distance_idx must be integer", value=data__czerodistanceidx, name="" + (name_prefix or "data") + ".c_zero_distance_idx", definition={'type': 'integer', 'minimum': 0, 'maximum': 255, 'x-fraction-digits': 0, 'description': "Index into 'distances'.", 'x-discrepancy': "dart's A7pValidator instead bounds this dynamically by len(distances)-1 rather than a fixed 255 -- a cross-field constraint plain JSON Schema can't express without a custom keyword/extension. profile.clj / py / js all use the static 0-255 range encoded here."}, rule='type')
            if isinstance(data__czerodistanceidx, (int, float, Decimal)):
                if data__czerodistanceidx < 0:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_zero_distance_idx must be bigger than or equal to 0", value=data__czerodistanceidx, name="" + (name_prefix or "data") + ".c_zero_distance_idx", definition={'type': 'integer', 'minimum': 0, 'maximum': 255, 'x-fraction-digits': 0, 'description': "Index into 'distances'.", 'x-discrepancy': "dart's A7pValidator instead bounds this dynamically by len(distances)-1 rather than a fixed 255 -- a cross-field constraint plain JSON Schema can't express without a custom keyword/extension. profile.clj / py / js all use the static 0-255 range encoded here."}, rule='minimum')
                if data__czerodistanceidx > 255:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_zero_distance_idx must be smaller than or equal to 255", value=data__czerodistanceidx, name="" + (name_prefix or "data") + ".c_zero_distance_idx", definition={'type': 'integer', 'minimum': 0, 'maximum': 255, 'x-fraction-digits': 0, 'description': "Index into 'distances'.", 'x-discrepancy': "dart's A7pValidator instead bounds this dynamically by len(distances)-1 rather than a fixed 255 -- a cross-field constraint plain JSON Schema can't express without a custom keyword/extension. profile.clj / py / js all use the static 0-255 range encoded here."}, rule='maximum')
        if "c_zero_air_temperature" in data_keys:
            data_keys.remove("c_zero_air_temperature")
            data__czeroairtemperature = data["c_zero_air_temperature"]
            if not isinstance(data__czeroairtemperature, (int)) and not (isinstance(data__czeroairtemperature, float) and data__czeroairtemperature.is_integer()) or isinstance(data__czeroairtemperature, bool):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_zero_air_temperature must be integer", value=data__czeroairtemperature, name="" + (name_prefix or "data") + ".c_zero_air_temperature", definition={'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, rule='type')
            if isinstance(data__czeroairtemperature, (int, float, Decimal)):
                if data__czeroairtemperature < -100:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_zero_air_temperature must be bigger than or equal to -100", value=data__czeroairtemperature, name="" + (name_prefix or "data") + ".c_zero_air_temperature", definition={'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, rule='minimum')
                if data__czeroairtemperature > 100:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_zero_air_temperature must be smaller than or equal to 100", value=data__czeroairtemperature, name="" + (name_prefix or "data") + ".c_zero_air_temperature", definition={'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, rule='maximum')
        if "c_zero_air_pressure" in data_keys:
            data_keys.remove("c_zero_air_pressure")
            data__czeroairpressure = data["c_zero_air_pressure"]
            if not isinstance(data__czeroairpressure, (int)) and not (isinstance(data__czeroairpressure, float) and data__czeroairpressure.is_integer()) or isinstance(data__czeroairpressure, bool):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_zero_air_pressure must be integer", value=data__czeroairpressure, name="" + (name_prefix or "data") + ".c_zero_air_pressure", definition={'type': 'integer', 'minimum': 3000, 'maximum': 15000, 'x-fraction-digits': 1, 'x-ui-fraction-digits': 0, 'x-unit': 'hPa'}, rule='type')
            if isinstance(data__czeroairpressure, (int, float, Decimal)):
                if data__czeroairpressure < 3000:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_zero_air_pressure must be bigger than or equal to 3000", value=data__czeroairpressure, name="" + (name_prefix or "data") + ".c_zero_air_pressure", definition={'type': 'integer', 'minimum': 3000, 'maximum': 15000, 'x-fraction-digits': 1, 'x-ui-fraction-digits': 0, 'x-unit': 'hPa'}, rule='minimum')
                if data__czeroairpressure > 15000:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_zero_air_pressure must be smaller than or equal to 15000", value=data__czeroairpressure, name="" + (name_prefix or "data") + ".c_zero_air_pressure", definition={'type': 'integer', 'minimum': 3000, 'maximum': 15000, 'x-fraction-digits': 1, 'x-ui-fraction-digits': 0, 'x-unit': 'hPa'}, rule='maximum')
        if "c_zero_air_humidity" in data_keys:
            data_keys.remove("c_zero_air_humidity")
            data__czeroairhumidity = data["c_zero_air_humidity"]
            if not isinstance(data__czeroairhumidity, (int)) and not (isinstance(data__czeroairhumidity, float) and data__czeroairhumidity.is_integer()) or isinstance(data__czeroairhumidity, bool):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_zero_air_humidity must be integer", value=data__czeroairhumidity, name="" + (name_prefix or "data") + ".c_zero_air_humidity", definition={'type': 'integer', 'minimum': 0, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '%'}, rule='type')
            if isinstance(data__czeroairhumidity, (int, float, Decimal)):
                if data__czeroairhumidity < 0:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_zero_air_humidity must be bigger than or equal to 0", value=data__czeroairhumidity, name="" + (name_prefix or "data") + ".c_zero_air_humidity", definition={'type': 'integer', 'minimum': 0, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '%'}, rule='minimum')
                if data__czeroairhumidity > 100:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_zero_air_humidity must be smaller than or equal to 100", value=data__czeroairhumidity, name="" + (name_prefix or "data") + ".c_zero_air_humidity", definition={'type': 'integer', 'minimum': 0, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '%'}, rule='maximum')
        if "c_zero_w_pitch" in data_keys:
            data_keys.remove("c_zero_w_pitch")
            data__czerowpitch = data["c_zero_w_pitch"]
            if not isinstance(data__czerowpitch, (int)) and not (isinstance(data__czerowpitch, float) and data__czerowpitch.is_integer()) or isinstance(data__czerowpitch, bool):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_zero_w_pitch must be integer", value=data__czerowpitch, name="" + (name_prefix or "data") + ".c_zero_w_pitch", definition={'type': 'integer', 'minimum': -90, 'maximum': 90, 'x-fraction-digits': 0, 'x-unit': '°', 'x-fixed': "dart's A7pValidator did not check this field at all (present in A7pFieldConstraints but missing from _validateProfile) -- check added."}, rule='type')
            if isinstance(data__czerowpitch, (int, float, Decimal)):
                if data__czerowpitch < -90:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_zero_w_pitch must be bigger than or equal to -90", value=data__czerowpitch, name="" + (name_prefix or "data") + ".c_zero_w_pitch", definition={'type': 'integer', 'minimum': -90, 'maximum': 90, 'x-fraction-digits': 0, 'x-unit': '°', 'x-fixed': "dart's A7pValidator did not check this field at all (present in A7pFieldConstraints but missing from _validateProfile) -- check added."}, rule='minimum')
                if data__czerowpitch > 90:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_zero_w_pitch must be smaller than or equal to 90", value=data__czerowpitch, name="" + (name_prefix or "data") + ".c_zero_w_pitch", definition={'type': 'integer', 'minimum': -90, 'maximum': 90, 'x-fraction-digits': 0, 'x-unit': '°', 'x-fixed': "dart's A7pValidator did not check this field at all (present in A7pFieldConstraints but missing from _validateProfile) -- check added."}, rule='maximum')
        if "c_zero_p_temperature" in data_keys:
            data_keys.remove("c_zero_p_temperature")
            data__czeroptemperature = data["c_zero_p_temperature"]
            if not isinstance(data__czeroptemperature, (int)) and not (isinstance(data__czeroptemperature, float) and data__czeroptemperature.is_integer()) or isinstance(data__czeroptemperature, bool):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_zero_p_temperature must be integer", value=data__czeroptemperature, name="" + (name_prefix or "data") + ".c_zero_p_temperature", definition={'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, rule='type')
            if isinstance(data__czeroptemperature, (int, float, Decimal)):
                if data__czeroptemperature < -100:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_zero_p_temperature must be bigger than or equal to -100", value=data__czeroptemperature, name="" + (name_prefix or "data") + ".c_zero_p_temperature", definition={'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, rule='minimum')
                if data__czeroptemperature > 100:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_zero_p_temperature must be smaller than or equal to 100", value=data__czeroptemperature, name="" + (name_prefix or "data") + ".c_zero_p_temperature", definition={'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, rule='maximum')
        if "b_diameter" in data_keys:
            data_keys.remove("b_diameter")
            data__bdiameter = data["b_diameter"]
            if not isinstance(data__bdiameter, (int)) and not (isinstance(data__bdiameter, float) and data__bdiameter.is_integer()) or isinstance(data__bdiameter, bool):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".b_diameter must be integer", value=data__bdiameter, name="" + (name_prefix or "data") + ".b_diameter", definition={'type': 'integer', 'minimum': 1, 'maximum': 50000, 'x-fraction-digits': 3, 'x-unit': 'in'}, rule='type')
            if isinstance(data__bdiameter, (int, float, Decimal)):
                if data__bdiameter < 1:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".b_diameter must be bigger than or equal to 1", value=data__bdiameter, name="" + (name_prefix or "data") + ".b_diameter", definition={'type': 'integer', 'minimum': 1, 'maximum': 50000, 'x-fraction-digits': 3, 'x-unit': 'in'}, rule='minimum')
                if data__bdiameter > 50000:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".b_diameter must be smaller than or equal to 50000", value=data__bdiameter, name="" + (name_prefix or "data") + ".b_diameter", definition={'type': 'integer', 'minimum': 1, 'maximum': 50000, 'x-fraction-digits': 3, 'x-unit': 'in'}, rule='maximum')
        if "b_weight" in data_keys:
            data_keys.remove("b_weight")
            data__bweight = data["b_weight"]
            if not isinstance(data__bweight, (int)) and not (isinstance(data__bweight, float) and data__bweight.is_integer()) or isinstance(data__bweight, bool):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".b_weight must be integer", value=data__bweight, name="" + (name_prefix or "data") + ".b_weight", definition={'type': 'integer', 'minimum': 10, 'maximum': 65535, 'x-fraction-digits': 1, 'x-unit': 'gr', 'x-fixed': "dart's A7pValidator checked minimum 1 instead of 10 (its own A7pFieldConstraints.bulletWeight implies raw min 10: 1.0 * 10^1) -- fixed."}, rule='type')
            if isinstance(data__bweight, (int, float, Decimal)):
                if data__bweight < 10:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".b_weight must be bigger than or equal to 10", value=data__bweight, name="" + (name_prefix or "data") + ".b_weight", definition={'type': 'integer', 'minimum': 10, 'maximum': 65535, 'x-fraction-digits': 1, 'x-unit': 'gr', 'x-fixed': "dart's A7pValidator checked minimum 1 instead of 10 (its own A7pFieldConstraints.bulletWeight implies raw min 10: 1.0 * 10^1) -- fixed."}, rule='minimum')
                if data__bweight > 65535:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".b_weight must be smaller than or equal to 65535", value=data__bweight, name="" + (name_prefix or "data") + ".b_weight", definition={'type': 'integer', 'minimum': 10, 'maximum': 65535, 'x-fraction-digits': 1, 'x-unit': 'gr', 'x-fixed': "dart's A7pValidator checked minimum 1 instead of 10 (its own A7pFieldConstraints.bulletWeight implies raw min 10: 1.0 * 10^1) -- fixed."}, rule='maximum')
        if "b_length" in data_keys:
            data_keys.remove("b_length")
            data__blength = data["b_length"]
            if not isinstance(data__blength, (int)) and not (isinstance(data__blength, float) and data__blength.is_integer()) or isinstance(data__blength, bool):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".b_length must be integer", value=data__blength, name="" + (name_prefix or "data") + ".b_length", definition={'type': 'integer', 'minimum': 10, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'in', 'x-fixed': "dart's A7pValidator used min 0 instead of 10 -- fixed. js validate.ts used min 1 instead of 10 -- fixed."}, rule='type')
            if isinstance(data__blength, (int, float, Decimal)):
                if data__blength < 10:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".b_length must be bigger than or equal to 10", value=data__blength, name="" + (name_prefix or "data") + ".b_length", definition={'type': 'integer', 'minimum': 10, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'in', 'x-fixed': "dart's A7pValidator used min 0 instead of 10 -- fixed. js validate.ts used min 1 instead of 10 -- fixed."}, rule='minimum')
                if data__blength > 200000:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".b_length must be smaller than or equal to 200000", value=data__blength, name="" + (name_prefix or "data") + ".b_length", definition={'type': 'integer', 'minimum': 10, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'in', 'x-fixed': "dart's A7pValidator used min 0 instead of 10 -- fixed. js validate.ts used min 1 instead of 10 -- fixed."}, rule='maximum')
        if "bc_type" in data_keys:
            data_keys.remove("bc_type")
            data__bctype = data["bc_type"]
            validate_https___a7p_cross_schema_a7p_schema_json___defs_bctype(data__bctype, custom_formats, (name_prefix or "data") + ".bc_type")
        if "switches" in data_keys:
            data_keys.remove("switches")
            data__switches = data["switches"]
            if not isinstance(data__switches, (list, tuple)):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".switches must be array", value=data__switches, name="" + (name_prefix or "data") + ".switches", definition={'type': 'array', 'minItems': 4, 'items': {'type': 'object', 'additionalProperties': False, 'required': ['c_idx', 'distance_from', 'distance', 'reticle_idx', 'zoom'], 'properties': {'c_idx': {'description': "Index into coef_rows, or 255 meaning 'unused'.", 'oneOf': [{'type': 'integer', 'minimum': 0, 'maximum': 200}, {'const': 255}], 'x-decision': 'Resolved: 201-254 is rejected (matches profile.clj / py). Locked in by tests/test_schema_validator.py::test_switch_c_idx_bounds in py, which now validates through the public a7p.validate() path (schema_validator.py), not just the old yupy_schema.py.', 'x-discrepancy': "js and dart's A7pValidator both still accept the full 0-255 range unconditionally -- not fixed there yet; would require changing validation logic (not just a numeric constant) in both."}, 'distance_from': {'$ref': '#/$defs/DistanceFrom'}, 'distance': {'description': "Either the 'unused' sentinel 0, or a real distance in [100, 300000] raw (1.0-3000.0 m, 2 fraction digits) -- per profile.clj's (s/or :distance ::distance :unused zero?), unconditional on distance_from.", 'oneOf': [{'const': 0}, {'type': 'integer', 'minimum': 100, 'maximum': 300000}], 'x-fraction-digits': 2, 'x-ui-fraction-digits': 0, 'x-unit': 'm', 'x-decision': 'Resolved: distance is 0-or-[100,300000] unconditionally, regardless of distance_from (matches profile.clj / py) -- distance_from is not consulted for this rule. Locked in by tests/test_schema_validator.py::test_switch_distance_bounds_independent_of_distance_from in py, which now validates through the public a7p.validate() path (schema_validator.py), not just the old yupy_schema.py.', 'x-discrepancy': "js and dart instead branch on distance_from: when INDEX, they validate 'distance' as an index in [0,255] into the distances array; when VALUE, as [100,300000]. Not fixed there yet -- this is a semantic fork, not just a range typo, and would require changing validation logic (not just a numeric constant) in both."}, 'reticle_idx': {'type': 'integer', 'minimum': 0, 'maximum': 255, 'x-fraction-digits': 0}, 'zoom': {'type': 'integer', 'minimum': 0, 'maximum': 6, 'x-fraction-digits': 0, 'description': '0 = unset/default (observed in real profiles for switches with distance_from=INDEX acting as a placeholder entry), 1-6 = real zoom levels on the device.', 'x-fixed': "dart's A7pValidator already checked 0-6 (matching this schema); its A7pFieldConstraints.zoom metadata said min 1, contradicting its own validator and the real shipped profiles below -- doc comment updated to 0-6. js validate.ts previously did not restrict this at all (0-255) -- now bounded to 0-6. py's public a7p.validate() uses this schema directly (0-6), confirmed by tests/test_schema_validator.py::test_switch_zoom_bounds.", 'x-discrepancy': "profile.clj says 0-4 (documented bug, not used here). py's yupy_schema.py module still hard-codes 0-4 in its own tests/regression suite (test_yupy_schema.py), but that module is no longer wired into the public a7p.validate() path, so this doesn't affect real validation -- only relevant if someone imports a7p.yupy_schema directly. Confirmed against real shipped profiles: py/tests/data/example2.a7p and js/scripts/example2.a7p both ship a switch with zoom == 0."}}}}, rule='type')
            data__switches_is_list = isinstance(data__switches, (list, tuple))
            if data__switches_is_list:
                data__switches_len = len(data__switches)
                if data__switches_len < 4:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".switches must contain at least 4 items", value=data__switches, name="" + (name_prefix or "data") + ".switches", definition={'type': 'array', 'minItems': 4, 'items': {'type': 'object', 'additionalProperties': False, 'required': ['c_idx', 'distance_from', 'distance', 'reticle_idx', 'zoom'], 'properties': {'c_idx': {'description': "Index into coef_rows, or 255 meaning 'unused'.", 'oneOf': [{'type': 'integer', 'minimum': 0, 'maximum': 200}, {'const': 255}], 'x-decision': 'Resolved: 201-254 is rejected (matches profile.clj / py). Locked in by tests/test_schema_validator.py::test_switch_c_idx_bounds in py, which now validates through the public a7p.validate() path (schema_validator.py), not just the old yupy_schema.py.', 'x-discrepancy': "js and dart's A7pValidator both still accept the full 0-255 range unconditionally -- not fixed there yet; would require changing validation logic (not just a numeric constant) in both."}, 'distance_from': {'$ref': '#/$defs/DistanceFrom'}, 'distance': {'description': "Either the 'unused' sentinel 0, or a real distance in [100, 300000] raw (1.0-3000.0 m, 2 fraction digits) -- per profile.clj's (s/or :distance ::distance :unused zero?), unconditional on distance_from.", 'oneOf': [{'const': 0}, {'type': 'integer', 'minimum': 100, 'maximum': 300000}], 'x-fraction-digits': 2, 'x-ui-fraction-digits': 0, 'x-unit': 'm', 'x-decision': 'Resolved: distance is 0-or-[100,300000] unconditionally, regardless of distance_from (matches profile.clj / py) -- distance_from is not consulted for this rule. Locked in by tests/test_schema_validator.py::test_switch_distance_bounds_independent_of_distance_from in py, which now validates through the public a7p.validate() path (schema_validator.py), not just the old yupy_schema.py.', 'x-discrepancy': "js and dart instead branch on distance_from: when INDEX, they validate 'distance' as an index in [0,255] into the distances array; when VALUE, as [100,300000]. Not fixed there yet -- this is a semantic fork, not just a range typo, and would require changing validation logic (not just a numeric constant) in both."}, 'reticle_idx': {'type': 'integer', 'minimum': 0, 'maximum': 255, 'x-fraction-digits': 0}, 'zoom': {'type': 'integer', 'minimum': 0, 'maximum': 6, 'x-fraction-digits': 0, 'description': '0 = unset/default (observed in real profiles for switches with distance_from=INDEX acting as a placeholder entry), 1-6 = real zoom levels on the device.', 'x-fixed': "dart's A7pValidator already checked 0-6 (matching this schema); its A7pFieldConstraints.zoom metadata said min 1, contradicting its own validator and the real shipped profiles below -- doc comment updated to 0-6. js validate.ts previously did not restrict this at all (0-255) -- now bounded to 0-6. py's public a7p.validate() uses this schema directly (0-6), confirmed by tests/test_schema_validator.py::test_switch_zoom_bounds.", 'x-discrepancy': "profile.clj says 0-4 (documented bug, not used here). py's yupy_schema.py module still hard-codes 0-4 in its own tests/regression suite (test_yupy_schema.py), but that module is no longer wired into the public a7p.validate() path, so this doesn't affect real validation -- only relevant if someone imports a7p.yupy_schema directly. Confirmed against real shipped profiles: py/tests/data/example2.a7p and js/scripts/example2.a7p both ship a switch with zoom == 0."}}}}, rule='minItems')
                for data__switches_x, data__switches_item in enumerate(data__switches):
                    validate_https___a7p_cross_schema_a7p_schema_json___defs_switchprops(data__switches_item, custom_formats, (name_prefix or "data") + ".switches[{data__switches_x}]".format(**locals()))
        if "distances" in data_keys:
            data_keys.remove("distances")
            data__distances = data["distances"]
            if not isinstance(data__distances, (list, tuple)):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".distances must be array", value=data__distances, name="" + (name_prefix or "data") + ".distances", definition={'type': 'array', 'minItems': 1, 'maxItems': 200, 'items': {'type': 'integer', 'minimum': 100, 'maximum': 300000, 'x-fraction-digits': 2, 'x-ui-fraction-digits': 0, 'x-unit': 'm'}}, rule='type')
            data__distances_is_list = isinstance(data__distances, (list, tuple))
            if data__distances_is_list:
                data__distances_len = len(data__distances)
                if data__distances_len < 1:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".distances must contain at least 1 items", value=data__distances, name="" + (name_prefix or "data") + ".distances", definition={'type': 'array', 'minItems': 1, 'maxItems': 200, 'items': {'type': 'integer', 'minimum': 100, 'maximum': 300000, 'x-fraction-digits': 2, 'x-ui-fraction-digits': 0, 'x-unit': 'm'}}, rule='minItems')
                if data__distances_len > 200:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".distances must contain less than or equal to 200 items", value=data__distances, name="" + (name_prefix or "data") + ".distances", definition={'type': 'array', 'minItems': 1, 'maxItems': 200, 'items': {'type': 'integer', 'minimum': 100, 'maximum': 300000, 'x-fraction-digits': 2, 'x-ui-fraction-digits': 0, 'x-unit': 'm'}}, rule='maxItems')
                for data__distances_x, data__distances_item in enumerate(data__distances):
                    if not isinstance(data__distances_item, (int)) and not (isinstance(data__distances_item, float) and data__distances_item.is_integer()) or isinstance(data__distances_item, bool):
                        raise JsonSchemaValueException("" + (name_prefix or "data") + ".distances[{data__distances_x}]".format(**locals()) + " must be integer", value=data__distances_item, name="" + (name_prefix or "data") + ".distances[{data__distances_x}]".format(**locals()) + "", definition={'type': 'integer', 'minimum': 100, 'maximum': 300000, 'x-fraction-digits': 2, 'x-ui-fraction-digits': 0, 'x-unit': 'm'}, rule='type')
                    if isinstance(data__distances_item, (int, float, Decimal)):
                        if data__distances_item < 100:
                            raise JsonSchemaValueException("" + (name_prefix or "data") + ".distances[{data__distances_x}]".format(**locals()) + " must be bigger than or equal to 100", value=data__distances_item, name="" + (name_prefix or "data") + ".distances[{data__distances_x}]".format(**locals()) + "", definition={'type': 'integer', 'minimum': 100, 'maximum': 300000, 'x-fraction-digits': 2, 'x-ui-fraction-digits': 0, 'x-unit': 'm'}, rule='minimum')
                        if data__distances_item > 300000:
                            raise JsonSchemaValueException("" + (name_prefix or "data") + ".distances[{data__distances_x}]".format(**locals()) + " must be smaller than or equal to 300000", value=data__distances_item, name="" + (name_prefix or "data") + ".distances[{data__distances_x}]".format(**locals()) + "", definition={'type': 'integer', 'minimum': 100, 'maximum': 300000, 'x-fraction-digits': 2, 'x-ui-fraction-digits': 0, 'x-unit': 'm'}, rule='maximum')
        if "coef_rows" in data_keys:
            data_keys.remove("coef_rows")
            data__coefrows = data["coef_rows"]
            if not isinstance(data__coefrows, (list, tuple)):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".coef_rows must be array", value=data__coefrows, name="" + (name_prefix or "data") + ".coef_rows", definition={'type': 'array', 'minItems': 1, 'items': {'type': 'object', 'additionalProperties': False, 'required': ['bc_cd', 'mv'], 'properties': {'bc_cd': {'type': 'integer', 'minimum': 0, 'maximum': 100000, 'x-fraction-digits': 4, 'x-ui-fraction-digits': 3, 'description': "Holds 'bc' (drag model G1/G7) or 'cd' (CUSTOM drag model); both share the same 0.0-10.0 display range.", 'x-fixed': 'js validate.ts capped this at raw 10000 (display max 1.0) instead of 100000 (display max 10.0), matching profile.clj / py / dart -- fixed.'}, 'mv': {'type': 'integer', 'minimum': 0, 'x-unit': 'm/s (G1/G7) or Ma (CUSTOM)', 'description': "Muzzle velocity for G1/G7 rows (0.0-3000.0 m/s, 1 fraction digit -> raw max 30000), or Mach number 'ma' for CUSTOM rows (0.0-10.0, 4 fraction digits -> raw max 100000). Effective maximum is set contextually by the CoefRows if/then below.", 'x-fixed': 'js capped CUSTOM mv at raw 10000 instead of 100000 -- same missing-factor-of-10 issue as bc_cd above -- fixed.'}}}, 'x-unique-except-zero': 'mv', 'description': "Not expressible in plain JSON Schema: all 'mv' values must be unique except that any number of rows may have mv == 0. Enforce with one small hand-written check per language, run against schema/fixtures/ to keep behavior in sync.", 'if': {'properties': {'bc_type': {'const': 'CUSTOM'}}}, 'then': {'maxItems': 200, 'items': {'properties': {'mv': {'maximum': 100000}}}}, 'else': {'maxItems': 5, 'items': {'properties': {'mv': {'maximum': 30000}}}}}, rule='type')
            data__coefrows_is_list = isinstance(data__coefrows, (list, tuple))
            if data__coefrows_is_list:
                data__coefrows_len = len(data__coefrows)
                if data__coefrows_len < 1:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".coef_rows must contain at least 1 items", value=data__coefrows, name="" + (name_prefix or "data") + ".coef_rows", definition={'type': 'array', 'minItems': 1, 'items': {'type': 'object', 'additionalProperties': False, 'required': ['bc_cd', 'mv'], 'properties': {'bc_cd': {'type': 'integer', 'minimum': 0, 'maximum': 100000, 'x-fraction-digits': 4, 'x-ui-fraction-digits': 3, 'description': "Holds 'bc' (drag model G1/G7) or 'cd' (CUSTOM drag model); both share the same 0.0-10.0 display range.", 'x-fixed': 'js validate.ts capped this at raw 10000 (display max 1.0) instead of 100000 (display max 10.0), matching profile.clj / py / dart -- fixed.'}, 'mv': {'type': 'integer', 'minimum': 0, 'x-unit': 'm/s (G1/G7) or Ma (CUSTOM)', 'description': "Muzzle velocity for G1/G7 rows (0.0-3000.0 m/s, 1 fraction digit -> raw max 30000), or Mach number 'ma' for CUSTOM rows (0.0-10.0, 4 fraction digits -> raw max 100000). Effective maximum is set contextually by the CoefRows if/then below.", 'x-fixed': 'js capped CUSTOM mv at raw 10000 instead of 100000 -- same missing-factor-of-10 issue as bc_cd above -- fixed.'}}}, 'x-unique-except-zero': 'mv', 'description': "Not expressible in plain JSON Schema: all 'mv' values must be unique except that any number of rows may have mv == 0. Enforce with one small hand-written check per language, run against schema/fixtures/ to keep behavior in sync.", 'if': {'properties': {'bc_type': {'const': 'CUSTOM'}}}, 'then': {'maxItems': 200, 'items': {'properties': {'mv': {'maximum': 100000}}}}, 'else': {'maxItems': 5, 'items': {'properties': {'mv': {'maximum': 30000}}}}}, rule='minItems')
                for data__coefrows_x, data__coefrows_item in enumerate(data__coefrows):
                    validate_https___a7p_cross_schema_a7p_schema_json___defs_coefrow(data__coefrows_item, custom_formats, (name_prefix or "data") + ".coef_rows[{data__coefrows_x}]".format(**locals()))
            try:
                data__coefrows_is_dict = isinstance(data__coefrows, dict)
                if data__coefrows_is_dict:
                    data__coefrows_keys = set(data__coefrows.keys())
                    if "bc_type" in data__coefrows_keys:
                        data__coefrows_keys.remove("bc_type")
                        data__coefrows__bctype = data__coefrows["bc_type"]
                        if data__coefrows__bctype != "CUSTOM":
                            raise JsonSchemaValueException("" + (name_prefix or "data") + ".coef_rows.bc_type must be same as const definition: CUSTOM", value=data__coefrows__bctype, name="" + (name_prefix or "data") + ".coef_rows.bc_type", definition={'const': 'CUSTOM'}, rule='const')
            except JsonSchemaValueException:
                data__coefrows_is_list = isinstance(data__coefrows, (list, tuple))
                if data__coefrows_is_list:
                    data__coefrows_len = len(data__coefrows)
                    if data__coefrows_len > 5:
                        raise JsonSchemaValueException("" + (name_prefix or "data") + ".coef_rows must contain less than or equal to 5 items", value=data__coefrows, name="" + (name_prefix or "data") + ".coef_rows", definition={'maxItems': 5, 'items': {'properties': {'mv': {'maximum': 30000}}}}, rule='maxItems')
                    for data__coefrows_x, data__coefrows_item in enumerate(data__coefrows):
                        data__coefrows_item_is_dict = isinstance(data__coefrows_item, dict)
                        if data__coefrows_item_is_dict:
                            data__coefrows_item_keys = set(data__coefrows_item.keys())
                            if "mv" in data__coefrows_item_keys:
                                data__coefrows_item_keys.remove("mv")
                                data__coefrows_item__mv = data__coefrows_item["mv"]
                                if isinstance(data__coefrows_item__mv, (int, float, Decimal)):
                                    if data__coefrows_item__mv > 30000:
                                        raise JsonSchemaValueException("" + (name_prefix or "data") + ".coef_rows[{data__coefrows_x}].mv".format(**locals()) + " must be smaller than or equal to 30000", value=data__coefrows_item__mv, name="" + (name_prefix or "data") + ".coef_rows[{data__coefrows_x}].mv".format(**locals()) + "", definition={'maximum': 30000}, rule='maximum')
            else:
                data__coefrows_is_list = isinstance(data__coefrows, (list, tuple))
                if data__coefrows_is_list:
                    data__coefrows_len = len(data__coefrows)
                    if data__coefrows_len > 200:
                        raise JsonSchemaValueException("" + (name_prefix or "data") + ".coef_rows must contain less than or equal to 200 items", value=data__coefrows, name="" + (name_prefix or "data") + ".coef_rows", definition={'maxItems': 200, 'items': {'properties': {'mv': {'maximum': 100000}}}}, rule='maxItems')
                    for data__coefrows_x, data__coefrows_item in enumerate(data__coefrows):
                        data__coefrows_item_is_dict = isinstance(data__coefrows_item, dict)
                        if data__coefrows_item_is_dict:
                            data__coefrows_item_keys = set(data__coefrows_item.keys())
                            if "mv" in data__coefrows_item_keys:
                                data__coefrows_item_keys.remove("mv")
                                data__coefrows_item__mv = data__coefrows_item["mv"]
                                if isinstance(data__coefrows_item__mv, (int, float, Decimal)):
                                    if data__coefrows_item__mv > 100000:
                                        raise JsonSchemaValueException("" + (name_prefix or "data") + ".coef_rows[{data__coefrows_x}].mv".format(**locals()) + " must be smaller than or equal to 100000", value=data__coefrows_item__mv, name="" + (name_prefix or "data") + ".coef_rows[{data__coefrows_x}].mv".format(**locals()) + "", definition={'maximum': 100000}, rule='maximum')
        if data_keys:
            raise JsonSchemaValueException("" + (name_prefix or "data") + " must not contain "+str(data_keys)+" properties", value=data, name="" + (name_prefix or "data") + "", definition={'type': 'object', 'additionalProperties': False, 'required': ['profile_name', 'cartridge_name', 'bullet_name', 'short_name_top', 'short_name_bot', 'caliber', 'device_uuid', 'user_note', 'zero_x', 'zero_y', 'sc_height', 'r_twist', 'twist_dir', 'c_muzzle_velocity', 'c_zero_temperature', 'c_t_coeff', 'c_zero_distance_idx', 'c_zero_air_temperature', 'c_zero_air_pressure', 'c_zero_air_humidity', 'c_zero_w_pitch', 'c_zero_p_temperature', 'b_diameter', 'b_weight', 'b_length', 'bc_type', 'switches', 'distances', 'coef_rows'], 'properties': {'profile_name': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'cartridge_name': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'bullet_name': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'short_name_top': {'type': 'string', 'minLength': 1, 'maxLength': 8}, 'short_name_bot': {'type': 'string', 'minLength': 1, 'maxLength': 8}, 'caliber': {'type': 'string', 'minLength': 1, 'maxLength': 50}, 'device_uuid': {'type': 'string', 'maxLength': 50}, 'user_note': {'type': 'string', 'maxLength': 1024}, 'zero_x': {'type': 'integer', 'minimum': -200000, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'click'}, 'zero_y': {'type': 'integer', 'minimum': -200000, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'click'}, 'sc_height': {'type': 'integer', 'minimum': -5000, 'maximum': 5000, 'x-fraction-digits': 0, 'x-unit': 'mm'}, 'r_twist': {'type': 'integer', 'minimum': 0, 'maximum': 10000, 'x-fraction-digits': 2, 'x-unit': 'in/turn'}, 'twist_dir': {'type': 'string', 'enum': ['RIGHT', 'LEFT']}, 'c_muzzle_velocity': {'type': 'integer', 'minimum': 100, 'maximum': 30000, 'x-fraction-digits': 1, 'x-ui-fraction-digits': 0, 'x-unit': 'm/s', 'x-fixed': "dart's A7pValidator checked minimum 10 instead of 100 (its own A7pFieldConstraints.muzzleVelocity implies raw min 100: 10.0 * 10^1) -- fixed."}, 'c_zero_temperature': {'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, 'c_t_coeff': {'type': 'integer', 'minimum': 0, 'maximum': 5000, 'x-fraction-digits': 3, 'x-unit': '%/15°C'}, 'c_zero_distance_idx': {'type': 'integer', 'minimum': 0, 'maximum': 255, 'x-fraction-digits': 0, 'description': "Index into 'distances'.", 'x-discrepancy': "dart's A7pValidator instead bounds this dynamically by len(distances)-1 rather than a fixed 255 -- a cross-field constraint plain JSON Schema can't express without a custom keyword/extension. profile.clj / py / js all use the static 0-255 range encoded here."}, 'c_zero_air_temperature': {'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, 'c_zero_air_pressure': {'type': 'integer', 'minimum': 3000, 'maximum': 15000, 'x-fraction-digits': 1, 'x-ui-fraction-digits': 0, 'x-unit': 'hPa'}, 'c_zero_air_humidity': {'type': 'integer', 'minimum': 0, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '%'}, 'c_zero_w_pitch': {'type': 'integer', 'minimum': -90, 'maximum': 90, 'x-fraction-digits': 0, 'x-unit': '°', 'x-fixed': "dart's A7pValidator did not check this field at all (present in A7pFieldConstraints but missing from _validateProfile) -- check added."}, 'c_zero_p_temperature': {'type': 'integer', 'minimum': -100, 'maximum': 100, 'x-fraction-digits': 0, 'x-unit': '°C'}, 'b_diameter': {'type': 'integer', 'minimum': 1, 'maximum': 50000, 'x-fraction-digits': 3, 'x-unit': 'in'}, 'b_weight': {'type': 'integer', 'minimum': 10, 'maximum': 65535, 'x-fraction-digits': 1, 'x-unit': 'gr', 'x-fixed': "dart's A7pValidator checked minimum 1 instead of 10 (its own A7pFieldConstraints.bulletWeight implies raw min 10: 1.0 * 10^1) -- fixed."}, 'b_length': {'type': 'integer', 'minimum': 10, 'maximum': 200000, 'x-fraction-digits': 3, 'x-unit': 'in', 'x-fixed': "dart's A7pValidator used min 0 instead of 10 -- fixed. js validate.ts used min 1 instead of 10 -- fixed."}, 'bc_type': {'type': 'string', 'enum': ['G1', 'G7', 'CUSTOM']}, 'switches': {'type': 'array', 'minItems': 4, 'items': {'type': 'object', 'additionalProperties': False, 'required': ['c_idx', 'distance_from', 'distance', 'reticle_idx', 'zoom'], 'properties': {'c_idx': {'description': "Index into coef_rows, or 255 meaning 'unused'.", 'oneOf': [{'type': 'integer', 'minimum': 0, 'maximum': 200}, {'const': 255}], 'x-decision': 'Resolved: 201-254 is rejected (matches profile.clj / py). Locked in by tests/test_schema_validator.py::test_switch_c_idx_bounds in py, which now validates through the public a7p.validate() path (schema_validator.py), not just the old yupy_schema.py.', 'x-discrepancy': "js and dart's A7pValidator both still accept the full 0-255 range unconditionally -- not fixed there yet; would require changing validation logic (not just a numeric constant) in both."}, 'distance_from': {'$ref': '#/$defs/DistanceFrom'}, 'distance': {'description': "Either the 'unused' sentinel 0, or a real distance in [100, 300000] raw (1.0-3000.0 m, 2 fraction digits) -- per profile.clj's (s/or :distance ::distance :unused zero?), unconditional on distance_from.", 'oneOf': [{'const': 0}, {'type': 'integer', 'minimum': 100, 'maximum': 300000}], 'x-fraction-digits': 2, 'x-ui-fraction-digits': 0, 'x-unit': 'm', 'x-decision': 'Resolved: distance is 0-or-[100,300000] unconditionally, regardless of distance_from (matches profile.clj / py) -- distance_from is not consulted for this rule. Locked in by tests/test_schema_validator.py::test_switch_distance_bounds_independent_of_distance_from in py, which now validates through the public a7p.validate() path (schema_validator.py), not just the old yupy_schema.py.', 'x-discrepancy': "js and dart instead branch on distance_from: when INDEX, they validate 'distance' as an index in [0,255] into the distances array; when VALUE, as [100,300000]. Not fixed there yet -- this is a semantic fork, not just a range typo, and would require changing validation logic (not just a numeric constant) in both."}, 'reticle_idx': {'type': 'integer', 'minimum': 0, 'maximum': 255, 'x-fraction-digits': 0}, 'zoom': {'type': 'integer', 'minimum': 0, 'maximum': 6, 'x-fraction-digits': 0, 'description': '0 = unset/default (observed in real profiles for switches with distance_from=INDEX acting as a placeholder entry), 1-6 = real zoom levels on the device.', 'x-fixed': "dart's A7pValidator already checked 0-6 (matching this schema); its A7pFieldConstraints.zoom metadata said min 1, contradicting its own validator and the real shipped profiles below -- doc comment updated to 0-6. js validate.ts previously did not restrict this at all (0-255) -- now bounded to 0-6. py's public a7p.validate() uses this schema directly (0-6), confirmed by tests/test_schema_validator.py::test_switch_zoom_bounds.", 'x-discrepancy': "profile.clj says 0-4 (documented bug, not used here). py's yupy_schema.py module still hard-codes 0-4 in its own tests/regression suite (test_yupy_schema.py), but that module is no longer wired into the public a7p.validate() path, so this doesn't affect real validation -- only relevant if someone imports a7p.yupy_schema directly. Confirmed against real shipped profiles: py/tests/data/example2.a7p and js/scripts/example2.a7p both ship a switch with zoom == 0."}}}}, 'distances': {'type': 'array', 'minItems': 1, 'maxItems': 200, 'items': {'type': 'integer', 'minimum': 100, 'maximum': 300000, 'x-fraction-digits': 2, 'x-ui-fraction-digits': 0, 'x-unit': 'm'}}, 'coef_rows': {'type': 'array', 'minItems': 1, 'items': {'type': 'object', 'additionalProperties': False, 'required': ['bc_cd', 'mv'], 'properties': {'bc_cd': {'type': 'integer', 'minimum': 0, 'maximum': 100000, 'x-fraction-digits': 4, 'x-ui-fraction-digits': 3, 'description': "Holds 'bc' (drag model G1/G7) or 'cd' (CUSTOM drag model); both share the same 0.0-10.0 display range.", 'x-fixed': 'js validate.ts capped this at raw 10000 (display max 1.0) instead of 100000 (display max 10.0), matching profile.clj / py / dart -- fixed.'}, 'mv': {'type': 'integer', 'minimum': 0, 'x-unit': 'm/s (G1/G7) or Ma (CUSTOM)', 'description': "Muzzle velocity for G1/G7 rows (0.0-3000.0 m/s, 1 fraction digit -> raw max 30000), or Mach number 'ma' for CUSTOM rows (0.0-10.0, 4 fraction digits -> raw max 100000). Effective maximum is set contextually by the CoefRows if/then below.", 'x-fixed': 'js capped CUSTOM mv at raw 10000 instead of 100000 -- same missing-factor-of-10 issue as bc_cd above -- fixed.'}}}, 'x-unique-except-zero': 'mv', 'description': "Not expressible in plain JSON Schema: all 'mv' values must be unique except that any number of rows may have mv == 0. Enforce with one small hand-written check per language, run against schema/fixtures/ to keep behavior in sync.", 'if': {'properties': {'bc_type': {'const': 'CUSTOM'}}}, 'then': {'maxItems': 200, 'items': {'properties': {'mv': {'maximum': 100000}}}}, 'else': {'maxItems': 5, 'items': {'properties': {'mv': {'maximum': 30000}}}}}}}, rule='additionalProperties')
    return data

def validate_https___a7p_cross_schema_a7p_schema_json___defs_coefrow(data, custom_formats={}, name_prefix=None):
    if not isinstance(data, (dict)):
        raise JsonSchemaValueException("" + (name_prefix or "data") + " must be object", value=data, name="" + (name_prefix or "data") + "", definition={'type': 'object', 'additionalProperties': False, 'required': ['bc_cd', 'mv'], 'properties': {'bc_cd': {'type': 'integer', 'minimum': 0, 'maximum': 100000, 'x-fraction-digits': 4, 'x-ui-fraction-digits': 3, 'description': "Holds 'bc' (drag model G1/G7) or 'cd' (CUSTOM drag model); both share the same 0.0-10.0 display range.", 'x-fixed': 'js validate.ts capped this at raw 10000 (display max 1.0) instead of 100000 (display max 10.0), matching profile.clj / py / dart -- fixed.'}, 'mv': {'type': 'integer', 'minimum': 0, 'x-unit': 'm/s (G1/G7) or Ma (CUSTOM)', 'description': "Muzzle velocity for G1/G7 rows (0.0-3000.0 m/s, 1 fraction digit -> raw max 30000), or Mach number 'ma' for CUSTOM rows (0.0-10.0, 4 fraction digits -> raw max 100000). Effective maximum is set contextually by the CoefRows if/then below.", 'x-fixed': 'js capped CUSTOM mv at raw 10000 instead of 100000 -- same missing-factor-of-10 issue as bc_cd above -- fixed.'}}}, rule='type')
    data_is_dict = isinstance(data, dict)
    if data_is_dict:
        data__missing_keys = set(['bc_cd', 'mv']) - data.keys()
        if data__missing_keys:
            raise JsonSchemaValueException("" + (name_prefix or "data") + " must contain " + (str(sorted(data__missing_keys)) + " properties"), value=data, name="" + (name_prefix or "data") + "", definition={'type': 'object', 'additionalProperties': False, 'required': ['bc_cd', 'mv'], 'properties': {'bc_cd': {'type': 'integer', 'minimum': 0, 'maximum': 100000, 'x-fraction-digits': 4, 'x-ui-fraction-digits': 3, 'description': "Holds 'bc' (drag model G1/G7) or 'cd' (CUSTOM drag model); both share the same 0.0-10.0 display range.", 'x-fixed': 'js validate.ts capped this at raw 10000 (display max 1.0) instead of 100000 (display max 10.0), matching profile.clj / py / dart -- fixed.'}, 'mv': {'type': 'integer', 'minimum': 0, 'x-unit': 'm/s (G1/G7) or Ma (CUSTOM)', 'description': "Muzzle velocity for G1/G7 rows (0.0-3000.0 m/s, 1 fraction digit -> raw max 30000), or Mach number 'ma' for CUSTOM rows (0.0-10.0, 4 fraction digits -> raw max 100000). Effective maximum is set contextually by the CoefRows if/then below.", 'x-fixed': 'js capped CUSTOM mv at raw 10000 instead of 100000 -- same missing-factor-of-10 issue as bc_cd above -- fixed.'}}}, rule='required')
        data_keys = set(data.keys())
        if "bc_cd" in data_keys:
            data_keys.remove("bc_cd")
            data__bccd = data["bc_cd"]
            if not isinstance(data__bccd, (int)) and not (isinstance(data__bccd, float) and data__bccd.is_integer()) or isinstance(data__bccd, bool):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".bc_cd must be integer", value=data__bccd, name="" + (name_prefix or "data") + ".bc_cd", definition={'type': 'integer', 'minimum': 0, 'maximum': 100000, 'x-fraction-digits': 4, 'x-ui-fraction-digits': 3, 'description': "Holds 'bc' (drag model G1/G7) or 'cd' (CUSTOM drag model); both share the same 0.0-10.0 display range.", 'x-fixed': 'js validate.ts capped this at raw 10000 (display max 1.0) instead of 100000 (display max 10.0), matching profile.clj / py / dart -- fixed.'}, rule='type')
            if isinstance(data__bccd, (int, float, Decimal)):
                if data__bccd < 0:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".bc_cd must be bigger than or equal to 0", value=data__bccd, name="" + (name_prefix or "data") + ".bc_cd", definition={'type': 'integer', 'minimum': 0, 'maximum': 100000, 'x-fraction-digits': 4, 'x-ui-fraction-digits': 3, 'description': "Holds 'bc' (drag model G1/G7) or 'cd' (CUSTOM drag model); both share the same 0.0-10.0 display range.", 'x-fixed': 'js validate.ts capped this at raw 10000 (display max 1.0) instead of 100000 (display max 10.0), matching profile.clj / py / dart -- fixed.'}, rule='minimum')
                if data__bccd > 100000:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".bc_cd must be smaller than or equal to 100000", value=data__bccd, name="" + (name_prefix or "data") + ".bc_cd", definition={'type': 'integer', 'minimum': 0, 'maximum': 100000, 'x-fraction-digits': 4, 'x-ui-fraction-digits': 3, 'description': "Holds 'bc' (drag model G1/G7) or 'cd' (CUSTOM drag model); both share the same 0.0-10.0 display range.", 'x-fixed': 'js validate.ts capped this at raw 10000 (display max 1.0) instead of 100000 (display max 10.0), matching profile.clj / py / dart -- fixed.'}, rule='maximum')
        if "mv" in data_keys:
            data_keys.remove("mv")
            data__mv = data["mv"]
            if not isinstance(data__mv, (int)) and not (isinstance(data__mv, float) and data__mv.is_integer()) or isinstance(data__mv, bool):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".mv must be integer", value=data__mv, name="" + (name_prefix or "data") + ".mv", definition={'type': 'integer', 'minimum': 0, 'x-unit': 'm/s (G1/G7) or Ma (CUSTOM)', 'description': "Muzzle velocity for G1/G7 rows (0.0-3000.0 m/s, 1 fraction digit -> raw max 30000), or Mach number 'ma' for CUSTOM rows (0.0-10.0, 4 fraction digits -> raw max 100000). Effective maximum is set contextually by the CoefRows if/then below.", 'x-fixed': 'js capped CUSTOM mv at raw 10000 instead of 100000 -- same missing-factor-of-10 issue as bc_cd above -- fixed.'}, rule='type')
            if isinstance(data__mv, (int, float, Decimal)):
                if data__mv < 0:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".mv must be bigger than or equal to 0", value=data__mv, name="" + (name_prefix or "data") + ".mv", definition={'type': 'integer', 'minimum': 0, 'x-unit': 'm/s (G1/G7) or Ma (CUSTOM)', 'description': "Muzzle velocity for G1/G7 rows (0.0-3000.0 m/s, 1 fraction digit -> raw max 30000), or Mach number 'ma' for CUSTOM rows (0.0-10.0, 4 fraction digits -> raw max 100000). Effective maximum is set contextually by the CoefRows if/then below.", 'x-fixed': 'js capped CUSTOM mv at raw 10000 instead of 100000 -- same missing-factor-of-10 issue as bc_cd above -- fixed.'}, rule='minimum')
        if data_keys:
            raise JsonSchemaValueException("" + (name_prefix or "data") + " must not contain "+str(data_keys)+" properties", value=data, name="" + (name_prefix or "data") + "", definition={'type': 'object', 'additionalProperties': False, 'required': ['bc_cd', 'mv'], 'properties': {'bc_cd': {'type': 'integer', 'minimum': 0, 'maximum': 100000, 'x-fraction-digits': 4, 'x-ui-fraction-digits': 3, 'description': "Holds 'bc' (drag model G1/G7) or 'cd' (CUSTOM drag model); both share the same 0.0-10.0 display range.", 'x-fixed': 'js validate.ts capped this at raw 10000 (display max 1.0) instead of 100000 (display max 10.0), matching profile.clj / py / dart -- fixed.'}, 'mv': {'type': 'integer', 'minimum': 0, 'x-unit': 'm/s (G1/G7) or Ma (CUSTOM)', 'description': "Muzzle velocity for G1/G7 rows (0.0-3000.0 m/s, 1 fraction digit -> raw max 30000), or Mach number 'ma' for CUSTOM rows (0.0-10.0, 4 fraction digits -> raw max 100000). Effective maximum is set contextually by the CoefRows if/then below.", 'x-fixed': 'js capped CUSTOM mv at raw 10000 instead of 100000 -- same missing-factor-of-10 issue as bc_cd above -- fixed.'}}}, rule='additionalProperties')
    return data

def validate_https___a7p_cross_schema_a7p_schema_json___defs_switchprops(data, custom_formats={}, name_prefix=None):
    if not isinstance(data, (dict)):
        raise JsonSchemaValueException("" + (name_prefix or "data") + " must be object", value=data, name="" + (name_prefix or "data") + "", definition={'type': 'object', 'additionalProperties': False, 'required': ['c_idx', 'distance_from', 'distance', 'reticle_idx', 'zoom'], 'properties': {'c_idx': {'description': "Index into coef_rows, or 255 meaning 'unused'.", 'oneOf': [{'type': 'integer', 'minimum': 0, 'maximum': 200}, {'const': 255}], 'x-decision': 'Resolved: 201-254 is rejected (matches profile.clj / py). Locked in by tests/test_schema_validator.py::test_switch_c_idx_bounds in py, which now validates through the public a7p.validate() path (schema_validator.py), not just the old yupy_schema.py.', 'x-discrepancy': "js and dart's A7pValidator both still accept the full 0-255 range unconditionally -- not fixed there yet; would require changing validation logic (not just a numeric constant) in both."}, 'distance_from': {'type': 'string', 'enum': ['VALUE', 'INDEX']}, 'distance': {'description': "Either the 'unused' sentinel 0, or a real distance in [100, 300000] raw (1.0-3000.0 m, 2 fraction digits) -- per profile.clj's (s/or :distance ::distance :unused zero?), unconditional on distance_from.", 'oneOf': [{'const': 0}, {'type': 'integer', 'minimum': 100, 'maximum': 300000}], 'x-fraction-digits': 2, 'x-ui-fraction-digits': 0, 'x-unit': 'm', 'x-decision': 'Resolved: distance is 0-or-[100,300000] unconditionally, regardless of distance_from (matches profile.clj / py) -- distance_from is not consulted for this rule. Locked in by tests/test_schema_validator.py::test_switch_distance_bounds_independent_of_distance_from in py, which now validates through the public a7p.validate() path (schema_validator.py), not just the old yupy_schema.py.', 'x-discrepancy': "js and dart instead branch on distance_from: when INDEX, they validate 'distance' as an index in [0,255] into the distances array; when VALUE, as [100,300000]. Not fixed there yet -- this is a semantic fork, not just a range typo, and would require changing validation logic (not just a numeric constant) in both."}, 'reticle_idx': {'type': 'integer', 'minimum': 0, 'maximum': 255, 'x-fraction-digits': 0}, 'zoom': {'type': 'integer', 'minimum': 0, 'maximum': 6, 'x-fraction-digits': 0, 'description': '0 = unset/default (observed in real profiles for switches with distance_from=INDEX acting as a placeholder entry), 1-6 = real zoom levels on the device.', 'x-fixed': "dart's A7pValidator already checked 0-6 (matching this schema); its A7pFieldConstraints.zoom metadata said min 1, contradicting its own validator and the real shipped profiles below -- doc comment updated to 0-6. js validate.ts previously did not restrict this at all (0-255) -- now bounded to 0-6. py's public a7p.validate() uses this schema directly (0-6), confirmed by tests/test_schema_validator.py::test_switch_zoom_bounds.", 'x-discrepancy': "profile.clj says 0-4 (documented bug, not used here). py's yupy_schema.py module still hard-codes 0-4 in its own tests/regression suite (test_yupy_schema.py), but that module is no longer wired into the public a7p.validate() path, so this doesn't affect real validation -- only relevant if someone imports a7p.yupy_schema directly. Confirmed against real shipped profiles: py/tests/data/example2.a7p and js/scripts/example2.a7p both ship a switch with zoom == 0."}}}, rule='type')
    data_is_dict = isinstance(data, dict)
    if data_is_dict:
        data__missing_keys = set(['c_idx', 'distance_from', 'distance', 'reticle_idx', 'zoom']) - data.keys()
        if data__missing_keys:
            raise JsonSchemaValueException("" + (name_prefix or "data") + " must contain " + (str(sorted(data__missing_keys)) + " properties"), value=data, name="" + (name_prefix or "data") + "", definition={'type': 'object', 'additionalProperties': False, 'required': ['c_idx', 'distance_from', 'distance', 'reticle_idx', 'zoom'], 'properties': {'c_idx': {'description': "Index into coef_rows, or 255 meaning 'unused'.", 'oneOf': [{'type': 'integer', 'minimum': 0, 'maximum': 200}, {'const': 255}], 'x-decision': 'Resolved: 201-254 is rejected (matches profile.clj / py). Locked in by tests/test_schema_validator.py::test_switch_c_idx_bounds in py, which now validates through the public a7p.validate() path (schema_validator.py), not just the old yupy_schema.py.', 'x-discrepancy': "js and dart's A7pValidator both still accept the full 0-255 range unconditionally -- not fixed there yet; would require changing validation logic (not just a numeric constant) in both."}, 'distance_from': {'type': 'string', 'enum': ['VALUE', 'INDEX']}, 'distance': {'description': "Either the 'unused' sentinel 0, or a real distance in [100, 300000] raw (1.0-3000.0 m, 2 fraction digits) -- per profile.clj's (s/or :distance ::distance :unused zero?), unconditional on distance_from.", 'oneOf': [{'const': 0}, {'type': 'integer', 'minimum': 100, 'maximum': 300000}], 'x-fraction-digits': 2, 'x-ui-fraction-digits': 0, 'x-unit': 'm', 'x-decision': 'Resolved: distance is 0-or-[100,300000] unconditionally, regardless of distance_from (matches profile.clj / py) -- distance_from is not consulted for this rule. Locked in by tests/test_schema_validator.py::test_switch_distance_bounds_independent_of_distance_from in py, which now validates through the public a7p.validate() path (schema_validator.py), not just the old yupy_schema.py.', 'x-discrepancy': "js and dart instead branch on distance_from: when INDEX, they validate 'distance' as an index in [0,255] into the distances array; when VALUE, as [100,300000]. Not fixed there yet -- this is a semantic fork, not just a range typo, and would require changing validation logic (not just a numeric constant) in both."}, 'reticle_idx': {'type': 'integer', 'minimum': 0, 'maximum': 255, 'x-fraction-digits': 0}, 'zoom': {'type': 'integer', 'minimum': 0, 'maximum': 6, 'x-fraction-digits': 0, 'description': '0 = unset/default (observed in real profiles for switches with distance_from=INDEX acting as a placeholder entry), 1-6 = real zoom levels on the device.', 'x-fixed': "dart's A7pValidator already checked 0-6 (matching this schema); its A7pFieldConstraints.zoom metadata said min 1, contradicting its own validator and the real shipped profiles below -- doc comment updated to 0-6. js validate.ts previously did not restrict this at all (0-255) -- now bounded to 0-6. py's public a7p.validate() uses this schema directly (0-6), confirmed by tests/test_schema_validator.py::test_switch_zoom_bounds.", 'x-discrepancy': "profile.clj says 0-4 (documented bug, not used here). py's yupy_schema.py module still hard-codes 0-4 in its own tests/regression suite (test_yupy_schema.py), but that module is no longer wired into the public a7p.validate() path, so this doesn't affect real validation -- only relevant if someone imports a7p.yupy_schema directly. Confirmed against real shipped profiles: py/tests/data/example2.a7p and js/scripts/example2.a7p both ship a switch with zoom == 0."}}}, rule='required')
        data_keys = set(data.keys())
        if "c_idx" in data_keys:
            data_keys.remove("c_idx")
            data__cidx = data["c_idx"]
            data__cidx_one_of_count1 = 0
            if data__cidx_one_of_count1 < 2:
                try:
                    if not isinstance(data__cidx, (int)) and not (isinstance(data__cidx, float) and data__cidx.is_integer()) or isinstance(data__cidx, bool):
                        raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_idx must be integer", value=data__cidx, name="" + (name_prefix or "data") + ".c_idx", definition={'type': 'integer', 'minimum': 0, 'maximum': 200}, rule='type')
                    if isinstance(data__cidx, (int, float, Decimal)):
                        if data__cidx < 0:
                            raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_idx must be bigger than or equal to 0", value=data__cidx, name="" + (name_prefix or "data") + ".c_idx", definition={'type': 'integer', 'minimum': 0, 'maximum': 200}, rule='minimum')
                        if data__cidx > 200:
                            raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_idx must be smaller than or equal to 200", value=data__cidx, name="" + (name_prefix or "data") + ".c_idx", definition={'type': 'integer', 'minimum': 0, 'maximum': 200}, rule='maximum')
                    data__cidx_one_of_count1 += 1
                except JsonSchemaValueException: pass
            if data__cidx_one_of_count1 < 2:
                try:
                    if data__cidx != 255:
                        raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_idx must be same as const definition: 255", value=data__cidx, name="" + (name_prefix or "data") + ".c_idx", definition={'const': 255}, rule='const')
                    data__cidx_one_of_count1 += 1
                except JsonSchemaValueException: pass
            if data__cidx_one_of_count1 != 1:
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".c_idx must be valid exactly by one definition" + (" (" + str(data__cidx_one_of_count1) + " matches found)"), value=data__cidx, name="" + (name_prefix or "data") + ".c_idx", definition={'description': "Index into coef_rows, or 255 meaning 'unused'.", 'oneOf': [{'type': 'integer', 'minimum': 0, 'maximum': 200}, {'const': 255}], 'x-decision': 'Resolved: 201-254 is rejected (matches profile.clj / py). Locked in by tests/test_schema_validator.py::test_switch_c_idx_bounds in py, which now validates through the public a7p.validate() path (schema_validator.py), not just the old yupy_schema.py.', 'x-discrepancy': "js and dart's A7pValidator both still accept the full 0-255 range unconditionally -- not fixed there yet; would require changing validation logic (not just a numeric constant) in both."}, rule='oneOf')
        if "distance_from" in data_keys:
            data_keys.remove("distance_from")
            data__distancefrom = data["distance_from"]
            validate_https___a7p_cross_schema_a7p_schema_json___defs_distancefrom(data__distancefrom, custom_formats, (name_prefix or "data") + ".distance_from")
        if "distance" in data_keys:
            data_keys.remove("distance")
            data__distance = data["distance"]
            data__distance_one_of_count2 = 0
            if data__distance_one_of_count2 < 2:
                try:
                    if data__distance != 0:
                        raise JsonSchemaValueException("" + (name_prefix or "data") + ".distance must be same as const definition: 0", value=data__distance, name="" + (name_prefix or "data") + ".distance", definition={'const': 0}, rule='const')
                    data__distance_one_of_count2 += 1
                except JsonSchemaValueException: pass
            if data__distance_one_of_count2 < 2:
                try:
                    if not isinstance(data__distance, (int)) and not (isinstance(data__distance, float) and data__distance.is_integer()) or isinstance(data__distance, bool):
                        raise JsonSchemaValueException("" + (name_prefix or "data") + ".distance must be integer", value=data__distance, name="" + (name_prefix or "data") + ".distance", definition={'type': 'integer', 'minimum': 100, 'maximum': 300000}, rule='type')
                    if isinstance(data__distance, (int, float, Decimal)):
                        if data__distance < 100:
                            raise JsonSchemaValueException("" + (name_prefix or "data") + ".distance must be bigger than or equal to 100", value=data__distance, name="" + (name_prefix or "data") + ".distance", definition={'type': 'integer', 'minimum': 100, 'maximum': 300000}, rule='minimum')
                        if data__distance > 300000:
                            raise JsonSchemaValueException("" + (name_prefix or "data") + ".distance must be smaller than or equal to 300000", value=data__distance, name="" + (name_prefix or "data") + ".distance", definition={'type': 'integer', 'minimum': 100, 'maximum': 300000}, rule='maximum')
                    data__distance_one_of_count2 += 1
                except JsonSchemaValueException: pass
            if data__distance_one_of_count2 != 1:
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".distance must be valid exactly by one definition" + (" (" + str(data__distance_one_of_count2) + " matches found)"), value=data__distance, name="" + (name_prefix or "data") + ".distance", definition={'description': "Either the 'unused' sentinel 0, or a real distance in [100, 300000] raw (1.0-3000.0 m, 2 fraction digits) -- per profile.clj's (s/or :distance ::distance :unused zero?), unconditional on distance_from.", 'oneOf': [{'const': 0}, {'type': 'integer', 'minimum': 100, 'maximum': 300000}], 'x-fraction-digits': 2, 'x-ui-fraction-digits': 0, 'x-unit': 'm', 'x-decision': 'Resolved: distance is 0-or-[100,300000] unconditionally, regardless of distance_from (matches profile.clj / py) -- distance_from is not consulted for this rule. Locked in by tests/test_schema_validator.py::test_switch_distance_bounds_independent_of_distance_from in py, which now validates through the public a7p.validate() path (schema_validator.py), not just the old yupy_schema.py.', 'x-discrepancy': "js and dart instead branch on distance_from: when INDEX, they validate 'distance' as an index in [0,255] into the distances array; when VALUE, as [100,300000]. Not fixed there yet -- this is a semantic fork, not just a range typo, and would require changing validation logic (not just a numeric constant) in both."}, rule='oneOf')
        if "reticle_idx" in data_keys:
            data_keys.remove("reticle_idx")
            data__reticleidx = data["reticle_idx"]
            if not isinstance(data__reticleidx, (int)) and not (isinstance(data__reticleidx, float) and data__reticleidx.is_integer()) or isinstance(data__reticleidx, bool):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".reticle_idx must be integer", value=data__reticleidx, name="" + (name_prefix or "data") + ".reticle_idx", definition={'type': 'integer', 'minimum': 0, 'maximum': 255, 'x-fraction-digits': 0}, rule='type')
            if isinstance(data__reticleidx, (int, float, Decimal)):
                if data__reticleidx < 0:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".reticle_idx must be bigger than or equal to 0", value=data__reticleidx, name="" + (name_prefix or "data") + ".reticle_idx", definition={'type': 'integer', 'minimum': 0, 'maximum': 255, 'x-fraction-digits': 0}, rule='minimum')
                if data__reticleidx > 255:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".reticle_idx must be smaller than or equal to 255", value=data__reticleidx, name="" + (name_prefix or "data") + ".reticle_idx", definition={'type': 'integer', 'minimum': 0, 'maximum': 255, 'x-fraction-digits': 0}, rule='maximum')
        if "zoom" in data_keys:
            data_keys.remove("zoom")
            data__zoom = data["zoom"]
            if not isinstance(data__zoom, (int)) and not (isinstance(data__zoom, float) and data__zoom.is_integer()) or isinstance(data__zoom, bool):
                raise JsonSchemaValueException("" + (name_prefix or "data") + ".zoom must be integer", value=data__zoom, name="" + (name_prefix or "data") + ".zoom", definition={'type': 'integer', 'minimum': 0, 'maximum': 6, 'x-fraction-digits': 0, 'description': '0 = unset/default (observed in real profiles for switches with distance_from=INDEX acting as a placeholder entry), 1-6 = real zoom levels on the device.', 'x-fixed': "dart's A7pValidator already checked 0-6 (matching this schema); its A7pFieldConstraints.zoom metadata said min 1, contradicting its own validator and the real shipped profiles below -- doc comment updated to 0-6. js validate.ts previously did not restrict this at all (0-255) -- now bounded to 0-6. py's public a7p.validate() uses this schema directly (0-6), confirmed by tests/test_schema_validator.py::test_switch_zoom_bounds.", 'x-discrepancy': "profile.clj says 0-4 (documented bug, not used here). py's yupy_schema.py module still hard-codes 0-4 in its own tests/regression suite (test_yupy_schema.py), but that module is no longer wired into the public a7p.validate() path, so this doesn't affect real validation -- only relevant if someone imports a7p.yupy_schema directly. Confirmed against real shipped profiles: py/tests/data/example2.a7p and js/scripts/example2.a7p both ship a switch with zoom == 0."}, rule='type')
            if isinstance(data__zoom, (int, float, Decimal)):
                if data__zoom < 0:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".zoom must be bigger than or equal to 0", value=data__zoom, name="" + (name_prefix or "data") + ".zoom", definition={'type': 'integer', 'minimum': 0, 'maximum': 6, 'x-fraction-digits': 0, 'description': '0 = unset/default (observed in real profiles for switches with distance_from=INDEX acting as a placeholder entry), 1-6 = real zoom levels on the device.', 'x-fixed': "dart's A7pValidator already checked 0-6 (matching this schema); its A7pFieldConstraints.zoom metadata said min 1, contradicting its own validator and the real shipped profiles below -- doc comment updated to 0-6. js validate.ts previously did not restrict this at all (0-255) -- now bounded to 0-6. py's public a7p.validate() uses this schema directly (0-6), confirmed by tests/test_schema_validator.py::test_switch_zoom_bounds.", 'x-discrepancy': "profile.clj says 0-4 (documented bug, not used here). py's yupy_schema.py module still hard-codes 0-4 in its own tests/regression suite (test_yupy_schema.py), but that module is no longer wired into the public a7p.validate() path, so this doesn't affect real validation -- only relevant if someone imports a7p.yupy_schema directly. Confirmed against real shipped profiles: py/tests/data/example2.a7p and js/scripts/example2.a7p both ship a switch with zoom == 0."}, rule='minimum')
                if data__zoom > 6:
                    raise JsonSchemaValueException("" + (name_prefix or "data") + ".zoom must be smaller than or equal to 6", value=data__zoom, name="" + (name_prefix or "data") + ".zoom", definition={'type': 'integer', 'minimum': 0, 'maximum': 6, 'x-fraction-digits': 0, 'description': '0 = unset/default (observed in real profiles for switches with distance_from=INDEX acting as a placeholder entry), 1-6 = real zoom levels on the device.', 'x-fixed': "dart's A7pValidator already checked 0-6 (matching this schema); its A7pFieldConstraints.zoom metadata said min 1, contradicting its own validator and the real shipped profiles below -- doc comment updated to 0-6. js validate.ts previously did not restrict this at all (0-255) -- now bounded to 0-6. py's public a7p.validate() uses this schema directly (0-6), confirmed by tests/test_schema_validator.py::test_switch_zoom_bounds.", 'x-discrepancy': "profile.clj says 0-4 (documented bug, not used here). py's yupy_schema.py module still hard-codes 0-4 in its own tests/regression suite (test_yupy_schema.py), but that module is no longer wired into the public a7p.validate() path, so this doesn't affect real validation -- only relevant if someone imports a7p.yupy_schema directly. Confirmed against real shipped profiles: py/tests/data/example2.a7p and js/scripts/example2.a7p both ship a switch with zoom == 0."}, rule='maximum')
        if data_keys:
            raise JsonSchemaValueException("" + (name_prefix or "data") + " must not contain "+str(data_keys)+" properties", value=data, name="" + (name_prefix or "data") + "", definition={'type': 'object', 'additionalProperties': False, 'required': ['c_idx', 'distance_from', 'distance', 'reticle_idx', 'zoom'], 'properties': {'c_idx': {'description': "Index into coef_rows, or 255 meaning 'unused'.", 'oneOf': [{'type': 'integer', 'minimum': 0, 'maximum': 200}, {'const': 255}], 'x-decision': 'Resolved: 201-254 is rejected (matches profile.clj / py). Locked in by tests/test_schema_validator.py::test_switch_c_idx_bounds in py, which now validates through the public a7p.validate() path (schema_validator.py), not just the old yupy_schema.py.', 'x-discrepancy': "js and dart's A7pValidator both still accept the full 0-255 range unconditionally -- not fixed there yet; would require changing validation logic (not just a numeric constant) in both."}, 'distance_from': {'type': 'string', 'enum': ['VALUE', 'INDEX']}, 'distance': {'description': "Either the 'unused' sentinel 0, or a real distance in [100, 300000] raw (1.0-3000.0 m, 2 fraction digits) -- per profile.clj's (s/or :distance ::distance :unused zero?), unconditional on distance_from.", 'oneOf': [{'const': 0}, {'type': 'integer', 'minimum': 100, 'maximum': 300000}], 'x-fraction-digits': 2, 'x-ui-fraction-digits': 0, 'x-unit': 'm', 'x-decision': 'Resolved: distance is 0-or-[100,300000] unconditionally, regardless of distance_from (matches profile.clj / py) -- distance_from is not consulted for this rule. Locked in by tests/test_schema_validator.py::test_switch_distance_bounds_independent_of_distance_from in py, which now validates through the public a7p.validate() path (schema_validator.py), not just the old yupy_schema.py.', 'x-discrepancy': "js and dart instead branch on distance_from: when INDEX, they validate 'distance' as an index in [0,255] into the distances array; when VALUE, as [100,300000]. Not fixed there yet -- this is a semantic fork, not just a range typo, and would require changing validation logic (not just a numeric constant) in both."}, 'reticle_idx': {'type': 'integer', 'minimum': 0, 'maximum': 255, 'x-fraction-digits': 0}, 'zoom': {'type': 'integer', 'minimum': 0, 'maximum': 6, 'x-fraction-digits': 0, 'description': '0 = unset/default (observed in real profiles for switches with distance_from=INDEX acting as a placeholder entry), 1-6 = real zoom levels on the device.', 'x-fixed': "dart's A7pValidator already checked 0-6 (matching this schema); its A7pFieldConstraints.zoom metadata said min 1, contradicting its own validator and the real shipped profiles below -- doc comment updated to 0-6. js validate.ts previously did not restrict this at all (0-255) -- now bounded to 0-6. py's public a7p.validate() uses this schema directly (0-6), confirmed by tests/test_schema_validator.py::test_switch_zoom_bounds.", 'x-discrepancy': "profile.clj says 0-4 (documented bug, not used here). py's yupy_schema.py module still hard-codes 0-4 in its own tests/regression suite (test_yupy_schema.py), but that module is no longer wired into the public a7p.validate() path, so this doesn't affect real validation -- only relevant if someone imports a7p.yupy_schema directly. Confirmed against real shipped profiles: py/tests/data/example2.a7p and js/scripts/example2.a7p both ship a switch with zoom == 0."}}}, rule='additionalProperties')
    return data

def validate_https___a7p_cross_schema_a7p_schema_json___defs_distancefrom(data, custom_formats={}, name_prefix=None):
    if not isinstance(data, (str)):
        raise JsonSchemaValueException("" + (name_prefix or "data") + " must be string", value=data, name="" + (name_prefix or "data") + "", definition={'type': 'string', 'enum': ['VALUE', 'INDEX']}, rule='type')
    if data not in ['VALUE', 'INDEX']:
        raise JsonSchemaValueException("" + (name_prefix or "data") + " must be one of ['VALUE', 'INDEX']", value=data, name="" + (name_prefix or "data") + "", definition={'type': 'string', 'enum': ['VALUE', 'INDEX']}, rule='enum')
    return data

def validate_https___a7p_cross_schema_a7p_schema_json___defs_bctype(data, custom_formats={}, name_prefix=None):
    if not isinstance(data, (str)):
        raise JsonSchemaValueException("" + (name_prefix or "data") + " must be string", value=data, name="" + (name_prefix or "data") + "", definition={'type': 'string', 'enum': ['G1', 'G7', 'CUSTOM']}, rule='type')
    if data not in ['G1', 'G7', 'CUSTOM']:
        raise JsonSchemaValueException("" + (name_prefix or "data") + " must be one of ['G1', 'G7', 'CUSTOM']", value=data, name="" + (name_prefix or "data") + "", definition={'type': 'string', 'enum': ['G1', 'G7', 'CUSTOM']}, rule='enum')
    return data

def validate_https___a7p_cross_schema_a7p_schema_json___defs_twistdir(data, custom_formats={}, name_prefix=None):
    if not isinstance(data, (str)):
        raise JsonSchemaValueException("" + (name_prefix or "data") + " must be string", value=data, name="" + (name_prefix or "data") + "", definition={'type': 'string', 'enum': ['RIGHT', 'LEFT']}, rule='type')
    if data not in ['RIGHT', 'LEFT']:
        raise JsonSchemaValueException("" + (name_prefix or "data") + " must be one of ['RIGHT', 'LEFT']", value=data, name="" + (name_prefix or "data") + "", definition={'type': 'string', 'enum': ['RIGHT', 'LEFT']}, rule='enum')
    return data

validate = validate_https___a7p_cross_schema_a7p_schema_json
