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
@@ -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
|
-
|
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/demometer/demometer.rb
CHANGED
@@ -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
|
-
/*
|
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
|
+
}
|