Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Calculates the heating/cooling degree days for a span of time
- class Home::DegreeDays
- extend ActiveSupport::Memoizable
- attr_reader :options
- # :call-seq:
- # DegreeDays.new(options)
- # DegreeDays.new(zip_value, options)
- # DegreeDays.new(zip_value, base_temp, options)
- # DegreeDays.new(zip_value, base_temp, lower_bound, options)
- # DegreeDays.new(zip_value, base_temp, lower_bound, upper_bound, options)
- #
- # :options:
- # :zip_value => the Home::ZipValue
- # :base_temperature
- # :lower_bound
- # :upper_bound
- # :years
- # :insulation_factor
- # :heating_insulation
- # :cooling_insulation
- # :threshold
- # :heating_threshold
- # :cooling_threshold
- # :daily_temperatures
- # :heating
- # :cooling
- # :heating_days
- # :cooling_days
- def initialize(*args)
- @options = HashWithIndifferentAccess.new(args.extract_options!)
- @options[:zip_value] ||= args[0]
- @options[:base_temperature] ||= args[1]
- @options[:lower_bound] ||= args[2]
- @options[:upper_bound] ||= args[3]
- @options[:years] ||= 1
- @heating = @options.delete(:heating)
- @cooling = @options.delete(:cooling)
- @heating_days = @options.delete(:heating_days)
- @cooling_days = @options.delete(:cooling_days)
- @options.freeze
- end
- def years
- @options[:years]
- end
- def insulation_factor
- @options[:insulation_factor]
- end
- def heating_insulation
- @options[:heating_insulation] || insulation_factor || 3
- end
- memoize :heating_insulation
- def cooling_insulation
- @options[:cooling_insulation] || insulation_factor || 0
- end
- memoize :cooling_insulation
- def threshold
- @options[:threshold]
- end
- def heating_threshold
- @options[:heating_threshold] || threshold || 6
- end
- memoize :heating_threshold
- def cooling_threshold
- @options[:cooling_threshold] || threshold || 3
- end
- memoize :cooling_threshold
- def upper_bound
- @options[:upper_bound] || Home::TemperatureCache.
- most_recent_timestamp_for(zip_value)
- end
- memoize :upper_bound
- def lower_bound
- @options[:lower_bound] || upper_bound.advance({
- :years => -1,
- :days => 1
- })
- end
- memoize :lower_bound
- def base_temperature
- @options[:base_temperature] || 65.0
- end
- def zip_value
- zip_value = @options[:zip_value]
- if !zip_value && @options.has_key?(:zip_code)
- zip_value = ::Home::ZipValue.find(:first, {
- :conditions => {:zip_code => @options[:zip_code]}
- })
- end
- zip_value
- end
- memoize :zip_value
- def zip_code
- zip_value.zip_code
- end
- def daily_temperatures
- @options[:daily_temperatures] || zip_value.
- cached_temperatures_between(lower_bound, upper_bound)
- end
- memoize :daily_temperatures
- def -(other)
- self.class.new({
- :zip_value => zip_value,
- :base_temperature => other.base_temperature,
- :lower_bound => lower_bound,
- :upper_bound => upper_bound,
- :daily_temperatures => daily_temperatures,
- :heating => heating - other.heating,
- :cooling => cooling - other.cooling,
- :heating_days => heating_days - other.heating_days,
- :cooling_days => cooling_days - other.cooling_days
- })
- end
- def heating(num_years = nil)
- (@heating ||= calculate && @heating).to_f / (num_years || years)
- end
- def cooling(num_years = nil)
- (@cooling ||= calculate && @cooling).to_f / (num_years || years)
- end
- def heating_days
- @heating_days ||= calculate && @heating_days
- end
- def cooling_days
- @cooling_days ||= calculate && @cooling_days
- end
- def inspect
- attrs = [
- :zip_code, :base_temperature, :years,
- :lower_bound, :upper_bound,
- :heating_insulation, :cooling_insulation,
- :heating_threshold, :cooling_threshold,
- :heating, :cooling, :heating_days, :cooling_days
- ].map {|atr| ":#{atr} => #{self.send(atr)}" }
- "<Home::DegreeDays {#{attrs.join(', ')}} >"
- end
- private
- def heating_degree(temp)
- deg = base_temperature - (temp + heating_insulation)
- deg > 0 ? deg : 0
- end
- def cooling_degree(temp)
- deg = (temp - cooling_insulation) - base_temperature
- deg > 0 ? deg : 0
- end
- def heating_day(temps)
- heat = temps.map {|temp| heating_degree(temp)}.average
- (heat > heating_threshold) ? heat : false
- end
- def cooling_day(temps)
- cool = temps.map {|temp| cooling_degree(temp)}.average
- (cool > cooling_threshold) ? cool : false
- end
- def calculate
- @heating = @cooling = @heating_days = @cooling_days = 0
- daily_temperatures.each do |day|
- heating_today = heating_day(day)
- cooling_today = cooling_day(day)
- if heating_today
- @heating_days += 1
- @heating += heating_today
- end
- if cooling_today
- @cooling_days += 1
- @cooling += cooling_today
- end
- end
- end
- add_method_tracer :calculate
- end
Add Comment
Please, Sign In to add comment