weatherzone 0.5.8
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/History.txt +6 -0
- data/Manifest.txt +51 -0
- data/README.txt +30 -0
- data/Rakefile +7 -0
- data/bin/weatherzone +0 -0
- data/lib/ext/class.rb +175 -0
- data/lib/ext/object.rb +74 -0
- data/lib/tzinfo/definitions/Australia/CDT.rb +13 -0
- data/lib/tzinfo/definitions/Australia/CST.rb +13 -0
- data/lib/tzinfo/definitions/Australia/EDT.rb +13 -0
- data/lib/tzinfo/definitions/Australia/EST.rb +13 -0
- data/lib/tzinfo/definitions/Australia/WDT.rb +13 -0
- data/lib/tzinfo/definitions/Australia/WST.rb +13 -0
- data/lib/vendor/openuri_memcached/History.txt +18 -0
- data/lib/vendor/openuri_memcached/License.txt +20 -0
- data/lib/vendor/openuri_memcached/README.markdown +48 -0
- data/lib/vendor/openuri_memcached/lib/openuri/common.rb +117 -0
- data/lib/vendor/openuri_memcached/lib/openuri/memcached.rb +36 -0
- data/lib/vendor/openuri_memcached/lib/openuri/rails-cache.rb +21 -0
- data/lib/vendor/openuri_memcached/lib/openuri_memcached.rb +1 -0
- data/lib/weatherzone.rb +39 -0
- data/lib/weatherzone/connection.rb +85 -0
- data/lib/weatherzone/finder.rb +129 -0
- data/lib/weatherzone/helpers/almanac_element.rb +28 -0
- data/lib/weatherzone/helpers/date_parser.rb +33 -0
- data/lib/weatherzone/helpers/units.rb +76 -0
- data/lib/weatherzone/resource.rb +46 -0
- data/lib/weatherzone/resources/almanac.rb +18 -0
- data/lib/weatherzone/resources/almanac_period.rb +51 -0
- data/lib/weatherzone/resources/climate_period.rb +8 -0
- data/lib/weatherzone/resources/conditions.rb +19 -0
- data/lib/weatherzone/resources/country.rb +4 -0
- data/lib/weatherzone/resources/daily_observation.rb +10 -0
- data/lib/weatherzone/resources/district_forecast.rb +5 -0
- data/lib/weatherzone/resources/forecast.rb +47 -0
- data/lib/weatherzone/resources/historical_observation.rb +57 -0
- data/lib/weatherzone/resources/image.rb +9 -0
- data/lib/weatherzone/resources/lift.rb +3 -0
- data/lib/weatherzone/resources/location.rb +100 -0
- data/lib/weatherzone/resources/marine_forecast.rb +9 -0
- data/lib/weatherzone/resources/marine_summary.rb +8 -0
- data/lib/weatherzone/resources/moon_phase.rb +23 -0
- data/lib/weatherzone/resources/news_item.rb +18 -0
- data/lib/weatherzone/resources/point_forecast.rb +40 -0
- data/lib/weatherzone/resources/snow_report.rb +5 -0
- data/lib/weatherzone/resources/state_forecast.rb +4 -0
- data/lib/weatherzone/resources/surf_report.rb +5 -0
- data/lib/weatherzone/resources/tide.rb +9 -0
- data/lib/weatherzone/resources/warning.rb +21 -0
- data/lib/weatherzone/resources/weather.rb +14 -0
- data/test/test_almanac.rb +25 -0
- data/test/test_almanac_period.rb +33 -0
- data/test/test_buoy_observation.rb +24 -0
- data/test/test_climate_period.rb +29 -0
- data/test/test_conditions.rb +32 -0
- data/test/test_connection.rb +28 -0
- data/test/test_country.rb +29 -0
- data/test/test_daily_observation.rb +29 -0
- data/test/test_district_forecast.rb +23 -0
- data/test/test_farenheit_conversion_factor.rb +48 -0
- data/test/test_finder.rb +148 -0
- data/test/test_forecast.rb +30 -0
- data/test/test_helper.rb +38 -0
- data/test/test_historical_observation.rb +32 -0
- data/test/test_image.rb +23 -0
- data/test/test_location.rb +70 -0
- data/test/test_marine_forecast.rb +27 -0
- data/test/test_marine_summary.rb +24 -0
- data/test/test_moon_phase.rb +33 -0
- data/test/test_news_item.rb +22 -0
- data/test/test_point_forecast.rb +24 -0
- data/test/test_snow_report.rb +27 -0
- data/test/test_state_forecast.rb +23 -0
- data/test/test_surf_report.rb +22 -0
- data/test/test_tide.rb +23 -0
- data/test/test_value_and_unit_helpers.rb +45 -0
- data/test/test_warning.rb +23 -0
- data/test/test_weather.rb +22 -0
- metadata +146 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
module Weatherzone
|
2
|
+
module Helpers
|
3
|
+
module AlmanacElement
|
4
|
+
|
5
|
+
def self.included(klass)
|
6
|
+
klass.class_eval do
|
7
|
+
def self.almanac_element(type, subtype, options={})
|
8
|
+
period = options[:period]
|
9
|
+
method_name = options[:as]
|
10
|
+
attributes = options[:with_attributes]
|
11
|
+
|
12
|
+
method_name = "#{subtype.downcase.gsub(' ', '_')}_#{type.downcase.gsub(' ', '_')}" unless method_name
|
13
|
+
|
14
|
+
with_options = {:type => type, :subtype => subtype}
|
15
|
+
with_options.merge!(:period => period) if period
|
16
|
+
|
17
|
+
element :almanac_element, :with => with_options, :as => method_name
|
18
|
+
|
19
|
+
attributes.each do |attr_name|
|
20
|
+
element :almanac_element, :value => attr_name, :with => with_options, :as => "#{method_name}_#{attr_name}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Weatherzone
|
2
|
+
module Helpers
|
3
|
+
module DateParser
|
4
|
+
def self.included(klass)
|
5
|
+
klass.class_eval do
|
6
|
+
|
7
|
+
def self.interpret_as_date(*methods)
|
8
|
+
methods.each do |method_name|
|
9
|
+
define_method method_name do
|
10
|
+
Date.parse(instance_variable_get("@#{method_name}"))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.interpret_as_time(*methods)
|
16
|
+
methods.each do |method_name|
|
17
|
+
has_attribute :tz, :on_elements => methods
|
18
|
+
define_method "#{method_name}_utc" do
|
19
|
+
tz = TZInfo::Timezone.get("Australia/#{send("#{method_name}_tz")}")
|
20
|
+
tz.local_to_utc(Time.parse(instance_variable_get("@#{method_name}")))
|
21
|
+
end
|
22
|
+
define_method method_name do
|
23
|
+
tz = TZInfo::Timezone.get("Australia/#{send("#{method_name}_tz")}")
|
24
|
+
tz.utc_to_local send("#{method_name}_utc")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'bigdecimal'
|
2
|
+
|
3
|
+
module Weatherzone
|
4
|
+
module Helpers
|
5
|
+
module Units
|
6
|
+
def self.included(klass)
|
7
|
+
klass.class_eval do
|
8
|
+
|
9
|
+
self.temperature_attributes = []
|
10
|
+
self.forecast_temperature_attributes = []
|
11
|
+
self.observed_temperature_attributes = []
|
12
|
+
|
13
|
+
def self.temperature(*methods)
|
14
|
+
self.temperature_attributes = methods
|
15
|
+
value_plus_unit_readers *methods
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.forecast_temperature(*methods)
|
19
|
+
self.forecast_temperature_attributes = methods
|
20
|
+
value_plus_unit_readers *methods
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.observed_temperature(*methods)
|
24
|
+
self.observed_temperature_attributes = methods
|
25
|
+
value_plus_unit_readers *methods
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.value_plus_unit_readers(*methods)
|
29
|
+
methods.each do |method_name|
|
30
|
+
define_method method_name do
|
31
|
+
value = send("#{method_name}_value")
|
32
|
+
if settings.strip_scale_from_units
|
33
|
+
value ? "#{value}#{instance_variable_get("@#{method_name}_units")}".gsub("C", "") : nil
|
34
|
+
else
|
35
|
+
value ? "#{value}#{instance_variable_get("@#{method_name}_units")}".gsub("C", Weather.temperature_unit || "C") : nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
define_method "#{method_name}_value" do
|
40
|
+
ivar_name = instance_variable_names.include?("@#{method_name}_value") ? "@#{method_name}_value" : "@#{method_name}"
|
41
|
+
value = instance_variable_get(ivar_name)
|
42
|
+
fahrenheit_conversion_required?(method_name) ? to_fahrenheit(value, method_name) : value
|
43
|
+
end
|
44
|
+
|
45
|
+
define_method "#{method_name}_units" do
|
46
|
+
ivar_name = "@#{method_name}_units"
|
47
|
+
unit = instance_variable_get(ivar_name)
|
48
|
+
fahrenheit_conversion_required?(method_name) ? unit.gsub("C", temperature_unit) : unit
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def fahrenheit_conversion_required?(method_name)
|
54
|
+
temperature_unit == "F" && (self.class.forecast_temperature_attributes.include?(method_name) || self.class.observed_temperature_attributes.include?(method_name))
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_fahrenheit(value, method_name)
|
58
|
+
temp_f = (BigDecimal(value) * BigDecimal("1.8")) + BigDecimal("32")
|
59
|
+
case
|
60
|
+
when self.class.forecast_temperature_attributes.include?(method_name)
|
61
|
+
temp_f.round(0).to_i.to_s
|
62
|
+
when self.class.observed_temperature_attributes.include?(method_name)
|
63
|
+
temp_f.round(1).to_s("F")
|
64
|
+
else
|
65
|
+
temp_f.to_s("F")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def temperature_unit
|
70
|
+
settings.weather_class.temperature_unit
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'weatherzone/connection'
|
2
|
+
|
3
|
+
module Weatherzone
|
4
|
+
|
5
|
+
class Resource
|
6
|
+
|
7
|
+
include SAXMachine
|
8
|
+
|
9
|
+
class_inheritable_accessor :top_level_element, :temperature_unit, :temperature_attributes, :forecast_temperature_attributes, :observed_temperature_attributes
|
10
|
+
|
11
|
+
def self.inherited(klass)
|
12
|
+
klass.class_eval do
|
13
|
+
self.top_level_element ||= self.name.downcase
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.has_elements(*elements)
|
18
|
+
elements.each do |e|
|
19
|
+
element e
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.has_attribute(attr_name, options={})
|
24
|
+
element_name = options[:on_elements] || self.top_level_element
|
25
|
+
if element_name.is_a? Array
|
26
|
+
element_name.each do |e|
|
27
|
+
element e, :value => attr_name, :as => "#{e}_#{attr_name}"
|
28
|
+
end
|
29
|
+
else
|
30
|
+
method_name = (element_name == self.top_level_element) ? "#{attr_name}" : "#{element_name}_#{attr_name}"
|
31
|
+
element element_name, :value => attr_name, :as => method_name
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def settings
|
36
|
+
Weatherzone::Settings.instance
|
37
|
+
end
|
38
|
+
# def hash
|
39
|
+
# @fields.collect { |field_name, data_element| data_element.hash }.hash
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# def eql?(other)
|
43
|
+
# self.hash == other.hash
|
44
|
+
# end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Almanac < Weatherzone::Resource
|
2
|
+
attributes :month_num, :month_name, :date_start, :date_end
|
3
|
+
|
4
|
+
elements :almanac_period, :as => :almanac_periods, :class => AlmanacPeriod
|
5
|
+
|
6
|
+
def mtd
|
7
|
+
@mtd ||= almanac_periods.detect { |ap| ap.code == "MTD" }
|
8
|
+
end
|
9
|
+
|
10
|
+
def ytd
|
11
|
+
@ytd ||= almanac_periods.detect { |ap| ap.code == "YTD" }
|
12
|
+
end
|
13
|
+
|
14
|
+
def extremes
|
15
|
+
@extremes ||= almanac_periods.detect { |ap| ap.code == "Extremes" }
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class AlmanacPeriod < Weatherzone::Resource
|
2
|
+
|
3
|
+
attributes :code, :title, :month_name, :from, :to
|
4
|
+
|
5
|
+
include Weatherzone::Helpers::AlmanacElement
|
6
|
+
include Weatherzone::Helpers::DateParser
|
7
|
+
include Weatherzone::Helpers::Units
|
8
|
+
|
9
|
+
# Rainfall this month
|
10
|
+
almanac_element "Rainfall", "average", :with_attributes => [:value, :units, :days], :period => "long term", :as => :avg_rainfall_this_month
|
11
|
+
almanac_element "Rainfall", "driest", :with_attributes => [:value, :units, :date], :period => "this month", :as => :driest_rainfall_this_month
|
12
|
+
almanac_element "Rainfall", "wettest", :with_attributes => [:value, :units, :date], :period => "this month", :as => :wettest_rainfall_this_month
|
13
|
+
almanac_element "Rainfall", "so far", :with_attributes => [:value, :units, :days, :from, :to], :period => "this month", :as => :rainfall_this_month
|
14
|
+
almanac_element "Rainfall", "so far", :with_attributes => [:value, :units, :days, :from, :to], :period => "this time last year", :as => :rainfall_this_time_last_year
|
15
|
+
|
16
|
+
# Rainfall this year
|
17
|
+
almanac_element "Rainfall", "average", :with_attributes => [:value, :units, :days], :period => "to the end of this month", :as => :avg_rainfall_this_year
|
18
|
+
almanac_element "Rainfall", "driest", :with_attributes => [:value, :units, :date], :period => "this year", :as => :driest_rainfall_this_year
|
19
|
+
almanac_element "Rainfall", "wettest", :with_attributes => [:value, :units, :date], :period => "this year", :as => :wettest_rainfall_this_year
|
20
|
+
almanac_element "Rainfall", "so far", :with_attributes => [:value, :units, :days, :from, :to], :period => "this year", :as => :rainfall_this_year
|
21
|
+
|
22
|
+
# Temperature this month
|
23
|
+
almanac_element "Temperature", "average max", :with_attributes => [:value, :units], :period => "long term", :as => :avg_max_temp_long_term
|
24
|
+
almanac_element "Temperature", "average min", :with_attributes => [:value, :units], :period => "long term", :as => :avg_min_temp_long_term
|
25
|
+
almanac_element "Temperature", "average max", :with_attributes => [:value, :units, :from, :to], :period => "this month", :as => :avg_max_temp_this_month
|
26
|
+
almanac_element "Temperature", "average min", :with_attributes => [:value, :units, :from, :to], :period => "this month", :as => :avg_min_temp_this_month
|
27
|
+
almanac_element "Temperature", "hottest", :with_attributes => [:value, :units, :date], :period => "this month", :as => :hottest_temp_this_month
|
28
|
+
almanac_element "Temperature", "coldest", :with_attributes => [:value, :units, :date], :period => "this month", :as => :coldest_temp_this_month
|
29
|
+
|
30
|
+
# Temperature this year
|
31
|
+
almanac_element "Temperature", "hottest", :with_attributes => [:value, :units, :date], :period => "this year", :as => :hottest_temp_this_year
|
32
|
+
almanac_element "Temperature", "coldest", :with_attributes => [:value, :units, :date], :period => "this year", :as => :coldest_temp_this_year
|
33
|
+
|
34
|
+
# Extremes
|
35
|
+
almanac_element "Extreme", "coldest", :with_attributes => [:period, :year, :value, :units], :as => :coldest_extreme
|
36
|
+
almanac_element "Extreme", "hottest", :with_attributes => [:period, :year, :value, :units], :as => :hottest_extreme
|
37
|
+
almanac_element "Extreme", "wettest", :with_attributes => [:period, :year, :value, :units], :as => :wettest_extreme
|
38
|
+
almanac_element "Extreme", "highest", :with_attributes => [:period, :date, :value, :units], :as => :highest_extreme_temp
|
39
|
+
almanac_element "Extreme", "lowest", :with_attributes => [:period, :date, :value, :units], :as => :lowest_extreme_temp
|
40
|
+
|
41
|
+
interpret_as_date :driest_rainfall_this_month_date, :wettest_rainfall_this_month_date, :driest_rainfall_this_year_date, :wettest_rainfall_this_year_date,
|
42
|
+
:hottest_temp_this_month_date, :coldest_temp_this_month_date, :hottest_temp_this_year_date, :coldest_temp_this_year_date, :highest_extreme_temp_date,
|
43
|
+
:lowest_extreme_temp_date
|
44
|
+
|
45
|
+
temperature :avg_max_temp_long_term, :avg_min_temp_long_term, :avg_max_temp_this_month, :avg_min_temp_this_month, :hottest_temp_this_month, :coldest_temp_this_month,
|
46
|
+
:hottest_temp_this_year, :coldest_temp_this_year, :coldest_extreme, :hottest_extreme, :wettest_extreme, :highest_extreme_temp, :lowest_extreme_temp
|
47
|
+
|
48
|
+
value_plus_unit_readers :avg_rainfall_this_month, :driest_rainfall_this_month, :wettest_rainfall_this_month, :rainfall_this_month, :rainfall_this_time_last_year,
|
49
|
+
:avg_rainfall_this_year, :driest_rainfall_this_year, :wettest_rainfall_this_year, :rainfall_this_year
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
class ClimatePeriod < Weatherzone::Resource
|
2
|
+
include Weatherzone::Helpers::Units
|
3
|
+
attributes :name
|
4
|
+
has_elements :mean_temp_min_c, :mean_temp_max_c, :rain_days, :mean_rainfall_mm
|
5
|
+
has_attribute :units, :on_elements => [:mean_temp_min_c, :mean_temp_max_c, :mean_rainfall_mm]
|
6
|
+
temperature :mean_temp_min_c, :mean_temp_max_c
|
7
|
+
value_plus_unit_readers :mean_rainfall_mm
|
8
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class Conditions < Weatherzone::Resource
|
2
|
+
|
3
|
+
include Weatherzone::Helpers::Units
|
4
|
+
|
5
|
+
has_elements :obs_time_utc, :obs_time_local, :temp_c, :dp_c, :rh,
|
6
|
+
:wind_dir_degrees, :wind_dir_compass, :wind_speed_kph, :wind_speed_kts,
|
7
|
+
:wind_gust_kph, :wind_gust_kts, :feels_like_c, :rainfall_mm, :pressure_qnh_hpa
|
8
|
+
|
9
|
+
has_attribute :units, :on_elements => [:temp_c, :dp_c, :rh, :wind_dir_degrees, :wind_speed_kph, :wind_speed_kts,
|
10
|
+
:wind_gust_kph, :wind_gust_kts, :feels_like_c, :pressure_qnh_hpa, :rainfall_mm]
|
11
|
+
has_attribute :period, :on_elements => :rainfall_mm
|
12
|
+
|
13
|
+
observed_temperature :temp_c
|
14
|
+
value_plus_unit_readers :dp_c, :rh, :wind_speed_kph, :wind_speed_kts, :wind_gust_kph, :wind_gust_kts, :feels_like_c, :rainfall_mm, :pressure_qnh_hpa
|
15
|
+
|
16
|
+
def wind_dir_and_speed
|
17
|
+
wind_dir_compass || wind_speed_kph ? "#{wind_dir_compass} #{wind_speed_kph}" : nil
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class DailyObservation < Weatherzone::Resource
|
2
|
+
include Weatherzone::Helpers::Units
|
3
|
+
|
4
|
+
has_elements :day_name, :date, :temp_min_c, :temp_max_c, :rainfall_mm
|
5
|
+
has_attribute :units, :on_elements => [:temp_min_c, :temp_max_c, :rainfall_mm]
|
6
|
+
has_attribute :period, :on_elements => :rainfall_mm
|
7
|
+
|
8
|
+
temperature :temp_min_c, :temp_max_c
|
9
|
+
value_plus_unit_readers :rainfall_mm
|
10
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class Forecast < Weatherzone::Resource
|
2
|
+
|
3
|
+
include Weatherzone::Helpers::Units
|
4
|
+
|
5
|
+
attributes :day
|
6
|
+
|
7
|
+
has_elements :day_name, :date, :temp_min_c, :temp_max_c, :prob_precip, :icon,
|
8
|
+
:rain_range_text, :frost_risk_text, :uv, :first_light, :sunrise, :sunset, :last_light,
|
9
|
+
:moonrise, :moonset, :moon_phase
|
10
|
+
|
11
|
+
has_attribute :units, :on_elements => [:temp_min_c, :temp_max_c, :prob_precip]
|
12
|
+
has_attribute :index, :on_elements => :uv
|
13
|
+
has_attribute :filename, :on_elements => :icon
|
14
|
+
has_attribute :phase_num, :on_elements => :moon_phase
|
15
|
+
has_attribute :phase_text, :on_elements => :moon_phase
|
16
|
+
has_attribute :image_name, :on_elements => :moon_phase
|
17
|
+
has_attribute :tz, :on_elements => [:first_light, :last_light, :sunset, :sunrise, :moonset, :moonrise]
|
18
|
+
|
19
|
+
elements :point_forecast, :as => :point_forecasts, :class => PointForecast
|
20
|
+
|
21
|
+
forecast_temperature :temp_min_c, :temp_max_c
|
22
|
+
|
23
|
+
def icon_name
|
24
|
+
icon_filename.split(".").first
|
25
|
+
end
|
26
|
+
|
27
|
+
def abbr_day_name
|
28
|
+
self.day_name[0..2]
|
29
|
+
end
|
30
|
+
|
31
|
+
def date
|
32
|
+
Date.parse(@date)
|
33
|
+
end
|
34
|
+
|
35
|
+
def chance_of_rain
|
36
|
+
"#{self.prob_precip}#{self.prob_precip_units}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def min_rain
|
40
|
+
self.rain_range_text.split("-")[0].to_i if rain_range_text
|
41
|
+
end
|
42
|
+
|
43
|
+
def max_rain
|
44
|
+
self.rain_range_text.split("-")[1].to_i if rain_range_text
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
class HistoricalObservation < Weatherzone::Resource
|
2
|
+
|
3
|
+
include Weatherzone::Helpers::Units
|
4
|
+
|
5
|
+
has_elements :obs_time_utc, :obs_time_local, :temp_c, :dp_c, :rh,
|
6
|
+
:wind_dir_degrees, :wind_dir_compass, :wind_speed_kph, :wind_speed_kts,
|
7
|
+
:wind_gust_kph, :wind_gust_kts, :feels_like_c, :rainfall_mm, :pressure_qnh_hpa
|
8
|
+
has_attribute :units, :on_elements => [:temp_c, :dp_c, :rh, :wind_dir_degrees, :wind_speed_kph,
|
9
|
+
:wind_speed_kts, :wind_gust_kph, :wind_gust_kts, :feels_like_c, :rainfall_mm, :pressure_qnh_hpa, :rainfall_mm]
|
10
|
+
has_attribute :period, :on_elements => :rainfall_mm
|
11
|
+
|
12
|
+
temperature :temp_c
|
13
|
+
|
14
|
+
WIND_SPEED_RANGE = {
|
15
|
+
(0..19) => "calm",
|
16
|
+
(20..30) => "moderate",
|
17
|
+
(31..39) => "fresh",
|
18
|
+
(40..61) => "strong",
|
19
|
+
(62..87) => "gale",
|
20
|
+
(88..1.0/0) => "storm"
|
21
|
+
}
|
22
|
+
|
23
|
+
WIND_SPEED_RANGE.instance_eval do
|
24
|
+
def find_by_speed(speed)
|
25
|
+
self[keys.find { |range| range.include? speed.to_i }] rescue nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def obs_time_local
|
30
|
+
Time.parse(@obs_time_local)
|
31
|
+
end
|
32
|
+
|
33
|
+
def is_on_the_half_hour?
|
34
|
+
obs_time_local.change(:min => 0) == obs_time_local || obs_time_local.change(:min => 30) == obs_time_local
|
35
|
+
end
|
36
|
+
|
37
|
+
def is_on_the_hour?
|
38
|
+
obs_time_local.change(:min => 0) == obs_time_local
|
39
|
+
end
|
40
|
+
|
41
|
+
def wind_speed
|
42
|
+
WIND_SPEED_RANGE.find_by_speed(wind_speed_kph)
|
43
|
+
end
|
44
|
+
|
45
|
+
def rainfall_mm
|
46
|
+
@rainfall_mm || "0"
|
47
|
+
end
|
48
|
+
|
49
|
+
def hash
|
50
|
+
obs_time_local.hash
|
51
|
+
end
|
52
|
+
|
53
|
+
def eql?(other)
|
54
|
+
self.obs_time_local == other.obs_time_local
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
class Location < Weatherzone::Resource
|
2
|
+
attributes :type, :code, :name, :state
|
3
|
+
|
4
|
+
has_elements :lat, :long, :elevation
|
5
|
+
has_attribute :units, :on_elements => [:lat, :long, :elevation]
|
6
|
+
|
7
|
+
elements :forecast, :as => :forecasts, :class => Forecast
|
8
|
+
elements :conditions, :as => :conditions, :class => Conditions
|
9
|
+
elements :district_forecast, :as => :district_forecasts, :class => DistrictForecast
|
10
|
+
elements :state_forecast, :as => :state_forecasts, :class => StateForecast
|
11
|
+
elements :marine_forecast, :as => :marine_forecasts, :class => MarineForecast
|
12
|
+
elements :surf_report, :as => :surf_reports, :class => SurfReport
|
13
|
+
elements :snow_report, :as => :snow_reports, :class => SnowReport
|
14
|
+
elements :historical_observation, :as => :historical_observations, :class => HistoricalObservation
|
15
|
+
elements :daily_observations, :as => :daily_observations, :class => DailyObservation
|
16
|
+
elements :climate_period, :as => :climate_periods, :class => ClimatePeriod
|
17
|
+
elements :warning, :as => :warnings, :class => Warning
|
18
|
+
elements :almanac, :as => :almanacs, :class => Almanac
|
19
|
+
elements :tide, :as => :tides, :class => Tide
|
20
|
+
elements :buoy_obs, :as => :buoy_observations, :class => BuoyObservation
|
21
|
+
|
22
|
+
elements :image, :as => :synoptic_charts, :with => {:type => "Synoptic chart"}, :class => Image
|
23
|
+
|
24
|
+
element :link, :value => :url, :as => :radar_animator, :with => {:type => "radar animator"}
|
25
|
+
element :link, :value => :url, :as => :radar_still, :with => {:type => "radar still"}
|
26
|
+
element :link, :value => :width, :as => :radar_still_width, :with => {:type => "radar still"}
|
27
|
+
element :link, :value => :height, :as => :radar_still_height, :with => {:type => "radar still"}
|
28
|
+
|
29
|
+
element :link, :value => :url, :as => :satellite_animator, :with => {:type => "satellite animator"}
|
30
|
+
element :link, :value => :url, :as => :satellite_still, :with => {:type => "satellite still"}
|
31
|
+
|
32
|
+
# override base ruby Object#type
|
33
|
+
attr_reader :type
|
34
|
+
|
35
|
+
def id
|
36
|
+
code
|
37
|
+
end
|
38
|
+
|
39
|
+
def current_forecast
|
40
|
+
@current_forecast ||= forecasts.first
|
41
|
+
end
|
42
|
+
|
43
|
+
def current_conditions
|
44
|
+
@current_conditions ||= conditions.first
|
45
|
+
end
|
46
|
+
|
47
|
+
def current_district_forecast
|
48
|
+
@current_district_forecast ||= district_forecasts.first
|
49
|
+
end
|
50
|
+
|
51
|
+
def current_district_forecast_precis
|
52
|
+
current_district_forecast ? current_district_forecast.precis : "District forecast unavailable"
|
53
|
+
end
|
54
|
+
|
55
|
+
def current_state_forecast
|
56
|
+
@current_state_forecast ||= state_forecasts.first
|
57
|
+
end
|
58
|
+
|
59
|
+
def current_state_forecast_precis
|
60
|
+
current_state_forecast ? current_state_forecast.precis : "State forecast unavailable"
|
61
|
+
end
|
62
|
+
|
63
|
+
def current_synoptic_chart
|
64
|
+
synoptic_chart.first
|
65
|
+
end
|
66
|
+
|
67
|
+
def current_synoptic_chart_text
|
68
|
+
current_synoptic_chart ? current_synoptic_chart.text : "Synoptic chart unavailable"
|
69
|
+
end
|
70
|
+
|
71
|
+
def current_marine_forecast
|
72
|
+
@marine_forecast ||= marine_forecasts.first
|
73
|
+
end
|
74
|
+
|
75
|
+
def historical_observations_shifted_to_nearest_half_hour
|
76
|
+
obs_to_shift = historical_observations.uniq.reverse
|
77
|
+
historical_observations.each do |ho|
|
78
|
+
break if ho.is_on_the_half_hour?
|
79
|
+
obs_to_shift.shift
|
80
|
+
end
|
81
|
+
obs_to_shift
|
82
|
+
end
|
83
|
+
|
84
|
+
def hourly_observations
|
85
|
+
historical_observations.uniq.reverse.select { |ho| ho.is_on_the_hour? }
|
86
|
+
end
|
87
|
+
|
88
|
+
def position
|
89
|
+
"(#{self.lat}°S, #{self.long}°E, #{self.elevation}m AMSL)"
|
90
|
+
end
|
91
|
+
|
92
|
+
def url_slug
|
93
|
+
self.name.parameterize
|
94
|
+
end
|
95
|
+
|
96
|
+
def <=>(other)
|
97
|
+
self.name <=> other.name
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|