atco 0.0.2 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 215cf54f3257e776c20d54d0177731f06cf62eda409e7763457c709757aa1a52
4
+ data.tar.gz: 97ebd8cf82c779b872f23204079a230aae0d9b159bacdf3db5042cada877a197
5
+ SHA512:
6
+ metadata.gz: 69b1de96881df1044138cbebe82ea3e22053c47d36aa38dbb39c1018683675eb44e27619be1d29346d5ef156f924c3ee8e408808aec11b7940ad2ca4877dfc25
7
+ data.tar.gz: d14f0b410610dbaf1d2e4e80ce41703becb6fddc99c06bbe3a88500d65bde6b3b44bdfa7768405682c654abf8cb0ecb5470a7589b7f6b978f0933db2e230736e
@@ -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.mdown](http://github.com/davidjrice/atco/blob/master/todo.mdown) list ).
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
- require 'lib/atco'
18
-
19
- result = Atco.parse('filename.cif')
20
- result = Atco.parse('SVRTMAO009A-20091005.cif) # an example data file
21
-
22
- => {
23
- :header => {...},
24
- :locations => [...],
25
- :journies => {...}
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,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+
1
5
  begin
2
- require 'jeweler'
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
6
+ require "rspec/core/rake_task"
7
+ RSpec::Core::RakeTask.new(:spec)
12
8
  rescue LoadError
13
- puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install jeweler"
14
- end
9
+ puts "RSpec, or one of its dependencies, is not available. Install it with: bundle install"
10
+ end
11
+
12
+ begin
13
+ require "rubocop/rake_task"
14
+ RuboCop::RakeTask.new
15
+ rescue LoadError
16
+ puts "rubocop, or one of its dependencies, is not available. Install it with: bundle install"
17
+ end
18
+
19
+ task default: %i[spec rubocop]
data/lib/atco/journey.rb CHANGED
@@ -1,13 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Atco
2
-
4
+ # Atco::Journey is a data class to abstract ATCO-CIF Journey records.
3
5
  class Journey
4
-
5
- attr_accessor :vehicle_type, :registration_number, :identifier, :operator, :route_number,
6
- :first_date_of_operation, :running_board, :last_date_of_operation, :school_term_time, :route_direction, :bank_holidays
7
-
8
- attr_accessor :stops
6
+ attr_accessor :vehicle_type, :registration_number, :identifier, :operator, :route_number, :first_date_of_operation,
7
+ :running_board, :last_date_of_operation, :school_term_time, :route_direction, :bank_holidays, :stops
9
8
 
10
- def initialize(data)
9
+ def initialize(data) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
11
10
  @mondays = parse_boolean_int data[:operates_on_mondays]
12
11
  @tuesdays = parse_boolean_int data[:operates_on_tuesdays]
13
12
  @wednesdays = parse_boolean_int data[:operates_on_wednesdays]
@@ -15,7 +14,7 @@ module Atco
15
14
  @fridays = parse_boolean_int data[:operates_on_fridays]
16
15
  @saturdays = parse_boolean_int data[:operates_on_saturdays]
17
16
  @sundays = parse_boolean_int data[:operates_on_sundays]
18
-
17
+
19
18
  @vehicle_type = data[:vehicle_type]
20
19
  @registration_number = data[:registration_number]
21
20
  @identifier = data[:unique_journey_identifier]
@@ -27,40 +26,60 @@ module Atco
27
26
  @running_board = data[:running_board]
28
27
  @school_term_time = data[:school_term_time]
29
28
  @bank_holidays = data[:bank_holidays]
30
-
29
+
31
30
  @stops = []
32
- #stops.each do |s|
33
- # @stops << Stop.new(s)
34
- #end
31
+ # stops.each do |s|
32
+ # @stops << Stop.new(s)
33
+ # end
34
+ end
35
+
36
+ def mondays?
37
+ @mondays
38
+ end
39
+
40
+ def tuesdays?
41
+ @tuesdays
42
+ end
43
+
44
+ def wednesdays?
45
+ @wednesdays
46
+ end
47
+
48
+ def thursdays?
49
+ @thursdays
50
+ end
51
+
52
+ def fridays?
53
+ @fridays
54
+ end
55
+
56
+ def saturdays?
57
+ @saturdays
58
+ end
59
+
60
+ def sundays?
61
+ @sundays
35
62
  end
36
63
 
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
64
  def parse_boolean_int(string)
46
- (string && string == "1") ? true : false
65
+ string && string == "1"
47
66
  end
48
-
49
- def to_json(*args)
67
+
68
+ def to_json(*attrs) # rubocop:disable Metrics/MethodLength
50
69
  {
51
- :vehicle_type => @vehicle_type,
52
- :registration_number => @registration_number,
53
- :identifier => @identifier,
54
- :operator => @operator,
55
- :route_number => @route_number,
56
- :first_date_of_operation => @first_date_of_operation,
57
- :running_board => @running_board,
58
- :last_date_of_operation => @last_date_of_operation,
59
- :school_term_time => @school_term_time,
60
- :route_direction => @route_direction,
61
- :bank_holidays => @bank_holidays,
62
- :stops => @stops
63
- }.to_json(*args)
70
+ vehicle_type: @vehicle_type,
71
+ registration_number: @registration_number,
72
+ identifier: @identifier,
73
+ operator: @operator,
74
+ route_number: @route_number,
75
+ first_date_of_operation: @first_date_of_operation,
76
+ running_board: @running_board,
77
+ last_date_of_operation: @last_date_of_operation,
78
+ school_term_time: @school_term_time,
79
+ route_direction: @route_direction,
80
+ bank_holidays: @bank_holidays,
81
+ stops: @stops
82
+ }.to_json(*attrs)
64
83
  end
65
84
  end
66
- end
85
+ end
data/lib/atco/location.rb CHANGED
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Atco
2
-
4
+ # Atco::Location is a data class to abstract ATCO-CIF Location records.
3
5
  class Location
4
-
5
6
  attr_accessor :name, :identifier, :easting, :northing, :gazeteer_code
6
7
 
7
8
  def initialize(location_header, additional_location_information)
@@ -12,16 +13,14 @@ module Atco
12
13
  @gazeteer_code = location_header[:gazetteer_code]
13
14
  end
14
15
 
15
- def to_json(*a)
16
- {
17
- :name => @name,
18
- :identifier => @identifier,
19
- :easting => @easting,
20
- :northing => @northing,
21
- :gazeteer_code => @gazeteer_code
22
- }.to_json(*a)
16
+ def to_json(*attrs)
17
+ {
18
+ name: @name,
19
+ identifier: @identifier,
20
+ easting: @easting,
21
+ northing: @northing,
22
+ gazeteer_code: @gazeteer_code
23
+ }.to_json(*attrs)
23
24
  end
24
-
25
25
  end
26
-
27
- end
26
+ end
data/lib/atco/stop.rb CHANGED
@@ -1,13 +1,23 @@
1
- module Atco
1
+ # frozen_string_literal: true
2
2
 
3
+ module Atco
4
+ # Atco::Stop is a class to abstract ATCO-CIF Origin, Intermediate and Destination (Stop) records.
3
5
  class Stop
6
+ attr_accessor :bay_number, :location, :timing_point_indicator, :fare_stage_indicator, :published_departure_time,
7
+ :record_identity
8
+
9
+ def origin?
10
+ @record_identity == "QO"
11
+ end
4
12
 
5
- attr_accessor :bay_number, :location, :timing_point_indicator, :fare_stage_indicator, :published_departure_time, :record_identity
13
+ def intermediate?
14
+ @record_identity == "QI"
15
+ end
16
+
17
+ def destination?
18
+ @record_identity == "QT"
19
+ end
6
20
 
7
- def origin?; @record_identity == "QO"; end
8
- def intermediate?; @record_identity == "QI"; end
9
- def destination?; @record_identity == "QT"; end
10
-
11
21
  def initialize(data)
12
22
  @bay_number = data[:bay_number]
13
23
  @location = data[:location]
@@ -17,15 +27,15 @@ module Atco
17
27
  @record_identity = data[:record_identity]
18
28
  end
19
29
 
20
- def to_json(*args)
30
+ def to_json(*attrs)
21
31
  {
22
- :record_identity => @record_identity,
23
- :location => @location,
24
- :published_departure_time => @published_departure_time,
25
- :timing_point_indicator => @timing_point_indicator,
26
- :fare_stage_indicator => @fare_stage_indicator,
27
- :bay_number => @bay_number
28
- }.to_json(*args)
32
+ record_identity: @record_identity,
33
+ location: @location,
34
+ published_departure_time: @published_departure_time,
35
+ timing_point_indicator: @timing_point_indicator,
36
+ fare_stage_indicator: @fare_stage_indicator,
37
+ bay_number: @bay_number
38
+ }.to_json(*attrs)
29
39
  end
30
40
  end
31
- end
41
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Atco
4
+ VERSION = "1.0.1"
5
+ end
data/lib/atco.rb CHANGED
@@ -1,183 +1,179 @@
1
- $:.unshift(File.dirname(__FILE__)) unless
2
- $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
1
+ # frozen_string_literal: true
3
2
 
4
- require 'open3'
5
- require 'tempfile'
6
- require 'atco/location'
7
- require 'atco/journey'
8
- require 'atco/stop'
3
+ require "open3"
4
+ require "tempfile"
5
+ require_relative "atco/location"
6
+ require_relative "atco/journey"
7
+ require_relative "atco/stop"
8
+ require_relative "atco/version"
9
9
 
10
-
11
- module Atco
12
- VERSION = '0.0.1'
13
-
14
- class << self
15
-
10
+ # Public: Atco is a module that provides a parser for the ATCO-CIF data format.
11
+ module Atco # rubocop:disable Metrics/ModuleLength
12
+ class << self # rubocop:disable Metrics/ClassLength
16
13
  @path = nil
17
- @@methods = {
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
- }
27
-
28
- def parse(file)
14
+ METHODS = {
15
+ bank_holiday: "QH",
16
+ operator: "QP",
17
+ additional_location_info: "QB",
18
+ location: "QL",
19
+ destination: "QT",
20
+ intermediate: "QI",
21
+ origin: "QO",
22
+ journey_header: "QS"
23
+ }.freeze
24
+
25
+ def parse(file) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
29
26
  @path = File.expand_path(file)
30
27
  data = File.readlines(@path)
31
-
28
+
32
29
  objects = []
33
30
  current_journey = nil
34
31
  current_location = nil
35
32
  locations = []
36
33
  journeys = {}
37
34
  header = nil
38
-
35
+
39
36
  data.each do |line|
40
37
  if line == data.first
41
38
  header = parse_header(line)
42
39
  next
43
40
  end
44
- @@methods.each do |method,identifier|
45
- object = self.send("parse_#{method}", line)
46
- if object[:record_identity] && object[:record_identity] == identifier
47
- current_journey = object if object[:record_identity] && object[:record_identity] == @@methods[:journey_header]
48
- if object[:record_identity] && ( object[:record_identity] == @@methods[:location] || object[:record_identity] == @@methods[:additional_location_info] )
49
- if object[:record_identity] == @@methods[:location]
50
- current_location = object
51
- else
52
- locations << Location.new(current_location, object)
53
- end
41
+ METHODS.each do |method, identifier|
42
+ object = send("parse_#{method}", line)
43
+ next unless object[:record_identity] && object[:record_identity] == identifier
44
+
45
+ current_journey = object if object[:record_identity] && object[:record_identity] == METHODS[:journey_header]
46
+ if object[:record_identity] && (object[:record_identity] == METHODS[:location] || object[:record_identity] == METHODS[:additional_location_info]) # rubocop:disable Layout/LineLength
47
+ if object[:record_identity] == METHODS[:location]
48
+ current_location = object
49
+ else
50
+ locations << Location.new(current_location, object)
54
51
  end
52
+ end
55
53
 
56
- if current_journey
57
- if journeys[current_journey[:unique_journey_identifier]]
58
- journeys[current_journey[:unique_journey_identifier]].stops << Stop.new(object)
59
- else
60
- journeys[current_journey[:unique_journey_identifier]] = Journey.new(object)
61
- end
54
+ if current_journey
55
+ if journeys[current_journey[:unique_journey_identifier]]
56
+ journeys[current_journey[:unique_journey_identifier]].stops << Stop.new(object)
57
+ else
58
+ journeys[current_journey[:unique_journey_identifier]] = Journey.new(object)
62
59
  end
63
- objects << object
64
60
  end
61
+ objects << object
65
62
  end
66
63
  end
67
- return {:header => header, :locations => locations, :journeys => journeys}
64
+ { header: header, locations: locations, journeys: journeys }
68
65
  end
69
-
66
+
70
67
  def parse_header(string)
71
68
  {
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
- }
69
+ file_type: string[0, 8],
70
+ version: "#{string[8, 2].to_i}.#{string[10, 2].to_i}",
71
+ file_originator: string[12, 32].strip!,
72
+ source_product: string[44, 16].strip!,
73
+ production_datetime: string[60, 14]
74
+ }
78
75
  end
79
-
76
+
80
77
  def parse_bank_holiday(string)
81
78
  {
82
- :record_identity => string[0,2],
83
- :transaction_type => string[2,1],
84
- :date_of_bank_holiday => string[3,8]
79
+ record_identity: string[0, 2],
80
+ transaction_type: string[2, 1],
81
+ date_of_bank_holiday: string[3, 8]
85
82
  }
86
83
  end
87
-
84
+
88
85
  def parse_operator(string)
89
86
  {
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])
87
+ record_identity: string[0, 2],
88
+ transaction_type: string[2, 1],
89
+ operator: parse_value(string[3, 4]),
90
+ operator_short_form: parse_value(string[7, 24]),
91
+ operator_legal_name: parse_value(string[31, 48])
95
92
  }
96
93
  end
97
94
 
98
95
  def parse_additional_location_info(string)
99
96
  {
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])
97
+ record_identity: string[0, 2],
98
+ transaction_type: string[2, 1],
99
+ location: string[3, 12].strip,
100
+ grid_reference_easting: parse_value(string[15, 8]),
101
+ grid_reference_northing: parse_value(string[23, 8])
105
102
  }
106
103
  end
107
104
 
108
105
  def parse_location(string)
109
106
  {
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]
107
+ record_identity: string[0, 2],
108
+ transaction_type: string[2, 1],
109
+ location: parse_value(string[3, 12]),
110
+ full_location: parse_value(string[15, 48]),
111
+ gazetteer_code: string[63, 1]
115
112
  }
116
113
  end
117
114
 
118
115
  def parse_destination(string)
119
116
  {
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]
117
+ record_identity: string[0, 2],
118
+ location: string[2, 12],
119
+ published_arrival_time: string[14, 4],
120
+ bay_number: parse_value(string[18, 3]),
121
+ timing_point_indicator: string[21, 2],
122
+ fare_stage_indicator: string[23, 2]
126
123
  }
127
124
  end
128
125
 
129
126
  def parse_intermediate(string)
130
127
  {
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]
128
+ record_identity: string[0, 2],
129
+ location: string[2, 12],
130
+ published_arrival_time: string[14, 4],
131
+ published_departure_time: string[18, 4],
132
+ activity_flag: string[22, 1],
133
+ bay_number: parse_value(string[23, 3]),
134
+ timing_point_indicator: string[26, 2],
135
+ fare_stage_indicator: string[28, 2]
139
136
  }
140
137
  end
141
138
 
142
139
  def parse_origin(string)
143
140
  {
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]
141
+ record_identity: string[0, 2],
142
+ location: string[2, 12],
143
+ published_departure_time: string[14, 4],
144
+ bay_number: parse_value(string[18, 3]),
145
+ timing_point_indicator: string[21, 2],
146
+ fare_stage_indicator: string[23, 2]
150
147
  }
151
148
  end
152
149
 
153
- def parse_journey_header(string)
150
+ def parse_journey_header(string) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
154
151
  {
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]
152
+ record_identity: string[0, 2],
153
+ transaction_type: string[2, 1],
154
+ operator: string[3, 4].strip,
155
+ unique_journey_identifier: string[7, 6],
156
+ first_date_of_operation: parse_value(string[13, 8]),
157
+ last_date_of_operation: parse_value(string[21, 8]),
158
+ operates_on_mondays: string[29, 1],
159
+ operates_on_tuesdays: string[30, 1],
160
+ operates_on_wednesdays: string[31, 1],
161
+ operates_on_thursdays: string[32, 1],
162
+ operates_on_fridays: string[33, 1],
163
+ operates_on_saturdays: string[34, 1],
164
+ operates_on_sundays: string[35, 1],
165
+ school_term_time: parse_value(string[36, 1]),
166
+ bank_holidays: parse_value(string[37, 1]),
167
+ route_number: parse_value(string[38, 4]),
168
+ running_board: parse_value(string[42, 6]),
169
+ vehicle_type: parse_value(string[48, 8]),
170
+ registration_number: parse_value(string[56, 8]),
171
+ route_direction: string[64, 1]
175
172
  }
176
173
  end
177
-
174
+
178
175
  def parse_value(value)
179
- return value.strip if value
176
+ value&.strip
180
177
  end
181
178
  end
182
-
183
- end
179
+ end
data/spec/atco_spec.rb CHANGED
@@ -1,150 +1,175 @@
1
- require File.dirname(__FILE__) + '/spec_helper'
2
- require 'json'
1
+ # frozen_string_literal: true
3
2
 
4
- describe Atco do
5
-
6
- before(:all) do
7
-
3
+ require "#{File.dirname(__FILE__)}/spec_helper"
4
+ require "json"
5
+
6
+ describe Atco do # rubocop:disable Metrics/BlockLength
7
+ it "has a version number" do
8
+ expect(Atco::VERSION).not_to be nil
8
9
  end
9
-
10
+
10
11
  it "should output file for debugging!" do
11
- result = Atco.parse('spec/fixtures/example.cif')
12
- File.open('test.output', 'w+') do |f|
12
+ result = Atco.parse("spec/fixtures/example.cif")
13
+ File.open("test.output", "w+") do |f|
13
14
  f.flush
14
15
  f.write(JSON.pretty_generate(result))
15
16
  end
16
- #fixture = JSON.parse(File.read('spec/fixtures/example.json'))
17
17
  end
18
-
18
+
19
19
  it "should parse header from fixture" do
20
- result = Atco.parse('spec/fixtures/example.cif')
21
- result[:header].should == {
22
- :file_type => "ATCO-CIF",
23
- :file_originator => "Electronic Registration",
24
- :source_product => "MIA 4.20.18",
25
- :version => "5.0",
26
- :production_datetime => "20090915113809"
20
+ result = Atco.parse("spec/fixtures/example.cif")
21
+ expect result[:header] == {
22
+ file_type: "ATCO-CIF",
23
+ file_originator: "Electronic Registration",
24
+ source_product: "MIA 4.20.18",
25
+ version: "5.0",
26
+ production_datetime: "20090915113809"
27
27
  }
28
28
  end
29
-
29
+
30
30
  it "should parse locations from fixture" do
31
- result = Atco.parse('spec/fixtures/example.cif')
32
- result[:header].should == {
33
- :file_type => "ATCO-CIF",
34
- :file_originator => "Electronic Registration",
35
- :source_product => "MIA 4.20.18",
36
- :version => "5.0",
37
- :production_datetime => "20090915113809"
31
+ result = Atco.parse("spec/fixtures/example.cif")
32
+ expect result[:header] == {
33
+ file_type: "ATCO-CIF",
34
+ file_originator: "Electronic Registration",
35
+ source_product: "MIA 4.20.18",
36
+ version: "5.0",
37
+ production_datetime: "20090915113809"
38
38
  }
39
39
  end
40
-
40
+
41
41
  it "should parse header" do
42
- Atco.parse_header("ATCO-CIF0500Electronic Registration MIA 4.20.18 20090915113809\r\n").should == {
43
- :file_type => 'ATCO-CIF',
44
- :version => '5.0',
45
- :file_originator => 'Electronic Registration',
46
- :source_product => 'MIA 4.20.18',
47
- :production_datetime => '20090915113809'
42
+ expect Atco.parse_header("ATCO-CIF0500Electronic Registration MIA 4.20.18 20090915113809\r\n") == {
43
+ file_type: "ATCO-CIF",
44
+ version: "5.0",
45
+ file_originator: "Electronic Registration",
46
+ source_product: "MIA 4.20.18",
47
+ production_datetime: "20090915113809"
48
48
  }
49
49
  end
50
-
50
+
51
51
  it "should parse bank holiday" do
52
- Atco.parse_bank_holiday("QHN20061225").should == {
53
- :record_identity => 'QH',
54
- :transaction_type => 'N',
55
- :date_of_bank_holiday => '20061225'
52
+ expect Atco.parse_bank_holiday("QHN20061225") == {
53
+ record_identity: "QH",
54
+ transaction_type: "N",
55
+ date_of_bank_holiday: "20061225"
56
56
  }
57
57
  end
58
-
58
+
59
59
  it "should parse operator" do
60
- Atco.parse_operator("QPNTM Translink Metro Translink Metro \r\n").should == {
61
- :record_identity => 'QP',
62
- :transaction_type => 'N',
63
- :operator => 'TM',
64
- :operator_short_form => 'Translink Metro',
65
- :operator_legal_name => 'Translink Metro'
60
+ expect Atco.parse_operator("QPNTM Translink Metro Translink Metro \r\n") == {
61
+ record_identity: "QP",
62
+ transaction_type: "N",
63
+ operator: "TM",
64
+ operator_short_form: "Translink Metro",
65
+ operator_legal_name: "Translink Metro"
66
66
  }
67
67
  end
68
-
68
+
69
69
  it "should parse additional location information" do
70
- Atco.parse_additional_location_info("QBN700000001252 328622 367433 \r\n").should == {
71
- :record_identity => 'QB',
72
- :transaction_type => 'N',
73
- :location => '700000001252',
74
- :grid_reference_easting => '328622',
75
- :grid_reference_northing => '367433'
70
+ expect Atco.parse_additional_location_info("QBN700000001252 328622 367433 \r\n") == {
71
+ record_identity: "QB",
72
+ transaction_type: "N",
73
+ location: "700000001252",
74
+ grid_reference_easting: "328622",
75
+ grid_reference_northing: "367433"
76
76
  }
77
77
  end
78
-
78
+
79
79
  it "should parse location" do
80
- Atco.parse_location("QLN700000001252Conway (River Rd) 1\r\n").should == {
81
- :record_identity => 'QL',
82
- :transaction_type => 'N',
83
- :location => '700000001252',
84
- :full_location => 'Conway (River Rd)',
85
- :gazetteer_code => '1'
80
+ expect Atco.parse_location("QLN700000001252Conway (River Rd) 1\r\n") == {
81
+ record_identity: "QL",
82
+ transaction_type: "N",
83
+ location: "700000001252",
84
+ full_location: "Conway (River Rd)",
85
+ gazetteer_code: "1"
86
86
  }
87
87
  end
88
88
 
89
89
  # QT7000000012520605 T1F0
90
90
  it "should parse destination" do
91
- Atco.parse_destination("QT7000000012520605 T1F0\r\n").should == {
92
- :record_identity => 'QT',
93
- :location => '700000001252',
94
- :published_arrival_time => '0605',
95
- :bay_number => "",
96
- :timing_point_indicator => 'T1',
97
- :fare_stage_indicator => 'F0'
91
+ expect Atco.parse_destination("QT7000000012520605 T1F0\r\n") == {
92
+ record_identity: "QT",
93
+ location: "700000001252",
94
+ published_arrival_time: "0605",
95
+ bay_number: "",
96
+ timing_point_indicator: "T1",
97
+ fare_stage_indicator: "F0"
98
98
  }
99
99
  end
100
-
100
+
101
101
  it "should parse intermediate" do
102
- Atco.parse_intermediate("QI70000000125607120712B T1F0\r\n").should == {
103
- :record_identity => 'QI',
104
- :location => '700000001256',
105
- :published_arrival_time => '0712',
106
- :published_departure_time => '0712',
107
- :activity_flag => "B",
108
- :bay_number => "",
109
- :timing_point_indicator => 'T1',
110
- :fare_stage_indicator => 'F0'
102
+ expect Atco.parse_intermediate("QI70000000125607120712B T1F0\r\n") == {
103
+ record_identity: "QI",
104
+ location: "700000001256",
105
+ published_arrival_time: "0712",
106
+ published_departure_time: "0712",
107
+ activity_flag: "B",
108
+ bay_number: "",
109
+ timing_point_indicator: "T1",
110
+ fare_stage_indicator: "F0"
111
111
  }
112
112
  end
113
-
113
+
114
114
  it "should parse origin" do
115
- Atco.parse_origin("QO7000000012520730 T1F0\r\n").should == {
116
- :record_identity => 'QO',
117
- :location => '700000001252',
118
- :published_departure_time => '0730',
119
- :bay_number => "",
120
- :timing_point_indicator => 'T1',
121
- :fare_stage_indicator => 'F0'
115
+ expect Atco.parse_origin("QO7000000012520730 T1F0\r\n") == {
116
+ record_identity: "QO",
117
+ location: "700000001252",
118
+ published_departure_time: "0730",
119
+ bay_number: "",
120
+ timing_point_indicator: "T1",
121
+ fare_stage_indicator: "F0"
122
122
  }
123
123
  end
124
124
 
125
125
  it "should parse journey header" do
126
- Atco.parse_journey_header("QSNTM 13986520091005 1111100 9A 9018 0 I\r\n").should == {
127
- :record_identity => 'QS',
128
- :transaction_type => 'N',
129
- :operator => 'TM',
130
- :unique_journey_identifier => '139865',
131
- :first_date_of_operation => '20091005',
132
- :last_date_of_operation => '',
133
- :operates_on_mondays => '1',
134
- :operates_on_tuesdays => '1',
135
- :operates_on_wednesdays => '1',
136
- :operates_on_thursdays => '1',
137
- :operates_on_fridays => '1',
138
- :operates_on_saturdays => '0',
139
- :operates_on_sundays => '0',
140
- :school_term_time => '',
141
- :bank_holidays => '',
142
- :route_number => '9A',
143
- :running_board => '9018',
144
- :vehicle_type => '0',
145
- :registration_number => '',
146
- :route_direction => 'I'
126
+ expect Atco.parse_journey_header("QSNTM 13986520091005 1111100 9A 9018 0 I\r\n") == {
127
+ record_identity: "QS",
128
+ transaction_type: "N",
129
+ operator: "TM",
130
+ unique_journey_identifier: "139865",
131
+ first_date_of_operation: "20091005",
132
+ last_date_of_operation: "",
133
+ operates_on_mondays: "1",
134
+ operates_on_tuesdays: "1",
135
+ operates_on_wednesdays: "1",
136
+ operates_on_thursdays: "1",
137
+ operates_on_fridays: "1",
138
+ operates_on_saturdays: "0",
139
+ operates_on_sundays: "0",
140
+ school_term_time: "",
141
+ bank_holidays: "",
142
+ route_number: "9A",
143
+ running_board: "9018",
144
+ vehicle_type: "0",
145
+ registration_number: "",
146
+ route_direction: "I"
147
147
  }
148
148
  end
149
149
 
150
- end
150
+ describe "with example.cif" do
151
+ before(:all) do
152
+ @atco = Atco.parse("spec/fixtures/example.cif")
153
+ end
154
+
155
+ it "should parse 1 journey" do
156
+ expect @atco[:journeys].size == 1
157
+ end
158
+
159
+ it "should parse journeys into Atco::Joruney objects" do
160
+ expect(@atco[:journeys]["139748"]).to be_a_kind_of(Atco::Journey)
161
+ end
162
+
163
+ it "should parse 6 stops for joureny 139748" do
164
+ expect @atco[:journeys]["139748"].stops.size == 6
165
+ end
166
+
167
+ it "should parse 6 stops for joureny 139748" do
168
+ expect @atco[:journeys]["139748"].stops.size == 6
169
+ end
170
+
171
+ it "should parse 2 locations" do
172
+ expect @atco[:locations].size == 2
173
+ end
174
+ end
175
+ 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
@@ -1,2 +1,6 @@
1
- require 'rubygems'
2
- require File.dirname(__FILE__) + '/../lib/atco'
1
+ # frozen_string_literal: true
2
+
3
+ require "rubygems"
4
+ require "rspec"
5
+
6
+ require "#{File.dirname(__FILE__)}/../lib/atco"
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
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 2
9
- version: 0.0.2
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
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
- date: 2010-02-22 00:00:00 +00:00
18
- default_executable:
19
- dependencies: []
20
-
21
- description: Simple and opinionated library for parsing ATCO-CIF files with Ruby.
11
+ date: 2024-04-11 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: '13.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '13.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: '3.9'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.9'
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
- extra_rdoc_files:
28
- - README.mdown
29
- files:
30
- - README.mdown
46
+ extra_rdoc_files:
47
+ - README.md
48
+ files:
49
+ - README.md
31
50
  - Rakefile
32
- - VERSION
33
51
  - lib/atco.rb
34
52
  - lib/atco/journey.rb
35
53
  - lib/atco/location.rb
36
54
  - lib/atco/stop.rb
37
- has_rdoc: true
55
+ - lib/atco/version.rb
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
- segments:
51
- - 0
52
- version: "0"
53
- required_rubygems_version: !ruby/object:Gem::Requirement
54
- requirements:
72
+ - !ruby/object:Gem::Version
73
+ version: 2.7.0
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
55
76
  - - ">="
56
- - !ruby/object:Gem::Version
57
- segments:
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: 3
66
- summary: Simple and opinionated library for parsing ATCO-CIF files with Ruby.
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: []
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.0.2