# frozen_string_literal: true module Jobshop class Inspection::DeviationCriterion < ApplicationRecord belongs_to :organization, -> { readonly } belongs_to :report, -> { readonly } has_one :criterion, -> (deviation_criterion) { where({ organization_id: deviation_criterion.organization_id, report_id: deviation_criterion.report_id }) }, as: :criterion, autosave: true, dependent: :destroy, inverse_of: :criterion def criterion super || build_criterion end delegate :name, :name=, :position, :position=, to: :criterion validates :nominal, presence: true validates :lower, presence: true validates :upper, presence: true validate :lower_less_than_upper def mean ((nominal + lower) + (nominal + upper)) / 2 end def nominal self[:nominal] && Unitwise(self[:nominal].truncate(4), self[:unit]) end def lower self[:lower] && Unitwise(self[:lower].truncate(4), self[:unit]) end def lower=(value) self[:lower] = if value.respond_to?(:unit) value.convert_to(self[:unit]).value else value end end def upper self[:upper] && Unitwise(self[:upper].truncate(4), self[:unit]) end def upper=(value) self[:upper] = if value.respond_to?(:unit) value.convert_to(self[:unit]).value else value end end def lower_less_than_upper return unless lower && upper if lower > upper errors[:base] << "minimum must be less than maximum" end end =begin def specification @specfication ||= if symmetric? "#{nominal}±#{abs(upper)}" else "#{nominal}\n#{lower}/#{upper}" end end =end def symmetric? @symmetrical ||= lower == upper * -1 end def pass?(value) !undersize?(value) && !oversize?(value) end # Generate a random value that has a 90% chance of being in spec. # TODO: This needs to go in the tests somewhere, not really in the model. def random rand_lower = nominal.to_f + lower.to_f * 1.1 rand_upper = nominal.to_f + upper.to_f * 1.1 value = rand(rand_lower..rand_upper) Unitwise(value.truncate(4), self[:unit]) end def oversize?(value) value = if value.respond_to?(:unit) value.convert_to(self[:unit]) else Unitwise(value, self[:unit]) end value > upper || false end def undersize?(value) value = if value.respond_to?(:unit) value.convert_to(self[:unit]) else Unitwise(value, self[:unit]) end value < nominal - lower || false end end end