translink 1.0.0 → 2.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.
data/CHANGELOG.md CHANGED
@@ -1,9 +1,16 @@
1
1
  # Changelog
2
2
 
3
- ## Current
3
+ ## 2012-07-21 / v2.0.0
4
+
5
+ * Add headsign column to trips table.
6
+ * Direction column distinguishes between travelling in one direction (Regular)
7
+ and opposite direction (Goofy).
8
+ * Headsign column is a human readable name for the given direction. Eg "Inbound".
9
+
10
+ ## 2012-06-26 / v1.0.0
4
11
 
5
12
  * Compatibility with Translink website (2012-05-29).
6
- * Changed schema to conform with Google Transit feed specification.
13
+ * Changed schema to conform with General Transit Feed Specification.
7
14
  * Stops include latitude and longitude fields.
8
15
  * Help command always gives working example.
9
16
 
data/README.md CHANGED
@@ -6,10 +6,14 @@
6
6
  South-East Queensland. Their website has an abundance of data with no easy way for a developer
7
7
  to query it.
8
8
 
9
- Translink (Program) scrapes bus routes, trips, stops and times into a relational database.
9
+ Translink (Program) scrapes bus routes, trips, stops and times into a relational database.
10
+ The schema is a subset of the [General Transit Feed Specification](https://developers.google.com/transit/gtfs/reference).
10
11
  Data is sourced from the [Translink website](http://translink.com.au/).You should be
11
12
  aware their data is protected by [copyright](http://translink.com.au/site-information/legal/copyright).
12
13
 
14
+ I created Translink (Program) to solve my problem of getting lost on new routes. With this data I
15
+ have been working on an app for iOS called [Next Stop](http://nextstop.me).
16
+
13
17
  ## Installation
14
18
 
15
19
  Translink requires Ruby 1.9.2 or greater. For documentation on how to install Ruby on your
@@ -50,10 +54,15 @@ Routes that visit the 'Calam Rd near Honeywood St' stop.
50
54
 
51
55
  ## Schema
52
56
 
57
+ Schema is a subset of the [General Transit Feed Specification](https://developers.google.com/transit/gtfs/reference)
58
+ defined by Google for [Google Transit](https://developers.google.com/transit/google-transit).
59
+
53
60
  ![Class Analysis Diagram](https://github.com/tatey/translink/raw/master/doc/schema.png)
54
61
 
55
62
  ## Contributing
56
63
 
64
+ If you would like to help, please browse the [issues](https://github.com/tatey/translink/issues).
65
+
57
66
  1. Fork it
58
67
  2. Install dependencies (`bundle install`)
59
68
  3. Create your feature branch (`git checkout -b my-new-feature`)
data/lib/translink.rb CHANGED
@@ -7,6 +7,7 @@ require 'translink/version'
7
7
  require 'translink/cli'
8
8
  require 'translink/crawler'
9
9
  require 'translink/db'
10
+ require 'translink/direction'
10
11
  require 'translink/model/route'
11
12
  require 'translink/model/stop'
12
13
  require 'translink/model/stop_time'
@@ -0,0 +1,6 @@
1
+ module Translink
2
+ module Direction
3
+ REGULAR = 0 # Travel in one direction.
4
+ GOOFY = 1 # Travel in opposite direction.
5
+ end
6
+ end
@@ -6,7 +6,8 @@ module Translink
6
6
  storage_names[:default] = 'trips'
7
7
 
8
8
  property :id, Serial
9
- property :direction, String
9
+ property :direction, Integer # Travel in one direction (Regular) or the opposite (Goofy) direction.
10
+ property :headsign, String # Name of the direction. Eg "Inbound".
10
11
  property :service_id, Integer # Service belongs to a trip. Assigned by Translink.
11
12
  property :trip_id, Integer # Unique ID assigned by Translink.
12
13
 
@@ -40,6 +41,7 @@ module Translink
40
41
  # @return [void]
41
42
  def trip_page! trip_page
42
43
  self.direction = trip_page.direction
44
+ self.headsign = trip_page.headsign
43
45
  self.service_id = trip_page.service_id
44
46
  self.trip_id = trip_page.trip_id
45
47
  end
@@ -31,12 +31,28 @@ module Translink
31
31
  DateTime.parse page.search('select#TimetableDate option[selected]').first['value']
32
32
  end
33
33
 
34
+ # Get headsigns of directions travelled by this route.
35
+ #
36
+ # @return [Array<String>]
37
+ def headsigns
38
+ page.search('h3').map { |node| node.text.downcase }.uniq
39
+ end
40
+
41
+ # Get the direction of travel for the given +anchor+.
42
+ #
43
+ # @param anchor [Nokogiri::XML::Node] Anchor to ascend from.
44
+ # @return [Integer] +0+ for one (Regular) direction of travel, +1+ for
45
+ # opposite (Goofy) direction of travel.
46
+ def direction_from_anchor anchor
47
+ headsigns.index anchor.ancestors('div.route-timetable').search('h3').first.text.downcase
48
+ end
49
+
34
50
  # Builds an array of trip pages.
35
51
  #
36
52
  # @return [Array<Page::Trip>]
37
53
  def trip_pages
38
54
  page.search('a.map-link-top').map do |anchor|
39
- Trip.new url_from_href(anchor[:href]), date
55
+ Trip.new url_from_href(anchor[:href]), date, direction_from_anchor(anchor)
40
56
  end
41
57
  end
42
58
 
@@ -61,21 +61,24 @@ module Translink
61
61
  end
62
62
  end
63
63
 
64
- attr_accessor :date # [Date] Date the trip runs on.
64
+ attr_accessor :date # [Date] Date the trip runs on.
65
+ attr_accessor :direction # [Integer] Travel in one direction (Regular)
66
+ # or the opposite (Goofy) direction.
65
67
 
66
68
  # Creates a new trip.
67
69
  #
68
70
  # @param url [String] URL to fetch the page from.
69
71
  # @param date [Date] Date the trip runs on.
70
- def initialize url, date
72
+ def initialize url, date, direction
71
73
  super url
72
74
  @date = date.to_date
75
+ @direction = direction
73
76
  end
74
77
 
75
- # Get the trip's direction of travel.
78
+ # Get the trip's headsign.
76
79
  #
77
80
  # @return [String] "inbound" or "outbound".
78
- def direction
81
+ def headsign
79
82
  url.to_s =~ /information\/([a-z]+)\//
80
83
  $1
81
84
  end
@@ -1,3 +1,3 @@
1
1
  module Translink
2
- VERSION = '1.0.0'
2
+ VERSION = '2.0.0'
3
3
  end
data/test/helper.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'minitest/autorun'
2
+ require 'pry'
2
3
  require 'translink'
3
4
  require 'webmock/minitest'
4
5
 
@@ -15,7 +15,7 @@ class Model::RouteTest < MiniTest::Unit::TestCase
15
15
 
16
16
  def test_add_trip_from_trip_page
17
17
  DB.context 'sqlite::memory:', :migrate => true do
18
- trip_page = OpenStruct.new :direction => 'outbound', :service_id => 8550, :trip_id => 1712196
18
+ trip_page = OpenStruct.new :direction => Direction::REGULAR, :headsign => 'outbound', :service_id => 8550, :trip_id => 1712196
19
19
  route_model = Model::Route.new
20
20
  trip_model = route_model.add_trip_from_trip_page trip_page
21
21
  assert trip_model.saved?
@@ -1,32 +1,43 @@
1
1
  require 'helper'
2
2
 
3
3
  class Page::RouteTest < MiniTest::Unit::TestCase
4
- def test_date
4
+ attr_accessor :route
5
+
6
+ def setup
5
7
  stub_request(:get, 'http://jp.translink.com.au/travel-information/network-information/buses/130/2012-06-21').
6
8
  to_return(:status => 200, :body => fixture('verbatim/route.html'), :headers => {'Content-Type' => 'text/html'})
7
- assert_equal DateTime.parse('21/06/2012 12:00:00 AM'), Page::Route.new('http://jp.translink.com.au/travel-information/network-information/buses/130/2012-06-21', 'City, Griffith Uni, Sunnybank Hills, Algester, Parkinson').date
9
+ @route = Page::Route.new 'http://jp.translink.com.au/travel-information/network-information/buses/130/2012-06-21', 'City, Griffith Uni, Sunnybank Hills, Algester, Parkinson'
8
10
  end
9
11
 
10
- def test_long_name
11
- route = Page::Route.new('http://local', 'City, Griffith Uni, Sunnybank Hills, Algester, Parkinson')
12
- assert_equal 'City, Griffith Uni, Sunnybank Hills, Algester, Parkinson', route.long_name
12
+ def test_date
13
+ assert_equal DateTime.parse('21/06/2012 12:00:00 AM'), route.date
14
+ end
15
+
16
+ def test_headsigns
17
+ assert_equal ['outbound', 'inbound'], route.headsigns
13
18
  end
14
19
 
15
20
  def test_short_name
16
- stub_request(:get, 'http://jp.translink.com.au/travel-information/network-information/buses/130/2012-06-21').
17
- to_return(:status => 200, :body => fixture('verbatim/route.html'), :headers => {'Content-Type' => 'text/html'})
18
- assert_equal '130', Page::Route.new('http://jp.translink.com.au/travel-information/network-information/buses/130/2012-06-21', 'City, Griffith Uni, Sunnybank Hills, Algester, Parkinson').short_name
21
+ assert_equal '130', route.short_name
19
22
  end
20
23
 
21
24
  def test_trip_pages
22
- stub_request(:get, 'http://jp.translink.com.au/travel-information/network-information/buses/130/2012-06-21').
23
- to_return(:status => 200, :body => fixture('verbatim/route.html'), :headers => {'Content-Type' => 'text/html'})
24
- route = Page::Route.new('http://jp.translink.com.au/travel-information/network-information/buses/130/2012-06-21', 'City, Griffith Uni, Sunnybank Hills, Algester, Parkinson')
25
25
  trip_pages = route.trip_pages
26
- assert_equal 'http://jp.translink.com.au/travel-information/network-information/service-information/outbound/8904/1891449/2012-06-20', trip_pages.first.url.to_s
27
- assert_equal route.date.to_date, trip_pages.first.date
28
- assert_equal 'http://jp.translink.com.au/travel-information/network-information/service-information/inbound/8904/1881543/2012-06-22', trip_pages.last.url.to_s
29
- assert_equal route.date.to_date, trip_pages.last.date
26
+ trip1 = trip_pages.first
27
+ trip2 = trip_pages.last
28
+ assert_equal 'http://jp.translink.com.au/travel-information/network-information/service-information/outbound/8904/1891449/2012-06-20', trip1.url.to_s
29
+ assert_equal route.date.to_date, trip1.date
30
+ assert_equal Direction::REGULAR, trip1.direction
31
+ assert_equal 'http://jp.translink.com.au/travel-information/network-information/service-information/inbound/8904/1881543/2012-06-22', trip2.url.to_s
32
+ assert_equal route.date.to_date, trip2.date
33
+ assert_equal Direction::GOOFY, trip2.direction
34
+ end
35
+ end
36
+
37
+ class Page::RouteLongNameTest < MiniTest::Unit::TestCase
38
+ def test_long_name
39
+ route = Page::Route.new('http://local', 'City, Griffith Uni, Sunnybank Hills, Algester, Parkinson')
40
+ assert_equal 'City, Griffith Uni, Sunnybank Hills, Algester, Parkinson', route.long_name
30
41
  end
31
42
  end
32
43
 
@@ -3,16 +3,22 @@ require 'helper'
3
3
  class Page::TripTest < MiniTest::Unit::TestCase
4
4
  def test_date
5
5
  timestamp = DateTime.now
6
- assert_equal timestamp.to_date, Page::Trip.new('http://localhost', timestamp).date
6
+ assert_equal timestamp.to_date, Page::Trip.new('http://localhost', timestamp, Direction::REGULAR).date
7
7
  date = Date.today
8
- assert_equal date, Page::Trip.new('http://localhost', date).date
8
+ assert_equal date, Page::Trip.new('http://localhost', date, Direction::REGULAR).date
9
9
  end
10
10
 
11
11
  def test_direction
12
- assert_equal 'inbound', Page::Trip.new('http://jp.translink.com.au/travel-information/network-information/service-information/inbound/8550/1704728', Date.today).direction
13
- assert_equal 'outbound', Page::Trip.new('http://jp.translink.com.au/travel-information/network-information/service-information/outbound/8550/1712196/2012-05-31', Date.today).direction
14
- assert_equal 'counterclockwise', Page::Trip.new('http://jp.translink.com.au/travel-information/network-information/service-information/counterclockwise/8904/1882248/2012-06-25', Date.today).direction
15
- assert_equal 'clockwise', Page::Trip.new('http://jp.translink.com.au/travel-information/network-information/service-information/clockwise/8904/1882152/2012-06-25', Date.today).direction
12
+ timestamp = DateTime.now
13
+ assert_equal Direction::REGULAR, Page::Trip.new('http://localhost', timestamp, Direction::REGULAR).direction
14
+ assert_equal Direction::GOOFY, Page::Trip.new('http://localhost', timestamp, Direction::GOOFY).direction
15
+ end
16
+
17
+ def test_headsign
18
+ assert_equal 'inbound', Page::Trip.new('http://jp.translink.com.au/travel-information/network-information/service-information/inbound/8550/1704728', Date.today, Direction::GOOFY).headsign
19
+ assert_equal 'outbound', Page::Trip.new('http://jp.translink.com.au/travel-information/network-information/service-information/outbound/8550/1712196/2012-05-31', Date.today, Direction::REGULAR).headsign
20
+ assert_equal 'counterclockwise', Page::Trip.new('http://jp.translink.com.au/travel-information/network-information/service-information/counterclockwise/8904/1882248/2012-06-25', Date.today, Direction::GOOFY).headsign
21
+ assert_equal 'clockwise', Page::Trip.new('http://jp.translink.com.au/travel-information/network-information/service-information/clockwise/8904/1882152/2012-06-25', Date.today, Direction::REGULAR).headsign
16
22
  end
17
23
  end
18
24
 
@@ -23,7 +29,7 @@ class Page::TripRequestTest < MiniTest::Unit::TestCase
23
29
  end
24
30
 
25
31
  def stub_trip
26
- Page::Trip.new('http://jp.translink.com.au/travel-information/network-information/service-information/outbound/8550/1712196/2012-05-31', Date.today)
32
+ Page::Trip.new('http://jp.translink.com.au/travel-information/network-information/service-information/outbound/8550/1712196/2012-05-31', Date.today, Direction::REGULAR)
27
33
  end
28
34
 
29
35
  def test_service_id
data/translink.gemspec CHANGED
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
20
20
  s.add_runtime_dependency 'dm-migrations', '~> 1.2.0'
21
21
  s.add_runtime_dependency 'dm-sqlite-adapter', '~> 1.2.0'
22
22
  s.add_runtime_dependency 'mechanize', '~> 2.0.1'
23
+ s.add_development_dependency 'pry'
23
24
  s.add_development_dependency 'rake', '~> 0.9.2'
24
25
  s.add_development_dependency 'webmock', '~> 1.7.8'
25
26
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: translink
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-25 00:00:00.000000000 Z
12
+ date: 2012-07-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: dm-core
16
- requirement: &70170271474960 !ruby/object:Gem::Requirement
16
+ requirement: &70220170640540 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.2.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70170271474960
24
+ version_requirements: *70220170640540
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: dm-migrations
27
- requirement: &70170271474500 !ruby/object:Gem::Requirement
27
+ requirement: &70220170639960 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.2.0
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70170271474500
35
+ version_requirements: *70220170639960
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: dm-sqlite-adapter
38
- requirement: &70170271474040 !ruby/object:Gem::Requirement
38
+ requirement: &70220170639060 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 1.2.0
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70170271474040
46
+ version_requirements: *70220170639060
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: mechanize
49
- requirement: &70170271473580 !ruby/object:Gem::Requirement
49
+ requirement: &70220170638380 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,21 @@ dependencies:
54
54
  version: 2.0.1
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70170271473580
57
+ version_requirements: *70220170638380
58
+ - !ruby/object:Gem::Dependency
59
+ name: pry
60
+ requirement: &70220170638000 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70220170638000
58
69
  - !ruby/object:Gem::Dependency
59
70
  name: rake
60
- requirement: &70170271753220 !ruby/object:Gem::Requirement
71
+ requirement: &70220170637340 !ruby/object:Gem::Requirement
61
72
  none: false
62
73
  requirements:
63
74
  - - ~>
@@ -65,10 +76,10 @@ dependencies:
65
76
  version: 0.9.2
66
77
  type: :development
67
78
  prerelease: false
68
- version_requirements: *70170271753220
79
+ version_requirements: *70220170637340
69
80
  - !ruby/object:Gem::Dependency
70
81
  name: webmock
71
- requirement: &70170271454480 !ruby/object:Gem::Requirement
82
+ requirement: &70220170636820 !ruby/object:Gem::Requirement
72
83
  none: false
73
84
  requirements:
74
85
  - - ~>
@@ -76,7 +87,7 @@ dependencies:
76
87
  version: 1.7.8
77
88
  type: :development
78
89
  prerelease: false
79
- version_requirements: *70170271454480
90
+ version_requirements: *70220170636820
80
91
  description: Scrapes bus routes, trips, stops and times into a relational database.
81
92
  email:
82
93
  - tate@tatey.com
@@ -99,6 +110,7 @@ files:
99
110
  - lib/translink/cli.rb
100
111
  - lib/translink/crawler.rb
101
112
  - lib/translink/db.rb
113
+ - lib/translink/direction.rb
102
114
  - lib/translink/model/route.rb
103
115
  - lib/translink/model/stop.rb
104
116
  - lib/translink/model/stop_time.rb
@@ -146,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
158
  version: '0'
147
159
  segments:
148
160
  - 0
149
- hash: 3982084261629869304
161
+ hash: -132775799840568295
150
162
  requirements: []
151
163
  rubyforge_project: translink
152
164
  rubygems_version: 1.8.11