Skip to content

Port OSRM Text Instructions to v0.5.0 #26

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

Merged
merged 4 commits into from
Jul 7, 2017
Merged
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 Cartfile
Original file line number Diff line number Diff line change
@@ -1 +1 @@
github "mapbox/MapboxDirections.swift" ~> 0.9
github "mapbox/MapboxDirections.swift" ~> 0.10
2 changes: 1 addition & 1 deletion Cartfile.resolved
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
github "mapbox/MapboxDirections.swift" "v0.9.0"
github "mapbox/MapboxDirections.swift" "v0.10.0"
github "raphaelmor/Polyline" "v4.1.1"
2 changes: 1 addition & 1 deletion OSRMTextInstructions.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Pod::Spec.new do |s|
s.requires_arc = true
s.module_name = "OSRMTextInstructions"

s.dependency "MapboxDirections.swift", "~> 0.9"
s.dependency "MapboxDirections.swift", "~> 0.10"

s.prepare_command = "./json2plist.sh"

Expand Down
25 changes: 17 additions & 8 deletions OSRMTextInstructions/OSRMTextInstructions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,10 @@ public class OSRMInstructionFormatter: Formatter {
typealias InstructionsByModifier = [String: InstructionsByToken]

override public func string(for obj: Any?) -> String? {
return string(for: obj, modifyValueByKey: nil)
return string(for: obj, legIndex: nil, numberOfLegs: nil, modifyValueByKey: nil)
}

public func string(for obj: Any?, modifyValueByKey: ((TokenType, String) -> String)?) -> String? {
public func string(for obj: Any?, legIndex: Int?, numberOfLegs: Int?, modifyValueByKey: ((TokenType, String) -> String)?) -> String? {
guard let step = obj as? RouteStep else {
return nil
}
Expand Down Expand Up @@ -212,7 +212,11 @@ public class OSRMInstructionFormatter: Formatter {
// Decide which instruction string to use
// Destination takes precedence over name
var instruction: String
if let _ = step.destinations, let obj = instructionObject["destination"] {
if let _ = step.destinations, let _ = step.exitCodes?.first, let obj = instructionObject["exit_destination"] {
instruction = obj
} else if let _ = step.destinations, let obj = instructionObject["destination"] {
instruction = obj
} else if let _ = step.exitCodes?.first, let obj = instructionObject["exit"] {
instruction = obj
} else if !wayName.isEmpty, let obj = instructionObject["name"] {
instruction = obj
Expand All @@ -221,11 +225,15 @@ public class OSRMInstructionFormatter: Formatter {
}

// Prepare token replacements
let nthWaypoint = "" // TODO: add correct waypoint counting
var nthWaypoint: String? = nil
if let legIndex = legIndex, let numberOfLegs = numberOfLegs, legIndex != numberOfLegs - 1 {
nthWaypoint = ordinalFormatter.string(from: (legIndex + 1) as NSNumber)
}
let exitCode = step.exitCodes?.first ?? ""
let destination = step.destinations?.first ?? ""
var exit: String = ""
var exitOrdinal: String = ""
if let exitIndex = step.exitIndex, exitIndex <= 10 {
exit = ordinalFormatter.string(from: exitIndex as NSNumber)!
exitOrdinal = ordinalFormatter.string(from: exitIndex as NSNumber)!
}
let modifierConstants = constants["modifier"] as! [String: String]
let modifierConstant = modifierConstants[modifier ?? "straight"]!
Expand Down Expand Up @@ -257,12 +265,13 @@ public class OSRMInstructionFormatter: Formatter {
switch tokenType {
case .wayName: replacement = wayName
case .destination: replacement = destination
case .exit: replacement = exit
case .exitCode: replacement = exitCode
case .exitIndex: replacement = exitOrdinal
case .rotaryName: replacement = rotaryName
case .laneInstruction: replacement = laneInstruction ?? ""
case .modifier: replacement = modifierConstant
case .direction: replacement = directionFromDegree(degree: bearing)
case .wayPoint: replacement = nthWaypoint
case .wayPoint: replacement = nthWaypoint ?? ""
}
if tokenType == .wayName {
result += replacement // already modified above
Expand Down
15 changes: 10 additions & 5 deletions OSRMTextInstructions/TokenType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ public enum TokenType: Int, CustomStringConvertible {
case wayName
case destination
case rotaryName
case exit
case exitCode
case exitIndex
case laneInstruction
case modifier
case direction
Expand All @@ -21,15 +22,17 @@ public enum TokenType: Int, CustomStringConvertible {
type = .destination
case "rotary_name":
type = .rotaryName
case "exit":
type = .exitCode
case "exit_number":
type = .exit
type = .exitIndex
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not stick with the js names exit and exitNumber?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same reasoning as in mapbox/mapbox-directions-swift#147, where exitCodes is for what’s colloquially called an exit number (exitIdentifiers being another candidate) and exitIndex remains the count of exits from the beginning of the step. I figured consistency with MapboxDirections.swift would be more important for Swift developers than consistency with the JavaScript library they’ll never use. But if you think it’s more important to keep the libraries consistent with each other (to make merging more straightforward?), I can change them to exit and exitNumber here.

Copy link
Member Author

@1ec5 1ec5 Jul 7, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per discussion with @bsudekum, I’m going to merge this and get a release out in order to unblock a navigation SDK release. However, if you think we should change the enumeration values back to match the JavaScript version, please open a ticket and we can address it in a subsequent release. (We’re pre-1.0, so we don’t have to worry much about backwards compatibility.)

case "lane_instruction":
type = .laneInstruction
case "modifier":
type = .modifier
case "direction":
type = .direction
case "way_point":
case "nth":
type = .wayPoint
default:
return nil
Expand All @@ -45,7 +48,9 @@ public enum TokenType: Int, CustomStringConvertible {
return "destination"
case .rotaryName:
return "rotary_name"
case .exit:
case .exitCode:
return "exit"
case .exitIndex:
return "exit_number"
case .laneInstruction:
return "lane_instruction"
Expand All @@ -54,7 +59,7 @@ public enum TokenType: Int, CustomStringConvertible {
case .direction:
return "direction"
case .wayPoint:
return "way_point"
return "nth"
}
}
}
16 changes: 14 additions & 2 deletions OSRMTextInstructionsTests/OSRMTextInstructionsTests.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import XCTest
import MapboxDirections
import OSRMTextInstructions
@testable import OSRMTextInstructions

class OSRMTextInstructionsTests: XCTestCase {
let instructions = OSRMInstructionFormatter(version: "v5")

override func setUp() {
super.setUp()

// Force an English locale to match the fixture language rather than the test machine’s language.
instructions.ordinalFormatter.locale = Locale(identifier: "en-US")
}

func testSentenceCasing() {
XCTAssertEqual("Capitalized String", "capitalized String".sentenceCased)
Expand All @@ -27,11 +34,12 @@ class OSRMTextInstructionsTests: XCTestCase {
XCTAssert(false, "invalid json")
return
}
let options = json["options"] as? [String: Int]

let step = RouteStep(json: json["step"] as! [String: Any])

// compile instruction
let instruction = instructions.string(for: step)
let instruction = instructions.string(for: step, legIndex: options?["legIndex"], numberOfLegs: options?["legCount"], modifyValueByKey: nil)

// check generated instruction against fixture
XCTAssertEqual(
Expand Down Expand Up @@ -78,6 +86,9 @@ class OSRMTextInstructionsTests: XCTestCase {
if let ref = jsonStep["ref"] {
step["ref"] = ref
}
if let exits = jsonStep["exits"] {
step["exits"] = exits
}
if let destinations = jsonStep["destinations"] {
step["destinations"] = destinations
}
Expand Down Expand Up @@ -107,6 +118,7 @@ class OSRMTextInstructionsTests: XCTestCase {
fixture["step"] = step
fixture["instruction"] = (json["instructions"] as! [ String: Any ])["en"] as! String

fixture["options"] = json["options"]
return fixture
}
}
2 changes: 1 addition & 1 deletion osrm-text-instructions