attack-barometer 0.5.0 → 0.6.0

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.
Files changed (64) hide show
  1. data/README.rdoc +51 -9
  2. data/VERSION.yml +1 -1
  3. data/bin/barometer +57 -7
  4. data/lib/barometer/base.rb +3 -0
  5. data/lib/barometer/data/sun.rb +10 -0
  6. data/lib/barometer/data/zone.rb +79 -188
  7. data/lib/barometer/data.rb +11 -6
  8. data/lib/barometer/formats/coordinates.rb +4 -1
  9. data/lib/barometer/formats/geocode.rb +9 -7
  10. data/lib/barometer/formats/icao.rb +2 -2
  11. data/lib/barometer/formats/weather_id.rb +2 -2
  12. data/lib/barometer/measurements/common.rb +113 -0
  13. data/lib/barometer/{data → measurements}/current.rb +17 -42
  14. data/lib/barometer/measurements/forecast.rb +62 -0
  15. data/lib/barometer/measurements/forecast_array.rb +72 -0
  16. data/lib/barometer/{data → measurements}/measurement.rb +57 -45
  17. data/lib/barometer/measurements/night.rb +27 -0
  18. data/lib/barometer/query.rb +55 -5
  19. data/lib/barometer/services.rb +3 -1
  20. data/lib/barometer/translations/zone_codes.yml +360 -0
  21. data/lib/barometer/weather.rb +5 -4
  22. data/lib/barometer/weather_services/google.rb +19 -35
  23. data/lib/barometer/weather_services/service.rb +113 -255
  24. data/lib/barometer/weather_services/weather_bug.rb +291 -2
  25. data/lib/barometer/weather_services/weather_dot_com.rb +45 -54
  26. data/lib/barometer/weather_services/wunderground.rb +83 -89
  27. data/lib/barometer/weather_services/yahoo.rb +44 -91
  28. data/lib/barometer/web_services/geocode.rb +1 -0
  29. data/lib/barometer/web_services/timezone.rb +40 -0
  30. data/lib/barometer/web_services/weather_id.rb +17 -2
  31. data/lib/barometer.rb +11 -0
  32. data/lib/demometer/demometer.rb +28 -0
  33. data/lib/demometer/public/css/master.css +259 -1
  34. data/lib/demometer/views/index.erb +2 -0
  35. data/lib/demometer/views/layout.erb +3 -2
  36. data/lib/demometer/views/measurement.erb +4 -1
  37. data/lib/demometer/views/readme.erb +116 -88
  38. data/spec/data/sun_spec.rb +53 -0
  39. data/spec/data/zone_spec.rb +330 -100
  40. data/spec/fixtures/formats/weather_id/ksfo.xml +1 -0
  41. data/spec/fixtures/services/weather_bug/90210_current.xml +1 -0
  42. data/spec/fixtures/services/weather_bug/90210_forecast.xml +1 -0
  43. data/spec/formats/weather_id_spec.rb +10 -5
  44. data/spec/measurements/common_spec.rb +352 -0
  45. data/spec/{data → measurements}/current_spec.rb +40 -103
  46. data/spec/measurements/forecast_array_spec.rb +165 -0
  47. data/spec/measurements/forecast_spec.rb +135 -0
  48. data/spec/{data → measurements}/measurement_spec.rb +86 -107
  49. data/spec/measurements/night_measurement_spec.rb +49 -0
  50. data/spec/query_spec.rb +12 -2
  51. data/spec/spec_helper.rb +28 -1
  52. data/spec/weather_services/google_spec.rb +27 -117
  53. data/spec/weather_services/services_spec.rb +49 -1024
  54. data/spec/weather_services/weather_bug_spec.rb +274 -0
  55. data/spec/weather_services/weather_dot_com_spec.rb +45 -125
  56. data/spec/weather_services/wunderground_spec.rb +42 -136
  57. data/spec/weather_services/yahoo_spec.rb +26 -116
  58. data/spec/weather_spec.rb +45 -45
  59. metadata +23 -11
  60. data/lib/barometer/data/forecast.rb +0 -84
  61. data/lib/barometer/data/night.rb +0 -69
  62. data/lib/barometer/extensions/graticule.rb +0 -51
  63. data/spec/data/forecast_spec.rb +0 -192
  64. data/spec/data/night_measurement_spec.rb +0 -136
@@ -46,72 +46,63 @@ module Barometer
46
46
  #
47
47
  class WeatherService::Wunderground < WeatherService
48
48
 
49
- def self.source_name; :wunderground; end
50
- def self.accepted_formats
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.wet_icon_codes
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.sunny_icon_codes
64
+ def self._sunny_icon_codes
60
65
  %w(clear mostlysunny partlysunny sunny partlycloudy)
61
66
  end
62
67
 
63
- def self._measure(measurement, query, metric=true)
64
- raise ArgumentError unless measurement.is_a?(Data::Measurement)
65
- raise ArgumentError unless query.is_a?(Barometer::Query)
66
- measurement.source = self.source_name
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.build_current(data, metric=true)
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 = Data::CurrentMeasurement.new
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.build_forecast(data, metric=true)
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 = Data::ForecastMeasurement.new
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.build_location(data)
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.build_station(data)
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.build_timezone(data)
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
- if data['moon_phase']['sunrise']
224
- rise = Data::LocalTime.new(
225
- data['moon_phase']['sunrise']['hour'].to_i,
226
- data['moon_phase']['sunrise']['minute'].to_i
227
- )
228
- end
229
- if data['moon_phase']['sunset']
230
- set = Data::LocalTime.new(
231
- data['moon_phase']['sunset']['hour'].to_i,
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
- def self.get_current(query)
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
- def self.get_forecast(query)
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
- def self.source_name; :yahoo; end
49
- def self.accepted_formats; [:zipcode, :weather_id]; end
48
+ #########################################################################
49
+ # PRIVATE
50
+ # If class methods could be private, the remaining methods would be.
51
+ #
50
52
 
51
- # these are the icon codes that indicate "wet", used by wet? function
52
- def self.wet_icon_codes
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.sunny_icon_codes
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
- def self._measure(measurement, query, metric=true)
62
- raise ArgumentError unless measurement.is_a?(Data::Measurement)
63
- raise ArgumentError unless query.is_a?(Barometer::Query)
64
- measurement.source = self.source_name
65
-
66
- begin
67
- result = self.fetch(query.q, metric)
68
- rescue Timeout::Error => e
69
- return measurement
70
- end
71
-
72
- measurement.current = self.build_current(result, metric)
73
- measurement.forecast = self.build_forecast(result, metric)
74
- measurement.location = self.build_location(result, query.geo)
75
-
76
- if result["title"] && result["link"]
77
- measurement.links[result["title"]] = result["link"]
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.build_local_time(data)
102
- if data
103
- if data['item']
104
- # what time is it now?
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
- nil
90
+ links
138
91
  end
139
- end
140
- end
141
92
 
142
- def self.build_current(data, metric=true)
93
+ def self._build_current(data, metric=true)
143
94
  raise ArgumentError unless data.is_a?(Hash)
144
- current = Data::CurrentMeasurement.new
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.build_forecast(data, metric=true)
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 = Data::ForecastMeasurement.new
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.build_location(data, geo=nil)
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.build_sun(data)
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.fetch(query, metric=true)
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']
@@ -8,6 +8,7 @@ module Barometer
8
8
 
9
9
  def self.fetch(query)
10
10
  raise ArgumentError unless _is_a_query?(query)
11
+ puts "geocoding: #{query.q}" if Barometer::debug?
11
12
  return nil unless _has_geocode_key?
12
13
  location = self.get(
13
14
  "http://maps.google.com/maps/geo",
@@ -0,0 +1,40 @@
1
+ module Barometer
2
+ #
3
+ # Web Service: Timezone
4
+ #
5
+ # uses geonames.org to obtain the full timezone for given coordinates
6
+ #
7
+ class WebService::Timezone < WebService
8
+
9
+ # get the full timezone for given coordinates
10
+ #
11
+ def self.fetch(latitude, longitude)
12
+ puts "timezone: #{latitude}, #{longitude}"
13
+ return nil unless latitude && longitude
14
+ _fetch_via_wunderground(latitude, longitude)
15
+ end
16
+
17
+ def self._fetch_via_geonames(latitude, longitude)
18
+ response = self.get(
19
+ "http://ws.geonames.org/timezone",
20
+ :query => { :lat => latitude, :lng => longitude },
21
+ :format => :xml,
22
+ :timeout => Barometer.timeout
23
+ )['geonames']['timezone']
24
+ response ? Data::Zone.new(response['timezoneId']) : nil
25
+ end
26
+
27
+ def self._fetch_via_wunderground(latitude, longitude)
28
+ response = self.get(
29
+ "http://api.wunderground.com/auto/wui/geo/ForecastXML/index.xml",
30
+ :query => {:query => "#{latitude},#{longitude}"},
31
+ :format => :xml,
32
+ :timeout => Barometer.timeout
33
+ )['forecast']['simpleforecast']['forecastday'].first
34
+ response ? Data::Zone.new(response['date']['tz_long']) : nil
35
+ end
36
+
37
+ end
38
+ end
39
+
40
+
@@ -9,11 +9,13 @@ module Barometer
9
9
  # get the weather_id for a given query
10
10
  #
11
11
  def self.fetch(query)
12
+ puts "fetch weather_id: #{query.q}" if Barometer::debug?
12
13
  return nil unless query
13
14
  raise ArgumentError unless _is_a_query?(query)
14
- response = self.get(
15
+
16
+ self.get(
15
17
  "http://xoap.weather.com/search/search",
16
- :query => { :where => query.q }, :format => :plain,
18
+ :query => { :where => _adjust_query(query.q) }, :format => :plain,
17
19
  :timeout => Barometer.timeout
18
20
  )
19
21
  end
@@ -21,6 +23,7 @@ module Barometer
21
23
  # get the location_date (geocode) for a given weather_id
22
24
  #
23
25
  def self.reverse(query)
26
+ puts "reverse weather_id: #{query.q}" if Barometer::debug?
24
27
  return nil unless query
25
28
  raise ArgumentError unless _is_a_query?(query)
26
29
  self.get(
@@ -30,6 +33,18 @@ module Barometer
30
33
  :timeout => Barometer.timeout
31
34
  )['rss']['channel']["yweather:location"]
32
35
  end
36
+
37
+ # filter out words that weather.com has trouble geo-locating
38
+ # mostly these are icao related
39
+ #
40
+ def self._adjust_query(query)
41
+ output = query.dup
42
+ words_to_remove = %w(international airport municipal)
43
+ words_to_remove.each do |word|
44
+ output.gsub!(/#{word}/i, "")
45
+ end
46
+ output
47
+ end
33
48
 
34
49
  end
35
50
  end
data/lib/barometer.rb CHANGED
@@ -9,6 +9,12 @@ require 'barometer/formats'
9
9
 
10
10
  module Barometer
11
11
 
12
+ @@debug_mode = false
13
+ def self.debug; @@debug_mode; end;
14
+ def self.debug=(value); @@debug_mode = value; end;
15
+ def self.debug!; @@debug_mode = true; end;
16
+ def self.debug?; @@debug_mode; end;
17
+
12
18
  @@google_geocode_key = nil
13
19
  def self.google_geocode_key; @@google_geocode_key; end;
14
20
  def self.google_geocode_key=(key); @@google_geocode_key = key; end;
@@ -25,6 +31,11 @@ module Barometer
25
31
  def self.force_geocode=(value); @@force_geocode = value; end;
26
32
  def self.force_geocode!; @@force_geocode = true; end;
27
33
 
34
+ @@enhance_timezone = false
35
+ def self.enhance_timezone; @@enhance_timezone; end;
36
+ def self.enhance_timezone=(value); @@enhance_timezone = value; end;
37
+ def self.enhance_timezone!; @@enhance_timezone = true; end;
38
+
28
39
  # adjust the timeout used when interactind with external web services
29
40
  #
30
41
  @@timeout = 15
@@ -32,6 +32,23 @@ class Demometer < Sinatra::Default
32
32
  { :weather_dot_com => { :keys => { :partner => partner_key, :license => license_key } } }
33
33
  end
34
34
 
35
+ def config_weather_bug
36
+ if File.exists?(@@config_file)
37
+ keys = YAML.load_file(@@config_file)
38
+ if keys["weather_bug"] && keys["weather_bug"]["code"]
39
+ code = keys["weather_bug"]["code"].to_s
40
+ else
41
+ raise RunTimeError "no weatherbug.com keys"
42
+ exit
43
+ end
44
+ else
45
+ File.open(@@config_file, 'w') {|f| f << "\weather_bug:\n code: API_CODE" }
46
+ raise RunTimeError "no weatherbug.com keys"
47
+ exit
48
+ end
49
+ { :weather_bug => { :keys => { :code => code } } }
50
+ end
51
+
35
52
  helpers do
36
53
  def data(title, value)
37
54
  return if value.nil?
@@ -58,6 +75,13 @@ class Demometer < Sinatra::Default
58
75
  Barometer::Base.config[1] << config_weather_dot_com
59
76
  end
60
77
 
78
+ # setup weatherbug.com
79
+ if Barometer::Base.config && Barometer::Base.config[1] &&
80
+ Barometer::Base.config[1].include?(:weather_bug)
81
+ Barometer::Base.config[1].delete(:weather_bug)
82
+ Barometer::Base.config[1] << config_weather_bug
83
+ end
84
+
61
85
  if params[:query] && !params[:query][:q].empty?
62
86
  @barometer = Barometer.new(params[:query][:q])
63
87
  @weather = @barometer.measure(metric)
@@ -72,5 +96,9 @@ class Demometer < Sinatra::Default
72
96
  get '/readme.html' do
73
97
  erb :readme
74
98
  end
99
+
100
+ get '/about.html' do
101
+ erb :about
102
+ end
75
103
 
76
104
  end