using Microsoft.Extensions.Options; using NetTopologySuite.Features; using NetTopologySuite.Geometries; using NetTopologySuite.IO; using SzakatsA.Result; namespace ProofOfConcept.Services; public class ZoneDeterminatorService { private readonly ILogger logger; private ZoneDeterminatorServiceConfiguration configuration; private FeatureCollection parkingZones; private bool initialized; public ZoneDeterminatorService(ILogger logger, IOptions options) { this.logger = logger; this.configuration = options.Value; this.parkingZones = new FeatureCollection(); this.initialized = false; } public async Task> DetermineZoneCodeAsync(double latitude, double longitude, CancellationToken cancellationToken = default(CancellationToken)) { this.logger.LogTrace("Determinating parking zone code for coordinates: {Latitude}, {Longitude}...", latitude, longitude); if (!this.initialized) await InitializeAsync(cancellationToken); Point point = new Point(longitude, latitude); IFeature? zone = this.parkingZones.FirstOrDefault(f => f.Geometry.Contains(point)); if (zone is null) return Result.Success(String.Empty); else if (!zone.Attributes.Exists("zoneid")) return Result.Fail(new MissingFieldException("Zone ID not found for parking zone")); else if (zone.Attributes["zoneid"] is null) return Result.Fail(new NullReferenceException("Zone ID null for parking zone")); else if (zone.Attributes["zoneid"].ToString() is null) return Result.Fail(new InvalidCastException($"Zone ID is of type {zone.Attributes["zoneID"].GetType().FullName}")); else return Result.Success(zone.Attributes["zoneid"].ToString()!); } private async Task InitializeAsync(CancellationToken cancellationToken = default(CancellationToken)) { this.logger.LogTrace("Initializing..."); string geojson = await File.ReadAllTextAsync(this.configuration.ZoneFilePath, cancellationToken); GeoJsonReader reader = new GeoJsonReader(); this.parkingZones = reader.Read(geojson); this.logger.LogInformation("Initialized"); } } public class ZoneDeterminatorServiceConfiguration { public string ZoneFilePath { get; set; } = "Resources/zones.geojson"; }