-
Notifications
You must be signed in to change notification settings - Fork 0
/
MoonData.js
146 lines (131 loc) · 4.47 KB
/
MoonData.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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
"use strict";
/**
* Returns Lunar Rise/Set times from USNO data
*/
var http = require('http');
var Q = require('q');
/**
* Returns USNO data as a 3-deep nested JavaScript Array of [months][days][riseSetPair], [2][0][3] would be March 4, moon rise time
* @todo add options for Eastern Hemisphere
* @param year {Number} - 4 digit year
* @param long_deg {Number} - Longitude in deg W
* @param long_m {Number} - Longitude in minutes W
* @param lat_deg {Number} - Latitude in deg
* @param lat_m {Number} - Latitude in minutes
* @param tz_offset {Number} - Western GMT offset, 5 = Eastern
* @param name {String} - Friendly Name of data set
* @returns {*|promise}
*/
function getData(year, long_deg, long_m, lat_deg, lat_m, tz_offset, name) {
var deferred = Q.defer();
var url = 'http://aa.usno.navy.mil/cgi-bin/aa_rstablew.pl?FFX=2&xxy=2015&type=0&place=' + name + '&xx0=-1&xx1=' + long_deg + '&xx2='+ long_m +'&yy0=1&yy1=' + lat_deg + '&yy2=' + lat_m + '&zz1=' + tz_offset + '&zz0=-1&ZZZ=END';
http.get(url, function (response) {
var str;
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
var dataTable = dataSetOnly(selectTable(str));
var rows = splitIntoRows(dataTable);
var months = dayMonths(rows);
var cleaned = cleanup(months);
var transformed = transform(cleaned, year);
deferred.resolve(transformed);
});
}).on('error', function (e) {
deferred.reject(e);
});
return deferred.promise;
}
/**
* Selects the data table from the HTML document
* Data is within a <pre> tag
* @param str
* @returns {String}
*/
function selectTable(str) {
return str.match(/<pre>([\s\S]*?)<\/pre>/g).map(function (val) {
return val.replace(/<\/?pre>/g, '');
})[0];
}
/**
* Select the data table only, regex starting at '01' and ending with two line breaks
* Regex are dark magic, this could break if the format changes
* @param str
*/
function dataSetOnly(str) {
return str.match(/\s01([\s\S]*?)\n\n/).map(function (val) {
return val.replace(/^\n/, '');
})[0];
}
/**
* Split each line into an array object (table -> rows) and remove the day index
* @param str
* @returns {Array}
*/
function splitIntoRows(str) {
return str.split(/\r?\n/).map(function (val) {
return val.replace(/^\d\d\ \ /g, '');
});
}
/**
* Push each rise/set tuple into an array for each month
* @param rows
* @returns {*[]}
*/
function dayMonths(rows) {
var months = [[], [], [], [], [], [], [], [], [], [], [], []];
rows.map(function (row) {
months[0].push(row.substr(0, 9));
months[1].push(row.substr(11, 9));
months[2].push(row.substr(22, 9));
months[3].push(row.substr(33, 9));
months[4].push(row.substr(44, 9));
months[5].push(row.substr(55, 9));
months[6].push(row.substr(66, 9));
months[7].push(row.substr(77, 9));
months[8].push(row.substr(88, 9));
months[9].push(row.substr(99, 9));
months[10].push(row.substr(110, 9));
months[11].push(row.substr(121, 9));
});
return months;
}
/**
* Remove empty values and replace blank spaces with no rise/set time with null to normalize the input format
* @param months
* @returns {*}
*/
function cleanup(months) {
for (var monthIdx in months) {
months[monthIdx] = months[monthIdx].filter(function (i) {
return i !== '' && i !== ' ';
});
months[monthIdx] = months[monthIdx].map(function (riseSetPairWithGap) {
return riseSetPairWithGap.replace(/(^\ \ \ \ )|(\ \ \ \ $)/, null).split(' ');
});
}
return months;
}
/**
* Transform rise/set times into JavaScript Date objects
* @param months
* @returns {*}
*/
function transform(months, year) {
for (var monthIdx = 0; monthIdx < 12; monthIdx++) {
for (var dayIdx = 0; dayIdx < months[monthIdx].length; dayIdx++) {
for (var riseSetIdx in months[monthIdx][dayIdx]) {
if (months[monthIdx][dayIdx][riseSetIdx] !== 'null') {
var hour = months[monthIdx][dayIdx][riseSetIdx].substring(0, 2);
var minute = months[monthIdx][dayIdx][riseSetIdx].substring(2, 4);
months[monthIdx][dayIdx][riseSetIdx] = new Date(year, monthIdx, dayIdx + 1, hour, minute);
}
}
}
}
return months;
}
module.exports = {
getData: getData
};