public async Task Should_remove_candidates_below_accept_score()
            {
                var candidates = new[] {
                    new Candidate {
                        Address     = "winner",
                        Score       = 1,
                        AddressGrid = "grid",
                        Location    = new Point(0, 0)
                    },
                    new Candidate {
                        Address     = "remove",
                        Score       = 0,
                        AddressGrid = "grid",
                        Location    = new Point(1, 1)
                    }
                };

                var options = new GeocodingOptions {
                    AcceptScore = 1,
                    Suggest     = 1
                };

                var address = new GeocodeAddress(new CleansedAddress())
                {
                    AddressGrids = new[] { new ZipGridLink(0, "grid", 0) }
                };

                var request = new FilterCandidates.Command(candidates, options, "street", "zone", address);
                var result  = await Handler.Handle(request, CancellationToken.None);

                result.Candidates.ShouldBeEmpty();
                result.MatchAddress.ShouldBe("winner");
            }
Esempio n. 2
0
        public async Task Should_return_candidate_from_poboxes()
        {
            const int pobox = -1;
            const int zip   = 84114;

            var parsedAddress = new CleansedAddress("inputAddress", 1, 0, pobox, Direction.North, "street",
                                                    StreetType.Alley, Direction.South, 0, zip, false, false);
            var address = new GeocodeAddress(parsedAddress)
            {
                AddressGrids = new[] { new ZipGridLink(84114, "grid", 0) }
            };

            var geocodeOptions = new GeocodingOptions {
                PoBox            = true,
                SpatialReference = 26912
            };

            var request = new PoBoxLocation.Command(address, geocodeOptions);
            var result  = await _handler.Handle(request, new CancellationToken());

            result.Score.ShouldBe(100);
            result.Locator.ShouldBe("Post Office Point");
            result.Location.X.ShouldBe(1);
            result.Location.Y.ShouldBe(1);
            result.AddressGrid.ShouldBe("grid");
        }
Esempio n. 3
0
            public async Task Should_create_extra_for_address_reversal()
            {
                var parsedAddress = new CleansedAddress("inputAddress", 1, 0, 0, Direction.North, "2", StreetType.Alley,
                                                        Direction.South, 0, 84114, false, false);
                var address = new GeocodeAddress(parsedAddress)
                {
                    AddressGrids = new[] { new PlaceGridLink("place", "grid", 0) }
                };

                var geocodeOptions = new GeocodingOptions {
                    Locators         = LocatorType.RoadCenterlines,
                    SpatialReference = 26912
                };

                var request = new LocatorsForGeocode.Command(address, geocodeOptions);
                var result  = await Handler.Handle(request, new CancellationToken());

                result.Count.ShouldBe(2);

                result.Count(x => x.Url ==
                             "proto://test:1/arcgis/rest/services/Geolocators/Roads_AddressSystem_STREET/GeocodeServer/findAddressCandidates?f=json&Street=1+North+2+Alley+South&City=grid&outSR=26912")
                .ShouldBe(1);
                result.Count(x => x.Url ==
                             "proto://test:1/arcgis/rest/services/Geolocators/Roads_AddressSystem_STREET/GeocodeServer/findAddressCandidates?f=json&Street=2+South+Alley+1+North&City=grid&outSR=26912")
                .ShouldBe(1);
            }
            public async Task Should_calculate_score_difference()
            {
                var candidates = new[] {
                    new Candidate {
                        Address     = "winner",
                        Score       = 10,
                        AddressGrid = "grid",
                        Location    = new Point(0, 0)
                    },
                    new Candidate {
                        Address     = "suggest",
                        Score       = 1,
                        AddressGrid = "grid",
                        Location    = new Point(1, 1)
                    }
                };

                var options = new GeocodingOptions {
                    AcceptScore     = 1,
                    ScoreDifference = true
                };

                var address = new GeocodeAddress(new CleansedAddress())
                {
                    AddressGrids = new[] { new ZipGridLink(0, "grid", 0) }
                };

                var request = new FilterCandidates.Command(candidates, options, "street", "zone", address);
                var result  = await Handler.Handle(request, CancellationToken.None);

                result.Candidates.ShouldBeEmpty();
                result.ScoreDifference.ShouldBe(9);
            }
Esempio n. 5
0
            public async Task Should_return_all_geocoders()
            {
                var parsedAddress = new CleansedAddress("inputAddress", 1, 0, 0, Direction.North, "street",
                                                        StreetType.Alley, Direction.South, 0, 84114, false, false);
                var address = new GeocodeAddress(parsedAddress)
                {
                    AddressGrids = new[] { new PlaceGridLink("place", "grid", 0) }
                };

                var geocodeOptions = new GeocodingOptions {
                    Locators         = LocatorType.All,
                    SpatialReference = 26912
                };

                var request = new LocatorsForGeocode.Command(address, geocodeOptions);
                var result  = await Handler.Handle(request, new CancellationToken());

                result.Count.ShouldBe(2);

                geocodeOptions = new GeocodingOptions {
                    Locators         = LocatorType.Default,
                    SpatialReference = 26912
                };

                request = new LocatorsForGeocode.Command(address, geocodeOptions);
                result  = await Handler.Handle(request, new CancellationToken());

                result.Count.ShouldBe(2);
            }
        public void Initialize(GeocodeAddress address, GeocodingOptions options)
        {
            Address = address;
            Options = options;

            BuildAddressPermutations();
            BuildLocatorLookup();
        }
Esempio n. 7
0
        public async Task Should_return_null_for_address_without_zip_code()
        {
            var parsedAddress = new CleansedAddress("inputAddress", 1, 0, 0, Direction.North, "street",
                                                    StreetType.Alley, Direction.South, 0, new int?(), false, false);
            var address = new GeocodeAddress(parsedAddress);

            var geocodeOptions = new GeocodingOptions {
                PoBox = true
            };

            var request = new PoBoxLocation.Command(address, geocodeOptions);
            var result  = await _handler.Handle(request, new CancellationToken());

            result.ShouldBeNull();
        }
Esempio n. 8
0
            public async Task Should_return_empty_when_no_grids()
            {
                var parsedAddress = new CleansedAddress("inputAddress", 1, 0, 0, Direction.North, "street",
                                                        StreetType.Alley, Direction.South, 0, 84114, false, false);
                var address = new GeocodeAddress(parsedAddress)
                {
                    AddressGrids = Array.Empty <GridLinkable>()
                };

                var geocodeOptions = new GeocodingOptions {
                    Locators         = LocatorType.RoadCenterlines,
                    SpatialReference = 26912
                };

                var request = new LocatorsForGeocode.Command(address, geocodeOptions);
                var result  = await Handler.Handle(request, new CancellationToken());

                result.ShouldBeEmpty();
            }
Esempio n. 9
0
            public Command(IList <Candidate> candidates, GeocodingOptions geocodeOptions,
                           string street, string zone, GeocodeAddress geocodedAddress)
            {
                GeocodeOptions  = geocodeOptions;
                Street          = street;
                Zone            = zone;
                GeocodedAddress = geocodedAddress;

                if (candidates == null)
                {
                    candidates = Array.Empty <Candidate>();
                }

                foreach (var candidate in candidates)
                {
                    candidate.ScoreDifference = -1;
                }

                Candidates = candidates;
            }
        public ChooseBestAddressCandidateCommand(IEnumerable <Candidate> candidates, GeocodingOptions geocodeOptions,
                                                 string street, string zone, GeocodeAddress geocodedAddress)
        {
            GeocodeOptions  = geocodeOptions;
            Street          = street;
            Zone            = zone;
            GeocodedAddress = geocodedAddress;

            if (candidates == null)
            {
                candidates = new List <Candidate>();
            }

            var enumerable = candidates as IList <Candidate> ?? candidates.ToList();

            foreach (var candidate in enumerable)
            {
                candidate.ScoreDifference = -1;
            }

            Candidates = enumerable.ToList();
        }
Esempio n. 11
0
            public async Task Should_return_centerline_geocoder_only()
            {
                var parsedAddress = new CleansedAddress("inputAddress", 1, 0, 0, Direction.North, "street",
                                                        StreetType.Alley, Direction.South, 0, 84114, false, false);
                var address = new GeocodeAddress(parsedAddress)
                {
                    AddressGrids = new[] { new PlaceGridLink("place", "grid", 0) }
                };

                var geocodeOptions = new GeocodingOptions {
                    Locators         = LocatorType.RoadCenterlines,
                    SpatialReference = 26912
                };

                var request = new LocatorsForGeocode.Command(address, geocodeOptions);
                var result  = await Handler.Handle(request, new CancellationToken());

                result.ShouldHaveSingleItem();

                var locator = result.First();

                locator.Url.ShouldBe("proto://test:1/arcgis/rest/services/Geolocators/Roads_AddressSystem_STREET/GeocodeServer/findAddressCandidates?f=json&Street=1+North+street+Alley+South&City=grid&outSR=26912");
                locator.Name.ShouldBe("Centerlines.StatewideRoads");
            }
 public void Initialize(GeocodeAddress geocodeAddress, GeocodingOptions options)
 {
     _options         = options;
     _geocodedAddress = geocodeAddress;
 }
        public async Task <ObjectResult> Get(string street, string zone, [FromQuery] GeocodingOptions options)
        {
            _log.Debug("Geocoding {street}, {zone} with options: {options}", street, zone, options);

            #region validation

            var errors = "";
            if (string.IsNullOrEmpty(street))
            {
                errors = "Street is empty.";
            }

            if (string.IsNullOrEmpty(zone))
            {
                errors += "Zip code or city name is emtpy";
            }

            if (errors.Length > 0)
            {
                _log.Debug("Bad geocode request", errors);

                return(BadRequest(new ApiResponseContainer <GeocodeAddressApiResponse> {
                    Status = (int)HttpStatusCode.BadRequest,
                    Message = errors
                }));
            }

            street = street?.Trim();
            zone   = zone?.Trim();

            #endregion

            var parseAddressCommand = new AddressParsing.Command(street);
            var parsedStreet        = await _mediator.Send(parseAddressCommand);

            var parseZoneCommand = new ZoneParsing.Command(zone, new GeocodeAddress(parsedStreet));
            var parsedAddress    = await _mediator.Send(parseZoneCommand);

            if (options.PoBox && parsedAddress.IsPoBox && parsedAddress.Zip5.HasValue)
            {
                var poboxCommand = new PoBoxLocation.Command(parsedAddress, options);
                var result       = await _mediator.Send(poboxCommand);

                if (result != null)
                {
                    var model = result.ToResponseObject(street, zone);

                    var standard = parsedAddress.StandardizedAddress.ToLowerInvariant();
                    var input    = street?.ToLowerInvariant();

                    if (input != standard)
                    {
                        model.StandardizedAddress = standard;
                    }

                    _log.Debug("Result score: {score} from {locator}", model.Score, model.Locator);

                    return(Ok(new ApiResponseContainer <GeocodeAddressApiResponse> {
                        Result = model,
                        Status = (int)HttpStatusCode.OK
                    }));
                }
            }

            var deliveryPointCommand = new UspsDeliveryPointLocation.Command(parsedAddress, options);
            var uspsPoint            = await _mediator.Send(deliveryPointCommand);

            if (uspsPoint != null)
            {
                var model = uspsPoint.ToResponseObject(street, zone);

                var standard = parsedAddress.StandardizedAddress.ToLowerInvariant();
                var input    = street?.ToLowerInvariant();

                if (input != standard)
                {
                    model.StandardizedAddress = standard;
                }

                _log.Debug("Result score: {score} from {locator}", model.Score, model.Locator);

                return(Ok(new ApiResponseContainer <GeocodeAddressApiResponse> {
                    Result = model,
                    Status = (int)HttpStatusCode.OK
                }));
            }

            var topCandidates = new TopAddressCandidates(options.Suggest,
                                                         new CandidateComparer(parsedAddress.StandardizedAddress
                                                                               .ToUpperInvariant()));
            var getLocatorsForAddressCommand = new LocatorsForGeocode.Command(parsedAddress, options);
            var locators = await _mediator.Send(getLocatorsForAddressCommand);

            if (locators == null || !locators.Any())
            {
                _log.Debug("No locators found for address {parsedAddress}", parsedAddress);

                return(NotFound(new ApiResponseContainer {
                    Message = $"No address candidates found with a score of {options.AcceptScore} or better.",
                    Status = (int)HttpStatusCode.NotFound
                }));
            }

            var tasks = await Task.WhenAll(locators.Select(locator => _mediator.Send(new Geocode.Command(locator)))
                                           .ToArray());

            var candidates = tasks.SelectMany(x => x);

            foreach (var candidate in candidates)
            {
                topCandidates.Add(candidate);
            }

            var highestScores = topCandidates.Get();

            var chooseBestAddressCandidateCommand = new FilterCandidates.Command(highestScores, options, street,
                                                                                 zone, parsedAddress);
            var winner = await _mediator.Send(chooseBestAddressCandidateCommand);

            if (winner == null || winner.Score < 0)
            {
                _log.Warning("Could not find match for {Street}, {Zone} with a score of {Score} or better.", street,
                             zone,
                             options.AcceptScore);

                return(NotFound(new ApiResponseContainer {
                    Message = $"No address candidates found with a score of {options.AcceptScore} or better.",
                    Status = (int)HttpStatusCode.NotFound
                }));
            }

            if (winner.Location == null)
            {
                _log.Warning("Could not find match for {Street}, {Zone} with a score of {Score} or better.", street,
                             zone,
                             options.AcceptScore);
            }

            winner.Wkid = options.SpatialReference;

            _log.Debug("Result score: {score} from {locator}", winner.Score, winner.Locator);

            return(Ok(new ApiResponseContainer <GeocodeAddressApiResponse> {
                Result = winner,
                Status = (int)HttpStatusCode.OK
            }));
        }
        public async Task <ObjectResult> Get(string street, string zone, [FromQuery] GeocodingOptions options)
        {
            #region validation

            var errors = "";
            if (string.IsNullOrEmpty(street))
            {
                errors = "Street is empty.";
            }

            if (string.IsNullOrEmpty(zone))
            {
                errors += "Zip code or city name is emtpy";
            }

            if (errors.Length > 0)
            {
                return(BadRequest(new ApiResponseContainer <GeocodeAddressApiResponse>
                {
                    Status = (int)HttpStatusCode.BadRequest,
                    Message = errors
                }));
            }

            street = street?.Trim();
            zone   = zone?.Trim();

            #endregion

            _parseAddressCommand.Initialize(street);
            var parsedStreet = CommandExecutor.ExecuteCommand(_parseAddressCommand);

            _parseZoneCommand.Initialize(zone, new GeocodeAddress(parsedStreet));
            var parsedAddress = CommandExecutor.ExecuteCommand(_parseZoneCommand);

            if (options.PoBox && parsedAddress.IsPoBox && parsedAddress.Zip5.HasValue)
            {
                _poboxCommand.Initialize(parsedAddress, options);
                var result = await _poboxCommand.Execute();

                if (result != null)
                {
                    // TODO this is silly change it
                    var model = new GeocodeAddressApiResponse
                    {
                        MatchAddress    = result.Address,
                        Score           = result.Score,
                        Locator         = result.Locator,
                        Location        = result.Location,
                        AddressGrid     = result.AddressGrid,
                        InputAddress    = $"{street}, {zone}",
                        ScoreDifference = result.ScoreDifference
                    };

                    var standard = parsedAddress.StandardizedAddress.ToLowerInvariant();
                    var input    = street?.ToLowerInvariant();

                    if (input != standard)
                    {
                        model.StandardizedAddress = standard;
                    }

                    return(Ok(new ApiResponseContainer <GeocodeAddressApiResponse>
                    {
                        Result = model
                    }));
                }
            }

            _deliveryPointCommand.Initialize(parsedAddress, options);
            var uspsPoint = await _deliveryPointCommand.Execute();

            if (uspsPoint != null)
            {
                // TODO this is silly change it
                var model = new GeocodeAddressApiResponse
                {
                    MatchAddress    = uspsPoint.Address,
                    Score           = uspsPoint.Score,
                    Locator         = uspsPoint.Locator,
                    Location        = uspsPoint.Location,
                    AddressGrid     = uspsPoint.AddressGrid,
                    InputAddress    = $"{street}, {zone}",
                    ScoreDifference = uspsPoint.ScoreDifference
                };

                var standard = parsedAddress.StandardizedAddress.ToLowerInvariant();
                var input    = street?.ToLowerInvariant();

                if (input != standard)
                {
                    model.StandardizedAddress = standard;
                }

                return(Ok(new ApiResponseContainer <GeocodeAddressApiResponse>
                {
                    Result = model
                }));
            }

            var topCandidates = new TopAddressCandidates(options.Suggest,
                                                         new CandidateComparer(parsedAddress.StandardizedAddress
                                                                               .ToUpperInvariant()));
            _getLocatorsForAddressCommand.Initialize(parsedAddress, options);
            var locators = CommandExecutor.ExecuteCommand(_getLocatorsForAddressCommand);

            if (locators == null || !locators.Any())
            {
                return(NotFound(new ApiResponseContainer
                {
                    Message = $"No address candidates found with a score of {options.AcceptScore} or better.",
                    Status = (int)HttpStatusCode.NotFound
                }));
            }

            var commandsToExecute = new ConcurrentQueue <GetAddressCandidatesCommand>();
            foreach (var locator in locators)
            {
                var geocodeWithLocator = new GetAddressCandidatesCommand(_clientFactory);
                geocodeWithLocator.Initialize(locator);

                commandsToExecute.Enqueue(geocodeWithLocator);
            }

            var tasks = new Collection <Task <IEnumerable <Candidate> > >();

            while (commandsToExecute.TryDequeue(out GetAddressCandidatesCommand currentCommand))
            {
                tasks.Add(currentCommand.Execute());
            }

            await Task.WhenAll(tasks);

            var candidates = tasks.Where(x => x.Result != null).SelectMany(x => x.Result);

            foreach (var candidate in candidates)
            {
                topCandidates.Add(candidate);
            }

            var highestScores = topCandidates.Get();

            var chooseBestAddressCandidateCommand = new ChooseBestAddressCandidateCommand(highestScores, options, street,
                                                                                          zone, parsedAddress);
            var winner = CommandExecutor.ExecuteCommand(chooseBestAddressCandidateCommand);

            if (winner == null || winner.Score < 0)
            {
                //                Log.Warning("Could not find match for {Street}, {Zone} with a score of {Score} or better.", street, zone,
                //                            options.AcceptScore);

                return(NotFound(new ApiResponseContainer
                {
                    Message = $"No address candidates found with a score of {options.AcceptScore} or better.",
                    Status = (int)HttpStatusCode.NotFound
                }));
            }

            if (winner.Location == null)
            {
//                Log.Warning("Could not find match for {Street}, {Zone} with a score of {Score} or better.", street, zone,
//                            options.AcceptScore);
            }

            winner.Wkid = options.SpatialReference;

            return(Ok(new ApiResponseContainer <GeocodeAddressApiResponse>
            {
                Result = winner
            }));
        }
Esempio n. 15
0
 public Command(GeocodeAddress address, GeocodingOptions options)
 {
     Address = address;
     Options = options;
 }