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

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