barometer 0.3.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. data/README.rdoc +78 -70
  2. data/VERSION.yml +2 -2
  3. data/bin/barometer +100 -37
  4. data/lib/barometer.rb +12 -8
  5. data/lib/barometer/base.rb +48 -20
  6. data/lib/barometer/data.rb +5 -1
  7. data/lib/barometer/data/current.rb +23 -15
  8. data/lib/barometer/data/distance.rb +15 -5
  9. data/lib/barometer/data/forecast.rb +23 -5
  10. data/lib/barometer/data/geo.rb +16 -54
  11. data/lib/barometer/data/local_datetime.rb +137 -0
  12. data/lib/barometer/data/local_time.rb +134 -0
  13. data/lib/barometer/data/location.rb +6 -1
  14. data/lib/barometer/data/measurement.rb +71 -42
  15. data/lib/barometer/data/night.rb +69 -0
  16. data/lib/barometer/data/pressure.rb +15 -5
  17. data/lib/barometer/data/speed.rb +16 -5
  18. data/lib/barometer/data/sun.rb +8 -20
  19. data/lib/barometer/data/temperature.rb +22 -9
  20. data/lib/barometer/data/units.rb +10 -19
  21. data/lib/barometer/data/zone.rb +135 -9
  22. data/lib/barometer/formats.rb +12 -0
  23. data/lib/barometer/formats/coordinates.rb +42 -0
  24. data/lib/barometer/formats/format.rb +46 -0
  25. data/lib/barometer/formats/geocode.rb +51 -0
  26. data/lib/barometer/formats/icao.rb +37 -0
  27. data/lib/barometer/formats/postalcode.rb +22 -0
  28. data/lib/barometer/formats/short_zipcode.rb +17 -0
  29. data/lib/barometer/formats/weather_id.rb +107 -0
  30. data/lib/barometer/formats/zipcode.rb +31 -0
  31. data/lib/barometer/query.rb +61 -232
  32. data/lib/barometer/services.rb +14 -4
  33. data/lib/barometer/translations/icao_country_codes.yml +9 -0
  34. data/lib/barometer/translations/weather_country_codes.yml +17 -0
  35. data/lib/barometer/weather.rb +51 -30
  36. data/lib/barometer/{services → weather_services}/google.rb +23 -26
  37. data/lib/barometer/weather_services/noaa.rb +6 -0
  38. data/lib/barometer/{services → weather_services}/service.rb +101 -92
  39. data/lib/barometer/weather_services/weather_bug.rb +6 -0
  40. data/lib/barometer/weather_services/weather_dot_com.rb +261 -0
  41. data/lib/barometer/{services → weather_services}/wunderground.rb +58 -76
  42. data/lib/barometer/{services → weather_services}/yahoo.rb +91 -121
  43. data/lib/barometer/web_services/geocode.rb +33 -0
  44. data/lib/barometer/web_services/weather_id.rb +37 -0
  45. data/lib/barometer/web_services/web_service.rb +32 -0
  46. data/lib/demometer/demometer.rb +31 -4
  47. data/lib/demometer/views/forecast.erb +20 -0
  48. data/lib/demometer/views/index.erb +10 -3
  49. data/lib/demometer/views/measurement.erb +8 -3
  50. data/lib/demometer/views/readme.erb +63 -24
  51. data/spec/barometer_spec.rb +18 -36
  52. data/spec/{data_current_spec.rb → data/current_spec.rb} +73 -49
  53. data/spec/{data_distance_spec.rb → data/distance_spec.rb} +30 -30
  54. data/spec/{data_forecast_spec.rb → data/forecast_spec.rb} +57 -15
  55. data/spec/data/geo_spec.rb +91 -0
  56. data/spec/data/local_datetime_spec.rb +269 -0
  57. data/spec/data/local_time_spec.rb +239 -0
  58. data/spec/{data_location_spec.rb → data/location_spec.rb} +12 -1
  59. data/spec/{data_measurement_spec.rb → data/measurement_spec.rb} +135 -66
  60. data/spec/data/night_measurement_spec.rb +136 -0
  61. data/spec/{data_pressure_spec.rb → data/pressure_spec.rb} +29 -29
  62. data/spec/{data_speed_spec.rb → data/speed_spec.rb} +30 -30
  63. data/spec/data/sun_spec.rb +49 -0
  64. data/spec/{data_temperature_spec.rb → data/temperature_spec.rb} +44 -44
  65. data/spec/{units_spec.rb → data/units_spec.rb} +6 -6
  66. data/spec/{data_zone_spec.rb → data/zone_spec.rb} +15 -15
  67. data/spec/fixtures/formats/weather_id/90210.xml +1 -0
  68. data/spec/fixtures/formats/weather_id/atlanta.xml +1 -0
  69. data/spec/fixtures/formats/weather_id/from_USGA0028.xml +1 -0
  70. data/spec/fixtures/formats/weather_id/new_york.xml +1 -0
  71. data/spec/fixtures/{geocode_40_73.xml → geocode/40_73.xml} +0 -0
  72. data/spec/fixtures/{geocode_90210.xml → geocode/90210.xml} +0 -0
  73. data/spec/fixtures/{geocode_T5B4M9.xml → geocode/T5B4M9.xml} +0 -0
  74. data/spec/fixtures/geocode/atlanta.xml +1 -0
  75. data/spec/fixtures/{geocode_calgary_ab.xml → geocode/calgary_ab.xml} +0 -0
  76. data/spec/fixtures/{geocode_ksfo.xml → geocode/ksfo.xml} +0 -0
  77. data/spec/fixtures/{geocode_newyork_ny.xml → geocode/newyork_ny.xml} +0 -0
  78. data/spec/fixtures/{google_calgary_ab.xml → services/google/calgary_ab.xml} +0 -0
  79. data/spec/fixtures/services/weather_dot_com/90210.xml +1 -0
  80. data/spec/fixtures/{current_calgary_ab.xml → services/wunderground/current_calgary_ab.xml} +0 -0
  81. data/spec/fixtures/{forecast_calgary_ab.xml → services/wunderground/forecast_calgary_ab.xml} +0 -0
  82. data/spec/fixtures/{yahoo_90210.xml → services/yahoo/90210.xml} +0 -0
  83. data/spec/formats/coordinates_spec.rb +158 -0
  84. data/spec/formats/format_spec.rb +73 -0
  85. data/spec/formats/geocode_spec.rb +179 -0
  86. data/spec/formats/icao_spec.rb +61 -0
  87. data/spec/formats/postalcode_spec.rb +59 -0
  88. data/spec/formats/short_zipcode_spec.rb +53 -0
  89. data/spec/formats/weather_id_spec.rb +191 -0
  90. data/spec/formats/zipcode_spec.rb +111 -0
  91. data/spec/query_spec.rb +261 -288
  92. data/spec/spec_helper.rb +128 -4
  93. data/spec/{service_google_spec.rb → weather_services/google_spec.rb} +46 -46
  94. data/spec/weather_services/services_spec.rb +1118 -0
  95. data/spec/weather_services/weather_dot_com_spec.rb +327 -0
  96. data/spec/weather_services/wunderground_spec.rb +332 -0
  97. data/spec/{service_yahoo_spec.rb → weather_services/yahoo_spec.rb} +65 -81
  98. data/spec/weather_spec.rb +73 -61
  99. data/spec/web_services/geocode_spec.rb +45 -0
  100. data/spec/web_services/web_services_spec.rb +26 -0
  101. metadata +88 -36
  102. data/lib/barometer/services/noaa.rb +0 -6
  103. data/lib/barometer/services/weather_bug.rb +0 -6
  104. data/lib/barometer/services/weather_dot_com.rb +0 -6
  105. data/spec/data_geo_spec.rb +0 -94
  106. data/spec/data_sun_spec.rb +0 -76
  107. data/spec/service_wunderground_spec.rb +0 -330
  108. data/spec/services_spec.rb +0 -1106
@@ -8,28 +8,39 @@ information, or they can be used in a hierarchical configuration where lower
8
8
  preferred weather services are only used if previous services are
9
9
  unavailable.
10
10
 
11
+ Barometer handles all conversions of the supplied query, so that the
12
+ same query can be used for all (or most) services, even if they don't
13
+ support the query directly.
14
+
15
+ For example, Yahoo! only accepts US Zip Code or Weather.com ID. With Barometer
16
+ you can query Yahoo! with a simple location (ie: Paris) and it will return the
17
+ weather.
18
+
11
19
  == version
12
20
 
13
- Version 0.3.2 is the current release of this gem.
21
+ Version 0.5.0 is the current release of this gem.
14
22
  The gem is available from github (attack-barometer) or rubyforge (barometer).
15
- It is fully functional (for three weather service APIs).
23
+ It is fully functional (for four weather service APIs).
16
24
 
17
25
  == status
18
26
 
19
27
  Currently this project is in development and will only work for a few weather
20
- services (wunderground, google, yahoo).
28
+ services (wunderground, google, yahoo, weather.com).
21
29
 
22
30
  Features to be added next:
23
- - even more weather service drivers (noaa, weather.com, weatherbug)
31
+ - even more weather service drivers (noaa, weatherbug)
32
+ - icon support
24
33
 
25
34
  = dependencies
26
35
 
27
- === Google API key
36
+ == Google API key
28
37
 
29
38
  In most cases you will need to have a free google geocode api key.
30
39
  Get one here: http://code.google.com/apis/maps/signup.html
31
- Then put it in the file '~/.barometer' by adding the line:
32
- geocode_google: YOUR_KEY_HERE
40
+ Then put it in the file '~/.barometer' by adding the lines:
41
+
42
+ google:
43
+ geocode: YOUR_KEY_HERE
33
44
 
34
45
  You will need this for:
35
46
  - using the Barometer gem (unless you use queries that are directly supported
@@ -38,7 +49,17 @@ You will need this for:
38
49
  - running the Barometer binary
39
50
  - running the Barometer Web Demo
40
51
 
41
- === HTTParty
52
+ === other keys
53
+
54
+ The same file can hold all your weather service API keys.
55
+
56
+ eg. weather.com
57
+
58
+ weather:
59
+ partner: YOUR_PARTNER_KEY
60
+ license: YOUR_LICENSE_KEY
61
+
62
+ == HTTParty
42
63
 
43
64
  Why? HTTParty was created and designed specifically for consuming web services.
44
65
  I choose to use this over using the Net::HTTP library directly to allow for
@@ -46,34 +67,13 @@ faster development of this project.
46
67
 
47
68
  HTTParty is also extended to include configurable Timeout support.
48
69
 
49
- === tzinfo
70
+ == tzinfo
50
71
 
51
72
  Why? Barometer deals with time information for locations all over the world.
52
73
  This information doesn't mean that much if it can't be converted to times
53
74
  that don't correspond to the applicable timezone.
54
75
  Tzinfo handles this time zone manipulation.
55
76
 
56
- === graticule (very soft dependency)
57
-
58
- Why? Barometer returns the weather for a given location. Most weather service
59
- APIs are somewhat restricted on the query format they receive. To bridge
60
- this gap and allow for maximum flexibility on the 'barometer' query format,
61
- the query will be geo-coded using the Google geocoding service, if required.
62
- Graticule can provide this geocoding interface.
63
-
64
- Using Graticule requires a free Google API key for geocoding. It is possible
65
- to use barometer without geocoding, though your query format will be
66
- limited to that of the weather service API.
67
-
68
- ALTERNATE: If you supply a Google API key but don't install the Graticule gem,
69
- HTTParty will be used instead to provide the same geocoding. Basically
70
- Graticule is only used if it exists.
71
-
72
- NOTE: you can force Barometer not to use Graticule, even if you have it installed
73
- using the following:
74
-
75
- Barometer.skip_graticule = true
76
-
77
77
  = usage
78
78
 
79
79
  You can use barometer right out of the box, as it is configured to use one
@@ -91,13 +91,45 @@ with geo-coding.
91
91
 
92
92
  puts weather.current.temperture
93
93
 
94
- == multiple weather API, with hierarchy
94
+ == sources
95
+
96
+ The available sources are:
97
+
98
+ Wunderground.com (:wunderground) [default]
99
+ Yahoo! Weather (:yahoo)
100
+ Google Weather (:google)
101
+ Weather.com (:weather_dot_com)
102
+
103
+ == source configuration
104
+
105
+ Barometer can be configured to use multiple weather service APIs (either in
106
+ a primary/failover config or in parallel). Each weather service can also
107
+ have its own config.
108
+
109
+ Weather services in parallel
110
+
111
+ Barometer.config = { 1 => [:yahoo, :google] }
112
+
113
+ Weather services in primary/failover
114
+
115
+ Barometer.config = { 1 => [:yahoo], 2 => :wunderground }
116
+
117
+ Weather services, one with some configuration. In this case we are setting
118
+ a weight value, this weight is respected when calculating averages.
119
+
120
+ Barometer.config = { 1 => [{:wunderground => {:weight => 2}}, :google] }
121
+
122
+ Weather services, one with keys.
123
+
124
+ Barometer.config = { 1 => [:yahoo, {:weather_dot_com => {:keys => {:partner => PARTNER_KEY, :license => LICENSE_KEY } }}] }
125
+
126
+ === multiple weather API, with hierarchy
95
127
 
96
128
  require 'barometer'
97
129
 
98
130
  Barometer.google_geocode_key = "THE_GOOGLE_API_KEY"
99
131
  # use yahoo and google, if they both fail, use wunderground
100
- Barometer.selection = { 1 => [:yahoo, :google], 2 => :wunderground }
132
+ Barometer.config = { 1 => [:yahoo, :google], 2 => :wunderground }
101
133
 
102
134
  barometer = Barometer.new("Paris")
103
135
  weather = barometer.measure
@@ -139,37 +171,6 @@ weather results for USA (at least at the time of writing). Therefore,
139
171
  Barometer would not use Yahoo, just Google and failover to use Wunderground
140
172
  (if needed).
141
173
 
142
- === bootstrapping
143
-
144
- You can use weather service drivers directly. Below is an example to use
145
- Wunderground, but since the driver interface is abstracted it will be the
146
- same for all supported services.
147
-
148
- require 'barometer'
149
- Barometer.google_geocode_key = "THE_GOOGLE_API_KEY"
150
-
151
- query = Barometer::Query.new("Paris")
152
- weather = Barometer::Service.source(:wunderground).measure(query)
153
-
154
- puts weather.current.temperture
155
-
156
- # OR, even more raw
157
-
158
- measurement = Barometer::Measurement.new
159
- weather = Barometer::Wunderground.measure_all(measurement, "Paris")
160
-
161
- puts weather.current.temperture
162
-
163
-
164
- NOTE: The disadvantage to using the drivers directly is that you lose the
165
- advantage of redundancy/failover added by the Module as a whole.
166
-
167
- NOTE: You still must create the Barometer::Query object with your query
168
- string instead of directly feeding the query string to the service (as in
169
- bootstrap example #1). The Barometer::Query object has behavior required
170
- by the service that a regular String doesn't have. Using a driver directly
171
- WILL accept a String (as in bootstrap example #2).
172
-
173
174
  == searching
174
175
 
175
176
  After you have measured the data, Barometer provides several methods to help
@@ -225,7 +226,7 @@ values).
225
226
 
226
227
  Barometer.google_geocode_key = "THE_GOOGLE_API_KEY"
227
228
  # use yahoo and wunderground
228
- Barometer.selection = { 1 => [:yahoo, :wunderground] }
229
+ Barometer.config = { 1 => [:yahoo, :wunderground] }
229
230
 
230
231
  barometer = Barometer.new("90210")
231
232
  weather = barometer.measure
@@ -233,6 +234,12 @@ values).
233
234
  puts weather.temperture
234
235
 
235
236
  This will calculate the average temperature as given by :yahoo and :wunderground
237
+
238
+ === weights
239
+
240
+ You can weight the values from a weather service so that the values from that
241
+ web service have more influence then other values. The weights are set in the
242
+ config ... see the config section
236
243
 
237
244
  == simple answers
238
245
 
@@ -289,14 +296,15 @@ there will be no answer.
289
296
  - create a Barometer instance
290
297
  - supply a query, there are very little restrictions on the format:
291
298
  - city, country, specific address (basically anything Google will geocode)
292
- - US zip code (skips geocoding if weather service accepts this directly)
293
- - postal code (skips geocoding if weather service accepts this directly)
294
- - latitude and longitude (skips geocoding if weather service accepts this
299
+ - US zip code (skips conversion if weather service accepts this directly)
300
+ - postal code (skips conversion if weather service accepts this directly)
301
+ - latitude and longitude (skips conversion if weather service accepts this
295
302
  directly)
296
- - TODO: international airport code (skips geocoding if weather service
303
+ - weather.com weather id (even if the service you are using doesn't use it)
304
+ - international airport code (skips conversion if weather service
297
305
  accepts this directly)
298
- - if geocoding required, geocode the query
299
- - determine which weather services will be queried (one or multiple)
306
+ - determine which weather services will be queried (one or multiple)
307
+ - if query conversion required for specific weather service, convert the query
300
308
  - query the weather services
301
309
  - save the data
302
310
  - repeat weather service queries as needed
@@ -1,4 +1,4 @@
1
1
  ---
2
- :patch: 2
2
+ :patch: 0
3
3
  :major: 0
4
- :minor: 3
4
+ :minor: 5
@@ -31,9 +31,10 @@
31
31
  # -g, --geocode Force Geocoding of query
32
32
  # -m, --metric measure in metric
33
33
  # -i, --imperial measure in imperial
34
- # --no-wunderground DONT use default wunderground as source
35
- # --yahoo use yahoo as source
36
- # --google use google as source
34
+ # --wunderground add wunderground as a source
35
+ # --yahoo add yahoo as a source
36
+ # --google add google as a source
37
+ # --weather add weather.com as a source
37
38
  # -p, --pop pop threshold used to determine wet?
38
39
  # -s, --wind wind speed threshold used to determine windy?
39
40
  # -a, --at time/date used to determine when to calculate summary
@@ -63,9 +64,9 @@ require 'yaml'
63
64
 
64
65
  # file where API keys are stored
65
66
  KEY_FILE = File.expand_path(File.join('~', '.barometer'))
67
+ BAROMETER_VERSION = '0.5.0'
66
68
 
67
69
  class App
68
- VERSION = '0.3.2'
69
70
 
70
71
  attr_reader :options
71
72
 
@@ -76,12 +77,12 @@ class App
76
77
  @options = OpenStruct.new
77
78
  @options.timeout = 15
78
79
  @options.geocode = false
79
- @options.skip_graticule = false
80
80
  @options.metric = true
81
- @options.sources = [:wunderground]
81
+ @options.sources = []
82
82
  @options.verbode = false
83
83
  @options.web = false
84
- @options.at = Time.now.utc
84
+ @options.at = nil
85
+ @options.default = true
85
86
 
86
87
  # thresholds
87
88
  @options.windy_m = 10
@@ -118,18 +119,18 @@ class App
118
119
  opt.on('-V', '--verbose') { @options.verbose = true }
119
120
  opt.on('-a n', '--at n') {|n| @options.at = Time.parse(n.to_s) }
120
121
  opt.on('-t n', '--timeout n') {|n| @options.timeout = n }
121
- opt.on('-w', '--web') { @options.web = true; ARGV.shift }
122
122
  opt.on('-g', '--geocode') { @options.geocode = true }
123
- opt.on('--skip') { @options.skip_graticule = true }
124
123
  opt.on('-m', '--metric') { @options.metric = true }
125
124
  opt.on('-i', '--imperial') { @options.metric = false }
126
- opt.on('--no-wunderground') { @options.sources = @options.sources.delete_if{|s| s == :wunderground} }
127
- opt.on('--yahoo') { @options.sources << :yahoo }
128
- opt.on('--google') { @options.sources << :google }
125
+ opt.on('--wunderground') { @options.sources << :wunderground; @options.default = false }
126
+ opt.on('--yahoo') { @options.sources << :yahoo; @options.default = false }
127
+ opt.on('--google') { @options.sources << :google; @options.default = false }
128
+ opt.on('--weather') { @options.sources << :weather_dot_com; @options.default = false }
129
129
  opt.on('-p n', '--pop n') {|n| @options.pop = n.to_i || 50 }
130
130
  opt.on('-s n', '--wind n') {|n| @options.metric ? @options.windy_m = n.to_f || 10 : @options.windy_i = n.to_f || 7 }
131
131
 
132
132
  # pass these onto vegas
133
+ opt.on('-w', '--web') { @options.web = true; ARGV.shift }
133
134
  opt.on('-k', '--kill') { @options.web = true }
134
135
  opt.on('-S', '--status') { @options.web = true }
135
136
 
@@ -138,12 +139,35 @@ class App
138
139
  process_options
139
140
  true
140
141
  end
142
+
143
+ def config_weather_dot_com
144
+ if File.exists?(KEY_FILE)
145
+ keys = YAML.load_file(KEY_FILE)
146
+ if keys["weather"] && keys["weather"]["partner"] && keys["weather"]["license"]
147
+ partner_key = keys["weather"]["partner"].to_s
148
+ license_key = keys["weather"]["license"].to_s
149
+ else
150
+ weather_key_message
151
+ exit
152
+ end
153
+ else
154
+ File.open(KEY_FILE, 'w') {|f| f << "\nweather:\n partner: PARTNER_KEY\n license: LICENSE_KEY" }
155
+ weather_key_message
156
+ exit
157
+ end
158
+ { :weather_dot_com => { :keys => { :partner => partner_key, :license => license_key } } }
159
+ end
141
160
 
142
161
  # Performs post-parse processing on options
143
162
  def process_options
163
+ @options.sources << :wunderground if @options.default
164
+ @options.sources = @options.sources.uniq
144
165
  Barometer.force_geocode = @options.geocode
145
- Barometer.selection = { 1 => @options.sources.uniq }
146
- Barometer.skip_graticule = @options.skip_graticule
166
+ if @options.sources.include?(:weather_dot_com)
167
+ @options.sources.delete(:weather_dot_com)
168
+ @options.sources << config_weather_dot_com
169
+ end
170
+ Barometer.config = { 1 => @options.sources }
147
171
  Barometer.timeout = @options.timeout
148
172
  end
149
173
 
@@ -184,9 +208,10 @@ class App
184
208
  puts " -g, --geocode Force Geocoding of query"
185
209
  puts " -m, --metric measure in metric"
186
210
  puts " -i, --imperial measure in imperial"
187
- puts " --no-wunderground DONT use default wunderground as source"
188
- puts " --yahoo use yahoo as source"
189
- puts " --google use google as source"
211
+ puts " --wunderground add wunderground as a source"
212
+ puts " --yahoo add yahoo as a source"
213
+ puts " --google add google as a source"
214
+ puts " --weather add weather.com as a source"
190
215
  puts " -p, --pop pop threshold used to determine wet?"
191
216
  puts " -s, --wind wind speed threshold used to determine windy?"
192
217
  puts " -a, --at time/date used to determine when to calculate summary"
@@ -198,7 +223,7 @@ class App
198
223
  end
199
224
 
200
225
  def output_version
201
- puts "#{File.basename(__FILE__)} version #{VERSION}"
226
+ puts "#{File.basename(__FILE__)} version #{BAROMETER_VERSION}"
202
227
  end
203
228
 
204
229
  def process_command
@@ -274,13 +299,19 @@ end
274
299
 
275
300
  def pretty_query(q)
276
301
  return unless q
277
- section("QUERY", 2) do
278
- pretty_hash({"Format" => q.format})
302
+ section("ORIGINAL QUERY", 1) do
279
303
  pretty_hash({
280
- "Address" => q.geo.address,
281
- "Locality" => q.geo.locality, "Region" => q.geo.region,
282
- "Country" => q.geo.country, "Country Code" => q.geo.country_code,
283
- "Latitude" => q.geo.latitude, "Longitude" => q.geo.longitude }) if q.geo
304
+ "Query" => q.q, "Format" => q.format,
305
+ "Country Code" => q.country_code })
306
+ end
307
+ if q.geo
308
+ section("GEO", 2) do
309
+ pretty_hash({
310
+ "Address" => q.geo.address, "Query" => q.geo.query,
311
+ "Locality" => q.geo.locality, "Region" => q.geo.region,
312
+ "Country" => q.geo.country, "Country Code" => q.geo.country_code,
313
+ "Latitude" => q.geo.latitude, "Longitude" => q.geo.longitude })
314
+ end
284
315
  end
285
316
  end
286
317
 
@@ -319,13 +350,14 @@ def pretty_current(c)
319
350
  return unless c
320
351
  section("CURRENT", 2) do
321
352
  pretty_hash({
322
- "Time" => c.time, "Local Time" => c.local_time,
353
+ "Measured at" => c.current_at, "Updated at" => c.updated_at,
323
354
  "Humidity" => c.humidity, "Icon" => c.icon,
324
355
  "Condition" => c.condition, "Temperature" => c.temperature,
325
356
  "Dew Point" => c.dew_point, "Heat Index" => c.heat_index,
326
- "Pressure" => c.pressure, "Visibility" => c.visibility })
327
- pretty_hash({ "Wind Chill" => c.wind_chill, "Wind" => c.wind,
328
- "Wind Direction" => c.wind.direction, "Degrees" => c.wind.degrees }) if c.wind
357
+ "Pressure" => c.pressure, "Visibility" => c.visibility,
358
+ "Wind Chill" => c.wind_chill })
359
+ pretty_hash({ "Wind" => c.wind, "Wind Direction" => c.wind.direction,
360
+ "Wind Degrees" => c.wind.degrees }) if c.wind
329
361
  pretty_hash({ "Sun Rise" => c.sun.rise, "Sun Set" => c.sun.set }) if c.sun
330
362
  end
331
363
  end
@@ -336,14 +368,26 @@ def pretty_forecast(f)
336
368
  pretty_hash({
337
369
  "Date" => f.date, "Icon" => f.icon,
338
370
  "Condition" => f.condition, "High" => f.high,
339
- "Low" => f.low, "POP" => f.pop })
371
+ "Low" => f.low, "POP" => f.pop, "Humidity" => f.humidity })
372
+ pretty_hash({ "Wind" => f.wind, "Wind Direction" => f.wind.direction,
373
+ "Wind Degrees" => f.wind.degrees }) if f.wind
340
374
  pretty_hash({ "Sun Rise" => f.sun.rise, "Sun Set" => f.sun.set }) if f.sun
375
+ if f.night
376
+ puts
377
+ title("NIGHT", 4)
378
+ pretty_hash({
379
+ "Date" => f.night.date, "Icon" => f.night.icon,
380
+ "Condition" => f.night.condition, "POP" => f.night.pop,
381
+ "Humidity" => f.night.humidity })
382
+ pretty_hash({ "Wind" => f.night.wind, "Wind Direction" => f.night.wind.direction,
383
+ "Wind Degrees" => f.night.wind.degrees }) if f.night.wind
384
+ end
341
385
  end
342
386
  end
343
387
 
344
388
  def pretty_forecasts(forecasts)
345
389
  return unless forecasts
346
- section("FORECAST", 3, false) do
390
+ section("FORECAST(s)", 3, false) do
347
391
  blank
348
392
  forecasts.each do |forecast|
349
393
  pretty_forecast(forecast)
@@ -355,9 +399,13 @@ def pretty_measurement(m)
355
399
  return unless m
356
400
  section(m.source.to_s, 1) do
357
401
  pretty_hash({
358
- "Source" => m.source, "Time" => m.time,
402
+ "Measured At" => m.measured_at,
403
+ "Source" => m.source, "Time Stamp" => m.utc_time_stamp,
359
404
  "Metric" => m.metric?, "Success" => m.success? })
360
405
  end
406
+ section("MODIFIED QUERY", 2) do
407
+ pretty_hash({ "Query" => m.query, "Format" => m.format })
408
+ end
361
409
  pretty_location(m.location)
362
410
  pretty_station(m.station)
363
411
  pretty_timezone(m.timezone)
@@ -378,7 +426,7 @@ end
378
426
  def pretty_info
379
427
  title("INFO", 1)
380
428
  value("GitHub", "http://github.com/attack/barometer")
381
- value("Barometer Version", VERSION)
429
+ value("Barometer Version", BAROMETER_VERSION)
382
430
  end
383
431
 
384
432
  def pretty_output(barometer)
@@ -400,6 +448,7 @@ end
400
448
 
401
449
  def run_web_mode(query=nil)
402
450
 
451
+ require 'rubygems'
403
452
  require File.expand_path(File.dirname(__FILE__) + '/../lib/demometer/demometer.rb')
404
453
  require 'vegas'
405
454
 
@@ -411,24 +460,38 @@ end
411
460
 
412
461
  def geocode_google_key_message
413
462
  puts
463
+ puts "MISSING KEYS !!!"
414
464
  puts "Please update the key_file '#{KEY_FILE}' with your google api key"
415
465
  puts "Get it here: http://code.google.com/apis/maps/signup.html"
416
- puts "The, add this line to the file:"
417
- puts "geocode_google: YOUR_KEY_KERE"
466
+ puts "Then, add this line to the file:"
467
+ puts "google:"
468
+ puts " geocode: YOUR_KEY_KERE"
469
+ puts
470
+ end
471
+
472
+ def weather_key_message
473
+ puts
474
+ puts "MISSING KEYS !!!"
475
+ puts "Please update the key_file '#{KEY_FILE}' with your weather api keys"
476
+ puts "Get it here: ???"
477
+ puts "Then, add these lines to the file:"
478
+ puts "weather:"
479
+ puts " partner: PARTNER_KEY"
480
+ puts " license: LICENSE_KEY"
418
481
  puts
419
482
  end
420
483
 
421
484
  # set API keys
422
485
  if File.exists?(KEY_FILE)
423
486
  keys = YAML.load_file(KEY_FILE)
424
- if keys["geocode_google"]
425
- Barometer.google_geocode_key = keys["geocode_google"]
487
+ if keys["google"] && keys["google"]["geocode"]
488
+ Barometer.google_geocode_key = keys["google"]["geocode"]
426
489
  else
427
490
  geocode_google_key_message
428
491
  exit
429
492
  end
430
493
  else
431
- File.open(KEY_FILE, 'w') {|f| f << "geocode_google: YOUR_KEY_KERE" }
494
+ File.open(KEY_FILE, 'w') {|f| f << "google: geocode: YOUR_KEY_KERE" }
432
495
  geocode_google_key_message
433
496
  exit
434
497
  end