From 6b439fcc0a1c3f176c5619de609843bbb68b6c6a Mon Sep 17 00:00:00 2001 From: Juuso Lehtinen Date: Sat, 18 Jul 2020 12:32:27 +0300 Subject: [PATCH 1/7] Convert coordinates to locator --- src/index.js | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/index.js b/src/index.js index 088bd43..33ec156 100644 --- a/src/index.js +++ b/src/index.js @@ -6,6 +6,7 @@ const CHAR_CODE_OFFSET = 65; const isValidLocatorString = locatorString => locatorString.match(/^[A-Ra-r][A-Ra-r]\d\d[A-Xa-x][A-Xa-x]/) !== null; const charToNumber = char => char.toUpperCase().charCodeAt(0) - CHAR_CODE_OFFSET; +const numberToChar = number => String.fromCharCode(number + CHAR_CODE_OFFSET); const locatorToLatLng = (locatorString) => { locatorString += 'll'; // append subsquare in case is 4 chars long... If not, is ignored. @@ -56,9 +57,28 @@ const bearingDistance = (from, to) => { const distance = (from, to) => bearingDistance(from, to).km; +const latLngToLocator = (lat, lng) => { + const longitude = lng + 180; + const latitude = lat + 90; + + const squareLng = numberToChar(Math.floor(longitude / 20)); + const squareLat = numberToChar(Math.floor(latitude / 10)); + + const fieldLng = Math.floor(longitude % 20 / 2); + const fieldLat = Math.floor(latitude % 10); + + const subsquareLng = numberToChar(Math.floor((longitude % 20 % 2) * 12)).toLowerCase(); + const subsquareLat = numberToChar((latitude % 10 - fieldLat) * 24).toLowerCase(); + + return squareLng + squareLat + + fieldLng + fieldLat + + subsquareLng + subsquareLat; +}; + module.exports = { - isValidLocatorString: isValidLocatorString, - locatorToLatLng: locatorToLatLng, - distance: distance, - bearingDistance: bearingDistance + isValidLocatorString, + locatorToLatLng, + distance, + bearingDistance, + latLngToLocator }; \ No newline at end of file From f5ab593eb5149a004065088703a1119f4b2fdad1 Mon Sep 17 00:00:00 2001 From: Juuso Lehtinen Date: Sat, 18 Jul 2020 12:32:47 +0300 Subject: [PATCH 2/7] Add test for latLngToLocator --- test/index.spec.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/index.spec.js b/test/index.spec.js index 5335003..ee5c9ff 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -69,4 +69,11 @@ describe('QTH locator', () => { it('detect invalid grid in bearingDistance 1', () => { expectInvalifGridErr(qthLocator.bearingDistance, 'FN20qr', 'F030ll'); }); + + it('Converts latLng to grid', () => { + expect(qthLocator.latLngToLocator(14.3125, -32.125)).toBe('HK34wh'); + expect(qthLocator.latLngToLocator(60.179, 24.945)).toBe('KP20le'); + expect(qthLocator.latLngToLocator(-33.886048, 151.193546)).toBe('QF56oc'); + expect(qthLocator.latLngToLocator(-22.904788, -43.184915)).toBe('GG87jc'); + }); }); From 04e59c9673483cf02d343bd9fcee36294cc98608 Mon Sep 17 00:00:00 2001 From: Juuso Lehtinen Date: Sat, 18 Jul 2020 12:34:11 +0300 Subject: [PATCH 3/7] Updated readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4d154b1..fcb421a 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,12 @@ Operations with [Maidenhead locator system](https://en.wikipedia.org/wiki/Maiden ## Usage ```javascript -const { locatorToLatLng, distance } = require('qth-locator'); +const { locatorToLatLng, distance, bearingDistance, latLngToLocator } = require('qth-locator'); locatorToLatLng('IO91wm'); // [51.521, -0.125] distance('IO91wm', 'KP20le'); // 1821.5 km bearingDistance('FN20qr', 'KP21ol') // 6586.72 km, 49.16 degrees - +latLngToLocator(60.179, 24.945) // KP21le ``` ## License From 810df037dea090dc05601d46e9f772619cbe88ba Mon Sep 17 00:00:00 2001 From: Juuso Lehtinen Date: Sat, 18 Jul 2020 12:35:29 +0300 Subject: [PATCH 4/7] Fix typo --- test/index.spec.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/index.spec.js b/test/index.spec.js index ee5c9ff..c862f6b 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -21,7 +21,7 @@ describe('QTH locator', () => { expect(BDPair.deg).toBeCloseTo(deg); }; - const expectInvalifGridErr = (fn, a, b) => { + const expectInvalidGridErr = (fn, a, b) => { expect.assertions(2); try { @@ -55,7 +55,7 @@ describe('QTH locator', () => { }); it('Detect invalid grid', () => { - expectInvalifGridErr(qthLocator.locatorToLatLng, 'RZ73'); + expectInvalidGridErr(qthLocator.locatorToLatLng, 'RZ73'); }); it('Locate debatable grid - It is in spec!', () => { @@ -63,11 +63,11 @@ describe('QTH locator', () => { }); it('Detect short grid', () => { - expectInvalifGridErr(qthLocator.locatorToLatLng, 'R73'); + expectInvalidGridErr(qthLocator.locatorToLatLng, 'R73'); }); it('detect invalid grid in bearingDistance 1', () => { - expectInvalifGridErr(qthLocator.bearingDistance, 'FN20qr', 'F030ll'); + expectInvalidGridErr(qthLocator.bearingDistance, 'FN20qr', 'F030ll'); }); it('Converts latLng to grid', () => { From 8cb7aa67894331015eeae5de2b4c24f8e756b478 Mon Sep 17 00:00:00 2001 From: Juuso Lehtinen Date: Sat, 18 Jul 2020 12:48:47 +0300 Subject: [PATCH 5/7] Validate input coordinates --- src/index.js | 6 ++++++ test/index.spec.js | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/index.js b/src/index.js index 33ec156..6e69e24 100644 --- a/src/index.js +++ b/src/index.js @@ -57,7 +57,13 @@ const bearingDistance = (from, to) => { const distance = (from, to) => bearingDistance(from, to).km; +const isValidPoint = (lat, lng) => (lat >= -90 && lat <= 90) && (lng >= -180 && lng <= 180); + const latLngToLocator = (lat, lng) => { + if (!isValidPoint(lat, lng)) { + throw new Error('Input is not a valid coordinate'); + } + const longitude = lng + 180; const latitude = lat + 90; diff --git a/test/index.spec.js b/test/index.spec.js index c862f6b..b74d72c 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -32,6 +32,17 @@ describe('QTH locator', () => { } }; + const expectInvalidLatLngErr = (fn, a, b) => { + expect.assertions(4); + + try { + fn(a, b); + } catch (error) { + expect(error).toHaveProperty('message', 'Input is not a valid coordinate'); + expect(error).toBeInstanceOf(Error); + } + }; + it('Converts locator string to coordinates', () => { expectCoordinates(qthLocator.locatorToLatLng('KP20le'), 60.188, 24.958); expectCoordinates(qthLocator.locatorToLatLng('FN31pr'), 41.729, -72.708); @@ -76,4 +87,14 @@ describe('QTH locator', () => { expect(qthLocator.latLngToLocator(-33.886048, 151.193546)).toBe('QF56oc'); expect(qthLocator.latLngToLocator(-22.904788, -43.184915)).toBe('GG87jc'); }); + + it('Throws error for invalid latitude', () => { + expectInvalidLatLngErr(qthLocator.latLngToLocator, 91, 120); + expectInvalidLatLngErr(qthLocator.latLngToLocator, -91, 120); + }); + + it('Throws error for invalid longitude', () => { + expectInvalidLatLngErr(qthLocator.latLngToLocator, 55, -181); + expectInvalidLatLngErr(qthLocator.latLngToLocator, 55, 181); + }); }); From 001942a9fa26e2116da63a3d3a3222ff67bfb208 Mon Sep 17 00:00:00 2001 From: Juuso Lehtinen Date: Sat, 18 Jul 2020 13:00:25 +0300 Subject: [PATCH 6/7] Simplify error checking tests --- test/index.spec.js | 42 +++++++++++------------------------------- 1 file changed, 11 insertions(+), 31 deletions(-) diff --git a/test/index.spec.js b/test/index.spec.js index b74d72c..7390a3d 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -21,27 +21,9 @@ describe('QTH locator', () => { expect(BDPair.deg).toBeCloseTo(deg); }; - const expectInvalidGridErr = (fn, a, b) => { - expect.assertions(2); - - try { - fn(a, b); - } catch (error) { - expect(error).toHaveProperty('message', 'Input is not valid locator string'); - expect(error).toBeInstanceOf(Error); - } - }; - - const expectInvalidLatLngErr = (fn, a, b) => { - expect.assertions(4); + const expectInvalidGridErr = fn => expect(fn).toThrow('Input is not valid locator string'); - try { - fn(a, b); - } catch (error) { - expect(error).toHaveProperty('message', 'Input is not a valid coordinate'); - expect(error).toBeInstanceOf(Error); - } - }; + const expectInvalidLatLngErr = fn => expect(fn).toThrow('Input is not a valid coordinate'); it('Converts locator string to coordinates', () => { expectCoordinates(qthLocator.locatorToLatLng('KP20le'), 60.188, 24.958); @@ -66,7 +48,7 @@ describe('QTH locator', () => { }); it('Detect invalid grid', () => { - expectInvalidGridErr(qthLocator.locatorToLatLng, 'RZ73'); + expectInvalidGridErr(() => qthLocator.locatorToLatLng('RZ73')); }); it('Locate debatable grid - It is in spec!', () => { @@ -74,11 +56,11 @@ describe('QTH locator', () => { }); it('Detect short grid', () => { - expectInvalidGridErr(qthLocator.locatorToLatLng, 'R73'); + expectInvalidGridErr(() => qthLocator.locatorToLatLng('R73')); }); it('detect invalid grid in bearingDistance 1', () => { - expectInvalidGridErr(qthLocator.bearingDistance, 'FN20qr', 'F030ll'); + expectInvalidGridErr(() => qthLocator.bearingDistance('FN20qr', 'F030ll')); }); it('Converts latLng to grid', () => { @@ -88,13 +70,11 @@ describe('QTH locator', () => { expect(qthLocator.latLngToLocator(-22.904788, -43.184915)).toBe('GG87jc'); }); - it('Throws error for invalid latitude', () => { - expectInvalidLatLngErr(qthLocator.latLngToLocator, 91, 120); - expectInvalidLatLngErr(qthLocator.latLngToLocator, -91, 120); - }); - - it('Throws error for invalid longitude', () => { - expectInvalidLatLngErr(qthLocator.latLngToLocator, 55, -181); - expectInvalidLatLngErr(qthLocator.latLngToLocator, 55, 181); + it('Throws error for invalid coordinates', () => { + expectInvalidLatLngErr(() => qthLocator.latLngToLocator(91, 120)); + expectInvalidLatLngErr(() => qthLocator.latLngToLocator(-91, 120)); + expectInvalidLatLngErr(() => qthLocator.latLngToLocator(55, 181)); + expectInvalidLatLngErr(() => qthLocator.latLngToLocator(55, -181)); + expectInvalidLatLngErr(() => qthLocator.latLngToLocator(-91, -181)); }); }); From 2db25817602be240771dc7e64099ffa731e5c9f5 Mon Sep 17 00:00:00 2001 From: Juuso Lehtinen Date: Sat, 18 Jul 2020 13:01:15 +0300 Subject: [PATCH 7/7] v2.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ba98a42..f04a8ad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "qth-locator", - "version": "2.0.0", + "version": "2.1.0", "description": "Maidenhead locator calculator", "repository": { "type": "git",