barometer 0.7.3 → 0.8.0

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 (138) hide show
  1. data/.gitignore +1 -0
  2. data/.travis.yml +7 -0
  3. data/LICENSE +1 -1
  4. data/{README.rdoc → README.md} +124 -110
  5. data/Rakefile +1 -21
  6. data/TODO +8 -9
  7. data/barometer.gemspec +20 -19
  8. data/bin/barometer +36 -83
  9. data/lib/barometer.rb +13 -11
  10. data/lib/barometer/base.rb +10 -10
  11. data/lib/barometer/data.rb +1 -1
  12. data/lib/barometer/data/distance.rb +25 -25
  13. data/lib/barometer/data/geo.rb +9 -9
  14. data/lib/barometer/data/local_datetime.rb +24 -20
  15. data/lib/barometer/data/local_time.rb +13 -13
  16. data/lib/barometer/data/location.rb +6 -6
  17. data/lib/barometer/data/pressure.rb +24 -24
  18. data/lib/barometer/data/speed.rb +28 -28
  19. data/lib/barometer/data/sun.rb +7 -7
  20. data/lib/barometer/data/temperature.rb +29 -29
  21. data/lib/barometer/data/units.rb +9 -9
  22. data/lib/barometer/data/zone.rb +19 -19
  23. data/lib/barometer/formats.rb +1 -1
  24. data/lib/barometer/formats/coordinates.rb +7 -7
  25. data/lib/barometer/formats/format.rb +6 -6
  26. data/lib/barometer/formats/geocode.rb +5 -5
  27. data/lib/barometer/formats/icao.rb +6 -6
  28. data/lib/barometer/formats/postalcode.rb +3 -3
  29. data/lib/barometer/formats/short_zipcode.rb +2 -2
  30. data/lib/barometer/formats/weather_id.rb +10 -10
  31. data/lib/barometer/formats/woe_id.rb +20 -20
  32. data/lib/barometer/formats/zipcode.rb +3 -3
  33. data/lib/barometer/key_file_parser.rb +20 -0
  34. data/lib/barometer/measurements/measurement.rb +32 -32
  35. data/lib/barometer/measurements/result.rb +39 -39
  36. data/lib/barometer/measurements/result_array.rb +12 -12
  37. data/lib/barometer/query.rb +15 -15
  38. data/lib/barometer/services.rb +3 -3
  39. data/lib/barometer/translations/icao_country_codes.yml +20 -20
  40. data/lib/barometer/translations/weather_country_codes.yml +1 -1
  41. data/lib/barometer/translations/zone_codes.yml +2 -2
  42. data/lib/barometer/version.rb +3 -0
  43. data/lib/barometer/weather.rb +27 -27
  44. data/lib/barometer/weather_services/noaa.rb +314 -3
  45. data/lib/barometer/weather_services/service.rb +32 -30
  46. data/lib/barometer/weather_services/weather_bug.rb +35 -33
  47. data/lib/barometer/weather_services/wunderground.rb +31 -29
  48. data/lib/barometer/weather_services/yahoo.rb +36 -35
  49. data/lib/barometer/web_services/geocode.rb +5 -7
  50. data/lib/barometer/web_services/noaa_station_id.rb +53 -0
  51. data/lib/barometer/web_services/placemaker.rb +11 -13
  52. data/lib/barometer/web_services/timezone.rb +5 -7
  53. data/lib/barometer/web_services/weather_id.rb +4 -6
  54. data/lib/barometer/web_services/web_service.rb +4 -4
  55. data/spec/barometer_spec.rb +25 -27
  56. data/spec/cassettes/Barometer.json +1 -0
  57. data/spec/cassettes/Query.json +1 -0
  58. data/spec/cassettes/Query_Format_Coordinates.json +1 -0
  59. data/spec/cassettes/Query_Format_Geocode.json +1 -0
  60. data/spec/cassettes/Query_Format_WeatherID.json +1 -0
  61. data/spec/cassettes/Query_Format_WoeID.json +1 -0
  62. data/spec/cassettes/WeatherService.json +1 -0
  63. data/spec/cassettes/WeatherService_Noaa.json +1 -0
  64. data/spec/cassettes/WeatherService_WeatherBug.json +1 -0
  65. data/spec/cassettes/WeatherService_Wunderground.json +1 -0
  66. data/spec/cassettes/WeatherService_Yahoo.json +1 -0
  67. data/spec/cassettes/WebService_Geocode.json +1 -0
  68. data/spec/cassettes/WebService_NoaaStation.json +1 -0
  69. data/spec/data/distance_spec.rb +60 -60
  70. data/spec/data/geo_spec.rb +23 -23
  71. data/spec/data/local_datetime_spec.rb +44 -44
  72. data/spec/data/local_time_spec.rb +47 -47
  73. data/spec/data/location_spec.rb +16 -16
  74. data/spec/data/pressure_spec.rb +61 -61
  75. data/spec/data/speed_spec.rb +69 -69
  76. data/spec/data/sun_spec.rb +25 -25
  77. data/spec/data/temperature_spec.rb +68 -68
  78. data/spec/data/units_spec.rb +21 -21
  79. data/spec/data/zone_spec.rb +35 -35
  80. data/spec/formats/coordinates_spec.rb +27 -27
  81. data/spec/formats/format_spec.rb +17 -25
  82. data/spec/formats/geocode_spec.rb +23 -31
  83. data/spec/formats/icao_spec.rb +26 -32
  84. data/spec/formats/postalcode_spec.rb +22 -28
  85. data/spec/formats/short_zipcode_spec.rb +20 -26
  86. data/spec/formats/weather_id_spec.rb +57 -67
  87. data/spec/formats/woe_id_spec.rb +59 -59
  88. data/spec/formats/zipcode_spec.rb +39 -47
  89. data/spec/key_file_parser_spec.rb +28 -0
  90. data/spec/measurements/measurement_spec.rb +79 -133
  91. data/spec/measurements/result_array_spec.rb +23 -38
  92. data/spec/measurements/result_spec.rb +100 -128
  93. data/spec/query_spec.rb +83 -100
  94. data/spec/spec_helper.rb +24 -6
  95. data/spec/weather_services/noaa_spec.rb +179 -0
  96. data/spec/weather_services/services_spec.rb +28 -36
  97. data/spec/weather_services/weather_bug_spec.rb +57 -77
  98. data/spec/weather_services/wunderground_spec.rb +36 -65
  99. data/spec/weather_services/yahoo_spec.rb +38 -60
  100. data/spec/weather_spec.rb +79 -79
  101. data/spec/web_services/geocode_spec.rb +7 -11
  102. data/spec/web_services/noaa_station_id_spec.rb +33 -0
  103. data/spec/web_services/placemaker_spec.rb +7 -12
  104. data/spec/web_services/web_services_spec.rb +3 -9
  105. metadata +214 -163
  106. data/VERSION.yml +0 -5
  107. data/lib/barometer/weather_services/google.rb +0 -142
  108. data/lib/barometer/weather_services/weather_dot_com.rb +0 -279
  109. data/spec/fakeweb_helper.rb +0 -179
  110. data/spec/fixtures/formats/weather_id/90210.xml +0 -7
  111. data/spec/fixtures/formats/weather_id/from_USGA0028.xml +0 -3
  112. data/spec/fixtures/formats/weather_id/ksfo.xml +0 -1
  113. data/spec/fixtures/formats/weather_id/manhattan.xml +0 -7
  114. data/spec/fixtures/formats/weather_id/new_york.xml +0 -1
  115. data/spec/fixtures/formats/weather_id/the_hills.xml +0 -1
  116. data/spec/fixtures/geocode/40_73_v3.json +0 -497
  117. data/spec/fixtures/geocode/90210_v3.json +0 -63
  118. data/spec/fixtures/geocode/T5B4M9_v3.json +0 -68
  119. data/spec/fixtures/geocode/atlanta_v3.json +0 -58
  120. data/spec/fixtures/geocode/calgary_ab_v3.json +0 -58
  121. data/spec/fixtures/geocode/ksfo_v3.json +0 -73
  122. data/spec/fixtures/geocode/newyork_ny_v3.json +0 -58
  123. data/spec/fixtures/services/google/calgary_ab.xml +0 -1
  124. data/spec/fixtures/services/placemaker/T5B4M9.xml +0 -65
  125. data/spec/fixtures/services/placemaker/atlanta.xml +0 -65
  126. data/spec/fixtures/services/placemaker/coords.xml +0 -65
  127. data/spec/fixtures/services/placemaker/ksfo.xml +0 -65
  128. data/spec/fixtures/services/placemaker/new_york.xml +0 -65
  129. data/spec/fixtures/services/placemaker/the_hills.xml +0 -65
  130. data/spec/fixtures/services/placemaker/w615702.xml +0 -47
  131. data/spec/fixtures/services/weather_bug/90210_current.xml +0 -93
  132. data/spec/fixtures/services/weather_bug/90210_forecast.xml +0 -76
  133. data/spec/fixtures/services/weather_dot_com/90210.xml +0 -1
  134. data/spec/fixtures/services/wunderground/current_calgary_ab.xml +0 -9
  135. data/spec/fixtures/services/wunderground/forecast_calgary_ab.xml +0 -13
  136. data/spec/fixtures/services/yahoo/90210.xml +0 -3
  137. data/spec/weather_services/google_spec.rb +0 -181
  138. data/spec/weather_services/weather_dot_com_spec.rb +0 -224
@@ -1,15 +1,15 @@
1
1
  module Barometer
2
2
  class Data::Units
3
3
  include Comparable
4
-
4
+
5
5
  attr_accessor :metric
6
-
6
+
7
7
  def initialize(metric=true); @metric = metric; end
8
-
8
+
9
9
  #
10
10
  # HELPERS
11
11
  #
12
-
12
+
13
13
  def metric?; @metric; end
14
14
  def metric!; @metric=true; end
15
15
  def imperial!; @metric=false; end
@@ -18,10 +18,10 @@ module Barometer
18
18
  #
19
19
  def <<(value)
20
20
  return unless value
21
-
21
+
22
22
  # these values can be treated like 'nil'
23
23
  nil_values = ["NA", "N/A", ""]
24
-
24
+
25
25
  begin
26
26
  if value.is_a?(Array)
27
27
  value_m = value[0].to_f if (value[0] && !nil_values.include?(value[0]))
@@ -35,15 +35,15 @@ module Barometer
35
35
  rescue
36
36
  # do nothing
37
37
  end
38
-
38
+
39
39
  self.metric? ? self.metric_default = value_m || value_b :
40
40
  self.imperial_default = value_i || value_b
41
41
  end
42
-
42
+
43
43
  # stubs
44
44
  #
45
45
  def metric_default=(value); raise NotImplementedError; end
46
46
  def imperial_default=(value); raise NotImplementedError; end
47
47
 
48
48
  end
49
- end
49
+ end
@@ -4,19 +4,19 @@ require 'tzinfo'
4
4
  module Barometer
5
5
  #
6
6
  # A simple Zone class
7
- #
7
+ #
8
8
  # Used for building and converting timezone aware date and times
9
9
  # Really, these are just wrappers for TZInfo conversions plus
10
10
  # some extras.
11
11
  #
12
12
  class Data::Zone
13
-
13
+
14
14
  @@zone_codes_file = File.expand_path(
15
15
  File.join(File.dirname(__FILE__), '..', 'translations', 'zone_codes.yml'))
16
16
  @@zone_codes = nil
17
17
 
18
18
  attr_accessor :zone_full, :zone_code, :zone_offset, :tz
19
-
19
+
20
20
  def initialize(zone)
21
21
  if Data::Zone.is_zone_full?(zone)
22
22
  @zone_full = zone
@@ -29,22 +29,22 @@ module Barometer
29
29
  raise(ArgumentError, "invalid time zone")
30
30
  end
31
31
  end
32
-
32
+
33
33
  def current
34
34
  @zone_full || @zone_offset || @zone_code
35
35
  end
36
-
36
+
37
37
  # what is the Timezone Short Code for the current timezone
38
38
  def code
39
39
  return @zone_code if @zone_code
40
40
  return nil unless @tz
41
41
  @tz.period_for_utc(Time.now.utc).zone_identifier.to_s
42
42
  end
43
-
43
+
44
44
  def full
45
45
  @zone_full || nil
46
46
  end
47
-
47
+
48
48
  def offset
49
49
  if @zone_offset
50
50
  @zone_offset.to_f * 60 * 60
@@ -53,13 +53,13 @@ module Barometer
53
53
  elsif @zone_full
54
54
  end
55
55
  end
56
-
56
+
57
57
  # is the current timezone in daylights savings mode?
58
58
  def dst?
59
59
  return nil unless @tz
60
60
  @tz.period_for_utc(Time.now.utc).dst?
61
61
  end
62
-
62
+
63
63
  # return Time.now.utc for the set timezone
64
64
  def now(convert=false)
65
65
  if @zone_full
@@ -69,13 +69,13 @@ module Barometer
69
69
  end
70
70
  convert ? Data::LocalTime.parse(now) : now
71
71
  end
72
-
72
+
73
73
  # return Date.today for the set timezone
74
74
  def today
75
75
  now = self.now
76
76
  Date.new(now.year, now.month, now.day)
77
77
  end
78
-
78
+
79
79
  def local_to_utc(local_time)
80
80
  if @zone_full
81
81
  @tz.local_to_utc(local_time)
@@ -85,7 +85,7 @@ module Barometer
85
85
  local_time.hour,local_time.min,local_time.sec)
86
86
  end
87
87
  end
88
-
88
+
89
89
  def utc_to_local(utc_time)
90
90
  if @zone_full
91
91
  @tz.utc_to_local(utc_time)
@@ -93,22 +93,22 @@ module Barometer
93
93
  utc_time + self.offset
94
94
  end
95
95
  end
96
-
96
+
97
97
  #
98
98
  # Class Methods
99
99
  #
100
-
100
+
101
101
  def self.is_zone_code?(zone)
102
102
  return false unless (zone && zone.is_a?(String))
103
103
  _load_zone_codes unless @@zone_codes
104
104
  Time.zone_offset(zone) || (@@zone_codes && @@zone_codes.has_key?(zone))
105
105
  end
106
-
106
+
107
107
  def self.is_zone_full?(zone)
108
108
  return false unless (zone && zone.is_a?(String))
109
109
  zone.match(/[A-Za-z]+\/[A-Za-z]+/) ? true : false
110
110
  end
111
-
111
+
112
112
  def self.is_zone_offset?(zone)
113
113
  return false unless (zone && (zone.is_a?(Fixnum) || zone.is_a?(Float)))
114
114
  zone.to_f.abs <= 14
@@ -131,11 +131,11 @@ module Barometer
131
131
  end
132
132
  offset
133
133
  end
134
-
134
+
135
135
  def self._load_zone_codes
136
136
  $:.unshift(File.dirname(__FILE__))
137
137
  @@zone_codes ||= YAML.load_file(@@zone_codes_file)
138
138
  end
139
-
139
+
140
140
  end
141
- end
141
+ end
@@ -10,4 +10,4 @@ require 'formats/weather_id'
10
10
  require 'formats/coordinates'
11
11
  require 'formats/icao'
12
12
  require 'formats/geocode'
13
- require 'formats/woe_id'
13
+ require 'formats/woe_id'
@@ -8,20 +8,20 @@ module Barometer
8
8
  # :coordinates and how to convert to :coordinates.
9
9
  #
10
10
  class Query::Format::Coordinates < Query::Format
11
-
11
+
12
12
  def self.format; :coordinates; end
13
13
  def self.regex; /^[-]?[0-9\.]+[,]{1}\s?[-]?[0-9\.]+$/; end
14
14
  def self.convertable_formats
15
15
  [:short_zipcode, :zipcode, :postalcode, :weather_id, :coordinates, :icao, :geocode, :woe_id]
16
16
  end
17
-
17
+
18
18
  # convert to this format, X -> :coordinates
19
19
  #
20
20
  def self.to(original_query)
21
21
  raise ArgumentError unless is_a_query?(original_query)
22
22
  return nil unless converts?(original_query)
23
23
  converted_query = Barometer::Query.new
24
-
24
+
25
25
  # pre-convert
26
26
  #
27
27
  pre_query = nil
@@ -33,7 +33,7 @@ module Barometer
33
33
  elsif original_query.format == :woe_id
34
34
  pre_query = Query::Format::WoeID.reverse(original_query)
35
35
  end
36
-
36
+
37
37
  # convert & adjust
38
38
  #
39
39
  converted_query = Query::Format::Geocode.geocode(pre_query || original_query)
@@ -42,16 +42,16 @@ module Barometer
42
42
 
43
43
  converted_query
44
44
  end
45
-
45
+
46
46
  def self.parse_latitude(query)
47
47
  coordinates = query.to_s.split(',')
48
48
  coordinates ? coordinates[0] : nil
49
49
  end
50
-
50
+
51
51
  def self.parse_longitude(query)
52
52
  coordinates = query.to_s.split(',')
53
53
  coordinates ? coordinates[1] : nil
54
54
  end
55
55
 
56
56
  end
57
- end
57
+ end
@@ -18,14 +18,14 @@ module Barometer
18
18
  #
19
19
  def self.regex; raise NotImplementedError; end
20
20
  def self.format; raise NotImplementedError; end
21
-
21
+
22
22
  # defaults
23
23
  #
24
24
  def self.to(query=nil,country=nil); nil; end
25
25
  def self.country_code(query=nil); nil; end
26
26
  def self.convertable_formats; []; end
27
27
  def self.convert_query(text); text; end
28
-
28
+
29
29
  # is the query of this format?
30
30
  #
31
31
  def self.is?(query=nil)
@@ -46,9 +46,9 @@ module Barometer
46
46
  return false unless object
47
47
  object.is_a?(Barometer::Query)
48
48
  end
49
-
49
+
50
50
  private
51
-
51
+
52
52
  # fix the country code
53
53
  #
54
54
  # weather.com uses non-standard two letter country codes that
@@ -59,6 +59,6 @@ module Barometer
59
59
  @@fixes ||= YAML.load_file(@@fixes_file)
60
60
  @@fixes[country_code.upcase.to_s] || country_code
61
61
  end
62
-
62
+
63
63
  end
64
- end
64
+ end
@@ -23,10 +23,10 @@ module Barometer
23
23
  unless converts?(original_query)
24
24
  return (original_query.format == format ? original_query.dup : nil)
25
25
  end
26
-
26
+
27
27
  unless converted_query = original_query.get_conversion(format)
28
28
  converted_query = Barometer::Query.new
29
-
29
+
30
30
  converted_query = case original_query.format
31
31
  when :weather_id
32
32
  Query::Format::WeatherID.reverse(original_query)
@@ -35,7 +35,7 @@ module Barometer
35
35
  else
36
36
  geocode(original_query)
37
37
  end
38
-
38
+
39
39
  original_query.post_conversion(converted_query) if converted_query
40
40
  end
41
41
  converted_query
@@ -45,7 +45,7 @@ module Barometer
45
45
  #
46
46
  def self.geocode(original_query)
47
47
  raise ArgumentError unless is_a_query?(original_query)
48
-
48
+
49
49
  converted_query = Barometer::Query.new
50
50
  converted_query.geo = Barometer::WebService::Geocode.fetch(original_query)
51
51
  if converted_query.geo
@@ -57,4 +57,4 @@ module Barometer
57
57
  end
58
58
 
59
59
  end
60
- end
60
+ end
@@ -2,26 +2,26 @@ module Barometer
2
2
  #
3
3
  # Format: ICAO (International Civil Aviation Organization)
4
4
  #
5
- # eg. KLAX (Los Angeles Airport)
5
+ # eg. KLAX (Los Angeles Airport)
6
6
  #
7
7
  # This class is used to determine if a query is a
8
8
  # :icao and what the country_code is.
9
9
  #
10
10
  class Query::Format::Icao < Query::Format
11
-
11
+
12
12
  @@codes_file = File.expand_path(
13
13
  File.join(File.dirname(__FILE__), '..', 'translations', 'icao_country_codes.yml'))
14
14
  @@codes = nil
15
15
 
16
16
  def self.format; :icao; end
17
-
17
+
18
18
  # call any 3-4 letter query, :icao ... obviously this will have a lot
19
19
  # of false positives. So far this isn't an issue as all weather services
20
20
  # that take :icao (which is just one, :wunderground) also take what
21
21
  # this would have been if it was not called :icao.
22
22
  #
23
23
  def self.regex; /^[A-Za-z]{3,4}$/; end
24
-
24
+
25
25
  # in some cases the first letter can designate the country
26
26
  #
27
27
  def self.country_code(query=nil)
@@ -32,6 +32,6 @@ module Barometer
32
32
  @@codes['one_letter'][query[0..0].upcase.to_s] ||
33
33
  @@codes['two_letter'][query[0..1].upcase.to_s] || nil
34
34
  end
35
-
35
+
36
36
  end
37
- end
37
+ end
@@ -8,7 +8,7 @@ module Barometer
8
8
  # :postalcode and what the country_code is.
9
9
  #
10
10
  class Query::Format::Postalcode < Query::Format
11
-
11
+
12
12
  def self.format; :postalcode; end
13
13
  def self.country_code(query=nil); "CA"; end
14
14
  def self.regex
@@ -17,6 +17,6 @@ module Barometer
17
17
  # [ ]?[0-9]{1}[ABCEGHJ-NPRSTV-Z]{1}[0-9]{1}$
18
18
  /^[A-Z]{1}[\d]{1}[A-Z]{1}[ ]?[\d]{1}[A-Z]{1}[\d]{1}$/
19
19
  end
20
-
20
+
21
21
  end
22
- end
22
+ end
@@ -8,10 +8,10 @@ module Barometer
8
8
  # :short_zipcode and what the country_code is.
9
9
  #
10
10
  class Query::Format::ShortZipcode < Query::Format
11
-
11
+
12
12
  def self.format; :short_zipcode; end
13
13
  def self.country_code(query=nil); "US"; end
14
14
  def self.regex; /(^[0-9]{5}$)/; end
15
15
 
16
16
  end
17
- end
17
+ end
@@ -9,19 +9,19 @@ module Barometer
9
9
  # and what the country_code is.
10
10
  #
11
11
  class Query::Format::WeatherID < Query::Format
12
-
12
+
13
13
  def self.format; :weather_id; end
14
14
  def self.regex; /(^[A-Za-z]{4}[0-9]{4}$)/; end
15
15
  def self.convertable_formats
16
16
  [:short_zipcode, :zipcode, :coordinates, :icao, :geocode]
17
17
  end
18
-
18
+
19
19
  # the first two letters of the :weather_id is the country_code
20
20
  #
21
21
  def self.country_code(query=nil)
22
22
  (query && query.size >= 2) ? _fix_country(query[0..1]) : nil
23
23
  end
24
-
24
+
25
25
  # convert to this format, X -> :weather_id
26
26
  #
27
27
  def self.to(original_query)
@@ -37,7 +37,7 @@ module Barometer
37
37
  converted_query.country_code = country_code(converted_query.q)
38
38
  converted_query
39
39
  end
40
-
40
+
41
41
  # reverse lookup, :weather_id -> (:geocode || :coordinates)
42
42
  #
43
43
  def self.reverse(original_query)
@@ -48,9 +48,9 @@ module Barometer
48
48
  converted_query.format = Query::Format::Geocode.format
49
49
  converted_query
50
50
  end
51
-
51
+
52
52
  private
53
-
53
+
54
54
  # :geocode -> :weather_id
55
55
  # search weather.com for the given query
56
56
  #
@@ -60,7 +60,7 @@ module Barometer
60
60
  response = WebService::WeatherID.fetch(query)
61
61
  _parse_weather_id(response)
62
62
  end
63
-
63
+
64
64
  # :weather_id -> :geocode
65
65
  # query yahoo with :weather_id and parse geo_data
66
66
  #
@@ -70,7 +70,7 @@ module Barometer
70
70
  response = WebService::WeatherID.reverse(query)
71
71
  _parse_geocode(response)
72
72
  end
73
-
73
+
74
74
  # match the first :weather_id (from search results)
75
75
  #
76
76
  def self._parse_weather_id(text)
@@ -78,7 +78,7 @@ module Barometer
78
78
  match = text.match(/loc id=[\\]?['|""]([0-9a-zA-Z]*)[\\]?['|""]/)
79
79
  match ? match[1] : nil
80
80
  end
81
-
81
+
82
82
  # parse the geo_data
83
83
  #
84
84
  def self._parse_geocode(text)
@@ -89,4 +89,4 @@ module Barometer
89
89
  end
90
90
 
91
91
  end
92
- end
92
+ end