Skip to content

Commit

Permalink
Incidents refreshing (#704)
Browse files Browse the repository at this point in the history
* vk-1634-incidents refresh: added Route.refreshLegIncidents method to refresh incidents data. Unit tests updated; CHANGELOG updated; API breakage accepted
  • Loading branch information
Udumft committed Jun 2, 2022
1 parent 7038b4e commit 5905f95
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 6 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changes to Mapbox Directions for Swift

## main

* Added `Route.refreshLegIncidents(from:)` method to allow refreshing `RouteLeg.incidents` during a route refresh. ([#704](https://github.com/mapbox/mapbox-directions-swift/pull/704))

## v2.5.0

* Added the `RestStop.name` property. ([#689](https://github.com/mapbox/mapbox-directions-swift/pull/689))
Expand Down
2 changes: 1 addition & 1 deletion Sources/MapboxDirections/Directions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ open class Directions: NSObject {
- parameter credentials: An object containing the credentials used to make the request.
- parameter result: A `Result` enum that represents the `RouteRefreshResponse` if the request returned successfully, or the error if it did not.
- postcondition: To update the original route, pass `RouteRefreshResponse.route` into the `Route.refreshLegAttributes(from:)` method.
- postcondition: To update the original route, pass `RouteRefreshResponse.route` into the `Route.refreshLegAttributes(from:)` and `Route.refreshLegIncidents(from:)` methods.
*/
public typealias RouteRefreshCompletionHandler = (_ credentials: Credentials, _ result: Result<RouteRefreshResponse, DirectionsError>) -> Void

Expand Down
4 changes: 4 additions & 0 deletions Sources/MapboxDirections/RefreshedRoute.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,27 @@ public struct RefreshedRouteLeg: ForeignMemberContainer {
public var foreignMembers: JSONObject = [:]

public var attributes: RouteLeg.Attributes
public var incidents: [Incident]?
}

extension RefreshedRouteLeg: Codable {
enum CodingKeys: String, CodingKey {
case attributes = "annotation"
case incidents = "incidents"
}

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
attributes = try container.decode(RouteLeg.Attributes.self, forKey: .attributes)
incidents = try container.decodeIfPresent([Incident].self, forKey: .incidents)

try decodeForeignMembers(notKeyedBy: CodingKeys.self, with: decoder)
}

public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(attributes, forKey: .attributes)
try container.encodeIfPresent(incidents, forKey: .incidents)

try encodeForeignMembers(notKeyedBy: CodingKeys.self, to: encoder)
}
Expand Down
13 changes: 12 additions & 1 deletion Sources/MapboxDirections/RouteRefreshResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public struct RouteRefreshResponse: ForeignMemberContainer {
/**
A skeleton route that contains only the time-sensitive information that has been updated.
Use the `Route.refreshLegAttributes(from:)` method to merge this object with the original route to continue using the original route with updated information.
Use the `Route.refreshLegAttributes(from:)` and `Route.refreshLegIncidents(from:)` methods to merge this object with the original route to continue using the original route with updated information.
*/
public var route: RefreshedRoute

Expand Down Expand Up @@ -111,4 +111,15 @@ extension Route {
leg.attributes = refreshedLeg.refreshedAttributes
}
}

/**
Merges the incidents of the given route’s legs into the receiver’s legs.
- parameter refreshedRoute: The route containing leg incidents to merge into the receiver. If this route contains fewer legs than the receiver, this method skips legs from the beginning of the route to make up the difference, so that merging the incidents from a one-leg route affects only the last leg of the receiver.
*/
public func refreshLegIncidents(from refreshedRoute: RouteRefreshSource) {
for (leg, refreshedLeg) in zip(legs.suffix(refreshedRoute.refreshedLegs.count), refreshedRoute.refreshedLegs) {
leg.incidents = refreshedLeg.refreshedIncidents
}
}
}
17 changes: 17 additions & 0 deletions Sources/MapboxDirections/RouteRefreshSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,43 @@ public protocol RouteRefreshSource {
*/
public protocol RouteLegRefreshSource {
var refreshedAttributes: RouteLeg.Attributes { get }
var refreshedIncidents: [Incident]? { get }
}

public extension RouteLegRefreshSource {
var refreshedIncidents: [Incident]? {
return nil
}
}

extension Route: RouteRefreshSource {
public var refreshedLegs: [RouteLegRefreshSource] {
legs
}
}

extension RouteLeg: RouteLegRefreshSource {
public var refreshedAttributes: Attributes {
attributes
}

public var refreshedIncidents: [Incident]? {
incidents
}
}

extension RefreshedRoute: RouteRefreshSource {
public var refreshedLegs: [RouteLegRefreshSource] {
legs
}
}

extension RefreshedRouteLeg: RouteLegRefreshSource {
public var refreshedAttributes: RouteLeg.Attributes {
attributes
}

public var refreshedIncidents: [Incident]? {
incidents
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,35 @@
"route": {
"legs": [
{
"incidents": [
{
"id": "12727074056824787215",
"type": "miscellaneous",
"description": "Bei Windach - Verkehrsbehinderung.",
"long_description": "Bei Windach - Verkehrsbehinderung. A96 Lindau Richtung München in Höhe Windach Grünpflege, bis 04.11.2020 15:00 Uhr",
"creation_time": "2020-11-04T09:51:00Z",
"start_time": "2020-11-04T07:07:50Z",
"end_time": "2020-11-04T14:00:00Z",
"impact": "minor",
"alertc_codes": [
1
],
"lanes_blocked": ["RIGHT", "SIDE"],
"geometry_index_start": 10,
"geometry_index_end": 15,
"iso_3166_1_alpha3": "DEU",
"iso_3166_1_alpha2": "DE",
"closed": false,
"num_lanes_blocked": 2,
"congestion": {
"value": 50
},
"affected_road_names": [
"A96",
"test"
]
}
],
"annotation": {
"duration": [
34.3,
Expand Down Expand Up @@ -353,6 +382,26 @@
}
},
{
"incidents": [
{
"id": "12779545487967908590",
"type": "construction",
"description": "Zwischen Eching und Inning a. Ammersee - Baustelle.",
"long_description": "Zwischen Eching und Inning a. Ammersee - Baustelle.",
"creation_time": "2020-11-04T09:51:00Z",
"start_time": "2020-07-03T17:00:00Z",
"end_time": "2020-12-08T04:30:00Z",
"impact": "minor",
"sub_type": "CONSTRUCTION",
"sub_type_description": "construction",
"alertc_codes": [
701
],
"geometry_index_start": 7,
"geometry_index_end": 14,
"closed": true
}
],
"annotation": {
"duration": [
4.9,
Expand Down
11 changes: 8 additions & 3 deletions Tests/MapboxDirectionsTests/RouteRefreshTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,10 @@ class RouteRefreshTests: XCTestCase {

let route = routeResponse.routes?[routeIndex]
route?.refreshLegAttributes(from: refresh.route)
route?.refreshLegIncidents(from: refresh.route)

XCTAssertEqual(refresh.route.legs[0].attributes, route?.legs[0].attributes, "Route legs are not refreshed")
XCTAssertEqual(refresh.route.legs[0].attributes, route?.legs[0].attributes, "Route legs attributes are not refreshed")
XCTAssertEqual(refresh.route.legs[0].incidents, route?.legs[0].incidents, "Route legs incidents are not refreshed")
routeUpdatedExpectation.fulfill()
}
}
Expand All @@ -127,8 +129,11 @@ class RouteRefreshTests: XCTestCase {
XCTAssertEqual(response.route.legs.count, 2)
let route = routeResponse.routes?[routeIndex]
route?.refreshLegAttributes(from: response.route)
XCTAssertEqual(route?.legs[0].attributes, response.route.legs[0].attributes, "Route legs are not refreshed correctly")
XCTAssertEqual(route?.legs[1].attributes, response.route.legs[1].attributes, "Route legs are not refreshed correctly")
route?.refreshLegIncidents(from: response.route)
XCTAssertEqual(route?.legs[0].attributes, response.route.legs[0].attributes, "Route legs attributes are not refreshed correctly")
XCTAssertEqual(route?.legs[1].attributes, response.route.legs[1].attributes, "Route legs attributes are not refreshed correctly")
XCTAssertEqual(route?.legs[0].incidents, response.route.legs[0].incidents, "Route legs incidents are not refreshed correctly")
XCTAssertEqual(route?.legs[1].incidents, response.route.legs[1].incidents, "Route legs incidents are not refreshed correctly")
routeUpdatedExpectation.fulfill()
case let .failure(error):
XCTFail("Refresh failed with unexpected error: \(error).")
Expand Down
2 changes: 1 addition & 1 deletion swift-package-baseline/breakage-allowlist-path.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@

API breakage: var RouteLegRefreshSource.refreshedIncidents has been added as a protocol requirement

0 comments on commit 5905f95

Please sign in to comment.