From 3ece313bde3a7aba253735f49ff4fc61ee5c2e0a Mon Sep 17 00:00:00 2001 From: Stanislau Komar Date: Thu, 18 May 2017 17:46:05 +0300 Subject: [PATCH] Improved the logic of parsing from YandexMaps --- spec/Geocoded.spec.js | 13 ++- spec/providers/YandexProvider.spec.js | 13 +++ src/Geocoded.js | 13 +-- src/providers/YandexProvider.js | 117 ++++++++++++++++++++++---- 4 files changed, 132 insertions(+), 24 deletions(-) diff --git a/spec/Geocoded.spec.js b/spec/Geocoded.spec.js index 97542e3..e8fa677 100644 --- a/spec/Geocoded.spec.js +++ b/spec/Geocoded.spec.js @@ -48,6 +48,14 @@ describe("Geocoded returns data properly", function() { geocoded.city = "Washington"; geocoded.region = "DC"; geocoded.postal_code = "20050"; + geocoded.countryName = "France"; + geocoded.bounds = [[48.8718,2.301097], [48.874597,2.30523]]; + + + it ("Geocoded returns proper Bounds", function() { + var expectedBounds = [[48.8718,2.301097], [48.874597,2.30523]]; + expect(geocoded.getBounds()).toEqual(expectedBounds); + }); it ("Geocoded returns proper coordinates", function() { var expectedCoordinates = [38.8978378, -77.0365123]; @@ -71,6 +79,10 @@ describe("Geocoded returns data properly", function() { expect(geocoded.getCity()).toEqual("Washington"); }); + it ("Geocoded returns proper Country", function() { + expect(geocoded.getCounty()).toEqual("France"); + }); + it ("Geocoded returns proper Region", function() { expect(geocoded.getRegion()).toEqual("DC"); }); @@ -78,5 +90,4 @@ describe("Geocoded returns data properly", function() { it ("Geocoded returns proper Postal Code", function() { expect(geocoded.getZipcode()).toEqual("20050"); }); - }); diff --git a/spec/providers/YandexProvider.spec.js b/spec/providers/YandexProvider.spec.js index 0aa6c8e..86c6f36 100644 --- a/spec/providers/YandexProvider.spec.js +++ b/spec/providers/YandexProvider.spec.js @@ -8,6 +8,15 @@ describe("Yandex Geocoder Provider raw result to Geocoded mapping tests", functi "kind": "house", "text": "United States, District of Columbia, Washington, Pennsylvania Ave NW, 1600", "precision": "exact", + "Address": { + "Components": [ + {"kind": "country", "name": "United States"}, + {"kind": "province", "name": "District of Columbia"}, + {"kind": "locality", "name": "Washington"}, + {"kind": "district", "name": "Washington district"}, + {"kind": "street", "name": "Pennsylvania Ave NW"} + ] + }, "AddressDetails": { "Country": { "AddressLine": "District of Columbia, Washington, Pennsylvania Ave NW, 1600", @@ -68,4 +77,8 @@ describe("Yandex Geocoder Provider raw result to Geocoded mapping tests", functi it ("maps region correctly", function() { expect(geocoded.getRegion()).toEqual("District of Columbia"); }); + + it ("maps boundary correctly", function() { + expect(geocoded.getBounds()).toEqual([[38.891265, -77.046921], [38.904125, -77.030464]]); + }); }); diff --git a/src/Geocoded.js b/src/Geocoded.js index f7b8cc9..7fbbecf 100644 --- a/src/Geocoded.js +++ b/src/Geocoded.js @@ -5,21 +5,24 @@ if (typeof GeocoderJS === "undefined" && typeof require === "function") { ;(function (GeocoderJS) { "use strict"; - GeocoderJS.Geocoded = function() {}; + GeocoderJS.Geocoded = function() { + this.other = {}; + }; GeocoderJS.Geocoded.prototype = { getCoordinates: function() {return[this.latitude, this.longitude];}, getLatitude: function() {return this.latitude;}, getLongitude: function() {return this.longitude;}, - getBounds: function() {}, + getBounds: function() { return this.bounds;}, getStreetNumber: function() {return this.streetNumber;}, getStreetName: function() {return this.streetName;}, getCity: function() {return this.city;}, getZipcode: function() {return this.postal_code;}, getCityDistrict: function() {}, - getCounty: function() {}, - getCountyCode: function() {}, - getRegion: function() {return this.region;} + getCounty: function() { return this.countryName;}, + getCountyCode: function() { return this.country_code;}, + getRegion: function() {return this.region;}, + getOther: function () {return this.other;} }; })(GeocoderJS); diff --git a/src/providers/YandexProvider.js b/src/providers/YandexProvider.js index 6c68607..42bc8af 100644 --- a/src/providers/YandexProvider.js +++ b/src/providers/YandexProvider.js @@ -72,31 +72,112 @@ if (typeof GeocoderJS === "undefined" && typeof require === "function") { }; GeocoderJS.YandexProvider.prototype.mapToGeocoded = function(result) { - var geocoded = new GeocoderJS.Geocoded(); + var geocoded = new GeocoderJS.Geocoded(), + component, point, addressMetaData, + addressComponents, i, tmpKind, tmpName, bounds; - var point = result.Point.pos.split(' '); + point = result.Point.pos.split(' '); geocoded.latitude = point[1] * 1; geocoded.longitude = point[0] * 1; - if (result.metaDataProperty.GeocoderMetaData.AddressDetails.Country) { - var tmp = result.metaDataProperty.GeocoderMetaData.AddressDetails.Country; - if (tmp.AdministrativeArea) { - tmp = tmp.AdministrativeArea; - geocoded.region = tmp.AdministrativeAreaName; - if (tmp.SubAdministrativeArea) { - tmp = tmp.SubAdministrativeArea; - if (tmp.Locality) { - tmp = tmp.Locality; - geocoded.city = tmp.LocalityName; - if (tmp.Thoroughfare) { - tmp = tmp.Thoroughfare; - geocoded.streetName = tmp.ThoroughfareName; - } - } - } + bounds = parseBounds(result.boundedBy); + if(bounds) { + geocoded.bounds = bounds; + } + + if(!result.metaDataProperty.GeocoderMetaData) { + return geocoded; + } + + addressMetaData = result.metaDataProperty.GeocoderMetaData; + addressComponents = addressMetaData.Address.Components; + + if (addressMetaData.AddressDetails.Country) { + geocoded.country_code = addressMetaData.AddressDetails.Country.CountryNameCode; + } + + for (i in addressComponents) { + if(!addressComponents.hasOwnProperty(i)) { + continue; + } + + component = addressComponents[i]; + tmpKind = component.kind; + tmpName = component.name; + switch (tmpKind) { + case 'country': + geocoded.countryName = tmpName; + break; + case 'locality': + geocoded.city = tmpName; + break; + case 'province': + geocoded.region = tmpName; + break; + case 'area': + geocoded.region_area = tmpName; + break; + case 'street': + geocoded.streetName = tmpName; + break; + case 'house': + geocoded.streetNumber = tmpName; + break; + default: + geocoded.other[tmpKind] = tmpName; } } + console.log(geocoded); + return geocoded; }; + + function parseBounds(boundary) { + var boundedTypes = ['Envelope'], + boundType, boundData, i + ; + + for (i in boundedTypes) { + if(!boundedTypes.hasOwnProperty(i)) { + continue; + } + + boundType = boundedTypes[i]; + if(!boundary.hasOwnProperty(boundType)) { + continue; + } + + boundData = boundary[boundType]; + break; + } + + switch (boundType) { + case 'Envelope': + return parseEnvelopeBound(boundData); + } + } + + function parseEnvelopeBound(boundData) { + var lowerCorner, upperCorner, + x1, y1, x2, y2, tmp + ; + + upperCorner = boundData.upperCorner; + lowerCorner = boundData.lowerCorner; + + tmp = lowerCorner.split(" "); + y1 = tmp[0] * 1; + x1 = tmp[1] * 1; + + tmp = upperCorner.split(" "); + y2 = tmp[0] * 1; + x2 = tmp[1] * 1; + + return [ + [x1, y1], + [x2, y2] + ]; + } + })(GeocoderJS);