barometer 0.6.1 → 0.6.2
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 +1 -1
- data/VERSION.yml +1 -1
- data/bin/barometer +4 -12
- data/lib/barometer/data.rb +2 -5
- data/lib/barometer/data/local_datetime.rb +2 -2
- data/lib/barometer/measurements/measurement.rb +6 -6
- data/lib/barometer/measurements/result.rb +207 -0
- data/lib/barometer/measurements/{forecast_array.rb → result_array.rb} +16 -13
- data/lib/barometer/translations/weather_country_codes.yml +3 -3
- data/lib/barometer/weather_services/google.rb +3 -3
- data/lib/barometer/weather_services/weather_bug.rb +3 -3
- data/lib/barometer/weather_services/weather_dot_com.rb +65 -38
- data/lib/barometer/weather_services/wunderground.rb +3 -3
- data/lib/barometer/weather_services/yahoo.rb +3 -3
- data/lib/demometer/demometer.rb +2 -2
- data/lib/demometer/public/css/master.css +4 -75
- data/lib/demometer/public/css/print.css +1 -2
- data/lib/demometer/public/css/syntax.css +1 -2
- data/lib/demometer/views/about.erb +1 -1
- data/lib/demometer/views/contributing.erb +4 -4
- data/lib/demometer/views/index.erb +8 -9
- data/lib/demometer/views/layout.erb +1 -2
- data/spec/measurements/measurement_spec.rb +29 -53
- data/spec/measurements/{forecast_array_spec.rb → result_array_spec.rb} +8 -8
- data/spec/measurements/result_spec.rb +660 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/weather_services/google_spec.rb +4 -4
- data/spec/weather_services/services_spec.rb +1 -1
- data/spec/weather_services/weather_bug_spec.rb +3 -3
- data/spec/weather_services/weather_dot_com_spec.rb +19 -22
- data/spec/weather_services/wunderground_spec.rb +2 -2
- data/spec/weather_services/yahoo_spec.rb +2 -2
- data/spec/weather_spec.rb +14 -39
- metadata +6 -12
- data/lib/barometer/measurements/common.rb +0 -113
- data/lib/barometer/measurements/current.rb +0 -76
- data/lib/barometer/measurements/forecast.rb +0 -62
- data/lib/barometer/measurements/night.rb +0 -27
- data/spec/measurements/common_spec.rb +0 -352
- data/spec/measurements/current_spec.rb +0 -186
- data/spec/measurements/forecast_spec.rb +0 -135
- data/spec/measurements/night_measurement_spec.rb +0 -49
data/README.rdoc
CHANGED
@@ -15,7 +15,7 @@ this.
|
|
15
15
|
|
16
16
|
== version
|
17
17
|
|
18
|
-
Version 0.6.
|
18
|
+
Version 0.6.2 is the current release of this gem.
|
19
19
|
The gem is available from github (attack-barometer) or rubyforge (barometer).
|
20
20
|
It is fully functional (for five weather service APIs).
|
21
21
|
|
data/VERSION.yml
CHANGED
data/bin/barometer
CHANGED
@@ -66,7 +66,7 @@ require 'yaml'
|
|
66
66
|
|
67
67
|
# file where API keys are stored
|
68
68
|
KEY_FILE = File.expand_path(File.join('~', '.barometer'))
|
69
|
-
BAROMETER_VERSION = '0.6.
|
69
|
+
BAROMETER_VERSION = '0.6.2'
|
70
70
|
|
71
71
|
class App
|
72
72
|
|
@@ -403,22 +403,14 @@ def pretty_forecast(f)
|
|
403
403
|
return unless f
|
404
404
|
section("FOR: #{f.date}", 3) do
|
405
405
|
pretty_hash({
|
406
|
-
"
|
406
|
+
"Valid From" => f.valid_start_date.to_s(true),
|
407
|
+
"Valid Until" => f.valid_end_date.to_s(true),
|
408
|
+
"Icon" => f.icon, "Description" => f.description,
|
407
409
|
"Condition" => f.condition, "High" => f.high,
|
408
410
|
"Low" => f.low, "POP" => f.pop, "Humidity" => f.humidity })
|
409
411
|
pretty_hash({ "Wind" => f.wind, "Wind Direction" => f.wind.direction,
|
410
412
|
"Wind Degrees" => f.wind.degrees }) if f.wind
|
411
413
|
pretty_hash({ "Sun Rise" => f.sun.rise, "Sun Set" => f.sun.set }) if f.sun
|
412
|
-
if f.night
|
413
|
-
puts
|
414
|
-
title("NIGHT", 4)
|
415
|
-
pretty_hash({
|
416
|
-
"Date" => f.night.date, "Icon" => f.night.icon,
|
417
|
-
"Condition" => f.night.condition, "POP" => f.night.pop,
|
418
|
-
"Humidity" => f.night.humidity })
|
419
|
-
pretty_hash({ "Wind" => f.night.wind, "Wind Direction" => f.night.wind.direction,
|
420
|
-
"Wind Degrees" => f.night.wind.degrees }) if f.night.wind
|
421
|
-
end
|
422
414
|
end
|
423
415
|
end
|
424
416
|
|
data/lib/barometer/data.rb
CHANGED
@@ -17,8 +17,5 @@ require 'data/local_datetime'
|
|
17
17
|
# measurements
|
18
18
|
#
|
19
19
|
require 'measurements/measurement'
|
20
|
-
require 'measurements/
|
21
|
-
require 'measurements/
|
22
|
-
require 'measurements/forecast_array'
|
23
|
-
require 'measurements/forecast'
|
24
|
-
require 'measurements/night'
|
20
|
+
require 'measurements/result'
|
21
|
+
require 'measurements/result_array'
|
@@ -101,8 +101,8 @@ module Barometer
|
|
101
101
|
end
|
102
102
|
raise ArgumentError unless the_other.is_a?(Data::LocalDateTime) || the_other.is_a?(Data::LocalTime)
|
103
103
|
|
104
|
-
if (other.is_a?(String) || other.is_a?(Time) || other.is_a?(DateTime)) &&
|
105
|
-
the_other.is_a?(Data::LocalDateTime)
|
104
|
+
if ((other.is_a?(String) || other.is_a?(Time) || other.is_a?(DateTime)) &&
|
105
|
+
the_other.is_a?(Data::LocalDateTime)) || other.is_a?(Data::LocalDateTime)
|
106
106
|
# we are counting days + seconds
|
107
107
|
if (_total_days <=> the_other._total_days) == 0
|
108
108
|
return total_seconds <=> the_other.total_seconds
|
@@ -3,8 +3,8 @@ module Barometer
|
|
3
3
|
# Measurement
|
4
4
|
# a class that holds the response from a weather service
|
5
5
|
#
|
6
|
-
# its main purpose is to hold all the data collected from a weather
|
7
|
-
# as it is passed to the weather object
|
6
|
+
# its main purpose is to hold all the data collected from a single weather
|
7
|
+
# service as it is passed to the weather object
|
8
8
|
#
|
9
9
|
# this response includes
|
10
10
|
# - current weather data (using the CurrentMeasurement class)
|
@@ -31,8 +31,8 @@ module Barometer
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def success!
|
34
|
-
|
35
|
-
|
34
|
+
current && current.temperature &&
|
35
|
+
!current.temperature.c.nil? && @success = true
|
36
36
|
end
|
37
37
|
|
38
38
|
def stamp!; @utc_time_stamp = Time.now.utc; end
|
@@ -95,14 +95,14 @@ module Barometer
|
|
95
95
|
end
|
96
96
|
|
97
97
|
def current=(current)
|
98
|
-
raise ArgumentError unless current.is_a?(Measurement::
|
98
|
+
raise ArgumentError unless current.is_a?(Measurement::Result)
|
99
99
|
@current = current
|
100
100
|
self.stamp!
|
101
101
|
self.success!
|
102
102
|
end
|
103
103
|
|
104
104
|
def forecast=(forecast)
|
105
|
-
raise ArgumentError unless forecast.is_a?(Measurement::
|
105
|
+
raise ArgumentError unless forecast.is_a?(Measurement::ResultArray)
|
106
106
|
@forecast = forecast
|
107
107
|
end
|
108
108
|
|
@@ -0,0 +1,207 @@
|
|
1
|
+
module Barometer
|
2
|
+
#
|
3
|
+
# Result Measurement
|
4
|
+
# a data class for resulting weather conditions
|
5
|
+
#
|
6
|
+
# This is basically a data holding class for the resulting weather
|
7
|
+
# conditions.
|
8
|
+
#
|
9
|
+
class Measurement::Result
|
10
|
+
|
11
|
+
attr_reader :current_at, :updated_at
|
12
|
+
attr_reader :valid_start_date, :valid_end_date, :date
|
13
|
+
attr_reader :humidity, :icon, :condition
|
14
|
+
attr_reader :temperature, :dew_point, :heat_index, :wind_chill
|
15
|
+
attr_reader :low, :high, :pop
|
16
|
+
attr_reader :wind, :sun, :pressure, :visibility
|
17
|
+
attr_accessor :metric, :description
|
18
|
+
|
19
|
+
def initialize(metric=true); @metric = metric; end
|
20
|
+
|
21
|
+
# accessors (with input checking)
|
22
|
+
#
|
23
|
+
def temperature=(temperature)
|
24
|
+
raise ArgumentError unless temperature.is_a?(Data::Temperature)
|
25
|
+
@temperature = temperature
|
26
|
+
end
|
27
|
+
|
28
|
+
def dew_point=(dew_point)
|
29
|
+
raise ArgumentError unless dew_point.is_a?(Data::Temperature)
|
30
|
+
@dew_point = dew_point
|
31
|
+
end
|
32
|
+
|
33
|
+
def heat_index=(heat_index)
|
34
|
+
raise ArgumentError unless heat_index.is_a?(Data::Temperature)
|
35
|
+
@heat_index = heat_index
|
36
|
+
end
|
37
|
+
|
38
|
+
def wind_chill=(wind_chill)
|
39
|
+
raise ArgumentError unless wind_chill.is_a?(Data::Temperature)
|
40
|
+
@wind_chill = wind_chill
|
41
|
+
end
|
42
|
+
|
43
|
+
def pressure=(pressure)
|
44
|
+
raise ArgumentError unless pressure.is_a?(Data::Pressure)
|
45
|
+
@pressure = pressure
|
46
|
+
end
|
47
|
+
|
48
|
+
def visibility=(visibility)
|
49
|
+
raise ArgumentError unless visibility.is_a?(Data::Distance)
|
50
|
+
@visibility = visibility
|
51
|
+
end
|
52
|
+
|
53
|
+
def current_at=(current_at)
|
54
|
+
raise ArgumentError unless (current_at.is_a?(Data::LocalTime) || current_at.is_a?(Data::LocalDateTime))
|
55
|
+
@current_at = current_at
|
56
|
+
end
|
57
|
+
|
58
|
+
def updated_at=(updated_at)
|
59
|
+
raise ArgumentError unless (updated_at.is_a?(Data::LocalTime) || updated_at.is_a?(Data::LocalDateTime))
|
60
|
+
@updated_at = updated_at
|
61
|
+
end
|
62
|
+
|
63
|
+
def date=(date)
|
64
|
+
raise ArgumentError unless date.is_a?(Date)
|
65
|
+
@date = date
|
66
|
+
@valid_start_date = Data::LocalDateTime.new(date.year,date.month,date.day,0,0,0)
|
67
|
+
@valid_end_date = Data::LocalDateTime.new(date.year,date.month,date.day,23,59,59)
|
68
|
+
end
|
69
|
+
|
70
|
+
def valid_start_date=(date)
|
71
|
+
raise ArgumentError unless date.is_a?(Data::LocalDateTime)
|
72
|
+
@valid_start_date = date
|
73
|
+
end
|
74
|
+
|
75
|
+
def valid_end_date=(date)
|
76
|
+
raise ArgumentError unless date.is_a?(Data::LocalDateTime)
|
77
|
+
@valid_end_date = date
|
78
|
+
end
|
79
|
+
|
80
|
+
def high=(high)
|
81
|
+
raise ArgumentError unless high.is_a?(Data::Temperature)
|
82
|
+
@high = high
|
83
|
+
end
|
84
|
+
|
85
|
+
def low=(low)
|
86
|
+
raise ArgumentError unless low.is_a?(Data::Temperature)
|
87
|
+
@low = low
|
88
|
+
end
|
89
|
+
|
90
|
+
def pop=(pop)
|
91
|
+
raise ArgumentError unless pop.is_a?(Fixnum)
|
92
|
+
@pop = pop
|
93
|
+
end
|
94
|
+
|
95
|
+
def humidity=(humidity)
|
96
|
+
raise ArgumentError unless
|
97
|
+
(humidity.is_a?(Fixnum) || humidity.is_a?(Float))
|
98
|
+
@humidity = humidity
|
99
|
+
end
|
100
|
+
|
101
|
+
def icon=(icon)
|
102
|
+
raise ArgumentError unless icon.is_a?(String)
|
103
|
+
@icon = icon
|
104
|
+
end
|
105
|
+
|
106
|
+
def condition=(condition)
|
107
|
+
raise ArgumentError unless condition.is_a?(String)
|
108
|
+
@condition = condition
|
109
|
+
end
|
110
|
+
|
111
|
+
def wind=(wind)
|
112
|
+
raise ArgumentError unless wind.is_a?(Data::Speed)
|
113
|
+
@wind = wind
|
114
|
+
end
|
115
|
+
|
116
|
+
def sun=(sun)
|
117
|
+
raise ArgumentError unless (sun.is_a?(Data::Sun) || sun.nil?)
|
118
|
+
@sun = sun
|
119
|
+
end
|
120
|
+
|
121
|
+
#
|
122
|
+
# answer simple questions
|
123
|
+
#
|
124
|
+
|
125
|
+
def windy?(threshold=10)
|
126
|
+
raise ArgumentError unless (threshold.is_a?(Fixnum) || threshold.is_a?(Float))
|
127
|
+
return nil unless wind?
|
128
|
+
wind.to_f(metric?) >= threshold.to_f
|
129
|
+
end
|
130
|
+
|
131
|
+
def day?(time)
|
132
|
+
return nil unless time && sun?
|
133
|
+
sun.after_rise?(time) && sun.before_set?(time)
|
134
|
+
end
|
135
|
+
|
136
|
+
def sunny?(time, sunny_icons=nil)
|
137
|
+
return nil unless time
|
138
|
+
is_day = day?(time)
|
139
|
+
return nil if is_day.nil?
|
140
|
+
is_day && _sunny_by_icon?(sunny_icons)
|
141
|
+
end
|
142
|
+
|
143
|
+
def wet?(wet_icons=nil, pop_threshold=50, humidity_threshold=99)
|
144
|
+
result = nil
|
145
|
+
result ||= _wet_by_pop?(pop_threshold) if pop?
|
146
|
+
result ||= _wet_by_icon?(wet_icons) if icon?
|
147
|
+
result ||= _wet_by_humidity?(humidity_threshold) if humidity?
|
148
|
+
result ||= _wet_by_dewpoint? if (dew_point? && temperature?)
|
149
|
+
result
|
150
|
+
end
|
151
|
+
|
152
|
+
#
|
153
|
+
# helpers
|
154
|
+
#
|
155
|
+
|
156
|
+
def metric?; metric; end
|
157
|
+
|
158
|
+
def for_datetime?(datetime)
|
159
|
+
raise ArgumentError unless datetime.is_a?(Data::LocalDateTime)
|
160
|
+
datetime >= @valid_start_date && datetime <= @valid_end_date
|
161
|
+
end
|
162
|
+
|
163
|
+
# creates "?" helpers for all attributes (which maps to nil?)
|
164
|
+
#
|
165
|
+
def method_missing(method,*args)
|
166
|
+
# if the method ends in ?, then strip it off and see if we
|
167
|
+
# respond to the method without the ?
|
168
|
+
if (call_method = method.to_s.chomp!("?")) && respond_to?(call_method)
|
169
|
+
return send(call_method).nil? ? false : true
|
170
|
+
else
|
171
|
+
super(method,*args)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
private
|
176
|
+
|
177
|
+
def _wet_by_dewpoint?
|
178
|
+
return nil unless dew_point? && temperature?
|
179
|
+
temperature.to_f(metric?) <= dew_point.to_f(metric?)
|
180
|
+
end
|
181
|
+
|
182
|
+
def _wet_by_pop?(threshold=50)
|
183
|
+
raise ArgumentError unless (threshold.is_a?(Fixnum) || threshold.is_a?(Float))
|
184
|
+
return nil unless pop?
|
185
|
+
pop.to_f >= threshold.to_f
|
186
|
+
end
|
187
|
+
|
188
|
+
def _wet_by_humidity?(threshold=99)
|
189
|
+
raise ArgumentError unless (threshold.is_a?(Fixnum) || threshold.is_a?(Float))
|
190
|
+
return nil unless humidity?
|
191
|
+
humidity.to_f >= threshold.to_f
|
192
|
+
end
|
193
|
+
|
194
|
+
def _wet_by_icon?(wet_icons=nil)
|
195
|
+
raise ArgumentError unless (wet_icons.nil? || wet_icons.is_a?(Array))
|
196
|
+
return nil unless (icon? && wet_icons)
|
197
|
+
wet_icons.include?(icon.to_s.downcase)
|
198
|
+
end
|
199
|
+
|
200
|
+
def _sunny_by_icon?(sunny_icons=nil)
|
201
|
+
raise ArgumentError unless (sunny_icons.nil? || sunny_icons.is_a?(Array))
|
202
|
+
return nil unless (icon? && sunny_icons)
|
203
|
+
sunny_icons.include?(icon.to_s.downcase)
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
end
|
@@ -1,13 +1,15 @@
|
|
1
1
|
require 'date'
|
2
2
|
module Barometer
|
3
3
|
#
|
4
|
-
#
|
5
|
-
# an array that holds multiple forecasts
|
4
|
+
# Result Array
|
6
5
|
#
|
7
|
-
|
6
|
+
# an array that holds multiple results,
|
7
|
+
# with methods for insertion and searching
|
8
|
+
#
|
9
|
+
class Measurement::ResultArray < Array
|
8
10
|
|
9
11
|
def <<(forecast)
|
10
|
-
raise ArgumentError unless forecast.is_a?(Measurement::
|
12
|
+
raise ArgumentError unless forecast.is_a?(Measurement::Result)
|
11
13
|
super(forecast)
|
12
14
|
end
|
13
15
|
|
@@ -17,31 +19,32 @@ module Barometer
|
|
17
19
|
|
18
20
|
#
|
19
21
|
# Returns a forecast for a day given by a Date, DateTime,
|
20
|
-
# Time, or a string that can be parsed to a
|
22
|
+
# Time, or a string that can be parsed to a Data::LocalDateTime
|
21
23
|
#
|
22
24
|
# credit: http://github.com/jdpace/weatherman/
|
23
25
|
#
|
24
|
-
def for(
|
26
|
+
def for(datetime)
|
25
27
|
|
26
28
|
return nil unless self.size > 0
|
27
29
|
|
28
30
|
# Format date into a Date class
|
29
|
-
|
31
|
+
datetime = case datetime.class.name
|
30
32
|
when 'Date'
|
31
|
-
date
|
33
|
+
# if just given a date, assume a time that will be mid-day
|
34
|
+
Data::LocalDateTime.new(datetime.year,datetime.month,datetime.day,12,0,0)
|
32
35
|
when 'Data::LocalDateTime'
|
33
|
-
|
36
|
+
datetime
|
34
37
|
when 'String'
|
35
|
-
|
38
|
+
Data::LocalDateTime.parse(datetime)
|
36
39
|
when 'Time'
|
37
|
-
|
40
|
+
Data::LocalDateTime.parse(datetime)
|
38
41
|
when 'DateTime'
|
39
|
-
|
42
|
+
Data::LocalDateTime.parse(datetime)
|
40
43
|
end
|
41
44
|
|
42
45
|
day = nil
|
43
46
|
self.each do |f|
|
44
|
-
day = f if
|
47
|
+
day = f if f.for_datetime?(datetime)
|
45
48
|
end
|
46
49
|
return day
|
47
50
|
end
|
@@ -102,7 +102,7 @@ MG : MN
|
|
102
102
|
|
103
103
|
WA : NA
|
104
104
|
NT : AN
|
105
|
-
NU: NI
|
105
|
+
NU : NI
|
106
106
|
NG : NE
|
107
107
|
NI : NG
|
108
108
|
|
@@ -127,7 +127,7 @@ LO : SK
|
|
127
127
|
BP : SB
|
128
128
|
SF : ZA
|
129
129
|
SP : ES
|
130
|
-
CE: LK
|
130
|
+
CE : LK
|
131
131
|
SU : SD
|
132
132
|
NS : SR
|
133
133
|
WZ : SZ
|
@@ -147,7 +147,7 @@ UP : UA
|
|
147
147
|
UK : GB
|
148
148
|
|
149
149
|
NH : VU
|
150
|
-
VM: VN
|
150
|
+
VM : VN
|
151
151
|
|
152
152
|
WI : EH
|
153
153
|
|
@@ -52,7 +52,7 @@ module Barometer
|
|
52
52
|
|
53
53
|
def self._build_current(data, metric=true)
|
54
54
|
raise ArgumentError unless data.is_a?(Hash)
|
55
|
-
current = Measurement::
|
55
|
+
current = Measurement::Result.new
|
56
56
|
|
57
57
|
if data['current_conditions']
|
58
58
|
data = data['current_conditions']
|
@@ -81,7 +81,7 @@ module Barometer
|
|
81
81
|
def self._build_forecast(data, metric=true)
|
82
82
|
raise ArgumentError unless data.is_a?(Hash)
|
83
83
|
|
84
|
-
forecasts = Measurement::
|
84
|
+
forecasts = Measurement::ResultArray.new
|
85
85
|
return forecasts unless data && data['forecast_information'] &&
|
86
86
|
data['forecast_information']['forecast_date']
|
87
87
|
start_date = Date.parse(data['forecast_information']['forecast_date']['data'])
|
@@ -90,7 +90,7 @@ module Barometer
|
|
90
90
|
# go through each forecast and create an instance
|
91
91
|
d = 0
|
92
92
|
data.each do |forecast|
|
93
|
-
forecast_measurement = Measurement::
|
93
|
+
forecast_measurement = Measurement::Result.new
|
94
94
|
if forecast['icon']
|
95
95
|
icon_match = forecast['icon']['data'].match(/.*\/([A-Za-z_]*)\.png/)
|
96
96
|
forecast_measurement.icon = icon_match[1] if icon_match
|
@@ -97,7 +97,7 @@ module Barometer
|
|
97
97
|
def self._build_current(data, metric=true)
|
98
98
|
raise ArgumentError unless data.is_a?(Hash)
|
99
99
|
|
100
|
-
current = Measurement::
|
100
|
+
current = Measurement::Result.new
|
101
101
|
# current.updated_at = Data::LocalDateTime.parse(data['observation_time']) if data['observation_time']
|
102
102
|
current.humidity = data['aws:humidity'].to_i
|
103
103
|
current.condition = data['aws:current_condition'] if data['aws:current_condition']
|
@@ -124,13 +124,13 @@ module Barometer
|
|
124
124
|
|
125
125
|
def self._build_forecast(data, metric=true)
|
126
126
|
raise ArgumentError unless data.is_a?(Hash)
|
127
|
-
forecasts = Measurement::
|
127
|
+
forecasts = Measurement::ResultArray.new
|
128
128
|
# go through each forecast and create an instance
|
129
129
|
if data && data["aws:forecast"]
|
130
130
|
start_date = Date.parse(data['date'])
|
131
131
|
i = 0
|
132
132
|
data["aws:forecast"].each do |forecast|
|
133
|
-
forecast_measurement = Measurement::
|
133
|
+
forecast_measurement = Measurement::Result.new
|
134
134
|
icon_match = forecast['aws:image'].match(/cond(\d*)\.gif$/)
|
135
135
|
forecast_measurement.icon = icon_match[1].to_i.to_s if icon_match
|
136
136
|
forecast_measurement.date = start_date + i
|