barometer 0.5.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/README.rdoc +51 -9
  2. data/VERSION.yml +2 -2
  3. data/bin/barometer +57 -7
  4. data/lib/barometer.rb +11 -0
  5. data/lib/barometer/base.rb +3 -0
  6. data/lib/barometer/data.rb +11 -6
  7. data/lib/barometer/data/sun.rb +10 -0
  8. data/lib/barometer/data/zone.rb +79 -188
  9. data/lib/barometer/formats/coordinates.rb +4 -1
  10. data/lib/barometer/formats/geocode.rb +9 -7
  11. data/lib/barometer/formats/icao.rb +2 -2
  12. data/lib/barometer/formats/weather_id.rb +2 -2
  13. data/lib/barometer/measurements/common.rb +113 -0
  14. data/lib/barometer/{data → measurements}/current.rb +17 -42
  15. data/lib/barometer/measurements/forecast.rb +62 -0
  16. data/lib/barometer/measurements/forecast_array.rb +72 -0
  17. data/lib/barometer/{data → measurements}/measurement.rb +57 -45
  18. data/lib/barometer/measurements/night.rb +27 -0
  19. data/lib/barometer/query.rb +55 -5
  20. data/lib/barometer/services.rb +3 -1
  21. data/lib/barometer/translations/icao_country_codes.yml +274 -1
  22. data/lib/barometer/translations/weather_country_codes.yml +189 -6
  23. data/lib/barometer/translations/zone_codes.yml +360 -0
  24. data/lib/barometer/weather.rb +5 -4
  25. data/lib/barometer/weather_services/google.rb +19 -35
  26. data/lib/barometer/weather_services/service.rb +113 -255
  27. data/lib/barometer/weather_services/weather_bug.rb +291 -2
  28. data/lib/barometer/weather_services/weather_dot_com.rb +45 -54
  29. data/lib/barometer/weather_services/wunderground.rb +83 -89
  30. data/lib/barometer/weather_services/yahoo.rb +44 -91
  31. data/lib/barometer/web_services/geocode.rb +1 -0
  32. data/lib/barometer/web_services/timezone.rb +40 -0
  33. data/lib/barometer/web_services/weather_id.rb +17 -2
  34. data/lib/demometer/demometer.rb +28 -0
  35. data/lib/demometer/public/css/master.css +259 -1
  36. data/lib/demometer/public/css/print.css +94 -0
  37. data/lib/demometer/public/css/syntax.css +64 -0
  38. data/lib/demometer/public/images/link-out.gif +0 -0
  39. data/lib/demometer/views/about.erb +10 -0
  40. data/lib/demometer/views/index.erb +2 -0
  41. data/lib/demometer/views/layout.erb +3 -2
  42. data/lib/demometer/views/measurement.erb +4 -1
  43. data/lib/demometer/views/readme.erb +116 -88
  44. data/spec/data/sun_spec.rb +53 -0
  45. data/spec/data/zone_spec.rb +330 -100
  46. data/spec/fixtures/formats/weather_id/ksfo.xml +1 -0
  47. data/spec/fixtures/services/weather_bug/90210_current.xml +1 -0
  48. data/spec/fixtures/services/weather_bug/90210_forecast.xml +1 -0
  49. data/spec/formats/weather_id_spec.rb +10 -5
  50. data/spec/measurements/common_spec.rb +352 -0
  51. data/spec/{data → measurements}/current_spec.rb +40 -103
  52. data/spec/measurements/forecast_array_spec.rb +165 -0
  53. data/spec/measurements/forecast_spec.rb +135 -0
  54. data/spec/{data → measurements}/measurement_spec.rb +86 -107
  55. data/spec/measurements/night_measurement_spec.rb +49 -0
  56. data/spec/query_spec.rb +12 -2
  57. data/spec/spec_helper.rb +28 -1
  58. data/spec/weather_services/google_spec.rb +27 -117
  59. data/spec/weather_services/services_spec.rb +49 -1024
  60. data/spec/weather_services/weather_bug_spec.rb +274 -0
  61. data/spec/weather_services/weather_dot_com_spec.rb +45 -125
  62. data/spec/weather_services/wunderground_spec.rb +42 -136
  63. data/spec/weather_services/yahoo_spec.rb +26 -116
  64. data/spec/weather_spec.rb +45 -45
  65. metadata +27 -11
  66. data/lib/barometer/data/forecast.rb +0 -84
  67. data/lib/barometer/data/night.rb +0 -69
  68. data/lib/barometer/extensions/graticule.rb +0 -51
  69. data/spec/data/forecast_spec.rb +0 -192
  70. data/spec/data/night_measurement_spec.rb +0 -136
@@ -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
@@ -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
@@ -1 +1,259 @@
1
- /* nothing to see here */
1
+ /*
2
+ Copyright: Blake Mizerany, www.sinatrarb.com
3
+ Permission Pending
4
+ */
5
+
6
+ body {
7
+ color:#000;
8
+ font-family:'lucida grande', 'lucida sans unicade', sans-serif;
9
+ font-size:100%;
10
+ line-height:1.3;
11
+ background-color:#fff;
12
+ margin:0;
13
+ padding:0;
14
+ }
15
+
16
+ /* HEADER */
17
+ #head {
18
+ text-align:center;
19
+ }
20
+ #head img {
21
+ vertical-align:middle;
22
+ margin:-10px 0 0 -82px;
23
+ padding:0 15px 0 0;
24
+ border:0;
25
+ }
26
+ #head h1 {
27
+ color:#000;
28
+ font-family:'georgia', 'bitstream vera serif', serif;
29
+ font-size:4em;
30
+ font-weight:normal;
31
+ letter-spacing:-3px;
32
+ line-height:1;
33
+ margin:0;
34
+ padding:20px 0 8px 0;
35
+ }
36
+ #head h1 a, #head h1 a:link, #head h1 a:visited, #head h1 a:hover {
37
+ color:#100;
38
+ text-decoration:none;
39
+ }
40
+ #head ul {
41
+ font-size:1.1em;
42
+ font-family:"lucida console", "monaco", "andale mono", "bitstream vera sans mono",
43
+ "consolas", monospace;
44
+ font-weight:normal;
45
+ text-transform:uppercase;
46
+ letter-spacing:2px;
47
+ text-align:center;
48
+ margin:0;
49
+ padding:0 40px 0.25em 40px;
50
+ }
51
+ #head ul li {
52
+ display:inline;
53
+ list-style-type:none;
54
+ padding:0 0.5em 0 0;
55
+ }
56
+ #head ul a, #head ul a:link, #head ul a:visited {
57
+ color:#56534f;
58
+ text-decoration:none;
59
+ }
60
+ #head ul a:hover {
61
+ color:#000;
62
+ text-decoration:underline
63
+ }
64
+
65
+ /* CONTENT */
66
+
67
+ #content {
68
+ color:#333;
69
+ font-size:1.1em;
70
+ max-width:44em;
71
+ min-width:27em;
72
+ margin:7px auto;
73
+ border-top:2px solid #837d7c;
74
+ }
75
+ strong {
76
+ font-weight:bold;
77
+ }
78
+
79
+ /* HEADINGS */
80
+
81
+ h1, h2, h3, h4, h5, h6 {
82
+ color:#000;
83
+ }
84
+ h1, h2 {
85
+ color:#211d1f;
86
+ font-family:'georgia', 'bitstream vera serif', serif;
87
+ font-weight:normal;
88
+ }
89
+ h1 a, h2 a { color:#222 }
90
+ h1 {
91
+ font-size:2.25em;
92
+ letter-spacing:-1px;
93
+ margin-bottom:0;
94
+ }
95
+ h2 {
96
+ font-size:1.5em;
97
+ letter-spacing:-1px;
98
+ margin:1.25em 0 -0.32em 0;
99
+ }
100
+ h3 {
101
+ color:#211d1f;
102
+ font-size:1.02em;
103
+ font-weight:bold;
104
+ margin:1.8em 0 -0.25em 0;
105
+ letter-spacing:-1px;
106
+ }
107
+ h3 a {
108
+ color:#000;
109
+ text-decoration:underline;
110
+ }
111
+
112
+ /* LINKS */
113
+ a {
114
+ color:#000;
115
+ text-decoration:underline;
116
+ }
117
+ a:hover {
118
+ color:#910;
119
+ text-decoration:underline;
120
+ }
121
+ a img {
122
+ border:none;
123
+ }
124
+ a.out {
125
+ background: url('/images/link-out.gif') center right no-repeat;
126
+ padding-right: 12px;
127
+ }
128
+
129
+
130
+ /* CODE */
131
+
132
+ code, pre, textarea, tt {
133
+ font-family:"lucida console", "monaco", "andale mono", "bitstream vera sans mono",
134
+ "consolas", monospace;
135
+ }
136
+ pre {
137
+ font-size:0.85em;
138
+ background:#f4f5f5;
139
+ border:2px solid #d5d0d2;
140
+ padding:0.5em;
141
+ line-height:1.15;
142
+ color:#222;
143
+ }
144
+ code, tt {
145
+ font-size:0.85em;
146
+ color:#444;
147
+ }
148
+ h1 code, h2 code, h3 code, h4 code {
149
+ color:#333;
150
+ }
151
+ pre code {
152
+ font-size:1em;
153
+ color:#222;
154
+ }
155
+
156
+ /* MISC */
157
+
158
+ hr {
159
+ margin:3em 0;
160
+ padding:0;
161
+ color:#eee;
162
+ }
163
+
164
+ /* HOME */
165
+
166
+ body#home {
167
+ background: #fff url(../images/legend.gif) no-repeat fixed right 130px;
168
+ }
169
+ #home #content {
170
+ font-size:1.05em;
171
+ margin:20px 0 0 0;
172
+ padding:0 20px;
173
+ border-width:0;
174
+ }
175
+ #home #head, #home #foot {
176
+ display:none;
177
+ }
178
+ .pipe {
179
+ clear:both;
180
+ padding:50px 0;
181
+ }
182
+ .pipe p {
183
+ color:#000;
184
+ font-size:62px;
185
+ font-family:'georgia', 'bitstream vera serif', serif;
186
+ letter-spacing:-3px;
187
+ line-height:1;
188
+ text-align:right;
189
+ margin:0em 43% 0 0;
190
+ padding:0 60px 0 0;
191
+ }
192
+ .pipe pre {
193
+ float:right;
194
+ background:transparent;
195
+ font-size:28px;
196
+ margin:0;
197
+ padding:5px 0 0 0;
198
+ width:42%;
199
+ border-width:0;
200
+ }
201
+ .pipe pre code {
202
+ color:#666;
203
+ background:transparent;
204
+ }
205
+ .pipe.shell p {
206
+ font-size:56px;
207
+ }
208
+ .pipe.shell pre {
209
+ font-size:18px;
210
+ }
211
+ .pipe.nav p {
212
+ font-size:100px;
213
+ letter-spacing:-6px;
214
+ }
215
+ .pipe.nav pre {
216
+ font-size:36px;
217
+ padding-top:20px;
218
+ text-transform:uppercase;
219
+ letter-spacing:4px;
220
+ line-height:1.25;
221
+ }
222
+ .pipe.nav {
223
+ padding:25px 0 50px 0;
224
+ }
225
+ .pipe.nav a, .pipe.nav a:link, .pipe.nav a:visited {
226
+ color:#444;
227
+ text-decoration:none;
228
+ }
229
+ .pipe.nav a:hover {
230
+ color:#000;
231
+ text-decoration:underline;
232
+ }
233
+
234
+ form {
235
+ text-align: center;
236
+ }
237
+
238
+ form .text-input input {
239
+ font-family: "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Helvetica, Arial, sans-serif;
240
+ margin: 10px 0 5px 10px;
241
+ color: #686868;
242
+ font-size: 40px;
243
+ text-align: left;
244
+ text-transform: lowercase;
245
+ }
246
+
247
+ form .submit-input input {
248
+ position: relative;
249
+ margin: 0 7% 0 0;
250
+ float: right;
251
+ }
252
+
253
+ form .options-input {
254
+ position: relative;
255
+ margin: 0 7% 0 0;
256
+ float: left;
257
+ text-align: left;
258
+ }
259
+
@@ -0,0 +1,94 @@
1
+ /*
2
+ Copyright: Blake Mizerany, www.sinatrarb.com
3
+ Permission Pending
4
+ */
5
+ body
6
+ { color: #000;
7
+ background: #fff;
8
+ font-size: 85%;
9
+ font-family: Helvetica, sans-serif;
10
+ line-height: 130%;
11
+ margin: 0.5cm; }
12
+
13
+ a
14
+ { color: #000;
15
+ text-decoration: underline; }
16
+
17
+ a img
18
+ { border: none; }
19
+
20
+ /* HEADER */
21
+ #head {
22
+ text-align: center;
23
+ }
24
+ #head img {
25
+ vertical-align:middle;
26
+ margin:-10px 0 0 -82px;
27
+ padding:0 15px 0 0;
28
+ border:0;
29
+ }
30
+ #head h1 {
31
+ color: #172533;
32
+ font-family: Georgia, "Times New Roman", 'bitstream vera serif', serif;
33
+ font-size: 500%;
34
+ font-weight: normal;
35
+ letter-spacing: -0.1em;
36
+ line-height: 1;
37
+ margin: 0;
38
+ padding: 20px 0 16px 0;
39
+ }
40
+ #head h1 a, #head h1 a:link, #head h1 a:visited, #head h1 a:hover {
41
+ color: #172533;
42
+ text-decoration: none;
43
+ }
44
+ #head ul {
45
+ font-size:1.1em;
46
+ font-family: 'Lucida Grande', 'lucida sans unicade', Verdana, sans-serif;
47
+ font-weight: normal;
48
+ text-transform: uppercase;
49
+ text-align: center;
50
+ margin: 0;
51
+ padding: 0 40px 10px 40px;
52
+ }
53
+ #head ul li {
54
+ display: inline;
55
+ list-style-type: none;
56
+ padding: 0 1.5em 0 0;
57
+ }
58
+ #head ul a, #head ul a:link, #head ul a:visited {
59
+ color: #1d2e40;
60
+ text-decoration: none;
61
+ }
62
+ #head ul a:hover {
63
+ color: #0e1c29;
64
+ text-decoration:underline
65
+ }
66
+
67
+
68
+
69
+ h2 {
70
+ font-size: 1.5em;
71
+ letter-spacing: -0.05em;
72
+ padding: 1.15em 0 0 0;
73
+ margin: 1.25em 0 0.25em 0;
74
+ border-top: 1mm solid #999;
75
+ }
76
+
77
+ h3 {
78
+ font-size: 1.1em;
79
+ font-weight:bold;
80
+ margin: 1.8em 0 0.25em 0;
81
+ letter-spacing: -0.05em;
82
+ }
83
+
84
+ h3 a {
85
+ text-decoration:underline;
86
+ }
87
+
88
+
89
+
90
+ pre {
91
+ border: 1pt solid #ccc;
92
+ padding: 0.5em;
93
+ white-space: pre-wrap; white-space: -moz-pre-wrap !important;
94
+ }