attack-barometer 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -30,12 +30,14 @@ module Barometer
30
30
  :geocode => "Geocode"
31
31
  }
32
32
 
33
- attr_accessor :format, :q, :country_code, :geo
33
+ attr_accessor :format, :q, :country_code
34
+ attr_accessor :geo, :timezone, :conversions
34
35
 
35
36
  def initialize(query=nil)
36
37
  return unless query
37
38
  @q = query
38
39
  self.analyze!
40
+ @conversions = {}
39
41
  end
40
42
 
41
43
  # analyze the saved query to determine the format.
@@ -61,10 +63,16 @@ module Barometer
61
63
  raise ArgumentError unless (preferred_formats && preferred_formats.size > 0)
62
64
 
63
65
  # why convert if we are already there?
66
+ # (except in the case that the serivce excepts coordinates and we have a
67
+ # a geocode ... the google geocode results are superior)
68
+ #
64
69
  skip_conversion = false
65
- if preferred_formats.include?(@format.to_sym)
66
- skip_conversion = true
67
- converted_query = self.dup
70
+ unless (@format.to_sym == Query::Format::Geocode.format) &&
71
+ preferred_formats.include?(Query::Format::Coordinates.format)
72
+ if preferred_formats.include?(@format.to_sym)
73
+ skip_conversion = true
74
+ converted_query = self.dup
75
+ end
68
76
  end
69
77
 
70
78
  unless skip_conversion
@@ -78,11 +86,14 @@ module Barometer
78
86
  converted_query = Barometer::Query.new(@q)
79
87
  end
80
88
  unless converted
81
- converted_query = Query::Format.const_get(klass.to_s).to(self)
89
+ unless converted_query = get_conversion(preferred_format)
90
+ converted_query = Query::Format.const_get(klass.to_s).to(self)
91
+ end
82
92
  converted = true if converted_query
83
93
  end
84
94
  if converted
85
95
  converted_query.country_code ||= Query::Format.const_get(klass.to_s).country_code(converted_query.q)
96
+ post_conversion(converted_query)
86
97
  break
87
98
  end
88
99
  end
@@ -94,13 +105,52 @@ module Barometer
94
105
  if converted_query && converted_query.geo
95
106
  @geo = converted_query.geo
96
107
  else
108
+ puts "enhance geocode: #{converted_query.q}" if Barometer::debug?
97
109
  geo_query = Query::Format::Coordinates.to(converted_query)
98
110
  @geo = geo_query.geo if (geo_query && geo_query.geo)
111
+ converted_query.geo = @geo.dup
112
+ end
113
+ end
114
+
115
+ # enhance timezone?, unless we already did
116
+ #
117
+ if Barometer.enhance_timezone && !@timezone
118
+ if converted_query && converted_query.timezone
119
+ @geo = converted_query.timezone
120
+ elsif @geo && @geo.latitude && @geo.longitude
121
+ puts "enhance timezone: #{@geo.latitude}, #{@geo.longitude}" if Barometer::debug?
122
+ @timezone = WebService::Timezone.fetch(@geo.latitude,@geo.longitude)
123
+ converted_query.timezone = @timezone.dup
99
124
  end
100
125
  end
101
126
 
102
127
  converted_query
103
128
  end
104
129
 
130
+ # save the important parts of the conversion ... by saving conversion we
131
+ # can avoid doing the same conversion multiple times
132
+ #
133
+ def post_conversion(converted_query)
134
+ return unless (converted_query && converted_query.q && converted_query.format)
135
+ @conversions = {} unless @conversions
136
+ return if @conversions.has_key?(converted_query.format.to_sym)
137
+ puts "store: #{self.format} -> #{converted_query.format.to_sym} = #{self.q} -> #{converted_query.q}" if Barometer::debug?
138
+ @conversions[converted_query.format.to_sym] = converted_query.q
139
+ end
140
+
141
+ def get_conversion(format)
142
+ return nil unless format && @conversions
143
+ puts "found: #{self.format} -> #{format.to_sym} = #{self.q} -> #{@conversions[format.to_sym]}" if Barometer::debug? && @conversions.has_key?(format.to_sym)
144
+ # re-constuct converted query
145
+ if q = @conversions[format.to_sym]
146
+ converted_query = self.dup
147
+ converted_query.q = q
148
+ converted_query.format = format
149
+ converted_query
150
+ else
151
+ nil
152
+ end
153
+ end
154
+
105
155
  end
106
156
  end
@@ -7,10 +7,12 @@ require 'weather_services/wunderground'
7
7
  require 'weather_services/google'
8
8
  require 'weather_services/yahoo'
9
9
  require 'weather_services/weather_dot_com'
10
+ require 'weather_services/weather_bug'
10
11
 
11
12
  #
12
13
  # web services (non weather)
13
14
  #
14
15
  require 'web_services/web_service'
15
16
  require 'web_services/geocode'
16
- require 'web_services/weather_id'
17
+ require 'web_services/weather_id'
18
+ require 'web_services/timezone'
@@ -0,0 +1,360 @@
1
+ # first term - time zone short code
2
+ # second term - UTC offset (- or +)
3
+ #
4
+ A : 1
5
+ ACDT : 10.5
6
+ ACST : 9.5
7
+ ADT : -3
8
+ AEDT : 11
9
+
10
+ AEST : 10
11
+ AFT : 4.5
12
+ AHDT : -9
13
+ AHST : -10
14
+ AKDT : -8
15
+ AKST : -9
16
+ AMST : 5
17
+ AMT : 4
18
+ ANAST : 13
19
+ ANAT : 12
20
+ ART : -3
21
+ AST : -4
22
+ AT : -1
23
+ AWDT : 9
24
+ AWST : 8
25
+ AZOST : 0
26
+ AZOT : -1
27
+ AZST : 5
28
+ AZT : 4
29
+
30
+ B : 2
31
+ BADT : 4
32
+ BAT : 6
33
+ BDST : 2
34
+ BDT : 6
35
+ BET : -11
36
+ BNT : 8
37
+ BORT : 8
38
+ BOT : -4
39
+ BRA : -3
40
+ BST : 1
41
+ BT : 6
42
+ BTT : 6
43
+
44
+ C : 3
45
+ CAT : 2
46
+ CCT : 8
47
+ CEST : 2
48
+ CET : 1
49
+ CHADT : 13.75
50
+ CHAST : 12.75
51
+ CHST : 10
52
+ CKT : -10
53
+ CLST : -3
54
+ CLT : -4
55
+ COT : -5
56
+ CUT : 0
57
+ CVT : -1
58
+ CWT : 8.75
59
+ CXT : 7
60
+ CEDT : 2
61
+
62
+ D : 4
63
+ DAVT : 7
64
+ DDUT : 10
65
+ DNT : 1
66
+ DST : 2
67
+
68
+ E : 5
69
+ EASST : -5
70
+ EAST : -6
71
+ EAT : 3
72
+ ECT : -5
73
+ EEST : 3
74
+ EET : 2
75
+ EGST : 0
76
+ EGT : -1
77
+ EMT : 1
78
+ EEDT : 3
79
+
80
+ F : 6
81
+ FDT : -1
82
+ FJST : 13
83
+ FJT : 12
84
+ FKST : -3
85
+ FKT : -4
86
+ FST : 2
87
+ FWT : 1
88
+
89
+ G : 7
90
+ GALT : -6
91
+ GAMT : -9
92
+ GEST : 5
93
+ GET : 4
94
+ GFT : -3
95
+ GILT : 12
96
+ GST : 4
97
+ GT : 0
98
+ GYT : -4
99
+ GZ : 0
100
+
101
+ H : 8
102
+ HAA : -3
103
+ HAC : -5
104
+ HADT : -9
105
+ HAE : -4
106
+ HAP : -7
107
+ HAR : -6
108
+ HAST : -10
109
+ HAT : -2.5
110
+ HAY : -8
111
+ HDT : -9.5
112
+ HFE : 2
113
+ HFH : 1
114
+ HG : 0
115
+ HKT : 8
116
+ HNA : -4
117
+ HNC : -6
118
+ HNE : -5
119
+ HNP : -8
120
+ HNR : -7
121
+ HNT : -3.5
122
+ HNY : -9
123
+ HOE : 1
124
+ HST : -10
125
+
126
+ I : 9
127
+ ICT : 4
128
+ IDLE : 12
129
+ IDLW : -12
130
+ IDT : 1
131
+ IOT : 5
132
+ IRDT : 4.5
133
+ IRKST : 9
134
+ IRKT : 8
135
+ IRST : 3.5
136
+ IRT : 3.5
137
+ IST : 1
138
+ IT : 3.5
139
+ ITA : 1
140
+
141
+ JAVT : 7
142
+ JAYT : 9
143
+ JFDT : -3
144
+ JFST : -4
145
+ JST : 9
146
+ JT : 7
147
+
148
+ K : 10
149
+ KDT : 10
150
+ KGST : 6
151
+ KGT : 5
152
+ KOST : 12
153
+ KOVT : 7
154
+ KOVST : 8
155
+ KRAST : 8
156
+ KRAT : 7
157
+ KST : 9
158
+
159
+ L : 11
160
+ LHDT : 11
161
+ LHST : 10.5
162
+ LIGT : 10
163
+ LINT : 14
164
+ LKT : 6
165
+ LST : 1
166
+
167
+ M : 12
168
+ MAGST : 12
169
+ MAGT : 11
170
+ MAL : 8
171
+ MART : -9.5
172
+ MAT : 3
173
+ MAWT : 6
174
+ MBT : 8
175
+ MED : 2
176
+ MEDST : 2
177
+ MEST : 2
178
+ MESZ : 2
179
+ MET : 1
180
+ MEWT : 1
181
+ MEX : -6
182
+ MEZ : 1
183
+ MHT : 12
184
+ MIT : 9.5
185
+ MMT : 6.5
186
+ MNT : 8
187
+ MNST : 9
188
+ MPT : 10
189
+ MSD : 4
190
+ MSK : 3
191
+ MSKS : 4
192
+ MT : 8.5
193
+ MUT : 4
194
+ MUST : 5
195
+ MVT : 5
196
+ MYT : 8
197
+ MFPT : -10
198
+
199
+ N : -1
200
+ NCT : 11
201
+ NDT : -2.5
202
+ NFT : 11.5
203
+ NOR : 1
204
+ NOVST : 7
205
+ NOVT : 6
206
+ NPT : 5.75
207
+ NRT : 12
208
+ NST : -3.5
209
+ NSUT : 6.5
210
+ NT : -11
211
+ NUT : -11
212
+ NZDT : 13
213
+ NZST : 12
214
+ NZT : 12
215
+
216
+ O : -2
217
+ OESZ : 3
218
+ OEZ : 2
219
+ OMSK : 7
220
+ OMSST : 7
221
+ OMST : 6
222
+
223
+ P : -3
224
+ PET : -5
225
+ PETST : 13
226
+ PETT : 12
227
+ PGT : 10
228
+ PHOT : 13
229
+ PHT : 8
230
+ PIT : 8
231
+ PKT : 5
232
+ PKST : 6
233
+ PMDT : -2
234
+ PMST : -3
235
+ PMT : -3
236
+ PNT : -8.5
237
+ PONT : 11
238
+ PYST : -3
239
+ PYT : -4
240
+ PWT : 9
241
+
242
+ Q : -4
243
+
244
+ R : -5
245
+ R1T : 2
246
+ R2T : 3
247
+ RET : 4
248
+ ROK : 9
249
+ ROTT : -3
250
+
251
+ S : -6
252
+ SADT : 10.5
253
+ SAMST : 5
254
+ SAMT : 4
255
+ SAST : 2
256
+ SBT : 11
257
+ SCT : 4
258
+ SCDT : 13
259
+ SCST : 12
260
+ SET : 1
261
+ SGT : 8
262
+ SIT : 8
263
+ SLT : -4
264
+ SLST : -3
265
+ SRT : -3
266
+ SST : -11
267
+ SYST : 3
268
+ SWT : 1
269
+ SYT : 2
270
+
271
+ T : -7
272
+ TAHT : -10
273
+ TFT : 5
274
+ THA : 7
275
+ THAT : -10
276
+ TJT : 5
277
+ TKT : -10
278
+ TMT : 5
279
+ TOT : 13
280
+ TRUK : 10
281
+ TPT : 9
282
+ TRUT : 10
283
+ TST : 3
284
+ TUC : 0
285
+ TVT : 12
286
+ TWT : 8
287
+
288
+ U : -8
289
+ ULAST : 9
290
+ ULAT : 8
291
+ USZ1 : 2
292
+ USZ1S : 3
293
+ USZ3 : 4
294
+ USZ3S : 5
295
+ USZ4 : 5
296
+ USZ4S : 6
297
+ USZ5 : 6
298
+ USZ5S : 7
299
+ USZ6 : 7
300
+ USZ6S : 8
301
+ USZ7 : 8
302
+ USZ7S : 9
303
+ USZ8 : 9
304
+ USZ8S : 10
305
+ USZ9 : 10
306
+ USZ9S : 11
307
+ UTZ : -3
308
+ UYT : -3
309
+ UYST : -2
310
+ UZ10 : 11
311
+ UZ10S : 12
312
+ UZ11 : 12
313
+ UZ11S : 13
314
+ UZ12 : 12
315
+ UZ12S : 13
316
+ UZT : 5
317
+
318
+ V : -9
319
+ VET : -4.5
320
+ VLAST : 11
321
+ VLAT : 10
322
+ VOST : 6
323
+ VST : -4.5
324
+ VTZ : -2
325
+ VUT : 11
326
+
327
+ W : -10
328
+ WAKT : 12
329
+ WAST : 2
330
+ WAT : 1
331
+ WCT : 8.75
332
+ WEST : 1
333
+ WESZ : 1
334
+ WET : 0
335
+ WEZ : 0
336
+ WFT : 12
337
+ WGST : -2
338
+ WGT : -3
339
+ WIB : 7
340
+ WITA : 8
341
+ WIT : 9
342
+ WST : 8
343
+ WKST : 5
344
+ WTZ : -1
345
+ WUT : 1
346
+ WEDT : 1
347
+ WDT : 9
348
+
349
+ X : -11
350
+
351
+ Y : -12
352
+ YAKST : 10
353
+ YAKT : 9
354
+ YAPT : 10
355
+ YDT : -8
356
+ YEKST : 6
357
+ YEKT : 5
358
+ YST : -9
359
+
360
+ Z : 0
@@ -8,6 +8,7 @@ module Barometer
8
8
  class Weather
9
9
 
10
10
  attr_accessor :measurements
11
+ attr_accessor :start_at, :end_at
11
12
 
12
13
  def initialize; @measurements = []; end
13
14
 
@@ -139,7 +140,7 @@ module Barometer
139
140
  # pass the question on to each successful measurement until we get an answer
140
141
  #
141
142
 
142
- def windy?(threshold=10, time_string=nil)
143
+ def windy?(time_string=nil, threshold=10)
143
144
  local_datetime = Data::LocalDateTime.parse(time_string)
144
145
  raise ArgumentError unless (threshold.is_a?(Fixnum) || threshold.is_a?(Float))
145
146
  raise ArgumentError unless (local_datetime.nil? || local_datetime.is_a?(Data::LocalDateTime))
@@ -147,14 +148,14 @@ module Barometer
147
148
  is_windy = nil
148
149
  @measurements.each do |measurement|
149
150
  if measurement.success?
150
- is_windy = measurement.windy?(threshold, local_datetime)
151
+ is_windy = measurement.windy?(local_datetime, threshold)
151
152
  return is_windy if !is_windy.nil?
152
153
  end
153
154
  end
154
155
  is_windy
155
156
  end
156
157
 
157
- def wet?(threshold=50, time_string=nil)
158
+ def wet?(time_string=nil, threshold=50)
158
159
  local_datetime = Data::LocalDateTime.parse(time_string)
159
160
  raise ArgumentError unless (threshold.is_a?(Fixnum) || threshold.is_a?(Float))
160
161
  raise ArgumentError unless (local_datetime.nil? || local_datetime.is_a?(Data::LocalDateTime))
@@ -162,7 +163,7 @@ module Barometer
162
163
  is_wet = nil
163
164
  @measurements.each do |measurement|
164
165
  if measurement.success?
165
- is_wet = measurement.wet?(threshold, local_datetime)
166
+ is_wet = measurement.wet?(local_datetime, threshold)
166
167
  return is_wet if !is_wet.nil?
167
168
  end
168
169
  end
@@ -35,43 +35,25 @@ module Barometer
35
35
  #
36
36
  class WeatherService::Google < WeatherService
37
37
 
38
- def self.source_name; :google; end
39
- def self.accepted_formats; [:zipcode, :postalcode, :geocode]; end
38
+ #########################################################################
39
+ # PRIVATE
40
+ # If class methods could be private, the remaining methods would be.
41
+ #
40
42
 
41
- def self.wet_icon_codes
43
+ def self._source_name; :google; end
44
+ def self._accepted_formats; [:zipcode, :postalcode, :geocode]; end
45
+
46
+ def self._wet_icon_codes
42
47
  %w(rain chance_of_rain chance_of_storm thunderstorm mist)
43
48
  end
44
- def self.sunny_icon_codes
49
+ def self._sunny_icon_codes
45
50
  %w(sunny mostly_sunny partly_cloudy)
46
51
  end
47
-
48
- def self._measure(measurement, query, metric=true)
49
- raise ArgumentError unless measurement.is_a?(Data::Measurement)
50
- raise ArgumentError unless query.is_a?(Barometer::Query)
51
- measurement.source = self.source_name
52
-
53
- begin
54
- result = self.get_all(query.q, metric)
55
- rescue Timeout::Error => e
56
- return measurement
57
- end
58
-
59
- measurement.current = self.build_current(result, metric)
60
- measurement.forecast = self.build_forecast(result, metric)
61
- measurement.location = self.build_location(query.geo)
62
- measurement
63
- end
64
52
 
65
- def self.build_current(data, metric=true)
53
+ def self._build_current(data, metric=true)
66
54
  raise ArgumentError unless data.is_a?(Hash)
67
- current = Data::CurrentMeasurement.new
55
+ current = Measurement::Current.new
68
56
 
69
- # google gives utc time, no way to convert to local
70
- #if data && data['forecast_information'] &&
71
- # data['forecast_information']['current_date_time']
72
- # current.updated_at = Data::LocalDateTime.parse(data['forecast_information']['current_date_time']['data'])
73
- #end
74
-
75
57
  if data['current_conditions']
76
58
  data = data['current_conditions']
77
59
  if data['icon']
@@ -96,10 +78,10 @@ module Barometer
96
78
  current
97
79
  end
98
80
 
99
- def self.build_forecast(data, metric=true)
81
+ def self._build_forecast(data, metric=true)
100
82
  raise ArgumentError unless data.is_a?(Hash)
101
83
 
102
- forecasts = []
84
+ forecasts = Measurement::ForecastArray.new
103
85
  return forecasts unless data && data['forecast_information'] &&
104
86
  data['forecast_information']['forecast_date']
105
87
  start_date = Date.parse(data['forecast_information']['forecast_date']['data'])
@@ -108,7 +90,7 @@ module Barometer
108
90
  # go through each forecast and create an instance
109
91
  d = 0
110
92
  data.each do |forecast|
111
- forecast_measurement = Data::ForecastMeasurement.new
93
+ forecast_measurement = Measurement::Forecast.new
112
94
  if forecast['icon']
113
95
  icon_match = forecast['icon']['data'].match(/.*\/([A-Za-z_]*)\.png/)
114
96
  forecast_measurement.icon = icon_match[1] if icon_match
@@ -130,7 +112,7 @@ module Barometer
130
112
  forecasts
131
113
  end
132
114
 
133
- def self.build_location(geo=nil)
115
+ def self._build_location(result=nil, geo=nil)
134
116
  raise ArgumentError unless (geo.nil? || geo.is_a?(Data::Geo))
135
117
  location = Data::Location.new
136
118
  if geo
@@ -145,10 +127,12 @@ module Barometer
145
127
  end
146
128
 
147
129
  # use HTTParty to get the current weather
148
- def self.get_all(query, metric=true)
130
+ def self._fetch(query, metric=true)
131
+ return unless query
132
+ puts "fetch google: #{query.q}" if Barometer::debug?
149
133
  self.get(
150
134
  "http://google.com/ig/api",
151
- :query => {:weather => query, :hl => (metric ? "en-GB" : "en-US")},
135
+ :query => {:weather => query.q, :hl => (metric ? "en-GB" : "en-US")},
152
136
  :format => :xml,
153
137
  :timeout => Barometer.timeout
154
138
  )['xml_api_reply']['weather']