translink 1.0.0 → 2.0.0

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