buoy_data 0.2.0 → 1.0.0.beta.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.
- data/Rakefile +2 -0
- data/VERSION +1 -1
- data/buoy_data.gemspec +21 -7
- data/lib/buoy_data/buoy_list.rb +66 -0
- data/lib/buoy_data/{buoy.rb → buoy_reading.rb} +1 -1
- data/lib/buoy_data/noaa_buoy_forecast.rb +149 -0
- data/lib/buoy_data/noaa_buoy_list.rb +49 -0
- data/lib/buoy_data/{noaa_buoy.rb → noaa_buoy_observation.rb} +40 -70
- data/lib/buoy_data/noaa_buoy_reading.rb +69 -0
- data/lib/buoy_data.rb +6 -2
- data/spec/noaa_buoy_forecast_spec.rb +28 -0
- data/spec/noaa_buoy_list_spec.rb +19 -0
- data/spec/noaa_buoy_observation_spec.rb +57 -0
- metadata +49 -11
- data/spec/noaa_buoy_spec.rb +0 -28
data/Rakefile
CHANGED
@@ -12,6 +12,8 @@ begin
|
|
12
12
|
gem.authors = ["Adam Weller"]
|
13
13
|
gem.add_development_dependency 'rspec'
|
14
14
|
gem.add_dependency 'httparty'
|
15
|
+
gem.add_dependency 'json'
|
16
|
+
gem.add_dependency 'nokogiri'
|
15
17
|
gem.files.include 'lib/buoy_data/*.rb'
|
16
18
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
17
19
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
1.0.0.beta.0
|
data/buoy_data.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{buoy_data}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "1.0.0.beta.0"
|
9
9
|
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new("
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Adam Weller"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2011-03-20}
|
13
13
|
s.description = %q{The goal of this gem is to provide marine buoy data from a variety of sources}
|
14
14
|
s.email = %q{minch@trazzler.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -25,9 +25,15 @@ Gem::Specification.new do |s|
|
|
25
25
|
"VERSION",
|
26
26
|
"buoy_data.gemspec",
|
27
27
|
"lib/buoy_data.rb",
|
28
|
-
"lib/buoy_data/
|
29
|
-
"lib/buoy_data/
|
30
|
-
"
|
28
|
+
"lib/buoy_data/buoy_list.rb",
|
29
|
+
"lib/buoy_data/buoy_reading.rb",
|
30
|
+
"lib/buoy_data/noaa_buoy_forecast.rb",
|
31
|
+
"lib/buoy_data/noaa_buoy_list.rb",
|
32
|
+
"lib/buoy_data/noaa_buoy_observation.rb",
|
33
|
+
"lib/buoy_data/noaa_buoy_reading.rb",
|
34
|
+
"spec/noaa_buoy_forecast_spec.rb",
|
35
|
+
"spec/noaa_buoy_list_spec.rb",
|
36
|
+
"spec/noaa_buoy_observation_spec.rb",
|
31
37
|
"spec/spec_helper.rb"
|
32
38
|
]
|
33
39
|
s.homepage = %q{http://github.com/minch/buoy_data}
|
@@ -36,7 +42,9 @@ Gem::Specification.new do |s|
|
|
36
42
|
s.rubygems_version = %q{1.3.7}
|
37
43
|
s.summary = %q{Fetch marine buoy data from various sources}
|
38
44
|
s.test_files = [
|
39
|
-
"spec/
|
45
|
+
"spec/noaa_buoy_forecast_spec.rb",
|
46
|
+
"spec/noaa_buoy_list_spec.rb",
|
47
|
+
"spec/noaa_buoy_observation_spec.rb",
|
40
48
|
"spec/spec_helper.rb"
|
41
49
|
]
|
42
50
|
|
@@ -47,13 +55,19 @@ Gem::Specification.new do |s|
|
|
47
55
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
48
56
|
s.add_development_dependency(%q<rspec>, [">= 0"])
|
49
57
|
s.add_runtime_dependency(%q<httparty>, [">= 0"])
|
58
|
+
s.add_runtime_dependency(%q<json>, [">= 0"])
|
59
|
+
s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
|
50
60
|
else
|
51
61
|
s.add_dependency(%q<rspec>, [">= 0"])
|
52
62
|
s.add_dependency(%q<httparty>, [">= 0"])
|
63
|
+
s.add_dependency(%q<json>, [">= 0"])
|
64
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
53
65
|
end
|
54
66
|
else
|
55
67
|
s.add_dependency(%q<rspec>, [">= 0"])
|
56
68
|
s.add_dependency(%q<httparty>, [">= 0"])
|
69
|
+
s.add_dependency(%q<json>, [">= 0"])
|
70
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
57
71
|
end
|
58
72
|
end
|
59
73
|
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module BuoyData
|
2
|
+
require 'open-uri'
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
class BuoyList
|
6
|
+
def get
|
7
|
+
stats = {
|
8
|
+
:stations => [],
|
9
|
+
:errors => []
|
10
|
+
}
|
11
|
+
@doc = doc
|
12
|
+
@station_list = stations doc
|
13
|
+
|
14
|
+
@station_list.each do |s|
|
15
|
+
begin
|
16
|
+
h = scrape_station s
|
17
|
+
stats[:stations].push h
|
18
|
+
rescue => e
|
19
|
+
stats[:errors].push({ :url => s, :error => e })
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
stats
|
24
|
+
end
|
25
|
+
|
26
|
+
def url
|
27
|
+
end
|
28
|
+
|
29
|
+
def base_url
|
30
|
+
end
|
31
|
+
|
32
|
+
def doc
|
33
|
+
doc = Nokogiri::HTML(open(url))
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
def stations(doc)
|
38
|
+
end
|
39
|
+
|
40
|
+
def scrape_station(url)
|
41
|
+
end
|
42
|
+
|
43
|
+
def lat_lng_from(text)
|
44
|
+
text = text.sub(/ \(.*$/, '')
|
45
|
+
matches = /([0-9\.]+ ?[NESW]) ([0-9\.]+ ?[NESW])/.match(text)
|
46
|
+
|
47
|
+
matches && matches.size == 3 ? [ $1, $2 ] : []
|
48
|
+
end
|
49
|
+
|
50
|
+
def normal_lat(lat)
|
51
|
+
lat, dir = lat.split(/ /)
|
52
|
+
lat = lat.to_f
|
53
|
+
lat = -lat if dir == 'S'
|
54
|
+
|
55
|
+
lat
|
56
|
+
end
|
57
|
+
|
58
|
+
def normal_lng(lng)
|
59
|
+
lng, dir = lng.split(/ /)
|
60
|
+
lng = lng.to_f
|
61
|
+
lng = -lng if dir == 'W'
|
62
|
+
|
63
|
+
lng
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
module BuoyData
|
2
|
+
class NoaaBuoyForecast < NoaaBuoyReading
|
3
|
+
require 'json/add/core'
|
4
|
+
|
5
|
+
def get(raw = true)
|
6
|
+
response = super raw
|
7
|
+
return unless response
|
8
|
+
@response = response
|
9
|
+
|
10
|
+
@parsed_response = parse_response @response
|
11
|
+
end
|
12
|
+
|
13
|
+
# This pattern differs from the previous design but seems better
|
14
|
+
def to_json
|
15
|
+
response = @parsed_response
|
16
|
+
response = response.map{|row| bull_row_to_hash row}
|
17
|
+
response.to_json
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def bull_row_to_hash(row)
|
23
|
+
hash = {
|
24
|
+
:time => { :day => row[0][0], :hour => row[0][1] },
|
25
|
+
:total => { :hst => row[1][0], :n => row[1][1], :x => row[1][2] }
|
26
|
+
}
|
27
|
+
5.times do |index|
|
28
|
+
hash.store("separate_wave_#{index}".to_sym, separate_wave_hash(row[2..row.size-1]))
|
29
|
+
end
|
30
|
+
hash
|
31
|
+
end
|
32
|
+
|
33
|
+
def separate_wave_hash(array)
|
34
|
+
h = {
|
35
|
+
:wind => array[0],
|
36
|
+
:hs => array[1],
|
37
|
+
:tp => array[2],
|
38
|
+
:dir => array[3]
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def parse_response(response)
|
43
|
+
# Get all readings
|
44
|
+
response = response_to_array response
|
45
|
+
|
46
|
+
# Remove header and footer
|
47
|
+
response = remove_header_from response
|
48
|
+
response = remove_footer_from response
|
49
|
+
|
50
|
+
# Now really go through this gnarly bull format and make some sense of it
|
51
|
+
response = parse_bull_response response
|
52
|
+
|
53
|
+
response
|
54
|
+
end
|
55
|
+
|
56
|
+
def parse_bull_response(response)
|
57
|
+
parsed_response = []
|
58
|
+
|
59
|
+
#
|
60
|
+
# Split on pipes so we can get the swell breakdown
|
61
|
+
#
|
62
|
+
response = response.map{|row| row.split(/\|/)}
|
63
|
+
|
64
|
+
# The first column is always empty
|
65
|
+
response = response.map{|row| row[1..row.size-1]}
|
66
|
+
|
67
|
+
#
|
68
|
+
# Now we have eight columns
|
69
|
+
#
|
70
|
+
# 1: day and hour
|
71
|
+
# 2: Total Significant wave height and exclusions (Hst, n and x)
|
72
|
+
# 3-7: Up to 6 swell breakdowns (* Hs, Tp, dir)
|
73
|
+
#
|
74
|
+
# Where:
|
75
|
+
#
|
76
|
+
# Hst : Total significant wave height.
|
77
|
+
# n : Number of fields with Hs > 0.05 in 2-D spectrum.
|
78
|
+
# x : Number of fields with Hs > 0.15 not in table.
|
79
|
+
# Hs : Significant wave height of separate wave field.
|
80
|
+
# Tp : Peak period of separate wave field.
|
81
|
+
# dir : Mean direction of separate wave field.
|
82
|
+
# * : Wave generation due to local wind probable.
|
83
|
+
#
|
84
|
+
|
85
|
+
days_and_hours = response.map{|row| row.first.strip.split(/\s+/)}
|
86
|
+
|
87
|
+
#
|
88
|
+
# totals
|
89
|
+
#
|
90
|
+
totals = response.map do |row|
|
91
|
+
row = row[1].strip.split(/\s+/)
|
92
|
+
row = row.size == 3 ? row : row << ""
|
93
|
+
end
|
94
|
+
|
95
|
+
#
|
96
|
+
# up to 6 swells
|
97
|
+
#
|
98
|
+
separate_waves = response.map{|row| row[2..7].map{|col| parse_separate_wave(col)}}
|
99
|
+
|
100
|
+
# build the parsed_response
|
101
|
+
num = response.size-1
|
102
|
+
num.times do |index|
|
103
|
+
row = []
|
104
|
+
|
105
|
+
row.push days_and_hours[index]
|
106
|
+
row.push totals[index]
|
107
|
+
separate_waves[index].each do |sw|
|
108
|
+
row.push sw
|
109
|
+
end
|
110
|
+
|
111
|
+
parsed_response.push row
|
112
|
+
end
|
113
|
+
|
114
|
+
parsed_response
|
115
|
+
end
|
116
|
+
|
117
|
+
# Example: "* 1.3 5.3 298"
|
118
|
+
def parse_separate_wave(separate_wave)
|
119
|
+
# There's probably a slicker way but...
|
120
|
+
separate_wave = separate_wave.split(/\s+/)
|
121
|
+
|
122
|
+
# The first column, the wind probable '*', may or may not be present
|
123
|
+
# In either cases we have an empty string as the first field
|
124
|
+
separate_wave.size == 5 ? separate_wave.shift : separate_wave
|
125
|
+
|
126
|
+
separate_wave
|
127
|
+
end
|
128
|
+
|
129
|
+
def base_url(buoy_id = @buoy_id)
|
130
|
+
@buoy_id ||= buoy_id
|
131
|
+
|
132
|
+
# NOTE: The bull files will probably change per ocean/geo:
|
133
|
+
# E.g., there are two model runs for the northern atlantic:
|
134
|
+
#"http://polar.ncep.noaa.gov/waves/latest_run/nah.#{buoy_id}.bull"
|
135
|
+
|
136
|
+
"http://polar.ncep.noaa.gov/waves/latest_run/wna.#{buoy_id}.bull"
|
137
|
+
end
|
138
|
+
|
139
|
+
# The header is the first 7 lines
|
140
|
+
def remove_header_from(response)
|
141
|
+
response[7..response.size-1]
|
142
|
+
end
|
143
|
+
|
144
|
+
# The footer is the last 8 lines
|
145
|
+
def remove_footer_from(response)
|
146
|
+
response[0..response.size-11]
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module BuoyData
|
2
|
+
class NoaaBuoyList < BuoyList
|
3
|
+
def url
|
4
|
+
"#{base_url}/to_station.shtml"
|
5
|
+
end
|
6
|
+
|
7
|
+
def base_url
|
8
|
+
'http://www.ndbc.noaa.gov'
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
def stations(doc)
|
13
|
+
text = "National Data Buoy Center Stations"
|
14
|
+
xpath = "//h4[text()='#{text}']/following-sibling::pre/a"
|
15
|
+
|
16
|
+
doc.xpath(xpath).map{|element| element['href']}
|
17
|
+
end
|
18
|
+
|
19
|
+
def scrape_station(url)
|
20
|
+
url = [base_url, url].join('/')
|
21
|
+
doc = Nokogiri::HTML(open(url))
|
22
|
+
h = {}
|
23
|
+
xpath = "//h1"
|
24
|
+
|
25
|
+
# Title, Station Id and Description
|
26
|
+
title = doc.xpath(xpath).text
|
27
|
+
h[:url] = url
|
28
|
+
h[:title] = title
|
29
|
+
station_id, description = title.split(/ - /)
|
30
|
+
station_id = station_id.sub(/station ?/i, '')
|
31
|
+
h[:station_id] = station_id
|
32
|
+
h[:description] = description
|
33
|
+
|
34
|
+
# Lat and Lng
|
35
|
+
xpath += "/following-sibling::table/tr/td/p/b"
|
36
|
+
elements = doc.xpath(xpath)
|
37
|
+
elements = elements.map(&:text)
|
38
|
+
element = elements.find{|e| /\d{2,3}\.\d{2,3}/.match(e)}
|
39
|
+
latlng = lat_lng_from element
|
40
|
+
|
41
|
+
unless latlng.empty?
|
42
|
+
h[:lat] = normal_lat latlng.first
|
43
|
+
h[:lng] = normal_lng latlng.last
|
44
|
+
end
|
45
|
+
|
46
|
+
h
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -1,34 +1,53 @@
|
|
1
1
|
module BuoyData
|
2
|
-
class
|
3
|
-
|
2
|
+
class NoaaBuoyObservation < NoaaBuoyReading
|
3
|
+
require 'json/add/core'
|
4
4
|
|
5
|
-
|
5
|
+
def get_all(format = :plain)
|
6
|
+
response = get(true)
|
7
|
+
return unless response
|
8
|
+
response = response_to_array response
|
6
9
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
10
|
+
case format
|
11
|
+
when :json
|
12
|
+
json_response = []
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
fields = fields_from_response response
|
15
|
+
# Remvoe the field rows
|
16
|
+
response = response[2..response.size-1]
|
17
|
+
|
18
|
+
response.each do |reading|
|
19
|
+
reading = reading.split
|
20
|
+
json = reading_to_hash(reading, fields).to_json
|
21
|
+
json_response.push json
|
22
|
+
end
|
17
23
|
|
18
|
-
|
19
|
-
|
20
|
-
return unless response and response.code == GET_SUCCESS
|
21
|
-
return response if raw
|
24
|
+
response = json_response
|
25
|
+
end
|
22
26
|
|
23
|
-
|
24
|
-
parse_response
|
27
|
+
response
|
25
28
|
end
|
26
29
|
|
27
|
-
def
|
28
|
-
|
30
|
+
def parse_response(response)
|
31
|
+
# Get all readings
|
32
|
+
response = response_to_array response
|
33
|
+
# The first line are the fields
|
34
|
+
fields = fields_from_response response
|
35
|
+
|
36
|
+
# The second line are different names of the fields
|
37
|
+
# The third line is the most recent reading
|
38
|
+
response = most_recent_from_response response
|
29
39
|
return unless response
|
30
40
|
|
31
|
-
|
41
|
+
# Set instance vars per field so we can use dot notation to reference each
|
42
|
+
hash = reading_to_hash(response, fields)
|
43
|
+
define_attributes(hash)
|
44
|
+
end
|
45
|
+
|
46
|
+
def define_attributes(hash)
|
47
|
+
hash.each_pair { |key, value|
|
48
|
+
metaclass.send :attr_accessor, key
|
49
|
+
send "#{key}=".to_sym, value
|
50
|
+
}
|
32
51
|
end
|
33
52
|
|
34
53
|
#
|
@@ -72,54 +91,5 @@ module BuoyData
|
|
72
91
|
|
73
92
|
"http://www.ndbc.noaa.gov/data/realtime2/#{buoy_id}.spec"
|
74
93
|
end
|
75
|
-
|
76
|
-
def self.source
|
77
|
-
:noaa
|
78
|
-
end
|
79
|
-
|
80
|
-
def self.google_chart_base(buoy_id)
|
81
|
-
url = [ "http://chart.apis.google.com/chart?cht=lc" ]
|
82
|
-
url << "chtt=#{buoy_id}"
|
83
|
-
url << "chts=666666,12"
|
84
|
-
url << "chco=3366FF"
|
85
|
-
url << "chs=250x100"
|
86
|
-
url << "chds=0,10"
|
87
|
-
url << "chl=WVHT".gsub(/ /, '%20')
|
88
|
-
url.join('&')
|
89
|
-
end
|
90
|
-
|
91
|
-
|
92
|
-
def self.default_unit_system
|
93
|
-
:metric
|
94
|
-
end
|
95
|
-
|
96
|
-
def parse_response
|
97
|
-
# Get all readings
|
98
|
-
response = @response.parsed_response.split(/\n/)
|
99
|
-
|
100
|
-
# The first line are the fields
|
101
|
-
fields = response.first.sub(/^#/, '').split
|
102
|
-
|
103
|
-
# The second line are different names of the fields
|
104
|
-
|
105
|
-
# The third line is the most recent reading
|
106
|
-
response = response[2].split rescue nil
|
107
|
-
return unless response
|
108
|
-
|
109
|
-
# Set instance vars per field so we can use dot notation to reference each
|
110
|
-
hash = {}
|
111
|
-
fields.each_with_index do |field, index|
|
112
|
-
hash.store(field, response[index])
|
113
|
-
end
|
114
|
-
|
115
|
-
define_attributes(hash)
|
116
|
-
end
|
117
|
-
|
118
|
-
def define_attributes(hash)
|
119
|
-
hash.each_pair { |key, value|
|
120
|
-
metaclass.send :attr_accessor, key
|
121
|
-
send "#{key}=".to_sym, value
|
122
|
-
}
|
123
|
-
end
|
124
94
|
end
|
125
95
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module BuoyData
|
2
|
+
class NoaaBuoyReading < BuoyReading
|
3
|
+
format :plain
|
4
|
+
|
5
|
+
attr_accessor :buoy_id, :url, :response
|
6
|
+
|
7
|
+
def initialize(buoy_id, unit_system = self.class.default_unit_system)
|
8
|
+
@url = base_url(buoy_id)
|
9
|
+
@unit_system = unit_system
|
10
|
+
end
|
11
|
+
|
12
|
+
def metaclass
|
13
|
+
class << self
|
14
|
+
self
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def get(raw = false)
|
19
|
+
response = self.class.get(@url)
|
20
|
+
return unless response and response.code == GET_SUCCESS
|
21
|
+
return response if raw
|
22
|
+
|
23
|
+
@response = response
|
24
|
+
parse_response(response)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.source
|
28
|
+
:noaa
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.google_chart_base(buoy_id)
|
32
|
+
url = [ "http://chart.apis.google.com/chart?cht=lc" ]
|
33
|
+
url << "chtt=#{buoy_id}"
|
34
|
+
url << "chts=666666,12"
|
35
|
+
url << "chco=3366FF"
|
36
|
+
url << "chs=250x100"
|
37
|
+
url << "chds=0,10"
|
38
|
+
url << "chl=WVHT".gsub(/ /, '%20')
|
39
|
+
url.join('&')
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def self.default_unit_system
|
44
|
+
:metric
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
def fields_from_response(response)
|
49
|
+
fields = response.first.sub(/^#/, '').split
|
50
|
+
end
|
51
|
+
|
52
|
+
def response_to_array(response)
|
53
|
+
response.parsed_response.split(/\n/)
|
54
|
+
end
|
55
|
+
|
56
|
+
def most_recent_from_response(response)
|
57
|
+
response[2].split rescue nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def reading_to_hash(reading, fields)
|
61
|
+
hash = {}
|
62
|
+
fields.each_with_index do |field, index|
|
63
|
+
hash.store(field, reading[index])
|
64
|
+
end
|
65
|
+
|
66
|
+
hash
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/buoy_data.rb
CHANGED
@@ -1,3 +1,7 @@
|
|
1
1
|
require 'httparty'
|
2
|
-
require 'buoy_data/
|
3
|
-
require 'buoy_data/
|
2
|
+
require 'buoy_data/buoy_list'
|
3
|
+
require 'buoy_data/buoy_reading'
|
4
|
+
require 'buoy_data/noaa_buoy_reading'
|
5
|
+
require 'buoy_data/noaa_buoy_list'
|
6
|
+
require 'buoy_data/noaa_buoy_observation'
|
7
|
+
require 'buoy_data/noaa_buoy_forecast'
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe BuoyData::NoaaBuoyForecast do
|
4
|
+
before(:each) do
|
5
|
+
#FakeWeb.allow_net_connect = false # TODO
|
6
|
+
end
|
7
|
+
|
8
|
+
let (:noaa_buoy_forecast) { BuoyData::NoaaBuoyForecast.new(41012) }
|
9
|
+
|
10
|
+
context 'get' do
|
11
|
+
before(:each) do
|
12
|
+
noaa_buoy_forecast.get
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should get buoy data' do
|
16
|
+
noaa_buoy_forecast.response.code.should == BuoyData::NoaaBuoyForecast::GET_SUCCESS
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should get buoy data as json' do
|
20
|
+
noaa_buoy_forecast.get
|
21
|
+
json = noaa_buoy_forecast.to_json
|
22
|
+
json.should be
|
23
|
+
# We really should get down and dirty here, thoroughly checking the fields
|
24
|
+
hash = JSON.parse(json).first
|
25
|
+
hash.should be_a Hash
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe BuoyData::NoaaBuoyList do
|
4
|
+
let (:buoy_list) { BuoyData::NoaaBuoyList.new }
|
5
|
+
|
6
|
+
context 'get' do
|
7
|
+
it "should get buoy list" do
|
8
|
+
buoy_list.should be
|
9
|
+
buoy_list.stub(:stations).and_return(stubbed_station_list)
|
10
|
+
stations = buoy_list.get
|
11
|
+
|
12
|
+
stations.should_not be_empty
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def stubbed_station_list
|
17
|
+
[ "station_page.php?station=41012", "station_page.php?station=sauf1" ]
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe BuoyData::NoaaBuoyObservation do
|
4
|
+
before(:each) do
|
5
|
+
#FakeWeb.allow_net_connect = false # TODO
|
6
|
+
end
|
7
|
+
|
8
|
+
let (:noaa_buoy_observation) { BuoyData::NoaaBuoyObservation.new(41012) }
|
9
|
+
|
10
|
+
context 'get' do
|
11
|
+
it 'should get buoy data' do
|
12
|
+
noaa_buoy_observation.get
|
13
|
+
noaa_buoy_observation.response.code.should == BuoyData::NoaaBuoyObservation::GET_SUCCESS
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should respond to noaa fields' do
|
17
|
+
noaa_buoy_observation.get
|
18
|
+
noaa_buoy_observation.should respond_to :WVHT
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should generate google chart url' do
|
22
|
+
noaa_buoy_observation.google_chart_url.should match(/chart.apis.google.com/)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should parse date fields' do
|
26
|
+
noaa_buoy_observation.get
|
27
|
+
noaa_buoy_observation.YY.should match(/^\d{4}$/)
|
28
|
+
noaa_buoy_observation.DD.should match(/^\d{2}$/)
|
29
|
+
noaa_buoy_observation.hh.should match(/^\d{2}$/)
|
30
|
+
noaa_buoy_observation.mm.should match(/^\d{2}$/)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'get_all' do
|
35
|
+
it 'should get all' do
|
36
|
+
response = noaa_buoy_observation.get_all
|
37
|
+
response.should be_a Array
|
38
|
+
response.size.should > 1
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should get all as :json' do
|
42
|
+
json = noaa_buoy_observation.get_all(:json)
|
43
|
+
hash = JSON.parse(json.first)
|
44
|
+
hash.should be_a(Hash)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should parse date fields' do
|
48
|
+
response = noaa_buoy_observation.get_all(:json)
|
49
|
+
noaa_buoy_observation = JSON.parse(response.first)
|
50
|
+
|
51
|
+
noaa_buoy_observation[:YY.to_s].should match(/^\d{4}$/)
|
52
|
+
noaa_buoy_observation[:DD.to_s].should match(/^\d{2}$/)
|
53
|
+
noaa_buoy_observation[:hh.to_s].should match(/^\d{2}$/)
|
54
|
+
noaa_buoy_observation[:mm.to_s].should match(/^\d{2}$/)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
metadata
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: buoy_data
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
4
|
+
prerelease: true
|
5
5
|
segments:
|
6
|
+
- 1
|
7
|
+
- 0
|
6
8
|
- 0
|
7
|
-
-
|
9
|
+
- beta
|
8
10
|
- 0
|
9
|
-
version: 0.
|
11
|
+
version: 1.0.0.beta.0
|
10
12
|
platform: ruby
|
11
13
|
authors:
|
12
14
|
- Adam Weller
|
@@ -14,7 +16,7 @@ autorequire:
|
|
14
16
|
bindir: bin
|
15
17
|
cert_chain: []
|
16
18
|
|
17
|
-
date:
|
19
|
+
date: 2011-03-20 00:00:00 -04:00
|
18
20
|
default_executable:
|
19
21
|
dependencies:
|
20
22
|
- !ruby/object:Gem::Dependency
|
@@ -43,6 +45,32 @@ dependencies:
|
|
43
45
|
version: "0"
|
44
46
|
type: :runtime
|
45
47
|
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: json
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
segments:
|
57
|
+
- 0
|
58
|
+
version: "0"
|
59
|
+
type: :runtime
|
60
|
+
version_requirements: *id003
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: nokogiri
|
63
|
+
prerelease: false
|
64
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
version: "0"
|
72
|
+
type: :runtime
|
73
|
+
version_requirements: *id004
|
46
74
|
description: The goal of this gem is to provide marine buoy data from a variety of sources
|
47
75
|
email: minch@trazzler.com
|
48
76
|
executables: []
|
@@ -61,9 +89,15 @@ files:
|
|
61
89
|
- VERSION
|
62
90
|
- buoy_data.gemspec
|
63
91
|
- lib/buoy_data.rb
|
64
|
-
- lib/buoy_data/
|
65
|
-
- lib/buoy_data/
|
66
|
-
-
|
92
|
+
- lib/buoy_data/buoy_list.rb
|
93
|
+
- lib/buoy_data/buoy_reading.rb
|
94
|
+
- lib/buoy_data/noaa_buoy_forecast.rb
|
95
|
+
- lib/buoy_data/noaa_buoy_list.rb
|
96
|
+
- lib/buoy_data/noaa_buoy_observation.rb
|
97
|
+
- lib/buoy_data/noaa_buoy_reading.rb
|
98
|
+
- spec/noaa_buoy_forecast_spec.rb
|
99
|
+
- spec/noaa_buoy_list_spec.rb
|
100
|
+
- spec/noaa_buoy_observation_spec.rb
|
67
101
|
- spec/spec_helper.rb
|
68
102
|
has_rdoc: true
|
69
103
|
homepage: http://github.com/minch/buoy_data
|
@@ -85,11 +119,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
85
119
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
120
|
none: false
|
87
121
|
requirements:
|
88
|
-
- - "
|
122
|
+
- - ">"
|
89
123
|
- !ruby/object:Gem::Version
|
90
124
|
segments:
|
91
|
-
-
|
92
|
-
|
125
|
+
- 1
|
126
|
+
- 3
|
127
|
+
- 1
|
128
|
+
version: 1.3.1
|
93
129
|
requirements: []
|
94
130
|
|
95
131
|
rubyforge_project:
|
@@ -98,5 +134,7 @@ signing_key:
|
|
98
134
|
specification_version: 3
|
99
135
|
summary: Fetch marine buoy data from various sources
|
100
136
|
test_files:
|
101
|
-
- spec/
|
137
|
+
- spec/noaa_buoy_forecast_spec.rb
|
138
|
+
- spec/noaa_buoy_list_spec.rb
|
139
|
+
- spec/noaa_buoy_observation_spec.rb
|
102
140
|
- spec/spec_helper.rb
|
data/spec/noaa_buoy_spec.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
-
|
3
|
-
describe BuoyData::NoaaBuoy do
|
4
|
-
before(:each) do
|
5
|
-
#FakeWeb.allow_net_connect = false # TODO
|
6
|
-
@noaa_buoy = BuoyData::NoaaBuoy.new(41114)
|
7
|
-
end
|
8
|
-
|
9
|
-
context 'get' do
|
10
|
-
it 'should get buoy data' do
|
11
|
-
@noaa_buoy.get
|
12
|
-
@noaa_buoy.response.code.should == BuoyData::NoaaBuoy::GET_SUCCESS
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'should respond to noaa fields' do
|
16
|
-
@noaa_buoy.get
|
17
|
-
@noaa_buoy.should respond_to :WVHT
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'should get all buoy data' do
|
21
|
-
@noaa_buoy.get_all.size.should >= 1
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'should get all buoy data' do
|
25
|
-
@noaa_buoy.google_chart_url.should match(/chart.apis.google.com/)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|