@neaps/tide-predictor 0.0.5 → 0.1.1

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 (52) hide show
  1. package/.eslintrc.cjs +18 -0
  2. package/.github/workflows/test.yml +8 -2
  3. package/.prettierrc +2 -1
  4. package/README.md +31 -15
  5. package/{lib/index.es6.js → dist/commonjs/index.js} +59 -59
  6. package/dist/commonjs/package.json +1 -0
  7. package/dist/{tide-predictor.js → web/tide-predictor.js} +58 -60
  8. package/dist/web/tide-predictor.min.js +1 -0
  9. package/package.json +24 -33
  10. package/rollup.config.js +2 -2
  11. package/src/astronomy/index.js +9 -9
  12. package/src/constituents/compound-constituent.js +3 -4
  13. package/src/constituents/constituent.js +5 -6
  14. package/src/constituents/index.js +17 -17
  15. package/src/harmonics/index.js +11 -11
  16. package/src/harmonics/prediction.js +12 -12
  17. package/src/index.js +3 -3
  18. package/src/node-corrections/index.js +2 -2
  19. package/{src/__mocks__ → test/_mocks}/constituents.js +0 -0
  20. package/{src/__mocks__ → test/_mocks}/secondary-station.js +0 -0
  21. package/{src/harmonics/__mocks__ → test/_mocks}/water-levels.js +0 -0
  22. package/test/astronomy/coefficients.js +15 -0
  23. package/test/astronomy/index.js +98 -0
  24. package/test/constituents/compound-constituent.js +46 -0
  25. package/test/constituents/constituent.js +67 -0
  26. package/test/constituents/index.js +35 -0
  27. package/{src/harmonics/__tests__ → test/harmonics}/index.js +29 -27
  28. package/{src/harmonics/__tests__ → test/harmonics}/prediction.js +37 -31
  29. package/{src/__tests__ → test}/index.js +23 -21
  30. package/test/lib/close-to.js +7 -0
  31. package/test/noaa.js +110 -0
  32. package/test/node-corrections/index.js +116 -0
  33. package/.eslintrc.js +0 -22
  34. package/Gruntfile.js +0 -87
  35. package/babel.config.js +0 -9
  36. package/lib/astronomy/coefficients.js +0 -31
  37. package/lib/astronomy/constants.js +0 -10
  38. package/lib/astronomy/index.js +0 -199
  39. package/lib/constituents/compound-constituent.js +0 -67
  40. package/lib/constituents/constituent.js +0 -74
  41. package/lib/constituents/index.js +0 -140
  42. package/lib/harmonics/index.js +0 -113
  43. package/lib/harmonics/prediction.js +0 -195
  44. package/lib/index.js +0 -53
  45. package/lib/node-corrections/index.js +0 -147
  46. package/src/__tests__/noaa.js +0 -92
  47. package/src/astronomy/__tests__/coefficients.js +0 -12
  48. package/src/astronomy/__tests__/index.js +0 -96
  49. package/src/constituents/__tests__/compound-constituent.js +0 -44
  50. package/src/constituents/__tests__/constituent.js +0 -65
  51. package/src/constituents/__tests__/index.js +0 -34
  52. package/src/node-corrections/__tests__/index.js +0 -114
package/.eslintrc.cjs ADDED
@@ -0,0 +1,18 @@
1
+ module.exports = {
2
+ env: {
3
+ browser: true,
4
+ es2021: true,
5
+ node: true
6
+ },
7
+ extends: 'eslint:recommended',
8
+ parserOptions: {
9
+ ecmaVersion: 'latest',
10
+ sourceType: 'module'
11
+ },
12
+ rules: {
13
+ indent: ['error', 2],
14
+ 'linebreak-style': ['error', 'unix'],
15
+ quotes: ['error', 'single'],
16
+ semi: ['error', 'never']
17
+ }
18
+ }
@@ -9,7 +9,13 @@ jobs:
9
9
  - uses: actions/checkout@v2
10
10
 
11
11
  - name: Install modules
12
- run: yarn
12
+ run: npm install
13
+
14
+ - name: Install codecov
15
+ run: npm install -g codecov
13
16
 
14
17
  - name: Test
15
- run: yarn ci
18
+ run: npm run ci
19
+
20
+ - name: Test build
21
+ run: npm run build
package/.prettierrc CHANGED
@@ -1,4 +1,5 @@
1
1
  {
2
2
  "semi": false,
3
- "singleQuote": true
3
+ "singleQuote": true,
4
+ "trailingComma": "none"
4
5
  }
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- ![example workflow](https://github.com/neaps/tide-predictor/actions/workflows/test.yml/badge.svg) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fneaps%2Ftide-predictor.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fneaps%2Ftide-predictor?ref=badge_shield)
1
+ ![example workflow](https://github.com/neaps/tide-predictor/actions/workflows/test.yml/badge.svg) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fneaps%2Ftide-predictor.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fneaps%2Ftide-predictor?ref=badge_shield) [![codecov](https://codecov.io/gh/neaps/tide-predictor/branch/main/graph/badge.svg?token=KEJK5NQR5H)](https://codecov.io/gh/neaps/tide-predictor)
2
2
 
3
3
  # Tide predictor
4
4
 
@@ -17,13 +17,25 @@ The tide predictions do not factor events such as storm surge, wind waves, uplif
17
17
  # Installation
18
18
 
19
19
  ```
20
+ #npm
21
+ npm install @neaps/tide-prediction
22
+
20
23
  # yarn
21
- yarn install @neaps/tide-prediction
24
+ yarn add @neaps/tide-prediction
22
25
 
23
- #npm
24
- npm install --save @neaps/tide-prediction
25
26
  ```
26
27
 
28
+ ## Importing
29
+
30
+ You can import the module using Ecmascript, or CommonJS. Note that the CommonJS export is transpiled, so deep debugging the module that way will be difficult.
31
+
32
+ ```js
33
+ import TidePrediction from '@neaps/tide-prediction'
34
+ const TidePrediction = require('@neaps/tide-prediction')
35
+ ```
36
+
37
+ There are also packaged and minified versions for the browser in `dist/web`.
38
+
27
39
  # Usage
28
40
 
29
41
  Neaps requires that you [provide your own tidal harmonics information](#constituent-object) to generate a prediction.
@@ -34,20 +46,24 @@ Note that, for now, Neaps **will not** do any timezone corrections. This means y
34
46
 
35
47
  ```javascript
36
48
  import TidePrediction from '@neaps/tide-prediction'
49
+
37
50
  const constituents = [
38
51
  {
39
52
  phase_GMT: 98.7,
40
53
  phase_local: 313.7,
41
54
  amplitude: 2.687,
42
55
  name: 'M2',
43
- speed: 28.984104,
44
- },
56
+ speed: 28.984104
57
+ }
45
58
  //....there are usually many, read the docs
46
59
  ]
47
60
 
48
61
  const highLowTides = tidePrediction(constituents, {
49
- phaseKey: 'phase_GMT',
50
- }).getExtremesPrediction(new Date('2019-01-01'), new Date('2019-01-10'))
62
+ phaseKey: 'phase_GMT'
63
+ }).getExtremesPrediction({
64
+ start: new Date('2019-01-01'),
65
+ end: new Date('2019-01-10')
66
+ })
51
67
  ```
52
68
 
53
69
  ## Tide prediction object
@@ -76,8 +92,8 @@ const tides = tidePrediction(constituents).getExtremesPrediction({
76
92
  labels: {
77
93
  //optional human-readable labels
78
94
  high: 'High tide',
79
- low: 'Low tide',
80
- },
95
+ low: 'Low tide'
96
+ }
81
97
  })
82
98
  ```
83
99
 
@@ -90,13 +106,13 @@ const tides = tidePrediction(constituents).getExtremesPrediction({
90
106
  offset: {
91
107
  height_offset: {
92
108
  high: 1,
93
- low: 2,
109
+ low: 2
94
110
  },
95
111
  time_offset: {
96
112
  high: 1,
97
- low: 2,
98
- },
99
- },
113
+ low: 2
114
+ }
115
+ }
100
116
  })
101
117
  ```
102
118
 
@@ -128,7 +144,7 @@ Gives you the predicted water level at a specific time.
128
144
 
129
145
  ```javascript
130
146
  const waterLevel = tidePrediction(constituents).getWaterLevelAtTime({
131
- time: new Date(),
147
+ time: new Date()
132
148
  })
133
149
  ```
134
150
 
@@ -1,3 +1,5 @@
1
+ 'use strict';
2
+
1
3
  const d2r = Math.PI / 180.0;
2
4
  const r2d = 180.0 / Math.PI;
3
5
 
@@ -30,7 +32,7 @@ const coefficients = {
30
32
  sexagesimalToDecimal(0, 0, 7.12),
31
33
  sexagesimalToDecimal(0, 0, 27.87),
32
34
  sexagesimalToDecimal(0, 0, 5.79),
33
- sexagesimalToDecimal(0, 0, 2.45)
35
+ sexagesimalToDecimal(0, 0, 2.45),
34
36
  ].map((number, index) => {
35
37
  return number * Math.pow(1e-2, index)
36
38
  }),
@@ -39,7 +41,7 @@ const coefficients = {
39
41
  280.46645 - 357.5291,
40
42
  36000.76932 - 35999.0503,
41
43
  0.0003032 + 0.0001559,
42
- 0.00000048
44
+ 0.00000048,
43
45
  ],
44
46
 
45
47
  solarLongitude: [280.46645, 36000.76983, 0.0003032],
@@ -50,7 +52,7 @@ const coefficients = {
50
52
  218.3164591,
51
53
  481267.88134236,
52
54
  -0.0013268,
53
- 1 / 538841.0 - 1 / 65194000.0
55
+ 1 / 538841.0 - 1 / 65194000.0,
54
56
  ],
55
57
 
56
58
  lunarNode: [
@@ -58,7 +60,7 @@ const coefficients = {
58
60
  -1934.1361849,
59
61
  0.0020762,
60
62
  1 / 467410.0,
61
- -1 / 60616000.0
63
+ -1 / 60616000.0,
62
64
  ],
63
65
 
64
66
  lunarPerigee: [
@@ -66,8 +68,8 @@ const coefficients = {
66
68
  4069.0137111,
67
69
  -0.0103238,
68
70
  -1 / 80053.0,
69
- 1 / 18999000.0
70
- ]
71
+ 1 / 18999000.0,
72
+ ],
71
73
  };
72
74
 
73
75
  // Evaluates a polynomial at argument
@@ -93,12 +95,12 @@ const derivativePolynomial = (coefficients, argument) => {
93
95
  };
94
96
 
95
97
  // Meeus formula 11.1
96
- const T = t => {
98
+ const T = (t) => {
97
99
  return (JD(t) - 2451545.0) / 36525
98
100
  };
99
101
 
100
102
  // Meeus formula 7.1
101
- const JD = t => {
103
+ const JD = (t) => {
102
104
  let Y = t.getFullYear();
103
105
  let M = t.getMonth() + 1;
104
106
  const D =
@@ -194,11 +196,11 @@ const _nupp = (N, i, omega) => {
194
196
  return r2d * 0.5 * Math.atan(tan2nupp)
195
197
  };
196
198
 
197
- const modulus = (a, b) => {
199
+ const modulus$1 = (a, b) => {
198
200
  return ((a % b) + b) % b
199
201
  };
200
202
 
201
- const astro = time => {
203
+ const astro = (time) => {
202
204
  const result = {};
203
205
  const polynomials = {
204
206
  s: coefficients.lunarLongitude,
@@ -214,9 +216,9 @@ const astro = time => {
214
216
  // Polynomials are in T, that is Julian Centuries; we want our speeds to be
215
217
  // in the more convenient unit of degrees per hour.
216
218
  const dTdHour = 1 / (24 * 365.25 * 100);
217
- Object.keys(polynomials).forEach(name => {
219
+ Object.keys(polynomials).forEach((name) => {
218
220
  result[name] = {
219
- value: modulus(polynomial(polynomials[name], T(time)), 360.0),
221
+ value: modulus$1(polynomial(polynomials[name], T(time)), 360.0),
220
222
  speed: derivativePolynomial(polynomials[name], T(time)) * dTdHour
221
223
  };
222
224
  });
@@ -231,10 +233,10 @@ const astro = time => {
231
233
  nup: _nup,
232
234
  nupp: _nupp
233
235
  };
234
- Object.keys(functions).forEach(name => {
236
+ Object.keys(functions).forEach((name) => {
235
237
  const functionCall = functions[name];
236
238
  result[name] = {
237
- value: modulus(
239
+ value: modulus$1(
238
240
  functionCall(result.N.value, result.i.value, result.omega.value),
239
241
  360.0
240
242
  ),
@@ -266,7 +268,7 @@ const astro = time => {
266
268
  return result
267
269
  };
268
270
 
269
- const modulus$1 = (a, b) => {
271
+ const modulus = (a, b) => {
270
272
  return ((a % b) + b) % b
271
273
  };
272
274
 
@@ -312,7 +314,7 @@ const predictionFactory = ({ timeline, constituents, start }) => {
312
314
  const amplitudes = [];
313
315
  let result = 0;
314
316
 
315
- constituents.forEach(constituent => {
317
+ constituents.forEach((constituent) => {
316
318
  const amplitude = constituent.amplitude;
317
319
  const phase = constituent._phase;
318
320
  const f = modelF[constituent.name];
@@ -322,7 +324,7 @@ const predictionFactory = ({ timeline, constituents, start }) => {
322
324
  amplitudes.push(amplitude * f * Math.cos(speed * hour + (V0 + u) - phase));
323
325
  });
324
326
  // sum up each row
325
- amplitudes.forEach(item => {
327
+ amplitudes.forEach((item) => {
326
328
  result += item;
327
329
  });
328
330
  return result
@@ -330,7 +332,7 @@ const predictionFactory = ({ timeline, constituents, start }) => {
330
332
 
331
333
  const prediction = {};
332
334
 
333
- prediction.getExtremesPrediction = options => {
335
+ prediction.getExtremesPrediction = (options) => {
334
336
  const { labels, offsets } = typeof options !== 'undefined' ? options : {};
335
337
  const results = [];
336
338
  const { baseSpeed, u, f, baseValue } = prepare();
@@ -389,8 +391,8 @@ const predictionFactory = ({ timeline, constituents, start }) => {
389
391
  timeline.items.forEach((time, index) => {
390
392
  const hour = timeline.hours[index];
391
393
  const prediction = {
392
- time: time,
393
- hour: hour,
394
+ time,
395
+ hour,
394
396
  level: getLevel(hour, baseSpeed, u[index], f[index], baseValue)
395
397
  };
396
398
 
@@ -406,31 +408,31 @@ const predictionFactory = ({ timeline, constituents, start }) => {
406
408
  const baseSpeed = {};
407
409
  const u = [];
408
410
  const f = [];
409
- constituents.forEach(constituent => {
411
+ constituents.forEach((constituent) => {
410
412
  const value = constituent._model.value(baseAstro);
411
413
  const speed = constituent._model.speed(baseAstro);
412
414
  baseValue[constituent.name] = d2r * value;
413
415
  baseSpeed[constituent.name] = d2r * speed;
414
416
  });
415
- timeline.items.forEach(time => {
417
+ timeline.items.forEach((time) => {
416
418
  const uItem = {};
417
419
  const fItem = {};
418
420
  const itemAstro = astro(time);
419
- constituents.forEach(constituent => {
420
- const constituentU = modulus$1(constituent._model.u(itemAstro), 360);
421
+ constituents.forEach((constituent) => {
422
+ const constituentU = modulus(constituent._model.u(itemAstro), 360);
421
423
 
422
424
  uItem[constituent.name] = d2r * constituentU;
423
- fItem[constituent.name] = modulus$1(constituent._model.f(itemAstro), 360);
425
+ fItem[constituent.name] = modulus(constituent._model.f(itemAstro), 360);
424
426
  });
425
427
  u.push(uItem);
426
428
  f.push(fItem);
427
429
  });
428
430
 
429
431
  return {
430
- baseValue: baseValue,
431
- baseSpeed: baseSpeed,
432
- u: u,
433
- f: f
432
+ baseValue,
433
+ baseSpeed,
434
+ u,
435
+ f
434
436
  }
435
437
  };
436
438
 
@@ -582,7 +584,7 @@ const corrections = {
582
584
 
583
585
  // Node factors u, see Table 2 of Schureman.
584
586
 
585
- uZero(a) {
587
+ uZero() {
586
588
  return 0.0
587
589
  },
588
590
 
@@ -657,7 +659,7 @@ const dotArray = (a, b) => {
657
659
  })
658
660
  };
659
661
 
660
- const astronimicDoodsonNumber = astro => {
662
+ const astronimicDoodsonNumber = (astro) => {
661
663
  return [
662
664
  astro['T+h-s'],
663
665
  astro.s,
@@ -669,17 +671,17 @@ const astronimicDoodsonNumber = astro => {
669
671
  ]
670
672
  };
671
673
 
672
- const astronomicSpeed = astro => {
674
+ const astronomicSpeed = (astro) => {
673
675
  const results = [];
674
- astronimicDoodsonNumber(astro).forEach(number => {
676
+ astronimicDoodsonNumber(astro).forEach((number) => {
675
677
  results.push(number.speed);
676
678
  });
677
679
  return results
678
680
  };
679
681
 
680
- const astronomicValues = astro => {
682
+ const astronomicValues = (astro) => {
681
683
  const results = [];
682
- astronimicDoodsonNumber(astro).forEach(number => {
684
+ astronimicDoodsonNumber(astro).forEach((number) => {
683
685
  results.push(number.value);
684
686
  });
685
687
  return results
@@ -691,11 +693,10 @@ const constituentFactory = (name, coefficients, u, f) => {
691
693
  }
692
694
 
693
695
  const constituent = {
694
- name: name,
696
+ name,
697
+ coefficients,
695
698
 
696
- coefficients: coefficients,
697
-
698
- value: astro => {
699
+ value: (astro) => {
699
700
  return dotArray(coefficients, astronomicValues(astro))
700
701
  },
701
702
 
@@ -723,11 +724,10 @@ const compoundConstituentFactory = (name, members) => {
723
724
  });
724
725
 
725
726
  const compoundConstituent = {
726
- name: name,
727
-
728
- coefficients: coefficients,
727
+ name,
728
+ coefficients,
729
729
 
730
- speed: astro => {
730
+ speed: (astro) => {
731
731
  let speed = 0;
732
732
  members.forEach(({ constituent, factor }) => {
733
733
  speed += constituent.speed(astro) * factor;
@@ -735,7 +735,7 @@ const compoundConstituentFactory = (name, members) => {
735
735
  return speed
736
736
  },
737
737
 
738
- value: astro => {
738
+ value: (astro) => {
739
739
  let value = 0;
740
740
  members.forEach(({ constituent, factor }) => {
741
741
  value += constituent.value(astro) * factor;
@@ -743,7 +743,7 @@ const compoundConstituentFactory = (name, members) => {
743
743
  return value
744
744
  },
745
745
 
746
- u: astro => {
746
+ u: (astro) => {
747
747
  let u = 0;
748
748
  members.forEach(({ constituent, factor }) => {
749
749
  u += constituent.u(astro) * factor;
@@ -751,7 +751,7 @@ const compoundConstituentFactory = (name, members) => {
751
751
  return u
752
752
  },
753
753
 
754
- f: astro => {
754
+ f: (astro) => {
755
755
  const f = [];
756
756
  members.forEach(({ constituent, factor }) => {
757
757
  f.push(Math.pow(constituent.f(astro), Math.abs(factor)));
@@ -806,10 +806,10 @@ constituents.K2 = constituentFactory('K2', [2, 2, 0, 0, 0, 0, 0], corrections.uK
806
806
  constituents.M3 = constituentFactory(
807
807
  'M3',
808
808
  [3, 0, 0, 0, 0, 0, 0],
809
- a => {
809
+ (a) => {
810
810
  return corrections.uModd(a, 3)
811
811
  },
812
- a => {
812
+ (a) => {
813
813
  return corrections.fModd(a, 3)
814
814
  }
815
815
  );
@@ -879,7 +879,7 @@ constituents.M8 = compoundConstituentFactory('M8', [
879
879
  { constituent: constituents.M2, factor: 4 }
880
880
  ]);
881
881
 
882
- const getDate = time => {
882
+ const getDate = (time) => {
883
883
  if (time instanceof Date) {
884
884
  return time
885
885
  }
@@ -891,20 +891,20 @@ const getDate = time => {
891
891
 
892
892
  const getTimeline = (start, end, seconds) => {
893
893
  seconds = typeof seconds !== 'undefined' ? seconds : 10 * 60;
894
- const timeline = [];
894
+ const items = [];
895
895
  const endTime = end.getTime() / 1000;
896
896
  let lastTime = start.getTime() / 1000;
897
897
  const startTime = lastTime;
898
898
  const hours = [];
899
899
  while (lastTime <= endTime) {
900
- timeline.push(new Date(lastTime * 1000));
900
+ items.push(new Date(lastTime * 1000));
901
901
  hours.push((lastTime - startTime) / (60 * 60));
902
902
  lastTime += seconds;
903
903
  }
904
904
 
905
905
  return {
906
- items: timeline,
907
- hours: hours
906
+ items,
907
+ hours
908
908
  }
909
909
  };
910
910
 
@@ -913,7 +913,7 @@ const harmonicsFactory = ({ harmonicConstituents, phaseKey, offset }) => {
913
913
  throw new Error('Harmonic constituents are not an array')
914
914
  }
915
915
  const constituents$1 = [];
916
- harmonicConstituents.forEach((constituent, index) => {
916
+ harmonicConstituents.forEach((constituent) => {
917
917
  if (typeof constituent.name === 'undefined') {
918
918
  throw new Error('Harmonic constituents must have a name property')
919
919
  }
@@ -947,13 +947,13 @@ const harmonicsFactory = ({ harmonicConstituents, phaseKey, offset }) => {
947
947
  return harmonics
948
948
  };
949
949
 
950
- harmonics.prediction = options => {
950
+ harmonics.prediction = (options) => {
951
951
  options =
952
952
  typeof options !== 'undefined' ? options : { timeFidelity: 10 * 60 };
953
953
  return predictionFactory({
954
954
  timeline: getTimeline(start, end, options.timeFidelity),
955
955
  constituents: constituents$1,
956
- start: start
956
+ start
957
957
  })
958
958
  };
959
959
 
@@ -968,7 +968,7 @@ const tidePredictionFactory = (constituents, options) => {
968
968
  };
969
969
 
970
970
  if (typeof options !== 'undefined') {
971
- Object.keys(harmonicsOptions).forEach(key => {
971
+ Object.keys(harmonicsOptions).forEach((key) => {
972
972
  if (typeof options[key] !== 'undefined') {
973
973
  harmonicsOptions[key] = options[key];
974
974
  }
@@ -986,7 +986,7 @@ const tidePredictionFactory = (constituents, options) => {
986
986
  getExtremesPrediction: ({ start, end, labels, offsets, timeFidelity }) => {
987
987
  return harmonicsFactory(harmonicsOptions)
988
988
  .setTimeSpan(start, end)
989
- .prediction({ timeFidelity: timeFidelity })
989
+ .prediction({ timeFidelity })
990
990
  .getExtremesPrediction(labels, offsets)
991
991
  },
992
992
 
@@ -1002,4 +1002,4 @@ const tidePredictionFactory = (constituents, options) => {
1002
1002
  return tidePrediction
1003
1003
  };
1004
1004
 
1005
- export default tidePredictionFactory;
1005
+ module.exports = tidePredictionFactory;
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}