buoy_data 1.0.0.beta.0 → 1.0.0.beta.1

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/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0.beta.0
1
+ 1.0.0.beta.1
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 = "1.0.0.beta.0"
8
+ s.version = "1.0.0.beta.1"
9
9
 
10
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{2011-03-20}
12
+ s.date = %q{2011-04-17}
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 = [
@@ -31,6 +31,7 @@ Gem::Specification.new do |s|
31
31
  "lib/buoy_data/noaa_buoy_list.rb",
32
32
  "lib/buoy_data/noaa_buoy_observation.rb",
33
33
  "lib/buoy_data/noaa_buoy_reading.rb",
34
+ "lib/buoy_data/noaa_station.rb",
34
35
  "spec/noaa_buoy_forecast_spec.rb",
35
36
  "spec/noaa_buoy_list_spec.rb",
36
37
  "spec/noaa_buoy_observation_spec.rb",
@@ -6,17 +6,21 @@ module BuoyData
6
6
  def get
7
7
  stats = {
8
8
  :stations => [],
9
- :errors => []
9
+ :station_count => 0,
10
+ :errors => [],
11
+ :error_count => 0
10
12
  }
11
13
  @doc = doc
12
14
  @station_list = stations doc
13
15
 
14
- @station_list.each do |s|
16
+ @station_list.each do |station_url|
15
17
  begin
16
- h = scrape_station s
18
+ h = scrape_station(station_url)
17
19
  stats[:stations].push h
20
+ stats[:station_count] += 1
18
21
  rescue => e
19
- stats[:errors].push({ :url => s, :error => e })
22
+ stats[:error_count] += 1
23
+ stats[:errors].push({ :url => s, :error => e.backtrace })
20
24
  end
21
25
  end
22
26
 
@@ -39,28 +43,5 @@ module BuoyData
39
43
 
40
44
  def scrape_station(url)
41
45
  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
46
  end
66
47
  end
@@ -17,33 +17,8 @@ module BuoyData
17
17
  end
18
18
 
19
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
20
+ url = [ base_url, url ].join('/')
21
+ NoaaStation.new.scrape(url)
47
22
  end
48
23
  end
49
24
  end
@@ -0,0 +1,105 @@
1
+ module BuoyData
2
+ require 'open-uri'
3
+ require 'nokogiri'
4
+
5
+ class NoaaStation
6
+ def scrape(url)
7
+ h = {}
8
+ xpath = "//h1"
9
+
10
+ doc = Nokogiri::HTML(open(url))
11
+
12
+ # Title, Station Id and Description
13
+ title = doc.xpath(xpath).first.text
14
+ title = title.rstrip
15
+ h[:url] = url
16
+ h[:title] = title
17
+ station_id, description = title.split(/ - /)
18
+ station_id = station_id.sub(/station ?/i, '')
19
+ station_id = /[A-Z0-9]+/.match(station_id).to_s rescue nil
20
+ h[:station_id] = station_id
21
+ h[:description] = description
22
+
23
+ # Lat and Lng
24
+ xpath += "/following-sibling::table/tr/td/p/b"
25
+ elements = doc.xpath(xpath)
26
+ elements = elements.map(&:text)
27
+ element = elements.find{|e| /\d{2,3}\.\d{2,3}/.match(e)}
28
+ latlng = lat_lng_from element
29
+
30
+ unless latlng.empty?
31
+ h[:lat] = normal_lat latlng.first
32
+ h[:lng] = normal_lng latlng.last
33
+ end
34
+
35
+ # Latest reading
36
+ xpath = "//table/caption[@class='titleDataHeader'][text()[contains(.,'Conditions')]]"
37
+ xpath += "/../tr"
38
+ elements = doc.xpath xpath
39
+
40
+ current_reading = {}
41
+ unless elements.empty?
42
+ elements.each do |element|
43
+ reading = scrape_condition_from_element(element)
44
+ current_reading.merge! reading unless reading.blank?
45
+ end
46
+ end
47
+
48
+ # If we couldn't get a water temp from this station then it's not of use
49
+ return {} unless valid_reading? current_reading
50
+ h.merge! current_reading
51
+
52
+ h
53
+ end
54
+
55
+ private
56
+ # No water temp (wtmp) is our filter
57
+ def valid_reading?(reading)
58
+ !reading.blank? && reading.keys.include?(:wtmp)
59
+ end
60
+
61
+ def scrape_condition_from_element(element)
62
+ reading = {}
63
+ # (include units)
64
+ #regexp = /\(([A-Z]+)\):\n\t ?(.*)\n$/
65
+ # (no units)
66
+ regexp = /\(([A-Z]+)\):\n\t ?([0-9.-]+).*\n$/
67
+ text = element.text
68
+
69
+ if regexp.match(text)
70
+ key = $1
71
+ return reading unless key
72
+ key = key.downcase.to_sym
73
+ value = $2
74
+ return reading unless value
75
+ value = value.lstrip.rstrip.to_f
76
+ reading = { key => value }
77
+ end
78
+
79
+ reading
80
+ end
81
+
82
+ def lat_lng_from(text)
83
+ text = text.sub(/ \(.*$/, '')
84
+ matches = /([0-9\.]+ ?[NESW]) ([0-9\.]+ ?[NESW])/.match(text)
85
+
86
+ matches && matches.size == 3 ? [ $1, $2 ] : []
87
+ end
88
+
89
+ def normal_lat(lat)
90
+ lat, dir = lat.split(/ /)
91
+ lat = lat.to_f
92
+ lat = -lat if dir == 'S'
93
+
94
+ lat
95
+ end
96
+
97
+ def normal_lng(lng)
98
+ lng, dir = lng.split(/ /)
99
+ lng = lng.to_f
100
+ lng = -lng if dir == 'W'
101
+
102
+ lng
103
+ end
104
+ end
105
+ end
data/lib/buoy_data.rb CHANGED
@@ -2,6 +2,7 @@ require 'httparty'
2
2
  require 'buoy_data/buoy_list'
3
3
  require 'buoy_data/buoy_reading'
4
4
  require 'buoy_data/noaa_buoy_reading'
5
+ require 'buoy_data/noaa_station'
5
6
  require 'buoy_data/noaa_buoy_list'
6
7
  require 'buoy_data/noaa_buoy_observation'
7
8
  require 'buoy_data/noaa_buoy_forecast'
@@ -7,13 +7,24 @@ describe BuoyData::NoaaBuoyList do
7
7
  it "should get buoy list" do
8
8
  buoy_list.should be
9
9
  buoy_list.stub(:stations).and_return(stubbed_station_list)
10
- stations = buoy_list.get
11
10
 
12
- stations.should_not be_empty
11
+ results = buoy_list.get
12
+ results.should_not be_empty
13
+ results[:errors].should be_empty
14
+ stations = results[:stations]
15
+ stations.compact.should_not be_empty
16
+ station = stations.first
17
+
18
+ # Verify we have water temp value
19
+ wtmp = station[:wtmp]
20
+ wtmp.should be_kind_of Float
13
21
  end
14
22
  end
15
23
 
16
24
  def stubbed_station_list
17
- [ "station_page.php?station=41012", "station_page.php?station=sauf1" ]
25
+ [
26
+ "station_page.php?station=41012",
27
+ "station_page.php?station=sauf1"
28
+ ]
18
29
  end
19
30
  end
metadata CHANGED
@@ -7,8 +7,8 @@ version: !ruby/object:Gem::Version
7
7
  - 0
8
8
  - 0
9
9
  - beta
10
- - 0
11
- version: 1.0.0.beta.0
10
+ - 1
11
+ version: 1.0.0.beta.1
12
12
  platform: ruby
13
13
  authors:
14
14
  - Adam Weller
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2011-03-20 00:00:00 -04:00
19
+ date: 2011-04-17 00:00:00 -04:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -95,6 +95,7 @@ files:
95
95
  - lib/buoy_data/noaa_buoy_list.rb
96
96
  - lib/buoy_data/noaa_buoy_observation.rb
97
97
  - lib/buoy_data/noaa_buoy_reading.rb
98
+ - lib/buoy_data/noaa_station.rb
98
99
  - spec/noaa_buoy_forecast_spec.rb
99
100
  - spec/noaa_buoy_list_spec.rb
100
101
  - spec/noaa_buoy_observation_spec.rb