senaev-utils 1.0.0
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.
- package/README.md +11 -0
- package/package.json +66 -0
- package/src/reactHooks/setDeepEqualState.ts +19 -0
- package/src/reactHooks/useLocationParameter.ts +46 -0
- package/src/reactHooks/useObjectDeepChangesCounter.ts +22 -0
- package/src/reactHooks/useObservableMap/useObservableMap.ts +21 -0
- package/src/reactHooks/useRecentChangeTimer.ts +42 -0
- package/src/reactHooks/useReload.ts +17 -0
- package/src/reactHooks/useVisualizedProcessesTree.ts +202 -0
- package/src/types/Boolean.ts +9 -0
- package/src/types/DeepPartial.ts +1 -0
- package/src/types/GlobalContext.ts +8 -0
- package/src/types/HexColorString.ts +9 -0
- package/src/types/ISOLang.ts +5 -0
- package/src/types/IsEqualUnion.ts +1 -0
- package/src/types/IterableWithIndexAccess.ts +4 -0
- package/src/types/Kilobits.ts +4 -0
- package/src/types/Network/Bits.ts +4 -0
- package/src/types/Network/Bps.ts +4 -0
- package/src/types/Network/Kbps.ts +4 -0
- package/src/types/Network/Mbps.ts +4 -0
- package/src/types/Number/AngleInDegrees.ts +3 -0
- package/src/types/Number/FiniteNumber.ts +11 -0
- package/src/types/Number/Integer.ts +14 -0
- package/src/types/Number/IntegerInString.ts +13 -0
- package/src/types/Number/Number.ts +15 -0
- package/src/types/Number/Portion.ts +4 -0
- package/src/types/Number/PositiveInteger.ts +30 -0
- package/src/types/Number/PositiveNumber.ts +4 -0
- package/src/types/Number/StringUnsignedInteger.ts +4 -0
- package/src/types/Number/UnsignedFiniteNumber.ts +13 -0
- package/src/types/Number/UnsignedInteger.ts +28 -0
- package/src/types/Object/Object.ts +20 -0
- package/src/types/Percent.ts +4 -0
- package/src/types/PixelPosition.ts +9 -0
- package/src/types/PixelSize.ts +9 -0
- package/src/types/Pixels.ts +4 -0
- package/src/types/RangeTuple.ts +1 -0
- package/src/types/Size.ts +8 -0
- package/src/types/Time/DaysCount.ts +6 -0
- package/src/types/Time/Hours.ts +4 -0
- package/src/types/Time/ISODateString/ISODateString.ts +16 -0
- package/src/types/Time/Milliseconds.ts +4 -0
- package/src/types/Time/Minutes.ts +4 -0
- package/src/types/Time/Seconds.ts +5 -0
- package/src/types/Time/Time.ts +13 -0
- package/src/types/Time/Timestamp.ts +6 -0
- package/src/types/Time/UnixTimeMs.ts +6 -0
- package/src/types/Time/UnixTimeSec.ts +11 -0
- package/src/types/Time/const.ts +24 -0
- package/src/types/any/AnyAsyncFunction.ts +2 -0
- package/src/types/any/AnyFunction.ts +2 -0
- package/src/types/assertions/ANY_VALUE.ts +2 -0
- package/src/types/assertions/isNever/isNever.ts +34 -0
- package/src/types/assertions/isTrue/isTrue.ts +13 -0
- package/src/utils/AbortableProcess.ts +160 -0
- package/src/utils/Array/createArray/createArray.ts +8 -0
- package/src/utils/Array/createIntegerSequenceArray/createIntegerSequenceArray.ts +3 -0
- package/src/utils/Array/getUniqueValues/getUniqueValues.ts +3 -0
- package/src/utils/Array/separateToArrays/separateToArrays.ts +24 -0
- package/src/utils/Array/shuffleArray/shuffleArray.ts +18 -0
- package/src/utils/CircularBuffer/CircularBuffer.ts +117 -0
- package/src/utils/DOM/blurDocument.ts +3 -0
- package/src/utils/DOM/unfocusDocument.ts +3 -0
- package/src/utils/Date/dateToUnixTimeSec/dateToUnixTimeSec.ts +6 -0
- package/src/utils/Date/isoDateStringToUnixTimeMs/isoDateStringToUnixTimeMs.ts +6 -0
- package/src/utils/Date/isoDateStringToUnixTimeSec/isoDateStringToUnixTimeSec.ts +7 -0
- package/src/utils/Date/unixTimeSecToIsoDateString/unixTimeSecToIsoDateString.ts +6 -0
- package/src/utils/Deque/Deque.ts +530 -0
- package/src/utils/DeviceDetection/isTouchScreenDevice/isTouchScreenDevice.ts +16 -0
- package/src/utils/Error/rethrowError/rethrowError.ts +8 -0
- package/src/utils/Error/wrapError.ts +32 -0
- package/src/utils/Function/callFirstThenOther/callFirstThenOther.ts +24 -0
- package/src/utils/Function/callFunctions/callFunctions.ts +11 -0
- package/src/utils/Function/callTimes/callTimes.ts +5 -0
- package/src/utils/Function/isFunction.ts +3 -0
- package/src/utils/Function/noop/index.ts +4 -0
- package/src/utils/Function/once/once.ts +32 -0
- package/src/utils/Function/subscribeUpdatesWithTimeout/index.ts +44 -0
- package/src/utils/Function/throttleFunction/throttleFunction.ts +18 -0
- package/src/utils/Function/throttleWithPromiseFunction/throttleWithPromiseFunction.ts +19 -0
- package/src/utils/Function/tryCatch/tryCatch.ts +13 -0
- package/src/utils/Latch/Latch.ts +63 -0
- package/src/utils/Map/ObservableMap/ObservableMap.ts +55 -0
- package/src/utils/Map/findMapsDifferences/findMapsDifferences.ts +35 -0
- package/src/utils/Map/mapGetOrSet/mapGetOrSet.ts +7 -0
- package/src/utils/Map/mapMapToArray/mapMapToArray.ts +6 -0
- package/src/utils/Map/mapMapValues/mapMapValues.ts +9 -0
- package/src/utils/Math/createSimpleMovingAverageSeries/createSimpleMovingAverageSeries.ts +22 -0
- package/src/utils/Math/mean/mean.ts +14 -0
- package/src/utils/Math/simpleMovingAverageUsingAccFabric/simpleMovingAverageUsingAccFabric.ts +29 -0
- package/src/utils/Math/sum/sum.ts +45 -0
- package/src/utils/MinHeap/MinHeap.ts +88 -0
- package/src/utils/MinHeapUniqueNumber/MinHeapUniqueNumber.ts +105 -0
- package/src/utils/MinMaxHeap/MinMaxHeap.ts +91 -0
- package/src/utils/Number/collectIntegerSequences/collectIntegerSequences.ts +36 -0
- package/src/utils/Number/numberToFixedPrecision/numberToFixedPrecision.ts +13 -0
- package/src/utils/Object/cloneObject/cloneObject.ts +3 -0
- package/src/utils/Object/deepEqual/deepEqual.ts +45 -0
- package/src/utils/Object/deleteUndefinedProperties/index.ts +13 -0
- package/src/utils/Object/entriesToObject/entriesToObject.ts +12 -0
- package/src/utils/Object/filterObject/filterObject.ts +18 -0
- package/src/utils/Object/forOwn/forOwn.ts +12 -0
- package/src/utils/Object/getObjectEntries/getObjectEntries.ts +3 -0
- package/src/utils/Object/getObjectKeys/getObjectKeys.ts +3 -0
- package/src/utils/Object/getObjectValues/index.ts +3 -0
- package/src/utils/Object/hasOwnProperty/hasOwnProperty.ts +3 -0
- package/src/utils/Object/invertObject/InvertedObject.ts +3 -0
- package/src/utils/Object/invertObject/invertObject.ts +15 -0
- package/src/utils/Object/isEmptyObject/index.ts +5 -0
- package/src/utils/Object/isObject/index.ts +8 -0
- package/src/utils/Object/mapObjectKeys/mapObjectKeys.ts +25 -0
- package/src/utils/Object/mapObjectValues/mapObjectValues.ts +16 -0
- package/src/utils/Object/mirrorObject/ObjectKeysMirror.ts +1 -0
- package/src/utils/Object/mirrorObject/mirrorObject.ts +7 -0
- package/src/utils/Pagination/DEFAULT_PAGE.ts +1 -0
- package/src/utils/Pagination/calculatePaginationParameters.ts +29 -0
- package/src/utils/Promise/promiseAll/promiseAll.ts +6 -0
- package/src/utils/Promise/restrictParallelCalls/restrictParallelCalls.ts +18 -0
- package/src/utils/Ranges/checkRangesAdjacent/checkRangesAdjacent.ts +23 -0
- package/src/utils/Ranges/checkRangesIntersection/checkRangesIntersection.ts +8 -0
- package/src/utils/Ranges/excludeRanges/excludeRanges.ts +42 -0
- package/src/utils/Ranges/getDistanceToRange/getDistanceToRange.ts +14 -0
- package/src/utils/Ranges/isRangeWithinRanges.ts +14 -0
- package/src/utils/Ranges/mapDateRangeToISODateStringRange/mapDateRangeToISODateStringRange.ts +7 -0
- package/src/utils/Ranges/mapISODateStringRangeToUnixTimeMsRange/mapISODateStringRangeToUnixTimeMsRange.ts +8 -0
- package/src/utils/Ranges/mapRange/mapRange.ts +13 -0
- package/src/utils/Ranges/mapUnixTimeMsRangeToISODateStringRange/mapUnixTimeMsRangeToISODateStringRange.ts +8 -0
- package/src/utils/Ranges/mergeRanges/mergeRanges.ts +34 -0
- package/src/utils/Signal/Signal.ts +47 -0
- package/src/utils/Signal/SignalCallback.ts +1 -0
- package/src/utils/Signal/combineSignalsIntoNewOne/combineSignalsIntoNewOne.ts +75 -0
- package/src/utils/Signal/subscribeSignalAndCallWithCurrentValue/subscribeSignalAndCallWithCurrentValue.ts +7 -0
- package/src/utils/Signal/useSignal.ts +10 -0
- package/src/utils/String/HexString/HEX_SYMBOLS.ts +1 -0
- package/src/utils/String/HexString/HexString.ts +2 -0
- package/src/utils/String/HexString/isHexString.ts +16 -0
- package/src/utils/String/NonEmptyString/NonEmptyString.ts +22 -0
- package/src/utils/String/endsWith/index.ts +6 -0
- package/src/utils/String/isString.ts +3 -0
- package/src/utils/binarySearch/binarySearch.ts +20 -0
- package/src/utils/binarySearchClosest/binarySearchClosest.ts +43 -0
- package/src/utils/createIncrementalIntegerGenerator.ts +7 -0
- package/src/utils/createRemoteDataProcessingWindow/createRemoteDataProcessingWindow.ts +157 -0
- package/src/utils/createSimultaneousOperationsHandler/createSimultaneousOperationsHandler.ts +65 -0
- package/src/utils/encryptDecryptString/encryptDecryptString.ts +34 -0
- package/src/utils/getPrimeNumbersWithEratosthenesSieve/getPrimeNumbersWithEratosthenesSieve.ts +21 -0
- package/src/utils/isPromise/isPromise.ts +30 -0
- package/src/utils/makeAsyncFunctionCallsSimultaneous/makeAsyncFunctionCallsSimultaneous.ts +64 -0
- package/src/utils/parallelsLimitPromise/index.ts +28 -0
- package/src/utils/parallelsLimitQueue/parallelsLimitQueue.ts +69 -0
- package/src/utils/prettyStringify/index.ts +3 -0
- package/src/utils/random/fnv1a/fnv1a.ts +87 -0
- package/src/utils/random/generateHashedFloats/generateHashedFloats.ts +28 -0
- package/src/utils/random/getRandomIntegerInARange/getRandomIntegerInARange.ts +3 -0
- package/src/utils/random/getSampleIndexByStringHash/getSampleIndexByStringHash.ts +10 -0
- package/src/utils/random/randomBoolean/randomBoolean.ts +3 -0
- package/src/utils/random/randomHexString/randomHexString.ts +12 -0
- package/src/utils/requestAnimationFrame/requestAnimationFramePromise/requestAnimationFramePromise.ts +7 -0
- package/src/utils/requestAnimationFrame/requestAnimationFrameThrottle/requestAnimationFrameThrottle.ts +6 -0
- package/src/utils/retryFunctionWrapper/retryFunctionWrapper.ts +40 -0
- package/src/utils/runParallelTimescalesProcessing/runParallelTimescalesProcessing.ts +113 -0
- package/src/utils/stringifyError.ts +3 -0
- package/src/utils/timers/promiseTimeout/promiseTimeout.ts +26 -0
- package/src/utils/timers/subscribeSyntheticInterval/subscribeSyntheticInterval.ts +47 -0
- package/src/utils/waitForFunction/waitForFunction.ts +50 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FNV-1a hash generation init value.
|
|
3
|
+
* More info: https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV_hash_parameters
|
|
4
|
+
*
|
|
5
|
+
* Stolen from https://github.com/sindresorhus/fnv1a/blob/main/index.js
|
|
6
|
+
*/
|
|
7
|
+
// FNV_PRIMES and FNV_OFFSETS from
|
|
8
|
+
// http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
|
|
9
|
+
|
|
10
|
+
const FNV_PRIMES: Record<number, bigint> = {
|
|
11
|
+
32: 16_777_619n,
|
|
12
|
+
64: 1_099_511_628_211n,
|
|
13
|
+
128: 309_485_009_821_345_068_724_781_371n,
|
|
14
|
+
256: 374_144_419_156_711_147_060_143_317_175_368_453_031_918_731_002_211n,
|
|
15
|
+
512: 35_835_915_874_844_867_368_919_076_489_095_108_449_946_327_955_754_392_558_399_825_615_420_669_938_882_575_126_094_039_892_345_713_852_759n,
|
|
16
|
+
1024: 5_016_456_510_113_118_655_434_598_811_035_278_955_030_765_345_404_790_744_303_017_523_831_112_055_108_147_451_509_157_692_220_295_382_716_162_651_878_526_895_249_385_292_291_816_524_375_083_746_691_371_804_094_271_873_160_484_737_966_720_260_389_217_684_476_157_468_082_573n,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const FNV_OFFSETS: Record<number, bigint> = {
|
|
20
|
+
32: 2_166_136_261n,
|
|
21
|
+
64: 14_695_981_039_346_656_037n,
|
|
22
|
+
128: 144_066_263_297_769_815_596_495_629_667_062_367_629n,
|
|
23
|
+
256: 100_029_257_958_052_580_907_070_968_620_625_704_837_092_796_014_241_193_945_225_284_501_741_471_925_557n,
|
|
24
|
+
512: 9_659_303_129_496_669_498_009_435_400_716_310_466_090_418_745_672_637_896_108_374_329_434_462_657_994_582_932_197_716_438_449_813_051_892_206_539_805_784_495_328_239_340_083_876_191_928_701_583_869_517_785n,
|
|
25
|
+
1024: 14_197_795_064_947_621_068_722_070_641_403_218_320_880_622_795_441_933_960_878_474_914_617_582_723_252_296_732_303_717_722_150_864_096_521_202_355_549_365_628_174_669_108_571_814_760_471_015_076_148_029_755_969_804_077_320_157_692_458_563_003_215_304_957_150_157_403_644_460_363_550_505_412_711_285_966_361_610_267_868_082_893_823_963_790_439_336_411_086_884_584_107_735_010_676_915n,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const cachedEncoder = new globalThis.TextEncoder();
|
|
29
|
+
|
|
30
|
+
function fnv1aUint8Array(uint8Array: Uint8Array, size: number) {
|
|
31
|
+
const fnvPrime = FNV_PRIMES[size];
|
|
32
|
+
let hash = FNV_OFFSETS[size];
|
|
33
|
+
|
|
34
|
+
for (let index = 0; index < uint8Array.length; index++) {
|
|
35
|
+
hash ^= BigInt(uint8Array[index]);
|
|
36
|
+
hash = BigInt.asUintN(size, hash * fnvPrime);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return hash;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function fnv1aEncodeInto(string: string, size: number, utf8Buffer: Uint8Array) {
|
|
43
|
+
if (utf8Buffer.length === 0) {
|
|
44
|
+
throw new Error('The `utf8Buffer` option must have a length greater than zero');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const fnvPrime = FNV_PRIMES[size];
|
|
48
|
+
let hash = FNV_OFFSETS[size];
|
|
49
|
+
let remaining = string;
|
|
50
|
+
|
|
51
|
+
while (remaining.length > 0) {
|
|
52
|
+
const result = cachedEncoder.encodeInto(remaining, utf8Buffer);
|
|
53
|
+
|
|
54
|
+
remaining = remaining.slice(result.read);
|
|
55
|
+
for (let index = 0; index < result.written; index++) {
|
|
56
|
+
hash ^= BigInt(utf8Buffer[index]);
|
|
57
|
+
hash = BigInt.asUintN(size, hash * fnvPrime);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return hash;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function fnv1a(
|
|
65
|
+
value: string | Uint8Array,
|
|
66
|
+
{
|
|
67
|
+
size = 32,
|
|
68
|
+
utf8Buffer,
|
|
69
|
+
}: {
|
|
70
|
+
size?: number;
|
|
71
|
+
utf8Buffer?: Uint8Array;
|
|
72
|
+
} = {}
|
|
73
|
+
) {
|
|
74
|
+
if (!FNV_PRIMES[size]) {
|
|
75
|
+
throw new Error('The `size` option must be one of 32, 64, 128, 256, 512, or 1024');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (typeof value === 'string') {
|
|
79
|
+
if (utf8Buffer) {
|
|
80
|
+
return fnv1aEncodeInto(value, size, utf8Buffer);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
value = cachedEncoder.encode(value);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return fnv1aUint8Array(value, size);
|
|
87
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Get independent values from hash sized for experiments
|
|
5
|
+
*/
|
|
6
|
+
export function generateHashedFloats(seed: string, count: number): number[] {
|
|
7
|
+
// 6 bytes is the maximum for buffer.readUIntBE method
|
|
8
|
+
const BYTES_PER_INT = 6;
|
|
9
|
+
const MAX_INT = 2 ** (BYTES_PER_INT * 8) - 1;
|
|
10
|
+
|
|
11
|
+
// Get exact number of bytes needed
|
|
12
|
+
const buffer = crypto
|
|
13
|
+
.createHash('shake256', { outputLength: count * BYTES_PER_INT })
|
|
14
|
+
.update(seed)
|
|
15
|
+
.digest();
|
|
16
|
+
|
|
17
|
+
const floats: number[] = [];
|
|
18
|
+
|
|
19
|
+
for (let i = 0; i < count; i++) {
|
|
20
|
+
const offset = i * BYTES_PER_INT;
|
|
21
|
+
const intValue = buffer.readUIntBE(offset, BYTES_PER_INT);
|
|
22
|
+
const float = intValue / MAX_INT;
|
|
23
|
+
|
|
24
|
+
floats.push(float);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return floats;
|
|
28
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PositiveInteger } from '../../../types/Number/PositiveInteger';
|
|
2
|
+
import { UnsignedInteger } from '../../../types/Number/UnsignedInteger';
|
|
3
|
+
import { fnv1a } from '../fnv1a/fnv1a';
|
|
4
|
+
|
|
5
|
+
export function getSampleIndexByStringHash(str: string, samplesCount: PositiveInteger): UnsignedInteger {
|
|
6
|
+
const bigint = fnv1a(str);
|
|
7
|
+
const int = Number(bigint);
|
|
8
|
+
|
|
9
|
+
return int % samplesCount;
|
|
10
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { UnsignedInteger } from '../../../types/Number/UnsignedInteger';
|
|
2
|
+
import { HexString } from '../../String/HexString/HexString';
|
|
3
|
+
|
|
4
|
+
export function randomHexString(length: UnsignedInteger): HexString {
|
|
5
|
+
let x: HexString = '';
|
|
6
|
+
|
|
7
|
+
for (let key = 0; key < length; key++) {
|
|
8
|
+
x += ((Math.random() * 16) | 0).toString(16);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return x;
|
|
12
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { throttleWithPromiseFunction } from '../../Function/throttleWithPromiseFunction/throttleWithPromiseFunction';
|
|
2
|
+
import { requestAnimationFramePromise } from '../requestAnimationFramePromise/requestAnimationFramePromise';
|
|
3
|
+
|
|
4
|
+
export function requestAnimationFrameThrottle(callback: VoidFunction) {
|
|
5
|
+
return throttleWithPromiseFunction(callback, requestAnimationFramePromise);
|
|
6
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { promiseTimeout } from '../timers/promiseTimeout/promiseTimeout';
|
|
2
|
+
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4
|
+
export function retryFunctionWrapper<T extends (...args: any[]) => Promise<any>>({
|
|
5
|
+
fn,
|
|
6
|
+
attempts,
|
|
7
|
+
delay,
|
|
8
|
+
onFailAttempt,
|
|
9
|
+
}: {
|
|
10
|
+
fn: T;
|
|
11
|
+
attempts: number;
|
|
12
|
+
delay: number;
|
|
13
|
+
onFailAttempt?: (error: unknown, attemptIndex: number) => void;
|
|
14
|
+
}): T {
|
|
15
|
+
return ((...args: Parameters<T>): Promise<ReturnType<T>> => new Promise<ReturnType<T>>((resolve, reject) => {
|
|
16
|
+
let attemptIndex = 0;
|
|
17
|
+
|
|
18
|
+
const makeAttempt = async () => {
|
|
19
|
+
try {
|
|
20
|
+
const fnReturnValue = fn(...args);
|
|
21
|
+
|
|
22
|
+
const result = await fnReturnValue as ReturnType<T>;
|
|
23
|
+
|
|
24
|
+
resolve(result);
|
|
25
|
+
} catch (error) {
|
|
26
|
+
onFailAttempt?.(error, attemptIndex);
|
|
27
|
+
attemptIndex++;
|
|
28
|
+
|
|
29
|
+
if (attemptIndex < attempts) {
|
|
30
|
+
promiseTimeout(delay).then(makeAttempt);
|
|
31
|
+
} else {
|
|
32
|
+
// eslint-disable-next-line prefer-promise-reject-errors
|
|
33
|
+
reject(error as Error);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
makeAttempt();
|
|
39
|
+
})) as T;
|
|
40
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { assertPositiveInteger, PositiveInteger } from '../../types/Number/PositiveInteger';
|
|
2
|
+
import { UnsignedInteger } from '../../types/Number/UnsignedInteger';
|
|
3
|
+
import { RemoteDataProcessingWindowExtractItemsFunction } from '../createRemoteDataProcessingWindow/createRemoteDataProcessingWindow';
|
|
4
|
+
import { MinHeapUniqueNumber } from '../MinHeapUniqueNumber/MinHeapUniqueNumber';
|
|
5
|
+
|
|
6
|
+
type ObjectWithTime = {
|
|
7
|
+
time: number;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
type ExtractItemsFunctions<T extends ObjectWithTime[]> = {
|
|
11
|
+
[K in keyof T]: RemoteDataProcessingWindowExtractItemsFunction<T[K]>;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type ObjectsWithTimePortion<T extends ObjectWithTime[]> = {
|
|
15
|
+
[K in keyof T]: T[K] | undefined;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
type TimescaleBufferInfo<T extends ObjectWithTime> = {
|
|
19
|
+
array: T[];
|
|
20
|
+
index: UnsignedInteger;
|
|
21
|
+
isLast: boolean;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
type TimescalesBuffersInfo<T extends ObjectWithTime[]> = {
|
|
25
|
+
[K in keyof T]: TimescaleBufferInfo<T[K]>;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export async function runParallelTimescalesProcessing<T extends ObjectWithTime[]>({
|
|
29
|
+
extractItemsFunctions,
|
|
30
|
+
callback,
|
|
31
|
+
bufferSize,
|
|
32
|
+
}: {
|
|
33
|
+
extractItemsFunctions: ExtractItemsFunctions<T>;
|
|
34
|
+
callback: (pointsInfo: ObjectsWithTimePortion<T>, time: ObjectWithTime['time']) => unknown;
|
|
35
|
+
bufferSize: PositiveInteger;
|
|
36
|
+
}): Promise<void> {
|
|
37
|
+
assertPositiveInteger(bufferSize, 'runParallelTimescalesProcessing bufferSize should be a positive integer');
|
|
38
|
+
|
|
39
|
+
const timescalesCount = extractItemsFunctions.length;
|
|
40
|
+
|
|
41
|
+
assertPositiveInteger(timescalesCount, 'runParallelTimescalesProcessing extractItemsFunctions should array should NOT be empty');
|
|
42
|
+
|
|
43
|
+
const notFinishedBuffers: Set<UnsignedInteger> = new Set();
|
|
44
|
+
const buffersToLoadData: UnsignedInteger[] = [];
|
|
45
|
+
const buffers = extractItemsFunctions.map(<O extends ObjectWithTime>(_: RemoteDataProcessingWindowExtractItemsFunction<O>, i: UnsignedInteger) => {
|
|
46
|
+
notFinishedBuffers.add(i);
|
|
47
|
+
buffersToLoadData.push(i);
|
|
48
|
+
|
|
49
|
+
const bufferInfo: TimescaleBufferInfo<O> = {
|
|
50
|
+
array: [],
|
|
51
|
+
index: 0,
|
|
52
|
+
isLast: false,
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
return bufferInfo;
|
|
56
|
+
}) as TimescalesBuffersInfo<T>;
|
|
57
|
+
|
|
58
|
+
const minHeapUniqueNumber = new MinHeapUniqueNumber();
|
|
59
|
+
|
|
60
|
+
while (true) {
|
|
61
|
+
if (buffersToLoadData.length > 0) {
|
|
62
|
+
await Promise.all(buffersToLoadData.map(async (index) => {
|
|
63
|
+
const { items, isLast } = await extractItemsFunctions[index](bufferSize);
|
|
64
|
+
|
|
65
|
+
if (isLast) {
|
|
66
|
+
buffers[index].isLast = true;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
buffers[index].array = items;
|
|
70
|
+
buffers[index].index = 0;
|
|
71
|
+
|
|
72
|
+
if (items[0]) {
|
|
73
|
+
minHeapUniqueNumber.push(items[0].time);
|
|
74
|
+
}
|
|
75
|
+
}));
|
|
76
|
+
|
|
77
|
+
buffersToLoadData.length = 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const minTime = minHeapUniqueNumber.pop();
|
|
81
|
+
|
|
82
|
+
const portion = new Array(timescalesCount) as ObjectsWithTimePortion<T>;
|
|
83
|
+
|
|
84
|
+
for (const i of notFinishedBuffers.values()) {
|
|
85
|
+
const buffer = buffers[i];
|
|
86
|
+
|
|
87
|
+
const item = buffer.array.at(buffer.index);
|
|
88
|
+
|
|
89
|
+
if (item) {
|
|
90
|
+
if (item.time === minTime) {
|
|
91
|
+
portion[i] = item;
|
|
92
|
+
buffer.index++;
|
|
93
|
+
|
|
94
|
+
const nextItem = buffer.array.at(buffer.index);
|
|
95
|
+
|
|
96
|
+
if (nextItem) {
|
|
97
|
+
minHeapUniqueNumber.push(nextItem.time);
|
|
98
|
+
} else if (!buffer.isLast) {
|
|
99
|
+
buffersToLoadData.push(i);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
} else if (buffer.isLast) {
|
|
103
|
+
notFinishedBuffers.delete(i);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (notFinishedBuffers.size === 0) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
callback(portion, minTime!);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Milliseconds } from '../../../types/Time/Milliseconds';
|
|
2
|
+
import { AbortableProcess } from '../../AbortableProcess';
|
|
3
|
+
|
|
4
|
+
export function promiseTimeout(timeoutMs: Milliseconds, {
|
|
5
|
+
abortable,
|
|
6
|
+
}: {
|
|
7
|
+
abortable?: AbortableProcess;
|
|
8
|
+
} = {}): Promise<void> {
|
|
9
|
+
return new Promise((resolve) => {
|
|
10
|
+
const timeoutId = setTimeout(() => {
|
|
11
|
+
if (abortable) {
|
|
12
|
+
abortable.unsubscribe(clearTimeoutId);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
resolve();
|
|
16
|
+
}, timeoutMs);
|
|
17
|
+
|
|
18
|
+
const clearTimeoutId = () => {
|
|
19
|
+
clearTimeout(timeoutId);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
if (abortable) {
|
|
23
|
+
abortable.subscribeAbort(clearTimeoutId);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { UnsignedInteger } from '../../../types/Number/UnsignedInteger';
|
|
2
|
+
import { Milliseconds } from '../../../types/Time/Milliseconds';
|
|
3
|
+
import { callFunctions } from '../../Function/callFunctions/callFunctions';
|
|
4
|
+
|
|
5
|
+
type IntervalSubscription = {
|
|
6
|
+
intervalId: UnsignedInteger;
|
|
7
|
+
subscribers: Set<VoidFunction>;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const subscribersMap: Map<Milliseconds, IntervalSubscription> = new Map();
|
|
11
|
+
|
|
12
|
+
const TIMEUPDATE_INTERVAL: Milliseconds = 1000;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Функция нужна для того, чтобы не дублировать интервалы, предназначенные для обновления состояния видео-рекламы
|
|
16
|
+
*
|
|
17
|
+
* Функция принимает коллбек, который будет вызываться по интервалу, возвращает метод для отписки
|
|
18
|
+
*
|
|
19
|
+
* Интервал запускается при первом вызове и останавливается после того, как у него не остаётся подписчиков.
|
|
20
|
+
*/
|
|
21
|
+
export function subscribeSyntheticInterval(intervalMs: Milliseconds, subscriber: () => void): () => void {
|
|
22
|
+
if (!subscribersMap.has(intervalMs)) {
|
|
23
|
+
subscribersMap.set(intervalMs, {
|
|
24
|
+
intervalId: 0,
|
|
25
|
+
subscribers: new Set(),
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const subscription: IntervalSubscription = subscribersMap.get(intervalMs)!;
|
|
30
|
+
|
|
31
|
+
if (subscription.subscribers.size === 0) {
|
|
32
|
+
subscription.intervalId = window.setInterval(() => {
|
|
33
|
+
callFunctions(subscription.subscribers);
|
|
34
|
+
}, TIMEUPDATE_INTERVAL);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
subscription.subscribers.add(subscriber);
|
|
38
|
+
|
|
39
|
+
return () => {
|
|
40
|
+
subscription.subscribers.delete(subscriber);
|
|
41
|
+
|
|
42
|
+
if (subscription.subscribers.size === 0) {
|
|
43
|
+
window.clearInterval(subscription.intervalId);
|
|
44
|
+
subscribersMap.delete(intervalMs);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { tryCatch } from '../Function/tryCatch/tryCatch';
|
|
2
|
+
|
|
3
|
+
export function waitForFunction(
|
|
4
|
+
condition: () => boolean,
|
|
5
|
+
{
|
|
6
|
+
timeout = 250,
|
|
7
|
+
interval = 10,
|
|
8
|
+
message = `waitForFunction timeout=[${timeout}]ms`,
|
|
9
|
+
}: Partial<
|
|
10
|
+
Readonly<{
|
|
11
|
+
timeout: number;
|
|
12
|
+
interval: number;
|
|
13
|
+
message: string;
|
|
14
|
+
}>
|
|
15
|
+
> = {}
|
|
16
|
+
): Promise<void> {
|
|
17
|
+
return new Promise((resolve, reject) => {
|
|
18
|
+
// eslint-disable-next-line prefer-const
|
|
19
|
+
let intervalId: ReturnType<typeof setInterval>;
|
|
20
|
+
// eslint-disable-next-line prefer-const
|
|
21
|
+
let timeoutId: ReturnType<typeof setTimeout>;
|
|
22
|
+
|
|
23
|
+
const clear = () => {
|
|
24
|
+
clearInterval(intervalId);
|
|
25
|
+
clearTimeout(timeoutId);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const rejectWithClear = (error: Error) => {
|
|
29
|
+
clear();
|
|
30
|
+
reject(error);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const check = () => {
|
|
34
|
+
if (tryCatch(condition, rejectWithClear) === true) {
|
|
35
|
+
resolve(undefined);
|
|
36
|
+
clear();
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
intervalId = setInterval(() => {
|
|
41
|
+
check();
|
|
42
|
+
}, interval);
|
|
43
|
+
|
|
44
|
+
timeoutId = setTimeout(() => {
|
|
45
|
+
rejectWithClear(new Error(message));
|
|
46
|
+
}, timeout);
|
|
47
|
+
|
|
48
|
+
check();
|
|
49
|
+
});
|
|
50
|
+
}
|