weatherzone 0.5.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|