Class: HeatingSystemCalculator::BaseCalculator

Inherits:
Object
  • Object
show all
Includes:
Service
Defined in:
app/services/heating_system_calculator/base_calculator.rb

Instance Method Summary collapse

Methods included from Service

#attributes_used, #build_result, call, #logger

Constructor Details

#initialize(attributes) ⇒ BaseCalculator

Returns a new instance of BaseCalculator.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'app/services/heating_system_calculator/base_calculator.rb', line 38

def initialize(attributes)
  # super() with no args initializes @attributes (ActiveModel::Attributes) without
  # calling assign_attributes on the incoming hash. BaseCalculator receives a superset
  # of its own attribute names (CalculateQuote passes attributes_used which includes
  # catalog_id, currency, cable_spacings, etc.), so bulk-assigning via super would
  # raise ActiveModel::UnknownAttributeError. We assign only what this class declares.
  super()
  self.require_expansion_joint = attributes[:require_expansion_joint]
  self.expansion_joint_spacing = attributes[:expansion_joint_spacing]
  self.skip_expansion_joint    = attributes[:skip_expansion_joint]
  self.heated_area = HeatedArea.new(attributes)
  return self if heated_area.error

  self.heating_system = HeatingSystem.new(attributes.merge(heated_area:))
  return self if heating_system.error

  self.heating_system_items = HeatingSystemItems.new(attributes.merge(heated_area:).merge(heating_system:))
  self if heating_system_items.error
end

Instance Method Details

#calculate_elementsObject



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'app/services/heating_system_calculator/base_calculator.rb', line 94

def calculate_elements
  case element_calculation_method
  when :classic_recursive
    element_res = ElementFinderByArea.new({ element_set: heating_system_items.element_set }).calculate_elements_for_heated_area_sqft(
      heated_area.heated_area_sqft, heated_area.insulation_surface
    )
  when :zone_fit
    exp_joint_sp = require_expansion_joint ? expansion_joint_spacing : nil
    skip_exp_joint = require_expansion_joint ? skip_expansion_joint : nil
    element_type = :mat
    cable_sp = nil
    if heating_system.heating_system_product_line.is_cable_system?
      element_type = :cable
      cable_sp = heating_system.cable_spacing
    end
    element_res = ElementFinderByZones.new({ element_set: heating_system_items.element_set, expansion_joint_spacing: exp_joint_sp, skip_expansion_joint: skip_exp_joint, element_type:, cable_spacing: cable_sp }).fit_elements_into_heated_area_zones(
      heated_area.zones, heated_area.heated_area_sqft
    )
  end
  element_res
end

#calculate_systemObject



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'app/services/heating_system_calculator/base_calculator.rb', line 58

def calculate_system
  return report_error(heated_area.error.merge({ params: attributes })) if heated_area.error
  return report_error(heating_system.error.merge({ params: attributes })) if heating_system.error
  return report_error(heating_system_items.error.merge({ params: attributes })) if heating_system_items.error

  case element_calculation_method
  when :unsupported
    return report_error({ error_status: :unsupported, error_message: 'Heating System Calculator system type not supported at this time.',
                          params: attributes })
  when :no_solutions_possible
    return report_error({ error_status: :no_solutions_found, error_message: 'Heating System Calculator could find no solutions.',
                          params: attributes })
  else
    elements_result = calculate_elements
  end
  return elements_result.error.merge({ params: attributes, found_solution: false }).with_indifferent_access if elements_result.error

  if elements_result.coverage_percentage < 70.0
    # valid solution must covers 70% or more
    return report_error({ error_status: :no_solutions_found,
                          error_message: 'Heating System Calculator could find no solutions to cover 70 % or more of the desired heated area.', params: attributes })
  end

  controls_result = find_controls(elements_result.elements)
  return report_error(controls_result.error.merge({ params: attributes, found_solution: false })) if controls_result.error

  accessories_result = find_accessories(elements_result.elements, controls_result.controls)
  return report_error(accessories_result.error.merge({ params: attributes, found_solution: false })) if accessories_result.error

  smart_services_result = find_smart_services(elements_result.elements, controls_result.controls, accessories_result.accessories)
  return report_error(smart_services_result.error.merge({ params: attributes, found_solution: false })) if smart_services_result.error

  { elements: elements_result.elements, coverage_percentage: elements_result.coverage_percentage, target_area: elements_result.target_area,
    controls: controls_result.controls, accessories: accessories_result.accessories, smart_services: smart_services_result.smart_services, found_solution: true }.with_indifferent_access
end

#element_calculation_methodObject



141
142
143
144
145
146
147
148
149
# File 'app/services/heating_system_calculator/base_calculator.rb', line 141

def element_calculation_method
  res = :unsupported
  if ['TempZone Flex Roll', 'Environ Flex Roll', 'Slab Heat Mat', 'Slab Heat Cable', 'TempZone Cable', 'TempZone Ruler Cable', 'TempZone Thin Cable'].include?(heating_system.heating_system_type_name) or (heating_system.heating_system_product_line&.snow_melt? and !([3, 4].include?(heated_area.coverage_state) || require_expansion_joint)) # only use this classic_recursive algorithm with snow melt mat or cable if we are *not* covering tire tracks
    res = :classic_recursive # this classic_recursive algorithm assumes the heating elements can be cut/flipped/turned to fill the equivalent square footage, and so ignores zone information
  elsif ['Environ Easy Mat', 'TempZone Easy Mat'].include?(heating_system.heating_system_type_name) or (heating_system.heating_system_product_line&.snow_melt? and ([3, 4].include?(heated_area.coverage_state) || require_expansion_joint)) # only use this zone_fit algorithm with snow melt mat if we are covering tire tracks
    res = :zone_fit
  end
  res
end

#find_accessories(elements, controls) ⇒ Object



129
130
131
132
133
# File 'app/services/heating_system_calculator/base_calculator.rb', line 129

def find_accessories(elements, controls)
  AccessoriesFinder.new({ heated_area:, heating_system:, accessory_set: heating_system_items.accessory_set, underlayment_set: heating_system_items.underlayment_set, rough_in_kit_for_tstat: heating_system_items.rough_in_kit_for_tstat, rough_in_kit_for_power_module: heating_system_items.rough_in_kit_for_power_module }).find_accessories(
    elements, controls
  )
end

#find_controls(elements) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
# File 'app/services/heating_system_calculator/base_calculator.rb', line 116

def find_controls(elements)
  case heating_system.heating_system_product_line.snow_melt?
  when true
    SnowMeltingControlsFinder.new({ control_set: heating_system_items.control_set, sensor_set: heating_system_items.sensor_set, power_set: heating_system_items.power_set }).find_controls_for_elements(
      elements, heating_system.voltage.id
    )
  else
    FloorHeatingControlsFinder.new({ control_set: heating_system_items.control_set, power_set: heating_system_items.power_set }).find_controls_for_elements(
      elements, heating_system.voltage.id
    )
  end
end

#find_smart_services(elements, controls, accessories) ⇒ Object



135
136
137
138
139
# File 'app/services/heating_system_calculator/base_calculator.rb', line 135

def find_smart_services(elements, controls, accessories)
  SmartServicesFinder.new({ heated_area:, heating_system:, accessory_set: heating_system_items.accessory_set, smart_service_set: heating_system_items.smart_service_set, underlayment_set: heating_system_items.underlayment_set, rough_in_kit_for_tstat: heating_system_items.rough_in_kit_for_tstat, rough_in_kit_for_power_module: heating_system_items.rough_in_kit_for_power_module }).find_smart_services(
    elements, controls, accessories
  )
end

#report_error(error_hash) ⇒ Object



151
152
153
154
# File 'app/services/heating_system_calculator/base_calculator.rb', line 151

def report_error(error_hash)
  self.error = error_hash.merge({ found_solution: false }).with_indifferent_access
  error
end