bikepoa-tools 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --format doc
data/.rvmrc ADDED
@@ -0,0 +1,2 @@
1
+ rvm_install_on_use_flag=1
2
+ rvm use --create 1.9.3@bikepoa-tools
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.2"
4
+ - "1.9.3"
5
+ - jruby-19mode # JRuby in 1.9 mode
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rake'
4
+ gem 'rspec'
5
+ gem 'hashie'
6
+ gem 'active_support'
7
+ gem 'rspec'
8
+
9
+ group :test do
10
+ gem 'fakeweb'
11
+ gem 'pry'
12
+ end
13
+
14
+ group :development do
15
+ gem 'bundler'
16
+ gem 'jeweler'
17
+ gem 'rdoc'
18
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,48 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ active_support (3.0.0)
5
+ activesupport (= 3.0.0)
6
+ activesupport (3.0.0)
7
+ coderay (1.0.8)
8
+ diff-lcs (1.1.3)
9
+ fakeweb (1.3.0)
10
+ git (1.2.5)
11
+ hashie (1.2.0)
12
+ jeweler (1.8.4)
13
+ bundler (~> 1.0)
14
+ git (>= 1.2.5)
15
+ rake
16
+ rdoc
17
+ json (1.7.5)
18
+ method_source (0.8.1)
19
+ pry (0.9.10)
20
+ coderay (~> 1.0.5)
21
+ method_source (~> 0.8)
22
+ slop (~> 3.3.1)
23
+ rake (0.9.2.2)
24
+ rdoc (3.12)
25
+ json (~> 1.4)
26
+ rspec (2.12.0)
27
+ rspec-core (~> 2.12.0)
28
+ rspec-expectations (~> 2.12.0)
29
+ rspec-mocks (~> 2.12.0)
30
+ rspec-core (2.12.2)
31
+ rspec-expectations (2.12.1)
32
+ diff-lcs (~> 1.1.3)
33
+ rspec-mocks (2.12.0)
34
+ slop (3.3.3)
35
+
36
+ PLATFORMS
37
+ ruby
38
+
39
+ DEPENDENCIES
40
+ active_support
41
+ bundler
42
+ fakeweb
43
+ hashie
44
+ jeweler
45
+ pry
46
+ rake
47
+ rdoc
48
+ rspec
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Felipe Mobus
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ [![Build Status](https://travis-ci.org/fmobus/bikepoa-tools.png)](https://travis-ci.org/fmobus/bikepoa-tools)
2
+ [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/fmobus/bikepoa-tools)
3
+
4
+ bikepoa-tools
5
+ =============
6
+
7
+ A simple API to interact with information systems of [BikePOA](http://mobilicidade.com.br/bikepoa/), the
8
+ bicycle-sharing program of Porto Alegre, Brazil.
9
+
10
+ usage
11
+ =====
12
+
13
+ ```ruby
14
+ >>> require './lib/bikepoa'
15
+ >>> client = BikePOA::Client.new
16
+ >>> client.stations
17
+ [
18
+ <BikePOA::Station:0x007fd60191aeb8
19
+ @id="1", @online="A", @status="EO", @size="12", @available="6"
20
+ @name="Mercado", @address="Rua Marechal Floriano, 66, entre a ...">,
21
+ ...
22
+ ]
23
+ >>> s.select(&:active?).map(&:to_s)
24
+ [
25
+ "<Station:Mercado, 0/12>",
26
+ "<Station:Pra\xE7a da Alf\xE2ndega, 1/12>",
27
+ "<Station:Casa de Cultura Mario Quintana, 4/12>",
28
+ "<Station:Usina do Gas\xF4metro, 0/12>",
29
+ "<Station:C\xE2mara de Vereadores, 5/12>",
30
+ "<Station:Largo Zumbi, 3/14>",
31
+ "<Station:Gin\xE1sio Tesourinha, 6/12>",
32
+ "<Station:Shopping Praia de Belas, 3/12>",
33
+ "<Station:Hospital M\xE3e de Deus, 5/14>",
34
+ "<Station:Terminal Azenha, 3/12>",
35
+ "<Station:Barra Shopping, 7/14>",
36
+ "<Station:Escola Parob\xE9, 3/12>",
37
+ "<Station:Regi\xE3o dos Tribunais, 5/12>"
38
+ ]
39
+ ```
40
+
41
+ todo
42
+ ====
43
+
44
+ * Package it as a gem
45
+ * Add latitude and longitude to Station
46
+ * Less crude interface in Station
data/README.rdoc ADDED
@@ -0,0 +1,19 @@
1
+ = bikepoa-tools
2
+
3
+ Description goes here.
4
+
5
+ == Contributing to bikepoa-tools
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
9
+ * Fork the project.
10
+ * Start a feature/bugfix branch.
11
+ * Commit and push until you are happy with your contribution.
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2012 Felipe Mobus. See LICENSE.txt for
18
+ further details.
19
+
data/Rakefile ADDED
@@ -0,0 +1,42 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ RSpec::Core::RakeTask.new(:spec)
4
+
5
+ task :default => :spec
6
+
7
+ # encoding: utf-8
8
+
9
+ require 'rubygems'
10
+ require 'bundler'
11
+ begin
12
+ Bundler.setup(:default, :development)
13
+ rescue Bundler::BundlerError => e
14
+ $stderr.puts e.message
15
+ $stderr.puts "Run `bundle install` to install missing gems"
16
+ exit e.status_code
17
+ end
18
+ require 'rake'
19
+
20
+ require 'jeweler'
21
+ Jeweler::Tasks.new do |gem|
22
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
23
+ gem.name = "bikepoa-tools"
24
+ gem.homepage = "http://github.com/fmobus/bikepoa-tools"
25
+ gem.license = "MIT"
26
+ gem.summary = "A simple read-only API for Porto Alegre's bike rental system, bikepoa."
27
+ gem.description = "A simple read-only API for Porto Alegre's bike rental system, bikepoa."
28
+ gem.email = "fmobus@gmail.com"
29
+ gem.authors = ["Felipe Mobus"]
30
+ # dependencies defined in Gemfile
31
+ end
32
+ Jeweler::RubygemsDotOrgTasks.new
33
+
34
+ require 'rdoc/task'
35
+ Rake::RDocTask.new do |rdoc|
36
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
37
+
38
+ rdoc.rdoc_dir = 'rdoc'
39
+ rdoc.title = "bikepoa-tools #{version}"
40
+ rdoc.rdoc_files.include('README*')
41
+ rdoc.rdoc_files.include('lib/**/*.rb')
42
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,85 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "bikepoa-tools"
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Felipe Mobus"]
12
+ s.date = "2012-12-30"
13
+ s.description = "A simple read-only API for Porto Alegre's bike rental system, bikepoa."
14
+ s.email = "fmobus@gmail.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.md",
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ ".rspec",
22
+ ".rvmrc",
23
+ ".travis.yml",
24
+ "Gemfile",
25
+ "Gemfile.lock",
26
+ "LICENSE.txt",
27
+ "README.md",
28
+ "README.rdoc",
29
+ "Rakefile",
30
+ "VERSION",
31
+ "bikepoa-tools.gemspec",
32
+ "lib/bikepoa.rb",
33
+ "lib/bikepoa/client.rb",
34
+ "lib/bikepoa/helpers.rb",
35
+ "lib/bikepoa/http_client.rb",
36
+ "lib/bikepoa/map_parser.rb",
37
+ "lib/bikepoa/station.rb",
38
+ "spec/client_spec.rb",
39
+ "spec/fixtures/full_page.html",
40
+ "spec/helpers_spec.rb",
41
+ "spec/http_client_spec.rb",
42
+ "spec/map_parser_spec.rb",
43
+ "spec/spec_helper.rb",
44
+ "spec/station_spec.rb"
45
+ ]
46
+ s.homepage = "http://github.com/fmobus/bikepoa-tools"
47
+ s.licenses = ["MIT"]
48
+ s.require_paths = ["lib"]
49
+ s.rubygems_version = "1.8.24"
50
+ s.summary = "A simple read-only API for Porto Alegre's bike rental system, bikepoa."
51
+
52
+ if s.respond_to? :specification_version then
53
+ s.specification_version = 3
54
+
55
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
56
+ s.add_runtime_dependency(%q<rake>, [">= 0"])
57
+ s.add_runtime_dependency(%q<rspec>, [">= 0"])
58
+ s.add_runtime_dependency(%q<hashie>, [">= 0"])
59
+ s.add_runtime_dependency(%q<active_support>, [">= 0"])
60
+ s.add_runtime_dependency(%q<rspec>, [">= 0"])
61
+ s.add_development_dependency(%q<bundler>, [">= 0"])
62
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
63
+ s.add_development_dependency(%q<rdoc>, [">= 0"])
64
+ else
65
+ s.add_dependency(%q<rake>, [">= 0"])
66
+ s.add_dependency(%q<rspec>, [">= 0"])
67
+ s.add_dependency(%q<hashie>, [">= 0"])
68
+ s.add_dependency(%q<active_support>, [">= 0"])
69
+ s.add_dependency(%q<rspec>, [">= 0"])
70
+ s.add_dependency(%q<bundler>, [">= 0"])
71
+ s.add_dependency(%q<jeweler>, [">= 0"])
72
+ s.add_dependency(%q<rdoc>, [">= 0"])
73
+ end
74
+ else
75
+ s.add_dependency(%q<rake>, [">= 0"])
76
+ s.add_dependency(%q<rspec>, [">= 0"])
77
+ s.add_dependency(%q<hashie>, [">= 0"])
78
+ s.add_dependency(%q<active_support>, [">= 0"])
79
+ s.add_dependency(%q<rspec>, [">= 0"])
80
+ s.add_dependency(%q<bundler>, [">= 0"])
81
+ s.add_dependency(%q<jeweler>, [">= 0"])
82
+ s.add_dependency(%q<rdoc>, [">= 0"])
83
+ end
84
+ end
85
+
data/lib/bikepoa.rb ADDED
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+ require 'hashie'
3
+ require 'active_support/inflector'
4
+
5
+ module BikePOA
6
+ def self.configure(&block)
7
+ yield params = Hashie::Mash.new
8
+ @config = params
9
+ end
10
+
11
+ def self.config
12
+ @config or {}
13
+ end
14
+
15
+ def self.root(*parts)
16
+ File.join(File.dirname(__FILE__), *parts)
17
+ end
18
+
19
+ %w[helpers client http_client map_parser station].each do |name|
20
+ autoload name.camelize.to_sym, BikePOA.root("bikepoa/#{name}")
21
+ end
22
+ end
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+ module BikePOA
3
+ class Client
4
+ def initialize
5
+ @http_client = HttpClient.new
6
+ @map_parser = MapParser.new
7
+ end
8
+
9
+ def stations
10
+ map_page = @http_client.fetch
11
+ @map_parser.parse(map_page).map do |station_data|
12
+ Station.new(station_data)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,20 @@
1
+ module BikePOA
2
+ module Helpers
3
+ module ForceField
4
+ def self.included(base)
5
+ base.send :extend, ClassMethods
6
+ end
7
+
8
+ module ClassMethods
9
+ def force_integer(field)
10
+ class_eval do
11
+ define_method("#{field}=".to_sym) do |value|
12
+ self.[]=(field, Integer(value))
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+ require 'net/http'
3
+
4
+ module BikePOA
5
+ DEFAULT_URI = 'http://ww2.mobilicidade.com.br/bikepoa/mapaestacao.asp'
6
+ class HttpClient
7
+ def fetch
8
+ location = BikePOA.config['bikepoa:uri'] || DEFAULT_URI
9
+ Net::HTTP.get URI(location)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+ require 'csv'
3
+
4
+ module BikePOA
5
+ class MapParser
6
+ CRIAPONTO = /criaPonto\(point,(.*)\) \);/
7
+ def parse(content)
8
+ content.scan(CRIAPONTO).map do |station_match|
9
+ line_data = CSV.parse_line(station_match.first, quote_char: "'")
10
+ fields = %w[id name address _ _ _ online status size available _ _]
11
+ Hash[fields.zip(line_data)].delete_if { |key,value| key == '_' }
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+ #
3
+ module BikePOA
4
+ class Station < Hashie::Dash
5
+ include Helpers::ForceField
6
+
7
+ property :id
8
+ property :size
9
+ property :available
10
+ property :name
11
+ property :address
12
+ property :online
13
+ property :status
14
+
15
+ force_integer :id
16
+ force_integer :size
17
+ force_integer :available
18
+
19
+ def active?
20
+ self.online == 'A'
21
+ end
22
+
23
+ def to_s
24
+ "<Station##{self.id}:#{self.name}, #{self.available}/#{self.size}>"
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe BikePOA::Client do
5
+ describe 'parses latest bikepoa status' do
6
+ it 'extracts the status of several stations' do
7
+ BikePOA::HttpClient.any_instance.should_receive(:fetch).and_return('html-file')
8
+ BikePOA::MapParser.any_instance.should_receive(:parse).with('html-file').and_return(%w[line1 line2])
9
+ BikePOA::Station.should_receive(:new).with('line1').and_return('station1')
10
+ BikePOA::Station.should_receive(:new).with('line2').and_return('station2')
11
+
12
+ subject.stations.should include('station1','station2')
13
+ end
14
+ end
15
+ end