weatherzone 0.5.8

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