Skip to content

Commit

Permalink
Additional Incident members (#672)
Browse files Browse the repository at this point in the history
* vk-1040-incidents-fields: added missing Incident fields; unit test updated; CHANGELOG updated
  • Loading branch information
Udumft committed Mar 31, 2022
1 parent 8284de2 commit 9daac3f
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,7 @@
* Fixed a crash that occurred when `RouteOptions.roadClassesToAvoid` or `RouteOptions.roadClassesToAllow` properties contained multiple road classes.
* `RoadClasses.tunnel` and `RoadClasses.restricted` are no longer supported in `RouteOptions.roadClassesToAvoid` or `RouteOptions.roadClassesToAllow` properties
* Added `DirectionsOptions(url:)`, `RouteOptions(url:)` and extended existing `DirectionsOptions(waypoints:profileIdentifier:queryItems:)`, `RouteOptions(waypoints:profileIdentifier:queryItems:)`, `MatchOptions(waypoints:profileIdentifier:queryItems:)` and related convenience init methods for deserializing corresponding options object using appropriate request URL or it's query items. ([#655](https://github.com/mapbox/mapbox-directions-swift/pull/655))
* Added `Incident` properties: `countryCode`, `countryCodeAlpha3`, `roadIsClosed`, `longDescription`, `numberOfBlockedLanes`, `congestionLevel`, `affectedRoadNames`. ([#672](https://github.com/mapbox/mapbox-directions-swift/pull/672))

## v2.3.0

Expand Down
73 changes: 72 additions & 1 deletion Sources/MapboxDirections/Incident.swift
Expand Up @@ -19,6 +19,13 @@ public struct Incident: Codable, Equatable {
case lanesBlocked = "lanes_blocked"
case geometryIndexStart = "geometry_index_start"
case geometryIndexEnd = "geometry_index_end"
case countryCodeAlpha3 = "iso_3166_1_alpha3"
case countryCode = "iso_3166_1_alpha2"
case roadIsClosed = "closed"
case longDescription = "long_description"
case numberOfBlockedLanes = "num_lanes_blocked"
case congestionLevel = "congestion"
case affectedRoadNames = "affected_road_names"
}

/// Defines known types of incidents.
Expand Down Expand Up @@ -65,6 +72,21 @@ public struct Incident: Codable, Equatable {
case low
}

private struct CongestionContainer: Codable {
// `Directions` define this as service value to indicate "no congestion calculated"
// see: https://docs.mapbox.com/api/navigation/directions/#incident-object
private static let CongestionUnavailableKey = 101

enum CodingKeys: String, CodingKey {
case value
}

let value: Int
var clampedValue: Int? {
value == Self.CongestionUnavailableKey ? nil : value
}
}

/// Incident identifier
public var identifier: String
/// The kind of an incident
Expand All @@ -88,6 +110,24 @@ public struct Incident: Codable, Equatable {
public var subtype: String?
/// Breif description of the subtype. May be not available for all incident types and is not available if `subtype` is `nil`
public var subtypeDescription: String?
/// The three-letter ISO 3166-1 alpha-3 code for the country the incident is located in. Example: "USA".
public var countryCodeAlpha3: String?
/// The two-letter ISO 3166-1 alpha-2 code for the country the incident is located in. Example: "US".
public var countryCode: String?
/// If this is true then the road has been completely closed.
public var roadIsClosed: Bool?
/// A long description of the incident in a human-readable format.
public var longDescription: String?
/// The number of items in the `lanesBlocked`.
public var numberOfBlockedLanes: Int?
/// Information about the amount of congestion on the road around the incident.
///
/// A number between 0 and 100 representing the level of congestion caused by the incident. The higher the number, the more congestion there is. A value of 0 means there is no congestion on the road. A value of 100 means that the road is closed.
public var congestionLevel: NumericCongestionLevel?
/// List of roads names affected by the incident.
///
/// Alternate road names are separated by a /. The list is ordered from the first affected road to the last one that the incident lies on.
public var affectedRoadNames: [String]?
/// Contains list of ISO 14819-2:2013 codes
///
/// See https://www.iso.org/standard/59231.html for details
Expand All @@ -110,7 +150,14 @@ public struct Incident: Codable, Equatable {
subtypeDescription: String?,
alertCodes: Set<Int>,
lanesBlocked: BlockedLanes?,
shapeIndexRange: Range<Int>) {
shapeIndexRange: Range<Int>,
countryCodeAlpha3: String? = nil,
countryCode: String? = nil,
roadIsClosed: Bool? = nil,
longDescription: String? = nil,
numberOfBlockedLanes: Int? = nil,
congestionLevel: NumericCongestionLevel? = nil,
affectedRoadNames: [String]? = nil) {
self.identifier = identifier
self.rawKind = type.rawValue
self.description = description
Expand All @@ -123,6 +170,13 @@ public struct Incident: Codable, Equatable {
self.alertCodes = alertCodes
self.lanesBlocked = lanesBlocked
self.shapeIndexRange = shapeIndexRange
self.countryCodeAlpha3 = countryCodeAlpha3
self.countryCode = countryCode
self.roadIsClosed = roadIsClosed
self.longDescription = longDescription
self.numberOfBlockedLanes = numberOfBlockedLanes
self.congestionLevel = congestionLevel
self.affectedRoadNames = affectedRoadNames
}

public init(from decoder: Decoder) throws {
Expand Down Expand Up @@ -166,6 +220,14 @@ public struct Incident: Codable, Equatable {
let geometryIndexStart = try container.decode(Int.self, forKey: .geometryIndexStart)
let geometryIndexEnd = try container.decode(Int.self, forKey: .geometryIndexEnd)
shapeIndexRange = geometryIndexStart..<geometryIndexEnd

countryCodeAlpha3 = try container.decodeIfPresent(String.self, forKey: .countryCodeAlpha3)
countryCode = try container.decodeIfPresent(String.self, forKey: .countryCode)
roadIsClosed = try container.decodeIfPresent(Bool.self, forKey: .roadIsClosed)
longDescription = try container.decodeIfPresent(String.self, forKey: .longDescription)
numberOfBlockedLanes = try container.decodeIfPresent(Int.self, forKey: .numberOfBlockedLanes)
congestionLevel = try container.decodeIfPresent(CongestionContainer.self, forKey: .congestionLevel)?.clampedValue
affectedRoadNames = try container.decodeIfPresent([String].self, forKey: .affectedRoadNames)
}

public func encode(to encoder: Encoder) throws {
Expand All @@ -185,5 +247,14 @@ public struct Incident: Codable, Equatable {
try container.encodeIfPresent(lanesBlocked, forKey: .lanesBlocked)
try container.encode(shapeIndexRange.lowerBound, forKey: .geometryIndexStart)
try container.encode(shapeIndexRange.upperBound, forKey: .geometryIndexEnd)
try container.encodeIfPresent(countryCodeAlpha3, forKey: .countryCodeAlpha3)
try container.encodeIfPresent(countryCode, forKey: .countryCode)
try container.encodeIfPresent(roadIsClosed, forKey: .roadIsClosed)
try container.encodeIfPresent(longDescription, forKey: .longDescription)
try container.encodeIfPresent(numberOfBlockedLanes, forKey: .numberOfBlockedLanes)
if let congestionLevel = congestionLevel {
try container.encode(CongestionContainer(value: congestionLevel), forKey: .congestionLevel)
}
try container.encodeIfPresent(affectedRoadNames, forKey: .affectedRoadNames)
}
}
19 changes: 16 additions & 3 deletions Tests/MapboxDirectionsTests/Fixtures/incidents.json
Expand Up @@ -24353,7 +24353,18 @@
],
"lanes_blocked": ["RIGHT", "SIDE"],
"geometry_index_start": 353,
"geometry_index_end": 367
"geometry_index_end": 367,
"iso_3166_1_alpha3": "DEU",
"iso_3166_1_alpha2": "DE",
"closed": false,
"num_lanes_blocked": 2,
"congestion": {
"value": 50
},
"affected_road_names": [
"A96",
"test"
]
},
{
"id": "12779545487967908590",
Expand All @@ -24370,7 +24381,8 @@
701
],
"geometry_index_start": 476,
"geometry_index_end": 566
"geometry_index_end": 566,
"closed": true
},
{
"id": "2113169574233653303",
Expand All @@ -24388,7 +24400,8 @@
],
"lanes_blocked": ["unknown lane type"],
"geometry_index_start": 810,
"geometry_index_end": 900
"geometry_index_end": 900,
"num_lanes_blocked": 1
}
],
"distance": 109978.258,
Expand Down
7 changes: 7 additions & 0 deletions Tests/MapboxDirectionsTests/RouteStepTests.swift
Expand Up @@ -343,9 +343,16 @@ class RouteStepTests: XCTestCase {
XCTAssert(leg.incidents!.first!.kind == Incident.Kind.miscellaneous)
XCTAssert(leg.incidents!.first!.impact == Incident.Impact.minor)
XCTAssert(leg.incidents![0].lanesBlocked!.contains(.right))
XCTAssert(leg.incidents![0].countryCodeAlpha3 == "DEU")
XCTAssert(leg.incidents![0].countryCode == "DE")
XCTAssert(leg.incidents![0].congestionLevel == 50)
XCTAssert(leg.incidents![0].affectedRoadNames?.count == 2)
XCTAssertNil(leg.incidents![1].lanesBlocked)
XCTAssertTrue(leg.incidents![1].roadIsClosed!)
XCTAssert(leg.incidents![2].lanesBlocked!.isEmpty)
XCTAssert(leg.incidents![2].shapeIndexRange == 810..<900)
XCTAssert(leg.incidents![2].numberOfBlockedLanes == 1)
XCTAssertNil(leg.incidents![2].roadIsClosed)
XCTAssert(leg.incidents!.first! == leg.incidents!.first!)

XCTAssert(leg.steps.contains(where: { $0.exitIndex != nil }))
Expand Down

0 comments on commit 9daac3f

Please sign in to comment.