---
$schema: "http://json-schema.org/draft-07/schema#"
$id: "https://oimlsmart.org/schemas/R76.yaml"
title: "OIML R76 (Non-automatic weighing instruments) Certificate Schema"
type: object
required: [certificate, certified_type, characteristics, recommendation]
properties:
  certificate:           { $ref: "_core.yaml#/definitions/Certificate" }
  issuing_authority:     { $ref: "_core.yaml#/definitions/IssuingAuthority" }
  applicants:            { $ref: "_core.yaml#/definitions/PartyList" }
  manufacturers:         { $ref: "_core.yaml#/definitions/PartyList" }
  certified_type:        { $ref: "#/definitions/CertifiedType" }
  characteristics:       { $ref: "#/definitions/Characteristics" }
  recommendation:
    type: object
    required: [id, edition, scheme]
    properties:
      id:          { type: string, enum: [R76, R76-1, "R 76"] }
      edition:
        type: integer
        oneOf:
        - const: 2006
          description: Edition 2006
        - const: 1992
          description: Legacy edition 1992
      amendment:   { type: [integer, string, "null"] }
      scheme:      { type: string, enum: [A, B] }
      accuracy_classes:
        type: array
        items: { $ref: "#/definitions/AccuracyClassValue" }
  test_reports:          { $ref: "_core.yaml#/definitions/TestReportList" }
  revision_history:      { $ref: "_core.yaml#/definitions/RevisionHistory" }
  model_family:          { $ref: "_core.yaml#/definitions/ModelFamily" }
  components:
    type: array
    items: { $ref: "_core.yaml#/definitions/Component" }
  footnotes:             { $ref: "_core.yaml#/definitions/FootnoteList" }
  d011_tests_applicable:
    description: Tests mandated by R76-2 type evaluation (D 11:2013 subset).
    type: array
    items: { $ref: "#/definitions/D011TestReference" }
    default:
    - { test_id: d011_t06_static_temperature }
    - { test_id: d011_t07_static_temperature }
    - { test_id: d011_t08_damp_heat_steady_state }
    - { test_id: d011_t09_damp_heat_cyclic }
    - { test_id: d011_t11_atmospheric_pressure }
    - { test_id: d011_t18_dc_mains_voltage_variation }
    - { test_id: d011_t20_ac_mains_voltage_variation }
    - { test_id: d011_t22_dc_mains_dips_interruptions }
    - { test_id: d011_t23_ac_mains_dips_interruptions }
    - { test_id: d011_t26_bursts_ac_dc_mains }
    - { test_id: d011_t27_surges_ac_dc_mains }
    - { test_id: d011_t28_bursts_signal_data_control }
    - { test_id: d011_t29_surges_signal_data_control }
    - { test_id: d011_t33_rf_em_fields_general }
    - { test_id: d011_t35_electrostatic_discharges }

definitions:
  AccuracyClass:
    description: |
      OIML R76-1 §3.2 accuracy class for a non-automatic weighing instrument.
      May carry a single class or, for multi-accuracy-class instruments, a list
      of classes (one per weighing range). The `value` subfield accepts either
      form; the enum tokens are the Roman numerals I, II, III, IIII.
    allOf:
    - $ref: "_core.yaml#/definitions/StructuredValue"
    - properties:
        value:
          description: |
            Accuracy class token. Single class = a string from the enum.
            Multi-accuracy instrument = an array of enum tokens, one per
            weighing range (R76-1 §3.2). Tokens are Roman numerals; note
            class IIII (four Is), distinct from III.
          oneOf:
          - type: string
            oneOf:
            - const: I
              description: Special accuracy — highest precision instruments
            - const: II
              description: High accuracy — precision balances, lab/retail
            - const: III
              description: Medium accuracy — most commercial/industrial scales
            - const: IIII
              description: Ordinary accuracy — coarse industrial scales
            - const: "N/A"
              description: Not applicable
          - type: array
            items:
              type: string
              enum: [I, II, III, IIII]

  AccuracyClassValue:
    description: |
      Bare accuracy class token used in `recommendation.accuracy_classes` array
      (the list of classes the certificate covers). Distinct from the
      StructuredValue-wrapped accuracy_class in characteristics.type_level.
    type: string
    oneOf:
    - const: I
      description: Special accuracy
    - const: II
      description: High accuracy
    - const: III
      description: Medium accuracy
    - const: IIII
      description: Ordinary accuracy

  InstrumentType:
    description: |
      R76-1 §3.4 instrument classification. Canonical tokens; surface synonyms
      (e.g. "electronic", "electromechanical") should be normalized to these.
    type: string
    oneOf:
    - const: single_interval
      description: Single-interval instrument — one verification scale interval
    - const: multi_interval
      description: Multi-interval instrument — multiple scale intervals within one range
    - const: single_range
      description: Single-range instrument
    - const: multi_range
      description: Multi-range instrument — two or more weighing ranges
    - const: multiple_range
      description: Multi-range instrument (synonym of multi_range)
    - const: "N/A"
      description: Not applicable
    # Surface forms observed in cert data (pre-normalization). These describe
    # the instrument type in human-readable form and SHOULD be normalized to
    # the canonical single_interval/multi_interval/etc tokens above.
    - const: "Non-automatic weighing instrument"
      description: Surface form — normalize to canonical token
    - const: "Non-automatic weighing instruments"
      description: Surface form — normalize to canonical token
    - const: "Non-automatic electronic weighing instrument"
      description: Surface form — normalize to canonical token
    - const: "Non-automatic weighing indicator"
      description: Surface form — normalize to canonical token
    - const: "Non-automatic electronic weighing indicator"
      description: Surface form — normalize to canonical token
    - const: "Analog data processing device"
      description: Surface form — component-level description
    - const: "Digital data processing device"
      description: Surface form — component-level description
    - const: "Analog load cells"
      description: Surface form — component-level description
    - const: "analog_passive"
      description: Surface form — load cell characterization (R60-style)

  CertifiedType:
    type: object
    required: [category, type_designations]
    properties:
      category:
        description: |
          R76-1 §3.2. Canonical value is "Non-automatic weighing instrument";
          historical certs may use variant phrasing pending migration.
        type: string
      type_designations:
        type: array
        minItems: 1
        items: { type: string }
      module_designation:
        oneOf:
        - $ref: "#/definitions/InstrumentType"
        - type: "null"
      description: { type: string }

  Characteristics:
    type: object
    properties:
      type_level: { $ref: "#/definitions/TypeLevel" }
      model_level:
        type: array
        items: { $ref: "#/definitions/ModelLevelEntry" }
      config_level:
        type: array
        items: { $ref: "#/definitions/ConfigLevelEntry" }

  TypeLevel:
    type: object
    properties:
      accuracy_class:                    { $ref: "#/definitions/AccuracyClass" }
      instrument_type:                   { $ref: "#/definitions/InstrumentType" }
      temperature_range:                 { $ref: "_modules/d011_environmental.yaml#/definitions/TemperatureRange" }
      humidity_class:                    { $ref: "_modules/d011_environmental.yaml#/definitions/ClimaticClass" }
      electromagnetic_environment_class: { $ref: "_modules/d011_environmental.yaml#/definitions/EMClass" }
      mechanical_environment_class:      { $ref: "_modules/d011_environmental.yaml#/definitions/MechanicalClass" }
      maximum_capacity:                  { $ref: "_core.yaml#/definitions/StructuredValue" }
      minimum_capacity:                  { $ref: "_core.yaml#/definitions/StructuredValue" }
      verification_scale_interval:       { $ref: "_core.yaml#/definitions/StructuredValue" }
      actual_scale_interval:             { $ref: "_core.yaml#/definitions/StructuredValue" }
      number_of_scale_intervals:         { $ref: "_core.yaml#/definitions/StructuredValue" }
      measuring_range:                   { $ref: "_core.yaml#/definitions/StructuredValue" }
      weighing_range:                    { $ref: "_core.yaml#/definitions/StructuredValue" }
      tare_balancing_range:              { $ref: "_core.yaml#/definitions/StructuredValue" }
      preset_tare_value:                 { $ref: "_core.yaml#/definitions/StructuredValue" }
      maximum_tare:                      { $ref: "_core.yaml#/definitions/StructuredValue" }
      maximum_tare_effect:               { $ref: "_core.yaml#/definitions/StructuredValue" }
      maximum_number_of_verification_scale_intervals: { $ref: "_core.yaml#/definitions/StructuredValue" }
      fraction_of_maximum_permissible_error: { $ref: "_core.yaml#/definitions/StructuredValue" }
      fraction_max_permissible_error_pi: { $ref: "_core.yaml#/definitions/StructuredValue" }
      power_supply_voltage:              { $ref: "_core.yaml#/definitions/StructuredValue" }
      power_supply_type:                 { $ref: "_core.yaml#/definitions/StructuredValue" }
      power_supply_frequency:            { $ref: "_core.yaml#/definitions/StructuredValue" }
      load_cell_excitation_voltage:      { $ref: "_core.yaml#/definitions/StructuredValue" }
      minimum_load_cell_impedance:       { $ref: "_core.yaml#/definitions/StructuredValue" }
      maximum_load_cell_impedance:       { $ref: "_core.yaml#/definitions/StructuredValue" }
      minimum_input_voltage_per_verification_scale_interval: { $ref: "_core.yaml#/definitions/StructuredValue" }
      maximum_cable_length:              { $ref: "_core.yaml#/definitions/StructuredValue" }
      software_identification:           { $ref: "_core.yaml#/definitions/SoftwareIdentification" }

  ModelLevelEntry:
    type: object
    required: [attribute, values]
    properties:
      attribute: { type: string }
      unit:      { $ref: "_units.yaml#/definitions/Unit" }
      values:
        type: array
        items:
          type: object
          required: [model, value]
          properties:
            model:            { type: string }
            value:            { $ref: "_core.yaml#/definitions/ValueOrScalar" }
            footnote_markers:
              type: array
              items: { type: string }

  ConfigLevelEntry:
    type: object
    required: [attribute, axis, values]
    properties:
      attribute: { type: string }
      axis:      { oneOf: [ { type: string }, { type: "null" } ] }
      unit:      { $ref: "_units.yaml#/definitions/Unit" }
      values:
        type: array
        items:
          type: object
          anyOf:
          - required: [condition, value]
            properties:
              condition: { type: string }
              value:     { $ref: "_core.yaml#/definitions/ValueOrScalar" }
          - required: [model, value]
            properties:
              model:     { type: string }
              value:     { $ref: "_core.yaml#/definitions/ValueOrScalar" }

  D011TestReference:
    description: Reference to an OIML D 11:2013 performance test.
    type: object
    required: [test_id]
    properties:
      test_id:          { type: string, pattern: '^d011_t\d{2}_' }
      test_level_index: { type: integer, minimum: 1, maximum: 5 }
      notes:            { type: string }

allOf:
- description: |
    Conditional applicability of D 11 damp heat tests (R76-1 §4.3, D 11 §9.2):
    t08 (steady state) applies iff humidity_class = H2 or H3 (non-condensing,
    non-temperature-controlled or open-air);
    t09 (cyclic) applies iff humidity_class = H3 (open-air, condensing).
    For R76 the humidity_class uses D 11 H1/H2/H3 directly (unlike R60 which
    uses the separate CH/NH/SH load-cell marking).
  if:
    properties:
      characteristics:
        properties:
          type_level:
            properties:
              humidity_class:
                properties:
                  value: { const: H2 }
  then:
    properties:
      d011_tests_applicable:
        contains: { properties: { test_id: { const: d011_t08_damp_heat_steady_state } } }
- if:
    properties:
      characteristics:
        properties:
          type_level:
            properties:
              humidity_class:
                properties:
                  value: { const: H3 }
  then:
    properties:
      d011_tests_applicable:
        contains: { properties: { test_id: { const: d011_t09_damp_heat_cyclic } } }
