@bitblit/ratchet-common 4.0.115-alpha → 4.0.119-alpha

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 (114) hide show
  1. package/lib/index.d.ts +73 -1
  2. package/lib/index.mjs +4 -0
  3. package/lib/index.mjs.map +1 -0
  4. package/lib/lang/base64-ratchet.d.ts +1 -1
  5. package/lib/stream/buffer-writable.d.ts +2 -2
  6. package/lib/stream/multi-stream.d.ts +1 -1
  7. package/lib/stream/stream-ratchet.d.ts +2 -2
  8. package/lib/stream/string-writable.d.ts +1 -1
  9. package/package.json +9 -5
  10. package/lib/2d/line-2d.js +0 -1
  11. package/lib/2d/plane-2d.js +0 -1
  12. package/lib/2d/point-2d.js +0 -1
  13. package/lib/2d/poly-line-2d.js +0 -1
  14. package/lib/2d/ratchet-2d.js +0 -245
  15. package/lib/2d/ratchet-2d.spec.js +0 -117
  16. package/lib/build/build-information.js +0 -1
  17. package/lib/build/ratchet-common-info.js +0 -14
  18. package/lib/histogram/histogram-entry.js +0 -1
  19. package/lib/histogram/histogram.js +0 -48
  20. package/lib/histogram/histogram.spec.js +0 -19
  21. package/lib/index.js +0 -1
  22. package/lib/jwt/common-jwt-token.js +0 -1
  23. package/lib/jwt/expired-jwt-handling.js +0 -6
  24. package/lib/jwt/jwt-ratchet-like.js +0 -1
  25. package/lib/jwt/jwt-ratchet.js +0 -164
  26. package/lib/jwt/jwt-ratchet.spec.js +0 -49
  27. package/lib/jwt/jwt-token-base.js +0 -1
  28. package/lib/lang/array-ratchet.js +0 -83
  29. package/lib/lang/array-ratchet.spec.js +0 -68
  30. package/lib/lang/base64-ratchet.js +0 -45
  31. package/lib/lang/base64-ratchet.spec.js +0 -28
  32. package/lib/lang/boolean-ratchet.js +0 -45
  33. package/lib/lang/boolean-ratchet.spec.js +0 -81
  34. package/lib/lang/composite-last-success-provider.js +0 -26
  35. package/lib/lang/composite-last-success-provider.spec.js +0 -26
  36. package/lib/lang/date-ratchet.js +0 -29
  37. package/lib/lang/date-ratchet.spec.js +0 -21
  38. package/lib/lang/duration-ratchet.js +0 -42
  39. package/lib/lang/duration-ratchet.spec.js +0 -39
  40. package/lib/lang/enum-ratchet.js +0 -30
  41. package/lib/lang/enum-ratchet.spec.js +0 -31
  42. package/lib/lang/error-ratchet.js +0 -44
  43. package/lib/lang/error-ratchet.spec.js +0 -20
  44. package/lib/lang/esm-ratchet.js +0 -17
  45. package/lib/lang/expiring-object.js +0 -72
  46. package/lib/lang/expiring-object.spec.js +0 -51
  47. package/lib/lang/geolocation-ratchet.js +0 -263
  48. package/lib/lang/geolocation-ratchet.spec.js +0 -74
  49. package/lib/lang/global-ratchet.js +0 -43
  50. package/lib/lang/global-ratchet.spec.js +0 -14
  51. package/lib/lang/key-value.js +0 -4
  52. package/lib/lang/last-success-provider.js +0 -1
  53. package/lib/lang/map-ratchet.js +0 -164
  54. package/lib/lang/map-ratchet.spec.js +0 -90
  55. package/lib/lang/no.js +0 -4
  56. package/lib/lang/no.spec.js +0 -7
  57. package/lib/lang/number-ratchet.js +0 -155
  58. package/lib/lang/number-ratchet.spec.js +0 -118
  59. package/lib/lang/parsed-url.js +0 -1
  60. package/lib/lang/promise-ratchet.js +0 -138
  61. package/lib/lang/promise-ratchet.spec.js +0 -74
  62. package/lib/lang/require-ratchet.js +0 -56
  63. package/lib/lang/require-ratchet.spec.js +0 -80
  64. package/lib/lang/stop-watch.js +0 -114
  65. package/lib/lang/string-ratchet.js +0 -201
  66. package/lib/lang/string-ratchet.spec.js +0 -158
  67. package/lib/lang/time-zone-ratchet.js +0 -77
  68. package/lib/lang/time-zone-ratchet.spec.js +0 -40
  69. package/lib/lang/timeout-token.js +0 -17
  70. package/lib/lang/timeout-token.spec.js +0 -9
  71. package/lib/lang/transform-ratchet.js +0 -66
  72. package/lib/lang/transform-ratchet.spec.js +0 -118
  73. package/lib/logger/classic-single-line-log-message-formatter.js +0 -13
  74. package/lib/logger/log-message-builder.js +0 -48
  75. package/lib/logger/log-message-format-type.js +0 -6
  76. package/lib/logger/log-message-formatter.js +0 -1
  77. package/lib/logger/log-message-processor.js +0 -1
  78. package/lib/logger/log-message.js +0 -1
  79. package/lib/logger/log-snapshot.js +0 -1
  80. package/lib/logger/logger-instance.js +0 -208
  81. package/lib/logger/logger-level-name.js +0 -9
  82. package/lib/logger/logger-meta.js +0 -1
  83. package/lib/logger/logger-options.js +0 -1
  84. package/lib/logger/logger-output-function.js +0 -6
  85. package/lib/logger/logger-ring-buffer.js +0 -73
  86. package/lib/logger/logger-util.js +0 -44
  87. package/lib/logger/logger-util.spec.js +0 -9
  88. package/lib/logger/logger.js +0 -134
  89. package/lib/logger/logger.spec.js +0 -134
  90. package/lib/logger/none-log-message-formatter.js +0 -5
  91. package/lib/logger/structured-json-log-message-formatter.js +0 -19
  92. package/lib/network/browser-local-ip-provider.js +0 -21
  93. package/lib/network/browser-local-ip-provider.spec.js +0 -16
  94. package/lib/network/fixed-local-ip-provider.js +0 -9
  95. package/lib/network/local-ip-provider.js +0 -1
  96. package/lib/network/network-ratchet.js +0 -102
  97. package/lib/network/network-ratchet.spec.js +0 -13
  98. package/lib/stream/buffer-writable.js +0 -16
  99. package/lib/stream/multi-stream.js +0 -12
  100. package/lib/stream/stream-ratchet.js +0 -68
  101. package/lib/stream/stream-ratchet.spec.js +0 -13
  102. package/lib/stream/string-writable.js +0 -14
  103. package/lib/stream/string-writable.spec.js +0 -12
  104. package/lib/third-party/google/google-recaptcha-ratchet.js +0 -28
  105. package/lib/third-party/google/google-recaptcha-ratchet.spec.js +0 -20
  106. package/lib/third-party/twilio/twilio-ratchet.js +0 -73
  107. package/lib/transform/built-in-transforms.js +0 -191
  108. package/lib/transform/transform-rule.js +0 -1
  109. package/lib/tx/transaction-configuration.js +0 -1
  110. package/lib/tx/transaction-final-state.js +0 -6
  111. package/lib/tx/transaction-ratchet.js +0 -76
  112. package/lib/tx/transaction-ratchet.spec.js +0 -130
  113. package/lib/tx/transaction-result.js +0 -1
  114. package/lib/tx/transaction-step.js +0 -1
@@ -1,42 +0,0 @@
1
- import { DateTime } from 'luxon';
2
- import { NumberRatchet } from './number-ratchet.js';
3
- export class DurationRatchet {
4
- static formatMsDuration(ms, includeMS = false) {
5
- const rem_ms = Math.floor(ms % 1000);
6
- const seconds = Math.floor(ms / 1000) % 60;
7
- const minutes = Math.floor(ms / (1000 * 60)) % 60;
8
- const hours = Math.floor(ms / (1000 * 60 * 60)) % 24;
9
- const days = Math.floor(ms / (1000 * 60 * 60 * 24));
10
- const f = NumberRatchet.leadingZeros;
11
- let rval = f(hours, 2) + 'h' + f(minutes, 2) + 'm';
12
- rval += includeMS ? f(seconds, 2) + '.' + f(rem_ms, 3) + 's' : f(seconds, 2) + 's';
13
- if (days > 0) {
14
- rval = days + 'd' + rval;
15
- }
16
- return rval;
17
- }
18
- static colonFormatMsDuration(ms, includeMS = false) {
19
- const rem_ms = ms % 1000;
20
- const seconds = Math.floor(ms / 1000) % 60;
21
- const minutes = Math.floor(ms / (1000 * 60)) % 60;
22
- const hours = Math.floor(ms / (1000 * 60 * 60));
23
- const f = NumberRatchet.leadingZeros;
24
- let rval = f(hours, 2) + ':' + f(minutes, 2) + ':';
25
- rval += includeMS ? f(seconds, 2) + '.' + f(rem_ms, 3) : f(seconds, 2);
26
- return rval;
27
- }
28
- static daysBetween(d1, d2) {
29
- const dur = DateTime.fromJSDate(d1).diff(DateTime.fromJSDate(d2));
30
- return dur.days;
31
- }
32
- static createSteps(startEpochMS, endEpochMS, timezone, outputFormat, stepUnit) {
33
- let curDate = DateTime.fromMillis(startEpochMS).setZone(timezone);
34
- const endDate = DateTime.fromMillis(endEpochMS);
35
- const rval = [];
36
- while (curDate < endDate) {
37
- rval.push(curDate.toFormat(outputFormat));
38
- curDate = curDate.plus(stepUnit);
39
- }
40
- return rval;
41
- }
42
- }
@@ -1,39 +0,0 @@
1
- import { DurationRatchet } from './duration-ratchet.js';
2
- import { DateTime } from 'luxon';
3
- describe('#formatMsDuration', function () {
4
- it('should format less than one second', function () {
5
- const result = DurationRatchet.formatMsDuration(409, true);
6
- expect(result).toEqual('00h00m00.409s');
7
- });
8
- it('should format more than one day', function () {
9
- const result = DurationRatchet.formatMsDuration(1000 * 60 * 60 * 123, true);
10
- expect(result).toEqual('5d03h00m00.000s');
11
- });
12
- });
13
- describe('#colonFormatMsDuration', function () {
14
- it('should format less than one second', function () {
15
- const result = DurationRatchet.colonFormatMsDuration(409, true);
16
- expect(result).toEqual('00:00:00.409');
17
- });
18
- it('should format more than ten hours', function () {
19
- const result = DurationRatchet.colonFormatMsDuration(1000 * 60 * 60 * 11, false);
20
- expect(result).toEqual('11:00:00');
21
- });
22
- it('should format more than one hundred hours', function () {
23
- const result = DurationRatchet.colonFormatMsDuration(1000 * 60 * 60 * 123, false);
24
- expect(result).toEqual('123:00:00');
25
- });
26
- it('should format 15 seconds', function () {
27
- const result = DurationRatchet.colonFormatMsDuration(15000, false);
28
- expect(result).toEqual('00:00:15');
29
- });
30
- });
31
- describe('#createSteps', function () {
32
- it('should create steps', function () {
33
- const tt = DateTime.fromFormat('2019-01-01', 'yyyy-MM-dd');
34
- const startEpochMS = DateTime.fromFormat('2019-01-01', 'yyyy-MM-dd').toJSDate().getTime();
35
- const endEpochMS = DateTime.fromFormat('2019-01-05', 'yyyy-MM-dd').toJSDate().getTime();
36
- const steps = DurationRatchet.createSteps(startEpochMS, endEpochMS, 'etc/GMT', 'yyyy-MM-dd', { days: 1 });
37
- expect(steps.length).toEqual(4);
38
- });
39
- });
@@ -1,30 +0,0 @@
1
- import { $enum } from 'ts-enum-util';
2
- import { StringRatchet } from './string-ratchet.js';
3
- export class EnumRatchet {
4
- static listEnumKeys(enumeration) {
5
- const rval = $enum(enumeration).getValues();
6
- return rval;
7
- }
8
- static keyToEnum(enumeration, val, caseSensitive = false) {
9
- const e = $enum(enumeration);
10
- let rval = null;
11
- if (!!val) {
12
- rval = e.asValueOrDefault(val, null);
13
- if (!rval && !caseSensitive) {
14
- const keys = EnumRatchet.listEnumKeys(enumeration);
15
- const mKey = keys.find((k) => k.toUpperCase() === val.toUpperCase());
16
- if (!!mKey) {
17
- rval = e.asValueOrDefault(mKey, null);
18
- }
19
- }
20
- }
21
- return rval;
22
- }
23
- static parseCsvToEnumArray(enumeration, input) {
24
- const split = StringRatchet.trimToEmpty(input)
25
- .split(',')
26
- .map((s) => s.trim());
27
- const rval = split.map((s) => EnumRatchet.keyToEnum(enumeration, s)).filter((s) => !!s);
28
- return rval;
29
- }
30
- }
@@ -1,31 +0,0 @@
1
- import { EnumRatchet } from './enum-ratchet.js';
2
- describe('#enumRatchet', function () {
3
- it('should list keys', async () => {
4
- const keys = EnumRatchet.listEnumKeys(TestEnum);
5
- expect(keys).toBeTruthy();
6
- expect(keys.length).toBeGreaterThan(1);
7
- });
8
- it('should find key case insensitive', async () => {
9
- const t1 = EnumRatchet.keyToEnum(TestEnum, 'a');
10
- const t2 = EnumRatchet.keyToEnum(TestEnum, 'b');
11
- const t3 = EnumRatchet.keyToEnum(TestEnum, 'A', true);
12
- const t4 = EnumRatchet.keyToEnum(TestEnum, 'A');
13
- const fixed = TestEnum.A;
14
- expect(t1).toBeTruthy();
15
- expect(t2).toBeTruthy();
16
- expect(t3).toBeNull();
17
- expect(t4).toEqual(fixed);
18
- expect(t4 === fixed).toBeTruthy();
19
- });
20
- it('should parse a csv of enums', async () => {
21
- const vals = EnumRatchet.parseCsvToEnumArray(TestEnum, 'a, b');
22
- expect(vals).toBeTruthy();
23
- expect(vals.length).toEqual(2);
24
- });
25
- });
26
- export var TestEnum;
27
- (function (TestEnum) {
28
- TestEnum["A"] = "a";
29
- TestEnum["B"] = "b";
30
- TestEnum["C"] = "c";
31
- })(TestEnum || (TestEnum = {}));
@@ -1,44 +0,0 @@
1
- import { Logger } from '../logger/logger.js';
2
- import util from 'util';
3
- export class ErrorRatchet {
4
- static safeStringifyErr(err, log = true) {
5
- let rval = 'ERR WAS NULL';
6
- if (err) {
7
- if (err['message']) {
8
- rval = err['message'];
9
- }
10
- else {
11
- try {
12
- rval = JSON.stringify(err);
13
- }
14
- catch (err2) {
15
- Logger.error('Failed to json stringify');
16
- rval = String(err);
17
- }
18
- }
19
- }
20
- if (log) {
21
- Logger.error('%s', rval, err);
22
- }
23
- return rval;
24
- }
25
- static asErr(input) {
26
- let rval = null;
27
- if (input) {
28
- if (input instanceof Error) {
29
- rval = input;
30
- }
31
- else {
32
- rval = new Error('Force-Cast to error : ' + String(input));
33
- }
34
- }
35
- return rval;
36
- }
37
- static fErr(format, ...input) {
38
- const msg = util.format(format, ...input);
39
- return new Error(msg);
40
- }
41
- static throwFormattedErr(format, ...input) {
42
- throw ErrorRatchet.fErr(format, ...input);
43
- }
44
- }
@@ -1,20 +0,0 @@
1
- import { ErrorRatchet } from './error-ratchet.js';
2
- describe('#errorRatchet', function () {
3
- it('should cast to error', async () => {
4
- const e1 = new Error('test1');
5
- const e2 = 'test2';
6
- const e1p = ErrorRatchet.asErr(e1);
7
- const e2p = ErrorRatchet.asErr(e2);
8
- const en = ErrorRatchet.asErr(null);
9
- expect(en).toBeNull();
10
- expect(e1p).toEqual(e1);
11
- expect(e2p).not.toEqual(e2);
12
- expect(e2p instanceof Error).toBeTruthy();
13
- });
14
- it('should correctly stringify', async () => {
15
- const flag = 'test1';
16
- const e1 = new Error(flag);
17
- const out = ErrorRatchet.safeStringifyErr(e1);
18
- expect(out).toEqual(flag);
19
- });
20
- });
@@ -1,17 +0,0 @@
1
- import url from 'url';
2
- export class EsmRatchet {
3
- static fetchDirName(root) {
4
- if (!root) {
5
- throw new Error('Need to provide root (should be import.meta.url)');
6
- }
7
- const rval = url.fileURLToPath(new URL('.', root));
8
- return rval;
9
- }
10
- static fetchFileName(root) {
11
- if (!root) {
12
- throw new Error('Need to provide root (should be import.meta.url)');
13
- }
14
- const rval = url.fileURLToPath(root);
15
- return rval;
16
- }
17
- }
@@ -1,72 +0,0 @@
1
- import { Logger } from '../logger/logger.js';
2
- import { ErrorRatchet } from './error-ratchet.js';
3
- import { LoggerLevelName } from '../logger/logger-level-name.js';
4
- export class ExpiringObject {
5
- _config;
6
- _cacheObject;
7
- _lastUpdatedEpochMS;
8
- _timeRemainingMS;
9
- constructor(inputConfig) {
10
- this._config = Object.assign({}, this.defaultConfig(), inputConfig || {});
11
- if (this._config.overrideTimeRemainingMS && this._config.timeToLiveMS) {
12
- ErrorRatchet.throwFormattedErr('Cannot define both time to live and overrideTimeRemainingMS');
13
- }
14
- if (!this._config.overrideTimeRemainingMS && !this._config.timeToLiveMS) {
15
- ErrorRatchet.throwFormattedErr('Must define exactly one of timeToLiveMS or overrideTimeRemainingMS');
16
- }
17
- if (this._config.initialValue) {
18
- this.update(this._config.initialValue);
19
- }
20
- this._timeRemainingMS = this._config.overrideTimeRemainingMS || this.defaultTimeRemainingMS;
21
- }
22
- defaultConfig() {
23
- const rval = {
24
- generator: null,
25
- initialValue: null,
26
- logLevel: LoggerLevelName.debug,
27
- overrideTimeRemainingMS: null,
28
- timeToLiveMS: 1_000 * 60,
29
- };
30
- return rval;
31
- }
32
- async defaultTimeRemainingMS(lastUpdatedEpochMS) {
33
- let rval = 0;
34
- if (lastUpdatedEpochMS) {
35
- const ageMS = new Date().getTime() - lastUpdatedEpochMS;
36
- rval = Math.max(0, this._config.timeToLiveMS - ageMS);
37
- }
38
- return rval;
39
- }
40
- update(newValue, doNotUpdateClock = false) {
41
- this._cacheObject = newValue;
42
- if (!doNotUpdateClock) {
43
- this._lastUpdatedEpochMS = new Date().getTime();
44
- }
45
- Logger.logByLevel(this._config.logLevel, 'Updated cache value to %j', newValue);
46
- }
47
- async fetchCacheObjectTimeRemainingMS() {
48
- return this._timeRemainingMS(this._lastUpdatedEpochMS);
49
- }
50
- async fetch() {
51
- const remainMS = await this._timeRemainingMS(this._lastUpdatedEpochMS);
52
- if (!remainMS) {
53
- this._cacheObject = null;
54
- this._lastUpdatedEpochMS = null;
55
- }
56
- if (!this._cacheObject) {
57
- if (this._config.generator) {
58
- const newValue = await this._config.generator();
59
- Logger.logByLevel(this._config.logLevel, 'Auto call to generator returned %j', newValue);
60
- this.update(newValue);
61
- }
62
- }
63
- return this._cacheObject;
64
- }
65
- }
66
- export class ExpiringObjectConfig {
67
- timeToLiveMS;
68
- generator;
69
- initialValue;
70
- logLevel;
71
- overrideTimeRemainingMS;
72
- }
@@ -1,51 +0,0 @@
1
- import { ExpiringObject } from './expiring-object.js';
2
- import { PromiseRatchet } from './promise-ratchet.js';
3
- import { LoggerLevelName } from '../logger/logger-level-name.js';
4
- describe('#expiringObject', function () {
5
- it('should default the object', async () => {
6
- const expObject = new ExpiringObject({
7
- initialValue: 7,
8
- timeToLiveMS: 50_000,
9
- logLevel: LoggerLevelName.info,
10
- });
11
- const val = await expObject.fetch();
12
- expect(val).toEqual(7);
13
- });
14
- it('should expire the object', async () => {
15
- const expObject = new ExpiringObject({
16
- initialValue: 7,
17
- timeToLiveMS: 100,
18
- logLevel: LoggerLevelName.info,
19
- });
20
- const val = await expObject.fetch();
21
- expect(val).toEqual(7);
22
- await PromiseRatchet.wait(101);
23
- const val2 = await expObject.fetch();
24
- expect(val2).toBeNull();
25
- });
26
- it('should regen the object', async () => {
27
- const expObject = new ExpiringObject({
28
- initialValue: 7,
29
- timeToLiveMS: 100,
30
- generator: async () => 8,
31
- logLevel: LoggerLevelName.info,
32
- });
33
- const val = await expObject.fetch();
34
- expect(val).toEqual(7);
35
- await PromiseRatchet.wait(101);
36
- const val2 = await expObject.fetch();
37
- expect(val2).toEqual(8);
38
- });
39
- it('should return time remaining', async () => {
40
- const expObject = new ExpiringObject({
41
- initialValue: 7,
42
- timeToLiveMS: 10_000,
43
- logLevel: LoggerLevelName.info,
44
- });
45
- const val = await expObject.fetch();
46
- expect(val).toEqual(7);
47
- const rem = await expObject.fetchCacheObjectTimeRemainingMS();
48
- expect(rem).toBeGreaterThan(0);
49
- expect(rem).toBeLessThanOrEqual(10_000);
50
- });
51
- });
@@ -1,263 +0,0 @@
1
- import { RequireRatchet } from './require-ratchet.js';
2
- import { NumberRatchet } from './number-ratchet.js';
3
- import { ErrorRatchet } from './error-ratchet.js';
4
- import { Logger } from '../logger/logger.js';
5
- export class GeolocationRatchet {
6
- constructor() { }
7
- static distanceBetweenLocations(lat1, lon1, lat2, lon2, unit = 'M') {
8
- const uU = !!unit ? unit.toUpperCase() : '';
9
- if (['M', 'K', 'N', 'F', 'E'].indexOf(uU) === -1) {
10
- throw new Error('Invalid unit');
11
- }
12
- if (lat1 == lat2 && lon1 == lon2) {
13
- return 0;
14
- }
15
- else {
16
- const radlat1 = (Math.PI * lat1) / 180;
17
- const radlat2 = (Math.PI * lat2) / 180;
18
- const theta = lon1 - lon2;
19
- const radtheta = (Math.PI * theta) / 180;
20
- let dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
21
- if (dist > 1) {
22
- dist = 1;
23
- }
24
- dist = Math.acos(dist);
25
- dist = (dist * 180) / Math.PI;
26
- dist = dist * 60 * 1.1515;
27
- if (uU === 'F') {
28
- dist *= 5280;
29
- }
30
- if (uU === 'K') {
31
- dist *= 1.609344;
32
- }
33
- if (uU === 'E') {
34
- dist *= 1609.344;
35
- }
36
- if (uU === 'N') {
37
- dist *= 0.8684;
38
- }
39
- return dist;
40
- }
41
- }
42
- static distanceBetweenRatchetGeoLocations(loc1, loc2, unit = 'M') {
43
- return GeolocationRatchet.distanceBetweenLocations(loc1.lat, loc1.lng, loc2.lat, loc2.lng, unit);
44
- }
45
- static degreeOfLatLngInMiles(latitudeInDecimalDegress = 0) {
46
- const latInRads = (latitudeInDecimalDegress * Math.PI) / 180;
47
- const cosLat = Math.cos(latInRads);
48
- const rval = NumberRatchet.safeNumber((cosLat * 69.172).toFixed(4));
49
- return rval;
50
- }
51
- static milesInDegLatLng(miles, latitudeInDecimalDegress = 0) {
52
- RequireRatchet.notNullOrUndefined(miles);
53
- RequireRatchet.true(miles >= 0);
54
- const degreeInMiles = GeolocationRatchet.degreeOfLatLngInMiles(latitudeInDecimalDegress);
55
- return miles / degreeInMiles;
56
- }
57
- static centerOfBounds(bounds) {
58
- RequireRatchet.notNullOrUndefined(bounds);
59
- return {
60
- lat: (bounds.extent.lat + bounds.origin.lat) / 2,
61
- lng: (bounds.extent.lng + bounds.origin.lng) / 2,
62
- };
63
- }
64
- static calculateSplits(input, slices, field) {
65
- RequireRatchet.notNullOrUndefined(input);
66
- RequireRatchet.notNullOrUndefined(slices);
67
- RequireRatchet.notNullOrUndefined(field);
68
- input.sort((a, b) => a.origin[field] - b.origin[field]);
69
- const centers = input.map((i) => GeolocationRatchet.centerOfBounds(i));
70
- const vals = centers.map((c) => c[field]);
71
- const splits = [];
72
- for (let i = 1; i < vals.length; i++) {
73
- const size = vals[i] - vals[i - 1];
74
- if (splits.length < slices) {
75
- splits.push({ idx: i, size: size });
76
- splits.sort((a, b) => a.size - b.size);
77
- }
78
- else if (size > splits[0].size) {
79
- splits[0] = { idx: i, size: size };
80
- splits.sort((a, b) => a.size - b.size);
81
- }
82
- else {
83
- Logger.silly('Skipping, size : %d, %j', size, splits);
84
- }
85
- }
86
- Logger.info('Splits at : %j', splits);
87
- splits.sort((a, b) => a.idx - b.idx);
88
- return splits;
89
- }
90
- static clusterGeoBounds(inputVal, latSlices = 2, lngSlices = 5) {
91
- let rval = null;
92
- if (latSlices * lngSlices < 2) {
93
- ErrorRatchet.throwFormattedErr('Cannot set slices to less than 2 : %d x %d', latSlices, lngSlices);
94
- }
95
- if (!!inputVal) {
96
- rval = [];
97
- const input = Object.assign([], inputVal);
98
- input.sort((a, b) => a.origin.lng - b.origin.lng);
99
- const lngSplits = GeolocationRatchet.calculateSplits(inputVal, lngSlices - 1, 'lng');
100
- lngSplits.sort((a, b) => a.idx - b.idx);
101
- for (let i = 0; i <= lngSplits.length; i++) {
102
- const lngStartIdx = i === 0 ? 0 : lngSplits[i - 1].idx;
103
- const lngEndIdx = i === lngSplits.length ? input.length : lngSplits[i].idx;
104
- const lngBatch = input.slice(lngStartIdx, lngEndIdx);
105
- lngBatch.sort((a, b) => a.origin.lat - b.origin.lat);
106
- const latSplits = GeolocationRatchet.calculateSplits(lngBatch, latSlices - 1, 'lat');
107
- for (let j = 0; j <= latSplits.length; j++) {
108
- const latStartIdx = j == 0 ? 0 : latSplits[j - 1].idx;
109
- const latEndIdx = j === latSplits.length ? lngBatch.length : latSplits[j].idx;
110
- const latBatch = lngBatch.slice(latStartIdx, latEndIdx);
111
- rval.push(GeolocationRatchet.combineBounds(latBatch));
112
- }
113
- }
114
- Logger.info('New bounds : %j', rval);
115
- }
116
- return rval;
117
- }
118
- static canonicalizeBounds(inp, allowCrossover = false) {
119
- RequireRatchet.notNullOrUndefined(inp, 'RatchetLocationBounds');
120
- const minLat = Math.min(inp.extent.lat, inp.origin.lat);
121
- const maxLat = Math.max(inp.extent.lat, inp.origin.lat);
122
- const minLng = Math.min(inp.extent.lng, inp.origin.lng);
123
- const maxLng = Math.max(inp.extent.lng, inp.origin.lng);
124
- const latXover = (minLat < 0 && maxLat > 0) || (minLat > 0 && maxLat < 0);
125
- const lngXover = (minLat < 0 && maxLat > 0) || (minLat > 0 && maxLat < 0);
126
- if (latXover || lngXover) {
127
- if (allowCrossover) {
128
- return inp;
129
- }
130
- else {
131
- throw new Error('Cannot canonicalize, bounds crosses over boundary');
132
- }
133
- }
134
- const rval = {
135
- origin: {
136
- lat: minLat,
137
- lng: minLng,
138
- },
139
- extent: {
140
- lat: maxLat,
141
- lng: maxLng,
142
- },
143
- };
144
- return rval;
145
- }
146
- static combineBounds(inp) {
147
- let rval = null;
148
- if (inp && inp.length > 0) {
149
- rval = {
150
- origin: {
151
- lat: inp.map((i) => i.origin.lat).reduce((a, i) => Math.min(a, i)),
152
- lng: inp.map((i) => i.origin.lng).reduce((a, i) => Math.min(a, i)),
153
- },
154
- extent: {
155
- lat: inp.map((i) => i.extent.lat).reduce((a, i) => Math.max(a, i)),
156
- lng: inp.map((i) => i.extent.lng).reduce((a, i) => Math.max(a, i)),
157
- },
158
- };
159
- }
160
- return rval;
161
- }
162
- static roundLocation(r, roundDigits) {
163
- return {
164
- lat: NumberRatchet.safeNumber(r.lat.toFixed(roundDigits)),
165
- lng: NumberRatchet.safeNumber(r.lng.toFixed(roundDigits)),
166
- };
167
- }
168
- static locationToBounds(loc, radiusMiles) {
169
- const offset = GeolocationRatchet.milesInDegLatLng(radiusMiles, loc.lat);
170
- const gfb = {
171
- origin: {
172
- lat: loc.lat - offset,
173
- lng: loc.lng - offset,
174
- },
175
- extent: {
176
- lat: loc.lat + offset,
177
- lng: loc.lng + offset,
178
- },
179
- };
180
- return gfb;
181
- }
182
- static sameLocation(loc1, loc2) {
183
- return !!loc1 && !!loc2 && loc1.lat === loc2.lat && loc1.lng === loc2.lng;
184
- }
185
- static pointInBounds(pt, bound) {
186
- return (!!pt &&
187
- !!bound &&
188
- NumberRatchet.between(pt.lat, bound.origin.lat, bound.extent.lat) &&
189
- NumberRatchet.between(pt.lng, bound.origin.lng, bound.extent.lng));
190
- }
191
- static pointInAnyBound(pt, inBounds, minPointsBeforeMapping = 10) {
192
- let rval = false;
193
- if (inBounds.length > minPointsBeforeMapping) {
194
- const mp = GeolocationRatchet.buildRatchetLocationBoundsMap(inBounds);
195
- rval = GeolocationRatchet.pointInRatchetLocationBoundsMap(pt, mp);
196
- }
197
- else {
198
- for (let i = 0; i < inBounds.length && !rval; i++) {
199
- rval = GeolocationRatchet.pointInBounds(pt, inBounds[i]);
200
- }
201
- }
202
- return rval;
203
- }
204
- static pointInRatchetLocationBoundsMap(pt, mp) {
205
- let rval = false;
206
- const entry = GeolocationRatchet.findRatchetLocationBoundsMapEntry(pt, mp);
207
- if (!!entry) {
208
- const bounds = entry.bounds;
209
- for (let i = 0; i < bounds.length && !rval; i++) {
210
- rval = GeolocationRatchet.pointInBounds(pt, bounds[i]);
211
- }
212
- }
213
- return rval;
214
- }
215
- static findRatchetLocationBoundsMapEntry(pt, mp) {
216
- let rval = null;
217
- if (pt.lat >= mp.latOffset && pt.lat <= mp.maxLat && pt.lng >= mp.lngOffset && pt.lng <= mp.maxLng) {
218
- const ltIdx = Math.trunc(pt.lat) - mp.latOffset;
219
- const lngIdx = Math.trunc(pt.lng) - mp.lngOffset;
220
- rval = mp.mapping[ltIdx][lngIdx];
221
- }
222
- return rval;
223
- }
224
- static buildRatchetLocationBoundsMap(inBounds) {
225
- const minLat = inBounds.map((i) => i.origin.lat).reduce((a, i) => Math.min(a, i));
226
- const minLng = inBounds.map((i) => i.origin.lng).reduce((a, i) => Math.min(a, i));
227
- const maxLat = inBounds.map((i) => i.extent.lat).reduce((a, i) => Math.max(a, i));
228
- const maxLng = inBounds.map((i) => i.extent.lng).reduce((a, i) => Math.max(a, i));
229
- const latOffset = Math.trunc(minLat) - 1;
230
- const lngOffset = Math.trunc(minLng) - 1;
231
- const latEntries = Math.trunc(maxLat) - latOffset + 1;
232
- const lngEntries = Math.trunc(maxLng) - lngOffset + 1;
233
- const mapping = [];
234
- for (let i = 0; i < latEntries; i++) {
235
- const newRow = [];
236
- for (let j = 0; j < lngEntries; j++) {
237
- newRow.push({
238
- lat: latOffset + i,
239
- lng: lngOffset + j,
240
- bounds: [],
241
- });
242
- }
243
- mapping.push(newRow);
244
- }
245
- inBounds.forEach((b) => {
246
- for (let i = Math.trunc(b.origin.lat); i <= Math.trunc(b.extent.lat); i++) {
247
- const latIdx = i - latOffset;
248
- const row = mapping[latIdx];
249
- for (let j = Math.trunc(b.origin.lng); j <= Math.trunc(b.extent.lng); j++) {
250
- const lngIdx = j - lngOffset;
251
- row[lngIdx].bounds.push(b);
252
- }
253
- }
254
- });
255
- return {
256
- latOffset: latOffset,
257
- lngOffset: lngOffset,
258
- maxLat: latOffset + latEntries,
259
- maxLng: lngOffset + lngEntries,
260
- mapping: mapping,
261
- };
262
- }
263
- }