Exemplo n.º 1
0
        public void Should_route_score_difference()
        {
            var model = new GeocodeAddressApiResponse {
                ScoreDifference = 1.1234
            };

            model.ScoreDifference.ShouldBe(1.12);

            model.ScoreDifference = 1.7;

            model.ScoreDifference.ShouldBe(1.7);
        }
        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
            }));
        }