forecast 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/.gitignore +11 -1
- data/CHANGELOG.md +27 -0
- data/README.md +196 -8
- data/bin/forecast +94 -0
- data/forecast.gemspec +4 -3
- data/lib/forecast/adapter.rb +126 -123
- data/lib/forecast/adapters/forecast_io_adapter.rb +57 -0
- data/lib/forecast/adapters/open_weather_map_adapter.rb +41 -58
- data/lib/forecast/adapters/wunderground_adapter.rb +53 -29
- data/lib/forecast/adapters/yahoo_adapter.rb +21 -29
- data/lib/forecast/collection.rb +4 -4
- data/lib/forecast/conditions.yml +2 -2
- data/lib/forecast/config.rb +4 -5
- data/lib/forecast/config.yml +2 -4
- data/lib/forecast/http.rb +80 -0
- data/lib/forecast/synonyms.yml +32 -0
- data/lib/forecast/themes/weather_icons.yml +10 -8
- data/lib/forecast/utils.rb +101 -6
- data/lib/forecast/version.rb +1 -1
- data/lib/forecast.rb +39 -107
- data/spec/fixtures/locations.yml +21 -0
- data/spec/forecast_spec.rb +58 -27
- data/spec/spec_helper.rb +16 -0
- metadata +28 -22
- data/.README.md.html +0 -480
- data/lib/forecast/adapters/open_weather_map_adapter.yml +0 -18
- data/lib/forecast/cache.rb +0 -7
- data/lib/forecast/model.rb +0 -71
data/lib/forecast/adapter.rb
CHANGED
@@ -3,15 +3,14 @@ require 'rexml/document'
|
|
3
3
|
require 'open-uri'
|
4
4
|
require 'json'
|
5
5
|
|
6
|
+
require 'forecast/http.rb'
|
7
|
+
|
6
8
|
class Forecast
|
7
9
|
module Adapter
|
8
10
|
|
9
|
-
|
11
|
+
attr_reader :options
|
10
12
|
|
11
13
|
module ClassMethods
|
12
|
-
def slug
|
13
|
-
self.name.split('::').last.gsub(/Adapter$/, '').gsub(/(.)([A-Z])/,'\1_\2').downcase
|
14
|
-
end
|
15
14
|
end
|
16
15
|
|
17
16
|
def self.included(base)
|
@@ -19,121 +18,146 @@ class Forecast
|
|
19
18
|
end
|
20
19
|
|
21
20
|
def self.instance
|
21
|
+
options = {}
|
22
22
|
provider = Forecast.config.provider
|
23
|
-
if provider.is_a?(
|
24
|
-
adapter_name = provider
|
23
|
+
if provider.is_a?(String) || provider.is_a?(Symbol)
|
24
|
+
adapter_name = provider.to_sym
|
25
|
+
elsif provider.is_a?(Hash)
|
26
|
+
adapter_name = provider[:adapter].to_s
|
25
27
|
options = provider.clone
|
26
28
|
options.delete('adapter')
|
27
|
-
else
|
28
|
-
adapter_name = provider
|
29
|
-
options = {}
|
30
29
|
end
|
31
30
|
if adapter_name
|
31
|
+
if Forecast.config.adapters != nil && Forecast.config.adapters.has_key?(adapter_name)
|
32
|
+
options = options.merge(Forecast.config.adapters[adapter_name])
|
33
|
+
end
|
32
34
|
adapter_classname = (adapter_name.to_s << "_adapter").split('_').collect!{ |w| w.capitalize }.join
|
33
35
|
adapter_class = Object.const_get('Forecast').const_get("Adapters").const_get(adapter_classname)
|
34
36
|
adapter_class.new(options)
|
35
37
|
else
|
36
|
-
puts '
|
38
|
+
puts 'Adapter not found'
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
40
42
|
def initialize(options = {})
|
41
|
-
@options = options
|
43
|
+
@options = ({cache: Forecast.config.cache}).merge(options)
|
44
|
+
@http = Http.new({cache: @options[:cache]})
|
45
|
+
end
|
46
|
+
|
47
|
+
def current(latitude, longitude)
|
42
48
|
end
|
43
49
|
|
44
|
-
def
|
45
|
-
@options
|
50
|
+
def hourly(latitude, longitude)
|
46
51
|
end
|
47
52
|
|
48
|
-
def
|
49
|
-
Forecast.config.adapters[self.class.slug] || {}
|
53
|
+
def daily(latitude, longitude)
|
50
54
|
end
|
51
55
|
|
52
56
|
protected
|
53
57
|
|
54
|
-
def
|
55
|
-
|
56
|
-
query_string = URI.encode_www_form(params)
|
57
|
-
url = url + "?" + query_string
|
58
|
-
end
|
59
|
-
resp = Net::HTTP.get_response(URI.parse(url))
|
60
|
-
data = resp.body
|
61
|
-
result = JSON.parse(data)
|
62
|
-
if result && result['cod'] != "404"
|
63
|
-
return result
|
64
|
-
end
|
65
|
-
return nil
|
58
|
+
def options
|
59
|
+
@options
|
66
60
|
end
|
67
|
-
|
68
|
-
def
|
69
|
-
|
70
|
-
query_string = URI.encode_www_form(params)
|
71
|
-
url = url + "?" + query_string
|
72
|
-
end
|
73
|
-
xml_data = Net::HTTP.get_response(URI.parse(url)).body
|
74
|
-
doc = REXML::Document.new(xml_data)
|
75
|
-
return doc
|
61
|
+
|
62
|
+
def get_json(url)
|
63
|
+
@http.get_json(url)
|
76
64
|
end
|
77
65
|
|
78
|
-
def
|
79
|
-
|
66
|
+
def get_dom(url)
|
67
|
+
@http.get_dom(url)
|
80
68
|
end
|
81
69
|
|
82
|
-
def
|
83
|
-
|
84
|
-
|
70
|
+
def get_temperature(value, input = :fahrenheit )
|
71
|
+
if value == nil
|
72
|
+
value = 0
|
73
|
+
elsif value.is_a?(Array)
|
74
|
+
value = value.inject{ |sum, v| sum.to_f + v.to_f }.to_f() / value.size
|
75
|
+
elsif value.is_a?(String) || value.is_a?(Numeric)
|
76
|
+
value = value.to_f
|
77
|
+
end
|
78
|
+
if input == :fahrenheit && Forecast.config.scale.to_sym == :kelvin
|
79
|
+
value = Forecast::Utils.fahrenheit_to_kelvin(value)
|
80
|
+
elsif input == :fahrenheit && Forecast.config.scale.to_sym == :celsius
|
81
|
+
value = Forecast::Utils.fahrenheit_to_celsius(value)
|
82
|
+
elsif input == :kelvin && Forecast.config.scale.to_sym == :fahrenheit
|
83
|
+
value = Forecast::Utils.kelvin_to_fahrenheit(value)
|
84
|
+
elsif input == :kelvin && Forecast.config.scale.to_sym == :celsius
|
85
|
+
value = Forecast::Utils.kelvin_to_celsius(value)
|
86
|
+
elsif input == :celsius && Forecast.config.scale.to_sym == :fahrenheit
|
87
|
+
value = Forecast::Utils.celsius_to_fahrenheit(value)
|
88
|
+
elsif input == :celsius && Forecast.config.scale.to_sym == :kelvin
|
89
|
+
value = Forecast::Utils.celsius_to_kelvin(value)
|
90
|
+
end
|
91
|
+
value.round
|
85
92
|
end
|
86
93
|
|
87
|
-
def
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
else
|
97
|
-
l1 = levenshtein(first_word, second_word)
|
98
|
-
if l1 > 0 && l1 < 3
|
99
|
-
similar = 1.0
|
100
|
-
end
|
101
|
-
end
|
102
|
-
similar_words+= similar
|
103
|
-
end
|
94
|
+
def get_time(value)
|
95
|
+
if value.is_a?(Time) || value.is_a?(Date)
|
96
|
+
value.to_datetime
|
97
|
+
elsif value.is_a?(String) && value =~ /\A\d+\Z/ || value.is_a?(Numeric)
|
98
|
+
Time.at(value.to_i).to_datetime
|
99
|
+
elsif value.is_a?(String)
|
100
|
+
DateTime.parse(value.to_s)
|
101
|
+
elsif value.is_a?(DateTime)
|
102
|
+
value
|
104
103
|
end
|
105
|
-
count = first_words.concat(second_words).uniq.length
|
106
|
-
similarity = similar_words / count
|
107
|
-
return similarity
|
108
104
|
end
|
109
105
|
|
110
|
-
def
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
106
|
+
def get_text(value)
|
107
|
+
value.capitalize
|
108
|
+
end
|
109
|
+
|
110
|
+
def get_condition_synonyms(name)
|
111
|
+
result = []
|
112
|
+
synonyms = Forecast.config.synonyms
|
113
|
+
synonym_values = synonyms.flatten.select { |v|
|
114
|
+
Forecast::Utils.word_similarity(name, v) > 0.6
|
115
|
+
}
|
116
|
+
if synonym_values.size > 0
|
117
|
+
c = synonym_values.sort { |a, b|
|
118
|
+
as = Forecast::Utils.word_similarity(name, a)
|
119
|
+
bs = Forecast::Utils.word_similarity(name, b)
|
120
|
+
as <=> bs
|
121
|
+
}.reverse
|
122
|
+
match = c.first
|
123
|
+
result = synonyms.select do |v|
|
124
|
+
v.include?(match)
|
125
|
+
end.first
|
127
126
|
end
|
128
|
-
return
|
127
|
+
return result
|
129
128
|
end
|
130
129
|
|
131
|
-
|
130
|
+
|
131
|
+
def get_similar_condition(name)
|
132
132
|
conditions = Forecast.config.conditions
|
133
|
-
|
134
|
-
|
135
|
-
|
133
|
+
condition_synonyms = {}
|
134
|
+
conditions.each do |k, v|
|
135
|
+
condition_synonyms[v] = get_condition_synonyms(v) - [v]
|
136
|
+
end
|
137
|
+
condition_synonym_similarity = {}
|
138
|
+
conditions.each do |k, v|
|
139
|
+
synonyms = [v] + get_condition_synonyms(v)
|
140
|
+
condition_synonym_similarity[v] = get_condition_synonyms(v) - [v]
|
141
|
+
similarity = 0
|
142
|
+
synonyms.each do |synonym|
|
143
|
+
similarity = [similarity, Forecast::Utils.word_similarity(name, synonym)].max
|
136
144
|
end
|
145
|
+
condition_synonym_similarity[v] = similarity
|
146
|
+
end
|
147
|
+
c = conditions.values.select { |condition|
|
148
|
+
condition_synonym_similarity[condition] > 0.1
|
149
|
+
}
|
150
|
+
c = c.sort { |a, b|
|
151
|
+
a_similarity = condition_synonym_similarity[a]
|
152
|
+
b_similarity = condition_synonym_similarity[b]
|
153
|
+
a_similarity <=> b_similarity
|
154
|
+
}.reverse
|
155
|
+
if c.first != nil
|
156
|
+
return {
|
157
|
+
condition: c.first,
|
158
|
+
similarity: condition_synonym_similarity[c.first] || 0
|
159
|
+
}
|
160
|
+
end
|
137
161
|
end
|
138
162
|
|
139
163
|
def get_condition_name(match)
|
@@ -141,7 +165,7 @@ class Forecast
|
|
141
165
|
return nil
|
142
166
|
end
|
143
167
|
conditions = Forecast.config.conditions
|
144
|
-
condition =
|
168
|
+
condition = nil
|
145
169
|
if conditions.keys.include?(match)
|
146
170
|
condition = conditions[match]
|
147
171
|
elsif conditions.values.include?(match)
|
@@ -150,55 +174,34 @@ class Forecast
|
|
150
174
|
return condition
|
151
175
|
end
|
152
176
|
|
153
|
-
def match_adapter_condition(api_condition)
|
154
|
-
match = nil
|
155
|
-
conditions = config['conditions']
|
156
|
-
if conditions != nil
|
157
|
-
conditions.each do |key, value|
|
158
|
-
# puts "match key #{api_condition} -> #{key.to_s}, #{value.to_s}"
|
159
|
-
if is_numeric?(api_condition) && key.is_a?(String)
|
160
|
-
if key.include? ".."
|
161
|
-
range = key.split(/\.{2}/)
|
162
|
-
if api_condition.to_i >= range[0].to_i && api_condition.to_i <= range[1].to_i
|
163
|
-
match = value
|
164
|
-
end
|
165
|
-
end
|
166
|
-
elsif key.to_s == api_condition.to_s
|
167
|
-
match = value;
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
171
|
-
return match
|
172
|
-
end
|
173
|
-
|
174
177
|
def get_condition(api_conditions)
|
175
178
|
if !api_conditions.is_a?(Array)
|
176
179
|
api_conditions = [api_conditions]
|
177
180
|
end
|
178
181
|
condition = nil
|
179
|
-
api_conditions.
|
180
|
-
|
181
|
-
|
182
|
-
|
182
|
+
if api_conditions.length > 0
|
183
|
+
similar_conditions = api_conditions.map { |api_condition|
|
184
|
+
get_similar_condition(api_condition)
|
185
|
+
}.select {|v|
|
186
|
+
v != nil
|
187
|
+
}
|
188
|
+
similar_condition = similar_conditions.sort { |a,b|
|
189
|
+
a[:similarity] <=> b[:similarity]
|
190
|
+
}.reverse.first
|
191
|
+
if similar_condition
|
192
|
+
condition = similar_condition[:condition]
|
193
|
+
condition_name = get_condition_name(condition)
|
194
|
+
if condition_name == nil
|
195
|
+
condition_name = api_conditions[0]
|
196
|
+
end
|
183
197
|
end
|
184
|
-
if
|
185
|
-
|
198
|
+
if condition_name != nil
|
199
|
+
return condition_name
|
186
200
|
end
|
187
201
|
end
|
188
|
-
|
202
|
+
return "Unknown"
|
189
203
|
end
|
190
204
|
|
191
|
-
private
|
192
|
-
|
193
|
-
def is_numeric?(s)
|
194
|
-
begin
|
195
|
-
Float(s)
|
196
|
-
rescue
|
197
|
-
false # not numeric
|
198
|
-
else
|
199
|
-
true # numeric
|
200
|
-
end
|
201
|
-
end
|
202
205
|
|
203
206
|
end
|
204
207
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
class Forecast
|
2
|
+
module Adapters
|
3
|
+
class ForecastIoAdapter
|
4
|
+
|
5
|
+
include Forecast::Adapter
|
6
|
+
|
7
|
+
def current(latitude, longitude)
|
8
|
+
result = get_json(get_action(latitude, longitude))
|
9
|
+
get_forecast({latitude: latitude, longitude: longitude}.merge(result['currently'])) unless nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def hourly(latitude, longitude)
|
13
|
+
result = get_json(get_action(latitude, longitude))
|
14
|
+
forecasts = Forecast::Collection.new
|
15
|
+
result['hourly']['data'].each do |hash|
|
16
|
+
forecasts << get_forecast({latitude: latitude, longitude: longitude}.merge(hash))
|
17
|
+
end
|
18
|
+
return forecasts
|
19
|
+
end
|
20
|
+
|
21
|
+
def daily(latitude, longitude)
|
22
|
+
result = get_json(get_action(latitude, longitude))
|
23
|
+
forecasts = Forecast::Collection.new
|
24
|
+
result['daily']['data'].each do |hash|
|
25
|
+
forecasts << get_forecast({latitude: latitude, longitude: longitude}.merge(hash))
|
26
|
+
end
|
27
|
+
return forecasts
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def get_action(latitude, longitude)
|
33
|
+
api_key = options[:api_key]
|
34
|
+
return "https://api.forecast.io/forecast/#{api_key}/#{latitude},#{longitude}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def get_forecast(hash)
|
38
|
+
forecast = Forecast.new(hash)
|
39
|
+
forecast.latitude = hash[:latitude]
|
40
|
+
forecast.longitude = hash[:longitude]
|
41
|
+
forecast.time = get_time(hash['time'])
|
42
|
+
forecast.condition = get_condition(hash['summary'])
|
43
|
+
forecast.text = get_text(hash['summary'])
|
44
|
+
forecast.temperature_min = get_temperature(hash['temperatureMin'], :fahrenheit)
|
45
|
+
forecast.temperature_max = get_temperature(hash['temperatureMax'], :fahrenheit)
|
46
|
+
forecast.temperature = get_temperature(hash.has_key?('temperature') ? hash['temperature'] : [hash['temperatureMin'], hash['temperatureMax']], :fahrenheit)
|
47
|
+
return forecast
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
|
@@ -5,70 +5,62 @@ class Forecast
|
|
5
5
|
include Forecast::Adapter
|
6
6
|
|
7
7
|
def current(latitude, longitude)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
forecast.date = Time.at(result['dt']).to_datetime
|
13
|
-
forecast.temp = get_temp(kelvin_to_fahrenheit(result['main']['temp']))
|
14
|
-
result['weather'].each do |obj|
|
15
|
-
condition = get_condition(obj['description'])
|
16
|
-
if condition != nil
|
17
|
-
forecast.condition = condition
|
18
|
-
break
|
19
|
-
end
|
20
|
-
end
|
8
|
+
hash = get_json(get_action('weather', latitude, longitude))
|
9
|
+
if hash
|
10
|
+
result = get_forecast({latitude: latitude, longitude: longitude}.merge(hash))
|
11
|
+
return result
|
21
12
|
end
|
22
|
-
return forecast
|
23
13
|
end
|
24
14
|
|
25
15
|
def hourly(latitude, longitude)
|
26
|
-
|
27
|
-
result =
|
28
|
-
if
|
29
|
-
|
30
|
-
|
31
|
-
forecast.date = Time.at(item['dt']).to_datetime
|
32
|
-
forecast.temp = get_temp(kelvin_to_fahrenheit(item['main']['temp']))
|
33
|
-
item['weather'].each do |obj|
|
34
|
-
condition = get_condition([obj['description'], obj['id']])
|
35
|
-
if condition != nil
|
36
|
-
forecast.condition = condition
|
37
|
-
break
|
38
|
-
end
|
39
|
-
end
|
40
|
-
# forecast.temp_min = item['main']['temp_min']
|
41
|
-
# forecast.temp_max = item['main']['temp_max']
|
42
|
-
forecasts << forecast
|
16
|
+
json = get_json(get_action('forecast', latitude, longitude))
|
17
|
+
result = Forecast::Collection.new
|
18
|
+
if json && json.has_key?('list')
|
19
|
+
json['list'].each do |hash|
|
20
|
+
result << get_forecast({latitude: latitude, longitude: longitude}.merge(hash))
|
43
21
|
end
|
44
22
|
end
|
45
|
-
return
|
23
|
+
return result
|
46
24
|
end
|
47
25
|
|
48
26
|
def daily(latitude, longitude)
|
49
|
-
|
50
|
-
result =
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
27
|
+
json = get_json(get_action('forecast/daily', latitude, longitude))
|
28
|
+
result = Forecast::Collection.new
|
29
|
+
if json && json.has_key?('list')
|
30
|
+
result = Forecast::Collection.new
|
31
|
+
json['list'].each do |hash|
|
32
|
+
result << get_forecast({latitude: latitude, longitude: longitude}.merge(hash))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
return result
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
def get_forecast(hash = {})
|
41
|
+
forecast = Forecast.new()
|
42
|
+
forecast.latitude = hash[:latitude]
|
43
|
+
forecast.longitude = hash[:longitude]
|
44
|
+
forecast.time = get_time(hash['dt'])
|
45
|
+
forecast.temperature = get_temperature(hash.has_key?('main') ? hash['main']['temp'] : hash['temp']['day'], :kelvin)
|
46
|
+
forecast.temperature_min = get_temperature(hash.has_key?('main') ? hash['main']['temp_min'] : hash['temp']['min'], :kelvin)
|
47
|
+
forecast.temperature_max = get_temperature(hash.has_key?('main') ? hash['main']['temp_max'] : hash['temp']['max'], :kelvin)
|
48
|
+
forecast.temperature = ((forecast.temperature_min + forecast.temperature_max) / 2).round
|
49
|
+
hash['weather'].each do |obj|
|
50
|
+
condition = get_condition([obj['description'], obj['main']])
|
59
51
|
if condition != nil
|
52
|
+
forecast.text = get_text(obj['description'])
|
60
53
|
forecast.condition = condition
|
61
54
|
break
|
62
|
-
end
|
55
|
+
end
|
63
56
|
end
|
64
|
-
|
57
|
+
return forecast
|
65
58
|
end
|
66
|
-
|
67
|
-
|
68
|
-
|
59
|
+
|
60
|
+
|
69
61
|
private
|
70
62
|
|
71
|
-
def
|
63
|
+
def get_action(action, latitude, longitude)
|
72
64
|
url = "http://api.openweathermap.org/data/2.5/#{action}"
|
73
65
|
params = {
|
74
66
|
lat: latitude,
|
@@ -81,15 +73,6 @@ class Forecast
|
|
81
73
|
return url + "?" + query_string
|
82
74
|
end
|
83
75
|
|
84
|
-
def kelvin_to_fahrenheit(kelvin)
|
85
|
-
return ((kelvin - 273.15) * 1.8000 + 32).round
|
86
|
-
end
|
87
|
-
|
88
76
|
end
|
89
77
|
end
|
90
|
-
end
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
78
|
+
end
|
@@ -6,29 +6,20 @@ class Forecast
|
|
6
6
|
|
7
7
|
def current(latitude, longitude)
|
8
8
|
forecast = nil
|
9
|
-
result = get_json(
|
10
|
-
if result
|
11
|
-
|
12
|
-
forecast = Forecast.new(latitude: latitude, longitude: longitude)
|
13
|
-
forecast.date = Time.rfc822(item['observation_time_rfc822'])
|
14
|
-
forecast.temp = get_temp(item['temp_f'])
|
15
|
-
forecast.condition = get_condition([item['weather']])
|
16
|
-
forecast.orig_condition = item['weather']
|
9
|
+
result = get_json(get_action('conditions', latitude, longitude))
|
10
|
+
if result.has_key?('current_observation')
|
11
|
+
forecast = get_current_forecast(result['current_observation'].merge({latitude: latitude, longitude: longitude}))
|
17
12
|
end
|
18
13
|
return forecast
|
19
14
|
end
|
20
15
|
|
21
16
|
def hourly(latitude, longitude)
|
22
17
|
forecasts = Forecast::Collection.new
|
23
|
-
result = get_json(
|
24
|
-
if result
|
18
|
+
result = get_json(get_action('hourly', latitude, longitude))
|
19
|
+
if result.has_key?('hourly_forecast')
|
25
20
|
items = result['hourly_forecast']
|
26
|
-
items.each do |
|
27
|
-
forecast =
|
28
|
-
forecast.date = Time.at(item['FCTTIME']['epoch'].to_i).to_datetime
|
29
|
-
forecast.temp = get_temp(item['temp']['english'])
|
30
|
-
forecast.condition = get_condition([item['condition']])
|
31
|
-
forecast.orig_condition = item['condition']
|
21
|
+
items.each do |hash|
|
22
|
+
forecast = get_hourly_forecast(hash.merge({latitude: latitude, longitude: longitude}))
|
32
23
|
forecasts << forecast
|
33
24
|
end
|
34
25
|
end
|
@@ -37,17 +28,11 @@ class Forecast
|
|
37
28
|
|
38
29
|
def daily(latitude, longitude)
|
39
30
|
forecasts = Forecast::Collection.new
|
40
|
-
result = get_json(
|
41
|
-
if result
|
31
|
+
result = get_json(get_action('forecast', latitude, longitude))
|
32
|
+
if result.has_key?('forecast')
|
42
33
|
items = result['forecast']['simpleforecast']['forecastday']
|
43
|
-
items.each do |
|
44
|
-
forecast =
|
45
|
-
forecast.date = Time.at(item['date']['epoch'].to_i).to_datetime
|
46
|
-
forecast.temp_min = get_temp(item['low']['fahrenheit'])
|
47
|
-
forecast.temp_max = get_temp(item['high']['fahrenheit'])
|
48
|
-
forecast.temp = (forecast.temp_min + forecast.temp_max) / 2
|
49
|
-
forecast.condition = get_condition([item['conditions']])
|
50
|
-
forecast.orig_condition = item['conditions']
|
34
|
+
items.each do |hash|
|
35
|
+
forecast = get_daily_forecast(hash.merge({latitude: latitude, longitude: longitude}))
|
51
36
|
forecasts << forecast
|
52
37
|
end
|
53
38
|
end
|
@@ -55,10 +40,49 @@ class Forecast
|
|
55
40
|
end
|
56
41
|
|
57
42
|
private
|
58
|
-
|
59
|
-
def
|
60
|
-
url = "http://api.wunderground.com/api/#{options[
|
43
|
+
|
44
|
+
def get_action(action, latitude, longitude)
|
45
|
+
url = "http://api.wunderground.com/api/#{options[:api_key]}/#{action}/q/#{latitude},#{longitude}.json"
|
61
46
|
end
|
47
|
+
|
48
|
+
def get_current_forecast(hash = {})
|
49
|
+
puts 'forecast hash: ' + hash.to_s
|
50
|
+
forecast = Forecast.new()
|
51
|
+
forecast.latitude = hash[:latitude]
|
52
|
+
forecast.longitude = hash[:longitude]
|
53
|
+
forecast.time = get_time(hash['observation_epoch'])
|
54
|
+
forecast.temperature = get_temperature(hash['temp_f'], :fahrenheit)
|
55
|
+
forecast.condition = get_condition(hash['weather'])
|
56
|
+
forecast.text = get_text(hash['weather'])
|
57
|
+
return forecast
|
58
|
+
end
|
59
|
+
|
60
|
+
def get_hourly_forecast(hash = {})
|
61
|
+
puts 'forecast hash: ' + hash.to_s
|
62
|
+
forecast = Forecast.new()
|
63
|
+
forecast.latitude = hash[:latitude]
|
64
|
+
forecast.longitude = hash[:longitude]
|
65
|
+
forecast.time = get_time(hash['FCTTIME']['epoch'])
|
66
|
+
forecast.temperature = get_temperature(hash['temp']['english'], :fahrenheit)
|
67
|
+
forecast.condition = get_condition([hash['condition']])
|
68
|
+
forecast.text = get_text(hash['condition'])
|
69
|
+
return forecast
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_daily_forecast(hash = {})
|
73
|
+
puts 'forecast hash: ' + hash.to_s
|
74
|
+
forecast = Forecast.new()
|
75
|
+
forecast.latitude = hash[:latitude]
|
76
|
+
forecast.longitude = hash[:longitude]
|
77
|
+
forecast.time = get_time(hash['date']['epoch'])
|
78
|
+
forecast.temperature_min = get_temperature(hash['low']['fahrenheit'], :fahrenheit)
|
79
|
+
forecast.temperature_max = get_temperature(hash['high']['fahrenheit'], :fahrenheit)
|
80
|
+
forecast.temperature = get_temperature([hash['low']['fahrenheit'], hash['high']['fahrenheit']], :fahrenheit)
|
81
|
+
forecast.condition = get_condition(hash['conditions'])
|
82
|
+
forecast.text = get_text(hash['conditions'])
|
83
|
+
return forecast
|
84
|
+
end
|
85
|
+
|
62
86
|
|
63
87
|
end
|
64
88
|
end
|