-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathindex.js
84 lines (82 loc) · 2.4 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
let zipTree = null;
function getByZipCode(_zip) {
// Cast to string
let zip = String(_zip);
// Validate
// - Check zip length
if (zip.length < 5) {
zip = "00000".substr(zip.length) + zip;
} else if (zip.length > 5) {
return null;
}
// - Reject non-numeric
if (zip.match(/\D/)) {
return null;
}
// Load data if not loaded
if (zipTree === null) {
zipTree = require("./data/zip-tree.json");
}
const p = zip.split("").map(x => parseInt(x, 10));
const place =
zipTree[p[0]] &&
zipTree[p[0]][p[1]] &&
zipTree[p[0]][p[1]][p[2]] &&
zipTree[p[0]][p[1]][p[2]][p[3]] &&
zipTree[p[0]][p[1]][p[2]][p[3]][p[4]]
? zipTree[p[0]][p[1]][p[2]][p[3]][p[4]]
: null;
// Octal check
if (place === null && typeof _zip !== "string" && _zip < 0o7777) {
return getByZipCode(_zip.toString(8));
}
return place;
}
let locTree = null;
function distance(lat, long, op) {
return Math.sqrt(Math.pow(lat - op.lat, 2) + Math.pow(long - op.long, 2));
}
function getByLocation(lat, long, count) {
// Validate
if (
typeof lat === "undefined" ||
isNaN(parseInt(lat, 10)) ||
typeof long === "undefined" ||
isNaN(parseInt(long, 10))
) {
return null;
}
if (locTree === null) {
locTree = require("./data/loc-tree.json");
}
const latIndex = Math.round(Math.abs(parseFloat(lat, 10)));
const longIndex = Math.round(Math.abs(parseFloat(long, 10)));
if (!locTree.zones[latIndex] || !locTree.zones[latIndex][longIndex]) {
return null;
}
const zone = locTree.zones[latIndex][longIndex];
// Return 1
if (!count || count === 1) {
let d = distance(lat, long, locTree.index[zone[0]]);
let index = 0;
for (let i = 1; i < zone.length; i += 1) {
const nd = distance(lat, long, locTree.index[zone[i]]);
if (nd < d) {
d = nd;
index = i;
}
}
return locTree.index[zone[index]];
}
// Return multiple
const sortzone = zone.map(index => {
const place = locTree.index[index];
place.distance = distance(lat, long, place);
return place;
});
return sortzone.sort((a, b) => a.distance - b.distance).slice(0, count);
}
module.exports = {
getByLocation,
getByZipCode,
};