-
Notifications
You must be signed in to change notification settings - Fork 92
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
Structured road names, codes, destinations #91
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good from my side, can't wait to integrate with instructions 😄
init(name: String?, ref: String?, destination: String?) { | ||
var codes: [String]? | ||
if let names = name, let ref = ref ?? destination { | ||
// OSRM v5.5 encodes the ref separately from the name but redundantly includes the ref in the name for backwards compatibility. Remove the ref from the name. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a feature of OSRM but of Mapbox Directions backwards-compatiblity
} | ||
codes = ref.tagValuesSeparatedByString(";") | ||
} else if let names = name, let codesRange = names.rangeOfString("\\(.+?\\)$", options: .RegularExpressionSearch, range: names.startIndex..<names.endIndex) { | ||
// OSRM v5.0 encodes the ref inside a parenthetical. Remove the ref from the name. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we are good dropping support for older OSRM versions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let’s tackle removing Directions API v4 support in a separate PR.
Changed RouteStep’s name and destinations properties into arrays, so that client code doesn’t have to do any splitting or parsing on its own. Removed redundant refs from the name property. Added a codes property that contains the route numbers. Updated test fixtures and tests.
|
||
init(name: String?, ref: String?, destination: String?) { | ||
var codes: [String]? | ||
if let names = name, let ref = ref ?? destination { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let ref = ref ?? destination
I think we should not put destination into ref, since these are difference concepts. We also have extra destination handling below, so I think ?? destination
can be removed here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that name
will never be undefined/nil
from OSRM, but an empty string "". So effectively this if
only tests for ref
being present.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ref
is a misnomer here: what I really meant is “whatever is inside the parentheses”, which can be either a ref or a destination, due to munging that either the Directions API or OSRM performs (not sure which).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed and fixed.
} else if let names = name, let codesRange = names.rangeOfString("\\(.+?\\)$", options: .RegularExpressionSearch, range: names.startIndex..<names.endIndex) { | ||
// Mapbox Directions API v4 encodes the ref inside a parenthetical. Remove the ref from the name. | ||
let parenthetical = names.substringWithRange(codesRange) | ||
if names == ref ?? destination { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above, remove ?? destination
|
||
let road = Road(name: name, ref: json["ref"] as? String, destination: json["destinations"] as? String) | ||
names = road.names | ||
codes = road.codes ?? road.destinationCodes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are destinationCodes mixed into codes
here? wouldn't it make more sense to create a new property to store them instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea here was to make it easier for applications to display a route shield for an upcoming ramp based on codes
without having to consult a separate property. We’ve since moved away from the notion that MapboxDirections.swift should perform any sort of munging, so I’ll remove this fallback.
I’ve gone back and forth quite a bit about whether destination codes should be conflated with destination
or live in a separate property. In OSM, destination:ref
usually follows a different format and encodes more information than ref
. For example, if I-80 travels over a ramp to go from one motorway to another, the highway=motorway_link
way is tagged ref=I 80
but may also be tagged destination:ref=I-80 West
. The format is loose enough that I don’t feel confident making destinationCodes
look like codes
. But I guess it can’t hurt much.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed. destinationCodes
is a separate property now.
let road = Road(name: name, ref: json["ref"] as? String, destination: json["destinations"] as? String) | ||
names = road.names | ||
codes = road.codes ?? road.destinationCodes | ||
destinations = road.destinations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume these are properties on self.
? Either these should be set that way, or below assignments should not have self.=
either (like self.intersections =
-> intersections =
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’ll remove self.
from self.intersections
, since there isn’t a conflict with a local variable named intersections
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ref ?? destination
continues to confuse me. I think these should stay separated, so they can be handled differently downstream. If you want to make sure that for a certain step we always have the correctly-chosen identifier, that should be handled via helper functions that look over all the data instead during initialization.
|
||
init(name: String?, ref: String?, destination: String?) { | ||
var codes: [String]? | ||
if let names = name, let gloss = ref ?? destination { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand the semantic meaning of gloss
and the dictionary did not help me understand. The case that in Mapbox Directions v5 destination
is mixed into name
can not exist. Likewise it makes no sense to me that codes
would ever have the contents of destination
in them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Turns out Directions API v5 used to conflate destination
with ref
in the parenthetical, but it no longer does so, much to my relief. I’ll gladly remove the fallbacks.
@@ -54,7 +54,7 @@ class V5Tests: XCTestCase { | |||
|
|||
XCTAssertNotNil(route) | |||
XCTAssertNotNil(route!.coordinates) | |||
XCTAssertEqual(route!.coordinates!.count, 842) | |||
XCTAssertEqual(route!.coordinates!.count, 28_442) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the semantics of 28_442
? Is this a range or math exponent syntax?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_
groups digits; it’s for human edification only and has no effect on the literal’s meaning. (C++ uses '
for the same purpose.)
|
||
let lane = intersection.approachLanes?.first | ||
let lane = intersection?.approachLanes?.first | ||
let indications = lane?.indications | ||
XCTAssertNotNil(indications) | ||
XCTAssertTrue(indications!.contains(.Left)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it might make sense to add a test for step.names
being populated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a test for this case.
let parenthetical = "(\(ref))" | ||
if names == ref { | ||
if let names = name, let gloss = ref ?? destination { | ||
// Mapbox Directions API v5 encodes the ref separately from the name but redundantly includes the ref or destination in the name for backwards compatibility. Remove the ref or destination from the name. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To clarify: This is not true, the direction
is never mixed into the name
, but only the ref
.
Removed an affordance for the destination being placed inside parentheses inside the name field, since the Directions API no longer does that. Separated destinationCodes from destinations and clarified the formats of codes and destinationCodes in OpenStreetMap data. Added tests of names in steps.
Changed RouteStep’s
name
anddestinations
properties into arrays, so that client code doesn’t have to do any splitting or parsing on its own. Removed redundant refs from the name property. Added acodes
property that contains the route numbers. Though a Route struct type is used internally during parsing, all the new properties live directly on RouteStep for easier Objective-C bridging.Also updated test fixtures and tests.
Fixes #67.
/cc @bsudekum @freenerd