Class: HeatingSystem

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/heating_system.rb

Overview

Catalogue of WarmlyYours heating-system product families, each
identified by a short code (TZ, EV2, SMC, …) and a customer-
facing name ('TempZone Flex Roll', 'Environ Easy Mat', …).
Comparable so collections of systems sort consistently.

Constant Summary collapse

HEATING_SYSTEM_TYPES_BY_CODE =

Short code => customer-facing heating-system name.

{ TZ: 'TempZone Flex Roll', TZEM: 'TempZone Easy Mat', EV2: 'Environ Easy Mat', EVFR: 'Environ Flex Roll', SMC: 'Snow Melt Cable', SMM: 'Snow Melt Mat', SHC: 'Slab Heat Cable', SHM: 'Slab Heat Mat',
UDH: 'Under Desk Heater', ARW: 'Area Rug Warmer', HTM: 'Heat Trak Mat', OTH: 'Other', IP: 'Infrared Panel' }.freeze
HEATING_SYSTEM_TYPES =

Recognised heating system type names.

HEATING_SYSTEM_TYPES_BY_CODE.map { |_k, v|; v.to_s }
HEATING_SYSTEM_CODES =

Recognised heating system short codes.

HEATING_SYSTEM_TYPES_BY_CODE.map { |k, _v|; k.to_s }

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(system_type) ⇒ HeatingSystem

Resolves a type name or short code to #heating_system_type and #code.

Parameters:



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/heating_system.rb', line 23

def initialize(system_type)
  if system_type.blank?
    code = "OTH"
    system_type = HEATING_SYSTEM_TYPES_BY_CODE[code.to_sym]
  end
  if HEATING_SYSTEM_TYPES.include? system_type
    @heating_system_type = system_type
    @code = HEATING_SYSTEM_CODES[HEATING_SYSTEM_TYPES.index(system_type)]
  else
    system_by_code = HEATING_SYSTEM_TYPES_BY_CODE[system_type.to_sym]
    raise "Invalid system types, must be one of #{HEATING_SYSTEM_TYPES.join(',')}" if system_by_code.nil?

    @heating_system_type = system_by_code
    @code = system_type

  end
end

Instance Attribute Details

#codeObject

Returns the value of attribute code.



10
11
12
# File 'lib/heating_system.rb', line 10

def code
  @code
end

#heating_system_typeObject

Returns the value of attribute heating_system_type.



10
11
12
# File 'lib/heating_system.rb', line 10

def heating_system_type
  @heating_system_type
end

Class Method Details

.heating_system_types_for_floor_type(floor_type, room_type = nil, for_iq = false) ⇒ Array<String>

Heating-system type names compatible with the given floor covering.

Parameters:

  • floor_type (FloorType, nil)

    floor covering; nil returns an empty list

  • room_type (RoomType, nil) (defaults to: nil)

    optional room type (stairs prefer cable)

  • for_iq (Boolean) (defaults to: false)

    when true, omit systems not offered on instant quote

Returns:

  • (Array<String>)

    the heating system type names



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/heating_system.rb', line 124

def self.heating_system_types_for_floor_type(floor_type, room_type = nil, for_iq = false)
  res = []
  # we will evaluate our options, simplest first
  unless floor_type.nil?
    # if Indoor and one of these three types we are an ev2
    if ['Bamboo (Floating)', 'Carpet', 'Cork', 'Engineered (Floating)', 'Laminate (Click Together Floating)', 'Laminate (Glued Together Floating)'].include? floor_type.name
      # we want the reps to have options but put EV2 first res << self.find_by(code: "EV2")
      res += ['Environ Flex Roll', 'Environ Easy Mat']
      res += ['TempZone Flex Roll', 'TempZone Easy Mat'] unless for_iq
    elsif floor_type.name.index('Concrete Slab (outdoor)')
      res += ['Snow Melt Mat', 'Snow Melt Cable']
      res.reverse! if 'Stairs'.eql? room_type.name # want to start with SMC if stairs
    elsif floor_type.environment.eql? "Indoor" # Anything else indoor includes TempZone
      if floor_type.id == 5 # Concrete Slab (indoor) Finished/Decorative
        res += ['Slab Heat Mat', 'Slab Heat Cable']
        res += ['TempZone Flex Roll'] unless for_iq
      else
        # we want the reps to have options but put TZ first
        res += ['TempZone Flex Roll', 'TempZone Easy Mat']
        res += ['Environ Flex Roll', 'Environ Easy Mat'] unless for_iq
      end
    elsif floor_type.environment.eql? "Outdoor"
      res += if !room_type.nil? && 'Stairs'.eql?(room_type.name)
               ['Snow Melt Cable']
             else # Make the Snow Melt Cable first
               ['Snow Melt Cable', 'Snow Melt Mat']
             end
    end
  end
  res
end

.recommendation(floor_type_in, room_type = nil) ⇒ Array<HeatingSystem>

Recommended heating systems for a floor covering.

Parameters:

  • floor_type_in (FloorType, String)

    a floor type or its name

  • room_type (RoomType, nil) (defaults to: nil)

    optional room type (stairs prefer cable)

Returns:

  • (Array<HeatingSystem>)

    recommended systems for the floor type

Raises:

  • (RuntimeError)

    when the floor type cannot be resolved



105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/heating_system.rb', line 105

def self.recommendation(floor_type_in, room_type = nil)
  nil
  floor_type = if floor_type_in.instance_of? String
                 FloorType.find_by(name: floor_type_in)
               else
                 floor_type_in
               end
  raise "Could not find floor type #{floor_type_in} or floor type not specified" if floor_type.nil?

  res = HeatingSystem.heating_system_types_for_floor_type(floor_type, room_type)
  res.map { |hs| HeatingSystem.new(hs) }
end

.shc_cable_spacing_for_select(_floor_type = nil, unit = "in") ⇒ Array<Array(String, Float)>

Select options for slab-heat cable spacing.

Parameters:

  • _floor_type (Object, nil) (defaults to: nil)

    unused; kept for call-site compatibility

  • unit (String) (defaults to: "in")

    unit label passed to RubyUnits (default: "in")

Returns:

  • (Array<Array(String, Float)>)

    [label, spacing-in-inches] option pairs



75
76
77
78
79
80
# File 'lib/heating_system.rb', line 75

def self.shc_cable_spacing_for_select(_floor_type = nil, unit = "in")
  opts = [["15 watts/sqft - #{RubyUnits::Unit.new('5.0 in').to_s(unit)}", 5.0]]
  opts << ["20 watts/sqft - #{RubyUnits::Unit.new('3.5 in').to_s(unit)}", 3.5]
  opts << ["25 watts/sqft - #{RubyUnits::Unit.new('3.0 in').to_s(unit)}", 3.0]
  opts
end

Instance Method Details

#==(other) ⇒ Boolean

Compares heating systems by their string form.

Parameters:

  • other (Object)

    compared via #to_s

Returns:

  • (Boolean)

    whether the other object stringifies equal



45
46
47
# File 'lib/heating_system.rb', line 45

def ==(other)
  other.to_s == to_s
end

#ideal_cable_spacing(_floor_type = nil) ⇒ Float?

Default cable spacing for systems that require it.

Parameters:

  • _floor_type (Object, nil) (defaults to: nil)

    unused; kept for call-site compatibility

Returns:

  • (Float, nil)

    the ideal cable spacing in inches, or nil when not required



86
87
88
89
90
91
92
# File 'lib/heating_system.rb', line 86

def ideal_cable_spacing(_floor_type = nil)
  return unless require_cable_spacing?

  cs = 3.0 # make this the default
  cs = 3.5 if @heating_system_type == "Slab Heat Cable"
  cs
end

#require_cable_spacing?Boolean

Whether this system needs an ideal cable-spacing value.

Returns:

  • (Boolean)


66
67
68
# File 'lib/heating_system.rb', line 66

def require_cable_spacing?
  ['Snow Melt Cable', 'Slab Heat Cable'].include? @heating_system_type
end

#snow_melt?Boolean

Whether this is a snow-melt cable or mat.

Returns:

  • (Boolean)


59
60
61
# File 'lib/heating_system.rb', line 59

def snow_melt?
  ['Snow Melt Cable', 'Snow Melt Mat'].include? @heating_system_type
end

#tempzone?Boolean

Whether this is a TempZone Flex Roll system.

Returns:

  • (Boolean)


52
53
54
# File 'lib/heating_system.rb', line 52

def tempzone?
  ['TempZone Flex Roll'].include? @heating_system_type
end

#to_sString

Returns the heating system type.

Returns:

  • (String)

    the heating system type



95
96
97
# File 'lib/heating_system.rb', line 95

def to_s
  @heating_system_type
end