Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: handle Ulsterbus formatted files #16

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
pkg/*
checksums/*
*.gem
spec/artefacts/test.json
spec/artefacts/*.json
.rspec_status
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,20 @@ irb
require 'rubygems'
require 'atco'

result = Atco.parse('filename.cif')
result = Atco.parse('SVRTMAO009A-20091005.cif) # an example data file in the repo
result = Atco.parse("filename.cif")
# example data files in the repo
result = Atco.parse("spec/fixtures/translink/SVRTMAO009A-20091005.cif")
result = Atco.parse("spec/fixtures/ulsterbus/Y18_Antrim_1_Sept_2023.cif")

=> {
header: {…},
locations: […],
journies: {…}
header: {…}, # Atco::Header
locations: […], # Atco::Location
journeys: {
"journey_identifier": {…} # Atco::Journey
},
unparsed: [
{line: "unparsed line", line_number:1234}
]
}
```

Expand Down
29 changes: 22 additions & 7 deletions lib/atco.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,20 @@ class << self # rubocop:disable Metrics/ClassLength
destination: "QT",
intermediate: "QI",
origin: "QO",
journey_header: "QS"
journey_header: "QS",
route_description: "QD"
}.freeze
METHODS_BY_RECORD_IDENTITY = METHODS.invert.freeze

def parse(file) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
@path = File.expand_path(file)
data = File.readlines(@path)

objects = []
current_journey = nil
current_location = nil
locations = []
journeys = {}
routes = []
header = nil
unparsed = []

Expand All @@ -54,6 +55,9 @@ def parse(file) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity,
next unless object[:record_identity] && object[:record_identity] == identifier

case method
when :route_description
routes << object
next # TODO: combine journey and route somehow
when :journey_header
current_journey = object
when :location
Expand All @@ -69,14 +73,12 @@ def parse(file) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity,
journeys[current_journey[:unique_journey_identifier]] = Journey.new(object)
end
end
objects << object
rescue UnidentifiedRecordError
unparsed << { line: line, line_number: line_number }
next
end
objects << object
end
{ header: header, locations: locations, journeys: journeys, unparsed: unparsed }
{ header: header, locations: locations, journeys: journeys, routes: routes, unparsed: unparsed }
end

def parse_bank_holiday(string)
Expand Down Expand Up @@ -113,7 +115,9 @@ def parse_location(string)
transaction_type: string[2, 1],
location: parse_value(string[3, 12]),
full_location: parse_value(string[15, 48]),
gazetteer_code: string[63, 1]
gazetteer_code: string[63, 1].strip,
point_type: string[64, 1].strip,
national_gazeteer_id: string[65, 8].strip
}
end

Expand Down Expand Up @@ -157,7 +161,7 @@ def parse_journey_header(string) # rubocop:disable Metrics/AbcSize, Metrics/Meth
record_identity: string[0, 2],
transaction_type: string[2, 1],
operator: string[3, 4].strip,
unique_journey_identifier: string[7, 6],
unique_journey_identifier: string[7, 6].strip,
first_date_of_operation: parse_value(string[13, 8]),
last_date_of_operation: parse_value(string[21, 8]),
operates_on_mondays: string[29, 1],
Expand All @@ -177,6 +181,17 @@ def parse_journey_header(string) # rubocop:disable Metrics/AbcSize, Metrics/Meth
}
end

def parse_route_description(string)
{
record_identity: string[0, 2],
transaction_type: string[2, 1],
operator: string[3, 4].strip,
route_number: string[8, 4].strip,
route_direction: string[11, 1].strip,
route_description: string[12, 68].strip
}
end

def parse_value(value)
value&.strip
end
Expand Down
49 changes: 46 additions & 3 deletions spec/atco_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,30 @@
)
end

it "should parse location" do
it "should parse translink location" do
expect(Atco.parse_location("QLN700000001252Conway (River Rd) 1\r\n")).to eq(
{
record_identity: "QL",
transaction_type: "N",
location: "700000001252",
full_location: "Conway (River Rd)",
gazetteer_code: "1"
gazetteer_code: "1",
point_type: "",
national_gazeteer_id: ""
}
)
end

it "should parse ulsterbus location" do
expect(Atco.parse_location("QLN700000015558Meetinghouse Lane A0000001\r\n")).to eq(
{
record_identity: "QL",
transaction_type: "N",
location: "700000015558",
full_location: "Meetinghouse Lane",
gazetteer_code: "",
point_type: "",
national_gazeteer_id: "A0000001"
}
)
end
Expand Down Expand Up @@ -93,7 +109,7 @@
)
end

it "should parse journey header" do
it "should parse translink journey header" do
expect(Atco.parse_journey_header("QSNTM 13986520091005 1111100 9A 9018 0 I\r\n")).to eq(
{
record_identity: "QS",
Expand All @@ -119,4 +135,31 @@
}
)
end

it "should parse ulsterbus journey header" do
expect(Atco.parse_journey_header("QSNUTS 1700 20230901999999990000010 X321e LF O\r\n")).to eq(
{
record_identity: "QS",
transaction_type: "N",
operator: "UTS",
unique_journey_identifier: "1700",
first_date_of_operation: "20230901",
last_date_of_operation: "99999999",
operates_on_mondays: "0",
operates_on_tuesdays: "0",
operates_on_wednesdays: "0",
operates_on_thursdays: "0",
operates_on_fridays: "0",
operates_on_saturdays: "1",
operates_on_sundays: "0",
school_term_time: "",
bank_holidays: "X",
route_number: "321e",
running_board: "",
vehicle_type: "LF",
registration_number: "",
route_direction: "O"
}
)
end
end
Loading
Loading