-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
EMBCESSMOD-5034: self-serve eligibility POC (#1963)
- Loading branch information
Showing
14 changed files
with
371 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,23 @@ | ||
{ | ||
"Serilog": { | ||
"MinimumLevel": { | ||
"Default": "Information", | ||
"Override": { | ||
"Microsoft ": "Information", | ||
"Microsoft.AspNetCore": "Warning", | ||
"Microsoft.Hosting.Lifetime": "Information", | ||
"System.Net.Http.HttpClient": "Warning", | ||
"Microsoft.OData.Extensions.Client": "Warning", | ||
"Grpc.Net.Client": "Warning" | ||
} | ||
"AllowedHosts": "*", | ||
"Serilog": { | ||
"MinimumLevel": { | ||
"Default": "Information", | ||
"Override": { | ||
"Microsoft ": "Information", | ||
"Microsoft.AspNetCore": "Warning", | ||
"Microsoft.Hosting.Lifetime": "Information", | ||
"System.Net.Http.HttpClient": "Warning", | ||
"Microsoft.OData.Extensions.Client": "Warning", | ||
"Grpc.Net.Client": "Warning" | ||
} | ||
} | ||
}, | ||
"messaging": { | ||
"mode": "both" | ||
}, | ||
"Spatial": { | ||
"ArcGISUrl": "https://services1.arcgis.com/xeMpV7tU1t4KD3Ei/ArcGIS", | ||
"GeocoderUrl": "https://geocoder.api.gov.bc.ca/" | ||
} | ||
}, | ||
"messaging": { | ||
"mode": "both" | ||
}, | ||
"AllowedHosts": "*" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
using System; | ||
using System.Linq; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using EMBC.ESS.Utilities.Spatial.ArcGISApi; | ||
using EMBC.ESS.Utilities.Spatial.GeocoderApi; | ||
|
||
namespace EMBC.ESS.Utilities.Spatial | ||
{ | ||
internal class AddressLocator : IAddressLocator | ||
{ | ||
private readonly IGeocoderAdapter geocoder; | ||
private readonly IArcGISAdapter arcGisAdapter; | ||
|
||
public AddressLocator(IGeocoderAdapter geocoder, IArcGISAdapter arcGisAdapter) | ||
{ | ||
this.geocoder = geocoder; | ||
this.arcGisAdapter = arcGisAdapter; | ||
} | ||
|
||
public async Task<AddressInformation> LocateAsync(Location location, CancellationToken ct) | ||
{ | ||
if (location is null) | ||
{ | ||
throw new ArgumentNullException(nameof(location)); | ||
} | ||
|
||
var geocode = await geocoder.Resolve(location.FullAddress, ct); | ||
if (geocode == null) return new AddressInformation(location, null, null); | ||
var features = await arcGisAdapter.QueryService(new PointIntersectionQuery("TASK_OA_24/FeatureServer/0", geocode)); | ||
|
||
return new AddressInformation(location, geocode, features.FirstOrDefault()?.Attributes.Select(a => new LocationAttribute(a.Key, a.Value?.ToString()))); | ||
} | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
ess/src/API/EMBC.ESS.Utilities.Spatial/ArcGISApi/ArcGISAdapter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Anywhere.ArcGIS; | ||
using Anywhere.ArcGIS.Common; | ||
using Anywhere.ArcGIS.Operation; | ||
|
||
namespace EMBC.ESS.Utilities.Spatial.ArcGISApi | ||
{ | ||
internal class ArcGISAdapter : IArcGISAdapter | ||
{ | ||
private readonly PortalGateway portalGateway; | ||
|
||
public ArcGISAdapter(PortalGateway portalGateway) | ||
{ | ||
this.portalGateway = portalGateway; | ||
} | ||
|
||
public async Task<IEnumerable<GISFeature>> QueryService(PointIntersectionQuery query) | ||
{ | ||
var arcGisQuery = new Query(query.ServiceName.AsEndpoint()) | ||
{ | ||
Geometry = new Point | ||
{ | ||
X = query.Point.Longitude, | ||
Y = query.Point.Latitude, | ||
SpatialReference = SpatialReference.WGS84 | ||
}, | ||
SpatialRelationship = SpatialRelationshipTypes.Intersects, | ||
}; | ||
|
||
var result = await portalGateway.Query(arcGisQuery); | ||
|
||
return result.Features.Select(f => new GISFeature(f.Attributes.ToDictionary(a => a.Key, a => a.Value))).ToList(); | ||
} | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
ess/src/API/EMBC.ESS.Utilities.Spatial/ArcGISApi/IArcGISAdapter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
using System.Collections.Generic; | ||
using System.Threading.Tasks; | ||
|
||
namespace EMBC.ESS.Utilities.Spatial.ArcGISApi | ||
{ | ||
internal interface IArcGISAdapter | ||
{ | ||
Task<IEnumerable<GISFeature>> QueryService(PointIntersectionQuery query); | ||
} | ||
|
||
internal record PointIntersectionQuery(string ServiceName, Geocode Point); | ||
|
||
internal record GISFeature(IEnumerable<KeyValuePair<string, object>> Attributes); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
using System; | ||
using EMBC.ESS.Utilities.Spatial.ArcGISApi; | ||
using EMBC.ESS.Utilities.Spatial.GeocoderApi; | ||
using EMBC.Utilities.Configuration; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Refit; | ||
|
||
namespace EMBC.ESS.Utilities.Spatial | ||
{ | ||
public class Configuration : IConfigureComponentServices | ||
{ | ||
public void ConfigureServices(ConfigurationServices configurationServices) | ||
{ | ||
var settings = configurationServices.Configuration.GetSection("Spatial").Get<SpatialSettings>(); | ||
if (settings == null || !settings.IsValid()) | ||
{ | ||
configurationServices.Logger.Report(EMBC.Utilities.Telemetry.ReportType.Warning, "Spatial settings are incomplete, skipping configuration"); | ||
return; | ||
} | ||
configurationServices.Services.AddRefitClient<IGeocoderApi>().ConfigureHttpClient(c => c.BaseAddress = settings.GeocoderUrl!); | ||
configurationServices.Services.AddSingleton(new Anywhere.ArcGIS.PortalGateway(settings.ArcGISUrl!.ToString())); | ||
configurationServices.Services.AddTransient<IGeocoderAdapter, GeocoderAdapter>(); | ||
configurationServices.Services.AddTransient<IArcGISAdapter, ArcGISAdapter>(); | ||
configurationServices.Services.AddTransient<IAddressLocator, AddressLocator>(); | ||
} | ||
} | ||
|
||
public record SpatialSettings | ||
{ | ||
public Uri? ArcGISUrl { get; set; } | ||
public Uri? GeocoderUrl { get; set; } | ||
|
||
public bool IsValid() => ArcGISUrl != null && GeocoderUrl != null; | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
ess/src/API/EMBC.ESS.Utilities.Spatial/EMBC.ESS.Utilities.Spatial.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net6</TargetFramework> | ||
<Nullable>enable</Nullable> | ||
<GenerateDocumentationFile>true</GenerateDocumentationFile> | ||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> | ||
<Company>Province of British Columbia</Company> | ||
<Authors>Quartech Systems Limited</Authors> | ||
<Copyright>Copyright 2022 Province of British Columbia</Copyright> | ||
<PackageLicenseExpression></PackageLicenseExpression> | ||
<RepositoryUrl>https://github.com/bcgov/embc-ess-mod</RepositoryUrl> | ||
<RepositoryType>GIT</RepositoryType> | ||
<AnalysisMode>Default</AnalysisMode> | ||
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild> | ||
<DebugType>full</DebugType> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Anywhere.ArcGIS" Version="2.0.1" /> | ||
<PackageReference Include="Refit.HttpClientFactory" Version="7.0.0" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\EMBC.Utilities\EMBC.Utilities.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
24 changes: 24 additions & 0 deletions
24
ess/src/API/EMBC.ESS.Utilities.Spatial/GeocoderApi/GeocoderAdapter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace EMBC.ESS.Utilities.Spatial.GeocoderApi | ||
{ | ||
internal class GeocoderAdapter : IGeocoderAdapter | ||
{ | ||
private readonly IGeocoderApi geocoderApi; | ||
|
||
public GeocoderAdapter(IGeocoderApi geocoderApi) | ||
{ | ||
this.geocoderApi = geocoderApi; | ||
} | ||
|
||
public async Task<Geocode?> Resolve(string address, CancellationToken ct) | ||
{ | ||
var response = await geocoderApi.GetAddress(new GetAddressRequest { addressString = address }); | ||
var coordinates = response?.features?[0].geometry?.coordinates; | ||
var score = response?.features?[0].properties?.score ?? 0; | ||
if (coordinates == null || coordinates.Length != 2) return null; | ||
return new Geocode(coordinates[1], coordinates[0], score); | ||
} | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
ess/src/API/EMBC.ESS.Utilities.Spatial/GeocoderApi/IGeocoderAdapter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace EMBC.ESS.Utilities.Spatial.GeocoderApi | ||
{ | ||
internal interface IGeocoderAdapter | ||
{ | ||
Task<Geocode?> Resolve(string address, CancellationToken ct); | ||
} | ||
} |
98 changes: 98 additions & 0 deletions
98
ess/src/API/EMBC.ESS.Utilities.Spatial/GeocoderApi/IGeocoderApi.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
using System.Threading.Tasks; | ||
using Refit; | ||
|
||
namespace EMBC.ESS.Utilities.Spatial.GeocoderApi | ||
{ | ||
internal interface IGeocoderApi | ||
{ | ||
[Get("/addresses.json?")] | ||
Task<GetAddressResponse> GetAddress([Query] GetAddressRequest request); | ||
} | ||
|
||
internal record GetAddressRequest | ||
{ | ||
public string? addressString { get; set; } | ||
} | ||
|
||
internal class GetAddressResponse | ||
{ | ||
public string? baseDataDate { get; set; } | ||
public string? copyrightLicense { get; set; } | ||
public string? copyrightNotice { get; set; } | ||
public Crs? crs { get; set; } | ||
public string? disclaimer { get; set; } | ||
public string? echo { get; set; } | ||
public float? executionTime { get; set; } | ||
public Feature[]? features { get; set; } | ||
public string? interpolation { get; set; } | ||
public string? locationDescriptor { get; set; } | ||
public int? maxResults { get; set; } | ||
public int? minScore { get; set; } | ||
public string? privacyStatement { get; set; } | ||
public string? queryAddress { get; set; } | ||
public string? searchTimestamp { get; set; } | ||
public int? setBack { get; set; } | ||
public string? type { get; set; } | ||
public string? version { get; set; } | ||
} | ||
|
||
internal record Crs | ||
{ | ||
public Properties? properties { get; set; } | ||
public string? type { get; set; } | ||
} | ||
|
||
internal record Properties | ||
{ | ||
public int code { get; set; } | ||
} | ||
|
||
internal record Feature | ||
{ | ||
public Geometry? geometry { get; set; } | ||
public Properties2? properties { get; set; } | ||
public string? type { get; set; } | ||
} | ||
|
||
internal record Geometry | ||
{ | ||
public double[]? coordinates { get; set; } | ||
public Crs? crs { get; set; } | ||
public string? type { get; set; } | ||
} | ||
|
||
internal record Properties2 | ||
{ | ||
public string? accessNotes { get; set; } | ||
public double? blockID { get; set; } | ||
public string? changeDate { get; set; } | ||
public double? civicNumber { get; set; } | ||
public string? civicNumberSuffix { get; set; } | ||
public string? electoralArea { get; set; } | ||
public object[]? faults { get; set; } | ||
public string? fullAddress { get; set; } | ||
public string? fullSiteDescriptor { get; set; } | ||
public string? isOfficial { get; set; } | ||
public string? isStreetDirectionPrefix { get; set; } | ||
public string? isStreetTypePrefix { get; set; } | ||
public string? localityName { get; set; } | ||
public string? localityType { get; set; } | ||
public string? locationDescriptor { get; set; } | ||
public string? locationPositionalAccuracy { get; set; } | ||
public string? matchPrecision { get; set; } | ||
public int? precisionPoints { get; set; } | ||
public string? provinceCode { get; set; } | ||
public double? score { get; set; } | ||
public string? siteID { get; set; } | ||
public string? siteName { get; set; } | ||
public string? siteRetireDate { get; set; } | ||
public string? siteStatus { get; set; } | ||
public string? streetDirection { get; set; } | ||
public string? streetName { get; set; } | ||
public string? streetQualifier { get; set; } | ||
public string? streetType { get; set; } | ||
public string? unitDesignator { get; set; } | ||
public string? unitNumber { get; set; } | ||
public string? unitNumberSuffix { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
using System.Collections.Generic; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace EMBC.ESS.Utilities.Spatial | ||
{ | ||
public interface IAddressLocator | ||
{ | ||
Task<AddressInformation> LocateAsync(Location location, CancellationToken ct); | ||
} | ||
|
||
public record Location(string FullAddress) | ||
{ | ||
} | ||
|
||
public record AddressInformation(Location Location, Geocode? geocode, IEnumerable<LocationAttribute>? Attributes); | ||
public record Geocode(double Latitude, double Longitude, double score); | ||
|
||
public record LocationAttribute(string Name, string? Value); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.