gull 0.4.0 → 1.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 499056dd7d0dfaf61fd26893aac65a8f8b2f802f
4
- data.tar.gz: 989cda9df71c6d5fc5d31c3ae9c4ff6a26e7ff7b
2
+ SHA256:
3
+ metadata.gz: eb20ff9550e66bb6897227d930069551cc9882c1eef9f285d7a1ba74e0b2133e
4
+ data.tar.gz: b50b4e87e416dce952046c357e2c06d1d826b84e451141e237570418569d4b1d
5
5
  SHA512:
6
- metadata.gz: 7b86f770036bbae32dd13ad68d793fc62043bbf199d3e980cdb92455e26c0498a952d1212a5af69ec26403377da32edce66ee2efdfa68d4e5249a6dc23a5ed35
7
- data.tar.gz: ffe0a676c31958d1c51c25a50a1be6d13046ba88689f734ec4a82112062c4d87e4c5cc6ef6abb52751689e3879a14e15d5d0f4d7fdd532e125eade99e47ff140
6
+ metadata.gz: b06376a56d00f2fa3ee684f4897b02439d24cd910722779a1f696e4d2a596550fa82cd7efb2e83c94934550fdaf406a266cddcab78a97b41d9fbdf6a13f65373
7
+ data.tar.gz: ca1f9f07f27e928571b1d0ed54bbe2275bccd8389995073f0892b4c5e469d176ea5084fa09bf0bdbca923b225105627da4f45e986fd5cd06e245a82a4515a577
@@ -0,0 +1,23 @@
1
+ name: CI
2
+ on:
3
+ push:
4
+ branches: [master]
5
+ pull_request:
6
+ branches: [master]
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ strategy:
11
+ matrix:
12
+ ruby-version: ['3.1', '3.2', '3.3', '3.4']
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - name: Set up Ruby ${{ matrix.ruby-version }}
16
+ uses: ruby/setup-ruby@v1
17
+ with:
18
+ ruby-version: ${{ matrix.ruby-version }}
19
+ bundler-cache: true
20
+ - name: Run tests
21
+ run: bundle exec rspec
22
+ - name: Run linter
23
+ run: bundle exec rubocop
data/.gitignore CHANGED
@@ -1,22 +1,6 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
1
+ /.bundle
2
+ /coverage
3
+ /pkg
4
+ /tmp
6
5
  Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
18
- *.bundle
19
- *.so
20
- *.o
21
- *.a
22
- mkmf.log
6
+ .ruby-version
data/.rubocop.yml CHANGED
@@ -1,5 +1,38 @@
1
1
  AllCops:
2
+ TargetRubyVersion: 3.1
3
+ NewCops: enable
4
+ SuggestExtensions: false
2
5
  Exclude:
3
6
  - 'spec/spec_helper.rb'
7
+ - 'gull.gemspec'
8
+ - 'vendor/**/*'
9
+ Metrics/BlockLength:
10
+ Exclude:
11
+ - 'spec/**/*'
12
+ Metrics/MethodLength:
13
+ Max: 20
14
+ Exclude:
15
+ - 'spec/**/*'
16
+ Metrics/AbcSize:
17
+ Max: 35
18
+ Exclude:
19
+ - 'spec/**/*'
20
+ Metrics/ClassLength:
21
+ Enabled: false
22
+ Metrics/CyclomaticComplexity:
23
+ Enabled: false
24
+ Metrics/PerceivedComplexity:
25
+ Enabled: false
26
+ Layout/LineLength:
27
+ Max: 80
28
+ Exclude:
29
+ - 'spec/**/*'
4
30
  Style/StringLiterals:
5
- EnforcedStyle: single_quotes
31
+ EnforcedStyle: single_quotes
32
+ Style/StringConcatenation:
33
+ Exclude:
34
+ - 'spec/**/*'
35
+ Style/Documentation:
36
+ Enabled: false
37
+ Naming/PredicateMethod:
38
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ 1.0.0 (03/07/2026) - Major rewrite: migrate from defunct `alerts.weather.gov` XML feed to `api.weather.gov/alerts` JSON API. Drop all runtime dependencies (`httpclient`, `nokogiri`) in favor of Ruby stdlib (`net/http`, `json`). Require Ruby >= 3.1. Add `area` option for state-based filtering. Replace Travis CI with GitHub Actions. Add RuboCop. **Breaking:** remove `url` option (use `area` instead), remove `Polygon#image_url`, remove `strict` option.
2
+
3
+ ***
4
+
1
5
  0.4.0 (07/26/2016) - Merged pull request #2 from [schrockwell](https://github.com/schrockwell), which adds `to_wkt` to `Polygon` which formats the polygon points as Well-Known Text (WKT). Removed `centroid` method, use new `to_wkt` method with an external geospatial library instead.
2
6
 
3
7
  ***
@@ -43,7 +47,7 @@
43
47
  ***
44
48
 
45
49
  0.2.0 (10/02/2014) - Introduced Polygon type.
46
-
50
+
47
51
  ***
48
52
 
49
53
  0.1.1 (10/01/2014) - Refactored and simplified alert processing.
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in gull.gemspec
data/Guardfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  guard :rspec, cmd: 'bundle exec rspec' do
2
4
  watch(%r{^spec/.+_spec\.rb$})
3
5
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014 Seth Deckard
1
+ Copyright (c) 2014-2026 Seth Deckard
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -1,12 +1,8 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/gull.svg)](http://badge.fury.io/rb/gull)
2
- [![Build Status](https://travis-ci.org/sethdeckard/gull.svg?branch=master)](https://travis-ci.org/sethdeckard/gull)
3
- [![Coverage Status](https://coveralls.io/repos/sethdeckard/gull/badge.svg?branch=master)](https://coveralls.io/r/sethdeckard/gull)
4
- [![Code Climate](https://codeclimate.com/github/sethdeckard/gull/badges/gpa.svg)](https://codeclimate.com/github/sethdeckard/gull)
5
- [![Dependency Status](https://gemnasium.com/sethdeckard/gull.svg)](https://gemnasium.com/sethdeckard/gull)
6
- [![security](https://hakiri.io/github/sethdeckard/gull/master.svg)](https://hakiri.io/github/sethdeckard/gull/master)
2
+ [![CI](https://github.com/sethdeckard/gull/actions/workflows/ci.yml/badge.svg)](https://github.com/sethdeckard/gull/actions/workflows/ci.yml)
7
3
  # Gull
8
4
 
9
- Ruby client for parsing NOAA/NWS alerts, warnings, and watches. The name comes from the type of bird featured on the NOAA logo. Please read the Notes/Caveats section for limitations.
5
+ Ruby client for parsing NOAA/NWS alerts, warnings, and watches. The name comes from the type of bird featured on the NOAA logo. Zero runtime dependencies -- uses only Ruby stdlib (`net/http`, `json`).
10
6
 
11
7
  ## Installation
12
8
 
@@ -49,41 +45,22 @@ alert.certainty
49
45
  alert.vtec
50
46
  ```
51
47
 
52
- To get alerts for a single state, territory, or marine zone just pass an optional URL
48
+ To get alerts for a single state or territory, pass the area option:
53
49
 
54
50
  ```ruby
55
- oklahoma_url = 'http://alerts.weather.gov/cap/ok.php?x=1'
56
- alerts = Gull::Alert.fetch(url: oklahoma_url)
57
- ```
58
-
59
- You can also generate a map (a really long URL pointing to a map) of the polygon if alert has one (requires Google Static Maps API Key)
60
-
61
- ```ruby
62
- alert.polygon.image_url 'YOUR_GOOGLE_API_KEY'
63
-
64
- => "http://maps.googleapis.com/maps/api/staticmap?size=640x640&maptype=roadmap&path=color:0xff0000|weight:3|fillcolor:0xff000060|38.73,-94.22|38.75,-94.16|38.57,-93.94|38.4,-93.84|38.4,-93.91|38.73,-94.22&key=YOUR_GOOGLE_API_KEY"
65
- ```
66
-
67
- Options can be passed for map to override defaults
68
-
69
- ```ruby
70
- options = { width: 600, height: 300, color: '0xfbf000', weight: 4,
71
- fillcolor: '0xfbf00070', maptype: 'hybrid' }
72
- alert.polygon.image_url 'YOUR_GOOGLE_API_KEY', options
51
+ alerts = Gull::Alert.fetch(area: 'OK')
73
52
  ```
74
53
 
75
54
  ##Notes, Caveats
76
- This library provides a simplified/flattened model of the [Common Alerting Protocol](http://docs.oasis-open.org/emergency/cap/v1.2/CAP-v1.2-os.html) based only on the elements NWS utilizes in their [public Atom feeds](http://alerts.weather.gov/). If you need a complete CAP parser I suggest looking at [RCAP](https://github.com/farrel/RCAP).
77
-
78
- The NWS will often cancel or update alerts before their expiration time. The public Atom feeds only provide current active alerts and do not include these separate update and cancellation CAP messages.
55
+ This library fetches active alerts from the [NWS API](https://api.weather.gov) (`api.weather.gov/alerts/active`), which returns GeoJSON. No authentication is required but the API does require a `User-Agent` header (set automatically by the gem).
79
56
 
80
- The public Atom feeds have not always been reliable in terms of uptime and are often delayed by 2-3 minutes. If you are considering using this (or another gem/library that accesses the public Atom feeds) for mission critical purposes then you should explore other options.
57
+ The NWS will often cancel or update alerts before their expiration time. The API only returns currently active alerts.
81
58
 
82
59
  ### Urgency
83
60
 
84
- | Symbol | Definition
61
+ | Symbol | Definition
85
62
  | :------------- |:-------------
86
- | :immediate | Responsive action should betaken immediately
63
+ | :immediate | Responsive action should be taken immediately
87
64
  | :expected | Responsive action should be taken soon (within next hour)
88
65
  | :future | Responsive action should be taken in the near future
89
66
  | :past | Responsive action is no longer required
@@ -91,7 +68,7 @@ The public Atom feeds have not always been reliable in terms of uptime and are o
91
68
 
92
69
  ### Severity
93
70
 
94
- | Symbol | Definition
71
+ | Symbol | Definition
95
72
  | :------------- |:-------------
96
73
  | :extreme | Extraordinary threat to life or property
97
74
  | :severe | Significant threat to life or property
@@ -101,7 +78,7 @@ The public Atom feeds have not always been reliable in terms of uptime and are o
101
78
 
102
79
  ### Certainty
103
80
 
104
- | Symbol | Definition
81
+ | Symbol | Definition
105
82
  | :------------- |:-------------
106
83
  | :very_likely | Highly likely (p > ~ 85%) or certain
107
84
  | :likely | Likely (p > ~50%)
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
4
  require 'rspec/core/rake_task'
3
5
 
data/gull.gemspec CHANGED
@@ -1,5 +1,6 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require 'gull/version'
5
6
 
@@ -9,22 +10,29 @@ Gem::Specification.new do |spec|
9
10
  spec.authors = ['Seth Deckard']
10
11
  spec.email = ['seth@deckard.me']
11
12
  spec.summary = 'Client for parsing NOAA/NWS alerts, warnings, and watches.'
12
- spec.description = 'Client for parsing NOAA/NWS alerts, warnings, and watches.'
13
+ spec.description = 'Fetches and parses NOAA/NWS alerts, warnings, and watches from api.weather.gov. Zero runtime dependencies.'
13
14
  spec.homepage = 'https://github.com/sethdeckard/gull'
14
15
  spec.license = 'MIT'
16
+ spec.required_ruby_version = '>= 3.1'
17
+
18
+ spec.metadata = {
19
+ 'source_code_uri' => 'https://github.com/sethdeckard/gull',
20
+ 'changelog_uri' => 'https://github.com/sethdeckard/gull/blob/master/CHANGELOG.md',
21
+ 'bug_tracker_uri' => 'https://github.com/sethdeckard/gull/issues'
22
+ }
15
23
 
16
- spec.files = `git ls-files -z`.split("\x0")
24
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
25
+ f.match(%r{^(AGENTS|CLAUDE)\.md$})
26
+ end
17
27
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
28
  spec.require_paths = ['lib']
20
29
 
21
- spec.add_runtime_dependency 'httpclient'
22
- spec.add_runtime_dependency 'nokogiri', '>= 1.6.8'
23
-
24
30
  spec.add_development_dependency 'bundler'
31
+ spec.add_development_dependency 'guard-rspec'
25
32
  spec.add_development_dependency 'rake'
26
- spec.add_development_dependency 'rspec', '>=3.0'
27
- spec.add_development_dependency 'coveralls'
28
- spec.add_development_dependency 'guard'
33
+ spec.add_development_dependency 'rspec', '>= 3.0'
34
+ spec.add_development_dependency 'rubocop'
35
+ spec.add_development_dependency 'rubocop-rake'
36
+ spec.add_development_dependency 'simplecov'
29
37
  spec.add_development_dependency 'webmock'
30
38
  end
data/lib/gull/alert.rb CHANGED
@@ -1,80 +1,89 @@
1
- require 'httpclient'
2
- require 'nokogiri'
1
+ # frozen_string_literal: true
3
2
 
4
3
  module Gull
5
- # Gull represents an NWS/NOAA alert and provides the ability to fetch
6
- # them from the public web service
7
4
  class Alert
8
- attr_accessor :id, :title, :summary, :link, :alert_type, :polygon, :area,
9
- :effective_at, :expires_at, :updated_at, :published_at,
10
- :urgency, :severity, :certainty, :geocode, :vtec
5
+ attr_accessor :id, :title, :summary, :link, :alert_type, :polygon,
6
+ :area, :effective_at, :expires_at, :updated_at,
7
+ :published_at, :urgency, :severity, :certainty,
8
+ :geocode, :vtec
11
9
 
12
10
  def initialize
13
11
  self.geocode = Geocode.new
14
12
  end
15
13
 
16
14
  def self.fetch(options = {})
17
- client = Client.new options
15
+ client = Client.new(options)
18
16
  client.fetch
19
17
  end
20
18
 
21
- def parse(element)
22
- parse_core_attributes element
23
- parse_times element
24
- parse_categories element
25
-
26
- parse_polygon element.xpath('cap:polygon').inner_text
27
- parse_geocode element.xpath('cap:geocode')
28
- parse_vtec element.xpath('cap:parameter')
19
+ def parse(feature)
20
+ props = feature['properties']
21
+ parse_core_attributes(feature, props)
22
+ parse_times(props)
23
+ parse_categories(props)
24
+ parse_polygon(feature)
25
+ parse_geocode(props)
26
+ parse_vtec(props)
29
27
  end
30
28
 
31
29
  private
32
30
 
33
- def parse_core_attributes(element)
34
- self.id = element.css('id').inner_text
35
- self.title = element.css('title').inner_text
36
- self.summary = element.css('summary').inner_text
37
- self.link = parse_link element
38
- self.alert_type = element.xpath('cap:event').inner_text
39
- self.area = element.xpath('cap:areaDesc').inner_text
31
+ def parse_core_attributes(feature, props)
32
+ self.id = props['id']
33
+ self.title = props['headline']
34
+ self.summary = props['description']
35
+ self.link = props['@id'] || feature['id']
36
+ self.alert_type = props['event']
37
+ self.area = props['areaDesc']
40
38
  end
41
39
 
42
- def parse_link(element)
43
- link = element.css('link').first
44
- link.attributes['href'].value unless link.nil?
40
+ def parse_times(props)
41
+ self.effective_at = Time.parse(props['effective'])
42
+ self.expires_at = Time.parse(props['expires'])
43
+ self.published_at = Time.parse(props['sent'])
44
+ self.updated_at = Time.parse(props['onset'] || props['sent'])
45
45
  end
46
46
 
47
- def parse_times(element)
48
- self.updated_at = Time.parse(element.css('updated').inner_text)
49
- self.published_at = Time.parse(element.css('published').inner_text)
50
- self.effective_at = Time.parse(element.xpath('cap:effective').inner_text)
51
- self.expires_at = Time.parse(element.xpath('cap:expires').inner_text)
47
+ def parse_categories(props)
48
+ self.urgency = code_to_symbol(props['urgency'])
49
+ self.severity = code_to_symbol(props['severity'])
50
+ self.certainty = code_to_symbol(props['certainty'])
52
51
  end
53
52
 
54
- def parse_categories(element)
55
- self.urgency = code_to_symbol element.xpath('cap:urgency').inner_text
56
- self.severity = code_to_symbol element.xpath('cap:severity').inner_text
57
- self.certainty = code_to_symbol element.xpath('cap:certainty').inner_text
58
- end
53
+ def parse_polygon(feature)
54
+ geometry = feature['geometry']
55
+ return if geometry.nil?
56
+
57
+ coords = geometry['coordinates']
58
+ return if coords.nil? || coords.empty?
59
59
 
60
- def parse_polygon(text)
61
- return if text.empty?
62
- self.polygon = Polygon.new text
60
+ ring = coords.first
61
+ ring = ring.first if geometry['type'] == 'MultiPolygon'
62
+ self.polygon = Polygon.new(ring)
63
63
  end
64
64
 
65
- def parse_geocode(element)
66
- return if element.children.css('value').first.nil?
65
+ def parse_geocode(props)
66
+ geocode_data = props['geocode']
67
+ return if geocode_data.nil?
67
68
 
68
- geocode.fips6 = element.children.css('value').first.inner_text
69
- geocode.ugc = element.children.css('value').last.inner_text
69
+ ugc = geocode_data['UGC']
70
+ geocode.ugc = ugc&.join(' ')
71
+
72
+ fips = geocode_data['SAME']
73
+ geocode.fips6 = fips&.join(' ')
70
74
  end
71
75
 
72
- def parse_vtec(element)
73
- value = element.children.css('value').inner_text
74
- self.vtec = value.empty? ? nil : value
76
+ def parse_vtec(props)
77
+ params = props['parameters']
78
+ return if params.nil?
79
+
80
+ vtec_values = params['VTEC']
81
+ self.vtec = vtec_values&.first
75
82
  end
76
83
 
77
84
  def code_to_symbol(code)
85
+ return :unknown if code.nil?
86
+
78
87
  code.tr(' ', '_').downcase.to_sym
79
88
  end
80
89
  end
data/lib/gull/client.rb CHANGED
@@ -1,65 +1,73 @@
1
- require 'httpclient'
2
- require 'nokogiri'
1
+ # frozen_string_literal: true
3
2
 
4
3
  module Gull
5
- # Client exposes methods and options for fetching alerts from the NWS/NOAA
6
- # web service
7
4
  class Client
5
+ URL = 'https://api.weather.gov/alerts/active'
6
+ USER_AGENT = "gull/#{VERSION} (Ruby #{RUBY_VERSION})".freeze
7
+
8
8
  attr_accessor :errors
9
9
 
10
10
  def initialize(options = {})
11
- @options = {
12
- url: 'http://alerts.weather.gov/cap/us.php?x=1',
13
- strict: false
14
- }.merge options
11
+ @options = options
15
12
  end
16
13
 
17
14
  def fetch
18
15
  self.errors = []
19
- content = response
20
- document = Nokogiri::XML content do |config|
21
- config.strict if @options[:strict]
22
- end
23
- process document.xpath('//xmlns:feed/xmlns:entry', namespaces)
16
+ json = response
17
+ data = JSON.parse(json)
18
+ process(data['features'] || [])
24
19
  end
25
20
 
26
21
  private
27
22
 
28
23
  def response
29
- client = HTTPClient.new
30
- begin
31
- return client.get_content @options[:url]
32
- rescue HTTPClient::TimeoutError
33
- raise TimeoutError, 'Timeout while connecting to NWS web service'
34
- rescue HTTPClient::KeepAliveDisconnected, HTTPClient::BadResponseError,
35
- SocketError, Errno::ECONNREFUSED, Errno::ECONNRESET
36
- raise HttpError, 'Could not connect to NWS web service'
24
+ uri = build_uri
25
+ http = Net::HTTP.new(uri.host, uri.port)
26
+ http.use_ssl = uri.scheme == 'https'
27
+ request = Net::HTTP::Get.new(uri)
28
+ request['User-Agent'] = USER_AGENT
29
+ request['Accept'] = 'application/geo+json'
30
+ result = http.request(request)
31
+ unless result.is_a?(Net::HTTPSuccess)
32
+ raise HttpError, "NWS API returned #{result.code}"
37
33
  end
34
+
35
+ result.body
36
+ rescue Net::OpenTimeout, Net::ReadTimeout
37
+ raise TimeoutError,
38
+ 'Timeout while connecting to NWS web service'
39
+ rescue SocketError, Errno::ECONNREFUSED, Errno::ECONNRESET
40
+ raise HttpError,
41
+ 'Could not connect to NWS web service'
38
42
  end
39
43
 
40
- def process(entries)
41
- alerts = []
42
- entries.each do |entry|
43
- alert = create_instance entry
44
- alerts.push alert unless alert.nil?
45
- errors.push entry if alert.nil?
44
+ def build_uri
45
+ uri = URI(URL)
46
+ if @options[:area]
47
+ params = URI.decode_www_form(uri.query || '')
48
+ params << ['area', @options[:area]]
49
+ uri.query = URI.encode_www_form(params)
46
50
  end
51
+ uri
52
+ end
47
53
 
54
+ def process(features)
55
+ alerts = []
56
+ features.each do |feature|
57
+ alert = create_instance(feature)
58
+ alerts.push(alert) unless alert.nil?
59
+ errors.push(feature) if alert.nil?
60
+ end
48
61
  alerts
49
62
  end
50
63
 
51
- def create_instance(entry)
52
- return if entry.xpath('cap:event').empty?
64
+ def create_instance(feature)
65
+ properties = feature['properties']
66
+ return if properties.nil? || properties['event'].nil?
53
67
 
54
68
  alert = Alert.new
55
- alert.parse entry
69
+ alert.parse(feature)
56
70
  alert
57
71
  end
58
-
59
- def namespaces
60
- { 'xmlns' => 'http://www.w3.org/2005/Atom',
61
- 'cap' => 'urn:oasis:names:tc:emergency:cap:1.1',
62
- 'ha' => 'http://www.alerting.net/namespace/index_1.0' }
63
- end
64
72
  end
65
73
  end
data/lib/gull/error.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'English'
2
4
 
3
5
  module Gull
data/lib/gull/geocode.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Gull
2
4
  class Geocode
3
5
  attr_accessor :fips6, :ugc
data/lib/gull/polygon.rb CHANGED
@@ -1,44 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Gull
2
4
  class Polygon
3
5
  attr_accessor :coordinates
4
6
 
5
- def initialize(polygon)
6
- self.coordinates = polygon.split(' ')
7
- .map { |point| point.split(',').map(&:to_f) }
8
- end
9
-
10
- def image_url(api_key, options = {})
11
- options = {
12
- width: 640,
13
- height: 640,
14
- color: '0xff0000',
15
- weight: 3,
16
- fillcolor: '0xff000060',
17
- maptype: 'roadmap'
18
- }.merge(options)
19
-
20
- url_base = 'http://maps.googleapis.com/maps/api/staticmap'
21
- "#{url_base}?size=#{options[:width]}x#{options[:height]}" \
22
- "&maptype=#{options[:maptype]}&path=color:#{options[:color]}" \
23
- "|weight:#{options[:weight]}|fillcolor:#{options[:fillcolor]}" \
24
- "|#{coordinates_piped}&key=#{api_key}"
7
+ def initialize(coords)
8
+ self.coordinates = coords.map { |point| [point[1], point[0]] }
25
9
  end
26
10
 
27
11
  def to_s
28
12
  coordinates.map { |pair| pair.join(',') }.join(' ')
29
13
  end
30
14
 
31
- # Returns well-known text (WKT) formatted polygon
32
15
  def to_wkt
33
16
  pairs = coordinates.map { |pair| "#{pair.last} #{pair.first}" }
34
17
  .join(', ')
35
18
  "POLYGON((#{pairs}))"
36
19
  end
37
-
38
- private
39
-
40
- def coordinates_piped
41
- coordinates.map { |pair| pair.join ',' }.join '|'
42
- end
43
20
  end
44
21
  end
data/lib/gull/version.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Gull
2
- VERSION = '0.4.0'
4
+ VERSION = '1.0.0'
3
5
  end
data/lib/gull.rb CHANGED
@@ -1,9 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'net/http'
5
+ require 'time'
6
+ require 'uri'
7
+
1
8
  require 'gull/version'
2
9
  require 'gull/error'
3
- require 'gull/client'
4
- require 'gull/alert'
5
- require 'gull/polygon'
6
10
  require 'gull/geocode'
11
+ require 'gull/polygon'
12
+ require 'gull/alert'
13
+ require 'gull/client'
7
14
 
8
15
  module Gull
9
16
  end