@neaps/tide-predictor 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/.eslintrc.js +22 -0
  2. package/.github/workflows/test.yml +15 -0
  3. package/.prettierrc +4 -0
  4. package/Gruntfile.js +87 -0
  5. package/LICENSE +21 -0
  6. package/README.md +199 -0
  7. package/babel.config.js +9 -0
  8. package/dist/tide-predictor.js +1013 -0
  9. package/examples/browser/index.html +51 -0
  10. package/jest.config.js +14 -0
  11. package/lib/astronomy/coefficients.js +31 -0
  12. package/lib/astronomy/constants.js +10 -0
  13. package/lib/astronomy/index.js +199 -0
  14. package/lib/constituents/compound-constituent.js +67 -0
  15. package/lib/constituents/constituent.js +74 -0
  16. package/lib/constituents/index.js +140 -0
  17. package/lib/harmonics/index.js +113 -0
  18. package/lib/harmonics/prediction.js +195 -0
  19. package/lib/index.es6.js +1005 -0
  20. package/lib/index.js +53 -0
  21. package/lib/node-corrections/index.js +147 -0
  22. package/package.json +45 -0
  23. package/rollup.config.js +21 -0
  24. package/src/__mocks__/constituents.js +335 -0
  25. package/src/__mocks__/secondary-station.js +11 -0
  26. package/src/__tests__/index.js +81 -0
  27. package/src/__tests__/noaa.js +92 -0
  28. package/src/astronomy/__tests__/coefficients.js +12 -0
  29. package/src/astronomy/__tests__/index.js +96 -0
  30. package/src/astronomy/coefficients.js +72 -0
  31. package/src/astronomy/constants.js +4 -0
  32. package/src/astronomy/index.js +201 -0
  33. package/src/constituents/__tests__/compound-constituent.js +44 -0
  34. package/src/constituents/__tests__/constituent.js +65 -0
  35. package/src/constituents/__tests__/index.js +34 -0
  36. package/src/constituents/compound-constituent.js +55 -0
  37. package/src/constituents/constituent.js +74 -0
  38. package/src/constituents/index.js +119 -0
  39. package/src/harmonics/__mocks__/water-levels.js +0 -0
  40. package/src/harmonics/__tests__/index.js +123 -0
  41. package/src/harmonics/__tests__/prediction.js +148 -0
  42. package/src/harmonics/index.js +87 -0
  43. package/src/harmonics/prediction.js +175 -0
  44. package/src/index.js +45 -0
  45. package/src/node-corrections/__tests__/index.js +114 -0
  46. package/src/node-corrections/index.js +208 -0
package/lib/index.js ADDED
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = void 0;
7
+
8
+ var _index = _interopRequireDefault(require("./harmonics/index"));
9
+
10
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
11
+
12
+ var tidePredictionFactory = function tidePredictionFactory(constituents, options) {
13
+ var harmonicsOptions = {
14
+ harmonicConstituents: constituents,
15
+ phaseKey: 'phase_GMT',
16
+ offset: false
17
+ };
18
+
19
+ if (typeof options !== 'undefined') {
20
+ Object.keys(harmonicsOptions).forEach(function (key) {
21
+ if (typeof options[key] !== 'undefined') {
22
+ harmonicsOptions[key] = options[key];
23
+ }
24
+ });
25
+ }
26
+
27
+ var tidePrediction = {
28
+ getTimelinePrediction: function getTimelinePrediction(_ref) {
29
+ var start = _ref.start,
30
+ end = _ref.end;
31
+ return (0, _index["default"])(harmonicsOptions).setTimeSpan(start, end).prediction().getTimelinePrediction();
32
+ },
33
+ getExtremesPrediction: function getExtremesPrediction(_ref2) {
34
+ var start = _ref2.start,
35
+ end = _ref2.end,
36
+ labels = _ref2.labels,
37
+ offsets = _ref2.offsets,
38
+ timeFidelity = _ref2.timeFidelity;
39
+ return (0, _index["default"])(harmonicsOptions).setTimeSpan(start, end).prediction({
40
+ timeFidelity: timeFidelity
41
+ }).getExtremesPrediction(labels, offsets);
42
+ },
43
+ getWaterLevelAtTime: function getWaterLevelAtTime(_ref3) {
44
+ var time = _ref3.time;
45
+ var endDate = new Date(time.getTime() + 10 * 60 * 1000);
46
+ return (0, _index["default"])(harmonicsOptions).setTimeSpan(time, endDate).prediction().getTimelinePrediction()[0];
47
+ }
48
+ };
49
+ return tidePrediction;
50
+ };
51
+
52
+ var _default = tidePredictionFactory;
53
+ exports["default"] = _default;
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = void 0;
7
+
8
+ var _constants = require("../astronomy/constants");
9
+
10
+ var corrections = {
11
+ fUnity: function fUnity() {
12
+ return 1;
13
+ },
14
+ // Schureman equations 73, 65
15
+ fMm: function fMm(a) {
16
+ var omega = _constants.d2r * a.omega.value;
17
+ var i = _constants.d2r * a.i.value;
18
+ var I = _constants.d2r * a.I.value;
19
+ var mean = (2 / 3.0 - Math.pow(Math.sin(omega), 2)) * (1 - 3 / 2.0 * Math.pow(Math.sin(i), 2));
20
+ return (2 / 3.0 - Math.pow(Math.sin(I), 2)) / mean;
21
+ },
22
+ // Schureman equations 74, 66
23
+ fMf: function fMf(a) {
24
+ var omega = _constants.d2r * a.omega.value;
25
+ var i = _constants.d2r * a.i.value;
26
+ var I = _constants.d2r * a.I.value;
27
+ var mean = Math.pow(Math.sin(omega), 2) * Math.pow(Math.cos(0.5 * i), 4);
28
+ return Math.pow(Math.sin(I), 2) / mean;
29
+ },
30
+ // Schureman equations 75, 67
31
+ fO1: function fO1(a) {
32
+ var omega = _constants.d2r * a.omega.value;
33
+ var i = _constants.d2r * a.i.value;
34
+ var I = _constants.d2r * a.I.value;
35
+ var mean = Math.sin(omega) * Math.pow(Math.cos(0.5 * omega), 2) * Math.pow(Math.cos(0.5 * i), 4);
36
+ return Math.sin(I) * Math.pow(Math.cos(0.5 * I), 2) / mean;
37
+ },
38
+ // Schureman equations 76, 68
39
+ fJ1: function fJ1(a) {
40
+ var omega = _constants.d2r * a.omega.value;
41
+ var i = _constants.d2r * a.i.value;
42
+ var I = _constants.d2r * a.I.value;
43
+ var mean = Math.sin(2 * omega) * (1 - 3 / 2.0 * Math.pow(Math.sin(i), 2));
44
+ return Math.sin(2 * I) / mean;
45
+ },
46
+ // Schureman equations 77, 69
47
+ fOO1: function fOO1(a) {
48
+ var omega = _constants.d2r * a.omega.value;
49
+ var i = _constants.d2r * a.i.value;
50
+ var I = _constants.d2r * a.I.value;
51
+ var mean = Math.sin(omega) * Math.pow(Math.sin(0.5 * omega), 2) * Math.pow(Math.cos(0.5 * i), 4);
52
+ return Math.sin(I) * Math.pow(Math.sin(0.5 * I), 2) / mean;
53
+ },
54
+ // Schureman equations 78, 70
55
+ fM2: function fM2(a) {
56
+ var omega = _constants.d2r * a.omega.value;
57
+ var i = _constants.d2r * a.i.value;
58
+ var I = _constants.d2r * a.I.value;
59
+ var mean = Math.pow(Math.cos(0.5 * omega), 4) * Math.pow(Math.cos(0.5 * i), 4);
60
+ return Math.pow(Math.cos(0.5 * I), 4) / mean;
61
+ },
62
+ // Schureman equations 227, 226, 68
63
+ // Should probably eventually include the derivations of the magic numbers (0.5023 etc).
64
+ fK1: function fK1(a) {
65
+ var omega = _constants.d2r * a.omega.value;
66
+ var i = _constants.d2r * a.i.value;
67
+ var I = _constants.d2r * a.I.value;
68
+ var nu = _constants.d2r * a.nu.value;
69
+ var sin2IcosnuMean = Math.sin(2 * omega) * (1 - 3 / 2.0 * Math.pow(Math.sin(i), 2));
70
+ var mean = 0.5023 * sin2IcosnuMean + 0.1681;
71
+ return Math.pow(0.2523 * Math.pow(Math.sin(2 * I), 2) + 0.1689 * Math.sin(2 * I) * Math.cos(nu) + 0.0283, 0.5) / mean;
72
+ },
73
+ // Schureman equations 215, 213, 204
74
+ // It can be (and has been) confirmed that the exponent for R_a reads 1/2 via Schureman Table 7
75
+ fL2: function fL2(a) {
76
+ var P = _constants.d2r * a.P.value;
77
+ var I = _constants.d2r * a.I.value;
78
+ var rAInv = Math.pow(1 - 12 * Math.pow(Math.tan(0.5 * I), 2) * Math.cos(2 * P) + 36 * Math.pow(Math.tan(0.5 * I), 4), 0.5);
79
+ return corrections.fM2(a) * rAInv;
80
+ },
81
+ // Schureman equations 235, 234, 71
82
+ // Again, magic numbers
83
+ fK2: function fK2(a) {
84
+ var omega = _constants.d2r * a.omega.value;
85
+ var i = _constants.d2r * a.i.value;
86
+ var I = _constants.d2r * a.I.value;
87
+ var nu = _constants.d2r * a.nu.value;
88
+ var sinsqIcos2nuMean = Math.pow(Math.sin(omega), 2) * (1 - 3 / 2.0 * Math.pow(Math.sin(i), 2));
89
+ var mean = 0.5023 * sinsqIcos2nuMean + 0.0365;
90
+ return Math.pow(0.2523 * Math.pow(Math.sin(I), 4) + 0.0367 * Math.pow(Math.sin(I), 2) * Math.cos(2 * nu) + 0.0013, 0.5) / mean;
91
+ },
92
+ // Schureman equations 206, 207, 195
93
+ fM1: function fM1(a) {
94
+ var P = _constants.d2r * a.P.value;
95
+ var I = _constants.d2r * a.I.value;
96
+ var qAInv = Math.pow(0.25 + 1.5 * Math.cos(I) * Math.cos(2 * P) * Math.pow(Math.cos(0.5 * I), -0.5) + 2.25 * Math.pow(Math.cos(I), 2) * Math.pow(Math.cos(0.5 * I), -4), 0.5);
97
+ return corrections.fO1(a) * qAInv;
98
+ },
99
+ // See e.g. Schureman equation 149
100
+ fModd: function fModd(a, n) {
101
+ return Math.pow(corrections.fM2(a), n / 2.0);
102
+ },
103
+ // Node factors u, see Table 2 of Schureman.
104
+ uZero: function uZero(a) {
105
+ return 0.0;
106
+ },
107
+ uMf: function uMf(a) {
108
+ return -2.0 * a.xi.value;
109
+ },
110
+ uO1: function uO1(a) {
111
+ return 2.0 * a.xi.value - a.nu.value;
112
+ },
113
+ uJ1: function uJ1(a) {
114
+ return -a.nu.value;
115
+ },
116
+ uOO1: function uOO1(a) {
117
+ return -2.0 * a.xi.value - a.nu.value;
118
+ },
119
+ uM2: function uM2(a) {
120
+ return 2.0 * a.xi.value - 2.0 * a.nu.value;
121
+ },
122
+ uK1: function uK1(a) {
123
+ return -a.nup.value;
124
+ },
125
+ // Schureman 214
126
+ uL2: function uL2(a) {
127
+ var I = _constants.d2r * a.I.value;
128
+ var P = _constants.d2r * a.P.value;
129
+ var R = _constants.r2d * Math.atan(Math.sin(2 * P) / (1 / 6.0 * Math.pow(Math.tan(0.5 * I), -2) - Math.cos(2 * P)));
130
+ return 2.0 * a.xi.value - 2.0 * a.nu.value - R;
131
+ },
132
+ uK2: function uK2(a) {
133
+ return -2.0 * a.nupp.value;
134
+ },
135
+ // Schureman 202
136
+ uM1: function uM1(a) {
137
+ var I = _constants.d2r * a.I.value;
138
+ var P = _constants.d2r * a.P.value;
139
+ var Q = _constants.r2d * Math.atan((5 * Math.cos(I) - 1) / (7 * Math.cos(I) + 1) * Math.tan(P));
140
+ return a.xi.value - a.nu.value + Q;
141
+ },
142
+ uModd: function uModd(a, n) {
143
+ return n / 2.0 * corrections.uM2(a);
144
+ }
145
+ };
146
+ var _default = corrections;
147
+ exports["default"] = _default;
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@neaps/tide-predictor",
3
+ "version": "0.0.4",
4
+ "description": "Tide predictor",
5
+ "main": "",
6
+ "repository": "https://github.com/neaps/tide-predictor",
7
+ "author": "Kevin Miller <keveemiller@gmail.com>",
8
+ "license": "MIT",
9
+ "module": "./lib/index.es6.js",
10
+ "browser": "./dist/tide-predictor.js",
11
+ "dependencies": {},
12
+ "devDependencies": {
13
+ "@babel/core": "^7.6.2",
14
+ "@babel/preset-env": "^7.6.2",
15
+ "babel-jest": "^27.2.0",
16
+ "babel-preset-env": "^1.7.0",
17
+ "eslint": "^7.10.0",
18
+ "eslint-config-standard": "^14.1.0",
19
+ "eslint-plugin-import": "^2.18.2",
20
+ "eslint-plugin-jest": "^24.0.2",
21
+ "eslint-plugin-node": "^11.1.0",
22
+ "eslint-plugin-promise": "^4.2.1",
23
+ "eslint-plugin-standard": "^4.0.1",
24
+ "grunt": "^1.4.1",
25
+ "grunt-babel": "^8.0.0",
26
+ "grunt-contrib-clean": "^2.0.0",
27
+ "grunt-contrib-uglify": "^5.0.0",
28
+ "grunt-contrib-watch": "^1.1.0",
29
+ "grunt-coveralls": "^2.0.0",
30
+ "grunt-eslint": "^23.0.0",
31
+ "grunt-exec": "^3.0.0",
32
+ "jest": "^27.2.0",
33
+ "jest-junit": "^11.0.1",
34
+ "kind-of": "^6.0.3",
35
+ "node-fetch": "^2.6.0",
36
+ "rollup-plugin-babel": "^4.3.3",
37
+ "rollup-plugin-node-resolve": "^5.2.0"
38
+ },
39
+ "scripts": {
40
+ "test": "BABEL_ENV=test jest",
41
+ "coverage": "jest --coverage; grunt coveralls;",
42
+ "lint": "eslint ./src",
43
+ "ci": "yarn run lint; jest --ci --runInBand --reporters=default --reporters=jest-junit"
44
+ }
45
+ }
@@ -0,0 +1,21 @@
1
+ import pkg from './package.json'
2
+ import resolve from 'rollup-plugin-node-resolve'
3
+
4
+ export default {
5
+ input: './src/index.js',
6
+ output: [
7
+ {
8
+ name: 'tidePredictor',
9
+ file: pkg.browser,
10
+ format: 'umd'
11
+ },
12
+ { file: pkg.module, format: 'es' }
13
+ ],
14
+ plugins: [
15
+ resolve({
16
+ mainFields: ['module', 'main'],
17
+
18
+ jail: '/src' // Default: '/'
19
+ })
20
+ ]
21
+ }
@@ -0,0 +1,335 @@
1
+ export default [
2
+ {
3
+ number: 1,
4
+ name: 'M2',
5
+ description: 'Principal lunar semidiurnal constituent',
6
+ amplitude: 1.61,
7
+ phase_GMT: 181.3,
8
+ phase_local: 309.4,
9
+ speed: 28.984104
10
+ },
11
+ {
12
+ number: 2,
13
+ name: 'S2',
14
+ description: 'Principal solar semidiurnal constituent',
15
+ amplitude: 0.43,
16
+ phase_GMT: 180.1,
17
+ phase_local: 300.1,
18
+ speed: 30.0
19
+ },
20
+ {
21
+ number: 3,
22
+ name: 'N2',
23
+ description: 'Larger lunar elliptic semidiurnal constituent',
24
+ amplitude: 0.37,
25
+ phase_GMT: 155.0,
26
+ phase_local: 287.4,
27
+ speed: 28.43973
28
+ },
29
+ {
30
+ number: 4,
31
+ name: 'K1',
32
+ description: 'Lunar diurnal constituent',
33
+ amplitude: 1.2,
34
+ phase_GMT: 219.6,
35
+ phase_local: 99.2,
36
+ speed: 15.041069
37
+ },
38
+ {
39
+ number: 5,
40
+ name: 'M4',
41
+ description: 'Shallow water overtides of principal lunar constituent',
42
+ amplitude: 0.0,
43
+ phase_GMT: 272.7,
44
+ phase_local: 168.9,
45
+ speed: 57.96821
46
+ },
47
+ {
48
+ number: 6,
49
+ name: 'O1',
50
+ description: 'Lunar diurnal constituent',
51
+ amplitude: 0.75,
52
+ phase_GMT: 203.5,
53
+ phase_local: 91.9,
54
+ speed: 13.943035
55
+ },
56
+ {
57
+ number: 7,
58
+ name: 'M6',
59
+ description: 'Shallow water overtides of principal lunar constituent',
60
+ amplitude: 0.0,
61
+ phase_GMT: 0.0,
62
+ phase_local: 0.0,
63
+ speed: 86.95232
64
+ },
65
+ {
66
+ number: 8,
67
+ name: 'MK3',
68
+ description: 'Shallow water terdiurnal',
69
+ amplitude: 0.0,
70
+ phase_GMT: 0.0,
71
+ phase_local: 0.0,
72
+ speed: 44.025173
73
+ },
74
+ {
75
+ number: 9,
76
+ name: 'S4',
77
+ description: 'Shallow water overtides of principal solar constituent',
78
+ amplitude: 0.0,
79
+ phase_GMT: 343.5,
80
+ phase_local: 223.5,
81
+ speed: 60.0
82
+ },
83
+ {
84
+ number: 10,
85
+ name: 'MN4',
86
+ description: 'Shallow water quarter diurnal constituent',
87
+ amplitude: 0.0,
88
+ phase_GMT: 233.4,
89
+ phase_local: 134.0,
90
+ speed: 57.423832
91
+ },
92
+ {
93
+ number: 11,
94
+ name: 'NU2',
95
+ description: 'Larger lunar evectional constituent',
96
+ amplitude: 0.07,
97
+ phase_GMT: 160.9,
98
+ phase_local: 292.8,
99
+ speed: 28.512583
100
+ },
101
+ {
102
+ number: 12,
103
+ name: 'S6',
104
+ description: 'Shallow water overtides of principal solar constituent',
105
+ amplitude: 0.0,
106
+ phase_GMT: 0.0,
107
+ phase_local: 0.0,
108
+ speed: 90.0
109
+ },
110
+ {
111
+ number: 13,
112
+ name: 'MU2',
113
+ description: 'Variational constituent',
114
+ amplitude: 0.04,
115
+ phase_GMT: 114.7,
116
+ phase_local: 250.9,
117
+ speed: 27.968208
118
+ },
119
+ {
120
+ number: 14,
121
+ name: '2N2',
122
+ description: 'Lunar elliptical semidiurnal second-order constituent',
123
+ amplitude: 0.05,
124
+ phase_GMT: 125.4,
125
+ phase_local: 262.2,
126
+ speed: 27.895355
127
+ },
128
+ {
129
+ number: 15,
130
+ name: 'OO1',
131
+ description: 'Lunar diurnal',
132
+ amplitude: 0.04,
133
+ phase_GMT: 246.4,
134
+ phase_local: 117.3,
135
+ speed: 16.139101
136
+ },
137
+ {
138
+ number: 16,
139
+ name: 'LAM2',
140
+ description: 'Smaller lunar evectional constituent',
141
+ amplitude: 0.01,
142
+ phase_GMT: 213.6,
143
+ phase_local: 337.9,
144
+ speed: 29.455626
145
+ },
146
+ {
147
+ number: 17,
148
+ name: 'S1',
149
+ description: 'Solar diurnal constituent',
150
+ amplitude: 0.03,
151
+ phase_GMT: 317.1,
152
+ phase_local: 197.1,
153
+ speed: 15.0
154
+ },
155
+ {
156
+ number: 18,
157
+ name: 'M1',
158
+ description: 'Smaller lunar elliptic diurnal constituent',
159
+ amplitude: 0.04,
160
+ phase_GMT: 224.9,
161
+ phase_local: 108.9,
162
+ speed: 14.496694
163
+ },
164
+ {
165
+ number: 19,
166
+ name: 'J1',
167
+ description: 'Smaller lunar elliptic diurnal constituent',
168
+ amplitude: 0.07,
169
+ phase_GMT: 232.3,
170
+ phase_local: 107.5,
171
+ speed: 15.5854435
172
+ },
173
+ {
174
+ number: 20,
175
+ name: 'MM',
176
+ description: 'Lunar monthly constituent',
177
+ amplitude: 0.0,
178
+ phase_GMT: 0.0,
179
+ phase_local: 0.0,
180
+ speed: 0.5443747
181
+ },
182
+ {
183
+ number: 21,
184
+ name: 'SSA',
185
+ description: 'Solar semiannual constituent',
186
+ amplitude: 0.07,
187
+ phase_GMT: 264.6,
188
+ phase_local: 263.9,
189
+ speed: 0.0821373
190
+ },
191
+ {
192
+ number: 22,
193
+ name: 'SA',
194
+ description: 'Solar annual constituent',
195
+ amplitude: 0.2,
196
+ phase_GMT: 198.5,
197
+ phase_local: 198.1,
198
+ speed: 0.0410686
199
+ },
200
+ {
201
+ number: 23,
202
+ name: 'MSF',
203
+ description: 'Lunisolar synodic fortnightly constituent',
204
+ amplitude: 0.0,
205
+ phase_GMT: 0.0,
206
+ phase_local: 0.0,
207
+ speed: 1.0158958
208
+ },
209
+ {
210
+ number: 24,
211
+ name: 'MF',
212
+ description: 'Lunisolar fortnightly constituent',
213
+ amplitude: 0.04,
214
+ phase_GMT: 138.1,
215
+ phase_local: 129.3,
216
+ speed: 1.0980331
217
+ },
218
+ {
219
+ number: 25,
220
+ name: 'RHO',
221
+ description: 'Larger lunar evectional diurnal constituent',
222
+ amplitude: 0.02,
223
+ phase_GMT: 197.0,
224
+ phase_local: 89.2,
225
+ speed: 13.471515
226
+ },
227
+ {
228
+ number: 26,
229
+ name: 'Q1',
230
+ description: 'Larger lunar elliptic diurnal constituent',
231
+ amplitude: 0.13,
232
+ phase_GMT: 194.8,
233
+ phase_local: 87.5,
234
+ speed: 13.398661
235
+ },
236
+ {
237
+ number: 27,
238
+ name: 'T2',
239
+ description: 'Larger solar elliptic constituent',
240
+ amplitude: 0.02,
241
+ phase_GMT: 165.3,
242
+ phase_local: 285.6,
243
+ speed: 29.958933
244
+ },
245
+ {
246
+ number: 28,
247
+ name: 'R2',
248
+ description: 'Smaller solar elliptic constituent',
249
+ amplitude: 0.0,
250
+ phase_GMT: 163.2,
251
+ phase_local: 282.9,
252
+ speed: 30.041067
253
+ },
254
+ {
255
+ number: 29,
256
+ name: '2Q1',
257
+ description: 'Larger elliptic diurnal',
258
+ amplitude: 0.02,
259
+ phase_GMT: 191.7,
260
+ phase_local: 88.8,
261
+ speed: 12.854286
262
+ },
263
+ {
264
+ number: 30,
265
+ name: 'P1',
266
+ description: 'Solar diurnal constituent',
267
+ amplitude: 0.38,
268
+ phase_GMT: 215.8,
269
+ phase_local: 96.1,
270
+ speed: 14.958931
271
+ },
272
+ {
273
+ number: 31,
274
+ name: '2SM2',
275
+ description: 'Shallow water semidiurnal constituent',
276
+ amplitude: 0.0,
277
+ phase_GMT: 348.1,
278
+ phase_local: 99.9,
279
+ speed: 31.015896
280
+ },
281
+ {
282
+ number: 32,
283
+ name: 'M3',
284
+ description: 'Lunar terdiurnal constituent',
285
+ amplitude: 0.01,
286
+ phase_GMT: 7.0,
287
+ phase_local: 19.1,
288
+ speed: 43.47616
289
+ },
290
+ {
291
+ number: 33,
292
+ name: 'L2',
293
+ description: 'Smaller lunar elliptic semidiurnal constituent',
294
+ amplitude: 0.04,
295
+ phase_GMT: 213.4,
296
+ phase_local: 337.1,
297
+ speed: 29.528479
298
+ },
299
+ {
300
+ number: 34,
301
+ name: '2MK3',
302
+ description: 'Shallow water terdiurnal constituent',
303
+ amplitude: 0.0,
304
+ phase_GMT: 126.8,
305
+ phase_local: 143.4,
306
+ speed: 42.92714
307
+ },
308
+ {
309
+ number: 35,
310
+ name: 'K2',
311
+ description: 'Lunisolar semidiurnal constituent',
312
+ amplitude: 0.12,
313
+ phase_GMT: 170.6,
314
+ phase_local: 289.9,
315
+ speed: 30.082138
316
+ },
317
+ {
318
+ number: 36,
319
+ name: 'M8',
320
+ description: 'Shallow water eighth diurnal constituent',
321
+ amplitude: 0.0,
322
+ phase_GMT: 0.0,
323
+ phase_local: 0.0,
324
+ speed: 115.93642
325
+ },
326
+ {
327
+ number: 37,
328
+ name: 'MS4',
329
+ description: 'Shallow water quarter diurnal constituent',
330
+ amplitude: 0.0,
331
+ phase_GMT: 264.0,
332
+ phase_local: 152.1,
333
+ speed: 58.984104
334
+ }
335
+ ]