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
@@ -26,7 +26,10 @@ module Barometer
|
|
26
26
|
#
|
27
27
|
pre_query = nil
|
28
28
|
if original_query.format == :weather_id
|
29
|
-
pre_query = Query::Format::
|
29
|
+
unless pre_query = original_query.get_conversion(Query::Format::Geocode.format)
|
30
|
+
pre_query = Query::Format::WeatherID.reverse(original_query)
|
31
|
+
original_query.post_conversion(pre_query)
|
32
|
+
end
|
30
33
|
end
|
31
34
|
|
32
35
|
# convert & adjust
|
@@ -23,11 +23,14 @@ module Barometer
|
|
23
23
|
unless converts?(original_query)
|
24
24
|
return (original_query.format == format ? original_query.dup : nil)
|
25
25
|
end
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
|
27
|
+
unless converted_query = original_query.get_conversion(format)
|
28
|
+
converted_query = Barometer::Query.new
|
29
|
+
converted_query = (original_query.format == :weather_id ?
|
30
|
+
Query::Format::WeatherID.reverse(original_query) :
|
31
|
+
geocode(original_query))
|
32
|
+
original_query.post_conversion(converted_query) if converted_query
|
33
|
+
end
|
31
34
|
converted_query
|
32
35
|
end
|
33
36
|
|
@@ -35,9 +38,8 @@ module Barometer
|
|
35
38
|
#
|
36
39
|
def self.geocode(original_query)
|
37
40
|
raise ArgumentError unless is_a_query?(original_query)
|
41
|
+
|
38
42
|
converted_query = Barometer::Query.new
|
39
|
-
|
40
|
-
#converted_query.geo = _geocode(original_query)
|
41
43
|
converted_query.geo = WebService::Geocode.fetch(original_query)
|
42
44
|
if converted_query.geo
|
43
45
|
converted_query.country_code = converted_query.geo.country_code
|
@@ -22,8 +22,8 @@ module Barometer
|
|
22
22
|
#
|
23
23
|
def self.regex; /^[A-Za-z]{3,4}$/; end
|
24
24
|
|
25
|
-
#
|
26
|
-
#
|
25
|
+
# in some cases the first letter can designate the country
|
26
|
+
#
|
27
27
|
def self.country_code(query=nil)
|
28
28
|
return unless query && query.is_a?(String)
|
29
29
|
$:.unshift(File.dirname(__FILE__))
|
@@ -17,7 +17,7 @@ module Barometer
|
|
17
17
|
def self.format; :weather_id; end
|
18
18
|
def self.regex; /(^[A-Za-z]{4}[0-9]{4}$)/; end
|
19
19
|
def self.convertable_formats
|
20
|
-
[:short_zipcode, :zipcode, :coordinates, :geocode]
|
20
|
+
[:short_zipcode, :zipcode, :coordinates, :icao, :geocode]
|
21
21
|
end
|
22
22
|
|
23
23
|
# the first two letters of the :weather_id is the country_code
|
@@ -31,10 +31,10 @@ module Barometer
|
|
31
31
|
def self.to(original_query)
|
32
32
|
raise ArgumentError unless is_a_query?(original_query)
|
33
33
|
return nil unless converts?(original_query)
|
34
|
-
converted_query = Barometer::Query.new
|
35
34
|
|
36
35
|
# convert original query to :geocode, as that is the only
|
37
36
|
# format we can convert directly from to weather_id
|
37
|
+
converted_query = Barometer::Query.new
|
38
38
|
converted_query = Query::Format::Geocode.to(original_query)
|
39
39
|
converted_query.q = _search(converted_query)
|
40
40
|
converted_query.format = format
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module Barometer
|
2
|
+
#
|
3
|
+
# Common Measurement
|
4
|
+
#
|
5
|
+
# Code common to both Current and Forecast Measurements
|
6
|
+
#
|
7
|
+
class Measurement::Common
|
8
|
+
|
9
|
+
attr_reader :humidity, :icon, :condition
|
10
|
+
attr_reader :wind, :sun
|
11
|
+
attr_accessor :metric
|
12
|
+
|
13
|
+
def initialize(metric=true)
|
14
|
+
@metric = metric
|
15
|
+
end
|
16
|
+
|
17
|
+
def metric?; metric; end
|
18
|
+
|
19
|
+
# accessors (with input checking)
|
20
|
+
#
|
21
|
+
def humidity=(humidity)
|
22
|
+
raise ArgumentError unless
|
23
|
+
(humidity.is_a?(Fixnum) || humidity.is_a?(Float))
|
24
|
+
@humidity = humidity
|
25
|
+
end
|
26
|
+
|
27
|
+
def icon=(icon)
|
28
|
+
raise ArgumentError unless icon.is_a?(String)
|
29
|
+
@icon = icon
|
30
|
+
end
|
31
|
+
|
32
|
+
def condition=(condition)
|
33
|
+
raise ArgumentError unless condition.is_a?(String)
|
34
|
+
@condition = condition
|
35
|
+
end
|
36
|
+
|
37
|
+
def wind=(wind)
|
38
|
+
raise ArgumentError unless wind.is_a?(Data::Speed)
|
39
|
+
@wind = wind
|
40
|
+
end
|
41
|
+
|
42
|
+
def sun=(sun)
|
43
|
+
raise ArgumentError unless (sun.is_a?(Data::Sun) || sun.nil?)
|
44
|
+
@sun = sun
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# helpers
|
49
|
+
#
|
50
|
+
|
51
|
+
# creates "?" helpers for all attributes (which maps to nil?)
|
52
|
+
#
|
53
|
+
def method_missing(method,*args)
|
54
|
+
# if the method ends in ?, then strip it off and see if we
|
55
|
+
# respond to the method without the ?
|
56
|
+
if (call_method = method.to_s.chomp!("?")) && respond_to?(call_method)
|
57
|
+
return send(call_method).nil? ? false : true
|
58
|
+
else
|
59
|
+
super(method,*args)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
# answer simple questions
|
65
|
+
#
|
66
|
+
|
67
|
+
def windy?(threshold=10)
|
68
|
+
raise ArgumentError unless (threshold.is_a?(Fixnum) || threshold.is_a?(Float))
|
69
|
+
return nil unless wind?
|
70
|
+
wind.to_f(metric?) >= threshold.to_f
|
71
|
+
end
|
72
|
+
|
73
|
+
def day?(time)
|
74
|
+
return nil unless time && sun?
|
75
|
+
sun.after_rise?(time) && sun.before_set?(time)
|
76
|
+
end
|
77
|
+
|
78
|
+
def wet?(wet_icons=nil, humidity_threshold=99)
|
79
|
+
result = nil
|
80
|
+
result ||= _wet_by_icon?(wet_icons) if icon?
|
81
|
+
result ||= _wet_by_humidity?(humidity_threshold) if humidity?
|
82
|
+
result
|
83
|
+
end
|
84
|
+
|
85
|
+
def sunny?(time, sunny_icons=nil)
|
86
|
+
return nil unless time
|
87
|
+
is_day = day?(time)
|
88
|
+
return nil if is_day.nil?
|
89
|
+
is_day && _sunny_by_icon?(sunny_icons)
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def _wet_by_humidity?(threshold=99)
|
95
|
+
raise ArgumentError unless (threshold.is_a?(Fixnum) || threshold.is_a?(Float))
|
96
|
+
return nil unless humidity?
|
97
|
+
humidity.to_f >= threshold.to_f
|
98
|
+
end
|
99
|
+
|
100
|
+
def _wet_by_icon?(wet_icons=nil)
|
101
|
+
raise ArgumentError unless (wet_icons.nil? || wet_icons.is_a?(Array))
|
102
|
+
return nil unless (icon? && wet_icons)
|
103
|
+
wet_icons.include?(icon.to_s.downcase)
|
104
|
+
end
|
105
|
+
|
106
|
+
def _sunny_by_icon?(sunny_icons=nil)
|
107
|
+
raise ArgumentError unless (sunny_icons.nil? || sunny_icons.is_a?(Array))
|
108
|
+
return nil unless (icon? && sunny_icons)
|
109
|
+
sunny_icons.include?(icon.to_s.downcase)
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
@@ -6,31 +6,14 @@ module Barometer
|
|
6
6
|
# This is basically a data holding class for the current weather
|
7
7
|
# conditions.
|
8
8
|
#
|
9
|
-
class
|
9
|
+
class Measurement::Current < Measurement::Common
|
10
10
|
|
11
11
|
attr_reader :current_at, :updated_at
|
12
|
-
attr_reader :humidity, :icon, :condition
|
13
12
|
attr_reader :temperature, :dew_point, :heat_index, :wind_chill
|
14
|
-
attr_reader :
|
13
|
+
attr_reader :pressure, :visibility
|
15
14
|
|
16
15
|
# accessors (with input checking)
|
17
16
|
#
|
18
|
-
def humidity=(humidity)
|
19
|
-
raise ArgumentError unless
|
20
|
-
(humidity.is_a?(Fixnum) || humidity.is_a?(Float))
|
21
|
-
@humidity = humidity
|
22
|
-
end
|
23
|
-
|
24
|
-
def icon=(icon)
|
25
|
-
raise ArgumentError unless icon.is_a?(String)
|
26
|
-
@icon = icon
|
27
|
-
end
|
28
|
-
|
29
|
-
def condition=(condition)
|
30
|
-
raise ArgumentError unless condition.is_a?(String)
|
31
|
-
@condition = condition
|
32
|
-
end
|
33
|
-
|
34
17
|
def temperature=(temperature)
|
35
18
|
raise ArgumentError unless temperature.is_a?(Data::Temperature)
|
36
19
|
@temperature = temperature
|
@@ -51,11 +34,6 @@ module Barometer
|
|
51
34
|
@wind_chill = wind_chill
|
52
35
|
end
|
53
36
|
|
54
|
-
def wind=(wind)
|
55
|
-
raise ArgumentError unless wind.is_a?(Data::Speed)
|
56
|
-
@wind = wind
|
57
|
-
end
|
58
|
-
|
59
37
|
def pressure=(pressure)
|
60
38
|
raise ArgumentError unless pressure.is_a?(Data::Pressure)
|
61
39
|
@pressure = pressure
|
@@ -66,35 +44,32 @@ module Barometer
|
|
66
44
|
@visibility = visibility
|
67
45
|
end
|
68
46
|
|
69
|
-
def sun=(sun)
|
70
|
-
raise ArgumentError unless sun.is_a?(Data::Sun)
|
71
|
-
@sun = sun
|
72
|
-
end
|
73
|
-
|
74
47
|
def current_at=(current_at)
|
75
48
|
raise ArgumentError unless (current_at.is_a?(Data::LocalTime) || current_at.is_a?(Data::LocalDateTime))
|
76
49
|
@current_at = current_at
|
77
50
|
end
|
78
51
|
|
79
52
|
def updated_at=(updated_at)
|
80
|
-
|
81
|
-
|
53
|
+
raise ArgumentError unless (updated_at.is_a?(Data::LocalTime) || updated_at.is_a?(Data::LocalDateTime))
|
54
|
+
@updated_at = updated_at
|
82
55
|
end
|
83
56
|
|
84
57
|
#
|
85
|
-
#
|
58
|
+
# answer simple questions
|
86
59
|
#
|
87
60
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
61
|
+
def wet?(wet_icons=nil, humidity_threshold=99)
|
62
|
+
result = nil
|
63
|
+
result ||= super(wet_icons, humidity_threshold) if (icon? || humidity?)
|
64
|
+
result ||= _wet_by_dewpoint? if (dew_point? && temperature?)
|
65
|
+
result
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def _wet_by_dewpoint?
|
71
|
+
return nil unless dew_point? && temperature?
|
72
|
+
temperature.to_f(metric?) <= dew_point.to_f(metric?)
|
98
73
|
end
|
99
74
|
|
100
75
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'date'
|
2
|
+
module Barometer
|
3
|
+
#
|
4
|
+
# Forecast Measurement
|
5
|
+
# a data class for forecasted weather conditions
|
6
|
+
#
|
7
|
+
# This is basically a data holding class for the forecasted weather
|
8
|
+
# conditions.
|
9
|
+
#
|
10
|
+
class Measurement::Forecast < Measurement::Common
|
11
|
+
|
12
|
+
attr_reader :date
|
13
|
+
attr_reader :low, :high, :pop, :night
|
14
|
+
|
15
|
+
# accessors (with input checking)
|
16
|
+
#
|
17
|
+
def date=(date)
|
18
|
+
raise ArgumentError unless date.is_a?(Date)
|
19
|
+
@date = date
|
20
|
+
end
|
21
|
+
|
22
|
+
def high=(high)
|
23
|
+
raise ArgumentError unless high.is_a?(Data::Temperature)
|
24
|
+
@high = high
|
25
|
+
end
|
26
|
+
|
27
|
+
def low=(low)
|
28
|
+
raise ArgumentError unless low.is_a?(Data::Temperature)
|
29
|
+
@low = low
|
30
|
+
end
|
31
|
+
|
32
|
+
def pop=(pop)
|
33
|
+
raise ArgumentError unless pop.is_a?(Fixnum)
|
34
|
+
@pop = pop
|
35
|
+
end
|
36
|
+
|
37
|
+
def night=(night)
|
38
|
+
raise ArgumentError unless night.is_a?(Measurement::ForecastNight)
|
39
|
+
@night = night
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# answer simple questions
|
44
|
+
#
|
45
|
+
|
46
|
+
def wet?(wet_icons=nil, pop_threshold=50, humidity_threshold=99)
|
47
|
+
result = nil
|
48
|
+
result ||= _wet_by_pop?(pop_threshold) if pop?
|
49
|
+
result ||= super(wet_icons, humidity_threshold) if (icon? || humidity?)
|
50
|
+
result
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def _wet_by_pop?(threshold=50)
|
56
|
+
raise ArgumentError unless (threshold.is_a?(Fixnum) || threshold.is_a?(Float))
|
57
|
+
return nil unless pop?
|
58
|
+
pop.to_f >= threshold.to_f
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'date'
|
2
|
+
module Barometer
|
3
|
+
#
|
4
|
+
# Forecast Array
|
5
|
+
# an array that holds multiple forecasts
|
6
|
+
#
|
7
|
+
class Measurement::ForecastArray < Array
|
8
|
+
|
9
|
+
def <<(forecast)
|
10
|
+
raise ArgumentError unless forecast.is_a?(Measurement::Forecast)
|
11
|
+
super(forecast)
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](index)
|
15
|
+
index.is_a?(Fixnum) ? super(index) : self.for(index)
|
16
|
+
end
|
17
|
+
|
18
|
+
#
|
19
|
+
# Returns a forecast for a day given by a Date, DateTime,
|
20
|
+
# Time, or a string that can be parsed to a date
|
21
|
+
#
|
22
|
+
# credit: http://github.com/jdpace/weatherman/
|
23
|
+
#
|
24
|
+
def for(date)
|
25
|
+
|
26
|
+
return nil unless self.size > 0
|
27
|
+
|
28
|
+
# Format date into a Date class
|
29
|
+
date = case date.class.name
|
30
|
+
when 'Date'
|
31
|
+
date
|
32
|
+
when 'Data::LocalDateTime'
|
33
|
+
date.to_d
|
34
|
+
when 'String'
|
35
|
+
Date.parse(date)
|
36
|
+
when 'Time'
|
37
|
+
Date.new(date.year, date.month, date.day)
|
38
|
+
when 'DateTime'
|
39
|
+
Date.new(date.year, date.month, date.day)
|
40
|
+
end
|
41
|
+
|
42
|
+
day = nil
|
43
|
+
self.each do |f|
|
44
|
+
day = f if date == f.date
|
45
|
+
end
|
46
|
+
return day
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# answer simple questions
|
51
|
+
#
|
52
|
+
|
53
|
+
def windy?(datetime, threshold=10)
|
54
|
+
(forecast = self[datetime]) ? forecast.windy?(threshold) : nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def day?(datetime)
|
58
|
+
local_time = Data::LocalTime.parse(datetime)
|
59
|
+
(forecast = self[datetime]) ? forecast.day?(local_time) : nil
|
60
|
+
end
|
61
|
+
|
62
|
+
def sunny?(datetime, sunny_icons=nil)
|
63
|
+
local_time = Data::LocalTime.parse(datetime)
|
64
|
+
(forecast = self[datetime]) ? forecast.sunny?(local_time, sunny_icons) : nil
|
65
|
+
end
|
66
|
+
|
67
|
+
def wet?(datetime, wet_icons=nil, pop_threshold=50, humidity_threshold=99)
|
68
|
+
(forecast = self[datetime]) ? forecast.wet?(wet_icons,pop_threshold,humidity_threshold) : nil
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -12,7 +12,7 @@ module Barometer
|
|
12
12
|
# - time_zone information (for the location in question)
|
13
13
|
# - weather station information (for the station that gave collected the data)
|
14
14
|
#
|
15
|
-
class
|
15
|
+
class Measurement
|
16
16
|
|
17
17
|
attr_reader :source, :weight
|
18
18
|
attr_reader :measured_at, :utc_time_stamp
|
@@ -20,6 +20,7 @@ module Barometer
|
|
20
20
|
attr_reader :timezone, :station, :location, :links
|
21
21
|
attr_reader :success
|
22
22
|
attr_accessor :metric, :query, :format
|
23
|
+
attr_accessor :start_at, :end_at
|
23
24
|
|
24
25
|
def initialize(source=nil, metric=true)
|
25
26
|
@source = source
|
@@ -39,6 +40,7 @@ module Barometer
|
|
39
40
|
def metric?; @metric; end
|
40
41
|
def metric!; @metric=true; end
|
41
42
|
def imperial!; @metric=false; end
|
43
|
+
def now; timezone ? timezone.now : nil; end
|
42
44
|
|
43
45
|
#
|
44
46
|
# this will tell us if the measurement is still current ... if it is still
|
@@ -58,7 +60,7 @@ module Barometer
|
|
58
60
|
self.current.current_at : self.measured_at)
|
59
61
|
|
60
62
|
local_time = (local_time.nil? ? current_at : Data::LocalTime.parse(local_time))
|
61
|
-
return
|
63
|
+
return true unless local_time
|
62
64
|
raise ArgumentError unless local_time.is_a?(Data::LocalTime)
|
63
65
|
|
64
66
|
hours_still_current = 4
|
@@ -70,32 +72,12 @@ module Barometer
|
|
70
72
|
# Returns a forecast for a day given by a Date, DateTime,
|
71
73
|
# Time, or a string that can be parsed to a date
|
72
74
|
#
|
73
|
-
# credit: http://github.com/jdpace/weatherman/
|
74
|
-
#
|
75
75
|
def for(date=nil)
|
76
76
|
date = @timezone.today unless date || !@timezone
|
77
77
|
date ||= Date.today
|
78
78
|
return nil unless (@forecast && @forecast.size > 0)
|
79
79
|
|
80
|
-
|
81
|
-
date = case date.class.name
|
82
|
-
when 'Date'
|
83
|
-
date
|
84
|
-
when 'Data::LocalDateTime'
|
85
|
-
date.to_d
|
86
|
-
when 'String'
|
87
|
-
Date.parse(date)
|
88
|
-
when 'Time'
|
89
|
-
Date.new(date.year, date.month, date.day)
|
90
|
-
when 'DateTime'
|
91
|
-
Date.new(date.year, date.month, date.day)
|
92
|
-
end
|
93
|
-
|
94
|
-
day = nil
|
95
|
-
@forecast.each do |f|
|
96
|
-
day = f if date == f.date
|
97
|
-
end
|
98
|
-
return day
|
80
|
+
@forecast.for(date)
|
99
81
|
end
|
100
82
|
|
101
83
|
#
|
@@ -113,18 +95,19 @@ module Barometer
|
|
113
95
|
end
|
114
96
|
|
115
97
|
def current=(current)
|
116
|
-
raise ArgumentError unless current.is_a?(
|
98
|
+
raise ArgumentError unless current.is_a?(Measurement::Current)
|
117
99
|
@current = current
|
118
100
|
self.stamp!
|
119
101
|
self.success!
|
120
102
|
end
|
121
103
|
|
122
104
|
def forecast=(forecast)
|
123
|
-
raise ArgumentError unless forecast.is_a?(
|
105
|
+
raise ArgumentError unless forecast.is_a?(Measurement::ForecastArray)
|
124
106
|
@forecast = forecast
|
125
107
|
end
|
126
108
|
|
127
109
|
def timezone=(timezone)
|
110
|
+
return unless timezone
|
128
111
|
raise ArgumentError unless timezone.is_a?(Data::Zone)
|
129
112
|
@timezone = timezone
|
130
113
|
end
|
@@ -156,34 +139,63 @@ module Barometer
|
|
156
139
|
|
157
140
|
#
|
158
141
|
# simple questions
|
159
|
-
# pass questions to the source
|
160
142
|
#
|
161
143
|
|
162
|
-
def windy?(
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
Barometer::WeatherService.source(@source).wet?(self, threshold, local_datetime)
|
144
|
+
def windy?(time_string=nil, threshold=10)
|
145
|
+
time_string ||= (measured_at || now)
|
146
|
+
local_time = Data::LocalTime.parse(time_string)
|
147
|
+
|
148
|
+
if current?(local_time)
|
149
|
+
return nil unless current
|
150
|
+
current.windy?(threshold)
|
151
|
+
else
|
152
|
+
return nil unless forecast && (future = forecast[local_time])
|
153
|
+
future.windy?(threshold)
|
154
|
+
end
|
174
155
|
end
|
175
156
|
|
176
157
|
def day?(time_string=nil)
|
177
|
-
|
178
|
-
|
179
|
-
|
158
|
+
time_string ||= (measured_at || now)
|
159
|
+
local_time = Data::LocalTime.parse(time_string)
|
160
|
+
|
161
|
+
if current?(local_time)
|
162
|
+
return nil unless current
|
163
|
+
current.day?(local_time)
|
164
|
+
else
|
165
|
+
return nil unless forecast && (future = forecast[local_time])
|
166
|
+
future.day?(local_time)
|
167
|
+
end
|
180
168
|
end
|
181
169
|
|
182
170
|
def sunny?(time_string=nil)
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
171
|
+
time_string ||= (measured_at || now)
|
172
|
+
local_time = Data::LocalTime.parse(time_string)
|
173
|
+
sunny_icons = Barometer::WeatherService.source(@source)._sunny_icon_codes
|
174
|
+
|
175
|
+
is_day = day?(local_time)
|
176
|
+
return is_day unless is_day
|
177
|
+
|
178
|
+
if current?(local_time)
|
179
|
+
return nil unless current
|
180
|
+
current.sunny?(local_time, sunny_icons)
|
181
|
+
else
|
182
|
+
return nil unless forecast && (future = forecast[local_time])
|
183
|
+
future.sunny?(local_time, sunny_icons)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def wet?(time_string=nil, pop_threshold=50, humidity_threshold=99)
|
188
|
+
time_string ||= (measured_at || now)
|
189
|
+
local_time = Data::LocalTime.parse(time_string)
|
190
|
+
wet_icons = Barometer::WeatherService.source(@source)._wet_icon_codes
|
191
|
+
|
192
|
+
if current?(local_time)
|
193
|
+
return nil unless current
|
194
|
+
current.wet?(wet_icons, humidity_threshold)
|
195
|
+
else
|
196
|
+
return nil unless forecast && (future = forecast[local_time])
|
197
|
+
future.wet?(wet_icons, pop_threshold, humidity_threshold)
|
198
|
+
end
|
187
199
|
end
|
188
200
|
|
189
201
|
end
|