barometer 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +51 -9
- data/VERSION.yml +2 -2
- data/bin/barometer +57 -7
- data/lib/barometer.rb +11 -0
- data/lib/barometer/base.rb +3 -0
- data/lib/barometer/data.rb +11 -6
- data/lib/barometer/data/sun.rb +10 -0
- data/lib/barometer/data/zone.rb +79 -188
- data/lib/barometer/formats/coordinates.rb +4 -1
- data/lib/barometer/formats/geocode.rb +9 -7
- data/lib/barometer/formats/icao.rb +2 -2
- data/lib/barometer/formats/weather_id.rb +2 -2
- data/lib/barometer/measurements/common.rb +113 -0
- data/lib/barometer/{data → measurements}/current.rb +17 -42
- data/lib/barometer/measurements/forecast.rb +62 -0
- data/lib/barometer/measurements/forecast_array.rb +72 -0
- data/lib/barometer/{data → measurements}/measurement.rb +57 -45
- data/lib/barometer/measurements/night.rb +27 -0
- data/lib/barometer/query.rb +55 -5
- data/lib/barometer/services.rb +3 -1
- data/lib/barometer/translations/icao_country_codes.yml +274 -1
- data/lib/barometer/translations/weather_country_codes.yml +189 -6
- data/lib/barometer/translations/zone_codes.yml +360 -0
- data/lib/barometer/weather.rb +5 -4
- data/lib/barometer/weather_services/google.rb +19 -35
- data/lib/barometer/weather_services/service.rb +113 -255
- data/lib/barometer/weather_services/weather_bug.rb +291 -2
- data/lib/barometer/weather_services/weather_dot_com.rb +45 -54
- data/lib/barometer/weather_services/wunderground.rb +83 -89
- data/lib/barometer/weather_services/yahoo.rb +44 -91
- data/lib/barometer/web_services/geocode.rb +1 -0
- data/lib/barometer/web_services/timezone.rb +40 -0
- data/lib/barometer/web_services/weather_id.rb +17 -2
- data/lib/demometer/demometer.rb +28 -0
- data/lib/demometer/public/css/master.css +259 -1
- data/lib/demometer/public/css/print.css +94 -0
- data/lib/demometer/public/css/syntax.css +64 -0
- data/lib/demometer/public/images/link-out.gif +0 -0
- data/lib/demometer/views/about.erb +10 -0
- data/lib/demometer/views/index.erb +2 -0
- data/lib/demometer/views/layout.erb +3 -2
- data/lib/demometer/views/measurement.erb +4 -1
- data/lib/demometer/views/readme.erb +116 -88
- data/spec/data/sun_spec.rb +53 -0
- data/spec/data/zone_spec.rb +330 -100
- data/spec/fixtures/formats/weather_id/ksfo.xml +1 -0
- data/spec/fixtures/services/weather_bug/90210_current.xml +1 -0
- data/spec/fixtures/services/weather_bug/90210_forecast.xml +1 -0
- data/spec/formats/weather_id_spec.rb +10 -5
- data/spec/measurements/common_spec.rb +352 -0
- data/spec/{data → measurements}/current_spec.rb +40 -103
- data/spec/measurements/forecast_array_spec.rb +165 -0
- data/spec/measurements/forecast_spec.rb +135 -0
- data/spec/{data → measurements}/measurement_spec.rb +86 -107
- data/spec/measurements/night_measurement_spec.rb +49 -0
- data/spec/query_spec.rb +12 -2
- data/spec/spec_helper.rb +28 -1
- data/spec/weather_services/google_spec.rb +27 -117
- data/spec/weather_services/services_spec.rb +49 -1024
- data/spec/weather_services/weather_bug_spec.rb +274 -0
- data/spec/weather_services/weather_dot_com_spec.rb +45 -125
- data/spec/weather_services/wunderground_spec.rb +42 -136
- data/spec/weather_services/yahoo_spec.rb +26 -116
- data/spec/weather_spec.rb +45 -45
- metadata +27 -11
- data/lib/barometer/data/forecast.rb +0 -84
- data/lib/barometer/data/night.rb +0 -69
- data/lib/barometer/extensions/graticule.rb +0 -51
- data/spec/data/forecast_spec.rb +0 -192
- data/spec/data/night_measurement_spec.rb +0 -136
@@ -43,9 +43,6 @@ module Barometer
|
|
43
43
|
@@partner_key = nil
|
44
44
|
@@license_key = nil
|
45
45
|
|
46
|
-
def self.source_name; :weather_dot_com; end
|
47
|
-
def self.accepted_formats; [:short_zipcode, :weather_id]; end
|
48
|
-
|
49
46
|
def self.keys=(keys)
|
50
47
|
raise ArgumentError unless keys.is_a?(Hash)
|
51
48
|
keys.each do |key, value|
|
@@ -54,64 +51,56 @@ module Barometer
|
|
54
51
|
end
|
55
52
|
end
|
56
53
|
|
57
|
-
|
58
|
-
|
54
|
+
#########################################################################
|
55
|
+
# PRIVATE
|
56
|
+
# If class methods could be private, the remaining methods would be.
|
57
|
+
#
|
58
|
+
|
59
|
+
def self._source_name; :weather_dot_com; end
|
60
|
+
def self._accepted_formats; [:short_zipcode, :weather_id]; end
|
59
61
|
|
60
|
-
def self.
|
62
|
+
def self._has_keys?; !@@partner_key.nil? && !@@license_key.nil?; end
|
63
|
+
def self._requires_keys?; true; end
|
64
|
+
|
65
|
+
def self._wet_icon_codes
|
61
66
|
codes = (0..18).to_a + [35] + (37..43).to_a + (45..47).to_a
|
62
67
|
codes.collect {|c| c.to_s}
|
63
68
|
end
|
64
|
-
def self.
|
69
|
+
def self._sunny_icon_codes
|
65
70
|
codes = [19, 22, 28, 30, 32, 34, 36]
|
66
71
|
codes.collect {|c| c.to_s}
|
67
72
|
end
|
68
73
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
end
|
79
|
-
|
80
|
-
measurement.current = self.build_current(result, metric)
|
81
|
-
measurement.forecast = self.build_forecast(result, metric)
|
82
|
-
measurement.location = self.build_location(result, query.geo)
|
83
|
-
measurement.current.sun = self.build_sun(result)
|
84
|
-
|
85
|
-
# add links
|
86
|
-
if result && result['lnks'] && result['lnks']['link']
|
87
|
-
result['lnks']['link'].each do |link_hash|
|
88
|
-
measurement.links[link_hash['t']] = link_hash['l']
|
74
|
+
# first try to match the zone code, otherwise use the zone offset
|
75
|
+
#
|
76
|
+
def self._build_timezone(data)
|
77
|
+
if data
|
78
|
+
if data['cc'] && data['cc']['lsup'] &&
|
79
|
+
(zone_match = data['cc']['lsup'].match(/ ([A-Z]{1,4})$/))
|
80
|
+
Data::Zone.new(zone_match[1])
|
81
|
+
elsif data['loc'] && data['loc']['zone']
|
82
|
+
Data::Zone.new(data['loc']['zone'].to_f)
|
89
83
|
end
|
90
84
|
end
|
91
|
-
|
92
|
-
# set local time of measurement
|
93
|
-
local_time = self.build_local_time(result)
|
94
|
-
measurement.measured_at = local_time
|
95
|
-
measurement.current.current_at = local_time
|
96
|
-
|
97
|
-
measurement
|
98
85
|
end
|
99
86
|
|
100
|
-
|
101
|
-
# this is a best guess method. the data provided for time conversions
|
102
|
-
# leaves a lot to be desired. some time zones, offsets, local times are
|
103
|
-
# out to lunch. eg. Tahiti (all times seem to be 30 min off), but there
|
104
|
-
# is no way to determine this
|
105
|
-
#
|
106
|
-
# regardless of the above, this method will trust the data given to it
|
107
|
-
#
|
108
|
-
def self.build_local_time(data)
|
87
|
+
def self._parse_local_time(data)
|
109
88
|
(data && data['loc']) ? Data::LocalTime.parse(data['loc']['tm']) : nil
|
110
89
|
end
|
111
|
-
|
112
|
-
def self.
|
90
|
+
|
91
|
+
def self._build_links(data)
|
92
|
+
links = {}
|
93
|
+
if data && data['lnks'] && data['lnks']['link']
|
94
|
+
data['lnks']['link'].each do |link_hash|
|
95
|
+
links[link_hash['t']] = link_hash['l']
|
96
|
+
end
|
97
|
+
end
|
98
|
+
links
|
99
|
+
end
|
100
|
+
|
101
|
+
def self._build_current(data, metric=true)
|
113
102
|
raise ArgumentError unless data.is_a?(Hash)
|
114
|
-
current =
|
103
|
+
current = Measurement::Current.new
|
115
104
|
if data
|
116
105
|
if data['cc']
|
117
106
|
current.updated_at = Data::LocalDateTime.parse(data['cc']['lsup'])
|
@@ -141,14 +130,14 @@ module Barometer
|
|
141
130
|
current
|
142
131
|
end
|
143
132
|
|
144
|
-
def self.
|
133
|
+
def self._build_forecast(data, metric=true)
|
145
134
|
raise ArgumentError unless data.is_a?(Hash)
|
146
|
-
forecasts =
|
135
|
+
forecasts = Measurement::ForecastArray.new
|
147
136
|
|
148
137
|
if data && data['dayf'] && data['dayf']['day']
|
149
138
|
local_date = data['dayf']['lsup']
|
150
139
|
data['dayf']['day'].each do |forecast|
|
151
|
-
forecast_measurement =
|
140
|
+
forecast_measurement = Measurement::Forecast.new
|
152
141
|
forecast_measurement.date = Date.parse(forecast['dt'])
|
153
142
|
|
154
143
|
forecast_measurement.high = Data::Temperature.new(metric)
|
@@ -180,7 +169,7 @@ module Barometer
|
|
180
169
|
|
181
170
|
elsif part['p'] == 'n'
|
182
171
|
# add this to the NightMeasurement
|
183
|
-
forecast_measurement.night =
|
172
|
+
forecast_measurement.night = Measurement::ForecastNight.new
|
184
173
|
forecast_measurement.night.condition = part['t']
|
185
174
|
forecast_measurement.night.icon = part['icon']
|
186
175
|
forecast_measurement.night.pop = part['ppcp'].to_i
|
@@ -202,7 +191,7 @@ module Barometer
|
|
202
191
|
forecasts
|
203
192
|
end
|
204
193
|
|
205
|
-
def self.
|
194
|
+
def self._build_location(data, geo=nil)
|
206
195
|
raise ArgumentError unless data.is_a?(Hash)
|
207
196
|
raise ArgumentError unless (geo.nil? || geo.is_a?(Data::Geo))
|
208
197
|
location = Data::Location.new
|
@@ -224,7 +213,7 @@ module Barometer
|
|
224
213
|
location
|
225
214
|
end
|
226
215
|
|
227
|
-
def self.
|
216
|
+
def self._build_sun(data)
|
228
217
|
raise ArgumentError unless data.is_a?(Hash)
|
229
218
|
sun = nil
|
230
219
|
if data
|
@@ -239,9 +228,11 @@ module Barometer
|
|
239
228
|
|
240
229
|
# use HTTParty to get the current weather
|
241
230
|
#
|
242
|
-
def self.
|
231
|
+
def self._fetch(query, metric=true)
|
232
|
+
return unless query
|
233
|
+
puts "fetch weather.com: #{query.q}" if Barometer::debug?
|
243
234
|
self.get(
|
244
|
-
"http://xoap.weather.com/weather/local/#{query}",
|
235
|
+
"http://xoap.weather.com/weather/local/#{query.q}",
|
245
236
|
:query => { :par => @@partner_key, :key => @@license_key,
|
246
237
|
:prod => "xoap", :link => "xoap", :cc => "*",
|
247
238
|
:dayf => "5", :unit => (metric ? 'm' : 's')
|
@@ -46,72 +46,63 @@ module Barometer
|
|
46
46
|
#
|
47
47
|
class WeatherService::Wunderground < WeatherService
|
48
48
|
|
49
|
-
|
50
|
-
|
49
|
+
#########################################################################
|
50
|
+
# PRIVATE
|
51
|
+
# If class methods could be private, the remaining methods would be.
|
52
|
+
#
|
53
|
+
|
54
|
+
def self._source_name; :wunderground; end
|
55
|
+
def self._accepted_formats
|
51
56
|
[:zipcode, :postalcode, :icao, :coordinates, :geocode]
|
52
57
|
end
|
53
58
|
|
54
59
|
# these are the icon codes that indicate "wet", used by wet? function
|
55
|
-
def self.
|
60
|
+
def self._wet_icon_codes
|
56
61
|
%w(flurries rain sleet snow tstorms nt_flurries nt_rain nt_sleet nt_snow nt_tstorms chancerain chancetstorms)
|
57
62
|
end
|
58
63
|
# these are the icon codes that indicate "sun", used by sunny? function
|
59
|
-
def self.
|
64
|
+
def self._sunny_icon_codes
|
60
65
|
%w(clear mostlysunny partlysunny sunny partlycloudy)
|
61
66
|
end
|
62
67
|
|
63
|
-
def self.
|
64
|
-
raise ArgumentError unless measurement.is_a?(Data::Measurement)
|
65
|
-
raise ArgumentError unless query.is_a?(Barometer::Query)
|
66
|
-
|
67
|
-
|
68
|
-
begin
|
69
|
-
current_result = self.get_current(query.q)
|
70
|
-
measurement.current = self.build_current(current_result, metric)
|
71
|
-
rescue Timeout::Error => e
|
72
|
-
return measurement
|
73
|
-
end
|
74
|
-
|
75
|
-
begin
|
76
|
-
forecast_result = self.get_forecast(query.q)
|
77
|
-
measurement.forecast = self.build_forecast(forecast_result, metric)
|
78
|
-
rescue Timeout::Error => e
|
79
|
-
return measurement
|
80
|
-
end
|
81
|
-
|
82
|
-
measurement.location = self.build_location(current_result)
|
83
|
-
measurement.station = self.build_station(current_result)
|
84
|
-
measurement.timezone = self.build_timezone(forecast_result)
|
85
|
-
|
86
|
-
if current_result["credit"] && current_result["credit_URL"]
|
87
|
-
measurement.links[current_result["credit"]] = current_result["credit_URL"]
|
88
|
-
end
|
89
|
-
|
90
|
-
sun = nil
|
91
|
-
if measurement.current
|
92
|
-
sun = self.build_sun(forecast_result, measurement.timezone)
|
93
|
-
measurement.current.sun = sun
|
94
|
-
end
|
68
|
+
def self._build_extra(measurement, result, metric=true)
|
69
|
+
#raise ArgumentError unless measurement.is_a?(Data::Measurement)
|
70
|
+
#raise ArgumentError unless query.is_a?(Barometer::Query)
|
71
|
+
|
95
72
|
# use todays sun data for all future days
|
96
|
-
if measurement.forecast && sun
|
73
|
+
if measurement.forecast && measurement.current.sun
|
97
74
|
measurement.forecast.each do |forecast|
|
98
|
-
forecast.sun = sun
|
75
|
+
forecast.sun = measurement.current.sun
|
99
76
|
end
|
100
77
|
end
|
101
78
|
|
102
|
-
local_time = measurement.timezone ? Data::LocalTime.parse(
|
103
|
-
measurement.timezone.utc_to_local(Time.now.utc)
|
104
|
-
) : nil
|
105
|
-
measurement.measured_at = local_time
|
106
|
-
measurement.current.current_at = local_time
|
107
|
-
|
108
79
|
measurement
|
109
80
|
end
|
81
|
+
|
82
|
+
def self._parse_full_timezone(data)
|
83
|
+
raise ArgumentError unless data.is_a?(Hash)
|
84
|
+
if data && data['simpleforecast'] &&
|
85
|
+
data['simpleforecast']['forecastday'] &&
|
86
|
+
data['simpleforecast']['forecastday'].first &&
|
87
|
+
data['simpleforecast']['forecastday'].first['date']
|
88
|
+
Data::Zone.new(
|
89
|
+
data['simpleforecast']['forecastday'].first['date']['tz_long']
|
90
|
+
)
|
91
|
+
end
|
92
|
+
end
|
110
93
|
|
111
|
-
def self.
|
94
|
+
def self._build_links(data)
|
95
|
+
links = {}
|
96
|
+
if data["credit"] && data["credit_URL"]
|
97
|
+
links[data["credit"]] = data["credit_URL"]
|
98
|
+
end
|
99
|
+
links
|
100
|
+
end
|
101
|
+
|
102
|
+
def self._build_current(data, metric=true)
|
112
103
|
raise ArgumentError unless data.is_a?(Hash)
|
113
104
|
|
114
|
-
current =
|
105
|
+
current = Measurement::Current.new
|
115
106
|
current.updated_at = Data::LocalDateTime.parse(data['observation_time']) if data['observation_time']
|
116
107
|
current.humidity = data['relative_humidity'].to_i
|
117
108
|
current.icon = data['icon'] if data['icon']
|
@@ -142,15 +133,15 @@ module Barometer
|
|
142
133
|
current
|
143
134
|
end
|
144
135
|
|
145
|
-
def self.
|
136
|
+
def self._build_forecast(data, metric=true)
|
146
137
|
raise ArgumentError unless data.is_a?(Hash)
|
147
|
-
forecasts =
|
138
|
+
forecasts = Measurement::ForecastArray.new
|
148
139
|
# go through each forecast and create an instance
|
149
140
|
if data && data['simpleforecast'] &&
|
150
141
|
data['simpleforecast']['forecastday']
|
151
142
|
|
152
143
|
data['simpleforecast']['forecastday'].each do |forecast|
|
153
|
-
forecast_measurement =
|
144
|
+
forecast_measurement = Measurement::Forecast.new
|
154
145
|
forecast_measurement.icon = forecast['icon']
|
155
146
|
forecast_measurement.date = Date.parse(forecast['date']['pretty'])
|
156
147
|
forecast_measurement.pop = forecast['pop'].to_i
|
@@ -166,8 +157,8 @@ module Barometer
|
|
166
157
|
end
|
167
158
|
forecasts
|
168
159
|
end
|
169
|
-
|
170
|
-
def self.
|
160
|
+
|
161
|
+
def self._build_location(data, geo=nil)
|
171
162
|
raise ArgumentError unless data.is_a?(Hash)
|
172
163
|
location = Data::Location.new
|
173
164
|
if data['display_location']
|
@@ -183,7 +174,7 @@ module Barometer
|
|
183
174
|
location
|
184
175
|
end
|
185
176
|
|
186
|
-
def self.
|
177
|
+
def self._build_station(data)
|
187
178
|
raise ArgumentError unless data.is_a?(Hash)
|
188
179
|
station = Data::Location.new
|
189
180
|
station.id = data['station_id']
|
@@ -200,69 +191,72 @@ module Barometer
|
|
200
191
|
station
|
201
192
|
end
|
202
193
|
|
203
|
-
def self.
|
204
|
-
raise ArgumentError unless data.is_a?(Hash)
|
205
|
-
timezone = nil
|
206
|
-
if data && data['simpleforecast'] &&
|
207
|
-
data['simpleforecast']['forecastday'] &&
|
208
|
-
data['simpleforecast']['forecastday'].first &&
|
209
|
-
data['simpleforecast']['forecastday'].first['date']
|
210
|
-
timezone = Data::Zone.new(
|
211
|
-
data['simpleforecast']['forecastday'].first['date']['tz_long']
|
212
|
-
)
|
213
|
-
end
|
214
|
-
timezone || Data::Zone.new(nil)
|
215
|
-
end
|
216
|
-
|
217
|
-
def self.build_sun(data, timezone)
|
194
|
+
def self._build_sun(data)
|
218
195
|
raise ArgumentError unless data.is_a?(Hash)
|
219
|
-
raise ArgumentError unless timezone.is_a?(Data::Zone)
|
220
196
|
sun = nil
|
221
197
|
if data
|
222
198
|
if data['moon_phase']
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
data['moon_phase']['sunset']['minute'].to_i
|
233
|
-
)
|
234
|
-
end
|
235
|
-
|
236
|
-
sun = Data::Sun.new(
|
237
|
-
rise,
|
238
|
-
set
|
239
|
-
)
|
199
|
+
rise = Data::LocalTime.new(
|
200
|
+
data['moon_phase']['sunrise']['hour'].to_i,
|
201
|
+
data['moon_phase']['sunrise']['minute'].to_i
|
202
|
+
) if data['moon_phase']['sunrise']
|
203
|
+
set = Data::LocalTime.new(
|
204
|
+
data['moon_phase']['sunset']['hour'].to_i,
|
205
|
+
data['moon_phase']['sunset']['minute'].to_i
|
206
|
+
) if data['moon_phase']['sunset']
|
207
|
+
sun = Data::Sun.new(rise,set)
|
240
208
|
end
|
241
209
|
end
|
242
210
|
sun || Data::Sun.new
|
243
211
|
end
|
244
212
|
|
213
|
+
# override default _fetch behavior
|
214
|
+
# this service requires TWO seperate http requests (one for current
|
215
|
+
# and one for forecasted weather) ... combine the results
|
216
|
+
#
|
217
|
+
def self._fetch(query, metric=true)
|
218
|
+
result = []
|
219
|
+
result << _fetch_current(query)
|
220
|
+
result << _fetch_forecast(query)
|
221
|
+
result
|
222
|
+
end
|
223
|
+
|
245
224
|
# use HTTParty to get the current weather
|
246
|
-
|
225
|
+
#
|
226
|
+
def self._fetch_current(query)
|
247
227
|
return unless query
|
228
|
+
puts "fetch wunderground current: #{query.q}" if Barometer::debug?
|
248
229
|
self.get(
|
249
230
|
"http://api.wunderground.com/auto/wui/geo/WXCurrentObXML/index.xml",
|
250
|
-
:query => {:query => query},
|
231
|
+
:query => {:query => query.q},
|
251
232
|
:format => :xml,
|
252
233
|
:timeout => Barometer.timeout
|
253
234
|
)['current_observation']
|
254
235
|
end
|
255
236
|
|
256
237
|
# use HTTParty to get the forecasted weather
|
257
|
-
|
238
|
+
#
|
239
|
+
def self._fetch_forecast(query)
|
258
240
|
return unless query
|
241
|
+
puts "fetch wunderground forecast: #{query.q}" if Barometer::debug?
|
259
242
|
self.get(
|
260
243
|
"http://api.wunderground.com/auto/wui/geo/ForecastXML/index.xml",
|
261
|
-
:query => {:query => query},
|
244
|
+
:query => {:query => query.q},
|
262
245
|
:format => :xml,
|
263
246
|
:timeout => Barometer.timeout
|
264
247
|
)['forecast']
|
265
248
|
end
|
266
249
|
|
250
|
+
# since we have two sets of data, override these calls to choose the
|
251
|
+
# right set of data
|
252
|
+
#
|
253
|
+
def self._current_result(data); data[0]; end
|
254
|
+
def self._forecast_result(data=nil); data[1]; end
|
255
|
+
def self._location_result(data=nil); data[0]; end
|
256
|
+
def self._station_result(data=nil); data[0]; end
|
257
|
+
def self._links_result(data=nil); data[0]; end
|
258
|
+
def self._sun_result(data=nil); data[1]; end
|
259
|
+
def self._timezone_result(data=nil); data[1]; end
|
260
|
+
|
267
261
|
end
|
268
262
|
end
|
@@ -45,103 +45,54 @@ module Barometer
|
|
45
45
|
#
|
46
46
|
class WeatherService::Yahoo < WeatherService
|
47
47
|
|
48
|
-
|
49
|
-
|
48
|
+
#########################################################################
|
49
|
+
# PRIVATE
|
50
|
+
# If class methods could be private, the remaining methods would be.
|
51
|
+
#
|
50
52
|
|
51
|
-
|
52
|
-
def self.
|
53
|
+
def self._source_name; :yahoo; end
|
54
|
+
def self._accepted_formats; [:zipcode, :weather_id]; end
|
55
|
+
|
56
|
+
def self._wet_icon_codes
|
53
57
|
codes = [1] + (3..18).to_a + [35] + (37..43).to_a + (45..47).to_a
|
54
58
|
codes.collect {|c| c.to_s}
|
55
59
|
end
|
56
|
-
def self.
|
60
|
+
def self._sunny_icon_codes
|
57
61
|
codes = (29..34).to_a + [36]
|
58
62
|
codes.collect {|c| c.to_s}
|
59
63
|
end
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
end
|
79
|
-
|
80
|
-
sun = nil
|
81
|
-
if measurement.current
|
82
|
-
sun = self.build_sun(result)
|
83
|
-
measurement.current.sun = sun
|
84
|
-
end
|
85
|
-
# use todays sun data for all future days
|
86
|
-
if measurement.forecast && sun
|
87
|
-
measurement.forecast.each do |forecast|
|
88
|
-
forecast.sun = sun
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
local_time = self.build_local_time(result)
|
93
|
-
if local_time
|
94
|
-
measurement.measured_at = local_time
|
95
|
-
measurement.current.current_at = local_time
|
64
|
+
|
65
|
+
def self._build_extra(measurement, result, metric=true)
|
66
|
+
#raise ArgumentError unless measurement.is_a?(Data::Measurement)
|
67
|
+
#raise ArgumentError unless query.is_a?(Barometer::Query)
|
68
|
+
|
69
|
+
# use todays sun data for all future days
|
70
|
+
if measurement.forecast && measurement.current.sun
|
71
|
+
measurement.forecast.each do |forecast|
|
72
|
+
forecast.sun = measurement.current.sun
|
73
|
+
end
|
74
|
+
end
|
75
|
+
measurement
|
76
|
+
end
|
77
|
+
|
78
|
+
def self._build_timezone(data)
|
79
|
+
if data && data['item'] && data['item']['pubDate']
|
80
|
+
zone_match = data['item']['pubDate'].match(/ ([A-Z]*)$/)
|
81
|
+
Data::Zone.new(zone_match[1]) if zone_match
|
96
82
|
end
|
97
|
-
|
98
|
-
measurement
|
99
83
|
end
|
100
84
|
|
101
|
-
def self.
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
now_utc = Time.now.utc
|
106
|
-
|
107
|
-
# get published date
|
108
|
-
pub_date = data['item']['pubDate']
|
109
|
-
|
110
|
-
# get the TIME ZONE CODE
|
111
|
-
zone_match = pub_date.match(/ ([A-Z]*)$/) if pub_date
|
112
|
-
|
113
|
-
if zone_match
|
114
|
-
zone = zone_match[1]
|
115
|
-
|
116
|
-
# try converting pub_date to utc
|
117
|
-
# pub_date_utc = Data::Zone.code_to_utc(Time.parse(pub_date), zone) if zone
|
118
|
-
|
119
|
-
# how far back was this?
|
120
|
-
# data_age_in_seconds = now_utc - pub_date_utc
|
121
|
-
|
122
|
-
# is this older then 2 hours
|
123
|
-
# if (data_age_in_seconds < 0) || (data_age_in_seconds > (60 * 60 * 2))
|
124
|
-
# we may have converted the time wrong.
|
125
|
-
# if pub_date in the future, then?
|
126
|
-
# if pub_date too far back, then?
|
127
|
-
|
128
|
-
# for now do nothing ... don't set measured_time
|
129
|
-
# return nil
|
130
|
-
# else
|
131
|
-
# everything seems fine
|
132
|
-
# convert now to the local time
|
133
|
-
offset = Data::Zone.zone_to_offset(zone)
|
134
|
-
return Data::LocalTime.parse(now_utc + offset)
|
135
|
-
# end
|
85
|
+
def self._build_links(data)
|
86
|
+
links = {}
|
87
|
+
if data["title"] && data["link"]
|
88
|
+
links[data["title"]] = data["link"]
|
136
89
|
end
|
137
|
-
|
90
|
+
links
|
138
91
|
end
|
139
|
-
end
|
140
|
-
end
|
141
92
|
|
142
|
-
def self.
|
93
|
+
def self._build_current(data, metric=true)
|
143
94
|
raise ArgumentError unless data.is_a?(Hash)
|
144
|
-
current =
|
95
|
+
current = Measurement::Current.new(metric)
|
145
96
|
if data
|
146
97
|
if data['item'] && data['item']['yweather:condition']
|
147
98
|
condition_result = data['item']['yweather:condition']
|
@@ -171,15 +122,15 @@ end
|
|
171
122
|
current
|
172
123
|
end
|
173
124
|
|
174
|
-
def self.
|
125
|
+
def self._build_forecast(data, metric=true)
|
175
126
|
raise ArgumentError unless data.is_a?(Hash)
|
176
|
-
forecasts =
|
127
|
+
forecasts = Measurement::ForecastArray.new
|
177
128
|
|
178
129
|
if data && data['item'] && data['item']['yweather:forecast']
|
179
130
|
forecast_result = data['item']['yweather:forecast']
|
180
131
|
|
181
132
|
forecast_result.each do |forecast|
|
182
|
-
forecast_measurement =
|
133
|
+
forecast_measurement = Measurement::Forecast.new
|
183
134
|
forecast_measurement.icon = forecast['code']
|
184
135
|
forecast_measurement.date = Date.parse(forecast['date'])
|
185
136
|
forecast_measurement.condition = forecast['text']
|
@@ -193,7 +144,7 @@ end
|
|
193
144
|
forecasts
|
194
145
|
end
|
195
146
|
|
196
|
-
def self.
|
147
|
+
def self._build_location(data, geo=nil)
|
197
148
|
raise ArgumentError unless data.is_a?(Hash)
|
198
149
|
raise ArgumentError unless (geo.nil? || geo.is_a?(Data::Geo))
|
199
150
|
location = Data::Location.new
|
@@ -219,7 +170,7 @@ end
|
|
219
170
|
location
|
220
171
|
end
|
221
172
|
|
222
|
-
def self.
|
173
|
+
def self._build_sun(data)
|
223
174
|
raise ArgumentError unless data.is_a?(Hash)
|
224
175
|
sun = nil
|
225
176
|
if data && data['yweather:astronomy'] && data['item']
|
@@ -229,12 +180,14 @@ end
|
|
229
180
|
end
|
230
181
|
sun || Data::Sun.new
|
231
182
|
end
|
232
|
-
|
183
|
+
|
233
184
|
# use HTTParty to get the current weather
|
234
|
-
def self.
|
185
|
+
def self._fetch(query, metric=true)
|
186
|
+
return unless query
|
187
|
+
puts "fetch yahoo: #{query.q}" if Barometer::debug?
|
235
188
|
self.get(
|
236
189
|
"http://weather.yahooapis.com/forecastrss",
|
237
|
-
:query => {:p => query, :u => (metric ? 'c' : 'f')},
|
190
|
+
:query => {:p => query.q, :u => (metric ? 'c' : 'f')},
|
238
191
|
:format => :xml,
|
239
192
|
:timeout => Barometer.timeout
|
240
193
|
)['rss']['channel']
|