Skip to content

Commit

Permalink
Support multiple .roadClassesToAvoid and .roadClassesToAllow para…
Browse files Browse the repository at this point in the history
…meters
  • Loading branch information
azarovalex committed Mar 14, 2022
1 parent 2b14b8c commit af2923b
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 10 deletions.
11 changes: 11 additions & 0 deletions Sources/MapboxDirections/RoadClasses.swift
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,14 @@ extension RoadClasses: Codable {
}
}
}

extension RoadClasses {
static var validAvoidClasses: RoadClasses {
// .restricted and .tunnel road types are not supported by Directions API anymore
return [.toll, .motorway, .ferry, .unpaved, .cashTollOnly]
}

static var validAllowClasses: RoadClasses {
return [.highOccupancyVehicle2, .highOccupancyVehicle3, .highOccupancyToll]
}
}
23 changes: 13 additions & 10 deletions Sources/MapboxDirections/RouteOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -281,20 +281,23 @@ open class RouteOptions: DirectionsOptions {
if let speed = speed {
params.append(URLQueryItem(name: CodingKeys.speed.stringValue, value: String(speed)))
}

if !roadClassesToAvoid.isEmpty && roadClassesToAvoid.isDisjoint(with: [.highOccupancyVehicle2, .highOccupancyVehicle3, .highOccupancyToll]) {
let allRoadClasses = roadClassesToAvoid.description.components(separatedBy: ",").filter { !$0.isEmpty }
precondition(allRoadClasses.count < 2, "You can only avoid one road class at a time.")
if let firstRoadClass = allRoadClasses.first {
params.append(URLQueryItem(name: CodingKeys.roadClassesToAvoid.stringValue, value: firstRoadClass))

if !roadClassesToAvoid.isEmpty {
if !roadClassesToAvoid.isSubset(of: .validAvoidClasses) {
assertionFailure("Provided road classes cannot be avoided")
}
let roadClasses = roadClassesToAvoid.intersection(.validAvoidClasses).description
params.append(URLQueryItem(name: CodingKeys.roadClassesToAvoid.stringValue, value: roadClasses))
}

roadClassesToAllow = [.highOccupancyVehicle3, .highOccupancyToll, .highOccupancyVehicle2]

if !roadClassesToAllow.isEmpty && roadClassesToAllow.isSubset(of: [.highOccupancyVehicle2, .highOccupancyVehicle3, .highOccupancyToll]) {
let allRoadClasses = roadClassesToAllow.description.components(separatedBy: ",").filter { !$0.isEmpty }
allRoadClasses.forEach { roadClass in
params.append(URLQueryItem(name: CodingKeys.roadClassesToAllow.stringValue, value: roadClass))
if !roadClassesToAllow.isEmpty {
if !roadClassesToAllow.isSubset(of: .validAllowClasses) {
assertionFailure("Provided road classes cannot be included")
}
let parameterValue = roadClassesToAllow.intersection(.validAllowClasses).description
params.append(URLQueryItem(name: CodingKeys.roadClassesToAllow.stringValue, value: parameterValue))
}

if refreshingEnabled && profileIdentifier == .automobileAvoidingTraffic {
Expand Down
12 changes: 12 additions & 0 deletions Tests/MapboxDirectionsTests/RouteOptionsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,18 @@ class RouteOptionsTests: XCTestCase {
XCTAssertTrue(options.urlQueryItems.contains(URLQueryItem(name: "max_width", value: String(widthValue))))
XCTAssertTrue(options.urlQueryItems.contains(URLQueryItem(name: "max_height", value: String(heightValue))))
}

func testExcludeAndIncludeRoadClasses() {
let options = RouteOptions(coordinates: [])
options.roadClassesToAvoid = .validAvoidClasses
options.roadClassesToAllow = .validAllowClasses

let expectedExcludeQueryItem = URLQueryItem(name: "exclude", value: "toll,motorway,ferry,unpaved,cash_only_toll")
XCTAssertTrue(options.urlQueryItems.contains(expectedExcludeQueryItem))

let expectedIncludeQueryItem = URLQueryItem(name: "include", value: "hov2,hov3,hot")
XCTAssertTrue(options.urlQueryItems.contains(expectedIncludeQueryItem))
}
}

fileprivate let testCoordinates = [
Expand Down

0 comments on commit af2923b

Please sign in to comment.