Skip to content

Commit 1abcb2f

Browse files
committed
js/closure: use floor for conversion, add integer tests
1 parent 3543e6f commit 1abcb2f

File tree

2 files changed

+85
-16
lines changed

2 files changed

+85
-16
lines changed

js/closure/openlocationcode.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -362,17 +362,6 @@ exports.isFull = isFull;
362362
specified.
363363
*/
364364
function encode(latitude, longitude, codeLength) {
365-
if (typeof codeLength == 'undefined') {
366-
codeLength = PAIR_CODE_LENGTH;
367-
}
368-
if (
369-
codeLength < MIN_CODE_LEN ||
370-
(codeLength < PAIR_CODE_LENGTH && codeLength % 2 == 1)
371-
) {
372-
throw new Error('IllegalArgumentException: Invalid Plus Code length');
373-
}
374-
codeLength = Math.min(codeLength, MAX_CODE_LEN);
375-
376365
const locationIntegers = _locationToIntegers(latitude, longitude);
377366

378367
return _encodeIntegers(locationIntegers[0], locationIntegers[1], codeLength);
@@ -428,6 +417,17 @@ exports._locationToIntegers = _locationToIntegers;
428417
specified.
429418
*/
430419
function _encodeIntegers(latInt, lngInt, codeLength) {
420+
if (typeof codeLength == 'undefined') {
421+
codeLength = PAIR_CODE_LENGTH;
422+
}
423+
if (
424+
codeLength < MIN_CODE_LEN ||
425+
(codeLength < PAIR_CODE_LENGTH && codeLength % 2 == 1)
426+
) {
427+
throw new Error('IllegalArgumentException: Invalid Plus Code length');
428+
}
429+
codeLength = Math.min(codeLength, MAX_CODE_LEN);
430+
431431
// Javascript strings are immutable and it doesn't have a native
432432
// StringBuilder, so we'll use an array.
433433
const code = new Array(MAX_CODE_LEN + 1);

js/closure/openlocationcode_test.js

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,21 +67,90 @@ testSuite({
6767
asyncTestCase.waitForAsync('Waiting for xhr to respond');
6868
xhrIo_.send(DECODING_TEST_FILE, 'GET');
6969
},
70-
testEncode: function() {
70+
testEncodeDegrees: function () {
7171
const xhrIo_ = new XhrIo();
7272
xhrIo_.listenOnce(EventType.COMPLETE, () => {
73+
// Allow a 5% error rate encoding from degree coordinates (because of floating
74+
// point precision).
75+
const allowedErrorRate = 0.05;
76+
var errors = 0;
7377
const lines = xhrIo_.getResponseText().match(/^[^#].+/gm);
7478
for (var i = 0; i < lines.length; i++) {
7579
const fields = lines[i].split(',');
76-
const lat = parseFloat(fields[0]);
77-
const lng = parseFloat(fields[1]);
80+
const latDegrees = parseFloat(fields[0]);
81+
const lngDegrees = parseFloat(fields[1]);
7882
const length = parseInt(fields[2], 10);
7983
const code = fields[3];
8084

81-
const gotCode = OpenLocationCode.encode(lat, lng, length);
85+
const got = OpenLocationCode.encode(latDegrees, lngDegrees, length);
8286
// Did we get the same code?
83-
assertEquals('testEncode ' + 1, code, gotCode);
87+
if (code != got) {
88+
console.log(
89+
'ENCODING DIFFERENCE: Expected code ' + code +', got ' + got
90+
);
91+
errors++;
92+
}
93+
asyncTestCase.continueTesting();
94+
}
95+
assertTrue(
96+
'testEncodeDegrees: too many errors ' + errors / lines.length,
97+
errors / lines.length < allowedErrorRate
98+
);
99+
});
100+
asyncTestCase.waitForAsync('Waiting for xhr to respond');
101+
xhrIo_.send(ENCODING_TEST_FILE, 'GET');
102+
},
103+
testLocationToIntegers: function () {
104+
const xhrIo_ = new XhrIo();
105+
xhrIo_.listenOnce(EventType.COMPLETE, () => {
106+
const lines = xhrIo_.getResponseText().match(/^[^#].+/gm);
107+
for (var i = 0; i < lines.length; i++) {
108+
const fields = lines[i].split(',');
109+
const latDegrees = parseFloat(fields[0]);
110+
const lngDegrees = parseFloat(fields[1]);
111+
const latIntegers = parseInt(fields[2]);
112+
const lngIntegers = parseInt(fields[3]);
84113

114+
const got = OpenLocationCode._locationToIntegers(
115+
latDegrees,
116+
lngDegrees
117+
);
118+
// Due to floating point precision limitations, we may get values 1 less
119+
// than expected.
120+
assertTrue(
121+
'testEncodeIntegers: expected latitude ' + latIntegers + ', got ' + got[0],
122+
got[0] == latIntegers || got[0] == latIntegers - 1
123+
);
124+
assertTrue(
125+
'testEncodeIntegers: expected longitude ' + lngIntegers + ', got ' + got[1],
126+
got[1] == lngIntegers || got[1] == lngIntegers - 1
127+
);
128+
asyncTestCase.continueTesting();
129+
}
130+
});
131+
asyncTestCase.waitForAsync('Waiting for xhr to respond');
132+
xhrIo_.send(ENCODING_TEST_FILE, 'GET');
133+
},
134+
testEncodeIntegers: function () {
135+
const xhrIo_ = new XhrIo();
136+
xhrIo_.listenOnce(EventType.COMPLETE, () => {
137+
const lines = xhrIo_.getResponseText().match(/^[^#].+/gm);
138+
for (var i = 0; i < lines.length; i++) {
139+
const fields = lines[i].split(',');
140+
const latIntegers = parseInt(fields[2]);
141+
const lngIntegers = parseInt(fields[3]);
142+
const length = parseInt(fields[2], 10);
143+
const code = fields[3];
144+
145+
const got = OpenLocationCode._encodeIntegers(
146+
latIntegers,
147+
lngIntegers,
148+
length
149+
);
150+
// Did we get the same code?
151+
assertEquals(
152+
'testEncodeIntegers: expected code ' + code + ', got ' + got
153+
);
85154
asyncTestCase.continueTesting();
86155
}
87156
});

0 commit comments

Comments
 (0)