From 1199a356c4fe734b924efa06db9d14d1ad25d376 Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Fri, 26 Jun 2020 22:26:39 +0100 Subject: [PATCH] Extract out a JS service for calculating where to centre the map when given a set of coordinates. Also removing the hardcoded default latitude/longitude from open_street_map directive because it's probably not very likely that it will be needed. --- .../directives/open_street_map.js.coffee | 38 ++-------- .../services/map_centre_calculator.js.coffee | 29 ++++++++ .../map_centre_calculator_spec.js.coffee | 70 +++++++++++++++++++ 3 files changed, 104 insertions(+), 33 deletions(-) create mode 100644 app/assets/javascripts/darkswarm/services/map_centre_calculator.js.coffee create mode 100644 spec/javascripts/unit/darkswarm/services/map_centre_calculator_spec.js.coffee diff --git a/app/assets/javascripts/darkswarm/directives/open_street_map.js.coffee b/app/assets/javascripts/darkswarm/directives/open_street_map.js.coffee index e9be4acb88..832878cd50 100644 --- a/app/assets/javascripts/darkswarm/directives/open_street_map.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/open_street_map.js.coffee @@ -1,4 +1,4 @@ -Darkswarm.directive 'ofnOpenStreetMap', ($window, Enterprises, EnterpriseModal, availableCountries, openStreetMapConfig) -> +Darkswarm.directive 'ofnOpenStreetMap', ($window, MapCentreCalculator, Enterprises, EnterpriseModal, availableCountries, openStreetMapConfig) -> restrict: 'E' replace: true scope: true @@ -11,34 +11,6 @@ Darkswarm.directive 'ofnOpenStreetMap', ($window, Enterprises, EnterpriseModal, openStreetMapProviderName = openStreetMapConfig.open_street_map_provider_name openStreetMapProviderOptions = JSON.parse(openStreetMapConfig.open_street_map_provider_options) - average = (values) -> - total = values.reduce (sum, value) -> - sum = sum + value - , 0 - total / values.length - - averageAngle = (angleName) -> - positiveAngles = [] - negativeAngles = [] - for enterprise in Enterprises.enterprises - if enterprise.latitude? && enterprise.longitude? - if enterprise[angleName] > 0 - positiveAngles.push(enterprise[angleName]) - else - negativeAngles.push(enterprise[angleName]) - - averageNegativeAngle = average(negativeAngles) - averagePositiveAngle = average(positiveAngles) - - if negativeAngles.length == 0 - averagePositiveAngle - else if positiveAngles.length == 0 - averageNegativeAngle - else if averagePositiveAngle > averageNegativeAngle - averagePositiveAngle - averageNegativeAngle - else - averageNegativeAngle - averagePositiveAngle - buildMarker = (enterprise, latlng, title) -> icon = L.icon iconUrl: enterprise.icon @@ -90,15 +62,15 @@ Darkswarm.directive 'ofnOpenStreetMap', ($window, Enterprises, EnterpriseModal, initialLatitude = () -> if geocodedEnterprises().length > 0 - averageAngle("latitude") + MapCentreCalculator.calculate_latitude(geocodedEnterprises()) else - openStreetMapConfig.open_street_map_default_latitude || -37.4713077 + openStreetMapConfig.open_street_map_default_latitude initialLongitude = () -> if geocodedEnterprises().length > 0 - averageAngle("longitude") + MapCentreCalculator.calculate_longitude(geocodedEnterprises()) else - openStreetMapConfig.open_street_map_default_longitude || 144.7851531 + openStreetMapConfig.open_street_map_default_longitude overwriteInlinePositionRelativeToAbsoluteOnSearchField = -> $('#open-street-map--search').css("position", "absolute") diff --git a/app/assets/javascripts/darkswarm/services/map_centre_calculator.js.coffee b/app/assets/javascripts/darkswarm/services/map_centre_calculator.js.coffee new file mode 100644 index 0000000000..f1023ce2d6 --- /dev/null +++ b/app/assets/javascripts/darkswarm/services/map_centre_calculator.js.coffee @@ -0,0 +1,29 @@ +Darkswarm.factory 'MapCentreCalculator', -> + new class MapCentreCalculator + calculate_latitude: (coordinates) => + @_calculate("latitude", coordinates) + + calculate_longitude: (coordinates) => + @_calculate("longitude", coordinates) + + _calculate: (angleName, coordinates) => + positiveAngles = [] + negativeAngles = [] + angles = [] + + for coordinate in coordinates + angles.push(coordinate[angleName]) + if coordinate[angleName] > 0 + positiveAngles.push(coordinate[angleName]) + else + negativeAngles.push(coordinate[angleName]) + + minimumAngle = Math.min.apply(null, angles) + maximumAngle = Math.max.apply(null, angles) + + distanceBetweenMinimumAndMaximum = if maximumAngle > minimumAngle + maximumAngle - minimumAngle + else + minimumAngle - maximumAngle + + minimumAngle + (distanceBetweenMinimumAndMaximum / 2) diff --git a/spec/javascripts/unit/darkswarm/services/map_centre_calculator_spec.js.coffee b/spec/javascripts/unit/darkswarm/services/map_centre_calculator_spec.js.coffee new file mode 100644 index 0000000000..00e747a0a8 --- /dev/null +++ b/spec/javascripts/unit/darkswarm/services/map_centre_calculator_spec.js.coffee @@ -0,0 +1,70 @@ +describe 'MapCentreCalculator service', -> + MapCentreCalculator = null + defaultLongitude = null + defaultLatitude = null + + beforeEach -> + module 'Darkswarm' + defaultLongitude = -6 + defaultLatitude = 53 + + inject (_MapCentreCalculator_)-> + MapCentreCalculator = _MapCentreCalculator_ + + describe "calculate_latitude", -> + it "calculates the center latitude", -> + coordinates = [ + { latitude: 53, longitude: defaultLongitude }, + { latitude: 54, longitude: defaultLongitude } + ] + + expect(MapCentreCalculator.calculate_latitude(coordinates)).toEqual 53.5 + + describe "calculate_longitude", -> + it "calculates the center longitude", -> + coordinates = [ + { latitude: defaultLatitude, longitude: -6 }, + { latitude: defaultLatitude, longitude: -7 } + ] + + expect(MapCentreCalculator.calculate_longitude(coordinates)).toEqual -6.5 + + describe "_calculate", -> + it "calculates the average angle correctly when given a single angle", -> + coordinates = [ + { latitude: defaultLatitude, longitude: -7 } + ] + + expect(MapCentreCalculator._calculate("longitude", coordinates)).toEqual -7 + + it "calculates the centre correctly when given a set of positive angles", -> + coordinates = [ + { latitude: 53, longitude: defaultLongitude }, + { latitude: 54, longitude: defaultLongitude } + ] + + expect(MapCentreCalculator._calculate("latitude", coordinates)).toEqual 53.5 + + it "calculates the centre correctly when given a set of negative angles", -> + coordinates = [ + { latitude: defaultLatitude, longitude: -6 }, + { latitude: defaultLatitude, longitude: -7 } + ] + + expect(MapCentreCalculator._calculate("longitude", coordinates)).toEqual -6.5 + + it "calculates the centre correctly when given a mixture of positive and negative angles and the centre is positive", -> + coordinates = [ + { latitude: defaultLatitude, longitude: 7 }, + { latitude: defaultLatitude, longitude: -4 } + ] + + expect(MapCentreCalculator._calculate("longitude", coordinates)).toEqual 1.5 + + it "calculates the centre correctly when given a mixture of positive and negative angles and the centre is negative", -> + coordinates = [ + { latitude: defaultLatitude, longitude: 4 }, + { latitude: defaultLatitude, longitude: -7 } + ] + + expect(MapCentreCalculator._calculate("longitude", coordinates)).toEqual -1.5