require 'net/http' require 'rexml/document' require 'open-uri' require 'json' require 'forecast/http.rb' class Forecast module Adapter attr_reader :options module ClassMethods end def self.included(base) base.extend(ClassMethods) end def self.instance options = {} provider = Forecast.config.provider if provider.is_a?(String) || provider.is_a?(Symbol) adapter_name = provider.to_sym elsif provider.is_a?(Hash) adapter_name = provider[:adapter].to_s options = provider.clone options.delete('adapter') end if adapter_name if Forecast.config.adapters != nil && Forecast.config.adapters.has_key?(adapter_name) options = options.merge(Forecast.config.adapters[adapter_name]) end adapter_classname = (adapter_name.to_s << "_adapter").split('_').collect!{ |w| w.capitalize }.join adapter_class = Object.const_get('Forecast').const_get("Adapters").const_get(adapter_classname) adapter_class.new(options) else puts 'Adapter not found' end end def initialize(options = {}) @options = ({cache: Forecast.config.cache}).merge(options) @http = Http.new({cache: @options[:cache]}) end def current(latitude, longitude) end def hourly(latitude, longitude) end def daily(latitude, longitude) end protected def options @options end def get_json(url) @http.get_json(url) end def get_dom(url) @http.get_dom(url) end def get_temperature(value, input = :fahrenheit ) if value == nil value = 0 elsif value.is_a?(Array) value = value.inject{ |sum, v| sum.to_f + v.to_f }.to_f() / value.size elsif value.is_a?(String) || value.is_a?(Numeric) value = value.to_f end if input == :fahrenheit && Forecast.config.scale.to_sym == :kelvin value = Forecast::Utils.fahrenheit_to_kelvin(value) elsif input == :fahrenheit && Forecast.config.scale.to_sym == :celsius value = Forecast::Utils.fahrenheit_to_celsius(value) elsif input == :kelvin && Forecast.config.scale.to_sym == :fahrenheit value = Forecast::Utils.kelvin_to_fahrenheit(value) elsif input == :kelvin && Forecast.config.scale.to_sym == :celsius value = Forecast::Utils.kelvin_to_celsius(value) elsif input == :celsius && Forecast.config.scale.to_sym == :fahrenheit value = Forecast::Utils.celsius_to_fahrenheit(value) elsif input == :celsius && Forecast.config.scale.to_sym == :kelvin value = Forecast::Utils.celsius_to_kelvin(value) end value.round end def get_time(value) if value.is_a?(Time) || value.is_a?(Date) value.to_datetime elsif value.is_a?(String) && value =~ /\A\d+\Z/ || value.is_a?(Numeric) Time.at(value.to_i).to_datetime elsif value.is_a?(String) DateTime.parse(value.to_s) elsif value.is_a?(DateTime) value end end def get_text(value) value.capitalize end def get_condition_synonyms(name) result = [] synonyms = Forecast.config.synonyms synonym_values = synonyms.flatten.select { |v| Forecast::Utils.word_similarity(name, v) > 0.6 } if synonym_values.size > 0 c = synonym_values.sort { |a, b| as = Forecast::Utils.word_similarity(name, a) bs = Forecast::Utils.word_similarity(name, b) as <=> bs }.reverse match = c.first result = synonyms.select do |v| v.include?(match) end.first end return result end def get_similar_condition(name) conditions = Forecast.config.conditions condition_synonyms = {} conditions.each do |k, v| condition_synonyms[v] = get_condition_synonyms(v) - [v] end condition_synonym_similarity = {} conditions.each do |k, v| synonyms = [v] + get_condition_synonyms(v) condition_synonym_similarity[v] = get_condition_synonyms(v) - [v] similarity = 0 synonyms.each do |synonym| similarity = [similarity, Forecast::Utils.word_similarity(name, synonym)].max end condition_synonym_similarity[v] = similarity end c = conditions.values.select { |condition| condition_synonym_similarity[condition] > 0.1 } c = c.sort { |a, b| a_similarity = condition_synonym_similarity[a] b_similarity = condition_synonym_similarity[b] a_similarity <=> b_similarity }.reverse if c.first != nil return { condition: c.first, similarity: condition_synonym_similarity[c.first] || 0 } end end def get_condition_name(match) if match == nil return nil end conditions = Forecast.config.conditions condition = nil if conditions.keys.include?(match) condition = conditions[match] elsif conditions.values.include?(match) condition = match end return condition end def get_condition(api_conditions) if !api_conditions.is_a?(Array) api_conditions = [api_conditions] end condition = nil if api_conditions.length > 0 similar_conditions = api_conditions.map { |api_condition| get_similar_condition(api_condition) }.select {|v| v != nil } similar_condition = similar_conditions.sort { |a,b| a[:similarity] <=> b[:similarity] }.reverse.first if similar_condition condition = similar_condition[:condition] condition_name = get_condition_name(condition) if condition_name == nil condition_name = api_conditions[0] end end if condition_name != nil return condition_name end end return "Unknown" end end end