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

Structured road names, codes, destinations #91

Merged
merged 6 commits into from
Nov 15, 2016
Merged

Structured road names, codes, destinations #91

merged 6 commits into from
Nov 15, 2016

Conversation

1ec5
Copy link
Contributor

@1ec5 1ec5 commented Nov 9, 2016

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. 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

@1ec5 1ec5 added the improvement Improvement for an existing feature. label Nov 9, 2016
@1ec5 1ec5 self-assigned this Nov 9, 2016
@1ec5 1ec5 mentioned this pull request Nov 9, 2016
Copy link
Contributor

@freenerd freenerd left a 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.
Copy link
Contributor

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.
Copy link
Contributor

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

Copy link
Contributor Author

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 {
Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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).

Copy link
Contributor Author

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 {
Copy link
Contributor

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
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor Author

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
Copy link
Contributor

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 =)

Copy link
Contributor Author

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.

Copy link
Contributor

@freenerd freenerd left a 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 {
Copy link
Contributor

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.

Copy link
Contributor Author

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)
Copy link
Contributor

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?

Copy link
Contributor Author

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))
Copy link
Contributor

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.

Copy link
Contributor Author

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.
Copy link
Contributor

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.
@1ec5 1ec5 merged commit d37f7f0 into master Nov 15, 2016
@1ec5 1ec5 deleted the 1ec5-ref-67 branch November 15, 2016 16:54
@1ec5 1ec5 added the backwards incompatible changes that break backwards compatibility of public API label Dec 18, 2018
@1ec5 1ec5 added this to the v0.7.0 milestone Dec 18, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backwards incompatible changes that break backwards compatibility of public API improvement Improvement for an existing feature.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Serialize ref field
2 participants