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.
Files changed (79) hide show
  1. data/History.txt +6 -0
  2. data/Manifest.txt +51 -0
  3. data/README.txt +30 -0
  4. data/Rakefile +7 -0
  5. data/bin/weatherzone +0 -0
  6. data/lib/ext/class.rb +175 -0
  7. data/lib/ext/object.rb +74 -0
  8. data/lib/tzinfo/definitions/Australia/CDT.rb +13 -0
  9. data/lib/tzinfo/definitions/Australia/CST.rb +13 -0
  10. data/lib/tzinfo/definitions/Australia/EDT.rb +13 -0
  11. data/lib/tzinfo/definitions/Australia/EST.rb +13 -0
  12. data/lib/tzinfo/definitions/Australia/WDT.rb +13 -0
  13. data/lib/tzinfo/definitions/Australia/WST.rb +13 -0
  14. data/lib/vendor/openuri_memcached/History.txt +18 -0
  15. data/lib/vendor/openuri_memcached/License.txt +20 -0
  16. data/lib/vendor/openuri_memcached/README.markdown +48 -0
  17. data/lib/vendor/openuri_memcached/lib/openuri/common.rb +117 -0
  18. data/lib/vendor/openuri_memcached/lib/openuri/memcached.rb +36 -0
  19. data/lib/vendor/openuri_memcached/lib/openuri/rails-cache.rb +21 -0
  20. data/lib/vendor/openuri_memcached/lib/openuri_memcached.rb +1 -0
  21. data/lib/weatherzone.rb +39 -0
  22. data/lib/weatherzone/connection.rb +85 -0
  23. data/lib/weatherzone/finder.rb +129 -0
  24. data/lib/weatherzone/helpers/almanac_element.rb +28 -0
  25. data/lib/weatherzone/helpers/date_parser.rb +33 -0
  26. data/lib/weatherzone/helpers/units.rb +76 -0
  27. data/lib/weatherzone/resource.rb +46 -0
  28. data/lib/weatherzone/resources/almanac.rb +18 -0
  29. data/lib/weatherzone/resources/almanac_period.rb +51 -0
  30. data/lib/weatherzone/resources/climate_period.rb +8 -0
  31. data/lib/weatherzone/resources/conditions.rb +19 -0
  32. data/lib/weatherzone/resources/country.rb +4 -0
  33. data/lib/weatherzone/resources/daily_observation.rb +10 -0
  34. data/lib/weatherzone/resources/district_forecast.rb +5 -0
  35. data/lib/weatherzone/resources/forecast.rb +47 -0
  36. data/lib/weatherzone/resources/historical_observation.rb +57 -0
  37. data/lib/weatherzone/resources/image.rb +9 -0
  38. data/lib/weatherzone/resources/lift.rb +3 -0
  39. data/lib/weatherzone/resources/location.rb +100 -0
  40. data/lib/weatherzone/resources/marine_forecast.rb +9 -0
  41. data/lib/weatherzone/resources/marine_summary.rb +8 -0
  42. data/lib/weatherzone/resources/moon_phase.rb +23 -0
  43. data/lib/weatherzone/resources/news_item.rb +18 -0
  44. data/lib/weatherzone/resources/point_forecast.rb +40 -0
  45. data/lib/weatherzone/resources/snow_report.rb +5 -0
  46. data/lib/weatherzone/resources/state_forecast.rb +4 -0
  47. data/lib/weatherzone/resources/surf_report.rb +5 -0
  48. data/lib/weatherzone/resources/tide.rb +9 -0
  49. data/lib/weatherzone/resources/warning.rb +21 -0
  50. data/lib/weatherzone/resources/weather.rb +14 -0
  51. data/test/test_almanac.rb +25 -0
  52. data/test/test_almanac_period.rb +33 -0
  53. data/test/test_buoy_observation.rb +24 -0
  54. data/test/test_climate_period.rb +29 -0
  55. data/test/test_conditions.rb +32 -0
  56. data/test/test_connection.rb +28 -0
  57. data/test/test_country.rb +29 -0
  58. data/test/test_daily_observation.rb +29 -0
  59. data/test/test_district_forecast.rb +23 -0
  60. data/test/test_farenheit_conversion_factor.rb +48 -0
  61. data/test/test_finder.rb +148 -0
  62. data/test/test_forecast.rb +30 -0
  63. data/test/test_helper.rb +38 -0
  64. data/test/test_historical_observation.rb +32 -0
  65. data/test/test_image.rb +23 -0
  66. data/test/test_location.rb +70 -0
  67. data/test/test_marine_forecast.rb +27 -0
  68. data/test/test_marine_summary.rb +24 -0
  69. data/test/test_moon_phase.rb +33 -0
  70. data/test/test_news_item.rb +22 -0
  71. data/test/test_point_forecast.rb +24 -0
  72. data/test/test_snow_report.rb +27 -0
  73. data/test/test_state_forecast.rb +23 -0
  74. data/test/test_surf_report.rb +22 -0
  75. data/test/test_tide.rb +23 -0
  76. data/test/test_value_and_unit_helpers.rb +45 -0
  77. data/test/test_warning.rb +23 -0
  78. data/test/test_weather.rb +22 -0
  79. 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,4 @@
1
+ class Country < Weatherzone::Resource
2
+ attributes :code, :name
3
+ elements :location, :as => :locations, :class => Location
4
+ 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,5 @@
1
+ class DistrictForecast < Weatherzone::Resource
2
+ attributes :period
3
+ has_elements :period_name, :precis, :icon
4
+ has_attribute :filename, :on_elements => :icon
5
+ 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,9 @@
1
+ class Image < Weatherzone::Resource
2
+ include Weatherzone::Helpers::DateParser
3
+ has_elements :issue_day_name, :issue_time_local, :valid_time, :text, :url
4
+ interpret_as_time :valid_time, :issue_time_local
5
+
6
+ def forecast_date
7
+ valid_time.to_date
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ class Lift < Weatherzone::Resource
2
+ attributes :time, :tz, :name, :status
3
+ 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}&deg;S, #{self.long}&deg;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