From 833258e2bb48280ee44c0695607d2be325663b6c Mon Sep 17 00:00:00 2001 From: Jacob Brady Date: Fri, 8 Dec 2023 18:15:19 -0500 Subject: [PATCH] Release version 4.2.0 (#14) This PR releases version 4.2.0 of the IBI.WZDx library which updates the models in accordance with WZDx 4.2. --- README.md | 6 +-- src/IBI.WZDx/IBI.WZDx.csproj | 2 +- .../FieldDevices/FieldDeviceCoreDetails.cs | 14 +++++- .../Models/FieldDevices/FlashingBeacon.cs | 5 +- .../Models/FieldDevices/MarkedLocationType.cs | 5 ++ src/IBI.WZDx/Models/RoadDirection.cs | 10 ++++ .../RoadEvents/CdsCurbZonesReference.cs | 49 +++++++++++++++++++ src/IBI.WZDx/Models/RoadEvents/LaneStatus.cs | 6 +-- .../Models/RoadEvents/WorkZoneType.cs | 31 ++++++++++++ .../RoadEvents/WorkZones/WorkZoneRoadEvent.cs | 29 ++++++++++- .../IBI.WZDx.UnitTests/WzdxSerializerTests.cs | 30 +++++++++--- 11 files changed, 168 insertions(+), 19 deletions(-) create mode 100644 src/IBI.WZDx/Models/RoadEvents/CdsCurbZonesReference.cs create mode 100644 src/IBI.WZDx/Models/RoadEvents/WorkZoneType.cs diff --git a/README.md b/README.md index b7f9e15..92b7c92 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# IBI WZDx .NET Library +# WZDx .NET Library This repository contains the source code for IBI Group's [.NET 6.0](https://docs.microsoft.com/en-us/dotnet/core/whats-new/dotnet-6) [WZDx (Work Zone Data Exchange)](https://github.com/usdot-jpo-ode/wzdx) class library, `IBI.WZDx`. @@ -14,7 +14,7 @@ The library provides the following functionality: ### WZDx Version Support -WZDx versions 4.0 and 4.1 are supported; the [WzdxSerializer](./src/IBI.WZDx/Serialization/WzdxSerializer.cs) defaults to outputting v4.1 (latest WZDx). +WZDx versions 4.0, 4.1, and 4.2 are supported; the [WzdxSerializer](./src/IBI.WZDx/Serialization/WzdxSerializer.cs) defaults to outputting v4.2 (latest WZDx). [Detour road events](https://github.com/usdot-jpo-ode/wzdx/blob/main/spec-content/objects/DetourRoadEvent.md) are not supported. When provided with a Work Zone Feed that includes detour road events, the WzdxSerializer.DeserializeFeed method will deserialize the detour events into a [RoadEventFeature](./src/IBI.WZDx/Models/RoadEvents/RoadEventFeature.cs) with `Properties` as `null`. @@ -75,4 +75,4 @@ This solution includes a [IBI.WZDx.UnitTests](/tests/IBI.WZDx.UnitTests/) Xunit ``` dotnet test -``` \ No newline at end of file +``` diff --git a/src/IBI.WZDx/IBI.WZDx.csproj b/src/IBI.WZDx/IBI.WZDx.csproj index b216920..d9cca1e 100644 --- a/src/IBI.WZDx/IBI.WZDx.csproj +++ b/src/IBI.WZDx/IBI.WZDx.csproj @@ -7,7 +7,7 @@ Models and utitlies for producing and consuming Work Zone Data Exchange (WZDx) data feeds. WZDx;Work Zone Data Exchange;Work Zone Feed;Road Event;Device Feed;Field Device;GeoJSON IBI Group - 4.1.1 + 4.2.0 true README.md git diff --git a/src/IBI.WZDx/Models/FieldDevices/FieldDeviceCoreDetails.cs b/src/IBI.WZDx/Models/FieldDevices/FieldDeviceCoreDetails.cs index 5655d45..6c7080e 100644 --- a/src/IBI.WZDx/Models/FieldDevices/FieldDeviceCoreDetails.cs +++ b/src/IBI.WZDx/Models/FieldDevices/FieldDeviceCoreDetails.cs @@ -72,6 +72,9 @@ namespace IBI.WZDx.Models.FieldDevices; /// /// The version of firmware the device is using to operate. /// +/// +/// The velocity of the device in kilometers per hour. +/// public record FieldDeviceCoreDetails( FieldDeviceType DeviceType, string DataSourceId, @@ -89,7 +92,8 @@ public record FieldDeviceCoreDetails( string? Make = null, string? Model = null, string? SerialNumber = null, - string? FirmwareVersion = null + string? FirmwareVersion = null, + double? VelocityKph = null ) { /// @@ -112,7 +116,8 @@ public virtual bool Equals(FieldDeviceCoreDetails? other) && Make == other.Make && Model == other.Model && SerialNumber == other.SerialNumber - && FirmwareVersion == other.FirmwareVersion; + && FirmwareVersion == other.FirmwareVersion + && VelocityKph == other.VelocityKph; } /// @@ -186,6 +191,11 @@ public override int GetHashCode() } } + if (VelocityKph != null) + { + hash.Add(VelocityKph); + } + return hash.ToHashCode(); } } \ No newline at end of file diff --git a/src/IBI.WZDx/Models/FieldDevices/FlashingBeacon.cs b/src/IBI.WZDx/Models/FieldDevices/FlashingBeacon.cs index 825c2d5..40b6e55 100644 --- a/src/IBI.WZDx/Models/FieldDevices/FlashingBeacon.cs +++ b/src/IBI.WZDx/Models/FieldDevices/FlashingBeacon.cs @@ -1,8 +1,9 @@ namespace IBI.WZDx.Models.FieldDevices; /// -/// Describes a flashing beacon light of any form (e.g. trailer-mounted, vehicle), used to indicate -/// something and capture driver attention. +/// Describes a flashing warning beacon used to supplement a temporary +/// traffic control device. A flashing warning beacon is mounted on a sign or channelizing device +/// and used to indicate a warning condition and capture driver attention. /// /// /// The core details of the flashing beacon device. diff --git a/src/IBI.WZDx/Models/FieldDevices/MarkedLocationType.cs b/src/IBI.WZDx/Models/FieldDevices/MarkedLocationType.cs index e4587d1..27e38fb 100644 --- a/src/IBI.WZDx/Models/FieldDevices/MarkedLocationType.cs +++ b/src/IBI.WZDx/Models/FieldDevices/MarkedLocationType.cs @@ -68,6 +68,11 @@ public enum MarkedLocationType /// RoadClosure, + /// + /// A work truck with lights flashing, actively engaged in construction or maintenance activity on the roadway. + /// + WorkTruckWithLightsFlashing, + /// /// A temporary traffic signal. /// diff --git a/src/IBI.WZDx/Models/RoadDirection.cs b/src/IBI.WZDx/Models/RoadDirection.cs index 087e81f..02dad12 100644 --- a/src/IBI.WZDx/Models/RoadDirection.cs +++ b/src/IBI.WZDx/Models/RoadDirection.cs @@ -32,6 +32,16 @@ public enum RoadDirection /// Westbound, + /// + /// The road direction is on the inner loop of a ring road or beltway. + /// + InnerLoop, + + /// + /// The road direction is on the outer loop of a ring road or beltway. + /// + OuterLoop, + /// /// The road does not have a signed direction. /// diff --git a/src/IBI.WZDx/Models/RoadEvents/CdsCurbZonesReference.cs b/src/IBI.WZDx/Models/RoadEvents/CdsCurbZonesReference.cs new file mode 100644 index 0000000..1d57092 --- /dev/null +++ b/src/IBI.WZDx/Models/RoadEvents/CdsCurbZonesReference.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using IBI.WZDx.Equality; + +namespace IBI.WZDx.Models.RoadEvents; + +/// +/// Describes specific curb zones that are impacted by a work zone via an external reference to the +/// curb data specification's +/// +/// Curb API +/// . +/// +/// A list of +/// +/// CDS Curb Zone +/// +/// ids. +/// An identifier for the source of the requested CDS Curbs API. +public record CdsCurbZonesReference( + IEnumerable CdsCurbZoneIds, + string CdsCurbsApiUrl + ) +{ + /// + /// Determine if another is equal to this . + /// + public virtual bool Equals(CdsCurbZonesReference? other) + { + return other != null + && CdsCurbZoneIds.NullHandlingSequenceEqual(other.CdsCurbZoneIds) + && CdsCurbsApiUrl == other.CdsCurbsApiUrl; + } + + /// + public override int GetHashCode() + { + var hash = new HashCode(); + + foreach (string id in CdsCurbZoneIds) + { + hash.Add(id); + } + + hash.Add(CdsCurbsApiUrl); + + return hash.ToHashCode(); + } +} diff --git a/src/IBI.WZDx/Models/RoadEvents/LaneStatus.cs b/src/IBI.WZDx/Models/RoadEvents/LaneStatus.cs index 6c474f7..d0f0938 100644 --- a/src/IBI.WZDx/Models/RoadEvents/LaneStatus.cs +++ b/src/IBI.WZDx/Models/RoadEvents/LaneStatus.cs @@ -6,12 +6,12 @@ namespace IBI.WZDx.Models.RoadEvents; public enum LaneStatus { /// - /// The lane is open for travel. + /// The lane is open for normal usage. /// Open, - + /// - /// The lane is closed to travel. + /// The lane is closed to normal usage. /// Closed, diff --git a/src/IBI.WZDx/Models/RoadEvents/WorkZoneType.cs b/src/IBI.WZDx/Models/RoadEvents/WorkZoneType.cs new file mode 100644 index 0000000..f063fe7 --- /dev/null +++ b/src/IBI.WZDx/Models/RoadEvents/WorkZoneType.cs @@ -0,0 +1,31 @@ +using IBI.WZDx.Models.RoadEvents.WorkZones; + +namespace IBI.WZDx.Models.RoadEvents; + +/// +/// The type of . +/// +public enum WorkZoneType +{ + /// + /// The road event is statically placed and is not moving. + /// + Static, + + /// + /// The road event is actively moving on the roadway. + /// + /// + /// As opposed to , the road event geometry changes at the operation moves. + /// + Moving, + + /// + /// The road event is the planned extent of a moving operation. The active work area will be + /// somewhere within this road event. + /// + /// + /// As opposed to , the road event geometry typically does not actively change. + /// + PlannedMovingArea +} diff --git a/src/IBI.WZDx/Models/RoadEvents/WorkZones/WorkZoneRoadEvent.cs b/src/IBI.WZDx/Models/RoadEvents/WorkZones/WorkZoneRoadEvent.cs index 715901f..c6fe593 100644 --- a/src/IBI.WZDx/Models/RoadEvents/WorkZones/WorkZoneRoadEvent.cs +++ b/src/IBI.WZDx/Models/RoadEvents/WorkZones/WorkZoneRoadEvent.cs @@ -89,6 +89,17 @@ namespace IBI.WZDx.Models.RoadEvents.WorkZones; /// A list of zero or more road restrictions that apply to the roadway segment described by this /// road event. /// +/// +/// A list of references to external +/// +/// CDS Curb Zones +/// +/// impacted by the work zone. +/// +/// +/// The type of work zone road event, such as if the road event is static or actively moving as part +/// of a moving operation. +/// public record WorkZoneRoadEvent( RoadEventCoreDetails CoreDetails, DateTimeOffset StartDate, @@ -113,7 +124,9 @@ public record WorkZoneRoadEvent( IEnumerable? TypesOfWork = null, WorkerPresence? WorkerPresence = null, double? ReducedSpeedLimitKph = null, - IEnumerable? Restrictions = null + IEnumerable? Restrictions = null, + IEnumerable? ImpactedCdsCurbZones = null, + WorkZoneType? WorkZoneType = null ) : IRoadEvent { /// @@ -144,7 +157,9 @@ public virtual bool Equals(WorkZoneRoadEvent? other) && TypesOfWork.NullHandlingSequenceEqual(other.TypesOfWork) && WorkerPresence == other.WorkerPresence && ReducedSpeedLimitKph == other.ReducedSpeedLimitKph - && Restrictions.NullHandlingSequenceEqual(other.Restrictions); + && Restrictions.NullHandlingSequenceEqual(other.Restrictions) + && ImpactedCdsCurbZones.NullHandlingSequenceEqual(other.ImpactedCdsCurbZones) + && WorkZoneType == other.WorkZoneType; } /// @@ -199,6 +214,16 @@ public override int GetHashCode() } } + if (ImpactedCdsCurbZones != null) + { + foreach (CdsCurbZonesReference cdsCurbZonesReference in ImpactedCdsCurbZones) + { + hash.Add(cdsCurbZonesReference); + } + } + + hash.Add(WorkZoneType); + return hash.ToHashCode(); } } \ No newline at end of file diff --git a/tests/IBI.WZDx.UnitTests/WzdxSerializerTests.cs b/tests/IBI.WZDx.UnitTests/WzdxSerializerTests.cs index 8d5ba04..709aac6 100644 --- a/tests/IBI.WZDx.UnitTests/WzdxSerializerTests.cs +++ b/tests/IBI.WZDx.UnitTests/WzdxSerializerTests.cs @@ -122,7 +122,8 @@ string expectedFeedJson Make: "Ver-Mac", Model: "AB-1", SerialNumber: "1234567890", - FirmwareVersion: "1.0.0" + FirmwareVersion: "1.0.0", + VelocityKph: 10.1 ), Pattern: ArrowBoardPattern.RightArrowFlashing, IsMoving: false, @@ -366,7 +367,8 @@ string expectedFeedJson ""make"": ""Ver-Mac"", ""model"": ""AB-1"", ""serial_number"": ""1234567890"", - ""firmware_version"": ""1.0.0"" + ""firmware_version"": ""1.0.0"", + ""velocity_kph"": 10.1 }, ""pattern"": ""right-arrow-flashing"", ""is_moving"": false, @@ -804,11 +806,20 @@ string expectedFeedJson Restrictions: new Restriction[] { new Restriction(RestrictionType.NoTrucks) - } + }, + ImpactedCdsCurbZones: new CdsCurbZonesReference[] + { + new CdsCurbZonesReference( + CdsCurbZoneIds: new string[] { "Zone Id 1", "Zone Id 2" }, + CdsCurbsApiUrl: "API Url" + ) + }, + WorkZoneType: WorkZoneType.Static ), Geometry: new RoadEventFeatureGeometry( Type: RoadEventFeatureGeometryType.LineString, - Coordinates: new double[][] { + Coordinates: new double[][] + { new double[] { -93.77668405099996, @@ -962,7 +973,14 @@ string expectedFeedJson { ""type"": ""no-trucks"" } - ] + ], + ""impacted_cds_curb_zones"": [ + { + ""cds_curb_zone_ids"": [ ""Zone Id 1"", ""Zone Id 2"" ], + ""cds_curbs_api_url"": ""API Url"" + } + ], + ""work_zone_type"": ""static"" }, ""geometry"": { ""type"": ""LineString"", @@ -1891,4 +1909,4 @@ private static void DeserializeFeed_JsonNotValid_ThrowsJsonException( Assert.Throws(action); } -} \ No newline at end of file +}