Guest User

Untitled

a guest
Jul 19th, 2018
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.12 KB | None | 0 0
  1. # Calculates the heating/cooling degree days for a span of time
  2. class Home::DegreeDays
  3. extend ActiveSupport::Memoizable
  4.  
  5. attr_reader :options
  6.  
  7. # :call-seq:
  8. # DegreeDays.new(options)
  9. # DegreeDays.new(zip_value, options)
  10. # DegreeDays.new(zip_value, base_temp, options)
  11. # DegreeDays.new(zip_value, base_temp, lower_bound, options)
  12. # DegreeDays.new(zip_value, base_temp, lower_bound, upper_bound, options)
  13. #
  14. # :options:
  15. # :zip_value => the Home::ZipValue
  16. # :base_temperature
  17. # :lower_bound
  18. # :upper_bound
  19. # :years
  20. # :insulation_factor
  21. # :heating_insulation
  22. # :cooling_insulation
  23. # :threshold
  24. # :heating_threshold
  25. # :cooling_threshold
  26. # :daily_temperatures
  27. # :heating
  28. # :cooling
  29. # :heating_days
  30. # :cooling_days
  31. def initialize(*args)
  32. @options = HashWithIndifferentAccess.new(args.extract_options!)
  33.  
  34. @options[:zip_value] ||= args[0]
  35. @options[:base_temperature] ||= args[1]
  36. @options[:lower_bound] ||= args[2]
  37. @options[:upper_bound] ||= args[3]
  38. @options[:years] ||= 1
  39.  
  40. @heating = @options.delete(:heating)
  41. @cooling = @options.delete(:cooling)
  42. @heating_days = @options.delete(:heating_days)
  43. @cooling_days = @options.delete(:cooling_days)
  44.  
  45. @options.freeze
  46. end
  47.  
  48. def years
  49. @options[:years]
  50. end
  51.  
  52. def insulation_factor
  53. @options[:insulation_factor]
  54. end
  55.  
  56. def heating_insulation
  57. @options[:heating_insulation] || insulation_factor || 3
  58. end
  59.  
  60. memoize :heating_insulation
  61.  
  62. def cooling_insulation
  63. @options[:cooling_insulation] || insulation_factor || 0
  64. end
  65.  
  66. memoize :cooling_insulation
  67.  
  68. def threshold
  69. @options[:threshold]
  70. end
  71.  
  72. def heating_threshold
  73. @options[:heating_threshold] || threshold || 6
  74. end
  75.  
  76. memoize :heating_threshold
  77.  
  78. def cooling_threshold
  79. @options[:cooling_threshold] || threshold || 3
  80. end
  81.  
  82. memoize :cooling_threshold
  83.  
  84. def upper_bound
  85. @options[:upper_bound] || Home::TemperatureCache.
  86. most_recent_timestamp_for(zip_value)
  87. end
  88.  
  89. memoize :upper_bound
  90.  
  91. def lower_bound
  92. @options[:lower_bound] || upper_bound.advance({
  93. :years => -1,
  94. :days => 1
  95. })
  96. end
  97.  
  98. memoize :lower_bound
  99.  
  100. def base_temperature
  101. @options[:base_temperature] || 65.0
  102. end
  103.  
  104. def zip_value
  105. zip_value = @options[:zip_value]
  106.  
  107. if !zip_value && @options.has_key?(:zip_code)
  108. zip_value = ::Home::ZipValue.find(:first, {
  109. :conditions => {:zip_code => @options[:zip_code]}
  110. })
  111. end
  112.  
  113. zip_value
  114. end
  115.  
  116. memoize :zip_value
  117.  
  118. def zip_code
  119. zip_value.zip_code
  120. end
  121.  
  122. def daily_temperatures
  123. @options[:daily_temperatures] || zip_value.
  124. cached_temperatures_between(lower_bound, upper_bound)
  125. end
  126.  
  127. memoize :daily_temperatures
  128.  
  129. def -(other)
  130. self.class.new({
  131. :zip_value => zip_value,
  132. :base_temperature => other.base_temperature,
  133. :lower_bound => lower_bound,
  134. :upper_bound => upper_bound,
  135. :daily_temperatures => daily_temperatures,
  136. :heating => heating - other.heating,
  137. :cooling => cooling - other.cooling,
  138. :heating_days => heating_days - other.heating_days,
  139. :cooling_days => cooling_days - other.cooling_days
  140. })
  141. end
  142.  
  143. def heating(num_years = nil)
  144. (@heating ||= calculate && @heating).to_f / (num_years || years)
  145. end
  146.  
  147. def cooling(num_years = nil)
  148. (@cooling ||= calculate && @cooling).to_f / (num_years || years)
  149. end
  150.  
  151. def heating_days
  152. @heating_days ||= calculate && @heating_days
  153. end
  154.  
  155. def cooling_days
  156. @cooling_days ||= calculate && @cooling_days
  157. end
  158.  
  159. def inspect
  160. attrs = [
  161. :zip_code, :base_temperature, :years,
  162. :lower_bound, :upper_bound,
  163. :heating_insulation, :cooling_insulation,
  164. :heating_threshold, :cooling_threshold,
  165. :heating, :cooling, :heating_days, :cooling_days
  166. ].map {|atr| ":#{atr} => #{self.send(atr)}" }
  167.  
  168. "<Home::DegreeDays {#{attrs.join(', ')}} >"
  169. end
  170.  
  171. private
  172.  
  173. def heating_degree(temp)
  174. deg = base_temperature - (temp + heating_insulation)
  175. deg > 0 ? deg : 0
  176. end
  177.  
  178. def cooling_degree(temp)
  179. deg = (temp - cooling_insulation) - base_temperature
  180. deg > 0 ? deg : 0
  181. end
  182.  
  183. def heating_day(temps)
  184. heat = temps.map {|temp| heating_degree(temp)}.average
  185. (heat > heating_threshold) ? heat : false
  186. end
  187.  
  188. def cooling_day(temps)
  189. cool = temps.map {|temp| cooling_degree(temp)}.average
  190. (cool > cooling_threshold) ? cool : false
  191. end
  192.  
  193. def calculate
  194. @heating = @cooling = @heating_days = @cooling_days = 0
  195.  
  196. daily_temperatures.each do |day|
  197. heating_today = heating_day(day)
  198. cooling_today = cooling_day(day)
  199.  
  200. if heating_today
  201. @heating_days += 1
  202. @heating += heating_today
  203. end
  204.  
  205. if cooling_today
  206. @cooling_days += 1
  207. @cooling += cooling_today
  208. end
  209. end
  210. end
  211.  
  212. add_method_tracer :calculate
  213.  
  214. end
Add Comment
Please, Sign In to add comment