lib/barometer/weather.rb
module Barometer
class Weather
attr_accessor :responses
attr_accessor :start_at, :end_at
def initialize(units=:metric)
@units = units
@responses = []
end
def source(source)
responses.detect{|response| response.source == source}
end
def success?
responses.any?(&:success?)
end
def current
successful_responses.first.current if successful_responses.any?
end
def forecast
successful_responses.first.forecast if successful_responses.any?
end
def today
successful_responses.first.forecast[0] if successful_responses.any?
end
def tomorrow
successful_responses.first.forecast[1] if successful_responses.any?
end
def for(query)
successful_responses.first.for(query) if successful_responses.any?
end
def temperature; average(:temperature, Data::Temperature); end
def dew_point; average(:dew_point, Data::Temperature); end
def heat_index; average(:heat_index, Data::Temperature); end
def wind_chill; average(:wind_chill, Data::Temperature); end
def pressure; average(:pressure, Data::Pressure); end
def visibility; average(:visibility, Data::Distance); end
def wind; average(:wind, Data::Vector); end
def humidity; average(:humidity); end
private
def successful_responses
@successful_responses ||= responses.select(&:success?)
end
def average(field, data_class=nil)
return if successful_responses.empty?
value = raw_average(field)
data_class ? data_class.new(@units, value) : value
end
def raw_average(field)
weighted_value(field) / total_weight(field)
end
def total_weight(field)
successful_responses.inject(0) do |sum, response|
sum + (response.current.send(field) ? response.weight : 0)
end
end
def weighted_value(field)
successful_responses.inject(0) do |sum, response|
sum + (value_in_correct_units(response, field).to_f * response.weight)
end
end
def value_in_correct_units(response, field)
value = response.current.send(field)
value = value.send(@units) if value.respond_to?(@units)
value
end
end
end