atco 0.0.2 → 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 +7 -0
- data/{README.mdown → README.md} +22 -12
- data/Rakefile +10 -12
- data/VERSION +1 -1
- data/lib/atco/journey.rb +52 -34
- data/lib/atco/location.rb +9 -11
- data/lib/atco/stop.rb +22 -13
- data/lib/atco.rb +105 -106
- data/spec/atco_spec.rb +135 -111
- data/spec/fixtures/example.cif +30 -0
- data/spec/fixtures/example.json +98 -0
- data/spec/spec_helper.rb +5 -1
- metadata +62 -47
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 91d4d697f6d487218aa3def133f0104257141ed8fb18b93be2c3f0c52ac92a6e
|
4
|
+
data.tar.gz: 213d51b686a0076c69f26b6d18173dd2b767eaf24db17f7e0cdc011406b94705
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fb0ccef50c6a0490c9b87b0b01a7179bec8ca755d594f52193ef6220ef6733e2c8ed600f46043c3a0a38038f3290a8687f1828adfe893dac7dad5c7413b23c89
|
7
|
+
data.tar.gz: 6ba15c31b4cfb1873577af0fe50c62c6325780d9f9c3c6ddb124cfe91397dd2808382757f1198f492ea6fbbe2a21131e010b49ac80a757f33041a3ff57db1d9f
|
data/{README.mdown → README.md}
RENAMED
@@ -2,11 +2,14 @@
|
|
2
2
|
|
3
3
|
ATCO-CIF is the format of choice for UK public transport authorities. This is a ruby library that reads **.cif** files and gives you JSON back.
|
4
4
|
|
5
|
+
* ATCO (Association of Transport Coordinating Officers)
|
6
|
+
* CIF (Common Interface File)
|
7
|
+
|
5
8
|
* **Official spec:** [http://www.pti.org.uk/CIF/atco-cif-spec.pdf](http://www.pti.org.uk/CIF/atco-cif-spec.pdf)
|
6
9
|
|
7
10
|
### USAGE
|
8
11
|
|
9
|
-
Currently this library is under-development and has several things left to do before it is perfect (see the [todo.
|
12
|
+
Currently this library is under-development and has several things left to do before it is perfect (see the [todo.md](http://github.com/davidjrice/atco/blob/master/TODO.md) list ).
|
10
13
|
|
11
14
|
* clone this library
|
12
15
|
* start an irb session
|
@@ -14,14 +17,21 @@ Currently this library is under-development and has several things left to do be
|
|
14
17
|
|
15
18
|
Code example, for more detailed internal api usage see the spec files.
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
gem install atco
|
23
|
+
irb
|
24
|
+
|
25
|
+
|
26
|
+
require 'rubygems
|
27
|
+
require 'atco'
|
28
|
+
|
29
|
+
result = Atco.parse('filename.cif')
|
30
|
+
result = Atco.parse('SVRTMAO009A-20091005.cif) # an example data file in the repo
|
31
|
+
|
32
|
+
=> {
|
33
|
+
header: {…},
|
34
|
+
locations: […],
|
35
|
+
journies: {…}
|
36
|
+
}
|
37
|
+
```
|
data/Rakefile
CHANGED
@@ -1,14 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
1
6
|
begin
|
2
|
-
|
3
|
-
Jeweler::Tasks.new do |s|
|
4
|
-
s.name = "atco"
|
5
|
-
s.summary = "Simple and opinionated library for parsing ATCO-CIF files with Ruby."
|
6
|
-
s.email = "me@davidjrice.co.uk"
|
7
|
-
s.homepage = "http://github.com/davidjrice/atco"
|
8
|
-
s.description = "Simple and opinionated library for parsing ATCO-CIF files with Ruby."
|
9
|
-
s.authors = ["David Rice"]
|
10
|
-
s.files = FileList["[A-Z]*", "{bin,generators,lib,test}/**/*", 'lib/jeweler/templates/.gitignore']
|
11
|
-
end
|
7
|
+
RSpec::Core::RakeTask.new(:spec)
|
12
8
|
rescue LoadError
|
13
|
-
puts
|
14
|
-
end
|
9
|
+
puts 'RSpec, or one of its dependencies, is not available. Install it with: bundle install'
|
10
|
+
end
|
11
|
+
|
12
|
+
task default: :spec
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
1.0.0
|
data/lib/atco/journey.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Atco
|
2
|
-
|
3
4
|
class Journey
|
4
|
-
|
5
|
-
|
6
|
-
:first_date_of_operation, :running_board, :last_date_of_operation, :school_term_time, :route_direction, :bank_holidays
|
7
|
-
|
8
|
-
attr_accessor :stops
|
5
|
+
attr_accessor :vehicle_type, :registration_number, :identifier, :operator, :route_number, :first_date_of_operation,
|
6
|
+
:running_board, :last_date_of_operation, :school_term_time, :route_direction, :bank_holidays, :stops
|
9
7
|
|
10
8
|
def initialize(data)
|
11
9
|
@mondays = parse_boolean_int data[:operates_on_mondays]
|
@@ -15,7 +13,7 @@ module Atco
|
|
15
13
|
@fridays = parse_boolean_int data[:operates_on_fridays]
|
16
14
|
@saturdays = parse_boolean_int data[:operates_on_saturdays]
|
17
15
|
@sundays = parse_boolean_int data[:operates_on_sundays]
|
18
|
-
|
16
|
+
|
19
17
|
@vehicle_type = data[:vehicle_type]
|
20
18
|
@registration_number = data[:registration_number]
|
21
19
|
@identifier = data[:unique_journey_identifier]
|
@@ -27,40 +25,60 @@ module Atco
|
|
27
25
|
@running_board = data[:running_board]
|
28
26
|
@school_term_time = data[:school_term_time]
|
29
27
|
@bank_holidays = data[:bank_holidays]
|
30
|
-
|
28
|
+
|
31
29
|
@stops = []
|
32
|
-
|
33
|
-
|
34
|
-
|
30
|
+
# stops.each do |s|
|
31
|
+
# @stops << Stop.new(s)
|
32
|
+
# end
|
33
|
+
end
|
34
|
+
|
35
|
+
def mondays?
|
36
|
+
@mondays
|
37
|
+
end
|
38
|
+
|
39
|
+
def tuesdays?
|
40
|
+
@tuesdays
|
41
|
+
end
|
42
|
+
|
43
|
+
def wednesdays?
|
44
|
+
@wednesdays
|
45
|
+
end
|
46
|
+
|
47
|
+
def thursdays?
|
48
|
+
@thursdays
|
49
|
+
end
|
50
|
+
|
51
|
+
def fridays?
|
52
|
+
@fridays
|
53
|
+
end
|
54
|
+
|
55
|
+
def saturdays?
|
56
|
+
@saturdays
|
57
|
+
end
|
58
|
+
|
59
|
+
def sundays?
|
60
|
+
@sundays
|
35
61
|
end
|
36
62
|
|
37
|
-
def mondays?; @mondays; end
|
38
|
-
def tuesdays?; @tuesdays; end
|
39
|
-
def wednesdays?; @wednesdays; end
|
40
|
-
def thursdays?; @thursdays; end
|
41
|
-
def fridays?; @fridays; end
|
42
|
-
def saturdays?; @saturdays; end
|
43
|
-
def sundays?; @sundays; end
|
44
|
-
|
45
63
|
def parse_boolean_int(string)
|
46
|
-
|
64
|
+
string && string == '1' ? true : false
|
47
65
|
end
|
48
|
-
|
66
|
+
|
49
67
|
def to_json(*args)
|
50
68
|
{
|
51
|
-
:
|
52
|
-
:
|
53
|
-
:
|
54
|
-
:
|
55
|
-
:
|
56
|
-
:
|
57
|
-
:
|
58
|
-
:
|
59
|
-
:
|
60
|
-
:
|
61
|
-
:
|
62
|
-
:
|
69
|
+
vehicle_type: @vehicle_type,
|
70
|
+
registration_number: @registration_number,
|
71
|
+
identifier: @identifier,
|
72
|
+
operator: @operator,
|
73
|
+
route_number: @route_number,
|
74
|
+
first_date_of_operation: @first_date_of_operation,
|
75
|
+
running_board: @running_board,
|
76
|
+
last_date_of_operation: @last_date_of_operation,
|
77
|
+
school_term_time: @school_term_time,
|
78
|
+
route_direction: @route_direction,
|
79
|
+
bank_holidays: @bank_holidays,
|
80
|
+
stops: @stops
|
63
81
|
}.to_json(*args)
|
64
82
|
end
|
65
83
|
end
|
66
|
-
end
|
84
|
+
end
|
data/lib/atco/location.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Atco
|
2
|
-
|
3
4
|
class Location
|
4
|
-
|
5
5
|
attr_accessor :name, :identifier, :easting, :northing, :gazeteer_code
|
6
6
|
|
7
7
|
def initialize(location_header, additional_location_information)
|
@@ -13,15 +13,13 @@ module Atco
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def to_json(*a)
|
16
|
-
{
|
17
|
-
:
|
18
|
-
:
|
19
|
-
:
|
20
|
-
:
|
21
|
-
:
|
16
|
+
{
|
17
|
+
name: @name,
|
18
|
+
identifier: @identifier,
|
19
|
+
easting: @easting,
|
20
|
+
northing: @northing,
|
21
|
+
gazeteer_code: @gazeteer_code
|
22
22
|
}.to_json(*a)
|
23
23
|
end
|
24
|
-
|
25
24
|
end
|
26
|
-
|
27
|
-
end
|
25
|
+
end
|
data/lib/atco/stop.rb
CHANGED
@@ -1,13 +1,22 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module Atco
|
3
4
|
class Stop
|
5
|
+
attr_accessor :bay_number, :location, :timing_point_indicator, :fare_stage_indicator, :published_departure_time,
|
6
|
+
:record_identity
|
7
|
+
|
8
|
+
def origin?
|
9
|
+
@record_identity == 'QO'
|
10
|
+
end
|
4
11
|
|
5
|
-
|
12
|
+
def intermediate?
|
13
|
+
@record_identity == 'QI'
|
14
|
+
end
|
15
|
+
|
16
|
+
def destination?
|
17
|
+
@record_identity == 'QT'
|
18
|
+
end
|
6
19
|
|
7
|
-
def origin?; @record_identity == "QO"; end
|
8
|
-
def intermediate?; @record_identity == "QI"; end
|
9
|
-
def destination?; @record_identity == "QT"; end
|
10
|
-
|
11
20
|
def initialize(data)
|
12
21
|
@bay_number = data[:bay_number]
|
13
22
|
@location = data[:location]
|
@@ -19,13 +28,13 @@ module Atco
|
|
19
28
|
|
20
29
|
def to_json(*args)
|
21
30
|
{
|
22
|
-
:
|
23
|
-
:
|
24
|
-
:
|
25
|
-
:
|
26
|
-
:
|
27
|
-
:
|
31
|
+
record_identity: @record_identity,
|
32
|
+
location: @location,
|
33
|
+
published_departure_time: @published_departure_time,
|
34
|
+
timing_point_indicator: @timing_point_indicator,
|
35
|
+
fare_stage_indicator: @fare_stage_indicator,
|
36
|
+
bay_number: @bay_number
|
28
37
|
}.to_json(*args)
|
29
38
|
end
|
30
39
|
end
|
31
|
-
end
|
40
|
+
end
|
data/lib/atco.rb
CHANGED
@@ -1,183 +1,182 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__)) unless
|
4
|
+
$LOAD_PATH.include?(File.dirname(__FILE__)) || $LOAD_PATH.include?(__dir__)
|
3
5
|
|
4
6
|
require 'open3'
|
5
|
-
require 'tempfile'
|
7
|
+
require 'tempfile'
|
6
8
|
require 'atco/location'
|
7
9
|
require 'atco/journey'
|
8
10
|
require 'atco/stop'
|
9
11
|
|
10
|
-
|
11
12
|
module Atco
|
12
13
|
VERSION = '0.0.1'
|
13
|
-
|
14
|
+
|
14
15
|
class << self
|
15
|
-
|
16
16
|
@path = nil
|
17
17
|
@@methods = {
|
18
|
-
:
|
19
|
-
:
|
20
|
-
:
|
21
|
-
:
|
22
|
-
:
|
23
|
-
:
|
24
|
-
:
|
25
|
-
:
|
18
|
+
bank_holiday: 'QH',
|
19
|
+
operator: 'QP',
|
20
|
+
additional_location_info: 'QB',
|
21
|
+
location: 'QL',
|
22
|
+
destination: 'QT',
|
23
|
+
intermediate: 'QI',
|
24
|
+
origin: 'QO',
|
25
|
+
journey_header: 'QS'
|
26
26
|
}
|
27
|
-
|
27
|
+
|
28
28
|
def parse(file)
|
29
29
|
@path = File.expand_path(file)
|
30
30
|
data = File.readlines(@path)
|
31
|
-
|
31
|
+
|
32
32
|
objects = []
|
33
33
|
current_journey = nil
|
34
34
|
current_location = nil
|
35
35
|
locations = []
|
36
36
|
journeys = {}
|
37
37
|
header = nil
|
38
|
-
|
38
|
+
|
39
39
|
data.each do |line|
|
40
40
|
if line == data.first
|
41
41
|
header = parse_header(line)
|
42
42
|
next
|
43
43
|
end
|
44
|
-
@@methods.each do |method,identifier|
|
45
|
-
object =
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
44
|
+
@@methods.each do |method, identifier|
|
45
|
+
object = send("parse_#{method}", line)
|
46
|
+
next unless object[:record_identity] && object[:record_identity] == identifier
|
47
|
+
|
48
|
+
current_journey = object if object[:record_identity] && object[:record_identity] == @@methods[:journey_header]
|
49
|
+
if object[:record_identity] && (object[:record_identity] == @@methods[:location] || object[:record_identity] == @@methods[:additional_location_info])
|
50
|
+
if object[:record_identity] == @@methods[:location]
|
51
|
+
current_location = object
|
52
|
+
else
|
53
|
+
locations << Location.new(current_location, object)
|
54
54
|
end
|
55
|
+
end
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
end
|
57
|
+
if current_journey
|
58
|
+
if journeys[current_journey[:unique_journey_identifier]]
|
59
|
+
journeys[current_journey[:unique_journey_identifier]].stops << Stop.new(object)
|
60
|
+
else
|
61
|
+
journeys[current_journey[:unique_journey_identifier]] = Journey.new(object)
|
62
62
|
end
|
63
|
-
objects << object
|
64
63
|
end
|
64
|
+
objects << object
|
65
65
|
end
|
66
66
|
end
|
67
|
-
|
67
|
+
{ header: header, locations: locations, journeys: journeys }
|
68
68
|
end
|
69
|
-
|
69
|
+
|
70
70
|
def parse_header(string)
|
71
71
|
{
|
72
|
-
:
|
73
|
-
:
|
74
|
-
:
|
75
|
-
:
|
76
|
-
:
|
77
|
-
}
|
72
|
+
file_type: string[0, 8],
|
73
|
+
version: "#{string[8, 2].to_i}.#{string[10, 2].to_i}",
|
74
|
+
file_originator: string[12, 32].strip!,
|
75
|
+
source_product: string[44, 16].strip!,
|
76
|
+
production_datetime: string[60, 14]
|
77
|
+
}
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
def parse_bank_holiday(string)
|
81
81
|
{
|
82
|
-
:
|
83
|
-
:
|
84
|
-
:
|
82
|
+
record_identity: string[0, 2],
|
83
|
+
transaction_type: string[2, 1],
|
84
|
+
date_of_bank_holiday: string[3, 8]
|
85
85
|
}
|
86
86
|
end
|
87
|
-
|
87
|
+
|
88
88
|
def parse_operator(string)
|
89
89
|
{
|
90
|
-
:
|
91
|
-
:
|
92
|
-
:
|
93
|
-
:
|
94
|
-
:
|
90
|
+
record_identity: string[0, 2],
|
91
|
+
transaction_type: string[2, 1],
|
92
|
+
operator: parse_value(string[3, 4]),
|
93
|
+
operator_short_form: parse_value(string[7, 24]),
|
94
|
+
operator_legal_name: parse_value(string[31, 48])
|
95
95
|
}
|
96
96
|
end
|
97
97
|
|
98
98
|
def parse_additional_location_info(string)
|
99
99
|
{
|
100
|
-
:
|
101
|
-
:
|
102
|
-
:
|
103
|
-
:
|
104
|
-
:
|
100
|
+
record_identity: string[0, 2],
|
101
|
+
transaction_type: string[2, 1],
|
102
|
+
location: string[3, 12].strip,
|
103
|
+
grid_reference_easting: parse_value(string[15, 8]),
|
104
|
+
grid_reference_northing: parse_value(string[23, 8])
|
105
105
|
}
|
106
106
|
end
|
107
107
|
|
108
108
|
def parse_location(string)
|
109
109
|
{
|
110
|
-
:
|
111
|
-
:
|
112
|
-
:
|
113
|
-
:
|
114
|
-
:
|
110
|
+
record_identity: string[0, 2],
|
111
|
+
transaction_type: string[2, 1],
|
112
|
+
location: parse_value(string[3, 12]),
|
113
|
+
full_location: parse_value(string[15, 48]),
|
114
|
+
gazetteer_code: string[63, 1]
|
115
115
|
}
|
116
116
|
end
|
117
117
|
|
118
118
|
def parse_destination(string)
|
119
119
|
{
|
120
|
-
:
|
121
|
-
:
|
122
|
-
:
|
123
|
-
:
|
124
|
-
:
|
125
|
-
:
|
120
|
+
record_identity: string[0, 2],
|
121
|
+
location: string[2, 12],
|
122
|
+
published_arrival_time: string[14, 4],
|
123
|
+
bay_number: parse_value(string[18, 3]),
|
124
|
+
timing_point_indicator: string[21, 2],
|
125
|
+
fare_stage_indicator: string[23, 2]
|
126
126
|
}
|
127
127
|
end
|
128
128
|
|
129
129
|
def parse_intermediate(string)
|
130
130
|
{
|
131
|
-
:
|
132
|
-
:
|
133
|
-
:
|
134
|
-
:
|
135
|
-
:
|
136
|
-
:
|
137
|
-
:
|
138
|
-
:
|
131
|
+
record_identity: string[0, 2],
|
132
|
+
location: string[2, 12],
|
133
|
+
published_arrival_time: string[14, 4],
|
134
|
+
published_departure_time: string[18, 4],
|
135
|
+
activity_flag: string[22, 1],
|
136
|
+
bay_number: parse_value(string[23, 3]),
|
137
|
+
timing_point_indicator: string[26, 2],
|
138
|
+
fare_stage_indicator: string[28, 2]
|
139
139
|
}
|
140
140
|
end
|
141
141
|
|
142
142
|
def parse_origin(string)
|
143
143
|
{
|
144
|
-
:
|
145
|
-
:
|
146
|
-
:
|
147
|
-
:
|
148
|
-
:
|
149
|
-
:
|
144
|
+
record_identity: string[0, 2],
|
145
|
+
location: string[2, 12],
|
146
|
+
published_departure_time: string[14, 4],
|
147
|
+
bay_number: parse_value(string[18, 3]),
|
148
|
+
timing_point_indicator: string[21, 2],
|
149
|
+
fare_stage_indicator: string[23, 2]
|
150
150
|
}
|
151
151
|
end
|
152
152
|
|
153
153
|
def parse_journey_header(string)
|
154
154
|
{
|
155
|
-
:
|
156
|
-
:
|
157
|
-
:
|
158
|
-
:
|
159
|
-
:
|
160
|
-
:
|
161
|
-
:
|
162
|
-
:
|
163
|
-
:
|
164
|
-
:
|
165
|
-
:
|
166
|
-
:
|
167
|
-
:
|
168
|
-
:
|
169
|
-
:
|
170
|
-
:
|
171
|
-
:
|
172
|
-
:
|
173
|
-
:
|
174
|
-
:
|
155
|
+
record_identity: string[0, 2],
|
156
|
+
transaction_type: string[2, 1],
|
157
|
+
operator: string[3, 4].strip,
|
158
|
+
unique_journey_identifier: string[7, 6],
|
159
|
+
first_date_of_operation: parse_value(string[13, 8]),
|
160
|
+
last_date_of_operation: parse_value(string[21, 8]),
|
161
|
+
operates_on_mondays: string[29, 1],
|
162
|
+
operates_on_tuesdays: string[30, 1],
|
163
|
+
operates_on_wednesdays: string[31, 1],
|
164
|
+
operates_on_thursdays: string[32, 1],
|
165
|
+
operates_on_fridays: string[33, 1],
|
166
|
+
operates_on_saturdays: string[34, 1],
|
167
|
+
operates_on_sundays: string[35, 1],
|
168
|
+
school_term_time: parse_value(string[36, 1]),
|
169
|
+
bank_holidays: parse_value(string[37, 1]),
|
170
|
+
route_number: parse_value(string[38, 4]),
|
171
|
+
running_board: parse_value(string[42, 6]),
|
172
|
+
vehicle_type: parse_value(string[48, 8]),
|
173
|
+
registration_number: parse_value(string[56, 8]),
|
174
|
+
route_direction: string[64, 1]
|
175
175
|
}
|
176
176
|
end
|
177
|
-
|
177
|
+
|
178
178
|
def parse_value(value)
|
179
|
-
|
179
|
+
value&.strip
|
180
180
|
end
|
181
181
|
end
|
182
|
-
|
183
|
-
end
|
182
|
+
end
|
data/spec/atco_spec.rb
CHANGED
@@ -1,150 +1,174 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "#{File.dirname(__FILE__)}/spec_helper"
|
2
4
|
require 'json'
|
3
5
|
|
4
6
|
describe Atco do
|
5
|
-
|
6
7
|
before(:all) do
|
7
|
-
|
8
8
|
end
|
9
|
-
|
10
|
-
it
|
9
|
+
|
10
|
+
it 'should output file for debugging!' do
|
11
11
|
result = Atco.parse('spec/fixtures/example.cif')
|
12
12
|
File.open('test.output', 'w+') do |f|
|
13
13
|
f.flush
|
14
14
|
f.write(JSON.pretty_generate(result))
|
15
15
|
end
|
16
|
-
#fixture = JSON.parse(File.read('spec/fixtures/example.json'))
|
17
16
|
end
|
18
|
-
|
19
|
-
it
|
17
|
+
|
18
|
+
it 'should parse header from fixture' do
|
20
19
|
result = Atco.parse('spec/fixtures/example.cif')
|
21
|
-
result[:header]
|
22
|
-
:
|
23
|
-
:
|
24
|
-
:
|
25
|
-
:
|
26
|
-
:
|
20
|
+
expect result[:header] == {
|
21
|
+
file_type: 'ATCO-CIF',
|
22
|
+
file_originator: 'Electronic Registration',
|
23
|
+
source_product: 'MIA 4.20.18',
|
24
|
+
version: '5.0',
|
25
|
+
production_datetime: '20090915113809'
|
27
26
|
}
|
28
27
|
end
|
29
|
-
|
30
|
-
it
|
28
|
+
|
29
|
+
it 'should parse locations from fixture' do
|
31
30
|
result = Atco.parse('spec/fixtures/example.cif')
|
32
|
-
result[:header]
|
33
|
-
:
|
34
|
-
:
|
35
|
-
:
|
36
|
-
:
|
37
|
-
:
|
31
|
+
expect result[:header] == {
|
32
|
+
file_type: 'ATCO-CIF',
|
33
|
+
file_originator: 'Electronic Registration',
|
34
|
+
source_product: 'MIA 4.20.18',
|
35
|
+
version: '5.0',
|
36
|
+
production_datetime: '20090915113809'
|
38
37
|
}
|
39
38
|
end
|
40
|
-
|
41
|
-
it
|
42
|
-
Atco.parse_header("ATCO-CIF0500Electronic Registration MIA 4.20.18 20090915113809\r\n")
|
43
|
-
:
|
44
|
-
:
|
45
|
-
:
|
46
|
-
:
|
47
|
-
:
|
39
|
+
|
40
|
+
it 'should parse header' do
|
41
|
+
expect Atco.parse_header("ATCO-CIF0500Electronic Registration MIA 4.20.18 20090915113809\r\n") == {
|
42
|
+
file_type: 'ATCO-CIF',
|
43
|
+
version: '5.0',
|
44
|
+
file_originator: 'Electronic Registration',
|
45
|
+
source_product: 'MIA 4.20.18',
|
46
|
+
production_datetime: '20090915113809'
|
48
47
|
}
|
49
48
|
end
|
50
|
-
|
51
|
-
it
|
52
|
-
Atco.parse_bank_holiday(
|
53
|
-
:
|
54
|
-
:
|
55
|
-
:
|
49
|
+
|
50
|
+
it 'should parse bank holiday' do
|
51
|
+
expect Atco.parse_bank_holiday('QHN20061225') == {
|
52
|
+
record_identity: 'QH',
|
53
|
+
transaction_type: 'N',
|
54
|
+
date_of_bank_holiday: '20061225'
|
56
55
|
}
|
57
56
|
end
|
58
|
-
|
59
|
-
it
|
60
|
-
Atco.parse_operator("QPNTM Translink Metro Translink Metro \r\n")
|
61
|
-
:
|
62
|
-
:
|
63
|
-
:
|
64
|
-
:
|
65
|
-
:
|
57
|
+
|
58
|
+
it 'should parse operator' do
|
59
|
+
expect Atco.parse_operator("QPNTM Translink Metro Translink Metro \r\n") == {
|
60
|
+
record_identity: 'QP',
|
61
|
+
transaction_type: 'N',
|
62
|
+
operator: 'TM',
|
63
|
+
operator_short_form: 'Translink Metro',
|
64
|
+
operator_legal_name: 'Translink Metro'
|
66
65
|
}
|
67
66
|
end
|
68
|
-
|
69
|
-
it
|
70
|
-
Atco.parse_additional_location_info("QBN700000001252 328622 367433 \r\n")
|
71
|
-
:
|
72
|
-
:
|
73
|
-
:
|
74
|
-
:
|
75
|
-
:
|
67
|
+
|
68
|
+
it 'should parse additional location information' do
|
69
|
+
expect Atco.parse_additional_location_info("QBN700000001252 328622 367433 \r\n") == {
|
70
|
+
record_identity: 'QB',
|
71
|
+
transaction_type: 'N',
|
72
|
+
location: '700000001252',
|
73
|
+
grid_reference_easting: '328622',
|
74
|
+
grid_reference_northing: '367433'
|
76
75
|
}
|
77
76
|
end
|
78
|
-
|
79
|
-
it
|
80
|
-
Atco.parse_location("QLN700000001252Conway (River Rd) 1\r\n")
|
81
|
-
:
|
82
|
-
:
|
83
|
-
:
|
84
|
-
:
|
85
|
-
:
|
77
|
+
|
78
|
+
it 'should parse location' do
|
79
|
+
expect Atco.parse_location("QLN700000001252Conway (River Rd) 1\r\n") == {
|
80
|
+
record_identity: 'QL',
|
81
|
+
transaction_type: 'N',
|
82
|
+
location: '700000001252',
|
83
|
+
full_location: 'Conway (River Rd)',
|
84
|
+
gazetteer_code: '1'
|
86
85
|
}
|
87
86
|
end
|
88
87
|
|
89
88
|
# QT7000000012520605 T1F0
|
90
|
-
it
|
91
|
-
Atco.parse_destination("QT7000000012520605 T1F0\r\n")
|
92
|
-
:
|
93
|
-
:
|
94
|
-
:
|
95
|
-
:
|
96
|
-
:
|
97
|
-
:
|
89
|
+
it 'should parse destination' do
|
90
|
+
expect Atco.parse_destination("QT7000000012520605 T1F0\r\n") == {
|
91
|
+
record_identity: 'QT',
|
92
|
+
location: '700000001252',
|
93
|
+
published_arrival_time: '0605',
|
94
|
+
bay_number: '',
|
95
|
+
timing_point_indicator: 'T1',
|
96
|
+
fare_stage_indicator: 'F0'
|
98
97
|
}
|
99
98
|
end
|
100
|
-
|
101
|
-
it
|
102
|
-
Atco.parse_intermediate("QI70000000125607120712B T1F0\r\n")
|
103
|
-
:
|
104
|
-
:
|
105
|
-
:
|
106
|
-
:
|
107
|
-
:
|
108
|
-
:
|
109
|
-
:
|
110
|
-
:
|
99
|
+
|
100
|
+
it 'should parse intermediate' do
|
101
|
+
expect Atco.parse_intermediate("QI70000000125607120712B T1F0\r\n") == {
|
102
|
+
record_identity: 'QI',
|
103
|
+
location: '700000001256',
|
104
|
+
published_arrival_time: '0712',
|
105
|
+
published_departure_time: '0712',
|
106
|
+
activity_flag: 'B',
|
107
|
+
bay_number: '',
|
108
|
+
timing_point_indicator: 'T1',
|
109
|
+
fare_stage_indicator: 'F0'
|
111
110
|
}
|
112
111
|
end
|
113
|
-
|
114
|
-
it
|
115
|
-
Atco.parse_origin("QO7000000012520730 T1F0\r\n")
|
116
|
-
:
|
117
|
-
:
|
118
|
-
:
|
119
|
-
:
|
120
|
-
:
|
121
|
-
:
|
112
|
+
|
113
|
+
it 'should parse origin' do
|
114
|
+
expect Atco.parse_origin("QO7000000012520730 T1F0\r\n") == {
|
115
|
+
record_identity: 'QO',
|
116
|
+
location: '700000001252',
|
117
|
+
published_departure_time: '0730',
|
118
|
+
bay_number: '',
|
119
|
+
timing_point_indicator: 'T1',
|
120
|
+
fare_stage_indicator: 'F0'
|
122
121
|
}
|
123
122
|
end
|
124
123
|
|
125
|
-
it
|
126
|
-
Atco.parse_journey_header("QSNTM 13986520091005 1111100 9A 9018 0 I\r\n")
|
127
|
-
:
|
128
|
-
:
|
129
|
-
:
|
130
|
-
:
|
131
|
-
:
|
132
|
-
:
|
133
|
-
:
|
134
|
-
:
|
135
|
-
:
|
136
|
-
:
|
137
|
-
:
|
138
|
-
:
|
139
|
-
:
|
140
|
-
:
|
141
|
-
:
|
142
|
-
:
|
143
|
-
:
|
144
|
-
:
|
145
|
-
:
|
146
|
-
:
|
124
|
+
it 'should parse journey header' do
|
125
|
+
expect Atco.parse_journey_header("QSNTM 13986520091005 1111100 9A 9018 0 I\r\n") == {
|
126
|
+
record_identity: 'QS',
|
127
|
+
transaction_type: 'N',
|
128
|
+
operator: 'TM',
|
129
|
+
unique_journey_identifier: '139865',
|
130
|
+
first_date_of_operation: '20091005',
|
131
|
+
last_date_of_operation: '',
|
132
|
+
operates_on_mondays: '1',
|
133
|
+
operates_on_tuesdays: '1',
|
134
|
+
operates_on_wednesdays: '1',
|
135
|
+
operates_on_thursdays: '1',
|
136
|
+
operates_on_fridays: '1',
|
137
|
+
operates_on_saturdays: '0',
|
138
|
+
operates_on_sundays: '0',
|
139
|
+
school_term_time: '',
|
140
|
+
bank_holidays: '',
|
141
|
+
route_number: '9A',
|
142
|
+
running_board: '9018',
|
143
|
+
vehicle_type: '0',
|
144
|
+
registration_number: '',
|
145
|
+
route_direction: 'I'
|
147
146
|
}
|
148
147
|
end
|
149
148
|
|
150
|
-
|
149
|
+
describe 'with example.cif' do
|
150
|
+
before(:all) do
|
151
|
+
@atco = Atco.parse('spec/fixtures/example.cif')
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'should parse 1 journey' do
|
155
|
+
expect @atco[:journeys].size == 1
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'should parse journeys into Atco::Joruney objects' do
|
159
|
+
expect(@atco[:journeys]['139748']).to be_a_kind_of(Atco::Journey)
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'should parse 6 stops for joureny 139748' do
|
163
|
+
expect @atco[:journeys]['139748'].stops.size == 6
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'should parse 6 stops for joureny 139748' do
|
167
|
+
expect @atco[:journeys]['139748'].stops.size == 6
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'should parse 2 locations' do
|
171
|
+
expect @atco[:locations].size == 2
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
ATCO-CIF0500Electronic Registration MIA 4.20.18 20090915113809
|
2
|
+
QLN700000001433Donegal Square East 1
|
3
|
+
QBN700000001433 333935 373979
|
4
|
+
GS00001433 N Belfast Metro Ops 7000
|
5
|
+
GR00001433Donegall Square East 7000
|
6
|
+
QLN700000001627Great Northern Mall 1
|
7
|
+
QBN700000001627 333575 373717
|
8
|
+
GS00001627 N Belfast Metro Ops 7000
|
9
|
+
GR00001627Great Victoria Street 7000 7000
|
10
|
+
QPNTM Translink Metro Translink Metro
|
11
|
+
QQ
|
12
|
+
ZLTMAO009AT05O
|
13
|
+
ZD20091005 Monday to Friday FFFFF00
|
14
|
+
ZSTMAO009A9A City Centre - Conway
|
15
|
+
ZAN700000001433 P1W1T1
|
16
|
+
ZAN700000001627 P1W1T1
|
17
|
+
QSNTM 13974820091005 1111100 9A 9011 0 O
|
18
|
+
ZJTMAO009A004 1 370 000CB 545 2237 C FFFFF00L0
|
19
|
+
QO7000000014330545 T1F0
|
20
|
+
ZECH0 054500054500P0W0
|
21
|
+
QI70000000162705460546B T1F0
|
22
|
+
ZECH0 054600054600P0W0
|
23
|
+
QI70000000124806020602B T1F0
|
24
|
+
ZECH0 060200060200P0W0
|
25
|
+
QI70000000125006030603B T0F0
|
26
|
+
ZECH0 060348060348P0W0
|
27
|
+
QT7000000012520605 T1F0
|
28
|
+
ZECH0 060500060500P0W0
|
29
|
+
QVN0 Bus
|
30
|
+
QHN20071226
|
@@ -0,0 +1,98 @@
|
|
1
|
+
{
|
2
|
+
"header": {
|
3
|
+
"file_type": "ATCO-CIF",
|
4
|
+
"file_originator": "Electronic Registration",
|
5
|
+
"source_product": "MIA 4.20.18",
|
6
|
+
"version": "5.0",
|
7
|
+
"production_datetime": "20090915113809"
|
8
|
+
},
|
9
|
+
"locations": [
|
10
|
+
[
|
11
|
+
{
|
12
|
+
"record_identity": "QL",
|
13
|
+
"location": "700000001433",
|
14
|
+
"transaction_type": "N",
|
15
|
+
"full_location": "Donegal Square East",
|
16
|
+
"gazetteer_code": "1"
|
17
|
+
},
|
18
|
+
{
|
19
|
+
"record_identity": "QB",
|
20
|
+
"location": "700000001433",
|
21
|
+
"transaction_type": "N",
|
22
|
+
"grid_reference_easting": "333935",
|
23
|
+
"grid_reference_northing": "373979"
|
24
|
+
}
|
25
|
+
],
|
26
|
+
[
|
27
|
+
{
|
28
|
+
"record_identity": "QL",
|
29
|
+
"location": "700000001627",
|
30
|
+
"transaction_type": "N",
|
31
|
+
"full_location": "Great Northern Mall",
|
32
|
+
"gazetteer_code": "1"
|
33
|
+
},
|
34
|
+
{
|
35
|
+
"record_identity": "QB",
|
36
|
+
"location": "700000001627",
|
37
|
+
"transaction_type": "N",
|
38
|
+
"grid_reference_easting": "333575",
|
39
|
+
"grid_reference_northing": "373717"
|
40
|
+
}
|
41
|
+
]
|
42
|
+
],
|
43
|
+
"journeys": {
|
44
|
+
"139748": [
|
45
|
+
{
|
46
|
+
"record_identity": "QO",
|
47
|
+
"published_departure_time": "0545",
|
48
|
+
"location": "700000001433",
|
49
|
+
"bay_number": "",
|
50
|
+
"timing_point_indicator": "T1",
|
51
|
+
"fare_stage_indicator": "F0"
|
52
|
+
},
|
53
|
+
{
|
54
|
+
"record_identity": "QI",
|
55
|
+
"published_departure_time": "0546",
|
56
|
+
"location": "700000001627",
|
57
|
+
"published_arrival_time": "0546",
|
58
|
+
"activity_flag": "B",
|
59
|
+
"bay_number": "",
|
60
|
+
"timing_point_indicator": "T1",
|
61
|
+
"fare_stage_indicator": "F0"
|
62
|
+
},
|
63
|
+
{
|
64
|
+
"record_identity": "QI",
|
65
|
+
"published_departure_time": "0602",
|
66
|
+
"location": "700000001248",
|
67
|
+
"published_arrival_time": "0602",
|
68
|
+
"activity_flag": "B",
|
69
|
+
"bay_number": "",
|
70
|
+
"timing_point_indicator": "T1",
|
71
|
+
"fare_stage_indicator": "F0"
|
72
|
+
},
|
73
|
+
{
|
74
|
+
"record_identity": "QI",
|
75
|
+
"published_departure_time": "0603",
|
76
|
+
"location": "700000001250",
|
77
|
+
"published_arrival_time": "0603",
|
78
|
+
"activity_flag": "B",
|
79
|
+
"bay_number": "",
|
80
|
+
"timing_point_indicator": "T0",
|
81
|
+
"fare_stage_indicator": "F0"
|
82
|
+
},
|
83
|
+
{
|
84
|
+
"record_identity": "QT",
|
85
|
+
"location": "700000001252",
|
86
|
+
"published_arrival_time": "0605",
|
87
|
+
"bay_number": "",
|
88
|
+
"timing_point_indicator": "T1",
|
89
|
+
"fare_stage_indicator": "F0"
|
90
|
+
},
|
91
|
+
{
|
92
|
+
"record_identity": "QH",
|
93
|
+
"transaction_type": "N",
|
94
|
+
"date_of_bank_holiday": "20071226"
|
95
|
+
}
|
96
|
+
]
|
97
|
+
}
|
98
|
+
}
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,69 +1,84 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: atco
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
segments:
|
6
|
-
- 0
|
7
|
-
- 0
|
8
|
-
- 2
|
9
|
-
version: 0.0.2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
10
5
|
platform: ruby
|
11
|
-
authors:
|
6
|
+
authors:
|
12
7
|
- David Rice
|
13
8
|
autorequire:
|
14
9
|
bindir: bin
|
15
10
|
cert_chain: []
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
11
|
+
date: 2024-04-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Simple and opinionated library for parsing ATCO .cif files to JSON with
|
42
|
+
Ruby
|
22
43
|
email: me@davidjrice.co.uk
|
23
44
|
executables: []
|
24
|
-
|
25
45
|
extensions: []
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
- README.mdown
|
46
|
+
extra_rdoc_files:
|
47
|
+
- README.md
|
48
|
+
files:
|
49
|
+
- README.md
|
31
50
|
- Rakefile
|
32
51
|
- VERSION
|
33
52
|
- lib/atco.rb
|
34
53
|
- lib/atco/journey.rb
|
35
54
|
- lib/atco/location.rb
|
36
55
|
- lib/atco/stop.rb
|
37
|
-
|
56
|
+
- spec/atco_spec.rb
|
57
|
+
- spec/fixtures/example.cif
|
58
|
+
- spec/fixtures/example.json
|
59
|
+
- spec/spec_helper.rb
|
38
60
|
homepage: http://github.com/davidjrice/atco
|
39
|
-
licenses:
|
40
|
-
|
61
|
+
licenses:
|
62
|
+
- MIT
|
63
|
+
metadata: {}
|
41
64
|
post_install_message:
|
42
|
-
rdoc_options:
|
43
|
-
- --charset=UTF-8
|
44
|
-
require_paths:
|
65
|
+
rdoc_options:
|
66
|
+
- "--charset=UTF-8"
|
67
|
+
require_paths:
|
45
68
|
- lib
|
46
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
-
requirements:
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
48
71
|
- - ">="
|
49
|
-
- !ruby/object:Gem::Version
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
-
requirements:
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
55
76
|
- - ">="
|
56
|
-
- !ruby/object:Gem::Version
|
57
|
-
|
58
|
-
- 0
|
59
|
-
version: "0"
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
60
79
|
requirements: []
|
61
|
-
|
62
|
-
rubyforge_project:
|
63
|
-
rubygems_version: 1.3.6
|
80
|
+
rubygems_version: 3.5.3
|
64
81
|
signing_key:
|
65
|
-
specification_version:
|
66
|
-
summary:
|
67
|
-
test_files:
|
68
|
-
- spec/atco_spec.rb
|
69
|
-
- spec/spec_helper.rb
|
82
|
+
specification_version: 4
|
83
|
+
summary: Parse ATCO .cif files to JSON with Ruby
|
84
|
+
test_files: []
|